Commit 4f0e9d6c authored by Benedikt Meurer's avatar Benedikt Meurer Committed by Commit Bot

[csa] Introduce ThrowIfArrayBufferIsDetached() helper.

This adds new CSA helpers ThrowIfArrayBufferIsDetached() and
ThrowIfArrayBufferViewBufferIsDetached() which check whether
ArrayBuffers or ArrayBufferViews have been detached. This
improves readability of the code that has to deal with typed
arrays.

Bug: v8:8015
Change-Id: Iafab86c418bd0e12bb7d7ec803151a1f6b786400
Reviewed-on: https://chromium-review.googlesource.com/1183422
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarPeter Marshall <petermarshall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55273}
parent 60cbde18
...@@ -501,8 +501,7 @@ Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) { ...@@ -501,8 +501,7 @@ Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) {
// ValidateTypedArray: tc39.github.io/ecma262/#sec-validatetypedarray // ValidateTypedArray: tc39.github.io/ecma262/#sec-validatetypedarray
Label throw_not_typed_array(this, Label::kDeferred), Label throw_not_typed_array(this, Label::kDeferred);
throw_detached(this, Label::kDeferred);
GotoIf(TaggedIsSmi(receiver_), &throw_not_typed_array); GotoIf(TaggedIsSmi(receiver_), &throw_not_typed_array);
GotoIfNot(HasInstanceType(CAST(receiver_), JS_TYPED_ARRAY_TYPE), GotoIfNot(HasInstanceType(CAST(receiver_), JS_TYPED_ARRAY_TYPE),
...@@ -511,9 +510,8 @@ Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) { ...@@ -511,9 +510,8 @@ Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) {
TNode<JSTypedArray> typed_array = CAST(receiver_); TNode<JSTypedArray> typed_array = CAST(receiver_);
o_ = typed_array; o_ = typed_array;
Node* array_buffer = TNode<JSArrayBuffer> array_buffer = LoadArrayBufferViewBuffer(typed_array);
LoadObjectField(typed_array, JSTypedArray::kBufferOffset); ThrowIfArrayBufferIsDetached(context_, array_buffer, name_);
GotoIf(IsDetachedBuffer(array_buffer), &throw_detached);
len_ = LoadTypedArrayLength(typed_array); len_ = LoadTypedArrayLength(typed_array);
...@@ -526,9 +524,6 @@ Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) { ...@@ -526,9 +524,6 @@ Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) {
BIND(&throw_not_typed_array); BIND(&throw_not_typed_array);
ThrowTypeError(context_, MessageTemplate::kNotTypedArray); ThrowTypeError(context_, MessageTemplate::kNotTypedArray);
BIND(&throw_detached);
ThrowTypeError(context_, MessageTemplate::kDetachedOperation, name_);
BIND(&throw_not_callable); BIND(&throw_not_callable);
ThrowTypeError(context_, MessageTemplate::kCalledNonCallable, callbackfn_); ThrowTypeError(context_, MessageTemplate::kCalledNonCallable, callbackfn_);
...@@ -3500,7 +3495,6 @@ TF_BUILTIN(ArrayIteratorPrototypeNext, CodeStubAssembler) { ...@@ -3500,7 +3495,6 @@ TF_BUILTIN(ArrayIteratorPrototypeNext, CodeStubAssembler) {
Label allocate_entry_if_needed(this); Label allocate_entry_if_needed(this);
Label allocate_iterator_result(this); Label allocate_iterator_result(this);
Label if_detached(this, Label::kDeferred);
Label if_typedarray(this), if_other(this, Label::kDeferred), if_array(this), Label if_typedarray(this), if_other(this, Label::kDeferred), if_array(this),
if_generic(this, Label::kDeferred); if_generic(this, Label::kDeferred);
Label set_done(this, Label::kDeferred); Label set_done(this, Label::kDeferred);
...@@ -3678,8 +3672,7 @@ TF_BUILTIN(ArrayIteratorPrototypeNext, CodeStubAssembler) { ...@@ -3678,8 +3672,7 @@ TF_BUILTIN(ArrayIteratorPrototypeNext, CodeStubAssembler) {
BIND(&if_typedarray); BIND(&if_typedarray);
{ {
// Check that the {array}s buffer wasn't neutered. // Check that the {array}s buffer wasn't neutered.
TNode<JSArrayBuffer> buffer = LoadArrayBufferViewBuffer(CAST(array)); ThrowIfArrayBufferViewBufferIsDetached(context, CAST(array), method_name);
GotoIf(IsDetachedBuffer(buffer), &if_detached);
// If we go outside of the {length}, we don't need to update the // If we go outside of the {length}, we don't need to update the
// [[ArrayIteratorNextIndex]] anymore, since a JSTypedArray's // [[ArrayIteratorNextIndex]] anymore, since a JSTypedArray's
...@@ -3710,9 +3703,6 @@ TF_BUILTIN(ArrayIteratorPrototypeNext, CodeStubAssembler) { ...@@ -3710,9 +3703,6 @@ TF_BUILTIN(ArrayIteratorPrototypeNext, CodeStubAssembler) {
var_value.Bind(LoadFixedTypedArrayElementAsTagged(data_ptr, CAST(index), var_value.Bind(LoadFixedTypedArrayElementAsTagged(data_ptr, CAST(index),
elements_kind)); elements_kind));
Goto(&allocate_entry_if_needed); Goto(&allocate_entry_if_needed);
BIND(&if_detached);
ThrowTypeError(context, MessageTemplate::kDetachedOperation, method_name);
} }
BIND(&allocate_entry_if_needed); BIND(&allocate_entry_if_needed);
......
...@@ -361,8 +361,7 @@ void TypedArrayBuiltinsAssembler::ConstructByArrayBuffer( ...@@ -361,8 +361,7 @@ void TypedArrayBuiltinsAssembler::ConstructByArrayBuffer(
invalid_offset_error(this, Label::kDeferred); invalid_offset_error(this, Label::kDeferred);
Label offset_is_smi(this), offset_not_smi(this, Label::kDeferred), Label offset_is_smi(this), offset_not_smi(this, Label::kDeferred),
check_length(this), call_init(this), invalid_length(this), check_length(this), call_init(this), invalid_length(this),
length_undefined(this), length_defined(this), detached_error(this), length_undefined(this), length_defined(this), done(this);
done(this);
GotoIf(IsUndefined(byte_offset), &check_length); GotoIf(IsUndefined(byte_offset), &check_length);
...@@ -399,7 +398,7 @@ void TypedArrayBuiltinsAssembler::ConstructByArrayBuffer( ...@@ -399,7 +398,7 @@ void TypedArrayBuiltinsAssembler::ConstructByArrayBuffer(
BIND(&length_undefined); BIND(&length_undefined);
{ {
GotoIf(IsDetachedBuffer(buffer), &detached_error); ThrowIfArrayBufferIsDetached(context, buffer, "Construct");
Node* buffer_byte_length = Node* buffer_byte_length =
LoadObjectField(buffer, JSArrayBuffer::kByteLengthOffset); LoadObjectField(buffer, JSArrayBuffer::kByteLengthOffset);
...@@ -421,7 +420,7 @@ void TypedArrayBuiltinsAssembler::ConstructByArrayBuffer( ...@@ -421,7 +420,7 @@ void TypedArrayBuiltinsAssembler::ConstructByArrayBuffer(
BIND(&length_defined); BIND(&length_defined);
{ {
TNode<Smi> new_length = ToSmiIndex(length, context, &invalid_length); TNode<Smi> new_length = ToSmiIndex(length, context, &invalid_length);
GotoIf(IsDetachedBuffer(buffer), &detached_error); ThrowIfArrayBufferIsDetached(context, buffer, "Construct");
new_byte_length.Bind(SmiMul(new_length, element_size)); new_byte_length.Bind(SmiMul(new_length, element_size));
// Reading the byte length must come after the ToIndex operation, which // Reading the byte length must come after the ToIndex operation, which
// could cause the buffer to become detached. // could cause the buffer to become detached.
...@@ -476,9 +475,6 @@ void TypedArrayBuiltinsAssembler::ConstructByArrayBuffer( ...@@ -476,9 +475,6 @@ void TypedArrayBuiltinsAssembler::ConstructByArrayBuffer(
ThrowRangeError(context, MessageTemplate::kInvalidTypedArrayLength, length); ThrowRangeError(context, MessageTemplate::kInvalidTypedArrayLength, length);
} }
BIND(&detached_error);
{ ThrowTypeError(context, MessageTemplate::kDetachedOperation, "Construct"); }
BIND(&done); BIND(&done);
} }
...@@ -573,7 +569,7 @@ void TypedArrayBuiltinsAssembler::ConstructByArrayLike( ...@@ -573,7 +569,7 @@ void TypedArrayBuiltinsAssembler::ConstructByArrayLike(
TNode<HeapObject> array_like, TNode<Object> initial_length, TNode<HeapObject> array_like, TNode<Object> initial_length,
TNode<Smi> element_size, TNode<JSReceiver> buffer_constructor) { TNode<Smi> element_size, TNode<JSReceiver> buffer_constructor) {
Label invalid_length(this, Label::kDeferred), fill(this), fast_copy(this), Label invalid_length(this, Label::kDeferred), fill(this), fast_copy(this),
detached_check(this), done(this), detached_error(this, Label::kDeferred); detached_check(this), done(this);
// The caller has looked up length on array_like, which is observable. // The caller has looked up length on array_like, which is observable.
TNode<Smi> length = ToSmiLength(initial_length, context, &invalid_length); TNode<Smi> length = ToSmiLength(initial_length, context, &invalid_length);
...@@ -586,9 +582,8 @@ void TypedArrayBuiltinsAssembler::ConstructByArrayLike( ...@@ -586,9 +582,8 @@ void TypedArrayBuiltinsAssembler::ConstructByArrayLike(
Goto(&fill); Goto(&fill);
BIND(&detached_check); BIND(&detached_check);
GotoIf(IsDetachedBuffer( ThrowIfArrayBufferViewBufferIsDetached(context, CAST(array_like),
LoadObjectField(array_like, JSTypedArray::kBufferOffset)), "Construct");
&detached_error);
Goto(&fill); Goto(&fill);
BIND(&fill); BIND(&fill);
...@@ -629,9 +624,6 @@ void TypedArrayBuiltinsAssembler::ConstructByArrayLike( ...@@ -629,9 +624,6 @@ void TypedArrayBuiltinsAssembler::ConstructByArrayLike(
Goto(&done); Goto(&done);
} }
BIND(&detached_error);
{ ThrowTypeError(context, MessageTemplate::kDetachedOperation, "Construct"); }
BIND(&invalid_length); BIND(&invalid_length);
{ {
ThrowRangeError(context, MessageTemplate::kInvalidTypedArrayLength, ThrowRangeError(context, MessageTemplate::kInvalidTypedArrayLength,
...@@ -964,18 +956,12 @@ TNode<JSArrayBuffer> TypedArrayBuiltinsAssembler::GetBuffer( ...@@ -964,18 +956,12 @@ TNode<JSArrayBuffer> TypedArrayBuiltinsAssembler::GetBuffer(
TNode<JSTypedArray> TypedArrayBuiltinsAssembler::ValidateTypedArray( TNode<JSTypedArray> TypedArrayBuiltinsAssembler::ValidateTypedArray(
TNode<Context> context, TNode<Object> obj, const char* method_name) { TNode<Context> context, TNode<Object> obj, const char* method_name) {
Label validation_done(this);
// If it is not a typed array, throw // If it is not a typed array, throw
ThrowIfNotInstanceType(context, obj, JS_TYPED_ARRAY_TYPE, method_name); ThrowIfNotInstanceType(context, obj, JS_TYPED_ARRAY_TYPE, method_name);
// If the typed array's buffer is detached, throw // If the typed array's buffer is detached, throw
TNode<Object> buffer = ThrowIfArrayBufferViewBufferIsDetached(context, CAST(obj), method_name);
LoadObjectField(CAST(obj), JSTypedArray::kBufferOffset);
GotoIfNot(IsDetachedBuffer(buffer), &validation_done);
ThrowTypeError(context, MessageTemplate::kDetachedOperation, method_name);
BIND(&validation_done);
return CAST(obj); return CAST(obj);
} }
...@@ -1189,6 +1175,7 @@ void TypedArrayBuiltinsAssembler::DispatchTypedArrayByElementsKind( ...@@ -1189,6 +1175,7 @@ void TypedArrayBuiltinsAssembler::DispatchTypedArrayByElementsKind(
// ES #sec-get-%typedarray%.prototype.set // ES #sec-get-%typedarray%.prototype.set
TF_BUILTIN(TypedArrayPrototypeSet, TypedArrayBuiltinsAssembler) { TF_BUILTIN(TypedArrayPrototypeSet, TypedArrayBuiltinsAssembler) {
const char* method_name = "%TypedArray%.prototype.set";
TNode<Context> context = CAST(Parameter(Descriptor::kContext)); TNode<Context> context = CAST(Parameter(Descriptor::kContext));
CodeStubArguments args( CodeStubArguments args(
this, this,
...@@ -1197,7 +1184,6 @@ TF_BUILTIN(TypedArrayPrototypeSet, TypedArrayBuiltinsAssembler) { ...@@ -1197,7 +1184,6 @@ TF_BUILTIN(TypedArrayPrototypeSet, TypedArrayBuiltinsAssembler) {
Label if_source_is_typed_array(this), if_source_is_fast_jsarray(this), Label if_source_is_typed_array(this), if_source_is_fast_jsarray(this),
if_offset_is_out_of_bounds(this, Label::kDeferred), if_offset_is_out_of_bounds(this, Label::kDeferred),
if_source_too_large(this, Label::kDeferred), if_source_too_large(this, Label::kDeferred),
if_typed_array_is_neutered(this, Label::kDeferred),
if_receiver_is_not_typedarray(this, Label::kDeferred); if_receiver_is_not_typedarray(this, Label::kDeferred);
// Check the receiver is a typed array. // Check the receiver is a typed array.
...@@ -1221,9 +1207,7 @@ TF_BUILTIN(TypedArrayPrototypeSet, TypedArrayBuiltinsAssembler) { ...@@ -1221,9 +1207,7 @@ TF_BUILTIN(TypedArrayPrototypeSet, TypedArrayBuiltinsAssembler) {
TNode<Smi> offset_smi = CAST(offset_num); TNode<Smi> offset_smi = CAST(offset_num);
// Check the receiver is not neutered. // Check the receiver is not neutered.
TNode<Object> receiver_buffer = ThrowIfArrayBufferViewBufferIsDetached(context, CAST(receiver), method_name);
LoadObjectField(CAST(receiver), JSTypedArray::kBufferOffset);
GotoIf(IsDetachedBuffer(receiver_buffer), &if_typed_array_is_neutered);
// Check the source argument is valid and whether a fast path can be taken. // Check the source argument is valid and whether a fast path can be taken.
Label call_runtime(this); Label call_runtime(this);
...@@ -1237,9 +1221,7 @@ TF_BUILTIN(TypedArrayPrototypeSet, TypedArrayBuiltinsAssembler) { ...@@ -1237,9 +1221,7 @@ TF_BUILTIN(TypedArrayPrototypeSet, TypedArrayBuiltinsAssembler) {
BIND(&if_source_is_typed_array); BIND(&if_source_is_typed_array);
{ {
// Check the source argument is not neutered. // Check the source argument is not neutered.
TNode<Object> source_buffer = ThrowIfArrayBufferViewBufferIsDetached(context, CAST(source), method_name);
LoadObjectField(CAST(source), JSTypedArray::kBufferOffset);
GotoIf(IsDetachedBuffer(source_buffer), &if_typed_array_is_neutered);
SetTypedArraySource(context, CAST(source), CAST(receiver), SetTypedArraySource(context, CAST(source), CAST(receiver),
SmiUntag(offset_smi), &call_runtime, SmiUntag(offset_smi), &call_runtime,
...@@ -1265,10 +1247,6 @@ TF_BUILTIN(TypedArrayPrototypeSet, TypedArrayBuiltinsAssembler) { ...@@ -1265,10 +1247,6 @@ TF_BUILTIN(TypedArrayPrototypeSet, TypedArrayBuiltinsAssembler) {
BIND(&if_source_too_large); BIND(&if_source_too_large);
ThrowRangeError(context, MessageTemplate::kTypedArraySetSourceTooLarge); ThrowRangeError(context, MessageTemplate::kTypedArraySetSourceTooLarge);
BIND(&if_typed_array_is_neutered);
ThrowTypeError(context, MessageTemplate::kDetachedOperation,
"%TypedArray%.prototype.set");
BIND(&if_receiver_is_not_typedarray); BIND(&if_receiver_is_not_typedarray);
ThrowTypeError(context, MessageTemplate::kNotTypedArray); ThrowTypeError(context, MessageTemplate::kNotTypedArray);
} }
...@@ -1277,7 +1255,6 @@ TF_BUILTIN(TypedArrayPrototypeSet, TypedArrayBuiltinsAssembler) { ...@@ -1277,7 +1255,6 @@ TF_BUILTIN(TypedArrayPrototypeSet, TypedArrayBuiltinsAssembler) {
TF_BUILTIN(TypedArrayPrototypeSlice, TypedArrayBuiltinsAssembler) { TF_BUILTIN(TypedArrayPrototypeSlice, TypedArrayBuiltinsAssembler) {
const char* method_name = "%TypedArray%.prototype.slice"; const char* method_name = "%TypedArray%.prototype.slice";
Label call_c(this), call_memmove(this), if_count_is_not_zero(this), Label call_c(this), call_memmove(this), if_count_is_not_zero(this),
if_typed_array_is_neutered(this, Label::kDeferred),
if_bigint_mixed_types(this, Label::kDeferred); if_bigint_mixed_types(this, Label::kDeferred);
TNode<Context> context = CAST(Parameter(Descriptor::kContext)); TNode<Context> context = CAST(Parameter(Descriptor::kContext));
...@@ -1321,9 +1298,9 @@ TF_BUILTIN(TypedArrayPrototypeSlice, TypedArrayBuiltinsAssembler) { ...@@ -1321,9 +1298,9 @@ TF_BUILTIN(TypedArrayPrototypeSlice, TypedArrayBuiltinsAssembler) {
// result array is neutered or not since TypedArraySpeciesCreate checked it. // result array is neutered or not since TypedArraySpeciesCreate checked it.
CSA_ASSERT(this, Word32BinaryNot(IsDetachedBuffer(LoadObjectField( CSA_ASSERT(this, Word32BinaryNot(IsDetachedBuffer(LoadObjectField(
result_array, JSTypedArray::kBufferOffset)))); result_array, JSTypedArray::kBufferOffset))));
TNode<Object> receiver_buffer = TNode<JSArrayBuffer> receiver_buffer =
LoadObjectField(CAST(receiver), JSTypedArray::kBufferOffset); LoadArrayBufferViewBuffer(CAST(receiver));
GotoIf(IsDetachedBuffer(receiver_buffer), &if_typed_array_is_neutered); ThrowIfArrayBufferIsDetached(context, receiver_buffer, method_name);
// result_array could be a different type from source or share the same // result_array could be a different type from source or share the same
// buffer with the source because of custom species constructor. // buffer with the source because of custom species constructor.
...@@ -1390,9 +1367,6 @@ TF_BUILTIN(TypedArrayPrototypeSlice, TypedArrayBuiltinsAssembler) { ...@@ -1390,9 +1367,6 @@ TF_BUILTIN(TypedArrayPrototypeSlice, TypedArrayBuiltinsAssembler) {
args.PopAndReturn(result_array); args.PopAndReturn(result_array);
} }
BIND(&if_typed_array_is_neutered);
ThrowTypeError(context, MessageTemplate::kDetachedOperation, method_name);
BIND(&if_bigint_mixed_types); BIND(&if_bigint_mixed_types);
ThrowTypeError(context, MessageTemplate::kBigIntMixedTypes); ThrowTypeError(context, MessageTemplate::kBigIntMixedTypes);
} }
...@@ -1520,18 +1494,12 @@ void TypedArrayBuiltinsAssembler::GenerateTypedArrayPrototypeIterationMethod( ...@@ -1520,18 +1494,12 @@ void TypedArrayBuiltinsAssembler::GenerateTypedArrayPrototypeIterationMethod(
GotoIfNot(IsJSTypedArray(CAST(receiver)), &throw_bad_receiver); GotoIfNot(IsJSTypedArray(CAST(receiver)), &throw_bad_receiver);
// Check if the {receiver}'s JSArrayBuffer was neutered. // Check if the {receiver}'s JSArrayBuffer was neutered.
TNode<JSArrayBuffer> receiver_buffer = LoadObjectField<JSArrayBuffer>( ThrowIfArrayBufferViewBufferIsDetached(context, CAST(receiver), method_name);
CAST(receiver), JSTypedArray::kBufferOffset);
Label if_receiverisneutered(this, Label::kDeferred);
GotoIf(IsDetachedBuffer(receiver_buffer), &if_receiverisneutered);
Return(CreateArrayIterator(context, receiver, kind)); Return(CreateArrayIterator(context, receiver, kind));
BIND(&throw_bad_receiver); BIND(&throw_bad_receiver);
ThrowTypeError(context, MessageTemplate::kNotTypedArray, method_name); ThrowTypeError(context, MessageTemplate::kNotTypedArray, method_name);
BIND(&if_receiverisneutered);
ThrowTypeError(context, MessageTemplate::kDetachedOperation, method_name);
} }
// ES #sec-%typedarray%.prototype.values // ES #sec-%typedarray%.prototype.values
......
...@@ -11979,6 +11979,23 @@ Node* CodeStubAssembler::IsDetachedBuffer(Node* buffer) { ...@@ -11979,6 +11979,23 @@ Node* CodeStubAssembler::IsDetachedBuffer(Node* buffer) {
return IsSetWord32<JSArrayBuffer::WasNeutered>(buffer_bit_field); return IsSetWord32<JSArrayBuffer::WasNeutered>(buffer_bit_field);
} }
void CodeStubAssembler::ThrowIfArrayBufferIsDetached(
SloppyTNode<Context> context, TNode<JSArrayBuffer> array_buffer,
const char* method_name) {
Label if_detached(this, Label::kDeferred), if_not_detached(this);
Branch(IsDetachedBuffer(array_buffer), &if_detached, &if_not_detached);
BIND(&if_detached);
ThrowTypeError(context, MessageTemplate::kDetachedOperation, method_name);
BIND(&if_not_detached);
}
void CodeStubAssembler::ThrowIfArrayBufferViewBufferIsDetached(
SloppyTNode<Context> context, TNode<JSArrayBufferView> array_buffer_view,
const char* method_name) {
TNode<JSArrayBuffer> buffer = LoadArrayBufferViewBuffer(array_buffer_view);
ThrowIfArrayBufferIsDetached(context, buffer, method_name);
}
TNode<JSArrayBuffer> CodeStubAssembler::LoadArrayBufferViewBuffer( TNode<JSArrayBuffer> CodeStubAssembler::LoadArrayBufferViewBuffer(
TNode<JSArrayBufferView> array_buffer_view) { TNode<JSArrayBufferView> array_buffer_view) {
return LoadObjectField<JSArrayBuffer>(array_buffer_view, return LoadObjectField<JSArrayBuffer>(array_buffer_view,
......
...@@ -2722,6 +2722,12 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -2722,6 +2722,12 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// TypedArray/ArrayBuffer helpers // TypedArray/ArrayBuffer helpers
Node* IsDetachedBuffer(Node* buffer); Node* IsDetachedBuffer(Node* buffer);
void ThrowIfArrayBufferIsDetached(SloppyTNode<Context> context,
TNode<JSArrayBuffer> array_buffer,
const char* method_name);
void ThrowIfArrayBufferViewBufferIsDetached(
SloppyTNode<Context> context, TNode<JSArrayBufferView> array_buffer_view,
const char* method_name);
TNode<JSArrayBuffer> LoadArrayBufferViewBuffer( TNode<JSArrayBuffer> LoadArrayBufferViewBuffer(
TNode<JSArrayBufferView> array_buffer_view); TNode<JSArrayBufferView> array_buffer_view);
TNode<RawPtrT> LoadArrayBufferBackingStore(TNode<JSArrayBuffer> array_buffer); TNode<RawPtrT> LoadArrayBufferBackingStore(TNode<JSArrayBuffer> array_buffer);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment