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

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

Print this page
rev 10271 : 8037209: Improvements and cleanups to bytecode assembly for lambda forms
Reviewed-by: vlivanov, psandoz
Contributed-by: john.r.rose@oracle.com
rev 10272 : 8038261: JSR292: cache and reuse typed array accessors
Reviewed-by: vlivanov, psandoz
Contributed-by: john.r.rose@oracle.com
rev 10273 : 8049555: Move varargsArray from sun.invoke.util package to java.lang.invoke
Reviewed-by: ?
rev 10274 : 8050052: Small cleanups in java.lang.invoke code
Reviewed-by: ?


 517             if (len == n)  return;
 518         }
 519         // fall through to error:
 520         throw newIllegalArgumentException("array is not of length "+n);
 521     }
 522 
 523     /**
 524      * Pre-initialized NamedFunctions for bootstrapping purposes.
 525      * Factored in an inner class to delay initialization until first usage.
 526      */
 527     private static class Lazy {
 528         private static final Class<?> MHI = MethodHandleImpl.class;
 529 
 530         static final NamedFunction NF_checkSpreadArgument;
 531         static final NamedFunction NF_guardWithCatch;
 532         static final NamedFunction NF_selectAlternative;
 533         static final NamedFunction NF_throwException;
 534 
 535         static final MethodHandle MH_castReference;
 536         static final MethodHandle MH_copyAsPrimitiveArray;
 537         static final MethodHandle MH_copyAsReferenceArray;
 538         static final MethodHandle MH_fillNewTypedArray;
 539         static final MethodHandle MH_fillNewArray;
 540         static final MethodHandle MH_arrayIdentity;
 541 
 542         static {
 543             try {
 544                 NF_checkSpreadArgument = new NamedFunction(MHI.getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
 545                 NF_guardWithCatch      = new NamedFunction(MHI.getDeclaredMethod("guardWithCatch", MethodHandle.class, Class.class,
 546                                                                                  MethodHandle.class, Object[].class));
 547                 NF_selectAlternative   = new NamedFunction(MHI.getDeclaredMethod("selectAlternative", boolean.class, MethodHandle.class,
 548                                                                                  MethodHandle.class));
 549                 NF_throwException      = new NamedFunction(MHI.getDeclaredMethod("throwException", Throwable.class));
 550 
 551                 NF_checkSpreadArgument.resolve();
 552                 NF_guardWithCatch.resolve();
 553                 NF_selectAlternative.resolve();
 554                 NF_throwException.resolve();
 555 
 556                 MH_castReference        = IMPL_LOOKUP.findStatic(MHI, "castReference",
 557                                             MethodType.methodType(Object.class, Class.class, Object.class));
 558                 MH_copyAsPrimitiveArray = IMPL_LOOKUP.findStatic(MHI, "copyAsPrimitiveArray",
 559                                             MethodType.methodType(Object.class, Wrapper.class, Object[].class));
 560                 MH_copyAsReferenceArray = IMPL_LOOKUP.findStatic(MHI, "copyAsReferenceArray",
 561                                             MethodType.methodType(Object[].class, Class.class, Object[].class));
 562                 MH_arrayIdentity        = IMPL_LOOKUP.findStatic(MHI, "identity",
 563                                             MethodType.methodType(Object[].class, Object[].class));
 564                 MH_fillNewArray         = IMPL_LOOKUP.findStatic(MHI, "fillNewArray",
 565                                             MethodType.methodType(Object[].class, Integer.class, Object[].class));
 566                 MH_fillNewTypedArray    = IMPL_LOOKUP.findStatic(MHI, "fillNewTypedArray",
 567                                             MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class));
 568             } catch (ReflectiveOperationException ex) {
 569                 throw newInternalError(ex);
 570             }
 571         }
 572     }
 573 
 574     /** Factory method:  Collect or filter selected argument(s). */
 575     static MethodHandle makeCollectArguments(MethodHandle target,
 576                 MethodHandle collector, int collectArgPos, boolean retainOriginalArgs) {
 577         MethodType targetType = target.type();          // (a..., c, [b...])=>r
 578         MethodType collectorType = collector.type();    // (b...)=>c
 579         int collectArgCount = collectorType.parameterCount();
 580         Class<?> collectValType = collectorType.returnType();
 581         int collectValCount = (collectValType == void.class ? 0 : 1);


 741                                     MethodHandle catcher) {
 742         MethodType type = target.type();
 743         LambdaForm form = makeGuardWithCatchForm(type.basicType());
 744 
 745         // Prepare auxiliary method handles used during LambdaForm interpreation.
 746         // Box arguments and wrap them into Object[]: ValueConversions.array().
 747         MethodType varargsType = type.changeReturnType(Object[].class);
 748         MethodHandle collectArgs = varargsArray(type.parameterCount()).asType(varargsType);
 749         // Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore().
 750         MethodHandle unboxResult;
 751         if (type.returnType().isPrimitive()) {
 752             unboxResult = ValueConversions.unbox(type.returnType());
 753         } else {
 754             unboxResult = ValueConversions.identity();
 755         }
 756 
 757         BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
 758         BoundMethodHandle mh;
 759         try {
 760             mh = (BoundMethodHandle)
 761                     data.constructor[0].invokeBasic(type, form, (Object) target, (Object) exType, (Object) catcher,
 762                                                     (Object) collectArgs, (Object) unboxResult);
 763         } catch (Throwable ex) {
 764             throw uncaughtException(ex);
 765         }
 766         assert(mh.type() == type);
 767         return mh;
 768     }
 769 
 770     /**
 771      * Intrinsified during LambdaForm compilation
 772      * (see {@link InvokerBytecodeGenerator#emitGuardWithCatch emitGuardWithCatch}).
 773      */
 774     @LambdaForm.Hidden
 775     static Object guardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher,
 776                                  Object... av) throws Throwable {
 777         // Use asFixedArity() to avoid unnecessary boxing of last argument for VarargsCollector case.
 778         try {
 779             return target.asFixedArity().invokeWithArguments(av);
 780         } catch (Throwable t) {
 781             if (!exType.isInstance(t)) throw t;


1078         ArrayList<MethodHandle> mhs = new ArrayList<>();
1079         for (;;) {
1080             MethodHandle mh = findCollector("array", mhs.size(), Object[].class);
1081             if (mh == null)  break;
1082             mhs.add(mh);
1083         }
1084         assert(mhs.size() == 11);  // current number of methods
1085         return mhs.toArray(new MethodHandle[MAX_ARITY+1]);
1086     }
1087     private static final MethodHandle[] ARRAYS = makeArrays();
1088 
1089     // filling versions of the above:
1090     // using Integer len instead of int len and no varargs to avoid bootstrapping problems
1091     private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) {
1092         Object[] a = new Object[len];
1093         fillWithArguments(a, 0, args);
1094         return a;
1095     }
1096     private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) {
1097         Object[] a = Arrays.copyOf(example, len);

1098         fillWithArguments(a, 0, args);
1099         return a;
1100     }
1101     private static void fillWithArguments(Object[] a, int pos, Object... args) {
1102         System.arraycopy(args, 0, a, pos, args.length);
1103     }
1104     // using Integer pos instead of int pos to avoid bootstrapping problems
1105     private static Object[] fillArray(Integer pos, Object[] a, Object a0)
1106                 { fillWithArguments(a, pos, a0); return a; }
1107     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1)
1108                 { fillWithArguments(a, pos, a0, a1); return a; }
1109     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2)
1110                 { fillWithArguments(a, pos, a0, a1, a2); return a; }
1111     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3)
1112                 { fillWithArguments(a, pos, a0, a1, a2, a3); return a; }
1113     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1114                                   Object a4)
1115                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; }
1116     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1117                                   Object a4, Object a5)


