test262/harness/atomicsHelper.js

325 lines
11 KiB
JavaScript
Raw Normal View History

// 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);
};
/**
Make Atomics tests more resilient against intermittent failures (#1617) Also fixes multiple issues and bugs in various Atomics tests. CONTRIBUTING.md and INTERPRETING.md: - Add missing description for `CanBlockIsFalse` flag and also introduce `CanBlockIsTrue` flag which is needed for some tests (see below). harness/atomicsHelper.js: - Updated `$262.agent.waitUntil` to clarify it can also be called with BigInt64Array objects. - Added `$262.agent.timeouts` constants to unify the various, inconsistently used timeouts in the Atomics tests. Each timeout constant has a brief description and a usage example to clarify when it should or should not be used. The default values were tested in SpiderMonkey (locally and CI) under various system load levels and should hopefully also be valid for other engines. - Added `$262.agent.tryYield` to yield control from the main thread. The default implementation simply calls `$262.agent.sleep`, but test262 hosts could theoretically provide a different implementation. - Added `$262.agent.trySleep` to replace direct calls to `$262.agent.sleep` from the main thread. Motivation for this function: Some test262 hosts (like browsers) may be able to pause and sleep on the main thread, so they could provide their implementation for `trySleep` which performs a busy-wait or something do nothing. harness/testAtomics.js: - Replace `let`, `arrow-functions`, and `for-of` loops to avoid creating extremely long `features` lists in tests using this helper. Removed `Map`, `WeakMap`, `Set`, and `WeakSet` (these weren't even listed in features.yaml) for the same reason and added the missing `Symbol` entry for this file to features.yaml. - Updated all files including "harness/testAtomics.js" to match the new feature requirements. test/built-ins/Atomics/store/good-views.js and test/built-ins/Atomics/store/bigint/good-views.js: - Replace `arrow-functions` and `for-of` loops with ES5 alternatives. test/built-ins/Atomics/wait/bigint/*.js and test/built-ins/Atomics/wake/bigint/*.js - Some tests were using `BigInt64Array.BYTES_PER_ELEMENT * 8` for the SharedArrayBuffer length, but their non-BigInt counterparts are using `Int32Array.BYTES_PER_ELEMENT * 4`. For consistency and to make it easier to compare the BigInt against the non-BigInt versions, I've changed it to `BigInt64Array.BYTES_PER_ELEMENT * 4`. - Also aligned formatting and statement placement when they differed between the non-BigInt and the BigInt version of a test file. (I've diffed some of the non-BigInt and BigInt files against each other and different formatting was a nuisance.) Test files using `$262.agent.monotonicNow()`: - Moved `$262.agent.report()` calls outside of the block of code measured `$262.agent.monotonicNow()` to avoid measuring how long it takes to execute `$262.agent.report()`. - Without this change some tests failed intermittently in certain test configurations in SpiderMonkey. For example with the flags `--ion-eager -- ion-offthread-compile=off` which forces early Ion compilation on the main thread. The `$262.agent.report()` implementation in the SpiderMonkey test262 host embedding uses a for-loop which was forcefully Ion compiled under these settings. And because Ion compilation can take some time, the test case ran longer than `$262.agent.MAX_TIME_EPSILON` which lead to intermittent failures. Test files using `CanBlockIsFalse` / `CanBlockIsTrue`: - Some of these tests actually expected that the main thread can wait and [[CanBlock]] is `true` for the agent record executing the test. Therefore I've added a new `CanBlockIsTrue` flag and replaced the flags where needed. test/built-ins/Atomics/wait/**/*.js and test/built-ins/Atomics/wake/**/*.js: - Use an atomic counter `RUNNING` in more tests to have better control when a worker agent was actually started. - Replace the various `$262.agent.sleep(/* Sleep X ms to ensure worker actually sleeps */)` calls with the new `$262.agent.tryYield()` function. This `X` was sometimes as low as 10 milliseconds, which is definitely too short for CI systems under heavy load (observed by intermittent CI failures for SpiderMonkey) and sometimes as high as 500 milliseconds, which is probably much longer than needed even when the system is under heavy load. - Removed duplicate strings in assertion messages, presumably from copy-pasting the messages between different files. - Removed extra empty lines at the end of multiple files. test/built-ins/Atomics/wake/bad-range.js, test/built-ins/Atomics/wake/bigint/bad-range.js, and test/built-ins/Atomics/wait/bigint/non-bigint64-typedarray-throws.js: - Removed unnecessary `features` and `includes` from this file. test/built-ins/Atomics/wait/waiterlist-order-of-operations-is-fifo.js and test/built-ins/Atomics/wait/bigint/waiterlist-order-of-operations-is-fifo.js: - The test was actually broken and didn't test what it said it does. This probably explains #1530. - The test wants to ensure the waiterlist is implemented as a FIFO structure. This requires that the waiting agents all wait on the same index position, because the waiterlists are defined by each index. But if the agents wait on different indices, each agent is inserted into a different FIFO structure and therefore we can't observe any FIFO ordering between the agents when they're woken up. - All this requires a bit of synchronization between the main agent and the waiting agent, I hope the added comments help to review these changes. test/built-ins/Atomics/wait/good-views.js: - The agent sends multiple reports to the main agent, but only the first one was read. - This error was introduced during previous refactorings. I've changed it to back to use a while-loop as used in the first version of this file. test/built-ins/Atomics/wait/no-spurious-wakeup-no-operation.js: - Only the BigInt version of this test was present, copied it so we also get code coverage for the non-BigInt case. test/built-ins/Atomics/wait/waiterlist-block-indexedposition-wake.js: - Added extra while loops to avoid intermittent failures when the agent worker haven't started to wait. - This should help to avoid some of the intermittent failures we saw for SpiderMonkey. test/built-ins/Atomics/wake/wake-all-on-loc.js and test/built-ins/Atomics/wake/bigint/wake-all-on-loc.js: - This test was also no longer after previous refactoring sessions. - The "B" agent only waited for 10 milliseconds, which made it likely that it already timed out before the main agent was able to call `Atomics.wake`, which in turn rendered the test useless, because the test case wants to ensure that `Atomics.wake` cannot wake "B". But if "B" was already timed out, it can trivially not be woken by `Atomics.wake`. - Added some safety measure to catch the case when "B" timed out before `Atomics.wake` was called and made it a test error if that happens. test/built-ins/Atomics/wake/count-defaults-to-infinity-missing.js, test/built-ins/Atomics/wake/count-defaults-to-infinity-undefined.js, and test/built-ins/Atomics/wake/undefined-index-defaults-to-zero.js: - Changed the `$262.agent.start()` calls to use a for-loop to avoid code duplication. - (Forgot to undo the code formatting around `assert.sameValue`, still need to change it back.) - Also more while-loops around `Atomics.wake`. - These changes should fix #1529 and #1566. test/built-ins/Atomics/wake/wake-all.js: - Removed "B" worker agent. - Without this removal the test case would be exactly equal to test/built-ins/Atomics/wake/wake-all-on-loc.js. test/built-ins/Atomics/wake/wake-in-order-one-time.js: - Add for-loops to avoid code duplication and make the test more readable. - Make the `Atomics.wake` assertion messages unique by adding the current loop counter. - Add `$262.agent.tryYield()` to give the worker agents enough time to actually start waiting. test/built-ins/Atomics/wake/wake-in-order.js: - Removed the outer loop `attempt < 10` because it uses `$262.agent` in a way currently not required to work. And which actually also doesn't work in SpiderMonkey's implementation of `$262.agent`. - According to INTERPRETING.md `$262.agent.broadcast()` broadcasts its message to all agents ever started by `$262.agent.start()` and then blocks until all agents received the broadcast. It is not required that the agents started by the first `$262.agent.broadcast()` call will all be disabled/destroyed/whatever when the second `$262.agent.broadcast()` call occurs, which then means the second `$262.agent.broadcast()` call still tries to reach the agents started in the first loop iteration, but these may no longer accept broadcasts and therefore won't acknowledge they've received the broadcast. Which then means the second `$262.agent.broadcast()` call waits forever.
2018-07-03 18:34:54 +02:00
* With a given Int32Array or BigInt64Array, wait until the expected number of agents have
* reported themselves by calling:
*
Make Atomics tests more resilient against intermittent failures (#1617) Also fixes multiple issues and bugs in various Atomics tests. CONTRIBUTING.md and INTERPRETING.md: - Add missing description for `CanBlockIsFalse` flag and also introduce `CanBlockIsTrue` flag which is needed for some tests (see below). harness/atomicsHelper.js: - Updated `$262.agent.waitUntil` to clarify it can also be called with BigInt64Array objects. - Added `$262.agent.timeouts` constants to unify the various, inconsistently used timeouts in the Atomics tests. Each timeout constant has a brief description and a usage example to clarify when it should or should not be used. The default values were tested in SpiderMonkey (locally and CI) under various system load levels and should hopefully also be valid for other engines. - Added `$262.agent.tryYield` to yield control from the main thread. The default implementation simply calls `$262.agent.sleep`, but test262 hosts could theoretically provide a different implementation. - Added `$262.agent.trySleep` to replace direct calls to `$262.agent.sleep` from the main thread. Motivation for this function: Some test262 hosts (like browsers) may be able to pause and sleep on the main thread, so they could provide their implementation for `trySleep` which performs a busy-wait or something do nothing. harness/testAtomics.js: - Replace `let`, `arrow-functions`, and `for-of` loops to avoid creating extremely long `features` lists in tests using this helper. Removed `Map`, `WeakMap`, `Set`, and `WeakSet` (these weren't even listed in features.yaml) for the same reason and added the missing `Symbol` entry for this file to features.yaml. - Updated all files including "harness/testAtomics.js" to match the new feature requirements. test/built-ins/Atomics/store/good-views.js and test/built-ins/Atomics/store/bigint/good-views.js: - Replace `arrow-functions` and `for-of` loops with ES5 alternatives. test/built-ins/Atomics/wait/bigint/*.js and test/built-ins/Atomics/wake/bigint/*.js - Some tests were using `BigInt64Array.BYTES_PER_ELEMENT * 8` for the SharedArrayBuffer length, but their non-BigInt counterparts are using `Int32Array.BYTES_PER_ELEMENT * 4`. For consistency and to make it easier to compare the BigInt against the non-BigInt versions, I've changed it to `BigInt64Array.BYTES_PER_ELEMENT * 4`. - Also aligned formatting and statement placement when they differed between the non-BigInt and the BigInt version of a test file. (I've diffed some of the non-BigInt and BigInt files against each other and different formatting was a nuisance.) Test files using `$262.agent.monotonicNow()`: - Moved `$262.agent.report()` calls outside of the block of code measured `$262.agent.monotonicNow()` to avoid measuring how long it takes to execute `$262.agent.report()`. - Without this change some tests failed intermittently in certain test configurations in SpiderMonkey. For example with the flags `--ion-eager -- ion-offthread-compile=off` which forces early Ion compilation on the main thread. The `$262.agent.report()` implementation in the SpiderMonkey test262 host embedding uses a for-loop which was forcefully Ion compiled under these settings. And because Ion compilation can take some time, the test case ran longer than `$262.agent.MAX_TIME_EPSILON` which lead to intermittent failures. Test files using `CanBlockIsFalse` / `CanBlockIsTrue`: - Some of these tests actually expected that the main thread can wait and [[CanBlock]] is `true` for the agent record executing the test. Therefore I've added a new `CanBlockIsTrue` flag and replaced the flags where needed. test/built-ins/Atomics/wait/**/*.js and test/built-ins/Atomics/wake/**/*.js: - Use an atomic counter `RUNNING` in more tests to have better control when a worker agent was actually started. - Replace the various `$262.agent.sleep(/* Sleep X ms to ensure worker actually sleeps */)` calls with the new `$262.agent.tryYield()` function. This `X` was sometimes as low as 10 milliseconds, which is definitely too short for CI systems under heavy load (observed by intermittent CI failures for SpiderMonkey) and sometimes as high as 500 milliseconds, which is probably much longer than needed even when the system is under heavy load. - Removed duplicate strings in assertion messages, presumably from copy-pasting the messages between different files. - Removed extra empty lines at the end of multiple files. test/built-ins/Atomics/wake/bad-range.js, test/built-ins/Atomics/wake/bigint/bad-range.js, and test/built-ins/Atomics/wait/bigint/non-bigint64-typedarray-throws.js: - Removed unnecessary `features` and `includes` from this file. test/built-ins/Atomics/wait/waiterlist-order-of-operations-is-fifo.js and test/built-ins/Atomics/wait/bigint/waiterlist-order-of-operations-is-fifo.js: - The test was actually broken and didn't test what it said it does. This probably explains #1530. - The test wants to ensure the waiterlist is implemented as a FIFO structure. This requires that the waiting agents all wait on the same index position, because the waiterlists are defined by each index. But if the agents wait on different indices, each agent is inserted into a different FIFO structure and therefore we can't observe any FIFO ordering between the agents when they're woken up. - All this requires a bit of synchronization between the main agent and the waiting agent, I hope the added comments help to review these changes. test/built-ins/Atomics/wait/good-views.js: - The agent sends multiple reports to the main agent, but only the first one was read. - This error was introduced during previous refactorings. I've changed it to back to use a while-loop as used in the first version of this file. test/built-ins/Atomics/wait/no-spurious-wakeup-no-operation.js: - Only the BigInt version of this test was present, copied it so we also get code coverage for the non-BigInt case. test/built-ins/Atomics/wait/waiterlist-block-indexedposition-wake.js: - Added extra while loops to avoid intermittent failures when the agent worker haven't started to wait. - This should help to avoid some of the intermittent failures we saw for SpiderMonkey. test/built-ins/Atomics/wake/wake-all-on-loc.js and test/built-ins/Atomics/wake/bigint/wake-all-on-loc.js: - This test was also no longer after previous refactoring sessions. - The "B" agent only waited for 10 milliseconds, which made it likely that it already timed out before the main agent was able to call `Atomics.wake`, which in turn rendered the test useless, because the test case wants to ensure that `Atomics.wake` cannot wake "B". But if "B" was already timed out, it can trivially not be woken by `Atomics.wake`. - Added some safety measure to catch the case when "B" timed out before `Atomics.wake` was called and made it a test error if that happens. test/built-ins/Atomics/wake/count-defaults-to-infinity-missing.js, test/built-ins/Atomics/wake/count-defaults-to-infinity-undefined.js, and test/built-ins/Atomics/wake/undefined-index-defaults-to-zero.js: - Changed the `$262.agent.start()` calls to use a for-loop to avoid code duplication. - (Forgot to undo the code formatting around `assert.sameValue`, still need to change it back.) - Also more while-loops around `Atomics.wake`. - These changes should fix #1529 and #1566. test/built-ins/Atomics/wake/wake-all.js: - Removed "B" worker agent. - Without this removal the test case would be exactly equal to test/built-ins/Atomics/wake/wake-all-on-loc.js. test/built-ins/Atomics/wake/wake-in-order-one-time.js: - Add for-loops to avoid code duplication and make the test more readable. - Make the `Atomics.wake` assertion messages unique by adding the current loop counter. - Add `$262.agent.tryYield()` to give the worker agents enough time to actually start waiting. test/built-ins/Atomics/wake/wake-in-order.js: - Removed the outer loop `attempt < 10` because it uses `$262.agent` in a way currently not required to work. And which actually also doesn't work in SpiderMonkey's implementation of `$262.agent`. - According to INTERPRETING.md `$262.agent.broadcast()` broadcasts its message to all agents ever started by `$262.agent.start()` and then blocks until all agents received the broadcast. It is not required that the agents started by the first `$262.agent.broadcast()` call will all be disabled/destroyed/whatever when the second `$262.agent.broadcast()` call occurs, which then means the second `$262.agent.broadcast()` call still tries to reach the agents started in the first loop iteration, but these may no longer accept broadcasts and therefore won't acknowledge they've received the broadcast. Which then means the second `$262.agent.broadcast()` call waits forever.
2018-07-03 18:34:54 +02:00
* Atomics.add(typedArray, index, 1);
*
Make Atomics tests more resilient against intermittent failures (#1617) Also fixes multiple issues and bugs in various Atomics tests. CONTRIBUTING.md and INTERPRETING.md: - Add missing description for `CanBlockIsFalse` flag and also introduce `CanBlockIsTrue` flag which is needed for some tests (see below). harness/atomicsHelper.js: - Updated `$262.agent.waitUntil` to clarify it can also be called with BigInt64Array objects. - Added `$262.agent.timeouts` constants to unify the various, inconsistently used timeouts in the Atomics tests. Each timeout constant has a brief description and a usage example to clarify when it should or should not be used. The default values were tested in SpiderMonkey (locally and CI) under various system load levels and should hopefully also be valid for other engines. - Added `$262.agent.tryYield` to yield control from the main thread. The default implementation simply calls `$262.agent.sleep`, but test262 hosts could theoretically provide a different implementation. - Added `$262.agent.trySleep` to replace direct calls to `$262.agent.sleep` from the main thread. Motivation for this function: Some test262 hosts (like browsers) may be able to pause and sleep on the main thread, so they could provide their implementation for `trySleep` which performs a busy-wait or something do nothing. harness/testAtomics.js: - Replace `let`, `arrow-functions`, and `for-of` loops to avoid creating extremely long `features` lists in tests using this helper. Removed `Map`, `WeakMap`, `Set`, and `WeakSet` (these weren't even listed in features.yaml) for the same reason and added the missing `Symbol` entry for this file to features.yaml. - Updated all files including "harness/testAtomics.js" to match the new feature requirements. test/built-ins/Atomics/store/good-views.js and test/built-ins/Atomics/store/bigint/good-views.js: - Replace `arrow-functions` and `for-of` loops with ES5 alternatives. test/built-ins/Atomics/wait/bigint/*.js and test/built-ins/Atomics/wake/bigint/*.js - Some tests were using `BigInt64Array.BYTES_PER_ELEMENT * 8` for the SharedArrayBuffer length, but their non-BigInt counterparts are using `Int32Array.BYTES_PER_ELEMENT * 4`. For consistency and to make it easier to compare the BigInt against the non-BigInt versions, I've changed it to `BigInt64Array.BYTES_PER_ELEMENT * 4`. - Also aligned formatting and statement placement when they differed between the non-BigInt and the BigInt version of a test file. (I've diffed some of the non-BigInt and BigInt files against each other and different formatting was a nuisance.) Test files using `$262.agent.monotonicNow()`: - Moved `$262.agent.report()` calls outside of the block of code measured `$262.agent.monotonicNow()` to avoid measuring how long it takes to execute `$262.agent.report()`. - Without this change some tests failed intermittently in certain test configurations in SpiderMonkey. For example with the flags `--ion-eager -- ion-offthread-compile=off` which forces early Ion compilation on the main thread. The `$262.agent.report()` implementation in the SpiderMonkey test262 host embedding uses a for-loop which was forcefully Ion compiled under these settings. And because Ion compilation can take some time, the test case ran longer than `$262.agent.MAX_TIME_EPSILON` which lead to intermittent failures. Test files using `CanBlockIsFalse` / `CanBlockIsTrue`: - Some of these tests actually expected that the main thread can wait and [[CanBlock]] is `true` for the agent record executing the test. Therefore I've added a new `CanBlockIsTrue` flag and replaced the flags where needed. test/built-ins/Atomics/wait/**/*.js and test/built-ins/Atomics/wake/**/*.js: - Use an atomic counter `RUNNING` in more tests to have better control when a worker agent was actually started. - Replace the various `$262.agent.sleep(/* Sleep X ms to ensure worker actually sleeps */)` calls with the new `$262.agent.tryYield()` function. This `X` was sometimes as low as 10 milliseconds, which is definitely too short for CI systems under heavy load (observed by intermittent CI failures for SpiderMonkey) and sometimes as high as 500 milliseconds, which is probably much longer than needed even when the system is under heavy load. - Removed duplicate strings in assertion messages, presumably from copy-pasting the messages between different files. - Removed extra empty lines at the end of multiple files. test/built-ins/Atomics/wake/bad-range.js, test/built-ins/Atomics/wake/bigint/bad-range.js, and test/built-ins/Atomics/wait/bigint/non-bigint64-typedarray-throws.js: - Removed unnecessary `features` and `includes` from this file. test/built-ins/Atomics/wait/waiterlist-order-of-operations-is-fifo.js and test/built-ins/Atomics/wait/bigint/waiterlist-order-of-operations-is-fifo.js: - The test was actually broken and didn't test what it said it does. This probably explains #1530. - The test wants to ensure the waiterlist is implemented as a FIFO structure. This requires that the waiting agents all wait on the same index position, because the waiterlists are defined by each index. But if the agents wait on different indices, each agent is inserted into a different FIFO structure and therefore we can't observe any FIFO ordering between the agents when they're woken up. - All this requires a bit of synchronization between the main agent and the waiting agent, I hope the added comments help to review these changes. test/built-ins/Atomics/wait/good-views.js: - The agent sends multiple reports to the main agent, but only the first one was read. - This error was introduced during previous refactorings. I've changed it to back to use a while-loop as used in the first version of this file. test/built-ins/Atomics/wait/no-spurious-wakeup-no-operation.js: - Only the BigInt version of this test was present, copied it so we also get code coverage for the non-BigInt case. test/built-ins/Atomics/wait/waiterlist-block-indexedposition-wake.js: - Added extra while loops to avoid intermittent failures when the agent worker haven't started to wait. - This should help to avoid some of the intermittent failures we saw for SpiderMonkey. test/built-ins/Atomics/wake/wake-all-on-loc.js and test/built-ins/Atomics/wake/bigint/wake-all-on-loc.js: - This test was also no longer after previous refactoring sessions. - The "B" agent only waited for 10 milliseconds, which made it likely that it already timed out before the main agent was able to call `Atomics.wake`, which in turn rendered the test useless, because the test case wants to ensure that `Atomics.wake` cannot wake "B". But if "B" was already timed out, it can trivially not be woken by `Atomics.wake`. - Added some safety measure to catch the case when "B" timed out before `Atomics.wake` was called and made it a test error if that happens. test/built-ins/Atomics/wake/count-defaults-to-infinity-missing.js, test/built-ins/Atomics/wake/count-defaults-to-infinity-undefined.js, and test/built-ins/Atomics/wake/undefined-index-defaults-to-zero.js: - Changed the `$262.agent.start()` calls to use a for-loop to avoid code duplication. - (Forgot to undo the code formatting around `assert.sameValue`, still need to change it back.) - Also more while-loops around `Atomics.wake`. - These changes should fix #1529 and #1566. test/built-ins/Atomics/wake/wake-all.js: - Removed "B" worker agent. - Without this removal the test case would be exactly equal to test/built-ins/Atomics/wake/wake-all-on-loc.js. test/built-ins/Atomics/wake/wake-in-order-one-time.js: - Add for-loops to avoid code duplication and make the test more readable. - Make the `Atomics.wake` assertion messages unique by adding the current loop counter. - Add `$262.agent.tryYield()` to give the worker agents enough time to actually start waiting. test/built-ins/Atomics/wake/wake-in-order.js: - Removed the outer loop `attempt < 10` because it uses `$262.agent` in a way currently not required to work. And which actually also doesn't work in SpiderMonkey's implementation of `$262.agent`. - According to INTERPRETING.md `$262.agent.broadcast()` broadcasts its message to all agents ever started by `$262.agent.start()` and then blocks until all agents received the broadcast. It is not required that the agents started by the first `$262.agent.broadcast()` call will all be disabled/destroyed/whatever when the second `$262.agent.broadcast()` call occurs, which then means the second `$262.agent.broadcast()` call still tries to reach the agents started in the first loop iteration, but these may no longer accept broadcasts and therefore won't acknowledge they've received the broadcast. Which then means the second `$262.agent.broadcast()` call waits forever.
2018-07-03 18:34:54 +02:00
* @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.
*/
Make Atomics tests more resilient against intermittent failures (#1617) Also fixes multiple issues and bugs in various Atomics tests. CONTRIBUTING.md and INTERPRETING.md: - Add missing description for `CanBlockIsFalse` flag and also introduce `CanBlockIsTrue` flag which is needed for some tests (see below). harness/atomicsHelper.js: - Updated `$262.agent.waitUntil` to clarify it can also be called with BigInt64Array objects. - Added `$262.agent.timeouts` constants to unify the various, inconsistently used timeouts in the Atomics tests. Each timeout constant has a brief description and a usage example to clarify when it should or should not be used. The default values were tested in SpiderMonkey (locally and CI) under various system load levels and should hopefully also be valid for other engines. - Added `$262.agent.tryYield` to yield control from the main thread. The default implementation simply calls `$262.agent.sleep`, but test262 hosts could theoretically provide a different implementation. - Added `$262.agent.trySleep` to replace direct calls to `$262.agent.sleep` from the main thread. Motivation for this function: Some test262 hosts (like browsers) may be able to pause and sleep on the main thread, so they could provide their implementation for `trySleep` which performs a busy-wait or something do nothing. harness/testAtomics.js: - Replace `let`, `arrow-functions`, and `for-of` loops to avoid creating extremely long `features` lists in tests using this helper. Removed `Map`, `WeakMap`, `Set`, and `WeakSet` (these weren't even listed in features.yaml) for the same reason and added the missing `Symbol` entry for this file to features.yaml. - Updated all files including "harness/testAtomics.js" to match the new feature requirements. test/built-ins/Atomics/store/good-views.js and test/built-ins/Atomics/store/bigint/good-views.js: - Replace `arrow-functions` and `for-of` loops with ES5 alternatives. test/built-ins/Atomics/wait/bigint/*.js and test/built-ins/Atomics/wake/bigint/*.js - Some tests were using `BigInt64Array.BYTES_PER_ELEMENT * 8` for the SharedArrayBuffer length, but their non-BigInt counterparts are using `Int32Array.BYTES_PER_ELEMENT * 4`. For consistency and to make it easier to compare the BigInt against the non-BigInt versions, I've changed it to `BigInt64Array.BYTES_PER_ELEMENT * 4`. - Also aligned formatting and statement placement when they differed between the non-BigInt and the BigInt version of a test file. (I've diffed some of the non-BigInt and BigInt files against each other and different formatting was a nuisance.) Test files using `$262.agent.monotonicNow()`: - Moved `$262.agent.report()` calls outside of the block of code measured `$262.agent.monotonicNow()` to avoid measuring how long it takes to execute `$262.agent.report()`. - Without this change some tests failed intermittently in certain test configurations in SpiderMonkey. For example with the flags `--ion-eager -- ion-offthread-compile=off` which forces early Ion compilation on the main thread. The `$262.agent.report()` implementation in the SpiderMonkey test262 host embedding uses a for-loop which was forcefully Ion compiled under these settings. And because Ion compilation can take some time, the test case ran longer than `$262.agent.MAX_TIME_EPSILON` which lead to intermittent failures. Test files using `CanBlockIsFalse` / `CanBlockIsTrue`: - Some of these tests actually expected that the main thread can wait and [[CanBlock]] is `true` for the agent record executing the test. Therefore I've added a new `CanBlockIsTrue` flag and replaced the flags where needed. test/built-ins/Atomics/wait/**/*.js and test/built-ins/Atomics/wake/**/*.js: - Use an atomic counter `RUNNING` in more tests to have better control when a worker agent was actually started. - Replace the various `$262.agent.sleep(/* Sleep X ms to ensure worker actually sleeps */)` calls with the new `$262.agent.tryYield()` function. This `X` was sometimes as low as 10 milliseconds, which is definitely too short for CI systems under heavy load (observed by intermittent CI failures for SpiderMonkey) and sometimes as high as 500 milliseconds, which is probably much longer than needed even when the system is under heavy load. - Removed duplicate strings in assertion messages, presumably from copy-pasting the messages between different files. - Removed extra empty lines at the end of multiple files. test/built-ins/Atomics/wake/bad-range.js, test/built-ins/Atomics/wake/bigint/bad-range.js, and test/built-ins/Atomics/wait/bigint/non-bigint64-typedarray-throws.js: - Removed unnecessary `features` and `includes` from this file. test/built-ins/Atomics/wait/waiterlist-order-of-operations-is-fifo.js and test/built-ins/Atomics/wait/bigint/waiterlist-order-of-operations-is-fifo.js: - The test was actually broken and didn't test what it said it does. This probably explains #1530. - The test wants to ensure the waiterlist is implemented as a FIFO structure. This requires that the waiting agents all wait on the same index position, because the waiterlists are defined by each index. But if the agents wait on different indices, each agent is inserted into a different FIFO structure and therefore we can't observe any FIFO ordering between the agents when they're woken up. - All this requires a bit of synchronization between the main agent and the waiting agent, I hope the added comments help to review these changes. test/built-ins/Atomics/wait/good-views.js: - The agent sends multiple reports to the main agent, but only the first one was read. - This error was introduced during previous refactorings. I've changed it to back to use a while-loop as used in the first version of this file. test/built-ins/Atomics/wait/no-spurious-wakeup-no-operation.js: - Only the BigInt version of this test was present, copied it so we also get code coverage for the non-BigInt case. test/built-ins/Atomics/wait/waiterlist-block-indexedposition-wake.js: - Added extra while loops to avoid intermittent failures when the agent worker haven't started to wait. - This should help to avoid some of the intermittent failures we saw for SpiderMonkey. test/built-ins/Atomics/wake/wake-all-on-loc.js and test/built-ins/Atomics/wake/bigint/wake-all-on-loc.js: - This test was also no longer after previous refactoring sessions. - The "B" agent only waited for 10 milliseconds, which made it likely that it already timed out before the main agent was able to call `Atomics.wake`, which in turn rendered the test useless, because the test case wants to ensure that `Atomics.wake` cannot wake "B". But if "B" was already timed out, it can trivially not be woken by `Atomics.wake`. - Added some safety measure to catch the case when "B" timed out before `Atomics.wake` was called and made it a test error if that happens. test/built-ins/Atomics/wake/count-defaults-to-infinity-missing.js, test/built-ins/Atomics/wake/count-defaults-to-infinity-undefined.js, and test/built-ins/Atomics/wake/undefined-index-defaults-to-zero.js: - Changed the `$262.agent.start()` calls to use a for-loop to avoid code duplication. - (Forgot to undo the code formatting around `assert.sameValue`, still need to change it back.) - Also more while-loops around `Atomics.wake`. - These changes should fix #1529 and #1566. test/built-ins/Atomics/wake/wake-all.js: - Removed "B" worker agent. - Without this removal the test case would be exactly equal to test/built-ins/Atomics/wake/wake-all-on-loc.js. test/built-ins/Atomics/wake/wake-in-order-one-time.js: - Add for-loops to avoid code duplication and make the test more readable. - Make the `Atomics.wake` assertion messages unique by adding the current loop counter. - Add `$262.agent.tryYield()` to give the worker agents enough time to actually start waiting. test/built-ins/Atomics/wake/wake-in-order.js: - Removed the outer loop `attempt < 10` because it uses `$262.agent` in a way currently not required to work. And which actually also doesn't work in SpiderMonkey's implementation of `$262.agent`. - According to INTERPRETING.md `$262.agent.broadcast()` broadcasts its message to all agents ever started by `$262.agent.start()` and then blocks until all agents received the broadcast. It is not required that the agents started by the first `$262.agent.broadcast()` call will all be disabled/destroyed/whatever when the second `$262.agent.broadcast()` call occurs, which then means the second `$262.agent.broadcast()` call still tries to reach the agents started in the first loop iteration, but these may no longer accept broadcasts and therefore won't acknowledge they've received the broadcast. Which then means the second `$262.agent.broadcast()` call waits forever.
2018-07-03 18:34:54 +02:00
$262.agent.waitUntil = function(typedArray, index, expected) {
Make Atomics tests more resilient against intermittent failures (#1617) Also fixes multiple issues and bugs in various Atomics tests. CONTRIBUTING.md and INTERPRETING.md: - Add missing description for `CanBlockIsFalse` flag and also introduce `CanBlockIsTrue` flag which is needed for some tests (see below). harness/atomicsHelper.js: - Updated `$262.agent.waitUntil` to clarify it can also be called with BigInt64Array objects. - Added `$262.agent.timeouts` constants to unify the various, inconsistently used timeouts in the Atomics tests. Each timeout constant has a brief description and a usage example to clarify when it should or should not be used. The default values were tested in SpiderMonkey (locally and CI) under various system load levels and should hopefully also be valid for other engines. - Added `$262.agent.tryYield` to yield control from the main thread. The default implementation simply calls `$262.agent.sleep`, but test262 hosts could theoretically provide a different implementation. - Added `$262.agent.trySleep` to replace direct calls to `$262.agent.sleep` from the main thread. Motivation for this function: Some test262 hosts (like browsers) may be able to pause and sleep on the main thread, so they could provide their implementation for `trySleep` which performs a busy-wait or something do nothing. harness/testAtomics.js: - Replace `let`, `arrow-functions`, and `for-of` loops to avoid creating extremely long `features` lists in tests using this helper. Removed `Map`, `WeakMap`, `Set`, and `WeakSet` (these weren't even listed in features.yaml) for the same reason and added the missing `Symbol` entry for this file to features.yaml. - Updated all files including "harness/testAtomics.js" to match the new feature requirements. test/built-ins/Atomics/store/good-views.js and test/built-ins/Atomics/store/bigint/good-views.js: - Replace `arrow-functions` and `for-of` loops with ES5 alternatives. test/built-ins/Atomics/wait/bigint/*.js and test/built-ins/Atomics/wake/bigint/*.js - Some tests were using `BigInt64Array.BYTES_PER_ELEMENT * 8` for the SharedArrayBuffer length, but their non-BigInt counterparts are using `Int32Array.BYTES_PER_ELEMENT * 4`. For consistency and to make it easier to compare the BigInt against the non-BigInt versions, I've changed it to `BigInt64Array.BYTES_PER_ELEMENT * 4`. - Also aligned formatting and statement placement when they differed between the non-BigInt and the BigInt version of a test file. (I've diffed some of the non-BigInt and BigInt files against each other and different formatting was a nuisance.) Test files using `$262.agent.monotonicNow()`: - Moved `$262.agent.report()` calls outside of the block of code measured `$262.agent.monotonicNow()` to avoid measuring how long it takes to execute `$262.agent.report()`. - Without this change some tests failed intermittently in certain test configurations in SpiderMonkey. For example with the flags `--ion-eager -- ion-offthread-compile=off` which forces early Ion compilation on the main thread. The `$262.agent.report()` implementation in the SpiderMonkey test262 host embedding uses a for-loop which was forcefully Ion compiled under these settings. And because Ion compilation can take some time, the test case ran longer than `$262.agent.MAX_TIME_EPSILON` which lead to intermittent failures. Test files using `CanBlockIsFalse` / `CanBlockIsTrue`: - Some of these tests actually expected that the main thread can wait and [[CanBlock]] is `true` for the agent record executing the test. Therefore I've added a new `CanBlockIsTrue` flag and replaced the flags where needed. test/built-ins/Atomics/wait/**/*.js and test/built-ins/Atomics/wake/**/*.js: - Use an atomic counter `RUNNING` in more tests to have better control when a worker agent was actually started. - Replace the various `$262.agent.sleep(/* Sleep X ms to ensure worker actually sleeps */)` calls with the new `$262.agent.tryYield()` function. This `X` was sometimes as low as 10 milliseconds, which is definitely too short for CI systems under heavy load (observed by intermittent CI failures for SpiderMonkey) and sometimes as high as 500 milliseconds, which is probably much longer than needed even when the system is under heavy load. - Removed duplicate strings in assertion messages, presumably from copy-pasting the messages between different files. - Removed extra empty lines at the end of multiple files. test/built-ins/Atomics/wake/bad-range.js, test/built-ins/Atomics/wake/bigint/bad-range.js, and test/built-ins/Atomics/wait/bigint/non-bigint64-typedarray-throws.js: - Removed unnecessary `features` and `includes` from this file. test/built-ins/Atomics/wait/waiterlist-order-of-operations-is-fifo.js and test/built-ins/Atomics/wait/bigint/waiterlist-order-of-operations-is-fifo.js: - The test was actually broken and didn't test what it said it does. This probably explains #1530. - The test wants to ensure the waiterlist is implemented as a FIFO structure. This requires that the waiting agents all wait on the same index position, because the waiterlists are defined by each index. But if the agents wait on different indices, each agent is inserted into a different FIFO structure and therefore we can't observe any FIFO ordering between the agents when they're woken up. - All this requires a bit of synchronization between the main agent and the waiting agent, I hope the added comments help to review these changes. test/built-ins/Atomics/wait/good-views.js: - The agent sends multiple reports to the main agent, but only the first one was read. - This error was introduced during previous refactorings. I've changed it to back to use a while-loop as used in the first version of this file. test/built-ins/Atomics/wait/no-spurious-wakeup-no-operation.js: - Only the BigInt version of this test was present, copied it so we also get code coverage for the non-BigInt case. test/built-ins/Atomics/wait/waiterlist-block-indexedposition-wake.js: - Added extra while loops to avoid intermittent failures when the agent worker haven't started to wait. - This should help to avoid some of the intermittent failures we saw for SpiderMonkey. test/built-ins/Atomics/wake/wake-all-on-loc.js and test/built-ins/Atomics/wake/bigint/wake-all-on-loc.js: - This test was also no longer after previous refactoring sessions. - The "B" agent only waited for 10 milliseconds, which made it likely that it already timed out before the main agent was able to call `Atomics.wake`, which in turn rendered the test useless, because the test case wants to ensure that `Atomics.wake` cannot wake "B". But if "B" was already timed out, it can trivially not be woken by `Atomics.wake`. - Added some safety measure to catch the case when "B" timed out before `Atomics.wake` was called and made it a test error if that happens. test/built-ins/Atomics/wake/count-defaults-to-infinity-missing.js, test/built-ins/Atomics/wake/count-defaults-to-infinity-undefined.js, and test/built-ins/Atomics/wake/undefined-index-defaults-to-zero.js: - Changed the `$262.agent.start()` calls to use a for-loop to avoid code duplication. - (Forgot to undo the code formatting around `assert.sameValue`, still need to change it back.) - Also more while-loops around `Atomics.wake`. - These changes should fix #1529 and #1566. test/built-ins/Atomics/wake/wake-all.js: - Removed "B" worker agent. - Without this removal the test case would be exactly equal to test/built-ins/Atomics/wake/wake-all-on-loc.js. test/built-ins/Atomics/wake/wake-in-order-one-time.js: - Add for-loops to avoid code duplication and make the test more readable. - Make the `Atomics.wake` assertion messages unique by adding the current loop counter. - Add `$262.agent.tryYield()` to give the worker agents enough time to actually start waiting. test/built-ins/Atomics/wake/wake-in-order.js: - Removed the outer loop `attempt < 10` because it uses `$262.agent` in a way currently not required to work. And which actually also doesn't work in SpiderMonkey's implementation of `$262.agent`. - According to INTERPRETING.md `$262.agent.broadcast()` broadcasts its message to all agents ever started by `$262.agent.start()` and then blocks until all agents received the broadcast. It is not required that the agents started by the first `$262.agent.broadcast()` call will all be disabled/destroyed/whatever when the second `$262.agent.broadcast()` call occurs, which then means the second `$262.agent.broadcast()` call still tries to reach the agents started in the first loop iteration, but these may no longer accept broadcasts and therefore won't acknowledge they've received the broadcast. Which then means the second `$262.agent.broadcast()` call waits forever.
2018-07-03 18:34:54 +02:00
var agents = 0;
while ((agents = Atomics.load(typedArray, index)) !== expected) {
/* nothing */
}
Make Atomics tests more resilient against intermittent failures (#1617) Also fixes multiple issues and bugs in various Atomics tests. CONTRIBUTING.md and INTERPRETING.md: - Add missing description for `CanBlockIsFalse` flag and also introduce `CanBlockIsTrue` flag which is needed for some tests (see below). harness/atomicsHelper.js: - Updated `$262.agent.waitUntil` to clarify it can also be called with BigInt64Array objects. - Added `$262.agent.timeouts` constants to unify the various, inconsistently used timeouts in the Atomics tests. Each timeout constant has a brief description and a usage example to clarify when it should or should not be used. The default values were tested in SpiderMonkey (locally and CI) under various system load levels and should hopefully also be valid for other engines. - Added `$262.agent.tryYield` to yield control from the main thread. The default implementation simply calls `$262.agent.sleep`, but test262 hosts could theoretically provide a different implementation. - Added `$262.agent.trySleep` to replace direct calls to `$262.agent.sleep` from the main thread. Motivation for this function: Some test262 hosts (like browsers) may be able to pause and sleep on the main thread, so they could provide their implementation for `trySleep` which performs a busy-wait or something do nothing. harness/testAtomics.js: - Replace `let`, `arrow-functions`, and `for-of` loops to avoid creating extremely long `features` lists in tests using this helper. Removed `Map`, `WeakMap`, `Set`, and `WeakSet` (these weren't even listed in features.yaml) for the same reason and added the missing `Symbol` entry for this file to features.yaml. - Updated all files including "harness/testAtomics.js" to match the new feature requirements. test/built-ins/Atomics/store/good-views.js and test/built-ins/Atomics/store/bigint/good-views.js: - Replace `arrow-functions` and `for-of` loops with ES5 alternatives. test/built-ins/Atomics/wait/bigint/*.js and test/built-ins/Atomics/wake/bigint/*.js - Some tests were using `BigInt64Array.BYTES_PER_ELEMENT * 8` for the SharedArrayBuffer length, but their non-BigInt counterparts are using `Int32Array.BYTES_PER_ELEMENT * 4`. For consistency and to make it easier to compare the BigInt against the non-BigInt versions, I've changed it to `BigInt64Array.BYTES_PER_ELEMENT * 4`. - Also aligned formatting and statement placement when they differed between the non-BigInt and the BigInt version of a test file. (I've diffed some of the non-BigInt and BigInt files against each other and different formatting was a nuisance.) Test files using `$262.agent.monotonicNow()`: - Moved `$262.agent.report()` calls outside of the block of code measured `$262.agent.monotonicNow()` to avoid measuring how long it takes to execute `$262.agent.report()`. - Without this change some tests failed intermittently in certain test configurations in SpiderMonkey. For example with the flags `--ion-eager -- ion-offthread-compile=off` which forces early Ion compilation on the main thread. The `$262.agent.report()` implementation in the SpiderMonkey test262 host embedding uses a for-loop which was forcefully Ion compiled under these settings. And because Ion compilation can take some time, the test case ran longer than `$262.agent.MAX_TIME_EPSILON` which lead to intermittent failures. Test files using `CanBlockIsFalse` / `CanBlockIsTrue`: - Some of these tests actually expected that the main thread can wait and [[CanBlock]] is `true` for the agent record executing the test. Therefore I've added a new `CanBlockIsTrue` flag and replaced the flags where needed. test/built-ins/Atomics/wait/**/*.js and test/built-ins/Atomics/wake/**/*.js: - Use an atomic counter `RUNNING` in more tests to have better control when a worker agent was actually started. - Replace the various `$262.agent.sleep(/* Sleep X ms to ensure worker actually sleeps */)` calls with the new `$262.agent.tryYield()` function. This `X` was sometimes as low as 10 milliseconds, which is definitely too short for CI systems under heavy load (observed by intermittent CI failures for SpiderMonkey) and sometimes as high as 500 milliseconds, which is probably much longer than needed even when the system is under heavy load. - Removed duplicate strings in assertion messages, presumably from copy-pasting the messages between different files. - Removed extra empty lines at the end of multiple files. test/built-ins/Atomics/wake/bad-range.js, test/built-ins/Atomics/wake/bigint/bad-range.js, and test/built-ins/Atomics/wait/bigint/non-bigint64-typedarray-throws.js: - Removed unnecessary `features` and `includes` from this file. test/built-ins/Atomics/wait/waiterlist-order-of-operations-is-fifo.js and test/built-ins/Atomics/wait/bigint/waiterlist-order-of-operations-is-fifo.js: - The test was actually broken and didn't test what it said it does. This probably explains #1530. - The test wants to ensure the waiterlist is implemented as a FIFO structure. This requires that the waiting agents all wait on the same index position, because the waiterlists are defined by each index. But if the agents wait on different indices, each agent is inserted into a different FIFO structure and therefore we can't observe any FIFO ordering between the agents when they're woken up. - All this requires a bit of synchronization between the main agent and the waiting agent, I hope the added comments help to review these changes. test/built-ins/Atomics/wait/good-views.js: - The agent sends multiple reports to the main agent, but only the first one was read. - This error was introduced during previous refactorings. I've changed it to back to use a while-loop as used in the first version of this file. test/built-ins/Atomics/wait/no-spurious-wakeup-no-operation.js: - Only the BigInt version of this test was present, copied it so we also get code coverage for the non-BigInt case. test/built-ins/Atomics/wait/waiterlist-block-indexedposition-wake.js: - Added extra while loops to avoid intermittent failures when the agent worker haven't started to wait. - This should help to avoid some of the intermittent failures we saw for SpiderMonkey. test/built-ins/Atomics/wake/wake-all-on-loc.js and test/built-ins/Atomics/wake/bigint/wake-all-on-loc.js: - This test was also no longer after previous refactoring sessions. - The "B" agent only waited for 10 milliseconds, which made it likely that it already timed out before the main agent was able to call `Atomics.wake`, which in turn rendered the test useless, because the test case wants to ensure that `Atomics.wake` cannot wake "B". But if "B" was already timed out, it can trivially not be woken by `Atomics.wake`. - Added some safety measure to catch the case when "B" timed out before `Atomics.wake` was called and made it a test error if that happens. test/built-ins/Atomics/wake/count-defaults-to-infinity-missing.js, test/built-ins/Atomics/wake/count-defaults-to-infinity-undefined.js, and test/built-ins/Atomics/wake/undefined-index-defaults-to-zero.js: - Changed the `$262.agent.start()` calls to use a for-loop to avoid code duplication. - (Forgot to undo the code formatting around `assert.sameValue`, still need to change it back.) - Also more while-loops around `Atomics.wake`. - These changes should fix #1529 and #1566. test/built-ins/Atomics/wake/wake-all.js: - Removed "B" worker agent. - Without this removal the test case would be exactly equal to test/built-ins/Atomics/wake/wake-all-on-loc.js. test/built-ins/Atomics/wake/wake-in-order-one-time.js: - Add for-loops to avoid code duplication and make the test more readable. - Make the `Atomics.wake` assertion messages unique by adding the current loop counter. - Add `$262.agent.tryYield()` to give the worker agents enough time to actually start waiting. test/built-ins/Atomics/wake/wake-in-order.js: - Removed the outer loop `attempt < 10` because it uses `$262.agent` in a way currently not required to work. And which actually also doesn't work in SpiderMonkey's implementation of `$262.agent`. - According to INTERPRETING.md `$262.agent.broadcast()` broadcasts its message to all agents ever started by `$262.agent.start()` and then blocks until all agents received the broadcast. It is not required that the agents started by the first `$262.agent.broadcast()` call will all be disabled/destroyed/whatever when the second `$262.agent.broadcast()` call occurs, which then means the second `$262.agent.broadcast()` call still tries to reach the agents started in the first loop iteration, but these may no longer accept broadcasts and therefore won't acknowledge they've received the broadcast. Which then means the second `$262.agent.broadcast()` call waits forever.
2018-07-03 18:34:54 +02:00
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);
Make Atomics tests more resilient against intermittent failures (#1617) Also fixes multiple issues and bugs in various Atomics tests. CONTRIBUTING.md and INTERPRETING.md: - Add missing description for `CanBlockIsFalse` flag and also introduce `CanBlockIsTrue` flag which is needed for some tests (see below). harness/atomicsHelper.js: - Updated `$262.agent.waitUntil` to clarify it can also be called with BigInt64Array objects. - Added `$262.agent.timeouts` constants to unify the various, inconsistently used timeouts in the Atomics tests. Each timeout constant has a brief description and a usage example to clarify when it should or should not be used. The default values were tested in SpiderMonkey (locally and CI) under various system load levels and should hopefully also be valid for other engines. - Added `$262.agent.tryYield` to yield control from the main thread. The default implementation simply calls `$262.agent.sleep`, but test262 hosts could theoretically provide a different implementation. - Added `$262.agent.trySleep` to replace direct calls to `$262.agent.sleep` from the main thread. Motivation for this function: Some test262 hosts (like browsers) may be able to pause and sleep on the main thread, so they could provide their implementation for `trySleep` which performs a busy-wait or something do nothing. harness/testAtomics.js: - Replace `let`, `arrow-functions`, and `for-of` loops to avoid creating extremely long `features` lists in tests using this helper. Removed `Map`, `WeakMap`, `Set`, and `WeakSet` (these weren't even listed in features.yaml) for the same reason and added the missing `Symbol` entry for this file to features.yaml. - Updated all files including "harness/testAtomics.js" to match the new feature requirements. test/built-ins/Atomics/store/good-views.js and test/built-ins/Atomics/store/bigint/good-views.js: - Replace `arrow-functions` and `for-of` loops with ES5 alternatives. test/built-ins/Atomics/wait/bigint/*.js and test/built-ins/Atomics/wake/bigint/*.js - Some tests were using `BigInt64Array.BYTES_PER_ELEMENT * 8` for the SharedArrayBuffer length, but their non-BigInt counterparts are using `Int32Array.BYTES_PER_ELEMENT * 4`. For consistency and to make it easier to compare the BigInt against the non-BigInt versions, I've changed it to `BigInt64Array.BYTES_PER_ELEMENT * 4`. - Also aligned formatting and statement placement when they differed between the non-BigInt and the BigInt version of a test file. (I've diffed some of the non-BigInt and BigInt files against each other and different formatting was a nuisance.) Test files using `$262.agent.monotonicNow()`: - Moved `$262.agent.report()` calls outside of the block of code measured `$262.agent.monotonicNow()` to avoid measuring how long it takes to execute `$262.agent.report()`. - Without this change some tests failed intermittently in certain test configurations in SpiderMonkey. For example with the flags `--ion-eager -- ion-offthread-compile=off` which forces early Ion compilation on the main thread. The `$262.agent.report()` implementation in the SpiderMonkey test262 host embedding uses a for-loop which was forcefully Ion compiled under these settings. And because Ion compilation can take some time, the test case ran longer than `$262.agent.MAX_TIME_EPSILON` which lead to intermittent failures. Test files using `CanBlockIsFalse` / `CanBlockIsTrue`: - Some of these tests actually expected that the main thread can wait and [[CanBlock]] is `true` for the agent record executing the test. Therefore I've added a new `CanBlockIsTrue` flag and replaced the flags where needed. test/built-ins/Atomics/wait/**/*.js and test/built-ins/Atomics/wake/**/*.js: - Use an atomic counter `RUNNING` in more tests to have better control when a worker agent was actually started. - Replace the various `$262.agent.sleep(/* Sleep X ms to ensure worker actually sleeps */)` calls with the new `$262.agent.tryYield()` function. This `X` was sometimes as low as 10 milliseconds, which is definitely too short for CI systems under heavy load (observed by intermittent CI failures for SpiderMonkey) and sometimes as high as 500 milliseconds, which is probably much longer than needed even when the system is under heavy load. - Removed duplicate strings in assertion messages, presumably from copy-pasting the messages between different files. - Removed extra empty lines at the end of multiple files. test/built-ins/Atomics/wake/bad-range.js, test/built-ins/Atomics/wake/bigint/bad-range.js, and test/built-ins/Atomics/wait/bigint/non-bigint64-typedarray-throws.js: - Removed unnecessary `features` and `includes` from this file. test/built-ins/Atomics/wait/waiterlist-order-of-operations-is-fifo.js and test/built-ins/Atomics/wait/bigint/waiterlist-order-of-operations-is-fifo.js: - The test was actually broken and didn't test what it said it does. This probably explains #1530. - The test wants to ensure the waiterlist is implemented as a FIFO structure. This requires that the waiting agents all wait on the same index position, because the waiterlists are defined by each index. But if the agents wait on different indices, each agent is inserted into a different FIFO structure and therefore we can't observe any FIFO ordering between the agents when they're woken up. - All this requires a bit of synchronization between the main agent and the waiting agent, I hope the added comments help to review these changes. test/built-ins/Atomics/wait/good-views.js: - The agent sends multiple reports to the main agent, but only the first one was read. - This error was introduced during previous refactorings. I've changed it to back to use a while-loop as used in the first version of this file. test/built-ins/Atomics/wait/no-spurious-wakeup-no-operation.js: - Only the BigInt version of this test was present, copied it so we also get code coverage for the non-BigInt case. test/built-ins/Atomics/wait/waiterlist-block-indexedposition-wake.js: - Added extra while loops to avoid intermittent failures when the agent worker haven't started to wait. - This should help to avoid some of the intermittent failures we saw for SpiderMonkey. test/built-ins/Atomics/wake/wake-all-on-loc.js and test/built-ins/Atomics/wake/bigint/wake-all-on-loc.js: - This test was also no longer after previous refactoring sessions. - The "B" agent only waited for 10 milliseconds, which made it likely that it already timed out before the main agent was able to call `Atomics.wake`, which in turn rendered the test useless, because the test case wants to ensure that `Atomics.wake` cannot wake "B". But if "B" was already timed out, it can trivially not be woken by `Atomics.wake`. - Added some safety measure to catch the case when "B" timed out before `Atomics.wake` was called and made it a test error if that happens. test/built-ins/Atomics/wake/count-defaults-to-infinity-missing.js, test/built-ins/Atomics/wake/count-defaults-to-infinity-undefined.js, and test/built-ins/Atomics/wake/undefined-index-defaults-to-zero.js: - Changed the `$262.agent.start()` calls to use a for-loop to avoid code duplication. - (Forgot to undo the code formatting around `assert.sameValue`, still need to change it back.) - Also more while-loops around `Atomics.wake`. - These changes should fix #1529 and #1566. test/built-ins/Atomics/wake/wake-all.js: - Removed "B" worker agent. - Without this removal the test case would be exactly equal to test/built-ins/Atomics/wake/wake-all-on-loc.js. test/built-ins/Atomics/wake/wake-in-order-one-time.js: - Add for-loops to avoid code duplication and make the test more readable. - Make the `Atomics.wake` assertion messages unique by adding the current loop counter. - Add `$262.agent.tryYield()` to give the worker agents enough time to actually start waiting. test/built-ins/Atomics/wake/wake-in-order.js: - Removed the outer loop `attempt < 10` because it uses `$262.agent` in a way currently not required to work. And which actually also doesn't work in SpiderMonkey's implementation of `$262.agent`. - According to INTERPRETING.md `$262.agent.broadcast()` broadcasts its message to all agents ever started by `$262.agent.start()` and then blocks until all agents received the broadcast. It is not required that the agents started by the first `$262.agent.broadcast()` call will all be disabled/destroyed/whatever when the second `$262.agent.broadcast()` call occurs, which then means the second `$262.agent.broadcast()` call still tries to reach the agents started in the first loop iteration, but these may no longer accept broadcasts and therefore won't acknowledge they've received the broadcast. Which then means the second `$262.agent.broadcast()` call waits forever.
2018-07-03 18:34:54 +02:00
*
* // 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);
Make Atomics tests more resilient against intermittent failures (#1617) Also fixes multiple issues and bugs in various Atomics tests. CONTRIBUTING.md and INTERPRETING.md: - Add missing description for `CanBlockIsFalse` flag and also introduce `CanBlockIsTrue` flag which is needed for some tests (see below). harness/atomicsHelper.js: - Updated `$262.agent.waitUntil` to clarify it can also be called with BigInt64Array objects. - Added `$262.agent.timeouts` constants to unify the various, inconsistently used timeouts in the Atomics tests. Each timeout constant has a brief description and a usage example to clarify when it should or should not be used. The default values were tested in SpiderMonkey (locally and CI) under various system load levels and should hopefully also be valid for other engines. - Added `$262.agent.tryYield` to yield control from the main thread. The default implementation simply calls `$262.agent.sleep`, but test262 hosts could theoretically provide a different implementation. - Added `$262.agent.trySleep` to replace direct calls to `$262.agent.sleep` from the main thread. Motivation for this function: Some test262 hosts (like browsers) may be able to pause and sleep on the main thread, so they could provide their implementation for `trySleep` which performs a busy-wait or something do nothing. harness/testAtomics.js: - Replace `let`, `arrow-functions`, and `for-of` loops to avoid creating extremely long `features` lists in tests using this helper. Removed `Map`, `WeakMap`, `Set`, and `WeakSet` (these weren't even listed in features.yaml) for the same reason and added the missing `Symbol` entry for this file to features.yaml. - Updated all files including "harness/testAtomics.js" to match the new feature requirements. test/built-ins/Atomics/store/good-views.js and test/built-ins/Atomics/store/bigint/good-views.js: - Replace `arrow-functions` and `for-of` loops with ES5 alternatives. test/built-ins/Atomics/wait/bigint/*.js and test/built-ins/Atomics/wake/bigint/*.js - Some tests were using `BigInt64Array.BYTES_PER_ELEMENT * 8` for the SharedArrayBuffer length, but their non-BigInt counterparts are using `Int32Array.BYTES_PER_ELEMENT * 4`. For consistency and to make it easier to compare the BigInt against the non-BigInt versions, I've changed it to `BigInt64Array.BYTES_PER_ELEMENT * 4`. - Also aligned formatting and statement placement when they differed between the non-BigInt and the BigInt version of a test file. (I've diffed some of the non-BigInt and BigInt files against each other and different formatting was a nuisance.) Test files using `$262.agent.monotonicNow()`: - Moved `$262.agent.report()` calls outside of the block of code measured `$262.agent.monotonicNow()` to avoid measuring how long it takes to execute `$262.agent.report()`. - Without this change some tests failed intermittently in certain test configurations in SpiderMonkey. For example with the flags `--ion-eager -- ion-offthread-compile=off` which forces early Ion compilation on the main thread. The `$262.agent.report()` implementation in the SpiderMonkey test262 host embedding uses a for-loop which was forcefully Ion compiled under these settings. And because Ion compilation can take some time, the test case ran longer than `$262.agent.MAX_TIME_EPSILON` which lead to intermittent failures. Test files using `CanBlockIsFalse` / `CanBlockIsTrue`: - Some of these tests actually expected that the main thread can wait and [[CanBlock]] is `true` for the agent record executing the test. Therefore I've added a new `CanBlockIsTrue` flag and replaced the flags where needed. test/built-ins/Atomics/wait/**/*.js and test/built-ins/Atomics/wake/**/*.js: - Use an atomic counter `RUNNING` in more tests to have better control when a worker agent was actually started. - Replace the various `$262.agent.sleep(/* Sleep X ms to ensure worker actually sleeps */)` calls with the new `$262.agent.tryYield()` function. This `X` was sometimes as low as 10 milliseconds, which is definitely too short for CI systems under heavy load (observed by intermittent CI failures for SpiderMonkey) and sometimes as high as 500 milliseconds, which is probably much longer than needed even when the system is under heavy load. - Removed duplicate strings in assertion messages, presumably from copy-pasting the messages between different files. - Removed extra empty lines at the end of multiple files. test/built-ins/Atomics/wake/bad-range.js, test/built-ins/Atomics/wake/bigint/bad-range.js, and test/built-ins/Atomics/wait/bigint/non-bigint64-typedarray-throws.js: - Removed unnecessary `features` and `includes` from this file. test/built-ins/Atomics/wait/waiterlist-order-of-operations-is-fifo.js and test/built-ins/Atomics/wait/bigint/waiterlist-order-of-operations-is-fifo.js: - The test was actually broken and didn't test what it said it does. This probably explains #1530. - The test wants to ensure the waiterlist is implemented as a FIFO structure. This requires that the waiting agents all wait on the same index position, because the waiterlists are defined by each index. But if the agents wait on different indices, each agent is inserted into a different FIFO structure and therefore we can't observe any FIFO ordering between the agents when they're woken up. - All this requires a bit of synchronization between the main agent and the waiting agent, I hope the added comments help to review these changes. test/built-ins/Atomics/wait/good-views.js: - The agent sends multiple reports to the main agent, but only the first one was read. - This error was introduced during previous refactorings. I've changed it to back to use a while-loop as used in the first version of this file. test/built-ins/Atomics/wait/no-spurious-wakeup-no-operation.js: - Only the BigInt version of this test was present, copied it so we also get code coverage for the non-BigInt case. test/built-ins/Atomics/wait/waiterlist-block-indexedposition-wake.js: - Added extra while loops to avoid intermittent failures when the agent worker haven't started to wait. - This should help to avoid some of the intermittent failures we saw for SpiderMonkey. test/built-ins/Atomics/wake/wake-all-on-loc.js and test/built-ins/Atomics/wake/bigint/wake-all-on-loc.js: - This test was also no longer after previous refactoring sessions. - The "B" agent only waited for 10 milliseconds, which made it likely that it already timed out before the main agent was able to call `Atomics.wake`, which in turn rendered the test useless, because the test case wants to ensure that `Atomics.wake` cannot wake "B". But if "B" was already timed out, it can trivially not be woken by `Atomics.wake`. - Added some safety measure to catch the case when "B" timed out before `Atomics.wake` was called and made it a test error if that happens. test/built-ins/Atomics/wake/count-defaults-to-infinity-missing.js, test/built-ins/Atomics/wake/count-defaults-to-infinity-undefined.js, and test/built-ins/Atomics/wake/undefined-index-defaults-to-zero.js: - Changed the `$262.agent.start()` calls to use a for-loop to avoid code duplication. - (Forgot to undo the code formatting around `assert.sameValue`, still need to change it back.) - Also more while-loops around `Atomics.wake`. - These changes should fix #1529 and #1566. test/built-ins/Atomics/wake/wake-all.js: - Removed "B" worker agent. - Without this removal the test case would be exactly equal to test/built-ins/Atomics/wake/wake-all-on-loc.js. test/built-ins/Atomics/wake/wake-in-order-one-time.js: - Add for-loops to avoid code duplication and make the test more readable. - Make the `Atomics.wake` assertion messages unique by adding the current loop counter. - Add `$262.agent.tryYield()` to give the worker agents enough time to actually start waiting. test/built-ins/Atomics/wake/wake-in-order.js: - Removed the outer loop `attempt < 10` because it uses `$262.agent` in a way currently not required to work. And which actually also doesn't work in SpiderMonkey's implementation of `$262.agent`. - According to INTERPRETING.md `$262.agent.broadcast()` broadcasts its message to all agents ever started by `$262.agent.start()` and then blocks until all agents received the broadcast. It is not required that the agents started by the first `$262.agent.broadcast()` call will all be disabled/destroyed/whatever when the second `$262.agent.broadcast()` call occurs, which then means the second `$262.agent.broadcast()` call still tries to reach the agents started in the first loop iteration, but these may no longer accept broadcasts and therefore won't acknowledge they've received the broadcast. Which then means the second `$262.agent.broadcast()` call waits forever.
2018-07-03 18:34:54 +02:00
*
* // 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);
Make Atomics tests more resilient against intermittent failures (#1617) Also fixes multiple issues and bugs in various Atomics tests. CONTRIBUTING.md and INTERPRETING.md: - Add missing description for `CanBlockIsFalse` flag and also introduce `CanBlockIsTrue` flag which is needed for some tests (see below). harness/atomicsHelper.js: - Updated `$262.agent.waitUntil` to clarify it can also be called with BigInt64Array objects. - Added `$262.agent.timeouts` constants to unify the various, inconsistently used timeouts in the Atomics tests. Each timeout constant has a brief description and a usage example to clarify when it should or should not be used. The default values were tested in SpiderMonkey (locally and CI) under various system load levels and should hopefully also be valid for other engines. - Added `$262.agent.tryYield` to yield control from the main thread. The default implementation simply calls `$262.agent.sleep`, but test262 hosts could theoretically provide a different implementation. - Added `$262.agent.trySleep` to replace direct calls to `$262.agent.sleep` from the main thread. Motivation for this function: Some test262 hosts (like browsers) may be able to pause and sleep on the main thread, so they could provide their implementation for `trySleep` which performs a busy-wait or something do nothing. harness/testAtomics.js: - Replace `let`, `arrow-functions`, and `for-of` loops to avoid creating extremely long `features` lists in tests using this helper. Removed `Map`, `WeakMap`, `Set`, and `WeakSet` (these weren't even listed in features.yaml) for the same reason and added the missing `Symbol` entry for this file to features.yaml. - Updated all files including "harness/testAtomics.js" to match the new feature requirements. test/built-ins/Atomics/store/good-views.js and test/built-ins/Atomics/store/bigint/good-views.js: - Replace `arrow-functions` and `for-of` loops with ES5 alternatives. test/built-ins/Atomics/wait/bigint/*.js and test/built-ins/Atomics/wake/bigint/*.js - Some tests were using `BigInt64Array.BYTES_PER_ELEMENT * 8` for the SharedArrayBuffer length, but their non-BigInt counterparts are using `Int32Array.BYTES_PER_ELEMENT * 4`. For consistency and to make it easier to compare the BigInt against the non-BigInt versions, I've changed it to `BigInt64Array.BYTES_PER_ELEMENT * 4`. - Also aligned formatting and statement placement when they differed between the non-BigInt and the BigInt version of a test file. (I've diffed some of the non-BigInt and BigInt files against each other and different formatting was a nuisance.) Test files using `$262.agent.monotonicNow()`: - Moved `$262.agent.report()` calls outside of the block of code measured `$262.agent.monotonicNow()` to avoid measuring how long it takes to execute `$262.agent.report()`. - Without this change some tests failed intermittently in certain test configurations in SpiderMonkey. For example with the flags `--ion-eager -- ion-offthread-compile=off` which forces early Ion compilation on the main thread. The `$262.agent.report()` implementation in the SpiderMonkey test262 host embedding uses a for-loop which was forcefully Ion compiled under these settings. And because Ion compilation can take some time, the test case ran longer than `$262.agent.MAX_TIME_EPSILON` which lead to intermittent failures. Test files using `CanBlockIsFalse` / `CanBlockIsTrue`: - Some of these tests actually expected that the main thread can wait and [[CanBlock]] is `true` for the agent record executing the test. Therefore I've added a new `CanBlockIsTrue` flag and replaced the flags where needed. test/built-ins/Atomics/wait/**/*.js and test/built-ins/Atomics/wake/**/*.js: - Use an atomic counter `RUNNING` in more tests to have better control when a worker agent was actually started. - Replace the various `$262.agent.sleep(/* Sleep X ms to ensure worker actually sleeps */)` calls with the new `$262.agent.tryYield()` function. This `X` was sometimes as low as 10 milliseconds, which is definitely too short for CI systems under heavy load (observed by intermittent CI failures for SpiderMonkey) and sometimes as high as 500 milliseconds, which is probably much longer than needed even when the system is under heavy load. - Removed duplicate strings in assertion messages, presumably from copy-pasting the messages between different files. - Removed extra empty lines at the end of multiple files. test/built-ins/Atomics/wake/bad-range.js, test/built-ins/Atomics/wake/bigint/bad-range.js, and test/built-ins/Atomics/wait/bigint/non-bigint64-typedarray-throws.js: - Removed unnecessary `features` and `includes` from this file. test/built-ins/Atomics/wait/waiterlist-order-of-operations-is-fifo.js and test/built-ins/Atomics/wait/bigint/waiterlist-order-of-operations-is-fifo.js: - The test was actually broken and didn't test what it said it does. This probably explains #1530. - The test wants to ensure the waiterlist is implemented as a FIFO structure. This requires that the waiting agents all wait on the same index position, because the waiterlists are defined by each index. But if the agents wait on different indices, each agent is inserted into a different FIFO structure and therefore we can't observe any FIFO ordering between the agents when they're woken up. - All this requires a bit of synchronization between the main agent and the waiting agent, I hope the added comments help to review these changes. test/built-ins/Atomics/wait/good-views.js: - The agent sends multiple reports to the main agent, but only the first one was read. - This error was introduced during previous refactorings. I've changed it to back to use a while-loop as used in the first version of this file. test/built-ins/Atomics/wait/no-spurious-wakeup-no-operation.js: - Only the BigInt version of this test was present, copied it so we also get code coverage for the non-BigInt case. test/built-ins/Atomics/wait/waiterlist-block-indexedposition-wake.js: - Added extra while loops to avoid intermittent failures when the agent worker haven't started to wait. - This should help to avoid some of the intermittent failures we saw for SpiderMonkey. test/built-ins/Atomics/wake/wake-all-on-loc.js and test/built-ins/Atomics/wake/bigint/wake-all-on-loc.js: - This test was also no longer after previous refactoring sessions. - The "B" agent only waited for 10 milliseconds, which made it likely that it already timed out before the main agent was able to call `Atomics.wake`, which in turn rendered the test useless, because the test case wants to ensure that `Atomics.wake` cannot wake "B". But if "B" was already timed out, it can trivially not be woken by `Atomics.wake`. - Added some safety measure to catch the case when "B" timed out before `Atomics.wake` was called and made it a test error if that happens. test/built-ins/Atomics/wake/count-defaults-to-infinity-missing.js, test/built-ins/Atomics/wake/count-defaults-to-infinity-undefined.js, and test/built-ins/Atomics/wake/undefined-index-defaults-to-zero.js: - Changed the `$262.agent.start()` calls to use a for-loop to avoid code duplication. - (Forgot to undo the code formatting around `assert.sameValue`, still need to change it back.) - Also more while-loops around `Atomics.wake`. - These changes should fix #1529 and #1566. test/built-ins/Atomics/wake/wake-all.js: - Removed "B" worker agent. - Without this removal the test case would be exactly equal to test/built-ins/Atomics/wake/wake-all-on-loc.js. test/built-ins/Atomics/wake/wake-in-order-one-time.js: - Add for-loops to avoid code duplication and make the test more readable. - Make the `Atomics.wake` assertion messages unique by adding the current loop counter. - Add `$262.agent.tryYield()` to give the worker agents enough time to actually start waiting. test/built-ins/Atomics/wake/wake-in-order.js: - Removed the outer loop `attempt < 10` because it uses `$262.agent` in a way currently not required to work. And which actually also doesn't work in SpiderMonkey's implementation of `$262.agent`. - According to INTERPRETING.md `$262.agent.broadcast()` broadcasts its message to all agents ever started by `$262.agent.start()` and then blocks until all agents received the broadcast. It is not required that the agents started by the first `$262.agent.broadcast()` call will all be disabled/destroyed/whatever when the second `$262.agent.broadcast()` call occurs, which then means the second `$262.agent.broadcast()` call still tries to reach the agents started in the first loop iteration, but these may no longer accept broadcasts and therefore won't acknowledge they've received the broadcast. Which then means the second `$262.agent.broadcast()` call waits forever.
2018-07-03 18:34:54 +02:00
*
* // 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);
Make Atomics tests more resilient against intermittent failures (#1617) Also fixes multiple issues and bugs in various Atomics tests. CONTRIBUTING.md and INTERPRETING.md: - Add missing description for `CanBlockIsFalse` flag and also introduce `CanBlockIsTrue` flag which is needed for some tests (see below). harness/atomicsHelper.js: - Updated `$262.agent.waitUntil` to clarify it can also be called with BigInt64Array objects. - Added `$262.agent.timeouts` constants to unify the various, inconsistently used timeouts in the Atomics tests. Each timeout constant has a brief description and a usage example to clarify when it should or should not be used. The default values were tested in SpiderMonkey (locally and CI) under various system load levels and should hopefully also be valid for other engines. - Added `$262.agent.tryYield` to yield control from the main thread. The default implementation simply calls `$262.agent.sleep`, but test262 hosts could theoretically provide a different implementation. - Added `$262.agent.trySleep` to replace direct calls to `$262.agent.sleep` from the main thread. Motivation for this function: Some test262 hosts (like browsers) may be able to pause and sleep on the main thread, so they could provide their implementation for `trySleep` which performs a busy-wait or something do nothing. harness/testAtomics.js: - Replace `let`, `arrow-functions`, and `for-of` loops to avoid creating extremely long `features` lists in tests using this helper. Removed `Map`, `WeakMap`, `Set`, and `WeakSet` (these weren't even listed in features.yaml) for the same reason and added the missing `Symbol` entry for this file to features.yaml. - Updated all files including "harness/testAtomics.js" to match the new feature requirements. test/built-ins/Atomics/store/good-views.js and test/built-ins/Atomics/store/bigint/good-views.js: - Replace `arrow-functions` and `for-of` loops with ES5 alternatives. test/built-ins/Atomics/wait/bigint/*.js and test/built-ins/Atomics/wake/bigint/*.js - Some tests were using `BigInt64Array.BYTES_PER_ELEMENT * 8` for the SharedArrayBuffer length, but their non-BigInt counterparts are using `Int32Array.BYTES_PER_ELEMENT * 4`. For consistency and to make it easier to compare the BigInt against the non-BigInt versions, I've changed it to `BigInt64Array.BYTES_PER_ELEMENT * 4`. - Also aligned formatting and statement placement when they differed between the non-BigInt and the BigInt version of a test file. (I've diffed some of the non-BigInt and BigInt files against each other and different formatting was a nuisance.) Test files using `$262.agent.monotonicNow()`: - Moved `$262.agent.report()` calls outside of the block of code measured `$262.agent.monotonicNow()` to avoid measuring how long it takes to execute `$262.agent.report()`. - Without this change some tests failed intermittently in certain test configurations in SpiderMonkey. For example with the flags `--ion-eager -- ion-offthread-compile=off` which forces early Ion compilation on the main thread. The `$262.agent.report()` implementation in the SpiderMonkey test262 host embedding uses a for-loop which was forcefully Ion compiled under these settings. And because Ion compilation can take some time, the test case ran longer than `$262.agent.MAX_TIME_EPSILON` which lead to intermittent failures. Test files using `CanBlockIsFalse` / `CanBlockIsTrue`: - Some of these tests actually expected that the main thread can wait and [[CanBlock]] is `true` for the agent record executing the test. Therefore I've added a new `CanBlockIsTrue` flag and replaced the flags where needed. test/built-ins/Atomics/wait/**/*.js and test/built-ins/Atomics/wake/**/*.js: - Use an atomic counter `RUNNING` in more tests to have better control when a worker agent was actually started. - Replace the various `$262.agent.sleep(/* Sleep X ms to ensure worker actually sleeps */)` calls with the new `$262.agent.tryYield()` function. This `X` was sometimes as low as 10 milliseconds, which is definitely too short for CI systems under heavy load (observed by intermittent CI failures for SpiderMonkey) and sometimes as high as 500 milliseconds, which is probably much longer than needed even when the system is under heavy load. - Removed duplicate strings in assertion messages, presumably from copy-pasting the messages between different files. - Removed extra empty lines at the end of multiple files. test/built-ins/Atomics/wake/bad-range.js, test/built-ins/Atomics/wake/bigint/bad-range.js, and test/built-ins/Atomics/wait/bigint/non-bigint64-typedarray-throws.js: - Removed unnecessary `features` and `includes` from this file. test/built-ins/Atomics/wait/waiterlist-order-of-operations-is-fifo.js and test/built-ins/Atomics/wait/bigint/waiterlist-order-of-operations-is-fifo.js: - The test was actually broken and didn't test what it said it does. This probably explains #1530. - The test wants to ensure the waiterlist is implemented as a FIFO structure. This requires that the waiting agents all wait on the same index position, because the waiterlists are defined by each index. But if the agents wait on different indices, each agent is inserted into a different FIFO structure and therefore we can't observe any FIFO ordering between the agents when they're woken up. - All this requires a bit of synchronization between the main agent and the waiting agent, I hope the added comments help to review these changes. test/built-ins/Atomics/wait/good-views.js: - The agent sends multiple reports to the main agent, but only the first one was read. - This error was introduced during previous refactorings. I've changed it to back to use a while-loop as used in the first version of this file. test/built-ins/Atomics/wait/no-spurious-wakeup-no-operation.js: - Only the BigInt version of this test was present, copied it so we also get code coverage for the non-BigInt case. test/built-ins/Atomics/wait/waiterlist-block-indexedposition-wake.js: - Added extra while loops to avoid intermittent failures when the agent worker haven't started to wait. - This should help to avoid some of the intermittent failures we saw for SpiderMonkey. test/built-ins/Atomics/wake/wake-all-on-loc.js and test/built-ins/Atomics/wake/bigint/wake-all-on-loc.js: - This test was also no longer after previous refactoring sessions. - The "B" agent only waited for 10 milliseconds, which made it likely that it already timed out before the main agent was able to call `Atomics.wake`, which in turn rendered the test useless, because the test case wants to ensure that `Atomics.wake` cannot wake "B". But if "B" was already timed out, it can trivially not be woken by `Atomics.wake`. - Added some safety measure to catch the case when "B" timed out before `Atomics.wake` was called and made it a test error if that happens. test/built-ins/Atomics/wake/count-defaults-to-infinity-missing.js, test/built-ins/Atomics/wake/count-defaults-to-infinity-undefined.js, and test/built-ins/Atomics/wake/undefined-index-defaults-to-zero.js: - Changed the `$262.agent.start()` calls to use a for-loop to avoid code duplication. - (Forgot to undo the code formatting around `assert.sameValue`, still need to change it back.) - Also more while-loops around `Atomics.wake`. - These changes should fix #1529 and #1566. test/built-ins/Atomics/wake/wake-all.js: - Removed "B" worker agent. - Without this removal the test case would be exactly equal to test/built-ins/Atomics/wake/wake-all-on-loc.js. test/built-ins/Atomics/wake/wake-in-order-one-time.js: - Add for-loops to avoid code duplication and make the test more readable. - Make the `Atomics.wake` assertion messages unique by adding the current loop counter. - Add `$262.agent.tryYield()` to give the worker agents enough time to actually start waiting. test/built-ins/Atomics/wake/wake-in-order.js: - Removed the outer loop `attempt < 10` because it uses `$262.agent` in a way currently not required to work. And which actually also doesn't work in SpiderMonkey's implementation of `$262.agent`. - According to INTERPRETING.md `$262.agent.broadcast()` broadcasts its message to all agents ever started by `$262.agent.start()` and then blocks until all agents received the broadcast. It is not required that the agents started by the first `$262.agent.broadcast()` call will all be disabled/destroyed/whatever when the second `$262.agent.broadcast()` call occurs, which then means the second `$262.agent.broadcast()` call still tries to reach the agents started in the first loop iteration, but these may no longer accept broadcasts and therefore won't acknowledge they've received the broadcast. Which then means the second `$262.agent.broadcast()` call waits forever.
2018-07-03 18:34:54 +02:00
*
* // 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);
};