Path: blob/master/jcl/src/java.base/share/classes/java/lang/invoke/CallSite.java
12520 views
/*[INCLUDE-IF Sidecar17 & !OPENJDK_METHODHANDLES]*/1/*******************************************************************************2* Copyright (c) 2011, 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 static java.lang.invoke.MethodType.*;2526/**27* CallSite is used by the invokedynamic bytecode to hold a reference to the MethodHandle target of the instruction.28* <p>29* Although CallSite is an abstract class, it cannot be directly sub-classed. Instead, it is necessary to sub-class30* one of the three implementation classes:31* <ul>32* <li>ConstantCallSite - if the target will never change</li>33* <li>VolatileCallSite - if the target is expected to frequently change. Changes will be immediately visible in all threads.</li>34* <li>MutableCallSite - if the target is expected to rarely change and threads may see previous values of the target for some time.</li>35* </ul>36*37* <p>38* CallSites are created with a MethodType and permanently bound to that type. Any changes to the target39* MethodHandle must be of the identical MethodType or a WrongMethodTypeException will be thrown.40*41* @since 1.742*/43public abstract class CallSite {44private final MethodType type;45private static MethodHandle initialTargetHandleCache;4647CallSite(MethodType type){48type.getClass(); // Throw NPE if null49this.type = type;50}5152/**53* Report the type of CallSite's target MethodHandle.54* A CallSite cannot change its type.55* @return The permanent MethodType of this CallSite.56*/57public MethodType type() {58return type;59}6061/**62* Return the target MethodHandle of the CallSite.63*64* @return the current target MethodHandle65*/66public abstract MethodHandle getTarget();6768/**69* Set the CallSite's target to be <i>nextTarget</i>.70* The <i>nextTarget</i> MethodHandle must have the same type as the CallSite.71*72* @param nextTarget - the new target value for the CallSite73* @throws WrongMethodTypeException - if the type of <i>nextTarget</i> differs from that of the CallSite.74* @throws NullPointerException - if <i>nextTarget</i> is null.75*/76public abstract void setTarget(MethodHandle nextTarget) throws WrongMethodTypeException, NullPointerException;7778/**79* Return a MethodHandle equivalent to the invokedynamic instruction on this CallSite.80* The MethodHandle is equivalent to getTarget().invokeExact(args).81*82* @return a MethodHandle that is equivalent to an invokedynamic instruction on this CallSite.83*/84public abstract MethodHandle dynamicInvoker();858687/* Defer the creation of the Exception until called in the IllegalState */88static void throwIllegalStateException() throws IllegalStateException {89throw new IllegalStateException();90}9192/* Return the initial target for the CallSite - it will throw an IllegalStateException. */93static MethodHandle initialTarget(MethodType type) {94MethodHandle initialTargetHandle = initialTargetHandleCache;95if (null == initialTargetHandle) {96initialTargetHandle = lookupInitialTarget();97}98initialTargetHandle = initialTargetHandle.asType(methodType(type.returnType()));99/* Adapt the initial target to be compliant with what the caller expects */100return MethodHandles.dropArguments(initialTargetHandle, 0, type.ptypes());101}102103/* Initialize the cached MethodHandle for initialTarget */104private static MethodHandle lookupInitialTarget() {105try {106initialTargetHandleCache = MethodHandles.Lookup.internalPrivilegedLookup.findStatic(CallSite.class, "throwIllegalStateException", methodType(void.class)); //$NON-NLS-1$107} catch (IllegalAccessException | NoSuchMethodException e) {108throw new InternalError("Unable to lookup CallSite initial target"); //$NON-NLS-1$109}110return initialTargetHandleCache;111}112}113114115116