1126                                   Object a4, Object a5, Object a6, Object a7,
1127                                   Object a8)
1128                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; }
1129     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1130                                   Object a4, Object a5, Object a6, Object a7,
1131                                   Object a8, Object a9)
1132                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; }
1133     private static MethodHandle[] makeFillArrays() {
1134         ArrayList<MethodHandle> mhs = new ArrayList<>();
1135         mhs.add(null);  // there is no empty fill; at least a0 is required
1136         for (;;) {
1137             MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class);
1138             if (mh == null)  break;
1139             mhs.add(mh);
1140         }
1141         assert(mhs.size() == 11);  // current number of methods
1142         return mhs.toArray(new MethodHandle[0]);
1143     }
1144     private static final MethodHandle[] FILL_ARRAYS = makeFillArrays();
1145 
1146     private static Object[] copyAsReferenceArray(Class<? extends Object[]> arrayType, Object... a) {
1147         return Arrays.copyOf(a, a.length, arrayType);
1148     }
1149     private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) {
1150         Object a = w.makeArray(boxes.length);
1151         w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length);
1152         return a;
1153     }
1154 
1155     /** Return a method handle that takes the indicated number of Object
1156      *  arguments and returns an Object array of them, as if for varargs.
1157      */
1158     static MethodHandle varargsArray(int nargs) {
1159         MethodHandle mh = ARRAYS[nargs];
1160         if (mh != null)  return mh;
1161         mh = findCollector("array", nargs, Object[].class);
1162         if (mh != null)  return ARRAYS[nargs] = mh;
1163         mh = buildVarargsArray(Lazy.MH_fillNewArray, Lazy.MH_arrayIdentity, nargs);
1164         assert(assertCorrectArity(mh, nargs));
1165         return ARRAYS[nargs] = mh;
1166     }
1167 
1168     private static boolean assertCorrectArity(MethodHandle mh, int arity) {


1248         = new ClassValue<MethodHandle[]>() {
1249             @Override
1250             protected MethodHandle[] computeValue(Class<?> type) {
1251                 return new MethodHandle[256];
1252             }
1253     };
1254 
1255     static final int MAX_JVM_ARITY = 255;  // limit imposed by the JVM
1256 
1257     /** Return a method handle that takes the indicated number of
1258      *  typed arguments and returns an array of them.
1259      *  The type argument is the array type.
1260      */
1261     static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
1262         Class<?> elemType = arrayType.getComponentType();
1263         if (elemType == null)  throw new IllegalArgumentException("not an array: "+arrayType);
1264         // FIXME: Need more special casing and caching here.
1265         if (nargs >= MAX_JVM_ARITY/2 - 1) {
1266             int slots = nargs;
1267             final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1;  // 1 for receiver MH
1268             if (arrayType == double[].class || arrayType == long[].class)
1269                 slots *= 2;
1270             if (slots > MAX_ARRAY_SLOTS)
1271                 throw new IllegalArgumentException("too many arguments: "+arrayType.getSimpleName()+", length "+nargs);
1272         }
1273         if (elemType == Object.class)
1274             return varargsArray(nargs);
1275         // other cases:  primitive arrays, subtypes of Object[]
1276         MethodHandle cache[] = TYPED_COLLECTORS.get(elemType);
1277         MethodHandle mh = nargs < cache.length ? cache[nargs] : null;
1278         if (mh != null)  return mh;
1279         if (elemType.isPrimitive()) {



1280             MethodHandle builder = Lazy.MH_fillNewArray;
1281             MethodHandle producer = buildArrayProducer(arrayType);
1282             mh = buildVarargsArray(builder, producer, nargs);
1283         } else {
1284             @SuppressWarnings("unchecked")
1285             Class<? extends Object[]> objArrayType = (Class<? extends Object[]>) arrayType;
1286             Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType);
1287             MethodHandle builder = Lazy.MH_fillNewTypedArray.bindTo(example);
1288             MethodHandle producer = Lazy.MH_arrayIdentity;
1289             mh = buildVarargsArray(builder, producer, nargs);
1290         }
1291         mh = mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)));
1292         assert(assertCorrectArity(mh, nargs));
1293         if (nargs < cache.length)
1294             cache[nargs] = mh;
1295         return mh;
1296     }
1297 
1298     private static MethodHandle buildArrayProducer(Class<?> arrayType) {
1299         Class<?> elemType = arrayType.getComponentType();
1300         if (elemType.isPrimitive())
1301             return Lazy.MH_copyAsPrimitiveArray.bindTo(Wrapper.forPrimitiveType(elemType));
1302         else
1303             return Lazy.MH_copyAsReferenceArray.bindTo(arrayType);
1304     }
1305 }


 517             if (len == n)  return;
 518         }
 519         // fall through to error:
 520         throw newIllegalArgumentException("array is not of length "+n);
 521     }
 522 
 523     /**
 524      * Pre-initialized NamedFunctions for bootstrapping purposes.
 525      * Factored in an inner class to delay initialization until first usage.
 526      */
 527     private static class Lazy {
 528         private static final Class<?> MHI = MethodHandleImpl.class;
 529 
 530         static final NamedFunction NF_checkSpreadArgument;
 531         static final NamedFunction NF_guardWithCatch;
 532         static final NamedFunction NF_selectAlternative;
 533         static final NamedFunction NF_throwException;
 534 
 535         static final MethodHandle MH_castReference;
 536         static final MethodHandle MH_copyAsPrimitiveArray;

 537         static final MethodHandle MH_fillNewTypedArray;
 538         static final MethodHandle MH_fillNewArray;
 539         static final MethodHandle MH_arrayIdentity;
 540 
 541         static {
 542             try {
 543                 NF_checkSpreadArgument = new NamedFunction(MHI.getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
 544                 NF_guardWithCatch      = new NamedFunction(MHI.getDeclaredMethod("guardWithCatch", MethodHandle.class, Class.class,
 545                                                                                  MethodHandle.class, Object[].class));
 546                 NF_selectAlternative   = new NamedFunction(MHI.getDeclaredMethod("selectAlternative", boolean.class, MethodHandle.class,
 547                                                                                  MethodHandle.class));
 548                 NF_throwException      = new NamedFunction(MHI.getDeclaredMethod("throwException", Throwable.class));
 549 
 550                 NF_checkSpreadArgument.resolve();
 551                 NF_guardWithCatch.resolve();
 552                 NF_selectAlternative.resolve();
 553                 NF_throwException.resolve();
 554 
 555                 MH_castReference        = IMPL_LOOKUP.findStatic(MHI, "castReference",
 556                                             MethodType.methodType(Object.class, Class.class, Object.class));
 557                 MH_copyAsPrimitiveArray = IMPL_LOOKUP.findStatic(MHI, "copyAsPrimitiveArray",
 558                                             MethodType.methodType(Object.class, Wrapper.class, Object[].class));


 559                 MH_arrayIdentity        = IMPL_LOOKUP.findStatic(MHI, "identity",
 560                                             MethodType.methodType(Object[].class, Object[].class));
 561                 MH_fillNewArray         = IMPL_LOOKUP.findStatic(MHI, "fillNewArray",
 562                                             MethodType.methodType(Object[].class, Integer.class, Object[].class));
 563                 MH_fillNewTypedArray    = IMPL_LOOKUP.findStatic(MHI, "fillNewTypedArray",
 564                                             MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class));
 565             } catch (ReflectiveOperationException ex) {
 566                 throw newInternalError(ex);
 567             }
 568         }
 569     }
 570 
 571     /** Factory method:  Collect or filter selected argument(s). */
 572     static MethodHandle makeCollectArguments(MethodHandle target,
 573                 MethodHandle collector, int collectArgPos, boolean retainOriginalArgs) {
 574         MethodType targetType = target.type();          // (a..., c, [b...])=>r
 575         MethodType collectorType = collector.type();    // (b...)=>c
 576         int collectArgCount = collectorType.parameterCount();
 577         Class<?> collectValType = collectorType.returnType();
 578         int collectValCount = (collectValType == void.class ? 0 : 1);


 738                                     MethodHandle catcher) {
 739         MethodType type = target.type();
 740         LambdaForm form = makeGuardWithCatchForm(type.basicType());
 741 
 742         // Prepare auxiliary method handles used during LambdaForm interpreation.
 743         // Box arguments and wrap them into Object[]: ValueConversions.array().
 744         MethodType varargsType = type.changeReturnType(Object[].class);
 745         MethodHandle collectArgs = varargsArray(type.parameterCount()).asType(varargsType);
 746         // Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore().
 747         MethodHandle unboxResult;
 748         if (type.returnType().isPrimitive()) {
 749             unboxResult = ValueConversions.unbox(type.returnType());
 750         } else {
 751             unboxResult = ValueConversions.identity();
 752         }
 753 
 754         BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
 755         BoundMethodHandle mh;
 756         try {
 757             mh = (BoundMethodHandle)
 758                     data.constructor().invokeBasic(type, form, (Object) target, (Object) exType, (Object) catcher,
 759                                                     (Object) collectArgs, (Object) unboxResult);
 760         } catch (Throwable ex) {
 761             throw uncaughtException(ex);
 762         }
 763         assert(mh.type() == type);
 764         return mh;
 765     }
 766 
 767     /**
 768      * Intrinsified during LambdaForm compilation
 769      * (see {@link InvokerBytecodeGenerator#emitGuardWithCatch emitGuardWithCatch}).
 770      */
 771     @LambdaForm.Hidden
 772     static Object guardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher,
 773                                  Object... av) throws Throwable {
 774         // Use asFixedArity() to avoid unnecessary boxing of last argument for VarargsCollector case.
 775         try {
 776             return target.asFixedArity().invokeWithArguments(av);
 777         } catch (Throwable t) {
 778             if (!exType.isInstance(t)) throw t;


1075         ArrayList<MethodHandle> mhs = new ArrayList<>();
1076         for (;;) {
1077             MethodHandle mh = findCollector("array", mhs.size(), Object[].class);
1078             if (mh == null)  break;
1079             mhs.add(mh);
1080         }
1081         assert(mhs.size() == 11);  // current number of methods
1082         return mhs.toArray(new MethodHandle[MAX_ARITY+1]);
1083     }
1084     private static final MethodHandle[] ARRAYS = makeArrays();
1085 
1086     // filling versions of the above:
1087     // using Integer len instead of int len and no varargs to avoid bootstrapping problems
1088     private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) {
1089         Object[] a = new Object[len];
1090         fillWithArguments(a, 0, args);
1091         return a;
1092     }
1093     private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) {
1094         Object[] a = Arrays.copyOf(example, len);
1095         assert(a.getClass() != Object[].class);
1096         fillWithArguments(a, 0, args);
1097         return a;
1098     }
1099     private static void fillWithArguments(Object[] a, int pos, Object... args) {
1100         System.arraycopy(args, 0, a, pos, args.length);
1101     }
1102     // using Integer pos instead of int pos to avoid bootstrapping problems
1103     private static Object[] fillArray(Integer pos, Object[] a, Object a0)
1104                 { fillWithArguments(a, pos, a0); return a; }
1105     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1)
1106                 { fillWithArguments(a, pos, a0, a1); return a; }
1107     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2)
1108                 { fillWithArguments(a, pos, a0, a1, a2); return a; }
1109     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3)
1110                 { fillWithArguments(a, pos, a0, a1, a2, a3); return a; }
1111     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1112                                   Object a4)
1113                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; }
1114     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1115                                   Object a4, Object a5)


