# HG changeset patch # User vlivanov # Date 1410876303 -14400 # Node ID 14bb608ce64ec3178ffb28d75d213476b3b5ffb3 # Parent cbeb3711fa94e18a80093aa9b24c9d23684f895a 8058293: Bit set computation in MHs.findFirstDupOrDrop/findFirstDrop is broken Reviewed-by: jrose diff -r cbeb3711fa94 -r 14bb608ce64e jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Tue Sep 16 18:05:01 2014 +0400 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Tue Sep 16 18:05:03 2014 +0400 @@ -2171,7 +2171,7 @@ // 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 = Arrays.copyOf(reorder, oldArity + 1); reorder[oldArity] = dropIdx; } assert(target == originalTarget || permuteArgumentChecks(reorder, newType, target.type())); @@ -2189,9 +2189,9 @@ long mask = 0; for (int arg : reorder) { assert(arg < newArity); - mask |= (1 << arg); + mask |= (1L << arg); } - if (mask == (1 << newArity) - 1) { + if (mask == (1L << newArity) - 1) { assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity); return -1; } @@ -2200,16 +2200,18 @@ 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; } - BitSet mask = new BitSet(newArity); - for (int arg : reorder) { - assert(arg < newArity); - mask.set(arg); - } - int zeroPos = mask.nextClearBit(0); - if (zeroPos == newArity) - return -1; - return zeroPos; } /** @@ -2225,32 +2227,42 @@ long mask = 0; for (int i = 0; i < reorder.length; i++) { int arg = reorder[i]; - if (arg >= newArity) return reorder.length; - int bit = 1 << arg; - if ((mask & bit) != 0) + if (arg >= newArity) { + return reorder.length; + } + long bit = 1L << arg; + if ((mask & bit) != 0) { return i; // >0 indicates a dup + } mask |= bit; } - if (mask == (1 << newArity) - 1) { + if (mask == (1L << newArity) - 1) { assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity); return 0; } // find first zero long zeroBit = Long.lowestOneBit(~mask); int zeroPos = Long.numberOfTrailingZeros(zeroBit); - assert(zeroPos < newArity); + assert(zeroPos <= newArity); + if (zeroPos == newArity) { + return 0; + } return ~zeroPos; } else { // same algorithm, different bit set BitSet mask = new BitSet(newArity); for (int i = 0; i < reorder.length; i++) { int arg = reorder[i]; - if (arg >= newArity) return reorder.length; - if (mask.get(arg)) + if (arg >= newArity) { + return reorder.length; + } + if (mask.get(arg)) { return i; // >0 indicates a dup + } mask.set(arg); } int zeroPos = mask.nextClearBit(0); + assert(zeroPos <= newArity); if (zeroPos == newArity) { return 0; }