< prev index next >

test/java/lang/invoke/MethodHandlesTest.java

Print this page
rev 13059 : 8130227: Extend MethodHandle APIs


  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /* @test
  25  * @summary unit tests for java.lang.invoke.MethodHandles
  26  * @library /lib/testlibrary /lib/testlibrary/jsr292
  27  * @compile MethodHandlesTest.java remote/RemoteExample.java
  28  * @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies -esa test.java.lang.invoke.MethodHandlesTest
  29  */
  30 
  31 package test.java.lang.invoke;
  32 
  33 import test.java.lang.invoke.remote.RemoteExample;
  34 import java.lang.invoke.*;

  35 import java.lang.invoke.MethodHandles.Lookup;
  36 import java.lang.reflect.*;
  37 import java.util.*;
  38 import org.junit.*;
  39 import static org.junit.Assert.*;
  40 import com.oracle.testlibrary.jsr292.CodeCacheOverflowProcessor;
  41 
  42 
  43 /**
  44  *
  45  * @author jrose
  46  */
  47 public class MethodHandlesTest {
  48     static final Class<?> THIS_CLASS = MethodHandlesTest.class;
  49     // How much output?
  50     static int verbosity = 0;
  51     static {
  52         String vstr = System.getProperty(THIS_CLASS.getSimpleName()+".verbosity");
  53         if (vstr == null)
  54             vstr = System.getProperty(THIS_CLASS.getName()+".verbosity");


 431         public Example(int x, int    y, int z, int a) { this.name = x+""+y+""+z+""+a; called("Example.<init>", x, y, z, a); }
 432 
 433         static final Lookup EXAMPLE = MethodHandles.lookup();  // for testing findSpecial
 434     }
 435     static final Lookup EXAMPLE = Example.EXAMPLE;
 436     public static class PubExample extends Example {
 437         public PubExample() { this("PubExample"); }
 438         protected PubExample(String prefix) { super(prefix+"#"+nextArg()); }
 439         protected void         pro_v0() { called("Pub/pro_v0", this); }
 440         protected static void  pro_s0() { called("Pub/pro_s0"); }
 441     }
 442     static class SubExample extends Example {
 443         @Override public void  v0()     { called("Sub/v0", this); }
 444         @Override void         pkg_v0() { called("Sub/pkg_v0", this); }
 445         @SuppressWarnings("LeakingThisInConstructor")
 446         private      SubExample(int x)  { called("<init>", this, x); }
 447         public SubExample() { super("SubExample#"+nextArg()); }
 448     }
 449     public static interface IntExample {
 450         public void            v0();

 451         public static class Impl implements IntExample {
 452             public void        v0()     { called("Int/v0", this); }
 453             final String name;
 454             public Impl() { name = "Impl#"+nextArg(); }
 455             @Override public String toString() { return name; }
 456         }
 457     }
 458     static interface SubIntExample extends IntExample { }
 459 
 460     static final Object[][][] ACCESS_CASES = {
 461         { { false, PUBLIC }, { false, SUBCLASS }, { false, PACKAGE }, { false, PRIVATE }, { false, EXAMPLE } }, //[0]: all false
 462         { { false, PUBLIC }, { false, SUBCLASS }, { false, PACKAGE }, { true,  PRIVATE }, { true,  EXAMPLE } }, //[1]: only PRIVATE
 463         { { false, PUBLIC }, { false, SUBCLASS }, { true,  PACKAGE }, { true,  PRIVATE }, { true,  EXAMPLE } }, //[2]: PUBLIC false
 464         { { false, PUBLIC }, { true,  SUBCLASS }, { true,  PACKAGE }, { true,  PRIVATE }, { true,  EXAMPLE } }, //[3]: subclass OK
 465         { { true,  PUBLIC }, { true,  SUBCLASS }, { true,  PACKAGE }, { true,  PRIVATE }, { true,  EXAMPLE } }, //[4]: all true
 466     };
 467 
 468     static Object[][] accessCases(Class<?> defc, String name, boolean isSpecial) {
 469         Object[][] cases;
 470         if (name.contains("pri_") || isSpecial) {


 702             Object orig = argsWithSelf[0];
 703             assertEquals(orig.getClass(), res.getClass());
 704             if (res instanceof Object[])
 705                 assertArrayEquals((Object[])res, (Object[])argsWithSelf[0]);
 706             assert(Arrays.deepEquals(new Object[]{res}, new Object[]{argsWithSelf[0]}));
 707         } else {
 708             assert(false) : Arrays.asList(positive, lookup, rcvc, defc, ret, name, deepToString(params));
 709         }
 710         if (verbosity >= 1)
 711             System.out.print(':');
 712     }
 713 
 714     @Test
 715     public void testFindSpecial() throws Throwable {
 716         CodeCacheOverflowProcessor.runMHTest(this::testFindSpecial0);
 717     }
 718 
 719     public void testFindSpecial0() throws Throwable {
 720         if (CAN_SKIP_WORKING)  return;
 721         startTest("findSpecial");
 722         testFindSpecial(SubExample.class, Example.class, void.class, "v0");
 723         testFindSpecial(SubExample.class, Example.class, void.class, "pkg_v0");
 724         testFindSpecial(RemoteExample.class, PubExample.class, void.class, "Pub/pro_v0");

 725         // Do some negative testing:
 726         for (Lookup lookup : new Lookup[]{ PRIVATE, EXAMPLE, PACKAGE, PUBLIC }) {
 727             testFindSpecial(false, lookup, Object.class, Example.class, void.class, "v0");
 728             testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "bogus");
 729             testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "<init>", int.class);
 730             testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "<init>", Void.class);
 731             testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "s0");

 732         }
 733     }
 734 
 735     void testFindSpecial(Class<?> specialCaller,
 736                          Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
 737         if (specialCaller == RemoteExample.class) {
 738             testFindSpecial(false, EXAMPLE,  specialCaller, defc, ret, name, params);
 739             testFindSpecial(false, PRIVATE,  specialCaller, defc, ret, name, params);
 740             testFindSpecial(false, PACKAGE,  specialCaller, defc, ret, name, params);
 741             testFindSpecial(true,  SUBCLASS, specialCaller, defc, ret, name, params);
 742             testFindSpecial(false, PUBLIC,   specialCaller, defc, ret, name, params);
 743             return;
 744         }
 745         testFindSpecial(true,  EXAMPLE,  specialCaller, defc, ret, name, params);
 746         testFindSpecial(true,  PRIVATE,  specialCaller, defc, ret, name, params);
 747         testFindSpecial(false, PACKAGE,  specialCaller, defc, ret, name, params);
 748         testFindSpecial(false, SUBCLASS, specialCaller, defc, ret, name, params);
 749         testFindSpecial(false, PUBLIC,   specialCaller, defc, ret, name, params);
 750     }
 751     void testFindSpecial(boolean positive, Lookup lookup, Class<?> specialCaller,
 752                          Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
 753         countTest(positive);
 754         String methodName = name.substring(1 + name.indexOf('/'));  // foo/bar => foo
 755         MethodType type = MethodType.methodType(ret, params);
 756         Lookup specialLookup = maybeMoveIn(lookup, specialCaller);
 757         boolean specialAccessOK = (specialLookup.lookupClass() == specialCaller &&
 758                                    (specialLookup.lookupModes() & Lookup.PRIVATE) != 0);
 759         MethodHandle target = null;
 760         Exception noAccess = null;
 761         try {
 762             if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
 763             if (verbosity >= 5)  System.out.println("  lookup => "+specialLookup);
 764             target = specialLookup.findSpecial(defc, methodName, type, specialCaller);
 765         } catch (ReflectiveOperationException ex) {
 766             noAccess = ex;
 767             assertExceptionClass(


1817         MethodType inType  = MethodType.methodType(Object.class, types);
1818         MethodType outType = MethodType.methodType(Object.class, permTypes);
1819         MethodHandle target = varargsList(outargs).asType(outType);
1820         MethodHandle newTarget = MethodHandles.permuteArguments(target, inType, reorder);
1821         if (verbosity >= 5)  System.out.println("newTarget = "+newTarget);
1822         Object result = newTarget.invokeWithArguments(args);
1823         Object expected = Arrays.asList(permArgs);
1824         if (!expected.equals(result)) {
1825             System.out.println("*** failed permuteArguments "+Arrays.toString(reorder)+" types="+Arrays.asList(types));
1826             System.out.println("in args:   "+Arrays.asList(args));
1827             System.out.println("out args:  "+expected);
1828             System.out.println("bad args:  "+result);
1829         }
1830         assertEquals(expected, result);
1831     }
1832 
1833 
1834     @Test // SLOW
1835     public void testSpreadArguments() throws Throwable {
1836         CodeCacheOverflowProcessor.runMHTest(this::testSpreadArguments0);

1837     }
1838 
1839     public void testSpreadArguments0() throws Throwable {
1840         if (CAN_SKIP_WORKING)  return;
1841         startTest("spreadArguments");
1842         for (Class<?> argType : new Class<?>[]{Object.class, Integer.class, int.class}) {
1843             if (verbosity >= 3)
1844                 System.out.println("spreadArguments "+argType);

1845             for (int nargs = 0; nargs < 50; nargs++) {
1846                 if (CAN_TEST_LIGHTLY && nargs > 11)  break;
1847                 for (int pos = 0; pos <= nargs; pos++) {
1848                     if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2)  continue;
1849                     if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3)
1850                         continue;
1851                     testSpreadArguments(argType, pos, nargs);
1852                 }
1853             }
1854         }
1855     }
1856     public void testSpreadArguments(Class<?> argType, int pos, int nargs) throws Throwable {
1857         countTest();
1858         Class<?> arrayType = java.lang.reflect.Array.newInstance(argType, 0).getClass();
1859         MethodHandle target2 = varargsArray(arrayType, nargs);
1860         MethodHandle target = target2.asType(target2.type().generic());
1861         if (verbosity >= 3)
1862             System.out.println("spread into "+target2+" ["+pos+".."+nargs+"]");
1863         Object[] args = randomArgs(target2.type().parameterArray());
1864         // make sure the target does what we think it does:







































































1865         if (pos == 0 && nargs < 5 && !argType.isPrimitive()) {
1866             Object[] check = (Object[]) target.invokeWithArguments(args);
1867             assertArrayEquals(args, check);
1868             switch (nargs) {
1869                 case 0:
1870                     check = (Object[]) (Object) target.invokeExact();
1871                     assertArrayEquals(args, check);
1872                     break;
1873                 case 1:
1874                     check = (Object[]) (Object) target.invokeExact(args[0]);
1875                     assertArrayEquals(args, check);
1876                     break;
1877                 case 2:
1878                     check = (Object[]) (Object) target.invokeExact(args[0], args[1]);
1879                     assertArrayEquals(args, check);
1880                     break;
1881             }
1882         }
1883         List<Class<?>> newParams = new ArrayList<>(target2.type().parameterList());
1884         {   // modify newParams in place
1885             List<Class<?>> spreadParams = newParams.subList(pos, nargs);
1886             spreadParams.clear(); spreadParams.add(arrayType);
1887         }
1888         MethodType newType = MethodType.methodType(arrayType, newParams);
1889         MethodHandle result = target2.asSpreader(arrayType, nargs-pos);
1890         assert(result.type() == newType) : Arrays.asList(result, newType);
1891         result = result.asType(newType.generic());
1892         Object returnValue;
1893         if (pos == 0) {
1894             Object args2 = ValueConversions.changeArrayType(arrayType, Arrays.copyOfRange(args, pos, args.length));
1895             returnValue = result.invokeExact(args2);
1896         } else {
1897             Object[] args1 = Arrays.copyOfRange(args, 0, pos+1);
1898             args1[pos] = ValueConversions.changeArrayType(arrayType, Arrays.copyOfRange(args, pos, args.length));
1899             returnValue = result.invokeWithArguments(args1);
1900         }

1901         String argstr = Arrays.toString(args);
1902         if (!argType.isPrimitive()) {
1903             Object[] rv = (Object[]) returnValue;
1904             String rvs = Arrays.toString(rv);
1905             if (!Arrays.equals(args, rv)) {
1906                 System.out.println("method:   "+result);
1907                 System.out.println("expected: "+argstr);
1908                 System.out.println("returned: "+rvs);
1909                 assertArrayEquals(args, rv);
1910             }
1911         } else if (argType == int.class) {
1912             String rvs = Arrays.toString((int[]) returnValue);
1913             if (!argstr.equals(rvs)) {
1914                 System.out.println("method:   "+result);
1915                 System.out.println("expected: "+argstr);
1916                 System.out.println("returned: "+rvs);
1917                 assertEquals(argstr, rvs);
1918             }
1919         } else if (argType == long.class) {
1920             String rvs = Arrays.toString((long[]) returnValue);
1921             if (!argstr.equals(rvs)) {
1922                 System.out.println("method:   "+result);
1923                 System.out.println("expected: "+argstr);
1924                 System.out.println("returned: "+rvs);
1925                 assertEquals(argstr, rvs);
1926             }
1927         } else {
1928             // cannot test...
1929         }
1930     }
1931 
1932     @Test // SLOW
1933     public void testAsCollector() throws Throwable {
1934         CodeCacheOverflowProcessor.runMHTest(this::testAsCollector0);

1935     }
1936 
1937     public void testAsCollector0() throws Throwable {
1938         if (CAN_SKIP_WORKING)  return;
1939         startTest("asCollector");
1940         for (Class<?> argType : new Class<?>[]{Object.class, Integer.class, int.class}) {
1941             if (verbosity >= 3)
1942                 System.out.println("asCollector "+argType);
1943             for (int nargs = 0; nargs < 50; nargs++) {
1944                 if (CAN_TEST_LIGHTLY && nargs > 11)  break;
1945                 for (int pos = 0; pos <= nargs; pos++) {
1946                     if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2)  continue;
1947                     if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3)
1948                         continue;
1949                     testAsCollector(argType, pos, nargs);
1950                 }
1951             }
1952         }
1953     }
1954     public void testAsCollector(Class<?> argType, int pos, int nargs) throws Throwable {


1957         MethodHandle fake = varargsArray(nargs);
1958         fake = changeArgTypes(fake, argType);
1959         MethodType newType = fake.type();
1960         Object[] args = randomArgs(newType.parameterArray());
1961         // here is what should happen:
1962         Object[] collectedArgs = Arrays.copyOfRange(args, 0, pos+1);
1963         collectedArgs[pos] = Arrays.copyOfRange(args, pos, args.length);
1964         // here is the MH which will witness the collected argument tail:
1965         MethodHandle target = varargsArray(pos+1);
1966         target = changeArgTypes(target, 0, pos, argType);
1967         target = changeArgTypes(target, pos, pos+1, Object[].class);
1968         if (verbosity >= 3)
1969             System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]");
1970         MethodHandle result = target.asCollector(Object[].class, nargs-pos).asType(newType);
1971         Object[] returnValue = (Object[]) result.invokeWithArguments(args);
1972 //        assertTrue(returnValue.length == pos+1 && returnValue[pos] instanceof Object[]);
1973 //        returnValue[pos] = Arrays.asList((Object[]) returnValue[pos]);
1974 //        collectedArgs[pos] = Arrays.asList((Object[]) collectedArgs[pos]);
1975         assertArrayEquals(collectedArgs, returnValue);
1976     }













































