--- old/src/share/classes/java/lang/invoke/CallSite.java 2014-07-11 20:22:59.000000000 +0400 +++ new/src/share/classes/java/lang/invoke/CallSite.java 2014-07-11 20:22:59.000000000 +0400 @@ -102,7 +102,7 @@ */ /*package-private*/ CallSite(MethodType type) { - target = type.invokers().uninitializedCallSite(); + target = makeUninitializedCallSite(type); } /** @@ -217,21 +217,34 @@ } private static final MethodHandle GET_TARGET; + private static final MethodHandle THROW_UCS; static { try { GET_TARGET = IMPL_LOOKUP. findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class)); + THROW_UCS = IMPL_LOOKUP. + findStatic(CallSite.class, "uninitializedCallSite", MethodType.methodType(Object.class, Object[].class)); } catch (ReflectiveOperationException e) { throw newInternalError(e); } } /** This guy is rolled into the default target if a MethodType is supplied to the constructor. */ - /*package-private*/ - static Empty uninitializedCallSite() { + private static Object uninitializedCallSite(Object... ignore) { throw new IllegalStateException("uninitialized call site"); } + private MethodHandle makeUninitializedCallSite(MethodType targetType) { + MethodType basicType = targetType.basicType(); + MethodHandle invoker = basicType.form().cachedMethodHandle(MethodTypeForm.MH_UNINIT_CS); + if (invoker == null) { + invoker = THROW_UCS.asType(basicType); + invoker = basicType.form().setCachedMethodHandle(MethodTypeForm.MH_UNINIT_CS, invoker); + } + // unchecked view is OK since no values will be received or returned + return invoker.viewAsType(targetType); + } + // unsafe stuff: private static final long TARGET_OFFSET; static { --- old/src/share/classes/java/lang/invoke/Invokers.java 2014-07-11 20:23:01.000000000 +0400 +++ new/src/share/classes/java/lang/invoke/Invokers.java 2014-07-11 20:23:01.000000000 +0400 @@ -26,7 +26,7 @@ package java.lang.invoke; import java.util.Arrays; -import sun.invoke.empty.Empty; + import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; @@ -42,27 +42,20 @@ // FIXME: Get rid of the invokers that are not useful. - // exact invoker for the outgoing call - private /*lazy*/ MethodHandle exactInvoker; - private /*lazy*/ MethodHandle basicInvoker; // invokeBasic (unchecked exact) - - // erased (partially untyped but with primitives) invoker for the outgoing call - // FIXME: get rid of - private /*lazy*/ MethodHandle erasedInvoker; - // FIXME: get rid of - /*lazy*/ MethodHandle erasedInvokerWithDrops; // for InvokeGeneric - - // general invoker for the outgoing call - private /*lazy*/ MethodHandle generalInvoker; - // general invoker for the outgoing call, uses varargs private /*lazy*/ MethodHandle varargsInvoker; // general invoker for the outgoing call; accepts a trailing Object[] private final /*lazy*/ MethodHandle[] spreadInvokers; - // invoker for an unbound callsite - private /*lazy*/ MethodHandle uninitializedCallSite; + // Cached adapter information: + private final @Stable MethodHandle[] invokers = new MethodHandle[INV_LIMIT]; + // Indexes into invokers: + static final int + INV_EXACT = 0, // MethodHandles.exactInvoker + INV_GENERIC = 1, // MethodHandles.invoker (generic invocation) + INV_BASIC = 2, // MethodHandles.basicInvoker + INV_LIMIT = 3; /** Compute and cache information common to all collecting adapters * that implement members of the erasure-family of the given erased type. @@ -73,19 +66,46 @@ } /*non-public*/ MethodHandle exactInvoker() { - MethodHandle invoker = exactInvoker; + MethodHandle invoker = cachedInvoker(INV_EXACT); if (invoker != null) return invoker; invoker = makeExactOrGeneralInvoker(true); - exactInvoker = invoker; - return invoker; + return setCachedInvoker(INV_EXACT, invoker); } - /*non-public*/ MethodHandle generalInvoker() { - MethodHandle invoker = generalInvoker; + /*non-public*/ MethodHandle genericInvoker() { + MethodHandle invoker = cachedInvoker(INV_GENERIC); if (invoker != null) return invoker; invoker = makeExactOrGeneralInvoker(false); - generalInvoker = invoker; - return invoker; + return setCachedInvoker(INV_GENERIC, invoker); + } + + /*non-public*/ MethodHandle basicInvoker() { + MethodHandle invoker = cachedInvoker(INV_BASIC); + if (invoker != null) return invoker; + MethodType basicType = targetType.basicType(); + if (basicType != targetType) { + // double cache; not used significantly + return setCachedInvoker(INV_BASIC, basicType.invokers().basicInvoker()); + } + invoker = basicType.form().cachedMethodHandle(MethodTypeForm.MH_BASIC_INV); + if (invoker == null) { + MemberName method = invokeBasicMethod(basicType); + invoker = DirectMethodHandle.make(method); + assert(checkInvoker(invoker)); + invoker = basicType.form().setCachedMethodHandle(MethodTypeForm.MH_BASIC_INV, invoker); + } + return setCachedInvoker(INV_BASIC, invoker); + } + + private MethodHandle cachedInvoker(int idx) { + return invokers[idx]; + } + + private synchronized MethodHandle setCachedInvoker(int idx, final MethodHandle invoker) { + // Simulate a CAS, to avoid racy duplication of results. + MethodHandle prev = invokers[idx]; + if (prev != null) return prev; + return invokers[idx] = invoker; } private MethodHandle makeExactOrGeneralInvoker(boolean isExact) { @@ -110,21 +130,6 @@ } } - /*non-public*/ MethodHandle basicInvoker() { - MethodHandle invoker = basicInvoker; - if (invoker != null) return invoker; - MethodType basicType = targetType.basicType(); - if (basicType != targetType) { - // double cache; not used significantly - return basicInvoker = basicType.invokers().basicInvoker(); - } - MemberName method = invokeBasicMethod(basicType); - invoker = DirectMethodHandle.make(method); - assert(checkInvoker(invoker)); - basicInvoker = invoker; - return invoker; - } - // This next one is called from LambdaForm.NamedFunction.. /*non-public*/ static MemberName invokeBasicMethod(MethodType basicType) { assert(basicType == basicType.basicType()); @@ -145,17 +150,6 @@ return true; } - // FIXME: get rid of - /*non-public*/ MethodHandle erasedInvoker() { - MethodHandle xinvoker = exactInvoker(); - MethodHandle invoker = erasedInvoker; - if (invoker != null) return invoker; - MethodType erasedType = targetType.erase(); - invoker = xinvoker.asType(erasedType.invokerType()); - erasedInvoker = invoker; - return invoker; - } - /*non-public*/ MethodHandle spreadInvoker(int leadingArgCount) { MethodHandle vaInvoker = spreadInvokers[leadingArgCount]; if (vaInvoker != null) return vaInvoker; @@ -165,7 +159,7 @@ if (targetType.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY) { // Factor sinvoker.invoke(mh, a) into ginvoker.asSpreader().invoke(mh, a) // where ginvoker.invoke(mh, a*) => mh.invoke(a*). - MethodHandle genInvoker = generalInvoker(); + MethodHandle genInvoker = genericInvoker(); vaInvoker = genInvoker.asSpreader(Object[].class, spreadArgCount); } else { // Cannot build a general invoker here of type ginvoker.invoke(mh, a*[254]). @@ -197,37 +191,6 @@ return vaInvoker; } - private static MethodHandle THROW_UCS = null; - - /*non-public*/ MethodHandle uninitializedCallSite() { - MethodHandle invoker = uninitializedCallSite; - if (invoker != null) return invoker; - if (targetType.parameterCount() > 0) { - MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount()); - Invokers invokers0 = type0.invokers(); - invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(), - 0, targetType.parameterList()); - assert(invoker.type().equals(targetType)); - uninitializedCallSite = invoker; - return invoker; - } - invoker = THROW_UCS; - if (invoker == null) { - try { - THROW_UCS = invoker = IMPL_LOOKUP - .findStatic(CallSite.class, "uninitializedCallSite", - MethodType.methodType(Empty.class)); - } catch (ReflectiveOperationException ex) { - throw newInternalError(ex); - } - } - invoker = MethodHandles.explicitCastArguments(invoker, MethodType.methodType(targetType.returnType())); - invoker = invoker.dropArguments(targetType, 0, targetType.parameterCount()); - assert(invoker.type().equals(targetType)); - uninitializedCallSite = invoker; - return invoker; - } - public String toString() { return "Invokers"+targetType; } --- old/src/share/classes/java/lang/invoke/LambdaForm.java 2014-07-11 20:23:02.000000000 +0400 +++ new/src/share/classes/java/lang/invoke/LambdaForm.java 2014-07-11 20:23:02.000000000 +0400 @@ -1147,7 +1147,7 @@ if (LambdaForm.signatureReturn(sig) == V_TYPE) srcType = srcType.changeReturnType(void.class); MethodTypeForm typeForm = srcType.form(); - typeForm.namedFunctionInvoker = DirectMethodHandle.make(m); + typeForm.setCachedMethodHandle(MethodTypeForm.MH_NF_INV, DirectMethodHandle.make(m)); } } } @@ -1245,15 +1245,16 @@ MethodType.methodType(Object.class, MethodHandle.class, Object[].class); private static MethodHandle computeInvoker(MethodTypeForm typeForm) { - MethodHandle mh = typeForm.namedFunctionInvoker; + typeForm = typeForm.basicType().form(); // normalize to basic type + MethodHandle mh = typeForm.cachedMethodHandle(MethodTypeForm.MH_NF_INV); if (mh != null) return mh; MemberName invoker = InvokerBytecodeGenerator.generateNamedFunctionInvoker(typeForm); // this could take a while mh = DirectMethodHandle.make(invoker); - MethodHandle mh2 = typeForm.namedFunctionInvoker; + MethodHandle mh2 = typeForm.cachedMethodHandle(MethodTypeForm.MH_NF_INV); if (mh2 != null) return mh2; // benign race if (!mh.type().equals(INVOKER_METHOD_TYPE)) throw newInternalError(mh.debugString()); - return typeForm.namedFunctionInvoker = mh; + return typeForm.setCachedMethodHandle(MethodTypeForm.MH_NF_INV, mh); } @Hidden --- old/src/share/classes/java/lang/invoke/MethodHandles.java 2014-07-11 20:23:04.000000000 +0400 +++ new/src/share/classes/java/lang/invoke/MethodHandles.java 2014-07-11 20:23:03.000000000 +0400 @@ -1957,7 +1957,7 @@ */ static public MethodHandle invoker(MethodType type) { - return type.invokers().generalInvoker(); + return type.invokers().genericInvoker(); } static /*non-public*/ --- old/src/share/classes/java/lang/invoke/MethodTypeForm.java 2014-07-11 20:23:05.000000000 +0400 +++ new/src/share/classes/java/lang/invoke/MethodTypeForm.java 2014-07-11 20:23:05.000000000 +0400 @@ -51,7 +51,13 @@ final MethodType basicType; // the canonical erasure, with primitives simplified // Cached adapter information: - @Stable MethodHandle namedFunctionInvoker; // cached helper for LF.NamedFunction + @Stable final MethodHandle[] methodHandles; + // Indexes into methodHandles: + static final int + MH_BASIC_INV = 0, // cached instance of MH.invokeBasic + MH_NF_INV = 1, // cached helper for LF.NamedFunction + MH_UNINIT_CS = 2, // uninitialized call site + MH_LIMIT = 3; // Cached lambda form information, for basic types only: final @Stable LambdaForm[] lambdaForms; @@ -98,6 +104,18 @@ return true; } + public MethodHandle cachedMethodHandle(int which) { + assert(assertIsBasicType()); + return methodHandles[which]; + } + + synchronized public MethodHandle setCachedMethodHandle(int which, MethodHandle mh) { + // Simulate a CAS, to avoid racy duplication of results. + MethodHandle prev = methodHandles[which]; + if (prev != null) return prev; + return methodHandles[which] = mh; + } + public LambdaForm cachedLambdaForm(int which) { assert(assertIsBasicType()); return lambdaForms[which]; @@ -169,6 +187,7 @@ this.argCounts = that.argCounts; this.argToSlotTable = that.argToSlotTable; this.slotToArgTable = that.slotToArgTable; + this.methodHandles = null; this.lambdaForms = null; return; } @@ -214,6 +233,7 @@ // Initialize caches, but only for basic types assert(basicType == erasedType); this.lambdaForms = new LambdaForm[LF_LIMIT]; + this.methodHandles = new MethodHandle[MH_LIMIT]; } private static long pack(int a, int b, int c, int d) {