diff --git a/src/wasm/function-body-decoder-impl.h b/src/wasm/function-body-decoder-impl.h index 65b5a284a2..bf88f2bb8c 100644 --- a/src/wasm/function-body-decoder-impl.h +++ b/src/wasm/function-body-decoder-impl.h @@ -561,9 +561,19 @@ struct SelectTypeImmediate { struct BlockTypeImmediate { uint32_t length = 1; - ValueType type = kWasmVoid; - uint32_t sig_index = 0; - const FunctionSig* sig = nullptr; + // After decoding, either {sig_index} is set XOR {sig} points to + // {single_return_sig_storage}. + uint32_t sig_index; + FunctionSig sig{0, 0, single_return_sig_storage}; + // Internal field, potentially pointed to by {sig}. Do not access directly. + ValueType single_return_sig_storage[1]; + + // Do not copy or move, as {sig} might point to {single_return_sig_storage} so + // this cannot trivially be copied. If needed, define those operators later. + BlockTypeImmediate(const BlockTypeImmediate&) = delete; + BlockTypeImmediate(BlockTypeImmediate&&) = delete; + BlockTypeImmediate& operator=(const BlockTypeImmediate&) = delete; + BlockTypeImmediate& operator=(BlockTypeImmediate&&) = delete; template BlockTypeImmediate(const WasmFeatures& enabled, Decoder* decoder, @@ -579,34 +589,26 @@ struct BlockTypeImmediate { block_type); return; } - if (static_cast(block_type & 0x7F) == kVoidCode) return; - type = value_type_reader::read_value_type( - decoder, pc, &length, enabled); + if (static_cast(block_type & 0x7F) != kVoidCode) { + sig = FunctionSig{1, 0, single_return_sig_storage}; + single_return_sig_storage[0] = + value_type_reader::read_value_type(decoder, pc, + &length, enabled); + } } else { - type = kWasmBottom; + sig = FunctionSig{0, 0, nullptr}; sig_index = static_cast(block_type); } } uint32_t in_arity() const { - if (type != kWasmBottom) return 0; - return static_cast(sig->parameter_count()); + return static_cast(sig.parameter_count()); } uint32_t out_arity() const { - if (type == kWasmVoid) return 0; - if (type != kWasmBottom) return 1; - return static_cast(sig->return_count()); - } - ValueType in_type(uint32_t index) { - DCHECK_EQ(kWasmBottom, type); - return sig->GetParam(index); - } - ValueType out_type(uint32_t index) { - if (type == kWasmBottom) return sig->GetReturn(index); - DCHECK_NE(kWasmVoid, type); - DCHECK_EQ(0, index); - return type; + return static_cast(sig.return_count()); } + ValueType in_type(uint32_t index) { return sig.GetParam(index); } + ValueType out_type(uint32_t index) { return sig.GetReturn(index); } }; struct BranchDepthImmediate { @@ -1653,14 +1655,21 @@ class WasmDecoder : public Decoder { } bool Validate(const byte* pc, BlockTypeImmediate& imm) { - if (!ValidateValueType(pc, imm.type)) return false; - if (imm.type == kWasmBottom) { + if (imm.sig.all().begin() == nullptr) { + // Then use {sig_index} to initialize the signature. if (!VALIDATE(module_->has_signature(imm.sig_index))) { DecodeError(pc, "block type index %u is not a signature definition", imm.sig_index); return false; } - imm.sig = module_->signature(imm.sig_index); + imm.sig = *module_->signature(imm.sig_index); + } else { + // Then it's an MVP immediate with 0 parameters and 0-1 returns. + DCHECK_EQ(0, imm.sig.parameter_count()); + DCHECK_GE(1, imm.sig.return_count()); + if (imm.sig.return_count()) { + if (!ValidateValueType(pc, imm.sig.GetReturn(0))) return false; + } } return true; } @@ -3000,11 +3009,11 @@ class WasmFullDecoder : public WasmDecoder { DECODE(Block) { BlockTypeImmediate imm(this->enabled_, this, this->pc_ + 1, validate); if (!this->Validate(this->pc_ + 1, imm)) return 0; - ArgVector args = PeekArgs(imm.sig); + ArgVector args = PeekArgs(&imm.sig); Control* block = PushControl(kControlBlock, args.length()); SetBlockType(block, imm, args.begin()); CALL_INTERFACE_IF_OK_AND_REACHABLE(Block, block); - DropArgs(imm.sig); + DropArgs(&imm.sig); PushMergeValues(block, &block->start_merge); return 1 + imm.length; } @@ -3038,13 +3047,13 @@ class WasmFullDecoder : public WasmDecoder { this->detected_->Add(kFeature_eh); BlockTypeImmediate imm(this->enabled_, this, this->pc_ + 1, validate); if (!this->Validate(this->pc_ + 1, imm)) return 0; - ArgVector args = PeekArgs(imm.sig); + ArgVector args = PeekArgs(&imm.sig); Control* try_block = PushControl(kControlTry, args.length()); SetBlockType(try_block, imm, args.begin()); try_block->previous_catch = current_catch_; current_catch_ = static_cast(control_depth() - 1); CALL_INTERFACE_IF_OK_AND_REACHABLE(Try, try_block); - DropArgs(imm.sig); + DropArgs(&imm.sig); PushMergeValues(try_block, &try_block->start_merge); return 1 + imm.length; } @@ -3225,11 +3234,11 @@ class WasmFullDecoder : public WasmDecoder { DECODE(Loop) { BlockTypeImmediate imm(this->enabled_, this, this->pc_ + 1, validate); if (!this->Validate(this->pc_ + 1, imm)) return 0; - ArgVector args = PeekArgs(imm.sig); + ArgVector args = PeekArgs(&imm.sig); Control* block = PushControl(kControlLoop, args.length()); SetBlockType(&control_.back(), imm, args.begin()); CALL_INTERFACE_IF_OK_AND_REACHABLE(Loop, block); - DropArgs(imm.sig); + DropArgs(&imm.sig); PushMergeValues(block, &block->start_merge); return 1 + imm.length; } @@ -3238,13 +3247,13 @@ class WasmFullDecoder : public WasmDecoder { BlockTypeImmediate imm(this->enabled_, this, this->pc_ + 1, validate); if (!this->Validate(this->pc_ + 1, imm)) return 0; Value cond = Peek(0, 0, kWasmI32); - ArgVector args = PeekArgs(imm.sig, 1); + ArgVector args = PeekArgs(&imm.sig, 1); if (!VALIDATE(this->ok())) return 0; Control* if_block = PushControl(kControlIf, 1 + args.length()); SetBlockType(if_block, imm, args.begin()); CALL_INTERFACE_IF_OK_AND_REACHABLE(If, cond, if_block); Drop(cond); - DropArgs(imm.sig); // Drop {args}. + DropArgs(&imm.sig); PushMergeValues(if_block, &if_block->start_merge); return 1 + imm.length; } @@ -4033,7 +4042,7 @@ class WasmFullDecoder : public WasmDecoder { // Peeks arguments as required by signature. V8_INLINE ArgVector PeekArgs(const FunctionSig* sig, int depth = 0) { - int count = sig ? static_cast(sig->parameter_count()) : 0; + int count = static_cast(sig->parameter_count()); if (count == 0) return {}; EnsureStackArguments(depth + count); ArgVector args(stack_value(depth + count), count); @@ -4045,7 +4054,7 @@ class WasmFullDecoder : public WasmDecoder { // Drops a number of stack elements equal to the {sig}'s parameter count (0 if // {sig} is null), or all of them if less are present. V8_INLINE void DropArgs(const FunctionSig* sig) { - int count = sig ? static_cast(sig->parameter_count()) : 0; + int count = static_cast(sig->parameter_count()); Drop(count); } diff --git a/src/wasm/value-type.cc b/src/wasm/value-type.cc index da184941a6..f84de26a6a 100644 --- a/src/wasm/value-type.cc +++ b/src/wasm/value-type.cc @@ -12,21 +12,11 @@ namespace wasm { base::Optional WasmReturnTypeFromSignature( const FunctionSig* wasm_signature) { - if (wasm_signature->return_count() == 0) { - return {}; - } else { - DCHECK_EQ(wasm_signature->return_count(), 1); - ValueType return_type = wasm_signature->GetReturn(0); - switch (return_type.kind()) { - case kI32: - case kI64: - case kF32: - case kF64: - return {return_type.kind()}; - default: - UNREACHABLE(); - } - } + if (wasm_signature->return_count() == 0) return {}; + + DCHECK_EQ(wasm_signature->return_count(), 1); + ValueType return_type = wasm_signature->GetReturn(0); + return {return_type.kind()}; } #if DEBUG diff --git a/src/wasm/wasm-disassembler.cc b/src/wasm/wasm-disassembler.cc index 3ab0805178..1a6d6e8615 100644 --- a/src/wasm/wasm-disassembler.cc +++ b/src/wasm/wasm-disassembler.cc @@ -310,16 +310,7 @@ class ImmediatesPrinter { } void BlockType(BlockTypeImmediate& imm) { - if (imm.type == kWasmBottom) { - const FunctionSig* sig = owner_->module_->signature(imm.sig_index); - PrintSignatureOneLine(out_, sig, 0 /* ignored */, names(), false); - } else if (imm.type == kWasmVoid) { - // Just be silent. - } else { - out_ << " (result "; - names()->PrintValueType(out_, imm.type); - out_ << ")"; - } + PrintSignatureOneLine(out_, &imm.sig, 0 /* ignored */, names(), false); } void HeapType(HeapTypeImmediate& imm) { diff --git a/test/common/wasm/wasm-interpreter.cc b/test/common/wasm/wasm-interpreter.cc index d8a5318833..7a0592d84c 100644 --- a/test/common/wasm/wasm-interpreter.cc +++ b/test/common/wasm/wasm-interpreter.cc @@ -751,6 +751,14 @@ class SideTable : public ZoneObject { max_exception_arity, static_cast(tag.sig->parameter_count())); } } + WasmFeatures unused_detected_features; + WasmDecoder decoder{zone, + module, + WasmFeatures::All(), + &unused_detected_features, + code->function->sig, + code->start, + code->end}; for (BytecodeIterator i(code->start, code->end, &code->locals, zone); i.has_next(); i.next()) { WasmOpcode opcode = i.current(); @@ -794,11 +802,9 @@ class SideTable : public ZoneObject { case kExprBlock: case kExprLoop: { bool is_loop = opcode == kExprLoop; - BlockTypeImmediate imm(WasmFeatures::All(), &i, i.pc() + 1, + BlockTypeImmediate imm(WasmFeatures::All(), &decoder, i.pc() + 1, kNoValidate); - if (imm.type == kWasmBottom) { - imm.sig = module->signature(imm.sig_index); - } + CHECK(decoder.Validate(i.pc() + 1, imm)); TRACE("control @%u: %s, arity %d->%d\n", i.pc_offset(), is_loop ? "Loop" : "Block", imm.in_arity(), imm.out_arity()); DCHECK_IMPLIES(!unreachable, @@ -816,11 +822,9 @@ class SideTable : public ZoneObject { break; } case kExprIf: { - BlockTypeImmediate imm(WasmFeatures::All(), &i, i.pc() + 1, + BlockTypeImmediate imm(WasmFeatures::All(), &decoder, i.pc() + 1, kNoValidate); - if (imm.type == kWasmBottom) { - imm.sig = module->signature(imm.sig_index); - } + CHECK(decoder.Validate(i.pc() + 1, imm)); TRACE("control @%u: If, arity %d->%d\n", i.pc_offset(), imm.in_arity(), imm.out_arity()); DCHECK_IMPLIES(!unreachable, @@ -877,11 +881,9 @@ class SideTable : public ZoneObject { break; } case kExprTry: { - BlockTypeImmediate imm(WasmFeatures::All(), &i, i.pc() + 1, + BlockTypeImmediate imm(WasmFeatures::All(), &decoder, i.pc() + 1, kNoValidate); - if (imm.type == kWasmBottom) { - imm.sig = module->signature(imm.sig_index); - } + CHECK(decoder.Validate(i.pc() + 1, imm)); TRACE("control @%u: Try, arity %d->%d\n", i.pc_offset(), imm.in_arity(), imm.out_arity()); int target_stack_height = stack_height - imm.in_arity(); @@ -901,7 +903,7 @@ class SideTable : public ZoneObject { break; } case kExprRethrow: { - BranchDepthImmediate imm(&i, i.pc() + 1, kNoValidate); + BranchDepthImmediate imm(&decoder, i.pc() + 1, kNoValidate); int index = static_cast(control_stack.size()) - 1 - imm.depth; rethrow_map_.emplace(i.pc() - i.start(), index); break; @@ -912,7 +914,7 @@ class SideTable : public ZoneObject { // Only pop the exception stack once when we enter the first catch. exception_stack.pop_back(); } - TagIndexImmediate imm(&i, i.pc() + 1, kNoValidate); + TagIndexImmediate imm(&decoder, i.pc() + 1, kNoValidate); Control* c = &control_stack.back(); copy_unreachable(); TRACE("control @%u: Catch\n", i.pc_offset()); @@ -980,7 +982,7 @@ class SideTable : public ZoneObject { break; } case kExprDelegate: { - BranchDepthImmediate imm(&i, i.pc() + 1, kNoValidate); + BranchDepthImmediate imm(&decoder, i.pc() + 1, kNoValidate); TRACE("control @%u: Delegate[depth=%u]\n", i.pc_offset(), imm.depth); Control* c = &control_stack.back(); const size_t new_stack_size = control_stack.size() - 1; @@ -1018,21 +1020,21 @@ class SideTable : public ZoneObject { break; } case kExprBr: { - BranchDepthImmediate imm(&i, i.pc() + 1, kNoValidate); + BranchDepthImmediate imm(&decoder, i.pc() + 1, kNoValidate); TRACE("control @%u: Br[depth=%u]\n", i.pc_offset(), imm.depth); Control* c = &control_stack[control_stack.size() - imm.depth - 1]; if (!unreachable) c->end_label->Ref(i.pc(), stack_height); break; } case kExprBrIf: { - BranchDepthImmediate imm(&i, i.pc() + 1, kNoValidate); + BranchDepthImmediate imm(&decoder, i.pc() + 1, kNoValidate); TRACE("control @%u: BrIf[depth=%u]\n", i.pc_offset(), imm.depth); Control* c = &control_stack[control_stack.size() - imm.depth - 1]; if (!unreachable) c->end_label->Ref(i.pc(), stack_height); break; } case kExprBrTable: { - BranchTableImmediate imm(&i, i.pc() + 1, kNoValidate); + BranchTableImmediate imm(&decoder, i.pc() + 1, kNoValidate); BranchTableIterator iterator(&i, imm); TRACE("control @%u: BrTable[count=%u]\n", i.pc_offset(), imm.table_count);