Add *UnsafeHeapByteBuf for improve performance on systems with sun.misc.Unsafe
Motivation: sun.misc.Unsafe allows us to handle heap ByteBuf in a more efficient matter. We should use special ByteBuf implementation when sun.misc.Unsafe can be used to increase performance. Modifications: - Add PooledUnsafeHeapByteBuf and UnpooledUnsafeHeapByteBuf that are used when sun.misc.Unsafe is ready to use. - Add UnsafeHeapSwappedByteBuf Result: Better performance when using heap buffers and sun.misc.Unsafe is ready to use.
This commit is contained in:
parent
eadf1bfc3f
commit
164f6f1731
@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015 The Netty Project
|
||||||
|
*
|
||||||
|
* The Netty Project licenses this file to you under the Apache License,
|
||||||
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at:
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package io.netty.buffer;
|
||||||
|
|
||||||
|
import io.netty.util.internal.PlatformDependent;
|
||||||
|
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special {@link SwappedByteBuf} for {@link ByteBuf}s that is using unsafe.
|
||||||
|
*/
|
||||||
|
abstract class AbstractUnsafeSwappedByteBuf extends SwappedByteBuf {
|
||||||
|
private final boolean nativeByteOrder;
|
||||||
|
private final AbstractByteBuf wrapped;
|
||||||
|
|
||||||
|
AbstractUnsafeSwappedByteBuf(AbstractByteBuf buf) {
|
||||||
|
super(buf);
|
||||||
|
assert PlatformDependent.isUnaligned();
|
||||||
|
wrapped = buf;
|
||||||
|
nativeByteOrder = UnsafeByteBufUtil.BIG_ENDIAN_NATIVE_ORDER == (order() == ByteOrder.BIG_ENDIAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final long getLong(int index) {
|
||||||
|
wrapped.checkIndex(index, 8);
|
||||||
|
long v = _getLong(wrapped, index);
|
||||||
|
return nativeByteOrder ? v : Long.reverseBytes(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final float getFloat(int index) {
|
||||||
|
return Float.intBitsToFloat(getInt(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final double getDouble(int index) {
|
||||||
|
return Double.longBitsToDouble(getLong(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final char getChar(int index) {
|
||||||
|
return (char) getShort(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final long getUnsignedInt(int index) {
|
||||||
|
return getInt(index) & 0xFFFFFFFFL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final int getInt(int index) {
|
||||||
|
wrapped.checkIndex0(index, 4);
|
||||||
|
int v = _getInt(wrapped, index);
|
||||||
|
return nativeByteOrder ? v : Integer.reverseBytes(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final int getUnsignedShort(int index) {
|
||||||
|
return getShort(index) & 0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final short getShort(int index) {
|
||||||
|
wrapped.checkIndex0(index, 2);
|
||||||
|
short v = _getShort(wrapped, index);
|
||||||
|
return nativeByteOrder ? v : Short.reverseBytes(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final ByteBuf setShort(int index, int value) {
|
||||||
|
wrapped.checkIndex0(index, 2);
|
||||||
|
_setShort(wrapped, index, nativeByteOrder ? (short) value : Short.reverseBytes((short) value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final ByteBuf setInt(int index, int value) {
|
||||||
|
wrapped.checkIndex0(index, 4);
|
||||||
|
_setInt(wrapped, index, nativeByteOrder ? value : Integer.reverseBytes(value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final ByteBuf setLong(int index, long value) {
|
||||||
|
wrapped.checkIndex(index, 8);
|
||||||
|
_setLong(wrapped, index, nativeByteOrder ? value : Long.reverseBytes(value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final ByteBuf setChar(int index, int value) {
|
||||||
|
setShort(index, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final ByteBuf setFloat(int index, float value) {
|
||||||
|
setInt(index, Float.floatToRawIntBits(value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final ByteBuf setDouble(int index, double value) {
|
||||||
|
setLong(index, Double.doubleToRawLongBits(value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final ByteBuf writeShort(int value) {
|
||||||
|
wrapped.ensureWritable(2);
|
||||||
|
_setShort(wrapped, wrapped.writerIndex, nativeByteOrder ? (short) value : Short.reverseBytes((short) value));
|
||||||
|
wrapped.writerIndex += 2;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final ByteBuf writeInt(int value) {
|
||||||
|
wrapped.ensureWritable(4);
|
||||||
|
_setInt(wrapped, wrapped.writerIndex, nativeByteOrder ? value : Integer.reverseBytes(value));
|
||||||
|
wrapped.writerIndex += 4;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final ByteBuf writeLong(long value) {
|
||||||
|
wrapped.ensureWritable(8);
|
||||||
|
_setLong(wrapped, wrapped.writerIndex, nativeByteOrder ? value : Long.reverseBytes(value));
|
||||||
|
wrapped.writerIndex += 8;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final ByteBuf writeChar(int value) {
|
||||||
|
writeShort(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final ByteBuf writeFloat(float value) {
|
||||||
|
writeInt(Float.floatToRawIntBits(value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final ByteBuf writeDouble(double value) {
|
||||||
|
writeLong(Double.doubleToRawLongBits(value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract short _getShort(AbstractByteBuf wrapped, int index);
|
||||||
|
protected abstract int _getInt(AbstractByteBuf wrapped, int index);
|
||||||
|
protected abstract long _getLong(AbstractByteBuf wrapped, int index);
|
||||||
|
protected abstract void _setShort(AbstractByteBuf wrapped, int index, short value);
|
||||||
|
protected abstract void _setInt(AbstractByteBuf wrapped, int index, int value);
|
||||||
|
protected abstract void _setLong(AbstractByteBuf wrapped, int index, long value);
|
||||||
|
}
|
@ -26,6 +26,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
abstract class PoolArena<T> implements PoolArenaMetric {
|
abstract class PoolArena<T> implements PoolArenaMetric {
|
||||||
|
static final boolean HAS_UNSAFE = PlatformDependent.hasUnsafe();
|
||||||
|
|
||||||
enum SizeClass {
|
enum SizeClass {
|
||||||
Tiny,
|
Tiny,
|
||||||
@ -614,7 +615,8 @@ abstract class PoolArena<T> implements PoolArenaMetric {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PooledByteBuf<byte[]> newByteBuf(int maxCapacity) {
|
protected PooledByteBuf<byte[]> newByteBuf(int maxCapacity) {
|
||||||
return PooledHeapByteBuf.newInstance(maxCapacity);
|
return HAS_UNSAFE ? PooledUnsafeHeapByteBuf.newUnsafeInstance(maxCapacity)
|
||||||
|
: PooledHeapByteBuf.newInstance(maxCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -629,8 +631,6 @@ abstract class PoolArena<T> implements PoolArenaMetric {
|
|||||||
|
|
||||||
static final class DirectArena extends PoolArena<ByteBuffer> {
|
static final class DirectArena extends PoolArena<ByteBuffer> {
|
||||||
|
|
||||||
private static final boolean HAS_UNSAFE = PlatformDependent.hasUnsafe();
|
|
||||||
|
|
||||||
DirectArena(PooledByteBufAllocator parent, int pageSize, int maxOrder, int pageShifts, int chunkSize) {
|
DirectArena(PooledByteBufAllocator parent, int pageSize, int maxOrder, int pageShifts, int chunkSize) {
|
||||||
super(parent, pageSize, maxOrder, pageShifts, chunkSize);
|
super(parent, pageSize, maxOrder, pageShifts, chunkSize);
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ import java.nio.channels.ClosedChannelException;
|
|||||||
import java.nio.channels.GatheringByteChannel;
|
import java.nio.channels.GatheringByteChannel;
|
||||||
import java.nio.channels.ScatteringByteChannel;
|
import java.nio.channels.ScatteringByteChannel;
|
||||||
|
|
||||||
final class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
|
class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
|
||||||
|
|
||||||
private static final Recycler<PooledHeapByteBuf> RECYCLER = new Recycler<PooledHeapByteBuf>() {
|
private static final Recycler<PooledHeapByteBuf> RECYCLER = new Recycler<PooledHeapByteBuf>() {
|
||||||
@Override
|
@Override
|
||||||
@ -40,12 +40,12 @@ final class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PooledHeapByteBuf(Recycler.Handle recyclerHandle, int maxCapacity) {
|
PooledHeapByteBuf(Recycler.Handle recyclerHandle, int maxCapacity) {
|
||||||
super(recyclerHandle, maxCapacity);
|
super(recyclerHandle, maxCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDirect() {
|
public final boolean isDirect() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ final class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
public final ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||||
checkDstIndex(index, length, dstIndex, dst.capacity());
|
checkDstIndex(index, length, dstIndex, dst.capacity());
|
||||||
if (dst.hasMemoryAddress()) {
|
if (dst.hasMemoryAddress()) {
|
||||||
PlatformDependent.copyMemory(memory, idx(index), dst.memoryAddress() + dstIndex, length);
|
PlatformDependent.copyMemory(memory, idx(index), dst.memoryAddress() + dstIndex, length);
|
||||||
@ -104,28 +104,28 @@ final class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
public final ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||||
checkDstIndex(index, length, dstIndex, dst.length);
|
checkDstIndex(index, length, dstIndex, dst.length);
|
||||||
System.arraycopy(memory, idx(index), dst, dstIndex, length);
|
System.arraycopy(memory, idx(index), dst, dstIndex, length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
public final ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||||
checkIndex(index);
|
checkIndex(index);
|
||||||
dst.put(memory, idx(index), Math.min(capacity() - index, dst.remaining()));
|
dst.put(memory, idx(index), Math.min(capacity() - index, dst.remaining()));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
|
public final ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
|
||||||
checkIndex(index, length);
|
checkIndex(index, length);
|
||||||
out.write(memory, idx(index), length);
|
out.write(memory, idx(index), length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
|
public final int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
|
||||||
return getBytes(index, out, length, false);
|
return getBytes(index, out, length, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ final class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int readBytes(GatheringByteChannel out, int length) throws IOException {
|
public final int readBytes(GatheringByteChannel out, int length) throws IOException {
|
||||||
checkReadableBytes(length);
|
checkReadableBytes(length);
|
||||||
int readBytes = getBytes(readerIndex, out, length, true);
|
int readBytes = getBytes(readerIndex, out, length, true);
|
||||||
readerIndex += readBytes;
|
readerIndex += readBytes;
|
||||||
@ -192,7 +192,7 @@ final class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
public final ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||||
checkSrcIndex(index, length, srcIndex, src.capacity());
|
checkSrcIndex(index, length, srcIndex, src.capacity());
|
||||||
if (src.hasMemoryAddress()) {
|
if (src.hasMemoryAddress()) {
|
||||||
PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, memory, idx(index), length);
|
PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, memory, idx(index), length);
|
||||||
@ -205,14 +205,14 @@ final class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
public final ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||||
checkSrcIndex(index, length, srcIndex, src.length);
|
checkSrcIndex(index, length, srcIndex, src.length);
|
||||||
System.arraycopy(src, srcIndex, memory, idx(index), length);
|
System.arraycopy(src, srcIndex, memory, idx(index), length);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf setBytes(int index, ByteBuffer src) {
|
public final ByteBuf setBytes(int index, ByteBuffer src) {
|
||||||
int length = src.remaining();
|
int length = src.remaining();
|
||||||
checkIndex(index, length);
|
checkIndex(index, length);
|
||||||
src.get(memory, idx(index), length);
|
src.get(memory, idx(index), length);
|
||||||
@ -220,13 +220,13 @@ final class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int setBytes(int index, InputStream in, int length) throws IOException {
|
public final int setBytes(int index, InputStream in, int length) throws IOException {
|
||||||
checkIndex(index, length);
|
checkIndex(index, length);
|
||||||
return in.read(memory, idx(index), length);
|
return in.read(memory, idx(index), length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
|
public final int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
|
||||||
checkIndex(index, length);
|
checkIndex(index, length);
|
||||||
index = idx(index);
|
index = idx(index);
|
||||||
try {
|
try {
|
||||||
@ -237,7 +237,7 @@ final class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf copy(int index, int length) {
|
public final ByteBuf copy(int index, int length) {
|
||||||
checkIndex(index, length);
|
checkIndex(index, length);
|
||||||
ByteBuf copy = alloc().heapBuffer(length, maxCapacity());
|
ByteBuf copy = alloc().heapBuffer(length, maxCapacity());
|
||||||
copy.writeBytes(memory, idx(index), length);
|
copy.writeBytes(memory, idx(index), length);
|
||||||
@ -245,17 +245,17 @@ final class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int nioBufferCount() {
|
public final int nioBufferCount() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuffer[] nioBuffers(int index, int length) {
|
public final ByteBuffer[] nioBuffers(int index, int length) {
|
||||||
return new ByteBuffer[] { nioBuffer(index, length) };
|
return new ByteBuffer[] { nioBuffer(index, length) };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuffer nioBuffer(int index, int length) {
|
public final ByteBuffer nioBuffer(int index, int length) {
|
||||||
checkIndex(index, length);
|
checkIndex(index, length);
|
||||||
index = idx(index);
|
index = idx(index);
|
||||||
ByteBuffer buf = ByteBuffer.wrap(memory, index, length);
|
ByteBuffer buf = ByteBuffer.wrap(memory, index, length);
|
||||||
@ -263,40 +263,40 @@ final class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuffer internalNioBuffer(int index, int length) {
|
public final ByteBuffer internalNioBuffer(int index, int length) {
|
||||||
checkIndex(index, length);
|
checkIndex(index, length);
|
||||||
index = idx(index);
|
index = idx(index);
|
||||||
return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length);
|
return (ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasArray() {
|
public final boolean hasArray() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] array() {
|
public final byte[] array() {
|
||||||
ensureAccessible();
|
ensureAccessible();
|
||||||
return memory;
|
return memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int arrayOffset() {
|
public final int arrayOffset() {
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasMemoryAddress() {
|
public final boolean hasMemoryAddress() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long memoryAddress() {
|
public final long memoryAddress() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ByteBuffer newInternalNioBuffer(byte[] memory) {
|
protected final ByteBuffer newInternalNioBuffer(byte[] memory) {
|
||||||
return ByteBuffer.wrap(memory);
|
return ByteBuffer.wrap(memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015 The Netty Project
|
||||||
|
*
|
||||||
|
* The Netty Project licenses this file tothe License at:
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package io.netty.buffer;
|
||||||
|
|
||||||
|
import io.netty.util.Recycler;
|
||||||
|
import io.netty.util.Recycler.Handle;
|
||||||
|
import io.netty.util.internal.PlatformDependent;
|
||||||
|
|
||||||
|
final class PooledUnsafeHeapByteBuf extends PooledHeapByteBuf {
|
||||||
|
|
||||||
|
private static final Recycler<PooledUnsafeHeapByteBuf> RECYCLER = new Recycler<PooledUnsafeHeapByteBuf>() {
|
||||||
|
@Override
|
||||||
|
protected PooledUnsafeHeapByteBuf newObject(Handle handle) {
|
||||||
|
return new PooledUnsafeHeapByteBuf(handle, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static PooledUnsafeHeapByteBuf newUnsafeInstance(int maxCapacity) {
|
||||||
|
PooledUnsafeHeapByteBuf buf = RECYCLER.get();
|
||||||
|
buf.reuse(maxCapacity);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PooledUnsafeHeapByteBuf(Handle recyclerHandle, int maxCapacity) {
|
||||||
|
super(recyclerHandle, maxCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected byte _getByte(int index) {
|
||||||
|
return UnsafeByteBufUtil.getByte(memory, idx(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected short _getShort(int index) {
|
||||||
|
return UnsafeByteBufUtil.getShort(memory, idx(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int _getUnsignedMedium(int index) {
|
||||||
|
return UnsafeByteBufUtil.getUnsignedMedium(memory, idx(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int _getInt(int index) {
|
||||||
|
return UnsafeByteBufUtil.getInt(memory, idx(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected long _getLong(int index) {
|
||||||
|
return UnsafeByteBufUtil.getLong(memory, idx(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void _setByte(int index, int value) {
|
||||||
|
UnsafeByteBufUtil.setByte(memory, idx(index), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void _setShort(int index, int value) {
|
||||||
|
UnsafeByteBufUtil.setShort(memory, idx(index), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void _setMedium(int index, int value) {
|
||||||
|
UnsafeByteBufUtil.setMedium(memory, idx(index), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void _setInt(int index, int value) {
|
||||||
|
UnsafeByteBufUtil.setInt(memory, idx(index), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void _setLong(int index, long value) {
|
||||||
|
UnsafeByteBufUtil.setLong(memory, idx(index), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Recycler<?> recycler() {
|
||||||
|
return RECYCLER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected SwappedByteBuf newSwappedByteBuf() {
|
||||||
|
if (PlatformDependent.isUnaligned()) {
|
||||||
|
// Only use if unaligned access is supported otherwise there is no gain.
|
||||||
|
return new UnsafeHeapSwappedByteBuf(this);
|
||||||
|
}
|
||||||
|
return super.newSwappedByteBuf();
|
||||||
|
}
|
||||||
|
}
|
@ -40,7 +40,8 @@ public final class UnpooledByteBufAllocator extends AbstractByteBufAllocator {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity) {
|
protected ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity) {
|
||||||
return new UnpooledHeapByteBuf(this, initialCapacity, maxCapacity);
|
return PlatformDependent.hasUnsafe() ? new UnpooledUnsafeHeapByteBuf(this, initialCapacity, maxCapacity)
|
||||||
|
: new UnpooledHeapByteBuf(this, initialCapacity, maxCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -32,7 +32,7 @@ import java.nio.channels.ScatteringByteChannel;
|
|||||||
public class UnpooledHeapByteBuf extends AbstractReferenceCountedByteBuf {
|
public class UnpooledHeapByteBuf extends AbstractReferenceCountedByteBuf {
|
||||||
|
|
||||||
private final ByteBufAllocator alloc;
|
private final ByteBufAllocator alloc;
|
||||||
private byte[] array;
|
byte[] array;
|
||||||
private ByteBuffer tmpNioBuf;
|
private ByteBuffer tmpNioBuf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015 The Netty Project
|
||||||
|
*
|
||||||
|
* The Netty Project licenses this file to you under the Apache License,
|
||||||
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at:
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package io.netty.buffer;
|
||||||
|
|
||||||
|
|
||||||
|
import io.netty.util.internal.PlatformDependent;
|
||||||
|
|
||||||
|
final class UnpooledUnsafeHeapByteBuf extends UnpooledHeapByteBuf {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new heap buffer with a newly allocated byte array.
|
||||||
|
*
|
||||||
|
* @param initialCapacity the initial capacity of the underlying byte array
|
||||||
|
* @param maxCapacity the max capacity of the underlying byte array
|
||||||
|
*/
|
||||||
|
UnpooledUnsafeHeapByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
|
||||||
|
super(alloc, initialCapacity, maxCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getByte(int index) {
|
||||||
|
checkIndex(index);
|
||||||
|
return _getByte(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected byte _getByte(int index) {
|
||||||
|
return UnsafeByteBufUtil.getByte(array, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public short getShort(int index) {
|
||||||
|
checkIndex(index, 2);
|
||||||
|
return _getShort(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected short _getShort(int index) {
|
||||||
|
return UnsafeByteBufUtil.getShort(array, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getUnsignedMedium(int index) {
|
||||||
|
checkIndex(index, 3);
|
||||||
|
return _getUnsignedMedium(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int _getUnsignedMedium(int index) {
|
||||||
|
return UnsafeByteBufUtil.getUnsignedMedium(array, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getInt(int index) {
|
||||||
|
checkIndex(index, 4);
|
||||||
|
return _getInt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int _getInt(int index) {
|
||||||
|
return UnsafeByteBufUtil.getInt(array, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLong(int index) {
|
||||||
|
checkIndex(index, 8);
|
||||||
|
return _getLong(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected long _getLong(int index) {
|
||||||
|
return UnsafeByteBufUtil.getLong(array, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf setByte(int index, int value) {
|
||||||
|
checkIndex(index);
|
||||||
|
_setByte(index, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void _setByte(int index, int value) {
|
||||||
|
UnsafeByteBufUtil.setByte(array, index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf setShort(int index, int value) {
|
||||||
|
checkIndex(index, 2);
|
||||||
|
_setShort(index, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void _setShort(int index, int value) {
|
||||||
|
UnsafeByteBufUtil.setShort(array, index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf setMedium(int index, int value) {
|
||||||
|
checkIndex(index, 3);
|
||||||
|
_setMedium(index, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void _setMedium(int index, int value) {
|
||||||
|
UnsafeByteBufUtil.setMedium(array, index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf setInt(int index, int value) {
|
||||||
|
checkIndex(index, 4);
|
||||||
|
_setInt(index, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void _setInt(int index, int value) {
|
||||||
|
UnsafeByteBufUtil.setInt(array, index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf setLong(int index, long value) {
|
||||||
|
checkIndex(index, 8);
|
||||||
|
_setLong(index, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void _setLong(int index, long value) {
|
||||||
|
UnsafeByteBufUtil.setLong(array, index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected SwappedByteBuf newSwappedByteBuf() {
|
||||||
|
if (PlatformDependent.isUnaligned()) {
|
||||||
|
// Only use if unaligned access is supported otherwise there is no gain.
|
||||||
|
return new UnsafeHeapSwappedByteBuf(this);
|
||||||
|
}
|
||||||
|
return super.newSwappedByteBuf();
|
||||||
|
}
|
||||||
|
}
|
@ -24,7 +24,7 @@ import java.nio.ByteOrder;
|
|||||||
*/
|
*/
|
||||||
final class UnsafeByteBufUtil {
|
final class UnsafeByteBufUtil {
|
||||||
|
|
||||||
private static final boolean NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
|
static final boolean BIG_ENDIAN_NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
|
||||||
private static final boolean UNALIGNED = PlatformDependent.isUnaligned();
|
private static final boolean UNALIGNED = PlatformDependent.isUnaligned();
|
||||||
|
|
||||||
static byte getByte(long address) {
|
static byte getByte(long address) {
|
||||||
@ -34,14 +34,14 @@ final class UnsafeByteBufUtil {
|
|||||||
static short getShort(long address) {
|
static short getShort(long address) {
|
||||||
if (UNALIGNED) {
|
if (UNALIGNED) {
|
||||||
short v = PlatformDependent.getShort(address);
|
short v = PlatformDependent.getShort(address);
|
||||||
return NATIVE_ORDER ? v : Short.reverseBytes(v);
|
return BIG_ENDIAN_NATIVE_ORDER ? v : Short.reverseBytes(v);
|
||||||
}
|
}
|
||||||
return (short) (PlatformDependent.getByte(address) << 8 | PlatformDependent.getByte(address + 1) & 0xff);
|
return (short) (PlatformDependent.getByte(address) << 8 | PlatformDependent.getByte(address + 1) & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getUnsignedMedium(long address) {
|
static int getUnsignedMedium(long address) {
|
||||||
if (UNALIGNED) {
|
if (UNALIGNED) {
|
||||||
if (NATIVE_ORDER) {
|
if (BIG_ENDIAN_NATIVE_ORDER) {
|
||||||
return (PlatformDependent.getByte(address) & 0xff) |
|
return (PlatformDependent.getByte(address) & 0xff) |
|
||||||
(PlatformDependent.getShort(address + 1) & 0xffff) << 8;
|
(PlatformDependent.getShort(address + 1) & 0xffff) << 8;
|
||||||
}
|
}
|
||||||
@ -56,7 +56,7 @@ final class UnsafeByteBufUtil {
|
|||||||
static int getInt(long address) {
|
static int getInt(long address) {
|
||||||
if (UNALIGNED) {
|
if (UNALIGNED) {
|
||||||
int v = PlatformDependent.getInt(address);
|
int v = PlatformDependent.getInt(address);
|
||||||
return NATIVE_ORDER ? v : Integer.reverseBytes(v);
|
return BIG_ENDIAN_NATIVE_ORDER ? v : Integer.reverseBytes(v);
|
||||||
}
|
}
|
||||||
return PlatformDependent.getByte(address) << 24 |
|
return PlatformDependent.getByte(address) << 24 |
|
||||||
(PlatformDependent.getByte(address + 1) & 0xff) << 16 |
|
(PlatformDependent.getByte(address + 1) & 0xff) << 16 |
|
||||||
@ -67,7 +67,7 @@ final class UnsafeByteBufUtil {
|
|||||||
static long getLong(long address) {
|
static long getLong(long address) {
|
||||||
if (UNALIGNED) {
|
if (UNALIGNED) {
|
||||||
long v = PlatformDependent.getLong(address);
|
long v = PlatformDependent.getLong(address);
|
||||||
return NATIVE_ORDER ? v : Long.reverseBytes(v);
|
return BIG_ENDIAN_NATIVE_ORDER ? v : Long.reverseBytes(v);
|
||||||
}
|
}
|
||||||
return (long) PlatformDependent.getByte(address) << 56 |
|
return (long) PlatformDependent.getByte(address) << 56 |
|
||||||
((long) PlatformDependent.getByte(address + 1) & 0xff) << 48 |
|
((long) PlatformDependent.getByte(address + 1) & 0xff) << 48 |
|
||||||
@ -85,7 +85,8 @@ final class UnsafeByteBufUtil {
|
|||||||
|
|
||||||
static void setShort(long address, int value) {
|
static void setShort(long address, int value) {
|
||||||
if (UNALIGNED) {
|
if (UNALIGNED) {
|
||||||
PlatformDependent.putShort(address, NATIVE_ORDER ? (short) value : Short.reverseBytes((short) value));
|
PlatformDependent.putShort(
|
||||||
|
address, BIG_ENDIAN_NATIVE_ORDER ? (short) value : Short.reverseBytes((short) value));
|
||||||
} else {
|
} else {
|
||||||
PlatformDependent.putByte(address, (byte) (value >>> 8));
|
PlatformDependent.putByte(address, (byte) (value >>> 8));
|
||||||
PlatformDependent.putByte(address + 1, (byte) value);
|
PlatformDependent.putByte(address + 1, (byte) value);
|
||||||
@ -94,7 +95,7 @@ final class UnsafeByteBufUtil {
|
|||||||
|
|
||||||
static void setMedium(long address, int value) {
|
static void setMedium(long address, int value) {
|
||||||
if (UNALIGNED) {
|
if (UNALIGNED) {
|
||||||
if (NATIVE_ORDER) {
|
if (BIG_ENDIAN_NATIVE_ORDER) {
|
||||||
PlatformDependent.putByte(address, (byte) value);
|
PlatformDependent.putByte(address, (byte) value);
|
||||||
PlatformDependent.putShort(address + 1, (short) (value >>> 8));
|
PlatformDependent.putShort(address + 1, (short) (value >>> 8));
|
||||||
} else {
|
} else {
|
||||||
@ -110,7 +111,7 @@ final class UnsafeByteBufUtil {
|
|||||||
|
|
||||||
static void setInt(long address, int value) {
|
static void setInt(long address, int value) {
|
||||||
if (UNALIGNED) {
|
if (UNALIGNED) {
|
||||||
PlatformDependent.putInt(address, NATIVE_ORDER ? value : Integer.reverseBytes(value));
|
PlatformDependent.putInt(address, BIG_ENDIAN_NATIVE_ORDER ? value : Integer.reverseBytes(value));
|
||||||
} else {
|
} else {
|
||||||
PlatformDependent.putByte(address, (byte) (value >>> 24));
|
PlatformDependent.putByte(address, (byte) (value >>> 24));
|
||||||
PlatformDependent.putByte(address + 1, (byte) (value >>> 16));
|
PlatformDependent.putByte(address + 1, (byte) (value >>> 16));
|
||||||
@ -121,7 +122,7 @@ final class UnsafeByteBufUtil {
|
|||||||
|
|
||||||
static void setLong(long address, long value) {
|
static void setLong(long address, long value) {
|
||||||
if (UNALIGNED) {
|
if (UNALIGNED) {
|
||||||
PlatformDependent.putLong(address, NATIVE_ORDER ? value : Long.reverseBytes(value));
|
PlatformDependent.putLong(address, BIG_ENDIAN_NATIVE_ORDER ? value : Long.reverseBytes(value));
|
||||||
} else {
|
} else {
|
||||||
PlatformDependent.putByte(address, (byte) (value >>> 56));
|
PlatformDependent.putByte(address, (byte) (value >>> 56));
|
||||||
PlatformDependent.putByte(address + 1, (byte) (value >>> 48));
|
PlatformDependent.putByte(address + 1, (byte) (value >>> 48));
|
||||||
@ -134,5 +135,113 @@ final class UnsafeByteBufUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static byte getByte(byte[] array, int index) {
|
||||||
|
return PlatformDependent.getByte(array, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
static short getShort(byte[] array, int index) {
|
||||||
|
if (UNALIGNED) {
|
||||||
|
short v = PlatformDependent.getShort(array, index);
|
||||||
|
return BIG_ENDIAN_NATIVE_ORDER ? v : Short.reverseBytes(v);
|
||||||
|
}
|
||||||
|
return (short) (PlatformDependent.getByte(index) << 8 | PlatformDependent.getByte(index + 1) & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getUnsignedMedium(byte[] array, int index) {
|
||||||
|
if (UNALIGNED) {
|
||||||
|
if (BIG_ENDIAN_NATIVE_ORDER) {
|
||||||
|
return (PlatformDependent.getByte(array, index) & 0xff) |
|
||||||
|
(PlatformDependent.getShort(array, index + 1) & 0xffff) << 8;
|
||||||
|
}
|
||||||
|
return (Short.reverseBytes(PlatformDependent.getShort(array, index)) & 0xffff) << 8 |
|
||||||
|
PlatformDependent.getByte(array, index + 2) & 0xff;
|
||||||
|
}
|
||||||
|
return (PlatformDependent.getByte(array, index) & 0xff) << 16 |
|
||||||
|
(PlatformDependent.getByte(array, index + 1) & 0xff) << 8 |
|
||||||
|
PlatformDependent.getByte(array, index + 2) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getInt(byte[] array, int index) {
|
||||||
|
if (UNALIGNED) {
|
||||||
|
int v = PlatformDependent.getInt(array, index);
|
||||||
|
return BIG_ENDIAN_NATIVE_ORDER ? v : Integer.reverseBytes(v);
|
||||||
|
}
|
||||||
|
return PlatformDependent.getByte(array, index) << 24 |
|
||||||
|
(PlatformDependent.getByte(array, index + 1) & 0xff) << 16 |
|
||||||
|
(PlatformDependent.getByte(array, index + 2) & 0xff) << 8 |
|
||||||
|
PlatformDependent.getByte(array, index + 3) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long getLong(byte[] array, int index) {
|
||||||
|
if (UNALIGNED) {
|
||||||
|
long v = PlatformDependent.getLong(array, index);
|
||||||
|
return BIG_ENDIAN_NATIVE_ORDER ? v : Long.reverseBytes(v);
|
||||||
|
}
|
||||||
|
return (long) PlatformDependent.getByte(array, index) << 56 |
|
||||||
|
((long) PlatformDependent.getByte(array, index + 1) & 0xff) << 48 |
|
||||||
|
((long) PlatformDependent.getByte(array, index + 2) & 0xff) << 40 |
|
||||||
|
((long) PlatformDependent.getByte(array, index + 3) & 0xff) << 32 |
|
||||||
|
((long) PlatformDependent.getByte(array, index + 4) & 0xff) << 24 |
|
||||||
|
((long) PlatformDependent.getByte(array, index + 5) & 0xff) << 16 |
|
||||||
|
((long) PlatformDependent.getByte(array, index + 6) & 0xff) << 8 |
|
||||||
|
(long) PlatformDependent.getByte(array, index + 7) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setByte(byte[] array, int index, int value) {
|
||||||
|
PlatformDependent.putByte(array, index, (byte) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setShort(byte[] array, int index, int value) {
|
||||||
|
if (UNALIGNED) {
|
||||||
|
PlatformDependent.putShort(
|
||||||
|
array, index, BIG_ENDIAN_NATIVE_ORDER ? (short) value : Short.reverseBytes((short) value));
|
||||||
|
} else {
|
||||||
|
PlatformDependent.putByte(array, index, (byte) (value >>> 8));
|
||||||
|
PlatformDependent.putByte(array, index + 1, (byte) value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setMedium(byte[] array, int index, int value) {
|
||||||
|
if (UNALIGNED) {
|
||||||
|
if (BIG_ENDIAN_NATIVE_ORDER) {
|
||||||
|
PlatformDependent.putByte(array, index, (byte) value);
|
||||||
|
PlatformDependent.putShort(array, index + 1, (short) (value >>> 8));
|
||||||
|
} else {
|
||||||
|
PlatformDependent.putShort(array, index, Short.reverseBytes((short) (value >>> 8)));
|
||||||
|
PlatformDependent.putByte(array, index + 2, (byte) value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PlatformDependent.putByte(array, index, (byte) (value >>> 16));
|
||||||
|
PlatformDependent.putByte(array, index + 1, (byte) (value >>> 8));
|
||||||
|
PlatformDependent.putByte(array, index + 2, (byte) value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setInt(byte[] array, int index, int value) {
|
||||||
|
if (UNALIGNED) {
|
||||||
|
PlatformDependent.putInt(array, index, BIG_ENDIAN_NATIVE_ORDER ? value : Integer.reverseBytes(value));
|
||||||
|
} else {
|
||||||
|
PlatformDependent.putByte(array, index, (byte) (value >>> 24));
|
||||||
|
PlatformDependent.putByte(array, index + 1, (byte) (value >>> 16));
|
||||||
|
PlatformDependent.putByte(array, index + 2, (byte) (value >>> 8));
|
||||||
|
PlatformDependent.putByte(array, index + 3, (byte) value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setLong(byte[] array, int index, long value) {
|
||||||
|
if (UNALIGNED) {
|
||||||
|
PlatformDependent.putLong(array, index, BIG_ENDIAN_NATIVE_ORDER ? value : Long.reverseBytes(value));
|
||||||
|
} else {
|
||||||
|
PlatformDependent.putByte(array, index, (byte) (value >>> 56));
|
||||||
|
PlatformDependent.putByte(array, index + 1, (byte) (value >>> 48));
|
||||||
|
PlatformDependent.putByte(array, index + 2, (byte) (value >>> 40));
|
||||||
|
PlatformDependent.putByte(array, index + 3, (byte) (value >>> 32));
|
||||||
|
PlatformDependent.putByte(array, index + 4, (byte) (value >>> 24));
|
||||||
|
PlatformDependent.putByte(array, index + 5, (byte) (value >>> 16));
|
||||||
|
PlatformDependent.putByte(array, index + 6, (byte) (value >>> 8));
|
||||||
|
PlatformDependent.putByte(array, index + 7, (byte) value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private UnsafeByteBufUtil() { }
|
private UnsafeByteBufUtil() { }
|
||||||
}
|
}
|
||||||
|
@ -18,24 +18,16 @@ package io.netty.buffer;
|
|||||||
|
|
||||||
import io.netty.util.internal.PlatformDependent;
|
import io.netty.util.internal.PlatformDependent;
|
||||||
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special {@link SwappedByteBuf} for {@link ByteBuf}s that are backed by a {@code memoryAddress}.
|
* Special {@link SwappedByteBuf} for {@link ByteBuf}s that are backed by a {@code memoryAddress}.
|
||||||
*/
|
*/
|
||||||
final class UnsafeDirectSwappedByteBuf extends SwappedByteBuf {
|
final class UnsafeDirectSwappedByteBuf extends AbstractUnsafeSwappedByteBuf {
|
||||||
private static final boolean NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
|
|
||||||
private final boolean nativeByteOrder;
|
|
||||||
private final AbstractByteBuf wrapped;
|
|
||||||
|
|
||||||
UnsafeDirectSwappedByteBuf(AbstractByteBuf buf) {
|
UnsafeDirectSwappedByteBuf(AbstractByteBuf buf) {
|
||||||
super(buf);
|
super(buf);
|
||||||
assert PlatformDependent.isUnaligned();
|
|
||||||
wrapped = buf;
|
|
||||||
nativeByteOrder = NATIVE_ORDER == (order() == ByteOrder.BIG_ENDIAN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private long addr(int index) {
|
private static long addr(AbstractByteBuf wrapped, int index) {
|
||||||
// We need to call wrapped.memoryAddress() everytime and NOT cache it as it may change if the buffer expand.
|
// We need to call wrapped.memoryAddress() everytime and NOT cache it as it may change if the buffer expand.
|
||||||
// See:
|
// See:
|
||||||
// - https://github.com/netty/netty/issues/2587
|
// - https://github.com/netty/netty/issues/2587
|
||||||
@ -44,144 +36,32 @@ final class UnsafeDirectSwappedByteBuf extends SwappedByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getLong(int index) {
|
protected long _getLong(AbstractByteBuf wrapped, int index) {
|
||||||
wrapped.checkIndex(index, 8);
|
return PlatformDependent.getLong(addr(wrapped, index));
|
||||||
long v = PlatformDependent.getLong(addr(index));
|
|
||||||
return nativeByteOrder? v : Long.reverseBytes(v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getFloat(int index) {
|
protected int _getInt(AbstractByteBuf wrapped, int index) {
|
||||||
return Float.intBitsToFloat(getInt(index));
|
return PlatformDependent.getInt(addr(wrapped, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getDouble(int index) {
|
protected short _getShort(AbstractByteBuf wrapped, int index) {
|
||||||
return Double.longBitsToDouble(getLong(index));
|
return PlatformDependent.getShort(addr(wrapped, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char getChar(int index) {
|
protected void _setShort(AbstractByteBuf wrapped, int index, short value) {
|
||||||
return (char) getShort(index);
|
PlatformDependent.putShort(addr(wrapped, index), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getUnsignedInt(int index) {
|
protected void _setInt(AbstractByteBuf wrapped, int index, int value) {
|
||||||
return getInt(index) & 0xFFFFFFFFL;
|
PlatformDependent.putInt(addr(wrapped, index), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getInt(int index) {
|
protected void _setLong(AbstractByteBuf wrapped, int index, long value) {
|
||||||
wrapped.checkIndex(index, 4);
|
PlatformDependent.putLong(addr(wrapped, index), value);
|
||||||
int v = PlatformDependent.getInt(addr(index));
|
|
||||||
return nativeByteOrder? v : Integer.reverseBytes(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getUnsignedShort(int index) {
|
|
||||||
return getShort(index) & 0xFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public short getShort(int index) {
|
|
||||||
wrapped.checkIndex(index, 2);
|
|
||||||
short v = PlatformDependent.getShort(addr(index));
|
|
||||||
return nativeByteOrder? v : Short.reverseBytes(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuf setShort(int index, int value) {
|
|
||||||
wrapped.checkIndex(index, 2);
|
|
||||||
_setShort(index, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuf setInt(int index, int value) {
|
|
||||||
wrapped.checkIndex(index, 4);
|
|
||||||
_setInt(index, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuf setLong(int index, long value) {
|
|
||||||
wrapped.checkIndex(index, 8);
|
|
||||||
_setLong(index, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuf setChar(int index, int value) {
|
|
||||||
setShort(index, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuf setFloat(int index, float value) {
|
|
||||||
setInt(index, Float.floatToRawIntBits(value));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuf setDouble(int index, double value) {
|
|
||||||
setLong(index, Double.doubleToRawLongBits(value));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuf writeShort(int value) {
|
|
||||||
wrapped.ensureAccessible();
|
|
||||||
wrapped.ensureWritable(2);
|
|
||||||
_setShort(wrapped.writerIndex, value);
|
|
||||||
wrapped.writerIndex += 2;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuf writeInt(int value) {
|
|
||||||
wrapped.ensureAccessible();
|
|
||||||
wrapped.ensureWritable(4);
|
|
||||||
_setInt(wrapped.writerIndex, value);
|
|
||||||
wrapped.writerIndex += 4;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuf writeLong(long value) {
|
|
||||||
wrapped.ensureAccessible();
|
|
||||||
wrapped.ensureWritable(8);
|
|
||||||
_setLong(wrapped.writerIndex, value);
|
|
||||||
wrapped.writerIndex += 8;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuf writeChar(int value) {
|
|
||||||
writeShort(value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuf writeFloat(float value) {
|
|
||||||
writeInt(Float.floatToRawIntBits(value));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ByteBuf writeDouble(double value) {
|
|
||||||
writeLong(Double.doubleToRawLongBits(value));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void _setShort(int index, int value) {
|
|
||||||
PlatformDependent.putShort(addr(index), nativeByteOrder ? (short) value : Short.reverseBytes((short) value));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void _setInt(int index, int value) {
|
|
||||||
PlatformDependent.putInt(addr(index), nativeByteOrder ? value : Integer.reverseBytes(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void _setLong(int index, long value) {
|
|
||||||
PlatformDependent.putLong(addr(index), nativeByteOrder ? value : Long.reverseBytes(value));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014 The Netty Project
|
||||||
|
*
|
||||||
|
* The Netty Project licenses this file to you under the Apache License,
|
||||||
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at:
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.netty.buffer;
|
||||||
|
|
||||||
|
import io.netty.util.internal.PlatformDependent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special {@link SwappedByteBuf} for {@link ByteBuf}s that use unsafe to access the byte array.
|
||||||
|
*/
|
||||||
|
final class UnsafeHeapSwappedByteBuf extends AbstractUnsafeSwappedByteBuf {
|
||||||
|
|
||||||
|
UnsafeHeapSwappedByteBuf(AbstractByteBuf buf) {
|
||||||
|
super(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int idx(ByteBuf wrapped, int index) {
|
||||||
|
return wrapped.arrayOffset() + index;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected long _getLong(AbstractByteBuf wrapped, int index) {
|
||||||
|
return PlatformDependent.getLong(wrapped.array(), idx(wrapped, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int _getInt(AbstractByteBuf wrapped, int index) {
|
||||||
|
return PlatformDependent.getInt(wrapped.array(), idx(wrapped, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected short _getShort(AbstractByteBuf wrapped, int index) {
|
||||||
|
return PlatformDependent.getShort(wrapped.array(), idx(wrapped, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void _setShort(AbstractByteBuf wrapped, int index, short value) {
|
||||||
|
PlatformDependent.putShort(wrapped.array(), idx(wrapped, index), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void _setInt(AbstractByteBuf wrapped, int index, int value) {
|
||||||
|
PlatformDependent.putInt(wrapped.array(), idx(wrapped, index), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void _setLong(AbstractByteBuf wrapped, int index, long value) {
|
||||||
|
PlatformDependent.putLong(wrapped.array(), idx(wrapped, index), value);
|
||||||
|
}
|
||||||
|
}
|
@ -30,6 +30,7 @@ import java.lang.reflect.Method;
|
|||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -87,6 +88,7 @@ public final class PlatformDependent {
|
|||||||
private static final int BIT_MODE = bitMode0();
|
private static final int BIT_MODE = bitMode0();
|
||||||
|
|
||||||
private static final int ADDRESS_SIZE = addressSize0();
|
private static final int ADDRESS_SIZE = addressSize0();
|
||||||
|
private static final boolean NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
@ -344,6 +346,22 @@ public final class PlatformDependent {
|
|||||||
return PlatformDependent0.getLong(address);
|
return PlatformDependent0.getLong(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte getByte(byte[] data, int index) {
|
||||||
|
return PlatformDependent0.getByte(data, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static short getShort(byte[] data, int index) {
|
||||||
|
return PlatformDependent0.getShort(data, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getInt(byte[] data, int index) {
|
||||||
|
return PlatformDependent0.getInt(data, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long getLong(byte[] data, int index) {
|
||||||
|
return PlatformDependent0.getLong(data, index);
|
||||||
|
}
|
||||||
|
|
||||||
public static void putOrderedObject(Object object, long address, Object value) {
|
public static void putOrderedObject(Object object, long address, Object value) {
|
||||||
PlatformDependent0.putOrderedObject(object, address, value);
|
PlatformDependent0.putOrderedObject(object, address, value);
|
||||||
}
|
}
|
||||||
@ -364,6 +382,22 @@ public final class PlatformDependent {
|
|||||||
PlatformDependent0.putLong(address, value);
|
PlatformDependent0.putLong(address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void putByte(byte[] data, int index, byte value) {
|
||||||
|
PlatformDependent0.putByte(data, index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void putShort(byte[] data, int index, short value) {
|
||||||
|
PlatformDependent0.putShort(data, index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void putInt(byte[] data, int index, int value) {
|
||||||
|
PlatformDependent0.putInt(data, index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void putLong(byte[] data, int index, long value) {
|
||||||
|
PlatformDependent0.putLong(data, index, value);
|
||||||
|
}
|
||||||
|
|
||||||
public static void copyMemory(long srcAddr, long dstAddr, long length) {
|
public static void copyMemory(long srcAddr, long dstAddr, long length) {
|
||||||
PlatformDependent0.copyMemory(srcAddr, dstAddr, length);
|
PlatformDependent0.copyMemory(srcAddr, dstAddr, length);
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ final class PlatformDependent0 {
|
|||||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(PlatformDependent0.class);
|
private static final InternalLogger logger = InternalLoggerFactory.getInstance(PlatformDependent0.class);
|
||||||
static final Unsafe UNSAFE;
|
static final Unsafe UNSAFE;
|
||||||
private static final long ADDRESS_FIELD_OFFSET;
|
private static final long ADDRESS_FIELD_OFFSET;
|
||||||
|
private static final long BYTE_ARRAY_BASE_OFFSET;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Limits the number of bytes to copy per {@link Unsafe#copyMemory(long, long, long)} to allow safepoint polling
|
* Limits the number of bytes to copy per {@link Unsafe#copyMemory(long, long, long)} to allow safepoint polling
|
||||||
@ -106,6 +107,7 @@ final class PlatformDependent0 {
|
|||||||
UNSAFE = unsafe;
|
UNSAFE = unsafe;
|
||||||
|
|
||||||
if (unsafe == null) {
|
if (unsafe == null) {
|
||||||
|
BYTE_ARRAY_BASE_OFFSET = -1;
|
||||||
ADDRESS_FIELD_OFFSET = -1;
|
ADDRESS_FIELD_OFFSET = -1;
|
||||||
UNALIGNED = false;
|
UNALIGNED = false;
|
||||||
} else {
|
} else {
|
||||||
@ -125,6 +127,7 @@ final class PlatformDependent0 {
|
|||||||
|
|
||||||
UNALIGNED = unaligned;
|
UNALIGNED = unaligned;
|
||||||
logger.debug("java.nio.Bits.unaligned: {}", UNALIGNED);
|
logger.debug("java.nio.Bits.unaligned: {}", UNALIGNED);
|
||||||
|
BYTE_ARRAY_BASE_OFFSET = arrayBaseOffset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,6 +194,22 @@ final class PlatformDependent0 {
|
|||||||
return UNSAFE.getLong(address);
|
return UNSAFE.getLong(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static byte getByte(byte[] data, int index) {
|
||||||
|
return UNSAFE.getByte(data, BYTE_ARRAY_BASE_OFFSET + index);
|
||||||
|
}
|
||||||
|
|
||||||
|
static short getShort(byte[] data, int index) {
|
||||||
|
return UNSAFE.getShort(data, BYTE_ARRAY_BASE_OFFSET + index);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getInt(byte[] data, int index) {
|
||||||
|
return UNSAFE.getInt(data, BYTE_ARRAY_BASE_OFFSET + index);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long getLong(byte[] data, int index) {
|
||||||
|
return UNSAFE.getLong(data, BYTE_ARRAY_BASE_OFFSET + index);
|
||||||
|
}
|
||||||
|
|
||||||
static void putOrderedObject(Object object, long address, Object value) {
|
static void putOrderedObject(Object object, long address, Object value) {
|
||||||
UNSAFE.putOrderedObject(object, address, value);
|
UNSAFE.putOrderedObject(object, address, value);
|
||||||
}
|
}
|
||||||
@ -211,6 +230,22 @@ final class PlatformDependent0 {
|
|||||||
UNSAFE.putLong(address, value);
|
UNSAFE.putLong(address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void putByte(byte[] data, int index, byte value) {
|
||||||
|
UNSAFE.putByte(data, BYTE_ARRAY_BASE_OFFSET + index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void putShort(byte[] data, int index, short value) {
|
||||||
|
UNSAFE.putShort(data, BYTE_ARRAY_BASE_OFFSET + index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void putInt(byte[] data, int index, int value) {
|
||||||
|
UNSAFE.putInt(data, BYTE_ARRAY_BASE_OFFSET + index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void putLong(byte[] data, int index, long value) {
|
||||||
|
UNSAFE.putLong(data, BYTE_ARRAY_BASE_OFFSET + index, value);
|
||||||
|
}
|
||||||
|
|
||||||
static void copyMemory(long srcAddr, long dstAddr, long length) {
|
static void copyMemory(long srcAddr, long dstAddr, long length) {
|
||||||
//UNSAFE.copyMemory(srcAddr, dstAddr, length);
|
//UNSAFE.copyMemory(srcAddr, dstAddr, length);
|
||||||
while (length > 0) {
|
while (length > 0) {
|
||||||
|
Loading…
Reference in New Issue
Block a user