Java Code Examples for java.lang.invoke.MethodHandle#invokeExact()

The following examples show how to use java.lang.invoke.MethodHandle#invokeExact() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: BrowserJSObjectLinker.java    From openjdk-jdk8u with GNU General Public License v2.0 6 votes vote down vote up
@SuppressWarnings("unused")
private static Object get(final MethodHandle fallback, final Object jsobj, final Object key) throws Throwable {
    if (key instanceof Integer) {
        return JSOBJECT_GETSLOT.invokeExact(jsobj, (int)key);
    } else if (key instanceof Number) {
        final int index = getIndex((Number)key);
        if (index > -1) {
            return JSOBJECT_GETSLOT.invokeExact(jsobj, index);
        }
    } else if (isString(key)) {
        final String name = key.toString();
        if (name.indexOf('(') != -1) {
            return fallback.invokeExact(jsobj, (Object) name);
        }
        return JSOBJECT_GETMEMBER.invokeExact(jsobj, name);
    }
    return null;
}
 
Example 2
Source File: ValueConversionsTest.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 6 votes vote down vote up
@Test
public void testBox() throws Throwable {
    for (Wrapper w : Wrapper.values()) {
        if (w == Wrapper.VOID)    continue;  // skip this; no unboxed form
        if (w == Wrapper.OBJECT)  continue;  // skip this; already unboxed
        for (int n = -5; n < 10; n++) {
            Object box = w.wrap(n);
            MethodHandle boxer = ValueConversions.boxExact(w);
            Object expResult = box;
            Object result = null;
            switch (w) {
                case INT:     result = (Integer) boxer.invokeExact(/*int*/n); break;
                case LONG:    result = (Long)    boxer.invokeExact((long)n); break;
                case FLOAT:   result = (Float)   boxer.invokeExact((float)n); break;
                case DOUBLE:  result = (Double)  boxer.invokeExact((double)n); break;
                case CHAR:    result = (Character) boxer.invokeExact((char)n); break;
                case BYTE:    result = (Byte)    boxer.invokeExact((byte)n); break;
                case SHORT:   result = (Short)   boxer.invokeExact((short)n); break;
                case BOOLEAN: result = (Boolean) boxer.invokeExact((n & 1) != 0); break;
            }
            assertEquals("(dst,src,n,box)="+Arrays.asList(w,w,n,box),
                         expResult, result);
        }
    }
}
 
Example 3
Source File: VMAnonymousClass.java    From jdk8u-jdk with GNU General Public License v2.0 6 votes vote down vote up
private static void test(String pkg) throws Throwable {
    byte[] bytes = dumpClass(pkg);
    // Define VM anonymous class in privileged context (on BCP).
    Class anonClass = unsafe.defineAnonymousClass(Object.class, bytes, null);

    MethodType t = MethodType.methodType(Object.class, int.class);
    MethodHandle target = MethodHandles.lookup().findStatic(anonClass, "get", t);

    // Wrap target into LF (convert) to get "target" referenced from LF
    MethodHandle wrappedMH = target.asType(MethodType.methodType(Object.class, Integer.class));

    // Invoke enough times to provoke LF compilation to bytecode.
    for (int i = 0; i<100; i++) {
        Object r = wrappedMH.invokeExact((Integer)1);
    }
}
 
Example 4
Source File: JSObjectLinker.java    From openjdk-jdk8u with GNU General Public License v2.0 6 votes vote down vote up
@SuppressWarnings("unused")
private static Object get(final MethodHandle fallback, final Object jsobj, final Object key)
    throws Throwable {
    if (key instanceof Integer) {
        return ((JSObject)jsobj).getSlot((Integer)key);
    } else if (key instanceof Number) {
        final int index = getIndex((Number)key);
        if (index > -1) {
            return ((JSObject)jsobj).getSlot(index);
        } else {
            return ((JSObject)jsobj).getMember(JSType.toString(key));
        }
    } else if (isString(key)) {
        final String name = key.toString();
        // get with method name and signature. delegate it to beans linker!
        if (name.indexOf('(') != -1) {
            return fallback.invokeExact(jsobj, (Object) name);
        }
        return ((JSObject)jsobj).getMember(name);
    }
    return null;
}
 