1977 
1978     @Test // SLOW
1979     public void testInsertArguments() throws Throwable {
1980         CodeCacheOverflowProcessor.runMHTest(this::testInsertArguments0);
1981     }
1982 
1983     public void testInsertArguments0() throws Throwable {
1984         if (CAN_SKIP_WORKING)  return;
1985         startTest("insertArguments");
1986         for (int nargs = 0; nargs < 50; nargs++) {
1987             if (CAN_TEST_LIGHTLY && nargs > 11)  break;
1988             for (int ins = 0; ins <= nargs; ins++) {
1989                 if (nargs > 10 && ins > 4 && ins < nargs-4 && ins % 10 != 3)
1990                     continue;
1991                 for (int pos = 0; pos <= nargs; pos++) {
1992                     if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3)
1993                         continue;
1994                     if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2)  continue;
1995                     testInsertArguments(nargs, pos, ins);
1996                 }


2100         // Simulate expected effect of filter on arglist:
2101         Object[] filteredArgs = argsToPass.clone();
2102         filteredArgs[pos] = filter.invokeExact(filteredArgs[pos]);
2103         List<Object> expected = Arrays.asList(filteredArgs);
2104         Object result = target2.invokeWithArguments(argsToPass);
2105         if (verbosity >= 3)
2106             System.out.println("result: "+result);
2107         if (!expected.equals(result))
2108             System.out.println("*** fail at n/p = "+nargs+"/"+pos+": "+Arrays.asList(argsToPass)+" => "+result+" != "+expected);
2109         assertEquals(expected, result);
2110     }
2111 
2112     @Test
2113     public void testCollectArguments() throws Throwable {
2114         CodeCacheOverflowProcessor.runMHTest(this::testCollectArguments0);
2115     }
2116 
2117     public void testCollectArguments0() throws Throwable {
2118         if (CAN_SKIP_WORKING)  return;
2119         startTest("collectArguments");
2120         testFoldOrCollectArguments(true);
2121     }
2122 
2123     @Test
2124     public void testFoldArguments() throws Throwable {
2125         CodeCacheOverflowProcessor.runMHTest(this::testFoldArguments0);

2126     }
2127 
2128     public void testFoldArguments0() throws Throwable {
2129         if (CAN_SKIP_WORKING)  return;
2130         startTest("foldArguments");
2131         testFoldOrCollectArguments(false);
2132     }
2133 
2134     void testFoldOrCollectArguments(boolean isCollect) throws Throwable {







2135         for (Class<?> lastType : new Class<?>[]{ Object.class, String.class, int.class }) {
2136             for (Class<?> collectType : new Class<?>[]{ Object.class, String.class, int.class, void.class }) {
2137                 int maxArity = 10;
2138                 if (collectType != String.class)  maxArity = 5;
2139                 if (lastType != Object.class)  maxArity = 4;
2140                 for (int nargs = 0; nargs <= maxArity; nargs++) {
2141                     ArrayList<Class<?>> argTypes = new ArrayList<>(Collections.nCopies(nargs, Object.class));
2142                     int maxMix = 20;
2143                     if (collectType != Object.class)  maxMix = 0;
2144                     Map<Object,Integer> argTypesSeen = new HashMap<>();
2145                     for (int mix = 0; mix <= maxMix; mix++) {
2146                         if (!mixArgs(argTypes, mix, argTypesSeen))  continue;
2147                         for (int collect = 0; collect <= nargs; collect++) {
2148                             for (int pos = 0; pos <= nargs - collect; pos++) {
2149                                 testFoldOrCollectArguments(argTypes, pos, collect, collectType, lastType, isCollect);
2150                             }
2151                         }
2152                     }
2153                 }
2154             }
2155         }
2156     }
2157 
2158     boolean mixArgs(List<Class<?>> argTypes, int mix, Map<Object,Integer> argTypesSeen) {
2159         assert(mix >= 0);
2160         if (mix == 0)  return true;  // no change
2161         if ((mix >>> argTypes.size()) != 0)  return false;
2162         for (int i = 0; i < argTypes.size(); i++) {
2163             if (i >= 31)  break;
2164             boolean bit = (mix & (1 << i)) != 0;
2165             if (bit) {
2166                 Class<?> type = argTypes.get(i);
2167                 if (type == Object.class)
2168                     type = String.class;
2169                 else if (type == String.class)
2170                     type = int.class;
2171                 else
2172                     type = Object.class;
2173                 argTypes.set(i, type);
2174             }
2175         }
2176         Integer prev = argTypesSeen.put(new ArrayList<>(argTypes), mix);
2177         if (prev != null) {
2178             if (verbosity >= 4)  System.out.println("mix "+prev+" repeated "+mix+": "+argTypes);
2179             return false;
2180         }
2181         if (verbosity >= 3)  System.out.println("mix "+mix+" = "+argTypes);
2182         return true;
2183     }
2184 
2185     void testFoldOrCollectArguments(List<Class<?>> argTypes,  // argument types minus the inserted combineType
2186                                     int pos, int fold, // position and length of the folded arguments
2187                                     Class<?> combineType, // type returned from the combiner
2188                                     Class<?> lastType,  // type returned from the target
2189                                     boolean isCollect) throws Throwable {

2190         int nargs = argTypes.size();
2191         if (pos != 0 && !isCollect)  return;  // can fold only at pos=0 for now
2192         countTest();
2193         List<Class<?>> combineArgTypes = argTypes.subList(pos, pos + fold);
2194         List<Class<?>> targetArgTypes = new ArrayList<>(argTypes);
2195         if (isCollect)  // does targret see arg[pos..pos+cc-1]?
2196             targetArgTypes.subList(pos, pos + fold).clear();
2197         if (combineType != void.class)
2198             targetArgTypes.add(pos, combineType);
2199         MethodHandle target = varargsList(targetArgTypes, lastType);
2200         MethodHandle combine = varargsList(combineArgTypes, combineType);
2201         List<Object> argsToPass = Arrays.asList(randomArgs(argTypes));
2202         if (verbosity >= 3)
2203             System.out.println((isCollect ? "collect" : "fold")+" "+target+" with "+combine);
2204         MethodHandle target2;
2205         if (isCollect)
2206             target2 = MethodHandles.collectArguments(target, pos, combine);
2207         else
2208             target2 = MethodHandles.foldArguments(target, combine);
2209         // Simulate expected effect of combiner on arglist:
2210         List<Object> expectedList = new ArrayList<>(argsToPass);
2211         List<Object> argsToFold = expectedList.subList(pos, pos + fold);
2212         if (verbosity >= 3)
2213             System.out.println((isCollect ? "collect" : "fold")+": "+argsToFold+" into "+target2);
2214         Object foldedArgs = combine.invokeWithArguments(argsToFold);
2215         if (isCollect)
2216             argsToFold.clear();
2217         if (combineType != void.class)
2218             argsToFold.add(0, foldedArgs);
2219         Object result = target2.invokeWithArguments(argsToPass);
2220         if (verbosity >= 3)
2221             System.out.println("result: "+result);
2222         Object expected = target.invokeWithArguments(expectedList);
2223         if (!expected.equals(result))
2224             System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result+" != "+expected);
2225         assertEquals(expected, result);
2226     }
2227 
2228     @Test


