caller = (Class>)callerObj;
String name = nameObj.toString().intern();
MethodType type = (MethodType)typeObj;
appendixResult[0] = CallSite.makeSite(bootstrapMethod,
name,
type,
staticArguments,
caller);
return Invokers.linkToCallSiteMethod(type);
}
/**
* The JVM wants a pointer to a MethodType. Oblige it by finding or creating one.
*/
static MethodType findMethodHandleType(Class> rtype, Class>[] ptypes) {
return MethodType.makeImpl(rtype, ptypes, true);
}
/**
* The JVM wants to link a call site that requires a dynamic type check.
* Name is a type-checking invoker, invokeExact or invoke.
* Return a JVM method (MemberName) to handle the invoking.
* The method assumes the following arguments on the stack:
* 0: the method handle being invoked
* 1-N: the arguments to the method handle invocation
* N+1: an implicitly added type argument (the given MethodType)
*/
static MemberName linkMethod(Class> callerClass, int refKind,
Class> defc, String name, Object type,
Object[] appendixResult) {
if (!TRACE_METHOD_LINKAGE)
return linkMethodImpl(callerClass, refKind, defc, name, type, appendixResult);
return linkMethodTracing(callerClass, refKind, defc, name, type, appendixResult);
}
static MemberName linkMethodImpl(Class> callerClass, int refKind,
Class> defc, String name, Object type,
Object[] appendixResult) {
try {
if (defc == MethodHandle.class && refKind == REF_invokeVirtual) {
switch (name) {
case "invoke":
return Invokers.genericInvokerMethod(fixMethodType(callerClass, type), appendixResult);
case "invokeExact":
return Invokers.exactInvokerMethod(fixMethodType(callerClass, type), appendixResult);
}
}
} catch (Throwable ex) {
if (ex instanceof LinkageError)
throw (LinkageError) ex;
else
throw new LinkageError(ex.getMessage(), ex);
}
throw new LinkageError("no such method "+defc.getName()+"."+name+type);
}
private static MethodType fixMethodType(Class> callerClass, Object type) {
if (type instanceof MethodType)
return (MethodType) type;
else
return MethodType.fromMethodDescriptorString((String)type, callerClass.getClassLoader());
}
// Tracing logic:
static MemberName linkMethodTracing(Class> callerClass, int refKind,
Class> defc, String name, Object type,
Object[] appendixResult) {
System.out.println("linkMethod "+defc.getName()+"."+
name+type+"/"+Integer.toHexString(refKind));
try {
MemberName res = linkMethodImpl(callerClass, refKind, defc, name, type, appendixResult);
System.out.println("linkMethod => "+res+" + "+appendixResult[0]);
return res;
} catch (Throwable ex) {
System.out.println("linkMethod => throw "+ex);
throw ex;
}
}
/**
* The JVM is resolving a CONSTANT_MethodHandle CP entry. And it wants our help.
* It will make an up-call to this method. (Do not change the name or signature.)
* The type argument is a Class for field requests and a MethodType for non-fields.
*
* Recent versions of the JVM may also pass a resolved MemberName for the type.
* In that case, the name is ignored and may be null.
*/
static MethodHandle linkMethodHandleConstant(Class> callerClass, int refKind,
Class> defc, String name, Object type) {
try {
Lookup lookup = IMPL_LOOKUP.in(callerClass);
assert(refKindIsValid(refKind));
return lookup.linkMethodHandleConstant((byte) refKind, defc, name, type);
} catch (IllegalAccessException ex) {
Error err = new IllegalAccessError(ex.getMessage());
// err.initCause(ex);
throw err;
} catch (ReflectiveOperationException ex) {
Error err = new IncompatibleClassChangeError();
err.initCause(ex);
throw err;
}
}
/**
* Is this method a caller-sensitive method?
* I.e., does it call Reflection.getCallerClass or a similer method
* to ask about the identity of its caller?
*/
static boolean isCallerSensitive(MemberName mem) {
if (!mem.isInvocable()) return false; // fields are not caller sensitive
return mem.isCallerSensitive() || canBeCalledVirtual(mem);
}
static boolean canBeCalledVirtual(MemberName mem) {
assert(mem.isInvocable());
Class> defc = mem.getDeclaringClass();
switch (mem.getName()) {
case "checkMemberAccess":
return canBeCalledVirtual(mem, java.lang.SecurityManager.class);
case "getContextClassLoader":
return canBeCalledVirtual(mem, java.lang.Thread.class);
}
return false;
}
static boolean canBeCalledVirtual(MemberName symbolicRef, Class> definingClass) {
Class> symbolicRefClass = symbolicRef.getDeclaringClass();
if (symbolicRefClass == definingClass) return true;
if (symbolicRef.isStatic() || symbolicRef.isPrivate()) return false;
return (definingClass.isAssignableFrom(symbolicRefClass) || // Msym overrides Mdef
symbolicRefClass.isInterface()); // Mdef implements Msym
}
}