Skip to content

Commit fe4f0a4

Browse files
committed
[JSC] Implement growable SharedArrayBuffer part 2
https://bugs.webkit.org/show_bug.cgi?id=247921 rdar://102339939 Reviewed by Mark Lam. This patch adds runtime support for growable SharedArrayBuffer, TypedArray, and DataView. We are not supporting JIT optimization yet, but still this patch implements the basic mechanism to support it in a subsequent patch. 1. TypedArray / DataView has a mode flag which says ResizableNonShared / GrowableShared / AutoLength etc. And we use this flag to dispatch the implementation. For non resizable one, we use super simple implementation as before. 2. This patch implements "auto" length, which automatically changes length / byteLength of TypedArray based on backing storage's SharedArrayBuffer etc. 3. This patch does not implement JIT optimizations. They will be done in a subsequent patch. * JSTests/stress/detached-typed-array-iteration.js: (shouldThrow): * JSTests/stress/typed-array-from.js: (shouldBeArray): * JSTests/stress/typedarray-defineOwnProperty-error.js: * JSTests/stress/typedarray-functions-with-neutered.js: (checkProtoFunc.throwsCorrectError): (checkProtoFunc): (callWithArgs): * JSTests/wasm/js-api/neutered-inputs.js: * Source/JavaScriptCore/API/JSTypedArray.cpp: (createTypedArray): (JSObjectMakeTypedArrayWithArrayBuffer): * Source/JavaScriptCore/builtins/ArrayIteratorPrototype.js: (next): * Source/JavaScriptCore/bytecode/AccessCase.cpp: (JSC::AccessCase::generateWithGuard): * Source/JavaScriptCore/bytecode/ArrayProfile.cpp: (JSC::ArrayProfile::computeUpdatedPrediction): (JSC::ArrayProfile::briefDescriptionWithoutUpdating): * Source/JavaScriptCore/bytecode/ArrayProfile.h: (JSC::ArrayProfile::mayBeResizableOrGrowableSharedTypedArray const): (JSC::UnlinkedArrayProfile::update): * Source/JavaScriptCore/bytecode/Repatch.cpp: (JSC::tryCacheArrayGetByVal): (JSC::tryCacheArrayPutByVal): * Source/JavaScriptCore/bytecode/SpeculatedType.cpp: (JSC::speculationFromClassInfoInheritance): * Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h: (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): * Source/JavaScriptCore/dfg/DFGArrayMode.cpp: (JSC::DFG::ArrayMode::originalArrayStructure const): (JSC::DFG::ArrayMode::dump const): * Source/JavaScriptCore/dfg/DFGArrayMode.h: (JSC::DFG::ArrayMode::ArrayMode): (JSC::DFG::ArrayMode::mayBeResizableOrGrowableSharedTypedArray const): (JSC::DFG::ArrayMode::withType const): (JSC::DFG::ArrayMode::withSpeculation const): (JSC::DFG::ArrayMode::withConversion const): (JSC::DFG::ArrayMode::withTypeAndConversion const): (JSC::DFG::ArrayMode::withArrayClassAndSpeculation const): (JSC::DFG::ArrayMode::withProfile const): (JSC::DFG::ArrayMode::operator== const): (JSC::DFG::ArrayMode::withArrayClassAndSpeculationAndMayBeLargeTypedArray const): Deleted. * Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::handleIntrinsicGetter): (JSC::DFG::ByteCodeParser::handleTypedArrayConstructor): * Source/JavaScriptCore/dfg/DFGClobberize.h: (JSC::DFG::clobberize): * Source/JavaScriptCore/dfg/DFGOperations.cpp: (JSC::DFG::newTypedArrayWithSize): * Source/JavaScriptCore/dfg/DFGOperations.h: * Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp: (JSC::DFG::SpeculativeJIT::jumpForTypedArrayOutOfBounds): (JSC::DFG::SpeculativeJIT::jumpForTypedArrayIsDetachedIfOutOfBounds): * Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp: (JSC::DFG::SpeculativeJIT::compileNewTypedArrayWithInt52Size): (JSC::DFG::SpeculativeJIT::compileGetTypedArrayLengthAsInt52): (JSC::DFG::SpeculativeJIT::compileGetTypedArrayByteOffsetAsInt52): (JSC::DFG::SpeculativeJIT::compile): * Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h: * Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp: (JSC::FTL::DFG::LowerDFGToB3::emitGetTypedArrayByteOffsetExceptSettingResult): (JSC::FTL::DFG::LowerDFGToB3::compileGetArrayLength): (JSC::FTL::DFG::LowerDFGToB3::compileGetTypedArrayLengthAsInt52): (JSC::FTL::DFG::LowerDFGToB3::compileNewTypedArray): (JSC::FTL::DFG::LowerDFGToB3::emitNewTypedArrayWithSize): (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq): * Source/JavaScriptCore/jit/IntrinsicEmitter.cpp: (JSC::IntrinsicGetterAccessCase::canEmitIntrinsicGetter): (JSC::IntrinsicGetterAccessCase::emitIntrinsicGetter): * Source/JavaScriptCore/jsc.cpp: (JSC_DEFINE_HOST_FUNCTION): * Source/JavaScriptCore/llint/LowLevelInterpreter.asm: * Source/JavaScriptCore/runtime/ArrayBuffer.h: (JSC::IdempotentArrayBufferByteLengthGetter::operator()): (JSC::IdempotentArrayBufferByteLengthGetter::IdempotentArrayBufferByteLengthGetter): Deleted. * Source/JavaScriptCore/runtime/ArrayBufferView.cpp: (JSC::ArrayBufferView::ArrayBufferView): * Source/JavaScriptCore/runtime/ArrayBufferView.h: (JSC::ArrayBufferView::baseAddress const): (JSC::ArrayBufferView::byteOffset const): (JSC::ArrayBufferView::byteLength const): (JSC::ArrayBufferView::isResizableOrGrowableShared const): (JSC::ArrayBufferView::isResizableNonShared const): (JSC::ArrayBufferView::isGrowableShared const): (JSC::ArrayBufferView::isAutoLength const): (JSC::ArrayBufferView::clampOffsetAndNumElements): (JSC::ArrayBufferView::setImpl): (JSC::ArrayBufferView::setRangeImpl): * Source/JavaScriptCore/runtime/AtomicsObject.cpp: * Source/JavaScriptCore/runtime/DataView.cpp: (JSC::DataView::DataView): (JSC::DataView::create): (JSC::DataView::wrapImpl): * Source/JavaScriptCore/runtime/DataView.h: * Source/JavaScriptCore/runtime/GenericTypedArrayView.h: * Source/JavaScriptCore/runtime/GenericTypedArrayViewInlines.h: (JSC::GenericTypedArrayView<Adaptor>::GenericTypedArrayView): (JSC::GenericTypedArrayView<Adaptor>::create): (JSC::GenericTypedArrayView<Adaptor>::tryCreate): (JSC::GenericTypedArrayView<Adaptor>::wrapImpl): * Source/JavaScriptCore/runtime/JSArrayBuffer.h: * Source/JavaScriptCore/runtime/JSArrayBufferPrototype.cpp: (JSC::arrayBufferSlice): (JSC::JSC_DEFINE_HOST_FUNCTION): * Source/JavaScriptCore/runtime/JSArrayBufferView.cpp: (JSC::JSArrayBufferView::ConstructionContext::ConstructionContext): (JSC::JSArrayBufferView::JSArrayBufferView): (JSC::JSArrayBufferView::finishCreation): (JSC::JSArrayBufferView::finalize): (JSC::JSArrayBufferView::detach): (JSC::JSArrayBufferView::slowDownAndWasteMemory): (JSC::JSArrayBufferView::possiblySharedImpl): (JSC::JSArrayBufferView::isIteratorProtocolFastAndNonObservable): (WTF::printInternal): (JSC::JSArrayBufferView::byteLength const): Deleted. (JSC::isIntegerIndexedObjectOutOfBounds): Deleted. (JSC::integerIndexedObjectLength): Deleted. (JSC::integerIndexedObjectByteLength): Deleted. (JSC::validateTypedArray): Deleted. * Source/JavaScriptCore/runtime/JSArrayBufferView.h: (JSC::hasArrayBuffer): (JSC::isResizableOrGrowableShared): (JSC::isGrowableShared): (JSC::isResizableNonShared): (JSC::isAutoLength): (JSC::isWastefulTypedArray): (JSC::JSArrayBufferView::ConstructionContext::vector const): (JSC::JSArrayBufferView::ConstructionContext::byteOffset const): (JSC::JSArrayBufferView::isResizableOrGrowableShared const): (JSC::JSArrayBufferView::isGrowableShared const): (JSC::JSArrayBufferView::isResizableNonShared const): (JSC::JSArrayBufferView::isAutoLength const): (JSC::JSArrayBufferView::vector const): (JSC::JSArrayBufferView::byteOffset const): (JSC::JSArrayBufferView::byteOffsetRaw const): (JSC::JSArrayBufferView::length const): (JSC::JSArrayBufferView::lengthRaw const): (JSC::JSArrayBufferView::byteLength const): (JSC::JSArrayBufferView::byteLengthRaw const): (JSC::JSArrayBufferView::offsetOfByteOffset): (JSC::isResizable): Deleted. (JSC::JSArrayBufferView::ConstructionContext::maxByteLength const): Deleted. (JSC::JSArrayBufferView::ConstructionContext::maxByteLengthUnsafe const): Deleted. (JSC::JSArrayBufferView::maxByteLength const): Deleted. (JSC::JSArrayBufferView::offsetOfMaxByteLength): Deleted. * Source/JavaScriptCore/runtime/JSArrayBufferViewInlines.h: (JSC::JSArrayBufferView::isShared): (JSC::JSArrayBufferView::possiblySharedBufferImpl): (JSC::JSArrayBufferView::existingBufferInButterfly): (JSC::JSArrayBufferView::toWrapped): (JSC::JSArrayBufferView::toWrappedAllowShared): (JSC::isIntegerIndexedObjectOutOfBounds): (JSC::integerIndexedObjectLength): (JSC::integerIndexedObjectByteLength): (JSC::validateTypedArray): (JSC::JSArrayBufferView::byteOffsetImpl): Deleted. (JSC::JSArrayBufferView::byteOffset): Deleted. (JSC::JSArrayBufferView::byteOffsetConcurrently): Deleted. * Source/JavaScriptCore/runtime/JSCast.h: * Source/JavaScriptCore/runtime/JSDataView.cpp: (JSC::JSDataView::create): (JSC::JSDataView::setFromTypedArray): (JSC::JSDataView::setFromArrayLike): (JSC::JSDataView::set): Deleted. * Source/JavaScriptCore/runtime/JSDataView.h: * Source/JavaScriptCore/runtime/JSDataViewPrototype.cpp: (JSC::getData): (JSC::setData): (JSC::JSC_DEFINE_CUSTOM_GETTER): (JSC::JSC_DEFINE_HOST_FUNCTION): * Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h: (JSC::JSGenericTypedArrayView::byteLength const): (JSC::JSGenericTypedArrayView::byteLengthRaw const): (JSC::JSGenericTypedArrayView::inBounds const): (JSC::JSGenericTypedArrayView::canSetIndexQuickly const): (JSC::JSGenericTypedArrayView::getIndexQuicklyAsNativeValue const): (JSC::JSGenericTypedArrayView::setIndexQuicklyToNativeValue): (JSC::JSGenericTypedArrayView::sort): (JSC::JSGenericTypedArrayView::canAccessRangeQuickly): (JSC::JSGenericTypedArrayView::info): (JSC::JSGenericTypedArrayView::sortFloat): * Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h: (JSC::constructGenericTypedArrayViewWithArguments): (JSC::constructGenericTypedArrayViewImpl): * Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h: (JSC::JSGenericTypedArrayView<Adaptor>::create): (JSC::JSGenericTypedArrayView<Adaptor>::setFromTypedArray): (JSC::JSGenericTypedArrayView<Adaptor>::setFromArrayLike): (JSC::JSGenericTypedArrayView<Adaptor>::getOwnPropertySlot): (JSC::JSGenericTypedArrayView<Adaptor>::put): (JSC::JSGenericTypedArrayView<Adaptor>::deleteProperty): (JSC::JSGenericTypedArrayView<Adaptor>::getOwnPropertyNames): (JSC::JSGenericTypedArrayView<Adaptor>::estimatedSize): (JSC::JSGenericTypedArrayView<Adaptor>::visitChildrenImpl): (JSC::JSGenericTypedArrayView<Adaptor>::set): Deleted. * Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h: (JSC::speciesConstruct): (JSC::genericTypedArrayViewProtoFuncSet): (JSC::genericTypedArrayViewProtoFuncCopyWithin): (JSC::genericTypedArrayViewProtoFuncIncludes): (JSC::genericTypedArrayViewProtoFuncIndexOf): (JSC::genericTypedArrayViewProtoFuncJoin): (JSC::genericTypedArrayViewProtoFuncFill): (JSC::genericTypedArrayViewProtoFuncLastIndexOf): (JSC::genericTypedArrayViewProtoFuncReverse): (JSC::genericTypedArrayViewProtoFuncToReversed): (JSC::genericTypedArrayViewPrivateFuncClone): (JSC::genericTypedArrayViewPrivateFuncSort): (JSC::genericTypedArrayViewPrivateFuncFromFast): (JSC::genericTypedArrayViewProtoFuncSlice): (JSC::genericTypedArrayViewProtoFuncSubarray): (JSC::validateIntegerIndex): (JSC::genericTypedArrayViewProtoFuncWith): * Source/JavaScriptCore/runtime/JSGlobalObject.cpp: (JSC::JSGlobalObject::init): (JSC::JSGlobalObject::visitChildrenImpl): * Source/JavaScriptCore/runtime/JSGlobalObject.h: (JSC::JSGlobalObject::lazyResizableOrGrowableSharedTypedArrayStructure): (JSC::JSGlobalObject::lazyResizableOrGrowableSharedTypedArrayStructure const): (JSC::JSGlobalObject::typedArrayStructure const): (JSC::JSGlobalObject::typedArrayStructureConcurrently const): (JSC::JSGlobalObject::isOriginalTypedArrayStructure): (JSC::JSGlobalObject::typedArrayStructureWithTypedArrayType const): (JSC::JSGlobalObject::resizableOrGrowableSharedTypedArrayStructureWithTypedArrayType const): * Source/JavaScriptCore/runtime/JSTypedArrayViewPrototype.cpp: (JSC::JSC_DEFINE_HOST_FUNCTION): (JSC::createTypedArrayIteratorObject): * Source/JavaScriptCore/runtime/JSTypedArrays.cpp: (): Deleted. * Source/JavaScriptCore/runtime/JSTypedArrays.h: (JSC::isResizableOrGrowableSharedTypedArray): * Source/JavaScriptCore/runtime/StructureInlines.h: (JSC::Structure::hasIndexingHeader const): * Source/JavaScriptCore/runtime/TypedArrayAdaptors.h: * Source/JavaScriptCore/wasm/js/JSWebAssemblyHelpers.h: (JSC::getWasmBufferFromValue): * Source/WTF/wtf/StdLibExtras.h: (WTF::mask): (WTF::roundDownToMultipleOf): * Source/WebCore/Modules/webaudio/AudioBuffer.cpp: (WebCore::AudioBuffer::getChannelData): * Source/WebCore/Modules/webaudio/AudioWorkletProcessor.cpp: (WebCore::constructJSFloat32Array): Canonical link: https://commits.webkit.org/256766@main
1 parent 7d62c54 commit fe4f0a4

