diff options
author | Paul Duffin <paulduffin@google.com> | 2015-02-27 17:16:12 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2015-02-27 17:16:12 +0000 |
commit | 5b9b416a211d8d2ac2012aaad1b77f79ffe7617c (patch) | |
tree | 85e50fb7fe39e68a08f2478fcc19886431d4d192 | |
parent | a1a9bcff09484f374ee7fa11a5ce38c48463b651 (diff) | |
parent | 0c29232f9e0a18dc064d9f2859f7bff889729002 (diff) | |
download | guava-marshmallow-dr-dragon-release.tar.gz |
am 0c29232f: Merge "Replaced usages of Unsafe in UnsignedBytes with standard Java"android-cts-6.0_r9android-cts-6.0_r8android-cts-6.0_r7android-cts-6.0_r6android-cts-6.0_r5android-cts-6.0_r4android-cts-6.0_r32android-cts-6.0_r31android-cts-6.0_r30android-cts-6.0_r3android-cts-6.0_r29android-cts-6.0_r28android-cts-6.0_r27android-cts-6.0_r26android-cts-6.0_r25android-cts-6.0_r24android-cts-6.0_r23android-cts-6.0_r22android-cts-6.0_r21android-cts-6.0_r20android-cts-6.0_r2android-cts-6.0_r19android-cts-6.0_r18android-cts-6.0_r17android-cts-6.0_r16android-cts-6.0_r15android-cts-6.0_r14android-cts-6.0_r13android-cts-6.0_r12android-cts-6.0_r1android-6.0.1_r9android-6.0.1_r81android-6.0.1_r80android-6.0.1_r8android-6.0.1_r79android-6.0.1_r78android-6.0.1_r77android-6.0.1_r74android-6.0.1_r73android-6.0.1_r72android-6.0.1_r70android-6.0.1_r7android-6.0.1_r69android-6.0.1_r68android-6.0.1_r67android-6.0.1_r66android-6.0.1_r65android-6.0.1_r63android-6.0.1_r62android-6.0.1_r61android-6.0.1_r60android-6.0.1_r59android-6.0.1_r58android-6.0.1_r57android-6.0.1_r56android-6.0.1_r55android-6.0.1_r54android-6.0.1_r53android-6.0.1_r52android-6.0.1_r51android-6.0.1_r50android-6.0.1_r5android-6.0.1_r49android-6.0.1_r48android-6.0.1_r47android-6.0.1_r46android-6.0.1_r45android-6.0.1_r43android-6.0.1_r42android-6.0.1_r41android-6.0.1_r40android-6.0.1_r4android-6.0.1_r33android-6.0.1_r32android-6.0.1_r31android-6.0.1_r30android-6.0.1_r3android-6.0.1_r28android-6.0.1_r27android-6.0.1_r26android-6.0.1_r25android-6.0.1_r24android-6.0.1_r22android-6.0.1_r21android-6.0.1_r20android-6.0.1_r18android-6.0.1_r17android-6.0.1_r16android-6.0.1_r13android-6.0.1_r12android-6.0.1_r11android-6.0.1_r10android-6.0.1_r1android-6.0.0_r7android-6.0.0_r6android-6.0.0_r5android-6.0.0_r41android-6.0.0_r4android-6.0.0_r3android-6.0.0_r26android-6.0.0_r25android-6.0.0_r24android-6.0.0_r23android-6.0.0_r2android-6.0.0_r13android-6.0.0_r12android-6.0.0_r11android-6.0.0_r1afw-test-harness-1.5marshmallow-releasemarshmallow-mr3-releasemarshmallow-mr2-releasemarshmallow-mr1-releasemarshmallow-mr1-devmarshmallow-dr1.6-releasemarshmallow-dr1.5-releasemarshmallow-dr1.5-devmarshmallow-dr-releasemarshmallow-dr-dragon-releasemarshmallow-dr-devmarshmallow-devmarshmallow-cts-releaselinaro-android-6.0.1android-live-tv
* commit '0c29232f9e0a18dc064d9f2859f7bff889729002':
Replaced usages of Unsafe in UnsignedBytes with standard Java
3 files changed, 5 insertions, 163 deletions
diff --git a/guava-tests/benchmark/com/google/common/primitives/UnsignedBytesBenchmark.java b/guava-tests/benchmark/com/google/common/primitives/UnsignedBytesBenchmark.java index 19511fc10..9b1cac270 100644 --- a/guava-tests/benchmark/com/google/common/primitives/UnsignedBytesBenchmark.java +++ b/guava-tests/benchmark/com/google/common/primitives/UnsignedBytesBenchmark.java @@ -36,7 +36,6 @@ public class UnsignedBytesBenchmark { private byte[] ba3; private byte[] ba4; private Comparator<byte[]> javaImpl; - private Comparator<byte[]> unsafeImpl; // 4, 8, 64, 1K, 1M, 1M (unaligned), 64M, 64M (unaligned) //@Param({"4", "8", "64", "1024", "1048576", "1048577", "6710884", "6710883"}) @@ -56,8 +55,6 @@ public class UnsignedBytesBenchmark { ba4[ba1.length - 1] = (byte) 42; javaImpl = UnsignedBytes.lexicographicalComparatorJavaImpl(); - unsafeImpl = - UnsignedBytes.LexicographicalComparatorHolder.UnsafeComparator.INSTANCE; } @Benchmark void longEqualJava(int reps) { @@ -68,14 +65,6 @@ public class UnsignedBytesBenchmark { } } - @Benchmark void longEqualUnsafe(int reps) { - for (int i = 0; i < reps; ++i) { - if (unsafeImpl.compare(ba1, ba2) != 0) { - throw new Error(); // deoptimization - } - } - } - @Benchmark void diffLastJava(int reps) { for (int i = 0; i < reps; ++i) { if (javaImpl.compare(ba3, ba4) == 0) { @@ -84,14 +73,6 @@ public class UnsignedBytesBenchmark { } } - @Benchmark void diffLastUnsafe(int reps) { - for (int i = 0; i < reps; ++i) { - if (unsafeImpl.compare(ba3, ba4) == 0) { - throw new Error(); // deoptimization - } - } - } - /* try { UnsignedBytesBenchmark bench = new UnsignedBytesBenchmark(); diff --git a/guava-tests/test/com/google/common/primitives/UnsignedBytesTest.java b/guava-tests/test/com/google/common/primitives/UnsignedBytesTest.java index 575eb7e73..c74e8a215 100644 --- a/guava-tests/test/com/google/common/primitives/UnsignedBytesTest.java +++ b/guava-tests/test/com/google/common/primitives/UnsignedBytesTest.java @@ -226,9 +226,9 @@ public class UnsignedBytesTest extends TestCase { public void testLexicographicalComparatorDefaultChoice() { Comparator<byte[]> defaultComparator = UnsignedBytes.lexicographicalComparator(); - Comparator<byte[]> unsafeComparator = - UnsignedBytes.LexicographicalComparatorHolder.UnsafeComparator.INSTANCE; - assertSame(defaultComparator, unsafeComparator); + Comparator<byte[]> pureJavaComparator = + UnsignedBytes.LexicographicalComparatorHolder.PureJavaComparator.INSTANCE; + assertSame(defaultComparator, pureJavaComparator); } public void testLexicographicalComparator() { diff --git a/guava/src/com/google/common/primitives/UnsignedBytes.java b/guava/src/com/google/common/primitives/UnsignedBytes.java index cc16b0c81..6177043b6 100644 --- a/guava/src/com/google/common/primitives/UnsignedBytes.java +++ b/guava/src/com/google/common/primitives/UnsignedBytes.java @@ -22,9 +22,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.Beta; import com.google.common.annotations.VisibleForTesting; -import sun.misc.Unsafe; - -import java.nio.ByteOrder; import java.util.Comparator; /** @@ -281,130 +278,12 @@ public final class UnsignedBytes { } /** - * Provides a lexicographical comparator implementation; either a Java - * implementation or a faster implementation based on {@link Unsafe}. - * - * <p>Uses reflection to gracefully fall back to the Java implementation if - * {@code Unsafe} isn't available. + * Provides a pure Java lexicographical comparator implementation. */ @VisibleForTesting static class LexicographicalComparatorHolder { - static final String UNSAFE_COMPARATOR_NAME = - LexicographicalComparatorHolder.class.getName() + "$UnsafeComparator"; - - static final Comparator<byte[]> BEST_COMPARATOR = getBestComparator(); - - @VisibleForTesting - enum UnsafeComparator implements Comparator<byte[]> { - INSTANCE; - - static final boolean BIG_ENDIAN = - ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN); - - /* - * The following static final fields exist for performance reasons. - * - * In UnsignedBytesBenchmark, accessing the following objects via static - * final fields is the fastest (more than twice as fast as the Java - * implementation, vs ~1.5x with non-final static fields, on x86_32) - * under the Hotspot server compiler. The reason is obviously that the - * non-final fields need to be reloaded inside the loop. - * - * And, no, defining (final or not) local variables out of the loop still - * isn't as good because the null check on the theUnsafe object remains - * inside the loop and BYTE_ARRAY_BASE_OFFSET doesn't get - * constant-folded. - * - * The compiler can treat static final fields as compile-time constants - * and can constant-fold them while (final or not) local variables are - * run time values. - */ - - static final Unsafe theUnsafe; - - /** The offset to the first element in a byte array. */ - static final int BYTE_ARRAY_BASE_OFFSET; - static { - theUnsafe = getUnsafe(); - - BYTE_ARRAY_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class); - - // sanity check - this should never fail - if (theUnsafe.arrayIndexScale(byte[].class) != 1) { - throw new AssertionError(); - } - } - - /** - * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package. - * Replace with a simple call to Unsafe.getUnsafe when integrating - * into a jdk. - * - * @return a sun.misc.Unsafe - */ - private static sun.misc.Unsafe getUnsafe() { - try { - return sun.misc.Unsafe.getUnsafe(); - } catch (SecurityException tryReflectionInstead) {} - try { - return java.security.AccessController.doPrivileged - (new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() { - public sun.misc.Unsafe run() throws Exception { - Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class; - for (java.lang.reflect.Field f : k.getDeclaredFields()) { - f.setAccessible(true); - Object x = f.get(null); - if (k.isInstance(x)) - return k.cast(x); - } - throw new NoSuchFieldError("the Unsafe"); - }}); - } catch (java.security.PrivilegedActionException e) { - throw new RuntimeException("Could not initialize intrinsics", - e.getCause()); - } - } - - @Override public int compare(byte[] left, byte[] right) { - int minLength = Math.min(left.length, right.length); - int minWords = minLength / Longs.BYTES; - - /* - * Compare 8 bytes at a time. Benchmarking shows comparing 8 bytes at a - * time is no slower than comparing 4 bytes at a time even on 32-bit. - * On the other hand, it is substantially faster on 64-bit. - */ - for (int i = 0; i < minWords * Longs.BYTES; i += Longs.BYTES) { - long lw = theUnsafe.getLong(left, BYTE_ARRAY_BASE_OFFSET + (long) i); - long rw = theUnsafe.getLong(right, BYTE_ARRAY_BASE_OFFSET + (long) i); - if (lw != rw) { - if (BIG_ENDIAN) { - return UnsignedLongs.compare(lw, rw); - } - - /* - * We want to compare only the first index where left[index] != right[index]. - * This corresponds to the least significant nonzero byte in lw ^ rw, since lw - * and rw are little-endian. Long.numberOfTrailingZeros(diff) tells us the least - * significant nonzero bit, and zeroing out the first three bits of L.nTZ gives us the - * shift to get that least significant nonzero byte. - */ - int n = Long.numberOfTrailingZeros(lw ^ rw) & ~0x7; - return (int) (((lw >>> n) & UNSIGNED_MASK) - ((rw >>> n) & UNSIGNED_MASK)); - } - } - - // The epilogue to cover the last (minLength % 8) elements. - for (int i = minWords * Longs.BYTES; i < minLength; i++) { - int result = UnsignedBytes.compare(left[i], right[i]); - if (result != 0) { - return result; - } - } - return left.length - right.length; - } - } + static final Comparator<byte[]> BEST_COMPARATOR = lexicographicalComparatorJavaImpl(); enum PureJavaComparator implements Comparator<byte[]> { INSTANCE; @@ -420,23 +299,5 @@ public final class UnsignedBytes { return left.length - right.length; } } - - /** - * Returns the Unsafe-using Comparator, or falls back to the pure-Java - * implementation if unable to do so. - */ - static Comparator<byte[]> getBestComparator() { - try { - Class<?> theClass = Class.forName(UNSAFE_COMPARATOR_NAME); - - // yes, UnsafeComparator does implement Comparator<byte[]> - @SuppressWarnings("unchecked") - Comparator<byte[]> comparator = - (Comparator<byte[]>) theClass.getEnumConstants()[0]; - return comparator; - } catch (Throwable t) { // ensure we really catch *everything* - return lexicographicalComparatorJavaImpl(); - } - } } } |