< prev index next >
src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java
Print this page
rev 50246 : imported patch jep181-rev1
*** 56,66 ****
private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) {
super(mtype, form);
if (!member.isResolved()) throw new InternalError();
if (member.getDeclaringClass().isInterface() &&
! member.isMethod() && !member.isAbstract()) {
// Check for corner case: invokeinterface of Object method
MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null);
if (m != null && m.isPublic()) {
assert(member.getReferenceKind() == m.getReferenceKind()); // else this.form is wrong
--- 56,67 ----
private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) {
super(mtype, form);
if (!member.isResolved()) throw new InternalError();
if (member.getDeclaringClass().isInterface() &&
! member.getReferenceKind() == REF_invokeInterface &&
! member.isMethod() && !member.isAbstract()) {
// Check for corner case: invokeinterface of Object method
MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null);
if (m != null && m.isPublic()) {
assert(member.getReferenceKind() == m.getReferenceKind()); // else this.form is wrong
*** 78,103 ****
if (!member.getDeclaringClass().isAssignableFrom(refc) || member.isConstructor())
throw new InternalError(member.toString());
mtype = mtype.insertParameterTypes(0, refc);
}
if (!member.isField()) {
switch (refKind) {
case REF_invokeSpecial: {
member = member.asSpecial();
! LambdaForm lform = preparedLambdaForm(member, callerClass);
! Class<?> checkClass = refc; // Class to use for receiver type check
! if (callerClass != null) {
! checkClass = callerClass; // potentially strengthen to caller class
}
! return new Special(mtype, lform, member, checkClass);
}
case REF_invokeInterface: {
! LambdaForm lform = preparedLambdaForm(member, callerClass);
return new Interface(mtype, lform, member, refc);
}
default: {
! LambdaForm lform = preparedLambdaForm(member, callerClass);
return new DirectMethodHandle(mtype, lform, member);
}
}
} else {
LambdaForm lform = preparedFieldLambdaForm(member);
--- 79,110 ----
if (!member.getDeclaringClass().isAssignableFrom(refc) || member.isConstructor())
throw new InternalError(member.toString());
mtype = mtype.insertParameterTypes(0, refc);
}
if (!member.isField()) {
+ // refKind reflects the original type of lookup via findSpecial or
+ // findVirtual etc.
switch (refKind) {
case REF_invokeSpecial: {
member = member.asSpecial();
! // if caller is an interface we need to adapt to get the
! // receiver check inserted
! if (callerClass == null) {
! throw new InternalError("callerClass must not be null for REF_invokeSpecial");
}
! LambdaForm lform = preparedLambdaForm(member, callerClass.isInterface());
! return new Special(mtype, lform, member, callerClass);
}
case REF_invokeInterface: {
! // for interfaces we always need the receiver typecheck,
! // so we always pass 'true' to ensure we adapt if needed
! // to include the REF_invokeSpecial case
! LambdaForm lform = preparedLambdaForm(member, true);
return new Interface(mtype, lform, member, refc);
}
default: {
! LambdaForm lform = preparedLambdaForm(member);
return new DirectMethodHandle(mtype, lform, member);
}
}
} else {
LambdaForm lform = preparedFieldLambdaForm(member);
*** 163,177 ****
/**
* Create a LF which can invoke the given method.
* Cache and share this structure among all methods with
* the same basicType and refKind.
*/
! private static LambdaForm preparedLambdaForm(MemberName m, Class<?> callerClass) {
assert(m.isInvocable()) : m; // call preparedFieldLambdaForm instead
MethodType mtype = m.getInvocationType().basicType();
assert(!m.isMethodHandleInvoke()) : m;
int which;
switch (m.getReferenceKind()) {
case REF_invokeVirtual: which = LF_INVVIRTUAL; break;
case REF_invokeStatic: which = LF_INVSTATIC; break;
case REF_invokeSpecial: which = LF_INVSPECIAL; break;
case REF_invokeInterface: which = LF_INVINTERFACE; break;
--- 170,189 ----
/**
* Create a LF which can invoke the given method.
* Cache and share this structure among all methods with
* the same basicType and refKind.
*/
! private static LambdaForm preparedLambdaForm(MemberName m, boolean adaptToSpecialIfc) {
assert(m.isInvocable()) : m; // call preparedFieldLambdaForm instead
MethodType mtype = m.getInvocationType().basicType();
assert(!m.isMethodHandleInvoke()) : m;
int which;
+ // MemberName.getReferenceKind represents the JVM optimized form of the call
+ // as distinct from the "kind" passed to DMH.make which represents the original
+ // bytecode-equivalent request. Specifically private/final methods that use a direct
+ // call have getReferenceKind adapted to REF_invokeSpecial, even though the actual
+ // invocation mode may be invokevirtual or invokeinterface.
switch (m.getReferenceKind()) {
case REF_invokeVirtual: which = LF_INVVIRTUAL; break;
case REF_invokeStatic: which = LF_INVSTATIC; break;
case REF_invokeSpecial: which = LF_INVSPECIAL; break;
case REF_invokeInterface: which = LF_INVINTERFACE; break;
*** 181,191 ****
if (which == LF_INVSTATIC && shouldBeInitialized(m)) {
// precompute the barrier-free version:
preparedLambdaForm(mtype, which);
which = LF_INVSTATIC_INIT;
}
! if (which == LF_INVSPECIAL && callerClass != null && callerClass.isInterface()) {
which = LF_INVSPECIAL_IFC;
}
LambdaForm lform = preparedLambdaForm(mtype, which);
maybeCompile(lform, m);
assert(lform.methodType().dropParameterTypes(0, 1)
--- 193,203 ----
if (which == LF_INVSTATIC && shouldBeInitialized(m)) {
// precompute the barrier-free version:
preparedLambdaForm(mtype, which);
which = LF_INVSTATIC_INIT;
}
! if (which == LF_INVSPECIAL && adaptToSpecialIfc) {
which = LF_INVSPECIAL_IFC;
}
LambdaForm lform = preparedLambdaForm(mtype, which);
maybeCompile(lform, m);
assert(lform.methodType().dropParameterTypes(0, 1)
*** 193,203 ****
: Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
return lform;
}
private static LambdaForm preparedLambdaForm(MemberName m) {
! return preparedLambdaForm(m, null);
}
private static LambdaForm preparedLambdaForm(MethodType mtype, int which) {
LambdaForm lform = mtype.form().cachedLambdaForm(which);
if (lform != null) return lform;
--- 205,215 ----
: Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
return lform;
}
private static LambdaForm preparedLambdaForm(MemberName m) {
! return preparedLambdaForm(m, false);
}
private static LambdaForm preparedLambdaForm(MethodType mtype, int which) {
LambdaForm lform = mtype.form().cachedLambdaForm(which);
if (lform != null) return lform;
< prev index next >