Skip to content

Commit 5303ccb

Browse files
committedApr 19, 2021
8265135: Reduce work initializing VarForms
Reviewed-by: psandoz, mchung
1 parent d9e40dd commit 5303ccb

File tree

3 files changed

+65
-49
lines changed

3 files changed

+65
-49
lines changed
 

‎src/java.base/share/classes/java/lang/invoke/MethodHandles.java

+14-3
Original file line numberDiff line numberDiff line change
@@ -3644,9 +3644,8 @@ MemberName resolveOrFail(byte refKind, Class<?> refc, String name, Class<?> type
36443644

36453645
MemberName resolveOrFail(byte refKind, Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
36463646
checkSymbolicClass(refc); // do this before attempting to resolve
3647-
Objects.requireNonNull(name);
36483647
Objects.requireNonNull(type);
3649-
checkMethodName(refKind, name); // NPE check on name
3648+
checkMethodName(refKind, name); // implicit null-check of name
36503649
return IMPL_NAMES.resolveOrFail(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(), allowedModes,
36513650
NoSuchMethodException.class);
36523651
}
@@ -3669,6 +3668,19 @@ MemberName resolveOrNull(byte refKind, MemberName member) {
36693668
return IMPL_NAMES.resolveOrNull(refKind, member, lookupClassOrNull(), allowedModes);
36703669
}
36713670

3671+
MemberName resolveOrNull(byte refKind, Class<?> refc, String name, MethodType type) {
3672+
// do this before attempting to resolve
3673+
if (!isClassAccessible(refc)) {
3674+
return null;
3675+
}
3676+
Objects.requireNonNull(type);
3677+
// implicit null-check of name
3678+
if (name.startsWith("<") && refKind != REF_newInvokeSpecial) {
3679+
return null;
3680+
}
3681+
return IMPL_NAMES.resolveOrNull(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(), allowedModes);
3682+
}
3683+
36723684
void checkSymbolicClass(Class<?> refc) throws IllegalAccessException {
36733685
if (!isClassAccessible(refc)) {
36743686
throw new MemberName(refc).makeAccessException("symbolic reference class is not accessible", this);
@@ -3687,7 +3699,6 @@ void checkMethodName(byte refKind, String name) throws NoSuchMethodException {
36873699
throw new NoSuchMethodException("illegal method name: "+name);
36883700
}
36893701

3690-
36913702
/**
36923703
* Find my trustable caller class if m is a caller sensitive method.
36933704
* If this lookup object has original full privilege access, then the caller class is the lookupClass.

‎src/java.base/share/classes/java/lang/invoke/VarForm.java

+49-38
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
*/
2525
package java.lang.invoke;
2626

27+
import jdk.internal.vm.annotation.DontInline;
2728
import jdk.internal.vm.annotation.ForceInline;
2829
import jdk.internal.vm.annotation.Stable;
2930

@@ -33,18 +34,24 @@
3334
import java.util.ArrayList;
3435
import java.util.List;
3536

37+
import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
38+
3639
/**
3740
* A var handle form containing a set of member name, one for each operation.
3841
* Each member characterizes a static method.
3942
*/
4043
final class VarForm {
4144

45+
final Class<?> implClass;
46+
4247
final @Stable MethodType[] methodType_table;
4348

4449
final @Stable MemberName[] memberName_table;
4550

4651
VarForm(Class<?> implClass, Class<?> receiver, Class<?> value, Class<?>... intermediate) {
4752
this.methodType_table = new MethodType[VarHandle.AccessType.values().length];
53+
this.memberName_table = new MemberName[VarHandle.AccessMode.values().length];
54+
this.implClass = implClass;
4855
if (receiver == null) {
4956
initMethodTypes(value, intermediate);
5057
} else {
@@ -53,37 +60,46 @@ final class VarForm {
5360
System.arraycopy(intermediate, 0, coordinates, 1, intermediate.length);
5461
initMethodTypes(value, coordinates);
5562
}
56-
57-
// TODO lazily calculate
58-
this.memberName_table = linkFromStatic(implClass);
5963
}
6064

65+
// Used by IndirectVarHandle
6166
VarForm(Class<?> value, Class<?>[] coordinates) {
6267
this.methodType_table = new MethodType[VarHandle.AccessType.values().length];
6368
this.memberName_table = null;
69+
this.implClass = null;
6470
initMethodTypes(value, coordinates);
6571
}
6672

6773
void initMethodTypes(Class<?> value, Class<?>... coordinates) {
74+
Class<?> erasedValue = MethodTypeForm.canonicalize(value, MethodTypeForm.ERASE);
75+
Class<?>[] erasedCoordinates = MethodTypeForm.canonicalizeAll(coordinates, MethodTypeForm.ERASE);
76+
77+
if (erasedValue != null) {
78+
value = erasedValue;
79+
}
80+
if (erasedCoordinates != null) {
81+
coordinates = erasedCoordinates;
82+
}
83+
84+
MethodType type = MethodType.methodType(value, coordinates);
85+
6886
// (Receiver, <Intermediates>)Value
69-
methodType_table[VarHandle.AccessType.GET.ordinal()] =
70-
MethodType.methodType(value, coordinates).erase();
87+
methodType_table[VarHandle.AccessType.GET.ordinal()] = type;
88+
89+
// (Receiver, <Intermediates>, Value)Value
90+
type = methodType_table[VarHandle.AccessType.GET_AND_UPDATE.ordinal()] =
91+
type.appendParameterTypes(value);
7192

7293
// (Receiver, <Intermediates>, Value)void
73-
methodType_table[VarHandle.AccessType.SET.ordinal()] =
74-
MethodType.methodType(void.class, coordinates).appendParameterTypes(value).erase();
94+
methodType_table[VarHandle.AccessType.SET.ordinal()] = type.changeReturnType(void.class);
7595

76-
// (Receiver, <Intermediates>, Value)Value
77-
methodType_table[VarHandle.AccessType.GET_AND_UPDATE.ordinal()] =
78-
MethodType.methodType(value, coordinates).appendParameterTypes(value).erase();
96+
// (Receiver, <Intermediates>, Value, Value)Value
97+
type = methodType_table[VarHandle.AccessType.COMPARE_AND_EXCHANGE.ordinal()] =
98+
type.appendParameterTypes(value);
7999

80100
// (Receiver, <Intermediates>, Value, Value)boolean
81101
methodType_table[VarHandle.AccessType.COMPARE_AND_SET.ordinal()] =
82-
MethodType.methodType(boolean.class, coordinates).appendParameterTypes(value, value).erase();
83-
84-
// (Receiver, <Intermediates>, Value, Value)Value
85-
methodType_table[VarHandle.AccessType.COMPARE_AND_EXCHANGE.ordinal()] =
86-
MethodType.methodType(value, coordinates).appendParameterTypes(value, value).erase();
102+
type.changeReturnType(boolean.class);
87103
}
88104

89105
@ForceInline
@@ -93,14 +109,30 @@ final MethodType getMethodType(int type) {
93109

94110
@ForceInline
95111
final MemberName getMemberName(int mode) {
96-
// TODO calculate lazily
97-
MemberName mn = memberName_table[mode];
112+
MemberName mn = getMemberNameOrNull(mode);
98113
if (mn == null) {
99114
throw new UnsupportedOperationException();
100115
}
101116
return mn;
102117
}
103118

119+
@ForceInline
120+
final MemberName getMemberNameOrNull(int mode) {
121+
MemberName mn = memberName_table[mode];
122+
if (mn == null) {
123+
mn = resolveMemberName(mode);
124+
}
125+
return mn;
126+
}
127+
128+
@DontInline
129+
MemberName resolveMemberName(int mode) {
130+
AccessMode value = AccessMode.values()[mode];
131+
String methodName = value.methodName();
132+
MethodType type = methodType_table[value.at.ordinal()].insertParameterTypes(0, VarHandle.class);
133+
return memberName_table[mode] = MethodHandles.Lookup.IMPL_LOOKUP
134+
.resolveOrNull(REF_invokeStatic, implClass, methodName, type);
135+
}
104136

105137
@Stable
106138
MethodType[] methodType_V_table;
@@ -125,25 +157,4 @@ final MethodType getMethodType_V(int type) {
125157
}
126158
return table[type];
127159
}
128-
129-
130-
/**
131-
* Link all signature polymorphic methods.
132-
*/
133-
private static MemberName[] linkFromStatic(Class<?> implClass) {
134-
MemberName[] table = new MemberName[AccessMode.values().length];
135-
136-
for (Class<?> c = implClass; c != VarHandle.class; c = c.getSuperclass()) {
137-
for (Method m : c.getDeclaredMethods()) {
138-
if (Modifier.isStatic(m.getModifiers())) {
139-
AccessMode am = AccessMode.methodNameToAccessMode.get(m.getName());
140-
if (am != null) {
141-
assert table[am.ordinal()] == null;
142-
table[am.ordinal()] = new MemberName(m);
143-
}
144-
}
145-
}
146-
}
147-
return table;
148-
}
149160
}

‎src/java.base/share/classes/java/lang/invoke/VarHandle.java

+2-8
Original file line numberDiff line numberDiff line change
@@ -1938,11 +1938,6 @@ public static AccessMode valueFromMethodName(String methodName) {
19381938
if (am != null) return am;
19391939
throw new IllegalArgumentException("No AccessMode value for method name " + methodName);
19401940
}
1941-
1942-
@ForceInline
1943-
static MemberName getMemberName(int ordinal, VarForm vform) {
1944-
return vform.memberName_table[ordinal];
1945-
}
19461941
}
19471942

19481943
static final class AccessDescriptor {
@@ -2045,7 +2040,7 @@ final MethodType accessModeTypeUncached(int accessTypeOrdinal) {
20452040
* {@code false}.
20462041
*/
20472042
public final boolean isAccessModeSupported(AccessMode accessMode) {
2048-
return AccessMode.getMemberName(accessMode.ordinal(), vform) != null;
2043+
return vform.getMemberNameOrNull(accessMode.ordinal()) != null;
20492044
}
20502045

20512046
/**
@@ -2068,8 +2063,7 @@ public final boolean isAccessModeSupported(AccessMode accessMode) {
20682063
* @return a method handle bound to this VarHandle and the given access mode
20692064
*/
20702065
public MethodHandle toMethodHandle(AccessMode accessMode) {
2071-
MemberName mn = AccessMode.getMemberName(accessMode.ordinal(), vform);
2072-
if (mn != null) {
2066+
if (isAccessModeSupported(accessMode)) {
20732067
MethodHandle mh = getMethodHandle(accessMode.ordinal());
20742068
return mh.bindTo(this);
20752069
}

0 commit comments

Comments
 (0)