shell.js (11923B)
1 // GENERATED, DO NOT EDIT 2 // file: atomicsHelper.js 3 // Copyright (C) 2017 Mozilla Corporation. All rights reserved. 4 // This code is governed by the BSD license found in the LICENSE file. 5 /*--- 6 description: > 7 Collection of functions used to interact with Atomics.* operations across agent boundaries. 8 defines: 9 - $262.agent.getReportAsync 10 - $262.agent.getReport 11 - $262.agent.safeBroadcastAsync 12 - $262.agent.safeBroadcast 13 - $262.agent.setTimeout 14 - $262.agent.tryYield 15 - $262.agent.trySleep 16 ---*/ 17 18 /** 19 * @return {String} A report sent from an agent. 20 */ 21 { 22 // This is only necessary because the original 23 // $262.agent.getReport API was insufficient. 24 // 25 // All runtimes currently have their own 26 // $262.agent.getReport which is wrong, so we 27 // will pave over it with a corrected version. 28 // 29 // Binding $262.agent is necessary to prevent 30 // breaking SpiderMonkey's $262.agent.getReport 31 let getReport = $262.agent.getReport.bind($262.agent); 32 33 $262.agent.getReport = function() { 34 var r; 35 while ((r = getReport()) == null) { 36 $262.agent.sleep(1); 37 } 38 return r; 39 }; 40 41 if (this.setTimeout === undefined) { 42 (function(that) { 43 that.setTimeout = function(callback, delay) { 44 let p = Promise.resolve(); 45 let start = Date.now(); 46 let end = start + delay; 47 function check() { 48 if ((end - Date.now()) > 0) { 49 p.then(check); 50 } 51 else { 52 callback(); 53 } 54 } 55 p.then(check); 56 } 57 })(this); 58 } 59 60 $262.agent.setTimeout = setTimeout; 61 62 $262.agent.getReportAsync = function() { 63 return new Promise(function(resolve) { 64 (function loop() { 65 let result = getReport(); 66 if (!result) { 67 setTimeout(loop, 1000); 68 } else { 69 resolve(result); 70 } 71 })(); 72 }); 73 }; 74 } 75 76 /** 77 * 78 * Share a given Int32Array or BigInt64Array to all running agents. Ensure that the 79 * provided TypedArray is a "shared typed array". 80 * 81 * NOTE: Migrating all tests to this API is necessary to prevent tests from hanging 82 * indefinitely when a SAB is sent to a worker but the code in the worker attempts to 83 * create a non-sharable TypedArray (something that is not Int32Array or BigInt64Array). 84 * When that scenario occurs, an exception is thrown and the agent worker can no 85 * longer communicate with any other threads that control the SAB. If the main 86 * thread happens to be spinning in the $262.agent.waitUntil() while loop, it will never 87 * meet its termination condition and the test will hang indefinitely. 88 * 89 * Because we've defined $262.agent.broadcast(SAB) in 90 * https://github.com/tc39/test262/blob/HEAD/INTERPRETING.md, there are host implementations 91 * that assume compatibility, which must be maintained. 92 * 93 * 94 * $262.agent.safeBroadcast(TA) should not be included in 95 * https://github.com/tc39/test262/blob/HEAD/INTERPRETING.md 96 * 97 * 98 * @param {(Int32Array|BigInt64Array)} typedArray An Int32Array or BigInt64Array with a SharedArrayBuffer 99 */ 100 $262.agent.safeBroadcast = function(typedArray) { 101 let Constructor = Object.getPrototypeOf(typedArray).constructor; 102 let temp = new Constructor( 103 new SharedArrayBuffer(Constructor.BYTES_PER_ELEMENT) 104 ); 105 try { 106 // This will never actually wait, but that's fine because we only 107 // want to ensure that this typedArray CAN be waited on and is shareable. 108 Atomics.wait(temp, 0, Constructor === Int32Array ? 1 : BigInt(1)); 109 } catch (error) { 110 throw new Test262Error(`${Constructor.name} cannot be used as a shared typed array. (${error})`); 111 } 112 113 $262.agent.broadcast(typedArray.buffer); 114 }; 115 116 $262.agent.safeBroadcastAsync = async function(ta, index, expected) { 117 await $262.agent.broadcast(ta.buffer); 118 await $262.agent.waitUntil(ta, index, expected); 119 await $262.agent.tryYield(); 120 return await Atomics.load(ta, index); 121 }; 122 123 124 /** 125 * With a given Int32Array or BigInt64Array, wait until the expected number of agents have 126 * reported themselves by calling: 127 * 128 * Atomics.add(typedArray, index, 1); 129 * 130 * @param {(Int32Array|BigInt64Array)} typedArray An Int32Array or BigInt64Array with a SharedArrayBuffer 131 * @param {number} index The index of which all agents will report. 132 * @param {number} expected The number of agents that are expected to report as active. 133 */ 134 $262.agent.waitUntil = function(typedArray, index, expected) { 135 136 var agents = 0; 137 while ((agents = Atomics.load(typedArray, index)) !== expected) { 138 /* nothing */ 139 } 140 assert.sameValue(agents, expected, "Reporting number of 'agents' equals the value of 'expected'"); 141 }; 142 143 /** 144 * Timeout values used throughout the Atomics tests. All timeouts are specified in milliseconds. 145 * 146 * @property {number} yield Used for `$262.agent.tryYield`. Must not be used in other functions. 147 * @property {number} small Used when agents will always timeout and `Atomics.wake` is not part 148 * of the test semantics. Must be larger than `$262.agent.timeouts.yield`. 149 * @property {number} long Used when some agents may timeout and `Atomics.wake` is called on some 150 * agents. The agents are required to wait and this needs to be observable 151 * by the main thread. 152 * @property {number} huge Used when `Atomics.wake` is called on all waiting agents. The waiting 153 * must not timeout. The agents are required to wait and this needs to be 154 * observable by the main thread. All waiting agents must be woken by the 155 * main thread. 156 * 157 * Usage for `$262.agent.timeouts.small`: 158 * const WAIT_INDEX = 0; 159 * const RUNNING = 1; 160 * const TIMEOUT = $262.agent.timeouts.small; 161 * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); 162 * 163 * $262.agent.start(` 164 * $262.agent.receiveBroadcast(function(sab) { 165 * const i32a = new Int32Array(sab); 166 * Atomics.add(i32a, ${RUNNING}, 1); 167 * 168 * $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); 169 * 170 * $262.agent.leaving(); 171 * }); 172 * `); 173 * $262.agent.safeBroadcast(i32a.buffer); 174 * 175 * // Wait until the agent was started and then try to yield control to increase 176 * // the likelihood the agent has called `Atomics.wait` and is now waiting. 177 * $262.agent.waitUntil(i32a, RUNNING, 1); 178 * $262.agent.tryYield(); 179 * 180 * // The agent is expected to time out. 181 * assert.sameValue($262.agent.getReport(), "timed-out"); 182 * 183 * 184 * Usage for `$262.agent.timeouts.long`: 185 * const WAIT_INDEX = 0; 186 * const RUNNING = 1; 187 * const NUMAGENT = 2; 188 * const TIMEOUT = $262.agent.timeouts.long; 189 * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); 190 * 191 * for (let i = 0; i < NUMAGENT; i++) { 192 * $262.agent.start(` 193 * $262.agent.receiveBroadcast(function(sab) { 194 * const i32a = new Int32Array(sab); 195 * Atomics.add(i32a, ${RUNNING}, 1); 196 * 197 * $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); 198 * 199 * $262.agent.leaving(); 200 * }); 201 * `); 202 * } 203 * $262.agent.safeBroadcast(i32a.buffer); 204 * 205 * // Wait until the agents were started and then try to yield control to increase 206 * // the likelihood the agents have called `Atomics.wait` and are now waiting. 207 * $262.agent.waitUntil(i32a, RUNNING, NUMAGENT); 208 * $262.agent.tryYield(); 209 * 210 * // Wake exactly one agent. 211 * assert.sameValue(Atomics.wake(i32a, WAIT_INDEX, 1), 1); 212 * 213 * // When it doesn't matter how many agents were woken at once, a while loop 214 * // can be used to make the test more resilient against intermittent failures 215 * // in case even though `tryYield` was called, the agents haven't started to 216 * // wait. 217 * // 218 * // // Repeat until exactly one agent was woken. 219 * // var woken = 0; 220 * // while ((woken = Atomics.wake(i32a, WAIT_INDEX, 1)) !== 0) ; 221 * // assert.sameValue(woken, 1); 222 * 223 * // One agent was woken and the other one timed out. 224 * const reports = [$262.agent.getReport(), $262.agent.getReport()]; 225 * assert(reports.includes("ok")); 226 * assert(reports.includes("timed-out")); 227 * 228 * 229 * Usage for `$262.agent.timeouts.huge`: 230 * const WAIT_INDEX = 0; 231 * const RUNNING = 1; 232 * const NUMAGENT = 2; 233 * const TIMEOUT = $262.agent.timeouts.huge; 234 * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); 235 * 236 * for (let i = 0; i < NUMAGENT; i++) { 237 * $262.agent.start(` 238 * $262.agent.receiveBroadcast(function(sab) { 239 * const i32a = new Int32Array(sab); 240 * Atomics.add(i32a, ${RUNNING}, 1); 241 * 242 * $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); 243 * 244 * $262.agent.leaving(); 245 * }); 246 * `); 247 * } 248 * $262.agent.safeBroadcast(i32a.buffer); 249 * 250 * // Wait until the agents were started and then try to yield control to increase 251 * // the likelihood the agents have called `Atomics.wait` and are now waiting. 252 * $262.agent.waitUntil(i32a, RUNNING, NUMAGENT); 253 * $262.agent.tryYield(); 254 * 255 * // Wake all agents. 256 * assert.sameValue(Atomics.wake(i32a, WAIT_INDEX), NUMAGENT); 257 * 258 * // When it doesn't matter how many agents were woken at once, a while loop 259 * // can be used to make the test more resilient against intermittent failures 260 * // in case even though `tryYield` was called, the agents haven't started to 261 * // wait. 262 * // 263 * // // Repeat until all agents were woken. 264 * // for (var wokenCount = 0; wokenCount < NUMAGENT; ) { 265 * // var woken = 0; 266 * // while ((woken = Atomics.wake(i32a, WAIT_INDEX)) !== 0) ; 267 * // // Maybe perform an action on the woken agents here. 268 * // wokenCount += woken; 269 * // } 270 * 271 * // All agents were woken and none timeout. 272 * for (var i = 0; i < NUMAGENT; i++) { 273 * assert($262.agent.getReport(), "ok"); 274 * } 275 */ 276 $262.agent.timeouts = { 277 yield: 100, 278 small: 200, 279 long: 1000, 280 huge: 10000, 281 }; 282 283 /** 284 * Try to yield control to the agent threads. 285 * 286 * Usage: 287 * const VALUE = 0; 288 * const RUNNING = 1; 289 * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); 290 * 291 * $262.agent.start(` 292 * $262.agent.receiveBroadcast(function(sab) { 293 * const i32a = new Int32Array(sab); 294 * Atomics.add(i32a, ${RUNNING}, 1); 295 * 296 * Atomics.store(i32a, ${VALUE}, 1); 297 * 298 * $262.agent.leaving(); 299 * }); 300 * `); 301 * $262.agent.safeBroadcast(i32a.buffer); 302 * 303 * // Wait until agent was started and then try to yield control. 304 * $262.agent.waitUntil(i32a, RUNNING, 1); 305 * $262.agent.tryYield(); 306 * 307 * // Note: This result is not guaranteed, but should hold in practice most of the time. 308 * assert.sameValue(Atomics.load(i32a, VALUE), 1); 309 * 310 * The default implementation simply waits for `$262.agent.timeouts.yield` milliseconds. 311 */ 312 $262.agent.tryYield = function() { 313 $262.agent.sleep($262.agent.timeouts.yield); 314 }; 315 316 /** 317 * Try to sleep the current agent for the given amount of milliseconds. It is acceptable, 318 * but not encouraged, to ignore this sleep request and directly continue execution. 319 * 320 * The default implementation calls `$262.agent.sleep(ms)`. 321 * 322 * @param {number} ms Time to sleep in milliseconds. 323 */ 324 $262.agent.trySleep = function(ms) { 325 $262.agent.sleep(ms); 326 }; 327 328 // file: detachArrayBuffer.js 329 // Copyright (C) 2016 the V8 project authors. All rights reserved. 330 // This code is governed by the BSD license found in the LICENSE file. 331 /*--- 332 description: | 333 A function used in the process of asserting correctness of TypedArray objects. 334 335 $262.detachArrayBuffer is defined by a host. 336 defines: [$DETACHBUFFER] 337 ---*/ 338 339 function $DETACHBUFFER(buffer) { 340 if (!$262 || typeof $262.detachArrayBuffer !== "function") { 341 throw new Test262Error("No method available to detach an ArrayBuffer"); 342 } 343 $262.detachArrayBuffer(buffer); 344 }