提交 4eb43f64 编写于 作者: J jrose

6914665: update jdk code for JSR 292 (post 6858164)

Summary: Fill in missing API implementations, fix numerous bugs, adjust APIs towards EG design.
Reviewed-by: twisti
上级 6145be84
...@@ -26,6 +26,9 @@ ...@@ -26,6 +26,9 @@
package java.dyn; package java.dyn;
import sun.dyn.util.BytecodeName; import sun.dyn.util.BytecodeName;
import sun.dyn.Access;
import sun.dyn.CallSiteImpl;
import sun.dyn.MethodHandleImpl;
/** /**
* An {@code invokedynamic} call site, as reified by the * An {@code invokedynamic} call site, as reified by the
...@@ -52,15 +55,25 @@ import sun.dyn.util.BytecodeName; ...@@ -52,15 +55,25 @@ import sun.dyn.util.BytecodeName;
* @see Linkage#registerBootstrapMethod(java.lang.Class, java.dyn.MethodHandle) * @see Linkage#registerBootstrapMethod(java.lang.Class, java.dyn.MethodHandle)
* @author John Rose, JSR 292 EG * @author John Rose, JSR 292 EG
*/ */
public class CallSite { public class CallSite
// Note: This is an implementation inheritance hack, and will be removed
// with a JVM change which moves the required hidden state onto this class.
extends CallSiteImpl
{
private static final Access IMPL_TOKEN = Access.getToken();
/*
// Fields used only by the JVM. Do not use or change. // Fields used only by the JVM. Do not use or change.
private Object vmmethod; private Object vmmethod;
int callerMID, callerBCI; // supplied by the JVM int callerMID, callerBCI; // supplied by the JVM
MethodHandle target; private MethodHandle target;
final Object caller; // usually a class final Object caller; // usually a class
final String name; final String name;
final MethodType type; final MethodType type;
*/
/** /**
* Make a call site given the parameters from a call to the bootstrap method. * Make a call site given the parameters from a call to the bootstrap method.
...@@ -72,16 +85,21 @@ public class CallSite { ...@@ -72,16 +85,21 @@ public class CallSite {
* @param type the method handle type derived from descriptor of the {@code invokedynamic} instruction * @param type the method handle type derived from descriptor of the {@code invokedynamic} instruction
*/ */
public CallSite(Object caller, String name, MethodType type) { public CallSite(Object caller, String name, MethodType type) {
this.caller = caller; super(IMPL_TOKEN, caller, name, type);
this.name = name;
this.type = type;
} }
private static void privateInitializeCallSite(CallSite site, int callerMID, int callerBCI) { private static void privateInitializeCallSite(CallSite site, int callerMID, int callerBCI) {
site.callerMID = callerMID; site.callerMID = callerMID;
site.callerBCI = callerBCI; site.callerBCI = callerBCI;
if (site.target == null) site.ensureTarget();
site.setTarget(site.initialTarget()); }
private void ensureTarget() {
// Note use of super, which accesses the field directly,
// without deferring to possible subclass overrides.
if (super.getTarget() == null) {
super.setTarget(this.initialTarget());
super.getTarget().type(); // provoke NPE if still null
}
} }
/** /**
...@@ -102,10 +120,11 @@ public class CallSite { ...@@ -102,10 +120,11 @@ public class CallSite {
/** /**
* Report the current linkage state of the call site. (This is mutable.) * Report the current linkage state of the call site. (This is mutable.)
* The value maybe null only if the call site is currently unlinked. * The value may not be null after the {@code CallSite} object is returned
* When a linked call site is invoked, the target method is used directly. * from the bootstrap method of the {@code invokedynamic} instruction.
* When an unlinked call site is invoked, its bootstrap method receives * When an {@code invokedynamic} instruction is executed, the target method
* the call, as if via {@link Linkage#bootstrapInvokeDynamic}. * of its associated {@code call site} object is invoked directly,
* as if via {@link MethodHandle}{@code .invoke}.
* <p> * <p>
* The interactions of {@code getTarget} with memory are the same * The interactions of {@code getTarget} with memory are the same
* as of a read from an ordinary variable, such as an array element or a * as of a read from an ordinary variable, such as an array element or a
...@@ -118,7 +137,7 @@ public class CallSite { ...@@ -118,7 +137,7 @@ public class CallSite {
* @see #setTarget * @see #setTarget
*/ */
public MethodHandle getTarget() { public MethodHandle getTarget() {
return target; return super.getTarget();
} }
/** /**
...@@ -140,13 +159,13 @@ public class CallSite { ...@@ -140,13 +159,13 @@ public class CallSite {
*/ */
public void setTarget(MethodHandle target) { public void setTarget(MethodHandle target) {
checkTarget(target); checkTarget(target);
this.target = target; super.setTarget(target);
} }
protected void checkTarget(MethodHandle target) { protected void checkTarget(MethodHandle target) {
target.type(); // provoke NPE target.type(); // provoke NPE
if (!canSetTarget(target)) if (!canSetTarget(target))
throw new WrongMethodTypeException(String.valueOf(target)); throw new WrongMethodTypeException(String.valueOf(target)+target.type()+" should be of type "+type());
} }
protected boolean canSetTarget(MethodHandle target) { protected boolean canSetTarget(MethodHandle target) {
...@@ -219,6 +238,10 @@ public class CallSite { ...@@ -219,6 +238,10 @@ public class CallSite {
@Override @Override
public String toString() { public String toString() {
return "CallSite#"+hashCode()+"["+name+type+" => "+target+"]"; return "CallSite#"+hashCode()+"["+name+type+" => "+getTarget()+"]";
} }
// Package-local constant:
static final MethodHandle GET_TARGET = MethodHandleImpl.getLookup(IMPL_TOKEN).
findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
} }
...@@ -45,6 +45,24 @@ package java.dyn; ...@@ -45,6 +45,24 @@ package java.dyn;
* class or interface supertype, or an object type; it can never be instantiated. * class or interface supertype, or an object type; it can never be instantiated.
* Logically, it denotes a source of all dynamically typed methods. * Logically, it denotes a source of all dynamically typed methods.
* It may be viewed as a pure syntactic marker (an importable one) of static calls. * It may be viewed as a pure syntactic marker (an importable one) of static calls.
* <p>
* Here are some examples of usage:
* <p><blockquote><pre>
* Object x; String s; int i;
* x = InvokeDynamic.greet("world"); // greet(Ljava/lang/String;)Ljava/lang/Object;
* s = InvokeDynamic.&lt;String&gt;hail(x); // hail(Ljava/lang/Object;)Ljava/lang/String;
* InvokeDynamic.&lt;void&gt;cogito(); // cogito()V
* i = InvokeDynamic.&lt;int&gt;#"op:+"(2, 3); // "op:+"(II)I
* </pre></blockquote>
* Each of the above calls generates a single invokedynamic instruction
* with the name-and-type descriptors indicated in the comments.
* The argument types are taken directly from the actual arguments,
* while the return type is taken from the type parameter.
* (This type parameter may be a primtive, and it defaults to {@code Object}.)
* The final example uses a special syntax for uttering non-Java names.
* Any name legal to the JVM may be given between the double quotes.
* None of these calls is complete without a bootstrap method,
* which must be registered by the static initializer of the enclosing class.
* @author John Rose, JSR 292 EG * @author John Rose, JSR 292 EG
*/ */
public final class InvokeDynamic { public final class InvokeDynamic {
......
...@@ -52,4 +52,16 @@ public class InvokeDynamicBootstrapError extends LinkageError { ...@@ -52,4 +52,16 @@ public class InvokeDynamicBootstrapError extends LinkageError {
public InvokeDynamicBootstrapError(String s) { public InvokeDynamicBootstrapError(String s) {
super(s); super(s);
} }
/**
* Constructs a {@code InvokeDynamicBootstrapError} with the specified
* detail message and cause.
*
* @param s the detail message.
* @param cause the cause.
*/
public InvokeDynamicBootstrapError(String s, Throwable cause) {
super(s);
this.initCause(cause);
}
} }
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
package java.dyn; package java.dyn;
import sun.dyn.Access;
/** /**
* A Java method handle extends the basic method handle type with additional * A Java method handle extends the basic method handle type with additional
* programmer defined methods and fields. * programmer defined methods and fields.
...@@ -39,31 +41,105 @@ package java.dyn; ...@@ -39,31 +41,105 @@ package java.dyn;
* of the entry point method handle, with the leading parameter type * of the entry point method handle, with the leading parameter type
* omitted. * omitted.
* <p> * <p>
* Here is an example of usage: * Here is an example of usage, creating a hybrid object/functional datum:
* <p><blockquote><pre>
* class Greeter extends JavaMethodHandle {
* private String greeting = "hello";
* public void setGreeting(String s) { greeting = s; }
* public void run() { System.out.println(greeting+", "+greetee); }
* private final String greetee;
* Greeter(String greetee) {
* super(RUN); // alternatively, super("run")
* this.greetee = greetee;
* }
* // the entry point function is computed once:
* private static final MethodHandle RUN
* = MethodHandles.lookup().findVirtual(Greeter.class, "run",
* MethodType.make(void.class));
* }
* // class Main { public static void main(String... av) { ...
* Greeter greeter = new Greeter("world");
* greeter.run(); // prints "hello, world"
* // Statically typed method handle invocation (most direct):
* MethodHandle mh = greeter;
* mh.&lt;void&gt;invoke(); // also prints "hello, world"
* // Dynamically typed method handle invocation:
* MethodHandles.invoke(greeter); // also prints "hello, world"
* greeter.setGreeting("howdy");
* mh.invoke(); // prints "howdy, world" (object-like mutable behavior)
* </pre></blockquote>
* <p>
* In the example of {@code Greeter}, the method {@code run} provides the entry point.
* The entry point need not be a constant value; it may be independently
* computed in each call to the constructor. The entry point does not
* even need to be a method on the {@code Greeter} class, though
* that is the typical case.
* <p>
* The entry point may also be provided symbolically, in which case the the
* {@code JavaMethodHandle} constructor performs the lookup of the entry point.
* This makes it possible to use {@code JavaMethodHandle} to create an anonymous
* inner class:
* <p><blockquote><pre> * <p><blockquote><pre>
* class Greeter extends JavaMethodHandle { * // We can also do this with symbolic names and/or inner classes:
* MethodHandles.invoke(new JavaMethodHandle("yow") {
* void yow() { System.out.println("yow, world"); }
* });
* </pre></blockquote>
* <p>
* Here is similar lower-level code which works in terms of a bound method handle.
* <p><blockquote><pre>
* class Greeter {
* public void run() { System.out.println("hello, "+greetee); } * public void run() { System.out.println("hello, "+greetee); }
* private final String greetee; * private final String greetee;
* Greeter(String greetee) { * Greeter(String greetee) { this.greetee = greetee; }
* super(RUN);
* this.greetee = greetee;
* }
* // the entry point function is computed once: * // the entry point function is computed once:
* private static final MethodHandle RUN * private static final MethodHandle RUN
* = MethodHandles.findVirtual(MyMethodHandle.class, "run", * = MethodHandles.findVirtual(Greeter.class, "run",
* MethodType.make(void.class)); * MethodType.make(void.class));
* } * }
* // class Main { public static void main(String... av) { ...
* Greeter greeter = new Greeter("world"); * Greeter greeter = new Greeter("world");
* greeter.run(); // prints "hello, world" * greeter.run(); // prints "hello, world"
* MethodHandle mh = greeter; * MethodHandle mh = MethodHanndles.insertArgument(Greeter.RUN, 0, greeter);
* mh.invoke(); // also prints "hello, world" * mh.invoke(); // also prints "hello, world"
* </pre></blockquote> * </pre></blockquote>
* Note that the method handle must be separately created as a view on the base object.
* This increases footprint, complexity, and dynamic indirections.
* <p> * <p>
* In this example, the method {@code run} provides the entry point. * Here is a pure functional value expressed most concisely as an anonymous inner class:
* The entry point need not be a constant value; it may be independently * <p><blockquote><pre>
* computed in each call to the constructor. The entry point does not * // class Main { public static void main(String... av) { ...
* even need to be a method on the Java method handle class, though * final String greetee = "world";
* that is the typical case. * MethodHandle greeter = new JavaMethodHandle("run") {
* private void run() { System.out.println("hello, "+greetee); }
* }
* greeter.invoke(); // prints "hello, world"
* </pre></blockquote>
* <p>
* Here is an abstract parameterized lvalue, efficiently expressed as a subtype of MethodHandle,
* and instantiated as an anonymous class. The data structure is a handle to 1-D array,
* with a specialized index type (long). It is created by inner class, and uses
* signature-polymorphic APIs throughout.
* <p><blockquote><pre>
* abstract class AssignableMethodHandle extends JavaMethodHandle {
* private final MethodHandle setter;
* public MethodHandle setter() { return setter; }
* public AssignableMethodHandle(String get, String set) {
* super(get);
* MethodType getType = this.type();
* MethodType setType = getType.insertParameterType(getType.parameterCount(), getType.returnType()).changeReturnType(void.class);
* this.setter = MethodHandles.publicLookup().bind(this, set, setType);
* }
* }
* // class Main { public static void main(String... av) { ...
* final Number[] stuff = { 123, 456 };
* AssignableMethodHandle stuffPtr = new AssignableMethodHandle("get", "set") {
* public Number get(long i) { return stuff[(int)i]; }
* public void set(long i, Object x) { stuff[(int)i] = x; }
* }
* int x = (Integer) stuffPtr.&lt;Number&gt;invoke(1L); // 456
* stuffPtr.setter().&lt;void&gt;invoke(0L, (Number) 789); // replaces 123 with 789
* </pre></blockquote>
* @see MethodHandle * @see MethodHandle
* @author John Rose, JSR 292 EG * @author John Rose, JSR 292 EG
*/ */
...@@ -72,12 +148,87 @@ public abstract class JavaMethodHandle ...@@ -72,12 +148,87 @@ public abstract class JavaMethodHandle
// with a JVM change which moves the required hidden behavior onto this class. // with a JVM change which moves the required hidden behavior onto this class.
extends sun.dyn.BoundMethodHandle extends sun.dyn.BoundMethodHandle
{ {
private static final Access IMPL_TOKEN = Access.getToken();
/** /**
* When creating a, pass in {@code entryPoint}, any method handle which * When creating a {@code JavaMethodHandle}, the actual method handle
* can take the current object * invocation behavior will be delegated to the specified {@code entryPoint}.
* @param entryPoint * This may be any method handle which can take the newly constructed object
* as a leading parameter.
* <p>
* The method handle type of {@code this} (i.e, the fully constructed object)
* will be {@code entryPoint}, minus the leading argument.
* The leading argument will be bound to {@code this} on every method
* handle invocation.
* @param entryPoint the method handle to handle calls
*/ */
protected JavaMethodHandle(MethodHandle entryPoint) { protected JavaMethodHandle(MethodHandle entryPoint) {
super(entryPoint, 0); super(entryPoint);
}
/**
* Create a method handle whose entry point is a non-static method
* visible in the exact (most specific) class of
* the newly constructed object.
* <p>
* The method is specified by name and type, as if via this expression:
* {@code MethodHandles.lookup().findVirtual(this.getClass(), name, type)}.
* The class defining the method might be an anonymous inner class.
* <p>
* The method handle type of {@code this} (i.e, the fully constructed object)
* will be the given method handle type.
* A call to {@code this} will invoke the selected method.
* The receiver argument will be bound to {@code this} on every method
* handle invocation.
* <p>
* <i>Rationale:</i>
* Although this constructor may seem to be a mere luxury,
* it is not subsumed by the more general constructor which
* takes any {@code MethodHandle} as the entry point argument.
* In order to convert an entry point name to a method handle,
* the self-class of the object is required (in order to do
* the lookup). The self-class, in turn, is generally not
* available at the time of the constructor invocation,
* due to the rules of Java and the JVM verifier.
* One cannot call {@code this.getClass()}, because
* the value of {@code this} is inaccessible at the point
* of the constructor call. (Changing this would require
* change to the Java language, verifiers, and compilers.)
* In particular, this constructor allows {@code JavaMethodHandle}s
* to be created in combination with the anonymous inner class syntax.
* @param entryPointName the name of the entry point method
* @param type (optional) the desired type of the method handle
*/
protected JavaMethodHandle(String entryPointName, MethodType type) {
super(entryPointName, type, true);
}
/**
* Create a method handle whose entry point is a non-static method
* visible in the exact (most specific) class of
* the newly constructed object.
* <p>
* The method is specified only by name.
* There must be exactly one method of that name visible in the object class,
* either inherited or locally declared.
* (That is, the method must not be overloaded.)
* <p>
* The method handle type of {@code this} (i.e, the fully constructed object)
* will be the same as the type of the selected non-static method.
* The receiver argument will be bound to {@code this} on every method
* handle invocation.
* <p>ISSUE: This signature wildcarding feature does not correspond to
* any MethodHandles.Lookup API element. Can we eliminate it?
* Alternatively, it is useful for naming non-overloaded methods.
* Shall we make type arguments optional in the Lookup methods,
* throwing an error in cases of ambiguity?
* <p>
* For this method's rationale, see the documentation
* for {@link #JavaMethodHandle(String,MethodType)}.
* @param entryPointName the name of the entry point method
*/
protected JavaMethodHandle(String entryPointName) {
super(entryPointName, (MethodType) null, false);
} }
} }
...@@ -25,7 +25,9 @@ ...@@ -25,7 +25,9 @@
package java.dyn; package java.dyn;
import java.dyn.MethodHandles.Lookup;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import sun.dyn.Access;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import static sun.dyn.util.VerifyAccess.checkBootstrapPrivilege; import static sun.dyn.util.VerifyAccess.checkBootstrapPrivilege;
...@@ -34,6 +36,8 @@ import static sun.dyn.util.VerifyAccess.checkBootstrapPrivilege; ...@@ -34,6 +36,8 @@ import static sun.dyn.util.VerifyAccess.checkBootstrapPrivilege;
* @author John Rose, JSR 292 EG * @author John Rose, JSR 292 EG
*/ */
public class Linkage { public class Linkage {
private static final Access IMPL_TOKEN = Access.getToken();
private Linkage() {} // do not instantiate private Linkage() {} // do not instantiate
/** /**
...@@ -53,19 +57,23 @@ public class Linkage { ...@@ -53,19 +57,23 @@ public class Linkage {
* call to this method. * call to this method.
* <li>The given class is already fully initialized. * <li>The given class is already fully initialized.
* <li>The given class is in the process of initialization, in another thread. * <li>The given class is in the process of initialization, in another thread.
* <li>The same {@code CallSite} object has already been returned from
* a bootstrap method call to another {@code invokedynamic} call site.
* </ul> * </ul>
* Because of these rules, a class may install its own bootstrap method in * Because of these rules, a class may install its own bootstrap method in
* a static initializer. * a static initializer.
* @param callerClass a class that may have {@code invokedynamic} sites
* @param bootstrapMethod the method to use to bootstrap all such sites
*/ */
public static public static
void registerBootstrapMethod(Class callerClass, MethodHandle mh) { void registerBootstrapMethod(Class callerClass, MethodHandle bootstrapMethod) {
Class callc = Reflection.getCallerClass(2); Class callc = Reflection.getCallerClass(2);
checkBootstrapPrivilege(callc, callerClass, "registerBootstrapMethod"); checkBootstrapPrivilege(callc, callerClass, "registerBootstrapMethod");
checkBSM(mh); checkBSM(bootstrapMethod);
synchronized (bootstrapMethods) { synchronized (bootstrapMethods) {
if (bootstrapMethods.containsKey(callerClass)) if (bootstrapMethods.containsKey(callerClass))
throw new IllegalStateException("bootstrap method already declared in "+callerClass); throw new IllegalStateException("bootstrap method already declared in "+callerClass);
bootstrapMethods.put(callerClass, mh); bootstrapMethods.put(callerClass, bootstrapMethod);
} }
} }
...@@ -88,8 +96,9 @@ public class Linkage { ...@@ -88,8 +96,9 @@ public class Linkage {
public static public static
void registerBootstrapMethod(Class<?> runtime, String name) { void registerBootstrapMethod(Class<?> runtime, String name) {
Class callc = Reflection.getCallerClass(2); Class callc = Reflection.getCallerClass(2);
Lookup lookup = new Lookup(IMPL_TOKEN, callc);
MethodHandle bootstrapMethod = MethodHandle bootstrapMethod =
MethodHandles.findStaticFrom(callc, runtime, name, BOOTSTRAP_METHOD_TYPE); lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE);
// FIXME: exception processing wrong here // FIXME: exception processing wrong here
checkBSM(bootstrapMethod); checkBSM(bootstrapMethod);
Linkage.registerBootstrapMethod(callc, bootstrapMethod); Linkage.registerBootstrapMethod(callc, bootstrapMethod);
...@@ -106,8 +115,9 @@ public class Linkage { ...@@ -106,8 +115,9 @@ public class Linkage {
public static public static
void registerBootstrapMethod(String name) { void registerBootstrapMethod(String name) {
Class callc = Reflection.getCallerClass(2); Class callc = Reflection.getCallerClass(2);
Lookup lookup = new Lookup(IMPL_TOKEN, callc);
MethodHandle bootstrapMethod = MethodHandle bootstrapMethod =
MethodHandles.findStaticFrom(callc, callc, name, BOOTSTRAP_METHOD_TYPE); lookup.findStatic(callc, name, BOOTSTRAP_METHOD_TYPE);
// FIXME: exception processing wrong here // FIXME: exception processing wrong here
checkBSM(bootstrapMethod); checkBSM(bootstrapMethod);
Linkage.registerBootstrapMethod(callc, bootstrapMethod); Linkage.registerBootstrapMethod(callc, bootstrapMethod);
...@@ -116,8 +126,7 @@ public class Linkage { ...@@ -116,8 +126,7 @@ public class Linkage {
/** /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em> * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Report the bootstrap method registered for a given class. * Report the bootstrap method registered for a given class.
* Returns null if the class has never yet registered a bootstrap method, * Returns null if the class has never yet registered a bootstrap method.
* or if the class has explicitly registered a null bootstrap method.
* Only callers privileged to set the bootstrap method may inquire * Only callers privileged to set the bootstrap method may inquire
* about it, because a bootstrap method is potentially a back-door entry * about it, because a bootstrap method is potentially a back-door entry
* point into its class. * point into its class.
...@@ -137,12 +146,12 @@ public class Linkage { ...@@ -137,12 +146,12 @@ public class Linkage {
* {@code (Class, String, MethodType)} returning a {@code CallSite}. * {@code (Class, String, MethodType)} returning a {@code CallSite}.
*/ */
public static final MethodType BOOTSTRAP_METHOD_TYPE public static final MethodType BOOTSTRAP_METHOD_TYPE
= MethodType.make(CallSite.class, = MethodType.methodType(CallSite.class,
Class.class, String.class, MethodType.class); Class.class, String.class, MethodType.class);
private static final MethodType OLD_BOOTSTRAP_METHOD_TYPE private static final MethodType OLD_BOOTSTRAP_METHOD_TYPE
= MethodType.make(Object.class, = MethodType.methodType(Object.class,
CallSite.class, Object[].class); CallSite.class, Object[].class);
private static final WeakHashMap<Class, MethodHandle> bootstrapMethods = private static final WeakHashMap<Class, MethodHandle> bootstrapMethods =
new WeakHashMap<Class, MethodHandle>(); new WeakHashMap<Class, MethodHandle>();
...@@ -173,8 +182,8 @@ public class Linkage { ...@@ -173,8 +182,8 @@ public class Linkage {
/** /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em> * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Invalidate all <code>invokedynamic</code> call sites associated * Invalidate all <code>invokedynamic</code> call sites in the bytecodes
* with the given class. * of any methods of the given class.
* (These are exactly those sites which report the given class * (These are exactly those sites which report the given class
* via the {@link CallSite#callerClass()} method.) * via the {@link CallSite#callerClass()} method.)
* <p> * <p>
......
...@@ -88,7 +88,7 @@ public final class LinkagePermission extends BasicPermission { ...@@ -88,7 +88,7 @@ public final class LinkagePermission extends BasicPermission {
/** /**
* Create a new LinkagePermission with the given name. * Create a new LinkagePermission with the given name.
* The name is the symbolic name of the LinkagePermission, such as * The name is the symbolic name of the LinkagePermission, such as
* "registerBootstrapMethod", "invalidateClass.*", etc. An asterisk * "registerBootstrapMethod", "invalidateCallerClass.*", etc. An asterisk
* may appear at the end of the name, following a ".", or by itself, to * may appear at the end of the name, following a ".", or by itself, to
* signify a wildcard match. * signify a wildcard match.
* *
......
...@@ -30,6 +30,9 @@ package java.dyn; ...@@ -30,6 +30,9 @@ package java.dyn;
import sun.dyn.Access; import sun.dyn.Access;
import sun.dyn.MethodHandleImpl; import sun.dyn.MethodHandleImpl;
import static java.dyn.MethodHandles.invokers; // package-private API
import static sun.dyn.MemberName.newIllegalArgumentException; // utility
/** /**
* A method handle is a typed reference to the entry point of a method. * A method handle is a typed reference to the entry point of a method.
* <p> * <p>
...@@ -45,8 +48,9 @@ import sun.dyn.MethodHandleImpl; ...@@ -45,8 +48,9 @@ import sun.dyn.MethodHandleImpl;
* Every method handle appears as an object containing a method named * Every method handle appears as an object containing a method named
* <code>invoke</code>, whose signature exactly matches * <code>invoke</code>, whose signature exactly matches
* the method handle's type. * the method handle's type.
* A normal Java method call (using the <code>invokevirtual</code> instruction) * A Java method call expression, which compiles to an
* can invoke this method from Java source code (if language support is present). * <code>invokevirtual</code> instruction,
* can invoke this method from Java source code.
* <p> * <p>
* Every call to a method handle specifies an intended method type, * Every call to a method handle specifies an intended method type,
* which must exactly match the type of the method handle. * which must exactly match the type of the method handle.
...@@ -57,6 +61,10 @@ import sun.dyn.MethodHandleImpl; ...@@ -57,6 +61,10 @@ import sun.dyn.MethodHandleImpl;
* The call fails with a {@link WrongMethodTypeException} * The call fails with a {@link WrongMethodTypeException}
* if the method does not exist, even if there is an <code>invoke</code> * if the method does not exist, even if there is an <code>invoke</code>
* method of a closely similar signature. * method of a closely similar signature.
* As with other kinds
* of methods in the JVM, signature matching during method linkage
* is exact, and does not allow for language-level implicit conversions
* such as {@code String} to {@code Object} or {@code short} to {@code int}.
* <p> * <p>
* A method handle is an unrestricted capability to call a method. * A method handle is an unrestricted capability to call a method.
* A method handle can be formed on a non-public method by a class * A method handle can be formed on a non-public method by a class
...@@ -74,6 +82,15 @@ import sun.dyn.MethodHandleImpl; ...@@ -74,6 +82,15 @@ import sun.dyn.MethodHandleImpl;
* (after resolving symbolic type names) must exactly match the method type * (after resolving symbolic type names) must exactly match the method type
* of the target method. * of the target method.
* <p> * <p>
* Every <code>invoke</code> method always throws {@link Exception},
* which is to say that there is no static restriction on what a method handle
* can throw. Since the JVM does not distinguish between checked
* and unchecked exceptions (other than by their class, of course),
* there is no particular effect on bytecode shape from ascribing
* checked exceptions to method handle invocations. But in Java source
* code, methods which perform method handle calls must either explicitly
* throw {@code Exception}, or else must catch all checked exceptions locally.
* <p>
* Bytecode in an extended JVM can directly obtain a method handle * Bytecode in an extended JVM can directly obtain a method handle
* for any accessible method from a <code>ldc</code> instruction * for any accessible method from a <code>ldc</code> instruction
* which refers to a <code>CONSTANT_Methodref</code> or * which refers to a <code>CONSTANT_Methodref</code> or
...@@ -97,6 +114,59 @@ import sun.dyn.MethodHandleImpl; ...@@ -97,6 +114,59 @@ import sun.dyn.MethodHandleImpl;
* can also be created. These do not perform virtual lookup based on * can also be created. These do not perform virtual lookup based on
* receiver type. Such a method handle simulates the effect of * receiver type. Such a method handle simulates the effect of
* an <code>invokespecial</code> instruction to the same method. * an <code>invokespecial</code> instruction to the same method.
* <p>
* Here are some examples of usage:
* <p><blockquote><pre>
* Object x, y; String s; int i;
* MethodType mt; MethodHandle mh;
* MethodHandles.Lookup lookup = MethodHandles.lookup();
* // mt is {(char,char) =&gt; String}
* mt = MethodType.make(String.class, char.class, char.class);
* mh = lookup.findVirtual(String.class, "replace", mt);
* // (Ljava/lang/String;CC)Ljava/lang/String;
* s = mh.&lt;String&gt;invoke("daddy",'d','n');
* assert(s.equals("nanny"));
* // weakly typed invocation (using MHs.invoke)
* s = (String) MethodHandles.invoke(mh, "sappy", 'p', 'v');
* assert(s.equals("savvy"));
* // mt is {Object[] =&gt; List}
* mt = MethodType.make(java.util.List.class, Object[].class);
* mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
* // mt is {(Object,Object,Object) =&gt; Object}
* mt = MethodType.makeGeneric(3);
* mh = MethodHandles.collectArguments(mh, mt);
* // mt is {(Object,Object,Object) =&gt; Object}
* // (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
* x = mh.invoke((Object)1, (Object)2, (Object)3);
* assert(x.equals(java.util.Arrays.asList(1,2,3)));
* // mt is { =&gt; int}
* mt = MethodType.make(int.class);
* mh = lookup.findVirtual(java.util.List.class, "size", mt);
* // (Ljava/util/List;)I
* i = mh.&lt;int&gt;invoke(java.util.Arrays.asList(1,2,3));
* assert(i == 3);
* </pre></blockquote>
* Each of the above calls generates a single invokevirtual instruction
* with the name {@code invoke} and the type descriptors indicated in the comments.
* The argument types are taken directly from the actual arguments,
* while the return type is taken from the type parameter.
* (This type parameter may be a primitive, and it defaults to {@code Object}.)
* <p>
* <em>A note on generic typing:</em> Method handles do not represent
* their function types in terms of Java parameterized (generic) types,
* because there are three mismatches between function types and parameterized
* Java types.
* <ol>
* <li>Method types range over all possible arities,
* from no arguments to an arbitrary number of arguments.
* Generics are not variadic, and so cannot represent this.</li>
* <li>Method types can specify arguments of primitive types,
* which Java generic types cannot range over.</li>
* <li>Higher order functions over method handles (combinators) are
* often generic across a wide range of function types, including
* those of multiple arities. It is impossible to represent such
* genericity with a Java type parameter.</li>
* </ol>
* *
* @see MethodType * @see MethodType
* @see MethodHandles * @see MethodHandles
...@@ -107,17 +177,19 @@ public abstract class MethodHandle ...@@ -107,17 +177,19 @@ public abstract class MethodHandle
// with a JVM change which moves the required hidden state onto this class. // with a JVM change which moves the required hidden state onto this class.
extends MethodHandleImpl extends MethodHandleImpl
{ {
// interface MethodHandle<T extends MethodType<R,A...>> private static Access IMPL_TOKEN = Access.getToken();
// { T type(); <R,A...> public R invoke(A...); }
final private MethodType type; // interface MethodHandle<R throws X extends Exception,A...>
// { MethodType<R throws X,A...> type(); public R invoke(A...) throws X; }
private MethodType type;
/** /**
* Report the type of this method handle. * Report the type of this method handle.
* Every invocation of this method handle must exactly match this type. * Every invocation of this method handle must exactly match this type.
* @return the method handle type * @return the method handle type
*/ */
public MethodType type() { public final MethodType type() {
return type; return type;
} }
...@@ -130,6 +202,369 @@ public abstract class MethodHandle ...@@ -130,6 +202,369 @@ public abstract class MethodHandle
*/ */
protected MethodHandle(Access token, MethodType type) { protected MethodHandle(Access token, MethodType type) {
super(token); super(token);
Access.check(token);
this.type = type;
}
private void initType(MethodType type) {
type.getClass(); // elicit NPE
if (this.type != null) throw new InternalError();
this.type = type; 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); }
});
}
/** The string of a direct method handle is the simple name of its target method.
* The string of an adapter or bound method handle is the string of its
* target method handle.
* The string of a Java method handle is the string of its entry point method,
* unless the Java method handle overrides the toString method.
*/
@Override
public String toString() {
return MethodHandleImpl.getNameString(IMPL_TOKEN, this);
}
//// First draft of the "Method Handle Kernel API" discussed at the JVM Language Summit, 9/2009.
//// Implementations here currently delegate to statics in MethodHandles. Some of those statics
//// will be deprecated. Others will be kept as "algorithms" to supply degrees of freedom
//// not present in the Kernel API.
/**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Perform an exact invocation. The signature at the call site of {@code invokeExact} must
* exactly match this method handle's {@code type}.
* No conversions are allowed on arguments or return values.
* <em>This is not yet implemented, pending required compiler and JVM support.</em>
*/
public final <T> T invokeExact(Object... arguments) throws Throwable {
// This is an approximate implementation, which discards the caller's signature and refuses the call.
throw new InternalError("not yet implemented");
}
/**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Perform a generic invocation. The signature at the call site of {@code invokeExact} must
* have the same arity as this method handle's {@code type}.
* The same conversions are allowed on arguments or return values as are supported by
* by {@link MethodHandles#convertArguments}.
* If the call site signature exactly matches this method handle's {@code type},
* the call proceeds as if by {@link #invokeExact}.
* <em>This is not fully implemented, pending required compiler and JVM support.</em>
*/
// This is an approximate implementation, which discards the caller's signature.
// When it is made signature polymorphic, the overloadings will disappear.
public final <T> T invokeGeneric() throws Throwable {
MethodHandle invoker = invokers(this.type()).genericInvoker();
return invoker.<T>invoke(this);
}
public final <T> T invokeGeneric(Object a0) throws Throwable {
MethodHandle invoker = invokers(this.type()).genericInvoker();
return invoker.<T>invoke(this, a0);
}
public final <T> T invokeGeneric(Object a0, Object a1) throws Throwable {
MethodHandle invoker = invokers(this.type()).genericInvoker();
return invoker.<T>invoke(this, a0, a1);
}
public final <T> T invokeGeneric(Object a0, Object a1, Object a2) throws Throwable {
MethodHandle invoker = invokers(this.type()).genericInvoker();
return invoker.<T>invoke(this, a0, a1, a2);
}
public final <T> T invokeGeneric(Object a0, Object a1, Object a2, Object a3) throws Throwable {
MethodHandle invoker = invokers(this.type()).genericInvoker();
return invoker.<T>invoke(this, a0, a1, a2, a3);
}
public final <T> T invokeGeneric(Object a0, Object a1, Object a2, Object a3,
Object a4) throws Throwable {
MethodHandle invoker = invokers(this.type()).genericInvoker();
return invoker.<T>invoke(this, a0, a1, a2, a3, a4);
}
public final <T> T invokeGeneric(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5) throws Throwable {
MethodHandle invoker = invokers(this.type()).genericInvoker();
return invoker.<T>invoke(this, a0, a1, a2, a3, a4, a5);
}
public final <T> T invokeGeneric(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5, Object a6) throws Throwable {
MethodHandle invoker = invokers(this.type()).genericInvoker();
return invoker.<T>invoke(this, a0, a1, a2, a3, a4, a5, a6);
}
public final <T> T invokeGeneric(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5, Object a6, Object a7) throws Throwable {
MethodHandle invoker = invokers(this.type()).genericInvoker();
return invoker.<T>invoke(this, a0, a1, a2, a3, a4, a5, a6, a7);
}
public final <T> T invokeGeneric(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable {
MethodHandle invoker = invokers(this.type()).genericInvoker();
return invoker.<T>invoke(this, a0, a1, a2, a3, a4, a5, a6, a7, a8);
}
public final <T> T invokeGeneric(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable {
MethodHandle invoker = invokers(this.type()).genericInvoker();
return invoker.<T>invoke(this, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
}
/**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Perform a varargs invocation, passing the arguments in the given array
* to the method handle, as if via {@link #invokeGeneric} from a call site
* which mentions only the type {@code Object}, and whose arity is the length
* of the argument array.
* <p>
* The length of the arguments array must equal the parameter count
* of the target's type.
* The arguments array is spread into separate arguments.
* <p>
* In order to match the type of the target, the following argument
* conversions are applied as necessary:
* <ul>
* <li>reference casting
* <li>unboxing
* </ul>
* The following conversions are not applied:
* <ul>
* <li>primitive conversions (e.g., {@code byte} to {@code int}
* <li>varargs conversions other than the initial spread
* <li>any application-specific conversions (e.g., string to number)
* </ul>
* The result returned by the call is boxed if it is a primitive,
* or forced to null if the return type is void.
* <p>
* This call is equivalent to the following code:
* <p><blockquote><pre>
* MethodHandle invoker = MethodHandles.genericInvoker(this.type(), 0, true);
* Object result = invoker.invoke(this, arguments);
* </pre></blockquote>
* @param arguments the arguments to pass to the target
* @return the result returned by the target
* @see MethodHandles#genericInvoker
*/
public final Object invokeVarargs(Object[] arguments) throws Throwable {
int argc = arguments == null ? 0 : arguments.length;
MethodType type = type();
if (argc <= 10) {
MethodHandle invoker = MethodHandles.invokers(type).genericInvoker();
switch (argc) {
case 0: return invoker.invoke(this);
case 1: return invoker.invoke(this,
arguments[0]);
case 2: return invoker.invoke(this,
arguments[0], arguments[1]);
case 3: return invoker.invoke(this,
arguments[0], arguments[1], arguments[2]);
case 4: return invoker.invoke(this,
arguments[0], arguments[1], arguments[2],
arguments[3]);
case 5: return invoker.invoke(this,
arguments[0], arguments[1], arguments[2],
arguments[3], arguments[4]);
case 6: return invoker.invoke(this,
arguments[0], arguments[1], arguments[2],
arguments[3], arguments[4], arguments[5]);
case 7: return invoker.invoke(this,
arguments[0], arguments[1], arguments[2],
arguments[3], arguments[4], arguments[5],
arguments[6]);
case 8: return invoker.invoke(this,
arguments[0], arguments[1], arguments[2],
arguments[3], arguments[4], arguments[5],
arguments[6], arguments[7]);
case 9: return invoker.invoke(this,
arguments[0], arguments[1], arguments[2],
arguments[3], arguments[4], arguments[5],
arguments[6], arguments[7], arguments[8]);
case 10: return invoker.invoke(this,
arguments[0], arguments[1], arguments[2],
arguments[3], arguments[4], arguments[5],
arguments[6], arguments[7], arguments[8],
arguments[9]);
}
}
// more than ten arguments get boxed in a varargs list:
MethodHandle invoker = MethodHandles.invokers(type).varargsInvoker(0);
return invoker.invoke(this, arguments);
}
/** Equivalent to {@code invokeVarargs(arguments.toArray())}. */
public final Object invokeVarargs(java.util.List<?> arguments) throws Throwable {
return invokeVarargs(arguments.toArray());
}
/* --- this is intentionally NOT a javadoc yet ---
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Produce an adapter method handle which adapts the type of the
* current method handle to a new type by pairwise argument conversion.
* The original type and new type must have the same number of arguments.
* The resulting method handle is guaranteed to confess a type
* which is equal to the desired new type.
* <p>
* If the original type and new type are equal, returns {@code this}.
* <p>
* The following conversions are applied as needed both to
* arguments and return types. Let T0 and T1 be the differing
* new and old parameter types (or old and new return types)
* for corresponding values passed by the new and old method types.
* Given those types T0, T1, one of the following conversions is applied
* if possible:
* <ul>
* <li>If T0 and T1 are references, and T1 is not an interface type,
* then a cast to T1 is applied.
* (The types do not need to be related in any particular way.)
* <li>If T0 and T1 are references, and T1 is an interface type,
* then the value of type T0 is passed as a T1 without a cast.
* (This treatment of interfaces follows the usage of the bytecode verifier.)
* <li>If T0 and T1 are primitives, then a Java casting
* conversion (JLS 5.5) is applied, if one exists.
* <li>If T0 and T1 are primitives and one is boolean,
* the boolean is treated as a one-bit unsigned integer.
* (This treatment follows the usage of the bytecode verifier.)
* A conversion from another primitive type behaves as if
* it first converts to byte, and then masks all but the low bit.
* <li>If T0 is a primitive and T1 a reference, a boxing
* conversion is applied if one exists, possibly followed by
* an reference conversion to a superclass.
* T1 must be a wrapper class or a supertype of one.
* If T1 is a wrapper class, T0 is converted if necessary
* to T1's primitive type by one of the preceding conversions.
* Otherwise, T0 is boxed, and its wrapper converted to T1.
* <li>If T0 is a reference and T1 a primitive, an unboxing
* conversion is applied if one exists, possibly preceded by
* a reference conversion to a wrapper class.
* T0 must be a wrapper class or a supertype of one.
* If T0 is a wrapper class, its primitive value is converted
* if necessary to T1 by one of the preceding conversions.
* Otherwise, T0 is converted directly to the wrapper type for T1,
* which is then unboxed.
* <li>If the return type T1 is void, any returned value is discarded
* <li>If the return type T0 is void and T1 a reference, a null value is introduced.
* <li>If the return type T0 is void and T1 a primitive, a zero value is introduced.
* </ul>
* <p>
*/
/**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Produce an adapter method handle which adapts the type of the
* current method handle to a new type by pairwise argument conversion.
* The original type and new type must have the same number of arguments.
* The resulting method handle is guaranteed to confess a type
* which is equal to the desired new type.
* <p>
* If the original type and new type are equal, returns {@code this}.
* <p>
* This method is equivalent to {@link MethodHandles#convertArguments}.
* @param newType the expected type of the new method handle
* @return a method handle which delegates to {@code this} after performing
* any necessary argument conversions, and arranges for any
* necessary return value conversions
* @throws IllegalArgumentException if the conversion cannot be made
* @see MethodHandles#convertArguments
*/
public final MethodHandle asType(MethodType newType) {
return MethodHandles.convertArguments(this, newType);
}
/**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Produce a method handle which adapts, as its <i>target</i>,
* the current method handle. The type of the adapter will be
* the same as the type of the target, except that all but the first
* {@code keepPosArgs} parameters of the target's type are replaced
* by a single array parameter of type {@code Object[]}.
* Thus, if {@code keepPosArgs} is zero, the adapter will take all
* arguments in a single object array.
* <p>
* When called, the adapter replaces a trailing array argument
* by the array's elements, each as its own argument to the target.
* (The order of the arguments is preserved.)
* They are converted pairwise by casting and/or unboxing
* (as if by {@link MethodHandles#convertArguments})
* to the types of the trailing parameters of the target.
* Finally the target is called.
* What the target eventually returns is returned unchanged by the adapter.
* <p>
* Before calling the target, the adapter verifies that the array
* contains exactly enough elements to provide a correct argument count
* to the target method handle.
* (The array may also be null when zero elements are required.)
* @param keepPosArgs the number of leading positional arguments to preserve
* @return a new method handle which spreads its final argument,
* before calling the original method handle
* @throws IllegalArgumentException if target does not have at least
* {@code keepPosArgs} parameter types
*/
public final MethodHandle asSpreader(int keepPosArgs) {
MethodType oldType = type();
int nargs = oldType.parameterCount();
MethodType newType = oldType.dropParameterTypes(keepPosArgs, nargs);
newType = newType.insertParameterTypes(keepPosArgs, Object[].class);
return MethodHandles.spreadArguments(this, newType);
}
/**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Produce a method handle which adapts, as its <i>target</i>,
* the current method handle. The type of the adapter will be
* the same as the type of the target, except that a single trailing
* array parameter of type {@code Object[]} is replaced by
* {@code spreadArrayArgs} parameters of type {@code Object}.
* <p>
* When called, the adapter replaces its trailing {@code spreadArrayArgs}
* arguments by a single new {@code Object} array, whose elements
* comprise (in order) the replaced arguments.
* Finally the target is called.
* What the target eventually returns is returned unchanged by the adapter.
* <p>
* (The array may also be a shared constant when {@code spreadArrayArgs} is zero.)
* @param spreadArrayArgs the number of arguments to spread from the trailing array
* @return a new method handle which collects some trailing argument
* into an array, before calling the original method handle
* @throws IllegalArgumentException if the last argument of the target
* is not {@code Object[]}
* @throws IllegalArgumentException if {@code spreadArrayArgs} is not
* a legal array size
* @deprecated Provisional and unstable; use {@link MethodHandles#collectArguments}.
*/
public final MethodHandle asCollector(int spreadArrayArgs) {
MethodType oldType = type();
int nargs = oldType.parameterCount();
MethodType newType = oldType.dropParameterTypes(nargs-1, nargs);
newType = newType.insertParameterTypes(nargs-1, MethodType.genericMethodType(spreadArrayArgs).parameterArray());
return MethodHandles.collectArguments(this, newType);
}
/**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Produce a method handle which binds the given argument
* to the current method handle as <i>target</i>.
* The type of the bound handle will be
* the same as the type of the target, except that a single leading
* reference parameter will be omitted.
* <p>
* When called, the bound handle inserts the given value {@code x}
* as a new leading argument to the target. The other arguments are
* also passed unchanged.
* What the target eventually returns is returned unchanged by the bound handle.
* <p>
* The reference {@code x} must be convertible to the first parameter
* type of the target.
* @param x the value to bind to the first argument of the target
* @return a new method handle which collects some trailing argument
* into an array, before calling the original method handle
* @throws IllegalArgumentException if the target does not have a
* leading parameter type that is a reference type
* @throws ClassCastException if {@code x} cannot be converted
* to the leading parameter type of the target
* @deprecated Provisional and unstable; use {@link MethodHandles#insertArguments}.
*/
public final MethodHandle bindTo(Object x) {
return MethodHandles.insertArguments(this, 0, x);
}
} }
...@@ -34,6 +34,7 @@ import sun.dyn.util.Wrapper; ...@@ -34,6 +34,7 @@ import sun.dyn.util.Wrapper;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import sun.dyn.Invokers; import sun.dyn.Invokers;
...@@ -44,17 +45,14 @@ import static sun.dyn.MemberName.newNoAccessException; ...@@ -44,17 +45,14 @@ import static sun.dyn.MemberName.newNoAccessException;
/** /**
* Fundamental operations and utilities for MethodHandle. * Fundamental operations and utilities for MethodHandle.
* They fall into several categories:
* <ul>
* <li>Reifying methods and fields. This is subject to access checks.
* <li>Invoking method handles on dynamically typed arguments and/or varargs arrays.
* <li>Combining or transforming pre-existing method handles into new ones.
* <li>Miscellaneous emulation of common JVM operations or control flow patterns.
* </ul>
* <p> * <p>
* <em>API Note:</em> The matching of method types in this API cannot
* be completely checked by Java's generic type system for three reasons:
* <ol>
* <li>Method types range over all possible arities,
* from no arguments to an arbitrary number of arguments.
* Generics are not variadic, and so cannot represent this.</li>
* <li>Method types can specify arguments of primitive types,
* which Java generic types cannot range over.</li>
* <li>Method types can optionally specify varargs (ellipsis).</li>
* </ol>
* @author John Rose, JSR 292 EG * @author John Rose, JSR 292 EG
*/ */
public class MethodHandles { public class MethodHandles {
...@@ -68,12 +66,22 @@ public class MethodHandles { ...@@ -68,12 +66,22 @@ public class MethodHandles {
//// Method handle creation from ordinary methods. //// Method handle creation from ordinary methods.
/** Create a {@link Lookup} lookup object on the caller.
*
*/
public static Lookup lookup() { public static Lookup lookup() {
return new Lookup(); return new Lookup();
} }
/** Version of lookup which is trusted minimally.
* It can only be used to create method handles to
* publicly accessible members.
*/
public static Lookup publicLookup() {
return Lookup.PUBLIC_LOOKUP;
}
/** /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* A factory object for creating method handles, when the creation * A factory object for creating method handles, when the creation
* requires access checking. Method handles do not perform * requires access checking. Method handles do not perform
* access checks when they are called; this is a major difference * access checks when they are called; this is a major difference
...@@ -121,7 +129,8 @@ public class MethodHandles { ...@@ -121,7 +129,8 @@ public class MethodHandles {
/** Which class is performing the lookup? It is this class against /** Which class is performing the lookup? It is this class against
* which checks are performed for visibility and access permissions. * which checks are performed for visibility and access permissions.
* <p> * <p>
* This value is null if and only if this lookup is {@link #PUBLIC_LOOKUP}. * This value is null if and only if this lookup was produced
* by {@link MethodHandles#publicLookup}.
*/ */
public Class<?> lookupClass() { public Class<?> lookupClass() {
return lookupClass; return lookupClass;
...@@ -135,23 +144,46 @@ public class MethodHandles { ...@@ -135,23 +144,46 @@ public class MethodHandles {
* an access$N method. * an access$N method.
*/ */
Lookup() { Lookup() {
Class caller = getCallerClassAtEntryPoint(); this(IMPL_TOKEN, getCallerClassAtEntryPoint());
// make sure we haven't accidentally picked up this class: }
checkUnprivilegedlookupClass(caller);
this.lookupClass = caller; Lookup(Access token, Class<?> lookupClass) {
// make sure we haven't accidentally picked up a privileged class:
checkUnprivilegedlookupClass(lookupClass);
this.lookupClass = lookupClass;
}
/**
* Create a lookup on the specified class.
* The result is guaranteed to have no more access privileges
* than the original.
*/
public Lookup in(Class<?> newLookupClass) {
if (this == PUBLIC_LOOKUP) return PUBLIC_LOOKUP;
if (newLookupClass == null) return PUBLIC_LOOKUP;
if (newLookupClass == lookupClass) return this;
if (this != IMPL_LOOKUP) {
if (!VerifyAccess.isSamePackage(lookupClass, newLookupClass))
throw newNoAccessException(new MemberName(newLookupClass), this);
checkUnprivilegedlookupClass(newLookupClass);
}
return new Lookup(newLookupClass);
} }
private Lookup(Class<?> lookupClass) { private Lookup(Class<?> lookupClass) {
this.lookupClass = lookupClass; this.lookupClass = lookupClass;
} }
// Make sure outer class is initialized first.
static { IMPL_TOKEN.getClass(); }
private static final Class<?> PUBLIC_ONLY = sun.dyn.empty.Empty.class; private static final Class<?> PUBLIC_ONLY = sun.dyn.empty.Empty.class;
/** Version of lookup which is trusted minimally. /** Version of lookup which is trusted minimally.
* It can only be used to create method handles to * It can only be used to create method handles to
* publicly accessible members. * publicly accessible members.
*/ */
public static final Lookup PUBLIC_LOOKUP = new Lookup(PUBLIC_ONLY); static final Lookup PUBLIC_LOOKUP = new Lookup(PUBLIC_ONLY);
/** Package-private version of lookup which is trusted. */ /** Package-private version of lookup which is trusted. */
static final Lookup IMPL_LOOKUP = new Lookup(null); static final Lookup IMPL_LOOKUP = new Lookup(null);
...@@ -178,12 +210,16 @@ public class MethodHandles { ...@@ -178,12 +210,16 @@ public class MethodHandles {
// 0: Reflection.getCC, 1: getCallerClassAtEntryPoint, // 0: Reflection.getCC, 1: getCallerClassAtEntryPoint,
// 2: Lookup.<init>, 3: MethodHandles.*, 4: caller // 2: Lookup.<init>, 3: MethodHandles.*, 4: caller
// Note: This should be the only use of getCallerClass in this file. // Note: This should be the only use of getCallerClass in this file.
assert(Reflection.getCallerClass(CALLER_DEPTH-1) == MethodHandles.class);
return Reflection.getCallerClass(CALLER_DEPTH); return Reflection.getCallerClass(CALLER_DEPTH);
} }
/** /**
* Produce a method handle for a static method. * Produce a method handle for a static method.
* The type of the method handle will be that of the method. * The type of the method handle will be that of the method.
* (Since static methods do not take receivers, there is no
* additional receiver argument inserted into the method handle type,
* as there would be with {@linkplain #findVirtual} or {@linkplain #findSpecial}.)
* The method and all its argument types must be accessible to the lookup class. * The method and all its argument types must be accessible to the lookup class.
* If the method's class has not yet been initialized, that is done * If the method's class has not yet been initialized, that is done
* immediately, before the method handle is returned. * immediately, before the method handle is returned.
...@@ -196,10 +232,11 @@ public class MethodHandles { ...@@ -196,10 +232,11 @@ public class MethodHandles {
*/ */
public public
MethodHandle findStatic(Class<?> defc, String name, MethodType type) throws NoAccessException { MethodHandle findStatic(Class<?> defc, String name, MethodType type) throws NoAccessException {
MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookupClass); MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookupClass());
checkStatic(true, method, lookupClass); VerifyAccess.checkName(method, this);
checkStatic(true, method, this);
//throw NoSuchMethodException //throw NoSuchMethodException
return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClass); return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClass());
} }
/** /**
...@@ -228,9 +265,10 @@ public class MethodHandles { ...@@ -228,9 +265,10 @@ public class MethodHandles {
* @exception NoAccessException if the method does not exist or access checking fails * @exception NoAccessException if the method does not exist or access checking fails
*/ */
public MethodHandle findVirtual(Class<?> defc, String name, MethodType type) throws NoAccessException { public MethodHandle findVirtual(Class<?> defc, String name, MethodType type) throws NoAccessException {
MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), true, lookupClass); MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), true, lookupClass());
checkStatic(false, method, lookupClass); VerifyAccess.checkName(method, this);
return MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass); checkStatic(false, method, this);
return MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass());
} }
/** /**
...@@ -259,15 +297,17 @@ public class MethodHandles { ...@@ -259,15 +297,17 @@ public class MethodHandles {
*/ */
public MethodHandle findSpecial(Class<?> defc, String name, MethodType type, public MethodHandle findSpecial(Class<?> defc, String name, MethodType type,
Class<?> specialCaller) throws NoAccessException { Class<?> specialCaller) throws NoAccessException {
checkSpecialCaller(specialCaller, lookupClass); checkSpecialCaller(specialCaller, this);
MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), false, specialCaller); Lookup slookup = this.in(specialCaller);
checkStatic(false, method, lookupClass); MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), false, slookup.lookupClass());
VerifyAccess.checkName(method, this);
checkStatic(false, method, this);
if (name.equals("<init>")) { if (name.equals("<init>")) {
throw newNoAccessException("cannot directly invoke a constructor", method, null); throw newNoAccessException("cannot directly invoke a constructor", method, null);
} else if (defc.isInterface() || !defc.isAssignableFrom(specialCaller)) { } else if (defc.isInterface() || !defc.isAssignableFrom(specialCaller)) {
throw newNoAccessException("method must be in a superclass of lookup class", method, lookupClass); throw newNoAccessException("method must be in a superclass of lookup class", method, slookup.lookupClass());
} }
return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, specialCaller); return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, slookup.lookupClass());
} }
/** /**
...@@ -275,13 +315,19 @@ public class MethodHandles { ...@@ -275,13 +315,19 @@ public class MethodHandles {
* The receiver must have a supertype {@code defc} in which a method * The receiver must have a supertype {@code defc} in which a method
* of the given name and type is accessible to the lookup class. * of the given name and type is accessible to the lookup class.
* The method and all its argument types must be accessible to the lookup class. * The method and all its argument types must be accessible to the lookup class.
* The type of the method handle will be that of the method. * The type of the method handle will be that of the method,
* The given receiver will be bound into the method handle. * without any insertion of an additional receiver parameter.
* The given receiver will be bound into the method handle,
* so that every call to the method handle will invoke the
* requested method on the given receiver.
* <p> * <p>
* Equivalent to the following expression: * This is equivalent to the following expression:
* <code> * <code>
* {@link #insertArgument}({@link #findVirtual}(defc, name, type), receiver) * {@link #insertArguments}({@link #findVirtual}(defc, name, type), receiver)
* </code> * </code>
* where {@code defc} is either {@code receiver.getClass()} or a super
* type of that class, in which the requested method is accessible
* to the lookup class.
* @param receiver the object from which the method is accessed * @param receiver the object from which the method is accessed
* @param name the name of the method * @param name the name of the method
* @param type the type of the method, with the receiver argument omitted * @param type the type of the method, with the receiver argument omitted
...@@ -292,16 +338,18 @@ public class MethodHandles { ...@@ -292,16 +338,18 @@ public class MethodHandles {
public MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException { public MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException {
Class<? extends Object> rcvc = receiver.getClass(); // may get NPE Class<? extends Object> rcvc = receiver.getClass(); // may get NPE
MemberName reference = new MemberName(rcvc, name, type); MemberName reference = new MemberName(rcvc, name, type);
MemberName method = IMPL_NAMES.resolveOrFail(reference, true, lookupClass); MemberName method = IMPL_NAMES.resolveOrFail(reference, true, lookupClass());
checkStatic(false, method, lookupClass); VerifyAccess.checkName(method, this);
MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass); checkStatic(false, method, this);
MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass());
MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver); MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver);
if (bmh == null) if (bmh == null)
throw newNoAccessException(method, lookupClass); throw newNoAccessException(method, this);
return bmh; return bmh;
} }
/** /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Make a direct method handle to <i>m</i>, if the lookup class has permission. * Make a direct method handle to <i>m</i>, if the lookup class has permission.
* If <i>m</i> is non-static, the receiver argument is treated as an initial argument. * If <i>m</i> is non-static, the receiver argument is treated as an initial argument.
* If <i>m</i> is virtual, overriding is respected on every call. * If <i>m</i> is virtual, overriding is respected on every call.
...@@ -316,10 +364,11 @@ public class MethodHandles { ...@@ -316,10 +364,11 @@ public class MethodHandles {
* @exception NoAccessException if access checking fails * @exception NoAccessException if access checking fails
*/ */
public MethodHandle unreflect(Method m) throws NoAccessException { public MethodHandle unreflect(Method m) throws NoAccessException {
return unreflectImpl(new MemberName(m), m.isAccessible(), true, lookupClass); return unreflectImpl(new MemberName(m), m.isAccessible(), true, false, this);
} }
/** /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Produce a method handle for a reflected method. * Produce a method handle for a reflected method.
* It will bypass checks for overriding methods on the receiver, * It will bypass checks for overriding methods on the receiver,
* as if by the {@code invokespecial} instruction. * as if by the {@code invokespecial} instruction.
...@@ -333,37 +382,41 @@ public class MethodHandles { ...@@ -333,37 +382,41 @@ public class MethodHandles {
* @exception NoAccessException if access checking fails * @exception NoAccessException if access checking fails
*/ */
public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws NoAccessException { public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws NoAccessException {
checkSpecialCaller(specialCaller, lookupClass); checkSpecialCaller(specialCaller, this);
Lookup slookup = this.in(specialCaller);
MemberName mname = new MemberName(m); MemberName mname = new MemberName(m);
checkStatic(false, mname, lookupClass); checkStatic(false, mname, this);
return unreflectImpl(mname, m.isAccessible(), false, specialCaller); return unreflectImpl(mname, m.isAccessible(), false, false, slookup);
} }
/** /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Produce a method handle for a reflected constructor. * Produce a method handle for a reflected constructor.
* The type of the method handle will be that of the constructor. * The type of the method handle will be that of the constructor,
* with the return type changed to the declaring class.
* The method handle will perform a {@code newInstance} operation, * The method handle will perform a {@code newInstance} operation,
* creating a new instance of the constructor's class on the * creating a new instance of the constructor's class on the
* arguments passed to the method handle. * arguments passed to the method handle.
* <p> * <p>
* If the constructor's {@code accessible} flag is not set, * If the constructor's {@code accessible} flag is not set,
* access checking is performed immediately on behalf of the lookup class, * access checking is performed immediately on behalf of the lookup class.
* as if {@code invokespecial} instruction were being linked.
* @param ctor the reflected constructor * @param ctor the reflected constructor
* @return a method handle which can invoke the reflected constructor * @return a method handle which can invoke the reflected constructor
* @exception NoAccessException if access checking fails * @exception NoAccessException if access checking fails
*/ */
public MethodHandle unreflectConstructor(Constructor ctor) throws NoAccessException { public MethodHandle unreflectConstructor(Constructor ctor) throws NoAccessException {
MemberName m = new MemberName(ctor); MemberName m = new MemberName(ctor);
return unreflectImpl(m, ctor.isAccessible(), false, lookupClass); return unreflectImpl(m, ctor.isAccessible(), false, false, this);
} }
/** /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em> * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Produce a method handle giving read access to a reflected field. * Produce a method handle giving read access to a reflected field.
* The type of the method handle will have a return type of the field's * The type of the method handle will have a return type of the field's
* value type. Its sole argument will be the field's containing class * value type.
* (but only if it is non-static). * If the field is static, the method handle will take no arguments.
* Otherwise, its single argument will be the instance containing
* the field.
* If the method's {@code accessible} flag is not set, * If the method's {@code accessible} flag is not set,
* access checking is performed immediately on behalf of the lookup class. * access checking is performed immediately on behalf of the lookup class.
* @param f the reflected field * @param f the reflected field
...@@ -371,16 +424,18 @@ public class MethodHandles { ...@@ -371,16 +424,18 @@ public class MethodHandles {
* @exception NoAccessException if access checking fails * @exception NoAccessException if access checking fails
*/ */
public MethodHandle unreflectGetter(Field f) throws NoAccessException { public MethodHandle unreflectGetter(Field f) throws NoAccessException {
return MethodHandleImpl.accessField(IMPL_TOKEN, new MemberName(f), false, lookupClass); MemberName m = new MemberName(f);
return unreflectImpl(m, f.isAccessible(), false, false, this);
} }
/** /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em> * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Produce a method handle giving write access to a reflected field. * Produce a method handle giving write access to a reflected field.
* The type of the method handle will have a void return type. * The type of the method handle will have a void return type.
* Its last argument will be the field's value type. * If the field is static, the method handle will take a single
* Its other argument will be the field's containing class * argument, of the field's value type, the value to be stored.
* (but only if it is non-static). * Otherwise, the two arguments will be the instance containing
* the field, and the value to be stored.
* If the method's {@code accessible} flag is not set, * If the method's {@code accessible} flag is not set,
* access checking is performed immediately on behalf of the lookup class. * access checking is performed immediately on behalf of the lookup class.
* @param f the reflected field * @param f the reflected field
...@@ -388,59 +443,75 @@ public class MethodHandles { ...@@ -388,59 +443,75 @@ public class MethodHandles {
* @exception NoAccessException if access checking fails * @exception NoAccessException if access checking fails
*/ */
public MethodHandle unreflectSetter(Field f) throws NoAccessException { public MethodHandle unreflectSetter(Field f) throws NoAccessException {
return MethodHandleImpl.accessField(IMPL_TOKEN, new MemberName(f), true, lookupClass); MemberName m = new MemberName(f);
return unreflectImpl(m, f.isAccessible(), false, true, this);
} }
} }
static /*must not be public*/ static /*must not be public*/
MethodHandle findStaticFrom(Class<?> lookupClass, MethodHandle findStaticFrom(Lookup lookup,
Class<?> defc, String name, MethodType type) throws NoAccessException { Class<?> defc, String name, MethodType type) throws NoAccessException {
MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookupClass); MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookup.lookupClass());
checkStatic(true, method, lookupClass); VerifyAccess.checkName(method, lookup);
return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClass); checkStatic(true, method, lookup);
return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookup.lookupClass());
} }
static void checkStatic(boolean wantStatic, MemberName m, Class<?> lookupClass) { static void checkStatic(boolean wantStatic, MemberName m, Lookup lookup) {
if (wantStatic != m.isStatic()) { if (wantStatic != m.isStatic()) {
String message = wantStatic ? "expected a static method" : "expected a non-static method"; String message = wantStatic ? "expected a static method" : "expected a non-static method";
throw newNoAccessException(message, m, lookupClass); throw newNoAccessException(message, m, lookup.lookupClass());
} }
} }
static void checkSpecialCaller(Class<?> specialCaller, Class<?> lookupClass) { static void checkSpecialCaller(Class<?> specialCaller, Lookup lookup) {
if (lookupClass == Lookup.IMPL_LOOKUP.lookupClass()) if (lookup == Lookup.IMPL_LOOKUP)
return; // privileged action return; // privileged action
if (lookupClass == null || // public-only access assert(lookup.lookupClass() != null);
!VerifyAccess.isSamePackageMember(specialCaller, lookupClass)) if (!VerifyAccess.isSamePackageMember(specialCaller, lookup.lookupClass()))
throw newNoAccessException("no private access", new MemberName(specialCaller), lookupClass); throw newNoAccessException("no private access", new MemberName(specialCaller), lookup.lookupClass());
} }
// Helper for creating handles on reflected methods and constructors. // Helper for creating handles on reflected methods and constructors.
static MethodHandle unreflectImpl(MemberName m, boolean isAccessible, static MethodHandle unreflectImpl(MemberName m, boolean isAccessible,
boolean doDispatch, Class<?> lookupClass) { boolean doDispatch, boolean isSetter, Lookup lookup) {
MethodType mtype = m.getInvocationType(); MethodType narrowMethodType = null;
Class<?> defc = m.getDeclaringClass(); Class<?> defc = m.getDeclaringClass();
boolean isSpecialInvoke = m.isInvocable() && !doDispatch;
int mods = m.getModifiers(); int mods = m.getModifiers();
if (m.isStatic()) { if (m.isStatic()) {
if (!isAccessible && if (!isAccessible &&
VerifyAccess.isAccessible(defc, mods, false, lookupClass) == null) VerifyAccess.isAccessible(defc, mods, lookup.lookupClass(), false) == null)
throw newNoAccessException(m, lookupClass); throw newNoAccessException(m, lookup);
} else { } else {
Class<?> constraint; Class<?> constraint;
if (isAccessible) { if (isAccessible) {
// abbreviated access check for "unlocked" method // abbreviated access check for "unlocked" method
constraint = doDispatch ? defc : lookupClass; constraint = doDispatch ? defc : lookup.lookupClass();
} else { } else {
constraint = VerifyAccess.isAccessible(defc, mods, doDispatch, lookupClass); constraint = VerifyAccess.isAccessible(defc, mods, lookup.lookupClass(), isSpecialInvoke);
}
if (constraint == null) {
throw newNoAccessException(m, lookup);
} }
if (constraint != defc && !constraint.isAssignableFrom(defc)) { if (constraint != defc && !constraint.isAssignableFrom(defc)) {
if (!defc.isAssignableFrom(constraint)) if (!defc.isAssignableFrom(constraint))
throw newNoAccessException("receiver must be in caller class", m, lookupClass); throw newNoAccessException("receiver must be in caller class", m, lookup.lookupClass());
mtype = mtype.changeParameterType(0, constraint); if (m.isInvocable())
narrowMethodType = m.getInvocationType().changeParameterType(0, constraint);
else if (m.isField())
narrowMethodType = (!isSetter
? MethodType.methodType(m.getFieldType(), constraint)
: MethodType.methodType(void.class, constraint, m.getFieldType()));
} }
} }
return MethodHandleImpl.findMethod(IMPL_TOKEN, m, doDispatch, lookupClass); if (m.isInvocable())
return MethodHandleImpl.findMethod(IMPL_TOKEN, m, doDispatch, lookup.lookupClass());
else if (m.isField())
return MethodHandleImpl.accessField(IMPL_TOKEN, m, isSetter, lookup.lookupClass());
else
throw new InternalError();
} }
/** /**
...@@ -472,138 +543,104 @@ public class MethodHandles { ...@@ -472,138 +543,104 @@ public class MethodHandles {
return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, true); return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, true);
} }
/// method handle invocation (reflective style) /// method handle invocation (reflective style)
/** /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em> * @deprecated Alias for MethodHandle.invokeVarargs.
* Call the {@code invoke} method of a given method handle,
* with arguments that exactly match the parameter types of the method handle.
* The length of the arguments array must equal the parameter count
* of the target's type.
* The arguments array is spread into separate arguments, and
* basic reference and unboxing conversions are applied.
* <p>
* In order to match the type of the target, the following argument
* conversions are applied as necessary:
* <ul>
* <li>reference casting
* <li>unboxing
* </ul>
* The following conversions are not applied:
* <ul>
* <li>primitive conversions (e.g., {@code byte} to {@code int}
* <li>varargs conversions other than the initial spread
* <li>any application-specific conversions (e.g., string to number)
* </ul>
* The result returned by the call is boxed if it is a primitive,
* or forced to null if the return type is void.
* <p>
* This call is a convenience method for the following code:
* <pre>
* MethodHandle invoker = MethodHandles.genericInvoker(target.type(), 0, true);
* Object result = invoker.invoke(arguments);
* </pre>
* @param target the method handle to invoke
* @param arguments the arguments to pass to the target
* @return the result returned by the target
*/ */
@Deprecated
public static public static
Object invoke(MethodHandle target, Object... arguments) { Object invokeVarargs(MethodHandle target, Object... arguments) throws Throwable {
int argc = arguments == null ? 0 : arguments.length; return target.invokeVarargs(arguments);
MethodType type = target.type();
if (argc <= 4) {
MethodHandle invoker = invokers(type).genericInvoker();
switch (argc) {
case 0: return invoker.<Object>invoke(target);
case 1: return invoker.<Object>invoke(target,
arguments[0]);
case 2: return invoker.<Object>invoke(target,
arguments[0], arguments[1]);
case 3: return invoker.<Object>invoke(target,
arguments[0], arguments[1], arguments[2]);
case 4: return invoker.<Object>invoke(target,
arguments[0], arguments[1], arguments[2], arguments[3]);
}
}
MethodHandle invoker = invokers(type).varargsInvoker();
return invoker.<Object>invoke(target, arguments);
} }
/**
* @deprecated Alias for MethodHandle.invokeVarargs.
*/
@Deprecated
public static public static
Object invoke_0(MethodHandle target) { Object invoke(MethodHandle target, Object... arguments) throws Throwable {
MethodHandle invoker = invokers(target.type()).genericInvoker(); return target.invokeVarargs(arguments);
return invoker.<Object>invoke(target);
}
public static
Object invoke_1(MethodHandle target, Object a0) {
MethodHandle invoker = invokers(target.type()).genericInvoker();
return invoker.<Object>invoke(target, a0);
}
public static
Object invoke_2(MethodHandle target, Object a0, Object a1) {
MethodHandle invoker = invokers(target.type()).genericInvoker();
return invoker.<Object>invoke(target, a0, a1);
}
public static
Object invoke_3(MethodHandle target, Object a0, Object a1, Object a2) {
MethodHandle invoker = invokers(target.type()).genericInvoker();
return invoker.<Object>invoke(target, a0, a1, a2);
}
public static
Object invoke_4(MethodHandle target, Object a0, Object a1, Object a2, Object a3) {
MethodHandle invoker = invokers(target.type()).genericInvoker();
return invoker.<Object>invoke(target, a0, a1, a2, a3);
} }
/** /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em> * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Give a method handle which will invoke any method handle of the * Produce a method handle which will invoke any method handle of the
* given type on a standard set of {@code Object} type arguments. * given type on a standard set of {@code Object} type arguments.
* The the resulting invoker will be a method handle with the following * The resulting invoker will be a method handle with the following
* arguments: * arguments:
* <ul> * <ul>
* <li>a single {@code MethodHandle} target * <li>a single {@code MethodHandle} target
* <li>zero or more {@code Object} values * <li>zero or more {@code Object} values (one for each argument in {@code type})
* <li>an optional {@code Object[]} array containing more arguments
* </ul> * </ul>
* The invoker will spread the varargs array (if present), apply * The invoker will apply reference casts as necessary and unbox primitive arguments,
* reference casts as necessary, and unbox primitive arguments. * as if by {@link #convertArguments}.
* The return value of the invoker will be an {@code Object} reference, * The return value of the invoker will be an {@code Object} reference,
* boxing a primitive value if the original type returns a primitive, * boxing a primitive value if the original type returns a primitive,
* and always null if the original type returns void. * and always null if the original type returns void.
* <p> * <p>
* This is a convenience method equivalent to the following code: * This method is equivalent to the following code (though it may be more efficient):
* <pre> * <p><blockquote><pre>
* MethodHandle invoker = exactInvoker(type); * MethodHandle invoker = exactInvoker(type);
* MethodType genericType = MethodType.makeGeneric(objectArgCount, varargs); * MethodType genericType = type.generic();
* genericType = genericType.insertParameterType(0, MethodHandle.class); * genericType = genericType.insertParameterType(0, MethodHandle.class);
* if (!varargs) * return convertArguments(invoker, genericType);
* return convertArguments(invoker, genericType); * </pre></blockquote>
* else * @param type the type of target methods which the invoker will apply to
* return spreadArguments(invoker, genericType); * @return a method handle suitable for invoking any method handle of the given type
* </pre> */
static public
MethodHandle genericInvoker(MethodType type) {
return invokers(type).genericInvoker();
}
/**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Produce a method handle which will invoke any method handle of the
* given type on a standard set of {@code Object} type arguments
* and a single trailing {@code Object[]} array.
* The resulting invoker will be a method handle with the following
* arguments:
* <ul>
* <li>a single {@code MethodHandle} target
* <li>zero or more {@code Object} values (counted by {@code objectArgCount})
* <li>an {@code Object[]} array containing more arguments
* </ul>
* The invoker will spread the varargs array, apply
* reference casts as necessary, and unbox primitive arguments.
* The return value of the invoker will be an {@code Object} reference,
* boxing a primitive value if the original type returns a primitive,
* and always null if the original type returns void.
* <p>
* This method is equivalent to the following code (though it may be more efficient):
* <p><blockquote><pre>
* MethodHandle invoker = exactInvoker(type);
* MethodType vaType = MethodType.makeGeneric(objectArgCount, true);
* vaType = vaType.insertParameterType(0, MethodHandle.class);
* return spreadArguments(invoker, vaType);
* </pre></blockquote>
* @param type the desired target type * @param type the desired target type
* @param objectArgCount number of fixed (non-varargs) {@code Object} arguments * @param objectArgCount number of fixed (non-varargs) {@code Object} arguments
* @param varargs if true, the invoker will accept a final {@code Object[]} argument
* @return a method handle suitable for invoking any method handle of the given type * @return a method handle suitable for invoking any method handle of the given type
*/ */
static public static public
MethodHandle genericInvoker(MethodType type, int objectArgCount, boolean varargs) { MethodHandle varargsInvoker(MethodType type, int objectArgCount) {
return invokers(type).genericInvoker(); if (objectArgCount < 0 || objectArgCount > type.parameterCount())
throw new IllegalArgumentException("bad argument count "+objectArgCount);
return invokers(type).varargsInvoker(objectArgCount);
} }
/** /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em> * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Give a method handle which will take a invoke any method handle of the * Produce a method handle which will take a invoke any method handle of the
* given type. The resulting invoker will have a type which is * given type. The resulting invoker will have a type which is
* exactly equal to the desired type, except that it will accept * exactly equal to the desired type, except that it will accept
* an additional leading argument of type {@code MethodHandle}. * an additional leading argument of type {@code MethodHandle}.
* <p> * <p>
* This is a convenience method equivalent to the following code: * This method is equivalent to the following code (though it may be more efficient):
* <pre> * <p><blockquote><pre>
* MethodHandles.lookup().findVirtual(MethodHandle.class, "invoke", type); * lookup().findVirtual(MethodHandle.class, "invoke", type);
* </pre> * </pre></blockquote>
* @param type the desired target type * @param type the desired target type
* @return a method handle suitable for invoking any method handle of the given type * @return a method handle suitable for invoking any method handle of the given type
*/ */
...@@ -612,7 +649,30 @@ public class MethodHandles { ...@@ -612,7 +649,30 @@ public class MethodHandles {
return invokers(type).exactInvoker(); return invokers(type).exactInvoker();
} }
static private Invokers invokers(MethodType type) { /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Produce a method handle equivalent to an invokedynamic instruction
* which has been linked to the given call site.
* Along with {@link Lookup#findVirtual}, {@link Lookup#findStatic},
* and {@link Lookup#findSpecial}, this completes the emulation
* of the JVM's {@code invoke} instructions.
* <p>This method is equivalent to the following code:
* <p><blockquote><pre>
* MethodHandle getTarget, invoker, result;
* getTarget = lookup().bind(site, "getTarget", methodType(MethodHandle.class));
* invoker = exactInvoker(site.type());
* result = foldArguments(invoker, getTarget)
* </pre></blockquote>
* @return a method handle which always invokes the call site's target
*/
public static
MethodHandle dynamicInvoker(CallSite site) {
MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, CallSite.GET_TARGET, site);
MethodHandle invoker = exactInvoker(site.type());
return foldArguments(invoker, getTarget);
}
static Invokers invokers(MethodType type) {
return MethodTypeImpl.invokers(IMPL_TOKEN, type); return MethodTypeImpl.invokers(IMPL_TOKEN, type);
} }
...@@ -688,14 +748,11 @@ public class MethodHandles { ...@@ -688,14 +748,11 @@ public class MethodHandles {
/// method handle modification (creation from other method handles) /// method handle modification (creation from other method handles)
/** /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Produce a method handle which adapts the type of the * Produce a method handle which adapts the type of the
* given method handle to a new type, by pairwise argument conversion, * given method handle to a new type by pairwise argument conversion.
* and/or varargs conversion. * The original type and new type must have the same number of arguments.
* The original type and new type must have the same number of
* arguments, or else one or both them the must be varargs types.
* The resulting method handle is guaranteed to confess a type * The resulting method handle is guaranteed to confess a type
* which is equal to the desired new type, with any varargs property erased. * which is equal to the desired new type.
* <p> * <p>
* If the original type and new type are equal, returns target. * If the original type and new type are equal, returns target.
* <p> * <p>
...@@ -703,26 +760,15 @@ public class MethodHandles { ...@@ -703,26 +760,15 @@ public class MethodHandles {
* arguments and return types. Let T0 and T1 be the differing * arguments and return types. Let T0 and T1 be the differing
* new and old parameter types (or old and new return types) * new and old parameter types (or old and new return types)
* for corresponding values passed by the new and old method types. * for corresponding values passed by the new and old method types.
* <p>
* If an ordinary (non-varargs) parameter of the new type is
* to be boxed in a varargs parameter of the old type of type T1[],
* then T1 is the element type of the varargs array.
* Otherwise, if a varargs parameter of the new type of type T0[]
* is to be spread into one or more outgoing old type parameters,
* then T0 is the element type of the
* If the new type is varargs and the old type is not, the varargs
* argument will be checked and must be a non-null array of exactly
* the right length. If there are no parameters in the old type
* corresponding to the new varargs parameter, the varargs argument
* is also allowed to be null.
* <p>
* Given those types T0, T1, one of the following conversions is applied * Given those types T0, T1, one of the following conversions is applied
* if possible: * if possible:
* <ul> * <ul>
* <li>If T0 and T1 are references, then a cast to T2 is applied, * <li>If T0 and T1 are references, and T1 is not an interface type,
* where T2 is Object if T1 is an interface, else T1. * then a cast to T1 is applied.
* (The types do not need to be related in any particular way. * (The types do not need to be related in any particular way.)
* The treatment of interfaces follows the usage of the bytecode verifier.) * <li>If T0 and T1 are references, and T1 is an interface type,
* then the value of type T0 is passed as a T1 without a cast.
* (This treatment of interfaces follows the usage of the bytecode verifier.)
* <li>If T0 and T1 are primitives, then a Java casting * <li>If T0 and T1 are primitives, then a Java casting
* conversion (JLS 5.5) is applied, if one exists. * conversion (JLS 5.5) is applied, if one exists.
* <li>If T0 and T1 are primitives and one is boolean, * <li>If T0 and T1 are primitives and one is boolean,
...@@ -745,16 +791,17 @@ public class MethodHandles { ...@@ -745,16 +791,17 @@ public class MethodHandles {
* if necessary to T1 by one of the preceding conversions. * if necessary to T1 by one of the preceding conversions.
* Otherwise, T0 is converted directly to the wrapper type for T1, * Otherwise, T0 is converted directly to the wrapper type for T1,
* which is then unboxed. * which is then unboxed.
* <li>If T1 is void, any returned value is discarded * <li>If the return type T1 is void, any returned value is discarded
* <li>If T0 is void and T1 a reference, a null value is introduced. * <li>If the return type T0 is void and T1 a reference, a null value is introduced.
* <li>If T0 is void and T1 a primitive, a zero value is introduced. * <li>If the return type T0 is void and T1 a primitive, a zero value is introduced.
* </ul> * </ul>
* @param target the method handle to invoke after arguments are retyped * @param target the method handle to invoke after arguments are retyped
* @param newType the expected type of the new method handle * @param newType the expected type of the new method handle
* @return a method handle which delegates to {@code target} after performing * @return a method handle which delegates to {@code target} after performing
* any necessary argument conversions, and arranges for any * any necessary argument conversions, and arranges for any
* necessary return value conversions * necessary return value conversions
* @throws WrongMethodTypeException if the conversion cannot be made * @throws IllegalArgumentException if the conversion cannot be made
* @see MethodHandle#asType
*/ */
public static public static
MethodHandle convertArguments(MethodHandle target, MethodType newType) { MethodHandle convertArguments(MethodHandle target, MethodType newType) {
...@@ -872,23 +919,17 @@ public class MethodHandles { ...@@ -872,23 +919,17 @@ public class MethodHandles {
* <em>PROVISIONAL API, WORK IN PROGRESS:</em> * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Produce a method handle which adapts the type of the * Produce a method handle which adapts the type of the
* given method handle to a new type, by collecting a series of * given method handle to a new type, by collecting a series of
* trailing arguments into an array. * trailing arguments as elements to a single argument array.
* The resulting method handle is guaranteed to confess a type
* which is equal to the desired new type.
* <p> * <p>
* This method is inverse to {@link #spreadArguments}. * This method may be used as an inverse to {@link #spreadArguments}.
* The final parameter type of the old type must be an array type T[], * The final parameter type of the old type must be an array type T[],
* which is the type of what is called the <i>spread</i> argument. * which is the type of what is called the <i>spread</i> argument.
* The trailing arguments of the new type which correspond to * The trailing arguments of the new type which correspond to
* the spread argument are all converted to type T and collected * the spread argument are all converted to type T and collected
* into an array before the original method is called. * into an array before the original method is called.
* <p>
* ISSUE: Unify this with combineArguments. CollectArguments
* is combineArguments with (a) new Object[]{...} as a combiner,
* and (b) the combined arguments dropped, in favor of the combined result.
* @param target the method handle to invoke after the argument is prepended * @param target the method handle to invoke after the argument is prepended
* @param newType the expected type of the new method handle * @param newType the expected type of the new method handle
* @return a new method handle which collects some trailings argument * @return a new method handle which collects some trailing argument
* into an array, before calling the original method handle * into an array, before calling the original method handle
*/ */
public static public static
...@@ -900,50 +941,72 @@ public class MethodHandles { ...@@ -900,50 +941,72 @@ public class MethodHandles {
int numCollect = (inargs - collectPos); int numCollect = (inargs - collectPos);
if (collectPos < 0 || numCollect < 0) if (collectPos < 0 || numCollect < 0)
throw newIllegalArgumentException("wrong number of arguments"); throw newIllegalArgumentException("wrong number of arguments");
return MethodHandleImpl.collectArguments(IMPL_TOKEN, target, newType, collectPos); MethodHandle res = MethodHandleImpl.collectArguments(IMPL_TOKEN, target, newType, collectPos, null);
if (res == null) {
throw newIllegalArgumentException("cannot collect from "+newType+" to " +oldType);
}
return res;
} }
/** /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em> * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Produce a method handle which calls the original method handle, * Produce a method handle which calls the original method handle {@code target},
* after inserting the given argument at the given position. * after inserting the given argument(s) at the given position.
* The type of the new method handle will drop the corresponding argument * The formal parameters to {@code target} which will be supplied by those
* type from the original handle's type. * arguments are called <em>bound parameters</em>, because the new method
* will contain bindings for those parameters take from {@code values}.
* The type of the new method handle will drop the types for the bound
* parameters from the original target type, since the new method handle
* will no longer require those arguments to be supplied by its callers.
* <p> * <p>
* The given argument object must match the dropped argument type. * Each given argument object must match the corresponding bound parameter type.
* If the dropped argument type is a primitive, the argument object * If a bound parameter type is a primitive, the argument object
* must be a wrapper, and is unboxed to produce the primitive. * must be a wrapper, and will be unboxed to produce the primitive value.
* <p> * <p>
* The <i>pos</i> may range between zero and <i>N</i> (inclusively), * The <i>pos</i> may range between zero and <i>N</i> (inclusively),
* where <i>N</i> is the number of argument types in <i>target</i>, * where <i>N</i> is the number of argument types in resulting method handle
* meaning to insert the new argument as the first or last (respectively), * (after bound parameter types are dropped).
* or somewhere in between.
* @param target the method handle to invoke after the argument is inserted * @param target the method handle to invoke after the argument is inserted
* @param pos where to insert the argument (zero for the first) * @param pos where to insert the argument (zero for the first)
* @param value the argument to insert * @param values the series of arguments to insert
* @return a new method handle which inserts an additional argument, * @return a new method handle which inserts an additional argument,
* before calling the original method handle * before calling the original method handle
*/ */
public static public static
MethodHandle insertArgument(MethodHandle target, int pos, Object value) { MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
int insCount = values.length;
MethodType oldType = target.type(); MethodType oldType = target.type();
ArrayList<Class<?>> ptypes = ArrayList<Class<?>> ptypes =
new ArrayList<Class<?>>(oldType.parameterList()); new ArrayList<Class<?>>(oldType.parameterList());
int outargs = oldType.parameterCount(); int outargs = oldType.parameterCount();
int inargs = outargs - 1; int inargs = outargs - insCount;
if (pos < 0 || pos >= outargs) if (inargs < 0)
throw newIllegalArgumentException("too many values to insert");
if (pos < 0 || pos > inargs)
throw newIllegalArgumentException("no argument type to append"); throw newIllegalArgumentException("no argument type to append");
Class<?> valueType = ptypes.remove(pos); MethodHandle result = target;
value = checkValue(valueType, value); for (int i = 0; i < insCount; i++) {
if (pos == 0 && !valueType.isPrimitive()) { Object value = values[i];
// At least for now, make bound method handles a special case. Class<?> valueType = oldType.parameterType(pos+i);
// This lets us get by with minimal JVM support, at the expense value = checkValue(valueType, value);
// of generating signature-specific adapters as Java bytecodes. if (pos == 0 && !valueType.isPrimitive()) {
MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, target, value); // At least for now, make bound method handles a special case.
if (bmh != null) return bmh; MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, result, value);
// else fall through to general adapter machinery if (bmh != null) {
result = bmh;
continue;
}
// else fall through to general adapter machinery
}
result = MethodHandleImpl.bindArgument(IMPL_TOKEN, result, pos, value);
} }
return MethodHandleImpl.bindArgument(IMPL_TOKEN, target, pos, value); return result;
}
@Deprecated // "use MethodHandles.insertArguments instead"
public static
MethodHandle insertArgument(MethodHandle target, int pos, Object value) {
return insertArguments(target, pos, value);
} }
/** /**
...@@ -953,10 +1016,25 @@ public class MethodHandles { ...@@ -953,10 +1016,25 @@ public class MethodHandles {
* The type of the new method handle will insert the given argument * The type of the new method handle will insert the given argument
* type(s), at that position, into the original handle's type. * type(s), at that position, into the original handle's type.
* <p> * <p>
* The <i>pos</i> may range between zero and <i>N-1</i>, * The <i>pos</i> may range between zero and <i>N</i>,
* where <i>N</i> is the number of argument types in <i>target</i>, * where <i>N</i> is the number of argument types in <i>target</i>,
* meaning to drop the first or last argument (respectively), * meaning to drop the first or last argument (respectively),
* or an argument somewhere in between. * or an argument somewhere in between.
* <p>
* <b>Example:</b>
* <p><blockquote><pre>
* MethodHandle cat = MethodHandles.lookup().
* findVirtual(String.class, "concat", String.class, String.class);
* System.out.println(cat.&lt;String&gt;invoke("x", "y")); // xy
* MethodHandle d0 = dropArguments(cat, 0, String.class);
* System.out.println(d0.&lt;String&gt;invoke("x", "y", "z")); // xy
* MethodHandle d1 = dropArguments(cat, 1, String.class);
* System.out.println(d1.&lt;String&gt;invoke("x", "y", "z")); // xz
* MethodHandle d2 = dropArguments(cat, 2, String.class);
* System.out.println(d2.&lt;String&gt;invoke("x", "y", "z")); // yz
* MethodHandle d12 = dropArguments(cat, 1, String.class, String.class);
* System.out.println(d12.&lt;String&gt;invoke("w", "x", "y", "z")); // wz
* </pre></blockquote>
* @param target the method handle to invoke after the argument is dropped * @param target the method handle to invoke after the argument is dropped
* @param valueTypes the type(s) of the argument to drop * @param valueTypes the type(s) of the argument to drop
* @param pos which argument to drop (zero for the first) * @param pos which argument to drop (zero for the first)
...@@ -964,20 +1042,150 @@ public class MethodHandles { ...@@ -964,20 +1042,150 @@ public class MethodHandles {
* before calling the original method handle * before calling the original method handle
*/ */
public static public static
MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) { MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
if (valueTypes.length == 0) return target; if (valueTypes.size() == 0) return target;
MethodType oldType = target.type(); MethodType oldType = target.type();
int outargs = oldType.parameterCount(); int outargs = oldType.parameterCount();
int inargs = outargs + valueTypes.length; int inargs = outargs + valueTypes.size();
if (pos < 0 || pos >= inargs) if (pos < 0 || pos >= inargs)
throw newIllegalArgumentException("no argument type to remove"); throw newIllegalArgumentException("no argument type to remove");
ArrayList<Class<?>> ptypes = ArrayList<Class<?>> ptypes =
new ArrayList<Class<?>>(oldType.parameterList()); new ArrayList<Class<?>>(oldType.parameterList());
ptypes.addAll(pos, Arrays.asList(valueTypes)); ptypes.addAll(pos, valueTypes);
MethodType newType = MethodType.make(oldType.returnType(), ptypes); MethodType newType = MethodType.methodType(oldType.returnType(), ptypes);
return MethodHandleImpl.dropArguments(IMPL_TOKEN, target, newType, pos); return MethodHandleImpl.dropArguments(IMPL_TOKEN, target, newType, pos);
} }
public static
MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
return dropArguments(target, pos, Arrays.asList(valueTypes));
}
/**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Adapt a target method handle {@code target} by pre-processing
* one or more of its arguments, each with its own unary filter function,
* and then calling the target with each pre-processed argument
* replaced by the result of its corresponding filter function.
* <p>
* The pre-processing is performed by one or more method handles,
* specified in the non-null elements of the {@code filters} array.
* (If there are no such elements, the original target is returned.)
* Each filter (that is, each non-null element of {@code filters})
* is applied to the corresponding argument of the adapter.
* <p>
* If a filter {@code F} applies to the {@code N}th argument of
* the method handle, then {@code F} must be a method handle which
* takes exactly one argument. The type of {@code F}'s sole argument
* replaces the corresponding argument type of the target
* in the resulting adapted method handle.
* The return type of {@code F} must be identical to the corresponding
* parameter type of the target.
* <p>
* It is an error if there are non-null elements of {@code filters}
* which do not correspond to argument positions in the target.
* The actual length of the target array may be any number, it need
* not be the same as the parameter count of the target type.
* (This provides an easy way to filter just the first argument or two
* of a target method handle.)
* <p> Here is pseudocode for the resulting adapter:
* <blockquote><pre>
* // there are N arguments in the A sequence
* T target(A[N]...);
* [i&lt;N] V[i] filter[i](B[i]) = filters[i] ?: identity;
* T adapter(B[N]... b) {
* A[N] a...;
* [i&lt;N] a[i] = filter[i](b[i]);
* return target(a...);
* }
* </pre></blockquote>
* @param target the method handle to invoke after arguments are filtered
* @param filters method handles to call initially on filtered arguments
* @return method handle which incorporates the specified argument filtering logic
* @throws IllegalArgumentException if a non-null element of {@code filters}
* does not match a corresponding argument type of {@code target}
*/
public static
MethodHandle filterArguments(MethodHandle target, MethodHandle... filters) {
MethodType targetType = target.type();
MethodHandle adapter = target;
MethodType adapterType = targetType;
int pos = -1, maxPos = targetType.parameterCount();
for (MethodHandle filter : filters) {
pos += 1;
if (filter == null) continue;
if (pos >= maxPos)
throw newIllegalArgumentException("too many filters");
MethodType filterType = filter.type();
if (filterType.parameterCount() != 1
|| filterType.returnType() != targetType.parameterType(pos))
throw newIllegalArgumentException("target and filter types do not match");
adapterType = adapterType.changeParameterType(pos, filterType.parameterType(0));
adapter = MethodHandleImpl.filterArgument(IMPL_TOKEN, adapter, pos, filter);
}
MethodType midType = adapter.type();
if (midType != adapterType)
adapter = MethodHandleImpl.convertArguments(IMPL_TOKEN, adapter, adapterType, midType, null);
return adapter;
}
/**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Adapt a target method handle {@code target} by pre-processing
* some of its arguments, and then calling the target with
* the result of the pre-processing, plus all original arguments.
* <p>
* The pre-processing is performed by a second method handle, the {@code combiner}.
* The first {@code N} arguments passed to the adapter,
* are copied to the combiner, which then produces a result.
* (Here, {@code N} is defined as the parameter count of the adapter.)
* After this, control passes to the {@code target}, with both the result
* of the combiner, and all the original incoming arguments.
* <p>
* The first argument type of the target must be identical with the
* return type of the combiner.
* The resulting adapter is the same type as the target, except that the
* initial argument type of the target is dropped.
* <p>
* (Note that {@link #dropArguments} can be used to remove any arguments
* that either the {@code combiner} or {@code target} does not wish to receive.
* If some of the incoming arguments are destined only for the combiner,
* consider using {@link #collectArguments} instead, since those
* arguments will not need to be live on the stack on entry to the
* target.)
* <p>
* The first argument of the target must be identical with the
* return value of the combiner.
* <p> Here is pseudocode for the resulting adapter:
* <blockquote><pre>
* // there are N arguments in the A sequence
* T target(V, A[N]..., B...);
* V combiner(A...);
* T adapter(A... a, B... b) {
* V v = combiner(a...);
* return target(v, a..., b...);
* }
* </pre></blockquote>
* @param target the method handle to invoke after arguments are combined
* @param combiner method handle to call initially on the incoming arguments
* @return method handle which incorporates the specified argument folding logic
* @throws IllegalArgumentException if the first argument type of
* {@code target} is not the same as {@code combiner}'s return type,
* or if the next {@code foldArgs} argument types of {@code target}
* are not identical with the argument types of {@code combiner}
*/
public static
MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) {
MethodType targetType = target.type();
MethodType combinerType = combiner.type();
int foldArgs = combinerType.parameterCount();
boolean ok = (targetType.parameterCount() >= 1 + foldArgs);
if (!ok)
throw misMatchedTypes("target and combiner types", targetType, combinerType);
MethodType newType = targetType.dropParameterTypes(0, 1);
return MethodHandleImpl.foldArguments(IMPL_TOKEN, target, newType, combiner);
}
/** /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em> * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Make a method handle which adapts a target method handle, * Make a method handle which adapts a target method handle,
...@@ -985,18 +1193,18 @@ public class MethodHandles { ...@@ -985,18 +1193,18 @@ public class MethodHandles {
* If the guard fails, a fallback handle is called instead. * If the guard fails, a fallback handle is called instead.
* All three method handles must have the same corresponding * All three method handles must have the same corresponding
* argument and return types, except that the return type * argument and return types, except that the return type
* of the test must be boolean. * of the test must be boolean, and the test is allowed
* to have fewer arguments than the other two method handles.
* <p> Here is pseudocode for the resulting adapter: * <p> Here is pseudocode for the resulting adapter:
* <blockquote><pre> * <blockquote><pre>
* signature T(A...);
* boolean test(A...); * boolean test(A...);
* T target(A...); * T target(A...,B...);
* T fallback(A...); * T fallback(A...,B...);
* T adapter(A... a) { * T adapter(A... a,B... b) {
* if (test(a...)) * if (test(a...))
* return target(a...); * return target(a..., b...);
* else * else
* return fallback(a...); * return fallback(a..., b...);
* } * }
* </pre></blockquote> * </pre></blockquote>
* @param test method handle used for test, must return boolean * @param test method handle used for test, must return boolean
...@@ -1011,10 +1219,23 @@ public class MethodHandles { ...@@ -1011,10 +1219,23 @@ public class MethodHandles {
MethodHandle guardWithTest(MethodHandle test, MethodHandle guardWithTest(MethodHandle test,
MethodHandle target, MethodHandle target,
MethodHandle fallback) { MethodHandle fallback) {
if (target.type() != fallback.type()) MethodType gtype = test.type();
throw newIllegalArgumentException("target and fallback types do not match"); MethodType ttype = target.type();
if (target.type().changeReturnType(boolean.class) != test.type()) MethodType ftype = fallback.type();
throw newIllegalArgumentException("target and test types do not match"); if (ttype != ftype)
throw misMatchedTypes("target and fallback types", ttype, ftype);
MethodType gtype2 = ttype.changeReturnType(boolean.class);
if (gtype2 != gtype) {
if (gtype.returnType() != boolean.class)
throw newIllegalArgumentException("guard type is not a predicate "+gtype);
int gpc = gtype.parameterCount(), tpc = ttype.parameterCount();
if (gpc < tpc) {
test = dropArguments(test, gpc, ttype.parameterList().subList(gpc, tpc));
gtype = test.type();
}
if (gtype2 != gtype)
throw misMatchedTypes("target and test types", ttype, gtype);
}
/* { /* {
MethodHandle invoke = findVirtual(MethodHandle.class, "invoke", target.type()); MethodHandle invoke = findVirtual(MethodHandle.class, "invoke", target.type());
static MethodHandle choose(boolean z, MethodHandle t, MethodHandle f) { static MethodHandle choose(boolean z, MethodHandle t, MethodHandle f) {
...@@ -1027,7 +1248,7 @@ public class MethodHandles { ...@@ -1027,7 +1248,7 @@ public class MethodHandles {
} }
// choose = \z.(z ? target : fallback) // choose = \z.(z ? target : fallback)
MethodHandle choose = findVirtual(MethodHandles.class, "choose", MethodHandle choose = findVirtual(MethodHandles.class, "choose",
MethodType.make(boolean.class, MethodHandle.class, MethodHandle.class)); MethodType.methodType(boolean.class, MethodHandle.class, MethodHandle.class));
choose = appendArgument(choose, target); choose = appendArgument(choose, target);
choose = appendArgument(choose, fallback); choose = appendArgument(choose, fallback);
MethodHandle dispatch = compose(choose, test); MethodHandle dispatch = compose(choose, test);
...@@ -1038,67 +1259,88 @@ public class MethodHandles { ...@@ -1038,67 +1259,88 @@ public class MethodHandles {
return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback); return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback);
} }
static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) {
return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2);
}
/** /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em> * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Adapt a target method handle {@code target} by first processing * Make a method handle which adapts a target method handle,
* its arguments, and then calling the target. * by running it inside an exception handler.
* The initial processing is performed by a second method handle, the {@code combiner}. * If the target returns normally, the adapter returns that value.
* After this, control passes to the {@code target}, with the same arguments. * If an exception matching the specified type is thrown, the fallback
* <p> * handle is called instead on the exception, plus the original arguments.
* The return value of the {@code combiner} is inserted into the argument list
* for the {@code target} at the indicated position {@code pos}, if it is non-negative.
* Except for this inserted argument (if any), the argument types of
* the target {@code target} and the {@code combiner} must be identical.
* <p>
* (Note that {@link #dropArguments} can be used to remove any arguments
* that either the {@code combiner} or {@code target} does not wish to receive.)
* <p> * <p>
* The combiner handle must have the same argument types as the * The handler must have leading parameter of {@code exType} or a supertype,
* target handle, but must return {@link MethodHandle} instead of * followed by arguments which correspond <em>(how? TBD)</em> to
* the ultimate return type. The returned method handle, in turn, * all the parameters of the target.
* is required to have exactly the given final method type. * The target and handler must return the same type.
* <p> Here is pseudocode for the resulting adapter: * <p> Here is pseudocode for the resulting adapter:
* <blockquote><pre> * <blockquote><pre>
* signature V(A[pos]..., B...); * T target(A...);
* signature T(A[pos]..., V, B...); * T handler(ExType, A...);
* T target(A... a, V v, B... b); * T adapter(A... a) {
* V combiner(A..., B...); * try {
* T adapter(A... a, B... b) { * return target(a...);
* V v = combiner(a..., b...); * } catch (ExType ex) {
* return target(a..., v, b...); * return handler(ex, a...);
* }
* } * }
* </pre></blockquote> * </pre></blockquote>
* @param target the method handle to invoke after arguments are combined * @param target method handle to call
* @param pos where the return value of {@code combiner} is to * @param exType the type of exception which the handler will catch
* be inserted as an argument to {@code target} * @param handler method handle to call if a matching exception is thrown
* @param combiner method handle to call initially on the incoming arguments * @return method handle which incorporates the specified try/catch logic
* @return method handle which incorporates the specified dispatch logic * @throws IllegalArgumentException if {@code handler} does not accept
* @throws IllegalArgumentException if {@code combiner} does not itself * the given exception type, or if the method handle types do
* return either void or the {@code pos}-th argument of {@code target}, * not match in their return types and their
* or does not have the same argument types as {@code target} * corresponding parameters
* (minus the inserted argument)
*/ */
public static public static
MethodHandle combineArguments(MethodHandle target, int pos, MethodHandle combiner) { MethodHandle catchException(MethodHandle target,
MethodType mhType = target.type(); Class<? extends Throwable> exType,
Class<?> combineType = combiner.type().returnType(); MethodHandle handler) {
MethodType incomingArgs; MethodType targetType = target.type();
if (pos < 0) { MethodType handlerType = handler.type();
// No inserted argument; target & combiner must have same argument types. boolean ok = (targetType.parameterCount() ==
incomingArgs = mhType; handlerType.parameterCount() - 1);
if (!incomingArgs.changeReturnType(combineType).equals(combiner.type())) // for (int i = 0; ok && i < numExArgs; i++) {
throw newIllegalArgumentException("target and combiner types do not match"); // if (targetType.parameterType(i) != handlerType.parameterType(1+i))
} else { // ok = false;
// Inserted argument. // }
if (pos >= mhType.parameterCount() if (!ok)
|| mhType.parameterType(pos) != combineType) throw newIllegalArgumentException("target and handler types do not match");
throw newIllegalArgumentException("inserted combiner argument does not match target"); return MethodHandleImpl.makeGuardWithCatch(IMPL_TOKEN, target, exType, handler);
incomingArgs = mhType.dropParameterType(pos);
}
if (!incomingArgs.changeReturnType(combineType).equals(combiner.type())) {
throw newIllegalArgumentException("target and combiner types do not match");
}
return MethodHandleImpl.combineArguments(IMPL_TOKEN, target, combiner, pos);
} }
/**
* Produce a method handle which will throw exceptions of the given {@code exType}.
* The method handle will accept a single argument of {@code exType},
* and immediately throw it as an exception.
* The method type will nominally specify a return of {@code returnType}.
* The return type may be anything convenient: It doesn't matter to the
* method handle's behavior, since it will never return normally.
*/
public static
MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
return MethodHandleImpl.throwException(IMPL_TOKEN, MethodType.methodType(returnType, exType));
}
/** Alias for {@link MethodType#methodType}. */
@Deprecated // "use MethodType.methodType instead"
public static MethodType methodType(Class<?> rtype) {
return MethodType.methodType(rtype);
}
/** Alias for {@link MethodType#methodType}. */
@Deprecated // "use MethodType.methodType instead"
public static MethodType methodType(Class<?> rtype, Class<?> ptype) {
return MethodType.methodType(rtype, ptype);
}
/** Alias for {@link MethodType#methodType}. */
@Deprecated // "use MethodType.methodType instead"
public static MethodType methodType(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) {
return MethodType.methodType(rtype, ptype0, ptypes);
}
} }
...@@ -32,7 +32,7 @@ import java.util.List; ...@@ -32,7 +32,7 @@ import java.util.List;
import sun.dyn.Access; import sun.dyn.Access;
import sun.dyn.Invokers; import sun.dyn.Invokers;
import sun.dyn.MethodTypeImpl; import sun.dyn.MethodTypeImpl;
import sun.dyn.util.BytecodeSignature; import sun.dyn.util.BytecodeDescriptor;
import static sun.dyn.MemberName.newIllegalArgumentException; import static sun.dyn.MemberName.newIllegalArgumentException;
/** /**
...@@ -63,7 +63,7 @@ class MethodType { ...@@ -63,7 +63,7 @@ class MethodType {
static { static {
// This hack allows the implementation package special access to // This hack allows the implementation package special access to
// the internals of MethodType. In particular, the Form has all sorts // the internals of MethodType. In particular, the MTImpl has all sorts
// of cached information useful to the implementation code. // of cached information useful to the implementation code.
MethodTypeImpl.setMethodTypeFriend(IMPL_TOKEN, new MethodTypeImpl.MethodTypeFriend() { MethodTypeImpl.setMethodTypeFriend(IMPL_TOKEN, new MethodTypeImpl.MethodTypeFriend() {
public Class<?>[] ptypes(MethodType mt) { return mt.ptypes; } public Class<?>[] ptypes(MethodType mt) { return mt.ptypes; }
...@@ -114,51 +114,76 @@ class MethodType { ...@@ -114,51 +114,76 @@ class MethodType {
* @throws IllegalArgumentException if any of the ptypes is void * @throws IllegalArgumentException if any of the ptypes is void
*/ */
public static public static
MethodType make(Class<?> rtype, Class<?>[] ptypes) { MethodType methodType(Class<?> rtype, Class<?>[] ptypes) {
return makeImpl(rtype, ptypes, false); return makeImpl(rtype, ptypes, false);
} }
@Deprecated public static
MethodType make(Class<?> rtype, Class<?>[] ptypes) {
return methodType(rtype, ptypes);
}
/** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. */ /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. */
public static public static
MethodType methodType(Class<?> rtype, List<? extends Class<?>> ptypes) {
boolean notrust = false; // random List impl. could return evil ptypes array
return makeImpl(rtype, ptypes.toArray(NO_PTYPES), notrust);
}
@Deprecated public static
MethodType make(Class<?> rtype, List<? extends Class<?>> ptypes) { MethodType make(Class<?> rtype, List<? extends Class<?>> ptypes) {
return makeImpl(rtype, ptypes.toArray(NO_PTYPES), true); return methodType(rtype, ptypes);
} }
/** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* The leading parameter type is prepended to the remaining array. * The leading parameter type is prepended to the remaining array.
*/ */
public static public static
MethodType make(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) { MethodType methodType(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) {
Class<?>[] ptypes1 = new Class<?>[1+ptypes.length]; Class<?>[] ptypes1 = new Class<?>[1+ptypes.length];
ptypes1[0] = ptype0; ptypes1[0] = ptype0;
System.arraycopy(ptypes, 0, ptypes1, 1, ptypes.length); System.arraycopy(ptypes, 0, ptypes1, 1, ptypes.length);
return makeImpl(rtype, ptypes1, true); return makeImpl(rtype, ptypes1, true);
} }
@Deprecated public static
MethodType make(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) {
return methodType(rtype, ptype0, ptypes);
}
/** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* The resulting method has no parameter types. * The resulting method has no parameter types.
*/ */
public static public static
MethodType make(Class<?> rtype) { MethodType methodType(Class<?> rtype) {
return makeImpl(rtype, NO_PTYPES, true); return makeImpl(rtype, NO_PTYPES, true);
} }
@Deprecated public static
MethodType make(Class<?> rtype) {
return methodType(rtype);
}
/** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* The resulting method has the single given parameter type. * The resulting method has the single given parameter type.
*/ */
public static public static
MethodType make(Class<?> rtype, Class<?> ptype0) { MethodType methodType(Class<?> rtype, Class<?> ptype0) {
return makeImpl(rtype, new Class<?>[]{ ptype0 }, true); return makeImpl(rtype, new Class<?>[]{ ptype0 }, true);
} }
@Deprecated public static
MethodType make(Class<?> rtype, Class<?> ptype0) {
return methodType(rtype, ptype0);
}
/** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* The resulting method has the same parameter types as {@code ptypes}, * The resulting method has the same parameter types as {@code ptypes},
* and the specified return type. * and the specified return type.
*/ */
public static public static
MethodType make(Class<?> rtype, MethodType ptypes) { MethodType methodType(Class<?> rtype, MethodType ptypes) {
return makeImpl(rtype, ptypes.ptypes, true); return makeImpl(rtype, ptypes.ptypes, true);
} }
@Deprecated public static
MethodType make(Class<?> rtype, MethodType ptypes) {
return methodType(rtype, ptypes);
}
/** /**
* Sole factory method to find or create an interned method type. * Sole factory method to find or create an interned method type.
...@@ -202,15 +227,16 @@ class MethodType { ...@@ -202,15 +227,16 @@ class MethodType {
private static final MethodType[] objectOnlyTypes = new MethodType[20]; private static final MethodType[] objectOnlyTypes = new MethodType[20];
/** /**
* Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}. * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* All parameters and the return type will be Object, except the final varargs parameter if any. * All parameters and the return type will be {@code Object},
* except the final varargs parameter if any, which will be {@code Object[]}.
* @param objectArgCount number of parameters (excluding the varargs parameter if any) * @param objectArgCount number of parameters (excluding the varargs parameter if any)
* @param varargs whether there will be a varargs parameter, of type Object[] * @param varargs whether there will be a varargs parameter, of type {@code Object[]}
* @return a totally generic method type, given only its count of parameters and varargs * @return a totally generic method type, given only its count of parameters and varargs
* @see #makeGeneric(int) * @see #genericMethodType(int)
*/ */
public static public static
MethodType makeGeneric(int objectArgCount, boolean varargs) { MethodType genericMethodType(int objectArgCount, boolean varargs) {
MethodType mt; MethodType mt;
int ivarargs = (!varargs ? 0 : 1); int ivarargs = (!varargs ? 0 : 1);
int ootIndex = objectArgCount*2 + ivarargs; int ootIndex = objectArgCount*2 + ivarargs;
...@@ -227,19 +253,27 @@ class MethodType { ...@@ -227,19 +253,27 @@ class MethodType {
} }
return mt; return mt;
} }
@Deprecated public static
MethodType makeGeneric(int objectArgCount, boolean varargs) {
return genericMethodType(objectArgCount, varargs);
}
/** /**
* All parameters and the return type will be Object. * All parameters and the return type will be Object.
* @param objectArgCount number of parameters * @param objectArgCount number of parameters
* @return a totally generic method type, given only its count of parameters * @return a totally generic method type, given only its count of parameters
* @see #makeGeneric(int, boolean) * @see #genericMethodType(int, boolean)
*/ */
public static public static
MethodType genericMethodType(int objectArgCount) {
return genericMethodType(objectArgCount, false);
}
@Deprecated public static
MethodType makeGeneric(int objectArgCount) { MethodType makeGeneric(int objectArgCount) {
return makeGeneric(objectArgCount, false); return genericMethodType(objectArgCount);
} }
/** Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}. /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* @param num the index (zero-based) of the parameter type to change * @param num the index (zero-based) of the parameter type to change
* @param nptype a new parameter type to replace the old one with * @param nptype a new parameter type to replace the old one with
* @return the same type, except with the selected parameter changed * @return the same type, except with the selected parameter changed
...@@ -251,11 +285,10 @@ class MethodType { ...@@ -251,11 +285,10 @@ class MethodType {
return makeImpl(rtype, nptypes, true); return makeImpl(rtype, nptypes, true);
} }
/** Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}. /** Convenience method for {@link #insertParameterTypes}.
* @param num the position (zero-based) of the inserted parameter type * @deprecated Use {@link #insertParameterTypes} instead.
* @param nptype a new parameter type to insert into the parameter list
* @return the same type, except with the selected parameter inserted
*/ */
@Deprecated
public MethodType insertParameterType(int num, Class<?> nptype) { public MethodType insertParameterType(int num, Class<?> nptype) {
int len = ptypes.length; int len = ptypes.length;
Class<?>[] nptypes = Arrays.copyOfRange(ptypes, 0, len+1); Class<?>[] nptypes = Arrays.copyOfRange(ptypes, 0, len+1);
...@@ -264,23 +297,73 @@ class MethodType { ...@@ -264,23 +297,73 @@ class MethodType {
return makeImpl(rtype, nptypes, true); return makeImpl(rtype, nptypes, true);
} }
/** Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}. /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* @param num the index (zero-based) of the parameter type to remove * @param num the position (zero-based) of the inserted parameter type(s)
* @return the same type, except with the selected parameter removed * @param ptypesToInsert zero or more a new parameter types to insert into the parameter list
* @return the same type, except with the selected parameter(s) inserted
*/ */
public MethodType dropParameterType(int num) { public MethodType insertParameterTypes(int num, Class<?>... ptypesToInsert) {
int len = ptypes.length;
if (num < 0 || num > len)
throw newIllegalArgumentException("num="+num); //SPECME
int ilen = ptypesToInsert.length;
if (ilen == 0) return this;
Class<?>[] nptypes = Arrays.copyOfRange(ptypes, 0, len+ilen);
System.arraycopy(nptypes, num, nptypes, num+ilen, len-num);
System.arraycopy(ptypesToInsert, 0, nptypes, num, ilen);
return makeImpl(rtype, nptypes, true);
}
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* @param num the position (zero-based) of the inserted parameter type(s)
* @param ptypesToInsert zero or more a new parameter types to insert into the parameter list
* @return the same type, except with the selected parameter(s) inserted
*/
public MethodType insertParameterTypes(int num, List<Class<?>> ptypesToInsert) {
return insertParameterTypes(num, ptypesToInsert.toArray(NO_PTYPES));
}
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* @param start the index (zero-based) of the first parameter type to remove
* @param end the index (greater than {@code start}) of the first parameter type after not to remove
* @return the same type, except with the selected parameter(s) removed
*/
public MethodType dropParameterTypes(int start, int end) {
int len = ptypes.length; int len = ptypes.length;
if (!(0 <= start && start <= end && end <= len))
throw newIllegalArgumentException("start="+start+" end="+end); //SPECME
if (start == end) return this;
Class<?>[] nptypes; Class<?>[] nptypes;
if (num == 0) { if (start == 0) {
nptypes = Arrays.copyOfRange(ptypes, 1, len); if (end == len) {
// drop all parameters
nptypes = NO_PTYPES;
} else {
// drop initial parameter(s)
nptypes = Arrays.copyOfRange(ptypes, end, len);
}
} else { } else {
nptypes = Arrays.copyOfRange(ptypes, 0, len-1); if (end == len) {
System.arraycopy(ptypes, num+1, nptypes, num, (len-1)-num); // drop trailing parameter(s)
nptypes = Arrays.copyOfRange(ptypes, 0, start);
} else {
int tail = len - end;
nptypes = Arrays.copyOfRange(ptypes, 0, start + tail);
System.arraycopy(ptypes, end, nptypes, start, tail);
}
} }
return makeImpl(rtype, nptypes, true); return makeImpl(rtype, nptypes, true);
} }
/** Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}. /** Convenience method for {@link #dropParameterTypes}.
* @deprecated Use {@link #dropParameterTypes} instead.
*/
@Deprecated
public MethodType dropParameterType(int num) {
return dropParameterTypes(num, num+1);
}
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* @param nrtype a return parameter type to replace the old one with * @param nrtype a return parameter type to replace the old one with
* @return the same type, except with the return type change * @return the same type, except with the return type change
*/ */
...@@ -291,6 +374,7 @@ class MethodType { ...@@ -291,6 +374,7 @@ class MethodType {
/** Convenience method. /** Convenience method.
* Report if this type contains a primitive argument or return value. * Report if this type contains a primitive argument or return value.
* The return type {@code void} counts as a primitive.
* @return true if any of the types are primitives * @return true if any of the types are primitives
*/ */
public boolean hasPrimitives() { public boolean hasPrimitives() {
...@@ -300,39 +384,47 @@ class MethodType { ...@@ -300,39 +384,47 @@ class MethodType {
/** Convenience method. /** Convenience method.
* Report if this type contains a wrapper argument or return value. * Report if this type contains a wrapper argument or return value.
* Wrappers are types which box primitive values, such as {@link Integer}. * Wrappers are types which box primitive values, such as {@link Integer}.
* The reference type {@code java.lang.Void} counts as a wrapper.
* @return true if any of the types are wrappers * @return true if any of the types are wrappers
*/ */
public boolean hasWrappers() { public boolean hasWrappers() {
return unwrap() != this; return unwrap() != this;
} }
/** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* Erase all reference types to Object. * Erase all reference types to {@code Object}.
* All primitive types (including {@code void}) will remain unchanged.
* @return a version of the original type with all reference types replaced * @return a version of the original type with all reference types replaced
*/ */
public MethodType erase() { public MethodType erase() {
return form.erasedType(); return form.erasedType();
} }
/** Convenience method for {@link #makeGeneric(int)}. /** Convenience method for {@link #genericMethodType(int)}.
* Convert all types, both reference and primitive, to Object. * Convert all types, both reference and primitive, to {@code Object}.
* The expression {@code type.wrap().erase()} produces the same value
* as {@code type.generic()}.
* @return a version of the original type with all types replaced * @return a version of the original type with all types replaced
*/ */
public MethodType generic() { public MethodType generic() {
return makeGeneric(parameterCount()); return genericMethodType(parameterCount());
} }
/** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* Convert all primitive types to their corresponding wrapper types. * Convert all primitive types to their corresponding wrapper types.
* All reference types (including wrapper types) will remain unchanged.
* A {@code void} return type is changed to the type {@code java.lang.Void}. * A {@code void} return type is changed to the type {@code java.lang.Void}.
* The expression {@code type.wrap().erase()} produces the same value
* as {@code type.generic()}.
* @return a version of the original type with all primitive types replaced * @return a version of the original type with all primitive types replaced
*/ */
public MethodType wrap() { public MethodType wrap() {
return hasPrimitives() ? wrapWithPrims(this) : this; return hasPrimitives() ? wrapWithPrims(this) : this;
} }
/** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* Convert all wrapper types to their corresponding primitive types. * Convert all wrapper types to their corresponding primitive types.
* All primitive types (including {@code void}) will remain unchanged.
* A return type of {@code java.lang.Void} is changed to {@code void}. * A return type of {@code java.lang.Void} is changed to {@code void}.
* @return a version of the original type with all wrapper types replaced * @return a version of the original type with all wrapper types replaced
*/ */
...@@ -391,6 +483,7 @@ class MethodType { ...@@ -391,6 +483,7 @@ class MethodType {
/** /**
* Convenience method to present the arguments as an array. * Convenience method to present the arguments as an array.
* Changes to the array will not result in changes to the type.
* @return the parameter types (as a fresh copy if necessary) * @return the parameter types (as a fresh copy if necessary)
*/ */
public Class<?>[] parameterArray() { public Class<?>[] parameterArray() {
...@@ -491,7 +584,7 @@ class MethodType { ...@@ -491,7 +584,7 @@ class MethodType {
return form.parameterSlotCount(); return form.parameterSlotCount();
} }
/** Number of JVM stack slots which carry all parameters after /** Number of JVM stack slots which carry all parameters including and after
* the given position, which must be in the range of 0 to * the given position, which must be in the range of 0 to
* {@code parameterCount} inclusive. Successive parameters are * {@code parameterCount} inclusive. Successive parameters are
* more shallowly stacked, and parameters are indexed in the bytecodes * more shallowly stacked, and parameters are indexed in the bytecodes
...@@ -532,7 +625,7 @@ class MethodType { ...@@ -532,7 +625,7 @@ class MethodType {
return form.returnSlotCount(); return form.returnSlotCount();
} }
/** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* Find or create an instance (interned) of the given method type. * Find or create an instance (interned) of the given method type.
* Any class or interface name embedded in the signature string * Any class or interface name embedded in the signature string
* will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)} * will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)}
...@@ -544,16 +637,16 @@ class MethodType { ...@@ -544,16 +637,16 @@ class MethodType {
* <p> * <p>
* This method is included for the benfit of applications that must * This method is included for the benfit of applications that must
* generate bytecodes that process method handles and invokedynamic. * generate bytecodes that process method handles and invokedynamic.
* @param bytecodeSignature a bytecode-level signature string "(T...)T" * @param descriptor a bytecode-level signature string "(T...)T"
* @param loader the class loader in which to look up the types * @param loader the class loader in which to look up the types
* @return a method type matching the bytecode-level signature * @return a method type matching the bytecode-level signature
* @throws IllegalArgumentException if the string is not well-formed * @throws IllegalArgumentException if the string is not well-formed
* @throws TypeNotPresentException if a named type cannot be found * @throws TypeNotPresentException if a named type cannot be found
*/ */
public static MethodType fromBytecodeString(String bytecodeSignature, ClassLoader loader) public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader)
throws IllegalArgumentException, TypeNotPresentException throws IllegalArgumentException, TypeNotPresentException
{ {
List<Class<?>> types = BytecodeSignature.parseMethod(bytecodeSignature, loader); List<Class<?>> types = BytecodeDescriptor.parseMethod(descriptor, loader);
Class<?> rtype = types.remove(types.size() - 1); Class<?> rtype = types.remove(types.size() - 1);
Class<?>[] ptypes = types.toArray(NO_PTYPES); Class<?>[] ptypes = types.toArray(NO_PTYPES);
return makeImpl(rtype, ptypes, true); return makeImpl(rtype, ptypes, true);
...@@ -565,11 +658,21 @@ class MethodType { ...@@ -565,11 +658,21 @@ class MethodType {
* <p> * <p>
* This method is included for the benfit of applications that must * This method is included for the benfit of applications that must
* generate bytecodes that process method handles and invokedynamic. * generate bytecodes that process method handles and invokedynamic.
* {@link #fromBytecodeString(java.lang.String, java.lang.ClassLoader)}, * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader)},
* because the latter requires a suitable class loader argument. * because the latter requires a suitable class loader argument.
* @return the bytecode signature representation * @return the bytecode signature representation
*/ */
public String toMethodDescriptorString() {
return BytecodeDescriptor.unparse(this);
}
/** Temporary alias for toMethodDescriptorString; delete after M3. */
public String toBytecodeString() { public String toBytecodeString() {
return BytecodeSignature.unparse(this); return toMethodDescriptorString();
}
/** Temporary alias for fromMethodDescriptorString; delete after M3. */
public static MethodType fromBytecodeString(String descriptor, ClassLoader loader)
throws IllegalArgumentException, TypeNotPresentException {
return fromMethodDescriptorString(descriptor, loader);
} }
} }
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
*/ */
/** /**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* This package contains dynamic language support provided directly by * This package contains dynamic language support provided directly by
* the Java core class libraries and virtual machine. * the Java core class libraries and virtual machine.
* @author John Rose, JSR 292 EG * @author John Rose, JSR 292 EG
......
...@@ -30,7 +30,7 @@ import sun.dyn.util.Wrapper; ...@@ -30,7 +30,7 @@ import sun.dyn.util.Wrapper;
import java.dyn.*; import java.dyn.*;
import java.util.Arrays; import java.util.Arrays;
import static sun.dyn.MethodHandleNatives.Constants.*; import static sun.dyn.MethodHandleNatives.Constants.*;
import static sun.dyn.MethodHandleImpl.newIllegalArgumentException; import static sun.dyn.MemberName.newIllegalArgumentException;
/** /**
* This method handle performs simple conversion or checking of a single argument. * This method handle performs simple conversion or checking of a single argument.
...@@ -302,7 +302,22 @@ public class AdapterMethodHandle extends BoundMethodHandle { ...@@ -302,7 +302,22 @@ public class AdapterMethodHandle extends BoundMethodHandle {
*/ */
private static int type2size(int type) { private static int type2size(int type) {
assert(type >= T_BOOLEAN && type <= T_OBJECT); assert(type >= T_BOOLEAN && type <= T_OBJECT);
return (type == T_FLOAT || type == T_DOUBLE) ? 2 : 1; return (type == T_LONG || type == T_DOUBLE) ? 2 : 1;
}
private static int type2size(Class<?> type) {
return type2size(basicType(type));
}
/** The given stackMove is the number of slots pushed.
* It might be negative. Scale it (multiply) by the
* VM's notion of how an address changes with a push,
* to get the raw SP change for stackMove.
* Then shift and mask it into the correct field.
*/
private static long insertStackMove(int stackMove) {
// following variable must be long to avoid sign extension after '<<'
long spChange = stackMove * MethodHandleNatives.JVM_STACK_MOVE_UNIT;
return (spChange & CONV_STACK_MOVE_MASK) << CONV_STACK_MOVE_SHIFT;
} }
/** Construct an adapter conversion descriptor for a single-argument conversion. */ /** Construct an adapter conversion descriptor for a single-argument conversion. */
...@@ -310,16 +325,16 @@ public class AdapterMethodHandle extends BoundMethodHandle { ...@@ -310,16 +325,16 @@ public class AdapterMethodHandle extends BoundMethodHandle {
assert(src == (src & 0xF)); assert(src == (src & 0xF));
assert(dest == (dest & 0xF)); assert(dest == (dest & 0xF));
assert(convOp >= OP_CHECK_CAST && convOp <= OP_PRIM_TO_REF); assert(convOp >= OP_CHECK_CAST && convOp <= OP_PRIM_TO_REF);
long stackMove = type2size(dest) - type2size(src); int stackMove = type2size(dest) - type2size(src);
return ((long) argnum << 32 | return ((long) argnum << 32 |
(long) convOp << CONV_OP_SHIFT | (long) convOp << CONV_OP_SHIFT |
(int) src << CONV_SRC_TYPE_SHIFT | (int) src << CONV_SRC_TYPE_SHIFT |
(int) dest << CONV_DEST_TYPE_SHIFT | (int) dest << CONV_DEST_TYPE_SHIFT |
stackMove << CONV_STACK_MOVE_SHIFT insertStackMove(stackMove)
); );
} }
private static long makeConv(int convOp, int argnum, int stackMove) { private static long makeConv(int convOp, int argnum, int stackMove) {
assert(convOp >= OP_SWAP_ARGS && convOp <= OP_SPREAD_ARGS); assert(convOp >= OP_DUP_ARGS && convOp <= OP_SPREAD_ARGS);
byte src = 0, dest = 0; byte src = 0, dest = 0;
if (convOp >= OP_COLLECT_ARGS && convOp <= OP_SPREAD_ARGS) if (convOp >= OP_COLLECT_ARGS && convOp <= OP_SPREAD_ARGS)
src = dest = T_OBJECT; src = dest = T_OBJECT;
...@@ -327,12 +342,21 @@ public class AdapterMethodHandle extends BoundMethodHandle { ...@@ -327,12 +342,21 @@ public class AdapterMethodHandle extends BoundMethodHandle {
(long) convOp << CONV_OP_SHIFT | (long) convOp << CONV_OP_SHIFT |
(int) src << CONV_SRC_TYPE_SHIFT | (int) src << CONV_SRC_TYPE_SHIFT |
(int) dest << CONV_DEST_TYPE_SHIFT | (int) dest << CONV_DEST_TYPE_SHIFT |
stackMove << CONV_STACK_MOVE_SHIFT insertStackMove(stackMove)
);
}
private static long makeSwapConv(int convOp, int srcArg, byte type, int destSlot) {
assert(convOp >= OP_SWAP_ARGS && convOp <= OP_ROT_ARGS);
return ((long) srcArg << 32 |
(long) convOp << CONV_OP_SHIFT |
(int) type << CONV_SRC_TYPE_SHIFT |
(int) type << CONV_DEST_TYPE_SHIFT |
(int) destSlot << CONV_VMINFO_SHIFT
); );
} }
private static long makeConv(int convOp) { private static long makeConv(int convOp) {
assert(convOp == OP_RETYPE_ONLY); assert(convOp == OP_RETYPE_ONLY || convOp == OP_RETYPE_RAW);
return (long) convOp << CONV_OP_SHIFT; // stackMove, src, dst, argnum all zero return ((long)-1 << 32) | (convOp << CONV_OP_SHIFT); // stackMove, src, dst all zero
} }
private static int convCode(long conv) { private static int convCode(long conv) {
return (int)conv; return (int)conv;
...@@ -348,16 +372,6 @@ public class AdapterMethodHandle extends BoundMethodHandle { ...@@ -348,16 +372,6 @@ public class AdapterMethodHandle extends BoundMethodHandle {
/** One of OP_RETYPE_ONLY, etc. */ /** One of OP_RETYPE_ONLY, etc. */
int conversionOp() { return (conversion & CONV_OP_MASK) >> CONV_OP_SHIFT; } int conversionOp() { return (conversion & CONV_OP_MASK) >> CONV_OP_SHIFT; }
@Override
public String toString() {
return addTypeString(this, "Adapted[" + basicToString(nonAdapter((MethodHandle)vmtarget)) + "]");
}
private static MethodHandle nonAdapter(MethodHandle mh) {
return (MethodHandle)
MethodHandleNatives.getTarget(mh, ETF_DIRECT_HANDLE);
}
/* Return one plus the position of the first non-trivial difference /* Return one plus the position of the first non-trivial difference
* between the given types. This is not a symmetric operation; * between the given types. This is not a symmetric operation;
* we are considering adapting the targetType to adapterType. * we are considering adapting the targetType to adapterType.
...@@ -399,14 +413,14 @@ public class AdapterMethodHandle extends BoundMethodHandle { ...@@ -399,14 +413,14 @@ public class AdapterMethodHandle extends BoundMethodHandle {
//if (false) return 1; // never adaptable! //if (false) return 1; // never adaptable!
return -1; // some significant difference return -1; // some significant difference
} }
private static int diffParamTypes(MethodType adapterType, int tstart, private static int diffParamTypes(MethodType adapterType, int astart,
MethodType targetType, int astart, MethodType targetType, int tstart,
int nargs, boolean raw) { int nargs, boolean raw) {
assert(nargs >= 0); assert(nargs >= 0);
int res = 0; int res = 0;
for (int i = 0; i < nargs; i++) { for (int i = 0; i < nargs; i++) {
Class<?> src = adapterType.parameterType(tstart+i); Class<?> src = adapterType.parameterType(astart+i);
Class<?> dest = targetType.parameterType(astart+i); Class<?> dest = targetType.parameterType(tstart+i);
if ((!raw if ((!raw
? VerifyType.canPassUnchecked(src, dest) ? VerifyType.canPassUnchecked(src, dest)
: VerifyType.canPassRaw(src, dest) : VerifyType.canPassRaw(src, dest)
...@@ -422,7 +436,7 @@ public class AdapterMethodHandle extends BoundMethodHandle { ...@@ -422,7 +436,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
/** Can a retyping adapter (alone) validly convert the target to newType? */ /** Can a retyping adapter (alone) validly convert the target to newType? */
public static boolean canRetypeOnly(MethodType newType, MethodType targetType) { public static boolean canRetypeOnly(MethodType newType, MethodType targetType) {
return canRetypeOnly(newType, targetType, false); return canRetype(newType, targetType, false);
} }
/** Can a retyping adapter (alone) convert the target to newType? /** Can a retyping adapter (alone) convert the target to newType?
* It is allowed to widen subword types and void to int, to make bitwise * It is allowed to widen subword types and void to int, to make bitwise
...@@ -430,14 +444,14 @@ public class AdapterMethodHandle extends BoundMethodHandle { ...@@ -430,14 +444,14 @@ public class AdapterMethodHandle extends BoundMethodHandle {
* reference conversions on return. This last feature requires that the * reference conversions on return. This last feature requires that the
* caller be trusted, and perform explicit cast conversions on return values. * caller be trusted, and perform explicit cast conversions on return values.
*/ */
static boolean canRawRetypeOnly(MethodType newType, MethodType targetType) { public static boolean canRetypeRaw(MethodType newType, MethodType targetType) {
return canRetypeOnly(newType, targetType, true); return canRetype(newType, targetType, true);
} }
static boolean canRetypeOnly(MethodType newType, MethodType targetType, boolean raw) { static boolean canRetype(MethodType newType, MethodType targetType, boolean raw) {
if (!convOpSupported(OP_RETYPE_ONLY)) return false; if (!convOpSupported(raw ? OP_RETYPE_RAW : OP_RETYPE_ONLY)) return false;
int diff = diffTypes(newType, targetType, raw); int diff = diffTypes(newType, targetType, raw);
// %%% This assert is too strong. Factor diff into VerifyType and reconcile. // %%% This assert is too strong. Factor diff into VerifyType and reconcile.
assert((diff == 0) == VerifyType.isNullConversion(newType, targetType)); assert(raw || (diff == 0) == VerifyType.isNullConversion(newType, targetType));
return diff == 0; return diff == 0;
} }
...@@ -447,19 +461,21 @@ public class AdapterMethodHandle extends BoundMethodHandle { ...@@ -447,19 +461,21 @@ public class AdapterMethodHandle extends BoundMethodHandle {
*/ */
public static MethodHandle makeRetypeOnly(Access token, public static MethodHandle makeRetypeOnly(Access token,
MethodType newType, MethodHandle target) { MethodType newType, MethodHandle target) {
return makeRetypeOnly(token, newType, target, false); return makeRetype(token, newType, target, false);
} }
public static MethodHandle makeRawRetypeOnly(Access token, public static MethodHandle makeRetypeRaw(Access token,
MethodType newType, MethodHandle target) { MethodType newType, MethodHandle target) {
return makeRetypeOnly(token, newType, target, true); return makeRetype(token, newType, target, true);
} }
static MethodHandle makeRetypeOnly(Access token, static MethodHandle makeRetype(Access token,
MethodType newType, MethodHandle target, boolean raw) { MethodType newType, MethodHandle target, boolean raw) {
Access.check(token); Access.check(token);
if (!canRetypeOnly(newType, target.type(), raw)) MethodType oldType = target.type();
if (oldType == newType) return target;
if (!canRetype(newType, oldType, raw))
return null; return null;
// TO DO: clone the target guy, whatever he is, with new type. // TO DO: clone the target guy, whatever he is, with new type.
return new AdapterMethodHandle(target, newType, makeConv(OP_RETYPE_ONLY)); return new AdapterMethodHandle(target, newType, makeConv(raw ? OP_RETYPE_RAW : OP_RETYPE_ONLY));
} }
/** Can a checkcast adapter validly convert the target to newType? /** Can a checkcast adapter validly convert the target to newType?
...@@ -492,7 +508,7 @@ public class AdapterMethodHandle extends BoundMethodHandle { ...@@ -492,7 +508,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
Access.check(token); Access.check(token);
if (!canCheckCast(newType, target.type(), arg, castType)) if (!canCheckCast(newType, target.type(), arg, castType))
return null; return null;
long conv = makeConv(OP_CHECK_CAST, arg, 0); long conv = makeConv(OP_CHECK_CAST, arg, T_OBJECT, T_OBJECT);
return new AdapterMethodHandle(target, newType, conv, castType); return new AdapterMethodHandle(target, newType, conv, castType);
} }
...@@ -537,10 +553,9 @@ public class AdapterMethodHandle extends BoundMethodHandle { ...@@ -537,10 +553,9 @@ public class AdapterMethodHandle extends BoundMethodHandle {
int arg, Class<?> convType) { int arg, Class<?> convType) {
Access.check(token); Access.check(token);
MethodType oldType = target.type(); MethodType oldType = target.type();
Class<?> src = newType.parameterType(arg);
Class<?> dst = oldType.parameterType(arg);
if (!canPrimCast(newType, oldType, arg, convType)) if (!canPrimCast(newType, oldType, arg, convType))
return null; return null;
Class<?> src = newType.parameterType(arg);
long conv = makeConv(OP_PRIM_TO_PRIM, arg, basicType(src), basicType(convType)); long conv = makeConv(OP_PRIM_TO_PRIM, arg, basicType(src), basicType(convType));
return new AdapterMethodHandle(target, newType, conv); return new AdapterMethodHandle(target, newType, conv);
} }
...@@ -607,8 +622,6 @@ public class AdapterMethodHandle extends BoundMethodHandle { ...@@ -607,8 +622,6 @@ public class AdapterMethodHandle extends BoundMethodHandle {
return null; return null;
} }
// TO DO: makeSwapArguments, makeRotateArguments, makeDuplicateArguments
/** Can an adapter simply drop arguments to convert the target to newType? */ /** Can an adapter simply drop arguments to convert the target to newType? */
public static boolean canDropArguments(MethodType newType, MethodType targetType, public static boolean canDropArguments(MethodType newType, MethodType targetType,
int dropArgPos, int dropArgCount) { int dropArgPos, int dropArgCount) {
...@@ -643,26 +656,195 @@ public class AdapterMethodHandle extends BoundMethodHandle { ...@@ -643,26 +656,195 @@ public class AdapterMethodHandle extends BoundMethodHandle {
Access.check(token); Access.check(token);
if (dropArgCount == 0) if (dropArgCount == 0)
return makeRetypeOnly(IMPL_TOKEN, newType, target); return makeRetypeOnly(IMPL_TOKEN, newType, target);
MethodType mt = target.type(); if (!canDropArguments(newType, target.type(), dropArgPos, dropArgCount))
int argCount = mt.parameterCount(); return null;
if (!canDropArguments(newType, mt, dropArgPos, dropArgCount)) // in arglist: [0: ...keep1 | dpos: drop... | dpos+dcount: keep2... ]
// out arglist: [0: ...keep1 | dpos: keep2... ]
int keep2InPos = dropArgPos + dropArgCount;
int dropSlot = newType.parameterSlotDepth(keep2InPos);
int keep1InSlot = newType.parameterSlotDepth(dropArgPos);
int slotCount = keep1InSlot - dropSlot;
assert(slotCount >= dropArgCount);
assert(target.type().parameterSlotCount() + slotCount == newType.parameterSlotCount());
long conv = makeConv(OP_DROP_ARGS, dropArgPos + dropArgCount - 1, -slotCount);
return new AdapterMethodHandle(target, newType, conv);
}
/** Can an adapter duplicate an argument to convert the target to newType? */
public static boolean canDupArguments(MethodType newType, MethodType targetType,
int dupArgPos, int dupArgCount) {
if (!convOpSupported(OP_DUP_ARGS)) return false;
if (diffReturnTypes(newType, targetType, false) != 0)
return false;
int nptypes = newType.parameterCount();
if (dupArgCount < 0 || dupArgPos + dupArgCount > nptypes)
return false;
if (targetType.parameterCount() != nptypes + dupArgCount)
return false;
// parameter types must be the same up to the duplicated arguments
if (diffParamTypes(newType, 0, targetType, 0, nptypes, false) != 0)
return false;
// duplicated types must be, well, duplicates
if (diffParamTypes(newType, dupArgPos, targetType, nptypes, dupArgCount, false) != 0)
return false;
return true;
}
/** Factory method: Duplicate the selected argument.
* Return null if this is not possible.
*/
public static MethodHandle makeDupArguments(Access token,
MethodType newType, MethodHandle target,
int dupArgPos, int dupArgCount) {
Access.check(token);
if (!canDupArguments(newType, target.type(), dupArgPos, dupArgCount))
return null; return null;
int dropSlotCount, dropSlotPos; if (dupArgCount == 0)
if (dropArgCount >= argCount) { return target;
assert(dropArgPos == argCount-1); // in arglist: [0: ...keep1 | dpos: dup... | dpos+dcount: keep2... ]
dropSlotPos = 0; // out arglist: [0: ...keep1 | dpos: dup... | dpos+dcount: keep2... | dup... ]
dropSlotCount = mt.parameterSlotCount(); int keep2InPos = dupArgPos + dupArgCount;
int dupSlot = newType.parameterSlotDepth(keep2InPos);
int keep1InSlot = newType.parameterSlotDepth(dupArgPos);
int slotCount = keep1InSlot - dupSlot;
assert(target.type().parameterSlotCount() - slotCount == newType.parameterSlotCount());
long conv = makeConv(OP_DUP_ARGS, dupArgPos + dupArgCount - 1, slotCount);
return new AdapterMethodHandle(target, newType, conv);
}
/** Can an adapter swap two arguments to convert the target to newType? */
public static boolean canSwapArguments(MethodType newType, MethodType targetType,
int swapArg1, int swapArg2) {
if (!convOpSupported(OP_SWAP_ARGS)) return false;
if (diffReturnTypes(newType, targetType, false) != 0)
return false;
if (swapArg1 >= swapArg2) return false; // caller resp
int nptypes = newType.parameterCount();
if (targetType.parameterCount() != nptypes)
return false;
if (swapArg1 < 0 || swapArg2 >= nptypes)
return false;
if (diffParamTypes(newType, 0, targetType, 0, swapArg1, false) != 0)
return false;
if (diffParamTypes(newType, swapArg1, targetType, swapArg2, 1, false) != 0)
return false;
if (diffParamTypes(newType, swapArg1+1, targetType, swapArg1+1, swapArg2-swapArg1-1, false) != 0)
return false;
if (diffParamTypes(newType, swapArg2, targetType, swapArg1, 1, false) != 0)
return false;
if (diffParamTypes(newType, swapArg2+1, targetType, swapArg2+1, nptypes-swapArg2-1, false) != 0)
return false;
return true;
}
/** Factory method: Swap the selected arguments.
* Return null if this is not possible.
*/
public static MethodHandle makeSwapArguments(Access token,
MethodType newType, MethodHandle target,
int swapArg1, int swapArg2) {
Access.check(token);
if (swapArg1 == swapArg2)
return target;
if (swapArg1 > swapArg2) { int t = swapArg1; swapArg1 = swapArg2; swapArg2 = t; }
if (!canSwapArguments(newType, target.type(), swapArg1, swapArg2))
return null;
Class<?> swapType = newType.parameterType(swapArg1);
// in arglist: [0: ...keep1 | pos1: a1 | pos1+1: keep2... | pos2: a2 | pos2+1: keep3... ]
// out arglist: [0: ...keep1 | pos1: a2 | pos1+1: keep2... | pos2: a1 | pos2+1: keep3... ]
int swapSlot2 = newType.parameterSlotDepth(swapArg2 + 1);
long conv = makeSwapConv(OP_SWAP_ARGS, swapArg1, basicType(swapType), swapSlot2);
return new AdapterMethodHandle(target, newType, conv);
}
static int positiveRotation(int argCount, int rotateBy) {
assert(argCount > 0);
if (rotateBy >= 0) {
if (rotateBy < argCount)
return rotateBy;
return rotateBy % argCount;
} else if (rotateBy >= -argCount) {
return rotateBy + argCount;
} else { } else {
// arglist: [0: keep... | dpos: drop... | dpos+dcount: keep... ] return (-1-((-1-rotateBy) % argCount)) + argCount;
int lastDroppedArg = dropArgPos + dropArgCount - 1;
int lastKeptArg = dropArgPos - 1; // might be -1, which is OK
dropSlotPos = mt.parameterSlotDepth(1+lastDroppedArg);
int lastKeptSlot = mt.parameterSlotDepth(1+lastKeptArg);
dropSlotCount = lastKeptSlot - dropSlotPos;
assert(dropSlotCount >= dropArgCount);
} }
long conv = makeConv(OP_DROP_ARGS, dropArgPos, +dropSlotCount); }
return new AdapterMethodHandle(target, newType, dropSlotCount, conv);
final static int MAX_ARG_ROTATION = 1;
/** Can an adapter rotate arguments to convert the target to newType? */
public static boolean canRotateArguments(MethodType newType, MethodType targetType,
int firstArg, int argCount, int rotateBy) {
if (!convOpSupported(OP_ROT_ARGS)) return false;
if (argCount <= 2) return false; // must be a swap, not a rotate
rotateBy = positiveRotation(argCount, rotateBy);
if (rotateBy == 0) return false; // no rotation
if (rotateBy > MAX_ARG_ROTATION && rotateBy < argCount - MAX_ARG_ROTATION)
return false; // too many argument positions
// Rotate incoming args right N to the out args, N in 1..(argCouunt-1).
if (diffReturnTypes(newType, targetType, false) != 0)
return false;
int nptypes = newType.parameterCount();
if (targetType.parameterCount() != nptypes)
return false;
if (firstArg < 0 || firstArg >= nptypes) return false;
int argLimit = firstArg + argCount;
if (argLimit > nptypes) return false;
if (diffParamTypes(newType, 0, targetType, 0, firstArg, false) != 0)
return false;
int newChunk1 = argCount - rotateBy, newChunk2 = rotateBy;
// swap new chunk1 with target chunk2
if (diffParamTypes(newType, firstArg, targetType, argLimit-newChunk1, newChunk1, false) != 0)
return false;
// swap new chunk2 with target chunk1
if (diffParamTypes(newType, firstArg+newChunk1, targetType, firstArg, newChunk2, false) != 0)
return false;
return true;
}
/** Factory method: Rotate the selected argument range.
* Return null if this is not possible.
*/
public static MethodHandle makeRotateArguments(Access token,
MethodType newType, MethodHandle target,
int firstArg, int argCount, int rotateBy) {
Access.check(token);
rotateBy = positiveRotation(argCount, rotateBy);
if (!canRotateArguments(newType, target.type(), firstArg, argCount, rotateBy))
return null;
// Decide whether it should be done as a right or left rotation,
// on the JVM stack. Return the number of stack slots to rotate by,
// positive if right, negative if left.
int limit = firstArg + argCount;
int depth0 = newType.parameterSlotDepth(firstArg);
int depth1 = newType.parameterSlotDepth(limit-rotateBy);
int depth2 = newType.parameterSlotDepth(limit);
int chunk1Slots = depth0 - depth1; assert(chunk1Slots > 0);
int chunk2Slots = depth1 - depth2; assert(chunk2Slots > 0);
// From here on out, it assumes a single-argument shift.
assert(MAX_ARG_ROTATION == 1);
int srcArg, dstArg;
byte basicType;
if (chunk2Slots <= chunk1Slots) {
// Rotate right/down N (rotateBy = +N, N small, c2 small):
// in arglist: [0: ...keep1 | arg1: c1... | limit-N: c2 | limit: keep2... ]
// out arglist: [0: ...keep1 | arg1: c2 | arg1+N: c1... | limit: keep2... ]
srcArg = limit-1;
dstArg = firstArg;
basicType = basicType(newType.parameterType(srcArg));
assert(chunk2Slots == type2size(basicType));
} else {
// Rotate left/up N (rotateBy = -N, N small, c1 small):
// in arglist: [0: ...keep1 | arg1: c1 | arg1+N: c2... | limit: keep2... ]
// out arglist: [0: ...keep1 | arg1: c2 ... | limit-N: c1 | limit: keep2... ]
srcArg = firstArg;
dstArg = limit-1;
basicType = basicType(newType.parameterType(srcArg));
assert(chunk1Slots == type2size(basicType));
}
int dstSlot = newType.parameterSlotDepth(dstArg + 1);
long conv = makeSwapConv(OP_ROT_ARGS, srcArg, basicType, dstSlot);
return new AdapterMethodHandle(target, newType, conv);
} }
/** Can an adapter spread an argument to convert the target to newType? */ /** Can an adapter spread an argument to convert the target to newType? */
...@@ -676,10 +858,10 @@ public class AdapterMethodHandle extends BoundMethodHandle { ...@@ -676,10 +858,10 @@ public class AdapterMethodHandle extends BoundMethodHandle {
if (spreadArgPos != 0 && diffParamTypes(newType, 0, targetType, 0, spreadArgPos, false) != 0) if (spreadArgPos != 0 && diffParamTypes(newType, 0, targetType, 0, spreadArgPos, false) != 0)
return false; return false;
int afterPos = spreadArgPos + spreadArgCount; int afterPos = spreadArgPos + spreadArgCount;
int afterCount = nptypes - afterPos; int afterCount = nptypes - (spreadArgPos + 1);
if (spreadArgPos < 0 || spreadArgPos >= nptypes || if (spreadArgPos < 0 || spreadArgPos >= nptypes ||
spreadArgCount < 0 || spreadArgCount < 0 ||
targetType.parameterCount() != nptypes - 1 + spreadArgCount) targetType.parameterCount() != afterPos + afterCount)
return false; return false;
// parameter types after the spread point must also be the same // parameter types after the spread point must also be the same
if (afterCount != 0 && diffParamTypes(newType, spreadArgPos+1, targetType, afterPos, afterCount, false) != 0) if (afterCount != 0 && diffParamTypes(newType, spreadArgPos+1, targetType, afterPos, afterCount, false) != 0)
...@@ -697,32 +879,40 @@ public class AdapterMethodHandle extends BoundMethodHandle { ...@@ -697,32 +879,40 @@ public class AdapterMethodHandle extends BoundMethodHandle {
return true; return true;
} }
/** Factory method: Spread selected argument. */ /** Factory method: Spread selected argument. */
public static MethodHandle makeSpreadArguments(Access token, public static MethodHandle makeSpreadArguments(Access token,
MethodType newType, MethodHandle target, MethodType newType, MethodHandle target,
Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) { Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
Access.check(token); Access.check(token);
MethodType mt = target.type(); MethodType targetType = target.type();
int argCount = mt.parameterCount(); if (!canSpreadArguments(newType, targetType, spreadArgType, spreadArgPos, spreadArgCount))
if (!canSpreadArguments(newType, mt, spreadArgType, spreadArgPos, spreadArgCount))
return null; return null;
int spreadSlotCount, spreadSlotPos; // in arglist: [0: ...keep1 | spos: spreadArg | spos+1: keep2... ]
if (spreadArgCount >= argCount) { // out arglist: [0: ...keep1 | spos: spread... | spos+scount: keep2... ]
assert(spreadArgPos == argCount-1); int keep2OutPos = spreadArgPos + spreadArgCount;
spreadSlotPos = 0; int spreadSlot = targetType.parameterSlotDepth(keep2OutPos);
spreadSlotCount = mt.parameterSlotCount(); int keep1OutSlot = targetType.parameterSlotDepth(spreadArgPos);
} else { int slotCount = keep1OutSlot - spreadSlot;
// arglist: [0: keep... | dpos: spread... | dpos+dcount: keep... ] assert(spreadSlot == newType.parameterSlotDepth(spreadArgPos+1));
int lastSpreadArg = spreadArgPos + spreadArgCount - 1; assert(slotCount >= spreadArgCount);
int lastKeptArg = spreadArgPos - 1; // might be -1, which is OK long conv = makeConv(OP_SPREAD_ARGS, spreadArgPos, slotCount-1);
spreadSlotPos = mt.parameterSlotDepth(1+lastSpreadArg); MethodHandle res = new AdapterMethodHandle(target, newType, conv, spreadArgType);
int lastKeptSlot = mt.parameterSlotDepth(1+lastKeptArg); assert(res.type().parameterType(spreadArgPos) == spreadArgType);
spreadSlotCount = lastKeptSlot - spreadSlotPos; return res;
assert(spreadSlotCount >= spreadArgCount);
}
long conv = makeConv(OP_SPREAD_ARGS, spreadArgPos, spreadSlotCount);
return new AdapterMethodHandle(target, newType, conv, spreadArgType);
} }
// TO DO: makeCollectArguments, makeFlyby, makeRicochet // TO DO: makeCollectArguments, makeFlyby, makeRicochet
@Override
public String toString() {
return nonAdapter((MethodHandle)vmtarget).toString();
}
private static MethodHandle nonAdapter(MethodHandle mh) {
while (mh instanceof AdapterMethodHandle) {
mh = (MethodHandle) mh.vmtarget;
}
return mh;
}
} }
...@@ -28,6 +28,10 @@ package sun.dyn; ...@@ -28,6 +28,10 @@ package sun.dyn;
import sun.dyn.util.VerifyType; import sun.dyn.util.VerifyType;
import sun.dyn.util.Wrapper; import sun.dyn.util.Wrapper;
import java.dyn.*; import java.dyn.*;
import java.util.List;
import sun.dyn.MethodHandleNatives.Constants;
import static sun.dyn.MethodHandleImpl.IMPL_LOOKUP;
import static sun.dyn.MemberName.newIllegalArgumentException;
/** /**
* The flavor of method handle which emulates an invoke instruction * The flavor of method handle which emulates an invoke instruction
...@@ -35,18 +39,23 @@ import java.dyn.*; ...@@ -35,18 +39,23 @@ import java.dyn.*;
* when the handle is created, not when it is invoked. * when the handle is created, not when it is invoked.
* @author jrose * @author jrose
*/ */
public class BoundMethodHandle extends MethodHandle { public class BoundMethodHandle extends MethodHandle {
//MethodHandle vmtarget; // next BMH or final DMH or methodOop //MethodHandle vmtarget; // next BMH or final DMH or methodOop
private final Object argument; // argument to insert private final Object argument; // argument to insert
private final int vmargslot; // position at which it is inserted private final int vmargslot; // position at which it is inserted
private static final Access IMPL_TOKEN = Access.getToken();
private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(IMPL_TOKEN);
// Constructors in this class *must* be package scoped or private. // Constructors in this class *must* be package scoped or private.
// Exception: JavaMethodHandle constructors are protected.
// (The link between JMH and BMH is temporary.)
/** Bind a direct MH to its receiver (or first ref. argument). /** Bind a direct MH to its receiver (or first ref. argument).
* The JVM will pre-dispatch the MH if it is not already static. * The JVM will pre-dispatch the MH if it is not already static.
*/ */
BoundMethodHandle(DirectMethodHandle mh, Object argument) { BoundMethodHandle(DirectMethodHandle mh, Object argument) {
super(Access.TOKEN, mh.type().dropParameterType(0)); super(Access.TOKEN, mh.type().dropParameterTypes(0, 1));
// check the type now, once for all: // check the type now, once for all:
this.argument = checkReferenceArgument(argument, mh, 0); this.argument = checkReferenceArgument(argument, mh, 0);
this.vmargslot = this.type().parameterSlotCount(); this.vmargslot = this.type().parameterSlotCount();
...@@ -56,32 +65,34 @@ public class BoundMethodHandle extends MethodHandle { ...@@ -56,32 +65,34 @@ public class BoundMethodHandle extends MethodHandle {
} else { } else {
this.vmtarget = mh; this.vmtarget = mh;
} }
} }
private static final int REF_ARG = 0, PRIM_ARG = 1, SELF_ARG = 2;
/** Insert an argument into an arbitrary method handle. /** Insert an argument into an arbitrary method handle.
* If argnum is zero, inserts the first argument, etc. * If argnum is zero, inserts the first argument, etc.
* The argument type must be a reference. * The argument type must be a reference.
*/ */
BoundMethodHandle(MethodHandle mh, Object argument, int argnum) { BoundMethodHandle(MethodHandle mh, Object argument, int argnum) {
this(mh, argument, argnum, mh.type().parameterType(argnum).isPrimitive() ? PRIM_ARG : REF_ARG); this(mh.type().dropParameterTypes(argnum, argnum+1),
mh, argument, argnum);
} }
/** Insert an argument into an arbitrary method handle. /** Insert an argument into an arbitrary method handle.
* If argnum is zero, inserts the first argument, etc. * If argnum is zero, inserts the first argument, etc.
*/ */
BoundMethodHandle(MethodHandle mh, Object argument, int argnum, int whichArg) { BoundMethodHandle(MethodType type, MethodHandle mh, Object argument, int argnum) {
super(Access.TOKEN, mh.type().dropParameterType(argnum)); super(Access.TOKEN, type);
if (whichArg == PRIM_ARG) if (mh.type().parameterType(argnum).isPrimitive())
this.argument = bindPrimitiveArgument(argument, mh, argnum); this.argument = bindPrimitiveArgument(argument, mh, argnum);
else { else {
if (whichArg == SELF_ARG) argument = this;
this.argument = checkReferenceArgument(argument, mh, argnum); this.argument = checkReferenceArgument(argument, mh, argnum);
} }
this.vmargslot = this.type().parameterSlotDepth(argnum); this.vmargslot = type.parameterSlotDepth(argnum);
initTarget(mh, argnum);
}
private void initTarget(MethodHandle mh, int argnum) {
if (MethodHandleNatives.JVM_SUPPORT) { if (MethodHandleNatives.JVM_SUPPORT) {
this.vmtarget = null; // maybe updated by JVM this.vmtarget = null; // maybe updated by JVM
MethodHandleNatives.init(this, mh, argnum); MethodHandleNatives.init(this, mh, argnum);
} else { } else {
this.vmtarget = mh; this.vmtarget = mh;
...@@ -97,29 +108,65 @@ public class BoundMethodHandle extends MethodHandle { ...@@ -97,29 +108,65 @@ public class BoundMethodHandle extends MethodHandle {
assert(this.getClass() == AdapterMethodHandle.class); assert(this.getClass() == AdapterMethodHandle.class);
} }
/** Initialize the current object as a method handle, binding it /** Initialize the current object as a Java method handle, binding it
* as the {@code argnum}th argument of the method handle {@code entryPoint}. * as the first argument of the method handle {@code entryPoint}.
* The invocation type of the resulting method handle will be the * The invocation type of the resulting method handle will be the
* same as {@code entryPoint}, except that the {@code argnum}th argument * same as {@code entryPoint}, except that the first argument
* type will be dropped. * type will be dropped.
*/ */
public BoundMethodHandle(MethodHandle entryPoint, int argnum) { protected BoundMethodHandle(MethodHandle entryPoint) {
this(entryPoint, null, argnum, SELF_ARG); super(Access.TOKEN, entryPoint.type().dropParameterTypes(0, 1));
this.argument = this; // kludge; get rid of
// Note: If the conversion fails, perhaps because of a bad entryPoint, this.vmargslot = this.type().parameterSlotDepth(0);
// the MethodHandle.type field will not be filled in, and therefore initTarget(entryPoint, 0);
// no MH.invoke call will ever succeed. The caller may retain a pointer assert(this instanceof JavaMethodHandle);
// to the broken method handle, but no harm can be done with it.
} }
/** Initialize the current object as a method handle, binding it /** Initialize the current object as a Java method handle.
* as the first argument of the method handle {@code entryPoint}.
* The invocation type of the resulting method handle will be the
* same as {@code entryPoint}, except that the first argument
* type will be dropped.
*/ */
public BoundMethodHandle(MethodHandle entryPoint) { protected BoundMethodHandle(String entryPointName, MethodType type, boolean matchArity) {
this(entryPoint, null, 0, SELF_ARG); super(Access.TOKEN, null);
MethodHandle entryPoint
= findJavaMethodHandleEntryPoint(this.getClass(),
entryPointName, type, matchArity);
MethodHandleImpl.initType(this, entryPoint.type().dropParameterTypes(0, 1));
this.argument = this; // kludge; get rid of
this.vmargslot = this.type().parameterSlotDepth(0);
initTarget(entryPoint, 0);
assert(this instanceof JavaMethodHandle);
}
private static
MethodHandle findJavaMethodHandleEntryPoint(Class<?> caller,
String name,
MethodType type,
boolean matchArity) {
if (matchArity) type.getClass(); // elicit NPE
List<MemberName> methods = IMPL_NAMES.getMethods(caller, true, name, null, caller);
MethodType foundType = null;
MemberName foundMethod = null;
for (MemberName method : methods) {
MethodType mtype = method.getMethodType();
if (type != null && type.parameterCount() != mtype.parameterCount())
continue;
else if (foundType == null)
foundType = mtype;
else if (foundType != mtype)
throw newIllegalArgumentException("more than one method named "+name+" in "+caller.getName());
// discard overrides
if (foundMethod == null)
foundMethod = method;
else if (foundMethod.getDeclaringClass().isAssignableFrom(method.getDeclaringClass()))
foundMethod = method;
}
if (foundMethod == null)
throw newIllegalArgumentException("no method named "+name+" in "+caller.getName());
MethodHandle entryPoint = MethodHandleImpl.findMethod(IMPL_TOKEN, foundMethod, true, caller);
if (type != null) {
MethodType epType = type.insertParameterTypes(0, entryPoint.type().parameterType(0));
entryPoint = MethodHandles.convertArguments(entryPoint, epType);
}
return entryPoint;
} }
/** Make sure the given {@code argument} can be used as {@code argnum}-th /** Make sure the given {@code argument} can be used as {@code argnum}-th
...@@ -175,6 +222,24 @@ public class BoundMethodHandle extends MethodHandle { ...@@ -175,6 +222,24 @@ public class BoundMethodHandle extends MethodHandle {
@Override @Override
public String toString() { public String toString() {
return "Bound[" + super.toString() + "]"; MethodHandle mh = this;
while (mh instanceof BoundMethodHandle) {
Object info = MethodHandleNatives.getTargetInfo(mh);
if (info instanceof MethodHandle) {
mh = (MethodHandle) info;
} else {
String name = null;
if (info instanceof MemberName)
name = ((MemberName)info).getName();
if (name != null)
return name;
else
return super.toString(); // <unknown>, probably
}
assert(mh != this);
if (mh instanceof JavaMethodHandle)
break; // access JMH.toString(), not BMH.toString()
}
return mh.toString();
} }
} }
...@@ -26,34 +26,51 @@ ...@@ -26,34 +26,51 @@
package sun.dyn; package sun.dyn;
import java.dyn.*; import java.dyn.*;
import java.util.logging.Level;
import java.util.logging.Logger;
/** /**
* The CallSite privately created by the JVM at every invokedynamic instruction. * Parts of CallSite known to the JVM.
* FIXME: Merge all this into CallSite proper.
* @author jrose * @author jrose
*/ */
class CallSiteImpl extends CallSite { public class CallSiteImpl {
// Fields used only by the JVM. Do not use or change. // Field used only by the JVM. Do not use or change.
private Object vmmethod; private Object vmmethod;
// Values supplied by the JVM: // Values supplied by the JVM:
int callerMID, callerBCI; protected int callerMID, callerBCI;
private CallSiteImpl(Class<?> caller, String name, MethodType type) { private MethodHandle target;
super(caller, name, type); protected final Object caller; // usually a class
protected final String name;
protected final MethodType type;
/** called only directly from CallSite() */
protected CallSiteImpl(Access token, Object caller, String name, MethodType type) {
Access.check(token);
this.caller = caller;
this.name = name;
this.type = type;
}
/** native version of setTarget */
protected void setTarget(MethodHandle mh) {
//System.out.println("setTarget "+this+" := "+mh);
// XXX I don't know how to fix this properly.
// if (false && MethodHandleNatives.JVM_SUPPORT) // FIXME: enable this
// MethodHandleNatives.linkCallSite(this, mh);
// else
this.target = mh;
} }
@Override protected MethodHandle getTarget() {
public void setTarget(MethodHandle mh) { return target;
checkTarget(mh);
if (MethodHandleNatives.JVM_SUPPORT)
MethodHandleNatives.linkCallSite(this, (MethodHandle) mh);
else
super.setTarget(mh);
} }
private static final MethodHandle PRIVATE_INITIALIZE_CALL_SITE = private static final MethodHandle PRIVATE_INITIALIZE_CALL_SITE =
MethodHandleImpl.IMPL_LOOKUP.findStatic(CallSite.class, "privateInitializeCallSite", MethodHandleImpl.IMPL_LOOKUP.findStatic(CallSite.class, "privateInitializeCallSite",
MethodType.make(void.class, CallSite.class, int.class, int.class)); MethodType.methodType(void.class, CallSite.class, int.class, int.class));
// this is the up-call from the JVM: // this is the up-call from the JVM:
static CallSite makeSite(Class<?> caller, String name, MethodType type, static CallSite makeSite(Class<?> caller, String name, MethodType type,
...@@ -61,10 +78,25 @@ class CallSiteImpl extends CallSite { ...@@ -61,10 +78,25 @@ class CallSiteImpl extends CallSite {
MethodHandle bsm = Linkage.getBootstrapMethod(caller); MethodHandle bsm = Linkage.getBootstrapMethod(caller);
if (bsm == null) if (bsm == null)
throw new InvokeDynamicBootstrapError("class has no bootstrap method: "+caller); throw new InvokeDynamicBootstrapError("class has no bootstrap method: "+caller);
CallSite site = bsm.<CallSite>invoke(caller, name, type); CallSite site;
try {
site = bsm.<CallSite>invoke(caller, name, type);
} catch (Throwable ex) {
throw new InvokeDynamicBootstrapError("exception thrown while linking", ex);
}
if (site == null) if (site == null)
throw new InvokeDynamicBootstrapError("class bootstrap method failed to create a call site: "+caller); throw new InvokeDynamicBootstrapError("class bootstrap method failed to create a call site: "+caller);
PRIVATE_INITIALIZE_CALL_SITE.<void>invoke(site, callerMID, callerBCI); if (site.type() != type)
throw new InvokeDynamicBootstrapError("call site type not initialized correctly: "+site);
if (site.callerClass() != caller)
throw new InvokeDynamicBootstrapError("call site caller not initialized correctly: "+site);
if ((Object)site.name() != name)
throw new InvokeDynamicBootstrapError("call site name not initialized correctly: "+site);
try {
PRIVATE_INITIALIZE_CALL_SITE.<void>invoke(site, callerMID, callerBCI);
} catch (Throwable ex) {
throw new InvokeDynamicBootstrapError("call site initialization exception", ex);
}
return site; return site;
} }
} }
因为 它太大了无法显示 source diff 。你可以改为 查看blob
...@@ -27,7 +27,6 @@ package sun.dyn; ...@@ -27,7 +27,6 @@ package sun.dyn;
import java.dyn.JavaMethodHandle; import java.dyn.JavaMethodHandle;
import java.dyn.MethodHandle; import java.dyn.MethodHandle;
import java.dyn.MethodHandles;
import java.dyn.MethodType; import java.dyn.MethodType;
/** /**
...@@ -42,16 +41,21 @@ public class FilterOneArgument extends JavaMethodHandle { ...@@ -42,16 +41,21 @@ public class FilterOneArgument extends JavaMethodHandle {
protected final MethodHandle filter; // Object -> Object protected final MethodHandle filter; // Object -> Object
protected final MethodHandle target; // Object -> Object protected final MethodHandle target; // Object -> Object
protected Object entryPoint(Object argument) { @Override
Object filteredArgument = filter.<Object>invoke(argument); public String toString() {
return target.<Object>invoke(filteredArgument); return target.toString();
}
protected Object invoke(Object argument) throws Throwable {
Object filteredArgument = filter.invoke(argument);
return target.invoke(filteredArgument);
} }
private static final MethodHandle entryPoint = private static final MethodHandle INVOKE =
MethodHandleImpl.IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "entryPoint", MethodType.makeGeneric(1)); MethodHandleImpl.IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "invoke", MethodType.genericMethodType(1));
protected FilterOneArgument(MethodHandle filter, MethodHandle target) { protected FilterOneArgument(MethodHandle filter, MethodHandle target) {
super(entryPoint); super(INVOKE);
this.filter = filter; this.filter = filter;
this.target = target; this.target = target;
} }
...@@ -62,10 +66,6 @@ public class FilterOneArgument extends JavaMethodHandle { ...@@ -62,10 +66,6 @@ public class FilterOneArgument extends JavaMethodHandle {
return new FilterOneArgument(filter, target); return new FilterOneArgument(filter, target);
} }
public String toString() {
return filter + "|>" + target;
}
// MethodHandle make(MethodHandle filter1, MethodHandle filter2, MethodHandle target) { // MethodHandle make(MethodHandle filter1, MethodHandle filter2, MethodHandle target) {
// MethodHandle filter = make(filter1, filter2); // MethodHandle filter = make(filter1, filter2);
// return make(filter, target); // return make(filter, target);
......
...@@ -36,8 +36,8 @@ import sun.dyn.util.ValueConversions; ...@@ -36,8 +36,8 @@ import sun.dyn.util.ValueConversions;
import sun.dyn.util.Wrapper; import sun.dyn.util.Wrapper;
/** /**
* Adapters which mediate between incoming calls which are not generic * Adapters which mediate between incoming calls which are generic
* and outgoing calls which are. Any call can be represented generically * and outgoing calls which are not. Any call can be represented generically
* boxing up its arguments, and (on return) unboxing the return value. * boxing up its arguments, and (on return) unboxing the return value.
* <p> * <p>
* A call is "generic" (in MethodHandle terms) if its MethodType features * A call is "generic" (in MethodHandle terms) if its MethodType features
...@@ -50,9 +50,6 @@ import sun.dyn.util.Wrapper; ...@@ -50,9 +50,6 @@ import sun.dyn.util.Wrapper;
* either binds internally or else takes as a leading argument). * either binds internally or else takes as a leading argument).
* (To stretch the term, adapter-like method handles may have multiple * (To stretch the term, adapter-like method handles may have multiple
* targets or be polymorphic across multiple call types.) * targets or be polymorphic across multiple call types.)
* <p>
* This adapter can sometimes be more directly implemented
* by the JVM's built-in OP_SPREAD_ARGS adapter.
* @author jrose * @author jrose
*/ */
class FromGeneric { class FromGeneric {
...@@ -99,7 +96,7 @@ class FromGeneric { ...@@ -99,7 +96,7 @@ class FromGeneric {
} }
this.internalType = internalType0; this.internalType = internalType0;
this.adapter = ad; this.adapter = ad;
MethodType tepType = targetType.insertParameterType(0, adapter.getClass()); MethodType tepType = targetType.insertParameterTypes(0, adapter.getClass());
this.entryPoint = ad.prototypeEntryPoint(); this.entryPoint = ad.prototypeEntryPoint();
this.returnConversion = computeReturnConversion(targetType, internalType0); this.returnConversion = computeReturnConversion(targetType, internalType0);
this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0); this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0);
...@@ -146,7 +143,7 @@ class FromGeneric { ...@@ -146,7 +143,7 @@ class FromGeneric {
if (fixArgs == null) if (fixArgs == null)
throw new InternalError("bad fixArgs"); throw new InternalError("bad fixArgs");
// reinterpret the calling sequence as raw: // reinterpret the calling sequence as raw:
MethodHandle retyper = AdapterMethodHandle.makeRawRetypeOnly(Access.TOKEN, MethodHandle retyper = AdapterMethodHandle.makeRetypeRaw(Access.TOKEN,
Invokers.invokerType(internalType), fixArgs); Invokers.invokerType(internalType), fixArgs);
if (retyper == null) if (retyper == null)
throw new InternalError("bad retyper"); throw new InternalError("bad retyper");
...@@ -226,7 +223,10 @@ class FromGeneric { ...@@ -226,7 +223,10 @@ class FromGeneric {
// Produce an instance configured as a prototype. // Produce an instance configured as a prototype.
return ctor.newInstance(entryPoint); return ctor.newInstance(entryPoint);
} catch (IllegalArgumentException ex) { } catch (IllegalArgumentException ex) {
} catch (InvocationTargetException ex) { } catch (InvocationTargetException wex) {
Throwable ex = wex.getTargetException();
if (ex instanceof Error) throw (Error)ex;
if (ex instanceof RuntimeException) throw (RuntimeException)ex;
} catch (InstantiationException ex) { } catch (InstantiationException ex) {
} catch (IllegalAccessException ex) { } catch (IllegalAccessException ex) {
} }
...@@ -260,6 +260,11 @@ class FromGeneric { ...@@ -260,6 +260,11 @@ class FromGeneric {
protected final MethodHandle convert; // raw(R) => Object protected final MethodHandle convert; // raw(R) => Object
protected final MethodHandle target; // (any**N) => R protected final MethodHandle target; // (any**N) => R
@Override
public String toString() {
return target.toString();
}
protected boolean isPrototype() { return target == null; } protected boolean isPrototype() { return target == null; }
protected Adapter(MethodHandle entryPoint) { protected Adapter(MethodHandle entryPoint) {
this(entryPoint, null, entryPoint, null); this(entryPoint, null, entryPoint, null);
...@@ -284,11 +289,11 @@ class FromGeneric { ...@@ -284,11 +289,11 @@ class FromGeneric {
// { return new ThisType(entryPoint, convert, target); } // { return new ThisType(entryPoint, convert, target); }
/// Conversions on the value returned from the target. /// Conversions on the value returned from the target.
protected Object convert_L(Object result) { return convert.<Object>invoke(result); } protected Object convert_L(Object result) throws Throwable { return convert.<Object>invoke(result); }
protected Object convert_I(int result) { return convert.<Object>invoke(result); } protected Object convert_I(int result) throws Throwable { return convert.<Object>invoke(result); }
protected Object convert_J(long result) { return convert.<Object>invoke(result); } protected Object convert_J(long result) throws Throwable { return convert.<Object>invoke(result); }
protected Object convert_F(float result) { return convert.<Object>invoke(result); } protected Object convert_F(float result) throws Throwable { return convert.<Object>invoke(result); }
protected Object convert_D(double result) { return convert.<Object>invoke(result); } protected Object convert_D(double result) throws Throwable { return convert.<Object>invoke(result); }
static private final String CLASS_PREFIX; // "sun.dyn.FromGeneric$" static private final String CLASS_PREFIX; // "sun.dyn.FromGeneric$"
static { static {
...@@ -317,11 +322,11 @@ class FromGeneric { ...@@ -317,11 +322,11 @@ class FromGeneric {
{ super(e, i, c, t); } { super(e, i, c, t); }
protected xA2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) protected xA2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
{ return new xA2(e, i, c, t); } { return new xA2(e, i, c, t); }
protected Object invoke_L2(Object a0, Object a1) { return convert_L(invoker.<Object>invoke(target, a0, a1)); } protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1)); }
protected Object invoke_I2(Object a0, Object a1) { return convert_I(invoker.<int >invoke(target, a0, a1)); } protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I(invoker.<int >invoke(target, a0, a1)); }
protected Object invoke_J2(Object a0, Object a1) { return convert_J(invoker.<long >invoke(target, a0, a1)); } protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J(invoker.<long >invoke(target, a0, a1)); }
protected Object invoke_F2(Object a0, Object a1) { return convert_F(invoker.<float >invoke(target, a0, a1)); } protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1)); }
protected Object invoke_D2(Object a0, Object a1) { return convert_D(invoker.<double>invoke(target, a0, a1)); } protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1)); }
} }
// */ // */
...@@ -342,7 +347,7 @@ class genclasses { ...@@ -342,7 +347,7 @@ class genclasses {
" protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)", " protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)",
" { return new @cat@(e, i, c, t); }", " { return new @cat@(e, i, c, t); }",
" //@each-R@", " //@each-R@",
" protected Object invoke_@catN@(@Tvav@) { return convert_@Rc@(invoker.<@R@>invoke(target@av@)); }", " protected Object invoke_@catN@(@Tvav@) throws Throwable { return convert_@Rc@(invoker.<@R@>invoke(target@av@)); }",
" //@end-R@", " //@end-R@",
" }", " }",
} }; } };
...@@ -498,11 +503,11 @@ class genclasses { ...@@ -498,11 +503,11 @@ class genclasses {
{ super(e, i, c, t); } { super(e, i, c, t); }
protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
{ return new A0(e, i, c, t); } { return new A0(e, i, c, t); }
protected Object invoke_L0() { return convert_L(invoker.<Object>invoke(target)); } protected Object invoke_L0() throws Throwable { return convert_L(invoker.<Object>invoke(target)); }
protected Object invoke_I0() { return convert_I(invoker.<int >invoke(target)); } protected Object invoke_I0() throws Throwable { return convert_I(invoker.<int >invoke(target)); }
protected Object invoke_J0() { return convert_J(invoker.<long >invoke(target)); } protected Object invoke_J0() throws Throwable { return convert_J(invoker.<long >invoke(target)); }
protected Object invoke_F0() { return convert_F(invoker.<float >invoke(target)); } protected Object invoke_F0() throws Throwable { return convert_F(invoker.<float >invoke(target)); }
protected Object invoke_D0() { return convert_D(invoker.<double>invoke(target)); } protected Object invoke_D0() throws Throwable { return convert_D(invoker.<double>invoke(target)); }
} }
static class A1 extends Adapter { static class A1 extends Adapter {
protected A1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
...@@ -510,11 +515,11 @@ class genclasses { ...@@ -510,11 +515,11 @@ class genclasses {
{ super(e, i, c, t); } { super(e, i, c, t); }
protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
{ return new A1(e, i, c, t); } { return new A1(e, i, c, t); }
protected Object invoke_L1(Object a0) { return convert_L(invoker.<Object>invoke(target, a0)); } protected Object invoke_L1(Object a0) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0)); }
protected Object invoke_I1(Object a0) { return convert_I(invoker.<int >invoke(target, a0)); } protected Object invoke_I1(Object a0) throws Throwable { return convert_I(invoker.<int >invoke(target, a0)); }
protected Object invoke_J1(Object a0) { return convert_J(invoker.<long >invoke(target, a0)); } protected Object invoke_J1(Object a0) throws Throwable { return convert_J(invoker.<long >invoke(target, a0)); }
protected Object invoke_F1(Object a0) { return convert_F(invoker.<float >invoke(target, a0)); } protected Object invoke_F1(Object a0) throws Throwable { return convert_F(invoker.<float >invoke(target, a0)); }
protected Object invoke_D1(Object a0) { return convert_D(invoker.<double>invoke(target, a0)); } protected Object invoke_D1(Object a0) throws Throwable { return convert_D(invoker.<double>invoke(target, a0)); }
} }
static class A2 extends Adapter { static class A2 extends Adapter {
protected A2(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A2(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
...@@ -522,11 +527,11 @@ class genclasses { ...@@ -522,11 +527,11 @@ class genclasses {
{ super(e, i, c, t); } { super(e, i, c, t); }
protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
{ return new A2(e, i, c, t); } { return new A2(e, i, c, t); }
protected Object invoke_L2(Object a0, Object a1) { return convert_L(invoker.<Object>invoke(target, a0, a1)); } protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1)); }
protected Object invoke_I2(Object a0, Object a1) { return convert_I(invoker.<int >invoke(target, a0, a1)); } protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I(invoker.<int >invoke(target, a0, a1)); }
protected Object invoke_J2(Object a0, Object a1) { return convert_J(invoker.<long >invoke(target, a0, a1)); } protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J(invoker.<long >invoke(target, a0, a1)); }
protected Object invoke_F2(Object a0, Object a1) { return convert_F(invoker.<float >invoke(target, a0, a1)); } protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1)); }
protected Object invoke_D2(Object a0, Object a1) { return convert_D(invoker.<double>invoke(target, a0, a1)); } protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1)); }
} }
static class A3 extends Adapter { static class A3 extends Adapter {
protected A3(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A3(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
...@@ -534,11 +539,11 @@ class genclasses { ...@@ -534,11 +539,11 @@ class genclasses {
{ super(e, i, c, t); } { super(e, i, c, t); }
protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
{ return new A3(e, i, c, t); } { return new A3(e, i, c, t); }
protected Object invoke_L3(Object a0, Object a1, Object a2) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2)); } protected Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1, a2)); }
protected Object invoke_I3(Object a0, Object a1, Object a2) { return convert_I(invoker.<int >invoke(target, a0, a1, a2)); } protected Object invoke_I3(Object a0, Object a1, Object a2) throws Throwable { return convert_I(invoker.<int >invoke(target, a0, a1, a2)); }
protected Object invoke_J3(Object a0, Object a1, Object a2) { return convert_J(invoker.<long >invoke(target, a0, a1, a2)); } protected Object invoke_J3(Object a0, Object a1, Object a2) throws Throwable { return convert_J(invoker.<long >invoke(target, a0, a1, a2)); }
protected Object invoke_F3(Object a0, Object a1, Object a2) { return convert_F(invoker.<float >invoke(target, a0, a1, a2)); } protected Object invoke_F3(Object a0, Object a1, Object a2) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1, a2)); }
protected Object invoke_D3(Object a0, Object a1, Object a2) { return convert_D(invoker.<double>invoke(target, a0, a1, a2)); } protected Object invoke_D3(Object a0, Object a1, Object a2) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1, a2)); }
} }
static class A4 extends Adapter { static class A4 extends Adapter {
protected A4(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A4(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
...@@ -546,11 +551,11 @@ class genclasses { ...@@ -546,11 +551,11 @@ class genclasses {
{ super(e, i, c, t); } { super(e, i, c, t); }
protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
{ return new A4(e, i, c, t); } { return new A4(e, i, c, t); }
protected Object invoke_L4(Object a0, Object a1, Object a2, Object a3) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3)); } protected Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3)); }
protected Object invoke_I4(Object a0, Object a1, Object a2, Object a3) { return convert_I(invoker.<int >invoke(target, a0, a1, a2, a3)); } protected Object invoke_I4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_I(invoker.<int >invoke(target, a0, a1, a2, a3)); }
protected Object invoke_J4(Object a0, Object a1, Object a2, Object a3) { return convert_J(invoker.<long >invoke(target, a0, a1, a2, a3)); } protected Object invoke_J4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_J(invoker.<long >invoke(target, a0, a1, a2, a3)); }
protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3)); } protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3)); }
protected Object invoke_D4(Object a0, Object a1, Object a2, Object a3) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3)); } protected Object invoke_D4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3)); }
} }
static class A5 extends Adapter { static class A5 extends Adapter {
protected A5(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A5(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
...@@ -558,11 +563,11 @@ class genclasses { ...@@ -558,11 +563,11 @@ class genclasses {
{ super(e, i, c, t); } { super(e, i, c, t); }
protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
{ return new A5(e, i, c, t); } { return new A5(e, i, c, t); }
protected Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4)); } protected Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4)); }
protected Object invoke_I5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_I(invoker.<int >invoke(target, a0, a1, a2, a3, a4)); } protected Object invoke_I5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_I(invoker.<int >invoke(target, a0, a1, a2, a3, a4)); }
protected Object invoke_J5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_J(invoker.<long >invoke(target, a0, a1, a2, a3, a4)); } protected Object invoke_J5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_J(invoker.<long >invoke(target, a0, a1, a2, a3, a4)); }
protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4)); } protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4)); }
protected Object invoke_D5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4)); } protected Object invoke_D5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4)); }
} }
static class A6 extends Adapter { static class A6 extends Adapter {
protected A6(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A6(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
...@@ -570,11 +575,11 @@ class genclasses { ...@@ -570,11 +575,11 @@ class genclasses {
{ super(e, i, c, t); } { super(e, i, c, t); }
protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
{ return new A6(e, i, c, t); } { return new A6(e, i, c, t); }
protected Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5)); } protected Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5)); }
protected Object invoke_I6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_I(invoker.<int >invoke(target, a0, a1, a2, a3, a4, a5)); } protected Object invoke_I6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_I(invoker.<int >invoke(target, a0, a1, a2, a3, a4, a5)); }
protected Object invoke_J6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_J(invoker.<long >invoke(target, a0, a1, a2, a3, a4, a5)); } protected Object invoke_J6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_J(invoker.<long >invoke(target, a0, a1, a2, a3, a4, a5)); }
protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5)); } protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5)); }
protected Object invoke_D6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5)); } protected Object invoke_D6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5)); }
} }
static class A7 extends Adapter { static class A7 extends Adapter {
protected A7(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A7(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
...@@ -582,11 +587,11 @@ class genclasses { ...@@ -582,11 +587,11 @@ class genclasses {
{ super(e, i, c, t); } { super(e, i, c, t); }
protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
{ return new A7(e, i, c, t); } { return new A7(e, i, c, t); }
protected Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6)); } protected Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
protected Object invoke_I7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_I(invoker.<int >invoke(target, a0, a1, a2, a3, a4, a5, a6)); } protected Object invoke_I7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_I(invoker.<int >invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
protected Object invoke_J7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_J(invoker.<long >invoke(target, a0, a1, a2, a3, a4, a5, a6)); } protected Object invoke_J7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_J(invoker.<long >invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6)); } protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
protected Object invoke_D7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6)); } protected Object invoke_D7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6)); }
} }
static class A8 extends Adapter { static class A8 extends Adapter {
protected A8(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A8(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
...@@ -594,11 +599,11 @@ class genclasses { ...@@ -594,11 +599,11 @@ class genclasses {
{ super(e, i, c, t); } { super(e, i, c, t); }
protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
{ return new A8(e, i, c, t); } { return new A8(e, i, c, t); }
protected Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); } protected Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
protected Object invoke_I8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_I(invoker.<int >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); } protected Object invoke_I8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_I(invoker.<int >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
protected Object invoke_J8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_J(invoker.<long >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); } protected Object invoke_J8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_J(invoker.<long >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); } protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
protected Object invoke_D8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); } protected Object invoke_D8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
} }
static class A9 extends Adapter { static class A9 extends Adapter {
protected A9(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A9(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
...@@ -606,11 +611,11 @@ class genclasses { ...@@ -606,11 +611,11 @@ class genclasses {
{ super(e, i, c, t); } { super(e, i, c, t); }
protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
{ return new A9(e, i, c, t); } { return new A9(e, i, c, t); }
protected Object invoke_L9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected Object invoke_L9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected Object invoke_I9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_I(invoker.<int >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected Object invoke_I9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_I(invoker.<int >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected Object invoke_J9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_J(invoker.<long >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected Object invoke_J9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_J(invoker.<long >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected Object invoke_D9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected Object invoke_D9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
} }
static class A10 extends Adapter { static class A10 extends Adapter {
protected A10(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A10(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
...@@ -618,10 +623,10 @@ class genclasses { ...@@ -618,10 +623,10 @@ class genclasses {
{ super(e, i, c, t); } { super(e, i, c, t); }
protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
{ return new A10(e, i, c, t); } { return new A10(e, i, c, t); }
protected Object invoke_L10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected Object invoke_L10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_L(invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected Object invoke_I10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_I(invoker.<int >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected Object invoke_I10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_I(invoker.<int >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected Object invoke_J10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_J(invoker.<long >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected Object invoke_J10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_J(invoker.<long >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_F(invoker.<float >invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected Object invoke_D10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected Object invoke_D10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_D(invoker.<double>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
} }
} }
...@@ -44,16 +44,20 @@ public class Invokers { ...@@ -44,16 +44,20 @@ public class Invokers {
// generic (untyped) invoker for the outgoing call // generic (untyped) invoker for the outgoing call
private /*lazy*/ MethodHandle genericInvoker; private /*lazy*/ MethodHandle genericInvoker;
// generic (untyped) invoker for the outgoing call; accepts a single Object[]
private final /*lazy*/ MethodHandle[] varargsInvokers;
/** Compute and cache information common to all collecting adapters /** Compute and cache information common to all collecting adapters
* that implement members of the erasure-family of the given erased type. * that implement members of the erasure-family of the given erased type.
*/ */
public Invokers(Access token, MethodType targetType) { public Invokers(Access token, MethodType targetType) {
Access.check(token); Access.check(token);
this.targetType = targetType; this.targetType = targetType;
this.varargsInvokers = new MethodHandle[targetType.parameterCount()+1];
} }
public static MethodType invokerType(MethodType targetType) { public static MethodType invokerType(MethodType targetType) {
return targetType.insertParameterType(0, MethodHandle.class); return targetType.insertParameterTypes(0, MethodHandle.class);
} }
public MethodHandle exactInvoker() { public MethodHandle exactInvoker() {
...@@ -76,8 +80,14 @@ public class Invokers { ...@@ -76,8 +80,14 @@ public class Invokers {
return invoker; return invoker;
} }
public MethodHandle varargsInvoker() { public MethodHandle varargsInvoker(int objectArgCount) {
throw new UnsupportedOperationException("NYI"); MethodHandle vaInvoker = varargsInvokers[objectArgCount];
if (vaInvoker != null) return vaInvoker;
MethodHandle gInvoker = genericInvoker();
MethodType vaType = MethodType.genericMethodType(objectArgCount, true);
vaInvoker = MethodHandles.spreadArguments(gInvoker, invokerType(vaType));
varargsInvokers[objectArgCount] = vaInvoker;
return vaInvoker;
} }
public String toString() { public String toString() {
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
package sun.dyn; package sun.dyn;
import sun.dyn.util.BytecodeSignature; import sun.dyn.util.BytecodeDescriptor;
import java.dyn.*; import java.dyn.*;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
...@@ -33,6 +33,7 @@ import java.lang.reflect.Method; ...@@ -33,6 +33,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
...@@ -93,7 +94,7 @@ public final class MemberName implements Member, Cloneable { ...@@ -93,7 +94,7 @@ public final class MemberName implements Member, Cloneable {
} }
if (type instanceof String) { if (type instanceof String) {
String sig = (String) type; String sig = (String) type;
MethodType res = MethodType.fromBytecodeString(sig, getClassLoader()); MethodType res = MethodType.fromMethodDescriptorString(sig, getClassLoader());
this.type = res; this.type = res;
return res; return res;
} }
...@@ -101,7 +102,7 @@ public final class MemberName implements Member, Cloneable { ...@@ -101,7 +102,7 @@ public final class MemberName implements Member, Cloneable {
Object[] typeInfo = (Object[]) type; Object[] typeInfo = (Object[]) type;
Class<?>[] ptypes = (Class<?>[]) typeInfo[1]; Class<?>[] ptypes = (Class<?>[]) typeInfo[1];
Class<?> rtype = (Class<?>) typeInfo[0]; Class<?> rtype = (Class<?>) typeInfo[0];
MethodType res = MethodType.make(rtype, ptypes); MethodType res = MethodType.methodType(rtype, ptypes);
this.type = res; this.type = res;
return res; return res;
} }
...@@ -111,7 +112,7 @@ public final class MemberName implements Member, Cloneable { ...@@ -111,7 +112,7 @@ public final class MemberName implements Member, Cloneable {
public MethodType getInvocationType() { public MethodType getInvocationType() {
MethodType itype = getMethodType(); MethodType itype = getMethodType();
if (!isStatic()) if (!isStatic())
itype = itype.insertParameterType(0, clazz); itype = itype.insertParameterTypes(0, clazz);
return itype; return itype;
} }
...@@ -135,7 +136,7 @@ public final class MemberName implements Member, Cloneable { ...@@ -135,7 +136,7 @@ public final class MemberName implements Member, Cloneable {
} }
if (type instanceof String) { if (type instanceof String) {
String sig = (String) type; String sig = (String) type;
MethodType mtype = MethodType.fromBytecodeString("()"+sig, getClassLoader()); MethodType mtype = MethodType.fromMethodDescriptorString("()"+sig, getClassLoader());
Class<?> res = mtype.returnType(); Class<?> res = mtype.returnType();
this.type = res; this.type = res;
return res; return res;
...@@ -155,9 +156,9 @@ public final class MemberName implements Member, Cloneable { ...@@ -155,9 +156,9 @@ public final class MemberName implements Member, Cloneable {
if (type instanceof String) if (type instanceof String)
return (String) type; return (String) type;
if (isInvocable()) if (isInvocable())
return BytecodeSignature.unparse(getMethodType()); return BytecodeDescriptor.unparse(getMethodType());
else else
return BytecodeSignature.unparse(getFieldType()); return BytecodeDescriptor.unparse(getFieldType());
} }
public int getModifiers() { public int getModifiers() {
...@@ -353,6 +354,8 @@ public final class MemberName implements Member, Cloneable { ...@@ -353,6 +354,8 @@ public final class MemberName implements Member, Cloneable {
return type.toString(); // class java.lang.String return type.toString(); // class java.lang.String
// else it is a field, method, or constructor // else it is a field, method, or constructor
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
if (!isResolved())
buf.append("*.");
if (getDeclaringClass() != null) { if (getDeclaringClass() != null) {
buf.append(getName(clazz)); buf.append(getName(clazz));
buf.append('.'); buf.append('.');
...@@ -381,7 +384,7 @@ public final class MemberName implements Member, Cloneable { ...@@ -381,7 +384,7 @@ public final class MemberName implements Member, Cloneable {
private static String getName(Object obj) { private static String getName(Object obj) {
if (obj instanceof Class<?>) if (obj instanceof Class<?>)
return ((Class<?>)obj).getName(); return ((Class<?>)obj).getName();
return obj.toString(); return String.valueOf(obj);
} }
// Queries to the JVM: // Queries to the JVM:
...@@ -408,6 +411,9 @@ public final class MemberName implements Member, Cloneable { ...@@ -408,6 +411,9 @@ public final class MemberName implements Member, Cloneable {
public static NoAccessException newNoAccessException(MemberName name, Class<?> lookupClass) { public static NoAccessException newNoAccessException(MemberName name, Class<?> lookupClass) {
return newNoAccessException("cannot access", name, lookupClass); return newNoAccessException("cannot access", name, lookupClass);
} }
public static NoAccessException newNoAccessException(MemberName name, MethodHandles.Lookup lookup) {
return newNoAccessException(name, lookup.lookupClass());
}
public static NoAccessException newNoAccessException(String message, public static NoAccessException newNoAccessException(String message,
MemberName name, Class<?> lookupClass) { MemberName name, Class<?> lookupClass) {
message += ": " + name; message += ": " + name;
...@@ -436,7 +442,7 @@ public final class MemberName implements Member, Cloneable { ...@@ -436,7 +442,7 @@ public final class MemberName implements Member, Cloneable {
matchFlags &= ALLOWED_FLAGS; matchFlags &= ALLOWED_FLAGS;
String matchSig = null; String matchSig = null;
if (matchType != null) { if (matchType != null) {
matchSig = BytecodeSignature.unparse(matchType); matchSig = BytecodeDescriptor.unparse(matchType);
if (matchSig.startsWith("(")) if (matchSig.startsWith("("))
matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE); matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE);
else else
...@@ -447,17 +453,18 @@ public final class MemberName implements Member, Cloneable { ...@@ -447,17 +453,18 @@ public final class MemberName implements Member, Cloneable {
MemberName[] buf = newMemberBuffer(len1); MemberName[] buf = newMemberBuffer(len1);
int totalCount = 0; int totalCount = 0;
ArrayList<MemberName[]> bufs = null; ArrayList<MemberName[]> bufs = null;
int bufCount = 0;
for (;;) { for (;;) {
int bufCount = MethodHandleNatives.getMembers(defc, bufCount = MethodHandleNatives.getMembers(defc,
matchName, matchSig, matchFlags, matchName, matchSig, matchFlags,
lookupClass, lookupClass,
totalCount, buf); totalCount, buf);
if (bufCount <= buf.length) { if (bufCount <= buf.length) {
if (bufCount >= 0) if (bufCount < 0) bufCount = 0;
totalCount += bufCount; totalCount += bufCount;
break; break;
} }
// JVM returned tp us with an intentional overflow! // JVM returned to us with an intentional overflow!
totalCount += buf.length; totalCount += buf.length;
int excess = bufCount - buf.length; int excess = bufCount - buf.length;
if (bufs == null) bufs = new ArrayList<MemberName[]>(1); if (bufs == null) bufs = new ArrayList<MemberName[]>(1);
...@@ -473,7 +480,7 @@ public final class MemberName implements Member, Cloneable { ...@@ -473,7 +480,7 @@ public final class MemberName implements Member, Cloneable {
Collections.addAll(result, buf0); Collections.addAll(result, buf0);
} }
} }
Collections.addAll(result, buf); result.addAll(Arrays.asList(buf).subList(0, bufCount));
// Signature matching is not the same as type matching, since // Signature matching is not the same as type matching, since
// one signature might correspond to several types. // one signature might correspond to several types.
// So if matchType is a Class or MethodType, refilter the results. // So if matchType is a Class or MethodType, refilter the results.
......
...@@ -25,12 +25,25 @@ ...@@ -25,12 +25,25 @@
package sun.dyn; package sun.dyn;
import java.dyn.JavaMethodHandle;
import java.dyn.MethodHandle; import java.dyn.MethodHandle;
import java.dyn.MethodHandles; import java.dyn.MethodHandles;
import java.dyn.MethodHandles.Lookup; import java.dyn.MethodHandles.Lookup;
import java.dyn.MethodType; import java.dyn.MethodType;
import java.util.logging.Level;
import java.util.logging.Logger;
import sun.dyn.util.VerifyType; import sun.dyn.util.VerifyType;
import java.dyn.NoAccessException; import java.dyn.NoAccessException;
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.newIllegalArgumentException;
import static sun.dyn.MemberName.newNoAccessException; import static sun.dyn.MemberName.newNoAccessException;
...@@ -57,6 +70,25 @@ public abstract class MethodHandleImpl { ...@@ -57,6 +70,25 @@ public abstract class MethodHandleImpl {
static final int INT_FIELD = 0; static final int INT_FIELD = 0;
static final long LONG_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 // type is defined in java.dyn.MethodHandle, which is platform-independent
// vmentry (a void* field) is used *only* by by the JVM. // vmentry (a void* field) is used *only* by by the JVM.
...@@ -106,8 +138,8 @@ public abstract class MethodHandleImpl { ...@@ -106,8 +138,8 @@ public abstract class MethodHandleImpl {
} }
static { static {
// Force initialization: // Force initialization of Lookup, so it calls us back as initLookup:
Lookup.PUBLIC_LOOKUP.lookupClass(); MethodHandles.publicLookup();
if (IMPL_LOOKUP_INIT == null) if (IMPL_LOOKUP_INIT == null)
throw new InternalError(); throw new InternalError();
} }
...@@ -151,7 +183,7 @@ public abstract class MethodHandleImpl { ...@@ -151,7 +183,7 @@ public abstract class MethodHandleImpl {
// adjust the advertised receiver type to be exactly the one requested // adjust the advertised receiver type to be exactly the one requested
// (in the case of invokespecial, this will be the calling class) // (in the case of invokespecial, this will be the calling class)
Class<?> recvType = method.getDeclaringClass(); Class<?> recvType = method.getDeclaringClass();
mtype = mtype.insertParameterType(0, recvType); mtype = mtype.insertParameterTypes(0, recvType);
if (method.isConstructor()) if (method.isConstructor())
doDispatch = true; doDispatch = true;
// FIXME: JVM has trouble building MH.invoke sites for // FIXME: JVM has trouble building MH.invoke sites for
...@@ -170,21 +202,223 @@ public abstract class MethodHandleImpl { ...@@ -170,21 +202,223 @@ public abstract class MethodHandleImpl {
public static public static
MethodHandle accessField(Access token, MethodHandle accessField(Access token,
MemberName member, boolean isSetter, MemberName member, boolean isSetter,
Class<?> lookupClass) { Class<?> lookupClass) {
Access.check(token); Access.check(token);
// FIXME: Use sun.misc.Unsafe to dig up the dirt on the field. // Use sun. misc.Unsafe to dig up the dirt on the field.
throw new UnsupportedOperationException("Not yet implemented"); MethodHandle mh = new FieldAccessor(token, member, isSetter);
return mh;
} }
public static public static
MethodHandle accessArrayElement(Access token, MethodHandle accessArrayElement(Access token,
Class<?> arrayClass, boolean isSetter) { Class<?> arrayClass, boolean isSetter) {
Access.check(token); Access.check(token);
if (!arrayClass.isArray()) if (!arrayClass.isArray())
throw newIllegalArgumentException("not an array: "+arrayClass); throw newIllegalArgumentException("not an array: "+arrayClass);
// FIXME: Use sun.misc.Unsafe to dig up the dirt on the array. Class<?> elemClass = arrayClass.getComponentType();
throw new UnsupportedOperationException("Not yet implemented"); MethodHandle[] mhs = FieldAccessor.ARRAY_CACHE.get(elemClass);
if (mhs == null) {
if (!FieldAccessor.doCache(elemClass))
return FieldAccessor.ahandle(arrayClass, isSetter);
mhs = new MethodHandle[] {
FieldAccessor.ahandle(arrayClass, false),
FieldAccessor.ahandle(arrayClass, true)
};
if (mhs[0].type().parameterType(0) == Class.class) {
mhs[0] = MethodHandles.insertArguments(mhs[0], 0, elemClass);
mhs[1] = MethodHandles.insertArguments(mhs[1], 0, elemClass);
}
synchronized (FieldAccessor.ARRAY_CACHE) {} // memory barrier
FieldAccessor.ARRAY_CACHE.put(elemClass, mhs);
}
return mhs[isSetter ? 1 : 0];
}
static final class FieldAccessor<C,V> extends JavaMethodHandle {
private static final Unsafe unsafe = Unsafe.getUnsafe();
final Object base; // for static refs only
final long offset;
final String name;
public FieldAccessor(Access token, MemberName field, boolean isSetter) {
super(fhandle(field.getDeclaringClass(), field.getFieldType(), isSetter, field.isStatic()));
this.offset = (long) field.getVMIndex(token);
this.name = field.getName();
this.base = staticBase(field);
}
public String toString() { return name; }
int getFieldI(C obj) { return unsafe.getInt(obj, offset); }
void setFieldI(C obj, int x) { unsafe.putInt(obj, offset, x); }
long getFieldJ(C obj) { return unsafe.getLong(obj, offset); }
void setFieldJ(C obj, long x) { unsafe.putLong(obj, offset, x); }
float getFieldF(C obj) { return unsafe.getFloat(obj, offset); }
void setFieldF(C obj, float x) { unsafe.putFloat(obj, offset, x); }
double getFieldD(C obj) { return unsafe.getDouble(obj, offset); }
void setFieldD(C obj, double x) { unsafe.putDouble(obj, offset, x); }
boolean getFieldZ(C obj) { return unsafe.getBoolean(obj, offset); }
void setFieldZ(C obj, boolean x) { unsafe.putBoolean(obj, offset, x); }
byte getFieldB(C obj) { return unsafe.getByte(obj, offset); }
void setFieldB(C obj, byte x) { unsafe.putByte(obj, offset, x); }
short getFieldS(C obj) { return unsafe.getShort(obj, offset); }
void setFieldS(C obj, short x) { unsafe.putShort(obj, offset, x); }
char getFieldC(C obj) { return unsafe.getChar(obj, offset); }
void setFieldC(C obj, char x) { unsafe.putChar(obj, offset, x); }
@SuppressWarnings("unchecked")
V getFieldL(C obj) { return (V) unsafe.getObject(obj, offset); }
@SuppressWarnings("unchecked")
void setFieldL(C obj, V x) { unsafe.putObject(obj, offset, x); }
// cast (V) is OK here, since we wrap convertArguments around the MH.
static Object staticBase(MemberName field) {
if (!field.isStatic()) return null;
Class c = field.getDeclaringClass();
java.lang.reflect.Field f;
try {
// FIXME: Should not have to create 'f' to get this value.
f = c.getDeclaredField(field.getName());
return unsafe.staticFieldBase(f);
} catch (Exception ee) {
Error e = new InternalError();
e.initCause(ee);
throw e;
}
}
int getStaticI() { return unsafe.getInt(base, offset); }
void setStaticI(int x) { unsafe.putInt(base, offset, x); }
long getStaticJ() { return unsafe.getLong(base, offset); }
void setStaticJ(long x) { unsafe.putLong(base, offset, x); }
float getStaticF() { return unsafe.getFloat(base, offset); }
void setStaticF(float x) { unsafe.putFloat(base, offset, x); }
double getStaticD() { return unsafe.getDouble(base, offset); }
void setStaticD(double x) { unsafe.putDouble(base, offset, x); }
boolean getStaticZ() { return unsafe.getBoolean(base, offset); }
void setStaticZ(boolean x) { unsafe.putBoolean(base, offset, x); }
byte getStaticB() { return unsafe.getByte(base, offset); }
void setStaticB(byte x) { unsafe.putByte(base, offset, x); }
short getStaticS() { return unsafe.getShort(base, offset); }
void setStaticS(short x) { unsafe.putShort(base, offset, x); }
char getStaticC() { return unsafe.getChar(base, offset); }
void setStaticC(char x) { unsafe.putChar(base, offset, x); }
V getStaticL() { return (V) unsafe.getObject(base, offset); }
void setStaticL(V x) { unsafe.putObject(base, offset, x); }
static String fname(Class<?> vclass, boolean isSetter, boolean isStatic) {
String stem;
if (!isStatic)
stem = (!isSetter ? "getField" : "setField");
else
stem = (!isSetter ? "getStatic" : "setStatic");
return stem + Wrapper.basicTypeChar(vclass);
}
static MethodType ftype(Class<?> cclass, Class<?> vclass, boolean isSetter, boolean isStatic) {
MethodType type;
if (!isStatic) {
if (!isSetter)
return MethodType.methodType(vclass, cclass);
else
return MethodType.methodType(void.class, cclass, vclass);
} else {
if (!isSetter)
return MethodType.methodType(vclass);
else
return MethodType.methodType(void.class, vclass);
}
}
static MethodHandle fhandle(Class<?> cclass, Class<?> vclass, boolean isSetter, boolean isStatic) {
String name = FieldAccessor.fname(vclass, isSetter, isStatic);
if (cclass.isPrimitive()) throw newIllegalArgumentException("primitive "+cclass);
Class<?> ecclass = Object.class; //erase this type
Class<?> evclass = vclass;
if (!evclass.isPrimitive()) evclass = Object.class;
MethodType type = FieldAccessor.ftype(ecclass, evclass, isSetter, isStatic);
MethodHandle mh;
try {
mh = IMPL_LOOKUP.findVirtual(FieldAccessor.class, name, type);
} catch (NoAccessException ee) {
Error e = new InternalError("name,type="+name+type);
e.initCause(ee);
throw e;
}
if (evclass != vclass || (!isStatic && ecclass != cclass)) {
MethodType strongType = FieldAccessor.ftype(cclass, vclass, isSetter, isStatic);
strongType = strongType.insertParameterTypes(0, FieldAccessor.class);
mh = MethodHandles.convertArguments(mh, strongType);
}
return mh;
}
/// Support for array element access
static final HashMap<Class<?>, MethodHandle[]> ARRAY_CACHE =
new HashMap<Class<?>, MethodHandle[]>();
// FIXME: Cache on the classes themselves, not here.
static boolean doCache(Class<?> elemClass) {
if (elemClass.isPrimitive()) return true;
ClassLoader cl = elemClass.getClassLoader();
return cl == null || cl == ClassLoader.getSystemClassLoader();
}
static int getElementI(int[] a, int i) { return a[i]; }
static void setElementI(int[] a, int i, int x) { a[i] = x; }
static long getElementJ(long[] a, int i) { return a[i]; }
static void setElementJ(long[] a, int i, long x) { a[i] = x; }
static float getElementF(float[] a, int i) { return a[i]; }
static void setElementF(float[] a, int i, float x) { a[i] = x; }
static double getElementD(double[] a, int i) { return a[i]; }
static void setElementD(double[] a, int i, double x) { a[i] = x; }
static boolean getElementZ(boolean[] a, int i) { return a[i]; }
static void setElementZ(boolean[] a, int i, boolean x) { a[i] = x; }
static byte getElementB(byte[] a, int i) { return a[i]; }
static void setElementB(byte[] a, int i, byte x) { a[i] = x; }
static short getElementS(short[] a, int i) { return a[i]; }
static void setElementS(short[] a, int i, short x) { a[i] = x; }
static char getElementC(char[] a, int i) { return a[i]; }
static void setElementC(char[] a, int i, char x) { a[i] = x; }
static Object getElementL(Object[] a, int i) { return a[i]; }
static void setElementL(Object[] a, int i, Object x) { a[i] = x; }
static <V> V getElementL(Class<V[]> aclass, V[] a, int i) { return aclass.cast(a)[i]; }
static <V> void setElementL(Class<V[]> aclass, V[] a, int i, V x) { aclass.cast(a)[i] = x; }
static String aname(Class<?> aclass, boolean isSetter) {
Class<?> vclass = aclass.getComponentType();
if (vclass == null) throw new IllegalArgumentException();
return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(vclass);
}
static MethodType atype(Class<?> aclass, boolean isSetter) {
Class<?> vclass = aclass.getComponentType();
if (!isSetter)
return MethodType.methodType(vclass, aclass, int.class);
else
return MethodType.methodType(void.class, aclass, int.class, vclass);
}
static MethodHandle ahandle(Class<?> aclass, boolean isSetter) {
Class<?> vclass = aclass.getComponentType();
String name = FieldAccessor.aname(aclass, isSetter);
Class<?> caclass = null;
if (!vclass.isPrimitive() && vclass != Object.class) {
caclass = aclass;
aclass = Object[].class;
vclass = Object.class;
}
MethodType type = FieldAccessor.atype(aclass, isSetter);
if (caclass != null)
type = type.insertParameterTypes(0, Class.class);
MethodHandle mh;
try {
mh = IMPL_LOOKUP.findStatic(FieldAccessor.class, name, type);
} catch (NoAccessException ee) {
Error e = new InternalError("name,type="+name+type);
e.initCause(ee);
throw e;
}
if (caclass != null) {
MethodType strongType = FieldAccessor.atype(caclass, isSetter);
mh = MethodHandles.insertArguments(mh, 0, caclass);
mh = MethodHandles.convertArguments(mh, strongType);
}
return mh;
}
} }
/** Bind a predetermined first argument to the given direct method handle. /** Bind a predetermined first argument to the given direct method handle.
...@@ -203,8 +437,11 @@ public abstract class MethodHandleImpl { ...@@ -203,8 +437,11 @@ public abstract class MethodHandleImpl {
if (info instanceof DirectMethodHandle) { if (info instanceof DirectMethodHandle) {
DirectMethodHandle dmh = (DirectMethodHandle) info; DirectMethodHandle dmh = (DirectMethodHandle) info;
if (receiver == null || if (receiver == null ||
dmh.type().parameterType(0).isAssignableFrom(receiver.getClass())) dmh.type().parameterType(0).isAssignableFrom(receiver.getClass())) {
target = dmh; MethodHandle bmh = new BoundMethodHandle(dmh, receiver, 0);
MethodType newType = target.type().dropParameterTypes(0, 1);
return convertArguments(token, bmh, newType, bmh.type(), null);
}
} }
} }
if (target instanceof DirectMethodHandle) if (target instanceof DirectMethodHandle)
...@@ -223,7 +460,7 @@ public abstract class MethodHandleImpl { ...@@ -223,7 +460,7 @@ public abstract class MethodHandleImpl {
MethodHandle bindArgument(Access token, MethodHandle bindArgument(Access token,
MethodHandle target, int argnum, Object receiver) { MethodHandle target, int argnum, Object receiver) {
Access.check(token); Access.check(token);
throw new UnsupportedOperationException("NYI"); return new BoundMethodHandle(target, receiver, argnum);
} }
public static MethodHandle convertArguments(Access token, public static MethodHandle convertArguments(Access token,
...@@ -232,6 +469,189 @@ public abstract class MethodHandleImpl { ...@@ -232,6 +469,189 @@ public abstract class MethodHandleImpl {
MethodType oldType, MethodType oldType,
int[] permutationOrNull) { int[] permutationOrNull) {
Access.check(token); Access.check(token);
if (permutationOrNull != null) {
int outargs = oldType.parameterCount(), inargs = newType.parameterCount();
if (permutationOrNull.length != outargs)
throw newIllegalArgumentException("wrong number of arguments in permutation");
// Make the individual outgoing argument types match up first.
Class<?>[] callTypeArgs = new Class<?>[outargs];
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);
assert(target != null);
oldType = target.type();
List<Integer> goal = new ArrayList<Integer>(); // i*TOKEN
List<Integer> state = new ArrayList<Integer>(); // i*TOKEN
List<Integer> drops = new ArrayList<Integer>(); // not tokens
List<Integer> dups = new ArrayList<Integer>(); // not tokens
final int TOKEN = 10; // to mark items which are symbolic only
// state represents the argument values coming into target
for (int i = 0; i < outargs; i++) {
state.add(permutationOrNull[i] * TOKEN);
}
// goal represents the desired state
for (int i = 0; i < inargs; i++) {
if (state.contains(i * TOKEN)) {
goal.add(i * TOKEN);
} else {
// adapter must initially drop all unused arguments
drops.add(i);
}
}
// detect duplications
while (state.size() > goal.size()) {
for (int i2 = 0; i2 < state.size(); i2++) {
int arg1 = state.get(i2);
int i1 = state.indexOf(arg1);
if (i1 != i2) {
// found duplicate occurrence at i2
int arg2 = (inargs++) * TOKEN;
state.set(i2, arg2);
dups.add(goal.indexOf(arg1));
goal.add(arg2);
}
}
}
assert(state.size() == goal.size());
int size = goal.size();
while (!state.equals(goal)) {
// Look for a maximal sequence of adjacent misplaced arguments,
// and try to rotate them into place.
int bestRotArg = -10 * TOKEN, bestRotLen = 0;
int thisRotArg = -10 * TOKEN, thisRotLen = 0;
for (int i = 0; i < size; i++) {
int arg = state.get(i);
// Does this argument match the current run?
if (arg == thisRotArg + TOKEN) {
thisRotArg = arg;
thisRotLen += 1;
if (bestRotLen < thisRotLen) {
bestRotLen = thisRotLen;
bestRotArg = thisRotArg;
}
} else {
// The old sequence (if any) stops here.
thisRotLen = 0;
thisRotArg = -10 * TOKEN;
// But maybe a new one starts here also.
int wantArg = goal.get(i);
final int MAX_ARG_ROTATION = AdapterMethodHandle.MAX_ARG_ROTATION;
if (arg != wantArg &&
arg >= wantArg - TOKEN * MAX_ARG_ROTATION &&
arg <= wantArg + TOKEN * MAX_ARG_ROTATION) {
thisRotArg = arg;
thisRotLen = 1;
}
}
}
if (bestRotLen >= 2) {
// Do a rotation if it can improve argument positioning
// by at least 2 arguments. This is not always optimal,
// but it seems to catch common cases.
int dstEnd = state.indexOf(bestRotArg);
int srcEnd = goal.indexOf(bestRotArg);
int rotBy = dstEnd - srcEnd;
int dstBeg = dstEnd - (bestRotLen - 1);
int srcBeg = srcEnd - (bestRotLen - 1);
assert((dstEnd | dstBeg | srcEnd | srcBeg) >= 0); // no negs
// Make a span which covers both source and destination.
int rotBeg = Math.min(dstBeg, srcBeg);
int rotEnd = Math.max(dstEnd, srcEnd);
int score = 0;
for (int i = rotBeg; i <= rotEnd; i++) {
if ((int)state.get(i) != (int)goal.get(i))
score += 1;
}
List<Integer> rotSpan = state.subList(rotBeg, rotEnd+1);
Collections.rotate(rotSpan, -rotBy); // reverse direction
for (int i = rotBeg; i <= rotEnd; i++) {
if ((int)state.get(i) != (int)goal.get(i))
score -= 1;
}
if (score >= 2) {
// Improved at least two argument positions. Do it.
List<Class<?>> ptypes = Arrays.asList(oldType.parameterArray());
Collections.rotate(ptypes.subList(rotBeg, rotEnd+1), -rotBy);
MethodType rotType = MethodType.methodType(oldType.returnType(), ptypes);
MethodHandle nextTarget
= AdapterMethodHandle.makeRotateArguments(token, rotType, target,
rotBeg, rotSpan.size(), rotBy);
if (nextTarget != null) {
//System.out.println("Rot: "+rotSpan+" by "+rotBy);
target = nextTarget;
oldType = rotType;
continue;
}
}
// Else de-rotate, and drop through to the swap-fest.
Collections.rotate(rotSpan, rotBy);
}
// Now swap like the wind!
List<Class<?>> ptypes = Arrays.asList(oldType.parameterArray());
for (int i = 0; i < size; i++) {
// What argument do I want here?
int arg = goal.get(i);
if (arg != state.get(i)) {
// Where is it now?
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);
if (target == null) throw newIllegalArgumentException("cannot swap");
assert(target.type() == swapType);
oldType = swapType;
Collections.swap(state, i, j);
}
}
// One pass of swapping must finish the job.
assert(state.equals(goal));
}
while (!dups.isEmpty()) {
// Grab a contiguous trailing sequence of dups.
int grab = dups.size() - 1;
int dupArgPos = dups.get(grab), dupArgCount = 1;
while (grab - 1 >= 0) {
int dup0 = dups.get(grab - 1);
if (dup0 != dupArgPos - 1) break;
dupArgPos -= 1;
dupArgCount += 1;
grab -= 1;
}
//if (dupArgCount > 1) System.out.println("Dup: "+dups.subList(grab, dups.size()));
dups.subList(grab, dups.size()).clear();
// In the new target type drop that many args from the tail:
List<Class<?>> 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);
if (target == null)
throw newIllegalArgumentException("cannot dup");
oldType = target.type();
}
while (!drops.isEmpty()) {
// Grab a contiguous initial sequence of drops.
int dropArgPos = drops.get(0), dropArgCount = 1;
while (dropArgCount < drops.size()) {
int drop1 = drops.get(dropArgCount);
if (drop1 != dropArgPos + dropArgCount) break;
dropArgCount += 1;
}
//if (dropArgCount > 1) System.out.println("Drop: "+drops.subList(0, dropArgCount));
drops.subList(0, dropArgCount).clear();
List<Class<?>> dropTypes = newType.parameterList()
.subList(dropArgPos, dropArgPos + dropArgCount);
MethodType dropType = oldType.insertParameterTypes(dropArgPos, dropTypes);
target = AdapterMethodHandle.makeDropArguments(token, dropType, target, dropArgPos, dropArgCount);
if (target == null) throw newIllegalArgumentException("cannot drop");
oldType = target.type();
}
}
if (newType == oldType)
return target;
if (oldType.parameterCount() != newType.parameterCount())
throw newIllegalArgumentException("mismatched parameter count");
MethodHandle res = AdapterMethodHandle.makePairwiseConvert(token, newType, target); MethodHandle res = AdapterMethodHandle.makePairwiseConvert(token, newType, target);
if (res != null) if (res != null)
return res; return res;
...@@ -241,7 +661,7 @@ public abstract class MethodHandleImpl { ...@@ -241,7 +661,7 @@ public abstract class MethodHandleImpl {
// Use a heavier method: Convert all the arguments to Object, // Use a heavier method: Convert all the arguments to Object,
// then back to the desired types. We might have to use Java-based // then back to the desired types. We might have to use Java-based
// method handles to do this. // method handles to do this.
MethodType objType = MethodType.makeGeneric(argc); MethodType objType = MethodType.genericMethodType(argc);
MethodHandle objTarget = AdapterMethodHandle.makePairwiseConvert(token, objType, target); MethodHandle objTarget = AdapterMethodHandle.makePairwiseConvert(token, objType, target);
if (objTarget == null) if (objTarget == null)
objTarget = FromGeneric.make(target); objTarget = FromGeneric.make(target);
...@@ -272,83 +692,386 @@ public abstract class MethodHandleImpl { ...@@ -272,83 +692,386 @@ public abstract class MethodHandleImpl {
Class<?>[] ptypes = oldType.parameterArray(); Class<?>[] ptypes = oldType.parameterArray();
for (int i = 0; i < spreadCount; i++) for (int i = 0; i < spreadCount; i++)
ptypes[spreadArg + i] = VerifyType.spreadArgElementType(spreadType, i); ptypes[spreadArg + i] = VerifyType.spreadArgElementType(spreadType, i);
MethodType midType = MethodType.make(newType.returnType(), ptypes); MethodType midType = MethodType.methodType(newType.returnType(), ptypes);
// after spreading, some arguments may need further conversion // after spreading, some arguments may need further conversion
target = convertArguments(token, target, midType, oldType, null); MethodHandle target2 = convertArguments(token, target, midType, oldType, null);
if (target == null) if (target2 == null)
throw new UnsupportedOperationException("NYI: convert "+midType+" =calls=> "+oldType); throw new UnsupportedOperationException("NYI: convert "+midType+" =calls=> "+oldType);
res = AdapterMethodHandle.makeSpreadArguments(token, newType, target, spreadArgType, spreadArg, spreadCount); res = AdapterMethodHandle.makeSpreadArguments(token, newType, target2, spreadArgType, spreadArg, spreadCount);
if (res != null)
return res;
res = SpreadGeneric.make(target2, spreadCount);
if (res != null)
res = convertArguments(token, res, newType, res.type(), null);
return res; return res;
} }
public static MethodHandle collectArguments(Access token, public static MethodHandle collectArguments(Access token,
MethodHandle target, MethodHandle target,
MethodType newType, MethodType newType,
int collectArg) { int collectArg,
if (collectArg > 0) MethodHandle collector) {
throw new UnsupportedOperationException("NYI"); MethodType oldType = target.type(); // (a...,c)=>r
throw new UnsupportedOperationException("NYI"); if (collector == null) {
int numCollect = newType.parameterCount() - oldType.parameterCount() + 1;
collector = ValueConversions.varargsArray(numCollect);
}
// newType // (a..., b...)=>r
MethodType colType = collector.type(); // (b...)=>c
// oldType // (a..., b...)=>r
assert(newType.parameterCount() == collectArg + colType.parameterCount());
assert(oldType.parameterCount() == collectArg + 1);
MethodHandle gtarget = convertArguments(token, target, oldType.generic(), oldType, null);
MethodHandle gcollector = convertArguments(token, collector, colType.generic(), colType, null);
if (gtarget == null || gcollector == null) return null;
MethodHandle gresult = FilterGeneric.makeArgumentCollector(gcollector, gtarget);
MethodHandle result = convertArguments(token, gresult, newType, gresult.type(), null);
return result;
} }
public static MethodHandle filterArgument(Access token,
MethodHandle target,
int pos,
MethodHandle filter) {
Access.check(token);
MethodType ttype = target.type(), gttype = ttype.generic();
if (ttype != gttype) {
target = convertArguments(token, target, gttype, ttype, null);
ttype = gttype;
}
MethodType ftype = filter.type(), gftype = ftype.generic();
if (ftype.parameterCount() != 1)
throw new InternalError();
if (ftype != gftype) {
filter = convertArguments(token, filter, gftype, ftype, null);
ftype = gftype;
}
if (ftype == ttype) {
// simple unary case
return FilterOneArgument.make(filter, target);
}
return FilterGeneric.makeArgumentFilter(pos, filter, target);
}
public static MethodHandle foldArguments(Access token,
MethodHandle target,
MethodType newType,
MethodHandle combiner) {
Access.check(token);
MethodType oldType = target.type();
MethodType ctype = combiner.type();
MethodHandle gtarget = convertArguments(token, target, oldType.generic(), oldType, null);
MethodHandle gcombiner = convertArguments(token, combiner, ctype.generic(), ctype, null);
if (gtarget == null || gcombiner == null) return null;
MethodHandle gresult = FilterGeneric.makeArgumentFolder(gcombiner, gtarget);
MethodHandle result = convertArguments(token, gresult, newType, gresult.type(), null);
return result;
}
public static public static
MethodHandle dropArguments(Access token, MethodHandle target, MethodHandle dropArguments(Access token, MethodHandle target,
MethodType newType, int argnum) { MethodType newType, int argnum) {
Access.check(token); Access.check(token);
int drops = newType.parameterCount() - target.type().parameterCount();
MethodHandle res = AdapterMethodHandle.makeDropArguments(token, newType, target, argnum, drops);
if (res != null)
return res;
throw new UnsupportedOperationException("NYI"); throw new UnsupportedOperationException("NYI");
} }
private static class GuardWithTest extends JavaMethodHandle {
private final MethodHandle test, target, fallback;
public GuardWithTest(MethodHandle test, MethodHandle target, MethodHandle fallback) {
this(INVOKES[target.type().parameterCount()], test, target, fallback);
}
public GuardWithTest(MethodHandle invoker,
MethodHandle test, MethodHandle target, MethodHandle fallback) {
super(invoker);
this.test = test;
this.target = target;
this.fallback = fallback;
}
@Override
public String toString() {
return target.toString();
}
private Object invoke_V(Object... av) throws Throwable {
if (test.<boolean>invoke(av))
return target.<Object>invoke(av);
return fallback.<Object>invoke(av);
}
private Object invoke_L0() throws Throwable {
if (test.<boolean>invoke())
return target.<Object>invoke();
return fallback.<Object>invoke();
}
private Object invoke_L1(Object a0) throws Throwable {
if (test.<boolean>invoke(a0))
return target.<Object>invoke(a0);
return fallback.<Object>invoke(a0);
}
private Object invoke_L2(Object a0, Object a1) throws Throwable {
if (test.<boolean>invoke(a0, a1))
return target.<Object>invoke(a0, a1);
return fallback.<Object>invoke(a0, a1);
}
private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
if (test.<boolean>invoke(a0, a1, a2))
return target.<Object>invoke(a0, a1, a2);
return fallback.<Object>invoke(a0, a1, a2);
}
private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
if (test.<boolean>invoke(a0, a1, a2, a3))
return target.<Object>invoke(a0, a1, a2, a3);
return fallback.<Object>invoke(a0, a1, a2, a3);
}
private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
if (test.<boolean>invoke(a0, a1, a2, a3, a4))
return target.<Object>invoke(a0, a1, a2, a3, a4);
return fallback.<Object>invoke(a0, a1, a2, a3, a4);
}
private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
if (test.<boolean>invoke(a0, a1, a2, a3, a4, a5))
return target.<Object>invoke(a0, a1, a2, a3, a4, a5);
return fallback.<Object>invoke(a0, a1, a2, a3, a4, a5);
}
private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
if (test.<boolean>invoke(a0, a1, a2, a3, a4, a5, a6))
return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6);
return fallback.<Object>invoke(a0, a1, a2, a3, a4, a5, a6);
}
private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
if (test.<boolean>invoke(a0, a1, a2, a3, a4, a5, a6, a7))
return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7);
return fallback.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7);
}
static MethodHandle[] makeInvokes() {
ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>();
MethodHandles.Lookup lookup = IMPL_LOOKUP;
for (;;) {
int nargs = invokes.size();
String name = "invoke_L"+nargs;
MethodHandle invoke = null;
try {
invoke = lookup.findVirtual(GuardWithTest.class, name, MethodType.genericMethodType(nargs));
} catch (NoAccessException ex) {
}
if (invoke == null) break;
invokes.add(invoke);
}
assert(invokes.size() == 9); // current number of methods
return invokes.toArray(new MethodHandle[0]);
};
static final MethodHandle[] INVOKES = makeInvokes();
// For testing use this:
//static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
static final MethodHandle VARARGS_INVOKE;
static {
try {
VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithTest.class, "invoke_V", MethodType.genericMethodType(0, true));
} catch (NoAccessException ex) {
throw new InternalError("");
}
}
}
public static public static
MethodHandle makeGuardWithTest(Access token, MethodHandle makeGuardWithTest(Access token,
final MethodHandle test, MethodHandle test,
final MethodHandle target, MethodHandle target,
final MethodHandle fallback) { MethodHandle fallback) {
Access.check(token); Access.check(token);
// %%% This is just a sketch. It needs to be de-boxed.
// Adjust the handles to accept varargs lists.
MethodType type = target.type(); MethodType type = target.type();
Class<?> rtype = type.returnType(); int nargs = type.parameterCount();
if (type.parameterCount() != 1 || type.parameterType(0).isPrimitive()) { if (nargs < GuardWithTest.INVOKES.length) {
MethodType vatestType = MethodType.make(boolean.class, Object[].class); MethodType gtype = type.generic();
MethodType vatargetType = MethodType.make(rtype, Object[].class); MethodHandle gtest = convertArguments(token, test, gtype.changeReturnType(boolean.class), test.type(), null);
MethodHandle vaguard = makeGuardWithTest(token, MethodHandle gtarget = convertArguments(token, target, gtype, type, null);
MethodHandles.spreadArguments(test, vatestType), MethodHandle gfallback = convertArguments(token, fallback, gtype, type, null);
MethodHandles.spreadArguments(target, vatargetType), if (gtest == null || gtarget == null || gfallback == null) return null;
MethodHandles.spreadArguments(fallback, vatargetType)); MethodHandle gguard = new GuardWithTest(gtest, gtarget, gfallback);
return MethodHandles.collectArguments(vaguard, type); return convertArguments(token, gguard, type, gtype, null);
} } else {
if (rtype.isPrimitive()) { MethodType gtype = MethodType.genericMethodType(0, true);
MethodType boxtype = type.changeReturnType(Object.class); MethodHandle gtest = spreadArguments(token, test, gtype.changeReturnType(boolean.class), 0);
MethodHandle boxguard = makeGuardWithTest(token, MethodHandle gtarget = spreadArguments(token, target, gtype, 0);
test, MethodHandle gfallback = spreadArguments(token, fallback, gtype, 0);
MethodHandles.convertArguments(target, boxtype), MethodHandle gguard = new GuardWithTest(GuardWithTest.VARARGS_INVOKE, gtest, gtarget, gfallback);
MethodHandles.convertArguments(fallback, boxtype)); if (gtest == null || gtarget == null || gfallback == null) return null;
return MethodHandles.convertArguments(boxguard, type); return collectArguments(token, gguard, type, 0, null);
} }
// Got here? Reduced calling sequence to Object(Object). }
class Guarder {
Object invoke(Object x) { private static class GuardWithCatch extends JavaMethodHandle {
// If javac supports MethodHandle.invoke directly: private final MethodHandle target;
//z = vatest.invoke<boolean>(arguments); private final Class<? extends Throwable> exType;
// If javac does not support direct MH.invoke calls: private final MethodHandle catcher;
boolean z = (Boolean) MethodHandles.invoke_1(test, x); public GuardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) {
MethodHandle mh = (z ? target : fallback); this(INVOKES[target.type().parameterCount()], target, exType, catcher);
return MethodHandles.invoke_1(mh, x); }
public GuardWithCatch(MethodHandle invoker,
MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) {
super(invoker);
this.target = target;
this.exType = exType;
this.catcher = catcher;
}
@Override
public String toString() {
return target.toString();
}
private Object invoke_V(Object... av) throws Throwable {
try {
return target.<Object>invoke(av);
} catch (Throwable t) {
if (!exType.isInstance(t)) throw t;
return catcher.<Object>invoke(t, av);
} }
MethodHandle handle() { }
MethodType invokeType = MethodType.makeGeneric(0, true); private Object invoke_L0() throws Throwable {
MethodHandle vh = IMPL_LOOKUP.bind(this, "invoke", invokeType); try {
return MethodHandles.collectArguments(vh, target.type()); return target.<Object>invoke();
} catch (Throwable t) {
if (!exType.isInstance(t)) throw t;
return catcher.<Object>invoke(t);
}
}
private Object invoke_L1(Object a0) throws Throwable {
try {
return target.<Object>invoke(a0);
} catch (Throwable t) {
if (!exType.isInstance(t)) throw t;
return catcher.<Object>invoke(t, a0);
} }
} }
return new Guarder().handle(); private Object invoke_L2(Object a0, Object a1) throws Throwable {
try {
return target.<Object>invoke(a0, a1);
} catch (Throwable t) {
if (!exType.isInstance(t)) throw t;
return catcher.<Object>invoke(t, a0, a1);
}
}
private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
try {
return target.<Object>invoke(a0, a1, a2);
} catch (Throwable t) {
if (!exType.isInstance(t)) throw t;
return catcher.<Object>invoke(t, a0, a1, a2);
}
}
private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
try {
return target.<Object>invoke(a0, a1, a2, a3);
} catch (Throwable t) {
if (!exType.isInstance(t)) throw t;
return catcher.<Object>invoke(t, a0, a1, a2, a3);
}
}
private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
try {
return target.<Object>invoke(a0, a1, a2, a3, a4);
} catch (Throwable t) {
if (!exType.isInstance(t)) throw t;
return catcher.<Object>invoke(t, a0, a1, a2, a3, a4);
}
}
private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
try {
return target.<Object>invoke(a0, a1, a2, a3, a4, a5);
} catch (Throwable t) {
if (!exType.isInstance(t)) throw t;
return catcher.<Object>invoke(t, a0, a1, a2, a3, a4, a5);
}
}
private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
try {
return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6);
} catch (Throwable t) {
if (!exType.isInstance(t)) throw t;
return catcher.<Object>invoke(t, a0, a1, a2, a3, a4, a5, a6);
}
}
private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
try {
return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7);
} catch (Throwable t) {
if (!exType.isInstance(t)) throw t;
return catcher.<Object>invoke(t, a0, a1, a2, a3, a4, a5, a6, a7);
}
}
static MethodHandle[] makeInvokes() {
ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>();
MethodHandles.Lookup lookup = IMPL_LOOKUP;
for (;;) {
int nargs = invokes.size();
String name = "invoke_L"+nargs;
MethodHandle invoke = null;
try {
invoke = lookup.findVirtual(GuardWithCatch.class, name, MethodType.genericMethodType(nargs));
} catch (NoAccessException ex) {
}
if (invoke == null) break;
invokes.add(invoke);
}
assert(invokes.size() == 9); // current number of methods
return invokes.toArray(new MethodHandle[0]);
};
static final MethodHandle[] INVOKES = makeInvokes();
// For testing use this:
//static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
static final MethodHandle VARARGS_INVOKE;
static {
try {
VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true));
} catch (NoAccessException ex) {
throw new InternalError("");
}
}
}
public static
MethodHandle makeGuardWithCatch(Access token,
MethodHandle target,
Class<? extends Throwable> exType,
MethodHandle catcher) {
Access.check(token);
MethodType type = target.type();
MethodType ctype = catcher.type();
int nargs = type.parameterCount();
if (nargs < GuardWithCatch.INVOKES.length) {
MethodType gtype = type.generic();
MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
MethodHandle gtarget = convertArguments(token, target, gtype, type, null);
MethodHandle gcatcher = convertArguments(token, catcher, gcatchType, ctype, null);
MethodHandle gguard = new GuardWithCatch(gtarget, exType, gcatcher);
if (gtarget == null || gcatcher == null || gguard == null) return null;
return convertArguments(token, gguard, type, gtype, null);
} else {
MethodType gtype = MethodType.genericMethodType(0, true);
MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
MethodHandle gtarget = spreadArguments(token, target, gtype, 0);
MethodHandle gcatcher = spreadArguments(token, catcher, gcatchType, 1);
MethodHandle gguard = new GuardWithCatch(GuardWithCatch.VARARGS_INVOKE, gtarget, exType, gcatcher);
if (gtarget == null || gcatcher == null || gguard == null) return null;
return collectArguments(token, gguard, type, 0, null);
}
} }
public static public static
MethodHandle combineArguments(Access token, MethodHandle target, MethodHandle checker, int pos) { MethodHandle throwException(Access token, MethodType type) {
Access.check(token); Access.check(token);
throw new UnsupportedOperationException("Not yet implemented"); return AdapterMethodHandle.makeRetypeRaw(token, type, THROW_EXCEPTION);
} }
protected static String basicToString(MethodHandle target) { static final MethodHandle THROW_EXCEPTION
= IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException",
MethodType.methodType(Empty.class, Throwable.class));
static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
public static String getNameString(Access token, MethodHandle target) {
Access.check(token);
MemberName name = null; MemberName name = null;
if (target != null) if (target != null)
name = MethodHandleNatives.getMethodName(target); name = MethodHandleNatives.getMethodName(target);
...@@ -357,17 +1080,30 @@ public abstract class MethodHandleImpl { ...@@ -357,17 +1080,30 @@ public abstract class MethodHandleImpl {
return name.getName(); return name.getName();
} }
protected static String addTypeString(MethodHandle target, String name) { public static String addTypeString(MethodHandle target) {
if (target == null) return name; if (target == null) return "null";
return name+target.type(); return target.toString() + target.type();
} }
static RuntimeException newIllegalArgumentException(String string) {
return new IllegalArgumentException(string); public static void checkSpreadArgument(Object av, int n) {
if (av == null ? n != 0 : ((Object[])av).length != n)
throw newIllegalArgumentException("Array is not of length "+n);
} }
@Override public static void raiseException(int code, Object actual, Object required) {
public String toString() { String message;
MethodHandle self = (MethodHandle) this; // disregard the identity of the actual object, if it is not a class:
return addTypeString(self, basicToString(self)); if (!(actual instanceof Class) && !(actual instanceof MethodType))
actual = actual.getClass();
if (actual != null)
message = "required "+required+" but encountered "+actual;
else
message = "required "+required;
switch (code) {
case 192: // checkcast
throw new ClassCastException(message);
default:
throw new InternalError("unexpected code "+code+": "+message);
}
} }
} }
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
package sun.dyn; package sun.dyn;
import java.dyn.CallSite;
import java.dyn.MethodHandle; import java.dyn.MethodHandle;
import java.dyn.MethodType; import java.dyn.MethodType;
import java.lang.reflect.AccessibleObject; import java.lang.reflect.AccessibleObject;
...@@ -60,7 +61,7 @@ class MethodHandleNatives { ...@@ -60,7 +61,7 @@ class MethodHandleNatives {
static native void init(MethodType self); static native void init(MethodType self);
/** Tell the JVM that we need to change the target of an invokedynamic. */ /** Tell the JVM that we need to change the target of an invokedynamic. */
static native void linkCallSite(CallSiteImpl site, MethodHandle target); static native void linkCallSite(CallSite site, MethodHandle target);
/** Fetch the vmtarget field. /** Fetch the vmtarget field.
* It will be sanitized as necessary to avoid exposing non-Java references. * It will be sanitized as necessary to avoid exposing non-Java references.
...@@ -84,8 +85,7 @@ class MethodHandleNatives { ...@@ -84,8 +85,7 @@ class MethodHandleNatives {
} }
/** Fetch the target of this method handle. /** Fetch the target of this method handle.
* If it directly targets a method, return a tuple of method info. * If it directly targets a method, return a MemberName for the method.
* The info is of the form new Object[]{defclass, name, sig, refclass}.
* If it is chained to another method handle, return that handle. * If it is chained to another method handle, return that handle.
*/ */
static Object getTargetInfo(MethodHandle self) { static Object getTargetInfo(MethodHandle self) {
...@@ -123,7 +123,7 @@ class MethodHandleNatives { ...@@ -123,7 +123,7 @@ class MethodHandleNatives {
registerNatives(); registerNatives();
JVM_SUPPORT_ = true; JVM_SUPPORT_ = true;
JVM_PUSH_LIMIT_ = getConstant(Constants.GC_JVM_PUSH_LIMIT); JVM_PUSH_LIMIT_ = getConstant(Constants.GC_JVM_PUSH_LIMIT);
JVM_STACK_MOVE_UNIT_ = getConstant(Constants.GC_JVM_STACK_MOVE_LIMIT); JVM_STACK_MOVE_UNIT_ = getConstant(Constants.GC_JVM_STACK_MOVE_UNIT);
//sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init"); //sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init");
} catch (UnsatisfiedLinkError ee) { } catch (UnsatisfiedLinkError ee) {
// ignore; if we use init() methods later we'll see linkage errors // ignore; if we use init() methods later we'll see linkage errors
...@@ -149,7 +149,7 @@ class MethodHandleNatives { ...@@ -149,7 +149,7 @@ class MethodHandleNatives {
// MethodHandleImpl // MethodHandleImpl
static final int // for getConstant static final int // for getConstant
GC_JVM_PUSH_LIMIT = 0, GC_JVM_PUSH_LIMIT = 0,
GC_JVM_STACK_MOVE_LIMIT = 1; GC_JVM_STACK_MOVE_UNIT = 1;
static final int static final int
ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method) ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method)
ETF_DIRECT_HANDLE = 1, // ultimate method handle (will be a DMH, may be self) ETF_DIRECT_HANDLE = 1, // ultimate method handle (will be a DMH, may be self)
...@@ -178,19 +178,20 @@ class MethodHandleNatives { ...@@ -178,19 +178,20 @@ class MethodHandleNatives {
*/ */
static final int static final int
OP_RETYPE_ONLY = 0x0, // no argument changes; straight retype OP_RETYPE_ONLY = 0x0, // no argument changes; straight retype
OP_CHECK_CAST = 0x1, // ref-to-ref conversion; requires a Class argument OP_RETYPE_RAW = 0x1, // no argument changes; straight retype
OP_PRIM_TO_PRIM = 0x2, // converts from one primitive to another OP_CHECK_CAST = 0x2, // ref-to-ref conversion; requires a Class argument
OP_REF_TO_PRIM = 0x3, // unboxes a wrapper to produce a primitive OP_PRIM_TO_PRIM = 0x3, // converts from one primitive to another
OP_PRIM_TO_REF = 0x4, // boxes a primitive into a wrapper (NYI) OP_REF_TO_PRIM = 0x4, // unboxes a wrapper to produce a primitive
OP_SWAP_ARGS = 0x5, // swap arguments (vminfo is 2nd arg) OP_PRIM_TO_REF = 0x5, // boxes a primitive into a wrapper (NYI)
OP_ROT_ARGS = 0x6, // rotate arguments (vminfo is displaced arg) OP_SWAP_ARGS = 0x6, // swap arguments (vminfo is 2nd arg)
OP_DUP_ARGS = 0x7, // duplicates one or more arguments (at TOS) OP_ROT_ARGS = 0x7, // rotate arguments (vminfo is displaced arg)
OP_DROP_ARGS = 0x8, // remove one or more argument slots OP_DUP_ARGS = 0x8, // duplicates one or more arguments (at TOS)
OP_COLLECT_ARGS = 0x9, // combine one or more arguments into a varargs (NYI) OP_DROP_ARGS = 0x9, // remove one or more argument slots
OP_SPREAD_ARGS = 0xA, // expand in place a varargs array (of known size) OP_COLLECT_ARGS = 0xA, // combine one or more arguments into a varargs (NYI)
OP_FLYBY = 0xB, // operate first on reified argument list (NYI) OP_SPREAD_ARGS = 0xB, // expand in place a varargs array (of known size)
OP_RICOCHET = 0xC, // run an adapter chain on the return value (NYI) OP_FLYBY = 0xC, // operate first on reified argument list (NYI)
CONV_OP_LIMIT = 0xD; // limit of CONV_OP enumeration OP_RICOCHET = 0xD, // run an adapter chain on the return value (NYI)
CONV_OP_LIMIT = 0xE; // limit of CONV_OP enumeration
/** Shift and mask values for decoding the AMH.conversion field. /** Shift and mask values for decoding the AMH.conversion field.
* These numbers are shared with the JVM for creating AMHs. * These numbers are shared with the JVM for creating AMHs.
*/ */
...@@ -209,6 +210,7 @@ class MethodHandleNatives { ...@@ -209,6 +210,7 @@ class MethodHandleNatives {
// TODO: The following expression should be replaced by // TODO: The following expression should be replaced by
// a JVM query. // a JVM query.
((1<<OP_RETYPE_ONLY) ((1<<OP_RETYPE_ONLY)
|(1<<OP_RETYPE_RAW)
|(1<<OP_CHECK_CAST) |(1<<OP_CHECK_CAST)
|(1<<OP_PRIM_TO_PRIM) |(1<<OP_PRIM_TO_PRIM)
|(1<<OP_REF_TO_PRIM) |(1<<OP_REF_TO_PRIM)
...@@ -216,6 +218,7 @@ class MethodHandleNatives { ...@@ -216,6 +218,7 @@ class MethodHandleNatives {
|(1<<OP_ROT_ARGS) |(1<<OP_ROT_ARGS)
|(1<<OP_DUP_ARGS) |(1<<OP_DUP_ARGS)
|(1<<OP_DROP_ARGS) |(1<<OP_DROP_ARGS)
//|(1<<OP_SPREAD_ARGS) // FIXME: Check JVM assembly code.
); );
/** /**
......
...@@ -27,6 +27,7 @@ package sun.dyn; ...@@ -27,6 +27,7 @@ package sun.dyn;
import java.dyn.*; import java.dyn.*;
import sun.dyn.util.Wrapper; import sun.dyn.util.Wrapper;
import static sun.dyn.MemberName.newIllegalArgumentException;
/** /**
* Shared information for a group of method types, which differ * Shared information for a group of method types, which differ
...@@ -56,8 +57,8 @@ public class MethodTypeImpl { ...@@ -56,8 +57,8 @@ public class MethodTypeImpl {
// Cached adapter information: // Cached adapter information:
/*lazy*/ ToGeneric toGeneric; // convert cs. with prims to w/o /*lazy*/ ToGeneric toGeneric; // convert cs. with prims to w/o
/*lazy*/ FromGeneric fromGeneric; // convert cs. w/o prims to with /*lazy*/ FromGeneric fromGeneric; // convert cs. w/o prims to with
/*lazy*/ SpreadGeneric[] spreadGeneric; // expand one argument to many
/*lazy*/ FilterGeneric filterGeneric; // convert argument(s) on the fly /*lazy*/ FilterGeneric filterGeneric; // convert argument(s) on the fly
///*lazy*/ Invokers invokers; // cache of handy higher-order adapters
public MethodType erasedType() { public MethodType erasedType() {
return erasedType; return erasedType;
...@@ -68,7 +69,7 @@ public class MethodTypeImpl { ...@@ -68,7 +69,7 @@ public class MethodTypeImpl {
} }
/** Access methods for the internals of MethodType, supplied to /** Access methods for the internals of MethodType, supplied to
* MethodTypeForm as a trusted agent. * MethodTypeImpl as a trusted agent.
*/ */
static public interface MethodTypeFriend { static public interface MethodTypeFriend {
Class<?>[] ptypes(MethodType mt); Class<?>[] ptypes(MethodType mt);
...@@ -150,7 +151,7 @@ public class MethodTypeImpl { ...@@ -150,7 +151,7 @@ public class MethodTypeImpl {
this.argToSlotTable = argToSlotTab; this.argToSlotTable = argToSlotTab;
this.slotToArgTable = slotToArgTab; this.slotToArgTable = slotToArgTab;
if (pslotCount >= 256) throw new IllegalArgumentException("too many arguments"); if (pslotCount >= 256) throw newIllegalArgumentException("too many arguments");
// send a few bits down to the JVM: // send a few bits down to the JVM:
this.vmslots = parameterSlotCount(); this.vmslots = parameterSlotCount();
...@@ -378,10 +379,10 @@ public class MethodTypeImpl { ...@@ -378,10 +379,10 @@ public class MethodTypeImpl {
static MethodTypeImpl findForm(MethodType mt) { static MethodTypeImpl findForm(MethodType mt) {
MethodType erased = canonicalize(mt, ERASE, ERASE); MethodType erased = canonicalize(mt, ERASE, ERASE);
if (erased == null) { if (erased == null) {
// It is already erased. Make a new MethodTypeForm. // It is already erased. Make a new MethodTypeImpl.
return METHOD_TYPE_FRIEND.newMethodTypeForm(mt); return METHOD_TYPE_FRIEND.newMethodTypeForm(mt);
} else { } else {
// Share the MethodTypeForm with the erased version. // Share the MethodTypeImpl with the erased version.
return METHOD_TYPE_FRIEND.form(erased); return METHOD_TYPE_FRIEND.form(erased);
} }
} }
......
/*
* Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.dyn;
import java.dyn.JavaMethodHandle;
import java.dyn.MethodHandle;
import java.dyn.MethodHandles;
import java.dyn.MethodType;
import java.dyn.NoAccessException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import sun.dyn.util.ValueConversions;
import static sun.dyn.MemberName.newIllegalArgumentException;
/**
* Generic spread adapter.
* Expands a final argument into multiple (zero or more) arguments, keeping the others the same.
* @author jrose
*/
class SpreadGeneric {
// type for the outgoing call
private final MethodType targetType;
// number of arguments to spread
private final int spreadCount;
// prototype adapter (clone and customize for each new target!)
private final Adapter adapter;
// entry point for adapter (Adapter mh, a...) => ...
private final MethodHandle entryPoint;
/** Compute and cache information common to all spreading adapters
* that accept calls of the given (generic) type.
*/
private SpreadGeneric(MethodType targetType, int spreadCount) {
assert(targetType == targetType.generic());
this.targetType = targetType;
this.spreadCount = spreadCount;
// the target invoker will generally need casts on reference arguments
MethodHandle[] ep = { null };
Adapter ad = findAdapter(this, ep);
if (ad != null) {
this.adapter = ad;
this.entryPoint = ep[0];
return;
}
this.adapter = buildAdapterFromBytecodes(targetType, spreadCount, ep);
this.entryPoint = ep[0];
}
/** From targetType remove the last spreadCount arguments, and instead
* append a simple Object argument.
*/
static MethodType preSpreadType(MethodType targetType, int spreadCount) {
@SuppressWarnings("unchecked")
ArrayList<Class<?>> params = new ArrayList(targetType.parameterList());
int outargs = params.size();
params.subList(outargs - spreadCount, outargs).clear();
params.add(Object.class);
return MethodType.methodType(targetType.returnType(), params);
}
MethodHandle makeInstance(MethodHandle target) {
MethodType type = target.type();
if (type != targetType) {
throw new UnsupportedOperationException("NYI type="+type);
}
return adapter.makeInstance(this, target);
}
/** Build an adapter of the given generic type, which invokes typedTarget
* on the incoming arguments, after unboxing as necessary.
* The return value is boxed if necessary.
* @param genericType the required type of the result
* @param typedTarget the target
* @return an adapter method handle
*/
public static MethodHandle make(MethodHandle target, int spreadCount) {
MethodType type = target.type();
MethodType gtype = type.generic();
if (type == gtype) {
return SpreadGeneric.of(type, spreadCount).makeInstance(target);
} else {
MethodHandle gtarget = FromGeneric.make(target);
assert(gtarget.type() == gtype);
MethodHandle gspread = SpreadGeneric.of(gtype, spreadCount).makeInstance(gtarget);
return ToGeneric.make(preSpreadType(type, spreadCount), gspread);
}
}
/** Return the adapter information for this type's erasure. */
static SpreadGeneric of(MethodType targetType, int spreadCount) {
if (targetType != targetType.generic())
throw new UnsupportedOperationException("NYI type="+targetType);
MethodTypeImpl form = MethodTypeImpl.of(targetType);
int outcount = form.parameterCount();
assert(spreadCount <= outcount);
SpreadGeneric[] spreadGens = form.spreadGeneric;
if (spreadGens == null)
form.spreadGeneric = spreadGens = new SpreadGeneric[outcount+1];
SpreadGeneric spreadGen = spreadGens[spreadCount];
if (spreadGen == null)
spreadGens[spreadCount] = spreadGen = new SpreadGeneric(form.erasedType(), spreadCount);
return spreadGen;
}
public String toString() {
return getClass().getSimpleName()+targetType+"["+spreadCount+"]";
}
// This mini-api is called from an Adapter to manage the spread.
/** A check/coercion that happens once before any selections. */
protected Object check(Object av, int n) {
MethodHandleImpl.checkSpreadArgument(av, n);
return av;
}
/** The selection operator for spreading; note that it takes Object not Object[]. */
protected Object select(Object av, int n) {
return ((Object[])av)[n];
}
/*
protected int select_I(Object av, int n) {
// maybe return ((int[])select)[n]
throw new UnsupportedOperationException("subclass resp.");
}
protected int select_J(Object av, int n) {
// maybe return ((long[])select)[n]
throw new UnsupportedOperationException("subclass resp.");
}
// */
/* Create an adapter that handles spreading calls for the given type. */
static Adapter findAdapter(SpreadGeneric outer, MethodHandle[] ep) {
MethodType targetType = outer.targetType;
int spreadCount = outer.spreadCount;
int outargs = targetType.parameterCount();
int inargs = outargs - spreadCount;
if (inargs < 0) return null;
MethodType entryType = MethodType.genericMethodType(inargs + 1); // 1 for av
String cname1 = "S" + outargs;
String[] cnames = { cname1 };
String iname = "invoke_S"+spreadCount;
// e.g., D5I2, D5, L5I2, L5; invoke_D5
for (String cname : cnames) {
Class<? extends Adapter> acls = Adapter.findSubClass(cname);
if (acls == null) continue;
// see if it has the required invoke method
MethodHandle entryPoint = null;
try {
entryPoint = MethodHandleImpl.IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
} catch (NoAccessException ex) {
}
if (entryPoint == null) continue;
Constructor<? extends Adapter> ctor = null;
try {
ctor = acls.getDeclaredConstructor(SpreadGeneric.class);
} catch (NoSuchMethodException ex) {
} catch (SecurityException ex) {
}
if (ctor == null) continue;
try {
// Produce an instance configured as a prototype.
Adapter ad = ctor.newInstance(outer);
ep[0] = entryPoint;
return ad;
} catch (IllegalArgumentException ex) {
} catch (InvocationTargetException wex) {
Throwable ex = wex.getTargetException();
if (ex instanceof Error) throw (Error)ex;
if (ex instanceof RuntimeException) throw (RuntimeException)ex;
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
}
}
return null;
}
static Adapter buildAdapterFromBytecodes(MethodType targetType,
int spreadCount, MethodHandle[] ep) {
throw new UnsupportedOperationException("NYI");
}
/**
* This adapter takes some untyped arguments, and returns an untyped result.
* Internally, it applies the invoker to the target, which causes the
* objects to be unboxed; the result is a raw type in L/I/J/F/D.
* This result is passed to convert, which is responsible for
* converting the raw result into a boxed object.
* The invoker is kept separate from the target because it can be
* generated once per type erasure family, and reused across adapters.
*/
static abstract class Adapter extends JavaMethodHandle {
/*
* class X<<R,int M,int N>> extends Adapter {
* (Object**N)=>R target;
* static int S = N-M;
* Object invoke(Object**M a, Object v) = target(a..., v[0]...v[S-1]);
* }
*/
protected final SpreadGeneric outer;
protected final MethodHandle target; // (any**N) => R
@Override
public String toString() {
return target.toString();
}
static final MethodHandle NO_ENTRY = ValueConversions.identity();
protected boolean isPrototype() { return target == null; }
protected Adapter(SpreadGeneric outer) {
super(NO_ENTRY);
this.outer = outer;
this.target = null;
assert(isPrototype());
}
protected Adapter(SpreadGeneric outer, MethodHandle target) {
super(outer.entryPoint);
this.outer = outer;
this.target = target;
}
/** Make a copy of self, with new fields. */
protected abstract Adapter makeInstance(SpreadGeneric outer, MethodHandle target);
// { return new ThisType(outer, target); }
protected Object check(Object av, int n) {
return outer.check(av, n);
}
protected Object select(Object av, int n) {
return outer.select(av, n);
}
static private final String CLASS_PREFIX; // "sun.dyn.SpreadGeneric$"
static {
String aname = Adapter.class.getName();
String sname = Adapter.class.getSimpleName();
if (!aname.endsWith(sname)) throw new InternalError();
CLASS_PREFIX = aname.substring(0, aname.length() - sname.length());
}
/** Find a sibing class of Adapter. */
static Class<? extends Adapter> findSubClass(String name) {
String cname = Adapter.CLASS_PREFIX + name;
try {
return Class.forName(cname).asSubclass(Adapter.class);
} catch (ClassNotFoundException ex) {
return null;
} catch (ClassCastException ex) {
return null;
}
}
}
/* generated classes follow this pattern:
static class xS2 extends Adapter {
protected xS2(SpreadGeneric outer) { super(outer); } // to build prototype
protected xS2(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
protected xS2 makeInstance(SpreadGeneric outer, MethodHandle t) { return new xS2(outer, t); }
protected Object invoke_S0(Object a0, Object a1, Object av) throws Throwable { av = super.check(av,0);
return target.<Object>invoke(a0, a1)); }
protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av,1);
return target.<Object>invoke(a0,
super.select(av,0)); }
protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av,1);
return target.<Object>invoke(
super.select(av,0), super.select(av,1)); }
}
// */
/*
: SHELL; n=SpreadGeneric; cp -p $n.java $n.java-; sed < $n.java- > $n.java+ -e '/{{*{{/,/}}*}}/w /tmp/genclasses.java' -e '/}}*}}/q'; (cd /tmp; javac -d . genclasses.java; java -cp . genclasses) >> $n.java+; echo '}' >> $n.java+; mv $n.java+ $n.java; mv $n.java- $n.java~
//{{{
import java.util.*;
class genclasses {
static String[][] TEMPLATES = { {
"@for@ N=0..10",
" //@each-cat@",
" static class @cat@ extends Adapter {",
" protected @cat@(SpreadGeneric outer) { super(outer); } // to build prototype",
" protected @cat@(SpreadGeneric outer, MethodHandle t) { super(outer, t); }",
" protected @cat@ makeInstance(SpreadGeneric outer, MethodHandle t) { return new @cat@(outer, t); }",
" protected Object invoke_S0(@Tvav,@Object av) throws Throwable { av = super.check(av, 0);",
" return target.<Object>invoke(@av@); }",
" //@each-S@",
" protected Object invoke_S@S@(@Tvav,@Object av) throws Throwable { av = super.check(av, @S@);",
" return target.<Object>invoke(@av,@@sv@); }",
" //@end-S@",
" }",
} };
static final String NEWLINE_INDENT = "\n ";
enum VAR {
cat, N, S, av, av_, Tvav_, sv;
public final String pattern = "@"+toString().replace('_','.')+"@";
public String binding = toString();
static void makeBindings(boolean topLevel, int outargs, int spread) {
int inargs = outargs - spread;
VAR.cat.binding = "S"+outargs;
VAR.N.binding = String.valueOf(outargs); // outgoing arg count
VAR.S.binding = String.valueOf(spread); // spread count
String[] av = new String[inargs];
String[] Tvav = new String[inargs];
for (int i = 0; i < inargs; i++) {
av[i] = arg(i);
Tvav[i] = param("Object", av[i]);
}
VAR.av.binding = comma(av);
VAR.av_.binding = comma(av, ", ");
VAR.Tvav_.binding = comma(Tvav, ", ");
String[] sv = new String[spread];
for (int i = 0; i < spread; i++) {
String spc = "";
if (i % 4 == 0) spc = NEWLINE_INDENT;
sv[i] = spc+"super.select(av,"+i+")";
}
VAR.sv.binding = comma(sv);
}
static String arg(int i) { return "a"+i; }
static String param(String t, String a) { return t+" "+a; }
static String comma(String[] v) { return comma(v, ""); }
static String comma(String[] v, String sep) {
if (v.length == 0) return "";
String res = v[0];
for (int i = 1; i < v.length; i++) res += ", "+v[i];
return res + sep;
}
static String transform(String string) {
for (VAR var : values())
string = string.replaceAll(var.pattern, var.binding);
return string;
}
}
static String[] stringsIn(String[] strings, int beg, int end) {
return Arrays.copyOfRange(strings, beg, Math.min(end, strings.length));
}
static String[] stringsBefore(String[] strings, int pos) {
return stringsIn(strings, 0, pos);
}
static String[] stringsAfter(String[] strings, int pos) {
return stringsIn(strings, pos, strings.length);
}
static int indexAfter(String[] strings, int pos, String tag) {
return Math.min(indexBefore(strings, pos, tag) + 1, strings.length);
}
static int indexBefore(String[] strings, int pos, String tag) {
for (int i = pos, end = strings.length; ; i++) {
if (i == end || strings[i].endsWith(tag)) return i;
}
}
static int MIN_ARITY, MAX_ARITY;
public static void main(String... av) {
for (String[] template : TEMPLATES) {
int forLinesLimit = indexBefore(template, 0, "@each-cat@");
String[] forLines = stringsBefore(template, forLinesLimit);
template = stringsAfter(template, forLinesLimit);
for (String forLine : forLines)
expandTemplate(forLine, template);
}
}
static void expandTemplate(String forLine, String[] template) {
String[] params = forLine.split("[^0-9]+");
if (params[0].length() == 0) params = stringsAfter(params, 1);
System.out.println("//params="+Arrays.asList(params));
int pcur = 0;
MIN_ARITY = Integer.valueOf(params[pcur++]);
MAX_ARITY = Integer.valueOf(params[pcur++]);
if (pcur != params.length) throw new RuntimeException("bad extra param: "+forLine);
for (int outargs = MIN_ARITY; outargs <= MAX_ARITY; outargs++) {
expandTemplate(template, true, outargs, 0);
}
}
static void expandTemplate(String[] template, boolean topLevel, int outargs, int spread) {
VAR.makeBindings(topLevel, outargs, spread);
for (int i = 0; i < template.length; i++) {
String line = template[i];
if (line.endsWith("@each-cat@")) {
// ignore
} else if (line.endsWith("@each-S@")) {
int blockEnd = indexAfter(template, i, "@end-S@");
String[] block = stringsIn(template, i+1, blockEnd-1);
for (int spread1 = spread+1; spread1 <= outargs; spread1++)
expandTemplate(block, false, outargs, spread1);
VAR.makeBindings(topLevel, outargs, spread);
i = blockEnd-1; continue;
} else {
System.out.println(VAR.transform(line));
}
}
}
}
//}}} */
//params=[0, 10]
static class S0 extends Adapter {
protected S0(SpreadGeneric outer) { super(outer); } // to build prototype
protected S0(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
protected S0 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S0(outer, t); }
protected Object invoke_S0(Object av) throws Throwable { av = super.check(av, 0);
return target.<Object>invoke(); }
}
static class S1 extends Adapter {
protected S1(SpreadGeneric outer) { super(outer); } // to build prototype
protected S1(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
protected S1 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S1(outer, t); }
protected Object invoke_S0(Object a0, Object av) throws Throwable { av = super.check(av, 0);
return target.<Object>invoke(a0); }
protected Object invoke_S1(Object av) throws Throwable { av = super.check(av, 1);
return target.<Object>invoke(
super.select(av,0)); }
}
static class S2 extends Adapter {
protected S2(SpreadGeneric outer) { super(outer); } // to build prototype
protected S2(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
protected S2 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S2(outer, t); }
protected Object invoke_S0(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 0);
return target.<Object>invoke(a0, a1); }
protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av, 1);
return target.<Object>invoke(a0,
super.select(av,0)); }
protected Object invoke_S2(Object av) throws Throwable { av = super.check(av, 2);
return target.<Object>invoke(
super.select(av,0), super.select(av,1)); }
}
static class S3 extends Adapter {
protected S3(SpreadGeneric outer) { super(outer); } // to build prototype
protected S3(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
protected S3 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S3(outer, t); }
protected Object invoke_S0(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 0);
return target.<Object>invoke(a0, a1, a2); }
protected Object invoke_S1(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 1);
return target.<Object>invoke(a0, a1,
super.select(av,0)); }
protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av, 2);
return target.<Object>invoke(a0,
super.select(av,0), super.select(av,1)); }
protected Object invoke_S3(Object av) throws Throwable { av = super.check(av, 3);
return target.<Object>invoke(
super.select(av,0), super.select(av,1), super.select(av,2)); }
}
static class S4 extends Adapter {
protected S4(SpreadGeneric outer) { super(outer); } // to build prototype
protected S4(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
protected S4 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S4(outer, t); }
protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 0);
return target.<Object>invoke(a0, a1, a2, a3); }
protected Object invoke_S1(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 1);
return target.<Object>invoke(a0, a1, a2,
super.select(av,0)); }
protected Object invoke_S2(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 2);
return target.<Object>invoke(a0, a1,
super.select(av,0), super.select(av,1)); }
protected Object invoke_S3(Object a0, Object av) throws Throwable { av = super.check(av, 3);
return target.<Object>invoke(a0,
super.select(av,0), super.select(av,1), super.select(av,2)); }
protected Object invoke_S4(Object av) throws Throwable { av = super.check(av, 4);
return target.<Object>invoke(
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
}
static class S5 extends Adapter {
protected S5(SpreadGeneric outer) { super(outer); } // to build prototype
protected S5(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
protected S5 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S5(outer, t); }
protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 0);
return target.<Object>invoke(a0, a1, a2, a3, a4); }
protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 1);
return target.<Object>invoke(a0, a1, a2, a3,
super.select(av,0)); }
protected Object invoke_S2(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 2);
return target.<Object>invoke(a0, a1, a2,
super.select(av,0), super.select(av,1)); }
protected Object invoke_S3(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 3);
return target.<Object>invoke(a0, a1,
super.select(av,0), super.select(av,1), super.select(av,2)); }
protected Object invoke_S4(Object a0, Object av) throws Throwable { av = super.check(av, 4);
return target.<Object>invoke(a0,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
protected Object invoke_S5(Object av) throws Throwable { av = super.check(av, 5);
return target.<Object>invoke(
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4)); }
}
static class S6 extends Adapter {
protected S6(SpreadGeneric outer) { super(outer); } // to build prototype
protected S6(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
protected S6 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S6(outer, t); }
protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 0);
return target.<Object>invoke(a0, a1, a2, a3, a4, a5); }
protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 1);
return target.<Object>invoke(a0, a1, a2, a3, a4,
super.select(av,0)); }
protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 2);
return target.<Object>invoke(a0, a1, a2, a3,
super.select(av,0), super.select(av,1)); }
protected Object invoke_S3(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 3);
return target.<Object>invoke(a0, a1, a2,
super.select(av,0), super.select(av,1), super.select(av,2)); }
protected Object invoke_S4(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 4);
return target.<Object>invoke(a0, a1,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
protected Object invoke_S5(Object a0, Object av) throws Throwable { av = super.check(av, 5);
return target.<Object>invoke(a0,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4)); }
protected Object invoke_S6(Object av) throws Throwable { av = super.check(av, 6);
return target.<Object>invoke(
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4), super.select(av,5)); }
}
static class S7 extends Adapter {
protected S7(SpreadGeneric outer) { super(outer); } // to build prototype
protected S7(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
protected S7 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S7(outer, t); }
protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 0);
return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6); }
protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 1);
return target.<Object>invoke(a0, a1, a2, a3, a4, a5,
super.select(av,0)); }
protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 2);
return target.<Object>invoke(a0, a1, a2, a3, a4,
super.select(av,0), super.select(av,1)); }
protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 3);
return target.<Object>invoke(a0, a1, a2, a3,
super.select(av,0), super.select(av,1), super.select(av,2)); }
protected Object invoke_S4(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 4);
return target.<Object>invoke(a0, a1, a2,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
protected Object invoke_S5(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 5);
return target.<Object>invoke(a0, a1,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4)); }
protected Object invoke_S6(Object a0, Object av) throws Throwable { av = super.check(av, 6);
return target.<Object>invoke(a0,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4), super.select(av,5)); }
protected Object invoke_S7(Object av) throws Throwable { av = super.check(av, 7);
return target.<Object>invoke(
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4), super.select(av,5), super.select(av,6)); }
}
static class S8 extends Adapter {
protected S8(SpreadGeneric outer) { super(outer); } // to build prototype
protected S8(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
protected S8 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S8(outer, t); }
protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 0);
return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7); }
protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 1);
return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6,
super.select(av,0)); }
protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 2);
return target.<Object>invoke(a0, a1, a2, a3, a4, a5,
super.select(av,0), super.select(av,1)); }
protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 3);
return target.<Object>invoke(a0, a1, a2, a3, a4,
super.select(av,0), super.select(av,1), super.select(av,2)); }
protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 4);
return target.<Object>invoke(a0, a1, a2, a3,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
protected Object invoke_S5(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 5);
return target.<Object>invoke(a0, a1, a2,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4)); }
protected Object invoke_S6(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 6);
return target.<Object>invoke(a0, a1,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4), super.select(av,5)); }
protected Object invoke_S7(Object a0, Object av) throws Throwable { av = super.check(av, 7);
return target.<Object>invoke(a0,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4), super.select(av,5), super.select(av,6)); }
protected Object invoke_S8(Object av) throws Throwable { av = super.check(av, 8);
return target.<Object>invoke(
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); }
}
static class S9 extends Adapter {
protected S9(SpreadGeneric outer) { super(outer); } // to build prototype
protected S9(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
protected S9 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S9(outer, t); }
protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object av) throws Throwable { av = super.check(av, 0);
return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 1);
return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7,
super.select(av,0)); }
protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 2);
return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6,
super.select(av,0), super.select(av,1)); }
protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 3);
return target.<Object>invoke(a0, a1, a2, a3, a4, a5,
super.select(av,0), super.select(av,1), super.select(av,2)); }
protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 4);
return target.<Object>invoke(a0, a1, a2, a3, a4,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
protected Object invoke_S5(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 5);
return target.<Object>invoke(a0, a1, a2, a3,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4)); }
protected Object invoke_S6(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 6);
return target.<Object>invoke(a0, a1, a2,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4), super.select(av,5)); }
protected Object invoke_S7(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 7);
return target.<Object>invoke(a0, a1,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4), super.select(av,5), super.select(av,6)); }
protected Object invoke_S8(Object a0, Object av) throws Throwable { av = super.check(av, 8);
return target.<Object>invoke(a0,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); }
protected Object invoke_S9(Object av) throws Throwable { av = super.check(av, 9);
return target.<Object>invoke(
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7),
super.select(av,8)); }
}
static class S10 extends Adapter {
protected S10(SpreadGeneric outer) { super(outer); } // to build prototype
protected S10(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
protected S10 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S10(outer, t); }
protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9, Object av) throws Throwable { av = super.check(av, 0);
return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object av) throws Throwable { av = super.check(av, 1);
return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8,
super.select(av,0)); }
protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 2);
return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7,
super.select(av,0), super.select(av,1)); }
protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 3);
return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6,
super.select(av,0), super.select(av,1), super.select(av,2)); }
protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 4);
return target.<Object>invoke(a0, a1, a2, a3, a4, a5,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
protected Object invoke_S5(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 5);
return target.<Object>invoke(a0, a1, a2, a3, a4,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4)); }
protected Object invoke_S6(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 6);
return target.<Object>invoke(a0, a1, a2, a3,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4), super.select(av,5)); }
protected Object invoke_S7(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 7);
return target.<Object>invoke(a0, a1, a2,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4), super.select(av,5), super.select(av,6)); }
protected Object invoke_S8(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 8);
return target.<Object>invoke(a0, a1,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); }
protected Object invoke_S9(Object a0, Object av) throws Throwable { av = super.check(av, 9);
return target.<Object>invoke(a0,
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7),
super.select(av,8)); }
protected Object invoke_S10(Object av) throws Throwable { av = super.check(av, 10);
return target.<Object>invoke(
super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7),
super.select(av,8), super.select(av,9)); }
}
}
...@@ -34,6 +34,7 @@ import java.lang.reflect.Constructor; ...@@ -34,6 +34,7 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import sun.dyn.util.ValueConversions; import sun.dyn.util.ValueConversions;
import sun.dyn.util.Wrapper; import sun.dyn.util.Wrapper;
import static sun.dyn.MemberName.newIllegalArgumentException;
/** /**
* Adapters which mediate between incoming calls which are not generic * Adapters which mediate between incoming calls which are not generic
...@@ -68,7 +69,7 @@ class ToGeneric { ...@@ -68,7 +69,7 @@ class ToGeneric {
// conversion which unboxes a primitive return value // conversion which unboxes a primitive return value
private final MethodHandle returnConversion; private final MethodHandle returnConversion;
/** Compute and cache information common to all collecting adapters /** Compute and cache information common to all generifying (boxing) adapters
* that implement members of the erasure-family of the given erased type. * that implement members of the erasure-family of the given erased type.
*/ */
private ToGeneric(MethodType entryType) { private ToGeneric(MethodType entryType) {
...@@ -111,30 +112,48 @@ class ToGeneric { ...@@ -111,30 +112,48 @@ class ToGeneric {
// primitive arguments according to their "raw" types int/long // primitive arguments according to their "raw" types int/long
MethodType intsAtEnd = MethodTypeImpl.of(primsAtEnd).primsAsInts(); MethodType intsAtEnd = MethodTypeImpl.of(primsAtEnd).primsAsInts();
ad = findAdapter(rawEntryTypeInit = intsAtEnd); ad = findAdapter(rawEntryTypeInit = intsAtEnd);
if (ad == null) { MethodHandle rawEntryPoint;
if (ad != null) {
rawEntryPoint = ad.prototypeEntryPoint();
} else {
// Perhaps the adapter is available only for longs. // Perhaps the adapter is available only for longs.
// If so, we can use it, but there will have to be a little // If so, we can use it, but there will have to be a little
// more stack motion on each call. // more stack motion on each call.
MethodType longsAtEnd = MethodTypeImpl.of(primsAtEnd).primsAsLongs(); MethodType longsAtEnd = MethodTypeImpl.of(primsAtEnd).primsAsLongs();
ad = findAdapter(rawEntryTypeInit = longsAtEnd); ad = findAdapter(rawEntryTypeInit = longsAtEnd);
if (ad == null) { if (ad != null) {
MethodType eptWithLongs = longsAtEnd.insertParameterTypes(0, ad.getClass());
MethodType eptWithInts = intsAtEnd.insertParameterTypes(0, ad.getClass());
rawEntryPoint = ad.prototypeEntryPoint();
MethodType midType = eptWithLongs; // will change longs to ints
for (int i = 0, nargs = midType.parameterCount(); i < nargs; i++) {
if (midType.parameterType(i) != eptWithInts.parameterType(i)) {
assert(midType.parameterType(i) == long.class);
assert(eptWithInts.parameterType(i) == int.class);
MethodType nextType = midType.changeParameterType(i, int.class);
rawEntryPoint = MethodHandle.convertArguments(Access.TOKEN,
rawEntryPoint, nextType, midType, null);
midType = nextType;
}
}
assert(midType == eptWithInts);
} else {
// If there is no statically compiled adapter, // If there is no statically compiled adapter,
// build one by means of dynamic bytecode generation. // build one by means of dynamic bytecode generation.
ad = buildAdapterFromBytecodes(rawEntryTypeInit = intsAtEnd); ad = buildAdapterFromBytecodes(rawEntryTypeInit = intsAtEnd);
rawEntryPoint = ad.prototypeEntryPoint();
} }
} }
MethodHandle rawEntryPoint = ad.prototypeEntryPoint(); MethodType tepType = entryType.insertParameterTypes(0, ad.getClass());
MethodType tepType = entryType.insertParameterType(0, ad.getClass());
this.entryPoint = this.entryPoint =
AdapterMethodHandle.makeRawRetypeOnly(Access.TOKEN, tepType, rawEntryPoint); AdapterMethodHandle.makeRetypeRaw(Access.TOKEN, tepType, rawEntryPoint);
if (this.entryPoint == null) if (this.entryPoint == null)
throw new UnsupportedOperationException("cannot retype to "+entryType throw new UnsupportedOperationException("cannot retype to "+entryType
+" from "+rawEntryPoint.type().dropParameterType(0)); +" from "+rawEntryPoint.type().dropParameterTypes(0, 1));
this.returnConversion = computeReturnConversion(entryType, rawEntryTypeInit, false); this.returnConversion = computeReturnConversion(entryType, rawEntryTypeInit, false);
this.rawEntryType = rawEntryTypeInit; this.rawEntryType = rawEntryTypeInit;
this.adapter = ad; this.adapter = ad;
this.invoker = makeRawArgumentFilter(invoker0, this.invoker = makeRawArgumentFilter(invoker0, rawEntryTypeInit, entryType);
rawEntryPoint.type().dropParameterType(0), entryType);
} }
/** A generic argument list will be created by a call of type 'raw'. /** A generic argument list will be created by a call of type 'raw'.
...@@ -157,8 +176,8 @@ class ToGeneric { ...@@ -157,8 +176,8 @@ class ToGeneric {
if (filteredInvoker == null) throw new UnsupportedOperationException("NYI"); if (filteredInvoker == null) throw new UnsupportedOperationException("NYI");
} }
MethodHandle reboxer = ValueConversions.rebox(dst, false); MethodHandle reboxer = ValueConversions.rebox(dst, false);
FilterGeneric gen = new FilterGeneric(filteredInvoker.type(), (short)(1+i), (short)1, 'R'); filteredInvoker = FilterGeneric.makeArgumentFilter(1+i, reboxer, filteredInvoker);
filteredInvoker = gen.makeInstance(reboxer, filteredInvoker); if (filteredInvoker == null) throw new InternalError();
} }
if (filteredInvoker == null) return invoker; if (filteredInvoker == null) return invoker;
return AdapterMethodHandle.makeRetypeOnly(Access.TOKEN, invoker.type(), filteredInvoker); return AdapterMethodHandle.makeRetypeOnly(Access.TOKEN, invoker.type(), filteredInvoker);
...@@ -209,9 +228,9 @@ class ToGeneric { ...@@ -209,9 +228,9 @@ class ToGeneric {
if (convert == null) if (convert == null)
convert = computeReturnConversion(type, rawEntryType, true); convert = computeReturnConversion(type, rawEntryType, true);
// retype erased reference arguments (the cast makes it safe to do this) // retype erased reference arguments (the cast makes it safe to do this)
MethodType tepType = type.insertParameterType(0, adapter.getClass()); MethodType tepType = type.insertParameterTypes(0, adapter.getClass());
MethodHandle typedEntryPoint = MethodHandle typedEntryPoint =
AdapterMethodHandle.makeRawRetypeOnly(Access.TOKEN, tepType, entryPoint); AdapterMethodHandle.makeRetypeRaw(Access.TOKEN, tepType, entryPoint);
return adapter.makeInstance(typedEntryPoint, invoker, convert, genericTarget); return adapter.makeInstance(typedEntryPoint, invoker, convert, genericTarget);
} }
...@@ -225,7 +244,7 @@ class ToGeneric { ...@@ -225,7 +244,7 @@ class ToGeneric {
public static MethodHandle make(MethodType type, MethodHandle genericTarget) { public static MethodHandle make(MethodType type, MethodHandle genericTarget) {
MethodType gtype = genericTarget.type(); MethodType gtype = genericTarget.type();
if (type.generic() != gtype) if (type.generic() != gtype)
throw new IllegalArgumentException(); throw newIllegalArgumentException("type must be generic");
if (type == gtype) return genericTarget; if (type == gtype) return genericTarget;
return ToGeneric.of(type).makeInstance(type, genericTarget); return ToGeneric.of(type).makeInstance(type, genericTarget);
} }
...@@ -283,7 +302,10 @@ class ToGeneric { ...@@ -283,7 +302,10 @@ class ToGeneric {
try { try {
return ctor.newInstance(entryPoint); return ctor.newInstance(entryPoint);
} catch (IllegalArgumentException ex) { } catch (IllegalArgumentException ex) {
} catch (InvocationTargetException ex) { } catch (InvocationTargetException wex) {
Throwable ex = wex.getTargetException();
if (ex instanceof Error) throw (Error)ex;
if (ex instanceof RuntimeException) throw (RuntimeException)ex;
} catch (InstantiationException ex) { } catch (InstantiationException ex) {
} catch (IllegalAccessException ex) { } catch (IllegalAccessException ex) {
} }
...@@ -317,6 +339,11 @@ class ToGeneric { ...@@ -317,6 +339,11 @@ class ToGeneric {
protected final MethodHandle target; // Object... -> Object protected final MethodHandle target; // Object... -> Object
protected final MethodHandle convert; // Object -> R protected final MethodHandle convert; // Object -> R
@Override
public String toString() {
return target.toString();
}
protected boolean isPrototype() { return target == null; } protected boolean isPrototype() { return target == null; }
/* Prototype constructor. */ /* Prototype constructor. */
protected Adapter(MethodHandle entryPoint) { protected Adapter(MethodHandle entryPoint) {
...@@ -344,33 +371,33 @@ class ToGeneric { ...@@ -344,33 +371,33 @@ class ToGeneric {
// { return new ThisType(entryPoint, convert, target); } // { return new ThisType(entryPoint, convert, target); }
// Code to run when the arguments (<= 4) have all been boxed. // Code to run when the arguments (<= 4) have all been boxed.
protected Object target() { return invoker.<Object>invoke(target); } protected Object target() throws Throwable { return invoker.<Object>invoke(target); }
protected Object target(Object a0) { return invoker.<Object>invoke(target, a0); } protected Object target(Object a0) throws Throwable { return invoker.<Object>invoke(target, a0); }
protected Object target(Object a0, Object a1) protected Object target(Object a0, Object a1)
{ return invoker.<Object>invoke(target, a0, a1); } throws Throwable { return invoker.<Object>invoke(target, a0, a1); }
protected Object target(Object a0, Object a1, Object a2) protected Object target(Object a0, Object a1, Object a2)
{ return invoker.<Object>invoke(target, a0, a1, a2); } throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2); }
protected Object target(Object a0, Object a1, Object a2, Object a3) protected Object target(Object a0, Object a1, Object a2, Object a3)
{ return invoker.<Object>invoke(target, a0, a1, a2, a3); } throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, a3); }
/* /*
protected Object target_0(Object... av) { return invoker.<Object>invoke(target, av); } protected Object target_0(Object... av) throws Throwable { return invoker.<Object>invoke(target, av); }
protected Object target_1(Object a0, Object... av) protected Object target_1(Object a0, Object... av)
{ return invoker.<Object>invoke(target, a0, (Object)av); } throws Throwable { return invoker.<Object>invoke(target, a0, (Object)av); }
protected Object target_2(Object a0, Object a1, Object... av) protected Object target_2(Object a0, Object a1, Object... av)
{ return invoker.<Object>invoke(target, a0, a1, (Object)av); } throws Throwable { return invoker.<Object>invoke(target, a0, a1, (Object)av); }
protected Object target_3(Object a0, Object a1, Object a2, Object... av) protected Object target_3(Object a0, Object a1, Object a2, Object... av)
{ return invoker.<Object>invoke(target, a0, a1, a2, (Object)av); } throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, (Object)av); }
protected Object target_4(Object a0, Object a1, Object a2, Object a3, Object... av) protected Object target_4(Object a0, Object a1, Object a2, Object a3, Object... av)
{ return invoker.<Object>invoke(target, a0, a1, a2, a3, (Object)av); } throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, a3, (Object)av); }
// */ // */
// (For more than 4 arguments, generate the code in the adapter itself.) // (For more than 4 arguments, generate the code in the adapter itself.)
// Code to run when the generic target has finished and produced a value. // Code to run when the generic target has finished and produced a value.
protected Object return_L(Object res) { return convert.<Object>invoke(res); } protected Object return_L(Object res) throws Throwable { return convert.<Object>invoke(res); }
protected int return_I(Object res) { return convert.<int >invoke(res); } protected int return_I(Object res) throws Throwable { return convert.<int >invoke(res); }
protected long return_J(Object res) { return convert.<long >invoke(res); } protected long return_J(Object res) throws Throwable { return convert.<long >invoke(res); }
protected float return_F(Object res) { return convert.<float >invoke(res); } protected float return_F(Object res) throws Throwable { return convert.<float >invoke(res); }
protected double return_D(Object res) { return convert.<double>invoke(res); } protected double return_D(Object res) throws Throwable { return convert.<double>invoke(res); }
static private final String CLASS_PREFIX; // "sun.dyn.ToGeneric$" static private final String CLASS_PREFIX; // "sun.dyn.ToGeneric$"
static { static {
...@@ -397,25 +424,25 @@ class ToGeneric { ...@@ -397,25 +424,25 @@ class ToGeneric {
protected A1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); } protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); }
protected Object target(Object a0) { return invoker.<Object>invoke(target, a0); } protected Object target(Object a0) throws Throwable { return invoker.<Object>invoke(target, a0); }
protected Object targetA1(Object a0) { return target(a0); } protected Object targetA1(Object a0) throws Throwable { return target(a0); }
protected Object targetA1(int a0) { return target(a0); } protected Object targetA1(int a0) throws Throwable { return target(a0); }
protected Object targetA1(long a0) { return target(a0); } protected Object targetA1(long a0) throws Throwable { return target(a0); }
protected Object invoke_L(Object a0) { return return_L(targetA1(a0)); } protected Object invoke_L(Object a0) throws Throwable { return return_L(targetA1(a0)); }
protected int invoke_I(Object a0) { return return_I(targetA1(a0)); } protected int invoke_I(Object a0) throws Throwable { return return_I(targetA1(a0)); }
protected long invoke_J(Object a0) { return return_J(targetA1(a0)); } protected long invoke_J(Object a0) throws Throwable { return return_J(targetA1(a0)); }
protected float invoke_F(Object a0) { return return_F(targetA1(a0)); } protected float invoke_F(Object a0) throws Throwable { return return_F(targetA1(a0)); }
protected double invoke_D(Object a0) { return return_D(targetA1(a0)); } protected double invoke_D(Object a0) throws Throwable { return return_D(targetA1(a0)); }
protected Object invoke_L(int a0) { return return_L(targetA1(a0)); } protected Object invoke_L(int a0) throws Throwable { return return_L(targetA1(a0)); }
protected int invoke_I(int a0) { return return_I(targetA1(a0)); } protected int invoke_I(int a0) throws Throwable { return return_I(targetA1(a0)); }
protected long invoke_J(int a0) { return return_J(targetA1(a0)); } protected long invoke_J(int a0) throws Throwable { return return_J(targetA1(a0)); }
protected float invoke_F(int a0) { return return_F(targetA1(a0)); } protected float invoke_F(int a0) throws Throwable { return return_F(targetA1(a0)); }
protected double invoke_D(int a0) { return return_D(targetA1(a0)); } protected double invoke_D(int a0) throws Throwable { return return_D(targetA1(a0)); }
protected Object invoke_L(long a0) { return return_L(targetA1(a0)); } protected Object invoke_L(long a0) throws Throwable { return return_L(targetA1(a0)); }
protected int invoke_I(long a0) { return return_I(targetA1(a0)); } protected int invoke_I(long a0) throws Throwable { return return_I(targetA1(a0)); }
protected long invoke_J(long a0) { return return_J(targetA1(a0)); } protected long invoke_J(long a0) throws Throwable { return return_J(targetA1(a0)); }
protected float invoke_F(long a0) { return return_F(targetA1(a0)); } protected float invoke_F(long a0) throws Throwable { return return_F(targetA1(a0)); }
protected double invoke_D(long a0) { return return_D(targetA1(a0)); } protected double invoke_D(long a0) throws Throwable { return return_D(targetA1(a0)); }
} }
// */ // */
...@@ -435,13 +462,13 @@ class genclasses { ...@@ -435,13 +462,13 @@ class genclasses {
" protected @cat@(MethodHandle entryPoint) { super(entryPoint); } // to build prototype", " protected @cat@(MethodHandle entryPoint) { super(entryPoint); } // to build prototype",
" protected @cat@(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }", " protected @cat@(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }",
" protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new @cat@(e, i, c, t); }", " protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new @cat@(e, i, c, t); }",
" protected Object target(@Ovav@) { return invoker.<Object>invoke(target, @av@); }", " protected Object target(@Ovav@) throws Throwable { return invoker.<Object>invoke(target, @av@); }",
" //@each-Tv@", " //@each-Tv@",
" protected Object target@cat@(@Tvav@) { return target(@av@); }", " protected Object target@cat@(@Tvav@) throws Throwable { return target(@av@); }",
" //@end-Tv@", " //@end-Tv@",
" //@each-Tv@", " //@each-Tv@",
" //@each-R@", " //@each-R@",
" protected @R@ invoke_@Rc@(@Tvav@) { return return_@Rc@(target@cat@(@av@)); }", " protected @R@ invoke_@Rc@(@Tvav@) throws Throwable { return return_@Rc@(target@cat@(@av@)); }",
" //@end-R@", " //@end-R@",
" //@end-Tv@", " //@end-Tv@",
" }", " }",
...@@ -595,424 +622,424 @@ class genclasses { ...@@ -595,424 +622,424 @@ class genclasses {
protected A0(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A0(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
protected A0(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A0(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A0(e, i, c, t); } protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A0(e, i, c, t); }
protected Object target() { return invoker.<Object>invoke(target); } protected Object target() throws Throwable { return invoker.<Object>invoke(target); }
protected Object targetA0() { return target(); } protected Object targetA0() throws Throwable { return target(); }
protected Object invoke_L() { return return_L(targetA0()); } protected Object invoke_L() throws Throwable { return return_L(targetA0()); }
protected int invoke_I() { return return_I(targetA0()); } protected int invoke_I() throws Throwable { return return_I(targetA0()); }
protected long invoke_J() { return return_J(targetA0()); } protected long invoke_J() throws Throwable { return return_J(targetA0()); }
protected float invoke_F() { return return_F(targetA0()); } protected float invoke_F() throws Throwable { return return_F(targetA0()); }
protected double invoke_D() { return return_D(targetA0()); } protected double invoke_D() throws Throwable { return return_D(targetA0()); }
} }
static class A1 extends Adapter { static class A1 extends Adapter {
protected A1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); } protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); }
protected Object target(Object a0) { return invoker.<Object>invoke(target, a0); } protected Object target(Object a0) throws Throwable { return invoker.<Object>invoke(target, a0); }
protected Object targetA1(Object a0) { return target(a0); } protected Object targetA1(Object a0) throws Throwable { return target(a0); }
protected Object targetA1(int a0) { return target(a0); } protected Object targetA1(int a0) throws Throwable { return target(a0); }
protected Object targetA1(long a0) { return target(a0); } protected Object targetA1(long a0) throws Throwable { return target(a0); }
protected Object invoke_L(Object a0) { return return_L(targetA1(a0)); } protected Object invoke_L(Object a0) throws Throwable { return return_L(targetA1(a0)); }
protected int invoke_I(Object a0) { return return_I(targetA1(a0)); } protected int invoke_I(Object a0) throws Throwable { return return_I(targetA1(a0)); }
protected long invoke_J(Object a0) { return return_J(targetA1(a0)); } protected long invoke_J(Object a0) throws Throwable { return return_J(targetA1(a0)); }
protected float invoke_F(Object a0) { return return_F(targetA1(a0)); } protected float invoke_F(Object a0) throws Throwable { return return_F(targetA1(a0)); }
protected double invoke_D(Object a0) { return return_D(targetA1(a0)); } protected double invoke_D(Object a0) throws Throwable { return return_D(targetA1(a0)); }
protected Object invoke_L(int a0) { return return_L(targetA1(a0)); } protected Object invoke_L(int a0) throws Throwable { return return_L(targetA1(a0)); }
protected int invoke_I(int a0) { return return_I(targetA1(a0)); } protected int invoke_I(int a0) throws Throwable { return return_I(targetA1(a0)); }
protected long invoke_J(int a0) { return return_J(targetA1(a0)); } protected long invoke_J(int a0) throws Throwable { return return_J(targetA1(a0)); }
protected float invoke_F(int a0) { return return_F(targetA1(a0)); } protected float invoke_F(int a0) throws Throwable { return return_F(targetA1(a0)); }
protected double invoke_D(int a0) { return return_D(targetA1(a0)); } protected double invoke_D(int a0) throws Throwable { return return_D(targetA1(a0)); }
protected Object invoke_L(long a0) { return return_L(targetA1(a0)); } protected Object invoke_L(long a0) throws Throwable { return return_L(targetA1(a0)); }
protected int invoke_I(long a0) { return return_I(targetA1(a0)); } protected int invoke_I(long a0) throws Throwable { return return_I(targetA1(a0)); }
protected long invoke_J(long a0) { return return_J(targetA1(a0)); } protected long invoke_J(long a0) throws Throwable { return return_J(targetA1(a0)); }
protected float invoke_F(long a0) { return return_F(targetA1(a0)); } protected float invoke_F(long a0) throws Throwable { return return_F(targetA1(a0)); }
protected double invoke_D(long a0) { return return_D(targetA1(a0)); } protected double invoke_D(long a0) throws Throwable { return return_D(targetA1(a0)); }
} }
static class A2 extends Adapter { static class A2 extends Adapter {
protected A2(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A2(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
protected A2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A2(e, i, c, t); } protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A2(e, i, c, t); }
protected Object target(Object a0, Object a1) { return invoker.<Object>invoke(target, a0, a1); } protected Object target(Object a0, Object a1) throws Throwable { return invoker.<Object>invoke(target, a0, a1); }
protected Object targetA2(Object a0, Object a1) { return target(a0, a1); } protected Object targetA2(Object a0, Object a1) throws Throwable { return target(a0, a1); }
protected Object targetA2(Object a0, int a1) { return target(a0, a1); } protected Object targetA2(Object a0, int a1) throws Throwable { return target(a0, a1); }
protected Object targetA2(int a0, int a1) { return target(a0, a1); } protected Object targetA2(int a0, int a1) throws Throwable { return target(a0, a1); }
protected Object targetA2(Object a0, long a1) { return target(a0, a1); } protected Object targetA2(Object a0, long a1) throws Throwable { return target(a0, a1); }
protected Object targetA2(long a0, long a1) { return target(a0, a1); } protected Object targetA2(long a0, long a1) throws Throwable { return target(a0, a1); }
protected Object invoke_L(Object a0, Object a1) { return return_L(targetA2(a0, a1)); } protected Object invoke_L(Object a0, Object a1) throws Throwable { return return_L(targetA2(a0, a1)); }
protected int invoke_I(Object a0, Object a1) { return return_I(targetA2(a0, a1)); } protected int invoke_I(Object a0, Object a1) throws Throwable { return return_I(targetA2(a0, a1)); }
protected long invoke_J(Object a0, Object a1) { return return_J(targetA2(a0, a1)); } protected long invoke_J(Object a0, Object a1) throws Throwable { return return_J(targetA2(a0, a1)); }
protected float invoke_F(Object a0, Object a1) { return return_F(targetA2(a0, a1)); } protected float invoke_F(Object a0, Object a1) throws Throwable { return return_F(targetA2(a0, a1)); }
protected double invoke_D(Object a0, Object a1) { return return_D(targetA2(a0, a1)); } protected double invoke_D(Object a0, Object a1) throws Throwable { return return_D(targetA2(a0, a1)); }
protected Object invoke_L(Object a0, int a1) { return return_L(targetA2(a0, a1)); } protected Object invoke_L(Object a0, int a1) throws Throwable { return return_L(targetA2(a0, a1)); }
protected int invoke_I(Object a0, int a1) { return return_I(targetA2(a0, a1)); } protected int invoke_I(Object a0, int a1) throws Throwable { return return_I(targetA2(a0, a1)); }
protected long invoke_J(Object a0, int a1) { return return_J(targetA2(a0, a1)); } protected long invoke_J(Object a0, int a1) throws Throwable { return return_J(targetA2(a0, a1)); }
protected float invoke_F(Object a0, int a1) { return return_F(targetA2(a0, a1)); } protected float invoke_F(Object a0, int a1) throws Throwable { return return_F(targetA2(a0, a1)); }
protected double invoke_D(Object a0, int a1) { return return_D(targetA2(a0, a1)); } protected double invoke_D(Object a0, int a1) throws Throwable { return return_D(targetA2(a0, a1)); }
protected Object invoke_L(int a0, int a1) { return return_L(targetA2(a0, a1)); } protected Object invoke_L(int a0, int a1) throws Throwable { return return_L(targetA2(a0, a1)); }
protected int invoke_I(int a0, int a1) { return return_I(targetA2(a0, a1)); } protected int invoke_I(int a0, int a1) throws Throwable { return return_I(targetA2(a0, a1)); }
protected long invoke_J(int a0, int a1) { return return_J(targetA2(a0, a1)); } protected long invoke_J(int a0, int a1) throws Throwable { return return_J(targetA2(a0, a1)); }
protected float invoke_F(int a0, int a1) { return return_F(targetA2(a0, a1)); } protected float invoke_F(int a0, int a1) throws Throwable { return return_F(targetA2(a0, a1)); }
protected double invoke_D(int a0, int a1) { return return_D(targetA2(a0, a1)); } protected double invoke_D(int a0, int a1) throws Throwable { return return_D(targetA2(a0, a1)); }
protected Object invoke_L(Object a0, long a1) { return return_L(targetA2(a0, a1)); } protected Object invoke_L(Object a0, long a1) throws Throwable { return return_L(targetA2(a0, a1)); }
protected int invoke_I(Object a0, long a1) { return return_I(targetA2(a0, a1)); } protected int invoke_I(Object a0, long a1) throws Throwable { return return_I(targetA2(a0, a1)); }
protected long invoke_J(Object a0, long a1) { return return_J(targetA2(a0, a1)); } protected long invoke_J(Object a0, long a1) throws Throwable { return return_J(targetA2(a0, a1)); }
protected float invoke_F(Object a0, long a1) { return return_F(targetA2(a0, a1)); } protected float invoke_F(Object a0, long a1) throws Throwable { return return_F(targetA2(a0, a1)); }
protected double invoke_D(Object a0, long a1) { return return_D(targetA2(a0, a1)); } protected double invoke_D(Object a0, long a1) throws Throwable { return return_D(targetA2(a0, a1)); }
protected Object invoke_L(long a0, long a1) { return return_L(targetA2(a0, a1)); } protected Object invoke_L(long a0, long a1) throws Throwable { return return_L(targetA2(a0, a1)); }
protected int invoke_I(long a0, long a1) { return return_I(targetA2(a0, a1)); } protected int invoke_I(long a0, long a1) throws Throwable { return return_I(targetA2(a0, a1)); }
protected long invoke_J(long a0, long a1) { return return_J(targetA2(a0, a1)); } protected long invoke_J(long a0, long a1) throws Throwable { return return_J(targetA2(a0, a1)); }
protected float invoke_F(long a0, long a1) { return return_F(targetA2(a0, a1)); } protected float invoke_F(long a0, long a1) throws Throwable { return return_F(targetA2(a0, a1)); }
protected double invoke_D(long a0, long a1) { return return_D(targetA2(a0, a1)); } protected double invoke_D(long a0, long a1) throws Throwable { return return_D(targetA2(a0, a1)); }
} }
static class A3 extends Adapter { static class A3 extends Adapter {
protected A3(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A3(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
protected A3(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A3(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A3(e, i, c, t); } protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A3(e, i, c, t); }
protected Object target(Object a0, Object a1, Object a2) { return invoker.<Object>invoke(target, a0, a1, a2); } protected Object target(Object a0, Object a1, Object a2) throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2); }
protected Object targetA3(Object a0, Object a1, Object a2) { return target(a0, a1, a2); } protected Object targetA3(Object a0, Object a1, Object a2) throws Throwable { return target(a0, a1, a2); }
protected Object targetA3(Object a0, Object a1, int a2) { return target(a0, a1, a2); } protected Object targetA3(Object a0, Object a1, int a2) throws Throwable { return target(a0, a1, a2); }
protected Object targetA3(Object a0, int a1, int a2) { return target(a0, a1, a2); } protected Object targetA3(Object a0, int a1, int a2) throws Throwable { return target(a0, a1, a2); }
protected Object targetA3(int a0, int a1, int a2) { return target(a0, a1, a2); } protected Object targetA3(int a0, int a1, int a2) throws Throwable { return target(a0, a1, a2); }
protected Object targetA3(Object a0, Object a1, long a2) { return target(a0, a1, a2); } protected Object targetA3(Object a0, Object a1, long a2) throws Throwable { return target(a0, a1, a2); }
protected Object targetA3(Object a0, long a1, long a2) { return target(a0, a1, a2); } protected Object targetA3(Object a0, long a1, long a2) throws Throwable { return target(a0, a1, a2); }
protected Object targetA3(long a0, long a1, long a2) { return target(a0, a1, a2); } protected Object targetA3(long a0, long a1, long a2) throws Throwable { return target(a0, a1, a2); }
protected Object invoke_L(Object a0, Object a1, Object a2) { return return_L(targetA3(a0, a1, a2)); } protected Object invoke_L(Object a0, Object a1, Object a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
protected int invoke_I(Object a0, Object a1, Object a2) { return return_I(targetA3(a0, a1, a2)); } protected int invoke_I(Object a0, Object a1, Object a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
protected long invoke_J(Object a0, Object a1, Object a2) { return return_J(targetA3(a0, a1, a2)); } protected long invoke_J(Object a0, Object a1, Object a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
protected float invoke_F(Object a0, Object a1, Object a2) { return return_F(targetA3(a0, a1, a2)); } protected float invoke_F(Object a0, Object a1, Object a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
protected double invoke_D(Object a0, Object a1, Object a2) { return return_D(targetA3(a0, a1, a2)); } protected double invoke_D(Object a0, Object a1, Object a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
protected Object invoke_L(Object a0, Object a1, int a2) { return return_L(targetA3(a0, a1, a2)); } protected Object invoke_L(Object a0, Object a1, int a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
protected int invoke_I(Object a0, Object a1, int a2) { return return_I(targetA3(a0, a1, a2)); } protected int invoke_I(Object a0, Object a1, int a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
protected long invoke_J(Object a0, Object a1, int a2) { return return_J(targetA3(a0, a1, a2)); } protected long invoke_J(Object a0, Object a1, int a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
protected float invoke_F(Object a0, Object a1, int a2) { return return_F(targetA3(a0, a1, a2)); } protected float invoke_F(Object a0, Object a1, int a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
protected double invoke_D(Object a0, Object a1, int a2) { return return_D(targetA3(a0, a1, a2)); } protected double invoke_D(Object a0, Object a1, int a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
protected Object invoke_L(Object a0, int a1, int a2) { return return_L(targetA3(a0, a1, a2)); } protected Object invoke_L(Object a0, int a1, int a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
protected int invoke_I(Object a0, int a1, int a2) { return return_I(targetA3(a0, a1, a2)); } protected int invoke_I(Object a0, int a1, int a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
protected long invoke_J(Object a0, int a1, int a2) { return return_J(targetA3(a0, a1, a2)); } protected long invoke_J(Object a0, int a1, int a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
protected float invoke_F(Object a0, int a1, int a2) { return return_F(targetA3(a0, a1, a2)); } protected float invoke_F(Object a0, int a1, int a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
protected double invoke_D(Object a0, int a1, int a2) { return return_D(targetA3(a0, a1, a2)); } protected double invoke_D(Object a0, int a1, int a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
protected Object invoke_L(int a0, int a1, int a2) { return return_L(targetA3(a0, a1, a2)); } protected Object invoke_L(int a0, int a1, int a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
protected int invoke_I(int a0, int a1, int a2) { return return_I(targetA3(a0, a1, a2)); } protected int invoke_I(int a0, int a1, int a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
protected long invoke_J(int a0, int a1, int a2) { return return_J(targetA3(a0, a1, a2)); } protected long invoke_J(int a0, int a1, int a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
protected float invoke_F(int a0, int a1, int a2) { return return_F(targetA3(a0, a1, a2)); } protected float invoke_F(int a0, int a1, int a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
protected double invoke_D(int a0, int a1, int a2) { return return_D(targetA3(a0, a1, a2)); } protected double invoke_D(int a0, int a1, int a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
protected Object invoke_L(Object a0, Object a1, long a2) { return return_L(targetA3(a0, a1, a2)); } protected Object invoke_L(Object a0, Object a1, long a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
protected int invoke_I(Object a0, Object a1, long a2) { return return_I(targetA3(a0, a1, a2)); } protected int invoke_I(Object a0, Object a1, long a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
protected long invoke_J(Object a0, Object a1, long a2) { return return_J(targetA3(a0, a1, a2)); } protected long invoke_J(Object a0, Object a1, long a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
protected float invoke_F(Object a0, Object a1, long a2) { return return_F(targetA3(a0, a1, a2)); } protected float invoke_F(Object a0, Object a1, long a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
protected double invoke_D(Object a0, Object a1, long a2) { return return_D(targetA3(a0, a1, a2)); } protected double invoke_D(Object a0, Object a1, long a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
protected Object invoke_L(Object a0, long a1, long a2) { return return_L(targetA3(a0, a1, a2)); } protected Object invoke_L(Object a0, long a1, long a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
protected int invoke_I(Object a0, long a1, long a2) { return return_I(targetA3(a0, a1, a2)); } protected int invoke_I(Object a0, long a1, long a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
protected long invoke_J(Object a0, long a1, long a2) { return return_J(targetA3(a0, a1, a2)); } protected long invoke_J(Object a0, long a1, long a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
protected float invoke_F(Object a0, long a1, long a2) { return return_F(targetA3(a0, a1, a2)); } protected float invoke_F(Object a0, long a1, long a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
protected double invoke_D(Object a0, long a1, long a2) { return return_D(targetA3(a0, a1, a2)); } protected double invoke_D(Object a0, long a1, long a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
protected Object invoke_L(long a0, long a1, long a2) { return return_L(targetA3(a0, a1, a2)); } protected Object invoke_L(long a0, long a1, long a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
protected int invoke_I(long a0, long a1, long a2) { return return_I(targetA3(a0, a1, a2)); } protected int invoke_I(long a0, long a1, long a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
protected long invoke_J(long a0, long a1, long a2) { return return_J(targetA3(a0, a1, a2)); } protected long invoke_J(long a0, long a1, long a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
protected float invoke_F(long a0, long a1, long a2) { return return_F(targetA3(a0, a1, a2)); } protected float invoke_F(long a0, long a1, long a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
protected double invoke_D(long a0, long a1, long a2) { return return_D(targetA3(a0, a1, a2)); } protected double invoke_D(long a0, long a1, long a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
} }
//params=[4, 5, 2, 99, 99, 99] //params=[4, 5, 2, 99, 99, 99]
static class A4 extends Adapter { static class A4 extends Adapter {
protected A4(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A4(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
protected A4(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A4(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A4(e, i, c, t); } protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A4(e, i, c, t); }
protected Object target(Object a0, Object a1, Object a2, Object a3) { return invoker.<Object>invoke(target, a0, a1, a2, a3); } protected Object target(Object a0, Object a1, Object a2, Object a3) throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, a3); }
protected Object targetA4(Object a0, Object a1, Object a2, Object a3) { return target(a0, a1, a2, a3); } protected Object targetA4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return target(a0, a1, a2, a3); }
protected Object targetA4(Object a0, Object a1, Object a2, int a3) { return target(a0, a1, a2, a3); } protected Object targetA4(Object a0, Object a1, Object a2, int a3) throws Throwable { return target(a0, a1, a2, a3); }
protected Object targetA4(Object a0, Object a1, int a2, int a3) { return target(a0, a1, a2, a3); } protected Object targetA4(Object a0, Object a1, int a2, int a3) throws Throwable { return target(a0, a1, a2, a3); }
protected Object targetA4(Object a0, int a1, int a2, int a3) { return target(a0, a1, a2, a3); } protected Object targetA4(Object a0, int a1, int a2, int a3) throws Throwable { return target(a0, a1, a2, a3); }
protected Object targetA4(int a0, int a1, int a2, int a3) { return target(a0, a1, a2, a3); } protected Object targetA4(int a0, int a1, int a2, int a3) throws Throwable { return target(a0, a1, a2, a3); }
protected Object targetA4(Object a0, Object a1, Object a2, long a3) { return target(a0, a1, a2, a3); } protected Object targetA4(Object a0, Object a1, Object a2, long a3) throws Throwable { return target(a0, a1, a2, a3); }
protected Object targetA4(Object a0, Object a1, long a2, long a3) { return target(a0, a1, a2, a3); } protected Object targetA4(Object a0, Object a1, long a2, long a3) throws Throwable { return target(a0, a1, a2, a3); }
protected Object targetA4(Object a0, long a1, long a2, long a3) { return target(a0, a1, a2, a3); } protected Object targetA4(Object a0, long a1, long a2, long a3) throws Throwable { return target(a0, a1, a2, a3); }
protected Object targetA4(long a0, long a1, long a2, long a3) { return target(a0, a1, a2, a3); } protected Object targetA4(long a0, long a1, long a2, long a3) throws Throwable { return target(a0, a1, a2, a3); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3) { return return_L(targetA4(a0, a1, a2, a3)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3) { return return_I(targetA4(a0, a1, a2, a3)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3) { return return_J(targetA4(a0, a1, a2, a3)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
protected Object invoke_L(Object a0, Object a1, Object a2, int a3) { return return_L(targetA4(a0, a1, a2, a3)); } protected Object invoke_L(Object a0, Object a1, Object a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
protected int invoke_I(Object a0, Object a1, Object a2, int a3) { return return_I(targetA4(a0, a1, a2, a3)); } protected int invoke_I(Object a0, Object a1, Object a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
protected long invoke_J(Object a0, Object a1, Object a2, int a3) { return return_J(targetA4(a0, a1, a2, a3)); } protected long invoke_J(Object a0, Object a1, Object a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
protected Object invoke_L(Object a0, Object a1, int a2, int a3) { return return_L(targetA4(a0, a1, a2, a3)); } protected Object invoke_L(Object a0, Object a1, int a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
protected int invoke_I(Object a0, Object a1, int a2, int a3) { return return_I(targetA4(a0, a1, a2, a3)); } protected int invoke_I(Object a0, Object a1, int a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
protected long invoke_J(Object a0, Object a1, int a2, int a3) { return return_J(targetA4(a0, a1, a2, a3)); } protected long invoke_J(Object a0, Object a1, int a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
protected Object invoke_L(Object a0, int a1, int a2, int a3) { return return_L(targetA4(a0, a1, a2, a3)); } protected Object invoke_L(Object a0, int a1, int a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
protected int invoke_I(Object a0, int a1, int a2, int a3) { return return_I(targetA4(a0, a1, a2, a3)); } protected int invoke_I(Object a0, int a1, int a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
protected long invoke_J(Object a0, int a1, int a2, int a3) { return return_J(targetA4(a0, a1, a2, a3)); } protected long invoke_J(Object a0, int a1, int a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
protected Object invoke_L(int a0, int a1, int a2, int a3) { return return_L(targetA4(a0, a1, a2, a3)); } protected Object invoke_L(int a0, int a1, int a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
protected int invoke_I(int a0, int a1, int a2, int a3) { return return_I(targetA4(a0, a1, a2, a3)); } protected int invoke_I(int a0, int a1, int a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
protected long invoke_J(int a0, int a1, int a2, int a3) { return return_J(targetA4(a0, a1, a2, a3)); } protected long invoke_J(int a0, int a1, int a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
protected Object invoke_L(Object a0, Object a1, Object a2, long a3) { return return_L(targetA4(a0, a1, a2, a3)); } protected Object invoke_L(Object a0, Object a1, Object a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
protected int invoke_I(Object a0, Object a1, Object a2, long a3) { return return_I(targetA4(a0, a1, a2, a3)); } protected int invoke_I(Object a0, Object a1, Object a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
protected long invoke_J(Object a0, Object a1, Object a2, long a3) { return return_J(targetA4(a0, a1, a2, a3)); } protected long invoke_J(Object a0, Object a1, Object a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
protected Object invoke_L(Object a0, Object a1, long a2, long a3) { return return_L(targetA4(a0, a1, a2, a3)); } protected Object invoke_L(Object a0, Object a1, long a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
protected int invoke_I(Object a0, Object a1, long a2, long a3) { return return_I(targetA4(a0, a1, a2, a3)); } protected int invoke_I(Object a0, Object a1, long a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
protected long invoke_J(Object a0, Object a1, long a2, long a3) { return return_J(targetA4(a0, a1, a2, a3)); } protected long invoke_J(Object a0, Object a1, long a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
protected Object invoke_L(Object a0, long a1, long a2, long a3) { return return_L(targetA4(a0, a1, a2, a3)); } protected Object invoke_L(Object a0, long a1, long a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
protected int invoke_I(Object a0, long a1, long a2, long a3) { return return_I(targetA4(a0, a1, a2, a3)); } protected int invoke_I(Object a0, long a1, long a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
protected long invoke_J(Object a0, long a1, long a2, long a3) { return return_J(targetA4(a0, a1, a2, a3)); } protected long invoke_J(Object a0, long a1, long a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
protected Object invoke_L(long a0, long a1, long a2, long a3) { return return_L(targetA4(a0, a1, a2, a3)); } protected Object invoke_L(long a0, long a1, long a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
protected int invoke_I(long a0, long a1, long a2, long a3) { return return_I(targetA4(a0, a1, a2, a3)); } protected int invoke_I(long a0, long a1, long a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
protected long invoke_J(long a0, long a1, long a2, long a3) { return return_J(targetA4(a0, a1, a2, a3)); } protected long invoke_J(long a0, long a1, long a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
} }
static class A5 extends Adapter { static class A5 extends Adapter {
protected A5(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A5(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
protected A5(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A5(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A5(e, i, c, t); } protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A5(e, i, c, t); }
protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4) { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4); } protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4); }
protected Object targetA5(Object a0, Object a1, Object a2, Object a3, Object a4) { return target(a0, a1, a2, a3, a4); } protected Object targetA5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
protected Object targetA5(Object a0, Object a1, Object a2, Object a3, int a4) { return target(a0, a1, a2, a3, a4); } protected Object targetA5(Object a0, Object a1, Object a2, Object a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
protected Object targetA5(Object a0, Object a1, Object a2, int a3, int a4) { return target(a0, a1, a2, a3, a4); } protected Object targetA5(Object a0, Object a1, Object a2, int a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
protected Object targetA5(Object a0, Object a1, int a2, int a3, int a4) { return target(a0, a1, a2, a3, a4); } protected Object targetA5(Object a0, Object a1, int a2, int a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
protected Object targetA5(Object a0, int a1, int a2, int a3, int a4) { return target(a0, a1, a2, a3, a4); } protected Object targetA5(Object a0, int a1, int a2, int a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
protected Object targetA5(int a0, int a1, int a2, int a3, int a4) { return target(a0, a1, a2, a3, a4); } protected Object targetA5(int a0, int a1, int a2, int a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
protected Object targetA5(Object a0, Object a1, Object a2, Object a3, long a4) { return target(a0, a1, a2, a3, a4); } protected Object targetA5(Object a0, Object a1, Object a2, Object a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
protected Object targetA5(Object a0, Object a1, Object a2, long a3, long a4) { return target(a0, a1, a2, a3, a4); } protected Object targetA5(Object a0, Object a1, Object a2, long a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
protected Object targetA5(Object a0, Object a1, long a2, long a3, long a4) { return target(a0, a1, a2, a3, a4); } protected Object targetA5(Object a0, Object a1, long a2, long a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
protected Object targetA5(Object a0, long a1, long a2, long a3, long a4) { return target(a0, a1, a2, a3, a4); } protected Object targetA5(Object a0, long a1, long a2, long a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
protected Object targetA5(long a0, long a1, long a2, long a3, long a4) { return target(a0, a1, a2, a3, a4); } protected Object targetA5(long a0, long a1, long a2, long a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, int a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, int a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, int a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
protected Object invoke_L(Object a0, Object a1, Object a2, int a3, int a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } protected Object invoke_L(Object a0, Object a1, Object a2, int a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
protected int invoke_I(Object a0, Object a1, Object a2, int a3, int a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } protected int invoke_I(Object a0, Object a1, Object a2, int a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
protected long invoke_J(Object a0, Object a1, Object a2, int a3, int a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } protected long invoke_J(Object a0, Object a1, Object a2, int a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
protected Object invoke_L(Object a0, Object a1, int a2, int a3, int a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } protected Object invoke_L(Object a0, Object a1, int a2, int a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
protected int invoke_I(Object a0, Object a1, int a2, int a3, int a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } protected int invoke_I(Object a0, Object a1, int a2, int a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
protected long invoke_J(Object a0, Object a1, int a2, int a3, int a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } protected long invoke_J(Object a0, Object a1, int a2, int a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
protected Object invoke_L(Object a0, int a1, int a2, int a3, int a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } protected Object invoke_L(Object a0, int a1, int a2, int a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
protected int invoke_I(Object a0, int a1, int a2, int a3, int a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } protected int invoke_I(Object a0, int a1, int a2, int a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
protected long invoke_J(Object a0, int a1, int a2, int a3, int a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } protected long invoke_J(Object a0, int a1, int a2, int a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
protected Object invoke_L(int a0, int a1, int a2, int a3, int a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } protected Object invoke_L(int a0, int a1, int a2, int a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
protected int invoke_I(int a0, int a1, int a2, int a3, int a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } protected int invoke_I(int a0, int a1, int a2, int a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
protected long invoke_J(int a0, int a1, int a2, int a3, int a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } protected long invoke_J(int a0, int a1, int a2, int a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
protected int invoke_I(Object a0, long a1, long a2, long a3, long a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } protected int invoke_I(Object a0, long a1, long a2, long a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
protected long invoke_J(Object a0, long a1, long a2, long a3, long a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } protected long invoke_J(Object a0, long a1, long a2, long a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
protected Object invoke_L(long a0, long a1, long a2, long a3, long a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } protected Object invoke_L(long a0, long a1, long a2, long a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
protected int invoke_I(long a0, long a1, long a2, long a3, long a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } protected int invoke_I(long a0, long a1, long a2, long a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
protected long invoke_J(long a0, long a1, long a2, long a3, long a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } protected long invoke_J(long a0, long a1, long a2, long a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
} }
//params=[6, 10, 2, 99, 0, 99] //params=[6, 10, 2, 99, 0, 99]
static class A6 extends Adapter { static class A6 extends Adapter {
protected A6(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A6(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
protected A6(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A6(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A6(e, i, c, t); } protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A6(e, i, c, t); }
protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5); } protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5); }
protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return target(a0, a1, a2, a3, a4, a5); } protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) { return target(a0, a1, a2, a3, a4, a5); } protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
protected Object targetA6(Object a0, Object a1, Object a2, Object a3, long a4, long a5) { return target(a0, a1, a2, a3, a4, a5); } protected Object targetA6(Object a0, Object a1, Object a2, Object a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
protected Object targetA6(Object a0, Object a1, Object a2, long a3, long a4, long a5) { return target(a0, a1, a2, a3, a4, a5); } protected Object targetA6(Object a0, Object a1, Object a2, long a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
protected Object targetA6(Object a0, Object a1, long a2, long a3, long a4, long a5) { return target(a0, a1, a2, a3, a4, a5); } protected Object targetA6(Object a0, Object a1, long a2, long a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
protected Object targetA6(Object a0, long a1, long a2, long a3, long a4, long a5) { return target(a0, a1, a2, a3, a4, a5); } protected Object targetA6(Object a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
protected Object targetA6(long a0, long a1, long a2, long a3, long a4, long a5) { return target(a0, a1, a2, a3, a4, a5); } protected Object targetA6(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
} }
static class A7 extends Adapter { static class A7 extends Adapter {
protected A7(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A7(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
protected A7(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A7(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A7(e, i, c, t); } protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A7(e, i, c, t); }
protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6); } protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6); }
protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return target(a0, a1, a2, a3, a4, a5, a6); } protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) { return target(a0, a1, a2, a3, a4, a5, a6); } protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) { return target(a0, a1, a2, a3, a4, a5, a6); } protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
protected Object targetA7(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) { return target(a0, a1, a2, a3, a4, a5, a6); } protected Object targetA7(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
protected Object targetA7(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) { return target(a0, a1, a2, a3, a4, a5, a6); } protected Object targetA7(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
protected Object targetA7(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) { return target(a0, a1, a2, a3, a4, a5, a6); } protected Object targetA7(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
protected Object targetA7(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) { return target(a0, a1, a2, a3, a4, a5, a6); } protected Object targetA7(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
protected Object targetA7(long a0, long a1, long a2, long a3, long a4, long a5, long a6) { return target(a0, a1, a2, a3, a4, a5, a6); } protected Object targetA7(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
} }
static class A8 extends Adapter { static class A8 extends Adapter {
protected A8(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A8(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
protected A8(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A8(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A8(e, i, c, t); } protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A8(e, i, c, t); }
protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7); } protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7); }
protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); } protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); } protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); } protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); } protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
protected Object targetA8(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); } protected Object targetA8(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
protected Object targetA8(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); } protected Object targetA8(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
protected Object targetA8(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); } protected Object targetA8(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
protected Object targetA8(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); } protected Object targetA8(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
protected Object targetA8(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); } protected Object targetA8(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
} }
static class A9 extends Adapter { static class A9 extends Adapter {
protected A9(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A9(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
protected A9(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A9(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A9(e, i, c, t); } protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A9(e, i, c, t); }
protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8); } protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8); }
protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
protected Object targetA9(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } protected Object targetA9(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
protected Object targetA9(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } protected Object targetA9(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
protected Object targetA9(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } protected Object targetA9(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
protected Object targetA9(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } protected Object targetA9(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
protected Object targetA9(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } protected Object targetA9(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
} }
static class A10 extends Adapter { static class A10 extends Adapter {
protected A10(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A10(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
protected A10(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A10(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A10(e, i, c, t); } protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A10(e, i, c, t); }
protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return invoker.<Object>invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
protected Object targetA10(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } protected Object targetA10(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
protected Object targetA10(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } protected Object targetA10(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
protected Object targetA10(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } protected Object targetA10(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
protected Object targetA10(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } protected Object targetA10(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
protected Object targetA10(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } protected Object targetA10(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
} }
} }
...@@ -29,6 +29,10 @@ package sun.dyn.empty; ...@@ -29,6 +29,10 @@ package sun.dyn.empty;
* An empty class in an empty package. * An empty class in an empty package.
* Used as a proxy for unprivileged code, since making access checks * Used as a proxy for unprivileged code, since making access checks
* against it will only succeed against public methods in public types. * against it will only succeed against public methods in public types.
* <p>
* This class also stands (internally to sun.dyn) for the type of a
* value that cannot be produced, because the expression of this type
* always returns abnormally. (Cf. Nothing in the closures proposal.)
* @author jrose * @author jrose
*/ */
public class Empty { public class Empty {
......
...@@ -33,9 +33,9 @@ import java.util.List; ...@@ -33,9 +33,9 @@ import java.util.List;
* Utility routines for dealing with bytecode-level signatures. * Utility routines for dealing with bytecode-level signatures.
* @author jrose * @author jrose
*/ */
public class BytecodeSignature { public class BytecodeDescriptor {
private BytecodeSignature() { } // cannot instantiate private BytecodeDescriptor() { } // cannot instantiate
public static List<Class<?>> parseMethod(String bytecodeSignature, ClassLoader loader) { public static List<Class<?>> parseMethod(String bytecodeSignature, ClassLoader loader) {
return parseMethod(bytecodeSignature, 0, bytecodeSignature.length(), loader); return parseMethod(bytecodeSignature, 0, bytecodeSignature.length(), loader);
......
...@@ -298,6 +298,8 @@ public class BytecodeName { ...@@ -298,6 +298,8 @@ public class BytecodeName {
* The name {@code &lt;init&gt;} will be parsed into { '&lt;', "init", '&gt;'}} * The name {@code &lt;init&gt;} will be parsed into { '&lt;', "init", '&gt;'}}
* The name {@code foo/bar$:baz} will be parsed into * The name {@code foo/bar$:baz} will be parsed into
* {@code {"foo", '/', "bar", '$', ':', "baz"}}. * {@code {"foo", '/', "bar", '$', ':', "baz"}}.
* The name {@code ::\=:foo:\=bar\!baz} will be parsed into
* {@code {':', ':', "", ':', "foo", ':', "bar:baz"}}.
*/ */
public static Object[] parseBytecodeName(String s) { public static Object[] parseBytecodeName(String s) {
int slen = s.length(); int slen = s.length();
...@@ -315,7 +317,7 @@ public class BytecodeName { ...@@ -315,7 +317,7 @@ public class BytecodeName {
if (lasti < i) { if (lasti < i) {
// normal component // normal component
if (pass != 0) if (pass != 0)
res[fillp] = s.substring(lasti, i); res[fillp] = toSourceName(s.substring(lasti, i));
fillp++; fillp++;
lasti = i+1; lasti = i+1;
} }
...@@ -323,13 +325,14 @@ public class BytecodeName { ...@@ -323,13 +325,14 @@ public class BytecodeName {
if (pass != 0) if (pass != 0)
res[fillp] = DANGEROUS_CHARS_CA[whichDC]; res[fillp] = DANGEROUS_CHARS_CA[whichDC];
fillp++; fillp++;
lasti = i+1;
} }
} }
if (pass != 0) break; if (pass != 0) break;
// between passes, build the result array // between passes, build the result array
res = new String[fillp]; res = new Object[fillp];
if (fillp <= 1) { if (fillp <= 1 && lasti == 0) {
if (fillp != 0) res[0] = s; if (fillp != 0) res[0] = toSourceName(s);
break; break;
} }
} }
...@@ -348,9 +351,19 @@ public class BytecodeName { ...@@ -348,9 +351,19 @@ public class BytecodeName {
* @throws NullPointerException if any component is null * @throws NullPointerException if any component is null
*/ */
public static String unparseBytecodeName(Object[] components) { public static String unparseBytecodeName(Object[] components) {
for (Object c : components) { Object[] components0 = components;
if (c instanceof String) for (int i = 0; i < components.length; i++) {
checkSafeBytecodeName((String) c); // may fail Object c = components[i];
if (c instanceof String) {
String mc = toBytecodeName((String) c);
if (i == 0 && components.length == 1)
return mc; // usual case
if ((Object)mc != c) {
if (components == components0)
components = components.clone();
components[i] = c = mc;
}
}
} }
return appendAll(components); return appendAll(components);
} }
...@@ -381,6 +394,14 @@ public class BytecodeName { ...@@ -381,6 +394,14 @@ public class BytecodeName {
* If the bytecode name contains dangerous characters, * If the bytecode name contains dangerous characters,
* assume that they are being used as punctuation, * assume that they are being used as punctuation,
* and pass them through unchanged. * and pass them through unchanged.
* Non-empty runs of non-dangerous characters are demangled
* if necessary, and the resulting names are quoted if
* they are not already valid Java identifiers, or if
* they contain a dangerous character (i.e., dollar sign "$").
* Single quotes are used when quoting.
* Within quoted names, embedded single quotes and backslashes
* are further escaped by prepended backslashes.
*
* @param s the original bytecode name (which may be qualified) * @param s the original bytecode name (which may be qualified)
* @return a human-readable presentation * @return a human-readable presentation
*/ */
...@@ -389,10 +410,10 @@ public class BytecodeName { ...@@ -389,10 +410,10 @@ public class BytecodeName {
for (int i = 0; i < components.length; i++) { for (int i = 0; i < components.length; i++) {
if (!(components[i] instanceof String)) if (!(components[i] instanceof String))
continue; continue;
String c = (String) components[i]; String sn = (String) components[i];
// pretty up the name by demangling it // note that the name is already demangled!
String sn = toSourceName(c); //sn = toSourceName(sn);
if ((Object)sn != c || !isJavaIdent(sn)) { if (!isJavaIdent(sn) || sn.indexOf('$') >=0 ) {
components[i] = quoteDisplay(sn); components[i] = quoteDisplay(sn);
} }
} }
...@@ -401,10 +422,10 @@ public class BytecodeName { ...@@ -401,10 +422,10 @@ public class BytecodeName {
private static boolean isJavaIdent(String s) { private static boolean isJavaIdent(String s) {
int slen = s.length(); int slen = s.length();
if (slen == 0) return false; if (slen == 0) return false;
if (!Character.isUnicodeIdentifierStart(s.charAt(0))) if (!Character.isJavaIdentifierStart(s.charAt(0)))
return false; return false;
for (int i = 1; i < slen; i++) { for (int i = 1; i < slen; i++) {
if (!Character.isUnicodeIdentifierPart(s.charAt(0))) if (!Character.isJavaIdentifierPart(s.charAt(i)))
return false; return false;
} }
return true; return true;
...@@ -602,110 +623,5 @@ public class BytecodeName { ...@@ -602,110 +623,5 @@ public class BytecodeName {
return -1; return -1;
} }
// test driver
static void main(String[] av) {
// If verbose is enabled, quietly check everything.
// Otherwise, print the output for the user to check.
boolean verbose = false;
int maxlen = 0;
while (av.length > 0 && av[0].startsWith("-")) {
String flag = av[0].intern();
av = java.util.Arrays.copyOfRange(av, 1, av.length); // Java 1.6 or later
if (flag == "-" || flag == "--") break;
else if (flag == "-q")
verbose = false;
else if (flag == "-v")
verbose = true;
else if (flag.startsWith("-l"))
maxlen = Integer.valueOf(flag.substring(2));
else
throw new Error("Illegal flag argument: "+flag);
}
if (maxlen == 0)
maxlen = (verbose ? 2 : 4);
if (verbose) System.out.println("Note: maxlen = "+maxlen);
switch (av.length) {
case 0: av = new String[] {
DANGEROUS_CHARS.substring(0) +
REPLACEMENT_CHARS.substring(0, 1) +
NULL_ESCAPE + "x"
}; // and fall through:
case 1:
char[] cv = av[0].toCharArray();
av = new String[cv.length];
int avp = 0;
for (char c : cv) {
String s = String.valueOf(c);
if (c == 'x') s = "foo"; // tradition...
av[avp++] = s;
}
}
if (verbose)
System.out.println("Note: Verbose output mode enabled. Use '-q' to suppress.");
Tester t = new Tester();
t.maxlen = maxlen;
t.verbose = verbose;
t.tokens = av;
t.test("", 0);
}
static class Tester {
boolean verbose;
int maxlen;
java.util.Map<String,String> map = new java.util.HashMap<String,String>();
String[] tokens;
void test(String stringSoFar, int tokensSoFar) {
test(stringSoFar);
if (tokensSoFar <= maxlen) {
for (String token : tokens) {
if (token.length() == 0) continue; // skip empty tokens
if (stringSoFar.indexOf(token) != stringSoFar.lastIndexOf(token))
continue; // there are already two occs. of this token
if (token.charAt(0) == ESCAPE_C && token.length() == 1 && maxlen < 4)
test(stringSoFar+token, tokensSoFar); // want lots of \'s
else if (tokensSoFar < maxlen)
test(stringSoFar+token, tokensSoFar+1);
}
}
}
void test(String s) {
// for small batches, do not test the null string
if (s.length() == 0 && maxlen >=1 && maxlen <= 2) return;
String bn = testSourceName(s);
if (bn == null) return;
if (bn == s) {
//if (verbose) System.out.println(s+" == id");
} else {
if (verbose) System.out.println(s+" => "+bn+" "+toDisplayName(bn));
String bnbn = testSourceName(bn);
if (bnbn == null) return;
if (verbose) System.out.println(bn+" => "+bnbn+" "+toDisplayName(bnbn));
/*
String bn3 = testSourceName(bnbn);
if (bn3 == null) return;
if (verbose) System.out.println(bnbn+" => "+bn3);
*/
}
}
String testSourceName(String s) {
if (map.containsKey(s)) return null;
String bn = toBytecodeName(s);
map.put(s, bn);
String sn = toSourceName(bn);
if (!sn.equals(s)) {
String bad = (s+" => "+bn+" != "+sn);
if (!verbose) throw new Error("Bad mangling: "+bad);
System.out.println("*** "+bad);
return null;
}
return bn;
}
}
} }
...@@ -27,7 +27,10 @@ package sun.dyn.util; ...@@ -27,7 +27,10 @@ package sun.dyn.util;
import java.dyn.*; import java.dyn.*;
import java.dyn.MethodHandles.Lookup; import java.dyn.MethodHandles.Lookup;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.List;
import sun.dyn.Access; import sun.dyn.Access;
import sun.dyn.AdapterMethodHandle; import sun.dyn.AdapterMethodHandle;
import sun.dyn.MethodHandleImpl; import sun.dyn.MethodHandleImpl;
...@@ -37,6 +40,7 @@ public class ValueConversions { ...@@ -37,6 +40,7 @@ public class ValueConversions {
private static final Lookup IMPL_LOOKUP = MethodHandleImpl.getLookup(IMPL_TOKEN); private static final Lookup IMPL_LOOKUP = MethodHandleImpl.getLookup(IMPL_TOKEN);
private static EnumMap<Wrapper, MethodHandle>[] newWrapperCaches(int n) { private static EnumMap<Wrapper, MethodHandle>[] newWrapperCaches(int n) {
@SuppressWarnings("unchecked")
EnumMap<Wrapper, MethodHandle>[] caches EnumMap<Wrapper, MethodHandle>[] caches
= (EnumMap<Wrapper, MethodHandle>[]) new EnumMap[n]; // unchecked warning expected here = (EnumMap<Wrapper, MethodHandle>[]) new EnumMap[n]; // unchecked warning expected here
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
...@@ -114,7 +118,7 @@ public class ValueConversions { ...@@ -114,7 +118,7 @@ public class ValueConversions {
} }
private static MethodType unboxType(Wrapper wrap, boolean raw) { private static MethodType unboxType(Wrapper wrap, boolean raw) {
return MethodType.make(rawWrapper(wrap, raw).primitiveType(), wrap.wrapperType()); return MethodType.methodType(rawWrapper(wrap, raw).primitiveType(), wrap.wrapperType());
} }
private static final EnumMap<Wrapper, MethodHandle>[] private static final EnumMap<Wrapper, MethodHandle>[]
...@@ -240,7 +244,7 @@ public class ValueConversions { ...@@ -240,7 +244,7 @@ public class ValueConversions {
private static MethodType boxType(Wrapper wrap, boolean raw) { private static MethodType boxType(Wrapper wrap, boolean raw) {
// be exact, since return casts are hard to compose // be exact, since return casts are hard to compose
Class<?> boxType = wrap.wrapperType(); Class<?> boxType = wrap.wrapperType();
return MethodType.make(boxType, rawWrapper(wrap, raw).primitiveType()); return MethodType.methodType(boxType, rawWrapper(wrap, raw).primitiveType());
} }
private static Wrapper rawWrapper(Wrapper wrap, boolean raw) { private static Wrapper rawWrapper(Wrapper wrap, boolean raw) {
...@@ -305,29 +309,47 @@ public class ValueConversions { ...@@ -305,29 +309,47 @@ public class ValueConversions {
/// Kludges for when raw values get accidentally boxed. /// Kludges for when raw values get accidentally boxed.
static int unboxRawInteger(Object x) {
if (x instanceof Integer)
return unboxInteger(x);
else
return (int) unboxLong(x);
}
static Integer reboxRawInteger(Object x) {
if (x instanceof Integer)
return (Integer) x;
else
return (int) unboxLong(x);
}
static Byte reboxRawByte(Object x) { static Byte reboxRawByte(Object x) {
if (x instanceof Byte) return (Byte) x; if (x instanceof Byte) return (Byte) x;
return boxByteRaw(unboxInteger(x)); return boxByteRaw(unboxRawInteger(x));
} }
static Short reboxRawShort(Object x) { static Short reboxRawShort(Object x) {
if (x instanceof Short) return (Short) x; if (x instanceof Short) return (Short) x;
return boxShortRaw(unboxInteger(x)); return boxShortRaw(unboxRawInteger(x));
} }
static Boolean reboxRawBoolean(Object x) { static Boolean reboxRawBoolean(Object x) {
if (x instanceof Boolean) return (Boolean) x; if (x instanceof Boolean) return (Boolean) x;
return boxBooleanRaw(unboxInteger(x)); return boxBooleanRaw(unboxRawInteger(x));
} }
static Character reboxRawCharacter(Object x) { static Character reboxRawCharacter(Object x) {
if (x instanceof Character) return (Character) x; if (x instanceof Character) return (Character) x;
return boxCharacterRaw(unboxInteger(x)); return boxCharacterRaw(unboxRawInteger(x));
} }
static Float reboxRawFloat(Object x) { static Float reboxRawFloat(Object x) {
if (x instanceof Float) return (Float) x; if (x instanceof Float) return (Float) x;
return boxFloatRaw(unboxInteger(x)); return boxFloatRaw(unboxRawInteger(x));
}
static Long reboxRawLong(Object x) {
return (Long) x; //never a rebox
} }
static Double reboxRawDouble(Object x) { static Double reboxRawDouble(Object x) {
...@@ -337,12 +359,21 @@ public class ValueConversions { ...@@ -337,12 +359,21 @@ public class ValueConversions {
private static MethodType reboxType(Wrapper wrap) { private static MethodType reboxType(Wrapper wrap) {
Class<?> boxType = wrap.wrapperType(); Class<?> boxType = wrap.wrapperType();
return MethodType.make(boxType, Object.class); return MethodType.methodType(boxType, Object.class);
} }
private static final EnumMap<Wrapper, MethodHandle>[] private static final EnumMap<Wrapper, MethodHandle>[]
REBOX_CONVERSIONS = newWrapperCaches(2); REBOX_CONVERSIONS = newWrapperCaches(2);
/**
* Becase we normalize primitive types to reduce the number of signatures,
* primitives are sometimes manipulated under an "erased" type,
* either int (for types other than long/double) or long (for all types).
* When the erased primitive value is then boxed into an Integer or Long,
* the final boxed primitive is sometimes required. This transformation
* is called a "rebox". It takes an Integer or Long and produces some
* other boxed value.
*/
public static MethodHandle rebox(Wrapper wrap, boolean exact) { public static MethodHandle rebox(Wrapper wrap, boolean exact) {
EnumMap<Wrapper, MethodHandle> cache = REBOX_CONVERSIONS[exact?1:0]; EnumMap<Wrapper, MethodHandle> cache = REBOX_CONVERSIONS[exact?1:0];
MethodHandle mh = cache.get(wrap); MethodHandle mh = cache.get(wrap);
...@@ -355,9 +386,6 @@ public class ValueConversions { ...@@ -355,9 +386,6 @@ public class ValueConversions {
mh = IDENTITY; break; mh = IDENTITY; break;
case VOID: case VOID:
throw new IllegalArgumentException("cannot rebox a void"); throw new IllegalArgumentException("cannot rebox a void");
case INT: case LONG:
mh = cast(wrap.wrapperType(), exact);
break;
} }
if (mh != null) { if (mh != null) {
cache.put(wrap, mh); cache.put(wrap, mh);
...@@ -384,13 +412,21 @@ public class ValueConversions { ...@@ -384,13 +412,21 @@ public class ValueConversions {
/// Width-changing conversions between int and long. /// Width-changing conversions between int and long.
static long widenInt(int x) { static long widenInt(int x) {
return x; return (long) x;
}
static Long widenBoxedInt(Integer x) {
return (long)(int)x;
} }
static int narrowLong(long x) { static int narrowLong(long x) {
return (int) x; return (int) x;
} }
static Integer narrowBoxedLong(Long x) {
return (int)(long) x;
}
/// Constant functions /// Constant functions
static void ignore(Object x) { static void ignore(Object x) {
...@@ -432,7 +468,7 @@ public class ValueConversions { ...@@ -432,7 +468,7 @@ public class ValueConversions {
return mh; return mh;
} }
// slow path // slow path
MethodType type = MethodType.make(wrap.primitiveType()); MethodType type = MethodType.methodType(wrap.primitiveType());
switch (wrap) { switch (wrap) {
case VOID: case VOID:
mh = EMPTY; mh = EMPTY;
...@@ -500,11 +536,11 @@ public class ValueConversions { ...@@ -500,11 +536,11 @@ public class ValueConversions {
private static final MethodHandle IDENTITY, CAST_REFERENCE, ALWAYS_NULL, ALWAYS_ZERO, ZERO_OBJECT, IGNORE, EMPTY; private static final MethodHandle IDENTITY, CAST_REFERENCE, ALWAYS_NULL, ALWAYS_ZERO, ZERO_OBJECT, IGNORE, EMPTY;
static { static {
try { try {
MethodType idType = MethodType.makeGeneric(1); MethodType idType = MethodType.genericMethodType(1);
MethodType castType = idType.insertParameterType(0, Class.class); MethodType castType = idType.insertParameterTypes(0, Class.class);
MethodType alwaysZeroType = idType.changeReturnType(int.class); MethodType alwaysZeroType = idType.changeReturnType(int.class);
MethodType ignoreType = idType.changeReturnType(void.class); MethodType ignoreType = idType.changeReturnType(void.class);
MethodType zeroObjectType = MethodType.makeGeneric(0); MethodType zeroObjectType = MethodType.genericMethodType(0);
IDENTITY = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", idType); IDENTITY = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", idType);
//CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType); //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
CAST_REFERENCE = IMPL_LOOKUP.findStatic(ValueConversions.class, "castReference", castType); CAST_REFERENCE = IMPL_LOOKUP.findStatic(ValueConversions.class, "castReference", castType);
...@@ -512,7 +548,7 @@ public class ValueConversions { ...@@ -512,7 +548,7 @@ public class ValueConversions {
ALWAYS_ZERO = IMPL_LOOKUP.findStatic(ValueConversions.class, "alwaysZero", alwaysZeroType); ALWAYS_ZERO = IMPL_LOOKUP.findStatic(ValueConversions.class, "alwaysZero", alwaysZeroType);
ZERO_OBJECT = IMPL_LOOKUP.findStatic(ValueConversions.class, "zeroObject", zeroObjectType); ZERO_OBJECT = IMPL_LOOKUP.findStatic(ValueConversions.class, "zeroObject", zeroObjectType);
IGNORE = IMPL_LOOKUP.findStatic(ValueConversions.class, "ignore", ignoreType); IGNORE = IMPL_LOOKUP.findStatic(ValueConversions.class, "ignore", ignoreType);
EMPTY = IMPL_LOOKUP.findStatic(ValueConversions.class, "empty", ignoreType.dropParameterType(0)); EMPTY = IMPL_LOOKUP.findStatic(ValueConversions.class, "empty", ignoreType.dropParameterTypes(0, 1));
} catch (RuntimeException ex) { } catch (RuntimeException ex) {
throw ex; throw ex;
} }
...@@ -543,10 +579,10 @@ public class ValueConversions { ...@@ -543,10 +579,10 @@ public class ValueConversions {
else if (VerifyType.isNullType(type)) else if (VerifyType.isNullType(type))
mh = ALWAYS_NULL; mh = ALWAYS_NULL;
else else
mh = MethodHandles.insertArgument(CAST_REFERENCE, 0, type); mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type);
if (exact) { if (exact) {
MethodType xmt = MethodType.make(type, Object.class); MethodType xmt = MethodType.methodType(type, Object.class);
mh = AdapterMethodHandle.makeRawRetypeOnly(IMPL_TOKEN, xmt, mh); mh = AdapterMethodHandle.makeRetypeRaw(IMPL_TOKEN, xmt, mh);
} }
if (cache != null) if (cache != null)
cache.put(wrap, mh); cache.put(wrap, mh);
...@@ -560,4 +596,127 @@ public class ValueConversions { ...@@ -560,4 +596,127 @@ public class ValueConversions {
private static MethodHandle retype(MethodType type, MethodHandle mh) { private static MethodHandle retype(MethodType type, MethodHandle mh) {
return AdapterMethodHandle.makeRetypeOnly(IMPL_TOKEN, type, mh); return AdapterMethodHandle.makeRetypeOnly(IMPL_TOKEN, type, mh);
} }
private static final Object[] NO_ARGS_ARRAY = {};
private static Object[] makeArray(Object... args) { return args; }
private static Object[] array() { return NO_ARGS_ARRAY; }
private static Object[] array(Object a0)
{ return makeArray(a0); }
private static Object[] array(Object a0, Object a1)
{ return makeArray(a0, a1); }
private static Object[] array(Object a0, Object a1, Object a2)
{ return makeArray(a0, a1, a2); }
private static Object[] array(Object a0, Object a1, Object a2, Object a3)
{ return makeArray(a0, a1, a2, a3); }
private static Object[] array(Object a0, Object a1, Object a2, Object a3,
Object a4)
{ return makeArray(a0, a1, a2, a3, a4); }
private static Object[] array(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5)
{ return makeArray(a0, a1, a2, a3, a4, a5); }
private static Object[] array(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5, Object a6)
{ return makeArray(a0, a1, a2, a3, a4, a5, a6); }
private static Object[] array(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5, Object a6, Object a7)
{ return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); }
private static Object[] array(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5, Object a6, Object a7,
Object a8)
{ return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
private static Object[] array(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5, Object a6, Object a7,
Object a8, Object a9)
{ return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
static MethodHandle[] makeArrays() {
ArrayList<MethodHandle> arrays = new ArrayList<MethodHandle>();
MethodHandles.Lookup lookup = IMPL_LOOKUP;
for (;;) {
int nargs = arrays.size();
MethodType type = MethodType.genericMethodType(nargs).changeReturnType(Object[].class);
String name = "array";
MethodHandle array = null;
try {
array = lookup.findStatic(ValueConversions.class, name, type);
} catch (NoAccessException ex) {
}
if (array == null) break;
arrays.add(array);
}
assert(arrays.size() == 11); // current number of methods
return arrays.toArray(new MethodHandle[0]);
}
static final MethodHandle[] ARRAYS = makeArrays();
/** Return a method handle that takes the indicated number of Object
* arguments and returns an Object array of them, as if for varargs.
*/
public static MethodHandle varargsArray(int nargs) {
if (nargs < ARRAYS.length)
return ARRAYS[nargs];
// else need to spin bytecode or do something else fancy
throw new UnsupportedOperationException("NYI");
}
private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY);
private static List<Object> makeList(Object... args) { return Arrays.asList(args); }
private static List<Object> list() { return NO_ARGS_LIST; }
private static List<Object> list(Object a0)
{ return makeList(a0); }
private static List<Object> list(Object a0, Object a1)
{ return makeList(a0, a1); }
private static List<Object> list(Object a0, Object a1, Object a2)
{ return makeList(a0, a1, a2); }
private static List<Object> list(Object a0, Object a1, Object a2, Object a3)
{ return makeList(a0, a1, a2, a3); }
private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
Object a4)
{ return makeList(a0, a1, a2, a3, a4); }
private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5)
{ return makeList(a0, a1, a2, a3, a4, a5); }
private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5, Object a6)
{ return makeList(a0, a1, a2, a3, a4, a5, a6); }
private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5, Object a6, Object a7)
{ return makeList(a0, a1, a2, a3, a4, a5, a6, a7); }
private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5, Object a6, Object a7,
Object a8)
{ return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5, Object a6, Object a7,
Object a8, Object a9)
{ return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
static MethodHandle[] makeLists() {
ArrayList<MethodHandle> arrays = new ArrayList<MethodHandle>();
MethodHandles.Lookup lookup = IMPL_LOOKUP;
for (;;) {
int nargs = arrays.size();
MethodType type = MethodType.genericMethodType(nargs).changeReturnType(List.class);
String name = "list";
MethodHandle array = null;
try {
array = lookup.findStatic(ValueConversions.class, name, type);
} catch (NoAccessException ex) {
}
if (array == null) break;
arrays.add(array);
}
assert(arrays.size() == 11); // current number of methods
return arrays.toArray(new MethodHandle[0]);
}
static final MethodHandle[] LISTS = makeLists();
/** Return a method handle that takes the indicated number of Object
* arguments and returns List.
*/
public static MethodHandle varargsList(int nargs) {
if (nargs < LISTS.length)
return LISTS[nargs];
// else need to spin bytecode or do something else fancy
throw new UnsupportedOperationException("NYI");
}
} }
...@@ -26,8 +26,12 @@ ...@@ -26,8 +26,12 @@
package sun.dyn.util; package sun.dyn.util;
import java.dyn.LinkagePermission; import java.dyn.LinkagePermission;
import java.dyn.MethodHandles.Lookup;
import java.dyn.NoAccessException;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import sun.dyn.Access; import sun.dyn.MemberName;
import sun.dyn.MethodHandleImpl;
import sun.dyn.empty.Empty;
/** /**
* This class centralizes information about the JVM's linkage access control. * This class centralizes information about the JVM's linkage access control.
...@@ -45,21 +49,21 @@ public class VerifyAccess { ...@@ -45,21 +49,21 @@ public class VerifyAccess {
* <p> * <p>
* Some circumstances require an additional check on the * Some circumstances require an additional check on the
* leading parameter (the receiver) of the method, if it is non-static. * leading parameter (the receiver) of the method, if it is non-static.
* In the case of {@code invokespecial} ({@code doDispatch} is false), * In the case of {@code invokespecial} ({@code isSpecialInvoke} is true),
* the leading parameter must be the accessing class or a subclass. * the leading parameter must be the accessing class or a subclass.
* In the case of a call to a {@code protected} method outside the same * In the case of a call to a {@code protected} method outside the same
* package, the same constraint applies. * package, the same constraint applies.
* @param m the proposed callee * @param m the proposed callee
* @param doDispatch if false, a non-static m will be invoked as if by {@code invokespecial} * @param isSpecialInvoke if true, a non-static method m is checked as if for {@code invokespecial}
* @param lookupClass the class for which the access check is being made * @param lookupClass the class for which the access check is being made
* @return null if the method is not accessible, else a receiver type constraint, else {@code Object.class} * @return null if the method is not accessible, else a receiver type constraint, else {@code Object.class}
*/ */
public static Class<?> isAccessible(Class<?> defc, int mods, public static Class<?> isAccessible(Class<?> defc, int mods,
boolean doDispatch, Class<?> lookupClass) { Class<?> lookupClass, boolean isSpecialInvoke) {
if (!isAccessible(defc, lookupClass)) if (!isAccessible(defc, lookupClass))
return null; return null;
Class<?> constraint = Object.class; Class<?> constraint = Object.class;
if (!doDispatch && !Modifier.isStatic(mods)) { if (isSpecialInvoke && !Modifier.isStatic(mods)) {
constraint = lookupClass; constraint = lookupClass;
} }
if (Modifier.isPublic(mods)) if (Modifier.isPublic(mods))
...@@ -166,4 +170,38 @@ public class VerifyAccess { ...@@ -166,4 +170,38 @@ public class VerifyAccess {
if (isSamePackage(requestingClass, subjectClass)) return; if (isSamePackage(requestingClass, subjectClass)) return;
security.checkPermission(new LinkagePermission(permissionName, requestingClass)); security.checkPermission(new LinkagePermission(permissionName, requestingClass));
} }
private static RuntimeException checkNameFailed(MemberName self, Lookup lookup, String comment) {
return new NoAccessException("cannot access from "+lookup+": "+self.toString()+": "+comment);
}
public static void checkName(MemberName self, Lookup lookup) {
Class<?> lc = lookup.lookupClass();
if (lc == null) return; // lookup is privileged
Class<?> dc = self.getDeclaringClass();
int samepkg = 0;
// First check the containing class. Must be public or local.
if (!Modifier.isPublic(dc.getModifiers())) {
if (lc != Empty.class)
samepkg = (isSamePackage(dc, lc) ? 1 : -1);
if (samepkg <= 0)
throw checkNameFailed(self, lookup, "class is not public");
}
// At this point dc is known to be accessible.
if (self.isPublic()) {
return;
} else if (lc == Empty.class) {
throw checkNameFailed(self, lookup, "member is not public");
} else if (self.isProtected()) {
if (dc.isAssignableFrom(lc)) return;
} else if (self.isPrivate()) {
if (isSamePackageMember(dc, lc)) return;
throw checkNameFailed(self, lookup, "member is private");
}
// Fall-through handles the package-private and protected cases.
if (samepkg == 0)
samepkg = (isSamePackage(dc, lc) ? 1 : -1);
if (samepkg > 0) return;
throw checkNameFailed(self, lookup,
self.isProtected() ? "member is protected" : "member is private to package");
}
} }
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
package sun.dyn.util; package sun.dyn.util;
import java.dyn.MethodType; import java.dyn.MethodType;
import sun.dyn.empty.Empty;
/** /**
* This class centralizes information about the JVM verifier * This class centralizes information about the JVM verifier
...@@ -73,29 +74,28 @@ public class VerifyType { ...@@ -73,29 +74,28 @@ public class VerifyType {
} }
/** /**
* Is the given type either java.lang.Void or java.lang.Null? * Is the given type java.lang.Null or an equivalent null-only type?
* These types serve as markers for bare nulls and therefore
* may be promoted to any type. This is secure, since
*/ */
public static boolean isNullType(Class<?> type) { public static boolean isNullType(Class<?> type) {
if (type == null) return false; if (type == null) return false;
return type == NULL_CLASS_1 || type == NULL_CLASS_2; return type == NULL_CLASS
// This one may also be used as a null type.
// TO DO: Decide if we really want to legitimize it here.
// Probably we do, unless java.lang.Null really makes it into Java 7
//|| type == Void.class
// Locally known null-only class:
|| type == Empty.class
;
} }
private static final Class<?> NULL_CLASS_1, NULL_CLASS_2; private static final Class<?> NULL_CLASS;
static { static {
Class<?> nullClass1 = null, nullClass2 = null; Class<?> nullClass = null;
try { try {
nullClass1 = Class.forName("java.lang.Null"); nullClass = Class.forName("java.lang.Null");
} catch (ClassNotFoundException ex) { } catch (ClassNotFoundException ex) {
// OK, we'll cope // OK, we'll cope
} }
NULL_CLASS_1 = nullClass1; NULL_CLASS = nullClass;
// This one may also be used as a null type.
// TO DO: Decide if we really want to legitimize it here.
// Probably we do, unless java.lang.Null really makes it into Java 7
nullClass2 = Void.class;
NULL_CLASS_2 = nullClass2;
} }
/** /**
...@@ -191,6 +191,11 @@ public class VerifyType { ...@@ -191,6 +191,11 @@ public class VerifyType {
// to be captured as a garbage int. // to be captured as a garbage int.
// Caller promises that the actual value will be disregarded. // Caller promises that the actual value will be disregarded.
return dst == int.class ? 1 : 0; return dst == int.class ? 1 : 0;
if (isNullType(src))
// Special permission for raw conversions: allow a null
// to be reinterpreted as anything. For objects, it is safe,
// and for primitives you get a garbage value (probably zero).
return 1;
if (!src.isPrimitive()) if (!src.isPrimitive())
return 0; return 0;
Wrapper sw = Wrapper.forPrimitiveType(src); Wrapper sw = Wrapper.forPrimitiveType(src);
......
...@@ -141,13 +141,19 @@ public enum Wrapper { ...@@ -141,13 +141,19 @@ public enum Wrapper {
* @throws IllegalArgumentException for unexpected types * @throws IllegalArgumentException for unexpected types
*/ */
public static Wrapper forPrimitiveType(Class<?> type) { public static Wrapper forPrimitiveType(Class<?> type) {
Wrapper w = findPrimitiveType(type);
if (w != null) return w;
if (type.isPrimitive())
throw new InternalError(); // redo hash function
throw newIllegalArgumentException("not primitive: "+type);
}
static Wrapper findPrimitiveType(Class<?> type) {
Wrapper w = FROM_PRIM[hashPrim(type)]; Wrapper w = FROM_PRIM[hashPrim(type)];
if (w != null && w.primitiveType == type) { if (w != null && w.primitiveType == type) {
return w; return w;
} }
if (type.isPrimitive()) return null;
throw new InternalError(); // redo hash function
throw newIllegalArgumentException("not primitive: "+type);
} }
/** Return the wrapper that wraps values into the given wrapper type. /** Return the wrapper that wraps values into the given wrapper type.
...@@ -160,7 +166,7 @@ public enum Wrapper { ...@@ -160,7 +166,7 @@ public enum Wrapper {
Wrapper w = findWrapperType(type); Wrapper w = findWrapperType(type);
if (w != null) return w; if (w != null) return w;
for (Wrapper x : values()) for (Wrapper x : values())
if (w.wrapperType == type) if (x.wrapperType == type)
throw new InternalError(); // redo hash function throw new InternalError(); // redo hash function
throw newIllegalArgumentException("not wrapper: "+type); throw newIllegalArgumentException("not wrapper: "+type);
} }
...@@ -244,8 +250,10 @@ public enum Wrapper { ...@@ -244,8 +250,10 @@ public enum Wrapper {
public Class<?> wrapperType() { return wrapperType; } public Class<?> wrapperType() { return wrapperType; }
/** What is the wrapper type for this wrapper? /** What is the wrapper type for this wrapper?
* The example type must be the wrapper type, * Otherwise, the example type must be the wrapper type,
* or the corresponding primitive type. * or the corresponding primitive type.
* (For {@code OBJECT}, the example type can be any non-primitive,
* and is normalized to {@code Object.class}.)
* The resulting class type has the same type parameter. * The resulting class type has the same type parameter.
*/ */
public <T> Class<T> wrapperType(Class<T> exampleType) { public <T> Class<T> wrapperType(Class<T> exampleType) {
...@@ -290,6 +298,16 @@ public enum Wrapper { ...@@ -290,6 +298,16 @@ public enum Wrapper {
return type.isPrimitive(); return type.isPrimitive();
} }
/** What is the bytecode signature character for this type?
* All non-primitives, including array types, report as 'L', the signature character for references.
*/
public static char basicTypeChar(Class<?> type) {
if (!type.isPrimitive())
return 'L';
else
return forPrimitiveType(type).basicTypeChar();
}
/** What is the bytecode signature character for this wrapper's /** What is the bytecode signature character for this wrapper's
* primitive type? * primitive type?
*/ */
...@@ -309,7 +327,7 @@ public enum Wrapper { ...@@ -309,7 +327,7 @@ public enum Wrapper {
/** Cast a wrapped value to the given type, which may be either a primitive or wrapper type. /** Cast a wrapped value to the given type, which may be either a primitive or wrapper type.
* Performs standard primitive conversions, including truncation and float conversions. * Performs standard primitive conversions, including truncation and float conversions.
* The given type must be compatible with this wrapper. That is, it must either * The given type must be compatible with this wrapper. That is, it must either
* be the wrapper type (or a subtype, in the case of {@code OBJECT} or else * be the wrapper type (or a subtype, in the case of {@code OBJECT}) or else
* it must be the wrapper's primitive type. * it must be the wrapper's primitive type.
* @throws ClassCastException if the given type is not compatible with this wrapper * @throws ClassCastException if the given type is not compatible with this wrapper
*/ */
...@@ -326,9 +344,17 @@ public enum Wrapper { ...@@ -326,9 +344,17 @@ public enum Wrapper {
* If the target type is a primitive, change it to a wrapper. * If the target type is a primitive, change it to a wrapper.
*/ */
static <T> Class<T> forceType(Class<?> type, Class<T> exampleType) { static <T> Class<T> forceType(Class<?> type, Class<T> exampleType) {
boolean z = (type == exampleType ||
type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
type == Object.class && !exampleType.isPrimitive());
if (!z)
System.out.println(type+" <= "+exampleType);
assert(type == exampleType || assert(type == exampleType ||
type == asWrapperType(exampleType) || type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
type == Object.class && exampleType.isInterface()); exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
type == Object.class && !exampleType.isPrimitive());
@SuppressWarnings("unchecked")
Class<T> result = (Class<T>) type; // unchecked warning is expected here Class<T> result = (Class<T>) type; // unchecked warning is expected here
return result; return result;
} }
......
...@@ -35,9 +35,10 @@ import java.dyn.*; ...@@ -35,9 +35,10 @@ import java.dyn.*;
import java.dyn.MethodHandles.Lookup; import java.dyn.MethodHandles.Lookup;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.*; import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.junit.*; import org.junit.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.junit.Assume.assumeTrue;
/** /**
...@@ -66,28 +67,37 @@ public class MethodHandlesTest { ...@@ -66,28 +67,37 @@ public class MethodHandlesTest {
} finally { verbosity -= 9; } } finally { verbosity -= 9; }
} }
// current failures
@Test @Ignore("failure in call to makeRawRetypeOnly in ToGeneric")
public void testFail_1() throws Throwable {
testSpreadArguments(int.class, 0, 6);
}
@Test @Ignore("failure in JVM when expanding the stack")
public void testFail_2() throws Throwable {
// if CONV_OP_IMPLEMENTED_MASK includes OP_SPREAD_ARGS, this crashes:
testSpreadArguments(Object.class, 0, 2);
}
@Test @Ignore("IllArgEx failure in call to ToGeneric.make")
public void testFail_3() throws Throwable {
testSpreadArguments(int.class, 1, 2);
}
@Test @Ignore("IllArgEx failure in call to ToGeneric.make")
public void testFail_4() throws Throwable {
testCollectArguments(int.class, 1, 2);
}
@Test @Ignore("cannot collect leading primitive types")
public void testFail_5() throws Throwable {
testInvokers(MethodType.genericMethodType(2).changeParameterType(0, int.class));
}
@Test @Ignore("should not insert arguments beyond MethodHandlePushLimit")
public void testFail_6() throws Throwable {
testInsertArguments(0, 0, MAX_ARG_INCREASE+1);
}
static final int MAX_ARG_INCREASE = 3; static final int MAX_ARG_INCREASE = 3;
public MethodHandlesTest() { public MethodHandlesTest() {
} }
@Before
public void checkImplementedPlatform() {
boolean platformOK = false;
Properties properties = System.getProperties();
String vers = properties.getProperty("java.vm.version");
String name = properties.getProperty("java.vm.name");
String arch = properties.getProperty("os.arch");
if (arch.equals("i386") &&
(name.contains("Client") || name.contains("Server"))
) {
platformOK = true;
} else {
System.err.println("Skipping tests for unsupported platform: "+Arrays.asList(vers, name, arch));
}
assumeTrue(platformOK);
}
String testName; String testName;
int posTests, negTests; int posTests, negTests;
@After @After
...@@ -171,6 +181,10 @@ public class MethodHandlesTest { ...@@ -171,6 +181,10 @@ public class MethodHandlesTest {
return (float)(value); return (float)(value);
if (dst == double.class || dst == Double.class) if (dst == double.class || dst == Double.class)
return (double)(value); return (double)(value);
if (dst == byte.class || dst == Byte.class)
return (byte)(value);
if (dst == boolean.class || dst == boolean.class)
return ((value % 29) & 1) == 0;
return null; return null;
} }
...@@ -249,7 +263,7 @@ public class MethodHandlesTest { ...@@ -249,7 +263,7 @@ public class MethodHandlesTest {
end = Math.min(end, targetType.parameterCount()); end = Math.min(end, targetType.parameterCount());
ArrayList<Class<?>> argTypes = new ArrayList<Class<?>>(targetType.parameterList()); ArrayList<Class<?>> argTypes = new ArrayList<Class<?>>(targetType.parameterList());
Collections.fill(argTypes.subList(beg, end), argType); Collections.fill(argTypes.subList(beg, end), argType);
MethodType ttype2 = MethodType.make(targetType.returnType(), argTypes); MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes);
return MethodHandles.convertArguments(target, ttype2); return MethodHandles.convertArguments(target, ttype2);
} }
...@@ -258,7 +272,7 @@ public class MethodHandlesTest { ...@@ -258,7 +272,7 @@ public class MethodHandlesTest {
// This lookup is good for package-private members but not private ones. // This lookup is good for package-private members but not private ones.
static final Lookup PACKAGE = PackageSibling.lookup(); static final Lookup PACKAGE = PackageSibling.lookup();
// This lookup is good only for public members. // This lookup is good only for public members.
static final Lookup PUBLIC = MethodHandles.Lookup.PUBLIC_LOOKUP; static final Lookup PUBLIC = MethodHandles.publicLookup();
// Subject methods... // Subject methods...
static class Example implements IntExample { static class Example implements IntExample {
...@@ -306,11 +320,24 @@ public class MethodHandlesTest { ...@@ -306,11 +320,24 @@ public class MethodHandlesTest {
} }
static final Object[][][] ACCESS_CASES = { static final Object[][][] ACCESS_CASES = {
{ { true, PRIVATE } } // only one test case at present { { false, PUBLIC }, { false, PACKAGE }, { false, PRIVATE } },
{ { false, PUBLIC }, { false, PACKAGE }, { true, PRIVATE } },
{ { false, PUBLIC }, { true, PACKAGE }, { true, PRIVATE } },
{ { true, PUBLIC }, { true, PACKAGE }, { true, PRIVATE } },
}; };
static Object[][] accessCases(Class<?> defc, String name) { static Object[][] accessCases(Class<?> defc, String name) {
return ACCESS_CASES[0]; if (name.contains("pri_")) {
return ACCESS_CASES[1]; // PRIVATE only
} else if (name.contains("pkg_")) {
return ACCESS_CASES[2]; // not PUBLIC
} else {
assertTrue(name.indexOf('_') < 0);
boolean pubc = Modifier.isPublic(defc.getModifiers());
if (pubc)
return ACCESS_CASES[3]; // all access levels
return ACCESS_CASES[2]; // PACKAGE but not PUBLIC
}
} }
@Test @Test
...@@ -343,7 +370,7 @@ public class MethodHandlesTest { ...@@ -343,7 +370,7 @@ public class MethodHandlesTest {
} }
void testFindStatic(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { void testFindStatic(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
countTest(positive); countTest(positive);
MethodType type = MethodType.make(ret, params); MethodType type = MethodType.methodType(ret, params);
MethodHandle target = null; MethodHandle target = null;
RuntimeException noAccess = null; RuntimeException noAccess = null;
try { try {
...@@ -362,7 +389,7 @@ public class MethodHandlesTest { ...@@ -362,7 +389,7 @@ public class MethodHandlesTest {
if (!DO_MORE_CALLS && lookup != PRIVATE) return; if (!DO_MORE_CALLS && lookup != PRIVATE) return;
Object[] args = randomArgs(params); Object[] args = randomArgs(params);
printCalled(target, name, args); printCalled(target, name, args);
MethodHandles.invoke(target, args); target.invokeVarargs(args);
assertCalled(name, args); assertCalled(name, args);
System.out.print(':'); System.out.print(':');
} }
...@@ -405,7 +432,7 @@ public class MethodHandlesTest { ...@@ -405,7 +432,7 @@ public class MethodHandlesTest {
void testFindVirtual(boolean positive, Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { void testFindVirtual(boolean positive, Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
countTest(positive); countTest(positive);
String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo
MethodType type = MethodType.make(ret, params); MethodType type = MethodType.methodType(ret, params);
MethodHandle target = null; MethodHandle target = null;
RuntimeException noAccess = null; RuntimeException noAccess = null;
try { try {
...@@ -420,7 +447,7 @@ public class MethodHandlesTest { ...@@ -420,7 +447,7 @@ public class MethodHandlesTest {
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
if (!positive) return; // negative test failed as expected if (!positive) return; // negative test failed as expected
Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params); Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params);
MethodType typeWithSelf = MethodType.make(ret, paramsWithSelf); MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
MethodType ttype = target.type(); MethodType ttype = target.type();
ttype = ttype.changeParameterType(0, defc); // FIXME: test this ttype = ttype.changeParameterType(0, defc); // FIXME: test this
assertEquals(typeWithSelf, ttype); assertEquals(typeWithSelf, ttype);
...@@ -429,7 +456,7 @@ public class MethodHandlesTest { ...@@ -429,7 +456,7 @@ public class MethodHandlesTest {
Object[] argsWithSelf = randomArgs(paramsWithSelf); Object[] argsWithSelf = randomArgs(paramsWithSelf);
if (rcvc != defc) argsWithSelf[0] = randomArg(rcvc); if (rcvc != defc) argsWithSelf[0] = randomArg(rcvc);
printCalled(target, name, argsWithSelf); printCalled(target, name, argsWithSelf);
MethodHandles.invoke(target, argsWithSelf); target.invokeVarargs(argsWithSelf);
assertCalled(name, argsWithSelf); assertCalled(name, argsWithSelf);
System.out.print(':'); System.out.print(':');
} }
...@@ -451,7 +478,7 @@ public class MethodHandlesTest { ...@@ -451,7 +478,7 @@ public class MethodHandlesTest {
} }
void testFindSpecial(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { void testFindSpecial(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
countTest(positive); countTest(positive);
MethodType type = MethodType.make(ret, params); MethodType type = MethodType.methodType(ret, params);
MethodHandle target = null; MethodHandle target = null;
RuntimeException noAccess = null; RuntimeException noAccess = null;
try { try {
...@@ -466,7 +493,7 @@ public class MethodHandlesTest { ...@@ -466,7 +493,7 @@ public class MethodHandlesTest {
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
if (!positive) return; // negative test failed as expected if (!positive) return; // negative test failed as expected
Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params); Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params);
MethodType typeWithSelf = MethodType.make(ret, paramsWithSelf); MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
MethodType ttype = target.type(); MethodType ttype = target.type();
ttype = ttype.changeParameterType(0, defc); // FIXME: test this ttype = ttype.changeParameterType(0, defc); // FIXME: test this
assertEquals(typeWithSelf, ttype); assertEquals(typeWithSelf, ttype);
...@@ -474,7 +501,7 @@ public class MethodHandlesTest { ...@@ -474,7 +501,7 @@ public class MethodHandlesTest {
if (!DO_MORE_CALLS && lookup != PRIVATE) return; if (!DO_MORE_CALLS && lookup != PRIVATE) return;
Object[] args = randomArgs(paramsWithSelf); Object[] args = randomArgs(paramsWithSelf);
printCalled(target, name, args); printCalled(target, name, args);
MethodHandles.invoke(target, args); target.invokeVarargs(args);
assertCalled(name, args); assertCalled(name, args);
System.out.print(':'); System.out.print(':');
} }
...@@ -506,7 +533,7 @@ public class MethodHandlesTest { ...@@ -506,7 +533,7 @@ public class MethodHandlesTest {
void testBind(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable { void testBind(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
countTest(positive); countTest(positive);
String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo
MethodType type = MethodType.make(ret, params); MethodType type = MethodType.methodType(ret, params);
Object receiver = randomArg(defc); Object receiver = randomArg(defc);
MethodHandle target = null; MethodHandle target = null;
RuntimeException noAccess = null; RuntimeException noAccess = null;
...@@ -524,7 +551,7 @@ public class MethodHandlesTest { ...@@ -524,7 +551,7 @@ public class MethodHandlesTest {
assertEquals(type, target.type()); assertEquals(type, target.type());
Object[] args = randomArgs(params); Object[] args = randomArgs(params);
printCalled(target, name, args); printCalled(target, name, args);
MethodHandles.invoke(target, args); target.invokeVarargs(args);
Object[] argsWithReceiver = cat(array(Object[].class, receiver), args); Object[] argsWithReceiver = cat(array(Object[].class, receiver), args);
assertCalled(name, argsWithReceiver); assertCalled(name, argsWithReceiver);
System.out.print(':'); System.out.print(':');
...@@ -562,7 +589,7 @@ public class MethodHandlesTest { ...@@ -562,7 +589,7 @@ public class MethodHandlesTest {
} }
void testUnreflect(boolean positive, Lookup lookup, Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) throws Throwable { void testUnreflect(boolean positive, Lookup lookup, Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) throws Throwable {
countTest(positive); countTest(positive);
MethodType type = MethodType.make(ret, params); MethodType type = MethodType.methodType(ret, params);
Method rmethod = null; Method rmethod = null;
MethodHandle target = null; MethodHandle target = null;
RuntimeException noAccess = null; RuntimeException noAccess = null;
...@@ -587,14 +614,14 @@ public class MethodHandlesTest { ...@@ -587,14 +614,14 @@ public class MethodHandlesTest {
if (!isStatic) { if (!isStatic) {
paramsMaybeWithSelf = cat(array(Class[].class, (Class)defc), params); paramsMaybeWithSelf = cat(array(Class[].class, (Class)defc), params);
} }
MethodType typeMaybeWithSelf = MethodType.make(ret, paramsMaybeWithSelf); MethodType typeMaybeWithSelf = MethodType.methodType(ret, paramsMaybeWithSelf);
MethodType ttype = target.type(); MethodType ttype = target.type();
if (!isStatic) if (!isStatic)
ttype = ttype.changeParameterType(0, defc); // FIXME: test this ttype = ttype.changeParameterType(0, defc); // FIXME: test this
assertEquals(typeMaybeWithSelf, ttype); assertEquals(typeMaybeWithSelf, ttype);
Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf); Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf);
printCalled(target, name, argsMaybeWithSelf); printCalled(target, name, argsMaybeWithSelf);
MethodHandles.invoke(target, argsMaybeWithSelf); target.invokeVarargs(argsMaybeWithSelf);
assertCalled(name, argsMaybeWithSelf); assertCalled(name, argsMaybeWithSelf);
System.out.print(':'); System.out.print(':');
} }
...@@ -610,46 +637,238 @@ public class MethodHandlesTest { ...@@ -610,46 +637,238 @@ public class MethodHandlesTest {
fail("The test case is a prototype."); fail("The test case is a prototype.");
} }
@Test @Ignore("unimplemented") public static class HasFields {
boolean fZ = false;
byte fB = (byte)'B';
short fS = (short)'S';
char fC = 'C';
int fI = 'I';
long fJ = 'J';
float fF = 'F';
double fD = 'D';
static boolean sZ = true;
static byte sB = 1+(byte)'B';
static short sS = 1+(short)'S';
static char sC = 1+'C';
static int sI = 1+'I';
static long sJ = 1+'J';
static float sF = 1+'F';
static double sD = 1+'D';
Object fL = 'L';
String fR = "R";
static Object sL = 'M';
static String sR = "S";
static final Object[][] CASES;
static {
ArrayList<Object[]> cases = new ArrayList<Object[]>();
Object types[][] = {
{'L',Object.class}, {'R',String.class},
{'I',int.class}, {'J',long.class},
{'F',float.class}, {'D',double.class},
{'Z',boolean.class}, {'B',byte.class},
{'S',short.class}, {'C',char.class},
};
HasFields fields = new HasFields();
for (Object[] t : types) {
for (int kind = 0; kind <= 1; kind++) {
boolean isStatic = (kind != 0);
char btc = (Character)t[0];
String name = (isStatic ? "s" : "f") + btc;
Class<?> type = (Class<?>) t[1];
Object value;
Field field;
try {
field = HasFields.class.getDeclaredField(name);
} catch (Exception ex) {
throw new InternalError("no field HasFields."+name);
}
try {
value = field.get(fields);
} catch (Exception ex) {
throw new InternalError("cannot fetch field HasFields."+name);
}
if (type == float.class) {
float v = 'F';
if (isStatic) v++;
assert(value.equals(v));
}
assert(name.equals(field.getName()));
assert(type.equals(field.getType()));
assert(isStatic == (Modifier.isStatic(field.getModifiers())));
cases.add(new Object[]{ field, value });
}
}
CASES = cases.toArray(new Object[0][]);
}
}
@Test
public void testUnreflectGetter() throws Throwable { public void testUnreflectGetter() throws Throwable {
Lookup lookup = PRIVATE; // FIXME: test more lookups than this one Lookup lookup = PRIVATE; // FIXME: test more lookups than this one
startTest("unreflectGetter"); startTest("unreflectGetter");
Field f = null; for (Object[] c : HasFields.CASES) {
MethodHandle expResult = null; Field f = (Field)c[0];
MethodHandle result = lookup.unreflectGetter(f); Object value = c[1];
assertEquals(expResult, result); Class<?> type = f.getType();
fail("The test case is a prototype."); if (type.isPrimitive() && type != int.class)
continue; //FIXME
testUnreflectGetter(lookup, f, type, value);
}
}
public void testUnreflectGetter(MethodHandles.Lookup lookup,
Field f, Class<?> type, Object value) throws Throwable {
countTest(true);
boolean isStatic = Modifier.isStatic(f.getModifiers());
MethodType expType = MethodType.methodType(type, HasFields.class);
if (isStatic) expType = expType.dropParameterTypes(0, 1);
MethodHandle mh = lookup.unreflectGetter(f);
assertSame(mh.type(), expType);
assertEquals(mh.toString(), f.getName());
HasFields fields = new HasFields();
Object sawValue;
Class<?> rtype = type;
if (type != int.class) rtype = Object.class;
mh = MethodHandles.convertArguments(mh, mh.type().generic().changeReturnType(rtype));
Object expValue = value;
for (int i = 0; i <= 1; i++) {
if (isStatic) {
if (type == int.class)
sawValue = mh.<int>invoke(); // do these exactly
else
sawValue = mh.invoke();
} else {
if (type == int.class)
sawValue = mh.<int>invoke((Object) fields);
else
sawValue = mh.invoke((Object) fields);
}
assertEquals(sawValue, expValue);
Object random = randomArg(type);
f.set(fields, random);
expValue = random;
}
f.set(fields, value); // put it back
} }
@Test @Ignore("unimplemented")
@Test
public void testUnreflectSetter() throws Throwable { public void testUnreflectSetter() throws Throwable {
Lookup lookup = PRIVATE; // FIXME: test more lookups than this one Lookup lookup = PRIVATE; // FIXME: test more lookups than this one
startTest("unreflectSetter"); startTest("unreflectSetter");
Field f = null; for (Object[] c : HasFields.CASES) {
MethodHandle expResult = null; Field f = (Field)c[0];
MethodHandle result = lookup.unreflectSetter(f); Object value = c[1];
assertEquals(expResult, result); Class<?> type = f.getType();
fail("The test case is a prototype."); if (type.isPrimitive() && type != int.class)
continue; //FIXME
testUnreflectSetter(lookup, f, type, value);
}
}
public void testUnreflectSetter(MethodHandles.Lookup lookup,
Field f, Class<?> type, Object value) throws Throwable {
countTest(true);
boolean isStatic = Modifier.isStatic(f.getModifiers());
MethodType expType = MethodType.methodType(void.class, HasFields.class, type);
if (isStatic) expType = expType.dropParameterTypes(0, 1);
MethodHandle mh = lookup.unreflectSetter(f);
assertSame(mh.type(), expType);
assertEquals(mh.toString(), f.getName());
HasFields fields = new HasFields();
Object sawValue;
Class<?> vtype = type;
if (type != int.class) vtype = Object.class;
int last = mh.type().parameterCount() - 1;
mh = MethodHandles.convertArguments(mh, mh.type().generic().changeReturnType(void.class).changeParameterType(last, vtype));
assertEquals(f.get(fields), value); // clean to start with
for (int i = 0; i <= 1; i++) {
Object putValue = randomArg(type);
if (isStatic) {
if (type == int.class)
mh.<void>invoke((int)(Integer)putValue); // do these exactly
else
mh.<void>invoke(putValue);
} else {
if (type == int.class)
mh.<void>invoke((Object) fields, (int)(Integer)putValue);
else
mh.<void>invoke((Object) fields, putValue);
}
assertEquals(f.get(fields), putValue);
}
f.set(fields, value); // put it back
} }
@Test @Ignore("unimplemented") @Test
public void testArrayElementGetter() throws Throwable { public void testArrayElementGetter() throws Throwable {
startTest("arrayElementGetter"); startTest("arrayElementGetter");
Class<?> arrayClass = null; testArrayElementGetterSetter(new Object[10], false);
MethodHandle expResult = null; testArrayElementGetterSetter(new String[10], false);
MethodHandle result = MethodHandles.arrayElementGetter(arrayClass); testArrayElementGetterSetter(new int[10], false);
assertEquals(expResult, result); // FIXME: Do the other primitive types.
fail("The test case is a prototype."); //testArrayElementGetterSetter(new float[10], false);
} }
@Test @Ignore("unimplemented") @Test
public void testArrayElementSetter() throws Throwable { public void testArrayElementSetter() throws Throwable {
startTest("arrayElementSetter"); startTest("arrayElementSetter");
Class<?> arrayClass = null; testArrayElementGetterSetter(new Object[10], true);
MethodHandle expResult = null; testArrayElementGetterSetter(new String[10], true);
MethodHandle result = MethodHandles.arrayElementSetter(arrayClass); testArrayElementGetterSetter(new int[10], true);
assertEquals(expResult, result); // FIXME: Do the other primitive types.
fail("The test case is a prototype."); //testArrayElementGetterSetter(new float[10], true);
}
public void testArrayElementGetterSetter(Object array, boolean testSetter) throws Throwable {
countTest(true);
Class<?> arrayType = array.getClass();
Class<?> elemType = arrayType.getComponentType();
MethodType expType = !testSetter
? MethodType.methodType(elemType, arrayType, int.class)
: MethodType.methodType(void.class, arrayType, int.class, elemType);
MethodHandle mh = !testSetter
? MethodHandles.arrayElementGetter(arrayType)
: MethodHandles.arrayElementSetter(arrayType);
assertSame(mh.type(), expType);
//assertEquals(mh.toString(), f.getName());
Object sawValue, expValue;
List<Object> model = array2list(array);
int length = Array.getLength(array);
for (int i = 0; i < length; i++) {
// update array element
Object random = randomArg(elemType);
model.set(i, random);
if (testSetter) {
if (elemType == int.class)
mh.<void>invoke((int[]) array, i, (int)(Integer)random);
else
mh.invokeGeneric(array, i, random);
assertEquals(model, array2list(array));
} else {
Array.set(array, i, random);
}
// observe array element
sawValue = Array.get(array, i);
if (!testSetter) {
expValue = sawValue;
if (elemType == int.class)
sawValue = mh.<int>invoke((int[]) array, i);
else
sawValue = mh.invokeGeneric(array, i);
assertEquals(sawValue, expValue);
assertEquals(model, array2list(array));
}
}
}
List<Object> array2list(Object array) {
int length = Array.getLength(array);
ArrayList<Object> model = new ArrayList<Object>(length);
for (int i = 0; i < length; i++)
model.add(Array.get(array, i));
return model;
} }
static class Callee { static class Callee {
...@@ -663,11 +882,11 @@ public class MethodHandlesTest { ...@@ -663,11 +882,11 @@ public class MethodHandlesTest {
} }
static MethodHandle ofType(Class<?> rtype, int n) { static MethodHandle ofType(Class<?> rtype, int n) {
if (n == -1) if (n == -1)
return ofType(MethodType.make(rtype, Object[].class)); return ofType(MethodType.methodType(rtype, Object[].class));
return ofType(MethodType.makeGeneric(n).changeReturnType(rtype)); return ofType(MethodType.genericMethodType(n).changeReturnType(rtype));
} }
static MethodHandle ofType(Class<?> rtype, Class<?>... ptypes) { static MethodHandle ofType(Class<?> rtype, Class<?>... ptypes) {
return ofType(MethodType.make(rtype, ptypes)); return ofType(MethodType.methodType(rtype, ptypes));
} }
static MethodHandle ofType(MethodType type) { static MethodHandle ofType(MethodType type) {
Class<?> rtype = type.returnType(); Class<?> rtype = type.returnType();
...@@ -701,7 +920,7 @@ public class MethodHandlesTest { ...@@ -701,7 +920,7 @@ public class MethodHandlesTest {
if (params[i] == null) params[i] = idType.parameterType(i); if (params[i] == null) params[i] = idType.parameterType(i);
} }
// simulate the pairwise conversion // simulate the pairwise conversion
MethodType newType = MethodType.make(rtype, params); MethodType newType = MethodType.methodType(rtype, params);
Object[] args = randomArgs(newType.parameterArray()); Object[] args = randomArgs(newType.parameterArray());
Object[] convArgs = args.clone(); Object[] convArgs = args.clone();
for (int i = 0; i < args.length; i++) { for (int i = 0; i < args.length; i++) {
...@@ -710,7 +929,7 @@ public class MethodHandlesTest { ...@@ -710,7 +929,7 @@ public class MethodHandlesTest {
if (src != dst) if (src != dst)
convArgs[i] = castToWrapper(convArgs[i], dst); convArgs[i] = castToWrapper(convArgs[i], dst);
} }
Object convResult = MethodHandles.invoke(id, convArgs); Object convResult = id.invokeVarargs(convArgs);
{ {
Class<?> dst = newType.returnType(); Class<?> dst = newType.returnType();
Class<?> src = idType.returnType(); Class<?> src = idType.returnType();
...@@ -732,12 +951,232 @@ public class MethodHandlesTest { ...@@ -732,12 +951,232 @@ public class MethodHandlesTest {
if (!positive) return; // negative test failed as expected if (!positive) return; // negative test failed as expected
assertEquals(newType, target.type()); assertEquals(newType, target.type());
printCalled(target, id.toString(), args); printCalled(target, id.toString(), args);
Object result = MethodHandles.invoke(target, args); Object result = target.invokeVarargs(args);
assertCalled(name, convArgs); assertCalled(name, convArgs);
assertEquals(convResult, result); assertEquals(convResult, result);
System.out.print(':'); System.out.print(':');
} }
@Test
public void testPermuteArguments() throws Throwable {
if (CAN_SKIP_WORKING) return;
startTest("permuteArguments");
testPermuteArguments(4, Integer.class, 2, String.class, 0);
//testPermuteArguments(6, Integer.class, 0, null, 30);
//testPermuteArguments(4, Integer.class, 1, int.class, 6);
}
public void testPermuteArguments(int max, Class<?> type1, int t2c, Class<?> type2, int dilution) throws Throwable {
if (verbosity >= 1)
System.out.println("permuteArguments "+max+"*"+type1.getName()
+(t2c==0?"":"/"+t2c+"*"+type2.getName())
+(dilution > 0 ? " with dilution "+dilution : ""));
int t2pos = t2c == 0 ? 0 : 1;
for (int inargs = t2pos+1; inargs <= max; inargs++) {
Class<?>[] types = new Class<?>[inargs];
Arrays.fill(types, type1);
if (t2c != 0) {
// Fill in a middle range with type2:
Arrays.fill(types, t2pos, Math.min(t2pos+t2c, inargs), type2);
}
Object[] args = randomArgs(types);
int numcases = 1;
for (int outargs = 0; outargs <= max; outargs++) {
if (outargs - inargs >= MAX_ARG_INCREASE) continue;
int[] reorder = new int[outargs];
int casStep = dilution + 1;
// Avoid some common factors:
while ((casStep > 2 && casStep % 2 == 0 && inargs % 2 == 0) ||
(casStep > 3 && casStep % 3 == 0 && inargs % 3 == 0))
casStep++;
for (int cas = 0; cas < numcases; cas += casStep) {
for (int i = 0, c = cas; i < outargs; i++) {
reorder[i] = c % inargs;
c /= inargs;
}
testPermuteArguments(args, types, reorder);
}
numcases *= inargs;
if (dilution > 10 && outargs >= 4) {
// Do some special patterns, which we probably missed.
// Replication of a single argument or argument pair.
for (int i = 0; i < inargs; i++) {
Arrays.fill(reorder, i);
testPermuteArguments(args, types, reorder);
for (int d = 1; d <= 2; d++) {
if (i + d >= inargs) continue;
for (int j = 1; j < outargs; j += 2)
reorder[j] += 1;
testPermuteArguments(args, types, reorder);
testPermuteArguments(args, types, reverse(reorder));
}
}
// Repetition of a sequence of 3 or more arguments.
for (int i = 1; i < inargs; i++) {
for (int len = 3; len <= inargs; len++) {
for (int j = 0; j < outargs; j++)
reorder[j] = (i + (j % len)) % inargs;
testPermuteArguments(args, types, reorder);
testPermuteArguments(args, types, reverse(reorder));
}
}
}
}
}
}
static int[] reverse(int[] reorder) {
reorder = reorder.clone();
for (int i = 0, imax = reorder.length / 2; i < imax; i++) {
int j = reorder.length - 1 - i;
int tem = reorder[i];
reorder[i] = reorder[j];
reorder[j] = tem;
}
return reorder;
}
void testPermuteArguments(Object[] args, Class<?>[] types, int[] reorder) throws Throwable {
countTest();
if (args == null && types == null) {
int max = 0;
for (int j : reorder) {
if (max < j) max = j;
}
args = randomArgs(max+1, Integer.class);
}
if (args == null) {
args = randomArgs(types);
}
if (types == null) {
types = new Class<?>[args.length];
for (int i = 0; i < args.length; i++)
types[i] = args[i].getClass();
}
int inargs = args.length, outargs = reorder.length;
assert(inargs == types.length);
if (verbosity >= 2)
System.out.println("permuteArguments "+Arrays.toString(reorder));
Object[] permArgs = new Object[outargs];
Class<?>[] permTypes = new Class<?>[outargs];
for (int i = 0; i < outargs; i++) {
permArgs[i] = args[reorder[i]];
permTypes[i] = types[reorder[i]];
}
if (verbosity >= 3) {
System.out.println("in args: "+Arrays.asList(args));
System.out.println("out args: "+Arrays.asList(permArgs));
System.out.println("in types: "+Arrays.asList(types));
System.out.println("out types: "+Arrays.asList(permTypes));
}
MethodType inType = MethodType.methodType(Object.class, types);
MethodType outType = MethodType.methodType(Object.class, permTypes);
MethodHandle target = MethodHandles.convertArguments(ValueConversions.varargsList(outargs), outType);
MethodHandle newTarget = MethodHandles.permuteArguments(target, inType, reorder);
Object result = newTarget.invokeVarargs(args);
Object expected = Arrays.asList(permArgs);
assertEquals(expected, result);
}
@Test
public void testSpreadArguments() throws Throwable {
if (CAN_SKIP_WORKING) return;
startTest("spreadArguments");
for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
if (verbosity >= 2)
System.out.println("spreadArguments "+argType);
for (int nargs = 0; nargs < 10; nargs++) {
if (argType == int.class && nargs >= 6) continue; // FIXME Fail_1
for (int pos = 0; pos < nargs; pos++) {
if (argType == int.class && pos > 0) continue; // FIXME Fail_3
testSpreadArguments(argType, pos, nargs);
}
}
}
}
public void testSpreadArguments(Class<?> argType, int pos, int nargs) throws Throwable {
countTest();
MethodHandle target = ValueConversions.varargsArray(nargs);
MethodHandle target2 = changeArgTypes(target, argType);
if (verbosity >= 2)
System.out.println("spread into "+target2+" ["+pos+".."+nargs+"]");
Object[] args = randomArgs(target2.type().parameterArray());
// make sure the target does what we think it does:
if (pos == 0 && nargs < 5) {
Object[] check = (Object[]) target.invokeVarargs(args);
assertArrayEquals(args, check);
switch (nargs) {
case 0:
check = target.<Object[]>invoke();
assertArrayEquals(args, check);
break;
case 1:
check = target.<Object[]>invoke(args[0]);
assertArrayEquals(args, check);
break;
case 2:
check = target.<Object[]>invoke(args[0], args[1]);
assertArrayEquals(args, check);
break;
}
}
List<Class<?>> newParams = new ArrayList<Class<?>>(target2.type().parameterList());
{ // modify newParams in place
List<Class<?>> spreadParams = newParams.subList(pos, nargs);
spreadParams.clear(); spreadParams.add(Object[].class);
}
MethodType newType = MethodType.methodType(Object.class, newParams);
MethodHandle result = MethodHandles.spreadArguments(target2, newType);
Object[] returnValue;
if (pos == 0) {
returnValue = (Object[]) result.invoke(args);
} else {
Object[] args1 = Arrays.copyOfRange(args, 0, pos+1);
args1[pos] = Arrays.copyOfRange(args, pos, args.length);
returnValue = (Object[]) result.invokeVarargs(args1);
}
assertArrayEquals(args, returnValue);
}
@Test
public void testCollectArguments() throws Throwable {
if (CAN_SKIP_WORKING) return;
startTest("collectArguments");
for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
if (verbosity >= 2)
System.out.println("collectArguments "+argType);
for (int nargs = 0; nargs < 10; nargs++) {
for (int pos = 0; pos < nargs; pos++) {
if (argType == int.class) continue; // FIXME Fail_4
testCollectArguments(argType, pos, nargs);
}
}
}
}
public void testCollectArguments(Class<?> argType, int pos, int nargs) throws Throwable {
countTest();
// fake up a MH with the same type as the desired adapter:
MethodHandle fake = ValueConversions.varargsArray(nargs);
fake = changeArgTypes(fake, argType);
MethodType newType = fake.type();
Object[] args = randomArgs(newType.parameterArray());
// here is what should happen:
Object[] collectedArgs = Arrays.copyOfRange(args, 0, pos+1);
collectedArgs[pos] = Arrays.copyOfRange(args, pos, args.length);
// here is the MH which will witness the collected argument tail:
MethodHandle target = ValueConversions.varargsArray(pos+1);
target = changeArgTypes(target, 0, pos, argType);
target = changeArgTypes(target, pos, pos+1, Object[].class);
if (verbosity >= 2)
System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]");
MethodHandle result = MethodHandles.collectArguments(target, newType);
Object[] returnValue = (Object[]) result.invokeVarargs(args);
// assertTrue(returnValue.length == pos+1 && returnValue[pos] instanceof Object[]);
// returnValue[pos] = Arrays.asList((Object[]) returnValue[pos]);
// collectedArgs[pos] = Arrays.asList((Object[]) collectedArgs[pos]);
assertArrayEquals(collectedArgs, returnValue);
}
@Test @Test
public void testInsertArguments() throws Throwable { public void testInsertArguments() throws Throwable {
if (CAN_SKIP_WORKING) return; if (CAN_SKIP_WORKING) return;
...@@ -753,7 +1192,6 @@ public class MethodHandlesTest { ...@@ -753,7 +1192,6 @@ public class MethodHandlesTest {
} }
void testInsertArguments(int nargs, int pos, int ins) throws Throwable { void testInsertArguments(int nargs, int pos, int ins) throws Throwable {
if (pos != 0 || ins != 1) return; // temp. restriction until MHs.insertArguments
countTest(); countTest();
MethodHandle target = ValueConversions.varargsArray(nargs + ins); MethodHandle target = ValueConversions.varargsArray(nargs + ins);
Object[] args = randomArgs(target.type().parameterArray()); Object[] args = randomArgs(target.type().parameterArray());
...@@ -762,10 +1200,10 @@ public class MethodHandlesTest { ...@@ -762,10 +1200,10 @@ public class MethodHandlesTest {
List<Object> argsToInsert = argsToPass.subList(pos, pos + ins); List<Object> argsToInsert = argsToPass.subList(pos, pos + ins);
if (verbosity >= 2) if (verbosity >= 2)
System.out.println("insert: "+argsToInsert+" into "+target); System.out.println("insert: "+argsToInsert+" into "+target);
MethodHandle target2 = MethodHandles.insertArgument(target, pos, MethodHandle target2 = MethodHandles.insertArguments(target, pos,
argsToInsert.get(0)); (Object[]) argsToInsert.toArray());
argsToInsert.clear(); // remove from argsToInsert argsToInsert.clear(); // remove from argsToInsert
Object res2 = MethodHandles.invoke(target2, argsToPass.toArray()); Object res2 = target2.invokeVarargs(argsToPass);
Object res2List = Arrays.asList((Object[])res2); Object res2List = Arrays.asList((Object[])res2);
if (verbosity >= 2) if (verbosity >= 2)
System.out.println("result: "+res2List); System.out.println("result: "+res2List);
...@@ -774,6 +1212,244 @@ public class MethodHandlesTest { ...@@ -774,6 +1212,244 @@ public class MethodHandlesTest {
assertEquals(resList, res2List); assertEquals(resList, res2List);
} }
@Test
public void testFilterArguments() throws Throwable {
if (CAN_SKIP_WORKING) return;
startTest("filterArguments");
for (int nargs = 1; nargs <= 6; nargs++) {
for (int pos = 0; pos < nargs; pos++) {
testFilterArguments(nargs, pos);
}
}
}
void testFilterArguments(int nargs, int pos) throws Throwable {
countTest();
MethodHandle target = ValueConversions.varargsList(nargs);
MethodHandle filter = ValueConversions.varargsList(1);
filter = MethodHandles.convertArguments(filter, filter.type().generic());
Object[] argsToPass = randomArgs(nargs, Object.class);
if (verbosity >= 2)
System.out.println("filter "+target+" at "+pos+" with "+filter);
MethodHandle[] filters = new MethodHandle[pos*2+1];
filters[pos] = filter;
MethodHandle target2 = MethodHandles.filterArguments(target, filters);
// Simulate expected effect of filter on arglist:
Object[] filteredArgs = argsToPass.clone();
filteredArgs[pos] = filter.invoke(filteredArgs[pos]);
List<Object> expected = Arrays.asList(filteredArgs);
Object result = target2.invokeVarargs(argsToPass);
if (verbosity >= 2)
System.out.println("result: "+result);
if (!expected.equals(result))
System.out.println("*** fail at n/p = "+nargs+"/"+pos+": "+argsToPass+" => "+result);
assertEquals(expected, result);
}
@Test
public void testFoldArguments() throws Throwable {
if (CAN_SKIP_WORKING) return;
startTest("foldArguments");
for (int nargs = 0; nargs <= 4; nargs++) {
for (int fold = 0; fold <= nargs; fold++) {
for (int pos = 0; pos <= nargs; pos++) {
testFoldArguments(nargs, pos, fold);
}
}
}
}
void testFoldArguments(int nargs, int pos, int fold) throws Throwable {
if (pos != 0) return; // can fold only at pos=0 for now
countTest();
MethodHandle target = ValueConversions.varargsList(1 + nargs);
MethodHandle combine = ValueConversions.varargsList(fold);
List<Object> argsToPass = Arrays.asList(randomArgs(nargs, Object.class));
if (verbosity >= 2)
System.out.println("fold "+target+" with "+combine);
MethodHandle target2 = MethodHandles.foldArguments(target, combine);
// Simulate expected effect of combiner on arglist:
List<Object> expected = new ArrayList<Object>(argsToPass);
List<Object> argsToFold = expected.subList(pos, pos + fold);
if (verbosity >= 2)
System.out.println("fold: "+argsToFold+" into "+target2);
Object foldedArgs = combine.invokeVarargs(argsToFold);
argsToFold.add(0, foldedArgs);
Object result = target2.invokeVarargs(argsToPass);
if (verbosity >= 2)
System.out.println("result: "+result);
if (!expected.equals(result))
System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result);
assertEquals(expected, result);
}
@Test
public void testDropArguments() throws Throwable {
if (CAN_SKIP_WORKING) return;
startTest("dropArguments");
for (int nargs = 0; nargs <= 4; nargs++) {
for (int drop = 1; drop <= 4; drop++) {
for (int pos = 0; pos <= nargs; pos++) {
testDropArguments(nargs, pos, drop);
}
}
}
}
void testDropArguments(int nargs, int pos, int drop) throws Throwable {
countTest();
MethodHandle target = ValueConversions.varargsArray(nargs);
Object[] args = randomArgs(target.type().parameterArray());
MethodHandle target2 = MethodHandles.dropArguments(target, pos,
Collections.nCopies(drop, Object.class).toArray(new Class[0]));
List<Object> resList = Arrays.asList(args);
List<Object> argsToDrop = new ArrayList<Object>(resList);
for (int i = drop; i > 0; i--) {
argsToDrop.add(pos, "blort#"+i);
}
Object res2 = target2.invokeVarargs(argsToDrop);
Object res2List = Arrays.asList((Object[])res2);
//if (!resList.equals(res2List))
// System.out.println("*** fail at n/p/d = "+nargs+"/"+pos+"/"+drop+": "+argsToDrop+" => "+res2List);
assertEquals(resList, res2List);
}
@Test
public void testInvokers() throws Throwable {
if (CAN_SKIP_WORKING) return;
startTest("exactInvoker, genericInvoker, varargsInvoker, dynamicInvoker");
// exactInvoker, genericInvoker, varargsInvoker[0..N], dynamicInvoker
Set<MethodType> done = new HashSet<MethodType>();
for (int i = 0; i <= 6; i++) {
MethodType gtype = MethodType.genericMethodType(i);
for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
for (int j = -1; j < i; j++) {
MethodType type = gtype;
if (j < 0)
type = type.changeReturnType(argType);
else if (argType == void.class)
continue;
else
type = type.changeParameterType(j, argType);
if (argType.isPrimitive() && j != i-1) continue; // FIXME Fail_5
if (done.add(type))
testInvokers(type);
MethodType vtype = type.changeReturnType(void.class);
if (done.add(vtype))
testInvokers(vtype);
}
}
}
}
public void testInvokers(MethodType type) throws Throwable {
if (verbosity >= 2)
System.out.println("test invokers for "+type);
int nargs = type.parameterCount();
boolean testRetCode = type.returnType() != void.class;
MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "invokee",
MethodType.genericMethodType(0, true));
target = MethodHandles.collectArguments(target, type);
Object[] args = randomArgs(type.parameterArray());
List<Object> targetPlusArgs = new ArrayList<Object>(Arrays.asList(args));
targetPlusArgs.add(0, target);
int code = (Integer) invokee(args);
Object log = logEntry("invokee", args);
assertEquals(log.hashCode(), code);
assertCalled("invokee", args);
MethodHandle inv;
Object result;
// exact invoker
countTest();
calledLog.clear();
inv = MethodHandles.exactInvoker(type);
result = inv.invokeVarargs(targetPlusArgs);
if (testRetCode) assertEquals(code, result);
assertCalled("invokee", args);
// generic invoker
countTest();
inv = MethodHandles.genericInvoker(type);
if (nargs <= 3) {
calledLog.clear();
switch (nargs) {
case 0:
result = inv.invoke(target);
break;
case 1:
result = inv.invoke(target, args[0]);
break;
case 2:
result = inv.invoke(target, args[0], args[1]);
break;
case 3:
result = inv.invoke(target, args[0], args[1], args[2]);
break;
}
if (testRetCode) assertEquals(code, result);
assertCalled("invokee", args);
}
calledLog.clear();
result = inv.invokeVarargs(targetPlusArgs);
if (testRetCode) assertEquals(code, result);
assertCalled("invokee", args);
// varargs invoker #0
calledLog.clear();
inv = MethodHandles.varargsInvoker(type, 0);
result = inv.invoke(target, args);
if (testRetCode) assertEquals(code, result);
assertCalled("invokee", args);
if (nargs >= 1) {
// varargs invoker #1
calledLog.clear();
inv = MethodHandles.varargsInvoker(type, 1);
result = inv.invoke(target, args[0], Arrays.copyOfRange(args, 1, nargs));
if (testRetCode) assertEquals(code, result);
assertCalled("invokee", args);
}
if (nargs >= 2) {
// varargs invoker #2
calledLog.clear();
inv = MethodHandles.varargsInvoker(type, 2);
result = inv.invoke(target, args[0], args[1], Arrays.copyOfRange(args, 2, nargs));
if (testRetCode) assertEquals(code, result);
assertCalled("invokee", args);
}
if (nargs >= 3) {
// varargs invoker #3
calledLog.clear();
inv = MethodHandles.varargsInvoker(type, 3);
result = inv.invoke(target, args[0], args[1], args[2], Arrays.copyOfRange(args, 3, nargs));
if (testRetCode) assertEquals(code, result);
assertCalled("invokee", args);
}
for (int k = 0; k <= nargs; k++) {
// varargs invoker #0..N
countTest();
calledLog.clear();
inv = MethodHandles.varargsInvoker(type, k);
List<Object> targetPlusVarArgs = new ArrayList<Object>(targetPlusArgs);
List<Object> tailList = targetPlusVarArgs.subList(1+k, 1+nargs);
Object[] tail = tailList.toArray();
tailList.clear(); tailList.add(tail);
result = inv.invokeVarargs(targetPlusVarArgs);
if (testRetCode) assertEquals(code, result);
assertCalled("invokee", args);
}
// dynamic invoker
countTest();
CallSite site = new CallSite(MethodHandlesTest.class, "foo", type);
inv = MethodHandles.dynamicInvoker(site);
site.setTarget(target);
calledLog.clear();
result = inv.invokeVarargs(args);
if (testRetCode) assertEquals(code, result);
assertCalled("invokee", args);
}
static Object invokee(Object... args) {
return called("invokee", args).hashCode();
}
private static final String MISSING_ARG = "missingArg"; private static final String MISSING_ARG = "missingArg";
static Object targetIfEquals() { static Object targetIfEquals() {
return called("targetIfEquals"); return called("targetIfEquals");
...@@ -806,6 +1482,228 @@ public class MethodHandlesTest { ...@@ -806,6 +1482,228 @@ public class MethodHandlesTest {
return called("fallbackIfNotEquals", x, y, z); return called("fallbackIfNotEquals", x, y, z);
} }
@Test
public void testGuardWithTest() throws Throwable {
if (CAN_SKIP_WORKING) return;
startTest("guardWithTest");
for (int nargs = 0; nargs <= 3; nargs++) {
if (nargs != 2) continue; // FIXME: test more later
testGuardWithTest(nargs, Object.class);
testGuardWithTest(nargs, String.class);
}
}
void testGuardWithTest(int nargs, Class<?> argClass) throws Throwable {
countTest();
MethodHandle test = PRIVATE.findVirtual(Object.class, "equals", MethodType.methodType(boolean.class, Object.class));
MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "targetIfEquals", MethodType.genericMethodType(nargs));
MethodHandle fallback = PRIVATE.findStatic(MethodHandlesTest.class, "fallbackIfNotEquals", MethodType.genericMethodType(nargs));
while (test.type().parameterCount() < nargs)
test = MethodHandles.dropArguments(test, test.type().parameterCount()-1, Object.class);
while (test.type().parameterCount() > nargs)
test = MethodHandles.insertArguments(test, 0, MISSING_ARG);
if (argClass != Object.class) {
test = changeArgTypes(test, argClass);
target = changeArgTypes(target, argClass);
fallback = changeArgTypes(fallback, argClass);
}
MethodHandle mh = MethodHandles.guardWithTest(test, target, fallback);
assertEquals(target.type(), mh.type());
Object[][] argLists = {
{ },
{ "foo" }, { MISSING_ARG },
{ "foo", "foo" }, { "foo", "bar" },
{ "foo", "foo", "baz" }, { "foo", "bar", "baz" }
};
for (Object[] argList : argLists) {
if (argList.length != nargs) continue;
boolean equals;
switch (nargs) {
case 0: equals = true; break;
case 1: equals = MISSING_ARG.equals(argList[0]); break;
default: equals = argList[0].equals(argList[1]); break;
}
String willCall = (equals ? "targetIfEquals" : "fallbackIfNotEquals");
if (verbosity >= 2)
System.out.println(logEntry(willCall, argList));
Object result = mh.invokeVarargs(argList);
assertCalled(willCall, argList);
}
}
@Test
public void testCatchException() throws Throwable {
if (CAN_SKIP_WORKING) return;
startTest("catchException");
for (int nargs = 2; nargs <= 6; nargs++) {
for (int ti = 0; ti <= 1; ti++) {
boolean throwIt = (ti != 0);
testCatchException(int.class, new ClassCastException("testing"), throwIt, nargs);
testCatchException(void.class, new java.io.IOException("testing"), throwIt, nargs);
testCatchException(String.class, new LinkageError("testing"), throwIt, nargs);
}
}
}
private static <T extends Throwable>
Object throwOrReturn(Object normal, T exception) throws T {
if (exception != null) throw exception;
return normal;
}
void testCatchException(Class<?> returnType, Throwable thrown, boolean throwIt, int nargs) throws Throwable {
countTest();
if (verbosity >= 2)
System.out.println("catchException rt="+returnType+" throw="+throwIt+" nargs="+nargs);
Class<? extends Throwable> exType = thrown.getClass();
MethodHandle throwOrReturn
= PRIVATE.findStatic(MethodHandlesTest.class, "throwOrReturn",
MethodType.methodType(Object.class, Object.class, Throwable.class));
MethodHandle thrower = throwOrReturn;
while (thrower.type().parameterCount() < nargs)
thrower = MethodHandles.dropArguments(thrower, thrower.type().parameterCount(), Object.class);
MethodHandle target = MethodHandles.catchException(thrower,
thrown.getClass(), ValueConversions.varargsList(1+nargs));
assertEquals(thrower.type(), target.type());
//System.out.println("catching with "+target+" : "+throwOrReturn);
Object[] args = randomArgs(nargs, Object.class);
args[1] = (throwIt ? thrown : null);
Object returned = target.invokeVarargs(args);
//System.out.println("return from "+target+" : "+returned);
if (!throwIt) {
assertSame(args[0], returned);
} else {
List<Object> catchArgs = new ArrayList<Object>(Arrays.asList(args));
catchArgs.add(0, thrown);
assertEquals(catchArgs, returned);
}
}
@Test
public void testThrowException() throws Throwable {
if (CAN_SKIP_WORKING) return;
startTest("throwException");
testThrowException(int.class, new ClassCastException("testing"));
testThrowException(void.class, new java.io.IOException("testing"));
testThrowException(String.class, new LinkageError("testing"));
}
void testThrowException(Class<?> returnType, Throwable thrown) throws Throwable {
countTest();
Class<? extends Throwable> exType = thrown.getClass();
MethodHandle target = MethodHandles.throwException(returnType, exType);
//System.out.println("throwing with "+target+" : "+thrown);
MethodType expectedType = MethodType.methodType(returnType, exType);
assertEquals(expectedType, target.type());
Throwable caught = null;
try {
Object res = target.invokeGeneric(thrown);
fail("got "+res+" instead of throwing "+thrown);
} catch (Throwable ex) {
if (ex != thrown) {
if (ex instanceof Error) throw (Error)ex;
if (ex instanceof RuntimeException) throw (RuntimeException)ex;
}
caught = ex;
}
assertSame(thrown, caught);
}
@Test
public void testCastFailure() throws Throwable {
if (CAN_SKIP_WORKING) return;
startTest("testCastFailure");
testCastFailure("cast/argument", 11000);
testCastFailure("unbox/argument", 11000);
testCastFailure("cast/return", 11000);
testCastFailure("unbox/return", 11000);
}
static class Surprise extends JavaMethodHandle {
Surprise() { super("value"); }
Object value(Object x) {
trace("value", x);
if (boo != null) return boo;
return x;
}
Object boo;
void boo(Object x) { boo = x; }
static void trace(String x, Object y) {
if (verbosity > 8) System.out.println(x+"="+y);
}
static Object refIdentity(Object x) { trace("ref.x", x); return x; }
static Integer boxIdentity(Integer x) { trace("box.x", x); return x; }
static int intIdentity(int x) { trace("int.x", x); return x; }
static MethodHandle REF_IDENTITY = PRIVATE.findStatic(
Surprise.class, "refIdentity",
MethodType.methodType(Object.class, Object.class));
static MethodHandle BOX_IDENTITY = PRIVATE.findStatic(
Surprise.class, "boxIdentity",
MethodType.methodType(Integer.class, Integer.class));
static MethodHandle INT_IDENTITY = PRIVATE.findStatic(
Surprise.class, "intIdentity",
MethodType.methodType(int.class, int.class));
}
void testCastFailure(String mode, int okCount) throws Throwable {
countTest(false);
if (verbosity > 1) System.out.println("mode="+mode);
Surprise boo = new Surprise();
MethodHandle identity = Surprise.REF_IDENTITY, surprise = boo;
if (mode.endsWith("/return")) {
if (mode.equals("unbox/return")) {
// fail on return to ((Integer)surprise).intValue
surprise = MethodHandles.convertArguments(surprise, MethodType.methodType(int.class, Object.class));
identity = MethodHandles.convertArguments(identity, MethodType.methodType(int.class, Object.class));
} else if (mode.equals("cast/return")) {
// fail on return to (Integer)surprise
surprise = MethodHandles.convertArguments(surprise, MethodType.methodType(Integer.class, Object.class));
identity = MethodHandles.convertArguments(identity, MethodType.methodType(Integer.class, Object.class));
}
} else if (mode.endsWith("/argument")) {
MethodHandle callee = null;
if (mode.equals("unbox/argument")) {
// fail on handing surprise to int argument
callee = Surprise.INT_IDENTITY;
} else if (mode.equals("cast/argument")) {
// fail on handing surprise to Integer argument
callee = Surprise.BOX_IDENTITY;
}
if (callee != null) {
callee = MethodHandles.convertArguments(callee, MethodType.genericMethodType(1));
surprise = MethodHandles.filterArguments(callee, surprise);
identity = MethodHandles.filterArguments(callee, identity);
}
}
assertNotSame(mode, surprise, boo);
identity = MethodHandles.convertArguments(identity, MethodType.genericMethodType(1));
surprise = MethodHandles.convertArguments(surprise, MethodType.genericMethodType(1));
Object x = 42;
for (int i = 0; i < okCount; i++) {
Object y = identity.invoke(x);
assertEquals(x, y);
Object z = surprise.invoke(x);
assertEquals(x, z);
}
boo.boo("Boo!");
Object y = identity.invoke(x);
assertEquals(x, y);
try {
Object z = surprise.invoke(x);
System.out.println("Failed to throw; got z="+z);
assertTrue(false);
} catch (Exception ex) {
if (verbosity > 1)
System.out.println("caught "+ex);
if (verbosity > 2)
ex.printStackTrace();
assertTrue(ex instanceof ClassCastException
// FIXME: accept only one of the two for any given unit test
|| ex instanceof WrongMethodTypeException
);
}
}
} }
// Local abbreviated copy of sun.dyn.util.ValueConversions // Local abbreviated copy of sun.dyn.util.ValueConversions
class ValueConversions { class ValueConversions {
...@@ -846,7 +1744,7 @@ class ValueConversions { ...@@ -846,7 +1744,7 @@ class ValueConversions {
MethodHandles.Lookup lookup = IMPL_LOOKUP; MethodHandles.Lookup lookup = IMPL_LOOKUP;
for (;;) { for (;;) {
int nargs = arrays.size(); int nargs = arrays.size();
MethodType type = MethodType.makeGeneric(nargs).changeReturnType(Object[].class); MethodType type = MethodType.genericMethodType(nargs).changeReturnType(Object[].class);
String name = "array"; String name = "array";
MethodHandle array = null; MethodHandle array = null;
try { try {
...@@ -870,6 +1768,67 @@ class ValueConversions { ...@@ -870,6 +1768,67 @@ class ValueConversions {
// else need to spin bytecode or do something else fancy // else need to spin bytecode or do something else fancy
throw new UnsupportedOperationException("NYI"); throw new UnsupportedOperationException("NYI");
} }
private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY);
private static List<Object> makeList(Object... args) { return Arrays.asList(args); }
private static List<Object> list() { return NO_ARGS_LIST; }
private static List<Object> list(Object a0)
{ return makeList(a0); }
private static List<Object> list(Object a0, Object a1)
{ return makeList(a0, a1); }
private static List<Object> list(Object a0, Object a1, Object a2)
{ return makeList(a0, a1, a2); }
private static List<Object> list(Object a0, Object a1, Object a2, Object a3)
{ return makeList(a0, a1, a2, a3); }
private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
Object a4)
{ return makeList(a0, a1, a2, a3, a4); }
private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5)
{ return makeList(a0, a1, a2, a3, a4, a5); }
private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5, Object a6)
{ return makeList(a0, a1, a2, a3, a4, a5, a6); }
private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5, Object a6, Object a7)
{ return makeList(a0, a1, a2, a3, a4, a5, a6, a7); }
private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5, Object a6, Object a7,
Object a8)
{ return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
Object a4, Object a5, Object a6, Object a7,
Object a8, Object a9)
{ return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
static MethodHandle[] makeLists() {
ArrayList<MethodHandle> arrays = new ArrayList<MethodHandle>();
MethodHandles.Lookup lookup = IMPL_LOOKUP;
for (;;) {
int nargs = arrays.size();
MethodType type = MethodType.genericMethodType(nargs).changeReturnType(List.class);
String name = "list";
MethodHandle array = null;
try {
array = lookup.findStatic(ValueConversions.class, name, type);
} catch (NoAccessException ex) {
}
if (array == null) break;
arrays.add(array);
}
assert(arrays.size() == 11); // current number of methods
return arrays.toArray(new MethodHandle[0]);
}
static final MethodHandle[] LISTS = makeLists();
/** Return a method handle that takes the indicated number of Object
* arguments and returns List.
*/
public static MethodHandle varargsList(int nargs) {
if (nargs < LISTS.length)
return LISTS[nargs];
// else need to spin bytecode or do something else fancy
throw new UnsupportedOperationException("NYI");
}
} }
// This guy tests access from outside the same package member, but inside // This guy tests access from outside the same package member, but inside
// the package itself. // the package itself.
...@@ -878,4 +1837,3 @@ class PackageSibling { ...@@ -878,4 +1837,3 @@ class PackageSibling {
return MethodHandles.lookup(); return MethodHandles.lookup();
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册