< prev index next >
src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java
Print this page
*** 1,7 ****
/*
! * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
--- 1,7 ----
/*
! * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
*** 70,99 ****
this.member = member;
}
// Factory methods:
! static DirectMethodHandle make(byte refKind, Class<?> receiver, MemberName member) {
MethodType mtype = member.getMethodOrFieldType();
if (!member.isStatic()) {
! if (!member.getDeclaringClass().isAssignableFrom(receiver) || member.isConstructor())
throw new InternalError(member.toString());
! mtype = mtype.insertParameterTypes(0, receiver);
}
if (!member.isField()) {
switch (refKind) {
case REF_invokeSpecial: {
member = member.asSpecial();
! LambdaForm lform = preparedLambdaForm(member);
! return new Special(mtype, lform, member);
}
case REF_invokeInterface: {
! LambdaForm lform = preparedLambdaForm(member);
! return new Interface(mtype, lform, member, receiver);
}
default: {
! LambdaForm lform = preparedLambdaForm(member);
return new DirectMethodHandle(mtype, lform, member);
}
}
} else {
LambdaForm lform = preparedFieldLambdaForm(member);
--- 70,103 ----
this.member = member;
}
// Factory methods:
! static DirectMethodHandle make(byte refKind, Class<?> refc, MemberName member, Class<?> callerClass) {
MethodType mtype = member.getMethodOrFieldType();
if (!member.isStatic()) {
! 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);
*** 106,120 ****
assert(offset == (int)offset);
return new Accessor(mtype, lform, member, (int)offset);
}
}
}
! static DirectMethodHandle make(Class<?> receiver, MemberName member) {
byte refKind = member.getReferenceKind();
if (refKind == REF_invokeSpecial)
refKind = REF_invokeVirtual;
! return make(refKind, receiver, member);
}
static DirectMethodHandle make(MemberName member) {
if (member.isConstructor())
return makeAllocator(member);
return make(member.getDeclaringClass(), member);
--- 110,124 ----
assert(offset == (int)offset);
return new Accessor(mtype, lform, member, (int)offset);
}
}
}
! static DirectMethodHandle make(Class<?> refc, MemberName member) {
byte refKind = member.getReferenceKind();
if (refKind == REF_invokeSpecial)
refKind = REF_invokeVirtual;
! return make(refKind, refc, member, null /* no callerClass context */);
}
static DirectMethodHandle make(MemberName member) {
if (member.isConstructor())
return makeAllocator(member);
return make(member.getDeclaringClass(), member);
*** 159,169 ****
/**
* 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) {
assert(m.isInvocable()) : m; // call preparedFieldLambdaForm instead
MethodType mtype = m.getInvocationType().basicType();
assert(!m.isMethodHandleInvoke()) : m;
int which;
switch (m.getReferenceKind()) {
--- 163,173 ----
/**
* 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()) {
*** 177,211 ****
if (which == LF_INVSTATIC && shouldBeInitialized(m)) {
// precompute the barrier-free version:
preparedLambdaForm(mtype, which);
which = LF_INVSTATIC_INIT;
}
LambdaForm lform = preparedLambdaForm(mtype, which);
maybeCompile(lform, m);
assert(lform.methodType().dropParameterTypes(0, 1)
.equals(m.getInvocationType().basicType()))
: Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
return lform;
}
private static LambdaForm preparedLambdaForm(MethodType mtype, int which) {
LambdaForm lform = mtype.form().cachedLambdaForm(which);
if (lform != null) return lform;
lform = makePreparedLambdaForm(mtype, which);
return mtype.form().setCachedLambdaForm(which, lform);
}
static LambdaForm makePreparedLambdaForm(MethodType mtype, int which) {
boolean needsInit = (which == LF_INVSTATIC_INIT);
boolean doesAlloc = (which == LF_NEWINVSPECIAL);
! boolean needsReceiverCheck = (which == LF_INVINTERFACE);
String linkerName;
LambdaForm.Kind kind;
switch (which) {
case LF_INVVIRTUAL: linkerName = "linkToVirtual"; kind = DIRECT_INVOKE_VIRTUAL; break;
case LF_INVSTATIC: linkerName = "linkToStatic"; kind = DIRECT_INVOKE_STATIC; break;
case LF_INVSTATIC_INIT:linkerName = "linkToStatic"; kind = DIRECT_INVOKE_STATIC_INIT; break;
case LF_INVSPECIAL: linkerName = "linkToSpecial"; kind = DIRECT_INVOKE_SPECIAL; break;
case LF_INVINTERFACE: linkerName = "linkToInterface"; kind = DIRECT_INVOKE_INTERFACE; break;
case LF_NEWINVSPECIAL: linkerName = "linkToSpecial"; kind = DIRECT_NEW_INVOKE_SPECIAL; break;
default: throw new InternalError("which="+which);
}
--- 181,225 ----
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)
.equals(m.getInvocationType().basicType()))
: 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;
lform = makePreparedLambdaForm(mtype, which);
return mtype.form().setCachedLambdaForm(which, lform);
}
static LambdaForm makePreparedLambdaForm(MethodType mtype, int which) {
boolean needsInit = (which == LF_INVSTATIC_INIT);
boolean doesAlloc = (which == LF_NEWINVSPECIAL);
! boolean needsReceiverCheck = (which == LF_INVINTERFACE ||
! which == LF_INVSPECIAL_IFC);
!
String linkerName;
LambdaForm.Kind kind;
switch (which) {
case LF_INVVIRTUAL: linkerName = "linkToVirtual"; kind = DIRECT_INVOKE_VIRTUAL; break;
case LF_INVSTATIC: linkerName = "linkToStatic"; kind = DIRECT_INVOKE_STATIC; break;
case LF_INVSTATIC_INIT:linkerName = "linkToStatic"; kind = DIRECT_INVOKE_STATIC_INIT; break;
+ case LF_INVSPECIAL_IFC:linkerName = "linkToSpecial"; kind = DIRECT_INVOKE_SPECIAL_IFC; break;
case LF_INVSPECIAL: linkerName = "linkToSpecial"; kind = DIRECT_INVOKE_SPECIAL; break;
case LF_INVINTERFACE: linkerName = "linkToInterface"; kind = DIRECT_INVOKE_INTERFACE; break;
case LF_NEWINVSPECIAL: linkerName = "linkToSpecial"; kind = DIRECT_NEW_INVOKE_SPECIAL; break;
default: throw new InternalError("which="+which);
}
*** 374,393 ****
((DirectMethodHandle)mh).ensureInitialized();
}
/** This subclass represents invokespecial instructions. */
static class Special extends DirectMethodHandle {
! private Special(MethodType mtype, LambdaForm form, MemberName member) {
super(mtype, form, member);
}
@Override
boolean isInvokeSpecial() {
return true;
}
@Override
MethodHandle copyWith(MethodType mt, LambdaForm lf) {
! return new Special(mt, lf, member);
}
}
/** This subclass represents invokeinterface instructions. */
static class Interface extends DirectMethodHandle {
--- 388,417 ----
((DirectMethodHandle)mh).ensureInitialized();
}
/** This subclass represents invokespecial instructions. */
static class Special extends DirectMethodHandle {
! private final Class<?> caller;
! private Special(MethodType mtype, LambdaForm form, MemberName member, Class<?> caller) {
super(mtype, form, member);
+ this.caller = caller;
}
@Override
boolean isInvokeSpecial() {
return true;
}
@Override
MethodHandle copyWith(MethodType mt, LambdaForm lf) {
! return new Special(mt, lf, member, caller);
! }
! Object checkReceiver(Object recv) {
! if (!caller.isInstance(recv)) {
! String msg = String.format("Receiver class %s is not a subclass of caller class %s",
! recv.getClass().getName(), caller.getName());
! throw new IncompatibleClassChangeError(msg);
! }
! return recv;
}
}
/** This subclass represents invokeinterface instructions. */
static class Interface extends DirectMethodHandle {
*** 399,419 ****
}
@Override
MethodHandle copyWith(MethodType mt, LambdaForm lf) {
return new Interface(mt, lf, member, refc);
}
!
Object checkReceiver(Object recv) {
if (!refc.isInstance(recv)) {
! String msg = String.format("Class %s does not implement the requested interface %s",
recv.getClass().getName(), refc.getName());
throw new IncompatibleClassChangeError(msg);
}
return recv;
}
}
/** This subclass handles constructor references. */
static class Constructor extends DirectMethodHandle {
final MemberName initMethod;
final Class<?> instanceClass;
--- 423,449 ----
}
@Override
MethodHandle copyWith(MethodType mt, LambdaForm lf) {
return new Interface(mt, lf, member, refc);
}
! @Override
Object checkReceiver(Object recv) {
if (!refc.isInstance(recv)) {
! String msg = String.format("Receiver class %s does not implement the requested interface %s",
recv.getClass().getName(), refc.getName());
throw new IncompatibleClassChangeError(msg);
}
return recv;
}
}
+ /** Used for interface receiver type checks, by Interface and Special modes. */
+ Object checkReceiver(Object recv) {
+ throw new InternalError("Should only be invoked on a subclass");
+ }
+
+
/** This subclass handles constructor references. */
static class Constructor extends DirectMethodHandle {
final MemberName initMethod;
final Class<?> instanceClass;
*** 821,834 ****
MemberName member = new MemberName(MethodHandleStatics.class, "UNSAFE", Unsafe.class, REF_getField);
return new NamedFunction(
MemberName.getFactory()
.resolveOrFail(REF_getField, member, DirectMethodHandle.class, NoSuchMethodException.class));
case NF_checkReceiver:
! member = new MemberName(Interface.class, "checkReceiver", OBJ_OBJ_TYPE, REF_invokeVirtual);
return new NamedFunction(
MemberName.getFactory()
! .resolveOrFail(REF_invokeVirtual, member, Interface.class, NoSuchMethodException.class));
default:
throw newInternalError("Unknown function: " + func);
}
} catch (ReflectiveOperationException ex) {
throw newInternalError(ex);
--- 851,864 ----
MemberName member = new MemberName(MethodHandleStatics.class, "UNSAFE", Unsafe.class, REF_getField);
return new NamedFunction(
MemberName.getFactory()
.resolveOrFail(REF_getField, member, DirectMethodHandle.class, NoSuchMethodException.class));
case NF_checkReceiver:
! member = new MemberName(DirectMethodHandle.class, "checkReceiver", OBJ_OBJ_TYPE, REF_invokeVirtual);
return new NamedFunction(
MemberName.getFactory()
! .resolveOrFail(REF_invokeVirtual, member, DirectMethodHandle.class, NoSuchMethodException.class));
default:
throw newInternalError("Unknown function: " + func);
}
} catch (ReflectiveOperationException ex) {
throw newInternalError(ex);
< prev index next >