From 140cd812a2b6771730832601ac6dabbd69ce4634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marja=20H=C3=B6ltt=C3=A4?= Date: Thu, 29 Jul 2021 15:53:10 +0200 Subject: [PATCH] [rab/gsab] Update TypedArrayPrototypeByteOffset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This CL assumes https://github.com/tc39/proposal-resizablearraybuffer/issues/68 is indeed a spec bug. Bug: v8:11111 Change-Id: I8d24f0d07f7ab40ba01b8c422868ad189d6f7e5a Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3060478 Commit-Queue: Marja Hölttä Reviewed-by: Jakob Kummerow Cr-Commit-Position: refs/heads/master@{#76001} --- src/builtins/builtins-typed-array-gen.cc | 17 ++++---- src/codegen/code-stub-assembler.cc | 39 +++++++++++++++++++ src/codegen/code-stub-assembler.h | 4 ++ .../typedarray-resizablearraybuffer.js | 13 +++++++ test/test262/test262.status | 5 ++- 5 files changed, 69 insertions(+), 9 deletions(-) diff --git a/src/builtins/builtins-typed-array-gen.cc b/src/builtins/builtins-typed-array-gen.cc index 735d8b674fce..99ba35b6ec35 100644 --- a/src/builtins/builtins-typed-array-gen.cc +++ b/src/builtins/builtins-typed-array-gen.cc @@ -154,13 +154,16 @@ TF_BUILTIN(TypedArrayPrototypeByteOffset, TypedArrayBuiltinsAssembler) { // Check if the {receiver} is actually a JSTypedArray. ThrowIfNotInstanceType(context, receiver, JS_TYPED_ARRAY_TYPE, kMethodName); - // Default to zero if the {receiver}s buffer was detached. - TNode receiver_buffer = - LoadJSArrayBufferViewBuffer(CAST(receiver)); - TNode byte_offset = Select( - IsDetachedBuffer(receiver_buffer), [=] { return UintPtrConstant(0); }, - [=] { return LoadJSArrayBufferViewByteOffset(CAST(receiver)); }); - Return(ChangeUintPtrToTagged(byte_offset)); + // Default to zero if the {receiver}s buffer was detached / out of bounds. + Label detached_or_oob(this), not_detached_or_oob(this); + IsTypedArrayDetachedOrOutOfBounds(CAST(receiver), &detached_or_oob, + ¬_detached_or_oob); + BIND(&detached_or_oob); + Return(ChangeUintPtrToTagged(UintPtrConstant(0))); + + BIND(¬_detached_or_oob); + Return( + ChangeUintPtrToTagged(LoadJSArrayBufferViewByteOffset(CAST(receiver)))); } // ES6 #sec-get-%typedarray%.prototype.length diff --git a/src/codegen/code-stub-assembler.cc b/src/codegen/code-stub-assembler.cc index 2c66895fbed1..e25135decee4 100644 --- a/src/codegen/code-stub-assembler.cc +++ b/src/codegen/code-stub-assembler.cc @@ -13926,6 +13926,45 @@ TNode CodeStubAssembler::LoadVariableLengthJSTypedArrayLength( return result.value(); } +void CodeStubAssembler::IsTypedArrayDetachedOrOutOfBounds( + TNode array, Label* detached_or_oob, + Label* not_detached_nor_oob) { + TNode buffer = LoadJSArrayBufferViewBuffer(array); + + GotoIf(IsDetachedBuffer(buffer), detached_or_oob); + GotoIfNot(IsVariableLengthTypedArray(array), not_detached_nor_oob); + GotoIf(IsSharedArrayBuffer(buffer), not_detached_nor_oob); + + { + TNode buffer_byte_length = LoadJSArrayBufferByteLength(buffer); + TNode array_byte_offset = LoadJSArrayBufferViewByteOffset(array); + + Label length_tracking(this), not_length_tracking(this); + Branch(IsLengthTrackingTypedArray(array), &length_tracking, + ¬_length_tracking); + + BIND(&length_tracking); + { + // The backing RAB might have been shrunk so that the start of the + // TypedArray is already out of bounds. + Branch(UintPtrLessThanOrEqual(array_byte_offset, buffer_byte_length), + not_detached_nor_oob, detached_or_oob); + } + + BIND(¬_length_tracking); + { + // Check if the backing RAB has shrunk so that the buffer is out of + // bounds. + TNode array_byte_length = + LoadJSArrayBufferViewByteLength(array); + Branch(UintPtrGreaterThanOrEqual( + buffer_byte_length, + UintPtrAdd(array_byte_offset, array_byte_length)), + not_detached_nor_oob, detached_or_oob); + } + } +} + // ES #sec-integerindexedobjectbytelength TNode CodeStubAssembler::LoadVariableLengthJSTypedArrayByteLength( TNode context, TNode array, diff --git a/src/codegen/code-stub-assembler.h b/src/codegen/code-stub-assembler.h index ff65cb11dae6..008af6006f5b 100644 --- a/src/codegen/code-stub-assembler.h +++ b/src/codegen/code-stub-assembler.h @@ -3569,6 +3569,10 @@ class V8_EXPORT_PRIVATE CodeStubAssembler TNode LoadVariableLengthJSTypedArrayByteLength( TNode context, TNode array, TNode buffer); + void IsTypedArrayDetachedOrOutOfBounds(TNode array, + Label* detached_or_oob, + Label* not_detached_nor_oob); + TNode RabGsabElementsKindToElementByteSize( TNode elementsKind); TNode LoadJSTypedArrayDataPtr(TNode typed_array); diff --git a/test/mjsunit/typedarray-resizablearraybuffer.js b/test/mjsunit/typedarray-resizablearraybuffer.js index 5409f053933e..b9a12f079d81 100644 --- a/test/mjsunit/typedarray-resizablearraybuffer.js +++ b/test/mjsunit/typedarray-resizablearraybuffer.js @@ -148,6 +148,7 @@ function CreateResizableArrayBuffer(byteLength, maxByteLength) { for (let [ta, length] of tas_and_lengths) { assertEquals(length, ta.length); assertEquals(length * ta.BYTES_PER_ELEMENT, ta.byteLength); + assertEquals(8, ta.byteOffset); } rab.resize(10); @@ -155,6 +156,7 @@ function CreateResizableArrayBuffer(byteLength, maxByteLength) { for (let [ta, length] of tas_and_lengths) { assertEquals(0, ta.length); assertEquals(0, ta.byteLength); + assertEquals(0, ta.byteOffset); } // Resize the rab so that it just barely covers the needed 8 bytes. @@ -163,6 +165,7 @@ function CreateResizableArrayBuffer(byteLength, maxByteLength) { for (let [ta, length] of tas_and_lengths) { assertEquals(length, ta.length); assertEquals(length * ta.BYTES_PER_ELEMENT, ta.byteLength); + assertEquals(8, ta.byteOffset); } rab.resize(40); @@ -170,6 +173,7 @@ function CreateResizableArrayBuffer(byteLength, maxByteLength) { for (let [ta, length] of tas_and_lengths) { assertEquals(length, ta.length); assertEquals(length * ta.BYTES_PER_ELEMENT, ta.byteLength); + assertEquals(8, ta.byteOffset); } })(); @@ -247,12 +251,14 @@ function CreateResizableArrayBuffer(byteLength, maxByteLength) { for (let ta of tas) { assertEquals((16 - offset) / ta.BYTES_PER_ELEMENT, ta.length); assertEquals(16 - offset, ta.byteLength); + assertEquals(offset, ta.byteOffset); } rab.resize(40); for (let ta of tas) { assertEquals((40 - offset) / ta.BYTES_PER_ELEMENT, ta.length); assertEquals(40 - offset, ta.byteLength); + assertEquals(offset, ta.byteOffset); } // Resize to a number which is not a multiple of all byte_lengths. @@ -261,6 +267,7 @@ function CreateResizableArrayBuffer(byteLength, maxByteLength) { const expected_length = Math.floor((20 - offset)/ ta.BYTES_PER_ELEMENT); assertEquals(expected_length, ta.length); assertEquals(expected_length * ta.BYTES_PER_ELEMENT, ta.byteLength); + assertEquals(offset, ta.byteOffset); } // Resize so that all TypedArrays go out of bounds (because of the offset). @@ -269,6 +276,7 @@ function CreateResizableArrayBuffer(byteLength, maxByteLength) { for (let ta of tas) { assertEquals(0, ta.length); assertEquals(0, ta.byteLength); + assertEquals(0, ta.byteOffset); } rab.resize(0); @@ -276,6 +284,7 @@ function CreateResizableArrayBuffer(byteLength, maxByteLength) { for (let ta of tas) { assertEquals(0, ta.length); assertEquals(0, ta.byteLength); + assertEquals(0, ta.byteOffset); } rab.resize(8); @@ -283,6 +292,7 @@ function CreateResizableArrayBuffer(byteLength, maxByteLength) { for (let ta of tas) { assertEquals(0, ta.length); assertEquals(0, ta.byteLength); + assertEquals(offset, ta.byteOffset); } // Resize so that the TypedArrays which have element size > 1 go out of bounds @@ -293,9 +303,11 @@ function CreateResizableArrayBuffer(byteLength, maxByteLength) { if (ta.BYTES_PER_ELEMENT == 1) { assertEquals(1, ta.length); assertEquals(1, ta.byteLength); + assertEquals(offset, ta.byteOffset); } else { assertEquals(0, ta.length); assertEquals(0, ta.byteLength); + assertEquals(offset, ta.byteOffset); } } @@ -304,6 +316,7 @@ function CreateResizableArrayBuffer(byteLength, maxByteLength) { for (let ta of tas) { assertEquals((40 - offset) / ta.BYTES_PER_ELEMENT, ta.length); assertEquals(40 - offset, ta.byteLength); + assertEquals(offset, ta.byteOffset); } })(); diff --git a/test/test262/test262.status b/test/test262/test262.status index e41c3869e21b..8f3871c4af6c 100644 --- a/test/test262/test262.status +++ b/test/test262/test262.status @@ -597,8 +597,6 @@ 'built-ins/DataView/prototype/setUint8/resizable-buffer': [FAIL], 'built-ins/TypedArrayConstructors/ctors/typedarray-arg/out-of-bounds-when-species-retrieved-different-type': [FAIL], 'built-ins/TypedArrayConstructors/ctors/typedarray-arg/out-of-bounds-when-species-retrieved-same-type': [FAIL], - 'built-ins/TypedArray/prototype/byteOffset/resizable-array-buffer-auto': [FAIL], - 'built-ins/TypedArray/prototype/byteOffset/resizable-array-buffer-fixed': [FAIL], # https://bugs.chromium.org/p/v8/issues/detail?id=11544 'built-ins/Temporal/Calendar/prototype/fields/long-input': [FAIL], @@ -694,6 +692,9 @@ 'built-ins/TypedArray/prototype/toLocaleString/return-abrupt-from-this-out-of-bounds': [SKIP], 'built-ins/TypedArray/prototype/values/return-abrupt-from-this-out-of-bounds': [FAIL], + # Pending update after https://github.com/tc39/proposal-resizablearraybuffer/issues/68 + 'built-ins/TypedArray/prototype/byteOffset/resizable-array-buffer-auto': [FAIL], + ############################ SKIPPED TESTS ############################# # These tests take a looong time to run.