From fb3321ea2763e1d5888297065ae72b7b89b54f8e Mon Sep 17 00:00:00 2001 From: Clemens Backes Date: Thu, 13 Oct 2022 10:36:53 +0200 Subject: [PATCH] [wasm] Store local types in a plain array After the let instruction was removed again, the number and types of locals stays constant throughout the decoding of a function. Hence store it in a plain array instead of a ZoneVector. This makes the decoder smaller and saves bounds checks for the "safe libc++". R=thibaudm@chromium.org Bug: chromium:1358853 Change-Id: Iad69aa0cfdc254710e1c2219cfb2c972241ef473 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3944929 Commit-Queue: Clemens Backes Reviewed-by: Thibaud Michaud Cr-Commit-Position: refs/heads/main@{#83671} --- src/wasm/function-body-decoder-impl.h | 68 ++++++++++++------- src/wasm/function-body-decoder.cc | 42 ++++++------ src/wasm/function-body-decoder.h | 19 +++--- src/wasm/value-type.h | 1 + src/wasm/wasm-debug.cc | 8 +-- src/wasm/wasm-disassembler.cc | 1 - test/common/wasm/wasm-interpreter.cc | 18 ++--- test/fuzzer/wasm-fuzzer-common.cc | 14 ++-- .../wasm/function-body-decoder-unittest.cc | 66 ++++++++---------- tools/wasm/module-inspector.cc | 1 - 10 files changed, 125 insertions(+), 113 deletions(-) diff --git a/src/wasm/function-body-decoder-impl.h b/src/wasm/function-body-decoder-impl.h index f966b0f26a..e140ea524a 100644 --- a/src/wasm/function-body-decoder-impl.h +++ b/src/wasm/function-body-decoder-impl.h @@ -1155,7 +1155,7 @@ class WasmDecoder : public Decoder { WasmFeatures* detected, const FunctionSig* sig, const byte* start, const byte* end, uint32_t buffer_offset = 0) : Decoder(start, end, buffer_offset), - local_types_(zone), + compilation_zone_(zone), module_(module), enabled_(enabled), detected_(detected), @@ -1176,20 +1176,13 @@ class WasmDecoder : public Decoder { } } - Zone* zone() const { return local_types_.get_allocator().zone(); } + Zone* zone() const { return compilation_zone_; } - uint32_t num_locals() const { - DCHECK_EQ(num_locals_, local_types_.size()); - return num_locals_; - } + uint32_t num_locals() const { return num_locals_; } - ValueType local_type(uint32_t index) const { return local_types_[index]; } - - void InitializeLocalsFromSig() { - DCHECK_NOT_NULL(sig_); - DCHECK_EQ(0, this->local_types_.size()); - local_types_.assign(sig_->parameters().begin(), sig_->parameters().end()); - num_locals_ = static_cast(sig_->parameters().size()); + ValueType local_type(uint32_t index) const { + DCHECK_GE(num_locals_, index); + return local_types_[index]; } // Decodes local definitions in the current decoder. @@ -1197,6 +1190,12 @@ class WasmDecoder : public Decoder { // The decoded locals will be appended to {this->local_types_}. // The decoder's pc is not advanced. void DecodeLocals(const byte* pc, uint32_t* total_length) { + DCHECK_NULL(local_types_); + DCHECK_EQ(0, num_locals_); + + // In a first step, count the number of locals and store the decoded + // entries. + num_locals_ = static_cast(this->sig_->parameter_count()); uint32_t length; *total_length = 0; @@ -1208,7 +1207,12 @@ class WasmDecoder : public Decoder { *total_length += length; TRACE("local decls count: %u\n", entries); - while (entries-- > 0) { + struct DecodedLocalEntry { + uint32_t count; + ValueType type; + }; + base::SmallVector decoded_locals(entries); + for (uint32_t entry = 0; entry < entries; ++entry) { if (!VALIDATE(more())) { return DecodeError( end(), "expected more local decls but reached end of input"); @@ -1219,8 +1223,8 @@ class WasmDecoder : public Decoder { if (!VALIDATE(ok())) { return DecodeError(pc + *total_length, "invalid local count"); } - DCHECK_LE(local_types_.size(), kV8MaxWasmFunctionLocals); - if (!VALIDATE(count <= kV8MaxWasmFunctionLocals - local_types_.size())) { + DCHECK_LE(num_locals_, kV8MaxWasmFunctionLocals); + if (!VALIDATE(count <= kV8MaxWasmFunctionLocals - num_locals_)) { return DecodeError(pc + *total_length, "local count too large"); } *total_length += length; @@ -1230,10 +1234,28 @@ class WasmDecoder : public Decoder { if (!VALIDATE(ok())) return; *total_length += length; - local_types_.insert(local_types_.end(), count, type); num_locals_ += count; + decoded_locals[entry] = DecodedLocalEntry{count, type}; } DCHECK(ok()); + + if (num_locals_ == 0) return; + + // Now build the array of local types from the parsed entries. + local_types_ = compilation_zone_->NewArray(num_locals_); + ValueType* locals_ptr = local_types_; + + if (sig_->parameter_count() > 0) { + std::copy(sig_->parameters().begin(), sig_->parameters().end(), + locals_ptr); + locals_ptr += sig_->parameter_count(); + } + + for (auto& entry : decoded_locals) { + std::fill_n(locals_ptr, entry.count, entry.type); + locals_ptr += entry.count; + } + DCHECK_EQ(locals_ptr, local_types_ + num_locals_); } // Shorthand that forwards to the {DecodeError} functions above, passing our @@ -2359,13 +2381,9 @@ class WasmDecoder : public Decoder { // clang-format on } - // The {Zone} is implicitly stored in the {ZoneAllocator} which is part of - // this {ZoneVector}. Hence save one field and just get it from there if - // needed (see {zone()} accessor below). - ZoneVector local_types_; + Zone* const compilation_zone_; - // Cached value, for speed (yes, it's measurably faster to load this value - // than to load the start and end pointer from a vector, subtract and shift). + ValueType* local_types_ = nullptr; uint32_t num_locals_ = 0; const WasmModule* module_; @@ -2437,13 +2455,13 @@ class WasmFullDecoder : public WasmDecoder { DCHECK_EQ(this->num_locals(), 0); locals_offset_ = this->pc_offset(); - this->InitializeLocalsFromSig(); - uint32_t params_count = this->num_locals(); uint32_t locals_length; this->DecodeLocals(this->pc(), &locals_length); if (this->failed()) return TraceFailed(); this->consume_bytes(locals_length); int non_defaultable = 0; + uint32_t params_count = + static_cast(this->sig_->parameter_count()); for (uint32_t index = params_count; index < this->num_locals(); index++) { if (!this->local_type(index).is_defaultable()) non_defaultable++; } diff --git a/src/wasm/function-body-decoder.cc b/src/wasm/function-body-decoder.cc index c50da6e182..2d25af7e27 100644 --- a/src/wasm/function-body-decoder.cc +++ b/src/wasm/function-body-decoder.cc @@ -18,11 +18,11 @@ namespace wasm { bool DecodeLocalDecls(const WasmFeatures& enabled, BodyLocalDecls* decls, const WasmModule* module, const byte* start, - const byte* end) { + const byte* end, Zone* zone) { WasmFeatures no_features = WasmFeatures::None(); - Zone* zone = decls->type_list.get_allocator().zone(); + constexpr FixedSizeSignature kNoSig; WasmDecoder decoder( - zone, module, enabled, &no_features, nullptr, start, end, 0); + zone, module, enabled, &no_features, &kNoSig, start, end, 0); uint32_t length; decoder.DecodeLocals(decoder.pc(), &length); if (decoder.failed()) { @@ -31,20 +31,24 @@ bool DecodeLocalDecls(const WasmFeatures& enabled, BodyLocalDecls* decls, } DCHECK(decoder.ok()); decls->encoded_size = length; - // Copy the decoded locals types into {decls->type_list}. - DCHECK(decls->type_list.empty()); - decls->type_list = std::move(decoder.local_types_); + // Copy the decoded locals types into {decls->local_types}. + DCHECK_NULL(decls->local_types); + decls->num_locals = decoder.num_locals_; + decls->local_types = decoder.local_types_; return true; } +BytecodeIterator::BytecodeIterator(const byte* start, const byte* end) + : Decoder(start, end) {} + BytecodeIterator::BytecodeIterator(const byte* start, const byte* end, - BodyLocalDecls* decls) + BodyLocalDecls* decls, Zone* zone) : Decoder(start, end) { - if (decls != nullptr) { - if (DecodeLocalDecls(WasmFeatures::All(), decls, nullptr, start, end)) { - pc_ += decls->encoded_size; - if (pc_ > end_) pc_ = end_; - } + DCHECK_NOT_NULL(decls); + DCHECK_NOT_NULL(zone); + if (DecodeLocalDecls(WasmFeatures::All(), decls, nullptr, start, end, zone)) { + pc_ += decls->encoded_size; + if (pc_ > end_) pc_ = end_; } } @@ -141,19 +145,19 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body, } // Print the local declarations. - BodyLocalDecls decls(&zone); - BytecodeIterator i(body.start, body.end, &decls); + BodyLocalDecls decls; + BytecodeIterator i(body.start, body.end, &decls, &zone); if (body.start != i.pc() && print_locals == kPrintLocals) { os << "// locals:"; - if (!decls.type_list.empty()) { - ValueType type = decls.type_list[0]; + if (decls.num_locals > 0) { + ValueType type = decls.local_types[0]; uint32_t count = 0; - for (size_t pos = 0; pos < decls.type_list.size(); ++pos) { - if (decls.type_list[pos] == type) { + for (size_t pos = 0; pos < decls.num_locals; ++pos) { + if (decls.local_types[pos] == type) { ++count; } else { os << " " << count << " " << type.name(); - type = decls.type_list[pos]; + type = decls.local_types[pos]; count = 1; } } diff --git a/src/wasm/function-body-decoder.h b/src/wasm/function-body-decoder.h index dd57e64f4e..d6fb2cfd99 100644 --- a/src/wasm/function-body-decoder.h +++ b/src/wasm/function-body-decoder.h @@ -64,15 +64,15 @@ struct BodyLocalDecls { // The size of the encoded declarations. uint32_t encoded_size = 0; // size of encoded declarations - ZoneVector type_list; - - explicit BodyLocalDecls(Zone* zone) : type_list(zone) {} + uint32_t num_locals = 0; + ValueType* local_types = nullptr; }; V8_EXPORT_PRIVATE bool DecodeLocalDecls(const WasmFeatures& enabled, BodyLocalDecls* decls, const WasmModule* module, - const byte* start, const byte* end); + const byte* start, const byte* end, + Zone* zone); V8_EXPORT_PRIVATE BitVector* AnalyzeLoopAssignmentForTesting( Zone* zone, uint32_t num_locals, const byte* start, const byte* end); @@ -150,11 +150,12 @@ class V8_EXPORT_PRIVATE BytecodeIterator : public NON_EXPORTED_BASE(Decoder) { : iterator_base(ptr, end), start_(start) {} }; - // Create a new {BytecodeIterator}. If the {decls} pointer is non-null, - // assume the bytecode starts with local declarations and decode them. - // Otherwise, do not decode local decls. - BytecodeIterator(const byte* start, const byte* end, - BodyLocalDecls* decls = nullptr); + // Create a new {BytecodeIterator}, starting after the locals declarations. + BytecodeIterator(const byte* start, const byte* end); + + // Create a new {BytecodeIterator}, starting with locals declarations. + BytecodeIterator(const byte* start, const byte* end, BodyLocalDecls* decls, + Zone* zone); base::iterator_range opcodes() { return base::iterator_range(opcode_iterator(pc_, end_), diff --git a/src/wasm/value-type.h b/src/wasm/value-type.h index fed87cfb99..da001f037a 100644 --- a/src/wasm/value-type.h +++ b/src/wasm/value-type.h @@ -666,6 +666,7 @@ class ValueType { uint32_t bit_field_; }; +ASSERT_TRIVIALLY_COPYABLE(ValueType); inline constexpr intptr_t ValueType::kBitFieldOffset = offsetof(ValueType, bit_field_); diff --git a/src/wasm/wasm-debug.cc b/src/wasm/wasm-debug.cc index 802c7fa940..d64a9c7032 100644 --- a/src/wasm/wasm-debug.cc +++ b/src/wasm/wasm-debug.cc @@ -783,13 +783,13 @@ int FindNextBreakablePosition(wasm::NativeModule* native_module, int func_index, int offset_in_func) { AccountingAllocator alloc; Zone tmp(&alloc, ZONE_NAME); - wasm::BodyLocalDecls locals(&tmp); + wasm::BodyLocalDecls locals; const byte* module_start = native_module->wire_bytes().begin(); const wasm::WasmFunction& func = native_module->module()->functions[func_index]; wasm::BytecodeIterator iterator(module_start + func.code.offset(), module_start + func.code.end_offset(), - &locals); + &locals, &tmp); DCHECK_LT(0, locals.encoded_size); if (offset_in_func < 0) return 0; for (; iterator.has_next(); iterator.next()) { @@ -1099,10 +1099,10 @@ bool WasmScript::GetPossibleBreakpoints( const wasm::WasmFunction& func = functions[func_idx]; if (func.code.length() == 0) continue; - wasm::BodyLocalDecls locals(&tmp); + wasm::BodyLocalDecls locals; wasm::BytecodeIterator iterator(module_start + func.code.offset(), module_start + func.code.end_offset(), - &locals); + &locals, &tmp); DCHECK_LT(0u, locals.encoded_size); for (; iterator.has_next(); iterator.next()) { uint32_t total_offset = func.code.offset() + iterator.pc_offset(); diff --git a/src/wasm/wasm-disassembler.cc b/src/wasm/wasm-disassembler.cc index d43b911e48..3504b6d998 100644 --- a/src/wasm/wasm-disassembler.cc +++ b/src/wasm/wasm-disassembler.cc @@ -168,7 +168,6 @@ void FunctionBodyDisassembler::DecodeAsWat(MultiLineStringBuilder& out, // Decode and print locals. uint32_t locals_length; - InitializeLocalsFromSig(); DecodeLocals(pc_, &locals_length); if (failed()) { // TODO(jkummerow): Improve error handling. diff --git a/test/common/wasm/wasm-interpreter.cc b/test/common/wasm/wasm-interpreter.cc index b3903c97fe..bb34b53b43 100644 --- a/test/common/wasm/wasm-interpreter.cc +++ b/test/common/wasm/wasm-interpreter.cc @@ -749,7 +749,7 @@ class SideTable : public ZoneObject { max_exception_arity, static_cast(tag.sig->parameter_count())); } } - for (BytecodeIterator i(code->start, code->end, &code->locals); + for (BytecodeIterator i(code->start, code->end, &code->locals, zone); i.has_next(); i.next()) { WasmOpcode opcode = i.current(); int32_t exceptional_stack_height = 0; @@ -1119,8 +1119,8 @@ class CodeMap { void AddFunction(const WasmFunction* function, const byte* code_start, const byte* code_end) { - InterpreterCode code = {function, BodyLocalDecls(zone_), code_start, - code_end, nullptr}; + InterpreterCode code = {function, BodyLocalDecls{}, code_start, code_end, + nullptr}; DCHECK_EQ(interpreter_code_.size(), function->func_index); interpreter_code_.push_back(code); @@ -1334,7 +1334,7 @@ class WasmInterpreterInternals { // Limit of parameters. sp_t plimit() { return sp + code->function->sig->parameter_count(); } // Limit of locals. - sp_t llimit() { return plimit() + code->locals.type_list.size(); } + sp_t llimit() { return plimit() + code->locals.num_locals; } Handle caught_exception_stack; }; @@ -1407,7 +1407,7 @@ class WasmInterpreterInternals { // Check if there is room for a function's activation. void EnsureStackSpaceForCall(InterpreterCode* code) { EnsureStackSpace(code->side_table->max_stack_height_ + - code->locals.type_list.size()); + code->locals.num_locals); DCHECK_GE(StackHeight(), code->function->sig->parameter_count()); } @@ -1430,7 +1430,8 @@ class WasmInterpreterInternals { } pc_t InitLocals(InterpreterCode* code) { - for (ValueType p : code->locals.type_list) { + for (ValueType p : + base::VectorOf(code->locals.local_types, code->locals.num_locals)) { WasmValue val; switch (p.kind()) { #define CASE_TYPE(valuetype, ctype) \ @@ -3313,8 +3314,7 @@ class WasmInterpreterInternals { DCHECK(!frames_.empty()); // There must be enough space on the stack to hold the arguments, locals, // and the value stack. - DCHECK_LE(code->function->sig->parameter_count() + - code->locals.type_list.size() + + DCHECK_LE(code->function->sig->parameter_count() + code->locals.num_locals + code->side_table->max_stack_height_, stack_limit_ - stack_.get() - frames_.back().sp); // Seal the surrounding {HandleScope} to ensure that all cases within the @@ -4242,7 +4242,7 @@ ControlTransferMap WasmInterpreter::ComputeControlTransfersForTesting( false, // imported false, // exported false}; // declared - InterpreterCode code{&function, BodyLocalDecls(zone), start, end, nullptr}; + InterpreterCode code{&function, BodyLocalDecls{}, start, end, nullptr}; // Now compute and return the control transfers. SideTable side_table(zone, module, &code); diff --git a/test/fuzzer/wasm-fuzzer-common.cc b/test/fuzzer/wasm-fuzzer-common.cc index 48189fddf0..7193ffc3ef 100644 --- a/test/fuzzer/wasm-fuzzer-common.cc +++ b/test/fuzzer/wasm-fuzzer-common.cc @@ -681,15 +681,15 @@ void GenerateTestCase(Isolate* isolate, ModuleWireBytes wire_bytes, << " /* sig */)\n"; // Add locals. - BodyLocalDecls decls(&tmp_zone); + BodyLocalDecls decls; DecodeLocalDecls(enabled_features, &decls, module, func_code.begin(), - func_code.end()); - if (!decls.type_list.empty()) { + func_code.end(), &tmp_zone); + if (decls.num_locals) { os << " "; - for (size_t pos = 0, count = 1, locals = decls.type_list.size(); - pos < locals; pos += count, count = 1) { - ValueType type = decls.type_list[pos]; - while (pos + count < locals && decls.type_list[pos + count] == type) { + for (size_t pos = 0, count = 1, locals = decls.num_locals; pos < locals; + pos += count, count = 1) { + ValueType type = decls.local_types[pos]; + while (pos + count < locals && decls.local_types[pos + count] == type) { ++count; } os << ".addLocals(" << ValueTypeToConstantName(type) << ", " << count diff --git a/test/unittests/wasm/function-body-decoder-unittest.cc b/test/unittests/wasm/function-body-decoder-unittest.cc index 5e5ba775dd..1b031200b5 100644 --- a/test/unittests/wasm/function-body-decoder-unittest.cc +++ b/test/unittests/wasm/function-body-decoder-unittest.cc @@ -4991,17 +4991,15 @@ TEST_F(TypeReaderTest, HeapTypeDecodingTest) { } } -using TypesOfLocals = ZoneVector; - class LocalDeclDecoderTest : public TestWithZone { public: v8::internal::AccountingAllocator allocator; WasmFeatures enabled_features_; - size_t ExpectRun(TypesOfLocals map, size_t pos, ValueType expected, + size_t ExpectRun(ValueType* local_types, size_t pos, ValueType expected, size_t count) { for (size_t i = 0; i < count; i++) { - EXPECT_EQ(expected, map[pos++]); + EXPECT_EQ(expected, local_types[pos++]); } return pos; } @@ -5010,27 +5008,27 @@ class LocalDeclDecoderTest : public TestWithZone { const byte* end) { WasmModule module; return i::wasm::DecodeLocalDecls(enabled_features_, decls, &module, start, - end); + end, zone()); } }; TEST_F(LocalDeclDecoderTest, EmptyLocals) { - BodyLocalDecls decls(zone()); + BodyLocalDecls decls; bool result = DecodeLocalDecls(&decls, nullptr, nullptr); EXPECT_FALSE(result); } TEST_F(LocalDeclDecoderTest, NoLocals) { static const byte data[] = {0}; - BodyLocalDecls decls(zone()); + BodyLocalDecls decls; bool result = DecodeLocalDecls(&decls, data, data + sizeof(data)); EXPECT_TRUE(result); - EXPECT_TRUE(decls.type_list.empty()); + EXPECT_EQ(0u, decls.num_locals); } TEST_F(LocalDeclDecoderTest, WrongLocalDeclsCount1) { static const byte data[] = {1}; - BodyLocalDecls decls(zone()); + BodyLocalDecls decls; bool result = DecodeLocalDecls(&decls, data, data + sizeof(data)); EXPECT_FALSE(result); } @@ -5038,7 +5036,7 @@ TEST_F(LocalDeclDecoderTest, WrongLocalDeclsCount1) { TEST_F(LocalDeclDecoderTest, WrongLocalDeclsCount2) { static const byte data[] = {2, 1, static_cast(kWasmI32.value_type_code())}; - BodyLocalDecls decls(zone()); + BodyLocalDecls decls; bool result = DecodeLocalDecls(&decls, data, data + sizeof(data)); EXPECT_FALSE(result); } @@ -5047,13 +5045,12 @@ TEST_F(LocalDeclDecoderTest, OneLocal) { for (size_t i = 0; i < arraysize(kValueTypes); i++) { ValueType type = kValueTypes[i]; const byte data[] = {1, 1, static_cast(type.value_type_code())}; - BodyLocalDecls decls(zone()); + BodyLocalDecls decls; bool result = DecodeLocalDecls(&decls, data, data + sizeof(data)); EXPECT_TRUE(result); - EXPECT_EQ(1u, decls.type_list.size()); + EXPECT_EQ(1u, decls.num_locals); - TypesOfLocals map = decls.type_list; - EXPECT_EQ(type, map[0]); + EXPECT_EQ(type, decls.local_types[0]); } } @@ -5061,15 +5058,12 @@ TEST_F(LocalDeclDecoderTest, FiveLocals) { for (size_t i = 0; i < arraysize(kValueTypes); i++) { ValueType type = kValueTypes[i]; const byte data[] = {1, 5, static_cast(type.value_type_code())}; - BodyLocalDecls decls(zone()); + BodyLocalDecls decls; bool result = DecodeLocalDecls(&decls, data, data + sizeof(data)); EXPECT_TRUE(result); EXPECT_EQ(sizeof(data), decls.encoded_size); - EXPECT_EQ(5u, decls.type_list.size()); - - TypesOfLocals map = decls.type_list; - EXPECT_EQ(5u, map.size()); - ExpectRun(map, 0, type, 5); + EXPECT_EQ(5u, decls.num_locals); + ExpectRun(decls.local_types, 0, type, 5); } } @@ -5080,20 +5074,17 @@ TEST_F(LocalDeclDecoderTest, MixedLocals) { for (byte d = 0; d < 3; d++) { const byte data[] = {4, a, kI32Code, b, kI64Code, c, kF32Code, d, kF64Code}; - BodyLocalDecls decls(zone()); + BodyLocalDecls decls; bool result = DecodeLocalDecls(&decls, data, data + sizeof(data)); EXPECT_TRUE(result); EXPECT_EQ(sizeof(data), decls.encoded_size); - EXPECT_EQ(static_cast(a + b + c + d), - decls.type_list.size()); - - TypesOfLocals map = decls.type_list; + EXPECT_EQ(static_cast(a + b + c + d), decls.num_locals); size_t pos = 0; - pos = ExpectRun(map, pos, kWasmI32, a); - pos = ExpectRun(map, pos, kWasmI64, b); - pos = ExpectRun(map, pos, kWasmF32, c); - pos = ExpectRun(map, pos, kWasmF64, d); + pos = ExpectRun(decls.local_types, pos, kWasmI32, a); + pos = ExpectRun(decls.local_types, pos, kWasmI64, b); + pos = ExpectRun(decls.local_types, pos, kWasmF32, c); + pos = ExpectRun(decls.local_types, pos, kWasmF64, d); } } } @@ -5110,16 +5101,15 @@ TEST_F(LocalDeclDecoderTest, UseEncoder) { local_decls.AddLocals(212, kWasmI64); local_decls.Prepend(zone(), &data, &end); - BodyLocalDecls decls(zone()); + BodyLocalDecls decls; bool result = DecodeLocalDecls(&decls, data, end); EXPECT_TRUE(result); - EXPECT_EQ(5u + 1337u + 212u, decls.type_list.size()); + EXPECT_EQ(5u + 1337u + 212u, decls.num_locals); - TypesOfLocals map = decls.type_list; size_t pos = 0; - pos = ExpectRun(map, pos, kWasmF32, 5); - pos = ExpectRun(map, pos, kWasmI32, 1337); - pos = ExpectRun(map, pos, kWasmI64, 212); + pos = ExpectRun(decls.local_types, pos, kWasmF32, 5); + pos = ExpectRun(decls.local_types, pos, kWasmI32, 1337); + pos = ExpectRun(decls.local_types, pos, kWasmI64, 212); } TEST_F(LocalDeclDecoderTest, InvalidTypeIndex) { @@ -5130,7 +5120,7 @@ TEST_F(LocalDeclDecoderTest, InvalidTypeIndex) { LocalDeclEncoder local_decls(zone()); local_decls.AddLocals(1, ValueType::RefNull(0)); - BodyLocalDecls decls(zone()); + BodyLocalDecls decls; bool result = DecodeLocalDecls(&decls, data, end); EXPECT_FALSE(result); } @@ -5195,8 +5185,8 @@ TEST_F(BytecodeIteratorTest, ForeachOffset) { TEST_F(BytecodeIteratorTest, WithLocalDecls) { byte code[] = {1, 1, kI32Code, WASM_I32V_1(9), WASM_I32V_1(11)}; - BodyLocalDecls decls(zone()); - BytecodeIterator iter(code, code + sizeof(code), &decls); + BodyLocalDecls decls; + BytecodeIterator iter(code, code + sizeof(code), &decls, zone()); EXPECT_EQ(3u, decls.encoded_size); EXPECT_EQ(3u, iter.pc_offset()); diff --git a/tools/wasm/module-inspector.cc b/tools/wasm/module-inspector.cc index 7ae2069f2c..267542b24e 100644 --- a/tools/wasm/module-inspector.cc +++ b/tools/wasm/module-inspector.cc @@ -234,7 +234,6 @@ class ExtendedFunctionDis : public FunctionBodyDisassembler { // Decode and print locals. uint32_t locals_length; - InitializeLocalsFromSig(); DecodeLocals(pc_, &locals_length); if (failed()) { // TODO(jkummerow): Better error handling.