Object a4, Object a5, Object a6, Object a7) { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); } private static Object[] array(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); } private static Object[] array(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } private static MethodHandle[] makeArrays() { ArrayList<MethodHandle> mhs = new ArrayList<>(); for (;;) { MethodHandle mh = findCollector("array", mhs.size(), Object[].class); if (mh == null) break; mhs.add(mh); } assert(mhs.size() == 11); // current number of methods return mhs.toArray(new MethodHandle[MAX_ARITY+1]); } private static final MethodHandle[] ARRAYS = makeArrays(); // mh-fill versions of the above: private static Object[] newArray(int len) { return new Object[len]; } private static void fillWithArguments(Object[] a, int pos, Object... args) { System.arraycopy(args, 0, a, pos, args.length); } // using Integer pos instead of int pos to avoid bootstrapping problems private static Object[] fillArray(Object[] a, Integer pos, Object a0) { fillWithArguments(a, pos, a0); return a; } private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1) { fillWithArguments(a, pos, a0, a1); return a; } private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2) { fillWithArguments(a, pos, a0, a1, a2); return a; } private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3) { fillWithArguments(a, pos, a0, a1, a2, a3); return a; } private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3, Object a4) { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; } private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; } private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; } private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; } private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; } private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; } private static MethodHandle[] makeFillArrays() { ArrayList<MethodHandle> mhs = new ArrayList<>(); mhs.add(null); // there is no empty fill; at least a0 is required for (;;) { MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Object[].class, Integer.class); if (mh == null) break; mhs.add(mh); } assert(mhs.size() == 11); // current number of methods return mhs.toArray(new MethodHandle[0]); } private static final MethodHandle[] FILL_ARRAYS = makeFillArrays(); private static Object[] copyAsReferenceArray(Class<? extends Object[]> arrayType, Object... a) { return Arrays.copyOf(a, a.length, arrayType); } private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) { Object a = w.makeArray(boxes.length); w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length); return a; } /** Return a method handle that takes the indicated number of Object * arguments and returns an Object array of them, as if for varargs. */ public static MethodHandle varargsArray(int nargs) { MethodHandle mh = ARRAYS[nargs]; if (mh != null) return mh; mh = findCollector("array", nargs, Object[].class); if (mh != null) return ARRAYS[nargs] = mh; MethodHandle producer = filler(0); // identity function produces result return ARRAYS[nargs] = buildVarargsArray(producer, nargs); } private static MethodHandle buildVarargsArray(MethodHandle producer, int nargs) { // Build up the result mh as a sequence of fills like this: // producer(fill(fill(fill(newArray(23),0,x1..x10),10,x11..x20),20,x21..x23)) // The various fill(_,10*I,___*[J]) are reusable. MethodHandle filler = filler(nargs); MethodHandle mh = producer; mh = MethodHandles.dropArguments(mh, 1, filler.type().parameterList()); mh = MethodHandles.foldArguments(mh, filler); mh = MethodHandles.foldArguments(mh, buildNewArray(nargs)); return mh; } private static MethodHandle buildNewArray(int nargs) { return MethodHandles.insertArguments(NEW_ARRAY, 0, (int) nargs); } private static final MethodHandle[] FILLERS = new MethodHandle[MAX_ARITY+1]; // filler(N).invoke(a, arg0..arg[N-1]) fills a[0]..a[N-1] private static MethodHandle filler(int nargs) { MethodHandle filler = FILLERS[nargs]; if (filler != null) return filler; return FILLERS[nargs] = buildFiller(nargs); } private static MethodHandle buildFiller(int nargs) { if (nargs == 0) return MethodHandles.identity(Object[].class); final int CHUNK = (FILL_ARRAYS.length - 1); int rightLen = nargs % CHUNK; int leftLen = nargs - rightLen; if (rightLen == 0) { leftLen = nargs - (rightLen = CHUNK); if (FILLERS[leftLen] == null) { // build some precursors from left to right for (int j = 0; j < leftLen; j += CHUNK) filler(j); } } MethodHandle leftFill = filler(leftLen); // recursive fill MethodHandle rightFill = FILL_ARRAYS[rightLen]; rightFill = MethodHandles.insertArguments(rightFill, 1, (int) leftLen); // [leftLen..nargs-1] // Combine the two fills: right(left(newArray(nargs), x1..x20), x21..x23) MethodHandle mh = filler(0); // identity function produces result mh = MethodHandles.dropArguments(mh, 1, rightFill.type().parameterList()); mh = MethodHandles.foldArguments(mh, rightFill); if (leftLen > 0) { mh = MethodHandles.dropArguments(mh, 1, leftFill.type().parameterList()); mh = MethodHandles.foldArguments(mh, leftFill); } return mh; } // Type-polymorphic version of varargs maker. private static final ClassValue<MethodHandle[]> TYPED_COLLECTORS = new ClassValue<MethodHandle[]>() { protected MethodHandle[] computeValue(Class<?> type) { return new MethodHandle[256]; } }; /** Return a method handle that takes the indicated number of * typed arguments and returns an array of them. * The type argument is the array type. */ public static MethodHandle varargsArray(Class<?> arrayType, int nargs) { Class<?> elemType = arrayType.getComponentType(); if (elemType == null) throw new IllegalArgumentException("not an array: "+arrayType); // FIXME: Need more special casing and caching here. if (elemType == Object.class) return varargsArray(nargs); // other cases: primitive arrays, subtypes of Object[] MethodHandle cache[] = TYPED_COLLECTORS.get(elemType); MethodHandle mh = nargs < cache.length ? cache[nargs] : null; if (mh != null) return mh; MethodHandle producer = buildArrayProducer(arrayType); mh = buildVarargsArray(producer, nargs); mh = mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType))); cache[nargs] = mh; return mh; } private static MethodHandle buildArrayProducer(Class<?> arrayType) { Class<?> elemType = arrayType.getComponentType(); if (elemType.isPrimitive()) return LazyStatics.COPY_AS_PRIMITIVE_ARRAY.bindTo(Wrapper.forPrimitiveType(elemType)); else return LazyStatics.COPY_AS_REFERENCE_ARRAY.bindTo(arrayType); } // List version of varargs maker. private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY); private static List<Object> makeList(Object... args) { return Arrays.asList(args); } private static List<Object> list() { return NO_ARGS_LIST; } private static List<Object> list(Object a0) { return makeList(a0); } private static List<Object> list(Object a0, Object a1) { return makeList(a0, a1); } private static List<Object> list(Object a0, Object a1, Object a2) { return makeList(a0, a1, a2); } private static List<Object> list(Object a0, Object a1, Object a2, Object a3) { return makeList(a0, a1, a2, a3); } private static List<Object> list(Object a0, Object a1, Object a2, Object a3, Object a4) { return makeList(a0, a1, a2, a3, a4); } private static List<Object> list(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return makeList(a0, a1, a2, a3, a4, a5); } private static List<Object> list(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return makeList(a0, a1, a2, a3, a4, a5, a6); } private static List<Object> list(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return makeList(a0, a1, a2, a3, a4, a5, a6, a7); } private static List<Object> list(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); } private static List<Object> list(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } private static MethodHandle[] makeLists() { ArrayList<MethodHandle> mhs = new ArrayList<>(); for (;;) { MethodHandle mh = findCollector("list", mhs.size(), List.class); if (mh == null) break; mhs.add(mh); } assert(mhs.size() == 11); // current number of methods return mhs.toArray(new MethodHandle[MAX_ARITY+1]); } private static final MethodHandle[] LISTS = makeLists(); /** Return a method handle that takes the indicated number of Object * arguments and returns a List. */ public static MethodHandle varargsList(int nargs) { MethodHandle mh = LISTS[nargs]; if (mh != null) return mh; mh = findCollector("list", nargs, List.class); if (mh != null) return LISTS[nargs] = mh; return LISTS[nargs] = buildVarargsList(nargs); } private static MethodHandle buildVarargsList(int nargs) { return MethodHandles.filterReturnValue(varargsArray(nargs), LazyStatics.MAKE_LIST); }}Lines 1001–1237 of 1237. Previous lines
Object a4, Object a5, Object a6, Object a7) { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); } private static Object[] array(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); } private static Object[] array(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } private static MethodHandle[] makeArrays() { ArrayList<MethodHandle> mhs = new ArrayList<>(); for (;;) { MethodHandle mh = findCollector("array", mhs.size(), Object[].class); if (mh == null) break; mhs.add(mh); } assert(mhs.size() == 11); // current number of methods return mhs.toArray(new MethodHandle[MAX_ARITY+1]); } private static final MethodHandle[] ARRAYS = makeArrays(); // mh-fill versions of the above: private static Object[] newArray(int len) { return new Object[len]; } private static void fillWithArguments(Object[] a, int pos, Object... args) { System.arraycopy(args, 0, a, pos, args.length); } // using Integer pos instead of int pos to avoid bootstrapping problems private static Object[] fillArray(Object[] a, Integer pos, Object a0) { fillWithArguments(a, pos, a0); return a; } private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1) { fillWithArguments(a, pos, a0, a1); return a; } private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2) { fillWithArguments(a, pos, a0, a1, a2); return a; } private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3) { fillWithArguments(a, pos, a0, a1, a2, a3); return a; } private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3, Object a4) { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; } private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; } private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; } private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; } private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; } private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; } private static MethodHandle[] makeFillArrays() { ArrayList<MethodHandle> mhs = new ArrayList<>(); mhs.add(null); // there is no empty fill; at least a0 is required for (;;) { MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Object[].class, Integer.class); if (mh == null) break; mhs.add(mh); } assert(mhs.size() == 11); // current number of methods return mhs.toArray(new MethodHandle[0]); } private static final MethodHandle[] FILL_ARRAYS = makeFillArrays(); private static Object[] copyAsReferenceArray(Class<? extends Object[]> arrayType, Object... a) { return Arrays.copyOf(a, a.length, arrayType); } private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) { Object a = w.makeArray(boxes.length); w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length); return a; } /** Return a method handle that takes the indicated number of Object * arguments and returns an Object array of them, as if for varargs. */ public static MethodHandle varargsArray(int nargs) { MethodHandle mh = ARRAYS[nargs]; if (mh != null) return mh; mh = findCollector("array", nargs, Object[].class); if (mh != null) return ARRAYS[nargs] = mh; MethodHandle producer = filler(0); // identity function produces result return ARRAYS[nargs] = buildVarargsArray(producer, nargs); } private static MethodHandle buildVarargsArray(MethodHandle producer, int nargs) { // Build up the result mh as a sequence of fills like this: // producer(fill(fill(fill(newArray(23),0,x1..x10),10,x11..x20),20,x21..x23)) // The various fill(_,10*I,___*[J]) are reusable. MethodHandle filler = filler(nargs); MethodHandle mh = producer; mh = MethodHandles.dropArguments(mh, 1, filler.type().parameterList()); mh = MethodHandles.foldArguments(mh, filler); mh = MethodHandles.foldArguments(mh, buildNewArray(nargs)); return mh; } private static MethodHandle buildNewArray(int nargs) { return MethodHandles.insertArguments(NEW_ARRAY, 0, (int) nargs); } private static final MethodHandle[] FILLERS = new MethodHandle[MAX_ARITY+1]; // filler(N).invoke(a, arg0..arg[N-1]) fills a[0]..a[N-1] private static MethodHandle filler(int nargs) { MethodHandle filler = FILLERS[nargs]; if (filler != null) return filler; return FILLERS[nargs] = buildFiller(nargs); } private static MethodHandle buildFiller(int nargs) { if (nargs == 0) return MethodHandles.identity(Object[].class); final int CHUNK = (FILL_ARRAYS.length - 1); int rightLen = nargs % CHUNK; int leftLen = nargs - rightLen; if (rightLen == 0) { leftLen = nargs - (rightLen = CHUNK); if (FILLERS[leftLen] == null) { // build some precursors from left to right for (int j = 0; j < leftLen; j += CHUNK) filler(j); } } MethodHandle leftFill = filler(leftLen); // recursive fill MethodHandle rightFill = FILL_ARRAYS[rightLen]; rightFill = MethodHandles.insertArguments(rightFill, 1, (int) leftLen); // [leftLen..nargs-1] // Combine the two fills: right(left(newArray(nargs), x1..x20), x21..x23) MethodHandle mh = filler(0); // identity function produces result mh = MethodHandles.dropArguments(mh, 1, rightFill.type().parameterList()); mh = MethodHandles.foldArguments(mh, rightFill); if (leftLen > 0) { mh = MethodHandles.dropArguments(mh, 1, leftFill.type().parameterList()); mh = MethodHandles.foldArguments(mh, leftFill); } return mh; } // Type-polymorphic version of varargs maker. private static final ClassValue<MethodHandle[]> TYPED_COLLECTORS = new ClassValue<MethodHandle[]>() { protected MethodHandle[] computeValue(Class<?> type) { return new MethodHandle[256]; } }; /** Return a method handle that takes the indicated number of * typed arguments and returns an array of them. * The type argument is the array type. */ public static MethodHandle varargsArray(Class<?> arrayType, int nargs) { Class<?> elemType = arrayType.getComponentType(); if (elemType == null) throw new IllegalArgumentException("not an array: "+arrayType); // FIXME: Need more special casing and caching here. if (elemType == Object.class) return varargsArray(nargs); // other cases: primitive arrays, subtypes of Object[] MethodHandle cache[] = TYPED_COLLECTORS.get(elemType); MethodHandle mh = nargs < cache.length ? cache[nargs] : null; if (mh != null) return mh; MethodHandle producer = buildArrayProducer(arrayType); mh = buildVarargsArray(producer, nargs); mh = mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType))); cache[nargs] = mh; return mh; } private static MethodHandle buildArrayProducer(Class<?> arrayType) { Class<?> elemType = arrayType.getComponentType(); if (elemType.isPrimitive()) return LazyStatics.COPY_AS_PRIMITIVE_ARRAY.bindTo(Wrapper.forPrimitiveType(elemType)); else return LazyStatics.COPY_AS_REFERENCE_ARRAY.bindTo(arrayType); } // List version of varargs maker. private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY); private static List<Object> makeList(Object... args) { return Arrays.asList(args); } private static List<Object> list() { return NO_ARGS_LIST; } private static List<Object> list(Object a0) { return makeList(a0); } private static List<Object> list(Object a0, Object a1) { return makeList(a0, a1); } private static List<Object> list(Object a0, Object a1, Object a2) { return makeList(a0, a1, a2); } private static List<Object> list(Object a0, Object a1, Object a2, Object a3) { return makeList(a0, a1, a2, a3); } private static List<Object> list(Object a0, Object a1, Object a2, Object a3, Object a4) { return makeList(a0, a1, a2, a3, a4); } private static List<Object> list(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return makeList(a0, a1, a2, a3, a4, a5); } private static List<Object> list(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return makeList(a0, a1, a2, a3, a4, a5, a6); } private static List<Object> list(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return makeList(a0, a1, a2, a3, a4, a5, a6, a7); } private static List<Object> list(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); } private static List<Object> list(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } private static MethodHandle[] makeLists() { ArrayList<MethodHandle> mhs = new ArrayList<>(); for (;;) { MethodHandle mh = findCollector("list", mhs.size(), List.class); if (mh == null) break; mhs.add(mh); } assert(mhs.size() == 11); // current number of methods return mhs.toArray(new MethodHandle[MAX_ARITY+1]); } private static final MethodHandle[] LISTS = makeLists(); /** Return a method handle that takes the indicated number of Object * arguments and returns a List. */ public static MethodHandle varargsList(int nargs) { MethodHandle mh = LISTS[nargs]; if (mh != null) return mh; mh = findCollector("list", nargs, List.class); if (mh != null) return LISTS[nargs] = mh; return LISTS[nargs] = buildVarargsList(nargs); } private static MethodHandle buildVarargsList(int nargs) { return MethodHandles.filterReturnValue(varargsArray(nargs), LazyStatics.MAKE_LIST); } }