Path: blob/master/jcl/src/java.base/share/classes/java/lang/invoke/DirectHandle.java
12521 views
/*[INCLUDE-IF Sidecar17 & !OPENJDK_METHODHANDLES]*/1/*******************************************************************************2* Copyright (c) 2009, 2020 IBM Corp. and others3*4* This program and the accompanying materials are made available under5* the terms of the Eclipse Public License 2.0 which accompanies this6* distribution and is available at https://www.eclipse.org/legal/epl-2.0/7* or the Apache License, Version 2.0 which accompanies this distribution and8* is available at https://www.apache.org/licenses/LICENSE-2.0.9*10* This Source Code may also be made available under the following11* Secondary Licenses when the conditions for such availability set12* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU13* General Public License, version 2 with the GNU Classpath14* Exception [1] and GNU General Public License, version 2 with the15* OpenJDK Assembly Exception [2].16*17* [1] https://www.gnu.org/software/classpath/license.html18* [2] http://openjdk.java.net/legal/assembly-exception.html19*20* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception21*******************************************************************************/22package java.lang.invoke;2324import java.lang.reflect.Method;25import java.lang.reflect.Modifier;2627/* DirectHandle is a MethodHandle subclass used to call methods that have already28* been resolved down to an exact method address.29* <p>30* The exact method address is known in the following cases:31* <ul>32* <li> MethodHandles.lookup().findStatic </li>33* <li> MethodHandles.lookup().findSpecial </li>34* </ul>35* <p>36* The vmSlot will hold a J9Method address.37*/38class DirectHandle extends PrimitiveHandle {39final boolean isStatic;40final boolean originIsFindVirtual;4142DirectHandle(Class<?> referenceClass, String methodName, MethodType type, byte kind, Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {43this(referenceClass, methodName, type, kind, specialCaller, false);44}4546DirectHandle(Class<?> referenceClass, String methodName, MethodType type, byte kind, Class<?> specialCaller, boolean originIsFindVirtual) throws NoSuchMethodException, IllegalAccessException {47super(directMethodType(type, kind, specialCaller), referenceClass, methodName, kind, null);48assert (kind != KIND_SPECIAL) || (specialCaller != null);49this.specialCaller = specialCaller;50addHandleToClassCache();51this.defc = finishMethodInitialization(specialCaller, type);52/* Kind should have been changed from KIND_VIRTUAL in finishMethodInitialization */53assert (this.kind != KIND_VIRTUAL);54isStatic = Modifier.isStatic(rawModifiers);55this.originIsFindVirtual = originIsFindVirtual;56}5758public DirectHandle(Method method, byte kind, Class<?> specialCaller) throws IllegalAccessException {59this(method, kind, specialCaller, false);60}6162public DirectHandle(Method method, byte kind, Class<?> specialCaller, boolean originIsFindVirtual) throws IllegalAccessException {63super(directMethodType(MethodType.methodType(method.getReturnType(), method.getParameterTypes()), kind, specialCaller), method.getDeclaringClass(), method.getName(), kind, method.getModifiers(), null);64assert (kind != KIND_SPECIAL) || (specialCaller != null);65this.specialCaller = specialCaller;66addHandleToClassCache();67boolean succeed = setVMSlotAndRawModifiersFromMethod(this, referenceClass, method, this.kind, specialCaller);68if (!succeed) {69throw new IllegalAccessException();70}71isStatic = Modifier.isStatic(rawModifiers);72this.originIsFindVirtual = originIsFindVirtual;73}7475/*76* Create a new DirectHandle from another DirectHandle.77* This is used by ReceiverBoundHandle78*/79DirectHandle(PrimitiveHandle other, byte kind) {80super(ReceiverBoundHandle.receiverBoundMethodType(other.type), other.referenceClass, other.name, kind, other.rawModifiers, null);81if (!(other instanceof DirectHandle)) {82throw new IllegalArgumentException();83}84this.specialCaller = other.specialCaller;85addHandleToClassCache();86this.vmSlot = other.vmSlot;87this.defc = other.defc;88isStatic = Modifier.isStatic(other.rawModifiers);89this.originIsFindVirtual = other.directHandleOriginatedInFindVirtual();90}9192DirectHandle(DirectHandle originalHandle, MethodType newType) {93super(originalHandle, newType);94isStatic = originalHandle.isStatic;95this.originIsFindVirtual = originalHandle.originIsFindVirtual;96addHandleToClassCache();97// Reassigning the vmSlot because an HCR may have occurred since it was assigned in super()98this.vmSlot = originalHandle.vmSlot;99}100101/*102* Determine the correct MethodType for the DirectHandle103* KIND_STATIC - unmodified104* KIND_SPECIAL - insert specialCaller as first parameter105*/106private static final MethodType directMethodType(MethodType existingType, byte kind, Class<?> specialCaller) {107if (kind == KIND_STATIC) {108return existingType;109}110return existingType.insertParameterTypes(0, specialCaller);111}112113private void addHandleToClassCache() {114MethodHandleCache cache = MethodHandleCache.getCache(defc);115cache.addDirectHandle(this);116}117118final void nullCheckIfRequired(Object receiver) throws NullPointerException {119if (!isStatic) {120receiver.getClass(); // Deliberate NPE121}122}123124@Override125boolean canRevealDirect() {126return true;127}128129@Override130boolean directHandleOriginatedInFindVirtual() {131return originIsFindVirtual;132}133134// {{{ JIT support135private static final ThunkTable _thunkTable = new ThunkTable();136protected ThunkTable thunkTable(){ return _thunkTable; }137138// ILGen macros139protected static native boolean isAlreadyCompiled(long j9method);140protected static native long compiledEntryPoint(long j9method);141142protected static native void directCall_V(int argPlaceholder);143protected static native int directCall_I(int argPlaceholder);144protected static native long directCall_J(int argPlaceholder);145protected static native float directCall_F(int argPlaceholder);146protected static native double directCall_D(int argPlaceholder);147protected static native Object directCall_L(int argPlaceholder);148149protected static native void directCall_V(Object receiver, int argPlaceholder);150protected static native int directCall_I(Object receiver, int argPlaceholder);151protected static native long directCall_J(Object receiver, int argPlaceholder);152protected static native float directCall_F(Object receiver, int argPlaceholder);153protected static native double directCall_D(Object receiver, int argPlaceholder);154protected static native Object directCall_L(Object receiver, int argPlaceholder);155156@FrameIteratorSkip157private final void invokeExact_thunkArchetype_V(int argPlaceholder) {158initializeClassIfRequired();159if (ILGenMacros.isCustomThunk()) {160directCall_V(argPlaceholder);161} else if (isAlreadyCompiled(vmSlot)) {162ComputedCalls.dispatchDirect_V(compiledEntryPoint(vmSlot), argPlaceholder);163} else {164ComputedCalls.dispatchJ9Method_V(vmSlot, argPlaceholder);165}166}167168@FrameIteratorSkip169private final void invokeExact_thunkArchetype_V(Object receiver, int argPlaceholder) {170nullCheckIfRequired(receiver);171initializeClassIfRequired();172if (ILGenMacros.isCustomThunk()) {173directCall_V(receiver, argPlaceholder);174} else if (isAlreadyCompiled(vmSlot)) {175ComputedCalls.dispatchDirect_V(compiledEntryPoint(vmSlot), receiver, argPlaceholder);176} else {177ComputedCalls.dispatchJ9Method_V(vmSlot, receiver, argPlaceholder);178}179}180181@FrameIteratorSkip182private final int invokeExact_thunkArchetype_I(int argPlaceholder) {183initializeClassIfRequired();184if (ILGenMacros.isCustomThunk()) {185return directCall_I(argPlaceholder);186} else if (isAlreadyCompiled(vmSlot)) {187return ComputedCalls.dispatchDirect_I(compiledEntryPoint(vmSlot), argPlaceholder);188} else {189return ComputedCalls.dispatchJ9Method_I(vmSlot, argPlaceholder);190}191}192193@FrameIteratorSkip194private final int invokeExact_thunkArchetype_I(Object receiver, int argPlaceholder) {195nullCheckIfRequired(receiver);196initializeClassIfRequired();197if (ILGenMacros.isCustomThunk()) {198return directCall_I(receiver, argPlaceholder);199} else if (isAlreadyCompiled(vmSlot)) {200return ComputedCalls.dispatchDirect_I(compiledEntryPoint(vmSlot), receiver, argPlaceholder);201} else {202return ComputedCalls.dispatchJ9Method_I(vmSlot, receiver, argPlaceholder);203}204}205206@FrameIteratorSkip207private final long invokeExact_thunkArchetype_J(int argPlaceholder) {208initializeClassIfRequired();209if (ILGenMacros.isCustomThunk()) {210return directCall_J(argPlaceholder);211} else if (isAlreadyCompiled(vmSlot)) {212return ComputedCalls.dispatchDirect_J(compiledEntryPoint(vmSlot), argPlaceholder);213} else {214return ComputedCalls.dispatchJ9Method_J(vmSlot, argPlaceholder);215}216}217218@FrameIteratorSkip219private final long invokeExact_thunkArchetype_J(Object receiver, int argPlaceholder) {220nullCheckIfRequired(receiver);221initializeClassIfRequired();222if (ILGenMacros.isCustomThunk()) {223return directCall_J(receiver, argPlaceholder);224} else if (isAlreadyCompiled(vmSlot)) {225return ComputedCalls.dispatchDirect_J(compiledEntryPoint(vmSlot), receiver, argPlaceholder);226} else {227return ComputedCalls.dispatchJ9Method_J(vmSlot, receiver, argPlaceholder);228}229}230231@FrameIteratorSkip232private final float invokeExact_thunkArchetype_F(int argPlaceholder) {233initializeClassIfRequired();234if (ILGenMacros.isCustomThunk()) {235return directCall_F(argPlaceholder);236} else if (isAlreadyCompiled(vmSlot)) {237return ComputedCalls.dispatchDirect_F(compiledEntryPoint(vmSlot), argPlaceholder);238} else {239return ComputedCalls.dispatchJ9Method_F(vmSlot, argPlaceholder);240}241}242243@FrameIteratorSkip244private final float invokeExact_thunkArchetype_F(Object receiver, int argPlaceholder) {245nullCheckIfRequired(receiver);246initializeClassIfRequired();247if (ILGenMacros.isCustomThunk()) {248return directCall_F(receiver, argPlaceholder);249} else if (isAlreadyCompiled(vmSlot)) {250return ComputedCalls.dispatchDirect_F(compiledEntryPoint(vmSlot), receiver, argPlaceholder);251} else {252return ComputedCalls.dispatchJ9Method_F(vmSlot, receiver, argPlaceholder);253}254}255256@FrameIteratorSkip257private final double invokeExact_thunkArchetype_D(int argPlaceholder) {258initializeClassIfRequired();259if (ILGenMacros.isCustomThunk()) {260return directCall_D(argPlaceholder);261} else if (isAlreadyCompiled(vmSlot)) {262return ComputedCalls.dispatchDirect_D(compiledEntryPoint(vmSlot), argPlaceholder);263} else {264return ComputedCalls.dispatchJ9Method_D(vmSlot, argPlaceholder);265}266}267268@FrameIteratorSkip269private final double invokeExact_thunkArchetype_D(Object receiver, int argPlaceholder) {270nullCheckIfRequired(receiver);271initializeClassIfRequired();272if (ILGenMacros.isCustomThunk()) {273return directCall_D(receiver, argPlaceholder);274} else if (isAlreadyCompiled(vmSlot)) {275return ComputedCalls.dispatchDirect_D(compiledEntryPoint(vmSlot), receiver, argPlaceholder);276} else {277return ComputedCalls.dispatchJ9Method_D(vmSlot, receiver, argPlaceholder);278}279}280281@FrameIteratorSkip282private final Object invokeExact_thunkArchetype_L(int argPlaceholder) {283initializeClassIfRequired();284if (ILGenMacros.isCustomThunk()) {285return directCall_L(argPlaceholder);286} else if (isAlreadyCompiled(vmSlot)) {287return ComputedCalls.dispatchDirect_L(compiledEntryPoint(vmSlot), argPlaceholder);288} else {289return ComputedCalls.dispatchJ9Method_L(vmSlot, argPlaceholder);290}291}292293@FrameIteratorSkip294private final Object invokeExact_thunkArchetype_L(Object receiver, int argPlaceholder) {295nullCheckIfRequired(receiver);296initializeClassIfRequired();297if (ILGenMacros.isCustomThunk()) {298return directCall_L(receiver, argPlaceholder);299} else if (isAlreadyCompiled(vmSlot)) {300return ComputedCalls.dispatchDirect_L(compiledEntryPoint(vmSlot), receiver, argPlaceholder);301} else {302return ComputedCalls.dispatchJ9Method_L(vmSlot, receiver, argPlaceholder);303}304}305306// }}} JIT support307308@Override309MethodHandle cloneWithNewType(MethodType newType) {310return new DirectHandle(this, newType);311}312313// Not final because it's overridden in ReceiverBoundHandle314void compareWith(MethodHandle right, Comparator c) {315if (right instanceof DirectHandle) {316((DirectHandle)right).compareWithDirect(this, c);317} else {318c.fail();319}320}321322void compareWithDirect(DirectHandle left, Comparator c) {323c.compareStructuralParameter(left.vmSlot, this.vmSlot);324}325326//Used by ConstructorHandle327//Making sure the DirectHandle class is loaded before ConstructorHandle is loaded. Therefore, to secure a correct thunk.328public static void load() {}329}330331332333