Example 5
Source File: VMAnonymousClass.java    From jdk8u-dev-jdk with GNU General Public License v2.0 6 votes vote down vote up
private static void test(String pkg) throws Throwable {
    byte[] bytes = dumpClass(pkg);
    // Define VM anonymous class in privileged context (on BCP).
    Class anonClass = unsafe.defineAnonymousClass(Object.class, bytes, null);

    MethodType t = MethodType.methodType(Object.class, int.class);
    MethodHandle target = MethodHandles.lookup().findStatic(anonClass, "get", t);

    // Wrap target into LF (convert) to get "target" referenced from LF
    MethodHandle wrappedMH = target.asType(MethodType.methodType(Object.class, Integer.class));

    // Invoke enough times to provoke LF compilation to bytecode.
    for (int i = 0; i<100; i++) {
        Object r = wrappedMH.invokeExact((Integer)1);
    }
}
 
Example 6
Source File: ValueConversionsTest.java    From jdk8u-dev-jdk with GNU General Public License v2.0 6 votes vote down vote up
@Test
public void testBox() throws Throwable {
    for (Wrapper w : Wrapper.values()) {
        if (w == Wrapper.VOID)    continue;  // skip this; no unboxed form
        if (w == Wrapper.OBJECT)  continue;  // skip this; already unboxed
        for (int n = -5; n < 10; n++) {
            Object box = w.wrap(n);
            MethodHandle boxer = ValueConversions.boxExact(w);
            Object expResult = box;
            Object result = null;
            switch (w) {
                case INT:     result = (Integer) boxer.invokeExact(/*int*/n); break;
                case LONG:    result = (Long)    boxer.invokeExact((long)n); break;
                case FLOAT:   result = (Float)   boxer.invokeExact((float)n); break;
                case DOUBLE:  result = (Double)  boxer.invokeExact((double)n); break;
                case CHAR:    result = (Character) boxer.invokeExact((char)n); break;
                case BYTE:    result = (Byte)    boxer.invokeExact((byte)n); break;
                case SHORT:   result = (Short)   boxer.invokeExact((short)n); break;
                case BOOLEAN: result = (Boolean) boxer.invokeExact((n & 1) != 0); break;
            }
            assertEquals("(dst,src,n,box)="+Arrays.asList(w,w,n,box),
                         expResult, result);
        }
    }
}
 
Example 7
Source File: VMAnonymousClass.java    From jdk8u_jdk with GNU General Public License v2.0 6 votes vote down vote up
private static void test(String pkg) throws Throwable {
    byte[] bytes = dumpClass(pkg);
    // Define VM anonymous class in privileged context (on BCP).
    Class anonClass = unsafe.defineAnonymousClass(Object.class, bytes, null);

    MethodType t = MethodType.methodType(Object.class, int.class);
    MethodHandle target = MethodHandles.lookup().findStatic(anonClass, "get", t);

    // Wrap target into LF (convert) to get "target" referenced from LF
    MethodHandle wrappedMH = target.asType(MethodType.methodType(Object.class, Integer.class));

    // Invoke enough times to provoke LF compilation to bytecode.
    for (int i = 0; i<100; i++) {
        Object r = wrappedMH.invokeExact((Integer)1);
    }
}
 
Example 8
Source File: ValueConversionsTest.java    From jdk8u-jdk with GNU General Public License v2.0 6 votes vote down vote up
@Test
public void testBox() throws Throwable {
    for (Wrapper w : Wrapper.values()) {
        if (w == Wrapper.VOID)    continue;  // skip this; no unboxed form
        if (w == Wrapper.OBJECT)  continue;  // skip this; already unboxed
        for (int n = -5; n < 10; n++) {
            Object box = w.wrap(n);
            MethodHandle boxer = ValueConversions.boxExact(w);
            Object expResult = box;
            Object result = null;
            switch (w) {
                case INT:     result = (Integer) boxer.invokeExact(/*int*/n); break;
                case LONG:    result = (Long)    boxer.invokeExact((long)n); break;
                case FLOAT:   result = (Float)   boxer.invokeExact((float)n); break;
                case DOUBLE:  result = (Double)  boxer.invokeExact((double)n); break;
                case CHAR:    result = (Character) boxer.invokeExact((char)n); break;
                case BYTE:    result = (Byte)    boxer.invokeExact((byte)n); break;
                case SHORT:   result = (Short)   boxer.invokeExact((short)n); break;
                case BOOLEAN: result = (Boolean) boxer.invokeExact((n & 1) != 0); break;
            }
            assertEquals("(dst,src,n,box)="+Arrays.asList(w,w,n,box),
                         expResult, result);
        }
    }
}
 
