# HG changeset patch # User vlivanov # Date 1416842198 28800 # Node ID c364f9f66362bca78affaacbb40efbde3e639d12 # Parent 87f9573422d78ded0198d3b81aca7d65e6ae275f 8063135: Enable full LF sharing by default Reviewed-by: psandoz, shade diff -r 87f9573422d7 -r c364f9f66362 src/share/classes/java/lang/invoke/MethodHandle.java --- a/src/share/classes/java/lang/invoke/MethodHandle.java Wed Oct 29 09:31:37 2014 -0700 +++ b/src/share/classes/java/lang/invoke/MethodHandle.java Mon Nov 24 07:16:38 2014 -0800 @@ -867,15 +867,11 @@ MethodType postSpreadType = asSpreaderChecks(arrayType, arrayLength); int arity = type().parameterCount(); int spreadArgPos = arity - arrayLength; - if (USE_LAMBDA_FORM_EDITOR) { - MethodHandle afterSpread = this.asType(postSpreadType); - BoundMethodHandle mh = afterSpread.rebind(); - LambdaForm lform = mh.editor().spreadArgumentsForm(1 + spreadArgPos, arrayType, arrayLength); - MethodType preSpreadType = postSpreadType.replaceParameterTypes(spreadArgPos, arity, arrayType); - return mh.copyWith(preSpreadType, lform); - } else { - return MethodHandleImpl.makeSpreadArguments(this, arrayType, spreadArgPos, arrayLength); - } + MethodHandle afterSpread = this.asType(postSpreadType); + BoundMethodHandle mh = afterSpread.rebind(); + LambdaForm lform = mh.editor().spreadArgumentsForm(1 + spreadArgPos, arrayType, arrayLength); + MethodType preSpreadType = postSpreadType.replaceParameterTypes(spreadArgPos, arity, arrayType); + return mh.copyWith(preSpreadType, lform); } /** @@ -996,23 +992,15 @@ public MethodHandle asCollector(Class arrayType, int arrayLength) { asCollectorChecks(arrayType, arrayLength); int collectArgPos = type().parameterCount() - 1; - if (USE_LAMBDA_FORM_EDITOR) { - BoundMethodHandle mh = rebind(); - MethodType resultType = type().asCollectorType(arrayType, arrayLength); - MethodHandle newArray = MethodHandleImpl.varargsArray(arrayType, arrayLength); - LambdaForm lform = mh.editor().collectArgumentArrayForm(1 + collectArgPos, newArray); - if (lform != null) { - return mh.copyWith(resultType, lform); - } - lform = mh.editor().collectArgumentsForm(1 + collectArgPos, newArray.type().basicType()); - return mh.copyWithExtendL(resultType, lform, newArray); - } else { - MethodHandle target = this; - if (arrayType != type().parameterType(collectArgPos)) - target = MethodHandleImpl.makePairwiseConvert(this, type().changeParameterType(collectArgPos, arrayType), true); - MethodHandle collector = MethodHandleImpl.varargsArray(arrayType, arrayLength); - return MethodHandles.collectArguments(target, collectArgPos, collector); + BoundMethodHandle mh = rebind(); + MethodType resultType = type().asCollectorType(arrayType, arrayLength); + MethodHandle newArray = MethodHandleImpl.varargsArray(arrayType, arrayLength); + LambdaForm lform = mh.editor().collectArgumentArrayForm(1 + collectArgPos, newArray); + if (lform != null) { + return mh.copyWith(resultType, lform); } + lform = mh.editor().collectArgumentsForm(1 + collectArgPos, newArray.type().basicType()); + return mh.copyWithExtendL(resultType, lform, newArray); } /** diff -r 87f9573422d7 -r c364f9f66362 src/share/classes/java/lang/invoke/MethodHandleImpl.java --- a/src/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Oct 29 09:31:37 2014 -0700 +++ b/src/share/classes/java/lang/invoke/MethodHandleImpl.java Mon Nov 24 07:16:38 2014 -0800 @@ -191,11 +191,7 @@ MethodType dstType = target.type(); if (srcType == dstType) return target; - if (USE_LAMBDA_FORM_EDITOR) { - return makePairwiseConvertByEditor(target, srcType, strict, monobox); - } else { - return makePairwiseConvertIndirect(target, srcType, strict, monobox); - } + return makePairwiseConvertByEditor(target, srcType, strict, monobox); } private static int countNonNull(Object[] array) { diff -r 87f9573422d7 -r c364f9f66362 src/share/classes/java/lang/invoke/MethodHandleStatics.java --- a/src/share/classes/java/lang/invoke/MethodHandleStatics.java Wed Oct 29 09:31:37 2014 -0700 +++ b/src/share/classes/java/lang/invoke/MethodHandleStatics.java Mon Nov 24 07:16:38 2014 -0800 @@ -45,23 +45,21 @@ static final boolean DUMP_CLASS_FILES; static final boolean TRACE_INTERPRETER; static final boolean TRACE_METHOD_LINKAGE; - static final boolean USE_LAMBDA_FORM_EDITOR; static final int COMPILE_THRESHOLD; static final int DONT_INLINE_THRESHOLD; static final int PROFILE_LEVEL; static { - final Object[] values = new Object[8]; + final Object[] values = new Object[7]; AccessController.doPrivileged(new PrivilegedAction() { public Void run() { values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES"); values[1] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES"); values[2] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_INTERPRETER"); values[3] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE"); - values[4] = Boolean.getBoolean("java.lang.invoke.MethodHandle.USE_LF_EDITOR"); - values[5] = Integer.getInteger("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", 30); - values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.DONT_INLINE_THRESHOLD", 30); - values[7] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0); + values[4] = Integer.getInteger("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", 30); + values[5] = Integer.getInteger("java.lang.invoke.MethodHandle.DONT_INLINE_THRESHOLD", 30); + values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0); return null; } }); @@ -69,10 +67,9 @@ DUMP_CLASS_FILES = (Boolean) values[1]; TRACE_INTERPRETER = (Boolean) values[2]; TRACE_METHOD_LINKAGE = (Boolean) values[3]; - USE_LAMBDA_FORM_EDITOR = (Boolean) values[4]; - COMPILE_THRESHOLD = (Integer) values[5]; - DONT_INLINE_THRESHOLD = (Integer) values[6]; - PROFILE_LEVEL = (Integer) values[7]; + COMPILE_THRESHOLD = (Integer) values[4]; + DONT_INLINE_THRESHOLD = (Integer) values[5]; + PROFILE_LEVEL = (Integer) values[6]; } /** Tell if any of the debugging switches are turned on. diff -r 87f9573422d7 -r c364f9f66362 src/share/classes/java/lang/invoke/MethodHandles.java --- a/src/share/classes/java/lang/invoke/MethodHandles.java Wed Oct 29 09:31:37 2014 -0700 +++ b/src/share/classes/java/lang/invoke/MethodHandles.java Mon Nov 24 07:16:38 2014 -0800 @@ -2104,115 +2104,65 @@ reorder = reorder.clone(); // get a private copy MethodType oldType = target.type(); permuteArgumentChecks(reorder, newType, oldType); - if (USE_LAMBDA_FORM_EDITOR) { - // first detect dropped arguments and handle them separately - int[] originalReorder = reorder; - BoundMethodHandle result = target.rebind(); - LambdaForm form = result.form; - int newArity = newType.parameterCount(); - // Normalize the reordering into a real permutation, - // by removing duplicates and adding dropped elements. - // This somewhat improves lambda form caching, as well - // as simplifying the transform by breaking it up into steps. - for (int ddIdx; (ddIdx = findFirstDupOrDrop(reorder, newArity)) != 0; ) { - if (ddIdx > 0) { - // We found a duplicated entry at reorder[ddIdx]. - // Example: (x,y,z)->asList(x,y,z) - // permuted by [1*,0,1] => (a0,a1)=>asList(a1,a0,a1) - // permuted by [0,1,0*] => (a0,a1)=>asList(a0,a1,a0) - // The starred element corresponds to the argument - // deleted by the dupArgumentForm transform. - int srcPos = ddIdx, dstPos = srcPos, dupVal = reorder[srcPos]; - boolean killFirst = false; - for (int val; (val = reorder[--dstPos]) != dupVal; ) { - // Set killFirst if the dup is larger than an intervening position. - // This will remove at least one inversion from the permutation. - if (dupVal > val) killFirst = true; - } - if (!killFirst) { - srcPos = dstPos; - dstPos = ddIdx; - } - form = form.editor().dupArgumentForm(1 + srcPos, 1 + dstPos); - assert (reorder[srcPos] == reorder[dstPos]); - oldType = oldType.dropParameterTypes(dstPos, dstPos + 1); - // contract the reordering by removing the element at dstPos - int tailPos = dstPos + 1; - System.arraycopy(reorder, tailPos, reorder, dstPos, reorder.length - tailPos); - reorder = Arrays.copyOf(reorder, reorder.length - 1); - } else { - int dropVal = ~ddIdx, insPos = 0; - while (insPos < reorder.length && reorder[insPos] < dropVal) { - // Find first element of reorder larger than dropVal. - // This is where we will insert the dropVal. - insPos += 1; - } - Class ptype = newType.parameterType(dropVal); - form = form.editor().addArgumentForm(1 + insPos, BasicType.basicType(ptype)); - oldType = oldType.insertParameterTypes(insPos, ptype); - // expand the reordering by inserting an element at insPos - int tailPos = insPos + 1; - reorder = Arrays.copyOf(reorder, reorder.length + 1); - System.arraycopy(reorder, insPos, reorder, tailPos, reorder.length - tailPos); - reorder[insPos] = dropVal; + // first detect dropped arguments and handle them separately + int[] originalReorder = reorder; + BoundMethodHandle result = target.rebind(); + LambdaForm form = result.form; + int newArity = newType.parameterCount(); + // Normalize the reordering into a real permutation, + // by removing duplicates and adding dropped elements. + // This somewhat improves lambda form caching, as well + // as simplifying the transform by breaking it up into steps. + for (int ddIdx; (ddIdx = findFirstDupOrDrop(reorder, newArity)) != 0; ) { + if (ddIdx > 0) { + // We found a duplicated entry at reorder[ddIdx]. + // Example: (x,y,z)->asList(x,y,z) + // permuted by [1*,0,1] => (a0,a1)=>asList(a1,a0,a1) + // permuted by [0,1,0*] => (a0,a1)=>asList(a0,a1,a0) + // The starred element corresponds to the argument + // deleted by the dupArgumentForm transform. + int srcPos = ddIdx, dstPos = srcPos, dupVal = reorder[srcPos]; + boolean killFirst = false; + for (int val; (val = reorder[--dstPos]) != dupVal; ) { + // Set killFirst if the dup is larger than an intervening position. + // This will remove at least one inversion from the permutation. + if (dupVal > val) killFirst = true; } - assert (permuteArgumentChecks(reorder, newType, oldType)); + if (!killFirst) { + srcPos = dstPos; + dstPos = ddIdx; + } + form = form.editor().dupArgumentForm(1 + srcPos, 1 + dstPos); + assert (reorder[srcPos] == reorder[dstPos]); + oldType = oldType.dropParameterTypes(dstPos, dstPos + 1); + // contract the reordering by removing the element at dstPos + int tailPos = dstPos + 1; + System.arraycopy(reorder, tailPos, reorder, dstPos, reorder.length - tailPos); + reorder = Arrays.copyOf(reorder, reorder.length - 1); + } else { + int dropVal = ~ddIdx, insPos = 0; + while (insPos < reorder.length && reorder[insPos] < dropVal) { + // Find first element of reorder larger than dropVal. + // This is where we will insert the dropVal. + insPos += 1; + } + Class ptype = newType.parameterType(dropVal); + form = form.editor().addArgumentForm(1 + insPos, BasicType.basicType(ptype)); + oldType = oldType.insertParameterTypes(insPos, ptype); + // expand the reordering by inserting an element at insPos + int tailPos = insPos + 1; + reorder = Arrays.copyOf(reorder, reorder.length + 1); + System.arraycopy(reorder, insPos, reorder, tailPos, reorder.length - tailPos); + reorder[insPos] = dropVal; } - assert (reorder.length == newArity); // a perfect permutation - // Note: This may cache too many distinct LFs. Consider backing off to varargs code. - form = form.editor().permuteArgumentsForm(1, reorder); - if (newType == result.type() && form == result.internalForm()) - return result; - return result.copyWith(newType, form); - } else { - // first detect dropped arguments and handle them separately - MethodHandle originalTarget = target; - int newArity = newType.parameterCount(); - for (int dropIdx; (dropIdx = findFirstDrop(reorder, newArity)) >= 0; ) { - // dropIdx is missing from reorder; add it in at the end - int oldArity = reorder.length; - target = dropArguments(target, oldArity, newType.parameterType(dropIdx)); - reorder = Arrays.copyOf(reorder, oldArity + 1); - reorder[oldArity] = dropIdx; - } - assert(target == originalTarget || permuteArgumentChecks(reorder, newType, target.type())); - // Note: This may cache too many distinct LFs. Consider backing off to varargs code. - BoundMethodHandle result = target.rebind(); - LambdaForm form = result.form.permuteArguments(1, reorder, basicTypes(newType.parameterList())); - return result.copyWith(newType, form); + assert (permuteArgumentChecks(reorder, newType, oldType)); } - } - - /** Return the first value in [0..newArity-1] that is not present in reorder. */ - private static int findFirstDrop(int[] reorder, int newArity) { - final int BIT_LIMIT = 63; // max number of bits in bit mask - if (newArity < BIT_LIMIT) { - long mask = 0; - for (int arg : reorder) { - assert(arg < newArity); - mask |= (1L << arg); - } - if (mask == (1L << newArity) - 1) { - assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity); - return -1; - } - // find first zero - long zeroBit = Long.lowestOneBit(~mask); - int zeroPos = Long.numberOfTrailingZeros(zeroBit); - assert(zeroPos < newArity); - return zeroPos; - } else { - BitSet mask = new BitSet(newArity); - for (int arg : reorder) { - assert (arg < newArity); - mask.set(arg); - } - int zeroPos = mask.nextClearBit(0); - assert(zeroPos <= newArity); - if (zeroPos == newArity) - return -1; - return zeroPos; - } + assert (reorder.length == newArity); // a perfect permutation + // Note: This may cache too many distinct LFs. Consider backing off to varargs code. + form = form.editor().permuteArgumentsForm(1, reorder); + if (newType == result.type() && form == result.internalForm()) + return result; + return result.copyWith(newType, form); } /** @@ -2503,13 +2453,9 @@ if (dropped == 0) return target; BoundMethodHandle result = target.rebind(); LambdaForm lform = result.form; - if (USE_LAMBDA_FORM_EDITOR) { - int insertFormArg = 1 + pos; - for (Class ptype : valueTypes) { - lform = lform.editor().addArgumentForm(insertFormArg++, BasicType.basicType(ptype)); - } - } else { - lform = lform.addArguments(pos, valueTypes); + int insertFormArg = 1 + pos; + for (Class ptype : valueTypes) { + lform = lform.editor().addArgumentForm(insertFormArg++, BasicType.basicType(ptype)); } result = result.copyWith(newType, lform); return result; @@ -2660,18 +2606,14 @@ /*non-public*/ static MethodHandle filterArgument(MethodHandle target, int pos, MethodHandle filter) { filterArgumentChecks(target, pos, filter); - if (USE_LAMBDA_FORM_EDITOR) { - MethodType targetType = target.type(); - MethodType filterType = filter.type(); - BoundMethodHandle result = target.rebind(); - Class newParamType = filterType.parameterType(0); - LambdaForm lform = result.editor().filterArgumentForm(1 + pos, BasicType.basicType(newParamType)); - MethodType newType = targetType.changeParameterType(pos, newParamType); - result = result.copyWithExtendL(newType, lform, filter); - return result; - } else { - return MethodHandleImpl.makeCollectArguments(target, filter, pos, false); - } + MethodType targetType = target.type(); + MethodType filterType = filter.type(); + BoundMethodHandle result = target.rebind(); + Class newParamType = filterType.parameterType(0); + LambdaForm lform = result.editor().filterArgumentForm(1 + pos, BasicType.basicType(newParamType)); + MethodType newType = targetType.changeParameterType(pos, newParamType); + result = result.copyWithExtendL(newType, lform, filter); + return result; } private static void filterArgumentsCheckArity(MethodHandle target, int pos, MethodHandle[] filters) { @@ -2798,21 +2740,17 @@ public static MethodHandle collectArguments(MethodHandle target, int pos, MethodHandle filter) { MethodType newType = collectArgumentsChecks(target, pos, filter); - if (USE_LAMBDA_FORM_EDITOR) { - MethodType collectorType = filter.type(); - BoundMethodHandle result = target.rebind(); - LambdaForm lform; - if (collectorType.returnType().isArray() && filter.intrinsicName() == Intrinsic.NEW_ARRAY) { - lform = result.editor().collectArgumentArrayForm(1 + pos, filter); - if (lform != null) { - return result.copyWith(newType, lform); - } + MethodType collectorType = filter.type(); + BoundMethodHandle result = target.rebind(); + LambdaForm lform; + if (collectorType.returnType().isArray() && filter.intrinsicName() == Intrinsic.NEW_ARRAY) { + lform = result.editor().collectArgumentArrayForm(1 + pos, filter); + if (lform != null) { + return result.copyWith(newType, lform); } - lform = result.editor().collectArgumentsForm(1 + pos, collectorType.basicType()); - return result.copyWithExtendL(newType, lform, filter); - } else { - return MethodHandleImpl.makeCollectArguments(target, filter, pos, false); } + lform = result.editor().collectArgumentsForm(1 + pos, collectorType.basicType()); + return result.copyWithExtendL(newType, lform, filter); } private static MethodType collectArgumentsChecks(MethodHandle target, int pos, MethodHandle filter) throws RuntimeException { @@ -2891,16 +2829,12 @@ MethodType targetType = target.type(); MethodType filterType = filter.type(); filterReturnValueChecks(targetType, filterType); - if (USE_LAMBDA_FORM_EDITOR) { - BoundMethodHandle result = target.rebind(); - BasicType rtype = BasicType.basicType(filterType.returnType()); - LambdaForm lform = result.editor().filterReturnForm(rtype, false); - MethodType newType = targetType.changeReturnType(filterType.returnType()); - result = result.copyWithExtendL(newType, lform, filter); - return result; - } else { - return MethodHandleImpl.makeCollectArguments(filter, target, 0, false); - } + BoundMethodHandle result = target.rebind(); + BasicType rtype = BasicType.basicType(filterType.returnType()); + LambdaForm lform = result.editor().filterReturnForm(rtype, false); + MethodType newType = targetType.changeReturnType(filterType.returnType()); + result = result.copyWithExtendL(newType, lform, filter); + return result; } private static void filterReturnValueChecks(MethodType targetType, MethodType filterType) throws RuntimeException { @@ -2994,19 +2928,15 @@ MethodType targetType = target.type(); MethodType combinerType = combiner.type(); Class rtype = foldArgumentChecks(foldPos, targetType, combinerType); - if (USE_LAMBDA_FORM_EDITOR) { - BoundMethodHandle result = target.rebind(); - boolean dropResult = (rtype == void.class); - // Note: This may cache too many distinct LFs. Consider backing off to varargs code. - LambdaForm lform = result.editor().foldArgumentsForm(1 + foldPos, dropResult, combinerType.basicType()); - MethodType newType = targetType; - if (!dropResult) - newType = newType.dropParameterTypes(foldPos, foldPos + 1); - result = result.copyWithExtendL(newType, lform, combiner); - return result; - } else { - return MethodHandleImpl.makeCollectArguments(target, combiner, foldPos, true); - } + BoundMethodHandle result = target.rebind(); + boolean dropResult = (rtype == void.class); + // Note: This may cache too many distinct LFs. Consider backing off to varargs code. + LambdaForm lform = result.editor().foldArgumentsForm(1 + foldPos, dropResult, combinerType.basicType()); + MethodType newType = targetType; + if (!dropResult) + newType = newType.dropParameterTypes(foldPos, foldPos + 1); + result = result.copyWithExtendL(newType, lform, combiner); + return result; } private static Class foldArgumentChecks(int foldPos, MethodType targetType, MethodType combinerType) { diff -r 87f9573422d7 -r c364f9f66362 test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java --- a/test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java Wed Oct 29 09:31:37 2014 -0700 +++ b/test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java Mon Nov 24 07:16:38 2014 -0800 @@ -31,7 +31,7 @@ * @build TestMethods * @build LambdaFormTestCase * @build LFGarbageCollectedTest - * @run main/othervm/timeout=600 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true -DtestLimit=150 LFGarbageCollectedTest + * @run main/othervm/timeout=600 -DtestLimit=150 LFGarbageCollectedTest */ import java.lang.invoke.MethodHandle; diff -r 87f9573422d7 -r c364f9f66362 test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java --- a/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java Wed Oct 29 09:31:37 2014 -0700 +++ b/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java Mon Nov 24 07:16:38 2014 -0800 @@ -31,7 +31,7 @@ * @build LambdaFormTestCase * @build LFCachingTestCase * @build LFMultiThreadCachingTest - * @run main/othervm/timeout=300 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true LFMultiThreadCachingTest + * @run main/othervm/timeout=300 LFMultiThreadCachingTest */ import java.lang.invoke.MethodHandle; diff -r 87f9573422d7 -r c364f9f66362 test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java --- a/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java Wed Oct 29 09:31:37 2014 -0700 +++ b/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java Mon Nov 24 07:16:38 2014 -0800 @@ -31,7 +31,7 @@ * @build LambdaFormTestCase * @build LFCachingTestCase * @build LFSingleThreadCachingTest - * @run main/othervm/timeout=300 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true LFSingleThreadCachingTest + * @run main/othervm/timeout=300 LFSingleThreadCachingTest */ import java.lang.invoke.MethodHandle;