Commit bcf85296 authored by Marja Hölttä's avatar Marja Hölttä Committed by V8 LUCI CQ

[rab/gsab] A.p.fill: Support RAB / GSAB

Bug: v8:11111
Change-Id: I2984b3ed6ac6b769f9b4ce758fdf4bfc3b6f6d49
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3714661Reviewed-by: 's avatarShu-yu Guo <syg@chromium.org>
Commit-Queue: Marja Hölttä <marja@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81322}
parent c9419236
......@@ -2804,21 +2804,15 @@ Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value) {
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, to_assign,
BigInt::FromObject(isolate, value),
Nothing<bool>());
// We have to recheck the length. However, it can only change if the
// underlying buffer was detached, so just check that.
if (Handle<JSArrayBufferView>::cast(receiver)->WasDetached()) {
if (Handle<JSTypedArray>::cast(receiver)->IsDetachedOrOutOfBounds()) {
return Just(true);
// TODO(neis): According to the spec, this should throw a TypeError.
}
} else if (!value->IsNumber() && !value->IsUndefined(isolate)) {
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, to_assign,
Object::ToNumber(isolate, value),
Nothing<bool>());
// We have to recheck the length. However, it can only change if the
// underlying buffer was detached, so just check that.
if (Handle<JSArrayBufferView>::cast(receiver)->WasDetached()) {
if (Handle<JSTypedArray>::cast(receiver)->IsDetachedOrOutOfBounds()) {
return Just(true);
// TODO(neis): According to the spec, this should throw a TypeError.
}
}
}
......
......@@ -725,7 +725,7 @@ function TestIterationAndGrow(ta, expected, gsab, grow_after,
}
}());
(function TestFill() {
function TestFill(helper) {
for (let ctor of ctors) {
const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
8 * ctor.BYTES_PER_ELEMENT);
......@@ -736,46 +736,48 @@ function TestIterationAndGrow(ta, expected, gsab, grow_after,
assertEquals([0, 0, 0, 0], ReadDataFromBuffer(gsab, ctor));
FillHelper(fixedLength, 1);
helper(fixedLength, 1);
assertEquals([1, 1, 1, 1], ReadDataFromBuffer(gsab, ctor));
FillHelper(fixedLengthWithOffset, 2);
helper(fixedLengthWithOffset, 2);
assertEquals([1, 1, 2, 2], ReadDataFromBuffer(gsab, ctor));
FillHelper(lengthTracking, 3);
helper(lengthTracking, 3);
assertEquals([3, 3, 3, 3], ReadDataFromBuffer(gsab, ctor));
FillHelper(lengthTrackingWithOffset, 4);
helper(lengthTrackingWithOffset, 4);
assertEquals([3, 3, 4, 4], ReadDataFromBuffer(gsab, ctor));
gsab.grow(6 * ctor.BYTES_PER_ELEMENT);
FillHelper(fixedLength, 13);
helper(fixedLength, 13);
assertEquals([13, 13, 13, 13, 0, 0], ReadDataFromBuffer(gsab, ctor));
FillHelper(fixedLengthWithOffset, 14);
helper(fixedLengthWithOffset, 14);
assertEquals([13, 13, 14, 14, 0, 0], ReadDataFromBuffer(gsab, ctor));
FillHelper(lengthTracking, 15);
helper(lengthTracking, 15);
assertEquals([15, 15, 15, 15, 15, 15], ReadDataFromBuffer(gsab, ctor));
FillHelper(lengthTrackingWithOffset, 16);
helper(lengthTrackingWithOffset, 16);
assertEquals([15, 15, 16, 16, 16, 16], ReadDataFromBuffer(gsab, ctor));
// Filling with non-undefined start & end.
FillHelper(fixedLength, 17, 1, 3);
helper(fixedLength, 17, 1, 3);
assertEquals([15, 17, 17, 16, 16, 16], ReadDataFromBuffer(gsab, ctor));
FillHelper(fixedLengthWithOffset, 18, 1, 2);
helper(fixedLengthWithOffset, 18, 1, 2);
assertEquals([15, 17, 17, 18, 16, 16], ReadDataFromBuffer(gsab, ctor));
FillHelper(lengthTracking, 19, 1, 3);
helper(lengthTracking, 19, 1, 3);
assertEquals([15, 19, 19, 18, 16, 16], ReadDataFromBuffer(gsab, ctor));
FillHelper(lengthTrackingWithOffset, 20, 1, 2);
helper(lengthTrackingWithOffset, 20, 1, 2);
assertEquals([15, 19, 19, 20, 16, 16], ReadDataFromBuffer(gsab, ctor));
}
})();
}
TestFill(FillHelper);
TestFill(ArrayFillHelper);
(function At() {
for (let ctor of ctors) {
......
......@@ -160,6 +160,14 @@ function FillHelper(array, n, start, end) {
}
}
function ArrayFillHelper(array, n, start, end) {
if (array instanceof BigInt64Array || array instanceof BigUint64Array) {
Array.prototype.fill.call(array, BigInt(n), start, end);
} else {
Array.prototype.fill.call(array, n, start, end);
}
}
function IncludesHelper(array, n, fromIndex) {
if (typeof n == 'number' &&
(array instanceof BigInt64Array || array instanceof BigUint64Array)) {
......
......@@ -1142,7 +1142,7 @@ function TestIterationAndResize(ta, expected, rab, resize_after,
}
}());
(function TestFill() {
function TestFill(helper, oobThrows) {
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
8 * ctor.BYTES_PER_ELEMENT);
......@@ -1153,77 +1153,86 @@ function TestIterationAndResize(ta, expected, rab, resize_after,
assertEquals([0, 0, 0, 0], ReadDataFromBuffer(rab, ctor));
FillHelper(fixedLength, 1);
helper(fixedLength, 1);
assertEquals([1, 1, 1, 1], ReadDataFromBuffer(rab, ctor));
FillHelper(fixedLengthWithOffset, 2);
helper(fixedLengthWithOffset, 2);
assertEquals([1, 1, 2, 2], ReadDataFromBuffer(rab, ctor));
FillHelper(lengthTracking, 3);
helper(lengthTracking, 3);
assertEquals([3, 3, 3, 3], ReadDataFromBuffer(rab, ctor));
FillHelper(lengthTrackingWithOffset, 4);
helper(lengthTrackingWithOffset, 4);
assertEquals([3, 3, 4, 4], ReadDataFromBuffer(rab, ctor));
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
assertThrows(() => FillHelper(fixedLength, 5), TypeError);
assertEquals([3, 3, 4], ReadDataFromBuffer(rab, ctor));
assertThrows(() => FillHelper(fixedLengthWithOffset, 6), TypeError);
if (oobThrows) {
assertThrows(() => helper(fixedLength, 5), TypeError);
assertThrows(() => helper(fixedLengthWithOffset, 6), TypeError);
} else {
helper(fixedLength, 5);
helper(fixedLengthWithOffset, 6);
// We'll check below that these were no-op.
}
assertEquals([3, 3, 4], ReadDataFromBuffer(rab, ctor));
FillHelper(lengthTracking, 7);
helper(lengthTracking, 7);
assertEquals([7, 7, 7], ReadDataFromBuffer(rab, ctor));
FillHelper(lengthTrackingWithOffset, 8);
helper(lengthTrackingWithOffset, 8);
assertEquals([7, 7, 8], ReadDataFromBuffer(rab, ctor));
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
assertThrows(() => FillHelper(fixedLength, 9), TypeError);
assertEquals([7], ReadDataFromBuffer(rab, ctor));
assertThrows(() => FillHelper(fixedLengthWithOffset, 10), TypeError);
if (oobThrows) {
assertThrows(() => helper(fixedLength, 9), TypeError);
assertThrows(() => helper(fixedLengthWithOffset, 10), TypeError);
assertThrows(() => helper(lengthTrackingWithOffset, 11), TypeError);
} else {
// We'll check below that these were no-op.
helper(fixedLength, 9);
helper(fixedLengthWithOffset, 10);
helper(lengthTrackingWithOffset, 11);
}
assertEquals([7], ReadDataFromBuffer(rab, ctor));
FillHelper(lengthTracking, 11);
assertEquals([11], ReadDataFromBuffer(rab, ctor));
assertThrows(() => FillHelper(lengthTrackingWithOffset, 12), TypeError);
assertEquals([11], ReadDataFromBuffer(rab, ctor));
helper(lengthTracking, 12);
assertEquals([12], ReadDataFromBuffer(rab, ctor));
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
FillHelper(fixedLength, 13);
helper(fixedLength, 13);
assertEquals([13, 13, 13, 13, 0, 0], ReadDataFromBuffer(rab, ctor));
FillHelper(fixedLengthWithOffset, 14);
helper(fixedLengthWithOffset, 14);
assertEquals([13, 13, 14, 14, 0, 0], ReadDataFromBuffer(rab, ctor));
FillHelper(lengthTracking, 15);
helper(lengthTracking, 15);
assertEquals([15, 15, 15, 15, 15, 15], ReadDataFromBuffer(rab, ctor));
FillHelper(lengthTrackingWithOffset, 16);
helper(lengthTrackingWithOffset, 16);
assertEquals([15, 15, 16, 16, 16, 16], ReadDataFromBuffer(rab, ctor));
// Filling with non-undefined start & end.
FillHelper(fixedLength, 17, 1, 3);
helper(fixedLength, 17, 1, 3);
assertEquals([15, 17, 17, 16, 16, 16], ReadDataFromBuffer(rab, ctor));
FillHelper(fixedLengthWithOffset, 18, 1, 2);
helper(fixedLengthWithOffset, 18, 1, 2);
assertEquals([15, 17, 17, 18, 16, 16], ReadDataFromBuffer(rab, ctor));
FillHelper(lengthTracking, 19, 1, 3);
helper(lengthTracking, 19, 1, 3);
assertEquals([15, 19, 19, 18, 16, 16], ReadDataFromBuffer(rab, ctor));
FillHelper(lengthTrackingWithOffset, 20, 1, 2);
helper(lengthTrackingWithOffset, 20, 1, 2);
assertEquals([15, 19, 19, 20, 16, 16], ReadDataFromBuffer(rab, ctor));
}
})();
}
TestFill(FillHelper, true);
TestFill(ArrayFillHelper, false);
(function FillParameterConversionResizes() {
for (let ctor of ctors) {
......@@ -1231,15 +1240,69 @@ function TestIterationAndResize(ta, expected, rab, resize_after,
8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
let evil = { valueOf: () => { rab.resize(2); return 0;}};
const evil = { valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT); return 3;
}};
assertThrows(() => { FillHelper(fixedLength, evil, 1, 2); }, TypeError);
rab.resize(4 * ctor.BYTES_PER_ELEMENT);
}
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const evil = { valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT); return 1;
}};
assertThrows(() => { FillHelper(fixedLength, 3, evil, 2); }, TypeError);
rab.resize(4 * ctor.BYTES_PER_ELEMENT);
}
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const evil = { valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT); return 2;
}};
assertThrows(() => { FillHelper(fixedLength, 3, 1, evil); }, TypeError);
}
})();
(function ArrayFillParameterConversionResizes() {
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const evil = { valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT); return 3;
}};
ArrayFillHelper(fixedLength, evil, 1, 2);
assertEquals([0, 0], ReadDataFromBuffer(rab, ctor));
}
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const evil = { valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT); return 1;
}};
ArrayFillHelper(fixedLength, 3, evil, 2);
assertEquals([0, 0], ReadDataFromBuffer(rab, ctor));
}
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 4);
const evil = { valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT); return 2;
}};
ArrayFillHelper(fixedLength, 3, 1, evil);
assertEquals([0, 0], ReadDataFromBuffer(rab, ctor));
}
})();
(function At() {
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
......
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