Commit 73d401b9 authored by Marja Hölttä's avatar Marja Hölttä Committed by Commit Bot

[test] Make worker related tests more fuzzable

Details: https://docs.google.com/document/d/1-Gi37Ks7rXMVVRkC_HkwGxenP7T1huQUOMrYOtkUCFk/edit?usp=sharing

Bug: v8:11340
Change-Id: Ia1d75270373a7ef2307e7ee0fd24da9ecfa27d18
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2643381Reviewed-by: 's avatarMichael Achenbach <machenbach@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72315}
parent ca5da5b9
......@@ -1928,51 +1928,141 @@ void Shell::SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& args) {
PerIsolateData::Get(isolate)->SetTimeout(callback, context);
}
void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args) {
Isolate* isolate = args.GetIsolate();
HandleScope handle_scope(isolate);
if (args.Length() < 1 || !args[0]->IsString()) {
Throw(args.GetIsolate(), "1st argument must be string");
return;
}
enum WorkerType { kClassic, kString, kFunction, kInvalid, kNone };
// d8 honors `options={type: string}`, which means the first argument is
// not a filename but string of script to be run.
bool load_from_file = true;
void ReadWorkerTypeAndArguments(const v8::FunctionCallbackInfo<v8::Value>& args,
WorkerType* worker_type,
Local<Value>* arguments = nullptr) {
Isolate* isolate = args.GetIsolate();
if (args.Length() > 1 && args[1]->IsObject()) {
Local<Object> object = args[1].As<Object>();
Local<Context> context = isolate->GetCurrentContext();
Local<Value> value;
if (TryGetValue(args.GetIsolate(), context, object, "type")
.ToLocal(&value) &&
value->IsString()) {
Local<String> worker_type = value->ToString(context).ToLocalChecked();
String::Utf8Value str(isolate, worker_type);
if (strcmp("string", *str) == 0) {
load_from_file = false;
} else if (strcmp("classic", *str) == 0) {
load_from_file = true;
} else {
Throw(args.GetIsolate(), "Unsupported worker type");
return;
if (!TryGetValue(isolate, context, object, "type").ToLocal(&value)) {
*worker_type = WorkerType::kNone;
return;
}
if (!value->IsString()) {
*worker_type = WorkerType::kInvalid;
return;
}
Local<String> worker_type_string =
value->ToString(context).ToLocalChecked();
String::Utf8Value str(isolate, worker_type_string);
if (strcmp("string", *str) == 0) {
*worker_type = WorkerType::kString;
} else if (strcmp("classic", *str) == 0) {
*worker_type = WorkerType::kClassic;
} else if (strcmp("function", *str) == 0) {
*worker_type = WorkerType::kFunction;
} else {
*worker_type = WorkerType::kInvalid;
}
if (arguments != nullptr) {
bool got_arguments =
TryGetValue(isolate, context, object, "arguments").ToLocal(arguments);
USE(got_arguments);
}
} else {
*worker_type = WorkerType::kNone;
}
}
bool FunctionAndArgumentsToString(Local<Function> function,
Local<Value> arguments, Local<String>* source,
Isolate* isolate) {
Local<Context> context = isolate->GetCurrentContext();
MaybeLocal<String> maybe_function_string =
function->FunctionProtoToString(context);
Local<String> function_string;
if (!maybe_function_string.ToLocal(&function_string)) {
Throw(isolate, "Failed to convert function to string");
return false;
}
*source = String::NewFromUtf8Literal(isolate, "(");
*source = String::Concat(isolate, *source, function_string);
Local<String> middle = String::NewFromUtf8Literal(isolate, ")(");
*source = String::Concat(isolate, *source, middle);
if (!arguments.IsEmpty() && !arguments->IsUndefined()) {
if (!arguments->IsArray()) {
Throw(isolate, "'arguments' must be an array");
return false;
}
Local<String> comma = String::NewFromUtf8Literal(isolate, ",");
Local<Array> array = arguments.As<Array>();
for (uint32_t i = 0; i < array->Length(); ++i) {
if (i > 0) {
*source = String::Concat(isolate, *source, comma);
}
Local<Value> argument = array->Get(context, i).ToLocalChecked();
Local<String> argument_string;
if (!JSON::Stringify(context, argument).ToLocal(&argument_string)) {
Throw(isolate, "Failed to convert argument to string");
return false;
}
*source = String::Concat(isolate, *source, argument_string);
}
}
Local<String> suffix = String::NewFromUtf8Literal(isolate, ")");
*source = String::Concat(isolate, *source, suffix);
return true;
}
Local<Value> source;
if (load_from_file) {
String::Utf8Value filename(args.GetIsolate(), args[0]);
source = ReadFile(args.GetIsolate(), *filename);
if (source.IsEmpty()) {
Throw(args.GetIsolate(), "Error loading worker script");
void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args) {
Isolate* isolate = args.GetIsolate();
HandleScope handle_scope(isolate);
if (args.Length() < 1 || (!args[0]->IsString() && !args[0]->IsFunction())) {
Throw(isolate, "1st argument must be a string or a function");
return;
}
Local<String> source;
if (args[0]->IsFunction()) {
// d8 supports `options={type: 'function', arguments:[...]}`, which means
// the first argument is a function with the code to be ran. Restrictions
// apply; in particular the function will be converted to a string and the
// Worker constructed based on it.
WorkerType worker_type;
Local<Value> arguments;
ReadWorkerTypeAndArguments(args, &worker_type, &arguments);
if (worker_type != WorkerType::kFunction) {
Throw(isolate, "Invalid or missing worker type");
return;
}
// Source: ( function_to_string )( params )
if (!FunctionAndArgumentsToString(args[0].As<Function>(), arguments,
&source, isolate)) {
return;
}
} else {
source = args[0];
// d8 honors `options={type: 'string'}`, which means the first argument is
// not a filename but string of script to be run.
bool load_from_file = true;
WorkerType worker_type;
ReadWorkerTypeAndArguments(args, &worker_type);
if (worker_type == WorkerType::kString) {
load_from_file = false;
} else if (worker_type != WorkerType::kNone &&
worker_type != WorkerType::kClassic) {
Throw(isolate, "Invalid worker type");
return;
}
if (load_from_file) {
String::Utf8Value filename(isolate, args[0]);
source = ReadFile(isolate, *filename);
if (source.IsEmpty()) {
Throw(args.GetIsolate(), "Error loading worker script");
return;
}
} else {
source = args[0].As<String>();
}
}
if (!args.IsConstructCall()) {
Throw(args.GetIsolate(), "Worker must be constructed with new");
Throw(isolate, "Worker must be constructed with new");
return;
}
......@@ -1987,9 +2077,9 @@ void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args) {
base::MutexGuard lock_guard(workers_mutex_.Pointer());
if (!allow_new_workers_) return;
String::Utf8Value script(args.GetIsolate(), source);
String::Utf8Value script(isolate, source);
if (!*script) {
Throw(args.GetIsolate(), "Can't get worker script");
Throw(isolate, "Can't get worker script");
return;
}
......@@ -2003,7 +2093,7 @@ void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args) {
i_isolate, kWorkerSizeEstimate, worker);
args.Holder()->SetInternalField(0, Utils::ToLocal(managed));
if (!Worker::StartWorkerThread(std::move(worker))) {
Throw(args.GetIsolate(), "Can't start thread");
Throw(isolate, "Can't start thread");
return;
}
}
......
// Copyright 2021 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.
// Tests for a more fuzzable way for creating workers based on functions.
(function TestWorker() {
function workerCode1() {
onmessage = function() {
postMessage('hi');
}
}
let w = new Worker(workerCode1, {type: 'function'});
w.postMessage('');
assertEquals('hi', w.getMessage());
})();
(function TestPassingNumberParam() {
function workerCode2(n) {
onmessage = function() {
postMessage('worker ' + (n + 1));
}
}
w = new Worker(workerCode2, {type: 'function', arguments: [2021]});
w.postMessage('');
assertEquals('worker 2022', w.getMessage());
})();
(function TestPassingStringParam() {
function workerCode3(s) {
onmessage = function() {
postMessage('worker ' + s);
}
}
w = new Worker(workerCode3, {type: 'function', arguments: ['hello']});
w.postMessage('');
assertEquals('worker hello', w.getMessage());
})();
(function TestPassingObjectParam() {
function workerCode4(o) {
onmessage = function() {
postMessage('worker ' + (o.x + 1));
}
}
w = new Worker(workerCode4, {type: 'function', arguments: [{x: 1}]});
w.postMessage('');
assertEquals('worker 2', w.getMessage());
})();
(function TestPassingFunctionParam() {
function workerCode5(f) {
eval(f);
onmessage = function() {
postMessage('worker ' + func());
}
}
let config = {'func': function func() { return 'hi';} };
w = new Worker(workerCode5, {type: 'function',
arguments: [config.func.toString()]});
w.postMessage('');
assertEquals('worker hi', w.getMessage());
})();
......@@ -8,11 +8,12 @@
var sab = new SharedArrayBuffer(4);
var sta = new Int8Array(sab);
sta[0] = 5;
var workerScript =
`onmessage=function(msg) {
postMessage(0);
};`;
var worker = new Worker(workerScript, {type: 'string'});
function workerCode() {
onmessage = function(msg) {
postMessage(0);
};
}
var worker = new Worker(workerCode, {type: 'function'});
var value_obj = {
valueOf: function() {worker.postMessage({sab:sab}, [sta.buffer]);
......
......@@ -6,7 +6,7 @@
load("test/mjsunit/harmony/atomics-waitasync-helpers.js");
const script = `
function workerCode() {
const sab = new SharedArrayBuffer(16);
const i32a = new Int32Array(sab);
......@@ -28,7 +28,8 @@ const script = `
postMessage("notify return value " + notify_return_value);
},
() => { postMessage("unexpected"); });
}`;
};
}
const expected_messages = [
"fast timed-out",
......@@ -36,4 +37,4 @@ const expected_messages = [
"slow ok"
];
runTestWithWorker(script, expected_messages);
runTestWithWorker(workerCode, expected_messages);
......@@ -6,7 +6,7 @@
load("test/mjsunit/harmony/atomics-waitasync-helpers.js");
const script = `
function workerCode() {
onmessage = function() {
(function() {
const sab = new SharedArrayBuffer(16);
......@@ -31,7 +31,8 @@ const script = `
const notify_return_value = Atomics.notify(i32a2, 0);
postMessage("notify return value " + notify_return_value);
}`;
};
}
const expected_messages = [
"notify return value 1",
......@@ -39,4 +40,4 @@ const expected_messages = [
"result timed-out"
];
runTestWithWorker(script, expected_messages);
runTestWithWorker(workerCode, expected_messages);
......@@ -6,7 +6,7 @@
load("test/mjsunit/harmony/atomics-waitasync-helpers.js");
const script = `
function workerCode() {
onmessage = function() {
const sab = new SharedArrayBuffer(16);
const i32a = new Int32Array(sab);
......@@ -17,10 +17,11 @@ const script = `
result.value.then(
(value) => { postMessage("result " + value); },
() => { postMessage("unexpected"); });
}`;
};
}
const expected_messages = [
"result timed-out"
];
runTestWithWorker(script, expected_messages);
runTestWithWorker(workerCode, expected_messages);
......@@ -6,14 +6,12 @@
const N = 10;
const script = `
function workerCode(N) {
const sab = new SharedArrayBuffer(16);
const i32a = new Int32Array(sab);
const location = 0;
const expected_value = 0;
const N = ${N};
function start() {
// Create N async waiters; the even ones without timeout and the odd ones
// with timeout.
......@@ -36,15 +34,16 @@ const script = `
postMessage("notify return value " + notify_return_value);
}
function onmessage(param) {
onmessage = function(param) {
if (param == "start") {
start();
} else if (param == "wakeUpRemainingWaiters") {
wakeUpRemainingWaiters();
}
}`
};
}
const w = new Worker(script, {type : 'string'});
const w = new Worker(workerCode, {type: 'function', arguments: [N]});
w.postMessage("start");
// Verify that all timed out waiters timed out in timeout order.
......
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function runTestWithWorker(script, expected_messages) {
const w = new Worker(script, {type : 'string'});
function runTestWithWorker(worker_code, expected_messages) {
const w = new Worker(worker_code, {type: 'function'});
w.postMessage('start');
let i = 0;
while (i < expected_messages.length) {
......
......@@ -10,16 +10,18 @@
const location = 0;
(function createWorker() {
const script = `onmessage = function(msg) {
if (msg.sab) {
const i32a = new Int32Array(msg.sab);
// Start 2 async waits in the same location.
const result1 = Atomics.waitAsync(i32a, ${location}, 0);
const result2 = Atomics.waitAsync(i32a, ${location}, 0);
postMessage('worker waiting');
function workerCode(location) {
onmessage = function(msg) {
if (msg.sab) {
const i32a = new Int32Array(msg.sab);
// Start 2 async waits in the same location.
const result1 = Atomics.waitAsync(i32a, location, 0);
const result2 = Atomics.waitAsync(i32a, location, 0);
postMessage('worker waiting');
}
}
}`;
const w = new Worker(script, {type : 'string'});
}
const w = new Worker(workerCode, {type: 'function', arguments: [location]});
w.postMessage({sab: sab});
const m = w.getMessage();
assertEquals('worker waiting', m);
......
......@@ -10,18 +10,21 @@
const location = 0;
(function createWorker() {
const script = `onmessage = function(msg) {
if (msg.sab) {
const i32a = new Int32Array(msg.sab);
Atomics.waitAsync(i32a, ${location}, 0);
postMessage('worker waiting');
function workerCode(location) {
onmessage = function(msg) {
if (msg.sab) {
const i32a = new Int32Array(msg.sab);
Atomics.waitAsync(i32a, location, 0);
postMessage('worker waiting');
}
}
}`;
}
// Create 2 workers which wait on the same location.
let workers = [];
const worker_count = 2;
for (let i = 0; i < worker_count; ++i) {
workers[i] = new Worker(script, {type : 'string'});
workers[i] = new Worker(workerCode,
{type: 'function', arguments: [location]});
workers[i].postMessage({sab: sab});
const m = workers[i].getMessage();
assertEquals('worker waiting', m);
......
......@@ -9,14 +9,16 @@
const i32a = new Int32Array(sab);
(function createWorker() {
const script = `onmessage = function(msg) {
if (msg.sab) {
const i32a = new Int32Array(msg.sab);
const result = Atomics.waitAsync(i32a, 0, 0);
postMessage('worker waiting');
function workerCode() {
onmessage = function(msg) {
if (msg.sab) {
const i32a = new Int32Array(msg.sab);
const result = Atomics.waitAsync(i32a, 0, 0);
postMessage('worker waiting');
}
}
}`;
const w = new Worker(script, {type : 'string'});
};
const w = new Worker(workerCode, {type: 'function'});
w.postMessage({sab: sab});
const m = w.getMessage();
assertEquals('worker waiting', m);
......
......@@ -9,14 +9,16 @@
const i32a = new Int32Array(sab);
(function createWorker() {
const script = `onmessage = function(msg) {
if (msg.sab) {
const i32a = new Int32Array(msg.sab);
const result = Atomics.waitAsync(i32a, 0, 0, 100000);
postMessage('worker waiting');
function workerCode() {
onmessage = function(msg) {
if (msg.sab) {
const i32a = new Int32Array(msg.sab);
const result = Atomics.waitAsync(i32a, 0, 0, 100000);
postMessage('worker waiting');
}
}
}`;
const w = new Worker(script, {type : 'string'});
}
const w = new Worker(workerCode, {type: 'function'});
w.postMessage({sab: sab});
const m = w.getMessage();
assertEquals('worker waiting', m);
......
......@@ -189,23 +189,24 @@ if (this.Worker) {
// i32a[4]:
// always 0. Each worker is waiting on this index.
var workerScript =
`onmessage = function(msg) {
var id = msg.id;
var i32a = new Int32Array(msg.sab);
// Wait on i32a[4] (should be zero).
var result = Atomics.wait(i32a, 4, 0);
// Set i32a[id] to 1 to notify the main thread which workers were
// woken up.
Atomics.store(i32a, id, 1);
postMessage(result);
};`;
function workerCode() {
onmessage = function(msg) {
var id = msg.id;
var i32a = new Int32Array(msg.sab);
// Wait on i32a[4] (should be zero).
var result = Atomics.wait(i32a, 4, 0);
// Set i32a[id] to 1 to notify the main thread which workers were
// woken up.
Atomics.store(i32a, id, 1);
postMessage(result);
};
}
var id;
var workers = [];
for (id = 0; id < 4; id++) {
workers[id] = new Worker(workerScript, {type: 'string'});
workers[id] = new Worker(workerCode, {type: 'function'});
workers[id].postMessage({sab: sab, id: id});
}
......
......@@ -299,25 +299,27 @@ function getSequence(start, end) {
}
function spawnWorkers() {
function workerCode() {
onmessage = function(msg) {
if (msg.module) {
let module = msg.module;
let mem = msg.mem;
this.instance = new WebAssembly.Instance(module, {m: {imported_mem: mem}});
postMessage({instantiated: true});
} else {
let address = msg.address;
let sequence = msg.sequence;
let index = msg.index;
let spin = msg.spin;
let result = instance.exports["worker" + index](address, sequence, spin);
postMessage({index: index, sequence: sequence, result: result});
}
}
}
let workers = [];
for (let i = 0; i < kNumberOfWorker; i++) {
let worker = new Worker(
`onmessage = function(msg) {
if (msg.module) {
let module = msg.module;
let mem = msg.mem;
this.instance = new WebAssembly.Instance(module, {m: {imported_mem: mem}});
postMessage({instantiated: true});
} else {
let address = msg.address;
let sequence = msg.sequence;
let index = msg.index;
let spin = msg.spin;
let result = instance.exports["worker" + index](address, sequence, spin);
postMessage({index: index, sequence: sequence, result: result});
}
}`,
{type: 'string'});
let worker = new Worker(workerCode, {type: 'function'});
workers.push(worker);
}
return workers;
......
This diff is collapsed.
......@@ -7,13 +7,14 @@
const kNumIterations = 10;
function NewWorker() {
let script =
`onmessage = (msg) => {
if (msg.memory) postMessage("ack");
if (msg.quit) postMessage("bye");
gc();
}`;
return new Worker(script, {type: 'string'});
function workerCode() {
onmessage = (msg) => {
if (msg.memory) postMessage("ack");
if (msg.quit) postMessage("bye");
gc();
}
}
return new Worker(workerCode, {type: 'function'});
}
function PingWorker(worker, memory) {
......
......@@ -11,12 +11,15 @@ function AllocMemory(pages = 1, max = pages) {
}
(function RunTest() {
let worker = new Worker(
`onmessage =
function(msg) {
if (msg.memory) postMessage({memory : msg.memory});
gc();
}`, {type : 'string'});
function workerCode() {
onmessage =
function(msg) {
if (msg.memory) postMessage({memory : msg.memory});
gc();
}
}
let worker = new Worker(workerCode);
let time = performance.now();
......
......@@ -12,34 +12,39 @@
})();
// Can't use assert in a worker.
let workerHelpers =
`function assertTrue(value, msg) {
function workerHelpersHelper() {
assertTrue = function(value, msg) {
if (!value) {
postMessage("Error: " + msg);
throw new Error("Exit"); // To stop testing.
}
}
function assertIsWasmMemory(memory, expectedSize) {
assertTrue(memory instanceof WebAssembly.Memory,
"object is not a WebAssembly.Memory");
assertIsWasmMemory = function(memory, expectedSize) {
assertTrue(memory instanceof WebAssembly.Memory,
"object is not a WebAssembly.Memory");
assertTrue(memory.buffer instanceof SharedArrayBuffer,
"object.buffer is not a SharedArrayBuffer");
assertTrue(memory.buffer instanceof SharedArrayBuffer,
"object.buffer is not a SharedArrayBuffer");
assertTrue(memory.buffer.byteLength == expectedSize,
"object.buffer.byteLength is not " + expectedSize + " bytes");
}
`;
assertTrue(memory.buffer.byteLength == expectedSize,
"object.buffer.byteLength is not " + expectedSize + " bytes");
}
}
let workerHelpers = "(" + workerHelpersHelper.toString() + ")()";
(function TestPostMessageSharedMemory() {
let workerScript = workerHelpers +
`onmessage = function(memory) {
assertIsWasmMemory(memory, 65536);
postMessage("OK");
};`;
function workerCode(workerHelpers) {
eval(workerHelpers);
onmessage = function(memory) {
assertIsWasmMemory(memory, 65536);
postMessage("OK");
};
}
let worker = new Worker(workerScript, {type: 'string'});
let worker = new Worker(workerCode,
{type: 'function', arguments: [workerHelpers]});
let memory = new WebAssembly.Memory({initial: 1, maximum: 2, shared: true});
worker.postMessage(memory);
assertEquals("OK", worker.getMessage());
......@@ -47,8 +52,9 @@ let workerHelpers =
})();
(function TestPostMessageComplexObjectWithSharedMemory() {
let workerScript = workerHelpers +
`onmessage = function(obj) {
function workerCode(workerHelpers) {
eval(workerHelpers);
onmessage = function(obj) {
assertIsWasmMemory(obj.memories[0], 65536);
assertIsWasmMemory(obj.memories[1], 65536);
assertTrue(obj.buffer instanceof SharedArrayBuffer,
......@@ -58,9 +64,11 @@ let workerHelpers =
"buffers aren't equal");
assertTrue(obj.foo === 1, "foo is not 1");
postMessage("OK");
};`;
};
}
let worker = new Worker(workerScript, {type: 'string'});
let worker = new Worker(workerCode,
{type: 'function', arguments: [workerHelpers]});
let memory = new WebAssembly.Memory({initial: 1, maximum: 2, shared: true});
let obj = {memories: [memory, memory], buffer: memory.buffer, foo: 1};
worker.postMessage(obj);
......@@ -69,14 +77,18 @@ let workerHelpers =
})();
(function TestTwoWorkers() {
let workerScript = workerHelpers +
`onmessage = function(memory) {
function workerCode(workerHelpers) {
eval(workerHelpers);
onmessage = function(memory) {
assertIsWasmMemory(memory, 65536);
postMessage("OK");
};`;
};
}
let workers = [new Worker(workerScript, {type: 'string'}),
new Worker(workerScript, {type: 'string'})];
let workers = [new Worker(workerCode,
{type: 'function', arguments: [workerHelpers]}),
new Worker(workerCode,
{type: 'function', arguments: [workerHelpers]})];
let memory = new WebAssembly.Memory({initial: 1, maximum: 2, shared: true});
for (let worker of workers) {
worker.postMessage(memory);
......
......@@ -12,7 +12,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
let module = builder.toModule();
let workerScript = `
function workerCode() {
onmessage = function(module) {
try {
let instance = new WebAssembly.Instance(module);
......@@ -22,9 +22,9 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
postMessage('ERROR: ' + e);
}
}
`;
}
let worker = new Worker(workerScript, {type: 'string'});
let worker = new Worker(workerCode, {type: 'function'});
worker.postMessage(module);
assertEquals(42, worker.getMessage());
worker.terminate();
......
......@@ -44,53 +44,63 @@ function RunWorkerPingTest(config) {
// Every {config.allocInterval}, a worker creates a new thing by
// {config.AllocThing}.
let script =
`const kNumThings = ${config.numThings};
const kAllocInterval = ${config.allocInterval};
let index = 0;
let total = 0;
let id = 0;
let things = new Array(kNumThings);
for (let i = 0; i < kNumThings; i++) {
things[i] = TryAllocThing();
}
function workerCode(config, AllocThing, BeforeReceive) {
eval(AllocThing);
eval(BeforeReceive);
const kNumThings = config.numThings;
const kAllocInterval = config.allocInterval;
let index = 0;
let total = 0;
let id = 0;
let things = new Array(kNumThings);
for (let i = 0; i < kNumThings; i++) {
things[i] = TryAllocThing();
}
function TryAllocThing() {
try {
let thing = AllocThing(id++);
${config.traceAlloc ? "print(\"alloc success\");" : ""}
function TryAllocThing() {
try {
let thing = AllocThing(id++);
if (config.traceAlloc) {
print("alloc success");
}
return thing;
} catch(e) {
${config.abortOnFail ? "postMessage({error: e.toString()}); throw e;" : "" }
${config.traceAlloc ? "print(\"alloc fail: \" + e);" : ""}
if (config.abortOnFail) {
postMessage({error: e.toString()}); throw e;
}
if (config.traceAlloc) {
print("alloc fail: " + e);
}
}
}
}
onmessage = function(msg) {
BeforeReceive(msg);
if (msg.thing !== undefined) {
let reply = things[index];
if ((total % kAllocInterval) == 0) {
reply = TryAllocThing();
onmessage = function(msg) {
BeforeReceive(msg);
if (msg.thing !== undefined) {
let reply = things[index];
if ((total % kAllocInterval) == 0) {
reply = TryAllocThing();
}
things[index] = msg.thing;
postMessage({thing : reply});
index = (index + 1) % kNumThings;
total++;
}
things[index] = msg.thing;
postMessage({thing : reply});
index = (index + 1) % kNumThings;
total++;
}
}
${config.AllocThing.toString()}
${beforeReceive.toString()}
`;
if (config.traceScript) {
print("========== Worker script ==========");
print(script);
print(workerCode.toString());
print("===================================");
}
let arguments = [config,
config.AllocThing.toString(),
beforeReceive.toString()];
for (let i = 0; i < config.numWorkers; i++) {
let worker = new Worker(script, {type : 'string'});
let worker = new Worker(workerCode, {type: 'function',
arguments: arguments});
workers.push(worker);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment