< 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,19 +271,19 @@
// 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);
+ 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(NF_checkGenericType, names[CALL_MH], mtypeArg);
+ 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(NF_checkCustomized, outArgs[0]);
+ 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,11 +367,11 @@
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]);
+ 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,36 +409,60 @@
} 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;
+ }
+ FUNCTIONS[idx] = function;
+ function.resolve();
+ 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 NamedFunction
- NF_checkExactType,
- NF_checkGenericType,
- NF_getCallSiteTarget,
- NF_checkCustomized;
- static {
+ private static final @Stable NamedFunction[] FUNCTIONS = new NamedFunction[NF_LIMIT];
+
+ private static NamedFunction makeConstantFunction(int idx) {
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();
+ 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 >