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