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