aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Duffin <paulduffin@google.com>2015-02-27 17:16:12 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2015-02-27 17:16:12 +0000
commit5b9b416a211d8d2ac2012aaad1b77f79ffe7617c (patch)
tree85e50fb7fe39e68a08f2478fcc19886431d4d192
parenta1a9bcff09484f374ee7fa11a5ce38c48463b651 (diff)
parent0c29232f9e0a18dc064d9f2859f7bff889729002 (diff)
downloadguava-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
-rw-r--r--guava-tests/benchmark/com/google/common/primitives/UnsignedBytesBenchmark.java19
-rw-r--r--guava-tests/test/com/google/common/primitives/UnsignedBytesTest.java6
-rw-r--r--guava/src/com/google/common/primitives/UnsignedBytes.java143
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();
- }
- }
}
}