jdk/test/java/dyn/MethodHandlesTest.java
changeset 5722 4ada807383c8
parent 4537 7c3c7f8d5195
child 5723 a58a0eed34b0
equal deleted inserted replaced
5371:ff9031a745d9 5722:4ada807383c8
     1 /*
     1 /*
     2  * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
     2  * Copyright 2009-2010 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Sun designates this
     7  * published by the Free Software Foundation.  Sun designates this
    24  */
    24  */
    25 
    25 
    26 /* @test
    26 /* @test
    27  * @summary unit tests for java.dyn.MethodHandles
    27  * @summary unit tests for java.dyn.MethodHandles
    28  * @compile -XDinvokedynamic MethodHandlesTest.java
    28  * @compile -XDinvokedynamic MethodHandlesTest.java
    29  * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic jdk.java.dyn.MethodHandlesTest
    29  * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic test.java.dyn.MethodHandlesTest
    30  */
    30  */
    31 
    31 
    32 package jdk.java.dyn;
    32 package test.java.dyn;
    33 
    33 
    34 import java.dyn.*;
    34 import java.dyn.*;
    35 import java.dyn.MethodHandles.Lookup;
    35 import java.dyn.MethodHandles.Lookup;
    36 import java.lang.reflect.*;
    36 import java.lang.reflect.*;
    37 import java.util.*;
    37 import java.util.*;
    38 import java.util.logging.Level;
       
    39 import java.util.logging.Logger;
       
    40 import org.junit.*;
    38 import org.junit.*;
    41 import static org.junit.Assert.*;
    39 import static org.junit.Assert.*;
       
    40 import static org.junit.Assume.*;
    42 
    41 
    43 
    42 
    44 /**
    43 /**
    45  *
    44  *
    46  * @author jrose
    45  * @author jrose
    47  */
    46  */
    48 public class MethodHandlesTest {
    47 public class MethodHandlesTest {
    49     // How much output?
    48     // How much output?
    50     static int verbosity = 1;
    49     static int verbosity = 0;
    51 
    50 
    52     // Set this true during development if you want to fast-forward to
    51     // Set this true during development if you want to fast-forward to
    53     // a particular new, non-working test.  Tests which are known to
    52     // a particular new, non-working test.  Tests which are known to
    54     // work (or have recently worked) test this flag and return on true.
    53     // work (or have recently worked) test this flag and return on true.
    55     static boolean CAN_SKIP_WORKING = false;
    54     static boolean CAN_SKIP_WORKING = false;
    56     //static { CAN_SKIP_WORKING = true; }
    55     //static { CAN_SKIP_WORKING = true; }
    57 
    56 
    58     // Set true to test more calls.  If false, some tests are just
    57     // Set true to test more calls.  If false, some tests are just
    59     // lookups, without exercising the actual method handle.
    58     // lookups, without exercising the actual method handle.
    60     static boolean DO_MORE_CALLS = false;
    59     static boolean DO_MORE_CALLS = true;
    61 
    60 
    62 
    61 
    63     @Test
    62     @Test
    64     public void testFirst() throws Throwable {
    63     public void testFirst() throws Throwable {
    65         verbosity += 9; try {
    64         verbosity += 9; try {
    66             // left blank for debugging
    65             // left blank for debugging
    67         } finally { verbosity -= 9; }
    66         } finally { printCounts(); verbosity -= 9; }
    68     }
    67     }
    69 
    68 
    70     // current failures
    69     // current failures
    71     @Test @Ignore("failure in call to makeRawRetypeOnly in ToGeneric")
    70     @Test @Ignore("failure in call to makeRawRetypeOnly in ToGeneric")
    72     public void testFail_1() throws Throwable {
    71     public void testFail_1() throws Throwable {
       
    72         // AMH.<init>: IllegalArgumentException: bad adapter (conversion=0xfffab300): adapter pushes too many parameters
    73         testSpreadArguments(int.class, 0, 6);
    73         testSpreadArguments(int.class, 0, 6);
    74     }
    74     }
    75     @Test @Ignore("failure in JVM when expanding the stack")
    75     @Test @Ignore("failure in JVM when expanding the stack using asm stub for _adapter_spread_args")
    76     public void testFail_2() throws Throwable {
    76     public void testFail_2() throws Throwable {
    77         // if CONV_OP_IMPLEMENTED_MASK includes OP_SPREAD_ARGS, this crashes:
    77         // if CONV_OP_IMPLEMENTED_MASK includes OP_SPREAD_ARGS, this crashes:
    78         testSpreadArguments(Object.class, 0, 2);
    78         testSpreadArguments(Object.class, 0, 2);
    79     }
    79     }
    80     @Test @Ignore("IllArgEx failure in call to ToGeneric.make")
    80     @Test @Ignore("IllArgEx failure in call to ToGeneric.make")
    81     public void testFail_3() throws Throwable {
    81     public void testFail_3() throws Throwable {
       
    82         // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
    82         testSpreadArguments(int.class, 1, 2);
    83         testSpreadArguments(int.class, 1, 2);
    83     }
    84     }
    84     @Test @Ignore("IllArgEx failure in call to ToGeneric.make")
    85     @Test @Ignore("IllArgEx failure in call to ToGeneric.make")
    85     public void testFail_4() throws Throwable {
    86     public void testFail_4() throws Throwable {
       
    87         // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
    86         testCollectArguments(int.class, 1, 2);
    88         testCollectArguments(int.class, 1, 2);
    87     }
    89     }
    88     @Test @Ignore("cannot collect leading primitive types")
    90     @Test @Ignore("cannot collect leading primitive types")
    89     public void testFail_5() throws Throwable {
    91     public void testFail_5() throws Throwable {
       
    92         // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
    90         testInvokers(MethodType.genericMethodType(2).changeParameterType(0, int.class));
    93         testInvokers(MethodType.genericMethodType(2).changeParameterType(0, int.class));
    91     }
    94     }
    92     @Test @Ignore("should not insert arguments beyond MethodHandlePushLimit")
    95     @Test @Ignore("should not insert arguments beyond MethodHandlePushLimit")
    93     public void testFail_6() throws Throwable {
    96     public void testFail_6() throws Throwable {
    94         testInsertArguments(0, 0, MAX_ARG_INCREASE+1);
    97         // ValueConversions.varargsArray: UnsupportedOperationException: NYI: cannot form a varargs array of length 13
       
    98         testInsertArguments(0, 0, MAX_ARG_INCREASE+10);
    95     }
    99     }
    96     static final int MAX_ARG_INCREASE = 3;
   100     static final int MAX_ARG_INCREASE = 3;
    97 
   101 
    98     public MethodHandlesTest() {
   102     public MethodHandlesTest() {
       
   103     }
       
   104 
       
   105     @Before
       
   106     public void checkImplementedPlatform() {
       
   107         boolean platformOK = false;
       
   108         Properties properties = System.getProperties();
       
   109         String vers = properties.getProperty("java.vm.version");
       
   110         String name = properties.getProperty("java.vm.name");
       
   111         String arch = properties.getProperty("os.arch");
       
   112         if ((arch.equals("i386")  || arch.equals("amd64") ||
       
   113              arch.equals("sparc") || arch.equals("sparcv9")) &&
       
   114             (name.contains("Client") || name.contains("Server"))
       
   115             ) {
       
   116             platformOK = true;
       
   117         } else {
       
   118             System.err.println("Skipping tests for unsupported platform: "+Arrays.asList(vers, name, arch));
       
   119         }
       
   120         assumeTrue(platformOK);
    99     }
   121     }
   100 
   122 
   101     String testName;
   123     String testName;
   102     int posTests, negTests;
   124     int posTests, negTests;
   103     @After
   125     @After
   104     public void printCounts() {
   126     public void printCounts() {
   105         if (verbosity >= 1 && (posTests | negTests) != 0) {
   127         if (verbosity >= 2 && (posTests | negTests) != 0) {
   106             System.out.println();
   128             System.out.println();
   107             if (posTests != 0)  System.out.println("=== "+testName+": "+posTests+" positive test cases run");
   129             if (posTests != 0)  System.out.println("=== "+testName+": "+posTests+" positive test cases run");
   108             if (negTests != 0)  System.out.println("=== "+testName+": "+negTests+" negative test cases run");
   130             if (negTests != 0)  System.out.println("=== "+testName+": "+negTests+" negative test cases run");
       
   131             posTests = negTests = 0;
   109         }
   132         }
   110     }
   133     }
   111     void countTest(boolean positive) {
   134     void countTest(boolean positive) {
   112         if (positive) ++posTests;
   135         if (positive) ++posTests;
   113         else          ++negTests;
   136         else          ++negTests;
   114     }
   137     }
   115     void countTest() { countTest(true); }
   138     void countTest() { countTest(true); }
   116     void startTest(String name) {
   139     void startTest(String name) {
   117         if (testName != null)  printCounts();
   140         if (testName != null)  printCounts();
   118         if (verbosity >= 0)
   141         if (verbosity >= 1)
   119             System.out.println(name);
   142             System.out.println(name);
   120         posTests = negTests = 0;
   143         posTests = negTests = 0;
   121         testName = name;
   144         testName = name;
   122     }
   145     }
   123 
   146 
   124     @BeforeClass
   147     @BeforeClass
   125     public static void setUpClass() throws Exception {
   148     public static void setUpClass() throws Exception {
   126         calledLog.clear();
   149         calledLog.clear();
   127         calledLog.add(null);
   150         calledLog.add(null);
   128         nextArg = 1000000;
   151         nextArgVal = INITIAL_ARG_VAL;
   129     }
   152     }
   130 
   153 
   131     @AfterClass
   154     @AfterClass
   132     public static void tearDownClass() throws Exception {
   155     public static void tearDownClass() throws Exception {
   133     }
   156     }
   142         return entry;
   165         return entry;
   143     }
   166     }
   144     static void assertCalled(String name, Object... args) {
   167     static void assertCalled(String name, Object... args) {
   145         Object expected = logEntry(name, args);
   168         Object expected = logEntry(name, args);
   146         Object actual   = calledLog.get(calledLog.size() - 1);
   169         Object actual   = calledLog.get(calledLog.size() - 1);
   147         if (expected.equals(actual))  return;
   170         if (expected.equals(actual) && verbosity < 9)  return;
   148         System.out.println("assertCalled "+name+":");
   171         System.out.println("assertCalled "+name+":");
   149         System.out.println("expected:   "+expected);
   172         System.out.println("expected:   "+expected);
   150         System.out.println("actual:     "+actual);
   173         System.out.println("actual:     "+actual);
   151         System.out.println("ex. types:  "+getClasses(expected));
   174         System.out.println("ex. types:  "+getClasses(expected));
   152         System.out.println("act. types: "+getClasses(actual));
   175         System.out.println("act. types: "+getClasses(actual));
   153         assertEquals("previous method call types", expected, actual);
       
   154         assertEquals("previous method call", expected, actual);
   176         assertEquals("previous method call", expected, actual);
   155     }
   177     }
   156     static void printCalled(MethodHandle target, String name, Object... args) {
   178     static void printCalled(MethodHandle target, String name, Object... args) {
   157         if (verbosity >= 2)
   179         if (verbosity >= 3)
   158             System.out.println("calling "+logEntry(name, args)+" on "+target);
   180             System.out.println("calling MH="+target+" to "+name+Arrays.toString(args));
   159     }
   181     }
   160 
   182 
   161     static Object castToWrapper(Object value, Class<?> dst) {
   183     static Object castToWrapper(Object value, Class<?> dst) {
   162         Object wrap = null;
   184         Object wrap = null;
   163         if (value instanceof Number)
   185         if (value instanceof Number)
   186         if (dst == boolean.class || dst == boolean.class)
   208         if (dst == boolean.class || dst == boolean.class)
   187             return ((value % 29) & 1) == 0;
   209             return ((value % 29) & 1) == 0;
   188         return null;
   210         return null;
   189     }
   211     }
   190 
   212 
   191     static int nextArg;
   213     static final int ONE_MILLION = (1000*1000),  // first int value
       
   214                      TEN_BILLION = (10*1000*1000*1000),  // scale factor to reach upper 32 bits
       
   215                      INITIAL_ARG_VAL = ONE_MILLION << 1;  // <<1 makes space for sign bit;
       
   216     static long nextArgVal;
       
   217     static long nextArg(boolean moreBits) {
       
   218         long val = nextArgVal++;
       
   219         long sign = -(val & 1); // alternate signs
       
   220         val >>= 1;
       
   221         if (moreBits)
       
   222             // Guarantee some bits in the high word.
       
   223             // In any case keep the decimal representation simple-looking,
       
   224             // with lots of zeroes, so as not to make the printed decimal
       
   225             // strings unnecessarily noisy.
       
   226             val += (val % ONE_MILLION) * TEN_BILLION;
       
   227         return val ^ sign;
       
   228     }
       
   229     static int nextArg() {
       
   230         // Produce a 32-bit result something like ONE_MILLION+(smallint).
       
   231         // Example: 1_000_042.
       
   232         return (int) nextArg(false);
       
   233     }
       
   234     static long nextArg(Class<?> kind) {
       
   235         if (kind == long.class   || kind == Long.class ||
       
   236             kind == double.class || kind == Double.class)
       
   237             // produce a 64-bit result something like
       
   238             // ((TEN_BILLION+1) * (ONE_MILLION+(smallint)))
       
   239             // Example: 10_000_420_001_000_042.
       
   240             return nextArg(true);
       
   241         return (long) nextArg();
       
   242     }
       
   243 
   192     static Object randomArg(Class<?> param) {
   244     static Object randomArg(Class<?> param) {
   193         Object wrap = castToWrapperOrNull(nextArg, param);
   245         Object wrap = castToWrapperOrNull(nextArg(param), param);
   194         if (wrap != null) {
   246         if (wrap != null) {
   195             nextArg++;
       
   196             return wrap;
   247             return wrap;
   197         }
   248         }
   198 //        import sun.dyn.util.Wrapper;
   249 //        import sun.dyn.util.Wrapper;
   199 //        Wrapper wrap = Wrapper.forBasicType(dst);
   250 //        Wrapper wrap = Wrapper.forBasicType(dst);
   200 //        if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst))
   251 //        if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst))
   201 //            wrap = Wrapper.forWrapperType(dst);
   252 //            wrap = Wrapper.forWrapperType(dst);
   202 //        if (wrap != Wrapper.OBJECT)
   253 //        if (wrap != Wrapper.OBJECT)
   203 //            return wrap.wrap(nextArg++);
   254 //            return wrap.wrap(nextArg++);
   204         if (param.isInterface() || param.isAssignableFrom(String.class))
   255         if (param.isInterface() || param.isAssignableFrom(String.class))
   205             return "#"+(nextArg++);
   256             return "#"+nextArg();
   206         else
   257         else
   207             try {
   258             try {
   208                 return param.newInstance();
   259                 return param.newInstance();
   209             } catch (InstantiationException ex) {
   260             } catch (InstantiationException ex) {
   210             } catch (IllegalAccessException ex) {
   261             } catch (IllegalAccessException ex) {
   275     static final Lookup PUBLIC  = MethodHandles.publicLookup();
   326     static final Lookup PUBLIC  = MethodHandles.publicLookup();
   276 
   327 
   277     // Subject methods...
   328     // Subject methods...
   278     static class Example implements IntExample {
   329     static class Example implements IntExample {
   279         final String name;
   330         final String name;
   280         public Example() { name = "Example#"+(nextArg++); }
   331         public Example() { name = "Example#"+nextArg(); }
   281         protected Example(String name) { this.name = name; }
   332         protected Example(String name) { this.name = name; }
   282         protected Example(int x) { this(); called("protected <init>", this, x); }
   333         protected Example(int x) { this(); called("protected <init>", this, x); }
   283         @Override public String toString() { return name; }
   334         @Override public String toString() { return name; }
   284 
   335 
   285         public void            v0()     { called("v0", this); }
   336         public void            v0()     { called("v0", this); }
   299         public static Object   s3(long x)   { return called("s3", x); }
   350         public static Object   s3(long x)   { return called("s3", x); }
   300         public static Object   s4(int x, int y) { return called("s4", x, y); }
   351         public static Object   s4(int x, int y) { return called("s4", x, y); }
   301         public static Object   s5(long x, int y) { return called("s5", x, y); }
   352         public static Object   s5(long x, int y) { return called("s5", x, y); }
   302         public static Object   s6(int x, long y) { return called("s6", x, y); }
   353         public static Object   s6(int x, long y) { return called("s6", x, y); }
   303         public static Object   s7(float x, double y) { return called("s7", x, y); }
   354         public static Object   s7(float x, double y) { return called("s7", x, y); }
   304     }
   355 
       
   356         static final Lookup EXAMPLE = MethodHandles.lookup();  // for testing findSpecial
       
   357     }
       
   358     static final Lookup EXAMPLE = Example.EXAMPLE;
   305     public static class PubExample extends Example {
   359     public static class PubExample extends Example {
       
   360         public PubExample() { super("PubExample#"+nextArg()); }
   306     }
   361     }
   307     static class SubExample extends Example {
   362     static class SubExample extends Example {
   308         @Override public void  v0()     { called("Sub/v0", this); }
   363         @Override public void  v0()     { called("Sub/v0", this); }
   309         @Override void         pkg_v0() { called("Sub/pkg_v0", this); }
   364         @Override void         pkg_v0() { called("Sub/pkg_v0", this); }
   310         private      SubExample(int x)  { called("<init>", this, x); }
   365         private      SubExample(int x)  { called("<init>", this, x); }
   311         public SubExample() { super("SubExample#"+(nextArg++)); }
   366         public SubExample() { super("SubExample#"+nextArg()); }
   312     }
   367     }
   313     public static interface IntExample {
   368     public static interface IntExample {
   314         public void            v0();
   369         public void            v0();
   315         static class Impl implements IntExample {
   370         static class Impl implements IntExample {
   316             public void        v0()     { called("Int/v0", this); }
   371             public void        v0()     { called("Int/v0", this); }
   317             final String name;
   372             final String name;
   318             public Impl() { name = "Example#"+(nextArg++); }
   373             public Impl() { name = "Impl#"+nextArg(); }
       
   374             @Override public String toString() { return name; }
   319         }
   375         }
   320     }
   376     }
   321 
   377 
   322     static final Object[][][] ACCESS_CASES = {
   378     static final Object[][][] ACCESS_CASES = {
   323         { { false, PUBLIC }, { false, PACKAGE }, { false, PRIVATE } },
   379         { { false, PUBLIC }, { false, PACKAGE }, { false, PRIVATE }, { false, EXAMPLE } }, //[0]: all false
   324         { { false, PUBLIC }, { false, PACKAGE }, { true,  PRIVATE } },
   380         { { false, PUBLIC }, { false, PACKAGE }, { true,  PRIVATE }, { true,  EXAMPLE } }, //[1]: only PRIVATE
   325         { { false, PUBLIC }, { true,  PACKAGE }, { true,  PRIVATE } },
   381         { { false, PUBLIC }, { true,  PACKAGE }, { true,  PRIVATE }, { true,  EXAMPLE } }, //[2]: PUBLIC false
   326         { { true,  PUBLIC }, { true,  PACKAGE }, { true,  PRIVATE } },
   382         { { true,  PUBLIC }, { true,  PACKAGE }, { true,  PRIVATE }, { true,  EXAMPLE } }, //[3]: all true
   327     };
   383     };
   328 
   384 
   329     static Object[][] accessCases(Class<?> defc, String name) {
   385     static Object[][] accessCases(Class<?> defc, String name, boolean isSpecial) {
   330         if (name.contains("pri_")) {
   386         Object[][] cases;
   331             return ACCESS_CASES[1]; // PRIVATE only
   387         if (name.contains("pri_") || isSpecial) {
   332         } else if (name.contains("pkg_")) {
   388             cases = ACCESS_CASES[1]; // PRIVATE only
   333             return ACCESS_CASES[2]; // not PUBLIC
   389         } else if (name.contains("pkg_") || !Modifier.isPublic(defc.getModifiers())) {
       
   390             cases = ACCESS_CASES[2]; // not PUBLIC
   334         } else {
   391         } else {
   335             assertTrue(name.indexOf('_') < 0);
   392             assertTrue(name.indexOf('_') < 0);
   336             boolean pubc = Modifier.isPublic(defc.getModifiers());
   393             boolean pubc = Modifier.isPublic(defc.getModifiers());
   337             if (pubc)
   394             if (pubc)
   338                 return ACCESS_CASES[3]; // all access levels
   395                 cases = ACCESS_CASES[3]; // all access levels
   339             return ACCESS_CASES[2]; // PACKAGE but not PUBLIC
   396             else
   340         }
   397                 cases = ACCESS_CASES[2]; // PACKAGE but not PUBLIC
       
   398         }
       
   399         if (defc != Example.class && cases[cases.length-1][1] == EXAMPLE)
       
   400             cases = Arrays.copyOfRange(cases, 0, cases.length-1);
       
   401         return cases;
       
   402     }
       
   403     static Object[][] accessCases(Class<?> defc, String name) {
       
   404         return accessCases(defc, name, false);
   341     }
   405     }
   342 
   406 
   343     @Test
   407     @Test
   344     public void testFindStatic() throws Throwable {
   408     public void testFindStatic() throws Throwable {
   345         if (CAN_SKIP_WORKING)  return;
   409         if (CAN_SKIP_WORKING)  return;
   372         countTest(positive);
   436         countTest(positive);
   373         MethodType type = MethodType.methodType(ret, params);
   437         MethodType type = MethodType.methodType(ret, params);
   374         MethodHandle target = null;
   438         MethodHandle target = null;
   375         RuntimeException noAccess = null;
   439         RuntimeException noAccess = null;
   376         try {
   440         try {
       
   441             if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
   377             target = lookup.findStatic(defc, name, type);
   442             target = lookup.findStatic(defc, name, type);
   378         } catch (NoAccessException ex) {
   443         } catch (NoAccessException ex) {
   379             noAccess = ex;
   444             noAccess = ex;
   380         }
   445         }
   381         if (verbosity >= 2)
   446         if (verbosity >= 3)
   382             System.out.println("findStatic "+lookup+": "+defc+"."+name+"/"+type+" => "+target
   447             System.out.println("findStatic "+lookup+": "+defc.getName()+"."+name+"/"+type+" => "+target
   383                     +(noAccess == null ? "" : " !! "+noAccess));
   448                     +(noAccess == null ? "" : " !! "+noAccess));
   384         if (positive && noAccess != null)  throw noAccess;
   449         if (positive && noAccess != null)  throw noAccess;
   385         assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
   450         assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
   386         if (!positive)  return; // negative test failed as expected
   451         if (!positive)  return; // negative test failed as expected
   387         assertEquals(type, target.type());
   452         assertEquals(type, target.type());
   389         if (!DO_MORE_CALLS && lookup != PRIVATE)  return;
   454         if (!DO_MORE_CALLS && lookup != PRIVATE)  return;
   390         Object[] args = randomArgs(params);
   455         Object[] args = randomArgs(params);
   391         printCalled(target, name, args);
   456         printCalled(target, name, args);
   392         target.invokeVarargs(args);
   457         target.invokeVarargs(args);
   393         assertCalled(name, args);
   458         assertCalled(name, args);
   394         System.out.print(':');
   459         if (verbosity >= 1)
       
   460             System.out.print(':');
   395     }
   461     }
   396 
   462 
   397     @Test
   463     @Test
   398     public void testFindVirtual() throws Throwable {
   464     public void testFindVirtual() throws Throwable {
   399         if (CAN_SKIP_WORKING)  return;
   465         if (CAN_SKIP_WORKING)  return;
   434         String methodName = name.substring(1 + name.indexOf('/'));  // foo/bar => foo
   500         String methodName = name.substring(1 + name.indexOf('/'));  // foo/bar => foo
   435         MethodType type = MethodType.methodType(ret, params);
   501         MethodType type = MethodType.methodType(ret, params);
   436         MethodHandle target = null;
   502         MethodHandle target = null;
   437         RuntimeException noAccess = null;
   503         RuntimeException noAccess = null;
   438         try {
   504         try {
       
   505             if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
   439             target = lookup.findVirtual(defc, methodName, type);
   506             target = lookup.findVirtual(defc, methodName, type);
   440         } catch (NoAccessException ex) {
   507         } catch (NoAccessException ex) {
   441             noAccess = ex;
   508             noAccess = ex;
   442         }
   509         }
   443         if (verbosity >= 2)
   510         if (verbosity >= 3)
   444             System.out.println("findVirtual "+lookup+": "+defc+"."+name+"/"+type+" => "+target
   511             System.out.println("findVirtual "+lookup+": "+defc.getName()+"."+name+"/"+type+" => "+target
   445                     +(noAccess == null ? "" : " !! "+noAccess));
   512                     +(noAccess == null ? "" : " !! "+noAccess));
   446         if (positive && noAccess != null)  throw noAccess;
   513         if (positive && noAccess != null)  throw noAccess;
   447         assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
   514         assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
   448         if (!positive)  return; // negative test failed as expected
   515         if (!positive)  return; // negative test failed as expected
   449         Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params);
   516         Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params);
   450         MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
   517         MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
   451         MethodType ttype = target.type();
   518         if (defc.getClassLoader() != null)  // detune due to 6939196
   452         ttype = ttype.changeParameterType(0, defc); // FIXME: test this
   519             assertEquals(typeWithSelf.dropParameterTypes(0,1),
   453         assertEquals(typeWithSelf, ttype);
   520                          target.type().dropParameterTypes(0,1));
       
   521         else // FIXME: use only this test when 6939196 is fixed
       
   522         assertEquals(typeWithSelf, target.type());
   454         assertTrue(target.toString().contains(methodName));  // rough check
   523         assertTrue(target.toString().contains(methodName));  // rough check
   455         if (!DO_MORE_CALLS && lookup != PRIVATE)  return;
   524         if (!DO_MORE_CALLS && lookup != PRIVATE)  return;
   456         Object[] argsWithSelf = randomArgs(paramsWithSelf);
   525         Object[] argsWithSelf = randomArgs(paramsWithSelf);
   457         if (rcvc != defc)  argsWithSelf[0] = randomArg(rcvc);
   526         if (rcvc != defc)  argsWithSelf[0] = randomArg(rcvc);
   458         printCalled(target, name, argsWithSelf);
   527         printCalled(target, name, argsWithSelf);
   459         target.invokeVarargs(argsWithSelf);
   528         target.invokeVarargs(argsWithSelf);
   460         assertCalled(name, argsWithSelf);
   529         assertCalled(name, argsWithSelf);
   461         System.out.print(':');
   530         if (verbosity >= 1)
       
   531             System.out.print(':');
   462     }
   532     }
   463 
   533 
   464     @Test
   534     @Test
   465     public void testFindSpecial() throws Throwable {
   535     public void testFindSpecial() throws Throwable {
   466         if (CAN_SKIP_WORKING)  return;
   536         if (CAN_SKIP_WORKING)  return;
   467         startTest("findSpecial");
   537         startTest("findSpecial");
   468         testFindSpecial(Example.class, void.class, "v0");
   538         testFindSpecial(SubExample.class, Example.class, void.class, "v0");
   469         testFindSpecial(Example.class, void.class, "pkg_v0");
   539         testFindSpecial(SubExample.class, Example.class, void.class, "pkg_v0");
   470         testFindSpecial(false, PRIVATE, Example.class, void.class, "<init>", int.class);
   540         // Do some negative testing:
   471         testFindSpecial(false, PRIVATE, Example.class, void.class, "bogus");
   541         for (Lookup lookup : new Lookup[]{ PRIVATE, EXAMPLE, PACKAGE, PUBLIC }) {
   472     }
   542             testFindSpecial(false, lookup, Object.class, Example.class, void.class, "v0");
   473 
   543             testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "<init>", int.class);
   474     void testFindSpecial(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
   544             testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "s0");
   475         testFindSpecial(true,  PRIVATE, defc, ret, name, params);
   545             testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "bogus");
   476         testFindSpecial(false, PACKAGE, defc, ret, name, params);
   546         }
   477         testFindSpecial(false, PUBLIC,  defc, ret, name, params);
   547     }
   478     }
   548 
   479     void testFindSpecial(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
   549     void testFindSpecial(Class<?> specialCaller,
       
   550                          Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
       
   551         testFindSpecial(true,  EXAMPLE, specialCaller, defc, ret, name, params);
       
   552         testFindSpecial(true,  PRIVATE, specialCaller, defc, ret, name, params);
       
   553         testFindSpecial(false, PACKAGE, specialCaller, defc, ret, name, params);
       
   554         testFindSpecial(false, PUBLIC,  specialCaller, defc, ret, name, params);
       
   555     }
       
   556     void testFindSpecial(boolean positive, Lookup lookup, Class<?> specialCaller,
       
   557                          Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
   480         countTest(positive);
   558         countTest(positive);
   481         MethodType type = MethodType.methodType(ret, params);
   559         MethodType type = MethodType.methodType(ret, params);
   482         MethodHandle target = null;
   560         MethodHandle target = null;
   483         RuntimeException noAccess = null;
   561         RuntimeException noAccess = null;
   484         try {
   562         try {
   485             target = lookup.findSpecial(defc, name, type, defc);
   563             if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
       
   564             target = lookup.findSpecial(defc, name, type, specialCaller);
   486         } catch (NoAccessException ex) {
   565         } catch (NoAccessException ex) {
   487             noAccess = ex;
   566             noAccess = ex;
   488         }
   567         }
   489         if (verbosity >= 2)
   568         if (verbosity >= 3)
   490             System.out.println("findSpecial "+defc+"."+name+"/"+type+" => "+target
   569             System.out.println("findSpecial from "+specialCaller.getName()+" to "+defc.getName()+"."+name+"/"+type+" => "+target
   491                     +(noAccess == null ? "" : " !! "+noAccess));
   570                                +(target == null ? "" : target.type())
       
   571                                +(noAccess == null ? "" : " !! "+noAccess));
   492         if (positive && noAccess != null)  throw noAccess;
   572         if (positive && noAccess != null)  throw noAccess;
   493         assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
   573         assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
   494         if (!positive)  return; // negative test failed as expected
   574         if (!positive)  return; // negative test failed as expected
   495         Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params);
   575         assertEquals(specialCaller, target.type().parameterType(0));
       
   576         assertEquals(type,          target.type().dropParameterTypes(0,1));
       
   577         Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)specialCaller), params);
   496         MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
   578         MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
   497         MethodType ttype = target.type();
       
   498         ttype = ttype.changeParameterType(0, defc); // FIXME: test this
       
   499         assertEquals(typeWithSelf, ttype);
       
   500         assertTrue(target.toString().contains(name));  // rough check
   579         assertTrue(target.toString().contains(name));  // rough check
   501         if (!DO_MORE_CALLS && lookup != PRIVATE)  return;
   580         if (!DO_MORE_CALLS && lookup != PRIVATE && lookup != EXAMPLE)  return;
   502         Object[] args = randomArgs(paramsWithSelf);
   581         Object[] args = randomArgs(paramsWithSelf);
   503         printCalled(target, name, args);
   582         printCalled(target, name, args);
   504         target.invokeVarargs(args);
   583         target.invokeVarargs(args);
   505         assertCalled(name, args);
   584         assertCalled(name, args);
   506         System.out.print(':');
       
   507     }
   585     }
   508 
   586 
   509     @Test
   587     @Test
   510     public void testBind() throws Throwable {
   588     public void testBind() throws Throwable {
   511         if (CAN_SKIP_WORKING)  return;
   589         if (CAN_SKIP_WORKING)  return;
   536         MethodType type = MethodType.methodType(ret, params);
   614         MethodType type = MethodType.methodType(ret, params);
   537         Object receiver = randomArg(defc);
   615         Object receiver = randomArg(defc);
   538         MethodHandle target = null;
   616         MethodHandle target = null;
   539         RuntimeException noAccess = null;
   617         RuntimeException noAccess = null;
   540         try {
   618         try {
       
   619             if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
   541             target = lookup.bind(receiver, methodName, type);
   620             target = lookup.bind(receiver, methodName, type);
   542         } catch (NoAccessException ex) {
   621         } catch (NoAccessException ex) {
   543             noAccess = ex;
   622             noAccess = ex;
   544         }
   623         }
   545         if (verbosity >= 2)
   624         if (verbosity >= 3)
   546             System.out.println("bind "+receiver+"."+name+"/"+type+" => "+target
   625             System.out.println("bind "+receiver+"."+name+"/"+type+" => "+target
   547                     +(noAccess == null ? "" : " !! "+noAccess));
   626                     +(noAccess == null ? "" : " !! "+noAccess));
   548         if (positive && noAccess != null)  throw noAccess;
   627         if (positive && noAccess != null)  throw noAccess;
   549         assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
   628         assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
   550         if (!positive)  return; // negative test failed as expected
   629         if (!positive)  return; // negative test failed as expected
   552         Object[] args = randomArgs(params);
   631         Object[] args = randomArgs(params);
   553         printCalled(target, name, args);
   632         printCalled(target, name, args);
   554         target.invokeVarargs(args);
   633         target.invokeVarargs(args);
   555         Object[] argsWithReceiver = cat(array(Object[].class, receiver), args);
   634         Object[] argsWithReceiver = cat(array(Object[].class, receiver), args);
   556         assertCalled(name, argsWithReceiver);
   635         assertCalled(name, argsWithReceiver);
   557         System.out.print(':');
   636         if (verbosity >= 1)
       
   637             System.out.print(':');
   558     }
   638     }
   559 
   639 
   560     @Test
   640     @Test
   561     public void testUnreflect() throws Throwable {
   641     public void testUnreflect() throws Throwable {
   562         if (CAN_SKIP_WORKING)  return;
   642         if (CAN_SKIP_WORKING)  return;
   565         testUnreflect(Example.class, true, void.class, "pkg_s0");
   645         testUnreflect(Example.class, true, void.class, "pkg_s0");
   566         testUnreflect(Example.class, true, void.class, "pri_s0");
   646         testUnreflect(Example.class, true, void.class, "pri_s0");
   567 
   647 
   568         testUnreflect(Example.class, true, Object.class, "s1", Object.class);
   648         testUnreflect(Example.class, true, Object.class, "s1", Object.class);
   569         testUnreflect(Example.class, true, Object.class, "s2", int.class);
   649         testUnreflect(Example.class, true, Object.class, "s2", int.class);
   570         //testUnreflect(Example.class, true, Object.class, "s3", long.class);
   650         testUnreflect(Example.class, true, Object.class, "s3", long.class);
   571         //testUnreflect(Example.class, true, Object.class, "s4", int.class, int.class);
   651         testUnreflect(Example.class, true, Object.class, "s4", int.class, int.class);
   572         //testUnreflect(Example.class, true, Object.class, "s5", long.class, int.class);
   652         testUnreflect(Example.class, true, Object.class, "s5", long.class, int.class);
   573         //testUnreflect(Example.class, true, Object.class, "s6", int.class, long.class);
   653         testUnreflect(Example.class, true, Object.class, "s6", int.class, long.class);
   574 
   654 
   575         testUnreflect(Example.class, false, void.class, "v0");
   655         testUnreflect(Example.class, false, void.class, "v0");
   576         testUnreflect(Example.class, false, void.class, "pkg_v0");
   656         testUnreflect(Example.class, false, void.class, "pkg_v0");
   577         testUnreflect(Example.class, false, void.class, "pri_v0");
   657         testUnreflect(Example.class, false, void.class, "pri_v0");
   578         testUnreflect(Example.class, false, Object.class, "v1", Object.class);
   658         testUnreflect(Example.class, false, Object.class, "v1", Object.class);
   582         testUnreflect(Example.class, false, Object.class, "v2", int.class, int.class);
   662         testUnreflect(Example.class, false, Object.class, "v2", int.class, int.class);
   583     }
   663     }
   584 
   664 
   585     void testUnreflect(Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) throws Throwable {
   665     void testUnreflect(Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) throws Throwable {
   586         for (Object[] ac : accessCases(defc, name)) {
   666         for (Object[] ac : accessCases(defc, name)) {
   587             testUnreflect((Boolean)ac[0], (Lookup)ac[1], defc, isStatic, ret, name, params);
   667             testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, (isStatic ? null : defc), ret, name, params);
   588         }
   668         }
   589     }
   669     }
   590     void testUnreflect(boolean positive, Lookup lookup, Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) throws Throwable {
   670     void testUnreflect(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable {
       
   671         for (Object[] ac : accessCases(defc, name)) {
       
   672             testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params);
       
   673         }
       
   674     }
       
   675     void testUnreflectMaybeSpecial(Class<?> specialCaller,
       
   676                                    boolean positive, Lookup lookup,
       
   677                                    Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable {
   591         countTest(positive);
   678         countTest(positive);
   592         MethodType type = MethodType.methodType(ret, params);
   679         MethodType type = MethodType.methodType(ret, params);
   593         Method rmethod = null;
   680         Method rmethod = null;
   594         MethodHandle target = null;
   681         MethodHandle target = null;
   595         RuntimeException noAccess = null;
   682         RuntimeException noAccess = null;
   596         try {
   683         try {
   597             rmethod = defc.getDeclaredMethod(name, params);
   684             rmethod = defc.getDeclaredMethod(name, params);
   598         } catch (NoSuchMethodException ex) {
   685         } catch (NoSuchMethodException ex) {
   599             throw new NoAccessException(ex);
   686             throw new NoAccessException(ex);
   600         }
   687         }
   601         assertEquals(isStatic, Modifier.isStatic(rmethod.getModifiers()));
   688         boolean isStatic = (rcvc == null);
       
   689         boolean isSpecial = (specialCaller != null);
   602         try {
   690         try {
   603             target = lookup.unreflect(rmethod);
   691             if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
       
   692             if (isSpecial)
       
   693                 target = lookup.unreflectSpecial(rmethod, specialCaller);
       
   694             else
       
   695                 target = lookup.unreflect(rmethod);
   604         } catch (NoAccessException ex) {
   696         } catch (NoAccessException ex) {
   605             noAccess = ex;
   697             noAccess = ex;
   606         }
   698         }
   607         if (verbosity >= 2)
   699         if (verbosity >= 3)
   608             System.out.println("unreflect "+defc+"."+name+"/"+type+" => "+target
   700             System.out.println("unreflect"+(isSpecial?"Special":"")+" "+defc.getName()+"."+name+"/"+type
   609                     +(noAccess == null ? "" : " !! "+noAccess));
   701                                +(!isSpecial ? "" : " specialCaller="+specialCaller)
       
   702                                +( isStatic  ? "" : " receiver="+rcvc)
       
   703                                +" => "+target
       
   704                                +(noAccess == null ? "" : " !! "+noAccess));
   610         if (positive && noAccess != null)  throw noAccess;
   705         if (positive && noAccess != null)  throw noAccess;
   611         assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
   706         assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
   612         if (!positive)  return; // negative test failed as expected
   707         if (!positive)  return; // negative test failed as expected
       
   708         assertEquals(isStatic, Modifier.isStatic(rmethod.getModifiers()));
   613         Class<?>[] paramsMaybeWithSelf = params;
   709         Class<?>[] paramsMaybeWithSelf = params;
   614         if (!isStatic) {
   710         if (!isStatic) {
   615             paramsMaybeWithSelf = cat(array(Class[].class, (Class)defc), params);
   711             paramsMaybeWithSelf = cat(array(Class[].class, (Class)rcvc), params);
   616         }
   712         }
   617         MethodType typeMaybeWithSelf = MethodType.methodType(ret, paramsMaybeWithSelf);
   713         MethodType typeMaybeWithSelf = MethodType.methodType(ret, paramsMaybeWithSelf);
   618         MethodType ttype = target.type();
   714         if (isStatic) {
   619         if (!isStatic)
   715             assertEquals(typeMaybeWithSelf, target.type());
   620             ttype = ttype.changeParameterType(0, defc); // FIXME: test this
   716         } else {
   621         assertEquals(typeMaybeWithSelf, ttype);
   717             if (defc.getClassLoader() != null)  // detune due to 6939196
       
   718                 assertEquals(typeMaybeWithSelf.dropParameterTypes(0,1),
       
   719                              target.type().dropParameterTypes(0,1));
       
   720             else // FIXME: use only this test when 6939196 is fixed
       
   721             if (isSpecial)
       
   722                 assertEquals(specialCaller, target.type().parameterType(0));
       
   723             else
       
   724                 assertEquals(defc, target.type().parameterType(0));
       
   725             assertEquals(typeMaybeWithSelf, target.type().changeParameterType(0, rcvc));
       
   726         }
   622         Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf);
   727         Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf);
   623         printCalled(target, name, argsMaybeWithSelf);
   728         printCalled(target, name, argsMaybeWithSelf);
   624         target.invokeVarargs(argsMaybeWithSelf);
   729         target.invokeVarargs(argsMaybeWithSelf);
   625         assertCalled(name, argsMaybeWithSelf);
   730         assertCalled(name, argsMaybeWithSelf);
   626         System.out.print(':');
   731         if (verbosity >= 1)
   627     }
   732             System.out.print(':');
   628 
   733     }
   629     @Test @Ignore("unimplemented")
   734 
       
   735     void testUnreflectSpecial(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable {
       
   736         for (Object[] ac : accessCases(defc, name, true)) {
       
   737             Class<?> specialCaller = rcvc;
       
   738             testUnreflectMaybeSpecial(specialCaller, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params);
       
   739         }
       
   740     }
       
   741 
       
   742     @Test
   630     public void testUnreflectSpecial() throws Throwable {
   743     public void testUnreflectSpecial() throws Throwable {
   631         Lookup lookup = PRIVATE;  // FIXME: test more lookups than this one
   744         if (CAN_SKIP_WORKING)  return;
   632         startTest("unreflectSpecial");
   745         startTest("unreflectSpecial");
   633         Method m = null;
   746         testUnreflectSpecial(Example.class,    Example.class, void.class, "v0");
   634         MethodHandle expResult = null;
   747         testUnreflectSpecial(Example.class, SubExample.class, void.class, "v0");
   635         MethodHandle result = lookup.unreflectSpecial(m, Example.class);
   748         testUnreflectSpecial(Example.class,    Example.class, void.class, "pkg_v0");
   636         assertEquals(expResult, result);
   749         testUnreflectSpecial(Example.class, SubExample.class, void.class, "pkg_v0");
   637         fail("The test case is a prototype.");
   750         testUnreflectSpecial(Example.class,    Example.class, Object.class, "v2", int.class, int.class);
       
   751         testUnreflectSpecial(Example.class, SubExample.class, Object.class, "v2", int.class, int.class);
       
   752         testUnreflectMaybeSpecial(Example.class, false, PRIVATE, Example.class, Example.class, void.class, "s0");
   638     }
   753     }
   639 
   754 
   640     public static class HasFields {
   755     public static class HasFields {
   641         boolean fZ = false;
   756         boolean fZ = false;
   642         byte fB = (byte)'B';
   757         byte fB = (byte)'B';
   733         mh = MethodHandles.convertArguments(mh, mh.type().generic().changeReturnType(rtype));
   848         mh = MethodHandles.convertArguments(mh, mh.type().generic().changeReturnType(rtype));
   734         Object expValue = value;
   849         Object expValue = value;
   735         for (int i = 0; i <= 1; i++) {
   850         for (int i = 0; i <= 1; i++) {
   736             if (isStatic) {
   851             if (isStatic) {
   737                 if (type == int.class)
   852                 if (type == int.class)
   738                     sawValue = mh.<int>invoke();  // do these exactly
   853                     sawValue = mh.<int>invokeExact();  // do these exactly
   739                 else
   854                 else
   740                     sawValue = mh.invoke();
   855                     sawValue = mh.invokeExact();
   741             } else {
   856             } else {
   742                 if (type == int.class)
   857                 if (type == int.class)
   743                     sawValue = mh.<int>invoke((Object) fields);
   858                     sawValue = mh.<int>invokeExact((Object) fields);
   744                 else
   859                 else
   745                     sawValue = mh.invoke((Object) fields);
   860                     sawValue = mh.invokeExact((Object) fields);
   746             }
   861             }
   747             assertEquals(sawValue, expValue);
   862             assertEquals(sawValue, expValue);
   748             Object random = randomArg(type);
   863             Object random = randomArg(type);
   749             f.set(fields, random);
   864             f.set(fields, random);
   750             expValue = random;
   865             expValue = random;
   784         assertEquals(f.get(fields), value);  // clean to start with
   899         assertEquals(f.get(fields), value);  // clean to start with
   785         for (int i = 0; i <= 1; i++) {
   900         for (int i = 0; i <= 1; i++) {
   786             Object putValue = randomArg(type);
   901             Object putValue = randomArg(type);
   787             if (isStatic) {
   902             if (isStatic) {
   788                 if (type == int.class)
   903                 if (type == int.class)
   789                     mh.<void>invoke((int)(Integer)putValue);  // do these exactly
   904                     mh.<void>invokeExact((int)(Integer)putValue);  // do these exactly
   790                 else
   905                 else
   791                     mh.<void>invoke(putValue);
   906                     mh.<void>invokeExact(putValue);
   792             } else {
   907             } else {
   793                 if (type == int.class)
   908                 if (type == int.class)
   794                     mh.<void>invoke((Object) fields, (int)(Integer)putValue);
   909                     mh.<void>invokeExact((Object) fields, (int)(Integer)putValue);
   795                 else
   910                 else
   796                     mh.<void>invoke((Object) fields, putValue);
   911                     mh.<void>invokeExact((Object) fields, putValue);
   797             }
   912             }
   798             assertEquals(f.get(fields), putValue);
   913             assertEquals(f.get(fields), putValue);
   799         }
   914         }
   800         f.set(fields, value);  // put it back
   915         f.set(fields, value);  // put it back
   801     }
   916     }
   802 
   917 
   803     @Test
   918     @Test
   804     public void testArrayElementGetter() throws Throwable {
   919     public void testArrayElementGetter() throws Throwable {
   805         startTest("arrayElementGetter");
   920         startTest("arrayElementGetter");
   806         testArrayElementGetterSetter(new Object[10], false);
   921         testArrayElementGetterSetter(false);
   807         testArrayElementGetterSetter(new String[10], false);
       
   808         testArrayElementGetterSetter(new int[10], false);
       
   809         // FIXME: Do the other primitive types.
       
   810         //testArrayElementGetterSetter(new float[10], false);
       
   811     }
   922     }
   812 
   923 
   813     @Test
   924     @Test
   814     public void testArrayElementSetter() throws Throwable {
   925     public void testArrayElementSetter() throws Throwable {
   815         startTest("arrayElementSetter");
   926         startTest("arrayElementSetter");
   816         testArrayElementGetterSetter(new Object[10], true);
   927         testArrayElementGetterSetter(true);
   817         testArrayElementGetterSetter(new String[10], true);
   928     }
   818         testArrayElementGetterSetter(new int[10], true);
   929 
   819         // FIXME: Do the other primitive types.
   930     public void testArrayElementGetterSetter(boolean testSetter) throws Throwable {
   820         //testArrayElementGetterSetter(new float[10], true);
   931         testArrayElementGetterSetter(new Object[10], testSetter);
       
   932         testArrayElementGetterSetter(new String[10], testSetter);
       
   933         testArrayElementGetterSetter(new boolean[10], testSetter);
       
   934         testArrayElementGetterSetter(new byte[10], testSetter);
       
   935         testArrayElementGetterSetter(new char[10], testSetter);
       
   936         testArrayElementGetterSetter(new short[10], testSetter);
       
   937         testArrayElementGetterSetter(new int[10], testSetter);
       
   938         testArrayElementGetterSetter(new float[10], testSetter);
       
   939         testArrayElementGetterSetter(new long[10], testSetter);
       
   940         testArrayElementGetterSetter(new double[10], testSetter);
   821     }
   941     }
   822 
   942 
   823     public void testArrayElementGetterSetter(Object array, boolean testSetter) throws Throwable {
   943     public void testArrayElementGetterSetter(Object array, boolean testSetter) throws Throwable {
   824         countTest(true);
   944         countTest(true);
       
   945         if (verbosity >= 2)  System.out.println("array type = "+array.getClass().getComponentType().getName()+"["+Array.getLength(array)+"]");
   825         Class<?> arrayType = array.getClass();
   946         Class<?> arrayType = array.getClass();
   826         Class<?> elemType = arrayType.getComponentType();
   947         Class<?> elemType = arrayType.getComponentType();
   827         MethodType expType = !testSetter
   948         MethodType expType = !testSetter
   828                 ? MethodType.methodType(elemType,   arrayType, int.class)
   949                 ? MethodType.methodType(elemType,   arrayType, int.class)
   829                 : MethodType.methodType(void.class, arrayType, int.class, elemType);
   950                 : MethodType.methodType(void.class, arrayType, int.class, elemType);
   830         MethodHandle mh = !testSetter
   951         MethodHandle mh = !testSetter
   831                 ? MethodHandles.arrayElementGetter(arrayType)
   952                 ? MethodHandles.arrayElementGetter(arrayType)
   832                 : MethodHandles.arrayElementSetter(arrayType);
   953                 : MethodHandles.arrayElementSetter(arrayType);
   833         assertSame(mh.type(), expType);
   954         assertSame(mh.type(), expType);
   834         //assertEquals(mh.toString(), f.getName());
   955         if (elemType != int.class && elemType != boolean.class) {
       
   956             MethodType gtype;
       
   957             if (true) { // FIXME: remove this path (and remove <void> below in the mh.invokes)
       
   958                 gtype = mh.type().changeParameterType(0, Object.class);
       
   959                 if (testSetter)
       
   960                     gtype = gtype.changeParameterType(2, Object.class);
       
   961                 else
       
   962                     gtype = gtype.changeReturnType(Object.class);
       
   963             } else
       
   964                 // FIXME: This simpler path hits a bug in convertArguments => ToGeneric
       
   965                 gtype = mh.type().generic().changeParameterType(1, int.class);
       
   966             mh = MethodHandles.convertArguments(mh, gtype);
       
   967         }
   835         Object sawValue, expValue;
   968         Object sawValue, expValue;
   836         List<Object> model = array2list(array);
   969         List<Object> model = array2list(array);
   837         int length = Array.getLength(array);
   970         int length = Array.getLength(array);
   838         for (int i = 0; i < length; i++) {
   971         for (int i = 0; i < length; i++) {
   839             // update array element
   972             // update array element
   840             Object random = randomArg(elemType);
   973             Object random = randomArg(elemType);
   841             model.set(i, random);
   974             model.set(i, random);
   842             if (testSetter) {
   975             if (testSetter) {
   843                 if (elemType == int.class)
   976                 if (elemType == int.class)
   844                     mh.<void>invoke((int[]) array, i, (int)(Integer)random);
   977                     mh.<void>invokeExact((int[]) array, i, (int)(Integer)random);
       
   978                 else if (elemType == boolean.class)
       
   979                     mh.<void>invokeExact((boolean[]) array, i, (boolean)(Boolean)random);
   845                 else
   980                 else
   846                     mh.invokeGeneric(array, i, random);
   981                     mh.<void>invokeExact(array, i, random);
   847                 assertEquals(model, array2list(array));
   982                 assertEquals(model, array2list(array));
   848             } else {
   983             } else {
   849                 Array.set(array, i, random);
   984                 Array.set(array, i, random);
   850 
   985             }
       
   986             if (verbosity >= 5) {
       
   987                 List<Object> array2list = array2list(array);
       
   988                 System.out.println("a["+i+"]="+random+" => "+array2list);
       
   989                 if (!array2list.equals(model))
       
   990                     System.out.println("***   != "+model);
   851             }
   991             }
   852             // observe array element
   992             // observe array element
   853             sawValue = Array.get(array, i);
   993             sawValue = Array.get(array, i);
   854             if (!testSetter) {
   994             if (!testSetter) {
   855                 expValue = sawValue;
   995                 expValue = sawValue;
   856                 if (elemType == int.class)
   996                 if (elemType == int.class)
   857                     sawValue = mh.<int>invoke((int[]) array, i);
   997                     sawValue = mh.<int>invokeExact((int[]) array, i);
       
   998                 else if (elemType == boolean.class)
       
   999                     sawValue = mh.<boolean>invokeExact((boolean[]) array, i);
   858                 else
  1000                 else
   859                     sawValue = mh.invokeGeneric(array, i);
  1001                     sawValue = mh.invokeExact(array, i);
   860                 assertEquals(sawValue, expValue);
  1002                 assertEquals(sawValue, expValue);
   861                 assertEquals(model, array2list(array));
  1003                 assertEquals(model, array2list(array));
   862             }
  1004             }
   863         }
  1005         }
   864     }
  1006     }
   904         startTest("convertArguments");
  1046         startTest("convertArguments");
   905         testConvert(Callee.ofType(1), null, "id", int.class);
  1047         testConvert(Callee.ofType(1), null, "id", int.class);
   906         testConvert(Callee.ofType(1), null, "id", String.class);
  1048         testConvert(Callee.ofType(1), null, "id", String.class);
   907         testConvert(Callee.ofType(1), null, "id", Integer.class);
  1049         testConvert(Callee.ofType(1), null, "id", Integer.class);
   908         testConvert(Callee.ofType(1), null, "id", short.class);
  1050         testConvert(Callee.ofType(1), null, "id", short.class);
       
  1051         testConvert(Callee.ofType(1), null, "id", char.class);
       
  1052         testConvert(Callee.ofType(1), null, "id", byte.class);
   909     }
  1053     }
   910 
  1054 
   911     void testConvert(MethodHandle id, Class<?> rtype, String name, Class<?>... params) throws Throwable {
  1055     void testConvert(MethodHandle id, Class<?> rtype, String name, Class<?>... params) throws Throwable {
   912         testConvert(true, id, rtype, name, params);
  1056         testConvert(true, id, rtype, name, params);
   913     }
  1057     }
   941         try {
  1085         try {
   942             target = MethodHandles.convertArguments(id, newType);
  1086             target = MethodHandles.convertArguments(id, newType);
   943         } catch (RuntimeException ex) {
  1087         } catch (RuntimeException ex) {
   944             error = ex;
  1088             error = ex;
   945         }
  1089         }
   946         if (verbosity >= 2)
  1090         if (verbosity >= 3)
   947             System.out.println("convert "+id+ " to "+newType+" => "+target
  1091             System.out.println("convert "+id+ " to "+newType+" => "+target
   948                     +(error == null ? "" : " !! "+error));
  1092                     +(error == null ? "" : " !! "+error));
   949         if (positive && error != null)  throw error;
  1093         if (positive && error != null)  throw error;
   950         assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
  1094         assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
   951         if (!positive)  return; // negative test failed as expected
  1095         if (!positive)  return; // negative test failed as expected
   952         assertEquals(newType, target.type());
  1096         assertEquals(newType, target.type());
   953         printCalled(target, id.toString(), args);
  1097         printCalled(target, id.toString(), args);
   954         Object result = target.invokeVarargs(args);
  1098         Object result = target.invokeVarargs(args);
   955         assertCalled(name, convArgs);
  1099         assertCalled(name, convArgs);
   956         assertEquals(convResult, result);
  1100         assertEquals(convResult, result);
   957         System.out.print(':');
  1101         if (verbosity >= 1)
       
  1102             System.out.print(':');
   958     }
  1103     }
   959 
  1104 
   960     @Test
  1105     @Test
   961     public void testPermuteArguments() throws Throwable {
  1106     public void testPermuteArguments() throws Throwable {
   962         if (CAN_SKIP_WORKING)  return;
  1107         if (CAN_SKIP_WORKING)  return;
   964         testPermuteArguments(4, Integer.class,  2, String.class,  0);
  1109         testPermuteArguments(4, Integer.class,  2, String.class,  0);
   965         //testPermuteArguments(6, Integer.class,  0, null,         30);
  1110         //testPermuteArguments(6, Integer.class,  0, null,         30);
   966         //testPermuteArguments(4, Integer.class,  1, int.class,     6);
  1111         //testPermuteArguments(4, Integer.class,  1, int.class,     6);
   967     }
  1112     }
   968     public void testPermuteArguments(int max, Class<?> type1, int t2c, Class<?> type2, int dilution) throws Throwable {
  1113     public void testPermuteArguments(int max, Class<?> type1, int t2c, Class<?> type2, int dilution) throws Throwable {
   969         if (verbosity >= 1)
  1114         if (verbosity >= 2)
   970             System.out.println("permuteArguments "+max+"*"+type1.getName()
  1115             System.out.println("permuteArguments "+max+"*"+type1.getName()
   971                     +(t2c==0?"":"/"+t2c+"*"+type2.getName())
  1116                     +(t2c==0?"":"/"+t2c+"*"+type2.getName())
   972                     +(dilution > 0 ? " with dilution "+dilution : ""));
  1117                     +(dilution > 0 ? " with dilution "+dilution : ""));
   973         int t2pos = t2c == 0 ? 0 : 1;
  1118         int t2pos = t2c == 0 ? 0 : 1;
   974         for (int inargs = t2pos+1; inargs <= max; inargs++) {
  1119         for (int inargs = t2pos+1; inargs <= max; inargs++) {
  1052             for (int i = 0; i < args.length; i++)
  1197             for (int i = 0; i < args.length; i++)
  1053                 types[i] = args[i].getClass();
  1198                 types[i] = args[i].getClass();
  1054         }
  1199         }
  1055         int inargs = args.length, outargs = reorder.length;
  1200         int inargs = args.length, outargs = reorder.length;
  1056         assert(inargs == types.length);
  1201         assert(inargs == types.length);
  1057         if (verbosity >= 2)
  1202         if (verbosity >= 3)
  1058             System.out.println("permuteArguments "+Arrays.toString(reorder));
  1203             System.out.println("permuteArguments "+Arrays.toString(reorder));
  1059         Object[] permArgs = new Object[outargs];
  1204         Object[] permArgs = new Object[outargs];
  1060         Class<?>[] permTypes = new Class<?>[outargs];
  1205         Class<?>[] permTypes = new Class<?>[outargs];
  1061         for (int i = 0; i < outargs; i++) {
  1206         for (int i = 0; i < outargs; i++) {
  1062             permArgs[i] = args[reorder[i]];
  1207             permArgs[i] = args[reorder[i]];
  1063             permTypes[i] = types[reorder[i]];
  1208             permTypes[i] = types[reorder[i]];
  1064         }
  1209         }
  1065         if (verbosity >= 3) {
  1210         if (verbosity >= 4) {
  1066             System.out.println("in args:   "+Arrays.asList(args));
  1211             System.out.println("in args:   "+Arrays.asList(args));
  1067             System.out.println("out args:  "+Arrays.asList(permArgs));
  1212             System.out.println("out args:  "+Arrays.asList(permArgs));
  1068             System.out.println("in types:  "+Arrays.asList(types));
  1213             System.out.println("in types:  "+Arrays.asList(types));
  1069             System.out.println("out types: "+Arrays.asList(permTypes));
  1214             System.out.println("out types: "+Arrays.asList(permTypes));
  1070         }
  1215         }
  1081     @Test
  1226     @Test
  1082     public void testSpreadArguments() throws Throwable {
  1227     public void testSpreadArguments() throws Throwable {
  1083         if (CAN_SKIP_WORKING)  return;
  1228         if (CAN_SKIP_WORKING)  return;
  1084         startTest("spreadArguments");
  1229         startTest("spreadArguments");
  1085         for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
  1230         for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
  1086             if (verbosity >= 2)
  1231             if (verbosity >= 3)
  1087                 System.out.println("spreadArguments "+argType);
  1232                 System.out.println("spreadArguments "+argType);
       
  1233             // FIXME: enable _adapter_spread_args and fix Fail_2
  1088             for (int nargs = 0; nargs < 10; nargs++) {
  1234             for (int nargs = 0; nargs < 10; nargs++) {
  1089                 if (argType == int.class && nargs >= 6)  continue; // FIXME Fail_1
  1235                 if (argType == int.class && nargs >= 6)  continue; // FIXME Fail_1
  1090                 for (int pos = 0; pos < nargs; pos++) {
  1236                 for (int pos = 0; pos < nargs; pos++) {
  1091                     if (argType == int.class && pos > 0)  continue; // FIXME Fail_3
  1237                     if (argType == int.class && pos > 0)  continue; // FIXME Fail_3
  1092                     testSpreadArguments(argType, pos, nargs);
  1238                      testSpreadArguments(argType, pos, nargs);
  1093                 }
  1239                 }
  1094             }
  1240             }
  1095         }
  1241         }
  1096     }
  1242     }
  1097     public void testSpreadArguments(Class<?> argType, int pos, int nargs) throws Throwable {
  1243     public void testSpreadArguments(Class<?> argType, int pos, int nargs) throws Throwable {
  1098         countTest();
  1244         countTest();
  1099         MethodHandle target = ValueConversions.varargsArray(nargs);
  1245         MethodHandle target = ValueConversions.varargsArray(nargs);
  1100         MethodHandle target2 = changeArgTypes(target, argType);
  1246         MethodHandle target2 = changeArgTypes(target, argType);
  1101         if (verbosity >= 2)
  1247         if (verbosity >= 3)
  1102             System.out.println("spread into "+target2+" ["+pos+".."+nargs+"]");
  1248             System.out.println("spread into "+target2+" ["+pos+".."+nargs+"]");
  1103         Object[] args = randomArgs(target2.type().parameterArray());
  1249         Object[] args = randomArgs(target2.type().parameterArray());
  1104         // make sure the target does what we think it does:
  1250         // make sure the target does what we think it does:
  1105         if (pos == 0 && nargs < 5) {
  1251         if (pos == 0 && nargs < 5) {
  1106             Object[] check = (Object[]) target.invokeVarargs(args);
  1252             Object[] check = (Object[]) target.invokeVarargs(args);
  1107             assertArrayEquals(args, check);
  1253             assertArrayEquals(args, check);
  1108             switch (nargs) {
  1254             switch (nargs) {
  1109                 case 0:
  1255                 case 0:
  1110                     check = target.<Object[]>invoke();
  1256                     check = target.<Object[]>invokeExact();
  1111                     assertArrayEquals(args, check);
  1257                     assertArrayEquals(args, check);
  1112                     break;
  1258                     break;
  1113                 case 1:
  1259                 case 1:
  1114                     check = target.<Object[]>invoke(args[0]);
  1260                     check = target.<Object[]>invokeExact(args[0]);
  1115                     assertArrayEquals(args, check);
  1261                     assertArrayEquals(args, check);
  1116                     break;
  1262                     break;
  1117                 case 2:
  1263                 case 2:
  1118                     check = target.<Object[]>invoke(args[0], args[1]);
  1264                     check = target.<Object[]>invokeExact(args[0], args[1]);
  1119                     assertArrayEquals(args, check);
  1265                     assertArrayEquals(args, check);
  1120                     break;
  1266                     break;
  1121             }
  1267             }
  1122         }
  1268         }
  1123         List<Class<?>> newParams = new ArrayList<Class<?>>(target2.type().parameterList());
  1269         List<Class<?>> newParams = new ArrayList<Class<?>>(target2.type().parameterList());
  1127         }
  1273         }
  1128         MethodType newType = MethodType.methodType(Object.class, newParams);
  1274         MethodType newType = MethodType.methodType(Object.class, newParams);
  1129         MethodHandle result = MethodHandles.spreadArguments(target2, newType);
  1275         MethodHandle result = MethodHandles.spreadArguments(target2, newType);
  1130         Object[] returnValue;
  1276         Object[] returnValue;
  1131         if (pos == 0) {
  1277         if (pos == 0) {
  1132             returnValue = (Object[]) result.invoke(args);
  1278             returnValue = (Object[]) result.invokeExact(args);
  1133         } else {
  1279         } else {
  1134             Object[] args1 = Arrays.copyOfRange(args, 0, pos+1);
  1280             Object[] args1 = Arrays.copyOfRange(args, 0, pos+1);
  1135             args1[pos] = Arrays.copyOfRange(args, pos, args.length);
  1281             args1[pos] = Arrays.copyOfRange(args, pos, args.length);
  1136             returnValue = (Object[]) result.invokeVarargs(args1);
  1282             returnValue = (Object[]) result.invokeVarargs(args1);
  1137         }
  1283         }
  1141     @Test
  1287     @Test
  1142     public void testCollectArguments() throws Throwable {
  1288     public void testCollectArguments() throws Throwable {
  1143         if (CAN_SKIP_WORKING)  return;
  1289         if (CAN_SKIP_WORKING)  return;
  1144         startTest("collectArguments");
  1290         startTest("collectArguments");
  1145         for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
  1291         for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
  1146             if (verbosity >= 2)
  1292             if (verbosity >= 3)
  1147                 System.out.println("collectArguments "+argType);
  1293                 System.out.println("collectArguments "+argType);
  1148             for (int nargs = 0; nargs < 10; nargs++) {
  1294             for (int nargs = 0; nargs < 10; nargs++) {
  1149                 for (int pos = 0; pos < nargs; pos++) {
  1295                 for (int pos = 0; pos < nargs; pos++) {
  1150                     if (argType == int.class)  continue; // FIXME Fail_4
  1296                     if (argType == int.class)  continue; // FIXME Fail_4
  1151                     testCollectArguments(argType, pos, nargs);
  1297                     testCollectArguments(argType, pos, nargs);
  1165         collectedArgs[pos] = Arrays.copyOfRange(args, pos, args.length);
  1311         collectedArgs[pos] = Arrays.copyOfRange(args, pos, args.length);
  1166         // here is the MH which will witness the collected argument tail:
  1312         // here is the MH which will witness the collected argument tail:
  1167         MethodHandle target = ValueConversions.varargsArray(pos+1);
  1313         MethodHandle target = ValueConversions.varargsArray(pos+1);
  1168         target = changeArgTypes(target, 0, pos, argType);
  1314         target = changeArgTypes(target, 0, pos, argType);
  1169         target = changeArgTypes(target, pos, pos+1, Object[].class);
  1315         target = changeArgTypes(target, pos, pos+1, Object[].class);
  1170         if (verbosity >= 2)
  1316         if (verbosity >= 3)
  1171             System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]");
  1317             System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]");
  1172         MethodHandle result = MethodHandles.collectArguments(target, newType);
  1318         MethodHandle result = MethodHandles.collectArguments(target, newType);
  1173         Object[] returnValue = (Object[]) result.invokeVarargs(args);
  1319         Object[] returnValue = (Object[]) result.invokeVarargs(args);
  1174 //        assertTrue(returnValue.length == pos+1 && returnValue[pos] instanceof Object[]);
  1320 //        assertTrue(returnValue.length == pos+1 && returnValue[pos] instanceof Object[]);
  1175 //        returnValue[pos] = Arrays.asList((Object[]) returnValue[pos]);
  1321 //        returnValue[pos] = Arrays.asList((Object[]) returnValue[pos]);
  1196         MethodHandle target = ValueConversions.varargsArray(nargs + ins);
  1342         MethodHandle target = ValueConversions.varargsArray(nargs + ins);
  1197         Object[] args = randomArgs(target.type().parameterArray());
  1343         Object[] args = randomArgs(target.type().parameterArray());
  1198         List<Object> resList = Arrays.asList(args);
  1344         List<Object> resList = Arrays.asList(args);
  1199         List<Object> argsToPass = new ArrayList<Object>(resList);
  1345         List<Object> argsToPass = new ArrayList<Object>(resList);
  1200         List<Object> argsToInsert = argsToPass.subList(pos, pos + ins);
  1346         List<Object> argsToInsert = argsToPass.subList(pos, pos + ins);
  1201         if (verbosity >= 2)
  1347         if (verbosity >= 3)
  1202             System.out.println("insert: "+argsToInsert+" into "+target);
  1348             System.out.println("insert: "+argsToInsert+" into "+target);
  1203         MethodHandle target2 = MethodHandles.insertArguments(target, pos,
  1349         MethodHandle target2 = MethodHandles.insertArguments(target, pos,
  1204                 (Object[]) argsToInsert.toArray());
  1350                 (Object[]) argsToInsert.toArray());
  1205         argsToInsert.clear();  // remove from argsToInsert
  1351         argsToInsert.clear();  // remove from argsToInsert
  1206         Object res2 = target2.invokeVarargs(argsToPass);
  1352         Object res2 = target2.invokeVarargs(argsToPass);
  1207         Object res2List = Arrays.asList((Object[])res2);
  1353         Object res2List = Arrays.asList((Object[])res2);
  1208         if (verbosity >= 2)
  1354         if (verbosity >= 3)
  1209             System.out.println("result: "+res2List);
  1355             System.out.println("result: "+res2List);
  1210         //if (!resList.equals(res2List))
  1356         //if (!resList.equals(res2List))
  1211         //    System.out.println("*** fail at n/p/i = "+nargs+"/"+pos+"/"+ins+": "+resList+" => "+res2List);
  1357         //    System.out.println("*** fail at n/p/i = "+nargs+"/"+pos+"/"+ins+": "+resList+" => "+res2List);
  1212         assertEquals(resList, res2List);
  1358         assertEquals(resList, res2List);
  1213     }
  1359     }
  1227         countTest();
  1373         countTest();
  1228         MethodHandle target = ValueConversions.varargsList(nargs);
  1374         MethodHandle target = ValueConversions.varargsList(nargs);
  1229         MethodHandle filter = ValueConversions.varargsList(1);
  1375         MethodHandle filter = ValueConversions.varargsList(1);
  1230         filter = MethodHandles.convertArguments(filter, filter.type().generic());
  1376         filter = MethodHandles.convertArguments(filter, filter.type().generic());
  1231         Object[] argsToPass = randomArgs(nargs, Object.class);
  1377         Object[] argsToPass = randomArgs(nargs, Object.class);
  1232         if (verbosity >= 2)
  1378         if (verbosity >= 3)
  1233             System.out.println("filter "+target+" at "+pos+" with "+filter);
  1379             System.out.println("filter "+target+" at "+pos+" with "+filter);
  1234         MethodHandle[] filters = new MethodHandle[pos*2+1];
  1380         MethodHandle[] filters = new MethodHandle[pos*2+1];
  1235         filters[pos] = filter;
  1381         filters[pos] = filter;
  1236         MethodHandle target2 = MethodHandles.filterArguments(target, filters);
  1382         MethodHandle target2 = MethodHandles.filterArguments(target, filters);
  1237         // Simulate expected effect of filter on arglist:
  1383         // Simulate expected effect of filter on arglist:
  1238         Object[] filteredArgs = argsToPass.clone();
  1384         Object[] filteredArgs = argsToPass.clone();
  1239         filteredArgs[pos] = filter.invoke(filteredArgs[pos]);
  1385         filteredArgs[pos] = filter.invokeExact(filteredArgs[pos]);
  1240         List<Object> expected = Arrays.asList(filteredArgs);
  1386         List<Object> expected = Arrays.asList(filteredArgs);
  1241         Object result = target2.invokeVarargs(argsToPass);
  1387         Object result = target2.invokeVarargs(argsToPass);
  1242         if (verbosity >= 2)
  1388         if (verbosity >= 3)
  1243             System.out.println("result: "+result);
  1389             System.out.println("result: "+result);
  1244         if (!expected.equals(result))
  1390         if (!expected.equals(result))
  1245             System.out.println("*** fail at n/p = "+nargs+"/"+pos+": "+argsToPass+" => "+result);
  1391             System.out.println("*** fail at n/p = "+nargs+"/"+pos+": "+argsToPass+" => "+result);
  1246         assertEquals(expected, result);
  1392         assertEquals(expected, result);
  1247     }
  1393     }
  1263         if (pos != 0)  return;  // can fold only at pos=0 for now
  1409         if (pos != 0)  return;  // can fold only at pos=0 for now
  1264         countTest();
  1410         countTest();
  1265         MethodHandle target = ValueConversions.varargsList(1 + nargs);
  1411         MethodHandle target = ValueConversions.varargsList(1 + nargs);
  1266         MethodHandle combine = ValueConversions.varargsList(fold);
  1412         MethodHandle combine = ValueConversions.varargsList(fold);
  1267         List<Object> argsToPass = Arrays.asList(randomArgs(nargs, Object.class));
  1413         List<Object> argsToPass = Arrays.asList(randomArgs(nargs, Object.class));
  1268         if (verbosity >= 2)
  1414         if (verbosity >= 3)
  1269             System.out.println("fold "+target+" with "+combine);
  1415             System.out.println("fold "+target+" with "+combine);
  1270         MethodHandle target2 = MethodHandles.foldArguments(target, combine);
  1416         MethodHandle target2 = MethodHandles.foldArguments(target, combine);
  1271         // Simulate expected effect of combiner on arglist:
  1417         // Simulate expected effect of combiner on arglist:
  1272         List<Object> expected = new ArrayList<Object>(argsToPass);
  1418         List<Object> expected = new ArrayList<Object>(argsToPass);
  1273         List<Object> argsToFold = expected.subList(pos, pos + fold);
  1419         List<Object> argsToFold = expected.subList(pos, pos + fold);
  1274         if (verbosity >= 2)
  1420         if (verbosity >= 3)
  1275             System.out.println("fold: "+argsToFold+" into "+target2);
  1421             System.out.println("fold: "+argsToFold+" into "+target2);
  1276         Object foldedArgs = combine.invokeVarargs(argsToFold);
  1422         Object foldedArgs = combine.invokeVarargs(argsToFold);
  1277         argsToFold.add(0, foldedArgs);
  1423         argsToFold.add(0, foldedArgs);
  1278         Object result = target2.invokeVarargs(argsToPass);
  1424         Object result = target2.invokeVarargs(argsToPass);
  1279         if (verbosity >= 2)
  1425         if (verbosity >= 3)
  1280             System.out.println("result: "+result);
  1426             System.out.println("result: "+result);
  1281         if (!expected.equals(result))
  1427         if (!expected.equals(result))
  1282             System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result);
  1428             System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result);
  1283         assertEquals(expected, result);
  1429         assertEquals(expected, result);
  1284     }
  1430     }
  1341             }
  1487             }
  1342         }
  1488         }
  1343     }
  1489     }
  1344 
  1490 
  1345     public void testInvokers(MethodType type) throws Throwable {
  1491     public void testInvokers(MethodType type) throws Throwable {
  1346         if (verbosity >= 2)
  1492         if (verbosity >= 3)
  1347             System.out.println("test invokers for "+type);
  1493             System.out.println("test invokers for "+type);
  1348         int nargs = type.parameterCount();
  1494         int nargs = type.parameterCount();
  1349         boolean testRetCode = type.returnType() != void.class;
  1495         boolean testRetCode = type.returnType() != void.class;
  1350         MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "invokee",
  1496         MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "invokee",
  1351                                 MethodType.genericMethodType(0, true));
  1497                                 MethodType.genericMethodType(0, true));
  1371         inv = MethodHandles.genericInvoker(type);
  1517         inv = MethodHandles.genericInvoker(type);
  1372         if (nargs <= 3) {
  1518         if (nargs <= 3) {
  1373             calledLog.clear();
  1519             calledLog.clear();
  1374             switch (nargs) {
  1520             switch (nargs) {
  1375             case 0:
  1521             case 0:
  1376                 result = inv.invoke(target);
  1522                 result = inv.invokeExact(target);
  1377                 break;
  1523                 break;
  1378             case 1:
  1524             case 1:
  1379                 result = inv.invoke(target, args[0]);
  1525                 result = inv.invokeExact(target, args[0]);
  1380                 break;
  1526                 break;
  1381             case 2:
  1527             case 2:
  1382                 result = inv.invoke(target, args[0], args[1]);
  1528                 result = inv.invokeExact(target, args[0], args[1]);
  1383                 break;
  1529                 break;
  1384             case 3:
  1530             case 3:
  1385                 result = inv.invoke(target, args[0], args[1], args[2]);
  1531                 result = inv.invokeExact(target, args[0], args[1], args[2]);
  1386                 break;
  1532                 break;
  1387             }
  1533             }
  1388             if (testRetCode)  assertEquals(code, result);
  1534             if (testRetCode)  assertEquals(code, result);
  1389             assertCalled("invokee", args);
  1535             assertCalled("invokee", args);
  1390         }
  1536         }
  1393         if (testRetCode)  assertEquals(code, result);
  1539         if (testRetCode)  assertEquals(code, result);
  1394         assertCalled("invokee", args);
  1540         assertCalled("invokee", args);
  1395         // varargs invoker #0
  1541         // varargs invoker #0
  1396         calledLog.clear();
  1542         calledLog.clear();
  1397         inv = MethodHandles.varargsInvoker(type, 0);
  1543         inv = MethodHandles.varargsInvoker(type, 0);
  1398         result = inv.invoke(target, args);
  1544         result = inv.invokeExact(target, args);
  1399         if (testRetCode)  assertEquals(code, result);
  1545         if (testRetCode)  assertEquals(code, result);
  1400         assertCalled("invokee", args);
  1546         assertCalled("invokee", args);
  1401         if (nargs >= 1) {
  1547         if (nargs >= 1) {
  1402             // varargs invoker #1
  1548             // varargs invoker #1
  1403             calledLog.clear();
  1549             calledLog.clear();
  1404             inv = MethodHandles.varargsInvoker(type, 1);
  1550             inv = MethodHandles.varargsInvoker(type, 1);
  1405             result = inv.invoke(target, args[0], Arrays.copyOfRange(args, 1, nargs));
  1551             result = inv.invokeExact(target, args[0], Arrays.copyOfRange(args, 1, nargs));
  1406             if (testRetCode)  assertEquals(code, result);
  1552             if (testRetCode)  assertEquals(code, result);
  1407             assertCalled("invokee", args);
  1553             assertCalled("invokee", args);
  1408         }
  1554         }
  1409         if (nargs >= 2) {
  1555         if (nargs >= 2) {
  1410             // varargs invoker #2
  1556             // varargs invoker #2
  1411             calledLog.clear();
  1557             calledLog.clear();
  1412             inv = MethodHandles.varargsInvoker(type, 2);
  1558             inv = MethodHandles.varargsInvoker(type, 2);
  1413             result = inv.invoke(target, args[0], args[1], Arrays.copyOfRange(args, 2, nargs));
  1559             result = inv.invokeExact(target, args[0], args[1], Arrays.copyOfRange(args, 2, nargs));
  1414             if (testRetCode)  assertEquals(code, result);
  1560             if (testRetCode)  assertEquals(code, result);
  1415             assertCalled("invokee", args);
  1561             assertCalled("invokee", args);
  1416         }
  1562         }
  1417         if (nargs >= 3) {
  1563         if (nargs >= 3) {
  1418             // varargs invoker #3
  1564             // varargs invoker #3
  1419             calledLog.clear();
  1565             calledLog.clear();
  1420             inv = MethodHandles.varargsInvoker(type, 3);
  1566             inv = MethodHandles.varargsInvoker(type, 3);
  1421             result = inv.invoke(target, args[0], args[1], args[2], Arrays.copyOfRange(args, 3, nargs));
  1567             result = inv.invokeExact(target, args[0], args[1], args[2], Arrays.copyOfRange(args, 3, nargs));
  1422             if (testRetCode)  assertEquals(code, result);
  1568             if (testRetCode)  assertEquals(code, result);
  1423             assertCalled("invokee", args);
  1569             assertCalled("invokee", args);
  1424         }
  1570         }
  1425         for (int k = 0; k <= nargs; k++) {
  1571         for (int k = 0; k <= nargs; k++) {
  1426             // varargs invoker #0..N
  1572             // varargs invoker #0..N
  1521             case 0:   equals = true; break;
  1667             case 0:   equals = true; break;
  1522             case 1:   equals = MISSING_ARG.equals(argList[0]); break;
  1668             case 1:   equals = MISSING_ARG.equals(argList[0]); break;
  1523             default:  equals = argList[0].equals(argList[1]); break;
  1669             default:  equals = argList[0].equals(argList[1]); break;
  1524             }
  1670             }
  1525             String willCall = (equals ? "targetIfEquals" : "fallbackIfNotEquals");
  1671             String willCall = (equals ? "targetIfEquals" : "fallbackIfNotEquals");
  1526             if (verbosity >= 2)
  1672             if (verbosity >= 3)
  1527                 System.out.println(logEntry(willCall, argList));
  1673                 System.out.println(logEntry(willCall, argList));
  1528             Object result = mh.invokeVarargs(argList);
  1674             Object result = mh.invokeVarargs(argList);
  1529             assertCalled(willCall, argList);
  1675             assertCalled(willCall, argList);
  1530         }
  1676         }
  1531     }
  1677     }
  1550         return normal;
  1696         return normal;
  1551     }
  1697     }
  1552 
  1698 
  1553     void testCatchException(Class<?> returnType, Throwable thrown, boolean throwIt, int nargs) throws Throwable {
  1699     void testCatchException(Class<?> returnType, Throwable thrown, boolean throwIt, int nargs) throws Throwable {
  1554         countTest();
  1700         countTest();
  1555         if (verbosity >= 2)
  1701         if (verbosity >= 3)
  1556             System.out.println("catchException rt="+returnType+" throw="+throwIt+" nargs="+nargs);
  1702             System.out.println("catchException rt="+returnType+" throw="+throwIt+" nargs="+nargs);
  1557         Class<? extends Throwable> exType = thrown.getClass();
  1703         Class<? extends Throwable> exType = thrown.getClass();
  1558         MethodHandle throwOrReturn
  1704         MethodHandle throwOrReturn
  1559                 = PRIVATE.findStatic(MethodHandlesTest.class, "throwOrReturn",
  1705                 = PRIVATE.findStatic(MethodHandlesTest.class, "throwOrReturn",
  1560                     MethodType.methodType(Object.class, Object.class, Throwable.class));
  1706                     MethodType.methodType(Object.class, Object.class, Throwable.class));
  1592         Class<? extends Throwable> exType = thrown.getClass();
  1738         Class<? extends Throwable> exType = thrown.getClass();
  1593         MethodHandle target = MethodHandles.throwException(returnType, exType);
  1739         MethodHandle target = MethodHandles.throwException(returnType, exType);
  1594         //System.out.println("throwing with "+target+" : "+thrown);
  1740         //System.out.println("throwing with "+target+" : "+thrown);
  1595         MethodType expectedType = MethodType.methodType(returnType, exType);
  1741         MethodType expectedType = MethodType.methodType(returnType, exType);
  1596         assertEquals(expectedType, target.type());
  1742         assertEquals(expectedType, target.type());
       
  1743         target = MethodHandles.convertArguments(target, target.type().generic());
  1597         Throwable caught = null;
  1744         Throwable caught = null;
  1598         try {
  1745         try {
  1599             Object res = target.invokeGeneric(thrown);
  1746             Object res = target.invokeExact((Object) thrown);
  1600             fail("got "+res+" instead of throwing "+thrown);
  1747             fail("got "+res+" instead of throwing "+thrown);
  1601         } catch (Throwable ex) {
  1748         } catch (Throwable ex) {
  1602             if (ex != thrown) {
  1749             if (ex != thrown) {
  1603                 if (ex instanceof Error)  throw (Error)ex;
  1750                 if (ex instanceof Error)  throw (Error)ex;
  1604                 if (ex instanceof RuntimeException)  throw (RuntimeException)ex;
  1751                 if (ex instanceof RuntimeException)  throw (RuntimeException)ex;
  1645                     MethodType.methodType(int.class, int.class));
  1792                     MethodType.methodType(int.class, int.class));
  1646     }
  1793     }
  1647 
  1794 
  1648     void testCastFailure(String mode, int okCount) throws Throwable {
  1795     void testCastFailure(String mode, int okCount) throws Throwable {
  1649         countTest(false);
  1796         countTest(false);
  1650         if (verbosity > 1)  System.out.println("mode="+mode);
  1797         if (verbosity > 2)  System.out.println("mode="+mode);
  1651         Surprise boo = new Surprise();
  1798         Surprise boo = new Surprise();
  1652         MethodHandle identity = Surprise.REF_IDENTITY, surprise = boo;
  1799         MethodHandle identity = Surprise.REF_IDENTITY, surprise = boo;
  1653         if (mode.endsWith("/return")) {
  1800         if (mode.endsWith("/return")) {
  1654             if (mode.equals("unbox/return")) {
  1801             if (mode.equals("unbox/return")) {
  1655                 // fail on return to ((Integer)surprise).intValue
  1802                 // fail on return to ((Integer)surprise).intValue
  1678         assertNotSame(mode, surprise, boo);
  1825         assertNotSame(mode, surprise, boo);
  1679         identity = MethodHandles.convertArguments(identity, MethodType.genericMethodType(1));
  1826         identity = MethodHandles.convertArguments(identity, MethodType.genericMethodType(1));
  1680         surprise = MethodHandles.convertArguments(surprise, MethodType.genericMethodType(1));
  1827         surprise = MethodHandles.convertArguments(surprise, MethodType.genericMethodType(1));
  1681         Object x = 42;
  1828         Object x = 42;
  1682         for (int i = 0; i < okCount; i++) {
  1829         for (int i = 0; i < okCount; i++) {
  1683             Object y = identity.invoke(x);
  1830             Object y = identity.invokeExact(x);
  1684             assertEquals(x, y);
  1831             assertEquals(x, y);
  1685             Object z = surprise.invoke(x);
  1832             Object z = surprise.invokeExact(x);
  1686             assertEquals(x, z);
  1833             assertEquals(x, z);
  1687         }
  1834         }
  1688         boo.boo("Boo!");
  1835         boo.boo("Boo!");
  1689         Object y = identity.invoke(x);
  1836         Object y = identity.invokeExact(x);
  1690         assertEquals(x, y);
  1837         assertEquals(x, y);
  1691         try {
  1838         try {
  1692             Object z = surprise.invoke(x);
  1839             Object z = surprise.invokeExact(x);
  1693             System.out.println("Failed to throw; got z="+z);
  1840             System.out.println("Failed to throw; got z="+z);
  1694             assertTrue(false);
  1841             assertTrue(false);
  1695         } catch (Exception ex) {
  1842         } catch (Exception ex) {
  1696             if (verbosity > 1)
  1843             if (verbosity > 2)
  1697                 System.out.println("caught "+ex);
  1844                 System.out.println("caught "+ex);
  1698             if (verbosity > 2)
  1845             if (verbosity > 3)
  1699                 ex.printStackTrace();
  1846                 ex.printStackTrace();
  1700             assertTrue(ex instanceof ClassCastException
  1847             assertTrue(ex instanceof ClassCastException
  1701                     // FIXME: accept only one of the two for any given unit test
  1848                     // FIXME: accept only one of the two for any given unit test
  1702                     || ex instanceof WrongMethodTypeException
  1849                     || ex instanceof WrongMethodTypeException
  1703                     );
  1850                     );
  1764      */
  1911      */
  1765     public static MethodHandle varargsArray(int nargs) {
  1912     public static MethodHandle varargsArray(int nargs) {
  1766         if (nargs < ARRAYS.length)
  1913         if (nargs < ARRAYS.length)
  1767             return ARRAYS[nargs];
  1914             return ARRAYS[nargs];
  1768         // else need to spin bytecode or do something else fancy
  1915         // else need to spin bytecode or do something else fancy
  1769         throw new UnsupportedOperationException("NYI");
  1916         throw new UnsupportedOperationException("NYI: cannot form a varargs array of length "+nargs);
  1770     }
  1917     }
  1771 
  1918 
  1772     private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY);
  1919     private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY);
  1773     private static List<Object> makeList(Object... args) { return Arrays.asList(args); }
  1920     private static List<Object> makeList(Object... args) { return Arrays.asList(args); }
  1774     private static List<Object> list() { return NO_ARGS_LIST; }
  1921     private static List<Object> list() { return NO_ARGS_LIST; }