8265135: Reduce work initializing VarForms

Reviewed-by: psandoz, mchung
This commit is contained in:
Claes Redestad 2021-04-19 14:39:31 +00:00
parent d9e40dd593
commit 5303ccb885
3 changed files with 66 additions and 50 deletions

View file

@ -24,6 +24,7 @@
*/
package java.lang.invoke;
import jdk.internal.vm.annotation.DontInline;
import jdk.internal.vm.annotation.ForceInline;
import jdk.internal.vm.annotation.Stable;
@ -33,18 +34,24 @@ import java.lang.reflect.Modifier;
import java.util.ArrayList;
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.
* Each member characterizes a static method.
*/
final class VarForm {
final Class<?> implClass;
final @Stable MethodType[] methodType_table;
final @Stable MemberName[] memberName_table;
VarForm(Class<?> implClass, Class<?> receiver, Class<?> value, Class<?>... intermediate) {
this.methodType_table = new MethodType[VarHandle.AccessType.values().length];
this.memberName_table = new MemberName[VarHandle.AccessMode.values().length];
this.implClass = implClass;
if (receiver == null) {
initMethodTypes(value, intermediate);
} else {
@ -53,37 +60,46 @@ final class VarForm {
System.arraycopy(intermediate, 0, coordinates, 1, intermediate.length);
initMethodTypes(value, coordinates);
}
// TODO lazily calculate
this.memberName_table = linkFromStatic(implClass);
}
// Used by IndirectVarHandle
VarForm(Class<?> value, Class<?>[] coordinates) {
this.methodType_table = new MethodType[VarHandle.AccessType.values().length];
this.memberName_table = null;
this.implClass = null;
initMethodTypes(value, coordinates);
}
void initMethodTypes(Class<?> value, Class<?>... coordinates) {
// (Receiver, <Intermediates>)Value
methodType_table[VarHandle.AccessType.GET.ordinal()] =
MethodType.methodType(value, coordinates).erase();
Class<?> erasedValue = MethodTypeForm.canonicalize(value, MethodTypeForm.ERASE);
Class<?>[] erasedCoordinates = MethodTypeForm.canonicalizeAll(coordinates, MethodTypeForm.ERASE);
// (Receiver, <Intermediates>, Value)void
methodType_table[VarHandle.AccessType.SET.ordinal()] =
MethodType.methodType(void.class, coordinates).appendParameterTypes(value).erase();
if (erasedValue != null) {
value = erasedValue;
}
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
methodType_table[VarHandle.AccessType.GET_AND_UPDATE.ordinal()] =
MethodType.methodType(value, coordinates).appendParameterTypes(value).erase();
type = methodType_table[VarHandle.AccessType.GET_AND_UPDATE.ordinal()] =
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
methodType_table[VarHandle.AccessType.COMPARE_AND_SET.ordinal()] =
MethodType.methodType(boolean.class, coordinates).appendParameterTypes(value, value).erase();
// (Receiver, <Intermediates>, Value, Value)Value
methodType_table[VarHandle.AccessType.COMPARE_AND_EXCHANGE.ordinal()] =
MethodType.methodType(value, coordinates).appendParameterTypes(value, value).erase();
type.changeReturnType(boolean.class);
}
@ForceInline
@ -93,14 +109,30 @@ final class VarForm {
@ForceInline
final MemberName getMemberName(int mode) {
// TODO calculate lazily
MemberName mn = memberName_table[mode];
MemberName mn = getMemberNameOrNull(mode);
if (mn == null) {
throw new UnsupportedOperationException();
}
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
MethodType[] methodType_V_table;
@ -125,25 +157,4 @@ final class VarForm {
}
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;
}
}