# HG changeset patch # User jrose # Date 1345236145 25200 # Node ID 28122b96858e585226cd3abf6665240ac9381813 # Parent c7aa5cca1c01689a7b1a92411daf83684af05a33 7191102: nightly failures after JSR 292 lazy method handle update (round 3) Reviewed-by: twisti, kvn diff -r c7aa5cca1c01 -r 28122b96858e jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java --- a/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java Wed Jul 05 18:20:00 2017 +0200 +++ b/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java Fri Aug 17 13:42:25 2012 -0700 @@ -143,6 +143,11 @@ protected abstract SpeciesData speciesData(); @Override + final Object internalProperties() { + return "/BMH="+internalValues(); + } + + @Override final Object internalValues() { Object[] boundValues = new Object[speciesData().fieldCount()]; for (int i = 0; i < boundValues.length; ++i) { diff -r c7aa5cca1c01 -r 28122b96858e jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java --- a/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java Wed Jul 05 18:20:00 2017 +0200 +++ b/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java Fri Aug 17 13:42:25 2012 -0700 @@ -108,8 +108,8 @@ } @Override - String debugString() { - return "DMH["+member.toString()+"]="+super.debugString(); + String internalProperties() { + return "/DMH="+member.toString(); } //// Implementation methods. diff -r c7aa5cca1c01 -r 28122b96858e jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java --- a/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Wed Jul 05 18:20:00 2017 +0200 +++ b/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Fri Aug 17 13:42:25 2012 -0700 @@ -185,12 +185,17 @@ } class CpPatch { - int index; - Object value; - CpPatch(int index, Object value) { + final int index; + final String placeholder; + final Object value; + CpPatch(int index, String placeholder, Object value) { this.index = index; + this.placeholder = placeholder; this.value = value; } + public String toString() { + return "CpPatch/index="+index+",placeholder="+placeholder+",value="+value; + } } Map cpPatches = new HashMap<>(); @@ -205,7 +210,7 @@ } // insert placeholder in CP and remember the patch int index = cw.newConst((Object) cpPlaceholder); // TODO check if aready in the constant pool - cpPatches.put(cpPlaceholder, new CpPatch(index, arg)); + cpPatches.put(cpPlaceholder, new CpPatch(index, cpPlaceholder, arg)); return cpPlaceholder; } @@ -213,7 +218,9 @@ int size = getConstantPoolSize(classFile); Object[] res = new Object[size]; for (CpPatch p : cpPatches.values()) { - res[p.index] = p.value; + if (p.index >= size) + throw new InternalError("in cpool["+size+"]: "+p+"\n"+Arrays.toString(Arrays.copyOf(classFile, 20))); + res[p.index] = p.value; } return res; } diff -r c7aa5cca1c01 -r 28122b96858e jdk/src/share/classes/java/lang/invoke/Invokers.java --- a/jdk/src/share/classes/java/lang/invoke/Invokers.java Wed Jul 05 18:20:00 2017 +0200 +++ b/jdk/src/share/classes/java/lang/invoke/Invokers.java Fri Aug 17 13:42:25 2012 -0700 @@ -74,8 +74,18 @@ MethodHandle invoker = exactInvoker; if (invoker != null) return invoker; MethodType mtype = targetType; - LambdaForm lform = invokeForm(mtype, MethodTypeForm.LF_EX_INVOKER); - invoker = BoundMethodHandle.bindSingle(mtype.invokerType(), lform, mtype); + MethodType invokerType = mtype.invokerType(); + LambdaForm lform; + final int MTYPE_ARG_APPENDED = 1; // argument count for appended mtype value + if (mtype.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY - MTYPE_ARG_APPENDED) { + lform = invokeForm(mtype, false, MethodTypeForm.LF_EX_INVOKER); + invoker = BoundMethodHandle.bindSingle(invokerType, lform, mtype); + } else { + // At maximum arity, we cannot afford an extra mtype argument, + // so build a fully customized (non-cached) invoker form. + lform = invokeForm(mtype, true, MethodTypeForm.LF_EX_INVOKER); + invoker = SimpleMethodHandle.make(invokerType, lform); + } assert(checkInvoker(invoker)); exactInvoker = invoker; return invoker; @@ -85,9 +95,20 @@ MethodHandle invoker = generalInvoker; if (invoker != null) return invoker; MethodType mtype = targetType; - prepareForGenericCall(mtype); - LambdaForm lform = invokeForm(mtype, MethodTypeForm.LF_GEN_INVOKER); - invoker = BoundMethodHandle.bindSingle(mtype.invokerType(), lform, mtype); + MethodType invokerType = mtype.invokerType(); + LambdaForm lform; + final int MTYPE_ARG_APPENDED = 1; // argument count for appended mtype value + assert(GENERIC_INVOKER_SLOP >= MTYPE_ARG_APPENDED); + if (mtype.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY - GENERIC_INVOKER_SLOP) { + prepareForGenericCall(mtype); + lform = invokeForm(mtype, false, MethodTypeForm.LF_GEN_INVOKER); + invoker = BoundMethodHandle.bindSingle(invokerType, lform, mtype); + } else { + // At maximum arity, we cannot afford an extra mtype argument, + // so build a fully customized (non-cached) invoker form. + lform = invokeForm(mtype, true, MethodTypeForm.LF_GEN_INVOKER); + invoker = SimpleMethodHandle.make(invokerType, lform); + } assert(checkInvoker(invoker)); generalInvoker = invoker; return invoker; @@ -102,6 +123,7 @@ } static MemberName invokeBasicMethod(MethodType type) { + type = type.basicType(); String name = "invokeBasic"; try { //Lookup.findVirtual(MethodHandle.class, name, type); @@ -135,9 +157,31 @@ /*non-public*/ MethodHandle spreadInvoker(int leadingArgCount) { MethodHandle vaInvoker = spreadInvokers[leadingArgCount]; if (vaInvoker != null) return vaInvoker; - MethodHandle gInvoker = generalInvoker(); int spreadArgCount = targetType.parameterCount() - leadingArgCount; - vaInvoker = gInvoker.asSpreader(Object[].class, spreadArgCount); + MethodType spreadInvokerType = targetType + .replaceParameterTypes(leadingArgCount, targetType.parameterCount(), Object[].class); + if (targetType.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY) { + // Factor sinvoker.invoke(mh, a) into ginvoker.asSpreader().invoke(mh, a) + // where ginvoker.invoke(mh, a*) => mh.invoke(a*). + MethodHandle genInvoker = generalInvoker(); + vaInvoker = genInvoker.asSpreader(Object[].class, spreadArgCount); + } else { + // Cannot build a general invoker here of type ginvoker.invoke(mh, a*[254]). + // Instead, factor sinvoker.invoke(mh, a) into ainvoker.invoke(filter(mh), a) + // where filter(mh) == mh.asSpreader(Object[], spreadArgCount) + MethodHandle arrayInvoker = MethodHandles.exactInvoker(spreadInvokerType); + MethodHandle makeSpreader; + try { + makeSpreader = IMPL_LOOKUP + .findVirtual(MethodHandle.class, "asSpreader", + MethodType.methodType(MethodHandle.class, Class.class, int.class)); + } catch (ReflectiveOperationException ex) { + throw new InternalError(ex); + } + makeSpreader = MethodHandles.insertArguments(makeSpreader, 1, Object[].class, spreadArgCount); + vaInvoker = MethodHandles.filterArgument(arrayInvoker, 0, makeSpreader); + } + assert(vaInvoker.type().equals(spreadInvokerType.invokerType())); spreadInvokers[leadingArgCount] = vaInvoker; return vaInvoker; } @@ -171,7 +215,7 @@ .findStatic(CallSite.class, "uninitializedCallSite", MethodType.methodType(Empty.class)); } catch (ReflectiveOperationException ex) { - throw new RuntimeException(ex); + throw new InternalError(ex); } } invoker = MethodHandles.explicitCastArguments(invoker, MethodType.methodType(targetType.returnType())); @@ -185,30 +229,39 @@ return "Invokers"+targetType; } - private static MethodType fixMethodType(Class callerClass, Object type) { - if (type instanceof MethodType) - return (MethodType) type; - else - return MethodType.fromMethodDescriptorString((String)type, callerClass.getClassLoader()); - } - - static MemberName exactInvokerMethod(Class callerClass, Object type, Object[] appendixResult) { - MethodType mtype = fixMethodType(callerClass, type); - LambdaForm lform = invokeForm(mtype, MethodTypeForm.LF_EX_LINKER); - appendixResult[0] = mtype; + static MemberName exactInvokerMethod(MethodType mtype, Object[] appendixResult) { + LambdaForm lform; + final int MTYPE_ARG_APPENDED = 1; // argument count for appended mtype value + if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - MTYPE_ARG_APPENDED) { + lform = invokeForm(mtype, false, MethodTypeForm.LF_EX_LINKER); + appendixResult[0] = mtype; + } else { + lform = invokeForm(mtype, true, MethodTypeForm.LF_EX_LINKER); + } return lform.vmentry; } - static MemberName genericInvokerMethod(Class callerClass, Object type, Object[] appendixResult) { - MethodType mtype = fixMethodType(callerClass, type); - LambdaForm lform = invokeForm(mtype, MethodTypeForm.LF_GEN_LINKER); - prepareForGenericCall(mtype); - appendixResult[0] = mtype; + static MemberName genericInvokerMethod(MethodType mtype, Object[] appendixResult) { + LambdaForm lform; + final int MTYPE_ARG_APPENDED = 1; // argument count for appended mtype value + if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - (MTYPE_ARG_APPENDED + GENERIC_INVOKER_SLOP)) { + lform = invokeForm(mtype, false, MethodTypeForm.LF_GEN_LINKER); + appendixResult[0] = mtype; + prepareForGenericCall(mtype); + } else { + lform = invokeForm(mtype, true, MethodTypeForm.LF_GEN_LINKER); + } return lform.vmentry; } - private static LambdaForm invokeForm(MethodType mtype, int which) { - mtype = mtype.basicType(); // normalize Z to I, String to Object, etc. + private static LambdaForm invokeForm(MethodType mtype, boolean customized, int which) { + boolean isCached; + if (!customized) { + mtype = mtype.basicType(); // normalize Z to I, String to Object, etc. + isCached = true; + } else { + isCached = false; // maybe cache if mtype == mtype.basicType() + } boolean isLinker, isGeneric; String debugName; switch (which) { @@ -218,27 +271,32 @@ case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true; debugName = "invoker"; break; default: throw new InternalError(); } - LambdaForm lform = mtype.form().cachedLambdaForm(which); - if (lform != null) return lform; + LambdaForm lform; + if (isCached) { + lform = mtype.form().cachedLambdaForm(which); + if (lform != null) return lform; + } // exactInvokerForm (Object,Object)Object // link with java.lang.invoke.MethodHandle.invokeBasic(MethodHandle,Object,Object)Object/invokeSpecial final int THIS_MH = 0; final int CALL_MH = THIS_MH + (isLinker ? 0 : 1); final int ARG_BASE = CALL_MH + 1; final int OUTARG_LIMIT = ARG_BASE + mtype.parameterCount(); - final int INARG_LIMIT = OUTARG_LIMIT + (isLinker ? 1 : 0); + final int INARG_LIMIT = OUTARG_LIMIT + (isLinker && !customized ? 1 : 0); int nameCursor = OUTARG_LIMIT; - final int MTYPE_ARG = nameCursor++; // might be last in-argument + final int MTYPE_ARG = customized ? -1 : nameCursor++; // might be last in-argument final int CHECK_TYPE = nameCursor++; final int LINKER_CALL = nameCursor++; MethodType invokerFormType = mtype.invokerType(); if (isLinker) { - invokerFormType = invokerFormType.appendParameterTypes(MemberName.class); + if (!customized) + invokerFormType = invokerFormType.appendParameterTypes(MemberName.class); } else { invokerFormType = invokerFormType.invokerType(); } Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType); - assert(names.length == nameCursor); + assert(names.length == nameCursor) + : Arrays.asList(mtype, customized, which, nameCursor, names.length); if (MTYPE_ARG >= INARG_LIMIT) { assert(names[MTYPE_ARG] == null); names[MTYPE_ARG] = BoundMethodHandle.getSpeciesData("L").getterName(names[THIS_MH], 0); @@ -248,31 +306,42 @@ // Make the final call. If isGeneric, then prepend the result of type checking. MethodType outCallType; Object[] outArgs; + Object mtypeArg = (customized ? mtype : names[MTYPE_ARG]); if (!isGeneric) { - names[CHECK_TYPE] = new Name(NF_checkExactType, names[CALL_MH], names[MTYPE_ARG]); + names[CHECK_TYPE] = new Name(NF_checkExactType, names[CALL_MH], mtypeArg); // mh.invokeExact(a*):R => checkExactType(mh, TYPEOF(a*:R)); mh.invokeBasic(a*) outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class); outCallType = mtype; + } else if (customized) { + names[CHECK_TYPE] = new Name(NF_asType, names[CALL_MH], mtypeArg); + // mh.invokeGeneric(a*):R => + // let mt=TYPEOF(a*:R), tmh=asType(mh, mt); + // tmh.invokeBasic(a*) + outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class); + outCallType = mtype; } else { - names[CHECK_TYPE] = new Name(NF_checkGenericType, names[CALL_MH], names[MTYPE_ARG]); + names[CHECK_TYPE] = new Name(NF_checkGenericType, names[CALL_MH], mtypeArg); // mh.invokeGeneric(a*):R => // let mt=TYPEOF(a*:R), gamh=checkGenericType(mh, mt); // gamh.invokeBasic(mt, mh, a*) final int PREPEND_GAMH = 0, PREPEND_MT = 1, PREPEND_COUNT = 2; + assert(GENERIC_INVOKER_SLOP == PREPEND_COUNT); outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT + PREPEND_COUNT, Object[].class); // prepend arguments: System.arraycopy(outArgs, 0, outArgs, PREPEND_COUNT, outArgs.length - PREPEND_COUNT); outArgs[PREPEND_GAMH] = names[CHECK_TYPE]; - outArgs[PREPEND_MT] = names[MTYPE_ARG]; + outArgs[PREPEND_MT] = mtypeArg; outCallType = mtype.insertParameterTypes(0, MethodType.class, MethodHandle.class); } names[LINKER_CALL] = new Name(invokeBasicMethod(outCallType), outArgs); lform = new LambdaForm(debugName, INARG_LIMIT, names); if (isLinker) lform.compileToBytecode(); // JVM needs a real methodOop - lform = mtype.form().setCachedLambdaForm(which, lform); + if (isCached) + lform = mtype.form().setCachedLambdaForm(which, lform); return lform; } + private static final int GENERIC_INVOKER_SLOP = 2; // used elsewhere to avoid arity problems /*non-public*/ static WrongMethodTypeException newWrongMethodTypeException(MethodType actual, MethodType expected) { @@ -370,6 +439,7 @@ // Local constant functions: private static final NamedFunction NF_checkExactType; private static final NamedFunction NF_checkGenericType; + private static final NamedFunction NF_asType; private static final NamedFunction NF_getCallSiteTarget; static { try { @@ -377,6 +447,8 @@ .getDeclaredMethod("checkExactType", Object.class, Object.class)); NF_checkGenericType = new NamedFunction(Invokers.class .getDeclaredMethod("checkGenericType", Object.class, Object.class)); + NF_asType = new NamedFunction(MethodHandle.class + .getDeclaredMethod("asType", MethodType.class)); NF_getCallSiteTarget = new NamedFunction(Invokers.class .getDeclaredMethod("getCallSiteTarget", Object.class)); NF_checkExactType.resolve(); diff -r c7aa5cca1c01 -r 28122b96858e jdk/src/share/classes/java/lang/invoke/LambdaForm.java --- a/jdk/src/share/classes/java/lang/invoke/LambdaForm.java Wed Jul 05 18:20:00 2017 +0200 +++ b/jdk/src/share/classes/java/lang/invoke/LambdaForm.java Fri Aug 17 13:42:25 2012 -0700 @@ -596,14 +596,7 @@ Object interpretWithArguments(Object... argumentValues) throws Throwable { if (TRACE_INTERPRETER) return interpretWithArgumentsTracing(argumentValues); - if (COMPILE_THRESHOLD != 0 && - invocationCounter < COMPILE_THRESHOLD) { - invocationCounter++; // benign race - if (invocationCounter >= COMPILE_THRESHOLD) { - // Replace vmentry with a bytecode version of this LF. - compileToBytecode(); - } - } + checkInvocationCounter(); assert(arityCheck(argumentValues)); Object[] values = Arrays.copyOf(argumentValues, names.length); for (int i = argumentValues.length; i < values.length; i++) { @@ -630,6 +623,16 @@ return name.function.invokeWithArguments(arguments); } + private void checkInvocationCounter() { + if (COMPILE_THRESHOLD != 0 && + invocationCounter < COMPILE_THRESHOLD) { + invocationCounter++; // benign race + if (invocationCounter >= COMPILE_THRESHOLD) { + // Replace vmentry with a bytecode version of this LF. + compileToBytecode(); + } + } + } Object interpretWithArgumentsTracing(Object... argumentValues) throws Throwable { traceInterpreter("[ interpretWithArguments", this, argumentValues); if (invocationCounter < COMPILE_THRESHOLD) { @@ -703,7 +706,7 @@ } public String toString() { - StringBuilder buf = new StringBuilder("Lambda("); + StringBuilder buf = new StringBuilder(debugName+"=Lambda("); for (int i = 0; i < names.length; i++) { if (i == arity) buf.append(")=>{"); Name n = names[i]; diff -r c7aa5cca1c01 -r 28122b96858e jdk/src/share/classes/java/lang/invoke/MethodHandle.java --- a/jdk/src/share/classes/java/lang/invoke/MethodHandle.java Wed Jul 05 18:20:00 2017 +0200 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandle.java Fri Aug 17 13:42:25 2012 -0700 @@ -924,7 +924,7 @@ if (arrayType != type().parameterType(collectArgPos)) target = convertArguments(type().changeParameterType(collectArgPos, arrayType)); MethodHandle collector = ValueConversions.varargsArray(arrayType, arrayLength); - return MethodHandleImpl.makeCollectArguments(target, collector, collectArgPos, false); + return MethodHandles.collectArguments(target, collectArgPos, collector); } // private API: return true if last param exactly matches arrayType @@ -1226,7 +1226,7 @@ return "MethodHandle"+type; } String debugString() { - return standardString()+"="+internalForm()+internalValues(); + return standardString()+"/LF="+internalForm()+internalProperties(); } //// Implementation methods. @@ -1269,6 +1269,12 @@ /*non-public*/ Object internalValues() { + return null; + } + + /*non-public*/ + Object internalProperties() { + // Override to something like "/FOO=bar" return ""; } diff -r c7aa5cca1c01 -r 28122b96858e jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Jul 05 18:20:00 2017 +0200 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java Fri Aug 17 13:42:25 2012 -0700 @@ -59,7 +59,7 @@ Name[] args = Arrays.copyOfRange(names, 1, 1 + srcType.parameterCount()); names[names.length - 1] = new Name(accessor.asType(srcType), (Object[]) args); LambdaForm form = new LambdaForm("getElement", lambdaType.parameterCount(), names); - MethodHandle mh = new SimpleMethodHandle(srcType, form); + MethodHandle mh = SimpleMethodHandle.make(srcType, form); if (ArrayAccessor.needCast(arrayClass)) { mh = mh.bindTo(arrayClass); } @@ -171,38 +171,46 @@ // Calculate extra arguments (temporaries) required in the names array. // FIXME: Use an ArrayList. Some arguments require more than one conversion step. - int extra = 0; - for (int i = 0; i < srcType.parameterCount(); i++) { - Class src = srcType.parameterType(i); - Class dst = dstType.parameterType(i); - if (!VerifyType.isNullConversion(src, dst)) { - extra++; + final int INARG_COUNT = srcType.parameterCount(); + int conversions = 0; + boolean[] needConv = new boolean[1+INARG_COUNT]; + for (int i = 0; i <= INARG_COUNT; i++) { + Class src = (i == INARG_COUNT) ? dstType.returnType() : srcType.parameterType(i); + Class dst = (i == INARG_COUNT) ? srcType.returnType() : dstType.parameterType(i); + if (!VerifyType.isNullConversion(src, dst) || + level <= 1 && dst.isInterface() && !dst.isAssignableFrom(src)) { + needConv[i] = true; + conversions++; } } + boolean retConv = needConv[INARG_COUNT]; - Class needReturn = srcType.returnType(); - Class haveReturn = dstType.returnType(); - boolean retConv = !VerifyType.isNullConversion(haveReturn, needReturn); + final int IN_MH = 0; + final int INARG_BASE = 1; + final int INARG_LIMIT = INARG_BASE + INARG_COUNT; + final int NAME_LIMIT = INARG_LIMIT + conversions + 1; + final int RETURN_CONV = (!retConv ? -1 : NAME_LIMIT - 1); + final int OUT_CALL = (!retConv ? NAME_LIMIT : RETURN_CONV) - 1; // Now build a LambdaForm. - MethodType lambdaType = srcType.invokerType(); - Name[] names = arguments(extra + 1, lambdaType); - int[] indexes = new int[lambdaType.parameterCount()]; + MethodType lambdaType = srcType.basicType().invokerType(); + Name[] names = arguments(NAME_LIMIT - INARG_LIMIT, lambdaType); + + // Collect the arguments to the outgoing call, maybe with conversions: + final int OUTARG_BASE = 0; // target MH is Name.function, name Name.arguments[0] + Object[] outArgs = new Object[OUTARG_BASE + INARG_COUNT]; - MethodType midType = dstType; - for (int i = 0, argIndex = 1, tmpIndex = lambdaType.parameterCount(); i < srcType.parameterCount(); i++, argIndex++) { + int nameCursor = INARG_LIMIT; + for (int i = 0; i < INARG_COUNT; i++) { Class src = srcType.parameterType(i); - Class dst = midType.parameterType(i); + Class dst = dstType.parameterType(i); - if (VerifyType.isNullConversion(src, dst)) { + if (!needConv[i]) { // do nothing: difference is trivial - indexes[i] = argIndex; + outArgs[OUTARG_BASE + i] = names[INARG_BASE + i]; continue; } - // Work the current type backward toward the desired caller type: - midType = midType.changeParameterType(i, src); - // Tricky case analysis follows. MethodHandle fn = null; if (src.isPrimitive()) { @@ -246,33 +254,41 @@ fn = ValueConversions.cast(dst); } } - names[tmpIndex] = new Name(fn, names[argIndex]); - indexes[i] = tmpIndex; - tmpIndex++; + Name conv = new Name(fn, names[INARG_BASE + i]); + assert(names[nameCursor] == null); + names[nameCursor++] = conv; + assert(outArgs[OUTARG_BASE + i] == null); + outArgs[OUTARG_BASE + i] = conv; } - if (retConv) { - MethodHandle adjustReturn; + + // Build argument array for the call. + assert(nameCursor == OUT_CALL); + names[OUT_CALL] = new Name(target, outArgs); + + if (RETURN_CONV < 0) { + assert(OUT_CALL == names.length-1); + } else { + Class needReturn = srcType.returnType(); + Class haveReturn = dstType.returnType(); + MethodHandle fn; + Object[] arg = { names[OUT_CALL] }; if (haveReturn == void.class) { // synthesize a zero value for the given void Object zero = Wrapper.forBasicType(needReturn).zero(); - adjustReturn = MethodHandles.constant(needReturn, zero); + fn = MethodHandles.constant(needReturn, zero); + arg = new Object[0]; // don't pass names[OUT_CALL] to conversion } else { MethodHandle identity = MethodHandles.identity(needReturn); MethodType needConversion = identity.type().changeParameterType(0, haveReturn); - adjustReturn = makePairwiseConvert(identity, needConversion, level); + fn = makePairwiseConvert(identity, needConversion, level); } - target = makeCollectArguments(adjustReturn, target, 0, false); + assert(names[RETURN_CONV] == null); + names[RETURN_CONV] = new Name(fn, arg); + assert(RETURN_CONV == names.length-1); } - // Build argument array for the call. - Name[] targetArgs = new Name[dstType.parameterCount()]; - for (int i = 0; i < dstType.parameterCount(); i++) { - int idx = indexes[i]; - targetArgs[i] = names[idx]; - } - names[names.length - 1] = new Name(target, (Object[]) targetArgs); LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names); - return new SimpleMethodHandle(srcType, form); + return SimpleMethodHandle.make(srcType, form); } static MethodHandle makeReferenceIdentity(Class refType) { @@ -280,7 +296,7 @@ Name[] names = arguments(1, lambdaType); names[names.length - 1] = new Name(ValueConversions.identity(), names[1]); LambdaForm form = new LambdaForm("identity", lambdaType.parameterCount(), names); - return new SimpleMethodHandle(MethodType.methodType(refType, refType), form); + return SimpleMethodHandle.make(MethodType.methodType(refType, refType), form); } static MethodHandle makeVarargsCollector(MethodHandle target, Class arrayType) { @@ -334,8 +350,9 @@ MethodHandle collector; try { collector = asFixedArity().asCollector(arrayType, arrayLength); + assert(collector.type().parameterCount() == newArity) : "newArity="+newArity+" but collector="+collector; } catch (IllegalArgumentException ex) { - throw new WrongMethodTypeException("cannot build collector"); + throw new WrongMethodTypeException("cannot build collector", ex); } cache = collector; return collector.asType(newType); @@ -429,12 +446,18 @@ names[names.length - 1] = new Name(target, (Object[]) targetArgs); LambdaForm form = new LambdaForm("spread", lambdaType.parameterCount(), names); - return new SimpleMethodHandle(srcType, form); + return SimpleMethodHandle.make(srcType, form); } static void checkSpreadArgument(Object av, int n) { + // FIXME: regression test for bug 7141637 erroneously expects an NPE, and other tests may expect IAE + // but the actual exception raised by an arity mismatch should be WMTE + final boolean RAISE_RANDOM_EXCEPTIONS = true; // FIXME: delete in JSR 292 M1 if (av == null) { if (n == 0) return; + int len; + if (RAISE_RANDOM_EXCEPTIONS) + len = ((Object[])av).length; // throw NPE; but delete this after tests are fixed } else if (av instanceof Object[]) { int len = ((Object[])av).length; if (len == n) return; @@ -443,7 +466,9 @@ if (len == n) return; } // fall through to error: - throw newIllegalArgumentException("Array is not of length "+n); + if (RAISE_RANDOM_EXCEPTIONS) + throw newIllegalArgumentException("Array is not of length "+n); + throw new WrongMethodTypeException("Array is not of length "+n); } private static final NamedFunction NF_checkSpreadArgument; @@ -508,7 +533,7 @@ names[targetNamePos] = new Name(target, (Object[]) targetArgs); LambdaForm form = new LambdaForm("collect", lambdaType.parameterCount(), names); - return new SimpleMethodHandle(srcType, form); + return SimpleMethodHandle.make(srcType, form); } static @@ -555,7 +580,7 @@ names[arity + 3] = new Name(new NamedFunction(invokeBasic), targetArgs); LambdaForm form = new LambdaForm("guard", lambdaType.parameterCount(), names); - return new SimpleMethodHandle(target.type(), form); + return SimpleMethodHandle.make(target.type(), form); } private static class GuardWithCatch { diff -r c7aa5cca1c01 -r 28122b96858e jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java Wed Jul 05 18:20:00 2017 +0200 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java Fri Aug 17 13:42:25 2012 -0700 @@ -325,15 +325,28 @@ static MemberName linkMethodImpl(Class callerClass, int refKind, Class defc, String name, Object type, Object[] appendixResult) { - if (defc != MethodHandle.class || refKind != REF_invokeVirtual) - throw new LinkageError("no such method "+defc.getName()+"."+name+type); - switch (name) { - case "invoke": - return Invokers.genericInvokerMethod(callerClass, type, appendixResult); - case "invokeExact": - return Invokers.exactInvokerMethod(callerClass, type, appendixResult); + try { + if (defc == MethodHandle.class && refKind == REF_invokeVirtual) { + switch (name) { + case "invoke": + return Invokers.genericInvokerMethod(fixMethodType(callerClass, type), appendixResult); + case "invokeExact": + return Invokers.exactInvokerMethod(fixMethodType(callerClass, type), appendixResult); + } + } + } catch (Throwable ex) { + if (ex instanceof LinkageError) + throw (LinkageError) ex; + else + throw new LinkageError(ex.getMessage(), ex); } - throw new UnsupportedOperationException("linkMethod "+name); + throw new LinkageError("no such method "+defc.getName()+"."+name+type); + } + private static MethodType fixMethodType(Class callerClass, Object type) { + if (type instanceof MethodType) + return (MethodType) type; + else + return MethodType.fromMethodDescriptorString((String)type, callerClass.getClassLoader()); } // Tracing logic: static MemberName linkMethodTracing(Class callerClass, int refKind, @@ -351,6 +364,7 @@ } } + /** * The JVM is resolving a CONSTANT_MethodHandle CP entry. And it wants our help. * It will make an up-call to this method. (Do not change the name or signature.) diff -r c7aa5cca1c01 -r 28122b96858e jdk/src/share/classes/java/lang/invoke/MethodHandles.java --- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Wed Jul 05 18:20:00 2017 +0200 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Fri Aug 17 13:42:25 2012 -0700 @@ -1876,6 +1876,17 @@ return MethodHandleImpl.makeCollectArguments(target, filter, pos, false); } + // FIXME: Make this public in M1. + /*non-public*/ static + MethodHandle collectArguments(MethodHandle target, int pos, MethodHandle collector) { + MethodType targetType = target.type(); + MethodType filterType = collector.type(); + if (filterType.returnType() != void.class && + filterType.returnType() != targetType.parameterType(pos)) + throw newIllegalArgumentException("target and filter types do not match", targetType, filterType); + return MethodHandleImpl.makeCollectArguments(target, collector, pos, false); + } + /** * Adapts a target method handle by post-processing * its return value (if any) with a filter (another method handle). diff -r c7aa5cca1c01 -r 28122b96858e jdk/src/share/classes/java/lang/invoke/MethodType.java --- a/jdk/src/share/classes/java/lang/invoke/MethodType.java Wed Jul 05 18:20:00 2017 +0200 +++ b/jdk/src/share/classes/java/lang/invoke/MethodType.java Fri Aug 17 13:42:25 2012 -0700 @@ -111,6 +111,36 @@ void setForm(MethodTypeForm f) { form = f; } + /** This number, mandated by the JVM spec as 255, + * is the maximum number of slots + * that any Java method can receive in its argument list. + * It limits both JVM signatures and method type objects. + * The longest possible invocation will look like + * {@code staticMethod(arg1, arg2, ..., arg255)} or + * {@code x.virtualMethod(arg1, arg2, ..., arg254)}. + */ + /*non-public*/ static final int MAX_JVM_ARITY = 255; // this is mandated by the JVM spec. + + /** This number is the maximum arity of a method handle, 254. + * It is derived from the absolute JVM-imposed arity by subtracting one, + * which is the slot occupied by the method handle itself at the + * beginning of the argument list used to invoke the method handle. + * The longest possible invocation will look like + * {@code mh.invoke(arg1, arg2, ..., arg254)}. + */ + // Issue: Should we allow MH.invokeWithArguments to go to the full 255? + /*non-public*/ static final int MAX_MH_ARITY = MAX_JVM_ARITY-1; // deduct one for mh receiver + + /** This number is the maximum arity of a method handle invoker, 253. + * It is derived from the absolute JVM-imposed arity by subtracting two, + * which are the slots occupied by invoke method handle, and the the + * target method handle, which are both at the beginning of the argument + * list used to invoke the target method handle. + * The longest possible invocation will look like + * {@code invokermh.invoke(targetmh, arg1, arg2, ..., arg253)}. + */ + /*non-public*/ static final int MAX_MH_INVOKER_ARITY = MAX_MH_ARITY-1; // deduct one more for invoker + private static void checkRtype(Class rtype) { rtype.equals(rtype); // null check } @@ -131,7 +161,9 @@ return slots; } static void checkSlotCount(int count) { - if ((count & 0xFF) != count) + assert((MAX_JVM_ARITY & (MAX_JVM_ARITY+1)) == 0); + // MAX_JVM_ARITY must be power of 2 minus 1 for following code trick to work: + if ((count & MAX_JVM_ARITY) != count) throw newIllegalArgumentException("bad parameter count "+count); } private static IndexOutOfBoundsException newIndexOutOfBoundsException(Object num) { diff -r c7aa5cca1c01 -r 28122b96858e jdk/src/share/classes/java/lang/invoke/SimpleMethodHandle.java --- a/jdk/src/share/classes/java/lang/invoke/SimpleMethodHandle.java Wed Jul 05 18:20:00 2017 +0200 +++ b/jdk/src/share/classes/java/lang/invoke/SimpleMethodHandle.java Fri Aug 17 13:42:25 2012 -0700 @@ -35,10 +35,14 @@ * @author jrose */ final class SimpleMethodHandle extends MethodHandle { - SimpleMethodHandle(MethodType type, LambdaForm form) { + private SimpleMethodHandle(MethodType type, LambdaForm form) { super(type, form); } + /*non-public*/ static SimpleMethodHandle make(MethodType type, LambdaForm form) { + return new SimpleMethodHandle(type, form); + } + @Override MethodHandle bindArgument(int pos, char basicType, Object value) { MethodType type2 = type().dropParameterTypes(pos, pos+1); diff -r c7aa5cca1c01 -r 28122b96858e jdk/src/share/classes/java/lang/invoke/WrongMethodTypeException.java --- a/jdk/src/share/classes/java/lang/invoke/WrongMethodTypeException.java Wed Jul 05 18:20:00 2017 +0200 +++ b/jdk/src/share/classes/java/lang/invoke/WrongMethodTypeException.java Fri Aug 17 13:42:25 2012 -0700 @@ -59,4 +59,27 @@ public WrongMethodTypeException(String s) { super(s); } + + /** + * Constructs a {@code WrongMethodTypeException} with the specified + * detail message and cause. + * + * @param s the detail message. + * @param cause the cause of the exception, or null. + */ + //FIXME: make this public in MR1 + /*non-public*/ WrongMethodTypeException(String s, Throwable cause) { + super(s, cause); + } + + /** + * Constructs a {@code WrongMethodTypeException} with the specified + * cause. + * + * @param cause the cause of the exception, or null. + */ + //FIXME: make this public in MR1 + /*non-public*/ WrongMethodTypeException(Throwable cause) { + super(cause); + } } diff -r c7aa5cca1c01 -r 28122b96858e jdk/src/share/classes/sun/invoke/util/ValueConversions.java --- a/jdk/src/share/classes/sun/invoke/util/ValueConversions.java Wed Jul 05 18:20:00 2017 +0200 +++ b/jdk/src/share/classes/sun/invoke/util/ValueConversions.java Fri Aug 17 13:42:25 2012 -0700 @@ -44,6 +44,7 @@ static { final Object[] values = { 255 }; AccessController.doPrivileged(new PrivilegedAction() { + @Override public Void run() { values[0] = Integer.getInteger(THIS_CLASS.getName()+".MAX_ARITY", 255); return null; @@ -182,7 +183,7 @@ */ public static Number primitiveConversion(Wrapper wrap, Object x, boolean cast) { // Maybe merge this code with Wrapper.convert/cast. - Number res = null; + Number res; if (x == null) { if (!cast) return null; return ZERO_INT; @@ -322,11 +323,9 @@ static void ignore(Object x) { // no value to return; this is an unbox of null - return; } static void empty() { - return; } static Object zeroObject() { @@ -390,24 +389,6 @@ /// Converting references to references. /** - * Value-killing function. - * @param x an arbitrary reference value - * @return a null - */ - static Object alwaysNull(Object x) { - return null; - } - - /** - * Value-killing function. - * @param x an arbitrary reference value - * @return a zero - */ - static int alwaysZero(Object x) { - return 0; - } - - /** * Identity function. * @param x an arbitrary reference value * @return the same value x @@ -416,6 +397,10 @@ return x; } + static T[] identity(T[] x) { + return x; + } + /** * Identity function on ints. * @param x an arbitrary int value @@ -468,29 +453,33 @@ return t.cast(x); } - private static final MethodHandle IDENTITY, CAST_REFERENCE, ALWAYS_NULL, ALWAYS_ZERO, ZERO_OBJECT, IGNORE, EMPTY, NEW_ARRAY; + private static final MethodHandle IDENTITY, CAST_REFERENCE, ZERO_OBJECT, IGNORE, EMPTY, + ARRAY_IDENTITY, FILL_NEW_TYPED_ARRAY, FILL_NEW_ARRAY; static { try { MethodType idType = MethodType.genericMethodType(1); MethodType castType = idType.insertParameterTypes(0, Class.class); - MethodType alwaysZeroType = idType.changeReturnType(int.class); MethodType ignoreType = idType.changeReturnType(void.class); MethodType zeroObjectType = MethodType.genericMethodType(0); IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", idType); //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType); CAST_REFERENCE = IMPL_LOOKUP.findStatic(THIS_CLASS, "castReference", castType); - ALWAYS_NULL = IMPL_LOOKUP.findStatic(THIS_CLASS, "alwaysNull", idType); - ALWAYS_ZERO = IMPL_LOOKUP.findStatic(THIS_CLASS, "alwaysZero", alwaysZeroType); ZERO_OBJECT = IMPL_LOOKUP.findStatic(THIS_CLASS, "zeroObject", zeroObjectType); IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType); EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1)); - NEW_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "newArray", MethodType.methodType(Object[].class, int.class)); + ARRAY_IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", MethodType.methodType(Object[].class, Object[].class)); + FILL_NEW_ARRAY = IMPL_LOOKUP + .findStatic(THIS_CLASS, "fillNewArray", + MethodType.methodType(Object[].class, Integer.class, Object[].class)); + FILL_NEW_TYPED_ARRAY = IMPL_LOOKUP + .findStatic(THIS_CLASS, "fillNewTypedArray", + MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class)); } catch (NoSuchMethodException | IllegalAccessException ex) { throw new InternalError("uncaught exception", ex); } } - // Varargs methods need to be in a separately initialized class, to bootstrapping problems. + // Varargs methods need to be in a separately initialized class, to avoid bootstrapping problems. static class LazyStatics { private static final MethodHandle COPY_AS_REFERENCE_ARRAY, COPY_AS_PRIMITIVE_ARRAY, MAKE_LIST; static { @@ -505,34 +494,64 @@ } } + static MethodHandle collectArguments(MethodHandle mh, int pos, MethodHandle collector) { + // FIXME: API needs public MHs.collectArguments. + // Should be: + // return MethodHandles.collectArguments(mh, 0, collector); + // The rest of this code is a workaround for not having that API. + if (COLLECT_ARGUMENTS != null) { + try { + return (MethodHandle) + COLLECT_ARGUMENTS.invokeExact(mh, pos, collector); + } catch (Throwable ex) { + if (ex instanceof RuntimeException) + throw (RuntimeException) ex; + if (ex instanceof Error) + throw (Error) ex; + throw new Error(ex.getMessage(), ex); + } + } + // Emulate MHs.collectArguments using fold + drop. + // This is slightly inefficient. + // More seriously, it can put a MH over the 255-argument limit. + mh = MethodHandles.dropArguments(mh, 1, collector.type().parameterList()); + mh = MethodHandles.foldArguments(mh, collector); + return mh; + } + private static final MethodHandle COLLECT_ARGUMENTS; + static { + MethodHandle mh = null; + try { + java.lang.reflect.Method m = MethodHandles.class + .getDeclaredMethod("collectArguments", + MethodHandle.class, int.class, MethodHandle.class); + m.setAccessible(true); + mh = IMPL_LOOKUP.unreflect(m); + + } catch (ReflectiveOperationException | SecurityException ex) { + throw new InternalError(ex); + } + COLLECT_ARGUMENTS = mh; + } + private static final EnumMap[] WRAPPER_CASTS - = newWrapperCaches(2); + = newWrapperCaches(1); /** Return a method that casts its sole argument (an Object) to the given type - * and returns it as the given type (if exact is true), or as plain Object (if erase is true). + * and returns it as the given type. */ public static MethodHandle cast(Class type) { - boolean exact = false; if (type.isPrimitive()) throw new IllegalArgumentException("cannot cast primitive type "+type); - MethodHandle mh = null; + MethodHandle mh; Wrapper wrap = null; EnumMap cache = null; if (Wrapper.isWrapperType(type)) { wrap = Wrapper.forWrapperType(type); - cache = WRAPPER_CASTS[exact?1:0]; + cache = WRAPPER_CASTS[0]; mh = cache.get(wrap); if (mh != null) return mh; } - if (VerifyType.isNullReferenceConversion(Object.class, type)) - mh = IDENTITY; - else if (VerifyType.isNullType(type)) - mh = ALWAYS_NULL; - else - mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type); - if (exact) { - MethodType xmt = MethodType.methodType(type, Object.class); - mh = MethodHandles.explicitCastArguments(mh, xmt); - } + mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type); if (cache != null) cache.put(wrap, mh); return mh; @@ -920,37 +939,47 @@ } private static final MethodHandle[] ARRAYS = makeArrays(); - // mh-fill versions of the above: - private static Object[] newArray(int len) { return new Object[len]; } + // filling versions of the above: + // using Integer len instead of int len and no varargs to avoid bootstrapping problems + private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) { + Object[] a = new Object[len]; + fillWithArguments(a, 0, args); + return a; + } + private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) { + Object[] a = Arrays.copyOf(example, len); + fillWithArguments(a, 0, args); + return a; + } 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) + private static Object[] fillArray(Integer pos, Object[] a, Object a0) { fillWithArguments(a, pos, a0); return a; } - private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1) + private static Object[] fillArray(Integer pos, Object[] a, 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) + private static Object[] fillArray(Integer pos, Object[] a, 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) + private static Object[] fillArray(Integer pos, Object[] a, 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, + private static Object[] fillArray(Integer pos, Object[] a, 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, + private static Object[] fillArray(Integer pos, Object[] a, 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, + private static Object[] fillArray(Integer pos, Object[] a, 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, + private static Object[] fillArray(Integer pos, Object[] a, 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, + private static Object[] fillArray(Integer pos, Object[] a, 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, + private static Object[] fillArray(Integer pos, Object[] a, 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; } @@ -958,7 +987,7 @@ ArrayList 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); + MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class); if (mh == null) break; mhs.add(mh); } @@ -984,69 +1013,95 @@ 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); + mh = buildVarargsArray(FILL_NEW_ARRAY, ARRAY_IDENTITY, nargs); + assert(assertCorrectArity(mh, nargs)); + return ARRAYS[nargs] = mh; + } + + private static boolean assertCorrectArity(MethodHandle mh, int arity) { + assert(mh.type().parameterCount() == arity) : "arity != "+arity+": "+mh; + return true; } - private static MethodHandle buildVarargsArray(MethodHandle producer, int nargs) { + private static MethodHandle buildVarargsArray(MethodHandle newArray, MethodHandle finisher, 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)) + // finisher(fill(fill(newArrayWA(23,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)); + int leftLen = Math.min(nargs, LEFT_ARGS); // absorb some arguments immediately + int rightLen = nargs - leftLen; + MethodHandle leftCollector = newArray.bindTo(nargs); + leftCollector = leftCollector.asCollector(Object[].class, leftLen); + MethodHandle mh = finisher; + if (rightLen > 0) { + MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen); + if (mh == ARRAY_IDENTITY) + mh = rightFiller; + else + mh = collectArguments(mh, 0, rightFiller); + } + if (mh == ARRAY_IDENTITY) + mh = leftCollector; + else + mh = collectArguments(mh, 0, leftCollector); return mh; } - private static MethodHandle buildNewArray(int nargs) { - return MethodHandles.insertArguments(NEW_ARRAY, 0, 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]; + private static final int LEFT_ARGS = (FILL_ARRAYS.length - 1); + private static final MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY+1]; + /** fill_array_to_right(N).invoke(a, argL..arg[N-1]) + * fills a[L]..a[N-1] with corresponding arguments, + * and then returns a. The value L is a global constant (LEFT_ARGS). + */ + private static MethodHandle fillToRight(int nargs) { + MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs]; if (filler != null) return filler; - return FILLERS[nargs] = buildFiller(nargs); + filler = buildFiller(nargs); + assert(assertCorrectArity(filler, nargs - LEFT_ARGS + 1)); + return FILL_ARRAY_TO_RIGHT[nargs] = filler; } private static MethodHandle buildFiller(int nargs) { - if (nargs == 0) - return MethodHandles.identity(Object[].class); - final int CHUNK = (FILL_ARRAYS.length - 1); + 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 leftLen = nargs - rightLen; + int midLen = nargs - rightLen; if (rightLen == 0) { - leftLen = nargs - (rightLen = CHUNK); - if (FILLERS[leftLen] == null) { + midLen = nargs - (rightLen = CHUNK); + if (FILL_ARRAY_TO_RIGHT[midLen] == null) { // build some precursors from left to right - for (int j = 0; j < leftLen; j += CHUNK) filler(j); + for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK) + if (j > LEFT_ARGS) fillToRight(j); } } - MethodHandle leftFill = filler(leftLen); // recursive fill - MethodHandle rightFill = FILL_ARRAYS[rightLen]; - rightFill = MethodHandles.insertArguments(rightFill, 1, leftLen); // [leftLen..nargs-1] + 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(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; + // 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 collectArguments(rightFill, 0, midFill); } // Type-polymorphic version of varargs maker. private static final ClassValue TYPED_COLLECTORS = new ClassValue() { + @Override protected MethodHandle[] computeValue(Class type) { return new MethodHandle[256]; } }; + static final int MAX_JVM_ARITY = 255; // limit imposed by the JVM + /** 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. @@ -1055,16 +1110,36 @@ Class elemType = arrayType.getComponentType(); if (elemType == null) throw new IllegalArgumentException("not an array: "+arrayType); // FIXME: Need more special casing and caching here. + if (nargs >= MAX_JVM_ARITY/2 - 1) { + int slots = nargs; + final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1; // 1 for receiver MH + if (arrayType == double[].class || arrayType == long[].class) + slots *= 2; + if (slots > MAX_ARRAY_SLOTS) + throw new IllegalArgumentException("too many arguments: "+arrayType.getSimpleName()+", length "+nargs); + } 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); + if (elemType.isPrimitive()) { + MethodHandle builder = FILL_NEW_ARRAY; + MethodHandle producer = buildArrayProducer(arrayType); + mh = buildVarargsArray(builder, producer, nargs); + } else { + @SuppressWarnings("unchecked") + Class objArrayType = (Class) arrayType; + Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType); + MethodHandle builder = FILL_NEW_TYPED_ARRAY.bindTo(example); + MethodHandle producer = ARRAY_IDENTITY; + mh = buildVarargsArray(builder, producer, nargs); + } mh = mh.asType(MethodType.methodType(arrayType, Collections.>nCopies(nargs, elemType))); - cache[nargs] = mh; + assert(assertCorrectArity(mh, nargs)); + if (nargs < cache.length) + cache[nargs] = mh; return mh; } diff -r c7aa5cca1c01 -r 28122b96858e jdk/test/java/lang/invoke/BigArityTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/invoke/BigArityTest.java Fri Aug 17 13:42:25 2012 -0700 @@ -0,0 +1,1044 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @summary High arity invocations, up to the maximum of 255 arguments + * @compile BigArityTest.java + * @run junit/othervm -DBigArityTest.ITERATION_COUNT=1 test.java.lang.invoke.BigArityTest + */ + +package test.java.lang.invoke; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.WrongMethodTypeException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Objects; +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +public class BigArityTest { + + static MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); + + static final int MAX_JVM_ARITY = 255; + static final int ITERATION_COUNT = getProperty("ITERATION_COUNT", 40000); + static final int MIN_ARITY = getProperty("MIN_ARITY", 250); + static final int SLOW_ARITY = getProperty("SLOW_ARITY", MAX_JVM_ARITY-3); + static final int MAX_ARITY = getProperty("MAX_ARITY", MAX_JVM_ARITY-1); // always -1 for the MH reciever itself + private static int getProperty(String name, int dflt) { + return Integer.parseInt(getProperty(name, ""+dflt)); + } + private static String getProperty(String name, String dflt) { + String x = System.getProperty(BigArityTest.class.getSimpleName() + "." + name); + if (x == null) x = System.getProperty(BigArityTest.class.getName() + "." + name); + return x == null ? dflt : x; + } + + static Object hashArguments(Object... args) { + return Objects.hash(args); + } + static final MethodHandle MH_hashArguments_VA; + static { + try { + MH_hashArguments_VA = + MethodHandles.lookup().unreflect( + BigArityTest.class.getDeclaredMethod("hashArguments", Object[].class)); + } catch (ReflectiveOperationException ex) { + throw new InternalError(ex); + } + } + static MethodHandle MH_hashArguments(int arity) { + MethodType mt = MethodType.genericMethodType(arity); + return MH_hashArguments_VA.asType(mt); + } + static MethodHandle MH_hashArguments(Class arrayClass, int arity) { + if (arrayClass == Object[].class) + return MH_hashArguments(arity); + ArrayList> ptypes = new ArrayList<>(Collections.>nCopies(arity, arrayClass.getComponentType())); + MethodType mt = MethodType.methodType(Object.class, ptypes); + return MH_hashArguments_VA.asType(mt); + } + + static Object[] testArgs(int arity) { + Object args[] = new Object[arity]; + for (int i = 0; i < arity; i++) + args[i] = i * (i + 1) / 2; + return args; + } + + @Test + public void testBoundaryValues() throws Throwable { + for (int badArity : new int[]{ -1, MAX_JVM_ARITY+1, MAX_JVM_ARITY }) { + try { + MethodHandle badmh = MH_hashArguments(badArity); + throw new AssertionError("should not be able to build a 255-arity MH: "+badmh); + } catch (IllegalArgumentException | WrongMethodTypeException ex) { + System.out.println("OK: "+ex); + } + } + } + + // Make sure the basic argument spreading and varargs mechanisms are working. + // Exercise arity 3 thoroughly. + @Test + public void testSpreads() throws Throwable { + System.out.println("testing asSpreader on arity=3"); + Object[] args = testArgs(3); + int r0 = Objects.hash(args); + MethodHandle mh = MH_hashArguments(3); + Object r; + r = mh.invokeExact(args[0], args[1], args[2]); + assertEquals(r0, r); + r = mh.invoke(args[0], args[1], args[2]); + assertEquals(r0, r); + r = mh.invoke((Comparable) args[0], (Integer) args[1], (Number) args[2]); + assertEquals(r0, r); + r = mh.invokeWithArguments(args); + assertEquals(r0, r); + for (Class cls0 : new Class[] { + Object[].class, Number[].class, Integer[].class, Comparable[].class + }) { + @SuppressWarnings("unchecked") + Class cls = (Class) cls0; + //Class cls = Object[].class.asSubclass(cls0); + int nargs = args.length, skip; + MethodHandle smh = mh.asSpreader(cls, nargs - (skip = 0)); + Object[] tail = Arrays.copyOfRange(args, skip, nargs, cls); + if (cls == Object[].class) + r = smh.invokeExact(tail); + else if (cls == Integer[].class) + r = smh.invokeExact((Integer[]) tail); + else + r = smh.invoke(tail); + assertEquals(r0, r); + smh = mh.asSpreader(cls, nargs - (skip = 1)); + tail = Arrays.copyOfRange(args, skip, nargs, cls); + if (cls == Object[].class) + r = smh.invokeExact(args[0], tail); + else if (cls == Integer[].class) + r = smh.invokeExact(args[0], (Integer[]) tail); + else + r = smh.invoke(args[0], tail); + assertEquals(r0, r); + smh = mh.asSpreader(cls, nargs - (skip = 2)); + tail = Arrays.copyOfRange(args, skip, nargs, cls); + if (cls == Object[].class) + r = smh.invokeExact(args[0], args[1], tail); + else if (cls == Integer[].class) + r = smh.invokeExact(args[0], args[1], (Integer[]) tail); + else + r = smh.invoke(args[0], args[1], tail); + assertEquals(r0, r); + smh = mh.asSpreader(cls, nargs - (skip = 3)); + tail = Arrays.copyOfRange(args, skip, nargs, cls); + if (cls == Object[].class) + r = smh.invokeExact(args[0], args[1], args[2], tail); + else if (cls == Integer[].class) + r = smh.invokeExact(args[0], args[1], args[2], (Integer[]) tail); + else + r = smh.invoke(args[0], args[1], args[2], tail); + assertEquals(r0, r); + // Try null array in addition to zero-length array: + tail = null; + if (cls == Object[].class) + r = smh.invokeExact(args[0], args[1], args[2], tail); + else if (cls == Integer[].class) + r = smh.invokeExact(args[0], args[1], args[2], (Integer[]) tail); + else + r = smh.invoke(args[0], args[1], args[2], tail); + assertEquals(r0, r); + } + } + + @Test + public void testInvokeWithArguments() throws Throwable { + System.out.println("testing invokeWithArguments on all arities"); + for (int arity = 0; arity < MAX_ARITY; arity++) { + Object[] args = testArgs(arity); + Object r0 = Objects.hash(args); + Object r = MH_hashArguments(arity).invokeWithArguments(args); + assertEquals("arity="+arity, r0, r); + } + // The next one is the most likely to fail: + int arity = MAX_ARITY; + Object[] args = testArgs(arity); + Object r0 = Objects.hash(args); + Object r = MH_hashArguments(arity).invokeWithArguments(args); + assertEquals("arity=MAX_ARITY", r0, r); + } + + static Object[] cat(Object a, Object[] b) { + int alen = 1, blen = b.length; + Object[] c = new Object[alen + blen]; + c[0] = a; + System.arraycopy(b, 0, c, alen, blen); + return c; + } + + @Test + public void testArities() throws Throwable { + System.out.println("testing spreaders and collectors on high arities..."); + int iterations = ITERATION_COUNT; + testArities(Object[].class, MIN_ARITY-10, MIN_ARITY-1, iterations / 1000); + testArities(Object[].class, MIN_ARITY, SLOW_ARITY-1, iterations); + testArities(Object[].class, SLOW_ARITY, MAX_ARITY, iterations / 1000); + } + + @Test + public void testAritiesOnTypedArrays() throws Throwable { + for (Class cls0 : new Class[] { + Number[].class, Integer[].class, Comparable[].class + }) { + @SuppressWarnings("unchecked") + Class cls = (Class) cls0; + System.out.println("array class: "+cls.getSimpleName()); + int iterations = ITERATION_COUNT / 1000; + testArities(cls, MIN_ARITY, SLOW_ARITY-1, iterations); + testArities(cls, SLOW_ARITY, MAX_ARITY, iterations / 100); + } + } + + private void testArities(Class cls, + int minArity, + int maxArity, + int iterations) throws Throwable { + boolean verbose = (cls == Object[].class); + for (int arity = minArity; arity <= maxArity; arity++) { + if (verbose) System.out.println("arity="+arity); + MethodHandle mh = MH_hashArguments(cls, arity); + MethodHandle mh_VA = mh.asSpreader(cls, arity); + assert(mh_VA.type().parameterType(0) == cls); + testArities(cls, arity, iterations, verbose, mh, mh_VA); + if (cls != Object[].class) { + // mh_CA will collect arguments of a particular type and pass them to mh_VA + MethodHandle mh_CA = mh_VA.asCollector(cls, arity); + MethodHandle mh_VA2 = mh_CA.asSpreader(cls, arity); + try { + mh_VA2.invokeWithArguments(new Object[arity]); + throw new AssertionError("should not reach"); + } catch (ClassCastException | WrongMethodTypeException ex) { + } + assert(mh_CA.type().equals(mh.type())); + assert(mh_VA2.type().equals(mh_VA.type())); + testArities(cls, arity, iterations, false, mh_CA, mh_VA2); + } + } + } + private void testArities(Class cls, + int arity, + int iterations, + boolean verbose, + MethodHandle mh, + MethodHandle mh_VA + ) throws Throwable { + if (iterations < 4) iterations = 4; + final int MAX_MH_ARITY = MAX_JVM_ARITY - 1; // mh.invoke(arg*[N]) + final int MAX_INVOKER_ARITY = MAX_MH_ARITY - 1; // inv.invoke(mh, arg*[N]) + Object[] args = testArgs(arity); + if (cls != Object[].class) + args = Arrays.copyOf(args, arity, cls); + Object r0 = Objects.hash(args); + Object r; + MethodHandle ximh = null; + MethodHandle gimh = null; + if (arity <= MAX_INVOKER_ARITY) { + ximh = MethodHandles.exactInvoker(mh.type()); + gimh = MethodHandles.invoker(mh.type()); + } else { + try { + ximh = MethodHandles.exactInvoker(mh.type()); + throw new AssertionError("should fail to create ximh of arity "+arity); + } catch (IllegalArgumentException ex) { + if (verbose) + System.out.println("OK: xmih["+arity+"] => "+ex); + } + try { + gimh = MethodHandles.invoker(mh.type()); + throw new AssertionError("should fail to create gimh of arity "+arity); + } catch (IllegalArgumentException ex) { + if (verbose) + System.out.println("OK: gmih["+arity+"] => "+ex); + } + } + Object[] mh_args = cat(mh, args); + assert(arity <= MAX_MH_ARITY); + for (int i = 0; i < iterations; ++i) { + if (cls == Object[].class) + r = mh_VA.invokeExact(args); + else if (cls == Integer[].class) + r = mh_VA.invokeExact((Integer[])args); + else + r = mh_VA.invoke(args); + assertEquals(r0, r); + r = mh.invokeWithArguments(args); + assertEquals(r0, r); + if (ximh != null) { + r = ximh.invokeWithArguments(mh_args); + assertEquals(r0, r); + } + if (gimh != null) { + r = gimh.invokeWithArguments(mh_args); + assertEquals(r0, r); + } + } + } + + static Object hashArguments_252( + // + Object x00, Object x01, Object x02, Object x03, Object x04, Object x05, Object x06, Object x07, + Object x08, Object x09, Object x0A, Object x0B, Object x0C, Object x0D, Object x0E, Object x0F, + Object x10, Object x11, Object x12, Object x13, Object x14, Object x15, Object x16, Object x17, + Object x18, Object x19, Object x1A, Object x1B, Object x1C, Object x1D, Object x1E, Object x1F, + Object x20, Object x21, Object x22, Object x23, Object x24, Object x25, Object x26, Object x27, + Object x28, Object x29, Object x2A, Object x2B, Object x2C, Object x2D, Object x2E, Object x2F, + Object x30, Object x31, Object x32, Object x33, Object x34, Object x35, Object x36, Object x37, + Object x38, Object x39, Object x3A, Object x3B, Object x3C, Object x3D, Object x3E, Object x3F, + Object x40, Object x41, Object x42, Object x43, Object x44, Object x45, Object x46, Object x47, + Object x48, Object x49, Object x4A, Object x4B, Object x4C, Object x4D, Object x4E, Object x4F, + Object x50, Object x51, Object x52, Object x53, Object x54, Object x55, Object x56, Object x57, + Object x58, Object x59, Object x5A, Object x5B, Object x5C, Object x5D, Object x5E, Object x5F, + Object x60, Object x61, Object x62, Object x63, Object x64, Object x65, Object x66, Object x67, + Object x68, Object x69, Object x6A, Object x6B, Object x6C, Object x6D, Object x6E, Object x6F, + Object x70, Object x71, Object x72, Object x73, Object x74, Object x75, Object x76, Object x77, + Object x78, Object x79, Object x7A, Object x7B, Object x7C, Object x7D, Object x7E, Object x7F, + Object x80, Object x81, Object x82, Object x83, Object x84, Object x85, Object x86, Object x87, + Object x88, Object x89, Object x8A, Object x8B, Object x8C, Object x8D, Object x8E, Object x8F, + Object x90, Object x91, Object x92, Object x93, Object x94, Object x95, Object x96, Object x97, + Object x98, Object x99, Object x9A, Object x9B, Object x9C, Object x9D, Object x9E, Object x9F, + Object xA0, Object xA1, Object xA2, Object xA3, Object xA4, Object xA5, Object xA6, Object xA7, + Object xA8, Object xA9, Object xAA, Object xAB, Object xAC, Object xAD, Object xAE, Object xAF, + Object xB0, Object xB1, Object xB2, Object xB3, Object xB4, Object xB5, Object xB6, Object xB7, + Object xB8, Object xB9, Object xBA, Object xBB, Object xBC, Object xBD, Object xBE, Object xBF, + Object xC0, Object xC1, Object xC2, Object xC3, Object xC4, Object xC5, Object xC6, Object xC7, + Object xC8, Object xC9, Object xCA, Object xCB, Object xCC, Object xCD, Object xCE, Object xCF, + Object xD0, Object xD1, Object xD2, Object xD3, Object xD4, Object xD5, Object xD6, Object xD7, + Object xD8, Object xD9, Object xDA, Object xDB, Object xDC, Object xDD, Object xDE, Object xDF, + Object xE0, Object xE1, Object xE2, Object xE3, Object xE4, Object xE5, Object xE6, Object xE7, + Object xE8, Object xE9, Object xEA, Object xEB, Object xEC, Object xED, Object xEE, Object xEF, + Object xF0, Object xF1, Object xF2, Object xF3, Object xF4, Object xF5, Object xF6, Object xF7, + // + Object xF8, Object xF9, Object xFA, Object xFB) { + return Objects.hash( + // + x00, x01, x02, x03, x04, x05, x06, x07, x08, x09, x0A, x0B, x0C, x0D, x0E, x0F, + x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x1A, x1B, x1C, x1D, x1E, x1F, + x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x2A, x2B, x2C, x2D, x2E, x2F, + x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x3A, x3B, x3C, x3D, x3E, x3F, + x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x4A, x4B, x4C, x4D, x4E, x4F, + x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x5A, x5B, x5C, x5D, x5E, x5F, + x60, x61, x62, x63, x64, x65, x66, x67, x68, x69, x6A, x6B, x6C, x6D, x6E, x6F, + x70, x71, x72, x73, x74, x75, x76, x77, x78, x79, x7A, x7B, x7C, x7D, x7E, x7F, + x80, x81, x82, x83, x84, x85, x86, x87, x88, x89, x8A, x8B, x8C, x8D, x8E, x8F, + x90, x91, x92, x93, x94, x95, x96, x97, x98, x99, x9A, x9B, x9C, x9D, x9E, x9F, + xA0, xA1, xA2, xA3, xA4, xA5, xA6, xA7, xA8, xA9, xAA, xAB, xAC, xAD, xAE, xAF, + xB0, xB1, xB2, xB3, xB4, xB5, xB6, xB7, xB8, xB9, xBA, xBB, xBC, xBD, xBE, xBF, + xC0, xC1, xC2, xC3, xC4, xC5, xC6, xC7, xC8, xC9, xCA, xCB, xCC, xCD, xCE, xCF, + xD0, xD1, xD2, xD3, xD4, xD5, xD6, xD7, xD8, xD9, xDA, xDB, xDC, xDD, xDE, xDF, + xE0, xE1, xE2, xE3, xE4, xE5, xE6, xE7, xE8, xE9, xEA, xEB, xEC, xED, xEE, xEF, + xF0, xF1, xF2, xF3, xF4, xF5, xF6, xF7, + // + xF8, xF9, xFA, xFB); + } + + @Test + public void test252() throws Throwable { + final int ARITY = 252; + System.out.println("test"+ARITY); + Object[] a = testArgs(ARITY); + Object r0 = hashArguments(a); + Object r; + r = hashArguments_252( + // + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB]); + assertEquals(r0, r); + MethodType mt = MethodType.genericMethodType(ARITY); + MethodHandle mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+ARITY, mt); + r = mh.invokeExact( + // + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB]); + assertEquals(r0, r); + r = mh.invokeWithArguments(a); + assertEquals(r0, r); + MethodHandle ximh = MethodHandles.exactInvoker(mh.type()); + r = ximh.invokeExact(mh, + // + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB]); + assertEquals(r0, r); + r = ximh.invokeWithArguments(cat(mh,a)); + assertEquals(r0, r); + MethodHandle gimh = MethodHandles.invoker(mh.type()); + r = gimh.invoke(mh, + // + (Number) + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB]); + assertEquals(r0, r); + r = gimh.invokeWithArguments(cat(mh,a)); + assertEquals(r0, r); + mh = mh.asType(mh.type().changeParameterType(0x10, Integer.class)); + //System.out.println("type="+mh.type().toString().replaceAll("Object", "")); + r = mh.invokeExact( + // + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + (Integer) + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB]); + assertEquals(r0, r); + r = mh.invoke( + // + (Comparable) + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB]); + assertEquals(r0, r); + } + + static Object hashArguments_253( + // + Object x00, Object x01, Object x02, Object x03, Object x04, Object x05, Object x06, Object x07, + Object x08, Object x09, Object x0A, Object x0B, Object x0C, Object x0D, Object x0E, Object x0F, + Object x10, Object x11, Object x12, Object x13, Object x14, Object x15, Object x16, Object x17, + Object x18, Object x19, Object x1A, Object x1B, Object x1C, Object x1D, Object x1E, Object x1F, + Object x20, Object x21, Object x22, Object x23, Object x24, Object x25, Object x26, Object x27, + Object x28, Object x29, Object x2A, Object x2B, Object x2C, Object x2D, Object x2E, Object x2F, + Object x30, Object x31, Object x32, Object x33, Object x34, Object x35, Object x36, Object x37, + Object x38, Object x39, Object x3A, Object x3B, Object x3C, Object x3D, Object x3E, Object x3F, + Object x40, Object x41, Object x42, Object x43, Object x44, Object x45, Object x46, Object x47, + Object x48, Object x49, Object x4A, Object x4B, Object x4C, Object x4D, Object x4E, Object x4F, + Object x50, Object x51, Object x52, Object x53, Object x54, Object x55, Object x56, Object x57, + Object x58, Object x59, Object x5A, Object x5B, Object x5C, Object x5D, Object x5E, Object x5F, + Object x60, Object x61, Object x62, Object x63, Object x64, Object x65, Object x66, Object x67, + Object x68, Object x69, Object x6A, Object x6B, Object x6C, Object x6D, Object x6E, Object x6F, + Object x70, Object x71, Object x72, Object x73, Object x74, Object x75, Object x76, Object x77, + Object x78, Object x79, Object x7A, Object x7B, Object x7C, Object x7D, Object x7E, Object x7F, + Object x80, Object x81, Object x82, Object x83, Object x84, Object x85, Object x86, Object x87, + Object x88, Object x89, Object x8A, Object x8B, Object x8C, Object x8D, Object x8E, Object x8F, + Object x90, Object x91, Object x92, Object x93, Object x94, Object x95, Object x96, Object x97, + Object x98, Object x99, Object x9A, Object x9B, Object x9C, Object x9D, Object x9E, Object x9F, + Object xA0, Object xA1, Object xA2, Object xA3, Object xA4, Object xA5, Object xA6, Object xA7, + Object xA8, Object xA9, Object xAA, Object xAB, Object xAC, Object xAD, Object xAE, Object xAF, + Object xB0, Object xB1, Object xB2, Object xB3, Object xB4, Object xB5, Object xB6, Object xB7, + Object xB8, Object xB9, Object xBA, Object xBB, Object xBC, Object xBD, Object xBE, Object xBF, + Object xC0, Object xC1, Object xC2, Object xC3, Object xC4, Object xC5, Object xC6, Object xC7, + Object xC8, Object xC9, Object xCA, Object xCB, Object xCC, Object xCD, Object xCE, Object xCF, + Object xD0, Object xD1, Object xD2, Object xD3, Object xD4, Object xD5, Object xD6, Object xD7, + Object xD8, Object xD9, Object xDA, Object xDB, Object xDC, Object xDD, Object xDE, Object xDF, + Object xE0, Object xE1, Object xE2, Object xE3, Object xE4, Object xE5, Object xE6, Object xE7, + Object xE8, Object xE9, Object xEA, Object xEB, Object xEC, Object xED, Object xEE, Object xEF, + Object xF0, Object xF1, Object xF2, Object xF3, Object xF4, Object xF5, Object xF6, Object xF7, + // + Object xF8, Object xF9, Object xFA, Object xFB, Object xFC) { + return Objects.hash( + // + x00, x01, x02, x03, x04, x05, x06, x07, x08, x09, x0A, x0B, x0C, x0D, x0E, x0F, + x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x1A, x1B, x1C, x1D, x1E, x1F, + x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x2A, x2B, x2C, x2D, x2E, x2F, + x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x3A, x3B, x3C, x3D, x3E, x3F, + x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x4A, x4B, x4C, x4D, x4E, x4F, + x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x5A, x5B, x5C, x5D, x5E, x5F, + x60, x61, x62, x63, x64, x65, x66, x67, x68, x69, x6A, x6B, x6C, x6D, x6E, x6F, + x70, x71, x72, x73, x74, x75, x76, x77, x78, x79, x7A, x7B, x7C, x7D, x7E, x7F, + x80, x81, x82, x83, x84, x85, x86, x87, x88, x89, x8A, x8B, x8C, x8D, x8E, x8F, + x90, x91, x92, x93, x94, x95, x96, x97, x98, x99, x9A, x9B, x9C, x9D, x9E, x9F, + xA0, xA1, xA2, xA3, xA4, xA5, xA6, xA7, xA8, xA9, xAA, xAB, xAC, xAD, xAE, xAF, + xB0, xB1, xB2, xB3, xB4, xB5, xB6, xB7, xB8, xB9, xBA, xBB, xBC, xBD, xBE, xBF, + xC0, xC1, xC2, xC3, xC4, xC5, xC6, xC7, xC8, xC9, xCA, xCB, xCC, xCD, xCE, xCF, + xD0, xD1, xD2, xD3, xD4, xD5, xD6, xD7, xD8, xD9, xDA, xDB, xDC, xDD, xDE, xDF, + xE0, xE1, xE2, xE3, xE4, xE5, xE6, xE7, xE8, xE9, xEA, xEB, xEC, xED, xEE, xEF, + xF0, xF1, xF2, xF3, xF4, xF5, xF6, xF7, + // + xF8, xF9, xFA, xFB, xFC); + } + + @Test + public void test253() throws Throwable { + final int ARITY = 253; + System.out.println("test"+ARITY); + Object[] a = testArgs(ARITY); + Object r0 = hashArguments(a); + Object r; + r = hashArguments_253( + // + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]); + assertEquals(r0, r); + MethodType mt = MethodType.genericMethodType(ARITY); + MethodHandle mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+ARITY, mt); + r = mh.invokeExact( + // + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]); + assertEquals(r0, r); + r = mh.invokeWithArguments(a); + assertEquals(r0, r); + MethodHandle ximh = MethodHandles.exactInvoker(mh.type()); + r = ximh.invokeExact(mh, + // + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]); + assertEquals(r0, r); + // FIXME: This next one fails, because it uses an internal invoker of arity 255. + r = ximh.invokeWithArguments(cat(mh,a)); + assertEquals(r0, r); + MethodHandle gimh = MethodHandles.invoker(mh.type()); + r = gimh.invoke(mh, + // + (Number) + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]); + assertEquals(r0, r); + // FIXME: This next one fails, because it uses an internal invoker of arity 255. + r = gimh.invokeWithArguments(cat(mh,a)); + assertEquals(r0, r); + mh = mh.asType(mh.type().changeParameterType(0x10, Integer.class)); + //System.out.println("type="+mh.type().toString().replaceAll("Object", "")); + r = mh.invokeExact( + // + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + (Integer) + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]); + assertEquals(r0, r); + r = mh.invoke( + // + (Comparable) + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]); + assertEquals(r0, r); + } + + static Object hashArguments_254( + // + Object x00, Object x01, Object x02, Object x03, Object x04, Object x05, Object x06, Object x07, + Object x08, Object x09, Object x0A, Object x0B, Object x0C, Object x0D, Object x0E, Object x0F, + Object x10, Object x11, Object x12, Object x13, Object x14, Object x15, Object x16, Object x17, + Object x18, Object x19, Object x1A, Object x1B, Object x1C, Object x1D, Object x1E, Object x1F, + Object x20, Object x21, Object x22, Object x23, Object x24, Object x25, Object x26, Object x27, + Object x28, Object x29, Object x2A, Object x2B, Object x2C, Object x2D, Object x2E, Object x2F, + Object x30, Object x31, Object x32, Object x33, Object x34, Object x35, Object x36, Object x37, + Object x38, Object x39, Object x3A, Object x3B, Object x3C, Object x3D, Object x3E, Object x3F, + Object x40, Object x41, Object x42, Object x43, Object x44, Object x45, Object x46, Object x47, + Object x48, Object x49, Object x4A, Object x4B, Object x4C, Object x4D, Object x4E, Object x4F, + Object x50, Object x51, Object x52, Object x53, Object x54, Object x55, Object x56, Object x57, + Object x58, Object x59, Object x5A, Object x5B, Object x5C, Object x5D, Object x5E, Object x5F, + Object x60, Object x61, Object x62, Object x63, Object x64, Object x65, Object x66, Object x67, + Object x68, Object x69, Object x6A, Object x6B, Object x6C, Object x6D, Object x6E, Object x6F, + Object x70, Object x71, Object x72, Object x73, Object x74, Object x75, Object x76, Object x77, + Object x78, Object x79, Object x7A, Object x7B, Object x7C, Object x7D, Object x7E, Object x7F, + Object x80, Object x81, Object x82, Object x83, Object x84, Object x85, Object x86, Object x87, + Object x88, Object x89, Object x8A, Object x8B, Object x8C, Object x8D, Object x8E, Object x8F, + Object x90, Object x91, Object x92, Object x93, Object x94, Object x95, Object x96, Object x97, + Object x98, Object x99, Object x9A, Object x9B, Object x9C, Object x9D, Object x9E, Object x9F, + Object xA0, Object xA1, Object xA2, Object xA3, Object xA4, Object xA5, Object xA6, Object xA7, + Object xA8, Object xA9, Object xAA, Object xAB, Object xAC, Object xAD, Object xAE, Object xAF, + Object xB0, Object xB1, Object xB2, Object xB3, Object xB4, Object xB5, Object xB6, Object xB7, + Object xB8, Object xB9, Object xBA, Object xBB, Object xBC, Object xBD, Object xBE, Object xBF, + Object xC0, Object xC1, Object xC2, Object xC3, Object xC4, Object xC5, Object xC6, Object xC7, + Object xC8, Object xC9, Object xCA, Object xCB, Object xCC, Object xCD, Object xCE, Object xCF, + Object xD0, Object xD1, Object xD2, Object xD3, Object xD4, Object xD5, Object xD6, Object xD7, + Object xD8, Object xD9, Object xDA, Object xDB, Object xDC, Object xDD, Object xDE, Object xDF, + Object xE0, Object xE1, Object xE2, Object xE3, Object xE4, Object xE5, Object xE6, Object xE7, + Object xE8, Object xE9, Object xEA, Object xEB, Object xEC, Object xED, Object xEE, Object xEF, + Object xF0, Object xF1, Object xF2, Object xF3, Object xF4, Object xF5, Object xF6, Object xF7, + // + Object xF8, Object xF9, Object xFA, Object xFB, Object xFC, Object xFD) { + return Objects.hash( + // + x00, x01, x02, x03, x04, x05, x06, x07, x08, x09, x0A, x0B, x0C, x0D, x0E, x0F, + x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x1A, x1B, x1C, x1D, x1E, x1F, + x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x2A, x2B, x2C, x2D, x2E, x2F, + x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x3A, x3B, x3C, x3D, x3E, x3F, + x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x4A, x4B, x4C, x4D, x4E, x4F, + x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x5A, x5B, x5C, x5D, x5E, x5F, + x60, x61, x62, x63, x64, x65, x66, x67, x68, x69, x6A, x6B, x6C, x6D, x6E, x6F, + x70, x71, x72, x73, x74, x75, x76, x77, x78, x79, x7A, x7B, x7C, x7D, x7E, x7F, + x80, x81, x82, x83, x84, x85, x86, x87, x88, x89, x8A, x8B, x8C, x8D, x8E, x8F, + x90, x91, x92, x93, x94, x95, x96, x97, x98, x99, x9A, x9B, x9C, x9D, x9E, x9F, + xA0, xA1, xA2, xA3, xA4, xA5, xA6, xA7, xA8, xA9, xAA, xAB, xAC, xAD, xAE, xAF, + xB0, xB1, xB2, xB3, xB4, xB5, xB6, xB7, xB8, xB9, xBA, xBB, xBC, xBD, xBE, xBF, + xC0, xC1, xC2, xC3, xC4, xC5, xC6, xC7, xC8, xC9, xCA, xCB, xCC, xCD, xCE, xCF, + xD0, xD1, xD2, xD3, xD4, xD5, xD6, xD7, xD8, xD9, xDA, xDB, xDC, xDD, xDE, xDF, + xE0, xE1, xE2, xE3, xE4, xE5, xE6, xE7, xE8, xE9, xEA, xEB, xEC, xED, xEE, xEF, + xF0, xF1, xF2, xF3, xF4, xF5, xF6, xF7, + // + xF8, xF9, xFA, xFB, xFC, xFD); + } + + @Test + public void test254() throws Throwable { + final int ARITY = 254; + System.out.println("test"+ARITY); + Object[] a = testArgs(ARITY); + Object r0 = hashArguments(a); + Object r; + r = hashArguments_254( + // + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]); + assertEquals(r0, r); + MethodType mt = MethodType.genericMethodType(ARITY); + MethodHandle mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+ARITY, mt); + r = mh.invokeExact( + // + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]); + assertEquals(r0, r); + // FIXME: This next one fails, because it uses an internal invoker of arity 255. + r = mh.invokeWithArguments(a); + assertEquals(r0, r); + try { + MethodHandle ximh = MethodHandles.exactInvoker(mh.type()); + throw new AssertionError("should have thrown IAE; cannot have 1+1+254 arguments"); + } catch (IllegalArgumentException ex) { + System.out.println("OK: "+ex); + } + mh = mh.asType(mh.type().changeParameterType(0x10, Integer.class)); + //System.out.println("type="+mh.type().toString().replaceAll("Object", "")); + r = mh.invokeExact( + // + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + (Integer) + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]); + assertEquals(r0, r); + mh = mh.asType(mh.type().changeParameterType(0xE0, Number.class)); + //System.out.println("type="+mh.type().toString().replaceAll("Object", "")); + r = mh.invokeExact( + // + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + (Integer) + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + (Number) + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]); + assertEquals(r0, r); + r = mh.invoke( + // + (Comparable) + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]); + assertEquals(r0, r); + } + + static Object hashArguments_255( + // + Object x00, Object x01, Object x02, Object x03, Object x04, Object x05, Object x06, Object x07, + Object x08, Object x09, Object x0A, Object x0B, Object x0C, Object x0D, Object x0E, Object x0F, + Object x10, Object x11, Object x12, Object x13, Object x14, Object x15, Object x16, Object x17, + Object x18, Object x19, Object x1A, Object x1B, Object x1C, Object x1D, Object x1E, Object x1F, + Object x20, Object x21, Object x22, Object x23, Object x24, Object x25, Object x26, Object x27, + Object x28, Object x29, Object x2A, Object x2B, Object x2C, Object x2D, Object x2E, Object x2F, + Object x30, Object x31, Object x32, Object x33, Object x34, Object x35, Object x36, Object x37, + Object x38, Object x39, Object x3A, Object x3B, Object x3C, Object x3D, Object x3E, Object x3F, + Object x40, Object x41, Object x42, Object x43, Object x44, Object x45, Object x46, Object x47, + Object x48, Object x49, Object x4A, Object x4B, Object x4C, Object x4D, Object x4E, Object x4F, + Object x50, Object x51, Object x52, Object x53, Object x54, Object x55, Object x56, Object x57, + Object x58, Object x59, Object x5A, Object x5B, Object x5C, Object x5D, Object x5E, Object x5F, + Object x60, Object x61, Object x62, Object x63, Object x64, Object x65, Object x66, Object x67, + Object x68, Object x69, Object x6A, Object x6B, Object x6C, Object x6D, Object x6E, Object x6F, + Object x70, Object x71, Object x72, Object x73, Object x74, Object x75, Object x76, Object x77, + Object x78, Object x79, Object x7A, Object x7B, Object x7C, Object x7D, Object x7E, Object x7F, + Object x80, Object x81, Object x82, Object x83, Object x84, Object x85, Object x86, Object x87, + Object x88, Object x89, Object x8A, Object x8B, Object x8C, Object x8D, Object x8E, Object x8F, + Object x90, Object x91, Object x92, Object x93, Object x94, Object x95, Object x96, Object x97, + Object x98, Object x99, Object x9A, Object x9B, Object x9C, Object x9D, Object x9E, Object x9F, + Object xA0, Object xA1, Object xA2, Object xA3, Object xA4, Object xA5, Object xA6, Object xA7, + Object xA8, Object xA9, Object xAA, Object xAB, Object xAC, Object xAD, Object xAE, Object xAF, + Object xB0, Object xB1, Object xB2, Object xB3, Object xB4, Object xB5, Object xB6, Object xB7, + Object xB8, Object xB9, Object xBA, Object xBB, Object xBC, Object xBD, Object xBE, Object xBF, + Object xC0, Object xC1, Object xC2, Object xC3, Object xC4, Object xC5, Object xC6, Object xC7, + Object xC8, Object xC9, Object xCA, Object xCB, Object xCC, Object xCD, Object xCE, Object xCF, + Object xD0, Object xD1, Object xD2, Object xD3, Object xD4, Object xD5, Object xD6, Object xD7, + Object xD8, Object xD9, Object xDA, Object xDB, Object xDC, Object xDD, Object xDE, Object xDF, + Object xE0, Object xE1, Object xE2, Object xE3, Object xE4, Object xE5, Object xE6, Object xE7, + Object xE8, Object xE9, Object xEA, Object xEB, Object xEC, Object xED, Object xEE, Object xEF, + Object xF0, Object xF1, Object xF2, Object xF3, Object xF4, Object xF5, Object xF6, Object xF7, + // + Object xF8, Object xF9, Object xFA, Object xFB, Object xFC, Object xFD, Object xFE) { + return Objects.hash( + // + x00, x01, x02, x03, x04, x05, x06, x07, x08, x09, x0A, x0B, x0C, x0D, x0E, x0F, + x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x1A, x1B, x1C, x1D, x1E, x1F, + x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x2A, x2B, x2C, x2D, x2E, x2F, + x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x3A, x3B, x3C, x3D, x3E, x3F, + x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x4A, x4B, x4C, x4D, x4E, x4F, + x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x5A, x5B, x5C, x5D, x5E, x5F, + x60, x61, x62, x63, x64, x65, x66, x67, x68, x69, x6A, x6B, x6C, x6D, x6E, x6F, + x70, x71, x72, x73, x74, x75, x76, x77, x78, x79, x7A, x7B, x7C, x7D, x7E, x7F, + x80, x81, x82, x83, x84, x85, x86, x87, x88, x89, x8A, x8B, x8C, x8D, x8E, x8F, + x90, x91, x92, x93, x94, x95, x96, x97, x98, x99, x9A, x9B, x9C, x9D, x9E, x9F, + xA0, xA1, xA2, xA3, xA4, xA5, xA6, xA7, xA8, xA9, xAA, xAB, xAC, xAD, xAE, xAF, + xB0, xB1, xB2, xB3, xB4, xB5, xB6, xB7, xB8, xB9, xBA, xBB, xBC, xBD, xBE, xBF, + xC0, xC1, xC2, xC3, xC4, xC5, xC6, xC7, xC8, xC9, xCA, xCB, xCC, xCD, xCE, xCF, + xD0, xD1, xD2, xD3, xD4, xD5, xD6, xD7, xD8, xD9, xDA, xDB, xDC, xDD, xDE, xDF, + xE0, xE1, xE2, xE3, xE4, xE5, xE6, xE7, xE8, xE9, xEA, xEB, xEC, xED, xEE, xEF, + xF0, xF1, xF2, xF3, xF4, xF5, xF6, xF7, + // + xF8, xF9, xFA, xFB, xFC, xFD, xFE); + } + + @Test + public void test255() throws Throwable { + final int ARITY = 255; + System.out.println("test"+ARITY); + Object[] a = testArgs(ARITY); + Object r0 = hashArguments(a); + Object r; + r = hashArguments_255( + // + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD], a[0xFE]); + assertEquals(r0, r); + MethodType mt = MethodType.genericMethodType(ARITY); + MethodHandle mh; + try { + mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+ARITY, mt); + throw new AssertionError("should not create an arity 255 method handle"); + } catch (IllegalArgumentException ex) { + System.out.println("OK: "+ex); + mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+(ARITY-1), mt.dropParameterTypes(ARITY-1, ARITY)); + } + try { + r = mh.invokeExact( + // + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD], a[0xFE]); + throw new AssertionError("should not call an arity 255 method handle"); + } catch (LinkageError ex) { + System.out.println("OK: "+ex); + } + try { + MethodHandle ximh = MethodHandles.exactInvoker(mt); + throw new AssertionError("should have thrown IAE; cannot have 1+1+255 arguments"); + } catch (IllegalArgumentException ex) { + System.out.println("OK: "+ex); + } + } +} diff -r c7aa5cca1c01 -r 28122b96858e jdk/test/java/lang/invoke/MaxTest.java --- a/jdk/test/java/lang/invoke/MaxTest.java Wed Jul 05 18:20:00 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* @test - * @summary BoundMethodHandle tests with primitive types - * @compile MaxTest.java - * @run junit/othervm test.java.lang.invoke.MaxTest - */ - -package test.java.lang.invoke; - -import static org.junit.Assert.assertEquals; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import org.junit.Test; - -public class MaxTest { - - static MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); - - private MethodHandle getMax(Class t) throws Throwable { - return LOOKUP.findStatic(Math.class, "max", MethodType.methodType(t, t, t)); - } - - static int ITERATION_COUNT = 40000; - static { - String iterations = System.getProperty(MaxTest.class.getSimpleName() + ".ITERATION_COUNT"); - if (iterations == null) { - iterations = System.getProperty(MaxTest.class.getName() + ".ITERATION_COUNT"); - } - if (iterations != null) { - ITERATION_COUNT = Integer.parseInt(iterations); - } - } - - @Test - public void testMaxLong() throws Throwable { - final Class C = long.class; - final long P = 23L; - final long Q = 42L; - final long R = Math.max(P, Q); - for (int i = 0; i < ITERATION_COUNT; ++i) { - MethodHandle h = getMax(C); - assertEquals((long) h.invokeExact(P, Q), R); - MethodHandle bh = MethodHandles.insertArguments(h, 0, P); - assertEquals((long) bh.invokeExact(Q), R); - MethodHandle bbh = MethodHandles.insertArguments(bh, 0, Q); - assertEquals((long) bbh.invokeExact(), R); - MethodHandle b2h = MethodHandles.insertArguments(h, 1, Q); - assertEquals((long) b2h.invokeExact(P), R); - MethodHandle bb2h = MethodHandles.insertArguments(b2h, 0, P); - assertEquals((long) bb2h.invokeExact(), R); - } - } - - @Test - public void testMaxInt() throws Throwable { - final Class C = int.class; - final int P = 23; - final int Q = 42; - final int R = Math.max(P, Q); - for (int i = 0; i < ITERATION_COUNT; ++i) { - MethodHandle h = getMax(C); - assertEquals((int) h.invokeExact(P, Q), R); - MethodHandle bh = MethodHandles.insertArguments(h, 0, P); - assertEquals((int) bh.invokeExact(Q), R); - MethodHandle bbh = MethodHandles.insertArguments(bh, 0, Q); - assertEquals((int) bbh.invokeExact(), R); - MethodHandle b2h = MethodHandles.insertArguments(h, 1, Q); - assertEquals((int) b2h.invokeExact(P), R); - MethodHandle bb2h = MethodHandles.insertArguments(b2h, 0, P); - assertEquals((int) bb2h.invokeExact(), R); - } - } - - @Test - public void testMaxFloat() throws Throwable { - final Class C = float.class; - final float P = 23F; - final float Q = 42F; - final float R = Math.max(P, Q); - final float D = 0.1F; - for (int i = 0; i < ITERATION_COUNT; ++i) { - MethodHandle h = getMax(C); - assertEquals((float) h.invokeExact(P, Q), R, D); - MethodHandle bh = MethodHandles.insertArguments(h, 0, P); - assertEquals((float) bh.invokeExact(Q), R, D); - MethodHandle bbh = MethodHandles.insertArguments(bh, 0, Q); - assertEquals((float) bbh.invokeExact(), R, D); - MethodHandle b2h = MethodHandles.insertArguments(h, 1, Q); - assertEquals((float) b2h.invokeExact(P), R, D); - MethodHandle bb2h = MethodHandles.insertArguments(b2h, 0, P); - assertEquals((float) bb2h.invokeExact(), R, D); - } - } - - @Test - public void testMaxDouble() throws Throwable { - final Class C = double.class; - final double P = 23F; - final double Q = 42F; - final double R = Math.max(P, Q); - final double D = 0.1; - for (int i = 0; i < ITERATION_COUNT; ++i) { - MethodHandle h = getMax(C); - assertEquals((double) h.invokeExact(P, Q), R, D); - MethodHandle bh = MethodHandles.insertArguments(h, 0, P); - assertEquals((double) bh.invokeExact(Q), R, D); - MethodHandle bbh = MethodHandles.insertArguments(bh, 0, Q); - assertEquals((double) bbh.invokeExact(), R, D); - MethodHandle b2h = MethodHandles.insertArguments(h, 1, Q); - assertEquals((double) b2h.invokeExact(P), R, D); - MethodHandle bb2h = MethodHandles.insertArguments(b2h, 0, P); - assertEquals((double) bb2h.invokeExact(), R, D); - } - } - -} diff -r c7aa5cca1c01 -r 28122b96858e jdk/test/java/lang/invoke/MethodHandlesTest.java --- a/jdk/test/java/lang/invoke/MethodHandlesTest.java Wed Jul 05 18:20:00 2017 +0200 +++ b/jdk/test/java/lang/invoke/MethodHandlesTest.java Fri Aug 17 13:42:25 2012 -0700 @@ -1485,7 +1485,7 @@ RuntimeException error = null; try { target = id.asType(newType); - } catch (RuntimeException ex) { + } catch (WrongMethodTypeException ex) { error = ex; } if (verbosity >= 3) @@ -2381,47 +2381,100 @@ assertSame(thrown, caught); } - //@Test + @Test public void testInterfaceCast() throws Throwable { //if (CAN_SKIP_WORKING) return; startTest("interfaceCast"); - for (Class ctype : new Class[]{ Object.class, String.class, CharSequence.class, Number.class, Iterable.class}) { - testInterfaceCast(ctype, false, false); - testInterfaceCast(ctype, true, false); - testInterfaceCast(ctype, false, true); - testInterfaceCast(ctype, true, true); + assert( (((Object)"foo") instanceof CharSequence)); + assert(!(((Object)"foo") instanceof Iterable)); + for (MethodHandle mh : new MethodHandle[]{ + MethodHandles.identity(String.class), + MethodHandles.identity(CharSequence.class), + MethodHandles.identity(Iterable.class) + }) { + if (verbosity > 0) System.out.println("-- mh = "+mh); + for (Class ctype : new Class[]{ + Object.class, String.class, CharSequence.class, + Number.class, Iterable.class + }) { + if (verbosity > 0) System.out.println("---- ctype = "+ctype.getName()); + // doret docast + testInterfaceCast(mh, ctype, false, false); + testInterfaceCast(mh, ctype, true, false); + testInterfaceCast(mh, ctype, false, true); + testInterfaceCast(mh, ctype, true, true); + } } } - public void testInterfaceCast(Class ctype, boolean doret, boolean docast) throws Throwable { - String str = "normal return value"; - MethodHandle mh = MethodHandles.identity(String.class); + private static Class i2o(Class c) { + return (c.isInterface() ? Object.class : c); + } + public void testInterfaceCast(MethodHandle mh, Class ctype, + boolean doret, boolean docast) throws Throwable { + MethodHandle mh0 = mh; + if (verbosity > 1) + System.out.println("mh="+mh+", ctype="+ctype.getName()+", doret="+doret+", docast="+docast); + String normalRetVal = "normal return value"; MethodType mt = mh.type(); + MethodType mt0 = mt; if (doret) mt = mt.changeReturnType(ctype); else mt = mt.changeParameterType(0, ctype); if (docast) mh = MethodHandles.explicitCastArguments(mh, mt); else mh = mh.asType(mt); + assertEquals(mt, mh.type()); + MethodType mt1 = mt; // this bit is needed to make the interface types disappear for invokeWithArguments: mh = MethodHandles.explicitCastArguments(mh, mt.generic()); - boolean expectFail = !ctype.isInstance(str); - if (ctype.isInterface()) { - // special rules: interfaces slide by more frequently - if (docast || !doret) expectFail = false; + Class[] step = { + mt1.parameterType(0), // param as passed to mh at first + mt0.parameterType(0), // param after incoming cast + mt0.returnType(), // return value before cast + mt1.returnType(), // return value after outgoing cast + }; + // where might a checkCast occur? + boolean[] checkCast = new boolean[step.length]; + // the string value must pass each step without causing an exception + if (!docast) { + if (!doret) { + if (step[0] != step[1]) + checkCast[1] = true; // incoming value is cast + } else { + if (step[2] != step[3]) + checkCast[3] = true; // outgoing value is cast + } } + boolean expectFail = false; + for (int i = 0; i < step.length; i++) { + Class c = step[i]; + if (!checkCast[i]) c = i2o(c); + if (!c.isInstance(normalRetVal)) { + if (verbosity > 3) + System.out.println("expect failure at step "+i+" in "+Arrays.toString(step)+Arrays.toString(checkCast)); + expectFail = true; + break; + } + } + countTest(!expectFail); + if (verbosity > 2) + System.out.println("expectFail="+expectFail+", mt="+mt); Object res; try { - res = mh.invokeWithArguments(str); + res = mh.invokeWithArguments(normalRetVal); } catch (Exception ex) { res = ex; } boolean sawFail = !(res instanceof String); if (sawFail != expectFail) { - System.out.println("*** testInterfaceCast: "+mh+" was "+mt+" => "+res+(docast ? " (explicitCastArguments)" : "")); + System.out.println("*** testInterfaceCast: mh0 = "+mh0); + System.out.println(" retype using "+(docast ? "explicitCastArguments" : "asType")+" to "+mt+" => "+mh); + System.out.println(" call returned "+res); + System.out.println(" expected "+(expectFail ? "an exception" : normalRetVal)); } - if (!sawFail) { - assertFalse(res.toString(), expectFail); - assertEquals(str, res); + if (!expectFail) { + assertFalse(res.toString(), sawFail); + assertEquals(normalRetVal, res); } else { - assertTrue(res.toString(), expectFail); + assertTrue(res.toString(), sawFail); } } diff -r c7aa5cca1c01 -r 28122b96858e jdk/test/java/lang/invoke/PermuteArgsTest.java --- a/jdk/test/java/lang/invoke/PermuteArgsTest.java Wed Jul 05 18:20:00 2017 +0200 +++ b/jdk/test/java/lang/invoke/PermuteArgsTest.java Fri Aug 17 13:42:25 2012 -0700 @@ -191,7 +191,11 @@ pt = mt1.parameterType(mt1.parameterCount() - posArgs); mt1 = mt1.appendParameterTypes(pt); } - return mh.asType(mt1); + try { + return mh.asType(mt1); + } catch (WrongMethodTypeException | IllegalArgumentException ex) { + throw new IllegalArgumentException("cannot convert to type "+mt1+" from "+mh, ex); + } } static MethodHandle findTestMH(String name, int[] perm) throws ReflectiveOperationException { int arity = perm.length; diff -r c7aa5cca1c01 -r 28122b96858e jdk/test/java/lang/invoke/RicochetTest.java --- a/jdk/test/java/lang/invoke/RicochetTest.java Wed Jul 05 18:20:00 2017 +0200 +++ b/jdk/test/java/lang/invoke/RicochetTest.java Fri Aug 17 13:42:25 2012 -0700 @@ -256,7 +256,7 @@ //System.out.println(" expect="+expect); // now use the combined MH, and test the output: - MethodHandle mh = collectArguments(lister, pos, INT_COLLECTORS[collects]); + MethodHandle mh = collectArguments(lister, pos, int[].class, INT_COLLECTORS[collects]); if (mh == null) continue; // no infix collection, yet assert(mh.type().parameterCount() == inputs); Object observe = mh.asSpreader(int[].class, args.length).invokeExact(args); @@ -266,13 +266,53 @@ } } - private static MethodHandle collectArguments(MethodHandle lister, int pos, MethodHandle collector) { + @Test + public void testByteCollects() throws Throwable { + if (!startTest("testByteCollects")) return; + for (MethodHandle lister : BYTE_LISTERS) { + int outputs = lister.type().parameterCount(); + for (int collects = 0; collects <= Math.min(outputs, BYTE_COLLECTORS.length-1); collects++) { + int inputs = outputs - 1 + collects; + if (inputs < 0) continue; + for (int pos = 0; pos + collects <= inputs; pos++) { + MethodHandle collector = BYTE_COLLECTORS[collects]; + byte[] args = new byte[inputs]; + int ap = 0, arg = 31; + for (int i = 0; i < pos; i++) + args[ap++] = (byte)(arg++ + 0); + for (int i = 0; i < collects; i++) + args[ap++] = (byte)(arg++ + 10); + while (ap < args.length) + args[ap++] = (byte)(arg++ + 20); + // calculate piecemeal: + //System.out.println("testIntCollects "+Arrays.asList(lister, pos, collector)+" on "+Arrays.toString(args)); + byte[] collargs = Arrays.copyOfRange(args, pos, pos+collects); + byte coll = (byte) collector.asSpreader(byte[].class, collargs.length).invokeExact(collargs); + byte[] listargs = Arrays.copyOfRange(args, 0, outputs); + System.arraycopy(args, pos+collects, listargs, pos+1, outputs - (pos+1)); + listargs[pos] = coll; + //System.out.println(" coll="+coll+" listargs="+Arrays.toString(listargs)); + Object expect = lister.asSpreader(byte[].class, listargs.length).invokeExact(listargs); + //System.out.println(" expect="+expect); + + // now use the combined MH, and test the output: + MethodHandle mh = collectArguments(lister, pos, byte[].class, BYTE_COLLECTORS[collects]); + if (mh == null) continue; // no infix collection, yet + assert(mh.type().parameterCount() == inputs); + Object observe = mh.asSpreader(byte[].class, args.length).invokeExact(args); + assertEquals(expect, observe); + } + } + } + } + + private static MethodHandle collectArguments(MethodHandle lister, int pos, Class array, MethodHandle collector) { int collects = collector.type().parameterCount(); int outputs = lister.type().parameterCount(); if (pos == outputs - 1) return MethodHandles.filterArguments(lister, pos, - collector.asSpreader(int[].class, collects)) - .asCollector(int[].class, collects); + collector.asSpreader(array, collects)) + .asCollector(array, collects); //return MethodHandles.collectArguments(lister, pos, collector); //no such animal return null; } @@ -537,6 +577,9 @@ private static final MethodHandle[] INT_COLLECTORS = { constant(int.class, 42), opI, opI2, opI3, opI4 }; + private static final MethodHandle[] BYTE_COLLECTORS = { + constant(byte.class, (byte)42), i2b(opI), i2b(opI2), i2b(opI3), i2b(opI4) + }; private static final MethodHandle[] LONG_COLLECTORS = { constant(long.class, 42), opJ, opJ2, opJ3 }; @@ -559,21 +602,36 @@ Collections.nCopies(8, int.class)); private static final MethodHandle list8longs = findStatic("list8longs", Object.class, Collections.nCopies(8, long.class)); - private static final MethodHandle[] INT_LISTERS, LONG_LISTERS; + private static final MethodHandle[] INT_LISTERS, LONG_LISTERS, BYTE_LISTERS; static { int listerCount = list8ints.type().parameterCount() + 1; INT_LISTERS = new MethodHandle[listerCount]; LONG_LISTERS = new MethodHandle[listerCount]; + BYTE_LISTERS = new MethodHandle[listerCount]; MethodHandle lister = list8ints; MethodHandle llister = list8longs; for (int i = listerCount - 1; ; i--) { INT_LISTERS[i] = lister; LONG_LISTERS[i] = llister; + BYTE_LISTERS[i] = i2b(lister); if (i == 0) break; lister = insertArguments(lister, i-1, 0); llister = insertArguments(llister, i-1, 0L); } } + private static MethodHandle i2b(MethodHandle mh) { + return MethodHandles.explicitCastArguments(mh, subst(mh.type(), int.class, byte.class)); + } + private static MethodType subst(MethodType mt, Class from, Class to) { + for (int i = 0; i < mt.parameterCount(); i++) { + if (mt.parameterType(i) == from) + mt = mt.changeParameterType(i, to); + } + if (mt.returnType() == from) + mt = mt.changeReturnType(to); + return mt; + } + private static Object convI_L(int x) { stress(); return (Object) x; } private static int convL_I(Object x) { stress(); return (int) x; } diff -r c7aa5cca1c01 -r 28122b96858e jdk/test/sun/invoke/util/ValueConversionsTest.java --- a/jdk/test/sun/invoke/util/ValueConversionsTest.java Wed Jul 05 18:20:00 2017 +0200 +++ b/jdk/test/sun/invoke/util/ValueConversionsTest.java Fri Aug 17 13:42:25 2012 -0700 @@ -159,14 +159,8 @@ assertEquals(caster.type(), ValueConversions.identity().type()); for (Object obj : objects) { Class src = obj.getClass(); - boolean canCast; - if (dst.isInterface()) { - canCast = true; - } else { - canCast = dst.isAssignableFrom(src); - assertEquals(canCast, dst.isInstance(obj)); - } - //System.out.println("obj="+obj+" <: dst="+dst); + boolean canCast = dst.isAssignableFrom(src); + //System.out.println("obj="+obj+" <: dst="+dst+(canCast ? " (OK)" : " (will fail)")); try { Object result = caster.invokeExact(obj); if (canCast)