2524                 int pc = test1.type().parameterCount();
2525                 test1 = MethodHandles.insertArguments(test, testArgs, Arrays.copyOfRange(argList1, testArgs, pc));
2526             }
2527             MethodHandle mh = MethodHandles.guardWithTest(test1, target, fallback);
2528             assertEquals(target.type(), mh.type());
2529             boolean equals;
2530             switch (nargs) {
2531             case 0:   equals = true; break;
2532             case 1:   equals = MISSING_ARG.equals(argList[0]); break;
2533             default:  equals = argList[0].equals(argList[1]); break;
2534             }
2535             String willCall = (equals ? "targetIfEquals" : "fallbackIfNotEquals");
2536             if (verbosity >= 3)
2537                 System.out.println(logEntry(willCall, argList));
2538             Object result = mh.invokeWithArguments(argList1);
2539             assertCalled(willCall, argList);
2540         }
2541     }
2542 
2543     @Test





































































































































































































2544     public void testThrowException() throws Throwable {
2545         CodeCacheOverflowProcessor.runMHTest(this::testThrowException0);
2546     }
2547 
2548     public void testThrowException0() throws Throwable {
2549         if (CAN_SKIP_WORKING)  return;
2550         startTest("throwException");
2551         testThrowException(int.class, new ClassCastException("testing"));
2552         testThrowException(void.class, new java.io.IOException("testing"));
2553         testThrowException(String.class, new LinkageError("testing"));
2554     }
2555 
2556     void testThrowException(Class<?> returnType, Throwable thrown) throws Throwable {
2557         countTest();
2558         Class<? extends Throwable> exType = thrown.getClass();
2559         MethodHandle target = MethodHandles.throwException(returnType, exType);
2560         //System.out.println("throwing with "+target+" : "+thrown);
2561         MethodType expectedType = MethodType.methodType(returnType, exType);
2562         assertEquals(expectedType, target.type());
2563         target = target.asType(target.type().generic());
2564         Throwable caught = null;
2565         try {
2566             Object res = target.invokeExact((Object) thrown);
2567             fail("got "+res+" instead of throwing "+thrown);
2568         } catch (Throwable ex) {
2569             if (ex != thrown) {
2570                 if (ex instanceof Error)  throw (Error)ex;
2571                 if (ex instanceof RuntimeException)  throw (RuntimeException)ex;
2572             }
2573             caught = ex;
2574         }
2575         assertSame(thrown, caught);
2576     }
2577 
2578     @Test































































































