|  | // Copyright 2017 the V8 project authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | $262.agent = (function () { | 
|  |  | 
|  | var workers = []; | 
|  | var i32a = null; | 
|  | var pendingReports = []; | 
|  |  | 
|  | // Agents call Atomics.wait on this location to sleep. | 
|  | var SLEEP_LOC = 0; | 
|  | // 1 if the started worker is ready, 0 otherwise. | 
|  | var START_LOC = 1; | 
|  | // The number of workers that have received the broadcast. | 
|  | var BROADCAST_LOC = 2; | 
|  | // Each worker has a count of outstanding reports; worker N uses memory | 
|  | // location [WORKER_REPORT_LOC + N]. | 
|  | var WORKER_REPORT_LOC = 3; | 
|  |  | 
|  | function workerScript(script) { | 
|  | return ` | 
|  | var index; | 
|  | var i32a = null; | 
|  | var broadcasts = []; | 
|  | var pendingReceiver = null; | 
|  |  | 
|  | function handleBroadcast() { | 
|  | if (pendingReceiver && broadcasts.length > 0) { | 
|  | pendingReceiver.apply(null, broadcasts.shift()); | 
|  | pendingReceiver = null; | 
|  | } | 
|  | }; | 
|  |  | 
|  | var onmessage = function(msg) { | 
|  | switch (msg.kind) { | 
|  | case 'start': | 
|  | i32a = msg.i32a; | 
|  | index = msg.index; | 
|  | (0, eval)(\`${script}\`); | 
|  | break; | 
|  |  | 
|  | case 'broadcast': | 
|  | Atomics.add(i32a, ${BROADCAST_LOC}, 1); | 
|  | broadcasts.push([msg.sab, msg.id]); | 
|  | handleBroadcast(); | 
|  | break; | 
|  | } | 
|  | }; | 
|  |  | 
|  | var $262 = { | 
|  | agent: { | 
|  | receiveBroadcast(receiver) { | 
|  | pendingReceiver = receiver; | 
|  | handleBroadcast(); | 
|  | }, | 
|  |  | 
|  | report(msg) { | 
|  | postMessage(String(msg)); | 
|  | Atomics.add(i32a, ${WORKER_REPORT_LOC} + index, 1); | 
|  | }, | 
|  |  | 
|  | sleep(s) { Atomics.wait(i32a, ${SLEEP_LOC}, 0, s); }, | 
|  |  | 
|  | leaving() {}, | 
|  |  | 
|  | monotonicNow() { | 
|  | return performance.now(); | 
|  | } | 
|  | } | 
|  | };`; | 
|  | } | 
|  |  | 
|  | var agent = { | 
|  | start(script) { | 
|  | if (i32a === null) { | 
|  | i32a = new Int32Array(new SharedArrayBuffer(256)); | 
|  | } | 
|  | var w = new Worker(workerScript(script), {type: 'string'}); | 
|  | w.index = workers.length; | 
|  | w.postMessage({kind: 'start', i32a: i32a, index: w.index}); | 
|  | workers.push(w); | 
|  | }, | 
|  |  | 
|  | broadcast(sab, id) { | 
|  | if (!(sab instanceof SharedArrayBuffer)) { | 
|  | throw new TypeError('sab must be a SharedArrayBuffer.'); | 
|  | } | 
|  |  | 
|  | Atomics.store(i32a, BROADCAST_LOC, 0); | 
|  |  | 
|  | for (var w of workers) { | 
|  | w.postMessage({kind: 'broadcast', sab: sab, id: id|0}); | 
|  | } | 
|  |  | 
|  | while (Atomics.load(i32a, BROADCAST_LOC) != workers.length) {} | 
|  | }, | 
|  |  | 
|  | getReport() { | 
|  | for (var w of workers) { | 
|  | while (Atomics.load(i32a, WORKER_REPORT_LOC + w.index) > 0) { | 
|  | pendingReports.push(w.getMessage()); | 
|  | Atomics.sub(i32a, WORKER_REPORT_LOC + w.index, 1); | 
|  | } | 
|  | } | 
|  |  | 
|  | return pendingReports.shift() || null; | 
|  | }, | 
|  |  | 
|  | sleep(s) { Atomics.wait(i32a, SLEEP_LOC, 0, s); }, | 
|  |  | 
|  | monotonicNow() { | 
|  | return performance.now(); | 
|  | } | 
|  | }; | 
|  | return agent; | 
|  |  | 
|  | })(); |