src/share/classes/java/lang/invoke/Invokers.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File
*** old/src/share/classes/java/lang/invoke/Invokers.java	Fri Jul 11 20:23:01 2014
--- new/src/share/classes/java/lang/invoke/Invokers.java	Fri Jul 11 20:23:01 2014

*** 24,34 **** --- 24,34 ---- */ 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; import static java.lang.invoke.LambdaForm.*;
*** 40,93 **** --- 40,113 ---- // exact type (sans leading taget MH) for the outgoing call private final MethodType targetType; // 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. */ /*non-public*/ Invokers(MethodType targetType) { this.targetType = targetType; this.spreadInvokers = new MethodHandle[targetType.parameterCount()+1]; } /*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) { MethodType mtype = targetType; MethodType invokerType = mtype.invokerType();
*** 108,132 **** --- 128,137 ---- targetType.parameterCount() < EAGER_COMPILE_ARITY_LIMIT) { invoker.form.compileToBytecode(); } } /*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.<init>. /*non-public*/ static MemberName invokeBasicMethod(MethodType basicType) { assert(basicType == basicType.basicType()); try { //Lookup.findVirtual(MethodHandle.class, name, type);
*** 143,173 **** --- 148,167 ---- invoker.internalMemberName().getMethodType().equals(targetType)); assert(!invoker.isVarargsCollector()); 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; int spreadArgCount = targetType.parameterCount() - leadingArgCount; MethodType spreadInvokerType = targetType .replaceParameterTypes(leadingArgCount, targetType.parameterCount(), Object[].class); 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]). // Instead, factor sinvoker.invoke(mh, a) into ainvoker.invoke(filter(mh), a) // where filter(mh) == mh.asSpreader(Object[], spreadArgCount)
*** 195,235 **** --- 189,198 ---- vaInvoker = spreadInvoker(0).asType(MethodType.genericMethodType(0, true).invokerType()); varargsInvoker = vaInvoker; 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; } static MemberName methodHandleInvokeLinkerMethod(String name,

src/share/classes/java/lang/invoke/Invokers.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File