68 files changed

Lines changed: 1595 additions & 1197 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

JSTests/stress/detached-typed-array-iteration.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ shouldThrow(() => {
2626
++count;
2727
$.detachArrayBuffer(array.buffer);
2828
}
29-
}, `TypeError: Underlying ArrayBuffer has been detached from the view`);
29+
}, `TypeError: Underlying ArrayBuffer has been detached from the view or out-of-bounds`);
3030

3131
shouldBe(count, 1);
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
//@ requireOptions("--useResizableArrayBuffer=1")
2+
3+
function shouldBe(actual, expected) {
4+
if (actual !== expected)
5+
throw new Error('bad value: ' + actual);
6+
}
7+
8+
function shouldThrow(func, errorMessage) {
9+
var errorThrown = false;
10+
var error = null;
11+
try {
12+
func();
13+
} catch (e) {
14+
errorThrown = true;
15+
error = e;
16+
}
17+
if (!errorThrown)
18+
throw new Error('not thrown');
19+
if (String(error) !== errorMessage)
20+
throw new Error(`bad error: ${String(error)}`);
21+
}
22+
23+
{
24+
let buffer = new SharedArrayBuffer(42, { maxByteLength: 1024 });
25+
let array = new Int8Array(buffer);
26+
shouldBe(array.length, 42);
27+
shouldBe(array.byteLength, 42);
28+
buffer.grow(128);
29+
shouldBe(array.length, 128);
30+
shouldBe(array.byteLength, 128);
31+
buffer.grow(1024);
32+
shouldBe(array.length, 1024);
33+
shouldBe(array.byteLength, 1024);
34+
}
35+
36+
{
37+
let buffer = new SharedArrayBuffer(42, { maxByteLength: 1024 });
38+
let view = new DataView(buffer);
39+
shouldBe(view.byteLength, 42);
40+
buffer.grow(128);
41+
shouldBe(view.byteLength, 128);
42+
buffer.grow(1024);
43+
shouldBe(view.byteLength, 1024);
44+
}
45+
46+
{
47+
let buffer = new SharedArrayBuffer(42, { maxByteLength: 1024 });
48+
shouldThrow(() => {
49+
let array = new Int8Array(buffer, 128);
50+
}, `RangeError: byteOffset exceeds source ArrayBuffer byteLength`);
51+
let array = new Int8Array(buffer, 16);
52+
shouldBe(array.length, 26);
53+
shouldBe(array.byteLength, 26);
54+
buffer.grow(128);
55+
shouldBe(array.length, 112);
56+
shouldBe(array.byteLength, 112);
57+
buffer.grow(1024);
58+
shouldBe(array.length, 1008);
59+
shouldBe(array.byteLength, 1008);
60+
}
61+
62+
{
63+
let buffer = new SharedArrayBuffer(42, { maxByteLength: 1024 });
64+
shouldThrow(() => {
65+
let view = new DataView(buffer, 128);
66+
}, `RangeError: byteOffset exceeds source ArrayBuffer byteLength`);
67+
let view = new DataView(buffer, 16);
68+
shouldBe(view.byteLength, 26);
69+
buffer.grow(128);
70+
shouldBe(view.byteLength, 112);
71+
buffer.grow(1024);
72+
shouldBe(view.byteLength, 1008);
73+
}

