blob: bf98c85099925a8cb0809fd5a9ecfeb53f37971b [file] [log] [blame]
// This test times out, probably because of the while loop in the agent.
// https://bugs.webkit.org/show_bug.cgi?id=170958
//@ skip
const pageSize = 64 * 1024;
const verbose = false;
// Start multiple agents and create WebAssembly.Memory from each of
// them. Perform writes into each memory, and then check that the memory only
// contains that agent's writes. This would find bugs where an implementation's
// memory reuse is buggy.
// Use the agent support from test262: https://github.com/tc39/test262/blob/master/INTERPRETING.md#host-defined-functions
const testIterations = 2;
const numAgents = 8;
const initialPages = 64;
const numWrites = 1024;
const stateWait = 0;
const stateReady = 1;
const stateCheck = 2;
const startAgents = numAgentsToStart => {
for (let a = 0; a < numAgentsToStart; ++a) {
const agentScript = `
let state = ${stateWait};
let u8;
if (${verbose})
print("Agent ${a} started");
$.agent.report("Agent ${a} started");
$.agent.receiveBroadcast((sab, newState) => {
if (${verbose})
print("Agent ${a} received broadcast");
u8 = new Uint8Array(sab);
state = newState;
});
const busyWaitForValue = value => {
// Busy-wait so that once the SAB write occurs all agents try to create a memory at the same time.
while (Atomics.load(u8, 0) !== value) ;
};
if (${verbose})
print("Agent ${a} waits");
$.agent.report("Agent ${a} waits");
// FIXME: How can this work? The state variable is in the JS heap and the while loop
// prevents any JS-heap-modifying things from happening because JS is a synchronous
// language
// https://bugs.webkit.org/show_bug.cgi?id=170958
while (state === ${stateWait}) ;
$.agent.report("Agent ${a} received SAB");
// Use it for faster state change so all agents are more likely to execute at the same time.
busyWaitForValue(${stateReady});
let wasmMemory = new WebAssembly.Memory({ initial: ${initialPages} });
let memory = new Uint8Array((wasmMemory).buffer);
if (${verbose})
print("Agent ${a} performing writes");
for (let write = 0; write < ${numWrites}; ++write) {
// Perform writes of our agent number at a random location. This memory should not be shared, if we see writes of other values then something went wrong.
const idx = (Math.random() * ${pageSize} * ${initialPages}) | 0;
memory[idx] = ${a};
}
if (${verbose})
print("Agent ${a} writes performed");
$.agent.report("Agent ${a} performed writes");
busyWaitForValue(${stateCheck});
if (${verbose})
print("Agent ${a} checking");
// Check that our memory only contains 0 and our agent number.
for (let idx = 0; idx < ${pageSize} * ${initialPages}; ++idx)
if (memory[idx] !== 0 && memory[idx] !== ${a})
throw new Error("Agent ${a} found unexpected value " + memory[idx] + " at location " + idx);
$.agent.report("Agent ${a} checks out OK");
$.agent.leaving();
`;
if (verbose)
print(`Starting agent ${a}`);
$.agent.start(agentScript);
}
};
const waitForAgents = numAgentsToWaitFor => {
for (let a = 0; a < numAgentsToWaitFor; ++a) {
while (true) {
const report = $.agent.getReport();
if (report === null) {
$.agent.sleep(1);
continue;
}
if (verbose)
print(`Received: ${report}`);
break;
}
}
};
const broadcastToAgents = (sab, newState) => {
$.agent.broadcast(sab, newState);
};
const sab = new SharedArrayBuffer(1024);
const u8 = new Uint8Array(sab);
for (let it = 0; it < testIterations; ++it) {
startAgents(numAgents);
waitForAgents(numAgents);
broadcastToAgents(sab, stateReady);
waitForAgents(numAgents);
$.agent.sleep(1);
Atomics.store(u8, 0, stateReady);
waitForAgents(numAgents);
$.agent.sleep(1);
Atomics.store(u8, 0, stateCheck);
waitForAgents(numAgents);
if (verbose)
print("Everyting was fine");
$.agent.sleep(1);
}