Commit ccfb815c authored by mtrofin's avatar mtrofin Committed by Commit bot

[wasm] factor lower level utilties out of WasmFullDecoder

Separated:
- decoding of locals
- loop assignment analysis
- determination of opcode length

as statics that work on a Decoder. Neither need the context of a
Module, and were used in scenarios where one wasn't available either.

Changed BodyLocalDecls to match the usecases for the type. In all but
one (a printer), we want the list (in order of declaration, with
repetitions) of types of locals.

Removed a now-unnecessary constructor for the WasmFullDecoder.

BUG=

Review-Url: https://codereview.chromium.org/2610813009
Cr-Commit-Position: refs/heads/master@{#42115}
parent 0d726624
...@@ -284,6 +284,7 @@ class Decoder { ...@@ -284,6 +284,7 @@ class Decoder {
const byte* start() const { return start_; } const byte* start() const { return start_; }
const byte* pc() const { return pc_; } const byte* pc() const { return pc_; }
uint32_t pc_offset() const { return static_cast<uint32_t>(pc_ - start_); } uint32_t pc_offset() const { return static_cast<uint32_t>(pc_ - start_); }
const byte* end() const { return end_; }
protected: protected:
const byte* start_; const byte* start_;
......
This diff is collapsed.
...@@ -359,20 +359,15 @@ inline DecodeResult BuildTFGraph(AccountingAllocator* allocator, ...@@ -359,20 +359,15 @@ inline DecodeResult BuildTFGraph(AccountingAllocator* allocator,
struct BodyLocalDecls { struct BodyLocalDecls {
// The size of the encoded declarations. // The size of the encoded declarations.
uint32_t decls_encoded_size; // size of encoded declarations uint32_t encoded_size; // size of encoded declarations
// Total number of locals. ZoneVector<ValueType> type_list;
uint32_t total_local_count;
// List of {local type, count} pairs.
ZoneVector<std::pair<ValueType, uint32_t>> local_types;
// Constructor initializes the vector. // Constructor initializes the vector.
explicit BodyLocalDecls(Zone* zone) explicit BodyLocalDecls(Zone* zone) : encoded_size(0), type_list(zone) {}
: decls_encoded_size(0), total_local_count(0), local_types(zone) {}
}; };
V8_EXPORT_PRIVATE bool DecodeLocalDecls(BodyLocalDecls& decls, V8_EXPORT_PRIVATE bool DecodeLocalDecls(BodyLocalDecls* decls,
const byte* start, const byte* end); const byte* start, const byte* end);
V8_EXPORT_PRIVATE BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, V8_EXPORT_PRIVATE BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone,
size_t num_locals, size_t num_locals,
......
...@@ -928,7 +928,7 @@ class CodeMap { ...@@ -928,7 +928,7 @@ class CodeMap {
InterpreterCode* Preprocess(InterpreterCode* code) { InterpreterCode* Preprocess(InterpreterCode* code) {
if (code->targets == nullptr && code->start) { if (code->targets == nullptr && code->start) {
// Compute the control targets map and the local declarations. // Compute the control targets map and the local declarations.
CHECK(DecodeLocalDecls(code->locals, code->start, code->end)); CHECK(DecodeLocalDecls(&code->locals, code->start, code->end));
code->targets = new (zone_) ControlTransfers( code->targets = new (zone_) ControlTransfers(
zone_, &code->locals, code->orig_start, code->orig_end); zone_, &code->locals, code->orig_start, code->orig_end);
} }
...@@ -1070,7 +1070,7 @@ class ThreadImpl : public WasmInterpreter::Thread { ...@@ -1070,7 +1070,7 @@ class ThreadImpl : public WasmInterpreter::Thread {
// Limit of parameters. // Limit of parameters.
sp_t plimit() { return sp + code->function->sig->parameter_count(); } sp_t plimit() { return sp + code->function->sig->parameter_count(); }
// Limit of locals. // Limit of locals.
sp_t llimit() { return plimit() + code->locals.total_local_count; } sp_t llimit() { return plimit() + code->locals.type_list.size(); }
}; };
struct Block { struct Block {
...@@ -1119,9 +1119,9 @@ class ThreadImpl : public WasmInterpreter::Thread { ...@@ -1119,9 +1119,9 @@ class ThreadImpl : public WasmInterpreter::Thread {
} }
pc_t InitLocals(InterpreterCode* code) { pc_t InitLocals(InterpreterCode* code) {
for (auto p : code->locals.local_types) { for (auto p : code->locals.type_list) {
WasmVal val; WasmVal val;
switch (p.first) { switch (p) {
case kWasmI32: case kWasmI32:
val = WasmVal(static_cast<int32_t>(0)); val = WasmVal(static_cast<int32_t>(0));
break; break;
...@@ -1138,9 +1138,9 @@ class ThreadImpl : public WasmInterpreter::Thread { ...@@ -1138,9 +1138,9 @@ class ThreadImpl : public WasmInterpreter::Thread {
UNREACHABLE(); UNREACHABLE();
break; break;
} }
stack_.insert(stack_.end(), p.second, val); stack_.push_back(val);
} }
return code->locals.decls_encoded_size; return code->locals.encoded_size;
} }
void CommitPc(pc_t pc) { void CommitPc(pc_t pc) {
...@@ -1800,7 +1800,7 @@ bool WasmInterpreter::SetBreakpoint(const WasmFunction* function, pc_t pc, ...@@ -1800,7 +1800,7 @@ bool WasmInterpreter::SetBreakpoint(const WasmFunction* function, pc_t pc,
if (!code) return false; if (!code) return false;
size_t size = static_cast<size_t>(code->end - code->start); size_t size = static_cast<size_t>(code->end - code->start);
// Check bounds for {pc}. // Check bounds for {pc}.
if (pc < code->locals.decls_encoded_size || pc >= size) return false; if (pc < code->locals.encoded_size || pc >= size) return false;
// Make a copy of the code before enabling a breakpoint. // Make a copy of the code before enabling a breakpoint.
if (enabled && code->orig_start == code->start) { if (enabled && code->orig_start == code->start) {
code->start = reinterpret_cast<byte*>(zone_.New(size)); code->start = reinterpret_cast<byte*>(zone_.New(size));
...@@ -1821,7 +1821,7 @@ bool WasmInterpreter::GetBreakpoint(const WasmFunction* function, pc_t pc) { ...@@ -1821,7 +1821,7 @@ bool WasmInterpreter::GetBreakpoint(const WasmFunction* function, pc_t pc) {
if (!code) return false; if (!code) return false;
size_t size = static_cast<size_t>(code->end - code->start); size_t size = static_cast<size_t>(code->end - code->start);
// Check bounds for {pc}. // Check bounds for {pc}.
if (pc < code->locals.decls_encoded_size || pc >= size) return false; if (pc < code->locals.encoded_size || pc >= size) return false;
// Check if a breakpoint is present at that place in the code. // Check if a breakpoint is present at that place in the code.
return code->start[pc] == kInternalBreakpoint; return code->start[pc] == kInternalBreakpoint;
} }
......
...@@ -798,7 +798,7 @@ bool WasmCompiledModule::GetPossibleBreakpoints( ...@@ -798,7 +798,7 @@ bool WasmCompiledModule::GetPossibleBreakpoints(
BodyLocalDecls locals(&tmp); BodyLocalDecls locals(&tmp);
BytecodeIterator iterator(module_start + func.code_start_offset, BytecodeIterator iterator(module_start + func.code_start_offset,
module_start + func.code_end_offset, &locals); module_start + func.code_end_offset, &locals);
DCHECK_LT(0u, locals.decls_encoded_size); DCHECK_LT(0u, locals.encoded_size);
for (uint32_t offset : iterator.offsets()) { for (uint32_t offset : iterator.offsets()) {
uint32_t total_offset = func.code_start_offset + offset; uint32_t total_offset = func.code_start_offset + offset;
if (total_offset >= end_offset) { if (total_offset >= end_offset) {
......
...@@ -173,11 +173,10 @@ void wasm::PrintWasmText(const WasmModule *module, ...@@ -173,11 +173,10 @@ void wasm::PrintWasmText(const WasmModule *module,
fun->code_start_offset, fun->code_end_offset); fun->code_start_offset, fun->code_end_offset);
BytecodeIterator i(func_bytes.begin(), func_bytes.end(), &decls); BytecodeIterator i(func_bytes.begin(), func_bytes.end(), &decls);
DCHECK_LT(func_bytes.begin(), i.pc()); DCHECK_LT(func_bytes.begin(), i.pc());
if (!decls.local_types.empty()) { if (!decls.type_list.empty()) {
os << "(local"; os << "(local";
for (auto p : decls.local_types) { for (const ValueType &v : decls.type_list) {
for (unsigned i = 0; i < p.second; ++i) os << ' ' << WasmOpcodes::TypeName(v);
os << ' ' << WasmOpcodes::TypeName(p.first);
} }
os << ")\n"; os << ")\n";
++line_nr; ++line_nr;
......
...@@ -2546,41 +2546,33 @@ TEST_F(WasmOpcodeLengthTest, SimdExpressions) { ...@@ -2546,41 +2546,33 @@ TEST_F(WasmOpcodeLengthTest, SimdExpressions) {
EXPECT_LENGTH_N(2, kSimdPrefix, 0xff); EXPECT_LENGTH_N(2, kSimdPrefix, 0xff);
} }
typedef ZoneVector<ValueType> ValueTypeMap; typedef ZoneVector<ValueType> TypesOfLocals;
class LocalDeclDecoderTest : public TestWithZone { class LocalDeclDecoderTest : public TestWithZone {
public: public:
v8::internal::AccountingAllocator allocator; v8::internal::AccountingAllocator allocator;
size_t ExpectRun(ValueTypeMap map, size_t pos, ValueType expected, size_t ExpectRun(TypesOfLocals map, size_t pos, ValueType expected,
size_t count) { size_t count) {
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
EXPECT_EQ(expected, map[pos++]); EXPECT_EQ(expected, map[pos++]);
} }
return pos; return pos;
} }
ValueTypeMap Expand(BodyLocalDecls& decls) {
ZoneVector<ValueType> map(zone());
for (auto p : decls.local_types) {
map.insert(map.end(), p.second, p.first);
}
return map;
}
}; };
TEST_F(LocalDeclDecoderTest, EmptyLocals) { TEST_F(LocalDeclDecoderTest, EmptyLocals) {
BodyLocalDecls decls(zone()); BodyLocalDecls decls(zone());
bool result = DecodeLocalDecls(decls, nullptr, nullptr); bool result = DecodeLocalDecls(&decls, nullptr, nullptr);
EXPECT_FALSE(result); EXPECT_FALSE(result);
} }
TEST_F(LocalDeclDecoderTest, NoLocals) { TEST_F(LocalDeclDecoderTest, NoLocals) {
static const byte data[] = {0}; static const byte data[] = {0};
BodyLocalDecls decls(zone()); BodyLocalDecls decls(zone());
bool result = DecodeLocalDecls(decls, data, data + sizeof(data)); bool result = DecodeLocalDecls(&decls, data, data + sizeof(data));
EXPECT_TRUE(result); EXPECT_TRUE(result);
EXPECT_EQ(0u, decls.total_local_count); EXPECT_TRUE(decls.type_list.empty());
} }
TEST_F(LocalDeclDecoderTest, OneLocal) { TEST_F(LocalDeclDecoderTest, OneLocal) {
...@@ -2589,12 +2581,11 @@ TEST_F(LocalDeclDecoderTest, OneLocal) { ...@@ -2589,12 +2581,11 @@ TEST_F(LocalDeclDecoderTest, OneLocal) {
const byte data[] = { const byte data[] = {
1, 1, static_cast<byte>(WasmOpcodes::ValueTypeCodeFor(type))}; 1, 1, static_cast<byte>(WasmOpcodes::ValueTypeCodeFor(type))};
BodyLocalDecls decls(zone()); BodyLocalDecls decls(zone());
bool result = DecodeLocalDecls(decls, data, data + sizeof(data)); bool result = DecodeLocalDecls(&decls, data, data + sizeof(data));
EXPECT_TRUE(result); EXPECT_TRUE(result);
EXPECT_EQ(1u, decls.total_local_count); EXPECT_EQ(1u, decls.type_list.size());
ValueTypeMap map = Expand(decls); TypesOfLocals map = decls.type_list;
EXPECT_EQ(1u, map.size());
EXPECT_EQ(type, map[0]); EXPECT_EQ(type, map[0]);
} }
} }
...@@ -2605,12 +2596,12 @@ TEST_F(LocalDeclDecoderTest, FiveLocals) { ...@@ -2605,12 +2596,12 @@ TEST_F(LocalDeclDecoderTest, FiveLocals) {
const byte data[] = { const byte data[] = {
1, 5, static_cast<byte>(WasmOpcodes::ValueTypeCodeFor(type))}; 1, 5, static_cast<byte>(WasmOpcodes::ValueTypeCodeFor(type))};
BodyLocalDecls decls(zone()); BodyLocalDecls decls(zone());
bool result = DecodeLocalDecls(decls, data, data + sizeof(data)); bool result = DecodeLocalDecls(&decls, data, data + sizeof(data));
EXPECT_TRUE(result); EXPECT_TRUE(result);
EXPECT_EQ(sizeof(data), decls.decls_encoded_size); EXPECT_EQ(sizeof(data), decls.encoded_size);
EXPECT_EQ(5u, decls.total_local_count); EXPECT_EQ(5u, decls.type_list.size());
ValueTypeMap map = Expand(decls); TypesOfLocals map = decls.type_list;
EXPECT_EQ(5u, map.size()); EXPECT_EQ(5u, map.size());
ExpectRun(map, 0, type, 5); ExpectRun(map, 0, type, 5);
} }
...@@ -2624,14 +2615,13 @@ TEST_F(LocalDeclDecoderTest, MixedLocals) { ...@@ -2624,14 +2615,13 @@ TEST_F(LocalDeclDecoderTest, MixedLocals) {
const byte data[] = {4, a, kLocalI32, b, kLocalI64, const byte data[] = {4, a, kLocalI32, b, kLocalI64,
c, kLocalF32, d, kLocalF64}; c, kLocalF32, d, kLocalF64};
BodyLocalDecls decls(zone()); BodyLocalDecls decls(zone());
bool result = DecodeLocalDecls(decls, data, data + sizeof(data)); bool result = DecodeLocalDecls(&decls, data, data + sizeof(data));
EXPECT_TRUE(result); EXPECT_TRUE(result);
EXPECT_EQ(sizeof(data), decls.decls_encoded_size); EXPECT_EQ(sizeof(data), decls.encoded_size);
EXPECT_EQ(static_cast<uint32_t>(a + b + c + d), EXPECT_EQ(static_cast<uint32_t>(a + b + c + d),
decls.total_local_count); decls.type_list.size());
ValueTypeMap map = Expand(decls); TypesOfLocals map = decls.type_list;
EXPECT_EQ(static_cast<uint32_t>(a + b + c + d), map.size());
size_t pos = 0; size_t pos = 0;
pos = ExpectRun(map, pos, kWasmI32, a); pos = ExpectRun(map, pos, kWasmI32, a);
...@@ -2655,11 +2645,11 @@ TEST_F(LocalDeclDecoderTest, UseEncoder) { ...@@ -2655,11 +2645,11 @@ TEST_F(LocalDeclDecoderTest, UseEncoder) {
local_decls.Prepend(zone(), &data, &end); local_decls.Prepend(zone(), &data, &end);
BodyLocalDecls decls(zone()); BodyLocalDecls decls(zone());
bool result = DecodeLocalDecls(decls, data, end); bool result = DecodeLocalDecls(&decls, data, end);
EXPECT_TRUE(result); EXPECT_TRUE(result);
EXPECT_EQ(5u + 1337u + 212u, decls.total_local_count); EXPECT_EQ(5u + 1337u + 212u, decls.type_list.size());
ValueTypeMap map = Expand(decls); TypesOfLocals map = decls.type_list;
size_t pos = 0; size_t pos = 0;
pos = ExpectRun(map, pos, kWasmF32, 5); pos = ExpectRun(map, pos, kWasmF32, 5);
pos = ExpectRun(map, pos, kWasmI32, 1337); pos = ExpectRun(map, pos, kWasmI32, 1337);
...@@ -2729,7 +2719,7 @@ TEST_F(BytecodeIteratorTest, WithLocalDecls) { ...@@ -2729,7 +2719,7 @@ TEST_F(BytecodeIteratorTest, WithLocalDecls) {
BodyLocalDecls decls(zone()); BodyLocalDecls decls(zone());
BytecodeIterator iter(code, code + sizeof(code), &decls); BytecodeIterator iter(code, code + sizeof(code), &decls);
EXPECT_EQ(3u, decls.decls_encoded_size); EXPECT_EQ(3u, decls.encoded_size);
EXPECT_EQ(3u, iter.pc_offset()); EXPECT_EQ(3u, iter.pc_offset());
EXPECT_TRUE(iter.has_next()); EXPECT_TRUE(iter.has_next());
EXPECT_EQ(kExprI8Const, iter.current()); EXPECT_EQ(kExprI8Const, iter.current());
......
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