diff options
Diffstat (limited to 'js/src/tests/test262/built-ins/Atomics/notify')
51 files changed, 2579 insertions, 0 deletions
diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bad-range.js b/js/src/tests/test262/built-ins/Atomics/notify/bad-range.js new file mode 100644 index 0000000000..cd149aea83 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bad-range.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test range checking of Atomics.notify on arrays that allow atomic operations +info: | + Atomics.notify( typedArray, index, count ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + .. + +includes: [testAtomics.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.notify(i32a, IdxGen(i32a), 0); + }, '`Atomics.notify(i32a, IdxGen(i32a), 0)` throws RangeError'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/bad-range.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/bad-range.js new file mode 100644 index 0000000000..7479c2fb00 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/bad-range.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test range checking of Atomics.notify on arrays that allow atomic operations +info: | + Atomics.notify( typedArray, index, count ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + .. + +includes: [testAtomics.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 8) +); + +testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.notify(i64a, IdxGen(i64a), 0); + }, '`Atomics.notify(i64a, IdxGen(i64a), 0)` throws RangeError'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/browser.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-bigint64-typedarray-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-bigint64-typedarray-throws.js new file mode 100644 index 0000000000..94fc29e40d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-bigint64-typedarray-throws.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Throws a TypeError if typedArray arg is not an BigInt64Array +info: | + Atomics.notify( typedArray, index, count ) + + 1.Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + 5.If onlyInt32 is true, then + If typeName is not "BigInt64Array", throw a TypeError exception. +features: [Atomics, BigInt, TypedArray] +---*/ + +const i64a = new BigUint64Array( + new SharedArrayBuffer(BigUint64Array.BYTES_PER_ELEMENT * 8) +); + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + Atomics.wait(i64a, 0, 0); +}, '`Atomics.wait(i64a, 0, 0)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.wait(i64a, poisoned, poisoned); +}, '`Atomics.wait(i64a, poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-count-evaluation-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-count-evaluation-throws.js new file mode 100644 index 0000000000..5c5781f429 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-count-evaluation-throws.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + Evaluates index before returning 0, when TA.buffer is not a SharedArrayBuffer +info: | + Atomics.notify( typedArray, index, count ) + + Let buffer be ? ValidateIntegerTypedArray(typedArray, true). + ... + Else, + Let intCount be ? ToInteger(count). + Let c be max(intCount, 0). + ... + If IsSharedArrayBuffer(buffer) is false, return 0. + +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ + +const i64a = new BigInt64Array( + new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 8) +); + +const poisoned = { + valueOf() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, function() { + Atomics.notify(i64a, poisoned, 0); +}, '`Atomics.notify(i64a, poisoned, 0)` throws Test262Error'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-index-evaluation-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-index-evaluation-throws.js new file mode 100644 index 0000000000..c345fa7265 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-index-evaluation-throws.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + Evaluates index before returning 0, when TA.buffer is not a SharedArrayBuffer +info: | + Atomics.notify( typedArray, index, count ) + + Let buffer be ? ValidateIntegerTypedArray(typedArray, true). + Let i be ? ValidateAtomicAccess(typedArray, index). + ... + If IsSharedArrayBuffer(buffer) is false, return 0. + +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ + +const i64a = new BigInt64Array( + new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 8) +); + +const poisoned = { + valueOf() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, function() { + Atomics.notify(i64a, 0, poisoned); +}, '`Atomics.notify(i64a, 0, poisoned)` throws Test262Error'); + + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-non-shared-int-views-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-non-shared-int-views-throws.js new file mode 100644 index 0000000000..274bb87374 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-non-shared-int-views-throws.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Atomics.notify throws on non-shared integer TypedArrays +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ + +const nonsab = new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 8); + +const poisoned = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + Atomics.notify(new BigUint64Array(nonsab), poisoned, poisoned); +}, '`Atomics.notify(new BigUint64Array(nonsab), poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-returns-0.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-returns-0.js new file mode 100644 index 0000000000..2662027e8b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-returns-0.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + Returns 0, when TA.buffer is not a SharedArrayBuffer +info: | + Atomics.notify( typedArray, index, count ) + + Let buffer be ? ValidateIntegerTypedArray(typedArray, true). + ... + If IsSharedArrayBuffer(buffer) is false, return 0. + +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ +const i64a = new BigInt64Array( + new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 8) +); + +assert.sameValue(Atomics.notify(i64a, 0, 0), 0, 'Atomics.notify(i64a, 0, 0) returns 0'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/notify-all-on-loc.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/notify-all-on-loc.js new file mode 100644 index 0000000000..18ea073bfc --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/notify-all-on-loc.js @@ -0,0 +1,92 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies all waiters on a location, but does not + notify waiters on other locations. +includes: [atomicsHelper.js] +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +const WAIT_INDEX = 0; // Waiters on this will be woken +const WAIT_FAKE = 1; // Waiters on this will not be woken +const RUNNING = 2; // Accounting of live agents +const NOTIFY_INDEX = 3; // Accounting for too early timeouts +const NUMAGENT = 3; +const TIMEOUT_AGENT_MESSAGES = 2; // Number of messages for the timeout agent +const BUFFER_SIZE = 4; + +// Long timeout to ensure the agent doesn't timeout before the main agent calls +// `Atomics.notify`. +const TIMEOUT = $262.agent.timeouts.long; + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +for (var i = 0; i < NUMAGENT; i++) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + $262.agent.report("A " + Atomics.wait(i64a, ${WAIT_INDEX}, 0n)); + $262.agent.leaving(); + }); + `); +} + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + // This will always time out. + $262.agent.report("B " + Atomics.wait(i64a, ${WAIT_FAKE}, 0n, ${TIMEOUT})); + + // If this value is not 1n, then the agent timeout before the main agent + // called Atomics.notify. + const result = Atomics.load(i64a, ${NOTIFY_INDEX}) === 1n + ? "timeout after Atomics.notify" + : "timeout before Atomics.notify"; + $262.agent.report("W " + result); + + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i64a); + +// Wait for agents to be running. +$262.agent.waitUntil(i64a, RUNNING, BigInt(NUMAGENT + 1)); + +// Try to yield control to ensure the agent actually started to wait. If we +// don't, we risk sending the notification before agents are sleeping, and we hang. +$262.agent.tryYield(); + +// Notify all waiting on WAIT_INDEX, should be 3 always, they won't time out. +assert.sameValue( + Atomics.notify(i64a, WAIT_INDEX), + NUMAGENT, + 'Atomics.notify(i64a, WAIT_INDEX) returns the value of `NUMAGENT`' +); + +Atomics.store(i64a, NOTIFY_INDEX, 1n); + +const reports = []; +for (var i = 0; i < NUMAGENT + TIMEOUT_AGENT_MESSAGES; i++) { + reports.push($262.agent.getReport()); +} +reports.sort(); + +for (var i = 0; i < NUMAGENT; i++) { + assert.sameValue(reports[i], 'A ok', 'The value of reports[i] is "A ok"'); +} +assert.sameValue(reports[NUMAGENT], 'B timed-out', 'The value of reports[NUMAGENT] is "B timed-out"'); +assert.sameValue(reports[NUMAGENT + 1], "W timeout after Atomics.notify", + 'The value of reports[NUMAGENT + 1] is "W timeout after Atomics.notify"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/null-bufferdata-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/null-bufferdata-throws.js new file mode 100644 index 0000000000..99bfc3cff9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/null-bufferdata-throws.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + A null value for bufferData throws a TypeError +info: | + Atomics.notify( typedArray, index, count ) + + 1.Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + 9.If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception. + ... + 3.If bufferData is null, return false. +includes: [detachArrayBuffer.js] +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ + +const i64a = new BigInt64Array( + new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 8) +); +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +try { + $DETACHBUFFER(i64a.buffer); // Detaching a non-shared ArrayBuffer sets the [[ArrayBufferData]] value to null +} catch (error) { + throw new Test262Error(`An unexpected error occurred when detaching ArrayBuffer: ${error.message}`); +} + +assert.throws(TypeError, function() { + Atomics.notify(i64a, poisoned, poisoned); +}, '`Atomics.notify(i64a, poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/shell.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/shell.js diff --git a/js/src/tests/test262/built-ins/Atomics/notify/browser.js b/js/src/tests/test262/built-ins/Atomics/notify/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/notify/count-boundary-cases.js b/js/src/tests/test262/built-ins/Atomics/notify/count-boundary-cases.js new file mode 100644 index 0000000000..c9975fe467 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/count-boundary-cases.js @@ -0,0 +1,64 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Allowed boundary cases for 'count' argument to Atomics.notify +info: | + Atomics.notify( typedArray, index, count ) + + ... + 3. If count is undefined, let c be +∞. + 4. Else, + a. Let intCount be ? ToInteger(count). + ... + + ToInteger ( argument ) + + 1. Let number be ? ToNumber(argument). + 2. If number is NaN, return +0. + 3. If number is +0, -0, +∞, or -∞, return number. + 4. Return the number value that is the same sign as number + and whose magnitude is floor(abs(number)). + +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +assert.sameValue( + Atomics.notify(i32a, 0, -3), + 0, + 'Atomics.notify(i32a, 0, -3) returns 0' +); +assert.sameValue( + Atomics.notify(i32a, 0, Number.POSITIVE_INFINITY), + 0, + 'Atomics.notify(i32a, 0, Number.POSITIVE_INFINITY) returns 0' +); +assert.sameValue( + Atomics.notify(i32a, 0, undefined), + 0, + 'Atomics.notify(i32a, 0, undefined) returns 0' +); +assert.sameValue( + Atomics.notify(i32a, 0, '33'), + 0, + 'Atomics.notify(i32a, 0, \'33\') returns 0' +); +assert.sameValue( + Atomics.notify(i32a, 0, { valueOf: 8 }), + 0, + 'Atomics.notify(i32a, 0, {valueOf: 8}) returns 0' +); +assert.sameValue( + Atomics.notify(i32a, 0), + 0, + 'Atomics.notify(i32a, 0) returns 0' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/count-defaults-to-infinity-missing.js b/js/src/tests/test262/built-ins/Atomics/notify/count-defaults-to-infinity-missing.js new file mode 100644 index 0000000000..e798141f30 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/count-defaults-to-infinity-missing.js @@ -0,0 +1,69 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Default to +Infinity when missing 'count' argument to Atomics.notify +info: | + Atomics.notify( typedArray, index, count ) + + ... + 3. If count is undefined, let c be +∞. + ... + +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 0; // Index to notify agent has started. +const WAIT_INDEX = 1; // Index all agents are waiting on. +const BUFFER_SIZE = 2; + +const NUMAGENT = 4; // Total number of agents started + +for (var i = 0; i < NUMAGENT; i++) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // Wait until restarted by main thread. + var status = Atomics.wait(i32a, ${WAIT_INDEX}, 0); + + // Report wait status and then exit the agent. + var name = String.fromCharCode(0x41 + ${i}); // "A", "B", "C", or "D" + $262.agent.report(name + " " + status); + $262.agent.leaving(); + }); + `); +} + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +// An agent may have been interrupted between reporting its initial report +// and the `Atomics.wait` call. Try to yield control to ensure the agent +// actually started to wait. +$262.agent.tryYield(); + +assert.sameValue(Atomics.notify(i32a, WAIT_INDEX /*, count missing */), NUMAGENT, + 'Atomics.notify(i32a, WAIT_INDEX /*, count missing */) returns the value of `NUMAGENT`'); + +const reports = []; +for (var i = 0; i < NUMAGENT; i++) { + reports.push($262.agent.getReport()); +} +reports.sort(); + +assert.sameValue(reports[0], 'A ok', 'The value of reports[0] is "A ok"'); +assert.sameValue(reports[1], 'B ok', 'The value of reports[1] is "B ok"'); +assert.sameValue(reports[2], 'C ok', 'The value of reports[2] is "C ok"'); +assert.sameValue(reports[3], 'D ok', 'The value of reports[3] is "D ok"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/count-defaults-to-infinity-undefined.js b/js/src/tests/test262/built-ins/Atomics/notify/count-defaults-to-infinity-undefined.js new file mode 100644 index 0000000000..c51af98018 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/count-defaults-to-infinity-undefined.js @@ -0,0 +1,67 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Undefined count arg should result in an infinite count +info: | + Atomics.notify( typedArray, index, count ) + + 3.If count is undefined, let c be +∞. + +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 0; // Index to notify agent has started. +const WAIT_INDEX = 1; // Index all agents are waiting on. +const BUFFER_SIZE = 2; + +const NUMAGENT = 4; // Total number of agents started + +for (var i = 0; i < NUMAGENT; i++) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // Wait until restarted by main thread. + var status = Atomics.wait(i32a, ${WAIT_INDEX}, 0); + + // Report wait status and then exit the agent. + var name = String.fromCharCode(0x41 + ${i}); // "A", "B", "C", or "D" + $262.agent.report(name + " " + status); + $262.agent.leaving(); + }); + `); +} + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +// An agent may have been interrupted between reporting its initial report +// and the `Atomics.wait` call. Try to yield control to ensure the agent +// actually started to wait. +$262.agent.tryYield(); + +assert.sameValue(Atomics.notify(i32a, WAIT_INDEX, undefined), NUMAGENT, + 'Atomics.notify(i32a, WAIT_INDEX, undefined) returns the value of `NUMAGENT`'); + +const reports = []; +for (var i = 0; i < NUMAGENT; i++) { + reports.push($262.agent.getReport()); +} +reports.sort(); + +assert.sameValue(reports[0], 'A ok', 'The value of reports[0] is "A ok"'); +assert.sameValue(reports[1], 'B ok', 'The value of reports[1] is "B ok"'); +assert.sameValue(reports[2], 'C ok', 'The value of reports[2] is "C ok"'); +assert.sameValue(reports[3], 'D ok', 'The value of reports[3] is "D ok"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/count-from-nans.js b/js/src/tests/test262/built-ins/Atomics/notify/count-from-nans.js new file mode 100644 index 0000000000..a8361fd5ed --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/count-from-nans.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + NaNs are converted to 0 for 'count' argument to Atomics.notify +info: | + Atomics.notify( typedArray, index, count ) + + ... + 3. If count is undefined, let c be +∞. + 4. Else, + a. Let intCount be ? ToInteger(count). + ... + + ToInteger ( argument ) + + ... + 2. If number is NaN, return +0. + ... + +includes: [nans.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +NaNs.forEach(nan => { + assert.sameValue(Atomics.notify(i32a, 0, nan), 0, 'Atomics.notify(i32a, 0, nan) returns 0'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/count-symbol-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/count-symbol-throws.js new file mode 100644 index 0000000000..d791756ef8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/count-symbol-throws.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Return abrupt when symbol passed for 'count' argument to Atomics.notify +info: | + Atomics.notify( typedArray, index, count ) + + ... + 3. If count is undefined, let c be +∞. + 4. Else, + a. Let intCount be ? ToInteger(count). + ... + +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +assert.throws(TypeError, function() { + Atomics.notify(i32a, 0, Symbol()); +}, '`Atomics.notify(i32a, 0, Symbol())` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/count-tointeger-throws-then-wake-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/count-tointeger-throws-then-wake-throws.js new file mode 100644 index 0000000000..184c2006d5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/count-tointeger-throws-then-wake-throws.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Return abrupt when ToInteger throws an exception on 'count' argument to Atomics.notify +info: | + Atomics.notify( typedArray, index, count ) + + ... + 3. If count is undefined, let c be +∞. + 4. Else, + a. Let intCount be ? ToInteger(count). + ... + +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(Test262Error, function() { + Atomics.notify(i32a, 0, poisoned); +}, '`Atomics.notify(i32a, 0, poisoned)` throws Test262Error'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/descriptor.js b/js/src/tests/test262/built-ins/Atomics/notify/descriptor.js new file mode 100644 index 0000000000..d293ca94c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/descriptor.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: Testing descriptor property of Atomics.notify +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics, 'notify', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/length.js b/js/src/tests/test262/built-ins/Atomics/notify/length.js new file mode 100644 index 0000000000..24a3571af5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/length.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Atomics.notify.length is 3. +info: | + Atomics.notify ( ia, index, count ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this + value is equal to the largest number of named arguments shown in the + subclause headings for the function description, including optional + parameters. However, rest parameters shown using the form “...name” + are not included in the default argument count. + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.notify, 'length', { + value: 3, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/name.js b/js/src/tests/test262/built-ins/Atomics/notify/name.js new file mode 100644 index 0000000000..438e54a04d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/name.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Atomics.notify.name is "notify". +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.notify, 'name', { + value: 'notify', + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/negative-count.js b/js/src/tests/test262/built-ins/Atomics/notify/negative-count.js new file mode 100644 index 0000000000..7ed96b1d7f --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/negative-count.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies zero waiters if the count is negative +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.long; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + $262.agent.report(Atomics.wait(i32a, 0, 0, ${TIMEOUT})); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue(Atomics.notify(i32a, 0, -1), 0, 'Atomics.notify(i32a, 0, -1) returns 0'); // Don't actually notify it + +assert.sameValue($262.agent.getReport(), 'timed-out', '$262.agent.getReport() returns "timed-out"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/negative-index-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/negative-index-throws.js new file mode 100644 index 0000000000..a6dc837540 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/negative-index-throws.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Throws a RangeError is index < 0 +info: | + Atomics.notify( typedArray, index, count ) + + 2.Let i be ? ValidateAtomicAccess(typedArray, index). + ... + 2.Let accessIndex be ? ToIndex(requestIndex). + ... + 2.b If integerIndex < 0, throw a RangeError exception +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(RangeError, function() { + Atomics.notify(i32a, -Infinity, poisoned); +}, '`Atomics.notify(i32a, -Infinity, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.notify(i32a, -7.999, poisoned); +}, '`Atomics.notify(i32a, -7.999, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.notify(i32a, -1, poisoned); +}, '`Atomics.notify(i32a, -1, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.notify(i32a, -300, poisoned); +}, '`Atomics.notify(i32a, -300, poisoned)` throws RangeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/non-int32-typedarray-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/non-int32-typedarray-throws.js new file mode 100644 index 0000000000..92d537192a --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/non-int32-typedarray-throws.js @@ -0,0 +1,81 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Throws a TypeError if typedArray arg is not an Int32Array +info: | + Atomics.notify( typedArray, index, count ) + + 1.Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + 5.If onlyInt32 is true, then + If typeName is not "Int32Array", throw a TypeError exception. +features: [Atomics, Float32Array, Float64Array, Int8Array, TypedArray, Uint16Array, Uint8Array, Uint8ClampedArray] +---*/ + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + const view = new Float64Array( + new SharedArrayBuffer(Float64Array.BYTES_PER_ELEMENT * 8) + ); + Atomics.notify(view, poisoned, poisoned); +}, '`const view = new Float64Array( new SharedArrayBuffer(Float64Array.BYTES_PER_ELEMENT * 8) ); Atomics.notify(view, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Float32Array( + new SharedArrayBuffer(Float32Array.BYTES_PER_ELEMENT * 4) + ); + Atomics.notify(view, poisoned, poisoned); +}, '`const view = new Float32Array( new SharedArrayBuffer(Float32Array.BYTES_PER_ELEMENT * 4) ); Atomics.notify(view, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Int16Array( + new SharedArrayBuffer(Int16Array.BYTES_PER_ELEMENT * 2) + ); + Atomics.notify(view, poisoned, poisoned); +}, '`const view = new Int16Array( new SharedArrayBuffer(Int16Array.BYTES_PER_ELEMENT * 2) ); Atomics.notify(view, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Int8Array( + new SharedArrayBuffer(Int8Array.BYTES_PER_ELEMENT) + ); + Atomics.notify(view, poisoned, poisoned); +}, '`const view = new Int8Array( new SharedArrayBuffer(Int8Array.BYTES_PER_ELEMENT) ); Atomics.notify(view, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Uint32Array( + new SharedArrayBuffer(Uint32Array.BYTES_PER_ELEMENT * 4) + ); + Atomics.notify(new Uint32Array(), poisoned, poisoned); +}, '`const view = new Uint32Array( new SharedArrayBuffer(Uint32Array.BYTES_PER_ELEMENT * 4) ); Atomics.notify(new Uint32Array(), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Uint16Array( + new SharedArrayBuffer(Uint16Array.BYTES_PER_ELEMENT * 2) + ); + Atomics.notify(view, poisoned, poisoned); +}, '`const view = new Uint16Array( new SharedArrayBuffer(Uint16Array.BYTES_PER_ELEMENT * 2) ); Atomics.notify(view, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Uint8Array( + new SharedArrayBuffer(Uint8Array.BYTES_PER_ELEMENT) + ); + Atomics.notify(view, poisoned, poisoned); +}, '`const view = new Uint8Array( new SharedArrayBuffer(Uint8Array.BYTES_PER_ELEMENT) ); Atomics.notify(view, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Uint8ClampedArray( + new SharedArrayBuffer(Uint8ClampedArray.BYTES_PER_ELEMENT) + ); + Atomics.notify(view, poisoned, poisoned); +}, '`const view = new Uint8ClampedArray( new SharedArrayBuffer(Uint8ClampedArray.BYTES_PER_ELEMENT) ); Atomics.notify(view, poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-count-evaluation-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-count-evaluation-throws.js new file mode 100644 index 0000000000..c745669449 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-count-evaluation-throws.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + Evaluates count before returning 0, when TA.buffer is not a SharedArrayBuffer +info: | + Atomics.notify( typedArray, index, count ) + + Let buffer be ? ValidateIntegerTypedArray(typedArray, true). + ... + Else, + Let intCount be ? ToInteger(count). + Let c be max(intCount, 0). + ... + If IsSharedArrayBuffer(buffer) is false, return 0. + + +features: [ArrayBuffer, Atomics, TypedArray] +---*/ + +const i32a = new Int32Array( + new ArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, function() { + Atomics.notify(i32a, 0, poisoned); +}, '`Atomics.notify(i32a, 0, poisoned)` throws Test262Error'); + + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-index-evaluation-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-index-evaluation-throws.js new file mode 100644 index 0000000000..d2cda0718b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-index-evaluation-throws.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + Evaluates index before returning 0, when TA.buffer is not a SharedArrayBuffer +info: | + Atomics.notify( typedArray, index, count ) + + Let buffer be ? ValidateIntegerTypedArray(typedArray, true). + Let i be ? ValidateAtomicAccess(typedArray, index). + ... + If IsSharedArrayBuffer(buffer) is false, return 0. + +features: [ArrayBuffer, Atomics, TypedArray] +---*/ + +const i32a = new Int32Array( + new ArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, function() { + Atomics.notify(i32a, poisoned, 0); +}, '`Atomics.notify(i32a, poisoned, 0)` throws Test262Error'); + + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-non-shared-int-views-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-non-shared-int-views-throws.js new file mode 100644 index 0000000000..9f9ebd1bb8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-non-shared-int-views-throws.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Atomics.notify throws on non-shared integer TypedArrays +features: [ArrayBuffer, Atomics, TypedArray] +---*/ + +const nonsab = new ArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4); + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + Atomics.notify(new Int16Array(nonsab), poisoned, poisoned); +}, '`Atomics.notify(new Int16Array(nonsab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Int8Array(nonsab), poisoned, poisoned); +}, '`Atomics.notify(new Int8Array(nonsab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Uint32Array(nonsab), poisoned, poisoned); +}, '`Atomics.notify(new Uint32Array(nonsab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Uint16Array(nonsab), poisoned, poisoned); +}, '`Atomics.notify(new Uint16Array(nonsab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Uint8Array(nonsab), poisoned, poisoned); +}, '`Atomics.notify(new Uint8Array(nonsab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Uint8ClampedArray(nonsab), poisoned, poisoned); +}, '`Atomics.notify(new Uint8ClampedArray(nonsab), poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-returns-0.js b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-returns-0.js new file mode 100644 index 0000000000..5578c67b0c --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-returns-0.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + Returns 0, when TA.buffer is not a SharedArrayBuffer +info: | + Atomics.notify( typedArray, index, count ) + + Let buffer be ? ValidateIntegerTypedArray(typedArray, true). + ... + If IsSharedArrayBuffer(buffer) is false, return 0. + +features: [ArrayBuffer, Atomics, TypedArray] +---*/ + +const i32a = new Int32Array( + new ArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +assert.sameValue(Atomics.notify(i32a, 0, 0), 0, 'Atomics.notify(i32a, 0, 0) returns 0'); +assert.sameValue(Atomics.notify(i32a, 0, 1), 0, 'Atomics.notify(i32a, 0, 1) returns 0'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/non-shared-int-views.js b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-int-views.js new file mode 100644 index 0000000000..d04f970f4b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-int-views.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test Atomics.notify on non-shared integer TypedArrays +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const sab = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4); + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + Atomics.notify(new Int16Array(sab), poisoned, poisoned); +}, '`Atomics.notify(new Int16Array(sab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Int8Array(sab), poisoned, poisoned); +}, '`Atomics.notify(new Int8Array(sab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Uint32Array(sab), poisoned, poisoned); +}, '`Atomics.notify(new Uint32Array(sab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Uint16Array(sab), poisoned, poisoned); +}, '`Atomics.notify(new Uint16Array(sab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Uint8Array(sab), poisoned, poisoned); +}, '`Atomics.notify(new Uint8Array(sab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Uint8ClampedArray(sab), poisoned, poisoned); +}, '`Atomics.notify(new Uint8ClampedArray(sab), poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/non-views.js b/js/src/tests/test262/built-ins/Atomics/notify/non-views.js new file mode 100644 index 0000000000..ef42622ab8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/non-views.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test Atomics.notify on view values other than TypedArrays +includes: [testAtomics.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +testWithAtomicsNonViewValues(function(nonView) { + assert.throws(TypeError, function() { + Atomics.notify(nonView, 0, 0); + }, '`Atomics.notify(nonView, 0, 0)` throws TypeError'); // Even with count == 0 +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/not-a-constructor.js b/js/src/tests/test262/built-ins/Atomics/notify/not-a-constructor.js new file mode 100644 index 0000000000..b2b75dcd28 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/not-a-constructor.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Atomics.notify does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, Atomics, arrow-function, TypedArray, SharedArrayBuffer] +---*/ + +assert.sameValue(isConstructor(Atomics.notify), false, 'isConstructor(Atomics.notify) must return false'); + +assert.throws(TypeError, () => { + new Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT))); +}, '`new Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT)))` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/not-a-typedarray-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/not-a-typedarray-throws.js new file mode 100644 index 0000000000..5f9b7e2b08 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/not-a-typedarray-throws.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + Throws a TypeError if the typedArray arg is not a TypedArray object +info: | + Atomics.notify( typedArray, index, count ) + + 1.Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + 3.If typedArray does not have a [[TypedArrayName]] internal slot, throw a TypeError exception. + +features: [Atomics] +---*/ + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + Atomics.wait({}, 0, 0, 0); +}, '`Atomics.wait({}, 0, 0, 0)` throws TypeError'); + +assert.throws(TypeError, function () { + Atomics.wait({}, poisoned, poisoned, poisoned); +}, '`Atomics.wait({}, poisoned, poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/not-an-object-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/not-an-object-throws.js new file mode 100644 index 0000000000..c8ca4b2a7f --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/not-an-object-throws.js @@ -0,0 +1,51 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + Throws a TypeError if typedArray arg is not an Object +info: | + Atomics.notify( typedArray, index, count ) + + 1.Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + 2. if Type(typedArray) is not Object, throw a TypeError exception +features: [Atomics, Symbol] +---*/ + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + Atomics.notify(null, poisoned, poisoned); +}, '`Atomics.notify(null, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(undefined, poisoned, poisoned); +}, '`Atomics.notify(undefined, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(true, poisoned, poisoned); +}, '`Atomics.notify(true, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(false, poisoned, poisoned); +}, '`Atomics.notify(false, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify('***string***', poisoned, poisoned); +}, '`Atomics.notify(\'***string***\', poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(Number.NEGATIVE_INFINITY, poisoned, poisoned); +}, '`Atomics.notify(Number.NEGATIVE_INFINITY, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(Symbol('***symbol***'), poisoned, poisoned); +}, '`Atomics.notify(Symbol(\'***symbol***\'), poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-all-on-loc.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-all-on-loc.js new file mode 100644 index 0000000000..dbc902b6a1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-all-on-loc.js @@ -0,0 +1,92 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies all waiters on a location, but does not + notify waiters on other locations. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const WAIT_INDEX = 0; // Waiters on this will be woken +const WAIT_FAKE = 1; // Waiters on this will not be woken +const RUNNING = 2; // Accounting of live agents +const NOTIFY_INDEX = 3; // Accounting for too early timeouts +const NUMAGENT = 3; +const TIMEOUT_AGENT_MESSAGES = 2; // Number of messages for the timeout agent +const BUFFER_SIZE = 4; + +// Long timeout to ensure the agent doesn't timeout before the main agent calls +// `Atomics.notify`. +const TIMEOUT = $262.agent.timeouts.long; + +for (var i = 0; i < NUMAGENT; i++) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + $262.agent.report("A " + Atomics.wait(i32a, ${WAIT_INDEX}, 0)); + $262.agent.leaving(); + }); + `); +} + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // This will always time out. + $262.agent.report("B " + Atomics.wait(i32a, ${WAIT_FAKE}, 0, ${TIMEOUT})); + + // If this value is not 1, then the agent timeout before the main agent + // called Atomics.notify. + const result = Atomics.load(i32a, ${NOTIFY_INDEX}) === 1 + ? "timeout after Atomics.notify" + : "timeout before Atomics.notify"; + $262.agent.report("W " + result); + + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +$262.agent.safeBroadcast(i32a); + +// Wait for agents to be running. +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT + 1); + +// Try to yield control to ensure the agent actually started to wait. If we +// don't, we risk sending the notification before agents are sleeping, and we hang. +$262.agent.tryYield(); + +// Notify all waiting on WAIT_INDEX, should be 3 always, they won't time out. +assert.sameValue( + Atomics.notify(i32a, WAIT_INDEX), + NUMAGENT, + 'Atomics.notify(i32a, WAIT_INDEX) returns the value of `NUMAGENT`' +); + +Atomics.store(i32a, NOTIFY_INDEX, 1); + +const reports = []; +for (var i = 0; i < NUMAGENT + TIMEOUT_AGENT_MESSAGES; i++) { + reports.push($262.agent.getReport()); +} +reports.sort(); + +for (var i = 0; i < NUMAGENT; i++) { + assert.sameValue(reports[i], "A ok", 'The value of reports[i] is "A ok"'); +} +assert.sameValue(reports[NUMAGENT], "B timed-out", 'The value of reports[NUMAGENT] is "B timed-out"'); +assert.sameValue(reports[NUMAGENT + 1], "W timeout after Atomics.notify", + 'The value of reports[NUMAGENT + 1] is "W timeout after Atomics.notify"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-all.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-all.js new file mode 100644 index 0000000000..9f283156ff --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-all.js @@ -0,0 +1,54 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies all waiters if that's what the count is. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const WAIT_INDEX = 0; // Waiters on this will be woken +const RUNNING = 1; // Accounting of live agents +const NUMAGENT = 3; +const BUFFER_SIZE = 4; + +for (var i = 0; i < NUMAGENT; i++) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + $262.agent.report("A " + Atomics.wait(i32a, ${WAIT_INDEX}, 0)); + $262.agent.leaving(); + }); + `); +} + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +$262.agent.safeBroadcast(i32a); + +// Wait for agents to be running. +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +// Try to yield control to ensure the agent actually started to wait. If we +// don't, we risk sending the notification before agents are sleeping, and we hang. +$262.agent.tryYield(); + +// Notify all waiting on WAIT_INDEX, should be 3 always, they won't time out. +assert.sameValue( + Atomics.notify(i32a, WAIT_INDEX), + NUMAGENT, + 'Atomics.notify(i32a, WAIT_INDEX) returns the value of `NUMAGENT`' +); + +for (var i = 0; i < NUMAGENT; i++) { + assert.sameValue($262.agent.getReport(), 'A ok', 'The value of reports[i] is "A ok"'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-in-order-one-time.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-in-order-one-time.js new file mode 100644 index 0000000000..b4abca79d3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-in-order-one-time.js @@ -0,0 +1,82 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies agents in the order they are waiting. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const NUMAGENT = 3; +const WAIT_INDEX = 0; // Waiters on this will be woken +const SPIN = 1; // Worker i (zero-based) spins on location SPIN+i +const RUNNING = SPIN + NUMAGENT; // Accounting of live agents +const BUFFER_SIZE = RUNNING + 1; + +// Create workers and start them all spinning. We set atomic slots to make +// them go into a wait, thus controlling the waiting order. Then we notify them +// one by one and observe the notification order. + +for (var i = 0; i < NUMAGENT; i++) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + while (Atomics.load(i32a, ${SPIN + i}) === 0) { + /* nothing */ + } + + $262.agent.report(${i}); + Atomics.wait(i32a, ${WAIT_INDEX}, 0); + $262.agent.report(${i}); + + $262.agent.leaving(); + }); + `); +} + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +$262.agent.safeBroadcast(i32a); + +// Wait for agents to be running. +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +var waiterlist = []; +for (var i = 0; i < NUMAGENT; i++) { + assert.sameValue( + Atomics.store(i32a, SPIN + i, 1), + 1, + `Atomics.store(i32a, SPIN + ${i}, 1) returns 1` + ); + + waiterlist.push($262.agent.getReport()); + + // Try to yield control to ensure the agent actually started to wait. + $262.agent.tryYield(); +} + +var notified = []; +for (var i = 0; i < NUMAGENT; i++) { + assert.sameValue( + Atomics.notify(i32a, WAIT_INDEX, 1), + 1, + `Atomics.notify(i32a, WAIT_INDEX, 1) returns 1 (${i})` + ); + + notified.push($262.agent.getReport()); +} + +assert.sameValue( + notified.join(''), + waiterlist.join(''), + 'notified.join(\'\') returns waiterlist.join(\'\')' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-in-order.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-in-order.js new file mode 100644 index 0000000000..b4abca79d3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-in-order.js @@ -0,0 +1,82 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies agents in the order they are waiting. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const NUMAGENT = 3; +const WAIT_INDEX = 0; // Waiters on this will be woken +const SPIN = 1; // Worker i (zero-based) spins on location SPIN+i +const RUNNING = SPIN + NUMAGENT; // Accounting of live agents +const BUFFER_SIZE = RUNNING + 1; + +// Create workers and start them all spinning. We set atomic slots to make +// them go into a wait, thus controlling the waiting order. Then we notify them +// one by one and observe the notification order. + +for (var i = 0; i < NUMAGENT; i++) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + while (Atomics.load(i32a, ${SPIN + i}) === 0) { + /* nothing */ + } + + $262.agent.report(${i}); + Atomics.wait(i32a, ${WAIT_INDEX}, 0); + $262.agent.report(${i}); + + $262.agent.leaving(); + }); + `); +} + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +$262.agent.safeBroadcast(i32a); + +// Wait for agents to be running. +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +var waiterlist = []; +for (var i = 0; i < NUMAGENT; i++) { + assert.sameValue( + Atomics.store(i32a, SPIN + i, 1), + 1, + `Atomics.store(i32a, SPIN + ${i}, 1) returns 1` + ); + + waiterlist.push($262.agent.getReport()); + + // Try to yield control to ensure the agent actually started to wait. + $262.agent.tryYield(); +} + +var notified = []; +for (var i = 0; i < NUMAGENT; i++) { + assert.sameValue( + Atomics.notify(i32a, WAIT_INDEX, 1), + 1, + `Atomics.notify(i32a, WAIT_INDEX, 1) returns 1 (${i})` + ); + + notified.push($262.agent.getReport()); +} + +assert.sameValue( + notified.join(''), + waiterlist.join(''), + 'notified.join(\'\') returns waiterlist.join(\'\')' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-nan.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-nan.js new file mode 100644 index 0000000000..909fc9a37c --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-nan.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.nofity nofities zero waiters if the count is NaN +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.long; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + $262.agent.report(Atomics.wait(i32a, 0, 0, ${TIMEOUT})); // We will timeout eventually + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue(Atomics.notify(i32a, 0, NaN), 0, 'Atomics.notify(i32a, 0, NaN) returns 0'); + +// Try to sleep past the timeout. +$262.agent.trySleep(TIMEOUT); + +assert.sameValue($262.agent.getReport(), 'timed-out', '$262.agent.getReport() returns "timed-out"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-one.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-one.js new file mode 100644 index 0000000000..9142d8b4c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-one.js @@ -0,0 +1,72 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies one waiter if that's what the count is. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const WAIT_INDEX = 0; // Agents wait here +const RUNNING = 1; // Accounting of live agents here +const NOTIFYCOUNT = 1; +const NUMAGENT = 3; +const BUFFER_SIZE = 4; + +const TIMEOUT = $262.agent.timeouts.long; + +for (var i = 0; i < NUMAGENT; i++ ) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // Waiters that are not woken will time out eventually. + $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); + $262.agent.leaving(); + }); + `); +} + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +$262.agent.safeBroadcast(i32a); + +// Wait for agents to be running. +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +// There's a slight risk we'll fail to notify the desired count, if the preceding +// tryYield() took much longer than anticipated and workers have started timing +// out. +assert.sameValue( + Atomics.notify(i32a, 0, NOTIFYCOUNT), + NOTIFYCOUNT, + 'Atomics.notify(i32a, 0, NOTIFYCOUNT) returns the value of `NOTIFYCOUNT`' +); + +// Try to sleep past the timeout. +$262.agent.trySleep(TIMEOUT); + +// Collect and check results +const reports = []; +for (var i = 0; i < NUMAGENT; i++) { + reports.push($262.agent.getReport()); +} +reports.sort(); + +for (var i = 0; i < NOTIFYCOUNT; i++) { + assert.sameValue(reports[i], 'ok', 'The value of reports[i] is "ok"'); +} +for (var i = NOTIFYCOUNT; i < NUMAGENT; i++) { + assert.sameValue(reports[i], 'timed-out', 'The value of reports[i] is "timed-out"'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-renotify-noop.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-renotify-noop.js new file mode 100644 index 0000000000..6aa5bbb186 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-renotify-noop.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify on awoken waiter is a noop. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.long; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + $262.agent.report(Atomics.wait(i32a, 0, 0, ${TIMEOUT})); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2) +); + +$262.agent.safeBroadcast(i32a); + +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue(Atomics.notify(i32a, 0, 1), 1, 'Atomics.notify(i32a, 0, 1) returns 1'); + +assert.sameValue($262.agent.getReport(), 'ok', '$262.agent.getReport() returns "ok"'); + +// Already notified, this should be a noop +assert.sameValue(Atomics.notify(i32a, 0, 1), 0, 'Atomics.notify(i32a, 0, 1) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-two.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-two.js new file mode 100644 index 0000000000..69225a2630 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-two.js @@ -0,0 +1,72 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies two waiters if that's what the count is. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const WAIT_INDEX = 0; // Agents wait here +const RUNNING = 1; // Accounting of live agents here +const NOTIFYCOUNT = 2; +const NUMAGENT = 3; +const BUFFER_SIZE = 4; + +const TIMEOUT = $262.agent.timeouts.long; + +for (var i = 0; i < NUMAGENT; i++ ) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // Waiters that are not woken will time out eventually. + $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); + $262.agent.leaving(); + }) + `); +} + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +$262.agent.safeBroadcast(i32a); + +// Wait for agents to be running. +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +// There's a slight risk we'll fail to notify the desired count, if the preceding +// tryYield() took much longer than anticipated and workers have started timing +// out. +assert.sameValue( + Atomics.notify(i32a, 0, NOTIFYCOUNT), + NOTIFYCOUNT, + 'Atomics.notify(i32a, 0, NOTIFYCOUNT) returns the value of `NOTIFYCOUNT`' +); + +// Try to sleep past the timeout. +$262.agent.trySleep(TIMEOUT); + +// Collect and check results +const reports = []; +for (var i = 0; i < NUMAGENT; i++) { + reports.push($262.agent.getReport()); +} +reports.sort(); + +for (var i = 0; i < NOTIFYCOUNT; i++) { + assert.sameValue(reports[i], 'ok', 'The value of reports[i] is "ok"'); +} +for (var i = NOTIFYCOUNT; i < NUMAGENT; i++) { + assert.sameValue(reports[i], 'timed-out', 'The value of reports[i] is "timed-out"'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-with-no-agents-waiting.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-with-no-agents-waiting.js new file mode 100644 index 0000000000..870632bfd0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-with-no-agents-waiting.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies zero waiters if there are no agents waiting. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + // THIS WILL NEVER WAIT. + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// There are ZERO agents waiting to notify... +assert.sameValue(Atomics.notify(i32a, 0, 1), 0, 'Atomics.notify(i32a, 0, 1) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-with-no-matching-agents-waiting.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-with-no-matching-agents-waiting.js new file mode 100644 index 0000000000..66f41832a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-with-no-matching-agents-waiting.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies zero waiters if there are no waiters + at the index specified. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 0; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// There are ZERO matching agents waiting on index 1 +assert.sameValue(Atomics.notify(i32a, 1, 1), 0, 'Atomics.notify(i32a, 1, 1) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-zero.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-zero.js new file mode 100644 index 0000000000..56df777715 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-zero.js @@ -0,0 +1,59 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies zero waiters if that's what the count is. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const WAIT_INDEX = 0; // Agents wait here +const RUNNING = 1; // Accounting of live agents here +const NOTIFYCOUNT = 0; +const NUMAGENT = 3; +const BUFFER_SIZE = 4; + +const TIMEOUT = $262.agent.timeouts.long; + +for (var i = 0; i < NUMAGENT; i++) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // Waiters that are not woken will time out eventually. + $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); + $262.agent.leaving(); + }); + `); +} + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +$262.agent.safeBroadcast(i32a); + +// Wait for agents to be running. +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue( + Atomics.notify(i32a, WAIT_INDEX, NOTIFYCOUNT), + NOTIFYCOUNT, + 'Atomics.notify(i32a, WAIT_INDEX, NOTIFYCOUNT) returns the value of `NOTIFYCOUNT`' +); + +// Try to sleep past the timeout. +$262.agent.trySleep(TIMEOUT); + +for (var i = 0; i < NUMAGENT; i++) { + assert.sameValue($262.agent.getReport(), 'timed-out', '$262.agent.getReport() returns "timed-out"'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/null-bufferdata-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/null-bufferdata-throws.js new file mode 100644 index 0000000000..f6594d3331 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/null-bufferdata-throws.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + A null value for bufferData (detached) throws a TypeError +info: | + Atomics.notify( typedArray, index, count ) + + Let buffer be ? ValidateIntegerTypedArray(typedArray, true). + ... + + Let buffer be ? ValidateTypedArray(typedArray). + ... + + If IsDetachedBuffer(buffer) is true, throw a TypeError exception. + ... + + If arrayBuffer.[[ArrayBufferData]] is null, return true. + +includes: [detachArrayBuffer.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ + +const i32a = new Int32Array( + new ArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +try { + $DETACHBUFFER(i32a.buffer); // Detaching a non-shared ArrayBuffer sets the [[ArrayBufferData]] value to null +} catch (error) { + throw new Test262Error(`An unexpected error occurred when detaching ArrayBuffer: ${error.message}`); +} + +assert.throws(TypeError, function() { + Atomics.notify(i32a, poisoned, poisoned); +}, '`Atomics.notify(i32a, poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/out-of-range-index-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/out-of-range-index-throws.js new file mode 100644 index 0000000000..e4e2d9f809 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/out-of-range-index-throws.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Throws a RangeError if value of index arg is out of range + info: | + Atomics.notify( typedArray, index, count ) + + 2.Let i be ? ValidateAtomicAccess(typedArray, index). + ... + 2.Let accessIndex be ? ToIndex(requestIndex). + ... + 5. If accessIndex ≥ length, throw a RangeError exception. +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +var poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(RangeError, function() { + Atomics.notify(i32a, Infinity, poisoned); +}, '`Atomics.notify(i32a, Infinity, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.notify(i32a, 4, poisoned); +}, '`Atomics.notify(i32a, 4, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.notify(i32a, 200, poisoned); +}, '`Atomics.notify(i32a, 200, poisoned)` throws RangeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/shell.js b/js/src/tests/test262/built-ins/Atomics/notify/shell.js new file mode 100644 index 0000000000..36d8753471 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/shell.js @@ -0,0 +1,392 @@ +// GENERATED, DO NOT EDIT +// file: atomicsHelper.js +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Collection of functions used to interact with Atomics.* operations across agent boundaries. +defines: + - $262.agent.getReportAsync + - $262.agent.getReport + - $262.agent.safeBroadcastAsync + - $262.agent.safeBroadcast + - $262.agent.setTimeout + - $262.agent.tryYield + - $262.agent.trySleep +---*/ + +/** + * @return {String} A report sent from an agent. + */ +{ + // This is only necessary because the original + // $262.agent.getReport API was insufficient. + // + // All runtimes currently have their own + // $262.agent.getReport which is wrong, so we + // will pave over it with a corrected version. + // + // Binding $262.agent is necessary to prevent + // breaking SpiderMonkey's $262.agent.getReport + let getReport = $262.agent.getReport.bind($262.agent); + + $262.agent.getReport = function() { + var r; + while ((r = getReport()) == null) { + $262.agent.sleep(1); + } + return r; + }; + + if (this.setTimeout === undefined) { + (function(that) { + that.setTimeout = function(callback, delay) { + let p = Promise.resolve(); + let start = Date.now(); + let end = start + delay; + function check() { + if ((end - Date.now()) > 0) { + p.then(check); + } + else { + callback(); + } + } + p.then(check); + } + })(this); + } + + $262.agent.setTimeout = setTimeout; + + $262.agent.getReportAsync = function() { + return new Promise(function(resolve) { + (function loop() { + let result = getReport(); + if (!result) { + setTimeout(loop, 1000); + } else { + resolve(result); + } + })(); + }); + }; +} + +/** + * + * Share a given Int32Array or BigInt64Array to all running agents. Ensure that the + * provided TypedArray is a "shared typed array". + * + * NOTE: Migrating all tests to this API is necessary to prevent tests from hanging + * indefinitely when a SAB is sent to a worker but the code in the worker attempts to + * create a non-sharable TypedArray (something that is not Int32Array or BigInt64Array). + * When that scenario occurs, an exception is thrown and the agent worker can no + * longer communicate with any other threads that control the SAB. If the main + * thread happens to be spinning in the $262.agent.waitUntil() while loop, it will never + * meet its termination condition and the test will hang indefinitely. + * + * Because we've defined $262.agent.broadcast(SAB) in + * https://github.com/tc39/test262/blob/HEAD/INTERPRETING.md, there are host implementations + * that assume compatibility, which must be maintained. + * + * + * $262.agent.safeBroadcast(TA) should not be included in + * https://github.com/tc39/test262/blob/HEAD/INTERPRETING.md + * + * + * @param {(Int32Array|BigInt64Array)} typedArray An Int32Array or BigInt64Array with a SharedArrayBuffer + */ +$262.agent.safeBroadcast = function(typedArray) { + let Constructor = Object.getPrototypeOf(typedArray).constructor; + let temp = new Constructor( + new SharedArrayBuffer(Constructor.BYTES_PER_ELEMENT) + ); + try { + // This will never actually wait, but that's fine because we only + // want to ensure that this typedArray CAN be waited on and is shareable. + Atomics.wait(temp, 0, Constructor === Int32Array ? 1 : BigInt(1)); + } catch (error) { + throw new Test262Error(`${Constructor.name} cannot be used as a shared typed array. (${error})`); + } + + $262.agent.broadcast(typedArray.buffer); +}; + +$262.agent.safeBroadcastAsync = async function(ta, index, expected) { + await $262.agent.broadcast(ta.buffer); + await $262.agent.waitUntil(ta, index, expected); + await $262.agent.tryYield(); + return await Atomics.load(ta, index); +}; + + +/** + * With a given Int32Array or BigInt64Array, wait until the expected number of agents have + * reported themselves by calling: + * + * Atomics.add(typedArray, index, 1); + * + * @param {(Int32Array|BigInt64Array)} typedArray An Int32Array or BigInt64Array with a SharedArrayBuffer + * @param {number} index The index of which all agents will report. + * @param {number} expected The number of agents that are expected to report as active. + */ +$262.agent.waitUntil = function(typedArray, index, expected) { + + var agents = 0; + while ((agents = Atomics.load(typedArray, index)) !== expected) { + /* nothing */ + } + assert.sameValue(agents, expected, "Reporting number of 'agents' equals the value of 'expected'"); +}; + +/** + * Timeout values used throughout the Atomics tests. All timeouts are specified in milliseconds. + * + * @property {number} yield Used for `$262.agent.tryYield`. Must not be used in other functions. + * @property {number} small Used when agents will always timeout and `Atomics.wake` is not part + * of the test semantics. Must be larger than `$262.agent.timeouts.yield`. + * @property {number} long Used when some agents may timeout and `Atomics.wake` is called on some + * agents. The agents are required to wait and this needs to be observable + * by the main thread. + * @property {number} huge Used when `Atomics.wake` is called on all waiting agents. The waiting + * must not timeout. The agents are required to wait and this needs to be + * observable by the main thread. All waiting agents must be woken by the + * main thread. + * + * Usage for `$262.agent.timeouts.small`: + * const WAIT_INDEX = 0; + * const RUNNING = 1; + * const TIMEOUT = $262.agent.timeouts.small; + * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); + * + * $262.agent.start(` + * $262.agent.receiveBroadcast(function(sab) { + * const i32a = new Int32Array(sab); + * Atomics.add(i32a, ${RUNNING}, 1); + * + * $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); + * + * $262.agent.leaving(); + * }); + * `); + * $262.agent.safeBroadcast(i32a.buffer); + * + * // Wait until the agent was started and then try to yield control to increase + * // the likelihood the agent has called `Atomics.wait` and is now waiting. + * $262.agent.waitUntil(i32a, RUNNING, 1); + * $262.agent.tryYield(); + * + * // The agent is expected to time out. + * assert.sameValue($262.agent.getReport(), "timed-out"); + * + * + * Usage for `$262.agent.timeouts.long`: + * const WAIT_INDEX = 0; + * const RUNNING = 1; + * const NUMAGENT = 2; + * const TIMEOUT = $262.agent.timeouts.long; + * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); + * + * for (let i = 0; i < NUMAGENT; i++) { + * $262.agent.start(` + * $262.agent.receiveBroadcast(function(sab) { + * const i32a = new Int32Array(sab); + * Atomics.add(i32a, ${RUNNING}, 1); + * + * $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); + * + * $262.agent.leaving(); + * }); + * `); + * } + * $262.agent.safeBroadcast(i32a.buffer); + * + * // Wait until the agents were started and then try to yield control to increase + * // the likelihood the agents have called `Atomics.wait` and are now waiting. + * $262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + * $262.agent.tryYield(); + * + * // Wake exactly one agent. + * assert.sameValue(Atomics.wake(i32a, WAIT_INDEX, 1), 1); + * + * // When it doesn't matter how many agents were woken at once, a while loop + * // can be used to make the test more resilient against intermittent failures + * // in case even though `tryYield` was called, the agents haven't started to + * // wait. + * // + * // // Repeat until exactly one agent was woken. + * // var woken = 0; + * // while ((woken = Atomics.wake(i32a, WAIT_INDEX, 1)) !== 0) ; + * // assert.sameValue(woken, 1); + * + * // One agent was woken and the other one timed out. + * const reports = [$262.agent.getReport(), $262.agent.getReport()]; + * assert(reports.includes("ok")); + * assert(reports.includes("timed-out")); + * + * + * Usage for `$262.agent.timeouts.huge`: + * const WAIT_INDEX = 0; + * const RUNNING = 1; + * const NUMAGENT = 2; + * const TIMEOUT = $262.agent.timeouts.huge; + * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); + * + * for (let i = 0; i < NUMAGENT; i++) { + * $262.agent.start(` + * $262.agent.receiveBroadcast(function(sab) { + * const i32a = new Int32Array(sab); + * Atomics.add(i32a, ${RUNNING}, 1); + * + * $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); + * + * $262.agent.leaving(); + * }); + * `); + * } + * $262.agent.safeBroadcast(i32a.buffer); + * + * // Wait until the agents were started and then try to yield control to increase + * // the likelihood the agents have called `Atomics.wait` and are now waiting. + * $262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + * $262.agent.tryYield(); + * + * // Wake all agents. + * assert.sameValue(Atomics.wake(i32a, WAIT_INDEX), NUMAGENT); + * + * // When it doesn't matter how many agents were woken at once, a while loop + * // can be used to make the test more resilient against intermittent failures + * // in case even though `tryYield` was called, the agents haven't started to + * // wait. + * // + * // // Repeat until all agents were woken. + * // for (var wokenCount = 0; wokenCount < NUMAGENT; ) { + * // var woken = 0; + * // while ((woken = Atomics.wake(i32a, WAIT_INDEX)) !== 0) ; + * // // Maybe perform an action on the woken agents here. + * // wokenCount += woken; + * // } + * + * // All agents were woken and none timeout. + * for (var i = 0; i < NUMAGENT; i++) { + * assert($262.agent.getReport(), "ok"); + * } + */ +$262.agent.timeouts = { + yield: 100, + small: 200, + long: 1000, + huge: 10000, +}; + +/** + * Try to yield control to the agent threads. + * + * Usage: + * const VALUE = 0; + * const RUNNING = 1; + * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); + * + * $262.agent.start(` + * $262.agent.receiveBroadcast(function(sab) { + * const i32a = new Int32Array(sab); + * Atomics.add(i32a, ${RUNNING}, 1); + * + * Atomics.store(i32a, ${VALUE}, 1); + * + * $262.agent.leaving(); + * }); + * `); + * $262.agent.safeBroadcast(i32a.buffer); + * + * // Wait until agent was started and then try to yield control. + * $262.agent.waitUntil(i32a, RUNNING, 1); + * $262.agent.tryYield(); + * + * // Note: This result is not guaranteed, but should hold in practice most of the time. + * assert.sameValue(Atomics.load(i32a, VALUE), 1); + * + * The default implementation simply waits for `$262.agent.timeouts.yield` milliseconds. + */ +$262.agent.tryYield = function() { + $262.agent.sleep($262.agent.timeouts.yield); +}; + +/** + * Try to sleep the current agent for the given amount of milliseconds. It is acceptable, + * but not encouraged, to ignore this sleep request and directly continue execution. + * + * The default implementation calls `$262.agent.sleep(ms)`. + * + * @param {number} ms Time to sleep in milliseconds. + */ +$262.agent.trySleep = function(ms) { + $262.agent.sleep(ms); +}; + +// file: detachArrayBuffer.js +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + A function used in the process of asserting correctness of TypedArray objects. + + $262.detachArrayBuffer is defined by a host. +defines: [$DETACHBUFFER] +---*/ + +function $DETACHBUFFER(buffer) { + if (!$262 || typeof $262.detachArrayBuffer !== "function") { + throw new Test262Error("No method available to detach an ArrayBuffer"); + } + $262.detachArrayBuffer(buffer); +} + +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: nans.js +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + A collection of NaN values produced from expressions that have been observed + to create distinct bit representations on various platforms. These provide a + weak basis for assertions regarding the consistent canonicalization of NaN + values in Array buffers. +defines: [NaNs] +---*/ + +var NaNs = [ + NaN, + Number.NaN, + NaN * 0, + 0/0, + Infinity/Infinity, + -(0/0), + Math.pow(-1, 0.5), + -Math.pow(-1, 0.5), + Number("Not-a-Number"), +]; diff --git a/js/src/tests/test262/built-ins/Atomics/notify/symbol-for-index-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/symbol-for-index-throws.js new file mode 100644 index 0000000000..33bbc00a1b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/symbol-for-index-throws.js @@ -0,0 +1,64 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Return abrupt when ToInteger throws for 'index' argument to Atomics.notify +info: | + Atomics.notify( typedArray, index, value, timeout ) + + 2. Let i be ? ValidateAtomicAccess(typedArray, index). + + ValidateAtomicAccess( typedArray, requestIndex ) + + 2. Let accessIndex be ? ToIndex(requestIndex). + + ToIndex ( value ) + + 2. Else, + a. Let integerIndex be ? ToInteger(value). + + ToInteger(value) + + 1. Let number be ? ToNumber(argument). + + Symbol --> Throw a TypeError exception. + +features: [Atomics, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisonedValueOf = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +const poisonedToPrimitive = { + [Symbol.toPrimitive]: function() { + throw new Test262Error("passing a poisoned object using @@ToPrimitive"); + } +}; + +assert.throws(Test262Error, function() { + Atomics.notify(i32a, poisonedValueOf, poisonedValueOf); +}, '`Atomics.notify(i32a, poisonedValueOf, poisonedValueOf)` throws Test262Error'); + +assert.throws(Test262Error, function() { + Atomics.notify(i32a, poisonedToPrimitive, poisonedToPrimitive); +}, '`Atomics.notify(i32a, poisonedToPrimitive, poisonedToPrimitive)` throws Test262Error'); + +assert.throws(TypeError, function() { + Atomics.notify(i32a, Symbol("foo"), poisonedValueOf); +}, '`Atomics.notify(i32a, Symbol("foo"), poisonedValueOf)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(i32a, Symbol("foo"), poisonedToPrimitive); +}, '`Atomics.notify(i32a, Symbol("foo"), poisonedToPrimitive)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/undefined-index-defaults-to-zero.js b/js/src/tests/test262/built-ins/Atomics/notify/undefined-index-defaults-to-zero.js new file mode 100644 index 0000000000..7533c65f53 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/undefined-index-defaults-to-zero.js @@ -0,0 +1,76 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + An undefined index arg should translate to 0 +info: | + Atomics.notify( typedArray, index, count ) + + 2.Let i be ? ValidateAtomicAccess(typedArray, index). + ... + 2.Let accessIndex be ? ToIndex(requestIndex). + + 9.If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception. + ... + 3.If bufferData is a Data Block, return false + + If value is undefined, then + Let index be 0. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +var WAIT_INDEX = 0; +var RUNNING = 1; + +var NUMAGENT = 2; + +for (var i = 0; i < NUMAGENT; i++) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + + // Notify main thread that the agent was started. + Atomics.add(i32a, ${RUNNING}, 1); + + // Wait until restarted by main thread. + var status = Atomics.wait(i32a, ${WAIT_INDEX}, 0); + + // Report wait status. + $262.agent.report(status); + + $262.agent.leaving(); + }); + `); +} + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); + +// Wait until both agents started. +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +// Try to yield control to ensure the agents actually started to wait. +$262.agent.tryYield(); + +// Notify at index 0, undefined => 0. +var woken = 0; +while ((woken = Atomics.notify(i32a, undefined, 1)) === 0) ; +assert.sameValue(woken, 1, 'Atomics.notify(i32a, undefined, 1) returns 1'); + +assert.sameValue($262.agent.getReport(), 'ok', '$262.agent.getReport() returns "ok"'); + +// Notify again at index 0, default => 0. +var woken = 0; +while ((woken = Atomics.notify(i32a /*, default values used */)) === 0) ; +assert.sameValue(woken, 1, 'Atomics.notify(i32a /*, default values used */) returns 1'); + +assert.sameValue($262.agent.getReport(), 'ok', '$262.agent.getReport() returns "ok"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/validate-arraytype-before-count-coercion.js b/js/src/tests/test262/built-ins/Atomics/notify/validate-arraytype-before-count-coercion.js new file mode 100644 index 0000000000..f47c665879 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/validate-arraytype-before-count-coercion.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + TypedArray type is validated before `count` argument is coerced. +info: | + 24.4.12 Atomics.notify ( typedArray, index, count ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var count = { + valueOf() { + throw new Test262Error("count coerced"); + } +}; + +var badArrayTypes = [ + Int8Array, Uint8Array, Int16Array, Uint16Array, Uint32Array, + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.notify(typedArray, 0, count); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/validate-arraytype-before-index-coercion.js b/js/src/tests/test262/built-ins/Atomics/notify/validate-arraytype-before-index-coercion.js new file mode 100644 index 0000000000..fcc334dd46 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/validate-arraytype-before-index-coercion.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + TypedArray type is validated before `index` argument is coerced. +info: | + 24.4.12 Atomics.notify ( typedArray, index, count ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var index = { + valueOf() { + throw new Test262Error("index coerced"); + } +}; + +var badArrayTypes = [ + Int8Array, Uint8Array, Int16Array, Uint16Array, Uint32Array, + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.notify(typedArray, index, 0); + }); +} + +reportCompare(0, 0); |