jdk/src/share/classes/sun/invoke/util/ValueConversions.java
changeset 13610 28122b96858e
parent 13423 17843fff200d
child 14089 0a41b980d62a
child 14222 58f55d4dde46
equal deleted inserted replaced
13460:c7aa5cca1c01 13610:28122b96858e
    42     // Do not adjust this except for special platforms:
    42     // Do not adjust this except for special platforms:
    43     private static final int MAX_ARITY;
    43     private static final int MAX_ARITY;
    44     static {
    44     static {
    45         final Object[] values = { 255 };
    45         final Object[] values = { 255 };
    46         AccessController.doPrivileged(new PrivilegedAction<Void>() {
    46         AccessController.doPrivileged(new PrivilegedAction<Void>() {
       
    47                 @Override
    47                 public Void run() {
    48                 public Void run() {
    48                     values[0] = Integer.getInteger(THIS_CLASS.getName()+".MAX_ARITY", 255);
    49                     values[0] = Integer.getInteger(THIS_CLASS.getName()+".MAX_ARITY", 255);
    49                     return null;
    50                     return null;
    50                 }
    51                 }
    51             });
    52             });
   180      * Caller must invoke intValue, byteValue, longValue (etc.) on the result
   181      * Caller must invoke intValue, byteValue, longValue (etc.) on the result
   181      * to retrieve the desired primitive value.
   182      * to retrieve the desired primitive value.
   182      */
   183      */
   183     public static Number primitiveConversion(Wrapper wrap, Object x, boolean cast) {
   184     public static Number primitiveConversion(Wrapper wrap, Object x, boolean cast) {
   184         // Maybe merge this code with Wrapper.convert/cast.
   185         // Maybe merge this code with Wrapper.convert/cast.
   185         Number res = null;
   186         Number res;
   186         if (x == null) {
   187         if (x == null) {
   187             if (!cast)  return null;
   188             if (!cast)  return null;
   188             return ZERO_INT;
   189             return ZERO_INT;
   189         }
   190         }
   190         if (x instanceof Number) {
   191         if (x instanceof Number) {
   320 
   321 
   321     /// Constant functions
   322     /// Constant functions
   322 
   323 
   323     static void ignore(Object x) {
   324     static void ignore(Object x) {
   324         // no value to return; this is an unbox of null
   325         // no value to return; this is an unbox of null
   325         return;
       
   326     }
   326     }
   327 
   327 
   328     static void empty() {
   328     static void empty() {
   329         return;
       
   330     }
   329     }
   331 
   330 
   332     static Object zeroObject() {
   331     static Object zeroObject() {
   333         return null;
   332         return null;
   334     }
   333     }
   388     }
   387     }
   389 
   388 
   390     /// Converting references to references.
   389     /// Converting references to references.
   391 
   390 
   392     /**
   391     /**
   393      * Value-killing function.
       
   394      * @param x an arbitrary reference value
       
   395      * @return a null
       
   396      */
       
   397     static Object alwaysNull(Object x) {
       
   398         return null;
       
   399     }
       
   400 
       
   401     /**
       
   402      * Value-killing function.
       
   403      * @param x an arbitrary reference value
       
   404      * @return a zero
       
   405      */
       
   406     static int alwaysZero(Object x) {
       
   407         return 0;
       
   408     }
       
   409 
       
   410     /**
       
   411      * Identity function.
   392      * Identity function.
   412      * @param x an arbitrary reference value
   393      * @param x an arbitrary reference value
   413      * @return the same value x
   394      * @return the same value x
   414      */
   395      */
   415     static <T> T identity(T x) {
   396     static <T> T identity(T x) {
       
   397         return x;
       
   398     }
       
   399 
       
   400     static <T> T[] identity(T[] x) {
   416         return x;
   401         return x;
   417     }
   402     }
   418 
   403 
   419     /**
   404     /**
   420      * Identity function on ints.
   405      * Identity function on ints.
   466      */
   451      */
   467     static <T,U> T castReference(Class<? extends T> t, U x) {
   452     static <T,U> T castReference(Class<? extends T> t, U x) {
   468         return t.cast(x);
   453         return t.cast(x);
   469     }
   454     }
   470 
   455 
   471     private static final MethodHandle IDENTITY, CAST_REFERENCE, ALWAYS_NULL, ALWAYS_ZERO, ZERO_OBJECT, IGNORE, EMPTY, NEW_ARRAY;
   456     private static final MethodHandle IDENTITY, CAST_REFERENCE, ZERO_OBJECT, IGNORE, EMPTY,
       
   457             ARRAY_IDENTITY, FILL_NEW_TYPED_ARRAY, FILL_NEW_ARRAY;
   472     static {
   458     static {
   473         try {
   459         try {
   474             MethodType idType = MethodType.genericMethodType(1);
   460             MethodType idType = MethodType.genericMethodType(1);
   475             MethodType castType = idType.insertParameterTypes(0, Class.class);
   461             MethodType castType = idType.insertParameterTypes(0, Class.class);
   476             MethodType alwaysZeroType = idType.changeReturnType(int.class);
       
   477             MethodType ignoreType = idType.changeReturnType(void.class);
   462             MethodType ignoreType = idType.changeReturnType(void.class);
   478             MethodType zeroObjectType = MethodType.genericMethodType(0);
   463             MethodType zeroObjectType = MethodType.genericMethodType(0);
   479             IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", idType);
   464             IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", idType);
   480             //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
   465             //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
   481             CAST_REFERENCE = IMPL_LOOKUP.findStatic(THIS_CLASS, "castReference", castType);
   466             CAST_REFERENCE = IMPL_LOOKUP.findStatic(THIS_CLASS, "castReference", castType);
   482             ALWAYS_NULL = IMPL_LOOKUP.findStatic(THIS_CLASS, "alwaysNull", idType);
       
   483             ALWAYS_ZERO = IMPL_LOOKUP.findStatic(THIS_CLASS, "alwaysZero", alwaysZeroType);
       
   484             ZERO_OBJECT = IMPL_LOOKUP.findStatic(THIS_CLASS, "zeroObject", zeroObjectType);
   467             ZERO_OBJECT = IMPL_LOOKUP.findStatic(THIS_CLASS, "zeroObject", zeroObjectType);
   485             IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType);
   468             IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType);
   486             EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1));
   469             EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1));
   487             NEW_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "newArray", MethodType.methodType(Object[].class, int.class));
   470             ARRAY_IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", MethodType.methodType(Object[].class, Object[].class));
       
   471             FILL_NEW_ARRAY = IMPL_LOOKUP
       
   472                     .findStatic(THIS_CLASS, "fillNewArray",
       
   473                           MethodType.methodType(Object[].class, Integer.class, Object[].class));
       
   474             FILL_NEW_TYPED_ARRAY = IMPL_LOOKUP
       
   475                     .findStatic(THIS_CLASS, "fillNewTypedArray",
       
   476                           MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class));
   488         } catch (NoSuchMethodException | IllegalAccessException ex) {
   477         } catch (NoSuchMethodException | IllegalAccessException ex) {
   489             throw new InternalError("uncaught exception", ex);
   478             throw new InternalError("uncaught exception", ex);
   490         }
   479         }
   491     }
   480     }
   492 
   481 
   493     // Varargs methods need to be in a separately initialized class, to bootstrapping problems.
   482     // Varargs methods need to be in a separately initialized class, to avoid bootstrapping problems.
   494     static class LazyStatics {
   483     static class LazyStatics {
   495         private static final MethodHandle COPY_AS_REFERENCE_ARRAY, COPY_AS_PRIMITIVE_ARRAY, MAKE_LIST;
   484         private static final MethodHandle COPY_AS_REFERENCE_ARRAY, COPY_AS_PRIMITIVE_ARRAY, MAKE_LIST;
   496         static {
   485         static {
   497             try {
   486             try {
   498                 //MAKE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeArray", MethodType.methodType(Object[].class, Object[].class));
   487                 //MAKE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeArray", MethodType.methodType(Object[].class, Object[].class));
   503                 throw new InternalError("uncaught exception", ex);
   492                 throw new InternalError("uncaught exception", ex);
   504             }
   493             }
   505         }
   494         }
   506     }
   495     }
   507 
   496 
       
   497     static MethodHandle collectArguments(MethodHandle mh, int pos, MethodHandle collector) {
       
   498         // FIXME: API needs public MHs.collectArguments.
       
   499         // Should be:
       
   500         //   return MethodHandles.collectArguments(mh, 0, collector);
       
   501         // The rest of this code is a workaround for not having that API.
       
   502         if (COLLECT_ARGUMENTS != null) {
       
   503             try {
       
   504                 return (MethodHandle)
       
   505                     COLLECT_ARGUMENTS.invokeExact(mh, pos, collector);
       
   506             } catch (Throwable ex) {
       
   507                 if (ex instanceof RuntimeException)
       
   508                     throw (RuntimeException) ex;
       
   509                 if (ex instanceof Error)
       
   510                     throw (Error) ex;
       
   511                 throw new Error(ex.getMessage(), ex);
       
   512             }
       
   513         }
       
   514         // Emulate MHs.collectArguments using fold + drop.
       
   515         // This is slightly inefficient.
       
   516         // More seriously, it can put a MH over the 255-argument limit.
       
   517         mh = MethodHandles.dropArguments(mh, 1, collector.type().parameterList());
       
   518         mh = MethodHandles.foldArguments(mh, collector);
       
   519         return mh;
       
   520     }
       
   521     private static final MethodHandle COLLECT_ARGUMENTS;
       
   522     static {
       
   523         MethodHandle mh = null;
       
   524         try {
       
   525             java.lang.reflect.Method m = MethodHandles.class
       
   526                 .getDeclaredMethod("collectArguments",
       
   527                     MethodHandle.class, int.class, MethodHandle.class);
       
   528             m.setAccessible(true);
       
   529             mh = IMPL_LOOKUP.unreflect(m);
       
   530 
       
   531         } catch (ReflectiveOperationException | SecurityException ex) {
       
   532             throw new InternalError(ex);
       
   533         }
       
   534         COLLECT_ARGUMENTS = mh;
       
   535     }
       
   536 
   508     private static final EnumMap<Wrapper, MethodHandle>[] WRAPPER_CASTS
   537     private static final EnumMap<Wrapper, MethodHandle>[] WRAPPER_CASTS
   509             = newWrapperCaches(2);
   538             = newWrapperCaches(1);
   510 
   539 
   511     /** Return a method that casts its sole argument (an Object) to the given type
   540     /** Return a method that casts its sole argument (an Object) to the given type
   512      *  and returns it as the given type (if exact is true), or as plain Object (if erase is true).
   541      *  and returns it as the given type.
   513      */
   542      */
   514     public static MethodHandle cast(Class<?> type) {
   543     public static MethodHandle cast(Class<?> type) {
   515         boolean exact = false;
       
   516         if (type.isPrimitive())  throw new IllegalArgumentException("cannot cast primitive type "+type);
   544         if (type.isPrimitive())  throw new IllegalArgumentException("cannot cast primitive type "+type);
   517         MethodHandle mh = null;
   545         MethodHandle mh;
   518         Wrapper wrap = null;
   546         Wrapper wrap = null;
   519         EnumMap<Wrapper, MethodHandle> cache = null;
   547         EnumMap<Wrapper, MethodHandle> cache = null;
   520         if (Wrapper.isWrapperType(type)) {
   548         if (Wrapper.isWrapperType(type)) {
   521             wrap = Wrapper.forWrapperType(type);
   549             wrap = Wrapper.forWrapperType(type);
   522             cache = WRAPPER_CASTS[exact?1:0];
   550             cache = WRAPPER_CASTS[0];
   523             mh = cache.get(wrap);
   551             mh = cache.get(wrap);
   524             if (mh != null)  return mh;
   552             if (mh != null)  return mh;
   525         }
   553         }
   526         if (VerifyType.isNullReferenceConversion(Object.class, type))
   554         mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type);
   527             mh = IDENTITY;
       
   528         else if (VerifyType.isNullType(type))
       
   529             mh = ALWAYS_NULL;
       
   530         else
       
   531             mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type);
       
   532         if (exact) {
       
   533             MethodType xmt = MethodType.methodType(type, Object.class);
       
   534             mh = MethodHandles.explicitCastArguments(mh, xmt);
       
   535         }
       
   536         if (cache != null)
   555         if (cache != null)
   537             cache.put(wrap, mh);
   556             cache.put(wrap, mh);
   538         return mh;
   557         return mh;
   539     }
   558     }
   540 
   559 
   918         assert(mhs.size() == 11);  // current number of methods
   937         assert(mhs.size() == 11);  // current number of methods
   919         return mhs.toArray(new MethodHandle[MAX_ARITY+1]);
   938         return mhs.toArray(new MethodHandle[MAX_ARITY+1]);
   920     }
   939     }
   921     private static final MethodHandle[] ARRAYS = makeArrays();
   940     private static final MethodHandle[] ARRAYS = makeArrays();
   922 
   941 
   923     // mh-fill versions of the above:
   942     // filling versions of the above:
   924     private static Object[] newArray(int len) { return new Object[len]; }
   943     // using Integer len instead of int len and no varargs to avoid bootstrapping problems
       
   944     private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) {
       
   945         Object[] a = new Object[len];
       
   946         fillWithArguments(a, 0, args);
       
   947         return a;
       
   948     }
       
   949     private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) {
       
   950         Object[] a = Arrays.copyOf(example, len);
       
   951         fillWithArguments(a, 0, args);
       
   952         return a;
       
   953     }
   925     private static void fillWithArguments(Object[] a, int pos, Object... args) {
   954     private static void fillWithArguments(Object[] a, int pos, Object... args) {
   926         System.arraycopy(args, 0, a, pos, args.length);
   955         System.arraycopy(args, 0, a, pos, args.length);
   927     }
   956     }
   928     // using Integer pos instead of int pos to avoid bootstrapping problems
   957     // using Integer pos instead of int pos to avoid bootstrapping problems
   929     private static Object[] fillArray(Object[] a, Integer pos, Object a0)
   958     private static Object[] fillArray(Integer pos, Object[] a, Object a0)
   930                 { fillWithArguments(a, pos, a0); return a; }
   959                 { fillWithArguments(a, pos, a0); return a; }
   931     private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1)
   960     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1)
   932                 { fillWithArguments(a, pos, a0, a1); return a; }
   961                 { fillWithArguments(a, pos, a0, a1); return a; }
   933     private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2)
   962     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2)
   934                 { fillWithArguments(a, pos, a0, a1, a2); return a; }
   963                 { fillWithArguments(a, pos, a0, a1, a2); return a; }
   935     private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3)
   964     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3)
   936                 { fillWithArguments(a, pos, a0, a1, a2, a3); return a; }
   965                 { fillWithArguments(a, pos, a0, a1, a2, a3); return a; }
   937     private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3,
   966     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
   938                                   Object a4)
   967                                   Object a4)
   939                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; }
   968                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; }
   940     private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3,
   969     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
   941                                   Object a4, Object a5)
   970                                   Object a4, Object a5)
   942                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; }
   971                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; }
   943     private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3,
   972     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
   944                                   Object a4, Object a5, Object a6)
   973                                   Object a4, Object a5, Object a6)
   945                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; }
   974                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; }
   946     private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3,
   975     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
   947                                   Object a4, Object a5, Object a6, Object a7)
   976                                   Object a4, Object a5, Object a6, Object a7)
   948                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; }
   977                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; }
   949     private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3,
   978     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
   950                                   Object a4, Object a5, Object a6, Object a7,
   979                                   Object a4, Object a5, Object a6, Object a7,
   951                                   Object a8)
   980                                   Object a8)
   952                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; }
   981                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; }
   953     private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3,
   982     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
   954                                   Object a4, Object a5, Object a6, Object a7,
   983                                   Object a4, Object a5, Object a6, Object a7,
   955                                   Object a8, Object a9)
   984                                   Object a8, Object a9)
   956                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; }
   985                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; }
   957     private static MethodHandle[] makeFillArrays() {
   986     private static MethodHandle[] makeFillArrays() {
   958         ArrayList<MethodHandle> mhs = new ArrayList<>();
   987         ArrayList<MethodHandle> mhs = new ArrayList<>();
   959         mhs.add(null);  // there is no empty fill; at least a0 is required
   988         mhs.add(null);  // there is no empty fill; at least a0 is required
   960         for (;;) {
   989         for (;;) {
   961             MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Object[].class, Integer.class);
   990             MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class);
   962             if (mh == null)  break;
   991             if (mh == null)  break;
   963             mhs.add(mh);
   992             mhs.add(mh);
   964         }
   993         }
   965         assert(mhs.size() == 11);  // current number of methods
   994         assert(mhs.size() == 11);  // current number of methods
   966         return mhs.toArray(new MethodHandle[0]);
   995         return mhs.toArray(new MethodHandle[0]);
   982     public static MethodHandle varargsArray(int nargs) {
  1011     public static MethodHandle varargsArray(int nargs) {
   983         MethodHandle mh = ARRAYS[nargs];
  1012         MethodHandle mh = ARRAYS[nargs];
   984         if (mh != null)  return mh;
  1013         if (mh != null)  return mh;
   985         mh = findCollector("array", nargs, Object[].class);
  1014         mh = findCollector("array", nargs, Object[].class);
   986         if (mh != null)  return ARRAYS[nargs] = mh;
  1015         if (mh != null)  return ARRAYS[nargs] = mh;
   987         MethodHandle producer = filler(0);  // identity function produces result
  1016         mh = buildVarargsArray(FILL_NEW_ARRAY, ARRAY_IDENTITY, nargs);
   988         return ARRAYS[nargs] = buildVarargsArray(producer, nargs);
  1017         assert(assertCorrectArity(mh, nargs));
   989     }
  1018         return ARRAYS[nargs] = mh;
   990 
  1019     }
   991     private static MethodHandle buildVarargsArray(MethodHandle producer, int nargs) {
  1020 
       
  1021     private static boolean assertCorrectArity(MethodHandle mh, int arity) {
       
  1022         assert(mh.type().parameterCount() == arity) : "arity != "+arity+": "+mh;
       
  1023         return true;
       
  1024     }
       
  1025 
       
  1026     private static MethodHandle buildVarargsArray(MethodHandle newArray, MethodHandle finisher, int nargs) {
   992         // Build up the result mh as a sequence of fills like this:
  1027         // Build up the result mh as a sequence of fills like this:
   993         //   producer(fill(fill(fill(newArray(23),0,x1..x10),10,x11..x20),20,x21..x23))
  1028         //   finisher(fill(fill(newArrayWA(23,x1..x10),10,x11..x20),20,x21..x23))
   994         // The various fill(_,10*I,___*[J]) are reusable.
  1029         // The various fill(_,10*I,___*[J]) are reusable.
   995         MethodHandle filler = filler(nargs);
  1030         int leftLen = Math.min(nargs, LEFT_ARGS);  // absorb some arguments immediately
   996         MethodHandle mh = producer;
  1031         int rightLen = nargs - leftLen;
   997         mh = MethodHandles.dropArguments(mh, 1, filler.type().parameterList());
  1032         MethodHandle leftCollector = newArray.bindTo(nargs);
   998         mh = MethodHandles.foldArguments(mh, filler);
  1033         leftCollector = leftCollector.asCollector(Object[].class, leftLen);
   999         mh = MethodHandles.foldArguments(mh, buildNewArray(nargs));
  1034         MethodHandle mh = finisher;
       
  1035         if (rightLen > 0) {
       
  1036             MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen);
       
  1037             if (mh == ARRAY_IDENTITY)
       
  1038                 mh = rightFiller;
       
  1039             else
       
  1040                 mh = collectArguments(mh, 0, rightFiller);
       
  1041         }
       
  1042         if (mh == ARRAY_IDENTITY)
       
  1043             mh = leftCollector;
       
  1044         else
       
  1045             mh = collectArguments(mh, 0, leftCollector);
  1000         return mh;
  1046         return mh;
  1001     }
  1047     }
  1002 
  1048 
  1003     private static MethodHandle buildNewArray(int nargs) {
  1049     private static final int LEFT_ARGS = (FILL_ARRAYS.length - 1);
  1004         return MethodHandles.insertArguments(NEW_ARRAY, 0, nargs);
  1050     private static final MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY+1];
  1005     }
  1051     /** fill_array_to_right(N).invoke(a, argL..arg[N-1])
  1006 
  1052      *  fills a[L]..a[N-1] with corresponding arguments,
  1007     private static final MethodHandle[] FILLERS = new MethodHandle[MAX_ARITY+1];
  1053      *  and then returns a.  The value L is a global constant (LEFT_ARGS).
  1008     // filler(N).invoke(a, arg0..arg[N-1]) fills a[0]..a[N-1]
  1054      */
  1009     private static MethodHandle filler(int nargs) {
  1055     private static MethodHandle fillToRight(int nargs) {
  1010         MethodHandle filler = FILLERS[nargs];
  1056         MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs];
  1011         if (filler != null)  return filler;
  1057         if (filler != null)  return filler;
  1012         return FILLERS[nargs] = buildFiller(nargs);
  1058         filler = buildFiller(nargs);
       
  1059         assert(assertCorrectArity(filler, nargs - LEFT_ARGS + 1));
       
  1060         return FILL_ARRAY_TO_RIGHT[nargs] = filler;
  1013     }
  1061     }
  1014     private static MethodHandle buildFiller(int nargs) {
  1062     private static MethodHandle buildFiller(int nargs) {
  1015         if (nargs == 0)
  1063         if (nargs <= LEFT_ARGS)
  1016             return MethodHandles.identity(Object[].class);
  1064             return ARRAY_IDENTITY;  // no args to fill; return the array unchanged
  1017         final int CHUNK = (FILL_ARRAYS.length - 1);
  1065         // we need room for both mh and a in mh.invoke(a, arg*[nargs])
       
  1066         final int CHUNK = LEFT_ARGS;
  1018         int rightLen = nargs % CHUNK;
  1067         int rightLen = nargs % CHUNK;
  1019         int leftLen = nargs - rightLen;
  1068         int midLen = nargs - rightLen;
  1020         if (rightLen == 0) {
  1069         if (rightLen == 0) {
  1021             leftLen = nargs - (rightLen = CHUNK);
  1070             midLen = nargs - (rightLen = CHUNK);
  1022             if (FILLERS[leftLen] == null) {
  1071             if (FILL_ARRAY_TO_RIGHT[midLen] == null) {
  1023                 // build some precursors from left to right
  1072                 // build some precursors from left to right
  1024                 for (int j = 0; j < leftLen; j += CHUNK)  filler(j);
  1073                 for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK)
       
  1074                     if (j > LEFT_ARGS)  fillToRight(j);
  1025             }
  1075             }
  1026         }
  1076         }
  1027         MethodHandle leftFill = filler(leftLen);  // recursive fill
  1077         if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS);
  1028         MethodHandle rightFill = FILL_ARRAYS[rightLen];
  1078         assert(rightLen > 0);
  1029         rightFill = MethodHandles.insertArguments(rightFill, 1, leftLen);  // [leftLen..nargs-1]
  1079         MethodHandle midFill = fillToRight(midLen);  // recursive fill
  1030 
  1080         MethodHandle rightFill = FILL_ARRAYS[rightLen].bindTo(midLen);  // [midLen..nargs-1]
  1031         // Combine the two fills: right(left(newArray(nargs), x1..x20), x21..x23)
  1081         assert(midFill.type().parameterCount()   == 1 + midLen - LEFT_ARGS);
  1032         MethodHandle mh = filler(0);  // identity function produces result
  1082         assert(rightFill.type().parameterCount() == 1 + rightLen);
  1033         mh = MethodHandles.dropArguments(mh, 1, rightFill.type().parameterList());
  1083 
  1034         mh = MethodHandles.foldArguments(mh, rightFill);
  1084         // Combine the two fills:
  1035         if (leftLen > 0) {
  1085         //   right(mid(a, x10..x19), x20..x23)
  1036             mh = MethodHandles.dropArguments(mh, 1, leftFill.type().parameterList());
  1086         // The final product will look like this:
  1037             mh = MethodHandles.foldArguments(mh, leftFill);
  1087         //   right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23)
  1038         }
  1088         if (midLen == LEFT_ARGS)
  1039         return mh;
  1089             return rightFill;
       
  1090         else
       
  1091             return collectArguments(rightFill, 0, midFill);
  1040     }
  1092     }
  1041 
  1093 
  1042     // Type-polymorphic version of varargs maker.
  1094     // Type-polymorphic version of varargs maker.
  1043     private static final ClassValue<MethodHandle[]> TYPED_COLLECTORS
  1095     private static final ClassValue<MethodHandle[]> TYPED_COLLECTORS
  1044         = new ClassValue<MethodHandle[]>() {
  1096         = new ClassValue<MethodHandle[]>() {
       
  1097             @Override
  1045             protected MethodHandle[] computeValue(Class<?> type) {
  1098             protected MethodHandle[] computeValue(Class<?> type) {
  1046                 return new MethodHandle[256];
  1099                 return new MethodHandle[256];
  1047             }
  1100             }
  1048     };
  1101     };
       
  1102 
       
  1103     static final int MAX_JVM_ARITY = 255;  // limit imposed by the JVM
  1049 
  1104 
  1050     /** Return a method handle that takes the indicated number of
  1105     /** Return a method handle that takes the indicated number of
  1051      *  typed arguments and returns an array of them.
  1106      *  typed arguments and returns an array of them.
  1052      *  The type argument is the array type.
  1107      *  The type argument is the array type.
  1053      */
  1108      */
  1054     public static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
  1109     public static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
  1055         Class<?> elemType = arrayType.getComponentType();
  1110         Class<?> elemType = arrayType.getComponentType();
  1056         if (elemType == null)  throw new IllegalArgumentException("not an array: "+arrayType);
  1111         if (elemType == null)  throw new IllegalArgumentException("not an array: "+arrayType);
  1057         // FIXME: Need more special casing and caching here.
  1112         // FIXME: Need more special casing and caching here.
       
  1113         if (nargs >= MAX_JVM_ARITY/2 - 1) {
       
  1114             int slots = nargs;
       
  1115             final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1;  // 1 for receiver MH
       
  1116             if (arrayType == double[].class || arrayType == long[].class)
       
  1117                 slots *= 2;
       
  1118             if (slots > MAX_ARRAY_SLOTS)
       
  1119                 throw new IllegalArgumentException("too many arguments: "+arrayType.getSimpleName()+", length "+nargs);
       
  1120         }
  1058         if (elemType == Object.class)
  1121         if (elemType == Object.class)
  1059             return varargsArray(nargs);
  1122             return varargsArray(nargs);
  1060         // other cases:  primitive arrays, subtypes of Object[]
  1123         // other cases:  primitive arrays, subtypes of Object[]
  1061         MethodHandle cache[] = TYPED_COLLECTORS.get(elemType);
  1124         MethodHandle cache[] = TYPED_COLLECTORS.get(elemType);
  1062         MethodHandle mh = nargs < cache.length ? cache[nargs] : null;
  1125         MethodHandle mh = nargs < cache.length ? cache[nargs] : null;
  1063         if (mh != null)  return mh;
  1126         if (mh != null)  return mh;
  1064         MethodHandle producer = buildArrayProducer(arrayType);
  1127         if (elemType.isPrimitive()) {
  1065         mh = buildVarargsArray(producer, nargs);
  1128             MethodHandle builder = FILL_NEW_ARRAY;
       
  1129             MethodHandle producer = buildArrayProducer(arrayType);
       
  1130             mh = buildVarargsArray(builder, producer, nargs);
       
  1131         } else {
       
  1132             @SuppressWarnings("unchecked")
       
  1133             Class<? extends Object[]> objArrayType = (Class<? extends Object[]>) arrayType;
       
  1134             Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType);
       
  1135             MethodHandle builder = FILL_NEW_TYPED_ARRAY.bindTo(example);
       
  1136             MethodHandle producer = ARRAY_IDENTITY;
       
  1137             mh = buildVarargsArray(builder, producer, nargs);
       
  1138         }
  1066         mh = mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)));
  1139         mh = mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)));
  1067         cache[nargs] = mh;
  1140         assert(assertCorrectArity(mh, nargs));
       
  1141         if (nargs < cache.length)
       
  1142             cache[nargs] = mh;
  1068         return mh;
  1143         return mh;
  1069     }
  1144     }
  1070 
  1145 
  1071     private static MethodHandle buildArrayProducer(Class<?> arrayType) {
  1146     private static MethodHandle buildArrayProducer(Class<?> arrayType) {
  1072         Class<?> elemType = arrayType.getComponentType();
  1147         Class<?> elemType = arrayType.getComponentType();