2579     public void testInterfaceCast() throws Throwable {
2580         CodeCacheOverflowProcessor.runMHTest(this::testInterfaceCast0);
2581     }
2582 
2583     public void testInterfaceCast0() throws Throwable {
2584         //if (CAN_SKIP_WORKING)  return;
2585         startTest("interfaceCast");
2586         assert( (((Object)"foo") instanceof CharSequence));
2587         assert(!(((Object)"foo") instanceof Iterable));
2588         for (MethodHandle mh : new MethodHandle[]{
2589             MethodHandles.identity(String.class),
2590             MethodHandles.identity(CharSequence.class),
2591             MethodHandles.identity(Iterable.class)
2592         }) {
2593             if (verbosity > 0)  System.out.println("-- mh = "+mh);
2594             for (Class<?> ctype : new Class<?>[]{
2595                 Object.class, String.class, CharSequence.class,
2596                 Number.class, Iterable.class
2597             }) {
2598                 if (verbosity > 0)  System.out.println("---- ctype = "+ctype.getName());
2599                 //                           doret  docast
2600                 testInterfaceCast(mh, ctype, false, false);
2601                 testInterfaceCast(mh, ctype, true,  false);
2602                 testInterfaceCast(mh, ctype, false, true);
2603                 testInterfaceCast(mh, ctype, true,  true);
2604             }




  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /* @test
  25  * @summary unit tests for java.lang.invoke.MethodHandles
  26  * @library /lib/testlibrary /lib/testlibrary/jsr292
  27  * @compile MethodHandlesTest.java remote/RemoteExample.java
  28  * @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies -esa test.java.lang.invoke.MethodHandlesTest
  29  */
  30 
  31 package test.java.lang.invoke;
  32 
  33 import test.java.lang.invoke.remote.RemoteExample;
  34 import java.lang.invoke.*;
  35 import static java.lang.invoke.MethodType.methodType;
  36 import java.lang.invoke.MethodHandles.Lookup;
  37 import java.lang.reflect.*;
  38 import java.util.*;
  39 import org.junit.*;
  40 import static org.junit.Assert.*;
  41 import com.oracle.testlibrary.jsr292.CodeCacheOverflowProcessor;
  42 
  43 
  44 /**
  45  *
  46  * @author jrose
  47  */
  48 public class MethodHandlesTest {
  49     static final Class<?> THIS_CLASS = MethodHandlesTest.class;
  50     // How much output?
  51     static int verbosity = 0;
  52     static {
  53         String vstr = System.getProperty(THIS_CLASS.getSimpleName()+".verbosity");
  54         if (vstr == null)
  55             vstr = System.getProperty(THIS_CLASS.getName()+".verbosity");


 432         public Example(int x, int    y, int z, int a) { this.name = x+""+y+""+z+""+a; called("Example.<init>", x, y, z, a); }
 433 
 434         static final Lookup EXAMPLE = MethodHandles.lookup();  // for testing findSpecial
 435     }
 436     static final Lookup EXAMPLE = Example.EXAMPLE;
 437     public static class PubExample extends Example {
 438         public PubExample() { this("PubExample"); }
 439         protected PubExample(String prefix) { super(prefix+"#"+nextArg()); }
 440         protected void         pro_v0() { called("Pub/pro_v0", this); }
 441         protected static void  pro_s0() { called("Pub/pro_s0"); }
 442     }
 443     static class SubExample extends Example {
 444         @Override public void  v0()     { called("Sub/v0", this); }
 445         @Override void         pkg_v0() { called("Sub/pkg_v0", this); }
 446         @SuppressWarnings("LeakingThisInConstructor")
 447         private      SubExample(int x)  { called("<init>", this, x); }
 448         public SubExample() { super("SubExample#"+nextArg()); }
 449     }
 450     public static interface IntExample {
 451         public void            v0();
 452         public default void    vd() { called("vd", this); }
 453         public static class Impl implements IntExample {
 454             public void        v0()     { called("Int/v0", this); }
 455             final String name;
 456             public Impl() { name = "Impl#"+nextArg(); }
 457             @Override public String toString() { return name; }
 458         }
 459     }
 460     static interface SubIntExample extends IntExample { }
 461 
 462     static final Object[][][] ACCESS_CASES = {
 463         { { false, PUBLIC }, { false, SUBCLASS }, { false, PACKAGE }, { false, PRIVATE }, { false, EXAMPLE } }, //[0]: all false
 464         { { false, PUBLIC }, { false, SUBCLASS }, { false, PACKAGE }, { true,  PRIVATE }, { true,  EXAMPLE } }, //[1]: only PRIVATE
 465         { { false, PUBLIC }, { false, SUBCLASS }, { true,  PACKAGE }, { true,  PRIVATE }, { true,  EXAMPLE } }, //[2]: PUBLIC false
 466         { { false, PUBLIC }, { true,  SUBCLASS }, { true,  PACKAGE }, { true,  PRIVATE }, { true,  EXAMPLE } }, //[3]: subclass OK
 467         { { true,  PUBLIC }, { true,  SUBCLASS }, { true,  PACKAGE }, { true,  PRIVATE }, { true,  EXAMPLE } }, //[4]: all true
 468     };
 469 
 470     static Object[][] accessCases(Class<?> defc, String name, boolean isSpecial) {
 471         Object[][] cases;
 472         if (name.contains("pri_") || isSpecial) {


 704             Object orig = argsWithSelf[0];
 705             assertEquals(orig.getClass(), res.getClass());
 706             if (res instanceof Object[])
 707                 assertArrayEquals((Object[])res, (Object[])argsWithSelf[0]);
 708             assert(Arrays.deepEquals(new Object[]{res}, new Object[]{argsWithSelf[0]}));
 709         } else {
 710             assert(false) : Arrays.asList(positive, lookup, rcvc, defc, ret, name, deepToString(params));
 711         }
 712         if (verbosity >= 1)
 713             System.out.print(':');
 714     }
 715 
 716     @Test
 717     public void testFindSpecial() throws Throwable {
 718         CodeCacheOverflowProcessor.runMHTest(this::testFindSpecial0);
 719     }
 720 
 721     public void testFindSpecial0() throws Throwable {
 722         if (CAN_SKIP_WORKING)  return;
 723         startTest("findSpecial");
 724         testFindSpecial(SubExample.class, Example.class, void.class, false, "v0");
 725         testFindSpecial(SubExample.class, Example.class, void.class, false, "pkg_v0");
 726         testFindSpecial(RemoteExample.class, PubExample.class, void.class, false, "Pub/pro_v0");
 727         testFindSpecial(Example.class, IntExample.class, void.class, true, "vd");
 728         // Do some negative testing:
 729         for (Lookup lookup : new Lookup[]{ PRIVATE, EXAMPLE, PACKAGE, PUBLIC }) {
 730             testFindSpecial(false, lookup, Object.class, Example.class, void.class, "v0");
 731             testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "bogus");
 732             testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "<init>", int.class);
 733             testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "<init>", Void.class);
 734             testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "s0");
 735             testFindSpecial(false, lookup, Example.class, IntExample.class, void.class, "v0");
 736         }
 737     }
 738 
 739     void testFindSpecial(Class<?> specialCaller,
 740                          Class<?> defc, Class<?> ret, boolean dflt, String name, Class<?>... params) throws Throwable {
 741         if (specialCaller == RemoteExample.class) {
 742             testFindSpecial(false, EXAMPLE,  specialCaller, defc, ret, name, params);
 743             testFindSpecial(false, PRIVATE,  specialCaller, defc, ret, name, params);
 744             testFindSpecial(false, PACKAGE,  specialCaller, defc, ret, name, params);
 745             testFindSpecial(true,  SUBCLASS, specialCaller, defc, ret, name, params);
 746             testFindSpecial(false, PUBLIC,   specialCaller, defc, ret, name, params);
 747             return;
 748         }
 749         testFindSpecial(true,          EXAMPLE,  specialCaller, defc, ret, name, params);
 750         testFindSpecial(true,          PRIVATE,  specialCaller, defc, ret, name, params);
 751         testFindSpecial(false || dflt, PACKAGE,  specialCaller, defc, ret, name, params);
 752         testFindSpecial(false,         SUBCLASS, specialCaller, defc, ret, name, params);
 753         testFindSpecial(false,         PUBLIC,   specialCaller, defc, ret, name, params);
 754     }
 755     void testFindSpecial(boolean positive, Lookup lookup, Class<?> specialCaller,
 756                          Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
 757         countTest(positive);
 758         String methodName = name.substring(1 + name.indexOf('/'));  // foo/bar => foo
 759         MethodType type = MethodType.methodType(ret, params);
 760         Lookup specialLookup = maybeMoveIn(lookup, specialCaller);
 761         boolean specialAccessOK = (specialLookup.lookupClass() == specialCaller &&
 762                                    (specialLookup.lookupModes() & Lookup.PRIVATE) != 0);
 763         MethodHandle target = null;
 764         Exception noAccess = null;
 765         try {
 766             if (verbosity >= 4)  System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
 767             if (verbosity >= 5)  System.out.println("  lookup => "+specialLookup);
 768             target = specialLookup.findSpecial(defc, methodName, type, specialCaller);
 769         } catch (ReflectiveOperationException ex) {
 770             noAccess = ex;
 771             assertExceptionClass(


1821         MethodType inType  = MethodType.methodType(Object.class, types);
1822         MethodType outType = MethodType.methodType(Object.class, permTypes);
1823         MethodHandle target = varargsList(outargs).asType(outType);
1824         MethodHandle newTarget = MethodHandles.permuteArguments(target, inType, reorder);
1825         if (verbosity >= 5)  System.out.println("newTarget = "+newTarget);
1826         Object result = newTarget.invokeWithArguments(args);
1827         Object expected = Arrays.asList(permArgs);
1828         if (!expected.equals(result)) {
1829             System.out.println("*** failed permuteArguments "+Arrays.toString(reorder)+" types="+Arrays.asList(types));
1830             System.out.println("in args:   "+Arrays.asList(args));
1831             System.out.println("out args:  "+expected);
1832             System.out.println("bad args:  "+result);
1833         }
1834         assertEquals(expected, result);
1835     }
1836 
1837 
1838     @Test // SLOW
1839     public void testSpreadArguments() throws Throwable {
1840         CodeCacheOverflowProcessor.runMHTest(this::testSpreadArguments0);
1841         CodeCacheOverflowProcessor.runMHTest(this::testSpreadArguments1);
1842     }
1843 
1844     public void testSpreadArguments0() throws Throwable {
1845         if (CAN_SKIP_WORKING)  return;
1846         startTest("spreadArguments");
1847         for (Class<?> argType : new Class<?>[]{Object.class, Integer.class, int.class}) {
1848             if (verbosity >= 3)
1849                 System.out.println("spreadArguments "+argType);
1850             Class<?> arrayType = java.lang.reflect.Array.newInstance(argType, 0).getClass();
1851             for (int nargs = 0; nargs < 50; nargs++) {
1852                 if (CAN_TEST_LIGHTLY && nargs > 11)  break;
1853                 for (int pos = 0; pos <= nargs; pos++) {
1854                     if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2)  continue;
1855                     if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3)
1856                         continue;
1857                     testSpreadArguments(argType, arrayType, pos, nargs);
1858                 }
1859             }
1860         }
1861     }
1862     public void testSpreadArguments(Class<?> argType, Class<?> arrayType, int pos, int nargs) throws Throwable {
1863         countTest();

1864         MethodHandle target2 = varargsArray(arrayType, nargs);
1865         MethodHandle target = target2.asType(target2.type().generic());
1866         if (verbosity >= 3)
1867             System.out.println("spread into "+target2+" ["+pos+".."+nargs+"]");
1868         Object[] args = randomArgs(target2.type().parameterArray());
1869         // make sure the target does what we think it does:
1870         checkTarget(argType, pos, nargs, target, args);
1871         List<Class<?>> newParams = new ArrayList<>(target2.type().parameterList());
1872         {   // modify newParams in place
1873             List<Class<?>> spreadParams = newParams.subList(pos, nargs);
1874             spreadParams.clear(); spreadParams.add(arrayType);
1875         }
1876         MethodType newType = MethodType.methodType(arrayType, newParams);
1877         MethodHandle result = target2.asSpreader(arrayType, nargs-pos);
1878         assert(result.type() == newType) : Arrays.asList(result, newType);
1879         result = result.asType(newType.generic());
1880         Object returnValue;
1881         if (pos == 0) {
1882             Object args2 = ValueConversions.changeArrayType(arrayType, Arrays.copyOfRange(args, pos, args.length));
1883             returnValue = result.invokeExact(args2);
1884         } else {
1885             Object[] args1 = Arrays.copyOfRange(args, 0, pos+1);
1886             args1[pos] = ValueConversions.changeArrayType(arrayType, Arrays.copyOfRange(args, pos, args.length));
1887             returnValue = result.invokeWithArguments(args1);
1888         }
1889         checkReturnValue(argType, args, result, returnValue);
1890     }
1891     public void testSpreadArguments1() throws Throwable {
1892         if (CAN_SKIP_WORKING)  return;
1893         startTest("spreadArguments/pos");
1894         for (Class<?> argType : new Class<?>[]{Object.class, Integer.class, int.class}) {
1895             if (verbosity >= 3)
1896                 System.out.println("spreadArguments "+argType);
1897             Class<?> arrayType = java.lang.reflect.Array.newInstance(argType, 0).getClass();
1898             for (int nargs = 0; nargs < 50; nargs++) {
1899                 if (CAN_TEST_LIGHTLY && nargs > 11)  break;
1900                 for (int pos = 0; pos <= nargs; pos++) {
1901                     if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2)  continue;
1902                     if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3)
1903                         continue;
1904                     for (int spr = 1; spr < nargs - pos; ++spr) {
1905                         if (spr > 4 && spr != 7 && spr != 11 && spr != 20 && spr < nargs - pos - 4) continue;
1906                         testSpreadArguments(argType, arrayType, pos, spr, nargs);
1907                     }
1908                 }
1909             }
1910         }
1911     }
1912     public void testSpreadArguments(Class<?> argType, Class<?> arrayType, int pos, int spread, int nargs) throws Throwable {
1913         countTest();
1914         MethodHandle target2 = varargsArray(arrayType, nargs);
1915         MethodHandle target = target2.asType(target2.type().generic());
1916         if (verbosity >= 3)
1917             System.out.println("spread into " + target2 + " [" + pos + ".." + (pos + spread) + "[");
1918         Object[] args = randomArgs(target2.type().parameterArray());
1919         // make sure the target does what we think it does:
1920         checkTarget(argType, pos, nargs, target, args);
1921         List<Class<?>> newParams = new ArrayList<>(target2.type().parameterList());
1922         {   // modify newParams in place
1923             List<Class<?>> spreadParams = newParams.subList(pos, pos + spread);
1924             spreadParams.clear();
1925             spreadParams.add(arrayType);
1926         }
1927         MethodType newType = MethodType.methodType(arrayType, newParams);
1928         MethodHandle result = target2.asSpreader(pos, arrayType, spread);
1929         assert (result.type() == newType) : Arrays.asList(result, newType);
1930         result = result.asType(newType.generic());
1931         // args1 has nargs-spread entries, plus one for the to-be-spread array
1932         int args1Length = nargs - (spread - 1);
1933         Object[] args1 = new Object[args1Length];
1934         System.arraycopy(args, 0, args1, 0, pos);
1935         args1[pos] = ValueConversions.changeArrayType(arrayType, Arrays.copyOfRange(args, pos, pos + spread));
1936         System.arraycopy(args, pos + spread, args1, pos + 1, nargs - spread - pos);
1937         Object returnValue = result.invokeWithArguments(args1);
1938         checkReturnValue(argType, args, result, returnValue);
1939     }
1940     private static void checkTarget(Class<?> argType, int pos, int nargs, MethodHandle target, Object[] args) throws Throwable {
1941         if (pos == 0 && nargs < 5 && !argType.isPrimitive()) {
1942             Object[] check = (Object[]) target.invokeWithArguments(args);
1943             assertArrayEquals(args, check);
1944             switch (nargs) {
1945                 case 0:
1946                     check = (Object[]) (Object) target.invokeExact();
1947                     assertArrayEquals(args, check);
1948                     break;
1949                 case 1:
1950                     check = (Object[]) (Object) target.invokeExact(args[0]);
1951                     assertArrayEquals(args, check);
1952                     break;
1953                 case 2:
1954                     check = (Object[]) (Object) target.invokeExact(args[0], args[1]);
1955                     assertArrayEquals(args, check);
1956                     break;
1957             }
1958         }

















1959     }
1960     private static void checkReturnValue(Class<?> argType, Object[] args, MethodHandle result, Object returnValue) {
1961         String argstr = Arrays.toString(args);
1962         if (!argType.isPrimitive()) {
1963             Object[] rv = (Object[]) returnValue;
1964             String rvs = Arrays.toString(rv);
1965             if (!Arrays.equals(args, rv)) {
1966                 System.out.println("method:   "+result);
1967                 System.out.println("expected: "+argstr);
1968                 System.out.println("returned: "+rvs);
1969                 assertArrayEquals(args, rv);
1970             }
1971         } else if (argType == int.class) {
1972             String rvs = Arrays.toString((int[]) returnValue);
1973             if (!argstr.equals(rvs)) {
1974                 System.out.println("method:   "+result);
1975                 System.out.println("expected: "+argstr);
1976                 System.out.println("returned: "+rvs);
1977                 assertEquals(argstr, rvs);
1978             }
1979         } else if (argType == long.class) {
1980             String rvs = Arrays.toString((long[]) returnValue);
1981             if (!argstr.equals(rvs)) {
1982                 System.out.println("method:   "+result);
1983                 System.out.println("expected: "+argstr);
1984                 System.out.println("returned: "+rvs);
1985                 assertEquals(argstr, rvs);
1986             }
1987         } else {
1988             // cannot test...
1989         }
1990     }
1991 
1992     @Test // SLOW
1993     public void testAsCollector() throws Throwable {
1994         CodeCacheOverflowProcessor.runMHTest(this::testAsCollector0);
1995         CodeCacheOverflowProcessor.runMHTest(this::testAsCollector1);
1996     }
1997 
1998     public void testAsCollector0() throws Throwable {
1999         if (CAN_SKIP_WORKING)  return;
2000         startTest("asCollector");
2001         for (Class<?> argType : new Class<?>[]{Object.class, Integer.class, int.class}) {
2002             if (verbosity >= 3)
2003                 System.out.println("asCollector "+argType);
2004             for (int nargs = 0; nargs < 50; nargs++) {
2005                 if (CAN_TEST_LIGHTLY && nargs > 11)  break;
2006                 for (int pos = 0; pos <= nargs; pos++) {
2007                     if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2)  continue;
2008                     if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3)
2009                         continue;
2010                     testAsCollector(argType, pos, nargs);
2011                 }
2012             }
2013         }
2014     }
2015     public void testAsCollector(Class<?> argType, int pos, int nargs) throws Throwable {


2018         MethodHandle fake = varargsArray(nargs);
2019         fake = changeArgTypes(fake, argType);
2020         MethodType newType = fake.type();
2021         Object[] args = randomArgs(newType.parameterArray());
2022         // here is what should happen:
2023         Object[] collectedArgs = Arrays.copyOfRange(args, 0, pos+1);
2024         collectedArgs[pos] = Arrays.copyOfRange(args, pos, args.length);
2025         // here is the MH which will witness the collected argument tail:
2026         MethodHandle target = varargsArray(pos+1);
2027         target = changeArgTypes(target, 0, pos, argType);
2028         target = changeArgTypes(target, pos, pos+1, Object[].class);
2029         if (verbosity >= 3)
2030             System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]");
2031         MethodHandle result = target.asCollector(Object[].class, nargs-pos).asType(newType);
2032         Object[] returnValue = (Object[]) result.invokeWithArguments(args);
2033 //        assertTrue(returnValue.length == pos+1 && returnValue[pos] instanceof Object[]);
2034 //        returnValue[pos] = Arrays.asList((Object[]) returnValue[pos]);
2035 //        collectedArgs[pos] = Arrays.asList((Object[]) collectedArgs[pos]);
2036         assertArrayEquals(collectedArgs, returnValue);
2037     }
2038     public void testAsCollector1() throws Throwable {
2039         if (CAN_SKIP_WORKING)  return;
2040         startTest("asCollector/pos");
2041         for (Class<?> argType : new Class<?>[]{Object.class, Integer.class, int.class}) {
2042             if (verbosity >= 3)
2043                 System.out.println("asCollector/pos "+argType);
2044             for (int nargs = 0; nargs < 50; nargs++) {
2045                 if (CAN_TEST_LIGHTLY && nargs > 11)  break;
2046                 for (int pos = 0; pos <= nargs; pos++) {
2047                     if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2)  continue;
2048                     if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3)
2049                         continue;
2050                     for (int coll = 1; coll < nargs - pos; ++coll) {
2051                         if (coll > 4 && coll != 7 && coll != 11 && coll != 20 && coll < nargs - pos - 4) continue;
2052                         testAsCollector(argType, pos, coll, nargs);
2053                     }
2054                 }
2055             }
2056         }
2057     }
2058     public void testAsCollector(Class<?> argType, int pos, int collect, int nargs) throws Throwable {
2059         countTest();
2060         // fake up a MH with the same type as the desired adapter:
2061         MethodHandle fake = varargsArray(nargs);
2062         fake = changeArgTypes(fake, argType);
2063         MethodType newType = fake.type();
2064         Object[] args = randomArgs(newType.parameterArray());
2065         // here is what should happen:
2066         // new arg list has "collect" less arguments, but one extra for collected arguments array
2067         int collectedLength = nargs-(collect-1);
2068         Object[] collectedArgs = new Object[collectedLength];
2069         System.arraycopy(args, 0, collectedArgs, 0, pos);
2070         collectedArgs[pos] = Arrays.copyOfRange(args, pos, pos+collect);
2071         System.arraycopy(args, pos+collect, collectedArgs, pos+1, args.length-(pos+collect));
2072         // here is the MH which will witness the collected argument part (not tail!):
2073         MethodHandle target = varargsArray(collectedLength);
2074         target = changeArgTypes(target, 0, pos, argType);
2075         target = changeArgTypes(target, pos, pos+1, Object[].class);
2076         target = changeArgTypes(target, pos+1, collectedLength, argType);
2077         if (verbosity >= 3)
2078             System.out.println("collect "+collect+" from "+Arrays.asList(args)+" ["+pos+".."+(pos+collect)+"[");
2079         MethodHandle result = target.asCollector(pos, Object[].class, collect).asType(newType);
2080         Object[] returnValue = (Object[]) result.invokeWithArguments(args);
2081         assertArrayEquals(collectedArgs, returnValue);
2082     }
2083 
2084     @Test // SLOW
2085     public void testInsertArguments() throws Throwable {
2086         CodeCacheOverflowProcessor.runMHTest(this::testInsertArguments0);
2087     }
2088 
2089     public void testInsertArguments0() throws Throwable {
2090         if (CAN_SKIP_WORKING)  return;
2091         startTest("insertArguments");
2092         for (int nargs = 0; nargs < 50; nargs++) {
2093             if (CAN_TEST_LIGHTLY && nargs > 11)  break;
2094             for (int ins = 0; ins <= nargs; ins++) {
2095                 if (nargs > 10 && ins > 4 && ins < nargs-4 && ins % 10 != 3)
2096                     continue;
2097                 for (int pos = 0; pos <= nargs; pos++) {
2098                     if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3)
2099                         continue;
2100                     if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2)  continue;
2101                     testInsertArguments(nargs, pos, ins);
2102                 }


2206         // Simulate expected effect of filter on arglist:
2207         Object[] filteredArgs = argsToPass.clone();
2208         filteredArgs[pos] = filter.invokeExact(filteredArgs[pos]);
2209         List<Object> expected = Arrays.asList(filteredArgs);
2210         Object result = target2.invokeWithArguments(argsToPass);
2211         if (verbosity >= 3)
2212             System.out.println("result: "+result);
2213         if (!expected.equals(result))
2214             System.out.println("*** fail at n/p = "+nargs+"/"+pos+": "+Arrays.asList(argsToPass)+" => "+result+" != "+expected);
2215         assertEquals(expected, result);
2216     }
2217 
2218     @Test
2219     public void testCollectArguments() throws Throwable {
2220         CodeCacheOverflowProcessor.runMHTest(this::testCollectArguments0);
2221     }
2222 
2223     public void testCollectArguments0() throws Throwable {
2224         if (CAN_SKIP_WORKING)  return;
2225         startTest("collectArguments");
2226         testFoldOrCollectArguments(true, false);
2227     }
2228 
2229     @Test
2230     public void testFoldArguments() throws Throwable {
2231         CodeCacheOverflowProcessor.runMHTest(this::testFoldArguments0);
2232         CodeCacheOverflowProcessor.runMHTest(this::testFoldArguments1);
2233     }
2234 
2235     public void testFoldArguments0() throws Throwable {
2236         if (CAN_SKIP_WORKING)  return;
2237         startTest("foldArguments");
2238         testFoldOrCollectArguments(false, false);
2239     }
2240 
2241     public void testFoldArguments1() throws Throwable {
2242         if (CAN_SKIP_WORKING) return;
2243         startTest("foldArguments/pos");
2244         testFoldOrCollectArguments(false, true);
2245     }
2246 
2247     void testFoldOrCollectArguments(boolean isCollect, boolean withFoldPos) throws Throwable {
2248         assert !(isCollect && withFoldPos); // exclude illegal argument combination
2249         for (Class<?> lastType : new Class<?>[]{ Object.class, String.class, int.class }) {
2250             for (Class<?> collectType : new Class<?>[]{ Object.class, String.class, int.class, void.class }) {
2251                 int maxArity = 10;
2252                 if (collectType != String.class)  maxArity = 5;
2253                 if (lastType != Object.class)  maxArity = 4;
2254                 for (int nargs = 0; nargs <= maxArity; nargs++) {
2255                     ArrayList<Class<?>> argTypes = new ArrayList<>(Collections.nCopies(nargs, Object.class));
2256                     int maxMix = 20;
2257                     if (collectType != Object.class)  maxMix = 0;
2258                     Map<Object,Integer> argTypesSeen = new HashMap<>();
2259                     for (int mix = 0; mix <= maxMix; mix++) {
2260                         if (!mixArgs(argTypes, mix, argTypesSeen))  continue;
2261                         for (int collect = 0; collect <= nargs; collect++) {
2262                             for (int pos = 0; pos <= nargs - collect; pos++) {
2263                                 testFoldOrCollectArguments(argTypes, pos, collect, collectType, lastType, isCollect, withFoldPos);
2264                             }
2265                         }
2266                     }
2267                 }
2268             }
2269         }
2270     }
2271 
2272     boolean mixArgs(List<Class<?>> argTypes, int mix, Map<Object,Integer> argTypesSeen) {
2273         assert(mix >= 0);
2274         if (mix == 0)  return true;  // no change
2275         if ((mix >>> argTypes.size()) != 0)  return false;
2276         for (int i = 0; i < argTypes.size(); i++) {
2277             if (i >= 31)  break;
2278             boolean bit = (mix & (1 << i)) != 0;
2279             if (bit) {
2280                 Class<?> type = argTypes.get(i);
2281                 if (type == Object.class)
2282                     type = String.class;
2283                 else if (type == String.class)
2284                     type = int.class;
2285                 else
2286                     type = Object.class;
2287                 argTypes.set(i, type);
2288             }
2289         }
2290         Integer prev = argTypesSeen.put(new ArrayList<>(argTypes), mix);
2291         if (prev != null) {
2292             if (verbosity >= 4)  System.out.println("mix "+prev+" repeated "+mix+": "+argTypes);
2293             return false;
2294         }
2295         if (verbosity >= 3)  System.out.println("mix "+mix+" = "+argTypes);
2296         return true;
2297     }
2298 
2299     void testFoldOrCollectArguments(List<Class<?>> argTypes,  // argument types minus the inserted combineType
2300                                     int pos, int fold, // position and length of the folded arguments
2301                                     Class<?> combineType, // type returned from the combiner
2302                                     Class<?> lastType,  // type returned from the target
2303                                     boolean isCollect,
2304                                     boolean withFoldPos) throws Throwable {
2305         int nargs = argTypes.size();
2306         if (pos != 0 && !isCollect && !withFoldPos)  return;  // test MethodHandles.foldArguments(MH,MH) only for pos=0
2307         countTest();
2308         List<Class<?>> combineArgTypes = argTypes.subList(pos, pos + fold);
2309         List<Class<?>> targetArgTypes = new ArrayList<>(argTypes);
2310         if (isCollect)  // does target see arg[pos..pos+cc-1]?
2311             targetArgTypes.subList(pos, pos + fold).clear();
2312         if (combineType != void.class)
2313             targetArgTypes.add(pos, combineType);
2314         MethodHandle target = varargsList(targetArgTypes, lastType);
2315         MethodHandle combine = varargsList(combineArgTypes, combineType);
2316         List<Object> argsToPass = Arrays.asList(randomArgs(argTypes));
2317         if (verbosity >= 3)
2318             System.out.println((isCollect ? "collect" : "fold")+" "+target+" with "+combine);
2319         MethodHandle target2;
2320         if (isCollect)
2321             target2 = MethodHandles.collectArguments(target, pos, combine);
2322         else
2323             target2 = withFoldPos ? MethodHandles.foldArguments(target, pos, combine) : MethodHandles.foldArguments(target, combine);
2324         // Simulate expected effect of combiner on arglist:
2325         List<Object> expectedList = new ArrayList<>(argsToPass);
2326         List<Object> argsToFold = expectedList.subList(pos, pos + fold);
2327         if (verbosity >= 3)
2328             System.out.println((isCollect ? "collect" : "fold")+": "+argsToFold+" into "+target2);
2329         Object foldedArgs = combine.invokeWithArguments(argsToFold);
2330         if (isCollect)
2331             argsToFold.clear();
2332         if (combineType != void.class)
2333             argsToFold.add(0, foldedArgs);
2334         Object result = target2.invokeWithArguments(argsToPass);
2335         if (verbosity >= 3)
2336             System.out.println("result: "+result);
2337         Object expected = target.invokeWithArguments(expectedList);
2338         if (!expected.equals(result))
2339             System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result+" != "+expected);
2340         assertEquals(expected, result);
2341     }
2342 
2343     @Test


