< prev index next >
src/java.base/share/classes/java/lang/invoke/Invokers.java
Print this page
rev 13050 : 8142334: Improve lazy initialization of java.lang.invoke
Reviewed-by: psandoz, vlivanov, mhaupt
*** 271,289 ****
// Make the final call. If isGeneric, then prepend the result of type checking.
MethodType outCallType = mtype.basicType();
Object[] outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class);
Object mtypeArg = (customized ? mtype : names[MTYPE_ARG]);
if (!isGeneric) {
! names[CHECK_TYPE] = new Name(NF_checkExactType, names[CALL_MH], mtypeArg);
// mh.invokeExact(a*):R => checkExactType(mh, TYPEOF(a*:R)); mh.invokeBasic(a*)
} else {
! names[CHECK_TYPE] = new Name(NF_checkGenericType, names[CALL_MH], mtypeArg);
// mh.invokeGeneric(a*):R => checkGenericType(mh, TYPEOF(a*:R)).invokeBasic(a*)
outArgs[0] = names[CHECK_TYPE];
}
if (CHECK_CUSTOM != -1) {
! names[CHECK_CUSTOM] = new Name(NF_checkCustomized, outArgs[0]);
}
names[LINKER_CALL] = new Name(outCallType, outArgs);
lform = new LambdaForm(debugName, INARG_LIMIT, names);
if (isLinker)
lform.compileToBytecode(); // JVM needs a real methodOop
--- 271,289 ----
// Make the final call. If isGeneric, then prepend the result of type checking.
MethodType outCallType = mtype.basicType();
Object[] outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class);
Object mtypeArg = (customized ? mtype : names[MTYPE_ARG]);
if (!isGeneric) {
! names[CHECK_TYPE] = new Name(getConstantFunction(NF_checkExactType), names[CALL_MH], mtypeArg);
// mh.invokeExact(a*):R => checkExactType(mh, TYPEOF(a*:R)); mh.invokeBasic(a*)
} else {
! names[CHECK_TYPE] = new Name(getConstantFunction(NF_checkGenericType), names[CALL_MH], mtypeArg);
// mh.invokeGeneric(a*):R => checkGenericType(mh, TYPEOF(a*:R)).invokeBasic(a*)
outArgs[0] = names[CHECK_TYPE];
}
if (CHECK_CUSTOM != -1) {
! names[CHECK_CUSTOM] = new Name(getConstantFunction(NF_checkCustomized), outArgs[0]);
}
names[LINKER_CALL] = new Name(outCallType, outArgs);
lform = new LambdaForm(debugName, INARG_LIMIT, names);
if (isLinker)
lform.compileToBytecode(); // JVM needs a real methodOop
*** 367,377 ****
MethodType invokerFormType = mtype.appendParameterTypes(skipCallSite ? MethodHandle.class : CallSite.class);
Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
assert(names.length == nameCursor);
assert(names[APPENDIX_ARG] != null);
if (!skipCallSite)
! names[CALL_MH] = new Name(NF_getCallSiteTarget, names[CSITE_ARG]);
// (site.)invokedynamic(a*):R => mh = site.getTarget(); mh.invokeBasic(a*)
final int PREPEND_MH = 0, PREPEND_COUNT = 1;
Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, OUTARG_LIMIT + PREPEND_COUNT, Object[].class);
// prepend MH argument:
System.arraycopy(outArgs, 0, outArgs, PREPEND_COUNT, outArgs.length - PREPEND_COUNT);
--- 367,377 ----
MethodType invokerFormType = mtype.appendParameterTypes(skipCallSite ? MethodHandle.class : CallSite.class);
Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
assert(names.length == nameCursor);
assert(names[APPENDIX_ARG] != null);
if (!skipCallSite)
! names[CALL_MH] = new Name(getConstantFunction(NF_getCallSiteTarget), names[CSITE_ARG]);
// (site.)invokedynamic(a*):R => mh = site.getTarget(); mh.invokeBasic(a*)
final int PREPEND_MH = 0, PREPEND_COUNT = 1;
Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, OUTARG_LIMIT + PREPEND_COUNT, Object[].class);
// prepend MH argument:
System.arraycopy(outArgs, 0, outArgs, PREPEND_COUNT, outArgs.length - PREPEND_COUNT);
*** 409,444 ****
} else {
mh.customizationCount = (byte)(count+1);
}
}
// Local constant functions:
! private static final NamedFunction
! NF_checkExactType,
! NF_checkGenericType,
! NF_getCallSiteTarget,
! NF_checkCustomized;
! static {
try {
! NamedFunction nfs[] = {
! NF_checkExactType = new NamedFunction(Invokers.class
! .getDeclaredMethod("checkExactType", Object.class, Object.class)),
! NF_checkGenericType = new NamedFunction(Invokers.class
! .getDeclaredMethod("checkGenericType", Object.class, Object.class)),
! NF_getCallSiteTarget = new NamedFunction(Invokers.class
! .getDeclaredMethod("getCallSiteTarget", Object.class)),
! NF_checkCustomized = new NamedFunction(Invokers.class
! .getDeclaredMethod("checkCustomized", 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);
}
}
private static class Lazy {
private static final MethodHandle MH_asSpreader;
--- 409,469 ----
} else {
mh.customizationCount = (byte)(count+1);
}
}
+ private static NamedFunction getConstantFunction(int idx) {
+ NamedFunction function = FUNCTIONS[idx];
+ if (function != null) {
+ return function;
+ }
+ return setCachedFunction(idx, makeConstantFunction(idx));
+ }
+
+ private static synchronized NamedFunction setCachedFunction(int idx, final NamedFunction function) {
+ // Simulate a CAS, to avoid racy duplication of results.
+ NamedFunction prev = FUNCTIONS[idx];
+ if (prev != null) {
+ return prev;
+ }
+ function.resolve();
+ UNSAFE.storeFence();
+ FUNCTIONS[idx] = function;
+ return function;
+ }
+
+ // Indexes into constant functions:
+ private static final int
+ NF_checkExactType = 0,
+ NF_checkGenericType = 1,
+ NF_getCallSiteTarget = 2,
+ NF_checkCustomized = 3,
+ NF_LIMIT = 4;
+
// Local constant functions:
! private static final @Stable NamedFunction[] FUNCTIONS = new NamedFunction[NF_LIMIT];
!
! private static NamedFunction makeConstantFunction(int idx) {
try {
! switch (idx) {
! case NF_checkExactType:
! return new NamedFunction(Invokers.class
! .getDeclaredMethod("checkExactType", Object.class, Object.class));
! case NF_checkGenericType:
! return new NamedFunction(Invokers.class
! .getDeclaredMethod("checkGenericType", Object.class, Object.class));
! case NF_getCallSiteTarget:
! return new NamedFunction(Invokers.class
! .getDeclaredMethod("getCallSiteTarget", Object.class));
! case NF_checkCustomized:
! return new NamedFunction(Invokers.class
! .getDeclaredMethod("checkCustomized", Object.class));
}
} catch (ReflectiveOperationException ex) {
throw newInternalError(ex);
}
+ throw newInternalError("Unknown function index: " + idx);
}
private static class Lazy {
private static final MethodHandle MH_asSpreader;
< prev index next >