Commit f4775f1c authored by Aseem Garg's avatar Aseem Garg Committed by Commit Bot

Revert "[wasm] Add I64AtomicWait implementation"

This reverts commit 9436e8a8.

Reason for revert: Breaks TSAN.

Original change's description:
> [wasm] Add I64AtomicWait implementation
> 
> Bug=v8:8075
> R=​adamk@chromium.org,binji@chromium.org
> 
> Change-Id: I11ef5daccd043123b23e60c93ee0df79cabe9ccd
> Reviewed-on: https://chromium-review.googlesource.com/c/1342948
> Reviewed-by: Adam Klein <adamk@chromium.org>
> Reviewed-by: Ben Smith <binji@chromium.org>
> Commit-Queue: Aseem Garg <aseemgarg@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#57917}

TBR=binji@chromium.org,adamk@chromium.org,aseemgarg@chromium.org

Change-Id: Ic82ce8794410a0d4d19de07abd9bb8a7aaff1c1c
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/c/1351303Reviewed-by: 's avatarAseem Garg <aseemgarg@chromium.org>
Commit-Queue: Aseem Garg <aseemgarg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57919}
parent 81620900
......@@ -7790,7 +7790,7 @@ class V8_EXPORT Isolate {
*/
typedef void (*AtomicsWaitCallback)(AtomicsWaitEvent event,
Local<SharedArrayBuffer> array_buffer,
size_t offset_in_bytes, int64_t value,
size_t offset_in_bytes, int32_t value,
double timeout_in_ms,
AtomicsWaitWakeHandle* stop_handle,
void* data);
......
......@@ -1239,7 +1239,6 @@ namespace internal {
TFC(WasmAllocateHeapNumber, AllocateHeapNumber, 1) \
TFC(WasmAtomicWake, WasmAtomicWake, 1) \
TFC(WasmI32AtomicWait, WasmI32AtomicWait, 1) \
TFC(WasmI64AtomicWait, WasmI64AtomicWait, 1) \
TFC(WasmCallJavaScript, CallTrampoline, 1) \
TFC(WasmMemoryGrow, WasmMemoryGrow, 1) \
TFC(WasmRecordWrite, RecordWrite, 1) \
......@@ -1540,7 +1539,6 @@ namespace internal {
V(WasmAllocateHeapNumber) \
V(WasmAtomicWake) \
V(WasmI32AtomicWait) \
V(WasmI64AtomicWait) \
V(WasmCallJavaScript) \
V(WasmMemoryGrow) \
V(WasmRecordWrite) \
......
......@@ -156,47 +156,6 @@ TF_BUILTIN(WasmI32AtomicWait, WasmBuiltinsAssembler) {
ReturnRaw(SmiToInt32(result_smi));
}
TF_BUILTIN(WasmI64AtomicWait, WasmBuiltinsAssembler) {
TNode<Uint32T> address =
UncheckedCast<Uint32T>(Parameter(Descriptor::kAddress));
TNode<Uint32T> expected_value_high =
UncheckedCast<Uint32T>(Parameter(Descriptor::kExpectedValueHigh));
TNode<Uint32T> expected_value_low =
UncheckedCast<Uint32T>(Parameter(Descriptor::kExpectedValueLow));
TNode<Float64T> timeout =
UncheckedCast<Float64T>(Parameter(Descriptor::kTimeout));
TNode<Object> instance = LoadInstanceFromFrame();
TNode<Code> centry = LoadCEntryFromInstance(instance);
TNode<Code> target = LoadBuiltinFromFrame(Builtins::kAllocateHeapNumber);
// TODO(aseemgarg): Use SMIs if possible for address and expected_value
TNode<HeapNumber> address_heap = UncheckedCast<HeapNumber>(
CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
StoreHeapNumberValue(address_heap, ChangeUint32ToFloat64(address));
TNode<HeapNumber> expected_value_high_heap = UncheckedCast<HeapNumber>(
CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
StoreHeapNumberValue(expected_value_high_heap,
ChangeUint32ToFloat64(expected_value_high));
TNode<HeapNumber> expected_value_low_heap = UncheckedCast<HeapNumber>(
CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
StoreHeapNumberValue(expected_value_low_heap,
ChangeUint32ToFloat64(expected_value_low));
TNode<HeapNumber> timeout_heap = UncheckedCast<HeapNumber>(
CallStub(AllocateHeapNumberDescriptor(), target, NoContextConstant()));
StoreHeapNumberValue(timeout_heap, timeout);
TNode<Smi> result_smi = UncheckedCast<Smi>(CallRuntimeWithCEntry(
Runtime::kWasmI64AtomicWait, centry, NoContextConstant(), instance,
address_heap, expected_value_high_heap, expected_value_low_heap,
timeout_heap));
ReturnRaw(SmiToInt32(result_smi));
}
TF_BUILTIN(WasmMemoryGrow, WasmBuiltinsAssembler) {
TNode<Int32T> num_pages =
UncheckedCast<Int32T>(Parameter(Descriptor::kNumPages));
......
......@@ -4114,40 +4114,6 @@ Node* WasmGraphBuilder::AtomicOp(wasm::WasmOpcode opcode, Node* const* inputs,
break;
}
case wasm::kExprI64AtomicWait: {
Node* index = CheckBoundsAndAlignment(
wasm::ValueTypes::MemSize(MachineType::Uint32()), inputs[0], offset,
position);
// Now that we've bounds-checked, compute the effective address.
Node* address = graph()->NewNode(mcgraph()->machine()->Int32Add(),
Uint32Constant(offset), index);
Node* timeout;
if (mcgraph()->machine()->Is32()) {
timeout = BuildF64SConvertI64(inputs[2]);
} else {
timeout = graph()->NewNode(mcgraph()->machine()->RoundInt64ToFloat64(),
inputs[2]);
}
Node* expected_value_low = graph()->NewNode(
mcgraph()->machine()->TruncateInt64ToInt32(), inputs[1]);
Node* tmp = graph()->NewNode(mcgraph()->machine()->Word64Shr(), inputs[1],
Int64Constant(32));
Node* expected_value_high =
graph()->NewNode(mcgraph()->machine()->TruncateInt64ToInt32(), tmp);
WasmI64AtomicWaitDescriptor interface_descriptor;
auto call_descriptor = Linkage::GetStubCallDescriptor(
mcgraph()->zone(), interface_descriptor,
interface_descriptor.GetStackParameterCount(),
CallDescriptor::kNoFlags, Operator::kNoProperties,
StubCallMode::kCallWasmRuntimeStub);
Node* call_target = mcgraph()->RelocatableIntPtrConstant(
wasm::WasmCode::kWasmI64AtomicWait, RelocInfo::WASM_STUB_CALL);
node = graph()->NewNode(mcgraph()->common()->Call(call_descriptor),
call_target, address, expected_value_high,
expected_value_low, timeout, Effect(), Control());
break;
}
default:
FATAL_UNSUPPORTED_OPCODE(opcode);
}
......
......@@ -62,7 +62,7 @@ namespace {
const int kMB = 1024 * 1024;
const int kMaxWorkers = 150;
const int kMaxWorkers = 100;
const int kMaxSerializerMemoryUsage =
1 * kMB; // Arbitrary maximum for testing.
......
......@@ -87,7 +87,7 @@ enum WaitReturnValue : int { kOk = 0, kNotEqual = 1, kTimedOut = 2 };
Object* FutexEmulation::WaitJs(Isolate* isolate,
Handle<JSArrayBuffer> array_buffer, size_t addr,
int32_t value, double rel_timeout_ms) {
Object* res = Wait32(isolate, array_buffer, addr, value, rel_timeout_ms);
Object* res = Wait(isolate, array_buffer, addr, value, rel_timeout_ms);
if (res->IsSmi()) {
int val = Smi::ToInt(res);
switch (val) {
......@@ -104,22 +104,9 @@ Object* FutexEmulation::WaitJs(Isolate* isolate,
return res;
}
Object* FutexEmulation::Wait32(Isolate* isolate,
Handle<JSArrayBuffer> array_buffer, size_t addr,
int32_t value, double rel_timeout_ms) {
return Wait<int32_t>(isolate, array_buffer, addr, value, rel_timeout_ms);
}
Object* FutexEmulation::Wait64(Isolate* isolate,
Handle<JSArrayBuffer> array_buffer, size_t addr,
int64_t value, double rel_timeout_ms) {
return Wait<int64_t>(isolate, array_buffer, addr, value, rel_timeout_ms);
}
template <typename T>
Object* FutexEmulation::Wait(Isolate* isolate,
Handle<JSArrayBuffer> array_buffer, size_t addr,
T value, double rel_timeout_ms) {
int32_t value, double rel_timeout_ms) {
DCHECK_LT(addr, array_buffer->byte_length());
bool use_timeout = rel_timeout_ms != V8_INFINITY;
......@@ -166,7 +153,8 @@ Object* FutexEmulation::Wait(Isolate* isolate,
// still holding the lock).
ResetWaitingOnScopeExit reset_waiting(node);
T* p = reinterpret_cast<T*>(static_cast<int8_t*>(backing_store) + addr);
int32_t* p =
reinterpret_cast<int32_t*>(static_cast<int8_t*>(backing_store) + addr);
if (*p != value) {
result = Smi::FromInt(WaitReturnValue::kNotEqual);
callback_result = AtomicsWaitEvent::kNotEqual;
......
......@@ -123,14 +123,9 @@ class FutexEmulation : public AllStatic {
// Same as WaitJs above except it returns 0 (ok), 1 (not equal) and 2 (timed
// out) as expected by Wasm.
static Object* Wait32(Isolate* isolate, Handle<JSArrayBuffer> array_buffer,
static Object* Wait(Isolate* isolate, Handle<JSArrayBuffer> array_buffer,
size_t addr, int32_t value, double rel_timeout_ms);
// Same as Wait32 above except it checks for an int64_t value in the
// array_buffer.
static Object* Wait64(Isolate* isolate, Handle<JSArrayBuffer> array_buffer,
size_t addr, int64_t value, double rel_timeout_ms);
// Wake |num_waiters_to_wake| threads that are waiting on the given |addr|.
// |num_waiters_to_wake| can be kWakeAll, in which case all waiters are
// woken. The rest of the waiters will continue to wait. The return value is
......@@ -147,10 +142,6 @@ class FutexEmulation : public AllStatic {
friend class FutexWaitListNode;
friend class AtomicsWaitWakeHandle;
template <typename T>
static Object* Wait(Isolate* isolate, Handle<JSArrayBuffer> array_buffer,
size_t addr, T value, double rel_timeout_ms);
// `mutex_` protects the composition of `wait_list_` (i.e. no elements may be
// added or removed without holding this mutex), as well as the `waiting_`
// and `interrupted_` fields for each individual list node that is currently
......
......@@ -366,11 +366,6 @@ void WasmI32AtomicWaitDescriptor::InitializePlatformSpecific(
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void WasmI64AtomicWaitDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void CloneObjectWithVectorDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
......
......@@ -78,7 +78,6 @@ namespace internal {
V(WasmThrow) \
V(WasmAtomicWake) \
V(WasmI32AtomicWait) \
V(WasmI64AtomicWait) \
V(CloneObjectWithVector) \
BUILTIN_LIST_TFS(V)
......@@ -1126,19 +1125,6 @@ class WasmI32AtomicWaitDescriptor final : public CallInterfaceDescriptor {
DECLARE_DESCRIPTOR(WasmI32AtomicWaitDescriptor, CallInterfaceDescriptor)
};
class WasmI64AtomicWaitDescriptor final : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS_NO_CONTEXT(kAddress, kExpectedValueHigh, kExpectedValueLow,
kTimeout)
DEFINE_RESULT_AND_PARAMETER_TYPES(
MachineType::Uint32(), // result 1
MachineType::Uint32(), // kAddress
MachineType::Uint32(), // kExpectedValueHigh
MachineType::Uint32(), // kExpectedValueLow
MachineType::Float64()) // kTimeout
DECLARE_DESCRIPTOR(WasmI64AtomicWaitDescriptor, CallInterfaceDescriptor)
};
class CloneObjectWithVectorDescriptor final : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kSource, kFlags, kSlot, kVector)
......
......@@ -4193,7 +4193,7 @@ void Isolate::SetAtomicsWaitCallback(v8::Isolate::AtomicsWaitCallback callback,
void Isolate::RunAtomicsWaitCallback(v8::Isolate::AtomicsWaitEvent event,
Handle<JSArrayBuffer> array_buffer,
size_t offset_in_bytes, int64_t value,
size_t offset_in_bytes, int32_t value,
double timeout_in_ms,
AtomicsWaitWakeHandle* stop_handle) {
DCHECK(array_buffer->is_shared());
......
......@@ -1443,7 +1443,7 @@ class Isolate final : private HiddenFactory {
void* data);
void RunAtomicsWaitCallback(v8::Isolate::AtomicsWaitEvent event,
Handle<JSArrayBuffer> array_buffer,
size_t offset_in_bytes, int64_t value,
size_t offset_in_bytes, int32_t value,
double timeout_in_ms,
AtomicsWaitWakeHandle* stop_handle);
......
......@@ -283,42 +283,20 @@ RUNTIME_FUNCTION(Runtime_WasmAtomicWake) {
return FutexEmulation::Wake(array_buffer, address, count);
}
double WaitTimeoutInMs(double timeout_ns) {
return timeout_ns < 0
? V8_INFINITY
: timeout_ns / (base::Time::kNanosecondsPerMicrosecond *
base::Time::kMicrosecondsPerMillisecond);
}
RUNTIME_FUNCTION(Runtime_WasmI32AtomicWait) {
HandleScope scope(isolate);
DCHECK_EQ(4, args.length());
CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
CONVERT_NUMBER_CHECKED(uint32_t, address, Uint32, args[1]);
CONVERT_NUMBER_CHECKED(int32_t, expected_value, Int32, args[2]);
CONVERT_DOUBLE_ARG_CHECKED(timeout_ns, 3);
double timeout_ms = WaitTimeoutInMs(timeout_ns);
Handle<JSArrayBuffer> array_buffer =
getSharedArrayBuffer(instance, isolate, address);
return FutexEmulation::Wait32(isolate, array_buffer, address, expected_value,
timeout_ms);
}
RUNTIME_FUNCTION(Runtime_WasmI64AtomicWait) {
HandleScope scope(isolate);
DCHECK_EQ(5, args.length());
CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
CONVERT_NUMBER_CHECKED(uint32_t, address, Uint32, args[1]);
CONVERT_NUMBER_CHECKED(uint32_t, expected_value_high, Uint32, args[2]);
CONVERT_NUMBER_CHECKED(uint32_t, expected_value_low, Uint32, args[3]);
CONVERT_DOUBLE_ARG_CHECKED(timeout_ns, 4);
int64_t expected_value = (static_cast<uint64_t>(expected_value_high) << 32) |
static_cast<uint64_t>(expected_value_low);
double timeout_ms = WaitTimeoutInMs(timeout_ns);
CONVERT_DOUBLE_ARG_CHECKED(timeout, 3);
timeout = timeout < 0 ? V8_INFINITY
: timeout / (base::Time::kNanosecondsPerMicrosecond *
base::Time::kMicrosecondsPerMillisecond);
Handle<JSArrayBuffer> array_buffer =
getSharedArrayBuffer(instance, isolate, address);
return FutexEmulation::Wait64(isolate, array_buffer, address, expected_value,
timeout_ms);
return FutexEmulation::Wait(isolate, array_buffer, address, expected_value,
timeout);
}
} // namespace internal
......
......@@ -532,7 +532,6 @@ namespace internal {
F(ThrowWasmError, 1, 1) \
F(ThrowWasmStackOverflow, 0, 1) \
F(WasmI32AtomicWait, 4, 1) \
F(WasmI64AtomicWait, 5, 1) \
F(WasmAtomicWake, 3, 1) \
F(WasmExceptionGetValues, 1, 1) \
F(WasmExceptionGetTag, 1, 1) \
......
......@@ -63,7 +63,6 @@ struct WasmException;
#define ATOMIC_OP_LIST(V) \
V(AtomicWake, Uint32) \
V(I32AtomicWait, Uint32) \
V(I64AtomicWait, Uint32) \
V(I32AtomicLoad, Uint32) \
V(I64AtomicLoad, Uint64) \
V(I32AtomicLoad8U, Uint8) \
......
......@@ -264,7 +264,7 @@ const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) {
// Atomic operations.
CASE_OP(AtomicWake, "atomic_wake")
CASE_INT_OP(AtomicWait, "atomic_wait")
CASE_I32_OP(AtomicWait, "atomic_wait")
CASE_UNSIGNED_ALL_OP(AtomicLoad, "atomic_load")
CASE_UNSIGNED_ALL_OP(AtomicStore, "atomic_store")
CASE_UNSIGNED_ALL_OP(AtomicAdd, "atomic_add")
......
......@@ -420,7 +420,6 @@ bool IsJSCompatibleSignature(const FunctionSig* sig);
#define FOREACH_ATOMIC_OPCODE(V) \
V(AtomicWake, 0xfe00, i_ii) \
V(I32AtomicWait, 0xfe01, i_iil) \
V(I64AtomicWait, 0xfe02, i_ill) \
V(I32AtomicLoad, 0xfe10, i_i) \
V(I64AtomicLoad, 0xfe11, l_i) \
V(I32AtomicLoad8U, 0xfe12, i_i) \
......@@ -541,7 +540,6 @@ bool IsJSCompatibleSignature(const FunctionSig* sig);
V(i_iii, kWasmI32, kWasmI32, kWasmI32, kWasmI32) \
V(l_ill, kWasmI64, kWasmI32, kWasmI64, kWasmI64) \
V(i_iil, kWasmI32, kWasmI32, kWasmI32, kWasmI64) \
V(i_ill, kWasmI32, kWasmI32, kWasmI64, kWasmI64) \
V(i_r, kWasmI32, kWasmAnyRef)
#define FOREACH_SIMD_SIGNATURE(V) \
......
......@@ -28744,7 +28744,7 @@ struct AtomicsWaitCallbackInfo {
Local<v8::SharedArrayBuffer> expected_sab;
v8::Isolate::AtomicsWaitEvent expected_event;
double expected_timeout;
int64_t expected_value;
int32_t expected_value;
size_t expected_offset;
size_t ncalls = 0;
......@@ -28766,7 +28766,7 @@ class StopAtomicsWaitThread : public v8::base::Thread {
void AtomicsWaitCallbackForTesting(
v8::Isolate::AtomicsWaitEvent event, Local<v8::SharedArrayBuffer> sab,
size_t offset_in_bytes, int64_t value, double timeout_in_ms,
size_t offset_in_bytes, int32_t value, double timeout_in_ms,
v8::Isolate::AtomicsWaitWakeHandle* wake_handle, void* data) {
AtomicsWaitCallbackInfo* info = static_cast<AtomicsWaitCallbackInfo*>(data);
info->ncalls++;
......@@ -47,38 +47,6 @@ function WasmI32AtomicWaitFunction(memory, offset, index, val, timeout) {
return instance.exports.main(index, val, timeout);
}
function WasmI64AtomicWaitFunction(memory, offset, index, val_low,
val_high, timeout) {
let builder = new WasmModuleBuilder();
builder.addImportedMemory("m", "memory", 0, 20, "shared");
// Wrapper for I64AtomicWait that takes two I32 values and combines to into
// I64 for the instruction parameter.
builder.addFunction("main",
makeSig([kWasmI32, kWasmI32, kWasmI32, kWasmF64], [kWasmI32]))
.addLocals({i64_count: 1}) // local that is passed as value param to wait
.addBody([
kExprGetLocal, 1,
kExprI64UConvertI32,
kExprI64Const, 32,
kExprI64Shl,
kExprGetLocal, 2,
kExprI64UConvertI32,
kExprI64Ior,
kExprSetLocal, 4, // Store the created I64 value in local
kExprGetLocal, 0,
kExprGetLocal, 4,
kExprGetLocal, 3,
kExprI64SConvertF64,
kAtomicPrefix,
kExprI64AtomicWait, /* alignment */ 0, offset])
.exportAs("main");
// Instantiate module, get function exports
let module = new WebAssembly.Module(builder.toBuffer());
let instance = new WebAssembly.Instance(module, {m: {memory}});
return instance.exports.main(index, val_high, val_low, timeout);
}
(function TestInvalidIndex() {
let memory = new WebAssembly.Memory({initial: 1, maximum: 1, shared: true});
......@@ -90,31 +58,22 @@ function WasmI64AtomicWaitFunction(memory, offset, index, val_low,
assertThrows(function() {
WasmI32AtomicWaitFunction(memory, 0, invalidIndex, 0, -1);
}, Error);
assertThrows(function() {
WasmI64AtomicWaitFunction(memory, 0, invalidIndex, 0, 0, -1);
}, Error);
assertThrows(function() {
WasmAtomicWakeFunction(memory, invalidIndex, 0, -1);
}, Error);
assertThrows(function() {
WasmI32AtomicWaitFunction(memory, invalidIndex, 0, 0, -1);
}, Error);
assertThrows(function() {
WasmI64AtomicWaitFunction(memory, invalidIndex, 0, 0, 0, -1);
}, Error);
assertThrows(function() {
WasmAtomicWakeFunction(memory, invalidIndex/2, invalidIndex/2, -1);
}, Error);
assertThrows(function() {
WasmI32AtomicWaitFunction(memory, invalidIndex/2, invalidIndex/2, 0, -1);
}, Error);
assertThrows(function() {
WasmI64AtomicWaitFunction(memory, invalidIndex/2, invalidIndex/2, 0, 0, -1);
}, Error);
});
})();
(function TestI32WaitTimeout() {
(function TestWaitTimeout() {
let memory = new WebAssembly.Memory({initial: 1, maximum: 1, shared: true});
var waitMs = 100;
var startTime = new Date();
......@@ -123,16 +82,7 @@ function WasmI64AtomicWaitFunction(memory, offset, index, val_low,
assertTrue(endTime - startTime >= waitMs);
})();
(function TestI64WaitTimeout() {
let memory = new WebAssembly.Memory({initial: 1, maximum: 1, shared: true});
var waitMs = 100;
var startTime = new Date();
assertEquals(2, WasmI64AtomicWaitFunction(memory, 0, 0, 0, 0, waitMs*1000000));
var endTime = new Date();
assertTrue(endTime - startTime >= waitMs);
})();
(function TestI32WaitNotEqual() {
(function TestWaitNotEqual() {
let memory = new WebAssembly.Memory({initial: 1, maximum: 1, shared: true});
assertEquals(1, WasmI32AtomicWaitFunction(memory, 0, 0, 42, -1));
......@@ -141,20 +91,6 @@ function WasmI64AtomicWaitFunction(memory, offset, index, val_low,
let i32a = new Int32Array(memory.buffer);
i32a[0] = 1;
assertEquals(1, WasmI32AtomicWaitFunction(memory, 0, 0, 0, -1));
assertEquals(2, WasmI32AtomicWaitFunction(memory, 0, 0, 1, 0));
})();
(function TestI64WaitNotEqual() {
let memory = new WebAssembly.Memory({initial: 1, maximum: 1, shared: true});
assertEquals(1, WasmI64AtomicWaitFunction(memory, 0, 0, 42, 0, -1));
assertEquals(2, WasmI64AtomicWaitFunction(memory, 0, 0, 0, 0, 0));
let i32a = new Int32Array(memory.buffer);
i32a[0] = 1;
i32a[1] = 2;
assertEquals(1, WasmI64AtomicWaitFunction(memory, 0, 0, 0, 0, -1));
assertEquals(2, WasmI64AtomicWaitFunction(memory, 0, 0, 1, 2, 0));
})();
(function TestWakeCounts() {
......@@ -179,37 +115,24 @@ if (this.Worker) {
// Wait adapter strings that can be passed as a parameter to TestWaitWake to generate
// custom worker script
let js_wait_adapter = `(memory, offset, index) => {
let js_wait_adapter = `(memory, offset, index, val) => {
let i32a = new Int32Array(memory.buffer, offset);
let res = Atomics.wait(i32a, index>>>2, 0);
let res = Atomics.wait(i32a, index>>>2, val);
if (res == "ok") return 0;
if (res == "not-equal") return 1;
return 2;
}`
let wasm_i32wait_adapter = `(memory, offset, index) => {
let wasm_wait_adapter = `(memory, offset, index, val) => {
load("test/mjsunit/wasm/wasm-constants.js");
load("test/mjsunit/wasm/wasm-module-builder.js");
${WasmI32AtomicWaitFunction.toString()}
return WasmI32AtomicWaitFunction(memory, offset, index, 0, -1);
}`
let wasm_i64wait_adapter = `(memory, offset, index) => {
load("test/mjsunit/wasm/wasm-constants.js");
load("test/mjsunit/wasm/wasm-module-builder.js");
${WasmI64AtomicWaitFunction.toString()}
return WasmI64AtomicWaitFunction(memory, offset, index, 0, 0, -1);
return WasmI32AtomicWaitFunction(memory, offset, index, val, -1);
}`
let TestWaitWake = function(wait_adapter, wake_adapter, num_workers, num_workers_wake) {
let memory = new WebAssembly.Memory({initial: 1, maximum: 1, shared: true});
let i32a = new Int32Array(memory.buffer);
let max_workers = 8;
assertTrue(num_workers <= max_workers);
// all workers wait on this index. max_workers*8 ensures that this can work for I64Wait too.
let wait_index = 8*max_workers;
let wait_index_i32a = wait_index>>>2;
// SAB values:
// memory[id*4], where id in range [0, num_workers]:
// 0 => Worker |id| is still waiting on the futex
......@@ -217,7 +140,7 @@ if (this.Worker) {
// main thread.
// 2 => Worker |id| has been reaped.
//
// memory[wait_index]:
// memory[num_workers*4]:
// always 0. Each worker is waiting on this index.
let workerScript =
......@@ -226,7 +149,7 @@ if (this.Worker) {
let memory = msg.memory;
let i32a = new Int32Array(memory.buffer);
let wait_adapter = eval(msg.wait_adapter);
let result = wait_adapter(memory, 0, ${wait_index});
let result = wait_adapter(memory, 0, 4*${num_workers}, 0);
// Set i32a[id] to 1 to notify the main thread which workers were
// woken up.
Atomics.store(i32a, id, 1);
......@@ -240,12 +163,12 @@ if (this.Worker) {
}
// Spin until all workers are waiting on the futex.
while (%AtomicsNumWaitersForTesting(i32a, wait_index_i32a) != num_workers) {}
while (%AtomicsNumWaitersForTesting(i32a, num_workers) != num_workers) {}
if (num_workers_wake < num_workers) {
assertEquals(num_workers_wake, wake_adapter(memory, 0, wait_index, num_workers_wake));
assertEquals(num_workers_wake, wake_adapter(memory, 0, 4*num_workers, num_workers_wake));
} else {
assertEquals(num_workers, wake_adapter(memory, 0, wait_index, num_workers_wake));
assertEquals(num_workers, wake_adapter(memory, 0, 4*num_workers, num_workers_wake));
num_workers_wake = num_workers;
}
......@@ -263,10 +186,10 @@ if (this.Worker) {
}
assertEquals(num_workers - num_workers_wake,
%AtomicsNumWaitersForTesting(i32a, wait_index_i32a));
%AtomicsNumWaitersForTesting(i32a, num_workers));
// Finally wake and kill all workers.
wake_adapter(memory, 0, wait_index, num_workers)
wake_adapter(memory, 0, 4*num_workers, num_workers)
for (let id = 0; id < num_workers; id++) {
workers[id].terminate();
}
......@@ -277,23 +200,13 @@ if (this.Worker) {
TestWaitWake(js_wait_adapter, wasm_wake_adapter, 4, 3);
TestWaitWake(js_wait_adapter, wasm_wake_adapter, 3, 4);
TestWaitWake(wasm_i32wait_adapter, wasm_wake_adapter, 1, 1);
TestWaitWake(wasm_i32wait_adapter, wasm_wake_adapter, 4, 4);
TestWaitWake(wasm_i32wait_adapter, wasm_wake_adapter, 4, 3);
TestWaitWake(wasm_i32wait_adapter, wasm_wake_adapter, 3, 4);
TestWaitWake(wasm_i32wait_adapter, js_wake_adapter, 1, 1);
TestWaitWake(wasm_i32wait_adapter, js_wake_adapter, 4, 4);
TestWaitWake(wasm_i32wait_adapter, js_wake_adapter, 4, 3);
TestWaitWake(wasm_i32wait_adapter, js_wake_adapter, 3, 4);
TestWaitWake(wasm_i64wait_adapter, wasm_wake_adapter, 1, 1);
TestWaitWake(wasm_i64wait_adapter, wasm_wake_adapter, 4, 4);
TestWaitWake(wasm_i64wait_adapter, wasm_wake_adapter, 4, 3);
TestWaitWake(wasm_i64wait_adapter, wasm_wake_adapter, 3, 4);
TestWaitWake(wasm_wait_adapter, wasm_wake_adapter, 1, 1);
TestWaitWake(wasm_wait_adapter, wasm_wake_adapter, 4, 4);
TestWaitWake(wasm_wait_adapter, wasm_wake_adapter, 4, 3);
TestWaitWake(wasm_wait_adapter, wasm_wake_adapter, 3, 4);
TestWaitWake(wasm_i64wait_adapter, js_wake_adapter, 1, 1);
TestWaitWake(wasm_i64wait_adapter, js_wake_adapter, 4, 4);
TestWaitWake(wasm_i64wait_adapter, js_wake_adapter, 4, 3);
TestWaitWake(wasm_i64wait_adapter, js_wake_adapter, 3, 4);
TestWaitWake(wasm_wait_adapter, js_wake_adapter, 1, 1);
TestWaitWake(wasm_wait_adapter, js_wake_adapter, 4, 4);
TestWaitWake(wasm_wait_adapter, js_wake_adapter, 4, 3);
TestWaitWake(wasm_wait_adapter, js_wake_adapter, 3, 4);
}
......@@ -357,7 +357,6 @@ let kAtomicPrefix = 0xfe;
let kExprAtomicWake = 0x00;
let kExprI32AtomicWait = 0x01;
let kExprI64AtomicWait = 0x02;
let kExprI32AtomicLoad = 0x10;
let kExprI32AtomicLoad8U = 0x12;
let kExprI32AtomicLoad16U = 0x13;
......
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