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

Unified Diff: src/wasm/ast-decoder.cc

Issue 1763433002: [wasm] Rework encoding of local declarations. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 9 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/ast-decoder.h ('k') | src/wasm/decoder.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/wasm/ast-decoder.cc
diff --git a/src/wasm/ast-decoder.cc b/src/wasm/ast-decoder.cc
index e56991a482e8e2dafc9037c11ed2d6b92730490b..78f50739dd8b4d999ac344379b5e5268404d9261 100644
--- a/src/wasm/ast-decoder.cc
+++ b/src/wasm/ast-decoder.cc
@@ -52,7 +52,6 @@ struct Production {
Tree* last() const { return index > 0 ? tree->children[index - 1] : nullptr; }
};
-
// An SsaEnv environment carries the current local variable renaming
// as well as the current effect and control dependency in the TF graph.
// It maintains a control state that tracks whether the environment
@@ -74,14 +73,12 @@ struct SsaEnv {
}
};
-
// An entry in the stack of blocks during decoding.
struct Block {
SsaEnv* ssa_env; // SSA renaming environment.
int stack_depth; // production stack depth.
};
-
// An entry in the stack of ifs during decoding.
struct IfEnv {
SsaEnv* false_env;
@@ -89,27 +86,27 @@ struct IfEnv {
SsaEnv** case_envs;
};
-
// Macros that build nodes only if there is a graph and the current SSA
// environment is reachable from start. This avoids problems with malformed
// TF graphs when decoding inputs that have unreachable code.
#define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr)
#define BUILD0(func) (build() ? builder_->func() : nullptr)
-
// Generic Wasm bytecode decoder with utilities for decoding operands,
// lengths, etc.
class WasmDecoder : public Decoder {
public:
- WasmDecoder() : Decoder(nullptr, nullptr), function_env_(nullptr) {}
- WasmDecoder(FunctionEnv* env, const byte* start, const byte* end)
- : Decoder(start, end), function_env_(env) {}
- FunctionEnv* function_env_;
-
- void Reset(FunctionEnv* function_env, const byte* start, const byte* end) {
- Decoder::Reset(start, end);
- function_env_ = function_env;
- }
+ WasmDecoder(ModuleEnv* module, FunctionSig* sig, const byte* start,
+ const byte* end)
+ : Decoder(start, end),
+ module_(module),
+ sig_(sig),
+ total_locals_(0),
+ local_types_(nullptr) {}
+ ModuleEnv* module_;
+ FunctionSig* sig_;
+ size_t total_locals_;
+ ZoneVector<LocalType>* local_types_;
byte ByteOperand(const byte* pc, const char* msg = "missing 1-byte operand") {
if ((pc + sizeof(byte)) >= limit_) {
@@ -136,8 +133,12 @@ class WasmDecoder : public Decoder {
}
inline bool Validate(const byte* pc, LocalIndexOperand& operand) {
- if (operand.index < function_env_->total_locals) {
- operand.type = function_env_->GetLocalType(operand.index);
+ if (operand.index < total_locals_) {
+ if (local_types_) {
+ operand.type = local_types_->at(operand.index);
+ } else {
+ operand.type = kAstStmt;
+ }
return true;
}
error(pc, pc + 1, "invalid local index");
@@ -145,7 +146,7 @@ class WasmDecoder : public Decoder {
}
inline bool Validate(const byte* pc, GlobalIndexOperand& operand) {
- ModuleEnv* m = function_env_->module;
+ ModuleEnv* m = module_;
if (m && m->module && operand.index < m->module->globals.size()) {
operand.machine_type = m->module->globals[operand.index].type;
operand.type = WasmOpcodes::LocalTypeFor(operand.machine_type);
@@ -156,7 +157,7 @@ class WasmDecoder : public Decoder {
}
inline bool Validate(const byte* pc, FunctionIndexOperand& operand) {
- ModuleEnv* m = function_env_->module;
+ ModuleEnv* m = module_;
if (m && m->module && operand.index < m->module->functions.size()) {
operand.sig = m->module->functions[operand.index].sig;
return true;
@@ -166,7 +167,7 @@ class WasmDecoder : public Decoder {
}
inline bool Validate(const byte* pc, SignatureIndexOperand& operand) {
- ModuleEnv* m = function_env_->module;
+ ModuleEnv* m = module_;
if (m && m->module && operand.index < m->module->signatures.size()) {
operand.sig = m->module->signatures[operand.index];
return true;
@@ -176,7 +177,7 @@ class WasmDecoder : public Decoder {
}
inline bool Validate(const byte* pc, ImportIndexOperand& operand) {
- ModuleEnv* m = function_env_->module;
+ ModuleEnv* m = module_;
if (m && m->module && operand.index < m->module->import_table.size()) {
operand.sig = m->module->import_table[operand.index].sig;
return true;
@@ -250,23 +251,20 @@ class WasmDecoder : public Decoder {
case kExprCallFunction: {
FunctionIndexOperand operand(this, pc);
return static_cast<int>(
- function_env_->module->GetFunctionSignature(operand.index)
- ->parameter_count());
+ module_->GetFunctionSignature(operand.index)->parameter_count());
}
case kExprCallIndirect: {
SignatureIndexOperand operand(this, pc);
return 1 + static_cast<int>(
- function_env_->module->GetSignature(operand.index)
- ->parameter_count());
+ module_->GetSignature(operand.index)->parameter_count());
}
case kExprCallImport: {
ImportIndexOperand operand(this, pc);
return static_cast<int>(
- function_env_->module->GetImportSignature(operand.index)
- ->parameter_count());
+ module_->GetImportSignature(operand.index)->parameter_count());
}
case kExprReturn: {
- return static_cast<int>(function_env_->sig->return_count());
+ return static_cast<int>(sig_->return_count());
}
case kExprBrTable: {
return 1;
@@ -282,9 +280,11 @@ class WasmDecoder : public Decoder {
FOREACH_SIMPLE_OPCODE(DECLARE_OPCODE_CASE)
FOREACH_ASMJS_COMPAT_OPCODE(DECLARE_OPCODE_CASE)
#undef DECLARE_OPCODE_CASE
+ case kExprDeclLocals:
+ default:
+ UNREACHABLE();
+ return 0;
}
- UNREACHABLE();
- return 0;
}
int OpcodeLength(const byte* pc) {
@@ -353,35 +353,33 @@ class WasmDecoder : public Decoder {
// A shift-reduce-parser strategy for decoding Wasm code that uses an explicit
// shift-reduce strategy with multiple internal stacks.
-class LR_WasmDecoder : public WasmDecoder {
+class SR_WasmDecoder : public WasmDecoder {
public:
- LR_WasmDecoder(Zone* zone, TFBuilder* builder)
- : zone_(zone),
+ SR_WasmDecoder(Zone* zone, TFBuilder* builder, FunctionBody& body)
+ : WasmDecoder(body.module, body.sig, body.start, body.end),
+ zone_(zone),
builder_(builder),
+ base_(body.base),
+ local_type_vec_(zone),
trees_(zone),
stack_(zone),
blocks_(zone),
- ifs_(zone) {}
+ ifs_(zone) {
+ local_types_ = &local_type_vec_;
+ }
- TreeResult Decode(FunctionEnv* function_env, const byte* base, const byte* pc,
- const byte* end) {
+ TreeResult Decode() {
base::ElapsedTimer decode_timer;
if (FLAG_trace_wasm_decode_time) {
decode_timer.Start();
}
- trees_.clear();
- stack_.clear();
- blocks_.clear();
- ifs_.clear();
- if (end < pc) {
- error(pc, "function body end < start");
+ if (end_ < pc_) {
+ error(pc_, "function body end < start");
return result_;
}
- base_ = base;
- Reset(function_env, pc, end);
-
+ DecodeLocalDecls();
InitSsaEnv();
DecodeFunctionBody();
@@ -389,12 +387,12 @@ class LR_WasmDecoder : public WasmDecoder {
if (ok()) {
if (ssa_env_->go()) {
if (stack_.size() > 0) {
- error(stack_.back().pc(), end, "fell off end of code");
+ error(stack_.back().pc(), end_, "fell off end of code");
}
AddImplicitReturnAtEnd();
}
if (trees_.size() == 0) {
- if (function_env_->sig->return_count() > 0) {
+ if (sig_->return_count() > 0) {
error(start_, "no trees created");
}
} else {
@@ -404,7 +402,8 @@ class LR_WasmDecoder : public WasmDecoder {
if (ok()) {
if (FLAG_trace_wasm_ast) {
- PrintAst(function_env, pc, end);
+ FunctionBody body = {module_, sig_, base_, start_, end_};
+ PrintAst(body);
}
if (FLAG_trace_wasm_decode_time) {
double ms = decode_timer.Elapsed().InMillisecondsF();
@@ -420,6 +419,28 @@ class LR_WasmDecoder : public WasmDecoder {
return toResult(tree);
}
+ std::vector<LocalType>* DecodeLocalDeclsForTesting() {
+ DecodeLocalDecls();
+ if (failed()) return nullptr;
+ auto result = new std::vector<LocalType>();
+ result->reserve(local_type_vec_.size());
+ for (size_t i = 0; i < local_type_vec_.size(); i++) {
+ result->push_back(local_type_vec_[i]);
+ }
+ return result;
+ }
+
+ 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(), kAstI32);
+ }
+ return AnalyzeLoopAssignment(pc);
+ }
+
private:
static const size_t kErrorMsgSize = 128;
@@ -430,6 +451,7 @@ class LR_WasmDecoder : public WasmDecoder {
SsaEnv* ssa_env_;
+ ZoneVector<LocalType> local_type_vec_;
ZoneVector<Tree*> trees_;
ZoneVector<Production> stack_;
ZoneVector<Block> blocks_;
@@ -438,8 +460,6 @@ class LR_WasmDecoder : public WasmDecoder {
inline bool build() { return builder_ && ssa_env_->go(); }
void InitSsaEnv() {
- FunctionSig* sig = function_env_->sig;
- int param_count = static_cast<int>(sig->parameter_count());
TFNode* start = nullptr;
SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
size_t size = sizeof(TFNode*) * EnvironmentCount();
@@ -447,50 +467,46 @@ class LR_WasmDecoder : public WasmDecoder {
ssa_env->locals =
size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
- int pos = 0;
if (builder_) {
- start = builder_->Start(param_count + 1);
- // Initialize parameters.
- for (int i = 0; i < param_count; i++) {
- ssa_env->locals[pos++] = builder_->Param(i, sig->GetParam(i));
- }
- // Initialize int32 locals.
- if (function_env_->local_i32_count > 0) {
- TFNode* zero = builder_->Int32Constant(0);
- for (uint32_t i = 0; i < function_env_->local_i32_count; i++) {
- ssa_env->locals[pos++] = zero;
- }
+ start = builder_->Start(static_cast<int>(sig_->parameter_count() + 1));
+ // Initialize local variables.
+ uint32_t index = 0;
+ while (index < sig_->parameter_count()) {
+ ssa_env->locals[index] = builder_->Param(index, local_type_vec_[index]);
+ index++;
}
- // Initialize int64 locals.
- if (function_env_->local_i64_count > 0) {
- TFNode* zero = builder_->Int64Constant(0);
- for (uint32_t i = 0; i < function_env_->local_i64_count; i++) {
- ssa_env->locals[pos++] = zero;
+ while (index < local_type_vec_.size()) {
+ LocalType type = local_type_vec_[index];
+ TFNode* node = DefaultValue(type);
+ while (index < local_type_vec_.size() &&
+ local_type_vec_[index] == type) {
+ // Do a whole run of like-typed locals at a time.
+ ssa_env->locals[index++] = node;
}
}
- // Initialize float32 locals.
- if (function_env_->local_f32_count > 0) {
- TFNode* zero = builder_->Float32Constant(0);
- for (uint32_t i = 0; i < function_env_->local_f32_count; i++) {
- ssa_env->locals[pos++] = zero;
- }
- }
- // Initialize float64 locals.
- if (function_env_->local_f64_count > 0) {
- TFNode* zero = builder_->Float64Constant(0);
- for (uint32_t i = 0; i < function_env_->local_f64_count; i++) {
- ssa_env->locals[pos++] = zero;
- }
- }
- DCHECK_EQ(function_env_->total_locals, pos);
- DCHECK_EQ(EnvironmentCount(), pos);
- builder_->set_module(function_env_->module);
+ builder_->set_module(module_);
}
ssa_env->control = start;
ssa_env->effect = start;
SetEnv("initial", ssa_env);
}
+ TFNode* DefaultValue(LocalType type) {
+ switch (type) {
+ case kAstI32:
+ return builder_->Int32Constant(0);
+ case kAstI64:
+ return builder_->Int64Constant(0);
+ case kAstF32:
+ return builder_->Float32Constant(0);
+ case kAstF64:
+ return builder_->Float64Constant(0);
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+ }
+
void Leaf(LocalType type, TFNode* node = nullptr) {
size_t size = sizeof(Tree);
Tree* tree = reinterpret_cast<Tree*>(zone_->New(size));
@@ -549,6 +565,45 @@ class LR_WasmDecoder : 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.
+ int length;
+ uint32_t entries = consume_u32v(&length, "local decls count");
+ while (entries-- > 0 && pc_ < limit_) {
+ uint32_t count = consume_u32v(&length, "local count");
+ byte code = consume_u8("local type");
+ LocalType type;
+ switch (code) {
+ case kLocalI32:
+ type = kAstI32;
+ break;
+ case kLocalI64:
+ type = kAstI64;
+ break;
+ case kLocalF32:
+ type = kAstF32;
+ break;
+ case kLocalF64:
+ type = kAstF64;
+ 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, producing reduced trees into {result}.
void DecodeFunctionBody() {
TRACE("wasm-decode %p...%p (%d bytes) %s\n",
@@ -652,7 +707,7 @@ class LR_WasmDecoder : public WasmDecoder {
break;
}
case kExprReturn: {
- int count = static_cast<int>(function_env_->sig->return_count());
+ int count = static_cast<int>(sig_->return_count());
if (count == 0) {
BUILD(Return, 0, builder_->Buffer(0));
ssa_env_->Kill();
@@ -809,6 +864,7 @@ class LR_WasmDecoder : public WasmDecoder {
len = 1 + operand.length;
break;
}
+ case kExprDeclLocals:
default:
error("Invalid opcode");
return;
@@ -841,7 +897,7 @@ class LR_WasmDecoder : public WasmDecoder {
}
void AddImplicitReturnAtEnd() {
- int retcount = static_cast<int>(function_env_->sig->return_count());
+ int retcount = static_cast<int>(sig_->return_count());
if (retcount == 0) {
BUILD0(ReturnVoid);
return;
@@ -860,7 +916,7 @@ class LR_WasmDecoder : public WasmDecoder {
for (int index = 0; index < retcount; index++) {
Tree* tree = trees_[trees_.size() - 1 - index];
if (buffer) buffer[index] = tree->node;
- LocalType expected = function_env_->sig->GetReturn(index);
+ LocalType expected = sig_->GetReturn(index);
if (tree->type != expected) {
error(limit_, tree->pc,
"ImplicitReturn[%d] expected type %s, found %s of type %s", index,
@@ -1066,7 +1122,7 @@ class LR_WasmDecoder : public WasmDecoder {
break;
}
case kExprReturn: {
- TypeCheckLast(p, function_env_->sig->GetReturn(p->index - 1));
+ TypeCheckLast(p, sig_->GetReturn(p->index - 1));
if (p->done()) {
if (build()) {
int count = p->tree->count;
@@ -1346,8 +1402,7 @@ class LR_WasmDecoder : public WasmDecoder {
TFNode* b = from->locals[i];
if (a != b) {
TFNode* vals[] = {a, b};
- to->locals[i] =
- builder_->Phi(function_env_->GetLocalType(i), 2, vals, merge);
+ to->locals[i] = builder_->Phi(local_type_vec_[i], 2, vals, merge);
}
}
break;
@@ -1382,8 +1437,8 @@ class LR_WasmDecoder : public WasmDecoder {
vals[j] = tnode;
}
vals[count - 1] = fnode;
- to->locals[i] = builder_->Phi(function_env_->GetLocalType(i), count,
- vals, merge);
+ to->locals[i] =
+ builder_->Phi(local_type_vec_[i], count, vals, merge);
}
}
break;
@@ -1426,8 +1481,8 @@ class LR_WasmDecoder : public WasmDecoder {
env->effect = builder_->EffectPhi(1, &env->effect, env->control);
builder_->Terminate(env->effect, env->control);
for (int i = EnvironmentCount() - 1; i >= 0; i--) {
- env->locals[i] = builder_->Phi(function_env_->GetLocalType(i), 1,
- &env->locals[i], env->control);
+ env->locals[i] = builder_->Phi(local_type_vec_[i], 1, &env->locals[i],
+ env->control);
}
}
}
@@ -1481,7 +1536,7 @@ class LR_WasmDecoder : public WasmDecoder {
}
int EnvironmentCount() {
- if (builder_) return static_cast<int>(function_env_->GetLocalCount());
+ if (builder_) return static_cast<int>(local_type_vec_.size());
return 0; // if we aren't building a graph, don't bother with SSA renaming.
}
@@ -1517,23 +1572,68 @@ class LR_WasmDecoder : public WasmDecoder {
PrintProduction(depth + 1);
}
#endif
+
+ BitVector* AnalyzeLoopAssignment(const byte* pc) {
+ if (pc >= limit_) return nullptr;
+ if (*pc != kExprLoop) return nullptr;
+
+ BitVector* assigned =
+ new (zone_) BitVector(static_cast<int>(total_locals_), zone_);
+ // Keep a stack to model the nesting of expressions.
+ std::vector<int> arity_stack;
+ arity_stack.push_back(OpcodeArity(pc));
+ pc += OpcodeLength(pc);
+
+ // Iteratively process all AST nodes nested inside the loop.
+ while (pc < limit_) {
+ WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
+ int arity = 0;
+ int length = 1;
+ if (opcode == kExprSetLocal) {
+ LocalIndexOperand operand(this, pc);
+ if (assigned->length() > 0 &&
+ static_cast<int>(operand.index) < assigned->length()) {
+ // Unverified code might have an out-of-bounds index.
+ assigned->Add(operand.index);
+ }
+ arity = 1;
+ length = 1 + operand.length;
+ } else {
+ arity = OpcodeArity(pc);
+ length = OpcodeLength(pc);
+ }
+
+ pc += length;
+ arity_stack.push_back(arity);
+ while (arity_stack.back() == 0) {
+ arity_stack.pop_back();
+ if (arity_stack.empty()) return assigned; // reached end of loop
+ arity_stack.back()--;
+ }
+ }
+ return assigned;
+ }
};
+std::vector<LocalType>* DecodeLocalDeclsForTesting(const byte* start,
+ const byte* end) {
+ Zone zone;
+ FunctionBody body = {nullptr, nullptr, nullptr, start, end};
+ SR_WasmDecoder decoder(&zone, nullptr, body);
+ return decoder.DecodeLocalDeclsForTesting();
+}
-TreeResult VerifyWasmCode(FunctionEnv* env, const byte* base, const byte* start,
- const byte* end) {
+TreeResult VerifyWasmCode(FunctionBody& body) {
Zone zone;
- LR_WasmDecoder decoder(&zone, nullptr);
- TreeResult result = decoder.Decode(env, base, start, end);
+ SR_WasmDecoder decoder(&zone, nullptr, body);
+ TreeResult result = decoder.Decode();
return result;
}
-
-TreeResult BuildTFGraph(TFBuilder* builder, FunctionEnv* env, const byte* base,
- const byte* start, const byte* end) {
+TreeResult BuildTFGraph(TFBuilder* builder, FunctionBody& body) {
Zone zone;
- LR_WasmDecoder decoder(&zone, builder);
- TreeResult result = decoder.Decode(env, base, start, end);
+ SR_WasmDecoder decoder(&zone, builder, body);
+ TreeResult result = decoder.Decode();
return result;
}
@@ -1565,20 +1665,21 @@ ReadUnsignedLEB128ErrorCode ReadUnsignedLEB128Operand(const byte* pc,
}
int OpcodeLength(const byte* pc, const byte* end) {
- WasmDecoder decoder(nullptr, pc, end);
+ WasmDecoder decoder(nullptr, nullptr, pc, end);
return decoder.OpcodeLength(pc);
}
-int OpcodeArity(FunctionEnv* env, const byte* pc, const byte* end) {
- WasmDecoder decoder(env, pc, end);
+int OpcodeArity(ModuleEnv* module, FunctionSig* sig, const byte* pc,
+ const byte* end) {
+ WasmDecoder decoder(module, sig, pc, end);
return decoder.OpcodeArity(pc);
}
-void PrintAst(FunctionEnv* env, const byte* start, const byte* end) {
- WasmDecoder decoder(env, start, end);
- const byte* pc = start;
+void PrintAst(FunctionBody& body) {
+ WasmDecoder decoder(body.module, body.sig, body.start, body.end);
+ const byte* pc = body.start;
std::vector<int> arity_stack;
- while (pc < end) {
+ while (pc < body.end) {
int arity = decoder.OpcodeArity(pc);
size_t length = decoder.OpcodeLength(pc);
@@ -1605,65 +1706,11 @@ void PrintAst(FunctionEnv* env, const byte* start, const byte* end) {
}
}
-// Analyzes loop bodies for static assignments to locals, which helps in
-// reducing the number of phis introduced at loop headers.
-class LoopAssignmentAnalyzer : public WasmDecoder {
- public:
- LoopAssignmentAnalyzer(Zone* zone, FunctionEnv* function_env) : zone_(zone) {
- function_env_ = function_env;
- }
-
- BitVector* Analyze(const byte* pc, const byte* limit) {
- Decoder::Reset(pc, limit);
- if (pc_ >= limit_) return nullptr;
- if (*pc_ != kExprLoop) return nullptr;
-
- BitVector* assigned =
- new (zone_) BitVector(function_env_->total_locals, zone_);
- // Keep a stack to model the nesting of expressions.
- std::vector<int> arity_stack;
- arity_stack.push_back(OpcodeArity(pc_));
- pc_ += OpcodeLength(pc_);
-
- // Iteratively process all AST nodes nested inside the loop.
- while (pc_ < limit_) {
- WasmOpcode opcode = static_cast<WasmOpcode>(*pc_);
- int arity = 0;
- int length = 1;
- if (opcode == kExprSetLocal) {
- LocalIndexOperand operand(this, pc_);
- if (assigned->length() > 0 &&
- static_cast<int>(operand.index) < assigned->length()) {
- // Unverified code might have an out-of-bounds index.
- assigned->Add(operand.index);
- }
- arity = 1;
- length = 1 + operand.length;
- } else {
- arity = OpcodeArity(pc_);
- length = OpcodeLength(pc_);
- }
-
- pc_ += length;
- arity_stack.push_back(arity);
- while (arity_stack.back() == 0) {
- arity_stack.pop_back();
- if (arity_stack.empty()) return assigned; // reached end of loop
- arity_stack.back()--;
- }
- }
- return assigned;
- }
-
- private:
- Zone* zone_;
-};
-
-
-BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, FunctionEnv* env,
+BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
const byte* start, const byte* end) {
- LoopAssignmentAnalyzer analyzer(zone, env);
- return analyzer.Analyze(start, end);
+ FunctionBody body = {nullptr, nullptr, nullptr, start, end};
+ SR_WasmDecoder decoder(zone, nullptr, body);
+ return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals);
}
} // namespace wasm
« no previous file with comments | « src/wasm/ast-decoder.h ('k') | src/wasm/decoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698