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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « src/wasm/ast-decoder.h ('k') | src/wasm/decoder.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/base/platform/elapsed-timer.h" 5 #include "src/base/platform/elapsed-timer.h"
6 #include "src/signature.h" 6 #include "src/signature.h"
7 7
8 #include "src/bit-vector.h" 8 #include "src/bit-vector.h"
9 #include "src/flags.h" 9 #include "src/flags.h"
10 #include "src/handles.h" 10 #include "src/handles.h"
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 struct Production { 45 struct Production {
46 Tree* tree; // the root of the syntax tree. 46 Tree* tree; // the root of the syntax tree.
47 int index; // the current index into the children of the tree. 47 int index; // the current index into the children of the tree.
48 48
49 WasmOpcode opcode() const { return static_cast<WasmOpcode>(*pc()); } 49 WasmOpcode opcode() const { return static_cast<WasmOpcode>(*pc()); }
50 const byte* pc() const { return tree->pc; } 50 const byte* pc() const { return tree->pc; }
51 bool done() const { return index >= static_cast<int>(tree->count); } 51 bool done() const { return index >= static_cast<int>(tree->count); }
52 Tree* last() const { return index > 0 ? tree->children[index - 1] : nullptr; } 52 Tree* last() const { return index > 0 ? tree->children[index - 1] : nullptr; }
53 }; 53 };
54 54
55
56 // An SsaEnv environment carries the current local variable renaming 55 // An SsaEnv environment carries the current local variable renaming
57 // as well as the current effect and control dependency in the TF graph. 56 // as well as the current effect and control dependency in the TF graph.
58 // It maintains a control state that tracks whether the environment 57 // It maintains a control state that tracks whether the environment
59 // is reachable, has reached a control end, or has been merged. 58 // is reachable, has reached a control end, or has been merged.
60 struct SsaEnv { 59 struct SsaEnv {
61 enum State { kControlEnd, kUnreachable, kReached, kMerged }; 60 enum State { kControlEnd, kUnreachable, kReached, kMerged };
62 61
63 State state; 62 State state;
64 TFNode* control; 63 TFNode* control;
65 TFNode* effect; 64 TFNode* effect;
66 TFNode** locals; 65 TFNode** locals;
67 66
68 bool go() { return state >= kReached; } 67 bool go() { return state >= kReached; }
69 void Kill(State new_state = kControlEnd) { 68 void Kill(State new_state = kControlEnd) {
70 state = new_state; 69 state = new_state;
71 locals = nullptr; 70 locals = nullptr;
72 control = nullptr; 71 control = nullptr;
73 effect = nullptr; 72 effect = nullptr;
74 } 73 }
75 }; 74 };
76 75
77
78 // An entry in the stack of blocks during decoding. 76 // An entry in the stack of blocks during decoding.
79 struct Block { 77 struct Block {
80 SsaEnv* ssa_env; // SSA renaming environment. 78 SsaEnv* ssa_env; // SSA renaming environment.
81 int stack_depth; // production stack depth. 79 int stack_depth; // production stack depth.
82 }; 80 };
83 81
84
85 // An entry in the stack of ifs during decoding. 82 // An entry in the stack of ifs during decoding.
86 struct IfEnv { 83 struct IfEnv {
87 SsaEnv* false_env; 84 SsaEnv* false_env;
88 SsaEnv* merge_env; 85 SsaEnv* merge_env;
89 SsaEnv** case_envs; 86 SsaEnv** case_envs;
90 }; 87 };
91 88
92
93 // Macros that build nodes only if there is a graph and the current SSA 89 // Macros that build nodes only if there is a graph and the current SSA
94 // environment is reachable from start. This avoids problems with malformed 90 // environment is reachable from start. This avoids problems with malformed
95 // TF graphs when decoding inputs that have unreachable code. 91 // TF graphs when decoding inputs that have unreachable code.
96 #define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr) 92 #define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr)
97 #define BUILD0(func) (build() ? builder_->func() : nullptr) 93 #define BUILD0(func) (build() ? builder_->func() : nullptr)
98 94
99
100 // Generic Wasm bytecode decoder with utilities for decoding operands, 95 // Generic Wasm bytecode decoder with utilities for decoding operands,
101 // lengths, etc. 96 // lengths, etc.
102 class WasmDecoder : public Decoder { 97 class WasmDecoder : public Decoder {
103 public: 98 public:
104 WasmDecoder() : Decoder(nullptr, nullptr), function_env_(nullptr) {} 99 WasmDecoder(ModuleEnv* module, FunctionSig* sig, const byte* start,
105 WasmDecoder(FunctionEnv* env, const byte* start, const byte* end) 100 const byte* end)
106 : Decoder(start, end), function_env_(env) {} 101 : Decoder(start, end),
107 FunctionEnv* function_env_; 102 module_(module),
108 103 sig_(sig),
109 void Reset(FunctionEnv* function_env, const byte* start, const byte* end) { 104 total_locals_(0),
110 Decoder::Reset(start, end); 105 local_types_(nullptr) {}
111 function_env_ = function_env; 106 ModuleEnv* module_;
112 } 107 FunctionSig* sig_;
108 size_t total_locals_;
109 ZoneVector<LocalType>* local_types_;
113 110
114 byte ByteOperand(const byte* pc, const char* msg = "missing 1-byte operand") { 111 byte ByteOperand(const byte* pc, const char* msg = "missing 1-byte operand") {
115 if ((pc + sizeof(byte)) >= limit_) { 112 if ((pc + sizeof(byte)) >= limit_) {
116 error(pc, msg); 113 error(pc, msg);
117 return 0; 114 return 0;
118 } 115 }
119 return pc[1]; 116 return pc[1];
120 } 117 }
121 118
122 uint32_t Uint32Operand(const byte* pc) { 119 uint32_t Uint32Operand(const byte* pc) {
123 if ((pc + sizeof(uint32_t)) >= limit_) { 120 if ((pc + sizeof(uint32_t)) >= limit_) {
124 error(pc, "missing 4-byte operand"); 121 error(pc, "missing 4-byte operand");
125 return 0; 122 return 0;
126 } 123 }
127 return read_u32(pc + 1); 124 return read_u32(pc + 1);
128 } 125 }
129 126
130 uint64_t Uint64Operand(const byte* pc) { 127 uint64_t Uint64Operand(const byte* pc) {
131 if ((pc + sizeof(uint64_t)) >= limit_) { 128 if ((pc + sizeof(uint64_t)) >= limit_) {
132 error(pc, "missing 8-byte operand"); 129 error(pc, "missing 8-byte operand");
133 return 0; 130 return 0;
134 } 131 }
135 return read_u64(pc + 1); 132 return read_u64(pc + 1);
136 } 133 }
137 134
138 inline bool Validate(const byte* pc, LocalIndexOperand& operand) { 135 inline bool Validate(const byte* pc, LocalIndexOperand& operand) {
139 if (operand.index < function_env_->total_locals) { 136 if (operand.index < total_locals_) {
140 operand.type = function_env_->GetLocalType(operand.index); 137 if (local_types_) {
138 operand.type = local_types_->at(operand.index);
139 } else {
140 operand.type = kAstStmt;
141 }
141 return true; 142 return true;
142 } 143 }
143 error(pc, pc + 1, "invalid local index"); 144 error(pc, pc + 1, "invalid local index");
144 return false; 145 return false;
145 } 146 }
146 147
147 inline bool Validate(const byte* pc, GlobalIndexOperand& operand) { 148 inline bool Validate(const byte* pc, GlobalIndexOperand& operand) {
148 ModuleEnv* m = function_env_->module; 149 ModuleEnv* m = module_;
149 if (m && m->module && operand.index < m->module->globals.size()) { 150 if (m && m->module && operand.index < m->module->globals.size()) {
150 operand.machine_type = m->module->globals[operand.index].type; 151 operand.machine_type = m->module->globals[operand.index].type;
151 operand.type = WasmOpcodes::LocalTypeFor(operand.machine_type); 152 operand.type = WasmOpcodes::LocalTypeFor(operand.machine_type);
152 return true; 153 return true;
153 } 154 }
154 error(pc, pc + 1, "invalid global index"); 155 error(pc, pc + 1, "invalid global index");
155 return false; 156 return false;
156 } 157 }
157 158
158 inline bool Validate(const byte* pc, FunctionIndexOperand& operand) { 159 inline bool Validate(const byte* pc, FunctionIndexOperand& operand) {
159 ModuleEnv* m = function_env_->module; 160 ModuleEnv* m = module_;
160 if (m && m->module && operand.index < m->module->functions.size()) { 161 if (m && m->module && operand.index < m->module->functions.size()) {
161 operand.sig = m->module->functions[operand.index].sig; 162 operand.sig = m->module->functions[operand.index].sig;
162 return true; 163 return true;
163 } 164 }
164 error(pc, pc + 1, "invalid function index"); 165 error(pc, pc + 1, "invalid function index");
165 return false; 166 return false;
166 } 167 }
167 168
168 inline bool Validate(const byte* pc, SignatureIndexOperand& operand) { 169 inline bool Validate(const byte* pc, SignatureIndexOperand& operand) {
169 ModuleEnv* m = function_env_->module; 170 ModuleEnv* m = module_;
170 if (m && m->module && operand.index < m->module->signatures.size()) { 171 if (m && m->module && operand.index < m->module->signatures.size()) {
171 operand.sig = m->module->signatures[operand.index]; 172 operand.sig = m->module->signatures[operand.index];
172 return true; 173 return true;
173 } 174 }
174 error(pc, pc + 1, "invalid signature index"); 175 error(pc, pc + 1, "invalid signature index");
175 return false; 176 return false;
176 } 177 }
177 178
178 inline bool Validate(const byte* pc, ImportIndexOperand& operand) { 179 inline bool Validate(const byte* pc, ImportIndexOperand& operand) {
179 ModuleEnv* m = function_env_->module; 180 ModuleEnv* m = module_;
180 if (m && m->module && operand.index < m->module->import_table.size()) { 181 if (m && m->module && operand.index < m->module->import_table.size()) {
181 operand.sig = m->module->import_table[operand.index].sig; 182 operand.sig = m->module->import_table[operand.index].sig;
182 return true; 183 return true;
183 } 184 }
184 error(pc, pc + 1, "invalid signature index"); 185 error(pc, pc + 1, "invalid signature index");
185 return false; 186 return false;
186 } 187 }
187 188
188 inline bool Validate(const byte* pc, BreakDepthOperand& operand, 189 inline bool Validate(const byte* pc, BreakDepthOperand& operand,
189 ZoneVector<Block>& blocks) { 190 ZoneVector<Block>& blocks) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 244
244 case kExprBlock: 245 case kExprBlock:
245 case kExprLoop: { 246 case kExprLoop: {
246 BlockCountOperand operand(this, pc); 247 BlockCountOperand operand(this, pc);
247 return operand.count; 248 return operand.count;
248 } 249 }
249 250
250 case kExprCallFunction: { 251 case kExprCallFunction: {
251 FunctionIndexOperand operand(this, pc); 252 FunctionIndexOperand operand(this, pc);
252 return static_cast<int>( 253 return static_cast<int>(
253 function_env_->module->GetFunctionSignature(operand.index) 254 module_->GetFunctionSignature(operand.index)->parameter_count());
254 ->parameter_count());
255 } 255 }
256 case kExprCallIndirect: { 256 case kExprCallIndirect: {
257 SignatureIndexOperand operand(this, pc); 257 SignatureIndexOperand operand(this, pc);
258 return 1 + static_cast<int>( 258 return 1 + static_cast<int>(
259 function_env_->module->GetSignature(operand.index) 259 module_->GetSignature(operand.index)->parameter_count());
260 ->parameter_count());
261 } 260 }
262 case kExprCallImport: { 261 case kExprCallImport: {
263 ImportIndexOperand operand(this, pc); 262 ImportIndexOperand operand(this, pc);
264 return static_cast<int>( 263 return static_cast<int>(
265 function_env_->module->GetImportSignature(operand.index) 264 module_->GetImportSignature(operand.index)->parameter_count());
266 ->parameter_count());
267 } 265 }
268 case kExprReturn: { 266 case kExprReturn: {
269 return static_cast<int>(function_env_->sig->return_count()); 267 return static_cast<int>(sig_->return_count());
270 } 268 }
271 case kExprBrTable: { 269 case kExprBrTable: {
272 return 1; 270 return 1;
273 } 271 }
274 272
275 #define DECLARE_OPCODE_CASE(name, opcode, sig) \ 273 #define DECLARE_OPCODE_CASE(name, opcode, sig) \
276 case kExpr##name: \ 274 case kExpr##name: \
277 return kArity_##sig; 275 return kArity_##sig;
278 276
279 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) 277 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
280 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) 278 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
281 FOREACH_MISC_MEM_OPCODE(DECLARE_OPCODE_CASE) 279 FOREACH_MISC_MEM_OPCODE(DECLARE_OPCODE_CASE)
282 FOREACH_SIMPLE_OPCODE(DECLARE_OPCODE_CASE) 280 FOREACH_SIMPLE_OPCODE(DECLARE_OPCODE_CASE)
283 FOREACH_ASMJS_COMPAT_OPCODE(DECLARE_OPCODE_CASE) 281 FOREACH_ASMJS_COMPAT_OPCODE(DECLARE_OPCODE_CASE)
284 #undef DECLARE_OPCODE_CASE 282 #undef DECLARE_OPCODE_CASE
283 case kExprDeclLocals:
284 default:
285 UNREACHABLE();
286 return 0;
285 } 287 }
286 UNREACHABLE();
287 return 0;
288 } 288 }
289 289
290 int OpcodeLength(const byte* pc) { 290 int OpcodeLength(const byte* pc) {
291 switch (static_cast<WasmOpcode>(*pc)) { 291 switch (static_cast<WasmOpcode>(*pc)) {
292 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: 292 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
293 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) 293 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
294 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) 294 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
295 #undef DECLARE_OPCODE_CASE 295 #undef DECLARE_OPCODE_CASE
296 { 296 {
297 MemoryAccessOperand operand(this, pc); 297 MemoryAccessOperand operand(this, pc);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 346
347 default: 347 default:
348 return 1; 348 return 1;
349 } 349 }
350 } 350 }
351 }; 351 };
352 352
353 353
354 // A shift-reduce-parser strategy for decoding Wasm code that uses an explicit 354 // A shift-reduce-parser strategy for decoding Wasm code that uses an explicit
355 // shift-reduce strategy with multiple internal stacks. 355 // shift-reduce strategy with multiple internal stacks.
356 class LR_WasmDecoder : public WasmDecoder { 356 class SR_WasmDecoder : public WasmDecoder {
357 public: 357 public:
358 LR_WasmDecoder(Zone* zone, TFBuilder* builder) 358 SR_WasmDecoder(Zone* zone, TFBuilder* builder, FunctionBody& body)
359 : zone_(zone), 359 : WasmDecoder(body.module, body.sig, body.start, body.end),
360 zone_(zone),
360 builder_(builder), 361 builder_(builder),
362 base_(body.base),
363 local_type_vec_(zone),
361 trees_(zone), 364 trees_(zone),
362 stack_(zone), 365 stack_(zone),
363 blocks_(zone), 366 blocks_(zone),
364 ifs_(zone) {} 367 ifs_(zone) {
368 local_types_ = &local_type_vec_;
369 }
365 370
366 TreeResult Decode(FunctionEnv* function_env, const byte* base, const byte* pc, 371 TreeResult Decode() {
367 const byte* end) {
368 base::ElapsedTimer decode_timer; 372 base::ElapsedTimer decode_timer;
369 if (FLAG_trace_wasm_decode_time) { 373 if (FLAG_trace_wasm_decode_time) {
370 decode_timer.Start(); 374 decode_timer.Start();
371 } 375 }
372 trees_.clear();
373 stack_.clear();
374 blocks_.clear();
375 ifs_.clear();
376 376
377 if (end < pc) { 377 if (end_ < pc_) {
378 error(pc, "function body end < start"); 378 error(pc_, "function body end < start");
379 return result_; 379 return result_;
380 } 380 }
381 381
382 base_ = base; 382 DecodeLocalDecls();
383 Reset(function_env, pc, end);
384
385 InitSsaEnv(); 383 InitSsaEnv();
386 DecodeFunctionBody(); 384 DecodeFunctionBody();
387 385
388 Tree* tree = nullptr; 386 Tree* tree = nullptr;
389 if (ok()) { 387 if (ok()) {
390 if (ssa_env_->go()) { 388 if (ssa_env_->go()) {
391 if (stack_.size() > 0) { 389 if (stack_.size() > 0) {
392 error(stack_.back().pc(), end, "fell off end of code"); 390 error(stack_.back().pc(), end_, "fell off end of code");
393 } 391 }
394 AddImplicitReturnAtEnd(); 392 AddImplicitReturnAtEnd();
395 } 393 }
396 if (trees_.size() == 0) { 394 if (trees_.size() == 0) {
397 if (function_env_->sig->return_count() > 0) { 395 if (sig_->return_count() > 0) {
398 error(start_, "no trees created"); 396 error(start_, "no trees created");
399 } 397 }
400 } else { 398 } else {
401 tree = trees_[0]; 399 tree = trees_[0];
402 } 400 }
403 } 401 }
404 402
405 if (ok()) { 403 if (ok()) {
406 if (FLAG_trace_wasm_ast) { 404 if (FLAG_trace_wasm_ast) {
407 PrintAst(function_env, pc, end); 405 FunctionBody body = {module_, sig_, base_, start_, end_};
406 PrintAst(body);
408 } 407 }
409 if (FLAG_trace_wasm_decode_time) { 408 if (FLAG_trace_wasm_decode_time) {
410 double ms = decode_timer.Elapsed().InMillisecondsF(); 409 double ms = decode_timer.Elapsed().InMillisecondsF();
411 PrintF("wasm-decode ok (%0.3f ms)\n\n", ms); 410 PrintF("wasm-decode ok (%0.3f ms)\n\n", ms);
412 } else { 411 } else {
413 TRACE("wasm-decode ok\n\n"); 412 TRACE("wasm-decode ok\n\n");
414 } 413 }
415 } else { 414 } else {
416 TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_), 415 TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_),
417 startrel(error_pc_), error_msg_.get()); 416 startrel(error_pc_), error_msg_.get());
418 } 417 }
419 418
420 return toResult(tree); 419 return toResult(tree);
421 } 420 }
422 421
422 std::vector<LocalType>* DecodeLocalDeclsForTesting() {
423 DecodeLocalDecls();
424 if (failed()) return nullptr;
425 auto result = new std::vector<LocalType>();
426 result->reserve(local_type_vec_.size());
427 for (size_t i = 0; i < local_type_vec_.size(); i++) {
428 result->push_back(local_type_vec_[i]);
429 }
430 return result;
431 }
432
433 BitVector* AnalyzeLoopAssignmentForTesting(const byte* pc,
434 size_t num_locals) {
435 total_locals_ = num_locals;
436 local_type_vec_.reserve(num_locals);
437 if (num_locals > local_type_vec_.size()) {
438 local_type_vec_.insert(local_type_vec_.end(),
439 num_locals - local_type_vec_.size(), kAstI32);
440 }
441 return AnalyzeLoopAssignment(pc);
442 }
443
423 private: 444 private:
424 static const size_t kErrorMsgSize = 128; 445 static const size_t kErrorMsgSize = 128;
425 446
426 Zone* zone_; 447 Zone* zone_;
427 TFBuilder* builder_; 448 TFBuilder* builder_;
428 const byte* base_; 449 const byte* base_;
429 TreeResult result_; 450 TreeResult result_;
430 451
431 SsaEnv* ssa_env_; 452 SsaEnv* ssa_env_;
432 453
454 ZoneVector<LocalType> local_type_vec_;
433 ZoneVector<Tree*> trees_; 455 ZoneVector<Tree*> trees_;
434 ZoneVector<Production> stack_; 456 ZoneVector<Production> stack_;
435 ZoneVector<Block> blocks_; 457 ZoneVector<Block> blocks_;
436 ZoneVector<IfEnv> ifs_; 458 ZoneVector<IfEnv> ifs_;
437 459
438 inline bool build() { return builder_ && ssa_env_->go(); } 460 inline bool build() { return builder_ && ssa_env_->go(); }
439 461
440 void InitSsaEnv() { 462 void InitSsaEnv() {
441 FunctionSig* sig = function_env_->sig;
442 int param_count = static_cast<int>(sig->parameter_count());
443 TFNode* start = nullptr; 463 TFNode* start = nullptr;
444 SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv))); 464 SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
445 size_t size = sizeof(TFNode*) * EnvironmentCount(); 465 size_t size = sizeof(TFNode*) * EnvironmentCount();
446 ssa_env->state = SsaEnv::kReached; 466 ssa_env->state = SsaEnv::kReached;
447 ssa_env->locals = 467 ssa_env->locals =
448 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr; 468 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
449 469
450 int pos = 0;
451 if (builder_) { 470 if (builder_) {
452 start = builder_->Start(param_count + 1); 471 start = builder_->Start(static_cast<int>(sig_->parameter_count() + 1));
453 // Initialize parameters. 472 // Initialize local variables.
454 for (int i = 0; i < param_count; i++) { 473 uint32_t index = 0;
455 ssa_env->locals[pos++] = builder_->Param(i, sig->GetParam(i)); 474 while (index < sig_->parameter_count()) {
475 ssa_env->locals[index] = builder_->Param(index, local_type_vec_[index]);
476 index++;
456 } 477 }
457 // Initialize int32 locals. 478 while (index < local_type_vec_.size()) {
458 if (function_env_->local_i32_count > 0) { 479 LocalType type = local_type_vec_[index];
459 TFNode* zero = builder_->Int32Constant(0); 480 TFNode* node = DefaultValue(type);
460 for (uint32_t i = 0; i < function_env_->local_i32_count; i++) { 481 while (index < local_type_vec_.size() &&
461 ssa_env->locals[pos++] = zero; 482 local_type_vec_[index] == type) {
483 // Do a whole run of like-typed locals at a time.
484 ssa_env->locals[index++] = node;
462 } 485 }
463 } 486 }
464 // Initialize int64 locals. 487 builder_->set_module(module_);
465 if (function_env_->local_i64_count > 0) {
466 TFNode* zero = builder_->Int64Constant(0);
467 for (uint32_t i = 0; i < function_env_->local_i64_count; i++) {
468 ssa_env->locals[pos++] = zero;
469 }
470 }
471 // Initialize float32 locals.
472 if (function_env_->local_f32_count > 0) {
473 TFNode* zero = builder_->Float32Constant(0);
474 for (uint32_t i = 0; i < function_env_->local_f32_count; i++) {
475 ssa_env->locals[pos++] = zero;
476 }
477 }
478 // Initialize float64 locals.
479 if (function_env_->local_f64_count > 0) {
480 TFNode* zero = builder_->Float64Constant(0);
481 for (uint32_t i = 0; i < function_env_->local_f64_count; i++) {
482 ssa_env->locals[pos++] = zero;
483 }
484 }
485 DCHECK_EQ(function_env_->total_locals, pos);
486 DCHECK_EQ(EnvironmentCount(), pos);
487 builder_->set_module(function_env_->module);
488 } 488 }
489 ssa_env->control = start; 489 ssa_env->control = start;
490 ssa_env->effect = start; 490 ssa_env->effect = start;
491 SetEnv("initial", ssa_env); 491 SetEnv("initial", ssa_env);
492 } 492 }
493 493
494 TFNode* DefaultValue(LocalType type) {
495 switch (type) {
496 case kAstI32:
497 return builder_->Int32Constant(0);
498 case kAstI64:
499 return builder_->Int64Constant(0);
500 case kAstF32:
501 return builder_->Float32Constant(0);
502 case kAstF64:
503 return builder_->Float64Constant(0);
504 default:
505 UNREACHABLE();
506 return nullptr;
507 }
508 }
509
494 void Leaf(LocalType type, TFNode* node = nullptr) { 510 void Leaf(LocalType type, TFNode* node = nullptr) {
495 size_t size = sizeof(Tree); 511 size_t size = sizeof(Tree);
496 Tree* tree = reinterpret_cast<Tree*>(zone_->New(size)); 512 Tree* tree = reinterpret_cast<Tree*>(zone_->New(size));
497 tree->type = type; 513 tree->type = type;
498 tree->count = 0; 514 tree->count = 0;
499 tree->pc = pc_; 515 tree->pc = pc_;
500 tree->node = node; 516 tree->node = node;
501 tree->children[0] = nullptr; 517 tree->children[0] = nullptr;
502 Reduce(tree); 518 Reduce(tree);
503 } 519 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 static const int kMaxIndent = 64; 558 static const int kMaxIndent = 64;
543 static char bytes[kMaxIndent + 1]; 559 static char bytes[kMaxIndent + 1];
544 for (int i = 0; i < kMaxIndent; i++) bytes[i] = ' '; 560 for (int i = 0; i < kMaxIndent; i++) bytes[i] = ' ';
545 bytes[kMaxIndent] = 0; 561 bytes[kMaxIndent] = 0;
546 if (stack_.size() < kMaxIndent / 2) { 562 if (stack_.size() < kMaxIndent / 2) {
547 bytes[stack_.size() * 2] = 0; 563 bytes[stack_.size() * 2] = 0;
548 } 564 }
549 return bytes; 565 return bytes;
550 } 566 }
551 567
568 // Decodes the locals declarations, if any, populating {local_type_vec_}.
569 void DecodeLocalDecls() {
570 DCHECK_EQ(0, local_type_vec_.size());
571 // Initialize {local_type_vec} from signature.
572 if (sig_) {
573 local_type_vec_.reserve(sig_->parameter_count());
574 for (size_t i = 0; i < sig_->parameter_count(); i++) {
575 local_type_vec_.push_back(sig_->GetParam(i));
576 }
577 }
578 // Decode local declarations, if any.
579 int length;
580 uint32_t entries = consume_u32v(&length, "local decls count");
581 while (entries-- > 0 && pc_ < limit_) {
582 uint32_t count = consume_u32v(&length, "local count");
583 byte code = consume_u8("local type");
584 LocalType type;
585 switch (code) {
586 case kLocalI32:
587 type = kAstI32;
588 break;
589 case kLocalI64:
590 type = kAstI64;
591 break;
592 case kLocalF32:
593 type = kAstF32;
594 break;
595 case kLocalF64:
596 type = kAstF64;
597 break;
598 default:
599 error(pc_ - 1, "invalid local type");
600 return;
601 }
602 local_type_vec_.insert(local_type_vec_.end(), count, type);
603 }
604 total_locals_ = local_type_vec_.size();
605 }
606
552 // Decodes the body of a function, producing reduced trees into {result}. 607 // Decodes the body of a function, producing reduced trees into {result}.
553 void DecodeFunctionBody() { 608 void DecodeFunctionBody() {
554 TRACE("wasm-decode %p...%p (%d bytes) %s\n", 609 TRACE("wasm-decode %p...%p (%d bytes) %s\n",
555 reinterpret_cast<const void*>(start_), 610 reinterpret_cast<const void*>(start_),
556 reinterpret_cast<const void*>(limit_), 611 reinterpret_cast<const void*>(limit_),
557 static_cast<int>(limit_ - start_), builder_ ? "graph building" : ""); 612 static_cast<int>(limit_ - start_), builder_ ? "graph building" : "");
558 613
559 if (pc_ >= limit_) return; // Nothing to do. 614 if (pc_ >= limit_) return; // Nothing to do.
560 615
561 while (true) { // decoding loop. 616 while (true) { // decoding loop.
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
645 } 700 }
646 case kExprBrTable: { 701 case kExprBrTable: {
647 BranchTableOperand operand(this, pc_); 702 BranchTableOperand operand(this, pc_);
648 if (Validate(pc_, operand, blocks_.size())) { 703 if (Validate(pc_, operand, blocks_.size())) {
649 Shift(kAstEnd, 1); 704 Shift(kAstEnd, 1);
650 } 705 }
651 len = 1 + operand.length; 706 len = 1 + operand.length;
652 break; 707 break;
653 } 708 }
654 case kExprReturn: { 709 case kExprReturn: {
655 int count = static_cast<int>(function_env_->sig->return_count()); 710 int count = static_cast<int>(sig_->return_count());
656 if (count == 0) { 711 if (count == 0) {
657 BUILD(Return, 0, builder_->Buffer(0)); 712 BUILD(Return, 0, builder_->Buffer(0));
658 ssa_env_->Kill(); 713 ssa_env_->Kill();
659 Leaf(kAstEnd); 714 Leaf(kAstEnd);
660 } else { 715 } else {
661 Shift(kAstEnd, count); 716 Shift(kAstEnd, count);
662 } 717 }
663 break; 718 break;
664 } 719 }
665 case kExprUnreachable: { 720 case kExprUnreachable: {
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 ImportIndexOperand operand(this, pc_); 857 ImportIndexOperand operand(this, pc_);
803 if (Validate(pc_, operand)) { 858 if (Validate(pc_, operand)) {
804 LocalType type = operand.sig->return_count() == 0 859 LocalType type = operand.sig->return_count() == 0
805 ? kAstStmt 860 ? kAstStmt
806 : operand.sig->GetReturn(); 861 : operand.sig->GetReturn();
807 Shift(type, static_cast<int>(operand.sig->parameter_count())); 862 Shift(type, static_cast<int>(operand.sig->parameter_count()));
808 } 863 }
809 len = 1 + operand.length; 864 len = 1 + operand.length;
810 break; 865 break;
811 } 866 }
867 case kExprDeclLocals:
812 default: 868 default:
813 error("Invalid opcode"); 869 error("Invalid opcode");
814 return; 870 return;
815 } 871 }
816 pc_ += len; 872 pc_ += len;
817 if (pc_ >= limit_) { 873 if (pc_ >= limit_) {
818 // End of code reached or exceeded. 874 // End of code reached or exceeded.
819 if (pc_ > limit_ && ok()) { 875 if (pc_ > limit_ && ok()) {
820 error("Beyond end of code"); 876 error("Beyond end of code");
821 } 877 }
(...skipping 12 matching lines...) Expand all
834 return 1 + operand.length; 890 return 1 + operand.length;
835 } 891 }
836 892
837 int DecodeStoreMem(const byte* pc, LocalType type) { 893 int DecodeStoreMem(const byte* pc, LocalType type) {
838 MemoryAccessOperand operand(this, pc); 894 MemoryAccessOperand operand(this, pc);
839 Shift(type, 2); 895 Shift(type, 2);
840 return 1 + operand.length; 896 return 1 + operand.length;
841 } 897 }
842 898
843 void AddImplicitReturnAtEnd() { 899 void AddImplicitReturnAtEnd() {
844 int retcount = static_cast<int>(function_env_->sig->return_count()); 900 int retcount = static_cast<int>(sig_->return_count());
845 if (retcount == 0) { 901 if (retcount == 0) {
846 BUILD0(ReturnVoid); 902 BUILD0(ReturnVoid);
847 return; 903 return;
848 } 904 }
849 905
850 if (static_cast<int>(trees_.size()) < retcount) { 906 if (static_cast<int>(trees_.size()) < retcount) {
851 error(limit_, nullptr, 907 error(limit_, nullptr,
852 "ImplicitReturn expects %d arguments, only %d remain", retcount, 908 "ImplicitReturn expects %d arguments, only %d remain", retcount,
853 static_cast<int>(trees_.size())); 909 static_cast<int>(trees_.size()));
854 return; 910 return;
855 } 911 }
856 912
857 TRACE("wasm-decode implicit return of %d args\n", retcount); 913 TRACE("wasm-decode implicit return of %d args\n", retcount);
858 914
859 TFNode** buffer = BUILD(Buffer, retcount); 915 TFNode** buffer = BUILD(Buffer, retcount);
860 for (int index = 0; index < retcount; index++) { 916 for (int index = 0; index < retcount; index++) {
861 Tree* tree = trees_[trees_.size() - 1 - index]; 917 Tree* tree = trees_[trees_.size() - 1 - index];
862 if (buffer) buffer[index] = tree->node; 918 if (buffer) buffer[index] = tree->node;
863 LocalType expected = function_env_->sig->GetReturn(index); 919 LocalType expected = sig_->GetReturn(index);
864 if (tree->type != expected) { 920 if (tree->type != expected) {
865 error(limit_, tree->pc, 921 error(limit_, tree->pc,
866 "ImplicitReturn[%d] expected type %s, found %s of type %s", index, 922 "ImplicitReturn[%d] expected type %s, found %s of type %s", index,
867 WasmOpcodes::TypeName(expected), 923 WasmOpcodes::TypeName(expected),
868 WasmOpcodes::OpcodeName(tree->opcode()), 924 WasmOpcodes::OpcodeName(tree->opcode()),
869 WasmOpcodes::TypeName(tree->type)); 925 WasmOpcodes::TypeName(tree->type));
870 return; 926 return;
871 } 927 }
872 } 928 }
873 929
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
1059 : BUILD(IfValue, i, sw); 1115 : BUILD(IfValue, i, sw);
1060 } 1116 }
1061 SsaEnv* tenv = blocks_[blocks_.size() - target - 1].ssa_env; 1117 SsaEnv* tenv = blocks_[blocks_.size() - target - 1].ssa_env;
1062 Goto(env, tenv); 1118 Goto(env, tenv);
1063 } 1119 }
1064 ssa_env_ = prev; 1120 ssa_env_ = prev;
1065 } 1121 }
1066 break; 1122 break;
1067 } 1123 }
1068 case kExprReturn: { 1124 case kExprReturn: {
1069 TypeCheckLast(p, function_env_->sig->GetReturn(p->index - 1)); 1125 TypeCheckLast(p, sig_->GetReturn(p->index - 1));
1070 if (p->done()) { 1126 if (p->done()) {
1071 if (build()) { 1127 if (build()) {
1072 int count = p->tree->count; 1128 int count = p->tree->count;
1073 TFNode** buffer = builder_->Buffer(count); 1129 TFNode** buffer = builder_->Buffer(count);
1074 for (int i = 0; i < count; i++) { 1130 for (int i = 0; i < count; i++) {
1075 buffer[i] = p->tree->children[i]->node; 1131 buffer[i] = p->tree->children[i]->node;
1076 } 1132 }
1077 BUILD(Return, count, buffer); 1133 BUILD(Return, count, buffer);
1078 } 1134 }
1079 ssa_env_->Kill(SsaEnv::kControlEnd); 1135 ssa_env_->Kill(SsaEnv::kControlEnd);
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
1339 if (from->effect != to->effect) { 1395 if (from->effect != to->effect) {
1340 TFNode* effects[] = {to->effect, from->effect, merge}; 1396 TFNode* effects[] = {to->effect, from->effect, merge};
1341 to->effect = builder_->EffectPhi(2, effects, merge); 1397 to->effect = builder_->EffectPhi(2, effects, merge);
1342 } 1398 }
1343 // Merge SSA values. 1399 // Merge SSA values.
1344 for (int i = EnvironmentCount() - 1; i >= 0; i--) { 1400 for (int i = EnvironmentCount() - 1; i >= 0; i--) {
1345 TFNode* a = to->locals[i]; 1401 TFNode* a = to->locals[i];
1346 TFNode* b = from->locals[i]; 1402 TFNode* b = from->locals[i];
1347 if (a != b) { 1403 if (a != b) {
1348 TFNode* vals[] = {a, b}; 1404 TFNode* vals[] = {a, b};
1349 to->locals[i] = 1405 to->locals[i] = builder_->Phi(local_type_vec_[i], 2, vals, merge);
1350 builder_->Phi(function_env_->GetLocalType(i), 2, vals, merge);
1351 } 1406 }
1352 } 1407 }
1353 break; 1408 break;
1354 } 1409 }
1355 case SsaEnv::kMerged: { 1410 case SsaEnv::kMerged: {
1356 if (!builder_) break; 1411 if (!builder_) break;
1357 TFNode* merge = to->control; 1412 TFNode* merge = to->control;
1358 // Extend the existing merge. 1413 // Extend the existing merge.
1359 builder_->AppendToMerge(merge, from->control); 1414 builder_->AppendToMerge(merge, from->control);
1360 // Merge effects. 1415 // Merge effects.
(...skipping 14 matching lines...) Expand all
1375 TFNode* fnode = from->locals[i]; 1430 TFNode* fnode = from->locals[i];
1376 if (builder_->IsPhiWithMerge(tnode, merge)) { 1431 if (builder_->IsPhiWithMerge(tnode, merge)) {
1377 builder_->AppendToPhi(merge, tnode, fnode); 1432 builder_->AppendToPhi(merge, tnode, fnode);
1378 } else if (tnode != fnode) { 1433 } else if (tnode != fnode) {
1379 uint32_t count = builder_->InputCount(merge); 1434 uint32_t count = builder_->InputCount(merge);
1380 TFNode** vals = builder_->Buffer(count); 1435 TFNode** vals = builder_->Buffer(count);
1381 for (uint32_t j = 0; j < count - 1; j++) { 1436 for (uint32_t j = 0; j < count - 1; j++) {
1382 vals[j] = tnode; 1437 vals[j] = tnode;
1383 } 1438 }
1384 vals[count - 1] = fnode; 1439 vals[count - 1] = fnode;
1385 to->locals[i] = builder_->Phi(function_env_->GetLocalType(i), count, 1440 to->locals[i] =
1386 vals, merge); 1441 builder_->Phi(local_type_vec_[i], count, vals, merge);
1387 } 1442 }
1388 } 1443 }
1389 break; 1444 break;
1390 } 1445 }
1391 default: 1446 default:
1392 UNREACHABLE(); 1447 UNREACHABLE();
1393 } 1448 }
1394 return from->Kill(); 1449 return from->Kill();
1395 } 1450 }
1396 1451
(...skipping 22 matching lines...) Expand all
1419 } 1474 }
1420 1475
1421 void PrepareForLoop(SsaEnv* env) { 1476 void PrepareForLoop(SsaEnv* env) {
1422 if (env->go()) { 1477 if (env->go()) {
1423 env->state = SsaEnv::kMerged; 1478 env->state = SsaEnv::kMerged;
1424 if (builder_) { 1479 if (builder_) {
1425 env->control = builder_->Loop(env->control); 1480 env->control = builder_->Loop(env->control);
1426 env->effect = builder_->EffectPhi(1, &env->effect, env->control); 1481 env->effect = builder_->EffectPhi(1, &env->effect, env->control);
1427 builder_->Terminate(env->effect, env->control); 1482 builder_->Terminate(env->effect, env->control);
1428 for (int i = EnvironmentCount() - 1; i >= 0; i--) { 1483 for (int i = EnvironmentCount() - 1; i >= 0; i--) {
1429 env->locals[i] = builder_->Phi(function_env_->GetLocalType(i), 1, 1484 env->locals[i] = builder_->Phi(local_type_vec_[i], 1, &env->locals[i],
1430 &env->locals[i], env->control); 1485 env->control);
1431 } 1486 }
1432 } 1487 }
1433 } 1488 }
1434 } 1489 }
1435 1490
1436 // Create a complete copy of the {from}. 1491 // Create a complete copy of the {from}.
1437 SsaEnv* Split(SsaEnv* from) { 1492 SsaEnv* Split(SsaEnv* from) {
1438 DCHECK_NOT_NULL(from); 1493 DCHECK_NOT_NULL(from);
1439 SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv))); 1494 SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
1440 size_t size = sizeof(TFNode*) * EnvironmentCount(); 1495 size_t size = sizeof(TFNode*) * EnvironmentCount();
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1474 SsaEnv* UnreachableEnv() { 1529 SsaEnv* UnreachableEnv() {
1475 SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv))); 1530 SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
1476 result->state = SsaEnv::kUnreachable; 1531 result->state = SsaEnv::kUnreachable;
1477 result->control = nullptr; 1532 result->control = nullptr;
1478 result->effect = nullptr; 1533 result->effect = nullptr;
1479 result->locals = nullptr; 1534 result->locals = nullptr;
1480 return result; 1535 return result;
1481 } 1536 }
1482 1537
1483 int EnvironmentCount() { 1538 int EnvironmentCount() {
1484 if (builder_) return static_cast<int>(function_env_->GetLocalCount()); 1539 if (builder_) return static_cast<int>(local_type_vec_.size());
1485 return 0; // if we aren't building a graph, don't bother with SSA renaming. 1540 return 0; // if we aren't building a graph, don't bother with SSA renaming.
1486 } 1541 }
1487 1542
1488 virtual void onFirstError() { 1543 virtual void onFirstError() {
1489 limit_ = start_; // Terminate decoding loop. 1544 limit_ = start_; // Terminate decoding loop.
1490 builder_ = nullptr; // Don't build any more nodes. 1545 builder_ = nullptr; // Don't build any more nodes.
1491 #if DEBUG 1546 #if DEBUG
1492 PrintStackForDebugging(); 1547 PrintStackForDebugging();
1493 #endif 1548 #endif
1494 } 1549 }
(...skipping 15 matching lines...) Expand all
1510 WasmOpcodes::OpcodeName(child->opcode()), child->count); 1565 WasmOpcodes::OpcodeName(child->opcode()), child->count);
1511 if (child->node) { 1566 if (child->node) {
1512 PrintF(" => TF"); 1567 PrintF(" => TF");
1513 compiler::WasmGraphBuilder::PrintDebugName(child->node); 1568 compiler::WasmGraphBuilder::PrintDebugName(child->node);
1514 } 1569 }
1515 PrintF("\n"); 1570 PrintF("\n");
1516 } 1571 }
1517 PrintProduction(depth + 1); 1572 PrintProduction(depth + 1);
1518 } 1573 }
1519 #endif 1574 #endif
1575
1576 BitVector* AnalyzeLoopAssignment(const byte* pc) {
1577 if (pc >= limit_) return nullptr;
1578 if (*pc != kExprLoop) return nullptr;
1579
1580 BitVector* assigned =
1581 new (zone_) BitVector(static_cast<int>(total_locals_), zone_);
1582 // Keep a stack to model the nesting of expressions.
1583 std::vector<int> arity_stack;
1584 arity_stack.push_back(OpcodeArity(pc));
1585 pc += OpcodeLength(pc);
1586
1587 // Iteratively process all AST nodes nested inside the loop.
1588 while (pc < limit_) {
1589 WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
1590 int arity = 0;
1591 int length = 1;
1592 if (opcode == kExprSetLocal) {
1593 LocalIndexOperand operand(this, pc);
1594 if (assigned->length() > 0 &&
1595 static_cast<int>(operand.index) < assigned->length()) {
1596 // Unverified code might have an out-of-bounds index.
1597 assigned->Add(operand.index);
1598 }
1599 arity = 1;
1600 length = 1 + operand.length;
1601 } else {
1602 arity = OpcodeArity(pc);
1603 length = OpcodeLength(pc);
1604 }
1605
1606 pc += length;
1607 arity_stack.push_back(arity);
1608 while (arity_stack.back() == 0) {
1609 arity_stack.pop_back();
1610 if (arity_stack.empty()) return assigned; // reached end of loop
1611 arity_stack.back()--;
1612 }
1613 }
1614 return assigned;
1615 }
1520 }; 1616 };
1521 1617
1618 std::vector<LocalType>* DecodeLocalDeclsForTesting(const byte* start,
1619 const byte* end) {
1620 Zone zone;
1621 FunctionBody body = {nullptr, nullptr, nullptr, start, end};
1622 SR_WasmDecoder decoder(&zone, nullptr, body);
1623 return decoder.DecodeLocalDeclsForTesting();
1624 }
1522 1625
1523 TreeResult VerifyWasmCode(FunctionEnv* env, const byte* base, const byte* start, 1626 TreeResult VerifyWasmCode(FunctionBody& body) {
1524 const byte* end) {
1525 Zone zone; 1627 Zone zone;
1526 LR_WasmDecoder decoder(&zone, nullptr); 1628 SR_WasmDecoder decoder(&zone, nullptr, body);
1527 TreeResult result = decoder.Decode(env, base, start, end); 1629 TreeResult result = decoder.Decode();
1528 return result; 1630 return result;
1529 } 1631 }
1530 1632
1531 1633 TreeResult BuildTFGraph(TFBuilder* builder, FunctionBody& body) {
1532 TreeResult BuildTFGraph(TFBuilder* builder, FunctionEnv* env, const byte* base,
1533 const byte* start, const byte* end) {
1534 Zone zone; 1634 Zone zone;
1535 LR_WasmDecoder decoder(&zone, builder); 1635 SR_WasmDecoder decoder(&zone, builder, body);
1536 TreeResult result = decoder.Decode(env, base, start, end); 1636 TreeResult result = decoder.Decode();
1537 return result; 1637 return result;
1538 } 1638 }
1539 1639
1540 1640
1541 std::ostream& operator<<(std::ostream& os, const Tree& tree) { 1641 std::ostream& operator<<(std::ostream& os, const Tree& tree) {
1542 if (tree.pc == nullptr) { 1642 if (tree.pc == nullptr) {
1543 os << "null"; 1643 os << "null";
1544 return os; 1644 return os;
1545 } 1645 }
1546 PrintF("%s", WasmOpcodes::OpcodeName(tree.opcode())); 1646 PrintF("%s", WasmOpcodes::OpcodeName(tree.opcode()));
(...skipping 11 matching lines...) Expand all
1558 const byte* limit, 1658 const byte* limit,
1559 int* length, 1659 int* length,
1560 uint32_t* result) { 1660 uint32_t* result) {
1561 Decoder decoder(pc, limit); 1661 Decoder decoder(pc, limit);
1562 *result = decoder.checked_read_u32v(pc, 0, length); 1662 *result = decoder.checked_read_u32v(pc, 0, length);
1563 if (decoder.ok()) return kNoError; 1663 if (decoder.ok()) return kNoError;
1564 return (limit - pc) > 1 ? kInvalidLEB128 : kMissingLEB128; 1664 return (limit - pc) > 1 ? kInvalidLEB128 : kMissingLEB128;
1565 } 1665 }
1566 1666
1567 int OpcodeLength(const byte* pc, const byte* end) { 1667 int OpcodeLength(const byte* pc, const byte* end) {
1568 WasmDecoder decoder(nullptr, pc, end); 1668 WasmDecoder decoder(nullptr, nullptr, pc, end);
1569 return decoder.OpcodeLength(pc); 1669 return decoder.OpcodeLength(pc);
1570 } 1670 }
1571 1671
1572 int OpcodeArity(FunctionEnv* env, const byte* pc, const byte* end) { 1672 int OpcodeArity(ModuleEnv* module, FunctionSig* sig, const byte* pc,
1573 WasmDecoder decoder(env, pc, end); 1673 const byte* end) {
1674 WasmDecoder decoder(module, sig, pc, end);
1574 return decoder.OpcodeArity(pc); 1675 return decoder.OpcodeArity(pc);
1575 } 1676 }
1576 1677
1577 void PrintAst(FunctionEnv* env, const byte* start, const byte* end) { 1678 void PrintAst(FunctionBody& body) {
1578 WasmDecoder decoder(env, start, end); 1679 WasmDecoder decoder(body.module, body.sig, body.start, body.end);
1579 const byte* pc = start; 1680 const byte* pc = body.start;
1580 std::vector<int> arity_stack; 1681 std::vector<int> arity_stack;
1581 while (pc < end) { 1682 while (pc < body.end) {
1582 int arity = decoder.OpcodeArity(pc); 1683 int arity = decoder.OpcodeArity(pc);
1583 size_t length = decoder.OpcodeLength(pc); 1684 size_t length = decoder.OpcodeLength(pc);
1584 1685
1585 for (auto arity : arity_stack) { 1686 for (auto arity : arity_stack) {
1586 printf(" "); 1687 printf(" ");
1587 USE(arity); 1688 USE(arity);
1588 } 1689 }
1589 1690
1590 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); 1691 WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
1591 printf("k%s,", WasmOpcodes::OpcodeName(opcode)); 1692 printf("k%s,", WasmOpcodes::OpcodeName(opcode));
1592 1693
1593 for (size_t i = 1; i < length; i++) { 1694 for (size_t i = 1; i < length; i++) {
1594 printf(" 0x%02x,", pc[i]); 1695 printf(" 0x%02x,", pc[i]);
1595 } 1696 }
1596 pc += length; 1697 pc += length;
1597 printf("\n"); 1698 printf("\n");
1598 1699
1599 arity_stack.push_back(arity); 1700 arity_stack.push_back(arity);
1600 while (arity_stack.back() == 0) { 1701 while (arity_stack.back() == 0) {
1601 arity_stack.pop_back(); 1702 arity_stack.pop_back();
1602 if (arity_stack.empty()) break; 1703 if (arity_stack.empty()) break;
1603 arity_stack.back()--; 1704 arity_stack.back()--;
1604 } 1705 }
1605 } 1706 }
1606 } 1707 }
1607 1708
1608 // Analyzes loop bodies for static assignments to locals, which helps in 1709 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
1609 // reducing the number of phis introduced at loop headers.
1610 class LoopAssignmentAnalyzer : public WasmDecoder {
1611 public:
1612 LoopAssignmentAnalyzer(Zone* zone, FunctionEnv* function_env) : zone_(zone) {
1613 function_env_ = function_env;
1614 }
1615
1616 BitVector* Analyze(const byte* pc, const byte* limit) {
1617 Decoder::Reset(pc, limit);
1618 if (pc_ >= limit_) return nullptr;
1619 if (*pc_ != kExprLoop) return nullptr;
1620
1621 BitVector* assigned =
1622 new (zone_) BitVector(function_env_->total_locals, zone_);
1623 // Keep a stack to model the nesting of expressions.
1624 std::vector<int> arity_stack;
1625 arity_stack.push_back(OpcodeArity(pc_));
1626 pc_ += OpcodeLength(pc_);
1627
1628 // Iteratively process all AST nodes nested inside the loop.
1629 while (pc_ < limit_) {
1630 WasmOpcode opcode = static_cast<WasmOpcode>(*pc_);
1631 int arity = 0;
1632 int length = 1;
1633 if (opcode == kExprSetLocal) {
1634 LocalIndexOperand operand(this, pc_);
1635 if (assigned->length() > 0 &&
1636 static_cast<int>(operand.index) < assigned->length()) {
1637 // Unverified code might have an out-of-bounds index.
1638 assigned->Add(operand.index);
1639 }
1640 arity = 1;
1641 length = 1 + operand.length;
1642 } else {
1643 arity = OpcodeArity(pc_);
1644 length = OpcodeLength(pc_);
1645 }
1646
1647 pc_ += length;
1648 arity_stack.push_back(arity);
1649 while (arity_stack.back() == 0) {
1650 arity_stack.pop_back();
1651 if (arity_stack.empty()) return assigned; // reached end of loop
1652 arity_stack.back()--;
1653 }
1654 }
1655 return assigned;
1656 }
1657
1658 private:
1659 Zone* zone_;
1660 };
1661
1662
1663 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, FunctionEnv* env,
1664 const byte* start, const byte* end) { 1710 const byte* start, const byte* end) {
1665 LoopAssignmentAnalyzer analyzer(zone, env); 1711 FunctionBody body = {nullptr, nullptr, nullptr, start, end};
1666 return analyzer.Analyze(start, end); 1712 SR_WasmDecoder decoder(zone, nullptr, body);
1713 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals);
1667 } 1714 }
1668 1715
1669 } // namespace wasm 1716 } // namespace wasm
1670 } // namespace internal 1717 } // namespace internal
1671 } // namespace v8 1718 } // namespace v8
OLDNEW
« 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