2639                 int pc = test1.type().parameterCount();
2640                 test1 = MethodHandles.insertArguments(test, testArgs, Arrays.copyOfRange(argList1, testArgs, pc));
2641             }
2642             MethodHandle mh = MethodHandles.guardWithTest(test1, target, fallback);
2643             assertEquals(target.type(), mh.type());
2644             boolean equals;
2645             switch (nargs) {
2646             case 0:   equals = true; break;
2647             case 1:   equals = MISSING_ARG.equals(argList[0]); break;
2648             default:  equals = argList[0].equals(argList[1]); break;
2649             }
2650             String willCall = (equals ? "targetIfEquals" : "fallbackIfNotEquals");
2651             if (verbosity >= 3)
2652                 System.out.println(logEntry(willCall, argList));
2653             Object result = mh.invokeWithArguments(argList1);
2654             assertCalled(willCall, argList);
2655         }
2656     }
2657 
2658     @Test
2659     public void testGenericLoopCombinator() throws Throwable {
2660         CodeCacheOverflowProcessor.runMHTest(this::testGenericLoopCombinator0);
2661     }
2662     public void testGenericLoopCombinator0() throws Throwable {
2663         if (CAN_SKIP_WORKING) return;
2664         startTest("loop");
2665         // Test as follows:
2666         // * Have an increasing number of loop-local state. Local state type diversity grows with the number.
2667         // * Initializers set the starting value of loop-local state from the corresponding loop argument.
2668         // * For each local state element, there is a predicate - for all state combinations, exercise all predicates.
2669         // * Steps modify each local state element in each iteration.
2670         // * Finalizers group all local state elements into a resulting array. Verify end values.
2671         // * Exercise both pre- and post-checked loops.
2672         // Local state types, start values, predicates, and steps:
2673         // * int a, 0, a < 7, a = a + 1
2674         // * double b, 7.0, b > 0.5, b = b / 2.0
2675         // * String c, "start", c.length <= 9, c = c + a
2676         final Class<?>[] argTypes = new Class<?>[] {int.class, double.class, String.class};
2677         final Object[][] args = new Object[][] {
2678             new Object[]{0              },
2679             new Object[]{0, 7.0         },
2680             new Object[]{0, 7.0, "start"}
2681         };
2682         // These are the expected final state tuples for argument type tuple / predicate combinations, for pre- and
2683         // post-checked loops:
2684         final Object[][] preCheckedResults = new Object[][] {
2685             new Object[]{7                           }, // (int) / int
2686             new Object[]{7, 0.0546875                }, // (int,double) / int
2687             new Object[]{5, 0.4375                   }, // (int,double) / double
2688             new Object[]{7, 0.0546875, "start1234567"}, // (int,double,String) / int
2689             new Object[]{5, 0.4375,    "start1234"   }, // (int,double,String) / double
2690             new Object[]{6, 0.109375,  "start12345"  }  // (int,double,String) / String
2691         };
2692         final Object[][] postCheckedResults = new Object[][] {
2693             new Object[]{7                         }, // (int) / int
2694             new Object[]{7, 0.109375               }, // (int,double) / int
2695             new Object[]{4, 0.4375                 }, // (int,double) / double
2696             new Object[]{7, 0.109375, "start123456"}, // (int,double,String) / int
2697             new Object[]{4, 0.4375,   "start123"   }, // (int,double,String) / double
2698             new Object[]{5, 0.21875,  "start12345" }  // (int,double,String) / String
2699         };
2700         final Lookup l = MethodHandles.lookup();
2701         final Class<?> MHT = MethodHandlesTest.class;
2702         final Class<?> B = boolean.class;
2703         final Class<?> I = int.class;
2704         final Class<?> D = double.class;
2705         final Class<?> S = String.class;
2706         final MethodHandle hip = l.findStatic(MHT, "loopIntPred", methodType(B, I));
2707         final MethodHandle hdp = l.findStatic(MHT, "loopDoublePred", methodType(B, I, D));
2708         final MethodHandle hsp = l.findStatic(MHT, "loopStringPred", methodType(B, I, D, S));
2709         final MethodHandle his = l.findStatic(MHT, "loopIntStep", methodType(I, I));
2710         final MethodHandle hds = l.findStatic(MHT, "loopDoubleStep", methodType(D, I, D));
2711         final MethodHandle hss = l.findStatic(MHT, "loopStringStep", methodType(S, I, D, S));
2712         final MethodHandle[] preds = new MethodHandle[] {hip, hdp, hsp};
2713         final MethodHandle[] steps = new MethodHandle[] {his, hds, hss};
2714         for (int nargs = 1, useResultsStart = 0; nargs <= argTypes.length; useResultsStart += nargs++) {
2715             Class<?>[] useArgTypes = Arrays.copyOf(argTypes, nargs, Class[].class);
2716             MethodHandle[] usePreds = Arrays.copyOf(preds, nargs, MethodHandle[].class);
2717             MethodHandle[] useSteps = Arrays.copyOf(steps, nargs, MethodHandle[].class);
2718             Object[] useArgs = args[nargs - 1];
2719             Object[][] usePreCheckedResults = new Object[nargs][];
2720             Object[][] usePostCheckedResults = new Object[nargs][];
2721             System.arraycopy(preCheckedResults, useResultsStart, usePreCheckedResults, 0, nargs);
2722             System.arraycopy(postCheckedResults, useResultsStart, usePostCheckedResults, 0, nargs);
2723             testGenericLoopCombinator(nargs, useArgTypes, usePreds, useSteps, useArgs, usePreCheckedResults,
2724                     usePostCheckedResults);
2725         }
2726     }
2727     void testGenericLoopCombinator(int nargs, Class<?>[] argTypes, MethodHandle[] preds, MethodHandle[] steps,
2728                                    Object[] args, Object[][] preCheckedResults, Object[][] postCheckedResults)
2729             throws Throwable {
2730         List<Class<?>> lArgTypes = Arrays.asList(argTypes);
2731         // Predicate and step handles are passed in as arguments, initializer and finalizer handles are constructed here
2732         // from the available information.
2733         MethodHandle[] inits = new MethodHandle[nargs];
2734         for (int i = 0; i < nargs; ++i) {
2735             MethodHandle h;
2736             // Initializers are meant to return whatever they are passed at a given argument position. This means that
2737             // additional arguments may have to be appended and prepended.
2738             h = MethodHandles.identity(argTypes[i]);
2739             if (i < nargs - 1) {
2740                 h = MethodHandles.dropArguments(h, 1, lArgTypes.subList(i + 1, nargs));
2741             }
2742             if (i > 0) {
2743                 h = MethodHandles.dropArguments(h, 0, lArgTypes.subList(0, i));
2744             }
2745             inits[i] = h;
2746         }
2747         // Finalizers are all meant to collect all of the loop-local state in a single array and return that. Local
2748         // state is passed before the loop args. Construct such a finalizer by first taking a varargsArray collector for
2749         // the number of local state arguments, and then appending the loop args as to-be-dropped arguments.
2750         MethodHandle[] finis = new MethodHandle[nargs];
2751         MethodHandle genericFini = MethodHandles.dropArguments(
2752                 varargsArray(nargs).asType(methodType(Object[].class, lArgTypes)), nargs, lArgTypes);
2753         Arrays.fill(finis, genericFini);
2754         // The predicate and step handles' signatures need to be extended. They currently just accept local state args;
2755         // append possibly missing local state args and loop args using dropArguments.
2756         for (int i = 0; i < nargs; ++i) {
2757             List<Class<?>> additionalLocalStateArgTypes = lArgTypes.subList(i + 1, nargs);
2758             preds[i] = MethodHandles.dropArguments(
2759                     MethodHandles.dropArguments(preds[i], i + 1, additionalLocalStateArgTypes), nargs, lArgTypes);
2760             steps[i] = MethodHandles.dropArguments(
2761                     MethodHandles.dropArguments(steps[i], i + 1, additionalLocalStateArgTypes), nargs, lArgTypes);
2762         }
2763         // Iterate over all of the predicates, using only one of them at a time.
2764         for (int i = 0; i < nargs; ++i) {
2765             MethodHandle[] usePreds;
2766             if (nargs == 1) {
2767                 usePreds = preds;
2768             } else {
2769                 // Create an all-null preds array, and only use one predicate in this iteration. The null entries will
2770                 // be substituted with true predicates by the loop combinator.
2771                 usePreds = new MethodHandle[nargs];
2772                 usePreds[i] = preds[i];
2773             }
2774             // Go for it.
2775             if (verbosity >= 3) {
2776                 System.out.println("calling loop for argument types " + lArgTypes + " with predicate at index " + i);
2777                 if (verbosity >= 5) {
2778                     System.out.println("predicates: " + Arrays.asList(usePreds));
2779                 }
2780             }
2781             MethodHandle[] preInits = new MethodHandle[nargs + 1];
2782             MethodHandle[] prePreds = new MethodHandle[nargs + 1];
2783             MethodHandle[] preSteps = new MethodHandle[nargs + 1];
2784             MethodHandle[] preFinis = new MethodHandle[nargs + 1];
2785             System.arraycopy(inits, 0, preInits, 1, nargs);
2786             System.arraycopy(usePreds, 0, prePreds, 0, nargs); // preds are offset by 1 for pre-checked loops
2787             System.arraycopy(steps, 0, preSteps, 1, nargs);
2788             System.arraycopy(finis, 0, preFinis, 0, nargs); // finis are also offset by 1 for pre-checked loops
2789             // Convert to clause-major form.
2790             MethodHandle[][] preClauses = new MethodHandle[nargs+1][4];
2791             MethodHandle[][] postClauses = new MethodHandle[nargs][4];
2792             toClauseMajor(preClauses, preInits, preSteps, prePreds, preFinis);
2793             toClauseMajor(postClauses, inits, steps, usePreds, finis);
2794             MethodHandle pre = MethodHandles.loop(preClauses);
2795             MethodHandle post = MethodHandles.loop(postClauses);
2796             Object[] preResults = (Object[]) pre.invokeWithArguments(args);
2797             if (verbosity >= 4) {
2798                 System.out.println("pre-checked: expected " + Arrays.asList(preCheckedResults[i]) + ", actual " +
2799                         Arrays.asList(preResults));
2800             }
2801             Object[] postResults = (Object[]) post.invokeWithArguments(args);
2802             if (verbosity >= 4) {
2803                 System.out.println("post-checked: expected " + Arrays.asList(postCheckedResults[i]) + ", actual " +
2804                         Arrays.asList(postResults));
2805             }
2806             assertArrayEquals(preCheckedResults[i], preResults);
2807             assertArrayEquals(postCheckedResults[i], postResults);
2808         }
2809     }
2810     static void toClauseMajor(MethodHandle[][] clauses, MethodHandle[] init, MethodHandle[] step, MethodHandle[] pred, MethodHandle[] fini) {
2811         for (int i = 0; i < clauses.length; ++i) {
2812             clauses[i][0] = init[i];
2813             clauses[i][1] = step[i];
2814             clauses[i][2] = pred[i];
2815             clauses[i][3] = fini[i];
2816         }
2817     }
2818     static boolean loopIntPred(int a) {
2819         if (verbosity >= 5) {
2820             System.out.println("int pred " + a + " -> " + (a < 7));
2821         }
2822         return a < 7;
2823     }
2824     static boolean loopDoublePred(int a, double b) {
2825         if (verbosity >= 5) {
2826             System.out.println("double pred (a=" + a + ") " + b + " -> " + (b > 0.5));
2827         }
2828         return b > 0.5;
2829     }
2830     static boolean loopStringPred(int a, double b, String c) {
2831         if (verbosity >= 5) {
2832             System.out.println("String pred (a=" + a + ",b=" + b + ") " + c + " -> " + (c.length() <= 9));
2833         }
2834         return c.length() <= 9;
2835     }
2836     static int loopIntStep(int a) {
2837         if (verbosity >= 5) {
2838             System.out.println("int step " + a + " -> " + (a + 1));
2839         }
2840         return a + 1;
2841     }
2842     static double loopDoubleStep(int a, double b) {
2843         if (verbosity >= 5) {
2844             System.out.println("double step (a=" + a + ") " + b + " -> " + (b / 2.0));
2845         }
2846         return b / 2.0;
2847     }
2848     static String loopStringStep(int a, double b, String c) {
2849         if (verbosity >= 5) {
2850             System.out.println("String step (a=" + a + ",b=" + b + ") " + c + " -> " + (c + a));
2851         }
2852         return c + a;
2853     }
2854 
2855     @Test
2856     public void testThrowException() throws Throwable {
2857         CodeCacheOverflowProcessor.runMHTest(this::testThrowException0);
2858     }
2859 
2860     public void testThrowException0() throws Throwable {
2861         if (CAN_SKIP_WORKING)  return;
2862         startTest("throwException");
2863         testThrowException(int.class, new ClassCastException("testing"));
2864         testThrowException(void.class, new java.io.IOException("testing"));
2865         testThrowException(String.class, new LinkageError("testing"));
2866     }
2867 
2868     void testThrowException(Class<?> returnType, Throwable thrown) throws Throwable {
2869         countTest();
2870         Class<? extends Throwable> exType = thrown.getClass();
2871         MethodHandle target = MethodHandles.throwException(returnType, exType);
2872         //System.out.println("throwing with "+target+" : "+thrown);
2873         MethodType expectedType = MethodType.methodType(returnType, exType);
2874         assertEquals(expectedType, target.type());
2875         target = target.asType(target.type().generic());
2876         Throwable caught = null;
2877         try {
2878             Object res = target.invokeExact((Object) thrown);
2879             fail("got "+res+" instead of throwing "+thrown);
2880         } catch (Throwable ex) {
2881             if (ex != thrown) {
2882                 if (ex instanceof Error)  throw (Error)ex;
2883                 if (ex instanceof RuntimeException)  throw (RuntimeException)ex;
2884             }
2885             caught = ex;
2886         }
2887         assertSame(thrown, caught);
2888     }
2889 
2890     @Test
2891     public void testTryFinally() throws Throwable {
2892         CodeCacheOverflowProcessor.runMHTest(this::testTryFinally0);
2893     }
2894     public void testTryFinally0() throws Throwable {
2895         if (CAN_SKIP_WORKING) return;
2896         startTest("tryFinally");
2897         String inputMessage = "returned";
2898         String augmentedMessage = "augmented";
2899         String thrownMessage = "thrown";
2900         String rethrownMessage = "rethrown";
2901         // Test these cases:
2902         // * target returns, cleanup passes through
2903         // * target returns, cleanup augments
2904         // * target throws, cleanup augments and returns
2905         // * target throws, cleanup augments and rethrows
2906         MethodHandle target = MethodHandles.identity(String.class);
2907         MethodHandle targetThrow = MethodHandles.dropArguments(
2908                 MethodHandles.throwException(String.class, Exception.class).bindTo(new Exception(thrownMessage)), 0, String.class);
2909         MethodHandle cleanupPassThrough = MethodHandles.dropArguments(MethodHandles.identity(String.class), 0,
2910                 Throwable.class, String.class);
2911         MethodHandle cleanupAugment = MethodHandles.dropArguments(MethodHandles.constant(String.class, augmentedMessage),
2912                 0, Throwable.class, String.class, String.class);
2913         MethodHandle cleanupCatch = MethodHandles.dropArguments(MethodHandles.constant(String.class, thrownMessage), 0,
2914                 Throwable.class, String.class, String.class);
2915         MethodHandle cleanupThrow = MethodHandles.dropArguments(MethodHandles.throwException(String.class, Exception.class).
2916                 bindTo(new Exception(rethrownMessage)), 0, Throwable.class, String.class, String.class);
2917         testTryFinally(target, cleanupPassThrough, inputMessage, inputMessage, false);
2918         testTryFinally(target, cleanupAugment, inputMessage, augmentedMessage, false);
2919         testTryFinally(targetThrow, cleanupCatch, inputMessage, thrownMessage, true);
2920         testTryFinally(targetThrow, cleanupThrow, inputMessage, rethrownMessage, true);
2921         // Test the same cases as above for void targets and cleanups.
2922         MethodHandles.Lookup lookup = MethodHandles.lookup();
2923         Class<?> C = this.getClass();
2924         MethodType targetType = methodType(void.class, String[].class);
2925         MethodType cleanupType = methodType(void.class, Throwable.class, String[].class);
2926         MethodHandle vtarget = lookup.findStatic(C, "vtarget", targetType);
2927         MethodHandle vtargetThrow = lookup.findStatic(C, "vtargetThrow", targetType);
2928         MethodHandle vcleanupPassThrough = lookup.findStatic(C, "vcleanupPassThrough", cleanupType);
2929         MethodHandle vcleanupAugment = lookup.findStatic(C, "vcleanupAugment", cleanupType);
2930         MethodHandle vcleanupCatch = lookup.findStatic(C, "vcleanupCatch", cleanupType);
2931         MethodHandle vcleanupThrow = lookup.findStatic(C, "vcleanupThrow", cleanupType);
2932         testTryFinally(vtarget, vcleanupPassThrough, inputMessage, inputMessage, false);
2933         testTryFinally(vtarget, vcleanupAugment, inputMessage, augmentedMessage, false);
2934         testTryFinally(vtargetThrow, vcleanupCatch, inputMessage, thrownMessage, true);
2935         testTryFinally(vtargetThrow, vcleanupThrow, inputMessage, rethrownMessage, true);
2936     }
2937     void testTryFinally(MethodHandle target, MethodHandle cleanup, String input, String msg, boolean mustCatch)
2938             throws Throwable {
2939         countTest();
2940         MethodHandle tf = MethodHandles.tryFinally(target, cleanup);
2941         String result = null;
2942         boolean isVoid = target.type().returnType() == void.class;
2943         String[] argArray = new String[]{input};
2944         try {
2945             if (isVoid) {
2946                 tf.invoke(argArray);
2947             } else {
2948                 result = (String) tf.invoke(input);
2949             }
2950         } catch (Throwable t) {
2951             assertTrue(mustCatch);
2952             assertEquals(msg, t.getMessage());
2953             return;
2954         }
2955         assertFalse(mustCatch);
2956         if (isVoid) {
2957             assertEquals(msg, argArray[0]);
2958         } else {
2959             assertEquals(msg, result);
2960         }
2961     }
2962     static void vtarget(String[] a) {
2963         // naught, akin to identity
2964     }
2965     static void vtargetThrow(String[] a) throws Exception {
2966         throw new Exception("thrown");
2967     }
2968     static void vcleanupPassThrough(Throwable t, String[] a) {
2969         assertNull(t);
2970         // naught, akin to identity
2971     }
2972     static void vcleanupAugment(Throwable t, String[] a) {
2973         assertNull(t);
2974         a[0] = "augmented";
2975     }
2976     static void vcleanupCatch(Throwable t, String[] a) {
2977         assertNotNull(t);
2978         a[0] = "caught";
2979     }
2980     static void vcleanupThrow(Throwable t, String[] a) throws Exception {
2981         assertNotNull(t);
2982         throw new Exception("rethrown");
2983     }
2984 
2985     @Test
2986     public void testInterfaceCast() throws Throwable {
2987         CodeCacheOverflowProcessor.runMHTest(this::testInterfaceCast0);
2988     }
2989 
2990     public void testInterfaceCast0() throws Throwable {
2991         if (CAN_SKIP_WORKING)  return;
2992         startTest("interfaceCast");
2993         assert( (((Object)"foo") instanceof CharSequence));
2994         assert(!(((Object)"foo") instanceof Iterable));
2995         for (MethodHandle mh : new MethodHandle[]{
2996             MethodHandles.identity(String.class),
2997             MethodHandles.identity(CharSequence.class),
2998             MethodHandles.identity(Iterable.class)
2999         }) {
3000             if (verbosity > 0)  System.out.println("-- mh = "+mh);
3001             for (Class<?> ctype : new Class<?>[]{
3002                 Object.class, String.class, CharSequence.class,
3003                 Number.class, Iterable.class
3004             }) {
3005                 if (verbosity > 0)  System.out.println("---- ctype = "+ctype.getName());
3006                 //                           doret  docast
3007                 testInterfaceCast(mh, ctype, false, false);
3008                 testInterfaceCast(mh, ctype, true,  false);
3009                 testInterfaceCast(mh, ctype, false, true);
3010                 testInterfaceCast(mh, ctype, true,  true);
3011             }


< prev index next >