src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File jdk Sdiff src/java.base/share/classes/java/lang/invoke

src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java

Print this page
rev 10755 : 8058892: FILL_ARRAYS and ARRAYS are eagely initialized in MethodHandleImpl
Reviewed-by: ?


 577         if (av == null) {
 578             if (n == 0)  return;
 579         } else if (av instanceof Object[]) {
 580             int len = ((Object[])av).length;
 581             if (len == n)  return;
 582         } else {
 583             int len = java.lang.reflect.Array.getLength(av);
 584             if (len == n)  return;
 585         }
 586         // fall through to error:
 587         throw newIllegalArgumentException("array is not of length "+n);
 588     }
 589 
 590     /**
 591      * Pre-initialized NamedFunctions for bootstrapping purposes.
 592      * Factored in an inner class to delay initialization until first usage.
 593      */
 594     static class Lazy {
 595         private static final Class<?> MHI = MethodHandleImpl.class;
 596 



 597         static final NamedFunction NF_checkSpreadArgument;
 598         static final NamedFunction NF_guardWithCatch;
 599         static final NamedFunction NF_throwException;
 600 
 601         static final MethodHandle MH_castReference;
 602         static final MethodHandle MH_selectAlternative;
 603         static final MethodHandle MH_copyAsPrimitiveArray;
 604         static final MethodHandle MH_fillNewTypedArray;
 605         static final MethodHandle MH_fillNewArray;
 606         static final MethodHandle MH_arrayIdentity;
 607 
 608         static {
 609             try {
 610                 NF_checkSpreadArgument = new NamedFunction(MHI.getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
 611                 NF_guardWithCatch      = new NamedFunction(MHI.getDeclaredMethod("guardWithCatch", MethodHandle.class, Class.class,
 612                                                                                  MethodHandle.class, Object[].class));
 613                 NF_throwException      = new NamedFunction(MHI.getDeclaredMethod("throwException", Throwable.class));
 614 
 615                 NF_checkSpreadArgument.resolve();
 616                 NF_guardWithCatch.resolve();


1251                 { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); }
1252     private static Object[] array(Object a0, Object a1, Object a2, Object a3,
1253                                   Object a4, Object a5, Object a6, Object a7,
1254                                   Object a8)
1255                 { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
1256     private static Object[] array(Object a0, Object a1, Object a2, Object a3,
1257                                   Object a4, Object a5, Object a6, Object a7,
1258                                   Object a8, Object a9)
1259                 { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
1260     private static MethodHandle[] makeArrays() {
1261         ArrayList<MethodHandle> mhs = new ArrayList<>();
1262         for (;;) {
1263             MethodHandle mh = findCollector("array", mhs.size(), Object[].class);
1264             if (mh == null)  break;
1265             mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
1266             mhs.add(mh);
1267         }
1268         assert(mhs.size() == 11);  // current number of methods
1269         return mhs.toArray(new MethodHandle[MAX_ARITY+1]);
1270     }
1271     private static final MethodHandle[] ARRAYS = makeArrays();
1272 
1273     // filling versions of the above:
1274     // using Integer len instead of int len and no varargs to avoid bootstrapping problems
1275     private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) {
1276         Object[] a = new Object[len];
1277         fillWithArguments(a, 0, args);
1278         return a;
1279     }
1280     private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) {
1281         Object[] a = Arrays.copyOf(example, len);
1282         assert(a.getClass() != Object[].class);
1283         fillWithArguments(a, 0, args);
1284         return a;
1285     }
1286     private static void fillWithArguments(Object[] a, int pos, Object... args) {
1287         System.arraycopy(args, 0, a, pos, args.length);
1288     }
1289     // using Integer pos instead of int pos to avoid bootstrapping problems
1290     private static Object[] fillArray(Integer pos, Object[] a, Object a0)
1291                 { fillWithArguments(a, pos, a0); return a; }


1298     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1299                                   Object a4)
1300                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; }
1301     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1302                                   Object a4, Object a5)
1303                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; }
1304     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1305                                   Object a4, Object a5, Object a6)
1306                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; }
1307     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1308                                   Object a4, Object a5, Object a6, Object a7)
1309                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; }
1310     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1311                                   Object a4, Object a5, Object a6, Object a7,
1312                                   Object a8)
1313                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; }
1314     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1315                                   Object a4, Object a5, Object a6, Object a7,
1316                                   Object a8, Object a9)
1317                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; }



