Skip to content

Commit

Permalink
[GR-54722] Fixes of performance regressions caused by resizable Array…
Browse files Browse the repository at this point in the history
…Buffers.

PullRequest: js/3176
  • Loading branch information
iamstolis committed Jun 14, 2024
2 parents 52b88d3 + ff51c8a commit 476c835
Show file tree
Hide file tree
Showing 11 changed files with 305 additions and 250 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ public abstract static class GetBufferElementNode extends JavaScriptBaseNode {
static Object doHeapArrayBuffer(JSArrayBufferObject.Heap buffer, int bufferIndex, boolean littleEndian, TypedArrayFactory factory) {
assert !JSArrayBuffer.isJSInteropArrayBuffer(buffer) && !JSArrayBuffer.isJSDirectOrSharedArrayBuffer(buffer) : buffer;
CompilerAsserts.partialEvaluationConstant(factory);
TypedArray strategy = factory.createArrayType(false, true, false);
TypedArray strategy = factory.createArrayType(TypedArray.BUFFER_TYPE_ARRAY, true, false);
CompilerAsserts.partialEvaluationConstant(strategy);
return strategy.getBufferElement(buffer, bufferIndex, littleEndian, null);
}
Expand All @@ -280,7 +280,8 @@ static Object doHeapArrayBuffer(JSArrayBufferObject.Heap buffer, int bufferIndex
static Object doDirectOrSharedArrayBuffer(JSArrayBufferObject.DirectBase buffer, int bufferIndex, boolean littleEndian, TypedArrayFactory factory) {
assert !JSArrayBuffer.isJSInteropArrayBuffer(buffer) && JSArrayBuffer.isJSDirectOrSharedArrayBuffer(buffer) : buffer;
CompilerAsserts.partialEvaluationConstant(factory);
TypedArray strategy = factory.createArrayType(true, true, false);
// It does not matter whether we use BUFFER_TYPE_DIRECT or BUFFER_TYPE_SHARED here
TypedArray strategy = factory.createArrayType(TypedArray.BUFFER_TYPE_DIRECT, true, false);
CompilerAsserts.partialEvaluationConstant(strategy);
return strategy.getBufferElement(buffer, bufferIndex, littleEndian, null);
}
Expand All @@ -290,7 +291,7 @@ static Object doInteropBuffer(JSArrayBufferObject.Interop buffer, int bufferInde
@CachedLibrary(limit = "InteropLibraryLimit") InteropLibrary interop) {
assert JSArrayBuffer.isJSInteropArrayBuffer(buffer) && !JSArrayBuffer.isJSDirectOrSharedArrayBuffer(buffer) : buffer;
CompilerAsserts.partialEvaluationConstant(factory);
TypedArray strategy = factory.createArrayType(false, true, true);
TypedArray strategy = factory.createArrayType(TypedArray.BUFFER_TYPE_INTEROP, true, false);
CompilerAsserts.partialEvaluationConstant(strategy);
return strategy.getBufferElement(buffer, bufferIndex, littleEndian, interop);
}
Expand Down Expand Up @@ -352,7 +353,7 @@ public abstract static class SetBufferElementNode extends JavaScriptBaseNode {
static void doHeapArrayBuffer(JSArrayBufferObject.Heap buffer, int bufferIndex, boolean littleEndian, Object value, TypedArrayFactory factory) {
assert !JSArrayBuffer.isJSInteropArrayBuffer(buffer) && !JSArrayBuffer.isJSDirectOrSharedArrayBuffer(buffer) : buffer;
CompilerAsserts.partialEvaluationConstant(factory);
TypedArray strategy = factory.createArrayType(false, true, false);
TypedArray strategy = factory.createArrayType(TypedArray.BUFFER_TYPE_ARRAY, true, false);
CompilerAsserts.partialEvaluationConstant(strategy);
strategy.setBufferElement(buffer, bufferIndex, littleEndian, value, null);
}
Expand All @@ -361,7 +362,8 @@ static void doHeapArrayBuffer(JSArrayBufferObject.Heap buffer, int bufferIndex,
static void doDirectOrSharedArrayBuffer(JSArrayBufferObject.DirectBase buffer, int bufferIndex, boolean littleEndian, Object value, TypedArrayFactory factory) {
assert !JSArrayBuffer.isJSInteropArrayBuffer(buffer) && JSArrayBuffer.isJSDirectOrSharedArrayBuffer(buffer) : buffer;
CompilerAsserts.partialEvaluationConstant(factory);
TypedArray strategy = factory.createArrayType(true, true, false);
// It does not matter whether we use BUFFER_TYPE_DIRECT or BUFFER_TYPE_SHARED here
TypedArray strategy = factory.createArrayType(TypedArray.BUFFER_TYPE_DIRECT, true, false);
CompilerAsserts.partialEvaluationConstant(strategy);
strategy.setBufferElement(buffer, bufferIndex, littleEndian, value, null);
}
Expand All @@ -371,7 +373,7 @@ static void doInteropBuffer(JSArrayBufferObject.Interop buffer, int bufferIndex,
@CachedLibrary(limit = "InteropLibraryLimit") InteropLibrary interop) {
assert JSArrayBuffer.isJSInteropArrayBuffer(buffer) && !JSArrayBuffer.isJSDirectOrSharedArrayBuffer(buffer) : buffer;
CompilerAsserts.partialEvaluationConstant(factory);
TypedArray strategy = factory.createArrayType(false, true, true);
TypedArray strategy = factory.createArrayType(TypedArray.BUFFER_TYPE_INTEROP, true, false);
CompilerAsserts.partialEvaluationConstant(strategy);
strategy.setBufferElement(buffer, bufferIndex, littleEndian, value, interop);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
*/
package com.oracle.truffle.js.builtins;

import static com.oracle.truffle.js.runtime.array.TypedArray.BUFFER_TYPE_ARRAY;
import static com.oracle.truffle.js.runtime.array.TypedArray.BUFFER_TYPE_DIRECT;
import static com.oracle.truffle.js.runtime.array.TypedArray.BUFFER_TYPE_INTEROP;
import static com.oracle.truffle.js.runtime.array.TypedArray.BUFFER_TYPE_SHARED;

import java.nio.ByteBuffer;
import java.util.NoSuchElementException;

Expand Down Expand Up @@ -181,19 +186,18 @@ private void checkDetachedBuffer(JSArrayBufferObject buffer) {
protected JSDynamicObject doArrayBuffer(JSDynamicObject newTarget, JSArrayBufferObject arrayBuffer, Object byteOffset0, Object length0,
@Cached @Shared InlinedConditionProfile lengthIsUndefined) {
checkDetachedBuffer(arrayBuffer);
return doArrayBufferImpl(arrayBuffer, byteOffset0, length0, newTarget, false, false, this, lengthIsUndefined);
return doArrayBufferImpl(arrayBuffer, byteOffset0, length0, newTarget, BUFFER_TYPE_ARRAY, this, lengthIsUndefined);
}

@Specialization(guards = {"!isUndefined(newTarget)", "isJSDirectArrayBuffer(arrayBuffer)"})
protected JSDynamicObject doDirectArrayBuffer(JSDynamicObject newTarget, JSArrayBufferObject arrayBuffer, Object byteOffset0, Object length0,
@Cached @Shared InlinedConditionProfile lengthIsUndefined) {
checkDetachedBuffer(arrayBuffer);
return doArrayBufferImpl(arrayBuffer, byteOffset0, length0, newTarget, true, false, this, lengthIsUndefined);
return doArrayBufferImpl(arrayBuffer, byteOffset0, length0, newTarget, BUFFER_TYPE_DIRECT, this, lengthIsUndefined);
}

private JSDynamicObject doArrayBufferImpl(JSArrayBufferObject arrayBuffer, Object byteOffset0, Object length0, JSDynamicObject newTarget,
boolean direct, boolean isInteropBuffer,
Node node, InlinedConditionProfile lengthIsUndefinedProfile) {
byte bufferType, Node node, InlinedConditionProfile lengthIsUndefinedProfile) {
final int elementSize = factory.getBytesPerElement();

final long byteOffset = toIndex(byteOffset0);
Expand Down Expand Up @@ -227,7 +231,7 @@ private JSDynamicObject doArrayBufferImpl(JSArrayBufferObject arrayBuffer, Objec
}

assert byteOffset <= Integer.MAX_VALUE && length <= Integer.MAX_VALUE;
TypedArray typedArray = factory.createArrayType(direct, byteOffset != 0, isInteropBuffer);
TypedArray typedArray = factory.createArrayType(bufferType, byteOffset != 0, length != JSArrayBufferViewBase.AUTO_LENGTH);
return createTypedArray(arrayBuffer, typedArray, (int) byteOffset, (int) length, newTarget);
}

Expand All @@ -242,7 +246,7 @@ private JSDynamicObject doArrayBufferImpl(JSArrayBufferObject arrayBuffer, Objec
@Specialization(guards = {"!isUndefined(newTarget)", "isJSSharedArrayBuffer(arrayBuffer)"})
protected JSDynamicObject doSharedArrayBuffer(JSDynamicObject newTarget, JSArrayBufferObject arrayBuffer, Object byteOffset0, Object length0,
@Cached @Shared InlinedConditionProfile lengthIsUndefined) {
return doDirectArrayBuffer(newTarget, arrayBuffer, byteOffset0, length0, lengthIsUndefined);
return doArrayBufferImpl(arrayBuffer, byteOffset0, length0, newTarget, BUFFER_TYPE_SHARED, this, lengthIsUndefined);
}

/**
Expand All @@ -256,7 +260,7 @@ protected JSDynamicObject doSharedArrayBuffer(JSDynamicObject newTarget, JSArray
@Specialization(guards = {"!isUndefined(newTarget)", "isJSInteropArrayBuffer(arrayBuffer)"})
protected JSDynamicObject doInteropArrayBuffer(JSDynamicObject newTarget, JSArrayBufferObject arrayBuffer, Object byteOffset0, Object length0,
@Cached @Shared InlinedConditionProfile lengthIsUndefined) {
return doArrayBufferImpl(arrayBuffer, byteOffset0, length0, newTarget, false, true, this, lengthIsUndefined);
return doArrayBufferImpl(arrayBuffer, byteOffset0, length0, newTarget, BUFFER_TYPE_INTEROP, this, lengthIsUndefined);
}

/**
Expand All @@ -282,7 +286,7 @@ protected JSDynamicObject doTypedArray(JSDynamicObject newTarget, JSTypedArrayOb
throw Errors.createTypeErrorCannotMixBigIntWithOtherTypes(this);
}

TypedArray typedArray = factory.createArrayType(getContext().isOptionDirectByteBuffer(), false);
TypedArray typedArray = factory.createArrayType(getContext().isOptionDirectByteBuffer() ? BUFFER_TYPE_DIRECT : BUFFER_TYPE_ARRAY, false, true);
JSDynamicObject result = createTypedArray(arrayBuffer, typedArray, 0, (int) length, newTarget);

assert typedArray == JSArrayBufferView.typedArrayGetArrayType(result);
Expand Down Expand Up @@ -375,7 +379,7 @@ protected JSDynamicObject doObject(JSDynamicObject newTarget, JSObject object, @
SimpleArrayList<Object> values = iterableToListNode.execute(getIteratorFromMethodNode.execute(node, object, usingIterator));
int len = values.size();
JSArrayBufferObject arrayBuffer = createTypedArrayBuffer(len);
TypedArray typedArray = factory.createArrayType(getContext().isOptionDirectByteBuffer(), false);
TypedArray typedArray = factory.createArrayType(getContext().isOptionDirectByteBuffer() ? BUFFER_TYPE_DIRECT : BUFFER_TYPE_ARRAY, false, true);
JSDynamicObject obj = integerIndexedObjectCreate(arrayBuffer, typedArray, 0, len, proto);
for (int k = 0; k < len; k++) {
Object kValue = values.get(k);
Expand All @@ -388,7 +392,7 @@ protected JSDynamicObject doObject(JSDynamicObject newTarget, JSObject object, @
long len = getLengthNode.executeLong(object);
JSArrayBufferObject arrayBuffer = createTypedArrayBuffer(len);
assert len <= Integer.MAX_VALUE;
TypedArray typedArray = factory.createArrayType(getContext().isOptionDirectByteBuffer(), false);
TypedArray typedArray = factory.createArrayType(getContext().isOptionDirectByteBuffer() ? BUFFER_TYPE_DIRECT : BUFFER_TYPE_ARRAY, false, true);
JSDynamicObject obj = integerIndexedObjectCreate(arrayBuffer, typedArray, 0, (int) len, proto);
for (int k = 0; k < len; k++) {
Object kValue = readNode.executeWithTargetAndIndex(object, k);
Expand All @@ -409,7 +413,7 @@ protected JSDynamicObject doForeignObject(JSDynamicObject newTarget, Object obje
if (interop.hasBufferElements(object)) {
JSArrayBufferObject arrayBuffer = JSArrayBuffer.createInteropArrayBuffer(getContext(), getRealm(), object);
checkLengthLimit(arrayBuffer.getByteLength(), 1);
return doArrayBufferImpl(arrayBuffer, byteOffset0, length0, newTarget, false, true, node, lengthIsUndefined);
return doArrayBufferImpl(arrayBuffer, byteOffset0, length0, newTarget, BUFFER_TYPE_INTEROP, node, lengthIsUndefined);
}

long length;
Expand Down Expand Up @@ -482,7 +486,7 @@ private JSArrayBufferObject createTypedArrayBuffer(long length) {
*/
private JSDynamicObject createTypedArrayWithLength(long length, JSDynamicObject newTarget) {
JSArrayBufferObject arrayBuffer = createTypedArrayBuffer(length);
TypedArray typedArray = factory.createArrayType(getContext().isOptionDirectByteBuffer(), false);
TypedArray typedArray = factory.createArrayType(getContext().isOptionDirectByteBuffer() ? BUFFER_TYPE_DIRECT : BUFFER_TYPE_ARRAY, false, true);
return createTypedArray(arrayBuffer, typedArray, 0, (int) length, newTarget);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
*/
package com.oracle.truffle.js.builtins;

import static com.oracle.truffle.js.runtime.array.TypedArray.BUFFER_TYPE_ARRAY;
import static com.oracle.truffle.js.runtime.array.TypedArray.BUFFER_TYPE_DIRECT;
import static com.oracle.truffle.js.runtime.array.TypedArray.BUFFER_TYPE_INTEROP;
import static com.oracle.truffle.js.runtime.builtins.JSAbstractArray.arrayGetArrayType;
import static com.oracle.truffle.js.runtime.builtins.JSArrayBufferView.typedArrayGetArrayType;

Expand Down Expand Up @@ -536,7 +539,7 @@ private void setArrayBufferView(JSTypedArrayObject targetView, JSTypedArrayObjec
sourceBuffer = cloneArrayBuffer(sourceBuffer, sourceArray, srcByteLength, srcByteOffset);
if (sourceArray.isInterop()) {
// cloned buffer is not an interop buffer anymore
sourceArray = sourceArray.getFactory().createArrayType(getContext().isOptionDirectByteBuffer(), false);
sourceArray = sourceArray.getFactory().createArrayType(getContext().isOptionDirectByteBuffer() ? BUFFER_TYPE_DIRECT : BUFFER_TYPE_ARRAY, false, true);
}
srcByteIndex = 0;
}
Expand Down Expand Up @@ -693,8 +696,8 @@ private JSArrayBufferObject cloneArrayBuffer(JSArrayBufferObject sourceBuffer, T
private JSArrayBufferObject cloneInteropArrayBuffer(JSArrayBufferObject sourceBuffer, int srcByteLength, int srcByteOffset, InteropLibrary interop) {
assert JSArrayBuffer.isJSInteropArrayBuffer(sourceBuffer);
boolean direct = getContext().isOptionDirectByteBuffer();
TypedArray sourceType = TypedArrayFactory.Int8Array.createArrayType(false, false, true);
TypedArray clonedType = TypedArrayFactory.Int8Array.createArrayType(direct, false);
TypedArray sourceType = TypedArrayFactory.Int8Array.createArrayType(BUFFER_TYPE_INTEROP, false, true);
TypedArray clonedType = TypedArrayFactory.Int8Array.createArrayType(direct ? BUFFER_TYPE_DIRECT : BUFFER_TYPE_ARRAY, false, true);
JSArrayBufferObject clonedArrayBuffer = direct
? JSArrayBuffer.createDirectArrayBuffer(getContext(), getRealm(), srcByteLength)
: JSArrayBuffer.createArrayBuffer(getContext(), getRealm(), srcByteLength);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,17 @@ private Object exportBuffer(JSArrayBufferObject arrayBuffer, int offset, int len
buffer = JSArrayBuffer.createArrayBuffer(context, realm, 0);
}
// Wrap ArrayBuffer into Uint8Array - to allow reading its bytes on WASM side
boolean interop = JSArrayBuffer.isJSInteropArrayBuffer(arrayBuffer);
boolean direct = JSArrayBuffer.isJSDirectArrayBuffer(arrayBuffer);
TypedArray arrayType = TypedArrayFactory.Uint8Array.createArrayType(direct, (offset != 0), interop);
byte bufferType;
if (JSArrayBuffer.isJSInteropArrayBuffer(arrayBuffer)) {
bufferType = TypedArray.BUFFER_TYPE_INTEROP;
} else if (JSArrayBuffer.isJSHeapArrayBuffer(arrayBuffer)) {
bufferType = TypedArray.BUFFER_TYPE_ARRAY;
} else if (JSArrayBuffer.isJSDirectArrayBuffer(arrayBuffer)) {
bufferType = TypedArray.BUFFER_TYPE_DIRECT;
} else {
bufferType = TypedArray.BUFFER_TYPE_SHARED;
}
TypedArray arrayType = TypedArrayFactory.Uint8Array.createArrayType(bufferType, (offset != 0), true);
return JSArrayBufferView.createArrayBufferView(context, realm, buffer, arrayType, offset, length);
}

Expand Down
Loading

0 comments on commit 476c835

Please sign in to comment.