Example 9
Source File: ValueConversionsTest.java    From jdk8u-jdk with GNU General Public License v2.0 6 votes vote down vote up
@Test
public void testCast() throws Throwable {
    Class<?>[] types = { Object.class, Serializable.class, String.class, Number.class, Integer.class };
    Object[] objects = { new Object(), Boolean.FALSE,      "hello",      (Long)12L,    (Integer)6    };
    for (Class<?> dst : types) {
        MethodHandle caster = ValueConversions.cast().bindTo(dst);
        assertEquals(caster.type(), MethodHandles.identity(Object.class).type());
        for (Object obj : objects) {
            Class<?> src = obj.getClass();
            boolean canCast = dst.isAssignableFrom(src);
            try {
                Object result = caster.invokeExact(obj);
                if (canCast)
                    assertEquals(obj, result);
                else
                    assertEquals("cast should not have succeeded", dst, obj);
            } catch (ClassCastException ex) {
                if (canCast)
                    throw ex;
            }
        }
    }
}
 
Example 10
Source File: ValueConversionsTest.java    From dragonwell8_jdk with GNU General Public License v2.0 6 votes vote down vote up
@Test
public void testBox() throws Throwable {
    for (Wrapper w : Wrapper.values()) {
        if (w == Wrapper.VOID)    continue;  // skip this; no unboxed form
        if (w == Wrapper.OBJECT)  continue;  // skip this; already unboxed
        for (int n = -5; n < 10; n++) {
            Object box = w.wrap(n);
            MethodHandle boxer = ValueConversions.boxExact(w);
            Object expResult = box;
            Object result = null;
            switch (w) {
                case INT:     result = (Integer) boxer.invokeExact(/*int*/n); break;
                case LONG:    result = (Long)    boxer.invokeExact((long)n); break;
                case FLOAT:   result = (Float)   boxer.invokeExact((float)n); break;
                case DOUBLE:  result = (Double)  boxer.invokeExact((double)n); break;
                case CHAR:    result = (Character) boxer.invokeExact((char)n); break;
                case BYTE:    result = (Byte)    boxer.invokeExact((byte)n); break;
                case SHORT:   result = (Short)   boxer.invokeExact((short)n); break;
                case BOOLEAN: result = (Boolean) boxer.invokeExact((n & 1) != 0); break;
            }
            assertEquals("(dst,src,n,box)="+Arrays.asList(w,w,n,box),
                         expResult, result);
        }
    }
}
 
Example 11
Source File: ReflectionBenchmarkSameAccessTest.java    From AVM with MIT License 6 votes vote down vote up
private long sameInstanceMethodHandleInstanceFieldWriteAccessInvokeExactOnly(int spins) throws Throwable {
    MethodHandle constructor = MethodHandles.lookup().findConstructor(
        ReflectionTarget.class,
        MethodType.methodType(void.class));
    ReflectionTarget target = (ReflectionTarget) constructor.invoke();
    MethodHandle field = MethodHandles.lookup().findSetter(
        ReflectionTarget.class,
        instanceField,
        Object.class);
    Object object = new Object();

    long start = System.nanoTime();
    for (int i = 0; i < spins; i++) {
        field.invokeExact(target, object);
    }
    long end = System.nanoTime();
    return end - start;
}
 
Example 12
Source File: VMAnonymousClass.java    From hottub with GNU General Public License v2.0 6 votes vote down vote up
private static void test(String pkg) throws Throwable {
    byte[] bytes = dumpClass(pkg);
    // Define VM anonymous class in privileged context (on BCP).
    Class anonClass = unsafe.defineAnonymousClass(Object.class, bytes, null);

    MethodType t = MethodType.methodType(Object.class, int.class);
    MethodHandle target = MethodHandles.lookup().findStatic(anonClass, "get", t);

    // Wrap target into LF (convert) to get "target" referenced from LF
    MethodHandle wrappedMH = target.asType(MethodType.methodType(Object.class, Integer.class));

    // Invoke enough times to provoke LF compilation to bytecode.
    for (int i = 0; i<100; i++) {
        Object r = wrappedMH.invokeExact((Integer)1);
    }
}
 
Example 13
Source File: ArrayDistinctFromOperator.java    From presto with Apache License 2.0 5 votes vote down vote up
@TypeParameter("E")
@SqlType(StandardTypes.BOOLEAN)
public static boolean isDistinctFrom(
        @OperatorDependency(
                operator = IS_DISTINCT_FROM,
                argumentTypes = {"E", "E"},
                convention = @Convention(arguments = {BLOCK_POSITION, BLOCK_POSITION}, result = FAIL_ON_NULL)) MethodHandle function,
        @SqlType("array(E)") Block left,
        @IsNull boolean leftNull,
        @SqlType("array(E)") Block right,
        @IsNull boolean rightNull)
{
    if (leftNull != rightNull) {
        return true;
    }
    if (leftNull) {
        return false;
    }
    if (left.getPositionCount() != right.getPositionCount()) {
        return true;
    }
    for (int i = 0; i < left.getPositionCount(); i++) {
        try {
            if ((boolean) function.invokeExact(
                    left,
                    i,
                    right,
                    i)) {
                return true;
            }
        }
        catch (Throwable t) {
            throw internalError(t);
        }
    }
    return false;
}
 
Example 14
Source File: ScriptObject.java    From TencentKona-8 with GNU General Public License v2.0 5 votes vote down vote up
@SuppressWarnings("unused")
private static boolean knownFunctionPropertyGuardSelf(final Object self, final PropertyMap map, final MethodHandle getter, final ScriptFunction func) {
    if (self instanceof ScriptObject && ((ScriptObject)self).getMap() == map) {
        try {
            return getter.invokeExact(self) == func;
        } catch (final RuntimeException | Error e) {
            throw e;
        } catch (final Throwable t) {
            throw new RuntimeException(t);
        }
    }

    return false;
}
 
Example 15
Source File: VMAnonymousClass.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
private static void test(String pkg) throws Throwable {
    byte[] bytes = dumpClass(pkg);
    Class host_class;
    if (pkg.equals("java/prohibited")) {
        VMAnonymousClass sampleclass = new VMAnonymousClass();
        host_class = (Class)sampleclass.getClass();
    } else if (pkg.equals("java/lang")) {
      host_class = Object.class;
    } else if (pkg.equals("java/util")) {
        host_class = java.util.ArrayList.class;
    } else if (pkg.equals("jdk/internal/misc")) {
        host_class = jdk.internal.misc.Signal.class;
    } else if (pkg.equals("java/lang/invoke")) {
        host_class = java.lang.invoke.CallSite.class;
    } else {
        throw new RuntimeException("Unexpected pkg: " + pkg);
    }
    // Define VM anonymous class
    Class anonClass = unsafe.defineAnonymousClass(host_class, bytes, null);

    MethodType t = MethodType.methodType(Object.class, int.class);
    MethodHandle target = MethodHandles.lookup().findStatic(anonClass, "get", t);

    // Wrap target into LF (convert) to get "target" referenced from LF
    MethodHandle wrappedMH = target.asType(MethodType.methodType(Object.class, Integer.class));

    // Invoke enough times to provoke LF compilation to bytecode.
    for (int i = 0; i<100; i++) {
        Object r = wrappedMH.invokeExact((Integer)1);
    }
}
 
Example 16
Source File: NativeRegExp.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
private String callReplaceValue(final MethodHandle invoker, final Object function, final Object self, final RegExpMatcher matcher, final String string) throws Throwable {
    final Object[] groups = groups(matcher);
    final Object[] args   = Arrays.copyOf(groups, groups.length + 2);

    args[groups.length]     = matcher.start();
    args[groups.length + 1] = string;

    return (String)invoker.invokeExact(function, self, args);
}
 
Example 17
Source File: BigArityTest.java    From openjdk-8 with GNU General Public License v2.0 4 votes vote down vote up
@Test
public void testSpreads() throws Throwable {
    System.out.println("testing asSpreader on arity=3");
    Object[] args = testArgs(3);
    int r0 = Objects.hash(args);
    MethodHandle mh = MH_hashArguments(3);
    Object r;
    r = mh.invokeExact(args[0], args[1], args[2]);
    assertEquals(r0, r);
    r = mh.invoke(args[0], args[1], args[2]);
    assertEquals(r0, r);
    r = mh.invoke((Comparable) args[0], (Integer) args[1], (Number) args[2]);
    assertEquals(r0, r);
    r = mh.invokeWithArguments(args);
    assertEquals(r0, r);
    for (Class<?> cls0 : new Class<?>[] {
        Object[].class, Number[].class, Integer[].class, Comparable[].class
    }) {
        @SuppressWarnings("unchecked")
        Class<? extends Object[]> cls = (Class<? extends Object[]>) cls0;
        //Class<? extends Object[]> cls = Object[].class.asSubclass(cls0);
        int nargs = args.length, skip;
        MethodHandle smh = mh.asSpreader(cls, nargs - (skip = 0));
        Object[] tail = Arrays.copyOfRange(args, skip, nargs, cls);
        if (cls == Object[].class)
            r = smh.invokeExact(tail);
        else if (cls == Integer[].class)
            r = smh.invokeExact((Integer[]) tail); //warning OK, see 8019340
        else
            r = smh.invoke(tail);
        assertEquals(r0, r);
        smh = mh.asSpreader(cls, nargs - (skip = 1));
        tail = Arrays.copyOfRange(args, skip, nargs, cls);
        if (cls == Object[].class)
            r = smh.invokeExact(args[0], tail);
        else if (cls == Integer[].class)
            r = smh.invokeExact(args[0], (Integer[]) tail);
        else
            r = smh.invoke(args[0], tail);
        assertEquals(r0, r);
        smh = mh.asSpreader(cls, nargs - (skip = 2));
        tail = Arrays.copyOfRange(args, skip, nargs, cls);
        if (cls == Object[].class)
            r = smh.invokeExact(args[0], args[1], tail);
        else if (cls == Integer[].class)
            r = smh.invokeExact(args[0], args[1], (Integer[]) tail);
        else
            r = smh.invoke(args[0], args[1], tail);
        assertEquals(r0, r);
        smh = mh.asSpreader(cls, nargs - (skip = 3));
        tail = Arrays.copyOfRange(args, skip, nargs, cls);
        if (cls == Object[].class)
            r = smh.invokeExact(args[0], args[1], args[2], tail);
        else if (cls == Integer[].class)
            r = smh.invokeExact(args[0], args[1], args[2], (Integer[]) tail);
        else
            r = smh.invoke(args[0], args[1], args[2], tail);
        assertEquals(r0, r);
        // Try null array in addition to zero-length array:
        tail = null;
        if (cls == Object[].class)
            r = smh.invokeExact(args[0], args[1], args[2], tail);
        else if (cls == Integer[].class)
            r = smh.invokeExact(args[0], args[1], args[2], (Integer[]) tail);
        else
            r = smh.invoke(args[0], args[1], args[2], tail);
        assertEquals(r0, r);
    }
}
 
Example 18
Source File: ScriptFunctionData.java    From hottub with GNU General Public License v2.0 4 votes vote down vote up
Object construct(final ScriptFunction fn, final Object... arguments) throws Throwable {
    final MethodHandle mh   = getGenericConstructor(fn.getScope());
    final Object[]     args = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments;

    DebuggerSupport.notifyInvoke(mh);

    if (isVarArg(mh)) {
        if (needsCallee(mh)) {
            return mh.invokeExact(fn, args);
        }
        return mh.invokeExact(args);
    }

    final int paramCount = mh.type().parameterCount();
    if (needsCallee(mh)) {
        switch (paramCount) {
        case 1:
            return mh.invokeExact(fn);
        case 2:
            return mh.invokeExact(fn, getArg(args, 0));
        case 3:
            return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1));
        case 4:
            return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1), getArg(args, 2));
        case 5:
            return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3));
        case 6:
            return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4));
        case 7:
            return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4), getArg(args, 5));
        default:
            return mh.invokeWithArguments(withArguments(fn, paramCount, args));
        }
    }

    switch (paramCount) {
    case 0:
        return mh.invokeExact();
    case 1:
        return mh.invokeExact(getArg(args, 0));
    case 2:
        return mh.invokeExact(getArg(args, 0), getArg(args, 1));
    case 3:
        return mh.invokeExact(getArg(args, 0), getArg(args, 1), getArg(args, 2));
    case 4:
        return mh.invokeExact(getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3));
    case 5:
        return mh.invokeExact(getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4));
    case 6:
        return mh.invokeExact(getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4), getArg(args, 5));
    default:
        return mh.invokeWithArguments(withArguments(null, paramCount, args));
    }
}
 