1318     private static MethodHandle[] makeFillArrays() {
1319         ArrayList<MethodHandle> mhs = new ArrayList<>();
1320         mhs.add(null);  // there is no empty fill; at least a0 is required
1321         for (;;) {
1322             MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class);
1323             if (mh == null)  break;
1324             mhs.add(mh);
1325         }
1326         assert(mhs.size() == 11);  // current number of methods
1327         return mhs.toArray(new MethodHandle[0]);
1328     }
1329     private static final MethodHandle[] FILL_ARRAYS = makeFillArrays();
1330 
1331     private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) {
1332         Object a = w.makeArray(boxes.length);
1333         w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length);
1334         return a;
1335     }
1336 
1337     /** Return a method handle that takes the indicated number of Object
1338      *  arguments and returns an Object array of them, as if for varargs.
1339      */
1340     static MethodHandle varargsArray(int nargs) {
1341         MethodHandle mh = ARRAYS[nargs];
1342         if (mh != null)  return mh;
1343         mh = findCollector("array", nargs, Object[].class);
1344         if (mh != null)  mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
1345         if (mh != null)  return ARRAYS[nargs] = mh;
1346         mh = buildVarargsArray(Lazy.MH_fillNewArray, Lazy.MH_arrayIdentity, nargs);
1347         assert(assertCorrectArity(mh, nargs));
1348         mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
1349         return ARRAYS[nargs] = mh;
1350     }
1351 
1352     private static boolean assertCorrectArity(MethodHandle mh, int arity) {
1353         assert(mh.type().parameterCount() == arity) : "arity != "+arity+": "+mh;
1354         return true;
1355     }
1356 
1357     // Array identity function (used as Lazy.MH_arrayIdentity).
1358     static <T> T[] identity(T[] x) {
1359         return x;
1360     }
1361 
1362     private static MethodHandle buildVarargsArray(MethodHandle newArray, MethodHandle finisher, int nargs) {
1363         // Build up the result mh as a sequence of fills like this:
1364         //   finisher(fill(fill(newArrayWA(23,x1..x10),10,x11..x20),20,x21..x23))
1365         // The various fill(_,10*I,___*[J]) are reusable.
1366         int leftLen = Math.min(nargs, LEFT_ARGS);  // absorb some arguments immediately
1367         int rightLen = nargs - leftLen;
1368         MethodHandle leftCollector = newArray.bindTo(nargs);
1369         leftCollector = leftCollector.asCollector(Object[].class, leftLen);
1370         MethodHandle mh = finisher;
1371         if (rightLen > 0) {
1372             MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen);
1373             if (mh == Lazy.MH_arrayIdentity)
1374                 mh = rightFiller;
1375             else
1376                 mh = MethodHandles.collectArguments(mh, 0, rightFiller);
1377         }
1378         if (mh == Lazy.MH_arrayIdentity)
1379             mh = leftCollector;
1380         else
1381             mh = MethodHandles.collectArguments(mh, 0, leftCollector);
1382         return mh;
1383     }
1384 
1385     private static final int LEFT_ARGS = (FILL_ARRAYS.length - 1);
1386     private static final MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY+1];
1387     /** fill_array_to_right(N).invoke(a, argL..arg[N-1])
1388      *  fills a[L]..a[N-1] with corresponding arguments,
1389      *  and then returns a.  The value L is a global constant (LEFT_ARGS).
1390      */
1391     private static MethodHandle fillToRight(int nargs) {
1392         MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs];
1393         if (filler != null)  return filler;
1394         filler = buildFiller(nargs);
1395         assert(assertCorrectArity(filler, nargs - LEFT_ARGS + 1));
1396         return FILL_ARRAY_TO_RIGHT[nargs] = filler;
1397     }
1398     private static MethodHandle buildFiller(int nargs) {
1399         if (nargs <= LEFT_ARGS)
1400             return Lazy.MH_arrayIdentity;  // no args to fill; return the array unchanged
1401         // we need room for both mh and a in mh.invoke(a, arg*[nargs])
1402         final int CHUNK = LEFT_ARGS;
1403         int rightLen = nargs % CHUNK;
1404         int midLen = nargs - rightLen;
1405         if (rightLen == 0) {
1406             midLen = nargs - (rightLen = CHUNK);
1407             if (FILL_ARRAY_TO_RIGHT[midLen] == null) {
1408                 // build some precursors from left to right
1409                 for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK)
1410                     if (j > LEFT_ARGS)  fillToRight(j);
1411             }
1412         }
1413         if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS);
1414         assert(rightLen > 0);
1415         MethodHandle midFill = fillToRight(midLen);  // recursive fill
1416         MethodHandle rightFill = FILL_ARRAYS[rightLen].bindTo(midLen);  // [midLen..nargs-1]
1417         assert(midFill.type().parameterCount()   == 1 + midLen - LEFT_ARGS);
1418         assert(rightFill.type().parameterCount() == 1 + rightLen);
1419 
1420         // Combine the two fills:
1421         //   right(mid(a, x10..x19), x20..x23)
1422         // The final product will look like this:
1423         //   right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23)
1424         if (midLen == LEFT_ARGS)
1425             return rightFill;
1426         else
1427             return MethodHandles.collectArguments(rightFill, 0, midFill);
1428     }
1429 
1430     // Type-polymorphic version of varargs maker.
1431     private static final ClassValue<MethodHandle[]> TYPED_COLLECTORS
1432         = new ClassValue<MethodHandle[]>() {
1433             @Override
1434             protected MethodHandle[] computeValue(Class<?> type) {
1435                 return new MethodHandle[256];
1436             }




 577         if (av == null) {
 578             if (n == 0)  return;
 579         } else if (av instanceof Object[]) {
 580             int len = ((Object[])av).length;
 581             if (len == n)  return;
 582         } else {
 583             int len = java.lang.reflect.Array.getLength(av);
 584             if (len == n)  return;
 585         }
 586         // fall through to error:
 587         throw newIllegalArgumentException("array is not of length "+n);
 588     }
 589 
 590     /**
 591      * Pre-initialized NamedFunctions for bootstrapping purposes.
 592      * Factored in an inner class to delay initialization until first usage.
 593      */
 594     static class Lazy {
 595         private static final Class<?> MHI = MethodHandleImpl.class;
 596 
 597         private static final MethodHandle[] ARRAYS      = makeArrays();
 598         private static final MethodHandle[] FILL_ARRAYS = makeFillArrays();
 599 
 600         static final NamedFunction NF_checkSpreadArgument;
 601         static final NamedFunction NF_guardWithCatch;
 602         static final NamedFunction NF_throwException;
 603 
 604         static final MethodHandle MH_castReference;
 605         static final MethodHandle MH_selectAlternative;
 606         static final MethodHandle MH_copyAsPrimitiveArray;
 607         static final MethodHandle MH_fillNewTypedArray;
 608         static final MethodHandle MH_fillNewArray;
 609         static final MethodHandle MH_arrayIdentity;
 610 
 611         static {
 612             try {
 613                 NF_checkSpreadArgument = new NamedFunction(MHI.getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
 614                 NF_guardWithCatch      = new NamedFunction(MHI.getDeclaredMethod("guardWithCatch", MethodHandle.class, Class.class,
 615                                                                                  MethodHandle.class, Object[].class));
 616                 NF_throwException      = new NamedFunction(MHI.getDeclaredMethod("throwException", Throwable.class));
 617 
 618                 NF_checkSpreadArgument.resolve();
 619                 NF_guardWithCatch.resolve();


1254                 { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); }
1255     private static Object[] array(Object a0, Object a1, Object a2, Object a3,
1256                                   Object a4, Object a5, Object a6, Object a7,
1257                                   Object a8)
1258                 { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
1259     private static Object[] array(Object a0, Object a1, Object a2, Object a3,
1260                                   Object a4, Object a5, Object a6, Object a7,
1261                                   Object a8, Object a9)
1262                 { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
1263     private static MethodHandle[] makeArrays() {
1264         ArrayList<MethodHandle> mhs = new ArrayList<>();
1265         for (;;) {
1266             MethodHandle mh = findCollector("array", mhs.size(), Object[].class);
1267             if (mh == null)  break;
1268             mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
1269             mhs.add(mh);
1270         }
1271         assert(mhs.size() == 11);  // current number of methods
1272         return mhs.toArray(new MethodHandle[MAX_ARITY+1]);
1273     }

1274 
1275     // filling versions of the above:
1276     // using Integer len instead of int len and no varargs to avoid bootstrapping problems
1277     private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) {
1278         Object[] a = new Object[len];
1279         fillWithArguments(a, 0, args);
1280         return a;
1281     }
1282     private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) {
1283         Object[] a = Arrays.copyOf(example, len);
1284         assert(a.getClass() != Object[].class);
1285         fillWithArguments(a, 0, args);
1286         return a;
1287     }
1288     private static void fillWithArguments(Object[] a, int pos, Object... args) {
1289         System.arraycopy(args, 0, a, pos, args.length);
1290     }
1291     // using Integer pos instead of int pos to avoid bootstrapping problems
1292     private static Object[] fillArray(Integer pos, Object[] a, Object a0)
1293                 { fillWithArguments(a, pos, a0); return a; }


1300     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1301                                   Object a4)
1302                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; }
1303     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1304                                   Object a4, Object a5)
1305                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; }
1306     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1307                                   Object a4, Object a5, Object a6)
1308                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; }
1309     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1310                                   Object a4, Object a5, Object a6, Object a7)
1311                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; }
1312     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1313                                   Object a4, Object a5, Object a6, Object a7,
1314                                   Object a8)
1315                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; }
1316     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1317                                   Object a4, Object a5, Object a6, Object a7,
1318                                   Object a8, Object a9)
1319                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; }
1320 
1321     private static final int FILL_ARRAYS_COUNT = 11; // current number of fillArray methods
1322 
1323     private static MethodHandle[] makeFillArrays() {
1324         ArrayList<MethodHandle> mhs = new ArrayList<>();
1325         mhs.add(null);  // there is no empty fill; at least a0 is required
1326         for (;;) {
1327             MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class);
1328             if (mh == null)  break;
1329             mhs.add(mh);
1330         }
1331         assert(mhs.size() == FILL_ARRAYS_COUNT);
1332         return mhs.toArray(new MethodHandle[0]);
1333     }

