8024616: JSR292: lazily initialize core NamedFunctions used for bootstrapping

Reviewed-by: jrose
This commit is contained in:
Vladimir Ivanov 2013-09-18 20:12:05 +04:00
parent b91ee23895
commit 8e924e70a6
2 changed files with 73 additions and 61 deletions

View File

@ -257,12 +257,12 @@ class DirectMethodHandle extends MethodHandle {
assert(names.length == nameCursor); assert(names.length == nameCursor);
if (doesAlloc) { if (doesAlloc) {
// names = { argx,y,z,... new C, init method } // names = { argx,y,z,... new C, init method }
names[NEW_OBJ] = new Name(NF_allocateInstance, names[DMH_THIS]); names[NEW_OBJ] = new Name(Lazy.NF_allocateInstance, names[DMH_THIS]);
names[GET_MEMBER] = new Name(NF_constructorMethod, names[DMH_THIS]); names[GET_MEMBER] = new Name(Lazy.NF_constructorMethod, names[DMH_THIS]);
} else if (needsInit) { } else if (needsInit) {
names[GET_MEMBER] = new Name(NF_internalMemberNameEnsureInit, names[DMH_THIS]); names[GET_MEMBER] = new Name(Lazy.NF_internalMemberNameEnsureInit, names[DMH_THIS]);
} else { } else {
names[GET_MEMBER] = new Name(NF_internalMemberName, names[DMH_THIS]); names[GET_MEMBER] = new Name(Lazy.NF_internalMemberName, names[DMH_THIS]);
} }
Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, GET_MEMBER+1, Object[].class); Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, GET_MEMBER+1, Object[].class);
assert(outArgs[outArgs.length-1] == names[GET_MEMBER]); // look, shifted args! assert(outArgs[outArgs.length-1] == names[GET_MEMBER]); // look, shifted args!
@ -637,18 +637,18 @@ class DirectMethodHandle extends MethodHandle {
final int RESULT = nameCursor-1; // either the call or the cast final int RESULT = nameCursor-1; // either the call or the cast
Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType()); Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
if (needsInit) if (needsInit)
names[INIT_BAR] = new Name(NF_ensureInitialized, names[DMH_THIS]); names[INIT_BAR] = new Name(Lazy.NF_ensureInitialized, names[DMH_THIS]);
if (needsCast && !isGetter) if (needsCast && !isGetter)
names[PRE_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[SET_VALUE]); names[PRE_CAST] = new Name(Lazy.NF_checkCast, names[DMH_THIS], names[SET_VALUE]);
Object[] outArgs = new Object[1 + linkerType.parameterCount()]; Object[] outArgs = new Object[1 + linkerType.parameterCount()];
assert(outArgs.length == (isGetter ? 3 : 4)); assert(outArgs.length == (isGetter ? 3 : 4));
outArgs[0] = UNSAFE; outArgs[0] = UNSAFE;
if (isStatic) { if (isStatic) {
outArgs[1] = names[F_HOLDER] = new Name(NF_staticBase, names[DMH_THIS]); outArgs[1] = names[F_HOLDER] = new Name(Lazy.NF_staticBase, names[DMH_THIS]);
outArgs[2] = names[F_OFFSET] = new Name(NF_staticOffset, names[DMH_THIS]); outArgs[2] = names[F_OFFSET] = new Name(Lazy.NF_staticOffset, names[DMH_THIS]);
} else { } else {
outArgs[1] = names[OBJ_CHECK] = new Name(NF_checkBase, names[OBJ_BASE]); outArgs[1] = names[OBJ_CHECK] = new Name(Lazy.NF_checkBase, names[OBJ_BASE]);
outArgs[2] = names[F_OFFSET] = new Name(NF_fieldOffset, names[DMH_THIS]); outArgs[2] = names[F_OFFSET] = new Name(Lazy.NF_fieldOffset, names[DMH_THIS]);
} }
if (!isGetter) { if (!isGetter) {
outArgs[3] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]); outArgs[3] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
@ -656,7 +656,7 @@ class DirectMethodHandle extends MethodHandle {
for (Object a : outArgs) assert(a != null); for (Object a : outArgs) assert(a != null);
names[LINKER_CALL] = new Name(linker, outArgs); names[LINKER_CALL] = new Name(linker, outArgs);
if (needsCast && isGetter) if (needsCast && isGetter)
names[POST_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[LINKER_CALL]); names[POST_CAST] = new Name(Lazy.NF_checkCast, names[DMH_THIS], names[LINKER_CALL]);
for (Name n : names) assert(n != null); for (Name n : names) assert(n != null);
String fieldOrStatic = (isStatic ? "Static" : "Field"); String fieldOrStatic = (isStatic ? "Static" : "Field");
String lambdaName = (linkerName + fieldOrStatic); // significant only for debugging String lambdaName = (linkerName + fieldOrStatic); // significant only for debugging
@ -665,48 +665,54 @@ class DirectMethodHandle extends MethodHandle {
return new LambdaForm(lambdaName, ARG_LIMIT, names, RESULT); return new LambdaForm(lambdaName, ARG_LIMIT, names, RESULT);
} }
private static final NamedFunction /**
NF_internalMemberName, * Pre-initialized NamedFunctions for bootstrapping purposes.
NF_internalMemberNameEnsureInit, * Factored in an inner class to delay initialization until first usage.
NF_ensureInitialized, */
NF_fieldOffset, private static class Lazy {
NF_checkBase, static final NamedFunction
NF_staticBase, NF_internalMemberName,
NF_staticOffset, NF_internalMemberNameEnsureInit,
NF_checkCast, NF_ensureInitialized,
NF_allocateInstance, NF_fieldOffset,
NF_constructorMethod; NF_checkBase,
static { NF_staticBase,
try { NF_staticOffset,
NamedFunction nfs[] = { NF_checkCast,
NF_internalMemberName = new NamedFunction(DirectMethodHandle.class NF_allocateInstance,
.getDeclaredMethod("internalMemberName", Object.class)), NF_constructorMethod;
NF_internalMemberNameEnsureInit = new NamedFunction(DirectMethodHandle.class static {
.getDeclaredMethod("internalMemberNameEnsureInit", Object.class)), try {
NF_ensureInitialized = new NamedFunction(DirectMethodHandle.class NamedFunction nfs[] = {
.getDeclaredMethod("ensureInitialized", Object.class)), NF_internalMemberName = new NamedFunction(DirectMethodHandle.class
NF_fieldOffset = new NamedFunction(DirectMethodHandle.class .getDeclaredMethod("internalMemberName", Object.class)),
.getDeclaredMethod("fieldOffset", Object.class)), NF_internalMemberNameEnsureInit = new NamedFunction(DirectMethodHandle.class
NF_checkBase = new NamedFunction(DirectMethodHandle.class .getDeclaredMethod("internalMemberNameEnsureInit", Object.class)),
.getDeclaredMethod("checkBase", Object.class)), NF_ensureInitialized = new NamedFunction(DirectMethodHandle.class
NF_staticBase = new NamedFunction(DirectMethodHandle.class .getDeclaredMethod("ensureInitialized", Object.class)),
.getDeclaredMethod("staticBase", Object.class)), NF_fieldOffset = new NamedFunction(DirectMethodHandle.class
NF_staticOffset = new NamedFunction(DirectMethodHandle.class .getDeclaredMethod("fieldOffset", Object.class)),
.getDeclaredMethod("staticOffset", Object.class)), NF_checkBase = new NamedFunction(DirectMethodHandle.class
NF_checkCast = new NamedFunction(DirectMethodHandle.class .getDeclaredMethod("checkBase", Object.class)),
.getDeclaredMethod("checkCast", Object.class, Object.class)), NF_staticBase = new NamedFunction(DirectMethodHandle.class
NF_allocateInstance = new NamedFunction(DirectMethodHandle.class .getDeclaredMethod("staticBase", Object.class)),
.getDeclaredMethod("allocateInstance", Object.class)), NF_staticOffset = new NamedFunction(DirectMethodHandle.class
NF_constructorMethod = new NamedFunction(DirectMethodHandle.class .getDeclaredMethod("staticOffset", Object.class)),
.getDeclaredMethod("constructorMethod", Object.class)) NF_checkCast = new NamedFunction(DirectMethodHandle.class
}; .getDeclaredMethod("checkCast", Object.class, Object.class)),
for (NamedFunction nf : nfs) { NF_allocateInstance = new NamedFunction(DirectMethodHandle.class
// Each nf must be statically invocable or we get tied up in our bootstraps. .getDeclaredMethod("allocateInstance", Object.class)),
assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf.member)) : nf; NF_constructorMethod = new NamedFunction(DirectMethodHandle.class
nf.resolve(); .getDeclaredMethod("constructorMethod", Object.class))
};
for (NamedFunction nf : nfs) {
// Each nf must be statically invocable or we get tied up in our bootstraps.
assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf.member)) : nf;
nf.resolve();
}
} catch (ReflectiveOperationException ex) {
throw newInternalError(ex);
} }
} catch (ReflectiveOperationException ex) {
throw newInternalError(ex);
} }
} }
} }