Example 19
Source File: ScriptFunctionData.java    From TencentKona-8 with GNU General Public License v2.0 4 votes vote down vote up
Object construct(final ScriptFunction fn, final Object... arguments) throws Throwable {
    final MethodHandle mh   = getGenericConstructor(fn.getScope());
    final Object[]     args = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments;

    DebuggerSupport.notifyInvoke(mh);

    if (isVarArg(mh)) {
        if (needsCallee(mh)) {
            return mh.invokeExact(fn, args);
        }
        return mh.invokeExact(args);
    }

    final int paramCount = mh.type().parameterCount();
    if (needsCallee(mh)) {
        switch (paramCount) {
        case 1:
            return mh.invokeExact(fn);
        case 2:
            return mh.invokeExact(fn, getArg(args, 0));
        case 3:
            return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1));
        case 4:
            return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1), getArg(args, 2));
        case 5:
            return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3));
        case 6:
            return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4));
        case 7:
            return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4), getArg(args, 5));
        default:
            return mh.invokeWithArguments(withArguments(fn, paramCount, args));
        }
    }

    switch (paramCount) {
    case 0:
        return mh.invokeExact();
    case 1:
        return mh.invokeExact(getArg(args, 0));
    case 2:
        return mh.invokeExact(getArg(args, 0), getArg(args, 1));
    case 3:
        return mh.invokeExact(getArg(args, 0), getArg(args, 1), getArg(args, 2));
    case 4:
        return mh.invokeExact(getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3));
    case 5:
        return mh.invokeExact(getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4));
    case 6:
        return mh.invokeExact(getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4), getArg(args, 5));
    default:
        return mh.invokeWithArguments(withArguments(null, paramCount, args));
    }
}
 
Example 20
Source File: BigArityTest.java    From hottub with GNU General Public License v2.0 4 votes vote down vote up
@Test
public void testSpreads() throws Throwable {
    System.out.println("testing asSpreader on arity=3");
    Object[] args = testArgs(3);
    int r0 = Objects.hash(args);
    MethodHandle mh = MH_hashArguments(3);
    Object r;
    r = mh.invokeExact(args[0], args[1], args[2]);
    assertEquals(r0, r);
    r = mh.invoke(args[0], args[1], args[2]);
    assertEquals(r0, r);
    r = mh.invoke((Comparable) args[0], (Integer) args[1], (Number) args[2]);
    assertEquals(r0, r);
    r = mh.invokeWithArguments(args);
    assertEquals(r0, r);
    for (Class<?> cls0 : new Class<?>[] {
        Object[].class, Number[].class, Integer[].class, Comparable[].class
    }) {
        @SuppressWarnings("unchecked")
        Class<? extends Object[]> cls = (Class<? extends Object[]>) cls0;
        //Class<? extends Object[]> cls = Object[].class.asSubclass(cls0);
        int nargs = args.length, skip;
        MethodHandle smh = mh.asSpreader(cls, nargs - (skip = 0));
        Object[] tail = Arrays.copyOfRange(args, skip, nargs, cls);
        if (cls == Object[].class)
            r = smh.invokeExact(tail);
        else if (cls == Integer[].class)
            r = smh.invokeExact((Integer[]) tail); //warning OK, see 8019340
        else
            r = smh.invoke(tail);
        assertEquals(r0, r);
        smh = mh.asSpreader(cls, nargs - (skip = 1));
        tail = Arrays.copyOfRange(args, skip, nargs, cls);
        if (cls == Object[].class)
            r = smh.invokeExact(args[0], tail);
        else if (cls == Integer[].class)
            r = smh.invokeExact(args[0], (Integer[]) tail);
        else
            r = smh.invoke(args[0], tail);
        assertEquals(r0, r);
        smh = mh.asSpreader(cls, nargs - (skip = 2));
        tail = Arrays.copyOfRange(args, skip, nargs, cls);
        if (cls == Object[].class)
            r = smh.invokeExact(args[0], args[1], tail);
        else if (cls == Integer[].class)
            r = smh.invokeExact(args[0], args[1], (Integer[]) tail);
        else
            r = smh.invoke(args[0], args[1], tail);
        assertEquals(r0, r);
        smh = mh.asSpreader(cls, nargs - (skip = 3));
        tail = Arrays.copyOfRange(args, skip, nargs, cls);
        if (cls == Object[].class)
            r = smh.invokeExact(args[0], args[1], args[2], tail);
        else if (cls == Integer[].class)
            r = smh.invokeExact(args[0], args[1], args[2], (Integer[]) tail);
        else
            r = smh.invoke(args[0], args[1], args[2], tail);
        assertEquals(r0, r);
        // Try null array in addition to zero-length array:
        tail = null;
        if (cls == Object[].class)
            r = smh.invokeExact(args[0], args[1], args[2], tail);
        else if (cls == Integer[].class)
            r = smh.invokeExact(args[0], args[1], args[2], (Integer[]) tail);
        else
            r = smh.invoke(args[0], args[1], args[2], tail);
        assertEquals(r0, r);
    }
}