8264762: ByteBuffer.byteOrder(BIG_ENDIAN).asXBuffer.put(Xarray) and ByteBuffer.byteOrder(nativeOrder()).asXBuffer.put(Xarray) are slow

Reviewed-by: alanb, psandoz, chegar
This commit is contained in:
Brian Burkhalter 2021-04-29 15:34:04 +00:00
parent f0f6b0d919
commit 6bb71d9e25
2 changed files with 109 additions and 204 deletions

View File

@ -344,82 +344,6 @@ class Direct$Type$Buffer$RW$$BO$
}
}
#end[streamableType]
public $Type$Buffer get($type$[] dst, int offset, int length) {
#if[rw]
if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
Objects.checkFromIndexSize(offset, length, dst.length);
int pos = position();
int lim = limit();
assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0);
if (length > rem)
throw new BufferUnderflowException();
long dstOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
try {
#if[!byte]
if (order() != ByteOrder.nativeOrder())
SCOPED_MEMORY_ACCESS.copySwapMemory(scope(), null, null,
ix(pos),
dst,
dstOffset,
(long)length << $LG_BYTES_PER_VALUE$,
(long)1 << $LG_BYTES_PER_VALUE$);
else
#end[!byte]
SCOPED_MEMORY_ACCESS.copyMemory(scope(), null, null,
ix(pos),
dst,
dstOffset,
(long)length << $LG_BYTES_PER_VALUE$);
} finally {
Reference.reachabilityFence(this);
}
position(pos + length);
} else {
super.get(dst, offset, length);
}
return this;
#else[rw]
throw new ReadOnlyBufferException();
#end[rw]
}
public $Type$Buffer get(int index, $type$[] dst, int offset, int length) {
#if[rw]
if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
Objects.checkFromIndexSize(index, length, limit());
Objects.checkFromIndexSize(offset, length, dst.length);
long dstOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
try {
#if[!byte]
if (order() != ByteOrder.nativeOrder())
SCOPED_MEMORY_ACCESS.copySwapMemory(scope(), null, null,
ix(index),
dst,
dstOffset,
(long)length << $LG_BYTES_PER_VALUE$,
(long)1 << $LG_BYTES_PER_VALUE$);
else
#end[!byte]
SCOPED_MEMORY_ACCESS.copyMemory(scope(), null, null,
ix(index),
dst,
dstOffset,
(long)length << $LG_BYTES_PER_VALUE$);
} finally {
Reference.reachabilityFence(this);
}
} else {
super.get(index, dst, offset, length);
}
return this;
#else[rw]
throw new ReadOnlyBufferException();
#end[rw]
}
#end[rw]
public $Type$Buffer put($type$ x) {
@ -448,99 +372,6 @@ class Direct$Type$Buffer$RW$$BO$
#end[rw]
}
public $Type$Buffer put($Type$Buffer src) {
#if[rw]
super.put(src);
return this;
#else[rw]
throw new ReadOnlyBufferException();
#end[rw]
}
public $Type$Buffer put(int index, $Type$Buffer src, int offset, int length) {
#if[rw]
super.put(index, src, offset, length);
return this;
#else[rw]
throw new ReadOnlyBufferException();
#end[rw]
}
public $Type$Buffer put($type$[] src, int offset, int length) {
#if[rw]
if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) {
Objects.checkFromIndexSize(offset, length, src.length);
int pos = position();
int lim = limit();
assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0);
if (length > rem)
throw new BufferOverflowException();
long srcOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
try {
#if[!byte]
if (order() != ByteOrder.nativeOrder())
SCOPED_MEMORY_ACCESS.copySwapMemory(null, scope(), src,
srcOffset,
null,
ix(pos),
(long)length << $LG_BYTES_PER_VALUE$,
(long)1 << $LG_BYTES_PER_VALUE$);
else
#end[!byte]
SCOPED_MEMORY_ACCESS.copyMemory(null, scope(), src,
srcOffset,
null,
ix(pos),
(long)length << $LG_BYTES_PER_VALUE$);
} finally {
Reference.reachabilityFence(this);
}
position(pos + length);
} else {
super.put(src, offset, length);
}
return this;
#else[rw]
throw new ReadOnlyBufferException();
#end[rw]
}
public $Type$Buffer put(int index, $type$[] src, int offset, int length) {
#if[rw]
if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) {
Objects.checkFromIndexSize(index, length, limit());
Objects.checkFromIndexSize(offset, length, src.length);
long srcOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
try {
#if[!byte]
if (order() != ByteOrder.nativeOrder())
SCOPED_MEMORY_ACCESS.copySwapMemory(null, scope(), src,
srcOffset,
null,
ix(index),
(long)length << $LG_BYTES_PER_VALUE$,
(long)1 << $LG_BYTES_PER_VALUE$);
else
#end[!byte]
SCOPED_MEMORY_ACCESS.copyMemory(
null, scope(), src,
srcOffset, null, ix(index), (long)length << $LG_BYTES_PER_VALUE$);
} finally {
Reference.reachabilityFence(this);
}
} else {
super.put(index, src, offset, length);
}
return this;
#else[rw]
throw new ReadOnlyBufferException();
#end[rw]
}
public {#if[byte]?Mapped$Type$Buffer:$Type$Buffer} compact() {
#if[rw]
int pos = position();

View File

@ -268,6 +268,8 @@ public abstract class $Type$Buffer
extends Buffer
implements Comparable<$Type$Buffer>{#if[char]?, Appendable, CharSequence, Readable}
{
// Cached array base offset
private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset($type$[].class);
// These fields are declared here rather than in Heap-X-Buffer in order to
// reduce the number of virtual method invocations needed to access these
@ -791,11 +793,13 @@ public abstract class $Type$Buffer
*/
public $Type$Buffer get($type$[] dst, int offset, int length) {
Objects.checkFromIndexSize(offset, length, dst.length);
if (length > remaining())
int pos = position();
if (length > limit() - pos)
throw new BufferUnderflowException();
int end = offset + length;
for (int i = offset; i < end; i++)
dst[i] = get();
getArray(pos, dst, offset, length);
position(pos + length);
return this;
}
@ -869,9 +873,9 @@ public abstract class $Type$Buffer
public $Type$Buffer get(int index, $type$[] dst, int offset, int length) {
Objects.checkFromIndexSize(index, length, limit());
Objects.checkFromIndexSize(offset, length, dst.length);
int end = offset + length;
for (int i = offset, j = index; i < end; i++, j++)
dst[i] = get(j);
getArray(index, dst, offset, length);
return this;
}
@ -906,6 +910,40 @@ public abstract class $Type$Buffer
return get(index, dst, 0, dst.length);
}
private $Type$Buffer getArray(int index, $type$[] dst, int offset, int length) {
if (
#if[char]
isAddressable() &&
#end[char]
((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
long bufAddr = address + ((long)index << $LG_BYTES_PER_VALUE$);
long dstOffset =
ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
long len = (long)length << $LG_BYTES_PER_VALUE$;
try {
#if[!byte]
if (order() != ByteOrder.nativeOrder())
SCOPED_MEMORY_ACCESS.copySwapMemory(
scope(), null, base(), bufAddr,
dst, dstOffset, len, $Fulltype$.BYTES);
else
#end[!byte]
SCOPED_MEMORY_ACCESS.copyMemory(
scope(), null, base(), bufAddr,
dst, dstOffset, len);
} finally {
Reference.reachabilityFence(this);
}
} else {
int end = offset + length;
for (int i = offset, j = index; i < end; i++, j++) {
dst[i] = get(j);
}
}
return this;
}
// -- Bulk put operations --
/**
@ -1038,8 +1076,8 @@ public abstract class $Type$Buffer
}
void putBuffer(int pos, $Type$Buffer src, int srcPos, int n) {
#if[rw]
Object srcBase = src.base();
#if[char]
if (src.isAddressable()) {
#else[char]
@ -1053,29 +1091,21 @@ public abstract class $Type$Buffer
long addr = address + ((long)pos << $LG_BYTES_PER_VALUE$);
long len = (long)n << $LG_BYTES_PER_VALUE$;
try {
#if[!byte]
if (this.order() == src.order()) {
#end[!byte]
try {
SCOPED_MEMORY_ACCESS.copyMemory(
src.scope(), scope(), srcBase,
srcAddr, base, addr, len);
} finally {
Reference.reachabilityFence(src);
Reference.reachabilityFence(this);
}
#if[!byte]
} else {
try {
if (this.order() != src.order())
SCOPED_MEMORY_ACCESS.copySwapMemory(
src.scope(), scope(), srcBase,
srcAddr, base, addr, len, (long)1 << $LG_BYTES_PER_VALUE$);
} finally {
Reference.reachabilityFence(src);
Reference.reachabilityFence(this);
}
}
src.scope(), scope(), srcBase, srcAddr,
base, addr, len, $Fulltype$.BYTES);
else
#end[!byte]
SCOPED_MEMORY_ACCESS.copyMemory(
src.scope(), scope(), srcBase, srcAddr,
base, addr, len);
} finally {
Reference.reachabilityFence(src);
Reference.reachabilityFence(this);
}
#if[char]
} else { // src.isAddressable() == false
assert StringCharBuffer.class.isInstance(src);
@ -1084,6 +1114,9 @@ public abstract class $Type$Buffer
put(i, src.get(j));
}
#end[char]
#else[rw]
throw new ReadOnlyBufferException();
#end[rw]
}
/**
@ -1138,12 +1171,16 @@ public abstract class $Type$Buffer
* If this buffer is read-only
*/
public $Type$Buffer put($type$[] src, int offset, int length) {
if (isReadOnly())
throw new ReadOnlyBufferException();
Objects.checkFromIndexSize(offset, length, src.length);
if (length > remaining())
int pos = position();
if (length > limit() - pos)
throw new BufferOverflowException();
int end = offset + length;
for (int i = offset; i < end; i++)
this.put(src[i]);
putArray(pos, src, offset, length);
position(pos + length);
return this;
}
@ -1223,9 +1260,9 @@ public abstract class $Type$Buffer
throw new ReadOnlyBufferException();
Objects.checkFromIndexSize(index, length, limit());
Objects.checkFromIndexSize(offset, length, src.length);
int end = offset + length;
for (int i = offset, j = index; i < end; i++, j++)
this.put(j, src[i]);
putArray(index, src, offset, length);
return this;
}
@ -1262,6 +1299,43 @@ public abstract class $Type$Buffer
return put(index, src, 0, src.length);
}
private $Type$Buffer putArray(int index, $type$[] src, int offset, int length) {
#if[rw]
if (
#if[char]
isAddressable() &&
#end[char]
((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) {
long bufAddr = address + ((long)index << $LG_BYTES_PER_VALUE$);
long srcOffset =
ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
long len = (long)length << $LG_BYTES_PER_VALUE$;
try {
#if[!byte]
if (order() != ByteOrder.nativeOrder())
SCOPED_MEMORY_ACCESS.copySwapMemory(
null, scope(), src, srcOffset,
base(), bufAddr, len, $Fulltype$.BYTES);
else
#end[!byte]
SCOPED_MEMORY_ACCESS.copyMemory(
null, scope(), src, srcOffset,
base(), bufAddr, len);
} finally {
Reference.reachabilityFence(this);
}
} else {
int end = offset + length;
for (int i = offset, j = index; i < end; i++, j++)
this.put(j, src[i]);
}
return this;
#else[rw]
throw new ReadOnlyBufferException();
#end[rw]
}
#if[char]
/**