1124                                   Object a4, Object a5, Object a6, Object a7,
1125                                   Object a8)
1126                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; }
1127     private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1128                                   Object a4, Object a5, Object a6, Object a7,
1129                                   Object a8, Object a9)
1130                 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; }
1131     private static MethodHandle[] makeFillArrays() {
1132         ArrayList<MethodHandle> mhs = new ArrayList<>();
1133         mhs.add(null);  // there is no empty fill; at least a0 is required
1134         for (;;) {
1135             MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class);
1136             if (mh == null)  break;
1137             mhs.add(mh);
1138         }
1139         assert(mhs.size() == 11);  // current number of methods
1140         return mhs.toArray(new MethodHandle[0]);
1141     }
1142     private static final MethodHandle[] FILL_ARRAYS = makeFillArrays();
1143 



1144     private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) {
1145         Object a = w.makeArray(boxes.length);
1146         w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length);
1147         return a;
1148     }
1149 
1150     /** Return a method handle that takes the indicated number of Object
1151      *  arguments and returns an Object array of them, as if for varargs.
1152      */
1153     static MethodHandle varargsArray(int nargs) {
1154         MethodHandle mh = ARRAYS[nargs];
1155         if (mh != null)  return mh;
1156         mh = findCollector("array", nargs, Object[].class);
1157         if (mh != null)  return ARRAYS[nargs] = mh;
1158         mh = buildVarargsArray(Lazy.MH_fillNewArray, Lazy.MH_arrayIdentity, nargs);
1159         assert(assertCorrectArity(mh, nargs));
1160         return ARRAYS[nargs] = mh;
1161     }
1162 
1163     private static boolean assertCorrectArity(MethodHandle mh, int arity) {


1243         = new ClassValue<MethodHandle[]>() {
1244             @Override
1245             protected MethodHandle[] computeValue(Class<?> type) {
1246                 return new MethodHandle[256];
1247             }
1248     };
1249 
1250     static final int MAX_JVM_ARITY = 255;  // limit imposed by the JVM
1251 
1252     /** Return a method handle that takes the indicated number of
1253      *  typed arguments and returns an array of them.
1254      *  The type argument is the array type.
1255      */
1256     static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
1257         Class<?> elemType = arrayType.getComponentType();
1258         if (elemType == null)  throw new IllegalArgumentException("not an array: "+arrayType);
1259         // FIXME: Need more special casing and caching here.
1260         if (nargs >= MAX_JVM_ARITY/2 - 1) {
1261             int slots = nargs;
1262             final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1;  // 1 for receiver MH
1263             if (slots <= MAX_ARRAY_SLOTS && elemType.isPrimitive())
1264                 slots *= Wrapper.forPrimitiveType(elemType).stackSlots();
1265             if (slots > MAX_ARRAY_SLOTS)
1266                 throw new IllegalArgumentException("too many arguments: "+arrayType.getSimpleName()+", length "+nargs);
1267         }
1268         if (elemType == Object.class)
1269             return varargsArray(nargs);
1270         // other cases:  primitive arrays, subtypes of Object[]
1271         MethodHandle cache[] = TYPED_COLLECTORS.get(elemType);
1272         MethodHandle mh = nargs < cache.length ? cache[nargs] : null;
1273         if (mh != null)  return mh;
1274         if (nargs == 0) {
1275             Object example = java.lang.reflect.Array.newInstance(arrayType.getComponentType(), 0);
1276             mh = MethodHandles.constant(arrayType, example);
1277         } else if (elemType.isPrimitive()) {
1278             MethodHandle builder = Lazy.MH_fillNewArray;
1279             MethodHandle producer = buildArrayProducer(arrayType);
1280             mh = buildVarargsArray(builder, producer, nargs);
1281         } else {
1282             Class<? extends Object[]> objArrayType = arrayType.asSubclass(Object[].class);

1283             Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType);
1284             MethodHandle builder = Lazy.MH_fillNewTypedArray.bindTo(example);
1285             MethodHandle producer = Lazy.MH_arrayIdentity; // must be weakly typed
1286             mh = buildVarargsArray(builder, producer, nargs);
1287         }
1288         mh = mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)));
1289         assert(assertCorrectArity(mh, nargs));
1290         if (nargs < cache.length)
1291             cache[nargs] = mh;
1292         return mh;
1293     }
1294 
1295     private static MethodHandle buildArrayProducer(Class<?> arrayType) {
1296         Class<?> elemType = arrayType.getComponentType();
1297         assert(elemType.isPrimitive());
1298         return Lazy.MH_copyAsPrimitiveArray.bindTo(Wrapper.forPrimitiveType(elemType));


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