View File

@ -435,7 +435,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
// Spread the array. // Spread the array.
MethodHandle aload = MethodHandles.arrayElementGetter(spreadArgType); MethodHandle aload = MethodHandles.arrayElementGetter(spreadArgType);
Name array = names[argIndex]; Name array = names[argIndex];
names[nameCursor++] = new Name(NF_checkSpreadArgument, array, spreadArgCount); names[nameCursor++] = new Name(Lazy.NF_checkSpreadArgument, array, spreadArgCount);
for (int j = 0; j < spreadArgCount; i++, j++) { for (int j = 0; j < spreadArgCount; i++, j++) {
indexes[i] = nameCursor; indexes[i] = nameCursor;
names[nameCursor++] = new Name(aload, array, j); names[nameCursor++] = new Name(aload, array, j);
@ -480,14 +480,20 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
throw new WrongMethodTypeException("Array is not of length "+n); throw new WrongMethodTypeException("Array is not of length "+n);
} }
private static final NamedFunction NF_checkSpreadArgument; /**
static { * Pre-initialized NamedFunctions for bootstrapping purposes.
try { * Factored in an inner class to delay initialization until first usage.
NF_checkSpreadArgument = new NamedFunction(MethodHandleImpl.class */
.getDeclaredMethod("checkSpreadArgument", Object.class, int.class)); private static class Lazy {
NF_checkSpreadArgument.resolve(); static final NamedFunction NF_checkSpreadArgument;
} catch (ReflectiveOperationException ex) { static {
throw newInternalError(ex); try {
NF_checkSpreadArgument = new NamedFunction(MethodHandleImpl.class
.getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
NF_checkSpreadArgument.resolve();
} catch (ReflectiveOperationException ex) {
throw newInternalError(ex);
}
} }
} }