Path: blob/master/jcl/src/java.base/share/classes/java/lang/invoke/IndirectHandle.java
12558 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*******************************************************************************/2223package java.lang.invoke;2425import java.lang.reflect.Method;26import java.lang.reflect.Modifier;2728import static java.lang.invoke.MethodHandleResolver.UNSAFE;29import static java.lang.invoke.MethodHandleResolver.getJ9ClassFromClass;3031abstract class IndirectHandle extends PrimitiveHandle {32IndirectHandle(MethodType type, Class<?> referenceClass, String name, byte kind, int modifiers) {33super(type, referenceClass, name, kind, modifiers, null);34}3536IndirectHandle(MethodType type, Class<?> referenceClass, String name, byte kind) {37super(type, referenceClass, name, kind, null);38}3940IndirectHandle(IndirectHandle originalHandle, MethodType newType) {41super(originalHandle, newType);42}4344// {{{ JIT support45protected abstract long vtableOffset(Object receiver);46protected final long vtableIndexArgument(Object receiver){ return - vtableOffset(receiver); }4748protected final long jittedMethodAddress(Object receiver) {49long receiverClass = getJ9ClassFromClass(receiver.getClass());50long result;51if (VTABLE_ENTRY_SIZE == 4) {52result = UNSAFE.getInt(receiverClass - vtableOffset(receiver));53} else {54result = UNSAFE.getLong(receiverClass - vtableOffset(receiver));55}56return result;57}5859@Override60boolean canRevealDirect() {61return true;62}6364// }}} JIT support6566protected static final MethodType indirectMethodType(Method method) {67MethodType originalType = MethodType.methodType(method.getReturnType(), method.getParameterTypes());68return indirectMethodType(originalType, method.getDeclaringClass());69}7071/* Indirect MethodHandles have the receiver type inserted as72* first argument of the MH's type.73*/74protected static final MethodType indirectMethodType(MethodType type, Class<?> referenceClazz) {75return type.insertParameterTypes(0, referenceClazz);76}7778@Override79public MethodHandle bindTo(Object value) throws IllegalArgumentException, ClassCastException {80if (null == value) {81return super.bindTo(value);82}8384/*85* Check whether the first parameter has a reference type assignable from value. Note that MethodType.parameterType(0) will86* throw an IllegalArgumentException if type has no parameters.87*/88Class<?> firstParameterType = type().parameterType(0);89if (firstParameterType.isPrimitive()) {90throw new IllegalArgumentException();91}9293/*94* Ensure type compatibility.95*/96value = firstParameterType.cast(value);9798/*99* Devirtualize virtual/interface handles.100*/101try {102MethodHandle result = MethodHandles.Lookup.internalPrivilegedLookup.bind(value, name, type().dropFirstParameterType());103104/*105* An interface method must devirtualize to a public method. If the devirtualized method is not public,106* an IllegalAccessError will be thrown when the MethodHandle is invoked. In order to enforce this behaviour,107* we must preserve the original MethodHandle, i.e. not optimize to a ReceiverBoundHandle.108*/109if (this instanceof InterfaceHandle) {110if ((result.getModifiers() & Modifier.PUBLIC) == 0) {111throw new IllegalAccessException();112}113}114115return result;116} catch (IllegalAccessException e) {117/*118* Create a receiver bound MethodHandle by inserting the receiver object as an argument. This is done to119* ensure that invocation is done using the original MethodHandle, which will result in an IllegalAccessError.120*/121return MethodHandles.insertArguments(this, 0, value);122} catch (NoSuchMethodException e) {123throw new Error(e);124}125}126127final void compareWithIndirect(IndirectHandle left, Comparator c) {128c.compareStructuralParameter(left.referenceClass, this.referenceClass);129c.compareStructuralParameter(left.vmSlot, this.vmSlot);130}131}132133134135