// Copyright 2022 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Flags: --harmony-rab-gsab --allow-natives-syntax "use strict"; d8.file.execute('test/mjsunit/typedarray-helpers.js'); (function AtomicsWait() { const gsab = CreateGrowableSharedArrayBuffer(16, 32); const i32a = new Int32Array(gsab); const workerScript = function() { onmessage = function(msg) { const i32a = new Int32Array(msg.gsab, msg.offset); const result = Atomics.wait(i32a, 0, 0, 5000); postMessage(result); }; } const worker = new Worker(workerScript, {type: 'function'}); worker.postMessage({gsab: gsab, offset: 0}); // Spin until the worker is waiting on the futex. while (%AtomicsNumWaitersForTesting(i32a, 0) != 1) {} Atomics.notify(i32a, 0, 1); assertEquals("ok", worker.getMessage()); worker.terminate(); })(); (function AtomicsWaitAfterGrowing() { // Test that Atomics.wait works on indices that are valid only after growing. const gsab = CreateGrowableSharedArrayBuffer(4 * 4, 8 * 4); const i32a = new Int32Array(gsab); gsab.grow(6 * 4); const index = 5; const workerScript = function() { onmessage = function(msg) { const i32a = new Int32Array(msg.gsab, msg.offset); const result = Atomics.wait(i32a, 5, 0, 5000); postMessage(result); }; } const worker = new Worker(workerScript, {type: 'function'}); worker.postMessage({gsab: gsab, offset: 0}); // Spin until the worker is waiting on the futex. while (%AtomicsNumWaitersForTesting(i32a, index) != 1) {} Atomics.notify(i32a, index, 1); assertEquals("ok", worker.getMessage()); worker.terminate(); })(); (function AtomicsWaitAsync() { for (let ctor of [Int32Array, BigInt64Array, MyBigInt64Array]) { const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT); const lengthTracking = new ctor(gsab, 0); const initialValue = false; // Can be converted to both Number and BigInt. const result = Atomics.waitAsync(lengthTracking, 0, initialValue); let wokeUp = false; result.value.then( (value) => { assertEquals("ok", value); wokeUp = true; }, () => { assertUnreachable(); }); assertEquals(true, result.async); gsab.grow(6 * ctor.BYTES_PER_ELEMENT); const notifyReturnValue = Atomics.notify(lengthTracking, 0, 1); assertEquals(1, notifyReturnValue); function continuation() { assertTrue(wokeUp); } setTimeout(continuation, 0); } })(); (function AtomicsWaitAsyncAfterGrowing() { for (let ctor of [Int32Array, BigInt64Array, MyBigInt64Array]) { const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT); const lengthTracking = new ctor(gsab, 0); gsab.grow(6 * ctor.BYTES_PER_ELEMENT); const index = 5; const initialValue = false; // Can be converted to both Number and BigInt. const result = Atomics.waitAsync(lengthTracking, index, initialValue); let wokeUp = false; result.value.then( (value) => { assertEquals("ok", value); wokeUp = true; }, () => { assertUnreachable(); }); assertEquals(true, result.async); const notifyReturnValue = Atomics.notify(lengthTracking, index, 1); assertEquals(1, notifyReturnValue); function continuation() { assertTrue(wokeUp); } setTimeout(continuation, 0); } })(); (function AtomicsWaitFailWithWrongArrayTypes() { const gsab = CreateGrowableSharedArrayBuffer(400, 800); const i8a = new Int8Array(gsab); const i16a = new Int16Array(gsab); const ui8a = new Uint8Array(gsab); const ui8ca = new Uint8ClampedArray(gsab); const ui16a = new Uint16Array(gsab); const ui32a = new Uint32Array(gsab); const f32a = new Float32Array(gsab); const f64a = new Float64Array(gsab); const myui8 = new MyUint8Array(gsab); const bui64 = new BigUint64Array(gsab); [i8a, i16a, ui8a, ui8ca, ui16a, ui32a, f32a, f64a, myui8, bui64].forEach( function(ta) { // Can be converted both to Number and BigInt. const exampleValue = false; assertThrows(() => { Atomics.wait(ta, 0, exampleValue); }, TypeError); assertThrows(() => { Atomics.notify(ta, 0, 1); }, TypeError); assertThrows(() => { Atomics.waitAsync(ta, 0, exampleValue); }, TypeError); }); })(); (function TestAtomics() { for (let ctor of intCtors) { const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT); const lengthTracking = new ctor(gsab, 0); TestAtomicsOperations(lengthTracking, 0); AssertAtomicsOperationsThrow(lengthTracking, 4, RangeError); gsab.grow(6 * ctor.BYTES_PER_ELEMENT); TestAtomicsOperations(lengthTracking, 4); } })(); (function AtomicsFailWithNonIntegerArray() { const gsab = CreateGrowableSharedArrayBuffer(400, 800); const ui8ca = new Uint8ClampedArray(gsab); const f32a = new Float32Array(gsab); const f64a = new Float64Array(gsab); const mf32a = new MyFloat32Array(gsab); [ui8ca, f32a, f64a, mf32a].forEach((ta) => { AssertAtomicsOperationsThrow(ta, 0, TypeError); }); })();