JSTests/stress/typed-array-from.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ function shouldThrow(func, errorMessage) {
6666

6767
shouldThrow(() => {
6868
Uint32Array.from(a0);
69-
}, `TypeError: Underlying ArrayBuffer has been detached from the view`);
69+
}, `TypeError: Underlying ArrayBuffer has been detached from the view or out-of-bounds`);
7070
}
7171

7272
Uint8Array.prototype.__proto__[Symbol.iterator] = function *() {

JSTests/stress/typedarray-defineOwnProperty-error.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ testException(TA => {
2222
let ta = new TA(4);
2323
transferArrayBuffer(ta.buffer);
2424
Object.defineProperty(ta, "0", {value: 1});
25-
}, "TypeError: Underlying ArrayBuffer has been detached from the view");
25+
}, "TypeError: Underlying ArrayBuffer has been detached from the view or out-of-bounds");
2626

2727
testException(TA => {
2828
let ta = new TA(4);

JSTests/stress/typedarray-functions-with-neutered.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ function checkProtoFunc(testArgs) {
5757
} catch (e) {
5858
if (testArgs.error)
5959
return e == testArgs.error;
60-
return e == "TypeError: Underlying ArrayBuffer has been detached from the view";
60+
return e == "TypeError: Underlying ArrayBuffer has been detached from the view or out-of-bounds";
6161
}
6262
return false;
6363
}
@@ -96,7 +96,7 @@ function callWithArgs(func, array, args, argNum) {
9696
try {
9797
func.call(array, ...args);
9898
} catch (e) {
99-
if (e != "TypeError: Underlying ArrayBuffer has been detached from the view")
99+
if (e != "TypeError: Underlying ArrayBuffer has been detached from the view or out-of-bounds")
100100
throw new Error(e);
101101
failed = false;
102102
}

JSTests/wasm/js-api/neutered-inputs.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,18 @@ let neuteredArray = new Uint8Array(1);
1010
transferArrayBuffer(neuteredArray.buffer);
1111

1212
const testAsyncFunction = func => {
13-
func(neuteredArray).then(fail).catch(catcher(TypeError, "underlying TypedArray has been detatched from the ArrayBuffer"));
14-
func(neuteredArray.buffer).then(fail).catch(catcher(TypeError, "underlying TypedArray has been detatched from the ArrayBuffer"));
13+
func(neuteredArray).then(fail).catch(catcher(TypeError, "Underlying ArrayBuffer has been detached from the view or out-of-bounds"));
14+
func(neuteredArray.buffer).then(fail).catch(catcher(TypeError, "Underlying ArrayBuffer has been detached from the view or out-of-bounds"));
1515
};
1616

1717
const testFunction = func => {
18-
assert.throws(() => func(neuteredArray), TypeError, "underlying TypedArray has been detatched from the ArrayBuffer");
19-
assert.throws(() => func(neuteredArray.buffer), TypeError, "underlying TypedArray has been detatched from the ArrayBuffer");
18+
assert.throws(() => func(neuteredArray), TypeError, "Underlying ArrayBuffer has been detached from the view or out-of-bounds");
19+
assert.throws(() => func(neuteredArray.buffer), TypeError, "Underlying ArrayBuffer has been detached from the view or out-of-bounds");
2020
};
2121

2222
const testConstructor = func => {
23-
assert.throws(() => new func(neuteredArray), TypeError, "underlying TypedArray has been detatched from the ArrayBuffer");
24-
assert.throws(() => new func(neuteredArray.buffer), TypeError, "underlying TypedArray has been detatched from the ArrayBuffer");
23+
assert.throws(() => new func(neuteredArray), TypeError, "Underlying ArrayBuffer has been detached from the view or out-of-bounds");
24+
assert.throws(() => new func(neuteredArray.buffer), TypeError, "Underlying ArrayBuffer has been detached from the view or out-of-bounds");
2525
};
2626

2727
testConstructor(WebAssembly.Module);

LayoutTests/fast/canvas/webgl/arraybuffer-transfer-of-control.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@
118118
testFailed(testName + ": set on a closed view succeeded");
119119
return false;
120120
} catch (xn) {
121-
if (xn != "TypeError: Underlying ArrayBuffer has been detached from the view") {
121+
if (xn != "TypeError: Underlying ArrayBuffer has been detached from the view or out-of-bounds") {
122122
testFailed(testName + ": set on a closed view threw the wrong exception: " + xn);
123123
return false;
124124
}

Source/JavaScriptCore/API/JSTypedArray.cpp

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -107,37 +107,21 @@ inline TypedArrayType toTypedArrayType(JSTypedArrayType type)
107107
RELEASE_ASSERT_NOT_REACHED();
108108
}
109109

110-
static JSObject* createTypedArray(JSGlobalObject* globalObject, JSTypedArrayType type, RefPtr<ArrayBuffer>&& buffer, size_t offset, size_t length)
110+
static JSObject* createTypedArray(JSGlobalObject* globalObject, JSTypedArrayType type, RefPtr<ArrayBuffer>&& buffer, size_t offset, std::optional<size_t> length)
111111
{
112112
VM& vm = globalObject->vm();
113113
auto scope = DECLARE_THROW_SCOPE(vm);
114114
if (!buffer) {
115115
throwOutOfMemoryError(globalObject, scope);
116116
return nullptr;
117117
}
118+
bool isResizableOrGrowableShared = buffer->isResizableOrGrowableShared();
118119
switch (type) {
119-
case kJSTypedArrayTypeInt8Array:
120-
return JSInt8Array::create(globalObject, globalObject->typedArrayStructure(TypeInt8), WTFMove(buffer), offset, length);
121-
case kJSTypedArrayTypeInt16Array:
122-
return JSInt16Array::create(globalObject, globalObject->typedArrayStructure(TypeInt16), WTFMove(buffer), offset, length);
123-
case kJSTypedArrayTypeInt32Array:
124-
return JSInt32Array::create(globalObject, globalObject->typedArrayStructure(TypeInt32), WTFMove(buffer), offset, length);
125-
case kJSTypedArrayTypeUint8Array:
126-
return JSUint8Array::create(globalObject, globalObject->typedArrayStructure(TypeUint8), WTFMove(buffer), offset, length);
127-
case kJSTypedArrayTypeUint8ClampedArray:
128-
return JSUint8ClampedArray::create(globalObject, globalObject->typedArrayStructure(TypeUint8Clamped), WTFMove(buffer), offset, length);
129-
case kJSTypedArrayTypeUint16Array:
130-
return JSUint16Array::create(globalObject, globalObject->typedArrayStructure(TypeUint16), WTFMove(buffer), offset, length);
131-
case kJSTypedArrayTypeUint32Array:
132-
return JSUint32Array::create(globalObject, globalObject->typedArrayStructure(TypeUint32), WTFMove(buffer), offset, length);
133-
case kJSTypedArrayTypeFloat32Array:
134-
return JSFloat32Array::create(globalObject, globalObject->typedArrayStructure(TypeFloat32), WTFMove(buffer), offset, length);
135-
case kJSTypedArrayTypeFloat64Array:
136-
return JSFloat64Array::create(globalObject, globalObject->typedArrayStructure(TypeFloat64), WTFMove(buffer), offset, length);
137-
case kJSTypedArrayTypeBigInt64Array:
138-
return JSBigInt64Array::create(globalObject, globalObject->typedArrayStructure(TypeBigInt64), WTFMove(buffer), offset, length);
139-
case kJSTypedArrayTypeBigUint64Array:
140-
return JSBigUint64Array::create(globalObject, globalObject->typedArrayStructure(TypeBigUint64), WTFMove(buffer), offset, length);
120+
#define JSC_TYPED_ARRAY_FACTORY(type) case kJSTypedArrayType##type##Array: { \
121+
return JS##type##Array::create(globalObject, globalObject->typedArrayStructure(Type##type, isResizableOrGrowableShared), WTFMove(buffer), offset, length.value()); \
122+
}
123+
FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(JSC_TYPED_ARRAY_FACTORY)
124+
#undef JSC_TYPED_ARRAY_CHECK
141125
case kJSTypedArrayTypeArrayBuffer:
142126
case kJSTypedArrayTypeNone:
143127
RELEASE_ASSERT_NOT_REACHED();
@@ -225,7 +209,10 @@ JSObjectRef JSObjectMakeTypedArrayWithArrayBuffer(JSContextRef ctx, JSTypedArray
225209
RefPtr<ArrayBuffer> buffer = jsBuffer->impl();
226210
unsigned elementByteSize = elementSize(toTypedArrayType(arrayType));
227211

228-
JSObject* result = createTypedArray(globalObject, arrayType, WTFMove(buffer), 0, buffer->byteLength() / elementByteSize);
212+
std::optional<size_t> length;
213+
if (!buffer->isResizableOrGrowableShared())
214+
length = buffer->byteLength() / elementByteSize;
215+
JSObject* result = createTypedArray(globalObject, arrayType, WTFMove(buffer), 0, length);
229216
if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
230217
return nullptr;
231218
return toRef(result);
@@ -286,7 +273,7 @@ size_t JSObjectGetTypedArrayByteLength(JSContextRef, JSObjectRef objectRef, JSVa
286273
JSObject* object = toJS(objectRef);
287274

288275
if (JSArrayBufferView* typedArray = jsDynamicCast<JSArrayBufferView*>(object))
289-
return typedArray->length() * elementSize(typedArray->type());
276+
return typedArray->byteLength();
290277

291278
return 0;
292279
}

Source/JavaScriptCore/builtins/ArrayIteratorPrototype.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ function next()
3333

3434
var array = @getArrayIteratorInternalField(this, @arrayIteratorFieldIteratedObject);
3535
if (@isTypedArrayView(array) && @isDetached(array))
36-
@throwTypeError("Underlying ArrayBuffer has been detached from the view");
36+
@throwTypeError("Underlying ArrayBuffer has been detached from the view or out-of-bounds");
3737

3838
var kind = @getArrayIteratorInternalField(this, @arrayIteratorFieldKind);
3939
return @arrayIteratorNextHelper.@call(this, array, kind);

Source/JavaScriptCore/bytecode/AccessCase.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,8 +1218,8 @@ void AccessCase::generateWithGuard(
12181218

12191219
GPRReg propertyGPR = stubInfo.propertyGPR();
12201220

1221-
jit.load8(CCallHelpers::Address(baseGPR, JSCell::typeInfoTypeOffset()), scratchGPR);
1222-
fallThrough.append(jit.branch32(CCallHelpers::NotEqual, scratchGPR, CCallHelpers::TrustedImm32(typeForTypedArrayType(type))));
1221+
fallThrough.append(jit.branch8(CCallHelpers::NotEqual, CCallHelpers::Address(baseGPR, JSCell::typeInfoTypeOffset()), CCallHelpers::TrustedImm32(typeForTypedArrayType(type))));
1222+
fallThrough.append(jit.branchTest8(CCallHelpers::NonZero, CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfMode()), CCallHelpers::TrustedImm32(isResizableOrGrowableSharedMode)));
12231223

12241224
CCallHelpers::Address addressOfLength = CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfLength());
12251225
jit.signExtend32ToPtr(propertyGPR, scratchGPR);
@@ -1237,9 +1237,9 @@ void AccessCase::generateWithGuard(
12371237
jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
12381238

12391239
#if USE(LARGE_TYPED_ARRAYS)
1240-
jit.load64(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfMaxByteLength()), scratchGPR);
1240+
jit.load64(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfLength()), scratchGPR);
12411241
#else
1242-
jit.load32(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfMaxByteLength()), scratchGPR);
1242+
jit.load32(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfLength()), scratchGPR);
12431243
#endif
12441244
jit.loadPtr(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfVector()), scratch2GPR);
12451245
jit.cageConditionallyAndUntag(Gigacage::Primitive, scratch2GPR, scratchGPR, scratchGPR, false);
@@ -1625,8 +1625,8 @@ void AccessCase::generateWithGuard(
16251625

16261626
GPRReg propertyGPR = stubInfo.propertyGPR();
16271627

1628-
jit.load8(CCallHelpers::Address(baseGPR, JSCell::typeInfoTypeOffset()), scratchGPR);
1629-
fallThrough.append(jit.branch32(CCallHelpers::NotEqual, scratchGPR, CCallHelpers::TrustedImm32(typeForTypedArrayType(type))));
1628+
fallThrough.append(jit.branch8(CCallHelpers::NotEqual, CCallHelpers::Address(baseGPR, JSCell::typeInfoTypeOffset()), CCallHelpers::TrustedImm32(typeForTypedArrayType(type))));
1629+
fallThrough.append(jit.branchTest8(CCallHelpers::NonZero, CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfMode()), CCallHelpers::TrustedImm32(isResizableOrGrowableSharedMode)));
16301630

16311631
if (isInt(type))
16321632
state.failAndRepatch.append(jit.branchIfNotInt32(valueRegs));
@@ -1663,9 +1663,9 @@ void AccessCase::generateWithGuard(
16631663
jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
16641664

16651665
#if USE(LARGE_TYPED_ARRAYS)
1666-
jit.load64(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfMaxByteLength()), scratchGPR);
1666+
jit.load64(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfLength()), scratchGPR);
16671667
#else
1668-
jit.load32(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfMaxByteLength()), scratchGPR);
1668+
jit.load32(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfLength()), scratchGPR);
16691669
#endif
16701670
jit.loadPtr(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfVector()), scratch2GPR);
16711671
jit.cageConditionallyAndUntag(Gigacage::Primitive, scratch2GPR, scratchGPR, scratchGPR, false);

0 commit comments

Comments
 (0)