Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(501)

Unified Diff: third_party/protobuf/java/core/src/main/java/com/google/protobuf/Utf8.java

Issue 2600753002: Reverts third_party/protobuf: Update to HEAD (f52e188fe4) (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/protobuf/java/core/src/main/java/com/google/protobuf/Utf8.java
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Utf8.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Utf8.java
index 5b80d405ebda7c11b8fc524b62b2d67cd4900d9d..308c69e95897fd7d56aed7a5dbed00cf78effbb8 100644
--- a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Utf8.java
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Utf8.java
@@ -30,16 +30,18 @@
package com.google.protobuf;
-import static com.google.protobuf.UnsafeUtil.addressOffset;
-import static com.google.protobuf.UnsafeUtil.getArrayBaseOffset;
-import static com.google.protobuf.UnsafeUtil.hasUnsafeArrayOperations;
-import static com.google.protobuf.UnsafeUtil.hasUnsafeByteBufferOperations;
import static java.lang.Character.MAX_SURROGATE;
import static java.lang.Character.MIN_SURROGATE;
import static java.lang.Character.isSurrogatePair;
import static java.lang.Character.toCodePoint;
+import java.lang.reflect.Field;
+import java.nio.Buffer;
import java.nio.ByteBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+import java.util.logging.Level;
+import java.util.logging.Logger;
/**
* A set of low-level, high-performance static utility methods related
@@ -77,6 +79,7 @@ import java.nio.ByteBuffer;
*/
// TODO(nathanmittler): Copy changes in this class back to Guava
final class Utf8 {
+ private static final Logger logger = Logger.getLogger(Utf8.class.getName());
/**
* UTF-8 is a runtime hot spot so we attempt to provide heavily optimized implementations
@@ -234,7 +237,7 @@ final class Utf8 {
// fallback to more lenient behavior.
static class UnpairedSurrogateException extends IllegalArgumentException {
- UnpairedSurrogateException(int index, int length) {
+ private UnpairedSurrogateException(int index, int length) {
super("Unpaired surrogate at index " + index + " of " + length);
}
}
@@ -988,11 +991,23 @@ final class Utf8 {
* {@link Processor} that uses {@code sun.misc.Unsafe} where possible to improve performance.
*/
static final class UnsafeProcessor extends Processor {
+ private static final sun.misc.Unsafe UNSAFE = getUnsafe();
+ private static final long BUFFER_ADDRESS_OFFSET =
+ fieldOffset(field(Buffer.class, "address"));
+ private static final int ARRAY_BASE_OFFSET = byteArrayBaseOffset();
+
+ /**
+ * We only use Unsafe operations if we have access to direct {@link ByteBuffer}'s address
+ * and the array base offset is a multiple of 8 (needed by Unsafe.getLong()).
+ */
+ private static final boolean AVAILABLE =
+ BUFFER_ADDRESS_OFFSET != -1 && ARRAY_BASE_OFFSET % 8 == 0;
+
/**
* Indicates whether or not all required unsafe operations are supported on this platform.
*/
static boolean isAvailable() {
- return hasUnsafeArrayOperations() && hasUnsafeByteBufferOperations();
+ return AVAILABLE;
}
@Override
@@ -1001,8 +1016,8 @@ final class Utf8 {
throw new ArrayIndexOutOfBoundsException(
String.format("Array length=%d, index=%d, limit=%d", bytes.length, index, limit));
}
- long offset = getArrayBaseOffset() + index;
- final long offsetLimit = getArrayBaseOffset() + limit;
+ long offset = ARRAY_BASE_OFFSET + index;
+ final long offsetLimit = ARRAY_BASE_OFFSET + limit;
if (state != COMPLETE) {
// The previous decoding operation was incomplete (or malformed).
// We look for a well-formed sequence consisting of bytes from
@@ -1023,7 +1038,7 @@ final class Utf8 {
// leading position and overlong 2-byte form.
if (byte1 < (byte) 0xC2
// byte2 trailing-byte test
- || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) {
+ || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF) {
return MALFORMED;
}
} else if (byte1 < (byte) 0xF0) {
@@ -1032,7 +1047,7 @@ final class Utf8 {
// Get byte2 from saved state or array
int byte2 = (byte) ~(state >> 8);
if (byte2 == 0) {
- byte2 = UnsafeUtil.getByte(bytes, offset++);
+ byte2 = UNSAFE.getByte(bytes, offset++);
if (offset >= offsetLimit) {
return incompleteStateFor(byte1, byte2);
}
@@ -1043,7 +1058,7 @@ final class Utf8 {
// illegal surrogate codepoint?
|| (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
// byte3 trailing-byte test
- || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) {
+ || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF) {
return MALFORMED;
}
} else {
@@ -1053,7 +1068,7 @@ final class Utf8 {
int byte2 = (byte) ~(state >> 8);
int byte3 = 0;
if (byte2 == 0) {
- byte2 = UnsafeUtil.getByte(bytes, offset++);
+ byte2 = UNSAFE.getByte(bytes, offset++);
if (offset >= offsetLimit) {
return incompleteStateFor(byte1, byte2);
}
@@ -1061,7 +1076,7 @@ final class Utf8 {
byte3 = (byte) (state >> 16);
}
if (byte3 == 0) {
- byte3 = UnsafeUtil.getByte(bytes, offset++);
+ byte3 = UNSAFE.getByte(bytes, offset++);
if (offset >= offsetLimit) {
return incompleteStateFor(byte1, byte2, byte3);
}
@@ -1080,7 +1095,7 @@ final class Utf8 {
// byte3 trailing-byte test
|| byte3 > (byte) 0xBF
// byte4 trailing-byte test
- || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) {
+ || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF) {
return MALFORMED;
}
}
@@ -1119,7 +1134,7 @@ final class Utf8 {
// leading position and overlong 2-byte form.
if (byte1 < (byte) 0xC2
// byte2 trailing-byte test
- || UnsafeUtil.getByte(address++) > (byte) 0xBF) {
+ || UNSAFE.getByte(address++) > (byte) 0xBF) {
return MALFORMED;
}
} else if (byte1 < (byte) 0xF0) {
@@ -1128,7 +1143,7 @@ final class Utf8 {
// Get byte2 from saved state or array
int byte2 = (byte) ~(state >> 8);
if (byte2 == 0) {
- byte2 = UnsafeUtil.getByte(address++);
+ byte2 = UNSAFE.getByte(address++);
if (address >= addressLimit) {
return incompleteStateFor(byte1, byte2);
}
@@ -1139,7 +1154,7 @@ final class Utf8 {
// illegal surrogate codepoint?
|| (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
// byte3 trailing-byte test
- || UnsafeUtil.getByte(address++) > (byte) 0xBF) {
+ || UNSAFE.getByte(address++) > (byte) 0xBF) {
return MALFORMED;
}
} else {
@@ -1149,7 +1164,7 @@ final class Utf8 {
int byte2 = (byte) ~(state >> 8);
int byte3 = 0;
if (byte2 == 0) {
- byte2 = UnsafeUtil.getByte(address++);
+ byte2 = UNSAFE.getByte(address++);
if (address >= addressLimit) {
return incompleteStateFor(byte1, byte2);
}
@@ -1157,7 +1172,7 @@ final class Utf8 {
byte3 = (byte) (state >> 16);
}
if (byte3 == 0) {
- byte3 = UnsafeUtil.getByte(address++);
+ byte3 = UNSAFE.getByte(address++);
if (address >= addressLimit) {
return incompleteStateFor(byte1, byte2, byte3);
}
@@ -1176,7 +1191,7 @@ final class Utf8 {
// byte3 trailing-byte test
|| byte3 > (byte) 0xBF
// byte4 trailing-byte test
- || UnsafeUtil.getByte(address++) > (byte) 0xBF) {
+ || UNSAFE.getByte(address++) > (byte) 0xBF) {
return MALFORMED;
}
}
@@ -1187,7 +1202,7 @@ final class Utf8 {
@Override
int encodeUtf8(final CharSequence in, final byte[] out, final int offset, final int length) {
- long outIx = getArrayBaseOffset() + offset;
+ long outIx = ARRAY_BASE_OFFSET + offset;
final long outLimit = outIx + length;
final int inLimit = in.length();
if (inLimit > length || out.length - length < offset) {
@@ -1200,25 +1215,25 @@ final class Utf8 {
// https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
int inIx = 0;
for (char c; inIx < inLimit && (c = in.charAt(inIx)) < 0x80; ++inIx) {
- UnsafeUtil.putByte(out, outIx++, (byte) c);
+ UNSAFE.putByte(out, outIx++, (byte) c);
}
if (inIx == inLimit) {
// We're done, it was ASCII encoded.
- return (int) (outIx - getArrayBaseOffset());
+ return (int) (outIx - ARRAY_BASE_OFFSET);
}
for (char c; inIx < inLimit; ++inIx) {
c = in.charAt(inIx);
if (c < 0x80 && outIx < outLimit) {
- UnsafeUtil.putByte(out, outIx++, (byte) c);
+ UNSAFE.putByte(out, outIx++, (byte) c);
} else if (c < 0x800 && outIx <= outLimit - 2L) { // 11 bits, two UTF-8 bytes
- UnsafeUtil.putByte(out, outIx++, (byte) ((0xF << 6) | (c >>> 6)));
- UnsafeUtil.putByte(out, outIx++, (byte) (0x80 | (0x3F & c)));
+ UNSAFE.putByte(out, outIx++, (byte) ((0xF << 6) | (c >>> 6)));
+ UNSAFE.putByte(out, outIx++, (byte) (0x80 | (0x3F & c)));
} else if ((c < MIN_SURROGATE || MAX_SURROGATE < c) && outIx <= outLimit - 3L) {
// Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
- UnsafeUtil.putByte(out, outIx++, (byte) ((0xF << 5) | (c >>> 12)));
- UnsafeUtil.putByte(out, outIx++, (byte) (0x80 | (0x3F & (c >>> 6))));
- UnsafeUtil.putByte(out, outIx++, (byte) (0x80 | (0x3F & c)));
+ UNSAFE.putByte(out, outIx++, (byte) ((0xF << 5) | (c >>> 12)));
+ UNSAFE.putByte(out, outIx++, (byte) (0x80 | (0x3F & (c >>> 6))));
+ UNSAFE.putByte(out, outIx++, (byte) (0x80 | (0x3F & c)));
} else if (outIx <= outLimit - 4L) {
// Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8
// bytes
@@ -1227,10 +1242,10 @@ final class Utf8 {
throw new UnpairedSurrogateException((inIx - 1), inLimit);
}
int codePoint = toCodePoint(c, low);
- UnsafeUtil.putByte(out, outIx++, (byte) ((0xF << 4) | (codePoint >>> 18)));
- UnsafeUtil.putByte(out, outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 12))));
- UnsafeUtil.putByte(out, outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 6))));
- UnsafeUtil.putByte(out, outIx++, (byte) (0x80 | (0x3F & codePoint)));
+ UNSAFE.putByte(out, outIx++, (byte) ((0xF << 4) | (codePoint >>> 18)));
+ UNSAFE.putByte(out, outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 12))));
+ UNSAFE.putByte(out, outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 6))));
+ UNSAFE.putByte(out, outIx++, (byte) (0x80 | (0x3F & codePoint)));
} else {
if ((MIN_SURROGATE <= c && c <= MAX_SURROGATE)
&& (inIx + 1 == inLimit || !isSurrogatePair(c, in.charAt(inIx + 1)))) {
@@ -1243,7 +1258,7 @@ final class Utf8 {
}
// All bytes have been encoded.
- return (int) (outIx - getArrayBaseOffset());
+ return (int) (outIx - ARRAY_BASE_OFFSET);
}
@Override
@@ -1262,7 +1277,7 @@ final class Utf8 {
// https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
int inIx = 0;
for (char c; inIx < inLimit && (c = in.charAt(inIx)) < 0x80; ++inIx) {
- UnsafeUtil.putByte(outIx++, (byte) c);
+ UNSAFE.putByte(outIx++, (byte) c);
}
if (inIx == inLimit) {
// We're done, it was ASCII encoded.
@@ -1273,15 +1288,15 @@ final class Utf8 {
for (char c; inIx < inLimit; ++inIx) {
c = in.charAt(inIx);
if (c < 0x80 && outIx < outLimit) {
- UnsafeUtil.putByte(outIx++, (byte) c);
+ UNSAFE.putByte(outIx++, (byte) c);
} else if (c < 0x800 && outIx <= outLimit - 2L) { // 11 bits, two UTF-8 bytes
- UnsafeUtil.putByte(outIx++, (byte) ((0xF << 6) | (c >>> 6)));
- UnsafeUtil.putByte(outIx++, (byte) (0x80 | (0x3F & c)));
+ UNSAFE.putByte(outIx++, (byte) ((0xF << 6) | (c >>> 6)));
+ UNSAFE.putByte(outIx++, (byte) (0x80 | (0x3F & c)));
} else if ((c < MIN_SURROGATE || MAX_SURROGATE < c) && outIx <= outLimit - 3L) {
// Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
- UnsafeUtil.putByte(outIx++, (byte) ((0xF << 5) | (c >>> 12)));
- UnsafeUtil.putByte(outIx++, (byte) (0x80 | (0x3F & (c >>> 6))));
- UnsafeUtil.putByte(outIx++, (byte) (0x80 | (0x3F & c)));
+ UNSAFE.putByte(outIx++, (byte) ((0xF << 5) | (c >>> 12)));
+ UNSAFE.putByte(outIx++, (byte) (0x80 | (0x3F & (c >>> 6))));
+ UNSAFE.putByte(outIx++, (byte) (0x80 | (0x3F & c)));
} else if (outIx <= outLimit - 4L) {
// Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8
// bytes
@@ -1290,10 +1305,10 @@ final class Utf8 {
throw new UnpairedSurrogateException((inIx - 1), inLimit);
}
int codePoint = toCodePoint(c, low);
- UnsafeUtil.putByte(outIx++, (byte) ((0xF << 4) | (codePoint >>> 18)));
- UnsafeUtil.putByte(outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 12))));
- UnsafeUtil.putByte(outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 6))));
- UnsafeUtil.putByte(outIx++, (byte) (0x80 | (0x3F & codePoint)));
+ UNSAFE.putByte(outIx++, (byte) ((0xF << 4) | (codePoint >>> 18)));
+ UNSAFE.putByte(outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 12))));
+ UNSAFE.putByte(outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 6))));
+ UNSAFE.putByte(outIx++, (byte) (0x80 | (0x3F & codePoint)));
} else {
if ((MIN_SURROGATE <= c && c <= MAX_SURROGATE)
&& (inIx + 1 == inLimit || !isSurrogatePair(c, in.charAt(inIx + 1)))) {
@@ -1334,7 +1349,7 @@ final class Utf8 {
// we're 8-byte aligned.
final int unaligned = (int) offset & 7;
for (int j = unaligned; j > 0; j--) {
- if (UnsafeUtil.getByte(bytes, offset++) < 0) {
+ if (UNSAFE.getByte(bytes, offset++) < 0) {
return unaligned - j;
}
}
@@ -1343,7 +1358,7 @@ final class Utf8 {
// To speed things up further, we're reading longs instead of bytes so we use a mask to
// determine if any byte in the current long is non-ASCII.
remaining -= unaligned;
- for (; remaining >= 8 && (UnsafeUtil.getLong(bytes, offset) & ASCII_MASK_LONG) == 0;
+ for (; remaining >= 8 && (UNSAFE.getLong(bytes, offset) & ASCII_MASK_LONG) == 0;
offset += 8, remaining -= 8) {}
return maxChars - remaining;
}
@@ -1364,7 +1379,7 @@ final class Utf8 {
// be read before we're 8-byte aligned.
final int unaligned = (int) address & 7;
for (int j = unaligned; j > 0; j--) {
- if (UnsafeUtil.getByte(address++) < 0) {
+ if (UNSAFE.getByte(address++) < 0) {
return unaligned - j;
}
}
@@ -1373,7 +1388,7 @@ final class Utf8 {
// To speed things up further, we're reading longs instead of bytes so we use a mask to
// determine if any byte in the current long is non-ASCII.
remaining -= unaligned;
- for (; remaining >= 8 && (UnsafeUtil.getLong(address) & ASCII_MASK_LONG) == 0;
+ for (; remaining >= 8 && (UNSAFE.getLong(address) & ASCII_MASK_LONG) == 0;
address += 8, remaining -= 8) {}
return maxChars - remaining;
}
@@ -1389,7 +1404,7 @@ final class Utf8 {
// TODO(nathanmittler): Consider checking 8 bytes at a time after some threshold?
// Maybe after seeing a few in a row that are ASCII, go back to fast mode?
int byte1 = 0;
- for (; remaining > 0 && (byte1 = UnsafeUtil.getByte(bytes, offset++)) >= 0; --remaining) {
+ for (; remaining > 0 && (byte1 = UNSAFE.getByte(bytes, offset++)) >= 0; --remaining) {
}
if (remaining == 0) {
return COMPLETE;
@@ -1408,7 +1423,7 @@ final class Utf8 {
// Simultaneously checks for illegal trailing-byte in
// leading position and overlong 2-byte form.
if (byte1 < (byte) 0xC2
- || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) {
+ || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF) {
return MALFORMED;
}
} else if (byte1 < (byte) 0xF0) {
@@ -1420,13 +1435,13 @@ final class Utf8 {
remaining -= 2;
final int byte2;
- if ((byte2 = UnsafeUtil.getByte(bytes, offset++)) > (byte) 0xBF
+ if ((byte2 = UNSAFE.getByte(bytes, offset++)) > (byte) 0xBF
// overlong? 5 most significant bits must not all be zero
|| (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
// check for illegal surrogate codepoints
|| (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
// byte3 trailing-byte test
- || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) {
+ || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF) {
return MALFORMED;
}
} else {
@@ -1438,16 +1453,16 @@ final class Utf8 {
remaining -= 3;
final int byte2;
- if ((byte2 = UnsafeUtil.getByte(bytes, offset++)) > (byte) 0xBF
+ if ((byte2 = UNSAFE.getByte(bytes, offset++)) > (byte) 0xBF
// Check that 1 <= plane <= 16. Tricky optimized form of:
// if (byte1 > (byte) 0xF4 ||
// byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
// byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
|| (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
// byte3 trailing-byte test
- || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF
+ || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF
// byte4 trailing-byte test
- || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) {
+ || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF) {
return MALFORMED;
}
}
@@ -1465,7 +1480,7 @@ final class Utf8 {
// TODO(nathanmittler): Consider checking 8 bytes at a time after some threshold?
// Maybe after seeing a few in a row that are ASCII, go back to fast mode?
int byte1 = 0;
- for (; remaining > 0 && (byte1 = UnsafeUtil.getByte(address++)) >= 0; --remaining) {
+ for (; remaining > 0 && (byte1 = UNSAFE.getByte(address++)) >= 0; --remaining) {
}
if (remaining == 0) {
return COMPLETE;
@@ -1483,7 +1498,7 @@ final class Utf8 {
// Simultaneously checks for illegal trailing-byte in
// leading position and overlong 2-byte form.
- if (byte1 < (byte) 0xC2 || UnsafeUtil.getByte(address++) > (byte) 0xBF) {
+ if (byte1 < (byte) 0xC2 || UNSAFE.getByte(address++) > (byte) 0xBF) {
return MALFORMED;
}
} else if (byte1 < (byte) 0xF0) {
@@ -1495,14 +1510,14 @@ final class Utf8 {
}
remaining -= 2;
- final byte byte2 = UnsafeUtil.getByte(address++);
+ final byte byte2 = UNSAFE.getByte(address++);
if (byte2 > (byte) 0xBF
// overlong? 5 most significant bits must not all be zero
|| (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
// check for illegal surrogate codepoints
|| (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
// byte3 trailing-byte test
- || UnsafeUtil.getByte(address++) > (byte) 0xBF) {
+ || UNSAFE.getByte(address++) > (byte) 0xBF) {
return MALFORMED;
}
} else {
@@ -1514,7 +1529,7 @@ final class Utf8 {
}
remaining -= 3;
- final byte byte2 = UnsafeUtil.getByte(address++);
+ final byte byte2 = UNSAFE.getByte(address++);
if (byte2 > (byte) 0xBF
// Check that 1 <= plane <= 16. Tricky optimized form of:
// if (byte1 > (byte) 0xF4 ||
@@ -1522,9 +1537,9 @@ final class Utf8 {
// byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
|| (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
// byte3 trailing-byte test
- || UnsafeUtil.getByte(address++) > (byte) 0xBF
+ || UNSAFE.getByte(address++) > (byte) 0xBF
// byte4 trailing-byte test
- || UnsafeUtil.getByte(address++) > (byte) 0xBF) {
+ || UNSAFE.getByte(address++) > (byte) 0xBF) {
return MALFORMED;
}
}
@@ -1538,11 +1553,11 @@ final class Utf8 {
return incompleteStateFor(byte1);
}
case 1: {
- return incompleteStateFor(byte1, UnsafeUtil.getByte(bytes, offset));
+ return incompleteStateFor(byte1, UNSAFE.getByte(bytes, offset));
}
case 2: {
- return incompleteStateFor(byte1, UnsafeUtil.getByte(bytes, offset),
- UnsafeUtil.getByte(bytes, offset + 1));
+ return incompleteStateFor(byte1, UNSAFE.getByte(bytes, offset),
+ UNSAFE.getByte(bytes, offset + 1));
}
default: {
throw new AssertionError();
@@ -1556,17 +1571,112 @@ final class Utf8 {
return incompleteStateFor(byte1);
}
case 1: {
- return incompleteStateFor(byte1, UnsafeUtil.getByte(address));
+ return incompleteStateFor(byte1, UNSAFE.getByte(address));
}
case 2: {
- return incompleteStateFor(byte1, UnsafeUtil.getByte(address),
- UnsafeUtil.getByte(address + 1));
+ return incompleteStateFor(byte1, UNSAFE.getByte(address), UNSAFE.getByte(address + 1));
}
default: {
throw new AssertionError();
}
}
}
+
+ /**
+ * Gets the field with the given name within the class, or {@code null} if not found. If
+ * found, the field is made accessible.
+ */
+ private static Field field(Class<?> clazz, String fieldName) {
+ Field field;
+ try {
+ field = clazz.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ } catch (Throwable t) {
+ // Failed to access the fields.
+ field = null;
+ }
+ logger.log(Level.FINEST, "{0}.{1}: {2}",
+ new Object[] {clazz.getName(), fieldName, (field != null ? "available" : "unavailable")});
+ return field;
+ }
+
+ /**
+ * Returns the offset of the provided field, or {@code -1} if {@code sun.misc.Unsafe} is not
+ * available.
+ */
+ private static long fieldOffset(Field field) {
+ return field == null || UNSAFE == null ? -1 : UNSAFE.objectFieldOffset(field);
+ }
+
+ /**
+ * Get the base offset for byte arrays, or {@code -1} if {@code sun.misc.Unsafe} is not
+ * available.
+ */
+ private static <T> int byteArrayBaseOffset() {
+ return UNSAFE == null ? -1 : UNSAFE.arrayBaseOffset(byte[].class);
+ }
+
+ /**
+ * Gets the offset of the {@code address} field of the given direct {@link ByteBuffer}.
+ */
+ private static long addressOffset(ByteBuffer buffer) {
+ return UNSAFE.getLong(buffer, BUFFER_ADDRESS_OFFSET);
+ }
+
+ /**
+ * Gets the {@code sun.misc.Unsafe} instance, or {@code null} if not available on this
+ * platform.
+ */
+ private static sun.misc.Unsafe getUnsafe() {
+ sun.misc.Unsafe unsafe = null;
+ try {
+ unsafe = AccessController.doPrivileged(new PrivilegedExceptionAction<sun.misc.Unsafe>() {
+ @Override
+ public sun.misc.Unsafe run() throws Exception {
+ Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
+
+ // Check that this platform supports all of the required unsafe methods.
+ checkRequiredMethods(k);
+
+ for (Field f : k.getDeclaredFields()) {
+ f.setAccessible(true);
+ Object x = f.get(null);
+ if (k.isInstance(x)) {
+ return k.cast(x);
+ }
+ }
+ // The sun.misc.Unsafe field does not exist.
+ return null;
+ }
+ });
+ } catch (Throwable e) {
+ // Catching Throwable here due to the fact that Google AppEngine raises NoClassDefFoundError
+ // for Unsafe.
+ }
+
+ logger.log(Level.FINEST, "sun.misc.Unsafe: {}",
+ unsafe != null ? "available" : "unavailable");
+ return unsafe;
+ }
+
+ /**
+ * Verifies that all required methods of {@code sun.misc.Unsafe} are available on this platform.
+ */
+ private static void checkRequiredMethods(Class<sun.misc.Unsafe> clazz)
+ throws NoSuchMethodException, SecurityException {
+ // Needed for Unsafe byte[] access
+ clazz.getMethod("arrayBaseOffset", Class.class);
+ clazz.getMethod("getByte", Object.class, long.class);
+ clazz.getMethod("putByte", Object.class, long.class, byte.class);
+ clazz.getMethod("getLong", Object.class, long.class);
+
+ // Needed for Unsafe Direct ByteBuffer access
+ clazz.getMethod("objectFieldOffset", Field.class);
+ clazz.getMethod("getByte", long.class);
+ clazz.getMethod("getLong", Object.class, long.class);
+ clazz.getMethod("putByte", long.class, byte.class);
+ clazz.getMethod("getLong", long.class);
+ }
}
private Utf8() {}

Powered by Google App Engine
This is Rietveld 408576698