mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-15 21:05:11 +00:00
8256477: Specialize heap memory segment implementations
Reviewed-by: jvernee, chegar
This commit is contained in:
parent
97074969a5
commit
d2ddf07461
@ -691,7 +691,7 @@ for (long l = 0; l < segment.byteSize(); l++) {
|
||||
* @return a new confined array memory segment.
|
||||
*/
|
||||
static MemorySegment ofArray(byte[] arr) {
|
||||
return HeapMemorySegmentImpl.makeArraySegment(arr);
|
||||
return HeapMemorySegmentImpl.OfByte.fromArray(arr);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -705,7 +705,7 @@ for (long l = 0; l < segment.byteSize(); l++) {
|
||||
* @return a new confined array memory segment.
|
||||
*/
|
||||
static MemorySegment ofArray(char[] arr) {
|
||||
return HeapMemorySegmentImpl.makeArraySegment(arr);
|
||||
return HeapMemorySegmentImpl.OfChar.fromArray(arr);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -719,7 +719,7 @@ for (long l = 0; l < segment.byteSize(); l++) {
|
||||
* @return a new confined array memory segment.
|
||||
*/
|
||||
static MemorySegment ofArray(short[] arr) {
|
||||
return HeapMemorySegmentImpl.makeArraySegment(arr);
|
||||
return HeapMemorySegmentImpl.OfShort.fromArray(arr);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -733,7 +733,7 @@ for (long l = 0; l < segment.byteSize(); l++) {
|
||||
* @return a new confined array memory segment.
|
||||
*/
|
||||
static MemorySegment ofArray(int[] arr) {
|
||||
return HeapMemorySegmentImpl.makeArraySegment(arr);
|
||||
return HeapMemorySegmentImpl.OfInt.fromArray(arr);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -747,7 +747,7 @@ for (long l = 0; l < segment.byteSize(); l++) {
|
||||
* @return a new confined array memory segment.
|
||||
*/
|
||||
static MemorySegment ofArray(float[] arr) {
|
||||
return HeapMemorySegmentImpl.makeArraySegment(arr);
|
||||
return HeapMemorySegmentImpl.OfFloat.fromArray(arr);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -761,7 +761,7 @@ for (long l = 0; l < segment.byteSize(); l++) {
|
||||
* @return a new confined array memory segment.
|
||||
*/
|
||||
static MemorySegment ofArray(long[] arr) {
|
||||
return HeapMemorySegmentImpl.makeArraySegment(arr);
|
||||
return HeapMemorySegmentImpl.OfLong.fromArray(arr);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -775,7 +775,7 @@ for (long l = 0; l < segment.byteSize(); l++) {
|
||||
* @return a new confined array memory segment.
|
||||
*/
|
||||
static MemorySegment ofArray(double[] arr) {
|
||||
return HeapMemorySegmentImpl.makeArraySegment(arr);
|
||||
return HeapMemorySegmentImpl.OfDouble.fromArray(arr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -588,7 +588,7 @@ public abstract class AbstractMemorySegmentImpl implements MemorySegment, Memory
|
||||
modes &= ~WRITE;
|
||||
}
|
||||
if (base != null) {
|
||||
return new HeapMemorySegmentImpl<>(bbAddress + pos, () -> (byte[])base, size, modes, bufferScope);
|
||||
return new HeapMemorySegmentImpl.OfByte(bbAddress + pos, (byte[])base, size, modes, bufferScope);
|
||||
} else if (unmapper == null) {
|
||||
return new NativeMemorySegmentImpl(bbAddress + pos, size, modes, bufferScope);
|
||||
} else {
|
||||
|
||||
@ -39,29 +39,27 @@ import java.util.function.Supplier;
|
||||
/**
|
||||
* Implementation for heap memory segments. An heap memory segment is composed by an offset and
|
||||
* a base object (typically an array). To enhance performances, the access to the base object needs to feature
|
||||
* sharp type information, as well as sharp null-check information. For this reason, the factories for heap segments
|
||||
* use a lambda to implement the base object accessor, so that the type information will remain sharp (e.g.
|
||||
* the static compiler will generate specialized base accessor for us).
|
||||
* sharp type information, as well as sharp null-check information. For this reason, many concrete subclasses
|
||||
* of {@link HeapMemorySegmentImpl} are defined (e.g. {@link OfFloat}, so that each subclass can override the
|
||||
* {@link HeapMemorySegmentImpl#base()} method so that it returns an array of the correct (sharp) type.
|
||||
*/
|
||||
public class HeapMemorySegmentImpl<H> extends AbstractMemorySegmentImpl {
|
||||
public abstract class HeapMemorySegmentImpl<H> extends AbstractMemorySegmentImpl {
|
||||
|
||||
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
|
||||
private static final int BYTE_ARR_BASE = UNSAFE.arrayBaseOffset(byte[].class);
|
||||
|
||||
final long offset;
|
||||
final Supplier<H> baseProvider;
|
||||
final H base;
|
||||
|
||||
@ForceInline
|
||||
HeapMemorySegmentImpl(long offset, Supplier<H> baseProvider, long length, int mask, MemoryScope scope) {
|
||||
HeapMemorySegmentImpl(long offset, H base, long length, int mask, MemoryScope scope) {
|
||||
super(length, mask, scope);
|
||||
this.offset = offset;
|
||||
this.baseProvider = baseProvider;
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
@Override
|
||||
H base() {
|
||||
return Objects.requireNonNull(baseProvider.get());
|
||||
}
|
||||
abstract H base();
|
||||
|
||||
@Override
|
||||
long min() {
|
||||
@ -69,9 +67,7 @@ public class HeapMemorySegmentImpl<H> extends AbstractMemorySegmentImpl {
|
||||
}
|
||||
|
||||
@Override
|
||||
HeapMemorySegmentImpl<H> dup(long offset, long size, int mask, MemoryScope scope) {
|
||||
return new HeapMemorySegmentImpl<>(this.offset + offset, baseProvider, size, mask, scope);
|
||||
}
|
||||
abstract HeapMemorySegmentImpl<H> dup(long offset, long size, int mask, MemoryScope scope);
|
||||
|
||||
@Override
|
||||
ByteBuffer makeByteBuffer() {
|
||||
@ -84,44 +80,164 @@ public class HeapMemorySegmentImpl<H> extends AbstractMemorySegmentImpl {
|
||||
|
||||
// factories
|
||||
|
||||
public static MemorySegment makeArraySegment(byte[] arr) {
|
||||
return makeHeapSegment(() -> arr, arr.length,
|
||||
Unsafe.ARRAY_BYTE_BASE_OFFSET, Unsafe.ARRAY_BYTE_INDEX_SCALE);
|
||||
public static class OfByte extends HeapMemorySegmentImpl<byte[]> {
|
||||
|
||||
OfByte(long offset, byte[] base, long length, int mask, MemoryScope scope) {
|
||||
super(offset, base, length, mask, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfByte dup(long offset, long size, int mask, MemoryScope scope) {
|
||||
return new OfByte(this.offset + offset, base, size, mask, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
byte[] base() {
|
||||
return Objects.requireNonNull(base);
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(byte[] arr) {
|
||||
int byteSize = arr.length * Unsafe.ARRAY_BYTE_INDEX_SCALE;
|
||||
MemoryScope scope = MemoryScope.createConfined(null, MemoryScope.DUMMY_CLEANUP_ACTION, null);
|
||||
return new OfByte(Unsafe.ARRAY_BYTE_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize), scope);
|
||||
}
|
||||
}
|
||||
|
||||
public static MemorySegment makeArraySegment(char[] arr) {
|
||||
return makeHeapSegment(() -> arr, arr.length,
|
||||
Unsafe.ARRAY_CHAR_BASE_OFFSET, Unsafe.ARRAY_CHAR_INDEX_SCALE);
|
||||
public static class OfChar extends HeapMemorySegmentImpl<char[]> {
|
||||
|
||||
OfChar(long offset, char[] base, long length, int mask, MemoryScope scope) {
|
||||
super(offset, base, length, mask, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfChar dup(long offset, long size, int mask, MemoryScope scope) {
|
||||
return new OfChar(this.offset + offset, base, size, mask, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
char[] base() {
|
||||
return Objects.requireNonNull(base);
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(char[] arr) {
|
||||
int byteSize = arr.length * Unsafe.ARRAY_CHAR_INDEX_SCALE;
|
||||
MemoryScope scope = MemoryScope.createConfined(null, MemoryScope.DUMMY_CLEANUP_ACTION, null);
|
||||
return new OfChar(Unsafe.ARRAY_CHAR_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize), scope);
|
||||
}
|
||||
}
|
||||
|
||||
public static MemorySegment makeArraySegment(short[] arr) {
|
||||
return makeHeapSegment(() -> arr, arr.length,
|
||||
Unsafe.ARRAY_SHORT_BASE_OFFSET, Unsafe.ARRAY_SHORT_INDEX_SCALE);
|
||||
public static class OfShort extends HeapMemorySegmentImpl<short[]> {
|
||||
|
||||
OfShort(long offset, short[] base, long length, int mask, MemoryScope scope) {
|
||||
super(offset, base, length, mask, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfShort dup(long offset, long size, int mask, MemoryScope scope) {
|
||||
return new OfShort(this.offset + offset, base, size, mask, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
short[] base() {
|
||||
return Objects.requireNonNull(base);
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(short[] arr) {
|
||||
int byteSize = arr.length * Unsafe.ARRAY_SHORT_INDEX_SCALE;
|
||||
MemoryScope scope = MemoryScope.createConfined(null, MemoryScope.DUMMY_CLEANUP_ACTION, null);
|
||||
return new OfShort(Unsafe.ARRAY_SHORT_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize), scope);
|
||||
}
|
||||
}
|
||||
|
||||
public static MemorySegment makeArraySegment(int[] arr) {
|
||||
return makeHeapSegment(() -> arr, arr.length,
|
||||
Unsafe.ARRAY_INT_BASE_OFFSET, Unsafe.ARRAY_INT_INDEX_SCALE);
|
||||
public static class OfInt extends HeapMemorySegmentImpl<int[]> {
|
||||
|
||||
OfInt(long offset, int[] base, long length, int mask, MemoryScope scope) {
|
||||
super(offset, base, length, mask, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfInt dup(long offset, long size, int mask, MemoryScope scope) {
|
||||
return new OfInt(this.offset + offset, base, size, mask, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
int[] base() {
|
||||
return Objects.requireNonNull(base);
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(int[] arr) {
|
||||
int byteSize = arr.length * Unsafe.ARRAY_INT_INDEX_SCALE;
|
||||
MemoryScope scope = MemoryScope.createConfined(null, MemoryScope.DUMMY_CLEANUP_ACTION, null);
|
||||
return new OfInt(Unsafe.ARRAY_INT_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize), scope);
|
||||
}
|
||||
}
|
||||
|
||||
public static MemorySegment makeArraySegment(long[] arr) {
|
||||
return makeHeapSegment(() -> arr, arr.length,
|
||||
Unsafe.ARRAY_LONG_BASE_OFFSET, Unsafe.ARRAY_LONG_INDEX_SCALE);
|
||||
public static class OfLong extends HeapMemorySegmentImpl<long[]> {
|
||||
|
||||
OfLong(long offset, long[] base, long length, int mask, MemoryScope scope) {
|
||||
super(offset, base, length, mask, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfLong dup(long offset, long size, int mask, MemoryScope scope) {
|
||||
return new OfLong(this.offset + offset, base, size, mask, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
long[] base() {
|
||||
return Objects.requireNonNull(base);
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(long[] arr) {
|
||||
int byteSize = arr.length * Unsafe.ARRAY_LONG_INDEX_SCALE;
|
||||
MemoryScope scope = MemoryScope.createConfined(null, MemoryScope.DUMMY_CLEANUP_ACTION, null);
|
||||
return new OfLong(Unsafe.ARRAY_LONG_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize), scope);
|
||||
}
|
||||
}
|
||||
|
||||
public static MemorySegment makeArraySegment(float[] arr) {
|
||||
return makeHeapSegment(() -> arr, arr.length,
|
||||
Unsafe.ARRAY_FLOAT_BASE_OFFSET, Unsafe.ARRAY_FLOAT_INDEX_SCALE);
|
||||
public static class OfFloat extends HeapMemorySegmentImpl<float[]> {
|
||||
|
||||
OfFloat(long offset, float[] base, long length, int mask, MemoryScope scope) {
|
||||
super(offset, base, length, mask, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfFloat dup(long offset, long size, int mask, MemoryScope scope) {
|
||||
return new OfFloat(this.offset + offset, base, size, mask, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
float[] base() {
|
||||
return Objects.requireNonNull(base);
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(float[] arr) {
|
||||
int byteSize = arr.length * Unsafe.ARRAY_FLOAT_INDEX_SCALE;
|
||||
MemoryScope scope = MemoryScope.createConfined(null, MemoryScope.DUMMY_CLEANUP_ACTION, null);
|
||||
return new OfFloat(Unsafe.ARRAY_FLOAT_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize), scope);
|
||||
}
|
||||
}
|
||||
|
||||
public static MemorySegment makeArraySegment(double[] arr) {
|
||||
return makeHeapSegment(() -> arr, arr.length,
|
||||
Unsafe.ARRAY_DOUBLE_BASE_OFFSET, Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
|
||||
}
|
||||
public static class OfDouble extends HeapMemorySegmentImpl<double[]> {
|
||||
|
||||
static <Z> HeapMemorySegmentImpl<Z> makeHeapSegment(Supplier<Z> obj, int length, int base, int scale) {
|
||||
int byteSize = length * scale;
|
||||
MemoryScope scope = MemoryScope.createConfined(null, MemoryScope.DUMMY_CLEANUP_ACTION, null);
|
||||
return new HeapMemorySegmentImpl<>(base, obj, byteSize, defaultAccessModes(byteSize), scope);
|
||||
OfDouble(long offset, double[] base, long length, int mask, MemoryScope scope) {
|
||||
super(offset, base, length, mask, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfDouble dup(long offset, long size, int mask, MemoryScope scope) {
|
||||
return new OfDouble(this.offset + offset, base, size, mask, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
double[] base() {
|
||||
return Objects.requireNonNull(base);
|
||||
}
|
||||
|
||||
public static MemorySegment fromArray(double[] arr) {
|
||||
int byteSize = arr.length * Unsafe.ARRAY_DOUBLE_INDEX_SCALE;
|
||||
MemoryScope scope = MemoryScope.createConfined(null, MemoryScope.DUMMY_CLEANUP_ACTION, null);
|
||||
return new OfDouble(Unsafe.ARRAY_DOUBLE_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize), scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,6 +32,7 @@ import org.openjdk.jmh.annotations.Fork;
|
||||
import org.openjdk.jmh.annotations.Measurement;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||
import org.openjdk.jmh.annotations.Param;
|
||||
import org.openjdk.jmh.annotations.Setup;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
import org.openjdk.jmh.annotations.TearDown;
|
||||
@ -67,8 +68,27 @@ public class LoopOverNonConstantHeap {
|
||||
|
||||
ByteBuffer byteBuffer;
|
||||
|
||||
@Param(value = {"false", "true"})
|
||||
boolean polluteProfile;
|
||||
|
||||
@Setup
|
||||
public void setup() {
|
||||
if (polluteProfile) {
|
||||
MemorySegment intB = MemorySegment.ofArray(new byte[ALLOC_SIZE]);
|
||||
MemorySegment intI = MemorySegment.ofArray(new int[ALLOC_SIZE]);
|
||||
MemorySegment intD = MemorySegment.ofArray(new double[ALLOC_SIZE]);
|
||||
MemorySegment intF = MemorySegment.ofArray(new float[ALLOC_SIZE]);
|
||||
try (MemorySegment s = MemorySegment.allocateNative(ALLOC_SIZE)) {
|
||||
for (int i = 0; i < ALLOC_SIZE; i++) {
|
||||
MemoryAccess.setByteAtOffset(intB, i, (byte)i);
|
||||
MemoryAccess.setIntAtIndex(intI, i, i);
|
||||
MemoryAccess.setDoubleAtIndex(intD, i, i);
|
||||
MemoryAccess.setFloatAtIndex(intF, i, i);
|
||||
MemoryAccess.setByteAtOffset(s, i, (byte) i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base = new byte[ALLOC_SIZE];
|
||||
for (int i = 0; i < ELEM_SIZE; i++) {
|
||||
unsafe.putInt(base, UNSAFE_BYTE_BASE + (i * CARRIER_SIZE) , i);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user