< 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 >