Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(283)

Unified Diff: src/wasm/function-body-decoder.cc

Issue 2610813009: [wasm] factor lower level utilties out of WasmFullDecoder (Closed)
Patch Set: harden decl decoding Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/wasm/function-body-decoder.h ('k') | src/wasm/wasm-interpreter.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/wasm/function-body-decoder.cc
diff --git a/src/wasm/function-body-decoder.cc b/src/wasm/function-body-decoder.cc
index 419b4999ad1e487eff38f5e144ea4b6187d0e458..a24087aafada55f77da7b216595ac63e8abda350 100644
--- a/src/wasm/function-body-decoder.cc
+++ b/src/wasm/function-body-decoder.cc
@@ -169,15 +169,114 @@ class WasmDecoder : public Decoder {
: Decoder(start, end),
module_(module),
sig_(sig),
- total_locals_(0),
local_types_(nullptr) {}
const WasmModule* module_;
FunctionSig* sig_;
- size_t total_locals_;
+
ZoneVector<ValueType>* local_types_;
+ size_t total_locals() const {
+ return local_types_ == nullptr ? 0 : local_types_->size();
+ }
+
+ static bool DecodeLocals(Decoder* decoder, const FunctionSig* sig,
+ ZoneVector<ValueType>* type_list) {
+ DCHECK_NOT_NULL(type_list);
+ // Initialize from signature.
+ if (sig != nullptr) {
+ type_list->reserve(sig->parameter_count());
+ for (size_t i = 0; i < sig->parameter_count(); ++i) {
+ type_list->push_back(sig->GetParam(i));
+ }
+ }
+ // Decode local declarations, if any.
+ uint32_t entries = decoder->consume_u32v("local decls count");
+ if (decoder->failed()) return false;
+
+ TRACE("local decls count: %u\n", entries);
+ while (entries-- > 0 && decoder->ok() && decoder->more()) {
+ uint32_t count = decoder->consume_u32v("local count");
+ if (decoder->failed()) return false;
+
+ if ((count + type_list->size()) > kMaxNumWasmLocals) {
+ decoder->error(decoder->pc() - 1, "local count too large");
+ return false;
+ }
+ byte code = decoder->consume_u8("local type");
+ if (decoder->failed()) return false;
+
+ ValueType type;
+ switch (code) {
+ case kLocalI32:
+ type = kWasmI32;
+ break;
+ case kLocalI64:
+ type = kWasmI64;
+ break;
+ case kLocalF32:
+ type = kWasmF32;
+ break;
+ case kLocalF64:
+ type = kWasmF64;
+ break;
+ case kLocalS128:
+ type = kWasmS128;
+ break;
+ default:
+ decoder->error(decoder->pc() - 1, "invalid local type");
+ return false;
+ }
+ type_list->insert(type_list->end(), count, type);
+ }
+ DCHECK(decoder->ok());
+ return true;
+ }
+
+ static BitVector* AnalyzeLoopAssignment(Decoder* decoder, const byte* pc,
+ int locals_count, Zone* zone) {
+ if (pc >= decoder->end()) return nullptr;
+ if (*pc != kExprLoop) return nullptr;
+
+ BitVector* assigned = new (zone) BitVector(locals_count, zone);
+ int depth = 0;
+ // Iteratively process all AST nodes nested inside the loop.
+ while (pc < decoder->end() && decoder->ok()) {
+ WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
+ unsigned length = 1;
+ switch (opcode) {
+ case kExprLoop:
+ case kExprIf:
+ case kExprBlock:
+ case kExprTry:
+ length = OpcodeLength(decoder, pc);
+ depth++;
+ break;
+ case kExprSetLocal: // fallthru
+ case kExprTeeLocal: {
+ LocalIndexOperand operand(decoder, pc);
+ if (assigned->length() > 0 &&
+ operand.index < static_cast<uint32_t>(assigned->length())) {
+ // Unverified code might have an out-of-bounds index.
+ assigned->Add(operand.index);
+ }
+ length = 1 + operand.length;
+ break;
+ }
+ case kExprEnd:
+ depth--;
+ break;
+ default:
+ length = OpcodeLength(decoder, pc);
+ break;
+ }
+ if (depth <= 0) break;
+ pc += length;
+ }
+ return decoder->ok() ? assigned : nullptr;
+ }
+
inline bool Validate(const byte* pc, LocalIndexOperand& operand) {
- if (operand.index < total_locals_) {
+ if (operand.index < total_locals()) {
if (local_types_) {
operand.type = local_types_->at(operand.index);
} else {
@@ -260,33 +359,33 @@ class WasmDecoder : public Decoder {
}
}
- unsigned OpcodeLength(const byte* pc) {
+ static unsigned OpcodeLength(Decoder* decoder, const byte* pc) {
switch (static_cast<byte>(*pc)) {
#define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
#undef DECLARE_OPCODE_CASE
{
- MemoryAccessOperand operand(this, pc, UINT32_MAX);
+ MemoryAccessOperand operand(decoder, pc, UINT32_MAX);
return 1 + operand.length;
}
case kExprBr:
case kExprBrIf: {
- BreakDepthOperand operand(this, pc);
+ BreakDepthOperand operand(decoder, pc);
return 1 + operand.length;
}
case kExprSetGlobal:
case kExprGetGlobal: {
- GlobalIndexOperand operand(this, pc);
+ GlobalIndexOperand operand(decoder, pc);
return 1 + operand.length;
}
case kExprCallFunction: {
- CallFunctionOperand operand(this, pc);
+ CallFunctionOperand operand(decoder, pc);
return 1 + operand.length;
}
case kExprCallIndirect: {
- CallIndirectOperand operand(this, pc);
+ CallIndirectOperand operand(decoder, pc);
return 1 + operand.length;
}
@@ -294,7 +393,7 @@ class WasmDecoder : public Decoder {
case kExprIf: // fall thru
case kExprLoop:
case kExprBlock: {
- BlockTypeOperand operand(this, pc);
+ BlockTypeOperand operand(decoder, pc);
return 1 + operand.length;
}
@@ -302,25 +401,25 @@ class WasmDecoder : public Decoder {
case kExprTeeLocal:
case kExprGetLocal:
case kExprCatch: {
- LocalIndexOperand operand(this, pc);
+ LocalIndexOperand operand(decoder, pc);
return 1 + operand.length;
}
case kExprBrTable: {
- BranchTableOperand operand(this, pc);
- BranchTableIterator iterator(this, operand);
+ BranchTableOperand operand(decoder, pc);
+ BranchTableIterator iterator(decoder, operand);
return 1 + iterator.length();
}
case kExprI32Const: {
- ImmI32Operand operand(this, pc);
+ ImmI32Operand operand(decoder, pc);
return 1 + operand.length;
}
case kExprI64Const: {
- ImmI64Operand operand(this, pc);
+ ImmI64Operand operand(decoder, pc);
return 1 + operand.length;
}
case kExprGrowMemory:
case kExprMemorySize: {
- MemoryIndexOperand operand(this, pc);
+ MemoryIndexOperand operand(decoder, pc);
return 1 + operand.length;
}
case kExprI8Const:
@@ -330,7 +429,7 @@ class WasmDecoder : public Decoder {
case kExprF64Const:
return 9;
case kSimdPrefix: {
- byte simd_index = checked_read_u8(pc, 1, "simd_index");
+ byte simd_index = decoder->checked_read_u8(pc, 1, "simd_index");
WasmOpcode opcode =
static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index);
switch (opcode) {
@@ -347,7 +446,7 @@ class WasmDecoder : public Decoder {
return 3;
}
default:
- error("invalid SIMD opcode");
+ decoder->error(pc, "invalid SIMD opcode");
return 2;
}
}
@@ -363,9 +462,6 @@ static const int32_t kNullCatch = -1;
// generates a TurboFan IR graph.
class WasmFullDecoder : public WasmDecoder {
public:
- WasmFullDecoder(Zone* zone, const FunctionBody& body)
- : WasmFullDecoder(zone, nullptr, nullptr, body) {}
-
WasmFullDecoder(Zone* zone, const wasm::WasmModule* module,
const FunctionBody& body)
: WasmFullDecoder(zone, module, nullptr, body) {}
@@ -392,7 +488,8 @@ class WasmFullDecoder : public WasmDecoder {
return false;
}
- DecodeLocalDecls();
+ DCHECK_EQ(0, local_types_->size());
+ WasmDecoder::DecodeLocals(this, sig_, local_types_);
InitSsaEnv();
DecodeFunctionBody();
@@ -458,35 +555,6 @@ class WasmFullDecoder : public WasmDecoder {
return false;
}
- bool DecodeLocalDecls(BodyLocalDecls& decls) {
- DecodeLocalDecls();
- if (failed()) return false;
- decls.decls_encoded_size = pc_offset();
- decls.local_types.reserve(local_type_vec_.size());
- for (size_t pos = 0; pos < local_type_vec_.size();) {
- uint32_t count = 0;
- ValueType type = local_type_vec_[pos];
- while (pos < local_type_vec_.size() && local_type_vec_[pos] == type) {
- pos++;
- count++;
- }
- decls.local_types.push_back(std::pair<ValueType, uint32_t>(type, count));
- }
- decls.total_local_count = static_cast<uint32_t>(local_type_vec_.size());
- return true;
- }
-
- BitVector* AnalyzeLoopAssignmentForTesting(const byte* pc,
- size_t num_locals) {
- total_locals_ = num_locals;
- local_type_vec_.reserve(num_locals);
- if (num_locals > local_type_vec_.size()) {
- local_type_vec_.insert(local_type_vec_.end(),
- num_locals - local_type_vec_.size(), kWasmI32);
- }
- return AnalyzeLoopAssignment(pc);
- }
-
private:
WasmFullDecoder(Zone* zone, const wasm::WasmModule* module,
TFBuilder* builder, const FunctionBody& body)
@@ -584,52 +652,6 @@ class WasmFullDecoder : public WasmDecoder {
return bytes;
}
- // Decodes the locals declarations, if any, populating {local_type_vec_}.
- void DecodeLocalDecls() {
- DCHECK_EQ(0, local_type_vec_.size());
- // Initialize {local_type_vec} from signature.
- if (sig_) {
- local_type_vec_.reserve(sig_->parameter_count());
- for (size_t i = 0; i < sig_->parameter_count(); ++i) {
- local_type_vec_.push_back(sig_->GetParam(i));
- }
- }
- // Decode local declarations, if any.
- uint32_t entries = consume_u32v("local decls count");
- TRACE("local decls count: %u\n", entries);
- while (entries-- > 0 && pc_ < end_) {
- uint32_t count = consume_u32v("local count");
- if ((count + local_type_vec_.size()) > kMaxNumWasmLocals) {
- error(pc_ - 1, "local count too large");
- return;
- }
- byte code = consume_u8("local type");
- ValueType type;
- switch (code) {
- case kLocalI32:
- type = kWasmI32;
- break;
- case kLocalI64:
- type = kWasmI64;
- break;
- case kLocalF32:
- type = kWasmF32;
- break;
- case kLocalF64:
- type = kWasmF64;
- break;
- case kLocalS128:
- type = kWasmS128;
- break;
- default:
- error(pc_ - 1, "invalid local type");
- return;
- }
- local_type_vec_.insert(local_type_vec_.end(), count, type);
- }
- total_locals_ = local_type_vec_.size();
- }
-
// Decodes the body of a function.
void DecodeFunctionBody() {
TRACE("wasm-decode %p...%p (module+%d, %d bytes) %s\n",
@@ -1744,7 +1766,8 @@ class WasmFullDecoder : public WasmDecoder {
env->effect = builder_->EffectPhi(1, &env->effect, env->control);
builder_->Terminate(env->effect, env->control);
if (FLAG_wasm_loop_assignment_analysis) {
- BitVector* assigned = AnalyzeLoopAssignment(pc);
+ BitVector* assigned = AnalyzeLoopAssignment(
+ this, pc, static_cast<int>(total_locals()), zone_);
if (failed()) return env;
if (assigned != nullptr) {
// Only introduce phis for variables assigned in this loop.
@@ -1827,48 +1850,6 @@ class WasmFullDecoder : public WasmDecoder {
builder_ = nullptr; // Don't build any more nodes.
TRACE(" !%s\n", error_msg_.get());
}
- BitVector* AnalyzeLoopAssignment(const byte* pc) {
- if (pc >= end_) return nullptr;
- if (*pc != kExprLoop) return nullptr;
-
- BitVector* assigned =
- new (zone_) BitVector(static_cast<int>(local_type_vec_.size()), zone_);
- int depth = 0;
- // Iteratively process all AST nodes nested inside the loop.
- while (pc < end_ && ok()) {
- WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
- unsigned length = 1;
- switch (opcode) {
- case kExprLoop:
- case kExprIf:
- case kExprBlock:
- case kExprTry:
- length = OpcodeLength(pc);
- depth++;
- break;
- case kExprSetLocal: // fallthru
- case kExprTeeLocal: {
- LocalIndexOperand operand(this, pc);
- if (assigned->length() > 0 &&
- operand.index < static_cast<uint32_t>(assigned->length())) {
- // Unverified code might have an out-of-bounds index.
- assigned->Add(operand.index);
- }
- length = 1 + operand.length;
- break;
- }
- case kExprEnd:
- depth--;
- break;
- default:
- length = OpcodeLength(pc);
- break;
- }
- if (depth <= 0) break;
- pc += length;
- }
- return ok() ? assigned : nullptr;
- }
inline wasm::WasmCodePosition position() {
int offset = static_cast<int>(pc_ - start_);
@@ -1899,21 +1880,23 @@ class WasmFullDecoder : public WasmDecoder {
}
};
-bool DecodeLocalDecls(BodyLocalDecls& decls, const byte* start,
+bool DecodeLocalDecls(BodyLocalDecls* decls, const byte* start,
const byte* end) {
- AccountingAllocator allocator;
- Zone tmp(&allocator, ZONE_NAME);
- FunctionBody body = {nullptr, nullptr, start, end};
- WasmFullDecoder decoder(&tmp, body);
- return decoder.DecodeLocalDecls(decls);
+ Decoder decoder(start, end);
+ if (WasmDecoder::DecodeLocals(&decoder, nullptr, &decls->type_list)) {
+ DCHECK(decoder.ok());
+ decls->encoded_size = decoder.pc_offset();
+ return true;
+ }
+ return false;
}
BytecodeIterator::BytecodeIterator(const byte* start, const byte* end,
BodyLocalDecls* decls)
: Decoder(start, end) {
if (decls != nullptr) {
- if (DecodeLocalDecls(*decls, start, end)) {
- pc_ += decls->decls_encoded_size;
+ if (DecodeLocalDecls(decls, start, end)) {
+ pc_ += decls->encoded_size;
if (pc_ > end_) pc_ = end_;
}
}
@@ -1937,8 +1920,8 @@ DecodeResult BuildTFGraph(AccountingAllocator* allocator, TFBuilder* builder,
}
unsigned OpcodeLength(const byte* pc, const byte* end) {
- WasmDecoder decoder(nullptr, nullptr, pc, end);
- return decoder.OpcodeLength(pc);
+ Decoder decoder(pc, end);
+ return WasmDecoder::OpcodeLength(&decoder, pc);
}
void PrintWasmCodeForDebugging(const byte* start, const byte* end) {
@@ -1966,10 +1949,18 @@ bool PrintWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
BytecodeIterator i(body.start, body.end, &decls);
if (body.start != i.pc() && !FLAG_wasm_code_fuzzer_gen_test) {
os << "// locals: ";
- for (auto p : decls.local_types) {
- ValueType type = p.first;
- uint32_t count = p.second;
- os << " " << count << " " << WasmOpcodes::TypeName(type);
+ if (!decls.type_list.empty()) {
+ ValueType type = decls.type_list[0];
+ uint32_t count = 0;
+ for (size_t pos = 0; pos < decls.type_list.size(); ++pos) {
+ if (decls.type_list[pos] == type) {
+ ++count;
+ } else {
+ os << " " << count << " " << WasmOpcodes::TypeName(type);
+ type = decls.type_list[pos];
+ count = 1;
+ }
+ }
}
os << std::endl;
++line_nr;
@@ -1985,7 +1976,7 @@ bool PrintWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
++line_nr;
unsigned control_depth = 0;
for (; i.has_next(); i.next()) {
- unsigned length = decoder.OpcodeLength(i.pc());
+ unsigned length = WasmDecoder::OpcodeLength(&decoder, i.pc());
WasmOpcode opcode = i.current();
if (opcode == kExprElse) control_depth--;
@@ -2070,9 +2061,9 @@ bool PrintWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
const byte* start, const byte* end) {
- FunctionBody body = {nullptr, nullptr, start, end};
- WasmFullDecoder decoder(zone, body);
- return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals);
+ Decoder decoder(start, end);
+ return WasmDecoder::AnalyzeLoopAssignment(&decoder, start,
+ static_cast<int>(num_locals), zone);
}
} // namespace wasm
« no previous file with comments | « src/wasm/function-body-decoder.h ('k') | src/wasm/wasm-interpreter.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698