@@ -467,37 +485,16 @@ public abstract class MethodHandle
}
/**
- * CONSTRUCTOR WILL BE REMOVED FOR PFD:
- * Temporary constructor in early versions of the Reference Implementation.
- * Method handle inheritance (if any) will be contained completely within
+ * Package-private constructor for the method handle implementation hierarchy.
+ * Method handle inheritance will be contained completely within
* the {@code java.dyn} package.
*/
- // The constructor for MethodHandle may only be called by privileged code.
- // Subclasses may be in other packages, but must possess
- // a token which they obtained from MH with a security check.
- // @param token non-null object which proves access permission
// @param type type (permanently assigned) of the new method handle
- protected MethodHandle(Access token, MethodType type) {
- super(token);
- Access.check(token);
- this.type = type;
- }
-
- private void initType(MethodType type) {
+ /*non-public*/ MethodHandle(MethodType type) {
type.getClass(); // elicit NPE
- if (this.type != null) throw new InternalError();
this.type = type;
}
- static {
- // This hack allows the implementation package special access to
- // the internals of MethodHandle. In particular, the MTImpl has all sorts
- // of cached information useful to the implementation code.
- MethodHandleImpl.setMethodHandleFriend(IMPL_TOKEN, new MethodHandleImpl.MethodHandleFriend() {
- public void initType(MethodHandle mh, MethodType type) { mh.initType(type); }
- });
- }
-
/**
* Invoke the method handle, allowing any caller type descriptor, but requiring an exact type match.
* The type descriptor at the call site of {@code invokeExact} must
@@ -608,7 +605,7 @@ public abstract class MethodHandle
return asType(MethodType.genericMethodType(argc)).invokeWithArguments(arguments);
}
if (argc <= 10) {
- MethodHandle invoker = invokers(type).genericInvoker();
+ MethodHandle invoker = type.invokers().genericInvoker();
switch (argc) {
case 0: return invoker.invokeExact(this);
case 1: return invoker.invokeExact(this,
@@ -647,7 +644,7 @@ public abstract class MethodHandle
}
// more than ten arguments get boxed in a varargs list:
- MethodHandle invoker = invokers(type).spreadInvoker(0);
+ MethodHandle invoker = type.invokers().spreadInvoker(0);
return invoker.invokeExact(this, arguments);
}
/** Equivalent to {@code invokeWithArguments(arguments.toArray())}. */
@@ -1004,6 +1001,6 @@ assert(failed);
*/
@Override
public String toString() {
- return MethodHandleImpl.getNameString(IMPL_TOKEN, this);
+ return getNameString(this);
}
}
diff --git a/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java b/jdk/src/share/classes/java/dyn/MethodHandleImpl.java
similarity index 78%
rename from jdk/src/share/classes/sun/dyn/MethodHandleImpl.java
rename to jdk/src/share/classes/java/dyn/MethodHandleImpl.java
index eab4923540e..51701cd3b63 100644
--- a/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java
+++ b/jdk/src/share/classes/java/dyn/MethodHandleImpl.java
@@ -23,134 +23,34 @@
* questions.
*/
-package sun.dyn;
+package java.dyn;
-import java.dyn.*;
-import java.dyn.MethodHandles.Lookup;
-import java.util.logging.Level;
-import java.util.logging.Logger;
import sun.dyn.util.VerifyType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import sun.dyn.empty.Empty;
import sun.dyn.util.ValueConversions;
import sun.dyn.util.Wrapper;
import sun.misc.Unsafe;
-import static sun.dyn.MemberName.newIllegalArgumentException;
-import static sun.dyn.MemberName.newNoAccessException;
-import static sun.dyn.MemberName.uncaughtException;
+import static java.dyn.MethodHandleStatics.*;
+import static java.dyn.MethodHandles.Lookup.IMPL_LOOKUP;
/**
- * Base class for method handles, containing JVM-specific fields and logic.
- * TO DO: It should not be a base class.
+ * Trusted implementation code for MethodHandle.
* @author jrose
*/
-public abstract class MethodHandleImpl {
-
- // Fields which really belong in MethodHandle:
- private byte vmentry; // adapter stub or method entry point
- //private int vmslots; // optionally, hoist type.form.vmslots
- protected Object vmtarget; // VM-specific, class-specific target value
- //MethodType type; // defined in MethodHandle
-
- // TO DO: vmtarget should be invisible to Java, since the JVM puts internal
- // managed pointers into it. Making it visible exposes it to debuggers,
- // which can cause errors when they treat the pointer as an Object.
-
- // These two dummy fields are present to force 'I' and 'J' signatures
- // into this class's constant pool, so they can be transferred
- // to vmentry when this class is loaded.
- static final int INT_FIELD = 0;
- static final long LONG_FIELD = 0;
-
- /** Access methods for the internals of MethodHandle, supplied to
- * MethodHandleImpl as a trusted agent.
- */
- static public interface MethodHandleFriend {
- void initType(MethodHandle mh, MethodType type);
- }
- public static void setMethodHandleFriend(Access token, MethodHandleFriend am) {
- Access.check(token);
- if (METHOD_HANDLE_FRIEND != null)
- throw new InternalError(); // just once
- METHOD_HANDLE_FRIEND = am;
- }
- static private MethodHandleFriend METHOD_HANDLE_FRIEND;
-
- // NOT public
- static void initType(MethodHandle mh, MethodType type) {
- METHOD_HANDLE_FRIEND.initType(mh, type);
- }
-
- // type is defined in java.dyn.MethodHandle, which is platform-independent
-
- // vmentry (a void* field) is used *only* by by the JVM.
- // The JVM adjusts its type to int or long depending on system wordsize.
- // Since it is statically typed as neither int nor long, it is impossible
- // to use this field from Java bytecode. (Please don't try to, either.)
-
- // The vmentry is an assembly-language stub which is jumped to
- // immediately after the method type is verified.
- // For a direct MH, this stub loads the vmtarget's entry point
- // and jumps to it.
-
- /**
- * VM-based method handles must have a security token.
- * This security token can only be obtained by trusted code.
- * Do not create method handles directly; use factory methods.
- */
- public MethodHandleImpl(Access token) {
- Access.check(token);
- }
-
- /** Initialize the method type form to participate in JVM calls.
- * This is done once for each erased type.
- */
- public static void init(Access token, MethodType self) {
- Access.check(token);
- if (MethodHandleNatives.JVM_SUPPORT)
- MethodHandleNatives.init(self);
- }
-
+/*non-public*/ abstract class MethodHandleImpl {
/// Factory methods to create method handles:
private static final MemberName.Factory LOOKUP = MemberName.Factory.INSTANCE;
- static private Lookup IMPL_LOOKUP_INIT;
-
- public static void initLookup(Access token, Lookup lookup) {
- Access.check(token);
- if (IMPL_LOOKUP_INIT != null)
- throw new InternalError();
- IMPL_LOOKUP_INIT = lookup;
- }
-
- public static Lookup getLookup(Access token) {
- Access.check(token);
- return IMPL_LOOKUP;
- }
-
- static {
- if (!MethodHandleNatives.JVM_SUPPORT) // force init of native API
- throw new InternalError("No JVM support for JSR 292");
- // Force initialization of Lookup, so it calls us back as initLookup:
- MethodHandles.publicLookup();
- if (IMPL_LOOKUP_INIT == null)
- throw new InternalError();
- }
-
- public static void initStatics() {
+ static void initStatics() {
// Trigger preceding sequence.
}
- /** Shared secret with MethodHandles.Lookup, a copy of Lookup.IMPL_LOOKUP. */
- static final Lookup IMPL_LOOKUP = IMPL_LOOKUP_INIT;
-
-
/** Look up a given method.
* Callable only from java.dyn and related packages.
*
@@ -170,10 +70,9 @@ public abstract class MethodHandleImpl {
* @return a direct handle to the matching method
* @throws IllegalAccessException if the given method cannot be accessed by the lookup class
*/
- public static
- MethodHandle findMethod(Access token, MemberName method,
+ static
+ MethodHandle findMethod(MemberName method,
boolean doDispatch, Class> lookupClass) throws IllegalAccessException {
- Access.check(token); // only trusted calls
MethodType mtype = method.getMethodType();
if (!method.isStatic()) {
// adjust the advertised receiver type to be exactly the one requested
@@ -183,7 +82,7 @@ public abstract class MethodHandleImpl {
}
DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass);
if (!mh.isValid())
- throw newNoAccessException(method, lookupClass);
+ throw method.makeAccessException("no access", lookupClass);
assert(mh.type() == mtype);
if (!method.isVarargs())
return mh;
@@ -191,13 +90,12 @@ public abstract class MethodHandleImpl {
return mh.asVarargsCollector(mtype.parameterType(mtype.parameterCount()-1));
}
- public static
- MethodHandle makeAllocator(Access token, MethodHandle rawConstructor) {
- Access.check(token);
+ static
+ MethodHandle makeAllocator(MethodHandle rawConstructor) {
MethodType rawConType = rawConstructor.type();
// Wrap the raw (unsafe) constructor with the allocation of a suitable object.
MethodHandle allocator
- = AllocateObject.make(token, rawConType.parameterType(0), rawConstructor);
+ = AllocateObject.make(rawConType.parameterType(0), rawConstructor);
assert(allocator.type()
.equals(rawConType.dropParameterTypes(0, 1).changeReturnType(rawConType.parameterType(0))));
return allocator;
@@ -211,13 +109,11 @@ public abstract class MethodHandleImpl {
private AllocateObject(MethodHandle invoker,
Class allocateClass, MethodHandle rawConstructor) {
- super(Access.TOKEN, invoker);
+ super(invoker);
this.allocateClass = allocateClass;
this.rawConstructor = rawConstructor;
}
- static MethodHandle make(Access token,
- Class> allocateClass, MethodHandle rawConstructor) {
- Access.check(token);
+ static MethodHandle make(Class> allocateClass, MethodHandle rawConstructor) {
MethodType rawConType = rawConstructor.type();
assert(rawConType.parameterType(0) == allocateClass);
MethodType newType = rawConType.dropParameterTypes(0, 1).changeReturnType(allocateClass);
@@ -225,18 +121,18 @@ public abstract class MethodHandleImpl {
if (nargs < INVOKES.length) {
MethodHandle invoke = INVOKES[nargs];
MethodType conType = CON_TYPES[nargs];
- MethodHandle gcon = convertArguments(token, rawConstructor, conType, rawConType, null);
+ MethodHandle gcon = convertArguments(rawConstructor, conType, rawConType, null);
if (gcon == null) return null;
MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
assert(galloc.type() == newType.generic());
- return convertArguments(token, galloc, newType, galloc.type(), null);
+ return convertArguments(galloc, newType, galloc.type(), null);
} else {
MethodHandle invoke = VARARGS_INVOKE;
MethodType conType = CON_TYPES[nargs];
- MethodHandle gcon = spreadArguments(token, rawConstructor, conType, 1);
+ MethodHandle gcon = spreadArguments(rawConstructor, conType, 1);
if (gcon == null) return null;
MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
- return collectArguments(token, galloc, newType, 1, null);
+ return collectArguments(galloc, newType, 1, null);
}
}
@Override
@@ -338,20 +234,16 @@ public abstract class MethodHandleImpl {
}
}
- public static
- MethodHandle accessField(Access token,
- MemberName member, boolean isSetter,
+ static
+ MethodHandle accessField(MemberName member, boolean isSetter,
Class> lookupClass) {
- Access.check(token);
// Use sun. misc.Unsafe to dig up the dirt on the field.
- MethodHandle mh = new FieldAccessor(token, member, isSetter);
+ MethodHandle mh = new FieldAccessor(member, isSetter);
return mh;
}
- public static
- MethodHandle accessArrayElement(Access token,
- Class> arrayClass, boolean isSetter) {
- Access.check(token);
+ static
+ MethodHandle accessArrayElement(Class> arrayClass, boolean isSetter) {
if (!arrayClass.isArray())
throw newIllegalArgumentException("not an array: "+arrayClass);
Class> elemClass = arrayClass.getComponentType();
@@ -379,12 +271,13 @@ public abstract class MethodHandleImpl {
final long offset;
final String name;
- public FieldAccessor(Access token, MemberName field, boolean isSetter) {
- super(Access.TOKEN, fhandle(field.getDeclaringClass(), field.getFieldType(), isSetter, field.isStatic()));
- this.offset = (long) field.getVMIndex(token);
+ FieldAccessor(MemberName field, boolean isSetter) {
+ super(fhandle(field.getDeclaringClass(), field.getFieldType(), isSetter, field.isStatic()));
+ this.offset = (long) field.getVMIndex();
this.name = field.getName();
this.base = staticBase(field);
}
+ @Override
public String toString() { return addTypeString(name, this); }
int getFieldI(C obj) { return unsafe.getInt(obj, offset); }
@@ -560,10 +453,8 @@ public abstract class MethodHandleImpl {
* @param receiver Receiver (or first static method argument) to pre-bind.
* @return a BoundMethodHandle for the given DirectMethodHandle, or null if it does not exist
*/
- public static
- MethodHandle bindReceiver(Access token,
- MethodHandle target, Object receiver) {
- Access.check(token);
+ static
+ MethodHandle bindReceiver(MethodHandle target, Object receiver) {
if (target instanceof AdapterMethodHandle &&
((AdapterMethodHandle)target).conversionOp() == MethodHandleNatives.Constants.OP_RETYPE_ONLY
) {
@@ -574,7 +465,7 @@ public abstract class MethodHandleImpl {
dmh.type().parameterType(0).isAssignableFrom(receiver.getClass())) {
MethodHandle bmh = new BoundMethodHandle(dmh, receiver, 0);
MethodType newType = target.type().dropParameterTypes(0, 1);
- return convertArguments(token, bmh, newType, bmh.type(), null);
+ return convertArguments(bmh, newType, bmh.type(), null);
}
}
}
@@ -590,19 +481,15 @@ public abstract class MethodHandleImpl {
* @param receiver Argument (which can be a boxed primitive) to pre-bind.
* @return a suitable BoundMethodHandle
*/
- public static
- MethodHandle bindArgument(Access token,
- MethodHandle target, int argnum, Object receiver) {
- Access.check(token);
+ static
+ MethodHandle bindArgument(MethodHandle target, int argnum, Object receiver) {
return new BoundMethodHandle(target, receiver, argnum);
}
- public static MethodHandle convertArguments(Access token,
- MethodHandle target,
+ static MethodHandle convertArguments(MethodHandle target,
MethodType newType,
MethodType oldType,
int[] permutationOrNull) {
- Access.check(token);
assert(oldType.parameterCount() == target.type().parameterCount());
if (permutationOrNull != null) {
int outargs = oldType.parameterCount(), inargs = newType.parameterCount();
@@ -613,7 +500,7 @@ public abstract class MethodHandleImpl {
for (int i = 0; i < outargs; i++)
callTypeArgs[i] = newType.parameterType(permutationOrNull[i]);
MethodType callType = MethodType.methodType(oldType.returnType(), callTypeArgs);
- target = convertArguments(token, target, callType, oldType, null);
+ target = convertArguments(target, callType, oldType, null);
assert(target != null);
oldType = target.type();
List goal = new ArrayList(); // i*TOKEN
@@ -710,7 +597,7 @@ public abstract class MethodHandleImpl {
Collections.rotate(ptypes.subList(rotBeg, rotEnd+1), -rotBy);
MethodType rotType = MethodType.methodType(oldType.returnType(), ptypes);
MethodHandle nextTarget
- = AdapterMethodHandle.makeRotateArguments(token, rotType, target,
+ = AdapterMethodHandle.makeRotateArguments(rotType, target,
rotBeg, rotSpan.size(), rotBy);
if (nextTarget != null) {
//System.out.println("Rot: "+rotSpan+" by "+rotBy);
@@ -733,7 +620,7 @@ public abstract class MethodHandleImpl {
int j = state.indexOf(arg);
Collections.swap(ptypes, i, j);
MethodType swapType = MethodType.methodType(oldType.returnType(), ptypes);
- target = AdapterMethodHandle.makeSwapArguments(token, swapType, target, i, j);
+ target = AdapterMethodHandle.makeSwapArguments(swapType, target, i, j);
if (target == null) throw newIllegalArgumentException("cannot swap");
assert(target.type() == swapType);
oldType = swapType;
@@ -760,7 +647,7 @@ public abstract class MethodHandleImpl {
List> ptypes = oldType.parameterList();
ptypes = ptypes.subList(0, ptypes.size() - dupArgCount);
MethodType dupType = MethodType.methodType(oldType.returnType(), ptypes);
- target = AdapterMethodHandle.makeDupArguments(token, dupType, target, dupArgPos, dupArgCount);
+ target = AdapterMethodHandle.makeDupArguments(dupType, target, dupArgPos, dupArgCount);
if (target == null)
throw newIllegalArgumentException("cannot dup");
oldType = target.type();
@@ -778,7 +665,7 @@ public abstract class MethodHandleImpl {
List> dropTypes = newType.parameterList()
.subList(dropArgPos, dropArgPos + dropArgCount);
MethodType dropType = oldType.insertParameterTypes(dropArgPos, dropTypes);
- target = AdapterMethodHandle.makeDropArguments(token, dropType, target, dropArgPos, dropArgCount);
+ target = AdapterMethodHandle.makeDropArguments(dropType, target, dropArgPos, dropArgCount);
if (target == null) throw newIllegalArgumentException("cannot drop");
oldType = target.type();
}
@@ -787,7 +674,7 @@ public abstract class MethodHandleImpl {
return target;
if (oldType.parameterCount() != newType.parameterCount())
throw newIllegalArgumentException("mismatched parameter count");
- MethodHandle res = AdapterMethodHandle.makePairwiseConvert(token, newType, target);
+ MethodHandle res = AdapterMethodHandle.makePairwiseConvert(newType, target);
if (res != null)
return res;
int argc = oldType.parameterCount();
@@ -797,26 +684,24 @@ public abstract class MethodHandleImpl {
// then back to the desired types. We might have to use Java-based
// method handles to do this.
MethodType objType = MethodType.genericMethodType(argc);
- MethodHandle objTarget = AdapterMethodHandle.makePairwiseConvert(token, objType, target);
+ MethodHandle objTarget = AdapterMethodHandle.makePairwiseConvert(objType, target);
if (objTarget == null)
objTarget = FromGeneric.make(target);
- res = AdapterMethodHandle.makePairwiseConvert(token, newType, objTarget);
+ res = AdapterMethodHandle.makePairwiseConvert(newType, objTarget);
if (res != null)
return res;
return ToGeneric.make(newType, objTarget);
}
- public static MethodHandle spreadArguments(Access token,
- MethodHandle target,
+ static MethodHandle spreadArguments(MethodHandle target,
MethodType newType,
int spreadArg) {
- Access.check(token);
// TO DO: maybe allow the restarg to be Object and implicitly cast to Object[]
MethodType oldType = target.type();
// spread the last argument of newType to oldType
int spreadCount = oldType.parameterCount() - spreadArg;
Class