Skip to content

Commit

Permalink
Copy primitive arrays via Unsafe.copyMemory()
Browse files Browse the repository at this point in the history
  • Loading branch information
fniephaus committed Mar 16, 2022
1 parent 538dbf3 commit 7b99bfa
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import de.hpi.swa.trufflesqueak.model.layout.ObjectLayouts.ERROR_TABLE;
import de.hpi.swa.trufflesqueak.nodes.SqueakGuards;
import de.hpi.swa.trufflesqueak.nodes.accessing.AbstractPointersObjectNodes.AbstractPointersObjectWriteNode;
import de.hpi.swa.trufflesqueak.util.UnsafeUtils;

/* Automatically generated by
VMPluginCodeGenerator * VMMaker.oscog-eem.2480 uuid: bb3ffda7-8241-4dea-b886-d656e474b6c1
Expand Down Expand Up @@ -591,7 +592,7 @@ private long allocateGradientFillrampWidthisRadial(final int[] ramp, final long
workBuffer[rampPtr + i] = transformColor(ramp[i]);
}
} else {
System.arraycopy(ramp, 0, workBuffer, rampPtr, (int) rampWidth);
UnsafeUtils.copyInts(ramp, 0L, workBuffer, rampPtr, rampWidth);
}
gradientRampLengthOfput(fill, rampWidth);
return fill;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
import de.hpi.swa.trufflesqueak.nodes.primitives.PrimitiveFallbacks.TernaryPrimitiveFallback;
import de.hpi.swa.trufflesqueak.nodes.primitives.PrimitiveFallbacks.UnaryPrimitiveFallback;
import de.hpi.swa.trufflesqueak.nodes.primitives.SqueakPrimitive;
import de.hpi.swa.trufflesqueak.util.UnsafeUtils;

public final class IOPrimitives extends AbstractPrimitiveFactoryHolder {

Expand Down Expand Up @@ -413,9 +414,9 @@ protected final void doEmptyArrays(final ArrayObject rcvr, final long start, fin
@Specialization(guards = {"rcvr.isBooleanType()", "repl.isBooleanType()"})
protected static final void doArraysOfBooleans(final ArrayObject rcvr, final long start, final long stop, final ArrayObject repl, final long replStart,
@Shared("errorProfile") @Cached final BranchProfile errorProfile) {
try {
System.arraycopy(repl.getBooleanStorage(), (int) replStart - 1, rcvr.getBooleanStorage(), (int) start - 1, (int) (1 + stop - start));
} catch (final IndexOutOfBoundsException e) {
if (inBounds(rcvr.getBooleanLength(), start, stop, repl.getBooleanLength(), replStart)) {
UnsafeUtils.copyBytes(repl.getBooleanStorage(), replStart - 1, rcvr.getBooleanStorage(), start - 1, 1 + stop - start);
} else {
errorProfile.enter();
throw PrimitiveFailed.BAD_INDEX;
}
Expand All @@ -424,9 +425,9 @@ protected static final void doArraysOfBooleans(final ArrayObject rcvr, final lon
@Specialization(guards = {"rcvr.isCharType()", "repl.isCharType()"})
protected static final void doArraysOfChars(final ArrayObject rcvr, final long start, final long stop, final ArrayObject repl, final long replStart,
@Shared("errorProfile") @Cached final BranchProfile errorProfile) {
try {
System.arraycopy(repl.getCharStorage(), (int) replStart - 1, rcvr.getCharStorage(), (int) start - 1, (int) (1 + stop - start));
} catch (final IndexOutOfBoundsException e) {
if (inBounds(rcvr.getCharLength(), start, stop, repl.getCharLength(), replStart)) {
UnsafeUtils.copyChars(repl.getCharStorage(), replStart - 1, rcvr.getCharStorage(), start - 1, 1 + stop - start);
} else {
errorProfile.enter();
throw PrimitiveFailed.BAD_INDEX;
}
Expand All @@ -435,9 +436,9 @@ protected static final void doArraysOfChars(final ArrayObject rcvr, final long s
@Specialization(guards = {"rcvr.isLongType()", "repl.isLongType()"})
protected static final void doArraysOfLongs(final ArrayObject rcvr, final long start, final long stop, final ArrayObject repl, final long replStart,
@Shared("errorProfile") @Cached final BranchProfile errorProfile) {
try {
System.arraycopy(repl.getLongStorage(), (int) replStart - 1, rcvr.getLongStorage(), (int) start - 1, (int) (1 + stop - start));
} catch (final IndexOutOfBoundsException e) {
if (inBounds(rcvr.getLongLength(), start, stop, repl.getLongLength(), replStart)) {
UnsafeUtils.copyLongs(repl.getLongStorage(), replStart - 1, rcvr.getLongStorage(), start - 1, 1 + stop - start);
} else {
errorProfile.enter();
throw PrimitiveFailed.BAD_INDEX;
}
Expand All @@ -446,9 +447,9 @@ protected static final void doArraysOfLongs(final ArrayObject rcvr, final long s
@Specialization(guards = {"rcvr.isDoubleType()", "repl.isDoubleType()"})
protected static final void doArraysOfDoubles(final ArrayObject rcvr, final long start, final long stop, final ArrayObject repl, final long replStart,
@Shared("errorProfile") @Cached final BranchProfile errorProfile) {
try {
System.arraycopy(repl.getDoubleStorage(), (int) replStart - 1, rcvr.getDoubleStorage(), (int) start - 1, (int) (1 + stop - start));
} catch (final IndexOutOfBoundsException e) {
if (inBounds(rcvr.getDoubleLength(), start, stop, repl.getDoubleLength(), replStart)) {
UnsafeUtils.copyDoubles(repl.getDoubleStorage(), replStart - 1, rcvr.getDoubleStorage(), start - 1, 1 + stop - start);
} else {
errorProfile.enter();
throw PrimitiveFailed.BAD_INDEX;
}
Expand Down Expand Up @@ -594,9 +595,9 @@ protected abstract static class NativeObjectReplaceNode extends AbstractNode {
@Specialization(guards = {"rcvr.isByteType()", "repl.isByteType()"})
protected static final void doNativeBytes(final NativeObject rcvr, final long start, final long stop, final NativeObject repl, final long replStart,
@Shared("errorProfile") @Cached final BranchProfile errorProfile) {
try {
System.arraycopy(repl.getByteStorage(), (int) replStart - 1, rcvr.getByteStorage(), (int) start - 1, (int) (1 + stop - start));
} catch (final IndexOutOfBoundsException e) {
if (inBounds(rcvr.getByteLength(), start, stop, repl.getByteLength(), replStart)) {
UnsafeUtils.copyBytes(repl.getByteStorage(), replStart - 1, rcvr.getByteStorage(), start - 1, 1 + stop - start);
} else {
errorProfile.enter();
throw PrimitiveFailed.BAD_INDEX;
}
Expand All @@ -605,9 +606,9 @@ protected static final void doNativeBytes(final NativeObject rcvr, final long st
@Specialization(guards = {"rcvr.isShortType()", "repl.isShortType()"})
protected static final void doNativeShorts(final NativeObject rcvr, final long start, final long stop, final NativeObject repl, final long replStart,
@Shared("errorProfile") @Cached final BranchProfile errorProfile) {
try {
System.arraycopy(repl.getShortStorage(), (int) replStart - 1, rcvr.getShortStorage(), (int) start - 1, (int) (1 + stop - start));
} catch (final IndexOutOfBoundsException e) {
if (inBounds(rcvr.getShortLength(), start, stop, repl.getShortLength(), replStart)) {
UnsafeUtils.copyShorts(repl.getShortStorage(), replStart - 1, rcvr.getShortStorage(), start - 1, 1 + stop - start);
} else {
errorProfile.enter();
throw PrimitiveFailed.BAD_INDEX;
}
Expand All @@ -616,9 +617,9 @@ protected static final void doNativeShorts(final NativeObject rcvr, final long s
@Specialization(guards = {"rcvr.isIntType()", "repl.isIntType()"})
protected static final void doNativeInts(final NativeObject rcvr, final long start, final long stop, final NativeObject repl, final long replStart,
@Shared("errorProfile") @Cached final BranchProfile errorProfile) {
try {
System.arraycopy(repl.getIntStorage(), (int) replStart - 1, rcvr.getIntStorage(), (int) start - 1, (int) (1 + stop - start));
} catch (final IndexOutOfBoundsException e) {
if (inBounds(rcvr.getIntLength(), start, stop, repl.getIntLength(), replStart)) {
UnsafeUtils.copyInts(repl.getIntStorage(), replStart - 1, rcvr.getIntStorage(), start - 1, 1 + stop - start);
} else {
errorProfile.enter();
throw PrimitiveFailed.BAD_INDEX;
}
Expand All @@ -627,9 +628,9 @@ protected static final void doNativeInts(final NativeObject rcvr, final long sta
@Specialization(guards = {"rcvr.isLongType()", "repl.isLongType()"})
protected static final void doNativeLongs(final NativeObject rcvr, final long start, final long stop, final NativeObject repl, final long replStart,
@Shared("errorProfile") @Cached final BranchProfile errorProfile) {
try {
System.arraycopy(repl.getLongStorage(), (int) replStart - 1, rcvr.getLongStorage(), (int) start - 1, (int) (1 + stop - start));
} catch (final IndexOutOfBoundsException e) {
if (inBounds(rcvr.getLongLength(), start, stop, repl.getLongLength(), replStart)) {
UnsafeUtils.copyLongs(repl.getLongStorage(), replStart - 1, rcvr.getLongStorage(), start - 1, 1 + stop - start);
} else {
errorProfile.enter();
throw PrimitiveFailed.BAD_INDEX;
}
Expand All @@ -638,9 +639,9 @@ protected static final void doNativeLongs(final NativeObject rcvr, final long st
@Specialization(guards = {"rcvr.isByteType()"})
protected static final void doNativeLargeInteger(final NativeObject rcvr, final long start, final long stop, final LargeIntegerObject repl, final long replStart,
@Shared("errorProfile") @Cached final BranchProfile errorProfile) {
try {
System.arraycopy(repl.getBytes(), (int) replStart - 1, rcvr.getByteStorage(), (int) start - 1, (int) (1 + stop - start));
} catch (final IndexOutOfBoundsException e) {
if (inBounds(rcvr.getByteLength(), start, stop, repl.getBytes().length, replStart)) {
UnsafeUtils.copyBytes(repl.getBytes(), replStart - 1, rcvr.getByteStorage(), start - 1, 1 + stop - start);
} else {
errorProfile.enter();
throw PrimitiveFailed.BAD_INDEX;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
import de.hpi.swa.trufflesqueak.util.ArrayUtils;
import de.hpi.swa.trufflesqueak.util.MiscUtils;
import de.hpi.swa.trufflesqueak.util.ObjectGraphUtils;
import de.hpi.swa.trufflesqueak.util.UnsafeUtils;

public final class MiscellaneousPrimitives extends AbstractPrimitiveFactoryHolder {

Expand Down Expand Up @@ -683,31 +684,31 @@ protected static final AbstractPointersObject doCopyWeakPointers(final WeakVaria
"receiver.isByteType()", "anotherObject.isByteType()", "receiver.getByteLength() == anotherObject.getByteLength()"})
protected static final NativeObject doCopyNativeByte(final NativeObject receiver, final NativeObject anotherObject) {
final byte[] destStorage = receiver.getByteStorage();
System.arraycopy(anotherObject.getByteStorage(), 0, destStorage, 0, destStorage.length);
UnsafeUtils.copyBytes(anotherObject.getByteStorage(), 0L, destStorage, 0L, destStorage.length);
return receiver;
}

@Specialization(guards = {"receiver.getSqueakClass() == anotherObject.getSqueakClass()",
"receiver.isShortType()", "anotherObject.isShortType()", "receiver.getShortLength() == anotherObject.getShortLength()"})
protected static final NativeObject doCopyNativeShort(final NativeObject receiver, final NativeObject anotherObject) {
final short[] destStorage = receiver.getShortStorage();
System.arraycopy(anotherObject.getShortStorage(), 0, destStorage, 0, destStorage.length);
UnsafeUtils.copyShorts(anotherObject.getShortStorage(), 0L, destStorage, 0L, destStorage.length);
return receiver;
}

@Specialization(guards = {"receiver.getSqueakClass() == anotherObject.getSqueakClass()",
"receiver.isIntType()", "anotherObject.isIntType()", "receiver.getIntLength() == anotherObject.getIntLength()"})
protected static final NativeObject doCopyNativeInt(final NativeObject receiver, final NativeObject anotherObject) {
final int[] destStorage = receiver.getIntStorage();
System.arraycopy(anotherObject.getIntStorage(), 0, destStorage, 0, destStorage.length);
UnsafeUtils.copyInts(anotherObject.getIntStorage(), 0L, destStorage, 0L, destStorage.length);
return receiver;
}

@Specialization(guards = {"receiver.getSqueakClass() == anotherObject.getSqueakClass()",
"receiver.isLongType()", "anotherObject.isLongType()", "receiver.getLongLength() == anotherObject.getLongLength()"})
protected static final NativeObject doCopyNativeLong(final NativeObject receiver, final NativeObject anotherObject) {
final long[] destStorage = receiver.getLongStorage();
System.arraycopy(anotherObject.getLongStorage(), 0, destStorage, 0, destStorage.length);
UnsafeUtils.copyLongs(anotherObject.getLongStorage(), 0L, destStorage, 0L, destStorage.length);
return receiver;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,42 @@ public final class UnsafeUtils {
private UnsafeUtils() {
}

public static void copyBytes(final byte[] src, final long srcPos, final byte[] dest, final long destPos, final long length) {
assert 0 <= srcPos && srcPos + length <= src.length && 0 <= destPos && destPos + length <= dest.length;
UNSAFE.copyMemory(src, Unsafe.ARRAY_BYTE_BASE_OFFSET + srcPos * Unsafe.ARRAY_BYTE_INDEX_SCALE,
dest, Unsafe.ARRAY_BYTE_BASE_OFFSET + destPos * Unsafe.ARRAY_BYTE_INDEX_SCALE, Byte.BYTES * length);
}

public static void copyChars(final char[] src, final long srcPos, final char[] dest, final long destPos, final long length) {
assert 0 <= srcPos && srcPos + length <= src.length && 0 <= destPos && destPos + length <= dest.length;
UNSAFE.copyMemory(src, Unsafe.ARRAY_CHAR_BASE_OFFSET + srcPos * Unsafe.ARRAY_CHAR_INDEX_SCALE,
dest, Unsafe.ARRAY_CHAR_BASE_OFFSET + destPos * Unsafe.ARRAY_CHAR_INDEX_SCALE, Character.BYTES * length);
}

public static void copyDoubles(final double[] src, final long srcPos, final double[] dest, final long destPos, final long length) {
assert 0 <= srcPos && srcPos + length <= src.length && 0 <= destPos && destPos + length <= dest.length;
UNSAFE.copyMemory(src, Unsafe.ARRAY_DOUBLE_BASE_OFFSET + srcPos * Unsafe.ARRAY_DOUBLE_INDEX_SCALE,
dest, Unsafe.ARRAY_DOUBLE_BASE_OFFSET + destPos * Unsafe.ARRAY_DOUBLE_INDEX_SCALE, Double.BYTES * length);
}

public static void copyInts(final int[] src, final long srcPos, final int[] dest, final long destPos, final long length) {
assert 0 <= srcPos && srcPos + length <= src.length && 0 <= destPos && destPos + length <= dest.length;
UNSAFE.copyMemory(src, Unsafe.ARRAY_INT_BASE_OFFSET + srcPos * Unsafe.ARRAY_INT_INDEX_SCALE,
dest, Unsafe.ARRAY_INT_BASE_OFFSET + destPos * Unsafe.ARRAY_INT_INDEX_SCALE, Integer.BYTES * length);
}

public static void copyLongs(final long[] src, final long srcPos, final long[] dest, final long destPos, final long length) {
assert 0 <= srcPos && srcPos + length <= src.length && 0 <= destPos && destPos + length <= dest.length;
UNSAFE.copyMemory(src, Unsafe.ARRAY_LONG_BASE_OFFSET + srcPos * Unsafe.ARRAY_LONG_INDEX_SCALE,
dest, Unsafe.ARRAY_LONG_BASE_OFFSET + destPos * Unsafe.ARRAY_LONG_INDEX_SCALE, Long.BYTES * length);
}

public static void copyShorts(final short[] src, final long srcPos, final short[] dest, final long destPos, final long length) {
assert 0 <= srcPos && srcPos + length <= src.length && 0 <= destPos && destPos + length <= dest.length;
UNSAFE.copyMemory(src, Unsafe.ARRAY_SHORT_BASE_OFFSET + srcPos * Unsafe.ARRAY_SHORT_INDEX_SCALE,
dest, Unsafe.ARRAY_SHORT_BASE_OFFSET + destPos * Unsafe.ARRAY_SHORT_INDEX_SCALE, Short.BYTES * length);
}

public static long getAddress(final Class<?> javaClass, final String fieldName) {
try {
return UNSAFE.objectFieldOffset(javaClass.getField(fieldName));
Expand Down

1 comment on commit 7b99bfa

@TruffleSqueak-Bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Performance Report (7b99bfa)

Benchmarks ran on graalvm-ce-java11-22.0.0.2.

Steady (after 50 iterations)

Benchmark Name Min Geomean Median Mean Max Total (ms) Total (min)
Bounce 181 273 183.47 182 183.25 36693 0.61
DeltaBlue 286 588 408.81 395 406.55 81762 1.36
Havlak 1729 1877 1797.15 1809.5 1796.91 359430 5.99
Json 769 819 778.26 775 778.2 155651 2.59
List 896 932 902.23 901 902.22 180446 3.01
Mandelbrot 144 190 148.73 145 148.48 29745 0.5
NBody 583 627 591.97 587.5 591.89 118393 1.97
Permute 235 259 237.67 236 237.62 47534 0.79
Queens 258 291 261.84 259 261.72 52368 0.87
Richards 1097 1142 1102.86 1098 1102.82 220571 3.68
Sieve 210 282 215.77 211 215.36 43153 0.72
Storage 290 321 294.02 291 293.95 58804 0.98
Towers 361 390 364.19 363 364.16 72838 1.21
7039 7991 7286.94 7253 7283.15 1457388 24.29

7b99bfa-2-steady.svg

Warmup (first 50 iterations)

7b99bfa-3-warmup.svg

Please sign in to comment.