8265135: Reduce work initializing VarForms
Reviewed-by: psandoz, mchung
This commit is contained in:
parent
d9e40dd593
commit
5303ccb885
@ -3644,9 +3644,8 @@ return mh1;
|
|||||||
|
|
||||||
MemberName resolveOrFail(byte refKind, Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
|
MemberName resolveOrFail(byte refKind, Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
|
||||||
checkSymbolicClass(refc); // do this before attempting to resolve
|
checkSymbolicClass(refc); // do this before attempting to resolve
|
||||||
Objects.requireNonNull(name);
|
|
||||||
Objects.requireNonNull(type);
|
Objects.requireNonNull(type);
|
||||||
checkMethodName(refKind, name); // NPE check on name
|
checkMethodName(refKind, name); // implicit null-check of name
|
||||||
return IMPL_NAMES.resolveOrFail(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(), allowedModes,
|
return IMPL_NAMES.resolveOrFail(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(), allowedModes,
|
||||||
NoSuchMethodException.class);
|
NoSuchMethodException.class);
|
||||||
}
|
}
|
||||||
@ -3669,6 +3668,19 @@ return mh1;
|
|||||||
return IMPL_NAMES.resolveOrNull(refKind, member, lookupClassOrNull(), allowedModes);
|
return IMPL_NAMES.resolveOrNull(refKind, member, lookupClassOrNull(), allowedModes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MemberName resolveOrNull(byte refKind, Class<?> refc, String name, MethodType type) {
|
||||||
|
// do this before attempting to resolve
|
||||||
|
if (!isClassAccessible(refc)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Objects.requireNonNull(type);
|
||||||
|
// implicit null-check of name
|
||||||
|
if (name.startsWith("<") && refKind != REF_newInvokeSpecial) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return IMPL_NAMES.resolveOrNull(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(), allowedModes);
|
||||||
|
}
|
||||||
|
|
||||||
void checkSymbolicClass(Class<?> refc) throws IllegalAccessException {
|
void checkSymbolicClass(Class<?> refc) throws IllegalAccessException {
|
||||||
if (!isClassAccessible(refc)) {
|
if (!isClassAccessible(refc)) {
|
||||||
throw new MemberName(refc).makeAccessException("symbolic reference class is not accessible", this);
|
throw new MemberName(refc).makeAccessException("symbolic reference class is not accessible", this);
|
||||||
@ -3687,7 +3699,6 @@ return mh1;
|
|||||||
throw new NoSuchMethodException("illegal method name: "+name);
|
throw new NoSuchMethodException("illegal method name: "+name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find my trustable caller class if m is a caller sensitive method.
|
* Find my trustable caller class if m is a caller sensitive method.
|
||||||
* If this lookup object has original full privilege access, then the caller class is the lookupClass.
|
* If this lookup object has original full privilege access, then the caller class is the lookupClass.
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
package java.lang.invoke;
|
package java.lang.invoke;
|
||||||
|
|
||||||
|
import jdk.internal.vm.annotation.DontInline;
|
||||||
import jdk.internal.vm.annotation.ForceInline;
|
import jdk.internal.vm.annotation.ForceInline;
|
||||||
import jdk.internal.vm.annotation.Stable;
|
import jdk.internal.vm.annotation.Stable;
|
||||||
|
|
||||||
@ -33,18 +34,24 @@ import java.lang.reflect.Modifier;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A var handle form containing a set of member name, one for each operation.
|
* A var handle form containing a set of member name, one for each operation.
|
||||||
* Each member characterizes a static method.
|
* Each member characterizes a static method.
|
||||||
*/
|
*/
|
||||||
final class VarForm {
|
final class VarForm {
|
||||||
|
|
||||||
|
final Class<?> implClass;
|
||||||
|
|
||||||
final @Stable MethodType[] methodType_table;
|
final @Stable MethodType[] methodType_table;
|
||||||
|
|
||||||
final @Stable MemberName[] memberName_table;
|
final @Stable MemberName[] memberName_table;
|
||||||
|
|
||||||
VarForm(Class<?> implClass, Class<?> receiver, Class<?> value, Class<?>... intermediate) {
|
VarForm(Class<?> implClass, Class<?> receiver, Class<?> value, Class<?>... intermediate) {
|
||||||
this.methodType_table = new MethodType[VarHandle.AccessType.values().length];
|
this.methodType_table = new MethodType[VarHandle.AccessType.values().length];
|
||||||
|
this.memberName_table = new MemberName[VarHandle.AccessMode.values().length];
|
||||||
|
this.implClass = implClass;
|
||||||
if (receiver == null) {
|
if (receiver == null) {
|
||||||
initMethodTypes(value, intermediate);
|
initMethodTypes(value, intermediate);
|
||||||
} else {
|
} else {
|
||||||
@ -53,37 +60,46 @@ final class VarForm {
|
|||||||
System.arraycopy(intermediate, 0, coordinates, 1, intermediate.length);
|
System.arraycopy(intermediate, 0, coordinates, 1, intermediate.length);
|
||||||
initMethodTypes(value, coordinates);
|
initMethodTypes(value, coordinates);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO lazily calculate
|
|
||||||
this.memberName_table = linkFromStatic(implClass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used by IndirectVarHandle
|
||||||
VarForm(Class<?> value, Class<?>[] coordinates) {
|
VarForm(Class<?> value, Class<?>[] coordinates) {
|
||||||
this.methodType_table = new MethodType[VarHandle.AccessType.values().length];
|
this.methodType_table = new MethodType[VarHandle.AccessType.values().length];
|
||||||
this.memberName_table = null;
|
this.memberName_table = null;
|
||||||
|
this.implClass = null;
|
||||||
initMethodTypes(value, coordinates);
|
initMethodTypes(value, coordinates);
|
||||||
}
|
}
|
||||||
|
|
||||||
void initMethodTypes(Class<?> value, Class<?>... coordinates) {
|
void initMethodTypes(Class<?> value, Class<?>... coordinates) {
|
||||||
// (Receiver, <Intermediates>)Value
|
Class<?> erasedValue = MethodTypeForm.canonicalize(value, MethodTypeForm.ERASE);
|
||||||
methodType_table[VarHandle.AccessType.GET.ordinal()] =
|
Class<?>[] erasedCoordinates = MethodTypeForm.canonicalizeAll(coordinates, MethodTypeForm.ERASE);
|
||||||
MethodType.methodType(value, coordinates).erase();
|
|
||||||
|
|
||||||
// (Receiver, <Intermediates>, Value)void
|
if (erasedValue != null) {
|
||||||
methodType_table[VarHandle.AccessType.SET.ordinal()] =
|
value = erasedValue;
|
||||||
MethodType.methodType(void.class, coordinates).appendParameterTypes(value).erase();
|
}
|
||||||
|
if (erasedCoordinates != null) {
|
||||||
|
coordinates = erasedCoordinates;
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodType type = MethodType.methodType(value, coordinates);
|
||||||
|
|
||||||
|
// (Receiver, <Intermediates>)Value
|
||||||
|
methodType_table[VarHandle.AccessType.GET.ordinal()] = type;
|
||||||
|
|
||||||
// (Receiver, <Intermediates>, Value)Value
|
// (Receiver, <Intermediates>, Value)Value
|
||||||
methodType_table[VarHandle.AccessType.GET_AND_UPDATE.ordinal()] =
|
type = methodType_table[VarHandle.AccessType.GET_AND_UPDATE.ordinal()] =
|
||||||
MethodType.methodType(value, coordinates).appendParameterTypes(value).erase();
|
type.appendParameterTypes(value);
|
||||||
|
|
||||||
|
// (Receiver, <Intermediates>, Value)void
|
||||||
|
methodType_table[VarHandle.AccessType.SET.ordinal()] = type.changeReturnType(void.class);
|
||||||
|
|
||||||
|
// (Receiver, <Intermediates>, Value, Value)Value
|
||||||
|
type = methodType_table[VarHandle.AccessType.COMPARE_AND_EXCHANGE.ordinal()] =
|
||||||
|
type.appendParameterTypes(value);
|
||||||
|
|
||||||
// (Receiver, <Intermediates>, Value, Value)boolean
|
// (Receiver, <Intermediates>, Value, Value)boolean
|
||||||
methodType_table[VarHandle.AccessType.COMPARE_AND_SET.ordinal()] =
|
methodType_table[VarHandle.AccessType.COMPARE_AND_SET.ordinal()] =
|
||||||
MethodType.methodType(boolean.class, coordinates).appendParameterTypes(value, value).erase();
|
type.changeReturnType(boolean.class);
|
||||||
|
|
||||||
// (Receiver, <Intermediates>, Value, Value)Value
|
|
||||||
methodType_table[VarHandle.AccessType.COMPARE_AND_EXCHANGE.ordinal()] =
|
|
||||||
MethodType.methodType(value, coordinates).appendParameterTypes(value, value).erase();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
@ -93,14 +109,30 @@ final class VarForm {
|
|||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
final MemberName getMemberName(int mode) {
|
final MemberName getMemberName(int mode) {
|
||||||
// TODO calculate lazily
|
MemberName mn = getMemberNameOrNull(mode);
|
||||||
MemberName mn = memberName_table[mode];
|
|
||||||
if (mn == null) {
|
if (mn == null) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
return mn;
|
return mn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
final MemberName getMemberNameOrNull(int mode) {
|
||||||
|
MemberName mn = memberName_table[mode];
|
||||||
|
if (mn == null) {
|
||||||
|
mn = resolveMemberName(mode);
|
||||||
|
}
|
||||||
|
return mn;
|
||||||
|
}
|
||||||
|
|
||||||
|
@DontInline
|
||||||
|
MemberName resolveMemberName(int mode) {
|
||||||
|
AccessMode value = AccessMode.values()[mode];
|
||||||
|
String methodName = value.methodName();
|
||||||
|
MethodType type = methodType_table[value.at.ordinal()].insertParameterTypes(0, VarHandle.class);
|
||||||
|
return memberName_table[mode] = MethodHandles.Lookup.IMPL_LOOKUP
|
||||||
|
.resolveOrNull(REF_invokeStatic, implClass, methodName, type);
|
||||||
|
}
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
MethodType[] methodType_V_table;
|
MethodType[] methodType_V_table;
|
||||||
@ -125,25 +157,4 @@ final class VarForm {
|
|||||||
}
|
}
|
||||||
return table[type];
|
return table[type];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Link all signature polymorphic methods.
|
|
||||||
*/
|
|
||||||
private static MemberName[] linkFromStatic(Class<?> implClass) {
|
|
||||||
MemberName[] table = new MemberName[AccessMode.values().length];
|
|
||||||
|
|
||||||
for (Class<?> c = implClass; c != VarHandle.class; c = c.getSuperclass()) {
|
|
||||||
for (Method m : c.getDeclaredMethods()) {
|
|
||||||
if (Modifier.isStatic(m.getModifiers())) {
|
|
||||||
AccessMode am = AccessMode.methodNameToAccessMode.get(m.getName());
|
|
||||||
if (am != null) {
|
|
||||||
assert table[am.ordinal()] == null;
|
|
||||||
table[am.ordinal()] = new MemberName(m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1938,11 +1938,6 @@ public abstract class VarHandle implements Constable {
|
|||||||
if (am != null) return am;
|
if (am != null) return am;
|
||||||
throw new IllegalArgumentException("No AccessMode value for method name " + methodName);
|
throw new IllegalArgumentException("No AccessMode value for method name " + methodName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
|
||||||
static MemberName getMemberName(int ordinal, VarForm vform) {
|
|
||||||
return vform.memberName_table[ordinal];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class AccessDescriptor {
|
static final class AccessDescriptor {
|
||||||
@ -2045,7 +2040,7 @@ public abstract class VarHandle implements Constable {
|
|||||||
* {@code false}.
|
* {@code false}.
|
||||||
*/
|
*/
|
||||||
public final boolean isAccessModeSupported(AccessMode accessMode) {
|
public final boolean isAccessModeSupported(AccessMode accessMode) {
|
||||||
return AccessMode.getMemberName(accessMode.ordinal(), vform) != null;
|
return vform.getMemberNameOrNull(accessMode.ordinal()) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2068,8 +2063,7 @@ public abstract class VarHandle implements Constable {
|
|||||||
* @return a method handle bound to this VarHandle and the given access mode
|
* @return a method handle bound to this VarHandle and the given access mode
|
||||||
*/
|
*/
|
||||||
public MethodHandle toMethodHandle(AccessMode accessMode) {
|
public MethodHandle toMethodHandle(AccessMode accessMode) {
|
||||||
MemberName mn = AccessMode.getMemberName(accessMode.ordinal(), vform);
|
if (isAccessModeSupported(accessMode)) {
|
||||||
if (mn != null) {
|
|
||||||
MethodHandle mh = getMethodHandle(accessMode.ordinal());
|
MethodHandle mh = getMethodHandle(accessMode.ordinal());
|
||||||
return mh.bindTo(this);
|
return mh.bindTo(this);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user