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

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

Issue 2590803003: Revert "third_party/protobuf: Update to HEAD (83d681ee2c)" (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/CodedOutputStream.java
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
index 3e32c2c536a87298eb8da64f3d149d944ab96df7..ad174d0ff6049c73dfad44cc55ed02e29284fb06 100644
--- a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
@@ -30,17 +30,18 @@
package com.google.protobuf;
-import static com.google.protobuf.WireFormat.FIXED_32_SIZE;
-import static com.google.protobuf.WireFormat.FIXED_64_SIZE;
-import static com.google.protobuf.WireFormat.MAX_VARINT_SIZE;
import static java.lang.Math.max;
import com.google.protobuf.Utf8.UnpairedSurrogateException;
+
import java.io.IOException;
import java.io.OutputStream;
+import java.lang.reflect.Field;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -58,8 +59,13 @@ import java.util.logging.Logger;
*/
public abstract class CodedOutputStream extends ByteOutput {
private static final Logger logger = Logger.getLogger(CodedOutputStream.class.getName());
- private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = UnsafeUtil.hasUnsafeArrayOperations();
- private static final long ARRAY_BASE_OFFSET = UnsafeUtil.getArrayBaseOffset();
+ private static final sun.misc.Unsafe UNSAFE = getUnsafe();
+ private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = supportsUnsafeArrayOperations();
+ private static final long ARRAY_BASE_OFFSET = byteArrayBaseOffset();
+
+ private static final int FIXED_32_SIZE = 4;
+ private static final int FIXED_64_SIZE = 8;
+ private static final int MAX_VARINT_SIZE = 10;
/**
* @deprecated Use {@link #computeFixed32SizeNoTag(int)} instead.
@@ -132,66 +138,15 @@ public abstract class CodedOutputStream extends ByteOutput {
return new ArrayEncoder(flatArray, offset, length);
}
- /** Create a new {@code CodedOutputStream} that writes to the given {@link ByteBuffer}. */
- public static CodedOutputStream newInstance(ByteBuffer buffer) {
- if (buffer.hasArray()) {
- return new HeapNioEncoder(buffer);
- }
- if (buffer.isDirect() && !buffer.isReadOnly()) {
- return UnsafeDirectNioEncoder.isSupported()
- ? newUnsafeInstance(buffer)
- : newSafeInstance(buffer);
- }
- throw new IllegalArgumentException("ByteBuffer is read-only");
- }
-
- /** For testing purposes only. */
- static CodedOutputStream newUnsafeInstance(ByteBuffer buffer) {
- return new UnsafeDirectNioEncoder(buffer);
- }
-
- /** For testing purposes only. */
- static CodedOutputStream newSafeInstance(ByteBuffer buffer) {
- return new SafeDirectNioEncoder(buffer);
- }
-
/**
- * Configures serialization to be deterministic.
- *
- * <p>The deterministic serialization guarantees that for a given binary, equal (defined by the
- * {@code equals()} methods in protos) messages will always be serialized to the same bytes. This
- * implies:
- *
- * <ul>
- * <li>repeated serialization of a message will return the same bytes
- * <li>different processes of the same binary (which may be executing on different machines) will
- * serialize equal messages to the same bytes.
- * </ul>
- *
- * <p>Note the deterministic serialization is NOT canonical across languages; it is also unstable
- * across different builds with schema changes due to unknown fields. Users who need canonical
- * serialization, e.g. persistent storage in a canonical form, fingerprinting, etc, should define
- * their own canonicalization specification and implement the serializer using reflection APIs
- * rather than relying on this API.
- *
- * <p> Once set, the serializer will: (Note this is an implementation detail and may subject to
- * change in the future)
- *
- * <ul>
- * <li> sort map entries by keys in lexicographical order or numerical order. Note: For string
- * keys, the order is based on comparing the Unicode value of each character in the strings.
- * The order may be different from the deterministic serialization in other languages where
- * maps are sorted on the lexicographical order of the UTF8 encoded keys.
- * </ul>
+ * Create a new {@code CodedOutputStream} that writes to the given {@link ByteBuffer}.
*/
- void useDeterministicSerialization() {
- serializationDeterministic = true;
- }
-
- boolean isSerializationDeterministic() {
- return serializationDeterministic;
+ public static CodedOutputStream newInstance(ByteBuffer byteBuffer) {
+ if (byteBuffer.hasArray()) {
+ return new NioHeapEncoder(byteBuffer);
+ }
+ return new NioEncoder(byteBuffer);
}
- private boolean serializationDeterministic;
/**
* Create a new {@code CodedOutputStream} that writes to the given {@link ByteBuffer}.
@@ -914,7 +869,7 @@ public abstract class CodedOutputStream extends ByteOutput {
return computeLengthDelimitedFieldSize(value.getSerializedSize());
}
- static int computeLengthDelimitedFieldSize(int fieldLength) {
+ private static int computeLengthDelimitedFieldSize(int fieldLength) {
return computeUInt32SizeNoTag(fieldLength) + fieldLength;
}
@@ -990,17 +945,9 @@ public abstract class CodedOutputStream extends ByteOutput {
super(MESSAGE);
}
- OutOfSpaceException(String explanationMessage) {
- super(MESSAGE + ": " + explanationMessage);
- }
-
OutOfSpaceException(Throwable cause) {
super(MESSAGE, cause);
}
-
- OutOfSpaceException(String explanationMessage, Throwable cause) {
- super(MESSAGE + ": " + explanationMessage, cause);
- }
}
/**
@@ -1303,8 +1250,8 @@ public abstract class CodedOutputStream extends ByteOutput {
try {
buffer[position++] = value;
} catch (IndexOutOfBoundsException e) {
- throw new OutOfSpaceException(
- String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e);
+ throw new OutOfSpaceException(new IndexOutOfBoundsException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
}
}
@@ -1324,11 +1271,11 @@ public abstract class CodedOutputStream extends ByteOutput {
long pos = ARRAY_BASE_OFFSET + position;
while (true) {
if ((value & ~0x7F) == 0) {
- UnsafeUtil.putByte(buffer, pos++, (byte) value);
+ UNSAFE.putByte(buffer, pos++, (byte) value);
position++;
return;
} else {
- UnsafeUtil.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80));
+ UNSAFE.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80));
position++;
value >>>= 7;
}
@@ -1346,7 +1293,8 @@ public abstract class CodedOutputStream extends ByteOutput {
}
} catch (IndexOutOfBoundsException e) {
throw new OutOfSpaceException(
- String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e);
+ new IndexOutOfBoundsException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
}
}
}
@@ -1360,7 +1308,8 @@ public abstract class CodedOutputStream extends ByteOutput {
buffer[position++] = (byte) ((value >> 24) & 0xFF);
} catch (IndexOutOfBoundsException e) {
throw new OutOfSpaceException(
- String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e);
+ new IndexOutOfBoundsException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
}
}
@@ -1370,11 +1319,11 @@ public abstract class CodedOutputStream extends ByteOutput {
long pos = ARRAY_BASE_OFFSET + position;
while (true) {
if ((value & ~0x7FL) == 0) {
- UnsafeUtil.putByte(buffer, pos++, (byte) value);
+ UNSAFE.putByte(buffer, pos++, (byte) value);
position++;
return;
} else {
- UnsafeUtil.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80));
+ UNSAFE.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80));
position++;
value >>>= 7;
}
@@ -1392,7 +1341,8 @@ public abstract class CodedOutputStream extends ByteOutput {
}
} catch (IndexOutOfBoundsException e) {
throw new OutOfSpaceException(
- String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e);
+ new IndexOutOfBoundsException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
}
}
}
@@ -1410,7 +1360,8 @@ public abstract class CodedOutputStream extends ByteOutput {
buffer[position++] = (byte) ((int) (value >> 56) & 0xFF);
} catch (IndexOutOfBoundsException e) {
throw new OutOfSpaceException(
- String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e);
+ new IndexOutOfBoundsException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
}
}
@@ -1421,7 +1372,8 @@ public abstract class CodedOutputStream extends ByteOutput {
position += length;
} catch (IndexOutOfBoundsException e) {
throw new OutOfSpaceException(
- String.format("Pos: %d, limit: %d, len: %d", position, limit, length), e);
+ new IndexOutOfBoundsException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, length)));
}
}
@@ -1438,7 +1390,8 @@ public abstract class CodedOutputStream extends ByteOutput {
position += length;
} catch (IndexOutOfBoundsException e) {
throw new OutOfSpaceException(
- String.format("Pos: %d, limit: %d, len: %d", position, limit, length), e);
+ new IndexOutOfBoundsException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, length)));
}
}
@@ -1501,11 +1454,11 @@ public abstract class CodedOutputStream extends ByteOutput {
* A {@link CodedOutputStream} that writes directly to a heap {@link ByteBuffer}. Writes are
* done directly to the underlying array. The buffer position is only updated after a flush.
*/
- private static final class HeapNioEncoder extends ArrayEncoder {
+ private static final class NioHeapEncoder extends ArrayEncoder {
private final ByteBuffer byteBuffer;
private int initialPosition;
- HeapNioEncoder(ByteBuffer byteBuffer) {
+ NioHeapEncoder(ByteBuffer byteBuffer) {
super(byteBuffer.array(), byteBuffer.arrayOffset() + byteBuffer.position(),
byteBuffer.remaining());
this.byteBuffer = byteBuffer;
@@ -1520,15 +1473,14 @@ public abstract class CodedOutputStream extends ByteOutput {
}
/**
- * A {@link CodedOutputStream} that writes directly to a direct {@link ByteBuffer}, using only
- * safe operations..
+ * A {@link CodedOutputStream} that writes directly to a {@link ByteBuffer}.
*/
- private static final class SafeDirectNioEncoder extends CodedOutputStream {
+ private static final class NioEncoder extends CodedOutputStream {
private final ByteBuffer originalBuffer;
private final ByteBuffer buffer;
private final int initialPosition;
- SafeDirectNioEncoder(ByteBuffer buffer) {
+ NioEncoder(ByteBuffer buffer) {
this.originalBuffer = buffer;
this.buffer = buffer.duplicate().order(ByteOrder.LITTLE_ENDIAN);
initialPosition = buffer.position();
@@ -1831,356 +1783,6 @@ public abstract class CodedOutputStream extends ByteOutput {
}
/**
- * A {@link CodedOutputStream} that writes directly to a direct {@link ByteBuffer} using {@code
- * sun.misc.Unsafe}.
- */
- private static final class UnsafeDirectNioEncoder extends CodedOutputStream {
- private final ByteBuffer originalBuffer;
- private final ByteBuffer buffer;
- private final long address;
- private final long initialPosition;
- private final long limit;
- private final long oneVarintLimit;
- private long position;
-
- UnsafeDirectNioEncoder(ByteBuffer buffer) {
- this.originalBuffer = buffer;
- this.buffer = buffer.duplicate().order(ByteOrder.LITTLE_ENDIAN);
- address = UnsafeUtil.addressOffset(buffer);
- initialPosition = address + buffer.position();
- limit = address + buffer.limit();
- oneVarintLimit = limit - MAX_VARINT_SIZE;
- position = initialPosition;
- }
-
- static boolean isSupported() {
- return UnsafeUtil.hasUnsafeByteBufferOperations();
- }
-
- @Override
- public void writeTag(int fieldNumber, int wireType) throws IOException {
- writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
- }
-
- @Override
- public void writeInt32(int fieldNumber, int value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeInt32NoTag(value);
- }
-
- @Override
- public void writeUInt32(int fieldNumber, int value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeUInt32NoTag(value);
- }
-
- @Override
- public void writeFixed32(int fieldNumber, int value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
- writeFixed32NoTag(value);
- }
-
- @Override
- public void writeUInt64(int fieldNumber, long value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeUInt64NoTag(value);
- }
-
- @Override
- public void writeFixed64(int fieldNumber, long value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
- writeFixed64NoTag(value);
- }
-
- @Override
- public void writeBool(int fieldNumber, boolean value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- write((byte) (value ? 1 : 0));
- }
-
- @Override
- public void writeString(int fieldNumber, String value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
- writeStringNoTag(value);
- }
-
- @Override
- public void writeBytes(int fieldNumber, ByteString value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
- writeBytesNoTag(value);
- }
-
- @Override
- public void writeByteArray(int fieldNumber, byte[] value) throws IOException {
- writeByteArray(fieldNumber, value, 0, value.length);
- }
-
- @Override
- public void writeByteArray(int fieldNumber, byte[] value, int offset, int length)
- throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
- writeByteArrayNoTag(value, offset, length);
- }
-
- @Override
- public void writeByteBuffer(int fieldNumber, ByteBuffer value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
- writeUInt32NoTag(value.capacity());
- writeRawBytes(value);
- }
-
- @Override
- public void writeMessage(int fieldNumber, MessageLite value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
- writeMessageNoTag(value);
- }
-
- @Override
- public void writeMessageSetExtension(int fieldNumber, MessageLite value) throws IOException {
- writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
- writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
- writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
- writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
- }
-
- @Override
- public void writeRawMessageSetExtension(int fieldNumber, ByteString value) throws IOException {
- writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
- writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
- writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
- writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
- }
-
- @Override
- public void writeMessageNoTag(MessageLite value) throws IOException {
- writeUInt32NoTag(value.getSerializedSize());
- value.writeTo(this);
- }
-
- @Override
- public void write(byte value) throws IOException {
- if (position >= limit) {
- throw new OutOfSpaceException(
- String.format("Pos: %d, limit: %d, len: %d", position, limit, 1));
- }
- UnsafeUtil.putByte(position++, value);
- }
-
- @Override
- public void writeBytesNoTag(ByteString value) throws IOException {
- writeUInt32NoTag(value.size());
- value.writeTo(this);
- }
-
- @Override
- public void writeByteArrayNoTag(byte[] value, int offset, int length) throws IOException {
- writeUInt32NoTag(length);
- write(value, offset, length);
- }
-
- @Override
- public void writeRawBytes(ByteBuffer value) throws IOException {
- if (value.hasArray()) {
- write(value.array(), value.arrayOffset(), value.capacity());
- } else {
- ByteBuffer duplicated = value.duplicate();
- duplicated.clear();
- write(duplicated);
- }
- }
-
- @Override
- public void writeInt32NoTag(int value) throws IOException {
- if (value >= 0) {
- writeUInt32NoTag(value);
- } else {
- // Must sign-extend.
- writeUInt64NoTag(value);
- }
- }
-
- @Override
- public void writeUInt32NoTag(int value) throws IOException {
- if (position <= oneVarintLimit) {
- // Optimization to avoid bounds checks on each iteration.
- while (true) {
- if ((value & ~0x7F) == 0) {
- UnsafeUtil.putByte(position++, (byte) value);
- return;
- } else {
- UnsafeUtil.putByte(position++, (byte) ((value & 0x7F) | 0x80));
- value >>>= 7;
- }
- }
- } else {
- while (position < limit) {
- if ((value & ~0x7F) == 0) {
- UnsafeUtil.putByte(position++, (byte) value);
- return;
- } else {
- UnsafeUtil.putByte(position++, (byte) ((value & 0x7F) | 0x80));
- value >>>= 7;
- }
- }
- throw new OutOfSpaceException(
- String.format("Pos: %d, limit: %d, len: %d", position, limit, 1));
- }
- }
-
- @Override
- public void writeFixed32NoTag(int value) throws IOException {
- buffer.putInt(bufferPos(position), value);
- position += FIXED_32_SIZE;
- }
-
- @Override
- public void writeUInt64NoTag(long value) throws IOException {
- if (position <= oneVarintLimit) {
- // Optimization to avoid bounds checks on each iteration.
- while (true) {
- if ((value & ~0x7FL) == 0) {
- UnsafeUtil.putByte(position++, (byte) value);
- return;
- } else {
- UnsafeUtil.putByte(position++, (byte) (((int) value & 0x7F) | 0x80));
- value >>>= 7;
- }
- }
- } else {
- while (position < limit) {
- if ((value & ~0x7FL) == 0) {
- UnsafeUtil.putByte(position++, (byte) value);
- return;
- } else {
- UnsafeUtil.putByte(position++, (byte) (((int) value & 0x7F) | 0x80));
- value >>>= 7;
- }
- }
- throw new OutOfSpaceException(
- String.format("Pos: %d, limit: %d, len: %d", position, limit, 1));
- }
- }
-
- @Override
- public void writeFixed64NoTag(long value) throws IOException {
- buffer.putLong(bufferPos(position), value);
- position += FIXED_64_SIZE;
- }
-
- @Override
- public void write(byte[] value, int offset, int length) throws IOException {
- if (value == null
- || offset < 0
- || length < 0
- || (value.length - length) < offset
- || (limit - length) < position) {
- if (value == null) {
- throw new NullPointerException("value");
- }
- throw new OutOfSpaceException(
- String.format("Pos: %d, limit: %d, len: %d", position, limit, length));
- }
-
- UnsafeUtil.copyMemory(
- value, UnsafeUtil.getArrayBaseOffset() + offset, null, position, length);
- position += length;
- }
-
- @Override
- public void writeLazy(byte[] value, int offset, int length) throws IOException {
- write(value, offset, length);
- }
-
- @Override
- public void write(ByteBuffer value) throws IOException {
- try {
- int length = value.remaining();
- repositionBuffer(position);
- buffer.put(value);
- position += length;
- } catch (BufferOverflowException e) {
- throw new OutOfSpaceException(e);
- }
- }
-
- @Override
- public void writeLazy(ByteBuffer value) throws IOException {
- write(value);
- }
-
- @Override
- public void writeStringNoTag(String value) throws IOException {
- long prevPos = position;
- try {
- // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
- // and at most 3 times of it. We take advantage of this in both branches below.
- int maxEncodedSize = value.length() * Utf8.MAX_BYTES_PER_CHAR;
- int maxLengthVarIntSize = computeUInt32SizeNoTag(maxEncodedSize);
- int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
- if (minLengthVarIntSize == maxLengthVarIntSize) {
- // Save the current position and increment past the length field. We'll come back
- // and write the length field after the encoding is complete.
- int stringStart = bufferPos(position) + minLengthVarIntSize;
- buffer.position(stringStart);
-
- // Encode the string.
- Utf8.encodeUtf8(value, buffer);
-
- // Write the length and advance the position.
- int length = buffer.position() - stringStart;
- writeUInt32NoTag(length);
- position += length;
- } else {
- // Calculate and write the encoded length.
- int length = Utf8.encodedLength(value);
- writeUInt32NoTag(length);
-
- // Write the string and advance the position.
- repositionBuffer(position);
- Utf8.encodeUtf8(value, buffer);
- position += length;
- }
- } catch (UnpairedSurrogateException e) {
- // Roll back the change and convert to an IOException.
- position = prevPos;
- repositionBuffer(position);
-
- // TODO(nathanmittler): We should throw an IOException here instead.
- inefficientWriteStringNoTag(value, e);
- } catch (IllegalArgumentException e) {
- // Thrown by buffer.position() if out of range.
- throw new OutOfSpaceException(e);
- } catch (IndexOutOfBoundsException e) {
- throw new OutOfSpaceException(e);
- }
- }
-
- @Override
- public void flush() {
- // Update the position of the original buffer.
- originalBuffer.position(bufferPos(position));
- }
-
- @Override
- public int spaceLeft() {
- return (int) (limit - position);
- }
-
- @Override
- public int getTotalBytesWritten() {
- return (int) (position - initialPosition);
- }
-
- private void repositionBuffer(long pos) {
- buffer.position(bufferPos(pos));
- }
-
- private int bufferPos(long pos) {
- return (int) (pos - address);
- }
- }
-
- /**
* Abstract base class for buffered encoders.
*/
private abstract static class AbstractBufferedEncoder extends CodedOutputStream {
@@ -2253,10 +1855,10 @@ public abstract class CodedOutputStream extends ByteOutput {
long pos = originalPos;
while (true) {
if ((value & ~0x7F) == 0) {
- UnsafeUtil.putByte(buffer, pos++, (byte) value);
+ UNSAFE.putByte(buffer, pos++, (byte) value);
break;
} else {
- UnsafeUtil.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80));
+ UNSAFE.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80));
value >>>= 7;
}
}
@@ -2288,10 +1890,10 @@ public abstract class CodedOutputStream extends ByteOutput {
long pos = originalPos;
while (true) {
if ((value & ~0x7FL) == 0) {
- UnsafeUtil.putByte(buffer, pos++, (byte) value);
+ UNSAFE.putByte(buffer, pos++, (byte) value);
break;
} else {
- UnsafeUtil.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80));
+ UNSAFE.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80));
value >>>= 7;
}
}
@@ -2998,4 +2600,65 @@ public abstract class CodedOutputStream extends ByteOutput {
position = 0;
}
}
+
+ /**
+ * 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;
+
+ 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;
+ }
+
+ /**
+ * Indicates whether or not unsafe array operations are supported on this platform.
+ */
+ // TODO(nathanmittler): Add support for Android's MemoryBlock.
+ private static boolean supportsUnsafeArrayOperations() {
+ boolean supported = false;
+ if (UNSAFE != null) {
+ try {
+ UNSAFE.getClass().getMethod("arrayBaseOffset", Class.class);
+ UNSAFE.getClass().getMethod("putByte", Object.class, long.class, byte.class);
+ supported = true;
+ } catch (Throwable e) {
+ // Do nothing.
+ }
+ }
+ logger.log(Level.FINEST, "Unsafe array operations: {}",
+ supported ? "available" : "unavailable");
+ return supported;
+ }
+
+ /**
+ * Get the base offset for byte arrays, or {@code -1} if {@code sun.misc.Unsafe} is not
+ * available.
+ */
+ private static <T> int byteArrayBaseOffset() {
+ return HAS_UNSAFE_ARRAY_OPERATIONS ? UNSAFE.arrayBaseOffset(byte[].class) : -1;
+ }
}

Powered by Google App Engine
This is Rietveld 408576698