提交 15350370 编写于 作者: J jrose

7034977: JSR 292 MethodHandle.invokeGeneric should be renamed MethodHandle.invoke

Summary: rename invokeGeneric to invoke
Reviewed-by: never, twisti
上级 34500ca9
...@@ -273,9 +273,9 @@ public class CallSite { ...@@ -273,9 +273,9 @@ public class CallSite {
Object binding; Object binding;
info = maybeReBox(info); info = maybeReBox(info);
if (info == null) { if (info == null) {
binding = bootstrapMethod.invokeGeneric(caller, name, type); binding = bootstrapMethod.invoke(caller, name, type);
} else if (!info.getClass().isArray()) { } else if (!info.getClass().isArray()) {
binding = bootstrapMethod.invokeGeneric(caller, name, type, info); binding = bootstrapMethod.invoke(caller, name, type, info);
} else { } else {
Object[] argv = (Object[]) info; Object[] argv = (Object[]) info;
maybeReBoxElements(argv); maybeReBoxElements(argv);
...@@ -283,10 +283,10 @@ public class CallSite { ...@@ -283,10 +283,10 @@ public class CallSite {
throw new BootstrapMethodError("too many bootstrap method arguments"); throw new BootstrapMethodError("too many bootstrap method arguments");
MethodType bsmType = bootstrapMethod.type(); MethodType bsmType = bootstrapMethod.type();
if (bsmType.parameterCount() == 4 && bsmType.parameterType(3) == Object[].class) if (bsmType.parameterCount() == 4 && bsmType.parameterType(3) == Object[].class)
binding = bootstrapMethod.invokeGeneric(caller, name, type, argv); binding = bootstrapMethod.invoke(caller, name, type, argv);
else else
binding = MethodHandles.spreadInvoker(bsmType, 3) binding = MethodHandles.spreadInvoker(bsmType, 3)
.invokeGeneric(bootstrapMethod, caller, name, type, argv); .invoke(bootstrapMethod, caller, name, type, argv);
} }
//System.out.println("BSM for "+name+type+" => "+binding); //System.out.println("BSM for "+name+type+" => "+binding);
if (binding instanceof CallSite) { if (binding instanceof CallSite) {
......
...@@ -160,7 +160,6 @@ class FromGeneric { ...@@ -160,7 +160,6 @@ class FromGeneric {
/** Build an adapter of the given generic type, which invokes typedTarget /** Build an adapter of the given generic type, which invokes typedTarget
* on the incoming arguments, after unboxing as necessary. * on the incoming arguments, after unboxing as necessary.
* The return value is boxed if necessary. * The return value is boxed if necessary.
* @param genericType the required type of the result
* @param typedTarget the target * @param typedTarget the target
* @return an adapter method handle * @return an adapter method handle
*/ */
......
...@@ -29,12 +29,12 @@ import sun.invoke.util.*; ...@@ -29,12 +29,12 @@ import sun.invoke.util.*;
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
/** /**
* Adapters which manage MethodHandle.invokeGeneric calls. * Adapters which manage inexact MethodHandle.invoke calls.
* The JVM calls one of these when the exact type match fails. * The JVM calls one of these when the exact type match fails.
* @author jrose * @author jrose
*/ */
class InvokeGeneric { class InvokeGeneric {
// erased type for the call, which originates from an invokeGeneric site // erased type for the call, which originates from an inexact invoke site
private final MethodType erasedCallerType; private final MethodType erasedCallerType;
// an invoker of type (MT, MH; A...) -> R // an invoker of type (MT, MH; A...) -> R
private final MethodHandle initialInvoker; private final MethodHandle initialInvoker;
...@@ -56,7 +56,7 @@ class InvokeGeneric { ...@@ -56,7 +56,7 @@ class InvokeGeneric {
} }
/** Return the adapter information for this type's erasure. */ /** Return the adapter information for this type's erasure. */
/*non-public*/ static MethodHandle genericInvokerOf(MethodType erasedCallerType) throws ReflectiveOperationException { /*non-public*/ static MethodHandle generalInvokerOf(MethodType erasedCallerType) throws ReflectiveOperationException {
InvokeGeneric gen = new InvokeGeneric(erasedCallerType); InvokeGeneric gen = new InvokeGeneric(erasedCallerType);
return gen.initialInvoker; return gen.initialInvoker;
} }
......
...@@ -43,10 +43,10 @@ class Invokers { ...@@ -43,10 +43,10 @@ class Invokers {
private /*lazy*/ MethodHandle erasedInvoker; private /*lazy*/ MethodHandle erasedInvoker;
/*lazy*/ MethodHandle erasedInvokerWithDrops; // for InvokeGeneric /*lazy*/ MethodHandle erasedInvokerWithDrops; // for InvokeGeneric
// generic (untyped) invoker for the outgoing call // general invoker for the outgoing call
private /*lazy*/ MethodHandle genericInvoker; private /*lazy*/ MethodHandle generalInvoker;
// generic (untyped) invoker for the outgoing call; accepts a single Object[] // general invoker for the outgoing call; accepts a single Object[]
private final /*lazy*/ MethodHandle[] spreadInvokers; private final /*lazy*/ MethodHandle[] spreadInvokers;
// invoker for an unbound callsite // invoker for an unbound callsite
...@@ -77,13 +77,13 @@ class Invokers { ...@@ -77,13 +77,13 @@ class Invokers {
return invoker; return invoker;
} }
/*non-public*/ MethodHandle genericInvoker() { /*non-public*/ MethodHandle generalInvoker() {
MethodHandle invoker1 = exactInvoker(); MethodHandle invoker1 = exactInvoker();
MethodHandle invoker = genericInvoker; MethodHandle invoker = generalInvoker;
if (invoker != null) return invoker; if (invoker != null) return invoker;
MethodType genericType = targetType.generic(); MethodType generalType = targetType.generic();
invoker = MethodHandles.convertArguments(invoker1, invokerType(genericType)); invoker = MethodHandles.convertArguments(invoker1, invokerType(generalType));
genericInvoker = invoker; generalInvoker = invoker;
return invoker; return invoker;
} }
...@@ -93,7 +93,7 @@ class Invokers { ...@@ -93,7 +93,7 @@ class Invokers {
if (invoker != null) return invoker; if (invoker != null) return invoker;
MethodType erasedType = targetType.erase(); MethodType erasedType = targetType.erase();
if (erasedType == targetType.generic()) if (erasedType == targetType.generic())
invoker = genericInvoker(); invoker = generalInvoker();
else else
invoker = MethodHandles.convertArguments(invoker1, invokerType(erasedType)); invoker = MethodHandles.convertArguments(invoker1, invokerType(erasedType));
erasedInvoker = invoker; erasedInvoker = invoker;
...@@ -103,7 +103,7 @@ class Invokers { ...@@ -103,7 +103,7 @@ class Invokers {
/*non-public*/ MethodHandle spreadInvoker(int objectArgCount) { /*non-public*/ MethodHandle spreadInvoker(int objectArgCount) {
MethodHandle vaInvoker = spreadInvokers[objectArgCount]; MethodHandle vaInvoker = spreadInvokers[objectArgCount];
if (vaInvoker != null) return vaInvoker; if (vaInvoker != null) return vaInvoker;
MethodHandle gInvoker = genericInvoker(); MethodHandle gInvoker = generalInvoker();
vaInvoker = gInvoker.asSpreader(Object[].class, targetType.parameterCount() - objectArgCount); vaInvoker = gInvoker.asSpreader(Object[].class, targetType.parameterCount() - objectArgCount);
spreadInvokers[objectArgCount] = vaInvoker; spreadInvokers[objectArgCount] = vaInvoker;
return vaInvoker; return vaInvoker;
......
...@@ -53,12 +53,12 @@ import static java.lang.invoke.MethodHandleStatics.*; ...@@ -53,12 +53,12 @@ import static java.lang.invoke.MethodHandleStatics.*;
* and the kinds of transformations that apply to it. * and the kinds of transformations that apply to it.
* <p> * <p>
* A method handle contains a pair of special invoker methods * A method handle contains a pair of special invoker methods
* called {@link #invokeExact invokeExact} and {@link #invokeGeneric invokeGeneric}. * called {@link #invokeExact invokeExact} and {@link #invoke invoke}.
* Both invoker methods provide direct access to the method handle's * Both invoker methods provide direct access to the method handle's
* underlying method, constructor, field, or other operation, * underlying method, constructor, field, or other operation,
* as modified by transformations of arguments and return values. * as modified by transformations of arguments and return values.
* Both invokers accept calls which exactly match the method handle's own type. * Both invokers accept calls which exactly match the method handle's own type.
* The {@code invokeGeneric} invoker also accepts a range of other call types. * The plain, inexact invoker also accepts a range of other call types.
* <p> * <p>
* Method handles are immutable and have no visible state. * Method handles are immutable and have no visible state.
* Of course, they can be bound to underlying methods or data which exhibit state. * Of course, they can be bound to underlying methods or data which exhibit state.
...@@ -76,7 +76,7 @@ import static java.lang.invoke.MethodHandleStatics.*; ...@@ -76,7 +76,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
* may change from time to time or across implementations from different vendors. * may change from time to time or across implementations from different vendors.
* *
* <h3>Method handle compilation</h3> * <h3>Method handle compilation</h3>
* A Java method call expression naming {@code invokeExact} or {@code invokeGeneric} * A Java method call expression naming {@code invokeExact} or {@code invoke}
* can invoke a method handle from Java source code. * can invoke a method handle from Java source code.
* From the viewpoint of source code, these methods can take any arguments * From the viewpoint of source code, these methods can take any arguments
* and their result can be cast to any return type. * and their result can be cast to any return type.
...@@ -86,7 +86,7 @@ import static java.lang.invoke.MethodHandleStatics.*; ...@@ -86,7 +86,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
* which connects this freedom of invocation directly to the JVM execution stack. * which connects this freedom of invocation directly to the JVM execution stack.
* <p> * <p>
* As is usual with virtual methods, source-level calls to {@code invokeExact} * As is usual with virtual methods, source-level calls to {@code invokeExact}
* and {@code invokeGeneric} compile to an {@code invokevirtual} instruction. * and {@code invoke} compile to an {@code invokevirtual} instruction.
* More unusually, the compiler must record the actual argument types, * More unusually, the compiler must record the actual argument types,
* and may not perform method invocation conversions on the arguments. * and may not perform method invocation conversions on the arguments.
* Instead, it must push them on the stack according to their own unconverted types. * Instead, it must push them on the stack according to their own unconverted types.
...@@ -109,7 +109,7 @@ import static java.lang.invoke.MethodHandleStatics.*; ...@@ -109,7 +109,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
* The first time a {@code invokevirtual} instruction is executed * The first time a {@code invokevirtual} instruction is executed
* it is linked, by symbolically resolving the names in the instruction * it is linked, by symbolically resolving the names in the instruction
* and verifying that the method call is statically legal. * and verifying that the method call is statically legal.
* This is true of calls to {@code invokeExact} and {@code invokeGeneric}. * This is true of calls to {@code invokeExact} and {@code invoke}.
* In this case, the type descriptor emitted by the compiler is checked for * In this case, the type descriptor emitted by the compiler is checked for
* correct syntax and names it contains are resolved. * correct syntax and names it contains are resolved.
* Thus, an {@code invokevirtual} instruction which invokes * Thus, an {@code invokevirtual} instruction which invokes
...@@ -127,18 +127,18 @@ import static java.lang.invoke.MethodHandleStatics.*; ...@@ -127,18 +127,18 @@ import static java.lang.invoke.MethodHandleStatics.*;
* In the case of {@code invokeExact}, the type descriptor of the invocation * In the case of {@code invokeExact}, the type descriptor of the invocation
* (after resolving symbolic type names) must exactly match the method type * (after resolving symbolic type names) must exactly match the method type
* of the receiving method handle. * of the receiving method handle.
* In the case of {@code invokeGeneric}, the resolved type descriptor * In the case of plain, inexact {@code invoke}, the resolved type descriptor
* must be a valid argument to the receiver's {@link #asType asType} method. * must be a valid argument to the receiver's {@link #asType asType} method.
* Thus, {@code invokeGeneric} is more permissive than {@code invokeExact}. * Thus, plain {@code invoke} is more permissive than {@code invokeExact}.
* <p> * <p>
* After type matching, a call to {@code invokeExact} directly * After type matching, a call to {@code invokeExact} directly
* and immediately invoke the method handle's underlying method * and immediately invoke the method handle's underlying method
* (or other behavior, as the case may be). * (or other behavior, as the case may be).
* <p> * <p>
* A call to {@code invokeGeneric} works the same as a call to * A call to plain {@code invoke} works the same as a call to
* {@code invokeExact}, if the type descriptor specified by the caller * {@code invokeExact}, if the type descriptor specified by the caller
* exactly matches the method handle's own type. * exactly matches the method handle's own type.
* If there is a type mismatch, {@code invokeGeneric} attempts * If there is a type mismatch, {@code invoke} attempts
* to adjust the type of the receiving method handle, * to adjust the type of the receiving method handle,
* as if by a call to {@link #asType asType}, * as if by a call to {@link #asType asType},
* to obtain an exactly invokable method handle {@code M2}. * to obtain an exactly invokable method handle {@code M2}.
...@@ -152,7 +152,7 @@ import static java.lang.invoke.MethodHandleStatics.*; ...@@ -152,7 +152,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
* In typical programs, method handle type matching will usually succeed. * In typical programs, method handle type matching will usually succeed.
* But if a match fails, the JVM will throw a {@link WrongMethodTypeException}, * But if a match fails, the JVM will throw a {@link WrongMethodTypeException},
* either directly (in the case of {@code invokeExact}) or indirectly as if * either directly (in the case of {@code invokeExact}) or indirectly as if
* by a failed call to {@code asType} (in the case of {@code invokeGeneric}). * by a failed call to {@code asType} (in the case of {@code invoke}).
* <p> * <p>
* Thus, a method type mismatch which might show up as a linkage error * Thus, a method type mismatch which might show up as a linkage error
* in a statically typed program can show up as * in a statically typed program can show up as
...@@ -249,8 +249,8 @@ assert(s.equals("savvy")); ...@@ -249,8 +249,8 @@ assert(s.equals("savvy"));
mt = MethodType.methodType(java.util.List.class, Object[].class); mt = MethodType.methodType(java.util.List.class, Object[].class);
mh = lookup.findStatic(java.util.Arrays.class, "asList", mt); mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
assert(mh.isVarargsCollector()); assert(mh.isVarargsCollector());
x = mh.invokeGeneric("one", "two"); x = mh.invoke("one", "two");
// invokeGeneric(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object; // invoke(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
assert(x.equals(java.util.Arrays.asList("one","two"))); assert(x.equals(java.util.Arrays.asList("one","two")));
// mt is (Object,Object,Object)Object // mt is (Object,Object,Object)Object
mt = MethodType.genericMethodType(3); mt = MethodType.genericMethodType(3);
...@@ -269,12 +269,12 @@ mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt); ...@@ -269,12 +269,12 @@ mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt);
mh.invokeExact(System.out, "Hello, world."); mh.invokeExact(System.out, "Hello, world.");
// invokeExact(Ljava/io/PrintStream;Ljava/lang/String;)V // invokeExact(Ljava/io/PrintStream;Ljava/lang/String;)V
* </pre></blockquote> * </pre></blockquote>
* Each of the above calls to {@code invokeExact} or {@code invokeGeneric} * Each of the above calls to {@code invokeExact} or plain {@code invoke}
* generates a single invokevirtual instruction with * generates a single invokevirtual instruction with
* the type descriptor indicated in the following comment. * the type descriptor indicated in the following comment.
* *
* <h3>Exceptions</h3> * <h3>Exceptions</h3>
* The methods {@code invokeExact} and {@code invokeGeneric} are declared * The methods {@code invokeExact} and {@code invoke} are declared
* to throw {@link java.lang.Throwable Throwable}, * to throw {@link java.lang.Throwable Throwable},
* which is to say that there is no static restriction on what a method handle * 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 * can throw. Since the JVM does not distinguish between checked
...@@ -288,7 +288,7 @@ mh.invokeExact(System.out, "Hello, world."); ...@@ -288,7 +288,7 @@ mh.invokeExact(System.out, "Hello, world.");
* *
* <h3><a name="sigpoly"></a>Signature polymorphism</h3> * <h3><a name="sigpoly"></a>Signature polymorphism</h3>
* The unusual compilation and linkage behavior of * The unusual compilation and linkage behavior of
* {@code invokeExact} and {@code invokeGeneric} * {@code invokeExact} and plain {@code invoke}
* is referenced by the term <em>signature polymorphism</em>. * is referenced by the term <em>signature polymorphism</em>.
* A signature polymorphic method is one which can operate with * A signature polymorphic method is one which can operate with
* any of a wide range of call signatures and return types. * any of a wide range of call signatures and return types.
...@@ -322,7 +322,7 @@ mh.invokeExact(System.out, "Hello, world."); ...@@ -322,7 +322,7 @@ mh.invokeExact(System.out, "Hello, world.");
* The following methods (and no others) are signature polymorphic: * The following methods (and no others) are signature polymorphic:
* <ul> * <ul>
* <li>{@link java.lang.invoke.MethodHandle#invokeExact MethodHandle.invokeExact} * <li>{@link java.lang.invoke.MethodHandle#invokeExact MethodHandle.invokeExact}
* <li>{@link java.lang.invoke.MethodHandle#invokeGeneric MethodHandle.invokeGeneric} * <li>{@link java.lang.invoke.MethodHandle#invoke MethodHandle.invoke}
* </ul> * </ul>
* <p> * <p>
* A signature polymorphic method will be declared with the following properties: * A signature polymorphic method will be declared with the following properties:
...@@ -374,24 +374,34 @@ mh.invokeExact(System.out, "Hello, world."); ...@@ -374,24 +374,34 @@ mh.invokeExact(System.out, "Hello, world.");
* <p> * <p>
* As a special case, * As a special case,
* when the Core Reflection API is used to view the signature polymorphic * when the Core Reflection API is used to view the signature polymorphic
* methods {@code invokeExact} or {@code invokeGeneric} in this class, * methods {@code invokeExact} or plain {@code invoke} in this class,
* they appear as single, non-polymorphic native methods. * they appear as ordinary non-polymorphic methods.
* Calls to these native methods do not result in method handle invocations. * Their reflective appearance, as viewed by
* {@link java.lang.Class#getDeclaredMethod Class.getDeclaredMethod},
* is unaffected by their special status in this API.
* For example, {@link java.lang.reflect.Method#getModifiers Method.getModifiers}
* will report exactly those modifier bits required for any similarly
* declared method, including in this case {@code native} and {@code varargs} bits.
* <p>
* As with any reflected method, these methods (when reflected) may be
* invoked via {@link java.lang.reflect.Method#invoke Method.invoke}.
* However, such reflective calls do not result in method handle invocations.
* Such a call, if passed the required argument
* (a single one, of type {@code Object[]}), will ignore the argument and
* will throw an {@code UnsupportedOperationException}.
* <p>
* Since {@code invokevirtual} instructions can natively * Since {@code invokevirtual} instructions can natively
* invoke method handles under any type descriptor, this reflective view conflicts * invoke method handles under any type descriptor, this reflective view conflicts
* with the normal presentation via bytecodes. * with the normal presentation of these methods via bytecodes.
* Thus, these two native methods, as viewed by * Thus, these two native methods, when reflectively viewed by
* {@link java.lang.Class#getDeclaredMethod Class.getDeclaredMethod}, * {@code Class.getDeclaredMethod}, may be regarded as placeholders only.
* are placeholders only.
* If invoked via {@link java.lang.reflect.Method#invoke Method.invoke},
* they will throw {@code UnsupportedOperationException}.
* <p> * <p>
* In order to obtain an invoker method for a particular type descriptor, * In order to obtain an invoker method for a particular type descriptor,
* use {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker}, * use {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker},
* or {@link java.lang.invoke.MethodHandles#genericInvoker MethodHandles.genericInvoker}. * or {@link java.lang.invoke.MethodHandles#invoker MethodHandles.invoker}.
* The {@link java.lang.invoke.MethodHandles.Lookup#findVirtual Lookup.findVirtual} * The {@link java.lang.invoke.MethodHandles.Lookup#findVirtual Lookup.findVirtual}
* API is also able to return a method handle * API is also able to return a method handle
* to call {@code invokeExact} or {@code invokeGeneric}, * to call {@code invokeExact} or plain {@code invoke},
* for any specified type descriptor . * for any specified type descriptor .
* *
* <h3>Interoperation between method handles and Java generics</h3> * <h3>Interoperation between method handles and Java generics</h3>
...@@ -523,7 +533,7 @@ public abstract class MethodHandle { ...@@ -523,7 +533,7 @@ public abstract class MethodHandle {
* adaptations directly on the caller's arguments, * adaptations directly on the caller's arguments,
* and call the target method handle according to its own exact type. * and call the target method handle according to its own exact type.
* <p> * <p>
* The type descriptor at the call site of {@code invokeGeneric} must * The type descriptor at the call site of {@code invoke} must
* be a valid argument to the receivers {@code asType} method. * be a valid argument to the receivers {@code asType} method.
* In particular, the caller must specify the same argument arity * In particular, the caller must specify the same argument arity
* as the callee's type, * as the callee's type,
...@@ -539,11 +549,18 @@ public abstract class MethodHandle { ...@@ -539,11 +549,18 @@ public abstract class MethodHandle {
* @throws ClassCastException if the target's type can be adjusted to the caller, but a reference cast fails * @throws ClassCastException if the target's type can be adjusted to the caller, but a reference cast fails
* @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
*/ */
public final native @PolymorphicSignature Object invoke(Object... args) throws Throwable;
/**
* <em>Temporary alias</em> for {@link #invoke}, for backward compatibility with some versions of JSR 292.
* On some JVMs, support can be excluded by the flags {@code -XX:+UnlockExperimentalVMOptions -XX:-AllowInvokeGeneric}.
* @deprecated Will be removed for JSR 292 Proposed Final Draft.
*/
public final native @PolymorphicSignature Object invokeGeneric(Object... args) throws Throwable; public final native @PolymorphicSignature Object invokeGeneric(Object... args) throws Throwable;
/** /**
* Performs a varargs invocation, passing the arguments in the given array * Performs a varargs invocation, passing the arguments in the given array
* to the method handle, as if via {@link #invokeGeneric invokeGeneric} from a call site * to the method handle, as if via an inexact {@link #invoke invoke} from a call site
* which mentions only the type {@code Object}, and whose arity is the length * which mentions only the type {@code Object}, and whose arity is the length
* of the argument array. * of the argument array.
* <p> * <p>
...@@ -553,7 +570,7 @@ public abstract class MethodHandle { ...@@ -553,7 +570,7 @@ public abstract class MethodHandle {
* <ul> * <ul>
* <li>Determine the length of the argument array as {@code N}. * <li>Determine the length of the argument array as {@code N}.
* For a null reference, {@code N=0}. </li> * For a null reference, {@code N=0}. </li>
* <li>Determine the generic type {@code TN} of {@code N} arguments as * <li>Determine the general type {@code TN} of {@code N} arguments as
* as {@code TN=MethodType.genericMethodType(N)}.</li> * as {@code TN=MethodType.genericMethodType(N)}.</li>
* <li>Force the original target method handle {@code MH0} to the * <li>Force the original target method handle {@code MH0} to the
* required type, as {@code MH1 = MH0.asType(TN)}. </li> * required type, as {@code MH1 = MH0.asType(TN)}. </li>
...@@ -580,7 +597,7 @@ public abstract class MethodHandle { ...@@ -580,7 +597,7 @@ public abstract class MethodHandle {
* Object result = invoker.invokeExact(this, arguments); * Object result = invoker.invokeExact(this, arguments);
* </pre></blockquote> * </pre></blockquote>
* <p> * <p>
* Unlike the signature polymorphic methods {@code invokeExact} and {@code invokeGeneric}, * Unlike the signature polymorphic methods {@code invokeExact} and {@code invoke},
* {@code invokeWithArguments} can be accessed normally via the Core Reflection API and JNI. * {@code invokeWithArguments} can be accessed normally via the Core Reflection API and JNI.
* It can therefore be used as a bridge between native or reflective code and method handles. * It can therefore be used as a bridge between native or reflective code and method handles.
* *
...@@ -595,11 +612,11 @@ public abstract class MethodHandle { ...@@ -595,11 +612,11 @@ public abstract class MethodHandle {
int argc = arguments == null ? 0 : arguments.length; int argc = arguments == null ? 0 : arguments.length;
MethodType type = type(); MethodType type = type();
if (type.parameterCount() != argc) { if (type.parameterCount() != argc) {
// simulate invokeGeneric // simulate invoke
return asType(MethodType.genericMethodType(argc)).invokeWithArguments(arguments); return asType(MethodType.genericMethodType(argc)).invokeWithArguments(arguments);
} }
if (argc <= 10) { if (argc <= 10) {
MethodHandle invoker = type.invokers().genericInvoker(); MethodHandle invoker = type.invokers().generalInvoker();
switch (argc) { switch (argc) {
case 0: return invoker.invokeExact(this); case 0: return invoker.invokeExact(this);
case 1: return invoker.invokeExact(this, case 1: return invoker.invokeExact(this,
...@@ -644,7 +661,7 @@ public abstract class MethodHandle { ...@@ -644,7 +661,7 @@ public abstract class MethodHandle {
/** /**
* Performs a varargs invocation, passing the arguments in the given array * Performs a varargs invocation, passing the arguments in the given array
* to the method handle, as if via {@link #invokeGeneric invokeGeneric} from a call site * to the method handle, as if via an inexact {@link #invoke invoke} from a call site
* which mentions only the type {@code Object}, and whose arity is the length * which mentions only the type {@code Object}, and whose arity is the length
* of the argument array. * of the argument array.
* <p> * <p>
...@@ -672,9 +689,9 @@ public abstract class MethodHandle { ...@@ -672,9 +689,9 @@ public abstract class MethodHandle {
* If the original type and new type are equal, returns {@code this}. * If the original type and new type are equal, returns {@code this}.
* <p> * <p>
* This method provides the crucial behavioral difference between * This method provides the crucial behavioral difference between
* {@link #invokeExact invokeExact} and {@link #invokeGeneric invokeGeneric}. The two methods * {@link #invokeExact invokeExact} and plain, inexact {@link #invoke invoke}. The two methods
* perform the same steps when the caller's type descriptor is identical * perform the same steps when the caller's type descriptor is identical
* with the callee's, but when the types differ, {@link #invokeGeneric invokeGeneric} * with the callee's, but when the types differ, plain {@link #invoke invoke}
* also calls {@code asType} (or some internal equivalent) in order * also calls {@code asType} (or some internal equivalent) in order
* to match up the caller's and callee's types. * to match up the caller's and callee's types.
* <p> * <p>
...@@ -798,7 +815,7 @@ public abstract class MethodHandle { ...@@ -798,7 +815,7 @@ public abstract class MethodHandle {
* <p> * <p>
* The type and behavior of the adapter will be the same as * The type and behavior of the adapter will be the same as
* the type and behavior of the target, except that certain * the type and behavior of the target, except that certain
* {@code invokeGeneric} and {@code asType} requests can lead to * {@code invoke} and {@code asType} requests can lead to
* trailing positional arguments being collected into target's * trailing positional arguments being collected into target's
* trailing parameter. * trailing parameter.
* Also, the last parameter type of the adapter will be * Also, the last parameter type of the adapter will be
...@@ -812,17 +829,17 @@ public abstract class MethodHandle { ...@@ -812,17 +829,17 @@ public abstract class MethodHandle {
* since it accepts a whole array of indeterminate length, * since it accepts a whole array of indeterminate length,
* rather than a fixed number of arguments.) * rather than a fixed number of arguments.)
* <p> * <p>
* When called with {@link #invokeGeneric invokeGeneric}, if the caller * When called with plain, inexact {@link #invoke invoke}, if the caller
* type is the same as the adapter, the adapter invokes the target as with * type is the same as the adapter, the adapter invokes the target as with
* {@code invokeExact}. * {@code invokeExact}.
* (This is the normal behavior for {@code invokeGeneric} when types match.) * (This is the normal behavior for {@code invoke} when types match.)
* <p> * <p>
* Otherwise, if the caller and adapter arity are the same, and the * Otherwise, if the caller and adapter arity are the same, and the
* trailing parameter type of the caller is a reference type identical to * trailing parameter type of the caller is a reference type identical to
* or assignable to the trailing parameter type of the adapter, * or assignable to the trailing parameter type of the adapter,
* the arguments and return values are converted pairwise, * the arguments and return values are converted pairwise,
* as if by {@link MethodHandles#convertArguments convertArguments}. * as if by {@link MethodHandles#convertArguments convertArguments}.
* (This is also normal behavior for {@code invokeGeneric} in such a case.) * (This is also normal behavior for {@code invoke} in such a case.)
* <p> * <p>
* Otherwise, the arities differ, or the adapter's trailing parameter * Otherwise, the arities differ, or the adapter's trailing parameter
* type is not assignable from the corresponding caller type. * type is not assignable from the corresponding caller type.
...@@ -838,7 +855,7 @@ public abstract class MethodHandle { ...@@ -838,7 +855,7 @@ public abstract class MethodHandle {
* where {@code N} is the arity of the target. * where {@code N} is the arity of the target.
* Also, there must exist conversions from the incoming arguments * Also, there must exist conversions from the incoming arguments
* to the target's arguments. * to the target's arguments.
* As with other uses of {@code invokeGeneric}, if these basic * As with other uses of plain {@code invoke}, if these basic
* requirements are not fulfilled, a {@code WrongMethodTypeException} * requirements are not fulfilled, a {@code WrongMethodTypeException}
* may be thrown. * may be thrown.
* <p> * <p>
...@@ -856,7 +873,7 @@ public abstract class MethodHandle { ...@@ -856,7 +873,7 @@ public abstract class MethodHandle {
* <p> * <p>
* The behavior of {@link #asType asType} is also specialized for * The behavior of {@link #asType asType} is also specialized for
* variable arity adapters, to maintain the invariant that * variable arity adapters, to maintain the invariant that
* {@code invokeGeneric} is always equivalent to an {@code asType} * plain, inexact {@code invoke} is always equivalent to an {@code asType}
* call to adjust the target type, followed by {@code invokeExact}. * call to adjust the target type, followed by {@code invokeExact}.
* Therefore, a variable arity adapter responds * Therefore, a variable arity adapter responds
* to an {@code asType} request by building a fixed arity collector, * to an {@code asType} request by building a fixed arity collector,
...@@ -893,12 +910,12 @@ public abstract class MethodHandle { ...@@ -893,12 +910,12 @@ public abstract class MethodHandle {
MethodHandle asList = publicLookup() MethodHandle asList = publicLookup()
.findStatic(Arrays.class, "asList", methodType(List.class, Object[].class)) .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
.asVarargsCollector(Object[].class); .asVarargsCollector(Object[].class);
assertEquals("[]", asList.invokeGeneric().toString()); assertEquals("[]", asList.invoke().toString());
assertEquals("[1]", asList.invokeGeneric(1).toString()); assertEquals("[1]", asList.invoke(1).toString());
assertEquals("[two, too]", asList.invokeGeneric("two", "too").toString()); assertEquals("[two, too]", asList.invoke("two", "too").toString());
Object[] argv = { "three", "thee", "tee" }; Object[] argv = { "three", "thee", "tee" };
assertEquals("[three, thee, tee]", asList.invokeGeneric(argv).toString()); assertEquals("[three, thee, tee]", asList.invoke(argv).toString());
List ls = (List) asList.invokeGeneric((Object)argv); List ls = (List) asList.invoke((Object)argv);
assertEquals(1, ls.size()); assertEquals(1, ls.size());
assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0))); assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0)));
* </pre></blockquote> * </pre></blockquote>
...@@ -926,9 +943,9 @@ MethodHandle vamh = publicLookup() ...@@ -926,9 +943,9 @@ MethodHandle vamh = publicLookup()
.asVarargsCollector(Object[].class); .asVarargsCollector(Object[].class);
MethodHandle mh = MethodHandles.exactInvoker(vamh.type()).bindTo(vamh); MethodHandle mh = MethodHandles.exactInvoker(vamh.type()).bindTo(vamh);
assert(vamh.type().equals(mh.type())); assert(vamh.type().equals(mh.type()));
assertEquals("[1, 2, 3]", vamh.invokeGeneric(1,2,3).toString()); assertEquals("[1, 2, 3]", vamh.invoke(1,2,3).toString());
boolean failed = false; boolean failed = false;
try { mh.invokeGeneric(1,2,3); } try { mh.invoke(1,2,3); }
catch (WrongMethodTypeException ex) { failed = true; } catch (WrongMethodTypeException ex) { failed = true; }
assert(failed); assert(failed);
* </pre></blockquote> * </pre></blockquote>
...@@ -960,7 +977,7 @@ assert(failed); ...@@ -960,7 +977,7 @@ assert(failed);
* <li>an {@code ldc} instruction of a {@code CONSTANT_MethodHandle} * <li>an {@code ldc} instruction of a {@code CONSTANT_MethodHandle}
* which resolves to a variable arity Java method or constructor * which resolves to a variable arity Java method or constructor
* </ul> * </ul>
* @return true if this method handle accepts more than one arity of {@code invokeGeneric} calls * @return true if this method handle accepts more than one arity of plain, inexact {@code invoke} calls
* @see #asVarargsCollector * @see #asVarargsCollector
*/ */
public boolean isVarargsCollector() { public boolean isVarargsCollector() {
......
...@@ -313,7 +313,7 @@ class MethodHandleNatives { ...@@ -313,7 +313,7 @@ class MethodHandleNatives {
} }
/** /**
* The JVM wants to use a MethodType with invokeGeneric. Give the runtime fair warning. * The JVM wants to use a MethodType with inexact invoke. Give the runtime fair warning.
*/ */
static void notifyGenericMethodType(MethodType type) { static void notifyGenericMethodType(MethodType type) {
type.form().notifyGenericMethodType(); type.form().notifyGenericMethodType();
......
...@@ -190,7 +190,7 @@ public class MethodHandles { ...@@ -190,7 +190,7 @@ public class MethodHandles {
* is not symbolically accessible from the lookup class's loader, * is not symbolically accessible from the lookup class's loader,
* the lookup can still succeed. * the lookup can still succeed.
* For example, lookups for {@code MethodHandle.invokeExact} and * For example, lookups for {@code MethodHandle.invokeExact} and
* {@code MethodHandle.invokeGeneric} will always succeed, regardless of requested type. * {@code MethodHandle.invoke} will always succeed, regardless of requested type.
* <li>If there is a security manager installed, it can forbid the lookup * <li>If there is a security manager installed, it can forbid the lookup
* on various grounds (<a href="#secmgr">see below</a>). * on various grounds (<a href="#secmgr">see below</a>).
* By contrast, the {@code ldc} instruction is not subject to * By contrast, the {@code ldc} instruction is not subject to
...@@ -590,10 +590,10 @@ public class MethodHandles { ...@@ -590,10 +590,10 @@ public class MethodHandles {
* Because of the general equivalence between {@code invokevirtual} * Because of the general equivalence between {@code invokevirtual}
* instructions and method handles produced by {@code findVirtual}, * instructions and method handles produced by {@code findVirtual},
* if the class is {@code MethodHandle} and the name string is * if the class is {@code MethodHandle} and the name string is
* {@code invokeExact} or {@code invokeGeneric}, the resulting * {@code invokeExact} or {@code invoke}, the resulting
* method handle is equivalent to one produced by * method handle is equivalent to one produced by
* {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or * {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
* {@link java.lang.invoke.MethodHandles#genericInvoker MethodHandles.genericInvoker} * {@link java.lang.invoke.MethodHandles#invoker MethodHandles.invoker}
* with the same {@code type} argument. * with the same {@code type} argument.
* *
* @param refc the class or interface from which the method is accessed * @param refc the class or interface from which the method is accessed
...@@ -1148,7 +1148,7 @@ return mh1; ...@@ -1148,7 +1148,7 @@ return mh1;
* <li>an {@code Object[]} array containing more arguments * <li>an {@code Object[]} array containing more arguments
* </ul> * </ul>
* <p> * <p>
* The invoker will behave like a call to {@link MethodHandle#invokeGeneric invokeGeneric} with * The invoker will behave like a call to {@link MethodHandle#invoke invoke} with
* the indicated {@code type}. * the indicated {@code type}.
* That is, if the target is exactly of the given {@code type}, it will behave * That is, if the target is exactly of the given {@code type}, it will behave
* like {@code invokeExact}; otherwise it behave as if {@link MethodHandle#asType asType} * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle#asType asType}
...@@ -1166,7 +1166,7 @@ return mh1; ...@@ -1166,7 +1166,7 @@ return mh1;
* <p> * <p>
* This method is equivalent to the following code (though it may be more efficient): * This method is equivalent to the following code (though it may be more efficient):
* <p><blockquote><pre> * <p><blockquote><pre>
MethodHandle invoker = MethodHandles.genericInvoker(type); MethodHandle invoker = MethodHandles.invoker(type);
int spreadArgCount = type.parameterCount - objectArgCount; int spreadArgCount = type.parameterCount - objectArgCount;
invoker = invoker.asSpreader(Object[].class, spreadArgCount); invoker = invoker.asSpreader(Object[].class, spreadArgCount);
return invoker; return invoker;
...@@ -1186,7 +1186,7 @@ return invoker; ...@@ -1186,7 +1186,7 @@ return invoker;
/** /**
* Produces a special <em>invoker method handle</em> which can be used to * Produces a special <em>invoker method handle</em> which can be used to
* invoke any method handle of the given type, as if by {@code invokeExact}. * invoke any method handle of the given type, as if by {@link MethodHandle#invokeExact invokeExact}.
* The resulting invoker will have a type which is * 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}.
...@@ -1203,7 +1203,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type) ...@@ -1203,7 +1203,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)
* For example, to emulate an {@code invokeExact} call to a variable method * For example, to emulate an {@code invokeExact} call to a variable method
* handle {@code M}, extract its type {@code T}, * handle {@code M}, extract its type {@code T},
* look up the invoker method {@code X} for {@code T}, * look up the invoker method {@code X} for {@code T},
* and call the invoker method, as {@code X.invokeGeneric(T, A...)}. * and call the invoker method, as {@code X.invoke(T, A...)}.
* (It would not work to call {@code X.invokeExact}, since the type {@code T} * (It would not work to call {@code X.invokeExact}, since the type {@code T}
* is unknown.) * is unknown.)
* If spreading, collecting, or other argument transformations are required, * If spreading, collecting, or other argument transformations are required,
...@@ -1212,7 +1212,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type) ...@@ -1212,7 +1212,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)
* <p> * <p>
* <em>(Note: The invoker method is not available via the Core Reflection API. * <em>(Note: The invoker method is not available via the Core Reflection API.
* An attempt to call {@linkplain java.lang.reflect.Method#invoke Method.invoke} * An attempt to call {@linkplain java.lang.reflect.Method#invoke Method.invoke}
* on the declared {@code invokeExact} or {@code invokeGeneric} method will raise an * on the declared {@code invokeExact} or {@code invoke} method will raise an
* {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em> * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em>
* <p> * <p>
* This method throws no reflective or security exceptions. * This method throws no reflective or security exceptions.
...@@ -1226,20 +1226,20 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type) ...@@ -1226,20 +1226,20 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)
/** /**
* Produces a special <em>invoker method handle</em> which can be used to * Produces a special <em>invoker method handle</em> which can be used to
* invoke any method handle of the given type, as if by {@code invokeGeneric}. * invoke any method handle compatible with the given type, as if by {@link MethodHandle#invoke invoke}.
* The resulting invoker will have a type which is * 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>
* Before invoking its target, the invoker will apply reference casts as * Before invoking its target, the invoker will apply reference casts as
* necessary and unbox and widen primitive arguments, as if by {@link #convertArguments convertArguments}. * necessary and box, unbox, or widen primitive values, as if by {@link MethodHandle#asType asType}.
* The return value of the invoker will be an {@code Object} reference, * Similarly, the return value will be converted as necessary.
* boxing a primitive value if the original type returns a primitive, * If the target is a {@linkplain MethodHandle#asVarargsCollector variable arity method handle},
* and always null if the original type returns void. * the required arity conversion will be made, again as if by {@link MethodHandle#asType asType}.
* <p> * <p>
* This method is equivalent to the following code (though it may be more efficient): * This method is equivalent to the following code (though it may be more efficient):
* <p><blockquote><pre> * <p><blockquote><pre>
publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type) publicLookup().findVirtual(MethodHandle.class, "invoke", type)
* </pre></blockquote> * </pre></blockquote>
* <p> * <p>
* This method throws no reflective or security exceptions. * This method throws no reflective or security exceptions.
...@@ -1247,8 +1247,17 @@ publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type) ...@@ -1247,8 +1247,17 @@ publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type)
* @return a method handle suitable for invoking any method handle convertible to the given type * @return a method handle suitable for invoking any method handle convertible to the given type
*/ */
static public static public
MethodHandle invoker(MethodType type) {
return type.invokers().generalInvoker();
}
/**
* <em>Temporary alias</em> for {@link #invoker}, for backward compatibility with some versions of JSR 292.
* @deprecated Will be removed for JSR 292 Proposed Final Draft.
*/
public static
MethodHandle genericInvoker(MethodType type) { MethodHandle genericInvoker(MethodType type) {
return type.invokers().genericInvoker(); return invoker(type);
} }
/** /**
...@@ -2142,7 +2151,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2 ...@@ -2142,7 +2151,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
* the given {@code target} on the incoming arguments, * the given {@code target} on the incoming arguments,
* and returning or throwing whatever the {@code target} * and returning or throwing whatever the {@code target}
* returns or throws. The invocation will be as if by * returns or throws. The invocation will be as if by
* {@code target.invokeGeneric}. * {@code target.invoke}.
* The target's type will be checked before the * The target's type will be checked before the
* instance is created, as if by a call to {@code asType}, * instance is created, as if by a call to {@code asType},
* which may result in a {@code WrongMethodTypeException}. * which may result in a {@code WrongMethodTypeException}.
......
...@@ -39,7 +39,7 @@ import static java.lang.invoke.MethodHandleStatics.*; ...@@ -39,7 +39,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
* matched between a method handle and all its callers, * matched between a method handle and all its callers,
* and the JVM's operations enforce this matching at, specifically * and the JVM's operations enforce this matching at, specifically
* during calls to {@link MethodHandle#invokeExact MethodHandle.invokeExact} * during calls to {@link MethodHandle#invokeExact MethodHandle.invokeExact}
* and {@link MethodHandle#invokeGeneric MethodHandle.invokeGeneric}, and during execution * and {@link MethodHandle#invoke MethodHandle.invoke}, and during execution
* of {@code invokedynamic} instructions. * of {@code invokedynamic} instructions.
* <p> * <p>
* The structure is a return type accompanied by any number of parameter types. * The structure is a return type accompanied by any number of parameter types.
...@@ -294,7 +294,7 @@ class MethodType implements java.io.Serializable { ...@@ -294,7 +294,7 @@ class MethodType implements java.io.Serializable {
* Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}. * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
* 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 generally applicable method type, for all calls of the given argument count
* @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255 * @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255
* @see #genericMethodType(int, boolean) * @see #genericMethodType(int, boolean)
*/ */
......
...@@ -59,7 +59,7 @@ class MethodTypeForm { ...@@ -59,7 +59,7 @@ class MethodTypeForm {
/*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*/ 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*/ MethodHandle genericInvoker; // hook for invokeGeneric /*lazy*/ MethodHandle genericInvoker; // hook for inexact invoke
public MethodType erasedType() { public MethodType erasedType() {
return erasedType; return erasedType;
...@@ -460,9 +460,9 @@ class MethodTypeForm { ...@@ -460,9 +460,9 @@ class MethodTypeForm {
if (genericInvoker != null) return; if (genericInvoker != null) return;
try { try {
// Trigger adapter creation. // Trigger adapter creation.
genericInvoker = InvokeGeneric.genericInvokerOf(erasedType); genericInvoker = InvokeGeneric.generalInvokerOf(erasedType);
} catch (Exception ex) { } catch (Exception ex) {
Error err = new InternalError("Exception while resolving invokeGeneric"); Error err = new InternalError("Exception while resolving inexact invoke");
err.initCause(ex); err.initCause(ex);
throw err; throw err;
} }
......
...@@ -185,7 +185,7 @@ ...@@ -185,7 +185,7 @@
* The method handle constant produced for such a method behaves as if * The method handle constant produced for such a method behaves as if
* it were created by {@link java.lang.invoke.MethodHandle#asVarargsCollector asVarargsCollector}. * it were created by {@link java.lang.invoke.MethodHandle#asVarargsCollector asVarargsCollector}.
* In other words, the constant method handle will exhibit variable arity, * In other words, the constant method handle will exhibit variable arity,
* when invoked via {@code invokeGeneric}. * when invoked via {@code MethodHandle.invoke}.
* On the other hand, its behavior with respect to {@code invokeExact} will be the same * On the other hand, its behavior with respect to {@code invokeExact} will be the same
* as if the {@code varargs} bit were not set. * as if the {@code varargs} bit were not set.
* <p> * <p>
...@@ -243,7 +243,7 @@ ...@@ -243,7 +243,7 @@
* <li>optionally, one or more <a href="#args">additional static arguments</a> </li> * <li>optionally, one or more <a href="#args">additional static arguments</a> </li>
* </ul> * </ul>
* The method handle is then applied to the other values as if by * The method handle is then applied to the other values as if by
* {@link java.lang.invoke.MethodHandle#invokeGeneric invokeGeneric}. * {@link java.lang.invoke.MethodHandle#invoke MethodHandle.invoke}.
* The returned result must be a {@link java.lang.invoke.CallSite CallSite} (or a subclass). * The returned result must be a {@link java.lang.invoke.CallSite CallSite} (or a subclass).
* The type of the call site's target must be exactly equal to the type * The type of the call site's target must be exactly equal to the type
* derived from the dynamic call site's type descriptor and passed to * derived from the dynamic call site's type descriptor and passed to
...@@ -251,7 +251,7 @@ ...@@ -251,7 +251,7 @@
* The call site then becomes permanently linked to the dynamic call site. * The call site then becomes permanently linked to the dynamic call site.
* <p> * <p>
* As long as each bootstrap method can be correctly invoked * As long as each bootstrap method can be correctly invoked
* by <code>invokeGeneric</code>, its detailed type is arbitrary. * by <code>MethodHandle.invoke</code>, its detailed type is arbitrary.
* For example, the first argument could be {@code Object} * For example, the first argument could be {@code Object}
* instead of {@code MethodHandles.Lookup}, and the return type * instead of {@code MethodHandles.Lookup}, and the return type
* could also be {@code Object} instead of {@code CallSite}. * could also be {@code Object} instead of {@code CallSite}.
...@@ -272,7 +272,7 @@ ...@@ -272,7 +272,7 @@
* (i.e., a {@code CONSTANT_Class}, {@code CONSTANT_MethodType}, * (i.e., a {@code CONSTANT_Class}, {@code CONSTANT_MethodType},
* or {@code CONSTANT_MethodHandle} argument cannot be linked) </li> * or {@code CONSTANT_MethodHandle} argument cannot be linked) </li>
* <li>the bootstrap method has the wrong arity, * <li>the bootstrap method has the wrong arity,
* causing {@code invokeGeneric} to throw {@code WrongMethodTypeException} </li> * causing {@code MethodHandle.invoke} to throw {@code WrongMethodTypeException} </li>
* <li>the bootstrap method has a wrong argument or return type </li> * <li>the bootstrap method has a wrong argument or return type </li>
* <li>the bootstrap method invocation completes abnormally </li> * <li>the bootstrap method invocation completes abnormally </li>
* <li>the result from the bootstrap invocation is not a reference to * <li>the result from the bootstrap invocation is not a reference to
...@@ -381,10 +381,10 @@ ...@@ -381,10 +381,10 @@
* those values will be passed as additional arguments to the method handle. * those values will be passed as additional arguments to the method handle.
* (Note that because there is a limit of 255 arguments to any method, * (Note that because there is a limit of 255 arguments to any method,
* at most 252 extra arguments can be supplied.) * at most 252 extra arguments can be supplied.)
* The bootstrap method will be invoked as if by either {@code invokeGeneric} * The bootstrap method will be invoked as if by either {@code MethodHandle.invoke}
* or {@code invokeWithArguments}. (There is no way to tell the difference.) * or {@code invokeWithArguments}. (There is no way to tell the difference.)
* <p> * <p>
* The normal argument conversion rules for {@code invokeGeneric} apply to all stacked arguments. * The normal argument conversion rules for {@code MethodHandle.invoke} apply to all stacked arguments.
* For example, if a pushed value is a primitive type, it may be converted to a reference by boxing conversion. * For example, if a pushed value is a primitive type, it may be converted to a reference by boxing conversion.
* If the bootstrap method is a variable arity method (its modifier bit {@code 0x0080} is set), * If the bootstrap method is a variable arity method (its modifier bit {@code 0x0080} is set),
* then some or all of the arguments specified here may be collected into a trailing array parameter. * then some or all of the arguments specified here may be collected into a trailing array parameter.
...@@ -419,8 +419,8 @@ ...@@ -419,8 +419,8 @@
* For example, the fourth argument could be {@code MethodHandle}, * For example, the fourth argument could be {@code MethodHandle},
* if that is the type of the corresponding constant in * if that is the type of the corresponding constant in
* the {@code CONSTANT_InvokeDynamic} entry. * the {@code CONSTANT_InvokeDynamic} entry.
* In that case, the {@code invokeGeneric} call will pass the extra method handle * In that case, the {@code MethodHandle.invoke} call will pass the extra method handle
* constant as an {@code Object}, but the type matching machinery of {@code invokeGeneric} * constant as an {@code Object}, but the type matching machinery of {@code MethodHandle.invoke}
* will cast the reference back to {@code MethodHandle} before invoking the bootstrap method. * will cast the reference back to {@code MethodHandle} before invoking the bootstrap method.
* (If a string constant were passed instead, by badly generated code, that cast would then fail, * (If a string constant were passed instead, by badly generated code, that cast would then fail,
* resulting in a {@code BootstrapMethodError}.) * resulting in a {@code BootstrapMethodError}.)
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
*/ */
/* @test /* @test
* @summary unit tests for java.lang.invoke.MethodHandle.invokeGeneric * @summary unit tests for java.lang.invoke.MethodHandle.invoke
* @compile -target 7 InvokeGenericTest.java * @compile -target 7 InvokeGenericTest.java
* @run junit/othervm test.java.lang.invoke.InvokeGenericTest * @run junit/othervm test.java.lang.invoke.InvokeGenericTest
*/ */
...@@ -350,6 +350,18 @@ public class InvokeGenericTest { ...@@ -350,6 +350,18 @@ public class InvokeGenericTest {
String[] args = { "one", "two" }; String[] args = { "one", "two" };
MethodHandle mh = callable(Object.class, String.class); MethodHandle mh = callable(Object.class, String.class);
Object res; List resl; Object res; List resl;
res = resl = (List) mh.invoke((String)args[0], (Object)args[1]);
//System.out.println(res);
assertEquals(Arrays.asList(args), res);
}
@Test
public void testAlternateName() throws Throwable {
startTest("testAlternateName");
countTest();
String[] args = { "one", "two" };
MethodHandle mh = callable(Object.class, String.class);
Object res; List resl;
res = resl = (List) mh.invokeGeneric((String)args[0], (Object)args[1]); res = resl = (List) mh.invokeGeneric((String)args[0], (Object)args[1]);
//System.out.println(res); //System.out.println(res);
assertEquals(Arrays.asList(args), res); assertEquals(Arrays.asList(args), res);
...@@ -388,15 +400,15 @@ public class InvokeGenericTest { ...@@ -388,15 +400,15 @@ public class InvokeGenericTest {
try { try {
switch (args.length) { switch (args.length) {
case 0: case 0:
junk = target.invokeGeneric(); break; junk = target.invoke(); break;
case 1: case 1:
junk = target.invokeGeneric(args[0]); break; junk = target.invoke(args[0]); break;
case 2: case 2:
junk = target.invokeGeneric(args[0], args[1]); break; junk = target.invoke(args[0], args[1]); break;
case 3: case 3:
junk = target.invokeGeneric(args[0], args[1], args[2]); break; junk = target.invoke(args[0], args[1], args[2]); break;
case 4: case 4:
junk = target.invokeGeneric(args[0], args[1], args[2], args[3]); break; junk = target.invoke(args[0], args[1], args[2], args[3]); break;
default: default:
junk = target.invokeWithArguments(args); break; junk = target.invokeWithArguments(args); break;
} }
...@@ -451,7 +463,7 @@ public class InvokeGenericTest { ...@@ -451,7 +463,7 @@ public class InvokeGenericTest {
startTest("testReferenceConversions"); startTest("testReferenceConversions");
toString_MH = LOOKUP. toString_MH = LOOKUP.
findVirtual(Object.class, "toString", MethodType.methodType(String.class)); findVirtual(Object.class, "toString", MethodType.methodType(String.class));
String[] args = { "one", "two" }; Object[] args = { "one", "two" };
for (MethodType type : allMethodTypes(2, Object.class, String.class, RandomInterface.class)) { for (MethodType type : allMethodTypes(2, Object.class, String.class, RandomInterface.class)) {
testReferenceConversions(type, args); testReferenceConversions(type, args);
} }
...@@ -463,7 +475,7 @@ public class InvokeGenericTest { ...@@ -463,7 +475,7 @@ public class InvokeGenericTest {
MethodHandle tsdrop = MethodHandles.dropArguments(toString_MH, 1, type.parameterList()); MethodHandle tsdrop = MethodHandles.dropArguments(toString_MH, 1, type.parameterList());
mh = MethodHandles.foldArguments(tsdrop, mh); mh = MethodHandles.foldArguments(tsdrop, mh);
mh = mh.asType(type); mh = mh.asType(type);
Object res = mh.invokeGeneric((String)args[0], (Object)args[1]); Object res = mh.invoke((String)args[0], (Object)args[1]);
//System.out.println(res); //System.out.println(res);
assertEquals(Arrays.asList(args).toString(), res); assertEquals(Arrays.asList(args).toString(), res);
} }
...@@ -473,10 +485,10 @@ public class InvokeGenericTest { ...@@ -473,10 +485,10 @@ public class InvokeGenericTest {
public void testBoxConversions() throws Throwable { public void testBoxConversions() throws Throwable {
startTest("testBoxConversions"); startTest("testBoxConversions");
countTest(); countTest();
Integer[] args = { 1, 2 }; Object[] args = { 1, 2 };
MethodHandle mh = callable(Object.class, int.class); MethodHandle mh = callable(Object.class, int.class);
Object res; List resl; Object res; List resl;
res = resl = (List) mh.invokeGeneric((int)args[0], (Object)args[1]); res = resl = (List) mh.invoke((int)args[0], (Object)args[1]);
//System.out.println(res); //System.out.println(res);
assertEquals(Arrays.asList(args), res); assertEquals(Arrays.asList(args), res);
} }
......
...@@ -170,8 +170,8 @@ assert(s.equals("savvy")); ...@@ -170,8 +170,8 @@ assert(s.equals("savvy"));
mt = MethodType.methodType(java.util.List.class, Object[].class); mt = MethodType.methodType(java.util.List.class, Object[].class);
mh = lookup.findStatic(java.util.Arrays.class, "asList", mt); mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
assert(mh.isVarargsCollector()); assert(mh.isVarargsCollector());
x = mh.invokeGeneric("one", "two"); x = mh.invoke("one", "two");
// invokeGeneric(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object; // invoke(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
assert(x.equals(java.util.Arrays.asList("one","two"))); assert(x.equals(java.util.Arrays.asList("one","two")));
// mt is (Object,Object,Object)Object // mt is (Object,Object,Object)Object
mt = MethodType.genericMethodType(3); mt = MethodType.genericMethodType(3);
...@@ -199,12 +199,12 @@ mh.invokeExact(System.out, "Hello, world."); ...@@ -199,12 +199,12 @@ mh.invokeExact(System.out, "Hello, world.");
MethodHandle asList = publicLookup() MethodHandle asList = publicLookup()
.findStatic(Arrays.class, "asList", methodType(List.class, Object[].class)) .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
.asVarargsCollector(Object[].class); .asVarargsCollector(Object[].class);
assertEquals("[]", asList.invokeGeneric().toString()); assertEquals("[]", asList.invoke().toString());
assertEquals("[1]", asList.invokeGeneric(1).toString()); assertEquals("[1]", asList.invoke(1).toString());
assertEquals("[two, too]", asList.invokeGeneric("two", "too").toString()); assertEquals("[two, too]", asList.invoke("two", "too").toString());
Object[] argv = { "three", "thee", "tee" }; Object[] argv = { "three", "thee", "tee" };
assertEquals("[three, thee, tee]", asList.invokeGeneric(argv).toString()); assertEquals("[three, thee, tee]", asList.invoke(argv).toString());
List ls = (List) asList.invokeGeneric((Object)argv); List ls = (List) asList.invoke((Object)argv);
assertEquals(1, ls.size()); assertEquals(1, ls.size());
assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0))); assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0)));
}} }}
...@@ -218,9 +218,9 @@ MethodHandle vamh = publicLookup() ...@@ -218,9 +218,9 @@ MethodHandle vamh = publicLookup()
.asVarargsCollector(Object[].class); .asVarargsCollector(Object[].class);
MethodHandle mh = MethodHandles.exactInvoker(vamh.type()).bindTo(vamh); MethodHandle mh = MethodHandles.exactInvoker(vamh.type()).bindTo(vamh);
assert(vamh.type().equals(mh.type())); assert(vamh.type().equals(mh.type()));
assertEquals("[1, 2, 3]", vamh.invokeGeneric(1,2,3).toString()); assertEquals("[1, 2, 3]", vamh.invoke(1,2,3).toString());
boolean failed = false; boolean failed = false;
try { mh.invokeGeneric(1,2,3); } try { mh.invoke(1,2,3); }
catch (WrongMethodTypeException ex) { failed = true; } catch (WrongMethodTypeException ex) { failed = true; }
assert(failed); assert(failed);
{} {}
......
...@@ -1780,7 +1780,7 @@ public class MethodHandlesTest { ...@@ -1780,7 +1780,7 @@ public class MethodHandlesTest {
assertCalled("invokee", args); assertCalled("invokee", args);
// generic invoker // generic invoker
countTest(); countTest();
inv = MethodHandles.genericInvoker(type); inv = MethodHandles.invoker(type);
if (nargs <= 3) { if (nargs <= 3) {
calledLog.clear(); calledLog.clear();
switch (nargs) { switch (nargs) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册