Commit 6dda75f2 authored by titzer's avatar titzer Committed by Commit bot

[wasm] Refactor decoding of local declarations and make more robust.

R=ahaas@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1856413002

Cr-Commit-Position: refs/heads/master@{#35272}
parent 7a38462e
...@@ -412,15 +412,23 @@ class SR_WasmDecoder : public WasmDecoder { ...@@ -412,15 +412,23 @@ class SR_WasmDecoder : public WasmDecoder {
return toResult(tree); return toResult(tree);
} }
std::vector<LocalType>* DecodeLocalDeclsForTesting() { bool DecodeLocalDecls(AstLocalDecls& decls) {
DecodeLocalDecls(); DecodeLocalDecls();
if (failed()) return nullptr; if (failed()) return false;
auto result = new std::vector<LocalType>(); decls.decls_encoded_size = pc_offset();
result->reserve(local_type_vec_.size()); decls.total_local_count = 0;
for (size_t i = 0; i < local_type_vec_.size(); i++) { decls.local_types.reserve(local_type_vec_.size());
result->push_back(local_type_vec_[i]); for (size_t pos = 0; pos < local_type_vec_.size();) {
uint32_t count = 0;
LocalType type = local_type_vec_[pos];
while (pos < local_type_vec_.size() && local_type_vec_[pos] == type) {
pos++;
count++;
}
decls.total_local_count += count;
decls.local_types.push_back(std::pair<LocalType, uint32_t>(type, count));
} }
return result; return true;
} }
BitVector* AnalyzeLoopAssignmentForTesting(const byte* pc, BitVector* AnalyzeLoopAssignmentForTesting(const byte* pc,
...@@ -1626,12 +1634,13 @@ class SR_WasmDecoder : public WasmDecoder { ...@@ -1626,12 +1634,13 @@ class SR_WasmDecoder : public WasmDecoder {
} }
}; };
std::vector<LocalType>* DecodeLocalDeclsForTesting( bool DecodeLocalDecls(AstLocalDecls& decls, const byte* start,
base::AccountingAllocator* allocator, const byte* start, const byte* end) { const byte* end) {
Zone zone(allocator); base::AccountingAllocator allocator;
Zone tmp(&allocator);
FunctionBody body = {nullptr, nullptr, nullptr, start, end}; FunctionBody body = {nullptr, nullptr, nullptr, start, end};
SR_WasmDecoder decoder(&zone, nullptr, body); SR_WasmDecoder decoder(&tmp, nullptr, body);
return decoder.DecodeLocalDeclsForTesting(); return decoder.DecodeLocalDecls(decls);
} }
TreeResult VerifyWasmCode(base::AccountingAllocator* allocator, TreeResult VerifyWasmCode(base::AccountingAllocator* allocator,
...@@ -1700,19 +1709,14 @@ void PrintAst(base::AccountingAllocator* allocator, FunctionBody& body) { ...@@ -1700,19 +1709,14 @@ void PrintAst(base::AccountingAllocator* allocator, FunctionBody& body) {
} }
// Print the local declarations. // Print the local declarations.
std::vector<LocalType>* decls = decoder.DecodeLocalDeclsForTesting(); AstLocalDecls decls(&zone);
decoder.DecodeLocalDecls(decls);
const byte* pc = decoder.pc(); const byte* pc = decoder.pc();
if (body.start != decoder.pc()) { if (body.start != decoder.pc()) {
printf("// locals:"); printf("// locals:");
size_t pos = 0; for (auto p : decls.local_types) {
while (pos < decls->size()) { LocalType type = p.first;
LocalType type = decls->at(pos++); uint32_t count = p.second;
size_t count = 1;
while (pos < decls->size() && decls->at(pos) == type) {
pos++;
count++;
}
os << " " << count << " " << WasmOpcodes::TypeName(type); os << " " << count << " " << WasmOpcodes::TypeName(type);
} }
os << std::endl; os << std::endl;
...@@ -1722,7 +1726,6 @@ void PrintAst(base::AccountingAllocator* allocator, FunctionBody& body) { ...@@ -1722,7 +1726,6 @@ void PrintAst(base::AccountingAllocator* allocator, FunctionBody& body) {
} }
printf("\n"); printf("\n");
} }
delete decls;
printf("// body: \n"); printf("// body: \n");
std::vector<int> arity_stack; std::vector<int> arity_stack;
......
...@@ -220,8 +220,22 @@ enum ReadUnsignedLEB128ErrorCode { kNoError, kInvalidLEB128, kMissingLEB128 }; ...@@ -220,8 +220,22 @@ enum ReadUnsignedLEB128ErrorCode { kNoError, kInvalidLEB128, kMissingLEB128 };
ReadUnsignedLEB128ErrorCode ReadUnsignedLEB128Operand(const byte*, const byte*, ReadUnsignedLEB128ErrorCode ReadUnsignedLEB128Operand(const byte*, const byte*,
int*, uint32_t*); int*, uint32_t*);
std::vector<LocalType>* DecodeLocalDeclsForTesting( struct AstLocalDecls {
base::AccountingAllocator* allocator, const byte* start, const byte* end); // The size of the encoded declarations.
uint32_t decls_encoded_size; // size of encoded declarations
// Total number of locals.
uint32_t total_local_count;
// List of {local type, count} pairs.
ZoneVector<std::pair<LocalType, uint32_t>> local_types;
// Constructor initializes the vector.
explicit AstLocalDecls(Zone* zone)
: decls_encoded_size(0), total_local_count(0), local_types(zone) {}
};
bool DecodeLocalDecls(AstLocalDecls& decls, const byte* start, const byte* end);
BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
const byte* start, const byte* end); const byte* start, const byte* end);
......
...@@ -329,7 +329,7 @@ class Decoder { ...@@ -329,7 +329,7 @@ class Decoder {
} }
bool ok() const { return error_pc_ == nullptr; } bool ok() const { return error_pc_ == nullptr; }
bool failed() const { return error_pc_ != nullptr; } bool failed() const { return !error_msg_.is_empty(); }
bool more() const { return pc_ < limit_; } bool more() const { return pc_ < limit_; }
const byte* start() { return start_; } const byte* start() { return start_; }
......
...@@ -2197,26 +2197,41 @@ TEST_F(WasmOpcodeArityTest, SimpleExpressions) { ...@@ -2197,26 +2197,41 @@ TEST_F(WasmOpcodeArityTest, SimpleExpressions) {
EXPECT_ARITY(1, kExprI64ReinterpretF64); EXPECT_ARITY(1, kExprI64ReinterpretF64);
} }
typedef std::vector<LocalType>* LocalTypeMap; typedef ZoneVector<LocalType> LocalTypeMap;
class LocalDeclDecoderTest : public TestWithZone { class LocalDeclDecoderTest : public TestWithZone {
public: public:
base::AccountingAllocator allocator;
size_t ExpectRun(LocalTypeMap map, size_t pos, LocalType expected, size_t ExpectRun(LocalTypeMap map, size_t pos, LocalType 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->at(pos++)); EXPECT_EQ(expected, map[pos++]);
} }
return pos; return pos;
} }
LocalTypeMap Expand(AstLocalDecls& decls) {
ZoneVector<LocalType> map(zone());
for (auto p : decls.local_types) {
map.insert(map.end(), p.second, p.first);
}
return map;
}
}; };
TEST_F(LocalDeclDecoderTest, EmptyLocals) {
AstLocalDecls decls(zone());
bool result = DecodeLocalDecls(decls, nullptr, nullptr);
EXPECT_FALSE(result);
}
TEST_F(LocalDeclDecoderTest, NoLocals) { TEST_F(LocalDeclDecoderTest, NoLocals) {
static const byte data[] = {0}; static const byte data[] = {0};
base::AccountingAllocator allocator; AstLocalDecls decls(zone());
LocalTypeMap map = bool result = DecodeLocalDecls(decls, data, data + sizeof(data));
DecodeLocalDeclsForTesting(&allocator, data, data + sizeof(data)); EXPECT_TRUE(result);
EXPECT_EQ(0, map->size()); EXPECT_EQ(0, decls.total_local_count);
if (map) delete map;
} }
TEST_F(LocalDeclDecoderTest, OneLocal) { TEST_F(LocalDeclDecoderTest, OneLocal) {
...@@ -2224,12 +2239,14 @@ TEST_F(LocalDeclDecoderTest, OneLocal) { ...@@ -2224,12 +2239,14 @@ TEST_F(LocalDeclDecoderTest, OneLocal) {
LocalType type = kLocalTypes[i]; LocalType type = kLocalTypes[i];
const byte data[] = { const byte data[] = {
1, 1, static_cast<byte>(WasmOpcodes::LocalTypeCodeFor(type))}; 1, 1, static_cast<byte>(WasmOpcodes::LocalTypeCodeFor(type))};
base::AccountingAllocator allocator; AstLocalDecls decls(zone());
LocalTypeMap map = bool result = DecodeLocalDecls(decls, data, data + sizeof(data));
DecodeLocalDeclsForTesting(&allocator, data, data + sizeof(data)); EXPECT_TRUE(result);
EXPECT_EQ(1, map->size()); EXPECT_EQ(1, decls.total_local_count);
EXPECT_EQ(type, map->at(0));
if (map) delete map; LocalTypeMap map = Expand(decls);
EXPECT_EQ(1, map.size());
EXPECT_EQ(type, map.at(0));
} }
} }
...@@ -2238,12 +2255,15 @@ TEST_F(LocalDeclDecoderTest, FiveLocals) { ...@@ -2238,12 +2255,15 @@ TEST_F(LocalDeclDecoderTest, FiveLocals) {
LocalType type = kLocalTypes[i]; LocalType type = kLocalTypes[i];
const byte data[] = { const byte data[] = {
1, 5, static_cast<byte>(WasmOpcodes::LocalTypeCodeFor(type))}; 1, 5, static_cast<byte>(WasmOpcodes::LocalTypeCodeFor(type))};
base::AccountingAllocator allocator; AstLocalDecls decls(zone());
LocalTypeMap map = bool result = DecodeLocalDecls(decls, data, data + sizeof(data));
DecodeLocalDeclsForTesting(&allocator, data, data + sizeof(data)); EXPECT_TRUE(result);
EXPECT_EQ(5, map->size()); EXPECT_EQ(sizeof(data), decls.decls_encoded_size);
EXPECT_EQ(5, decls.total_local_count);
LocalTypeMap map = Expand(decls);
EXPECT_EQ(5, map.size());
ExpectRun(map, 0, type, 5); ExpectRun(map, 0, type, 5);
if (map) delete map;
} }
} }
...@@ -2254,18 +2274,20 @@ TEST_F(LocalDeclDecoderTest, MixedLocals) { ...@@ -2254,18 +2274,20 @@ TEST_F(LocalDeclDecoderTest, MixedLocals) {
for (byte d = 0; d < 3; d++) { for (byte d = 0; d < 3; d++) {
const byte data[] = {4, a, kLocalI32, b, kLocalI64, const byte data[] = {4, a, kLocalI32, b, kLocalI64,
c, kLocalF32, d, kLocalF64}; c, kLocalF32, d, kLocalF64};
base::AccountingAllocator allocator; AstLocalDecls decls(zone());
LocalTypeMap map = bool result = DecodeLocalDecls(decls, data, data + sizeof(data));
DecodeLocalDeclsForTesting(&allocator, data, data + sizeof(data)); EXPECT_TRUE(result);
EXPECT_EQ(a + b + c + d, map->size()); EXPECT_EQ(sizeof(data), decls.decls_encoded_size);
EXPECT_EQ(a + b + c + d, decls.total_local_count);
LocalTypeMap map = Expand(decls);
EXPECT_EQ(a + b + c + d, map.size());
size_t pos = 0; size_t pos = 0;
pos = ExpectRun(map, pos, kAstI32, a); pos = ExpectRun(map, pos, kAstI32, a);
pos = ExpectRun(map, pos, kAstI64, b); pos = ExpectRun(map, pos, kAstI64, b);
pos = ExpectRun(map, pos, kAstF32, c); pos = ExpectRun(map, pos, kAstF32, c);
pos = ExpectRun(map, pos, kAstF64, d); pos = ExpectRun(map, pos, kAstF64, d);
if (map) delete map;
} }
} }
} }
...@@ -2282,14 +2304,16 @@ TEST_F(LocalDeclDecoderTest, UseEncoder) { ...@@ -2282,14 +2304,16 @@ TEST_F(LocalDeclDecoderTest, UseEncoder) {
local_decls.AddLocals(212, kAstI64); local_decls.AddLocals(212, kAstI64);
local_decls.Prepend(&data, &end); local_decls.Prepend(&data, &end);
base::AccountingAllocator allocator; AstLocalDecls decls(zone());
LocalTypeMap map = DecodeLocalDeclsForTesting(&allocator, data, end); bool result = DecodeLocalDecls(decls, data, end);
EXPECT_TRUE(result);
EXPECT_EQ(5 + 1337 + 212, decls.total_local_count);
LocalTypeMap map = Expand(decls);
size_t pos = 0; size_t pos = 0;
pos = ExpectRun(map, pos, kAstF32, 5); pos = ExpectRun(map, pos, kAstF32, 5);
pos = ExpectRun(map, pos, kAstI32, 1337); pos = ExpectRun(map, pos, kAstI32, 1337);
pos = ExpectRun(map, pos, kAstI64, 212); pos = ExpectRun(map, pos, kAstI64, 212);
if (map) delete map;
delete[] data; delete[] data;
} }
......
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