diff --git a/src/flag-definitions.h b/src/flag-definitions.h index 8f44145054..117834d09e 100644 --- a/src/flag-definitions.h +++ b/src/flag-definitions.h @@ -528,6 +528,8 @@ DEFINE_BOOL(wasm_eh_prototype, false, "enable prototype exception handling opcodes for wasm") DEFINE_BOOL(wasm_mv_prototype, false, "enable prototype multi-value support for wasm") +DEFINE_BOOL(wasm_atomics_prototype, false, + "enable prototype atomic opcodes for wasm") DEFINE_BOOL(wasm_trap_handler, false, "use signal handlers to catch out of bounds memory access in wasm" diff --git a/src/wasm/ast-decoder.cc b/src/wasm/ast-decoder.cc index ff5211d8fb..ea7ddcf528 100644 --- a/src/wasm/ast-decoder.cc +++ b/src/wasm/ast-decoder.cc @@ -1158,6 +1158,24 @@ class WasmFullDecoder : public WasmDecoder { len += DecodeSimdOpcode(opcode); break; } + case kAtomicPrefix: { + if (!module_ || module_->origin != kAsmJsOrigin) { + error("Atomics are allowed only in AsmJs modules"); + break; + } + if (!FLAG_wasm_atomics_prototype) { + error("Invalid opcode (enable with --wasm_atomics_prototype)"); + break; + } + len = 2; + byte atomic_opcode = checked_read_u8(pc_, 1, "atomic index"); + opcode = static_cast(opcode << 8 | atomic_opcode); + sig = WasmOpcodes::AtomicSignature(opcode); + if (sig) { + BuildAtomicOperator(opcode); + } + break; + } default: { // Deal with special asmjs opcodes. if (module_ && module_->origin == kAsmJsOrigin) { @@ -1340,6 +1358,8 @@ class WasmFullDecoder : public WasmDecoder { return len; } + void BuildAtomicOperator(WasmOpcode opcode) { UNIMPLEMENTED(); } + void DoReturn() { int count = static_cast(sig_->return_count()); TFNode** buffer = nullptr; diff --git a/src/wasm/wasm-opcodes.cc b/src/wasm/wasm-opcodes.cc index cd2dde4748..8f81b81a50 100644 --- a/src/wasm/wasm-opcodes.cc +++ b/src/wasm/wasm-opcodes.cc @@ -88,6 +88,7 @@ static const FunctionSig* kSimdExprSigs[] = { static byte kSimpleExprSigTable[256]; static byte kSimpleAsmjsExprSigTable[256]; static byte kSimdExprSigTable[256]; +static byte kAtomicExprSigTable[256]; // Initialize the signature table. static void InitSigTables() { @@ -105,6 +106,12 @@ static void InitSigTables() { kSimdExprSigTable[simd_index] = static_cast(kSigEnum_##sig) + 1; FOREACH_SIMD_0_OPERAND_OPCODE(SET_SIG_TABLE) #undef SET_SIG_TABLE + byte atomic_index; +#define SET_ATOMIC_SIG_TABLE(name, opcode, sig) \ + atomic_index = opcode & 0xff; \ + kAtomicExprSigTable[atomic_index] = static_cast(kSigEnum_##sig) + 1; + FOREACH_ATOMIC_OPCODE(SET_ATOMIC_SIG_TABLE) +#undef SET_ATOMIC_SIG_TABLE } class SigTable { @@ -125,6 +132,10 @@ class SigTable { return const_cast( kSimdExprSigs[kSimdExprSigTable[static_cast(opcode & 0xff)]]); } + FunctionSig* AtomicSignature(WasmOpcode opcode) const { + return const_cast( + kSimpleExprSigs[kAtomicExprSigTable[static_cast(opcode & 0xff)]]); + } }; static base::LazyInstance::type sig_table = LAZY_INSTANCE_INITIALIZER; @@ -141,6 +152,10 @@ FunctionSig* WasmOpcodes::AsmjsSignature(WasmOpcode opcode) { return sig_table.Get().AsmjsSignature(opcode); } +FunctionSig* WasmOpcodes::AtomicSignature(WasmOpcode opcode) { + return sig_table.Get().AtomicSignature(opcode); +} + // TODO(titzer): pull WASM_64 up to a common header. #if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64 #define WASM_64 1 diff --git a/src/wasm/wasm-opcodes.h b/src/wasm/wasm-opcodes.h index 67de8e7cea..ec22579bd7 100644 --- a/src/wasm/wasm-opcodes.h +++ b/src/wasm/wasm-opcodes.h @@ -400,6 +400,43 @@ const WasmCodePosition kNoCodePosition = -1; V(I16x8ExtractLane, 0xe539, _) \ V(I8x16ExtractLane, 0xe558, _) +#define FOREACH_ATOMIC_OPCODE(V) \ + V(I32AtomicAdd8S, 0xe601, i_ii) \ + V(I32AtomicAdd8U, 0xe602, i_ii) \ + V(I32AtomicAdd16S, 0xe603, i_ii) \ + V(I32AtomicAdd16U, 0xe604, i_ii) \ + V(I32AtomicAdd32, 0xe605, i_ii) \ + V(I32AtomicAnd8S, 0xe606, i_ii) \ + V(I32AtomicAnd8U, 0xe607, i_ii) \ + V(I32AtomicAnd16S, 0xe608, i_ii) \ + V(I32AtomicAnd16U, 0xe609, i_ii) \ + V(I32AtomicAnd32, 0xe60a, i_ii) \ + V(I32AtomicCompareExchange8S, 0xe60b, i_ii) \ + V(I32AtomicCompareExchange8U, 0xe60c, i_ii) \ + V(I32AtomicCompareExchange16S, 0xe60d, i_ii) \ + V(I32AtomicCompareExchange16U, 0xe60e, i_ii) \ + V(I32AtomicCompareExchange32, 0xe60f, i_ii) \ + V(I32AtomicExchange8S, 0xe610, i_ii) \ + V(I32AtomicExchange8U, 0xe611, i_ii) \ + V(I32AtomicExchange16S, 0xe612, i_ii) \ + V(I32AtomicExchange16U, 0xe613, i_ii) \ + V(I32AtomicExchange32, 0xe614, i_ii) \ + V(I32AtomicOr8S, 0xe615, i_ii) \ + V(I32AtomicOr8U, 0xe616, i_ii) \ + V(I32AtomicOr16S, 0xe617, i_ii) \ + V(I32AtomicOr16U, 0xe618, i_ii) \ + V(I32AtomicOr32, 0xe619, i_ii) \ + V(I32AtomicSub8S, 0xe61a, i_ii) \ + V(I32AtomicSub8U, 0xe61b, i_ii) \ + V(I32AtomicSub16S, 0xe61c, i_ii) \ + V(I32AtomicSub16U, 0xe61d, i_ii) \ + V(I32AtomicSub32, 0xe61e, i_ii) \ + V(I32AtomicXor8S, 0xe61f, i_ii) \ + V(I32AtomicXor8U, 0xe620, i_ii) \ + V(I32AtomicXor16S, 0xe621, i_ii) \ + V(I32AtomicXor16U, 0xe622, i_ii) \ + V(I32AtomicXor32, 0xe623, i_ii) + // All opcodes. #define FOREACH_OPCODE(V) \ FOREACH_CONTROL_OPCODE(V) \ @@ -410,7 +447,8 @@ const WasmCodePosition kNoCodePosition = -1; FOREACH_MISC_MEM_OPCODE(V) \ FOREACH_ASMJS_COMPAT_OPCODE(V) \ FOREACH_SIMD_0_OPERAND_OPCODE(V) \ - FOREACH_SIMD_1_OPERAND_OPCODE(V) + FOREACH_SIMD_1_OPERAND_OPCODE(V) \ + FOREACH_ATOMIC_OPCODE(V) // All signatures. #define FOREACH_SIGNATURE(V) \ @@ -453,7 +491,9 @@ const WasmCodePosition kNoCodePosition = -1; V(s_sii, kAstS128, kAstS128, kAstI32, kAstI32) \ V(s_si, kAstS128, kAstS128, kAstI32) -#define FOREACH_PREFIX(V) V(Simd, 0xe5) +#define FOREACH_PREFIX(V) \ + V(Simd, 0xe5) \ + V(Atomic, 0xe6) enum WasmOpcode { // Declare expression opcodes. @@ -491,6 +531,7 @@ class V8_EXPORT_PRIVATE WasmOpcodes { static const char* ShortOpcodeName(WasmOpcode opcode); static FunctionSig* Signature(WasmOpcode opcode); static FunctionSig* AsmjsSignature(WasmOpcode opcode); + static FunctionSig* AtomicSignature(WasmOpcode opcode); static bool IsPrefixOpcode(WasmOpcode opcode); static int TrapReasonToMessageId(TrapReason reason);