Commit ec8e7e65 authored by Deepti Gandluri's avatar Deepti Gandluri Committed by Commit Bot

[wasm] Add Atomic Load, Store Ops to the interpreter

Bug: v8:6532
Change-Id: I2ae9c2a2d2b6a02826a50cd150cb8008841f55e4
Reviewed-on: https://chromium-review.googlesource.com/804212
Commit-Queue: Deepti Gandluri <gdeepti@chromium.org>
Reviewed-by: 's avatarEric Holk <eholk@chromium.org>
Reviewed-by: 's avatarBen Smith <binji@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49807}
parent 6c830b48
...@@ -1026,9 +1026,6 @@ class WasmDecoder : public Decoder { ...@@ -1026,9 +1026,6 @@ class WasmDecoder : public Decoder {
std::pair<uint32_t, uint32_t> StackEffect(const byte* pc) { std::pair<uint32_t, uint32_t> StackEffect(const byte* pc) {
WasmOpcode opcode = static_cast<WasmOpcode>(*pc); WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
if (WasmOpcodes::IsPrefixOpcode(opcode)) {
opcode = static_cast<WasmOpcode>(opcode << 8 | *(pc + 1));
}
// Handle "simple" opcodes with a fixed signature first. // Handle "simple" opcodes with a fixed signature first.
FunctionSig* sig = WasmOpcodes::Signature(opcode); FunctionSig* sig = WasmOpcodes::Signature(opcode);
if (!sig) sig = WasmOpcodes::AsmjsSignature(opcode); if (!sig) sig = WasmOpcodes::AsmjsSignature(opcode);
...@@ -1039,10 +1036,8 @@ class WasmDecoder : public Decoder { ...@@ -1039,10 +1036,8 @@ class WasmDecoder : public Decoder {
switch (opcode) { switch (opcode) {
case kExprSelect: case kExprSelect:
return {3, 1}; return {3, 1};
case kExprS128StoreMem:
FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
return {2, 0}; return {2, 0};
case kExprS128LoadMem:
FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
case kExprTeeLocal: case kExprTeeLocal:
case kExprGrowMemory: case kExprGrowMemory:
...@@ -1083,6 +1078,23 @@ class WasmDecoder : public Decoder { ...@@ -1083,6 +1078,23 @@ class WasmDecoder : public Decoder {
case kExprReturn: case kExprReturn:
case kExprUnreachable: case kExprUnreachable:
return {0, 0}; return {0, 0};
case kAtomicPrefix:
case kSimdPrefix: {
opcode = static_cast<WasmOpcode>(opcode << 8 | *(pc + 1));
switch (opcode) {
case kExprI32AtomicStore:
case kExprI32AtomicStore8U:
case kExprI32AtomicStore16U:
case kExprS128StoreMem:
return {2, 0};
default: {
sig = WasmOpcodes::Signature(opcode);
if (sig) {
return {sig->parameter_count(), sig->return_count()};
}
}
}
}
default: default:
V8_Fatal(__FILE__, __LINE__, "unimplemented opcode: %x (%s)", opcode, V8_Fatal(__FILE__, __LINE__, "unimplemented opcode: %x (%s)", opcode,
WasmOpcodes::OpcodeName(opcode)); WasmOpcodes::OpcodeName(opcode));
......
...@@ -1540,12 +1540,12 @@ class ThreadImpl { ...@@ -1540,12 +1540,12 @@ class ThreadImpl {
} }
template <typename type> template <typename type>
bool ExtractAtomicBinOpParams(Decoder* decoder, InterpreterCode* code, bool ExtractAtomicOpParams(Decoder* decoder, InterpreterCode* code,
Address& address, pc_t pc, type& val, Address& address, pc_t pc, int& len,
int& len) { type* val = nullptr) {
MemoryAccessOperand<Decoder::kNoValidate> operand(decoder, code->at(pc + 1), MemoryAccessOperand<Decoder::kNoValidate> operand(decoder, code->at(pc + 1),
sizeof(type)); sizeof(type));
val = Pop().to<uint32_t>(); if (val) *val = Pop().to<uint32_t>();
uint32_t index = Pop().to<uint32_t>(); uint32_t index = Pop().to<uint32_t>();
if (!BoundsCheck<type>(wasm_context_->mem_size, operand.offset, index)) { if (!BoundsCheck<type>(wasm_context_->mem_size, operand.offset, index)) {
DoTrap(kTrapMemOutOfBounds, pc); DoTrap(kTrapMemOutOfBounds, pc);
...@@ -1560,19 +1560,20 @@ class ThreadImpl { ...@@ -1560,19 +1560,20 @@ class ThreadImpl {
InterpreterCode* code, pc_t pc, int& len) { InterpreterCode* code, pc_t pc, int& len) {
WasmValue result; WasmValue result;
switch (opcode) { switch (opcode) {
#define ATOMIC_BINOP_CASE(name, type, operation) \ #define ATOMIC_BINOP_CASE(name, type, operation) \
case kExpr##name: { \ case kExpr##name: { \
type val; \ type val; \
Address addr; \ Address addr; \
if (!ExtractAtomicBinOpParams<type>(decoder, code, addr, pc, val, len)) { \ if (!ExtractAtomicOpParams<type>(decoder, code, addr, pc, len, &val)) { \
return false; \ return false; \
} \ } \
static_assert(sizeof(std::atomic<type>) == sizeof(type), \ static_assert(sizeof(std::atomic<type>) == sizeof(type), \
"Size mismatch for types std::atomic<" #type \ "Size mismatch for types std::atomic<" #type \
">, and " #type); \ ">, and " #type); \
result = WasmValue( \ result = WasmValue( \
std::operation(reinterpret_cast<std::atomic<type>*>(addr), val)); \ std::operation(reinterpret_cast<std::atomic<type>*>(addr), val)); \
break; \ Push(result); \
break; \
} }
ATOMIC_BINOP_CASE(I32AtomicAdd, uint32_t, atomic_fetch_add); ATOMIC_BINOP_CASE(I32AtomicAdd, uint32_t, atomic_fetch_add);
ATOMIC_BINOP_CASE(I32AtomicAdd8U, uint8_t, atomic_fetch_add); ATOMIC_BINOP_CASE(I32AtomicAdd8U, uint8_t, atomic_fetch_add);
...@@ -1593,10 +1594,44 @@ class ThreadImpl { ...@@ -1593,10 +1594,44 @@ class ThreadImpl {
ATOMIC_BINOP_CASE(I32AtomicExchange8U, uint8_t, atomic_exchange); ATOMIC_BINOP_CASE(I32AtomicExchange8U, uint8_t, atomic_exchange);
ATOMIC_BINOP_CASE(I32AtomicExchange16U, uint16_t, atomic_exchange); ATOMIC_BINOP_CASE(I32AtomicExchange16U, uint16_t, atomic_exchange);
#undef ATOMIC_BINOP_CASE #undef ATOMIC_BINOP_CASE
#define ATOMIC_LOAD_CASE(name, type, operation) \
case kExpr##name: { \
Address addr; \
if (!ExtractAtomicOpParams<type>(decoder, code, addr, pc, len)) { \
return false; \
} \
static_assert(sizeof(std::atomic<type>) == sizeof(type), \
"Size mismatch for types std::atomic<" #type \
">, and " #type); \
result = \
WasmValue(std::operation(reinterpret_cast<std::atomic<type>*>(addr))); \
Push(result); \
break; \
}
ATOMIC_LOAD_CASE(I32AtomicLoad, uint32_t, atomic_load);
ATOMIC_LOAD_CASE(I32AtomicLoad8U, uint8_t, atomic_load);
ATOMIC_LOAD_CASE(I32AtomicLoad16U, uint16_t, atomic_load);
#undef ATOMIC_LOAD_CASE
#define ATOMIC_STORE_CASE(name, type, operation) \
case kExpr##name: { \
type val; \
Address addr; \
if (!ExtractAtomicOpParams<type>(decoder, code, addr, pc, len, &val)) { \
return false; \
} \
static_assert(sizeof(std::atomic<type>) == sizeof(type), \
"Size mismatch for types std::atomic<" #type \
">, and " #type); \
std::operation(reinterpret_cast<std::atomic<type>*>(addr), val); \
break; \
}
ATOMIC_STORE_CASE(I32AtomicStore, uint32_t, atomic_store);
ATOMIC_STORE_CASE(I32AtomicStore8U, uint8_t, atomic_store);
ATOMIC_STORE_CASE(I32AtomicStore16U, uint16_t, atomic_store);
#undef ATOMIC_STORE_CASE
default: default:
return false; return false;
} }
Push(result);
return true; return true;
} }
......
...@@ -234,7 +234,7 @@ WASM_COMPILED_EXEC_TEST(I32AtomicCompareExchange8U) { ...@@ -234,7 +234,7 @@ WASM_COMPILED_EXEC_TEST(I32AtomicCompareExchange8U) {
} }
} }
WASM_COMPILED_EXEC_TEST(I32AtomicLoad) { WASM_EXEC_TEST(I32AtomicLoad) {
EXPERIMENTAL_FLAG_SCOPE(threads); EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint32_t> r(execution_mode); WasmRunner<uint32_t> r(execution_mode);
r.builder().SetHasSharedMemory(); r.builder().SetHasSharedMemory();
...@@ -249,7 +249,7 @@ WASM_COMPILED_EXEC_TEST(I32AtomicLoad) { ...@@ -249,7 +249,7 @@ WASM_COMPILED_EXEC_TEST(I32AtomicLoad) {
} }
} }
WASM_COMPILED_EXEC_TEST(I32AtomicLoad16U) { WASM_EXEC_TEST(I32AtomicLoad16U) {
EXPERIMENTAL_FLAG_SCOPE(threads); EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint32_t> r(execution_mode); WasmRunner<uint32_t> r(execution_mode);
r.builder().SetHasSharedMemory(); r.builder().SetHasSharedMemory();
...@@ -264,7 +264,7 @@ WASM_COMPILED_EXEC_TEST(I32AtomicLoad16U) { ...@@ -264,7 +264,7 @@ WASM_COMPILED_EXEC_TEST(I32AtomicLoad16U) {
} }
} }
WASM_COMPILED_EXEC_TEST(I32AtomicLoad8U) { WASM_EXEC_TEST(I32AtomicLoad8U) {
EXPERIMENTAL_FLAG_SCOPE(threads); EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint32_t> r(execution_mode); WasmRunner<uint32_t> r(execution_mode);
r.builder().SetHasSharedMemory(); r.builder().SetHasSharedMemory();
...@@ -279,7 +279,7 @@ WASM_COMPILED_EXEC_TEST(I32AtomicLoad8U) { ...@@ -279,7 +279,7 @@ WASM_COMPILED_EXEC_TEST(I32AtomicLoad8U) {
} }
} }
WASM_COMPILED_EXEC_TEST(I32AtomicStoreLoad) { WASM_EXEC_TEST(I32AtomicStoreLoad) {
EXPERIMENTAL_FLAG_SCOPE(threads); EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint32_t, uint32_t> r(execution_mode); WasmRunner<uint32_t, uint32_t> r(execution_mode);
r.builder().SetHasSharedMemory(); r.builder().SetHasSharedMemory();
...@@ -298,7 +298,7 @@ WASM_COMPILED_EXEC_TEST(I32AtomicStoreLoad) { ...@@ -298,7 +298,7 @@ WASM_COMPILED_EXEC_TEST(I32AtomicStoreLoad) {
} }
} }
WASM_COMPILED_EXEC_TEST(I32AtomicStoreLoad16U) { WASM_EXEC_TEST(I32AtomicStoreLoad16U) {
EXPERIMENTAL_FLAG_SCOPE(threads); EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint32_t, uint32_t> r(execution_mode); WasmRunner<uint32_t, uint32_t> r(execution_mode);
r.builder().SetHasSharedMemory(); r.builder().SetHasSharedMemory();
...@@ -318,7 +318,7 @@ WASM_COMPILED_EXEC_TEST(I32AtomicStoreLoad16U) { ...@@ -318,7 +318,7 @@ WASM_COMPILED_EXEC_TEST(I32AtomicStoreLoad16U) {
} }
} }
WASM_COMPILED_EXEC_TEST(I32AtomicStoreLoad8U) { WASM_EXEC_TEST(I32AtomicStoreLoad8U) {
EXPERIMENTAL_FLAG_SCOPE(threads); EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint32_t, uint32_t> r(execution_mode); WasmRunner<uint32_t, uint32_t> r(execution_mode);
r.builder().SetHasSharedMemory(); r.builder().SetHasSharedMemory();
......
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