| 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 308c69e95897fd7d56aed7a5dbed00cf78effbb8..5b80d405ebda7c11b8fc524b62b2d67cd4900d9d 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,18 +30,16 @@
|
|
|
| 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
|
| @@ -79,7 +77,6 @@ import java.util.logging.Logger;
|
| */
|
| // 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
|
| @@ -237,7 +234,7 @@ final class Utf8 {
|
| // fallback to more lenient behavior.
|
|
|
| static class UnpairedSurrogateException extends IllegalArgumentException {
|
| - private UnpairedSurrogateException(int index, int length) {
|
| + UnpairedSurrogateException(int index, int length) {
|
| super("Unpaired surrogate at index " + index + " of " + length);
|
| }
|
| }
|
| @@ -991,23 +988,11 @@ 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 AVAILABLE;
|
| + return hasUnsafeArrayOperations() && hasUnsafeByteBufferOperations();
|
| }
|
|
|
| @Override
|
| @@ -1016,8 +1001,8 @@ final class Utf8 {
|
| throw new ArrayIndexOutOfBoundsException(
|
| String.format("Array length=%d, index=%d, limit=%d", bytes.length, index, limit));
|
| }
|
| - long offset = ARRAY_BASE_OFFSET + index;
|
| - final long offsetLimit = ARRAY_BASE_OFFSET + limit;
|
| + long offset = getArrayBaseOffset() + index;
|
| + final long offsetLimit = getArrayBaseOffset() + limit;
|
| if (state != COMPLETE) {
|
| // The previous decoding operation was incomplete (or malformed).
|
| // We look for a well-formed sequence consisting of bytes from
|
| @@ -1038,7 +1023,7 @@ final class Utf8 {
|
| // leading position and overlong 2-byte form.
|
| if (byte1 < (byte) 0xC2
|
| // byte2 trailing-byte test
|
| - || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF) {
|
| + || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) {
|
| return MALFORMED;
|
| }
|
| } else if (byte1 < (byte) 0xF0) {
|
| @@ -1047,7 +1032,7 @@ final class Utf8 {
|
| // Get byte2 from saved state or array
|
| int byte2 = (byte) ~(state >> 8);
|
| if (byte2 == 0) {
|
| - byte2 = UNSAFE.getByte(bytes, offset++);
|
| + byte2 = UnsafeUtil.getByte(bytes, offset++);
|
| if (offset >= offsetLimit) {
|
| return incompleteStateFor(byte1, byte2);
|
| }
|
| @@ -1058,7 +1043,7 @@ final class Utf8 {
|
| // illegal surrogate codepoint?
|
| || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
|
| // byte3 trailing-byte test
|
| - || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF) {
|
| + || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) {
|
| return MALFORMED;
|
| }
|
| } else {
|
| @@ -1068,7 +1053,7 @@ final class Utf8 {
|
| int byte2 = (byte) ~(state >> 8);
|
| int byte3 = 0;
|
| if (byte2 == 0) {
|
| - byte2 = UNSAFE.getByte(bytes, offset++);
|
| + byte2 = UnsafeUtil.getByte(bytes, offset++);
|
| if (offset >= offsetLimit) {
|
| return incompleteStateFor(byte1, byte2);
|
| }
|
| @@ -1076,7 +1061,7 @@ final class Utf8 {
|
| byte3 = (byte) (state >> 16);
|
| }
|
| if (byte3 == 0) {
|
| - byte3 = UNSAFE.getByte(bytes, offset++);
|
| + byte3 = UnsafeUtil.getByte(bytes, offset++);
|
| if (offset >= offsetLimit) {
|
| return incompleteStateFor(byte1, byte2, byte3);
|
| }
|
| @@ -1095,7 +1080,7 @@ final class Utf8 {
|
| // byte3 trailing-byte test
|
| || byte3 > (byte) 0xBF
|
| // byte4 trailing-byte test
|
| - || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF) {
|
| + || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) {
|
| return MALFORMED;
|
| }
|
| }
|
| @@ -1134,7 +1119,7 @@ final class Utf8 {
|
| // leading position and overlong 2-byte form.
|
| if (byte1 < (byte) 0xC2
|
| // byte2 trailing-byte test
|
| - || UNSAFE.getByte(address++) > (byte) 0xBF) {
|
| + || UnsafeUtil.getByte(address++) > (byte) 0xBF) {
|
| return MALFORMED;
|
| }
|
| } else if (byte1 < (byte) 0xF0) {
|
| @@ -1143,7 +1128,7 @@ final class Utf8 {
|
| // Get byte2 from saved state or array
|
| int byte2 = (byte) ~(state >> 8);
|
| if (byte2 == 0) {
|
| - byte2 = UNSAFE.getByte(address++);
|
| + byte2 = UnsafeUtil.getByte(address++);
|
| if (address >= addressLimit) {
|
| return incompleteStateFor(byte1, byte2);
|
| }
|
| @@ -1154,7 +1139,7 @@ final class Utf8 {
|
| // illegal surrogate codepoint?
|
| || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
|
| // byte3 trailing-byte test
|
| - || UNSAFE.getByte(address++) > (byte) 0xBF) {
|
| + || UnsafeUtil.getByte(address++) > (byte) 0xBF) {
|
| return MALFORMED;
|
| }
|
| } else {
|
| @@ -1164,7 +1149,7 @@ final class Utf8 {
|
| int byte2 = (byte) ~(state >> 8);
|
| int byte3 = 0;
|
| if (byte2 == 0) {
|
| - byte2 = UNSAFE.getByte(address++);
|
| + byte2 = UnsafeUtil.getByte(address++);
|
| if (address >= addressLimit) {
|
| return incompleteStateFor(byte1, byte2);
|
| }
|
| @@ -1172,7 +1157,7 @@ final class Utf8 {
|
| byte3 = (byte) (state >> 16);
|
| }
|
| if (byte3 == 0) {
|
| - byte3 = UNSAFE.getByte(address++);
|
| + byte3 = UnsafeUtil.getByte(address++);
|
| if (address >= addressLimit) {
|
| return incompleteStateFor(byte1, byte2, byte3);
|
| }
|
| @@ -1191,7 +1176,7 @@ final class Utf8 {
|
| // byte3 trailing-byte test
|
| || byte3 > (byte) 0xBF
|
| // byte4 trailing-byte test
|
| - || UNSAFE.getByte(address++) > (byte) 0xBF) {
|
| + || UnsafeUtil.getByte(address++) > (byte) 0xBF) {
|
| return MALFORMED;
|
| }
|
| }
|
| @@ -1202,7 +1187,7 @@ final class Utf8 {
|
|
|
| @Override
|
| int encodeUtf8(final CharSequence in, final byte[] out, final int offset, final int length) {
|
| - long outIx = ARRAY_BASE_OFFSET + offset;
|
| + long outIx = getArrayBaseOffset() + offset;
|
| final long outLimit = outIx + length;
|
| final int inLimit = in.length();
|
| if (inLimit > length || out.length - length < offset) {
|
| @@ -1215,25 +1200,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) {
|
| - UNSAFE.putByte(out, outIx++, (byte) c);
|
| + UnsafeUtil.putByte(out, outIx++, (byte) c);
|
| }
|
| if (inIx == inLimit) {
|
| // We're done, it was ASCII encoded.
|
| - return (int) (outIx - ARRAY_BASE_OFFSET);
|
| + return (int) (outIx - getArrayBaseOffset());
|
| }
|
|
|
| for (char c; inIx < inLimit; ++inIx) {
|
| c = in.charAt(inIx);
|
| if (c < 0x80 && outIx < outLimit) {
|
| - UNSAFE.putByte(out, outIx++, (byte) c);
|
| + UnsafeUtil.putByte(out, outIx++, (byte) c);
|
| } else if (c < 0x800 && outIx <= outLimit - 2L) { // 11 bits, two UTF-8 bytes
|
| - UNSAFE.putByte(out, outIx++, (byte) ((0xF << 6) | (c >>> 6)));
|
| - UNSAFE.putByte(out, outIx++, (byte) (0x80 | (0x3F & c)));
|
| + UnsafeUtil.putByte(out, outIx++, (byte) ((0xF << 6) | (c >>> 6)));
|
| + UnsafeUtil.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
|
| - 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)));
|
| + 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)));
|
| } else if (outIx <= outLimit - 4L) {
|
| // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8
|
| // bytes
|
| @@ -1242,10 +1227,10 @@ final class Utf8 {
|
| throw new UnpairedSurrogateException((inIx - 1), inLimit);
|
| }
|
| int codePoint = toCodePoint(c, low);
|
| - 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)));
|
| + 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)));
|
| } else {
|
| if ((MIN_SURROGATE <= c && c <= MAX_SURROGATE)
|
| && (inIx + 1 == inLimit || !isSurrogatePair(c, in.charAt(inIx + 1)))) {
|
| @@ -1258,7 +1243,7 @@ final class Utf8 {
|
| }
|
|
|
| // All bytes have been encoded.
|
| - return (int) (outIx - ARRAY_BASE_OFFSET);
|
| + return (int) (outIx - getArrayBaseOffset());
|
| }
|
|
|
| @Override
|
| @@ -1277,7 +1262,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) {
|
| - UNSAFE.putByte(outIx++, (byte) c);
|
| + UnsafeUtil.putByte(outIx++, (byte) c);
|
| }
|
| if (inIx == inLimit) {
|
| // We're done, it was ASCII encoded.
|
| @@ -1288,15 +1273,15 @@ final class Utf8 {
|
| for (char c; inIx < inLimit; ++inIx) {
|
| c = in.charAt(inIx);
|
| if (c < 0x80 && outIx < outLimit) {
|
| - UNSAFE.putByte(outIx++, (byte) c);
|
| + UnsafeUtil.putByte(outIx++, (byte) c);
|
| } else if (c < 0x800 && outIx <= outLimit - 2L) { // 11 bits, two UTF-8 bytes
|
| - UNSAFE.putByte(outIx++, (byte) ((0xF << 6) | (c >>> 6)));
|
| - UNSAFE.putByte(outIx++, (byte) (0x80 | (0x3F & c)));
|
| + UnsafeUtil.putByte(outIx++, (byte) ((0xF << 6) | (c >>> 6)));
|
| + UnsafeUtil.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
|
| - UNSAFE.putByte(outIx++, (byte) ((0xF << 5) | (c >>> 12)));
|
| - UNSAFE.putByte(outIx++, (byte) (0x80 | (0x3F & (c >>> 6))));
|
| - UNSAFE.putByte(outIx++, (byte) (0x80 | (0x3F & c)));
|
| + UnsafeUtil.putByte(outIx++, (byte) ((0xF << 5) | (c >>> 12)));
|
| + UnsafeUtil.putByte(outIx++, (byte) (0x80 | (0x3F & (c >>> 6))));
|
| + UnsafeUtil.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
|
| @@ -1305,10 +1290,10 @@ final class Utf8 {
|
| throw new UnpairedSurrogateException((inIx - 1), inLimit);
|
| }
|
| int codePoint = toCodePoint(c, low);
|
| - 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)));
|
| + 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)));
|
| } else {
|
| if ((MIN_SURROGATE <= c && c <= MAX_SURROGATE)
|
| && (inIx + 1 == inLimit || !isSurrogatePair(c, in.charAt(inIx + 1)))) {
|
| @@ -1349,7 +1334,7 @@ final class Utf8 {
|
| // we're 8-byte aligned.
|
| final int unaligned = (int) offset & 7;
|
| for (int j = unaligned; j > 0; j--) {
|
| - if (UNSAFE.getByte(bytes, offset++) < 0) {
|
| + if (UnsafeUtil.getByte(bytes, offset++) < 0) {
|
| return unaligned - j;
|
| }
|
| }
|
| @@ -1358,7 +1343,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 && (UNSAFE.getLong(bytes, offset) & ASCII_MASK_LONG) == 0;
|
| + for (; remaining >= 8 && (UnsafeUtil.getLong(bytes, offset) & ASCII_MASK_LONG) == 0;
|
| offset += 8, remaining -= 8) {}
|
| return maxChars - remaining;
|
| }
|
| @@ -1379,7 +1364,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 (UNSAFE.getByte(address++) < 0) {
|
| + if (UnsafeUtil.getByte(address++) < 0) {
|
| return unaligned - j;
|
| }
|
| }
|
| @@ -1388,7 +1373,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 && (UNSAFE.getLong(address) & ASCII_MASK_LONG) == 0;
|
| + for (; remaining >= 8 && (UnsafeUtil.getLong(address) & ASCII_MASK_LONG) == 0;
|
| address += 8, remaining -= 8) {}
|
| return maxChars - remaining;
|
| }
|
| @@ -1404,7 +1389,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 = UNSAFE.getByte(bytes, offset++)) >= 0; --remaining) {
|
| + for (; remaining > 0 && (byte1 = UnsafeUtil.getByte(bytes, offset++)) >= 0; --remaining) {
|
| }
|
| if (remaining == 0) {
|
| return COMPLETE;
|
| @@ -1423,7 +1408,7 @@ final class Utf8 {
|
| // Simultaneously checks for illegal trailing-byte in
|
| // leading position and overlong 2-byte form.
|
| if (byte1 < (byte) 0xC2
|
| - || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF) {
|
| + || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) {
|
| return MALFORMED;
|
| }
|
| } else if (byte1 < (byte) 0xF0) {
|
| @@ -1435,13 +1420,13 @@ final class Utf8 {
|
| remaining -= 2;
|
|
|
| final int byte2;
|
| - if ((byte2 = UNSAFE.getByte(bytes, offset++)) > (byte) 0xBF
|
| + if ((byte2 = UnsafeUtil.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
|
| - || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF) {
|
| + || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) {
|
| return MALFORMED;
|
| }
|
| } else {
|
| @@ -1453,16 +1438,16 @@ final class Utf8 {
|
| remaining -= 3;
|
|
|
| final int byte2;
|
| - if ((byte2 = UNSAFE.getByte(bytes, offset++)) > (byte) 0xBF
|
| + if ((byte2 = UnsafeUtil.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
|
| - || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF
|
| + || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF
|
| // byte4 trailing-byte test
|
| - || UNSAFE.getByte(bytes, offset++) > (byte) 0xBF) {
|
| + || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) {
|
| return MALFORMED;
|
| }
|
| }
|
| @@ -1480,7 +1465,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 = UNSAFE.getByte(address++)) >= 0; --remaining) {
|
| + for (; remaining > 0 && (byte1 = UnsafeUtil.getByte(address++)) >= 0; --remaining) {
|
| }
|
| if (remaining == 0) {
|
| return COMPLETE;
|
| @@ -1498,7 +1483,7 @@ final class Utf8 {
|
|
|
| // Simultaneously checks for illegal trailing-byte in
|
| // leading position and overlong 2-byte form.
|
| - if (byte1 < (byte) 0xC2 || UNSAFE.getByte(address++) > (byte) 0xBF) {
|
| + if (byte1 < (byte) 0xC2 || UnsafeUtil.getByte(address++) > (byte) 0xBF) {
|
| return MALFORMED;
|
| }
|
| } else if (byte1 < (byte) 0xF0) {
|
| @@ -1510,14 +1495,14 @@ final class Utf8 {
|
| }
|
| remaining -= 2;
|
|
|
| - final byte byte2 = UNSAFE.getByte(address++);
|
| + final byte byte2 = UnsafeUtil.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
|
| - || UNSAFE.getByte(address++) > (byte) 0xBF) {
|
| + || UnsafeUtil.getByte(address++) > (byte) 0xBF) {
|
| return MALFORMED;
|
| }
|
| } else {
|
| @@ -1529,7 +1514,7 @@ final class Utf8 {
|
| }
|
| remaining -= 3;
|
|
|
| - final byte byte2 = UNSAFE.getByte(address++);
|
| + final byte byte2 = UnsafeUtil.getByte(address++);
|
| if (byte2 > (byte) 0xBF
|
| // Check that 1 <= plane <= 16. Tricky optimized form of:
|
| // if (byte1 > (byte) 0xF4 ||
|
| @@ -1537,9 +1522,9 @@ final class Utf8 {
|
| // byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
|
| || (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
|
| // byte3 trailing-byte test
|
| - || UNSAFE.getByte(address++) > (byte) 0xBF
|
| + || UnsafeUtil.getByte(address++) > (byte) 0xBF
|
| // byte4 trailing-byte test
|
| - || UNSAFE.getByte(address++) > (byte) 0xBF) {
|
| + || UnsafeUtil.getByte(address++) > (byte) 0xBF) {
|
| return MALFORMED;
|
| }
|
| }
|
| @@ -1553,11 +1538,11 @@ final class Utf8 {
|
| return incompleteStateFor(byte1);
|
| }
|
| case 1: {
|
| - return incompleteStateFor(byte1, UNSAFE.getByte(bytes, offset));
|
| + return incompleteStateFor(byte1, UnsafeUtil.getByte(bytes, offset));
|
| }
|
| case 2: {
|
| - return incompleteStateFor(byte1, UNSAFE.getByte(bytes, offset),
|
| - UNSAFE.getByte(bytes, offset + 1));
|
| + return incompleteStateFor(byte1, UnsafeUtil.getByte(bytes, offset),
|
| + UnsafeUtil.getByte(bytes, offset + 1));
|
| }
|
| default: {
|
| throw new AssertionError();
|
| @@ -1571,112 +1556,17 @@ final class Utf8 {
|
| return incompleteStateFor(byte1);
|
| }
|
| case 1: {
|
| - return incompleteStateFor(byte1, UNSAFE.getByte(address));
|
| + return incompleteStateFor(byte1, UnsafeUtil.getByte(address));
|
| }
|
| case 2: {
|
| - return incompleteStateFor(byte1, UNSAFE.getByte(address), UNSAFE.getByte(address + 1));
|
| + return incompleteStateFor(byte1, UnsafeUtil.getByte(address),
|
| + UnsafeUtil.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() {}
|
|
|