1334 
1335     private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) {
1336         Object a = w.makeArray(boxes.length);
1337         w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length);
1338         return a;
1339     }
1340 
1341     /** Return a method handle that takes the indicated number of Object
1342      *  arguments and returns an Object array of them, as if for varargs.
1343      */
1344     static MethodHandle varargsArray(int nargs) {
1345         MethodHandle mh = Lazy.ARRAYS[nargs];
1346         if (mh != null)  return mh;
1347         mh = findCollector("array", nargs, Object[].class);
1348         if (mh != null)  mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
1349         if (mh != null)  return Lazy.ARRAYS[nargs] = mh;
1350         mh = buildVarargsArray(Lazy.MH_fillNewArray, Lazy.MH_arrayIdentity, nargs);
1351         assert(assertCorrectArity(mh, nargs));
1352         mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
1353         return Lazy.ARRAYS[nargs] = mh;
1354     }
1355 
1356     private static boolean assertCorrectArity(MethodHandle mh, int arity) {
1357         assert(mh.type().parameterCount() == arity) : "arity != "+arity+": "+mh;
1358         return true;
1359     }
1360 
1361     // Array identity function (used as Lazy.MH_arrayIdentity).
1362     static <T> T[] identity(T[] x) {
1363         return x;
1364     }
1365 
1366     private static MethodHandle buildVarargsArray(MethodHandle newArray, MethodHandle finisher, int nargs) {
1367         // Build up the result mh as a sequence of fills like this:
1368         //   finisher(fill(fill(newArrayWA(23,x1..x10),10,x11..x20),20,x21..x23))
1369         // The various fill(_,10*I,___*[J]) are reusable.
1370         int leftLen = Math.min(nargs, LEFT_ARGS);  // absorb some arguments immediately
1371         int rightLen = nargs - leftLen;
1372         MethodHandle leftCollector = newArray.bindTo(nargs);
1373         leftCollector = leftCollector.asCollector(Object[].class, leftLen);
1374         MethodHandle mh = finisher;
1375         if (rightLen > 0) {
1376             MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen);
1377             if (mh == Lazy.MH_arrayIdentity)
1378                 mh = rightFiller;
1379             else
1380                 mh = MethodHandles.collectArguments(mh, 0, rightFiller);
1381         }
1382         if (mh == Lazy.MH_arrayIdentity)
1383             mh = leftCollector;
1384         else
1385             mh = MethodHandles.collectArguments(mh, 0, leftCollector);
1386         return mh;
1387     }
1388 
1389     private static final int LEFT_ARGS = FILL_ARRAYS_COUNT - 1;
1390     private static final MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY+1];
1391     /** fill_array_to_right(N).invoke(a, argL..arg[N-1])
1392      *  fills a[L]..a[N-1] with corresponding arguments,
1393      *  and then returns a.  The value L is a global constant (LEFT_ARGS).
1394      */
1395     private static MethodHandle fillToRight(int nargs) {
1396         MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs];
1397         if (filler != null)  return filler;
1398         filler = buildFiller(nargs);
1399         assert(assertCorrectArity(filler, nargs - LEFT_ARGS + 1));
1400         return FILL_ARRAY_TO_RIGHT[nargs] = filler;
1401     }
1402     private static MethodHandle buildFiller(int nargs) {
1403         if (nargs <= LEFT_ARGS)
1404             return Lazy.MH_arrayIdentity;  // no args to fill; return the array unchanged
1405         // we need room for both mh and a in mh.invoke(a, arg*[nargs])
1406         final int CHUNK = LEFT_ARGS;
1407         int rightLen = nargs % CHUNK;
1408         int midLen = nargs - rightLen;
1409         if (rightLen == 0) {
1410             midLen = nargs - (rightLen = CHUNK);
1411             if (FILL_ARRAY_TO_RIGHT[midLen] == null) {
1412                 // build some precursors from left to right
1413                 for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK)
1414                     if (j > LEFT_ARGS)  fillToRight(j);
1415             }
1416         }
1417         if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS);
1418         assert(rightLen > 0);
1419         MethodHandle midFill = fillToRight(midLen);  // recursive fill
1420         MethodHandle rightFill = Lazy.FILL_ARRAYS[rightLen].bindTo(midLen);  // [midLen..nargs-1]
1421         assert(midFill.type().parameterCount()   == 1 + midLen - LEFT_ARGS);
1422         assert(rightFill.type().parameterCount() == 1 + rightLen);
1423 
1424         // Combine the two fills:
1425         //   right(mid(a, x10..x19), x20..x23)
1426         // The final product will look like this:
1427         //   right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23)
1428         if (midLen == LEFT_ARGS)
1429             return rightFill;
1430         else
1431             return MethodHandles.collectArguments(rightFill, 0, midFill);
1432     }
1433 
1434     // Type-polymorphic version of varargs maker.
1435     private static final ClassValue<MethodHandle[]> TYPED_COLLECTORS
1436         = new ClassValue<MethodHandle[]>() {
1437             @Override
1438             protected MethodHandle[] computeValue(Class<?> type) {
1439                 return new MethodHandle[256];
1440             }


src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File