private static MethodHandle buildFiller(int nargs) { if (nargs <= LEFT_ARGS) return ARRAY_IDENTITY; // no args to fill; return the array unchanged // we need room for both mh and a in mh.invoke(a, arg*[nargs]) final int CHUNK = LEFT_ARGS; int rightLen = nargs % CHUNK; int midLen = nargs - rightLen; if (rightLen == 0) { midLen = nargs - (rightLen = CHUNK); if (FILL_ARRAY_TO_RIGHT[midLen] == null) { // build some precursors from left to right for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK) if (j > LEFT_ARGS) fillToRight(j); } } if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS); assert (rightLen > 0); MethodHandle midFill = fillToRight(midLen); // recursive fill MethodHandle rightFill = FILL_ARRAYS[rightLen].bindTo(midLen); // [midLen..nargs-1] assert (midFill.type().parameterCount() == 1 + midLen - LEFT_ARGS); assert (rightFill.type().parameterCount() == 1 + rightLen); // Combine the two fills: // right(mid(a, x10..x19), x20..x23) // The final product will look like this: // right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23) if (midLen == LEFT_ARGS) return rightFill; else return MethodHandles.collectArguments(rightFill, 0, midFill); }
public static MethodHandle convertPrimitive(Wrapper wsrc, Wrapper wdst) { EnumMap<Wrapper, MethodHandle> cache = CONVERT_PRIMITIVE_FUNCTIONS[wsrc.ordinal()]; MethodHandle mh = cache.get(wdst); if (mh != null) { return mh; } // slow path Class<?> src = wsrc.primitiveType(); Class<?> dst = wdst.primitiveType(); MethodType type = src == void.class ? MethodType.methodType(dst) : MethodType.methodType(dst, src); if (wsrc == wdst) { mh = identity(src); } else if (wsrc == Wrapper.VOID) { mh = zeroConstantFunction(wdst); } else if (wdst == Wrapper.VOID) { mh = MethodHandles.dropArguments(EMPTY, 0, src); // Defer back to MethodHandles. } else if (wsrc == Wrapper.OBJECT) { mh = unboxCast(dst); } else if (wdst == Wrapper.OBJECT) { mh = box(src); } else { assert (src.isPrimitive() && dst.isPrimitive()); try { mh = IMPL_LOOKUP.findStatic( THIS_CLASS, src.getSimpleName() + "To" + capitalize(dst.getSimpleName()), type); } catch (ReflectiveOperationException ex) { mh = null; } } if (mh != null) { assert (mh.type() == type) : mh; cache.put(wdst, mh); return mh; } throw new IllegalArgumentException( "cannot find primitive conversion function for " + src.getSimpleName() + " -> " + dst.getSimpleName()); }
private static boolean assertCorrectArity(MethodHandle mh, int arity) { assert (mh.type().parameterCount() == arity) : "arity != " + arity + ": " + mh; return true; }