| OLD | NEW | 
|---|
| 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/signature.h" | 5 #include "src/signature.h" | 
| 6 | 6 | 
| 7 #include "src/bit-vector.h" | 7 #include "src/bit-vector.h" | 
| 8 #include "src/flags.h" | 8 #include "src/flags.h" | 
| 9 #include "src/handles.h" | 9 #include "src/handles.h" | 
| 10 #include "src/zone-containers.h" | 10 #include "src/zone-containers.h" | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
| 35 struct Tree { | 35 struct Tree { | 
| 36   LocalType type;     // tree type. | 36   LocalType type;     // tree type. | 
| 37   uint32_t count;     // number of children. | 37   uint32_t count;     // number of children. | 
| 38   const byte* pc;     // start of the syntax tree. | 38   const byte* pc;     // start of the syntax tree. | 
| 39   TFNode* node;       // node in the TurboFan graph. | 39   TFNode* node;       // node in the TurboFan graph. | 
| 40   Tree* children[1];  // pointers to children. | 40   Tree* children[1];  // pointers to children. | 
| 41 | 41 | 
| 42   WasmOpcode opcode() const { return static_cast<WasmOpcode>(*pc); } | 42   WasmOpcode opcode() const { return static_cast<WasmOpcode>(*pc); } | 
| 43 }; | 43 }; | 
| 44 | 44 | 
| 45 // A production represents an incomplete decoded tree in the LR decoder. |  | 
| 46 struct Production { |  | 
| 47   Tree* tree;  // the root of the syntax tree. |  | 
| 48   int index;   // the current index into the children of the tree. |  | 
| 49 |  | 
| 50   WasmOpcode opcode() const { return static_cast<WasmOpcode>(*pc()); } |  | 
| 51   const byte* pc() const { return tree->pc; } |  | 
| 52   bool done() const { return index >= static_cast<int>(tree->count); } |  | 
| 53   Tree* last() const { return index > 0 ? tree->children[index - 1] : nullptr; } |  | 
| 54 }; |  | 
| 55 |  | 
| 56 // An SsaEnv environment carries the current local variable renaming | 45 // An SsaEnv environment carries the current local variable renaming | 
| 57 // as well as the current effect and control dependency in the TF graph. | 46 // as well as the current effect and control dependency in the TF graph. | 
| 58 // It maintains a control state that tracks whether the environment | 47 // It maintains a control state that tracks whether the environment | 
| 59 // is reachable, has reached a control end, or has been merged. | 48 // is reachable, has reached a control end, or has been merged. | 
| 60 struct SsaEnv { | 49 struct SsaEnv { | 
| 61   enum State { kControlEnd, kUnreachable, kReached, kMerged }; | 50   enum State { kControlEnd, kUnreachable, kReached, kMerged }; | 
| 62 | 51 | 
| 63   State state; | 52   State state; | 
| 64   TFNode* control; | 53   TFNode* control; | 
| 65   TFNode* effect; | 54   TFNode* effect; | 
| 66   TFNode** locals; | 55   TFNode** locals; | 
| 67 | 56 | 
| 68   bool go() { return state >= kReached; } | 57   bool go() { return state >= kReached; } | 
| 69   void Kill(State new_state = kControlEnd) { | 58   void Kill(State new_state = kControlEnd) { | 
| 70     state = new_state; | 59     state = new_state; | 
| 71     locals = nullptr; | 60     locals = nullptr; | 
| 72     control = nullptr; | 61     control = nullptr; | 
| 73     effect = nullptr; | 62     effect = nullptr; | 
| 74   } | 63   } | 
|  | 64   void SetNotMerged() { | 
|  | 65     if (state == kMerged) state = kReached; | 
|  | 66   } | 
| 75 }; | 67 }; | 
| 76 | 68 | 
| 77 // An entry in the stack of blocks during decoding. | 69 // An entry on the value stack. | 
| 78 struct Block { | 70 struct Value { | 
| 79   SsaEnv* ssa_env;  // SSA renaming environment. | 71   const byte* pc; | 
| 80   int stack_depth;  // production stack depth. | 72   TFNode* node; | 
|  | 73   LocalType type; | 
| 81 }; | 74 }; | 
| 82 | 75 | 
| 83 // An entry in the stack of ifs during decoding. | 76 // An entry on the control stack (i.e. if, block, loop). | 
| 84 struct IfEnv { | 77 struct Control { | 
| 85   SsaEnv* false_env; | 78   const byte* pc; | 
| 86   SsaEnv* merge_env; | 79   int stack_depth;  // stack height at the beginning of the construct. | 
| 87   SsaEnv** case_envs; | 80   int block_depth;  // block height at the beginning of the construct. | 
|  | 81   SsaEnv* ssa_env;  // end environment for the construct. | 
|  | 82   TFNode* node;     // result node for the construct. | 
|  | 83   LocalType type;   // result type for the construct. | 
|  | 84 | 
|  | 85   int counter;  // used by if. | 
|  | 86   int max;      // used by fi | 
|  | 87 | 
|  | 88   bool is_if() { return *pc == kExprIf; } | 
|  | 89   bool is_block() { return *pc == kExprBlock; } | 
|  | 90   bool is_loop() { return *pc == kExprLoop && stack_depth < 0; } | 
| 88 }; | 91 }; | 
| 89 | 92 | 
| 90 // Macros that build nodes only if there is a graph and the current SSA | 93 // Macros that build nodes only if there is a graph and the current SSA | 
| 91 // environment is reachable from start. This avoids problems with malformed | 94 // environment is reachable from start. This avoids problems with malformed | 
| 92 // TF graphs when decoding inputs that have unreachable code. | 95 // TF graphs when decoding inputs that have unreachable code. | 
| 93 #define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr) | 96 #define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr) | 
| 94 #define BUILD0(func) (build() ? builder_->func() : nullptr) | 97 #define BUILD0(func) (build() ? builder_->func() : nullptr) | 
| 95 | 98 | 
| 96 // Generic Wasm bytecode decoder with utilities for decoding operands, | 99 // Generic Wasm bytecode decoder with utilities for decoding operands, | 
| 97 // lengths, etc. | 100 // lengths, etc. | 
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 181     ModuleEnv* m = module_; | 184     ModuleEnv* m = module_; | 
| 182     if (m && m->module && operand.index < m->module->import_table.size()) { | 185     if (m && m->module && operand.index < m->module->import_table.size()) { | 
| 183       operand.sig = m->module->import_table[operand.index].sig; | 186       operand.sig = m->module->import_table[operand.index].sig; | 
| 184       return true; | 187       return true; | 
| 185     } | 188     } | 
| 186     error(pc, pc + 1, "invalid signature index"); | 189     error(pc, pc + 1, "invalid signature index"); | 
| 187     return false; | 190     return false; | 
| 188   } | 191   } | 
| 189 | 192 | 
| 190   inline bool Validate(const byte* pc, BreakDepthOperand& operand, | 193   inline bool Validate(const byte* pc, BreakDepthOperand& operand, | 
| 191                        ZoneVector<Block>& blocks) { | 194                        ZoneVector<size_t>& blocks, | 
|  | 195                        ZoneVector<Control>& control) { | 
| 192     if (operand.depth < blocks.size()) { | 196     if (operand.depth < blocks.size()) { | 
| 193       operand.target = &blocks[blocks.size() - operand.depth - 1]; | 197       operand.target = &control[blocks[blocks.size() - operand.depth - 1]]; | 
|  | 198       DCHECK(!operand.target->is_if()); | 
| 194       return true; | 199       return true; | 
| 195     } | 200     } | 
| 196     error(pc, pc + 1, "invalid break depth"); | 201     error(pc, pc + 1, "invalid break depth"); | 
| 197     return false; | 202     return false; | 
| 198   } | 203   } | 
| 199 | 204 | 
| 200   bool Validate(const byte* pc, BranchTableOperand& operand, | 205   bool Validate(const byte* pc, BranchTableOperand& operand, | 
| 201                 size_t block_depth) { | 206                 size_t block_depth) { | 
| 202     // Verify table. | 207     // Verify table. | 
| 203     for (uint32_t i = 0; i < operand.table_count + 1; i++) { | 208     for (uint32_t i = 0; i < operand.table_count + 1; i++) { | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
| 222     switch (static_cast<WasmOpcode>(*pc)) { | 227     switch (static_cast<WasmOpcode>(*pc)) { | 
| 223       case kExprI8Const: | 228       case kExprI8Const: | 
| 224       case kExprI32Const: | 229       case kExprI32Const: | 
| 225       case kExprI64Const: | 230       case kExprI64Const: | 
| 226       case kExprF64Const: | 231       case kExprF64Const: | 
| 227       case kExprF32Const: | 232       case kExprF32Const: | 
| 228       case kExprGetLocal: | 233       case kExprGetLocal: | 
| 229       case kExprLoadGlobal: | 234       case kExprLoadGlobal: | 
| 230       case kExprNop: | 235       case kExprNop: | 
| 231       case kExprUnreachable: | 236       case kExprUnreachable: | 
|  | 237       case kExprEnd: | 
|  | 238       case kExprNext: | 
| 232         return 0; | 239         return 0; | 
| 233 | 240 | 
| 234       case kExprBr: | 241       case kExprBr: | 
| 235       case kExprStoreGlobal: | 242       case kExprStoreGlobal: | 
| 236       case kExprSetLocal: | 243       case kExprSetLocal: | 
|  | 244       case kExprElse: | 
| 237         return 1; | 245         return 1; | 
| 238 | 246 | 
| 239       case kExprIf: | 247       case kExprIf: | 
| 240       case kExprBrIf: | 248       case kExprBrIf: | 
| 241         return 2; | 249         return 2; | 
| 242       case kExprIfElse: |  | 
| 243       case kExprSelect: | 250       case kExprSelect: | 
| 244         return 3; | 251         return 3; | 
| 245 | 252 | 
| 246       case kExprBlock: | 253       case kExprBlock: | 
| 247       case kExprLoop: { | 254       case kExprLoop: { | 
| 248         BlockCountOperand operand(this, pc); | 255         BlockCountOperand operand(this, pc); | 
| 249         return operand.count; | 256         return operand.count; | 
| 250       } | 257       } | 
| 251 | 258 | 
| 252       case kExprCallFunction: { | 259       case kExprCallFunction: { | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 291   int OpcodeLength(const byte* pc) { | 298   int OpcodeLength(const byte* pc) { | 
| 292     switch (static_cast<WasmOpcode>(*pc)) { | 299     switch (static_cast<WasmOpcode>(*pc)) { | 
| 293 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: | 300 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: | 
| 294       FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) | 301       FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) | 
| 295       FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) | 302       FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) | 
| 296 #undef DECLARE_OPCODE_CASE | 303 #undef DECLARE_OPCODE_CASE | 
| 297       { | 304       { | 
| 298         MemoryAccessOperand operand(this, pc); | 305         MemoryAccessOperand operand(this, pc); | 
| 299         return 1 + operand.length; | 306         return 1 + operand.length; | 
| 300       } | 307       } | 
| 301       case kExprBlock: |  | 
| 302       case kExprLoop: { |  | 
| 303         BlockCountOperand operand(this, pc); |  | 
| 304         return 1 + operand.length; |  | 
| 305       } |  | 
| 306       case kExprBr: | 308       case kExprBr: | 
| 307       case kExprBrIf: { | 309       case kExprBrIf: { | 
| 308         BreakDepthOperand operand(this, pc); | 310         BreakDepthOperand operand(this, pc); | 
| 309         return 1 + operand.length; | 311         return 1 + operand.length; | 
| 310       } | 312       } | 
| 311       case kExprStoreGlobal: | 313       case kExprStoreGlobal: | 
| 312       case kExprLoadGlobal: { | 314       case kExprLoadGlobal: { | 
| 313         GlobalIndexOperand operand(this, pc); | 315         GlobalIndexOperand operand(this, pc); | 
| 314         return 1 + operand.length; | 316         return 1 + operand.length; | 
| 315       } | 317       } | 
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 361 // A shift-reduce-parser strategy for decoding Wasm code that uses an explicit | 363 // A shift-reduce-parser strategy for decoding Wasm code that uses an explicit | 
| 362 // shift-reduce strategy with multiple internal stacks. | 364 // shift-reduce strategy with multiple internal stacks. | 
| 363 class SR_WasmDecoder : public WasmDecoder { | 365 class SR_WasmDecoder : public WasmDecoder { | 
| 364  public: | 366  public: | 
| 365   SR_WasmDecoder(Zone* zone, TFBuilder* builder, FunctionBody& body) | 367   SR_WasmDecoder(Zone* zone, TFBuilder* builder, FunctionBody& body) | 
| 366       : WasmDecoder(body.module, body.sig, body.start, body.end), | 368       : WasmDecoder(body.module, body.sig, body.start, body.end), | 
| 367         zone_(zone), | 369         zone_(zone), | 
| 368         builder_(builder), | 370         builder_(builder), | 
| 369         base_(body.base), | 371         base_(body.base), | 
| 370         local_type_vec_(zone), | 372         local_type_vec_(zone), | 
| 371         trees_(zone), |  | 
| 372         stack_(zone), | 373         stack_(zone), | 
| 373         blocks_(zone), | 374         control_(zone), | 
| 374         ifs_(zone) { | 375         blocks_(zone) { | 
| 375     local_types_ = &local_type_vec_; | 376     local_types_ = &local_type_vec_; | 
| 376   } | 377   } | 
| 377 | 378 | 
| 378   TreeResult Decode() { | 379   bool Decode() { | 
|  | 380     base::ElapsedTimer decode_timer; | 
|  | 381     if (FLAG_trace_wasm_decode_time) { | 
|  | 382       decode_timer.Start(); | 
|  | 383     } | 
|  | 384     stack_.clear(); | 
|  | 385     control_.clear(); | 
|  | 386 | 
| 379     if (end_ < pc_) { | 387     if (end_ < pc_) { | 
| 380       error(pc_, "function body end < start"); | 388       error(pc_, "function body end < start"); | 
| 381       return result_; | 389       return false; | 
| 382     } | 390     } | 
| 383 | 391 | 
| 384     DecodeLocalDecls(); | 392     DecodeLocalDecls(); | 
| 385     InitSsaEnv(); | 393     InitSsaEnv(); | 
| 386     DecodeFunctionBody(); | 394     DecodeFunctionBody(); | 
| 387 | 395 | 
| 388     Tree* tree = nullptr; | 396     if (failed()) return TraceFailed(); | 
| 389     if (ok()) { | 397 | 
| 390       if (ssa_env_->go()) { | 398     if (!control_.empty()) { | 
| 391         if (stack_.size() > 0) { | 399       error(pc_, control_.back().pc, "unterminated control structure"); | 
| 392           error(stack_.back().pc(), end_, "fell off end of code"); | 400       return TraceFailed(); | 
| 393         } |  | 
| 394         AddImplicitReturnAtEnd(); |  | 
| 395       } |  | 
| 396       if (trees_.size() == 0) { |  | 
| 397         if (sig_->return_count() > 0) { |  | 
| 398           error(start_, "no trees created"); |  | 
| 399         } |  | 
| 400       } else { |  | 
| 401         tree = trees_[0]; |  | 
| 402       } |  | 
| 403     } | 401     } | 
| 404 | 402 | 
| 405     if (ok()) { | 403     if (ssa_env_->go()) { | 
| 406       TRACE("wasm-decode ok\n"); | 404       TRACE("  @%-6d #xx:%-20s|", startrel(pc_), "ImplicitReturn"); | 
| 407     } else { | 405       DoReturn(); | 
| 408       TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_), | 406       if (failed()) return TraceFailed(); | 
| 409             startrel(error_pc_), error_msg_.get()); | 407       TRACE("\n"); | 
| 410     } | 408     } | 
| 411 | 409 | 
| 412     return toResult(tree); | 410     if (FLAG_trace_wasm_decode_time) { | 
|  | 411       double ms = decode_timer.Elapsed().InMillisecondsF(); | 
|  | 412       PrintF("wasm-decode ok (%0.3f ms)\n\n", ms); | 
|  | 413     } else { | 
|  | 414       TRACE("wasm-decode ok\n\n"); | 
|  | 415     } | 
|  | 416 | 
|  | 417     return true; | 
|  | 418   } | 
|  | 419 | 
|  | 420   bool TraceFailed() { | 
|  | 421     TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_), | 
|  | 422           startrel(error_pc_), error_msg_.get()); | 
|  | 423     return false; | 
| 413   } | 424   } | 
| 414 | 425 | 
| 415   std::vector<LocalType>* DecodeLocalDeclsForTesting() { | 426   std::vector<LocalType>* DecodeLocalDeclsForTesting() { | 
| 416     DecodeLocalDecls(); | 427     DecodeLocalDecls(); | 
| 417     if (failed()) return nullptr; | 428     if (failed()) return nullptr; | 
| 418     auto result = new std::vector<LocalType>(); | 429     auto result = new std::vector<LocalType>(); | 
| 419     result->reserve(local_type_vec_.size()); | 430     result->reserve(local_type_vec_.size()); | 
| 420     for (size_t i = 0; i < local_type_vec_.size(); i++) { | 431     for (size_t i = 0; i < local_type_vec_.size(); i++) { | 
| 421       result->push_back(local_type_vec_[i]); | 432       result->push_back(local_type_vec_[i]); | 
| 422     } | 433     } | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 433     } | 444     } | 
| 434     return AnalyzeLoopAssignment(pc); | 445     return AnalyzeLoopAssignment(pc); | 
| 435   } | 446   } | 
| 436 | 447 | 
| 437  private: | 448  private: | 
| 438   static const size_t kErrorMsgSize = 128; | 449   static const size_t kErrorMsgSize = 128; | 
| 439 | 450 | 
| 440   Zone* zone_; | 451   Zone* zone_; | 
| 441   TFBuilder* builder_; | 452   TFBuilder* builder_; | 
| 442   const byte* base_; | 453   const byte* base_; | 
| 443   TreeResult result_; |  | 
| 444 | 454 | 
| 445   SsaEnv* ssa_env_; | 455   SsaEnv* ssa_env_; | 
| 446 | 456 | 
| 447   ZoneVector<LocalType> local_type_vec_; | 457   ZoneVector<LocalType> local_type_vec_; | 
| 448   ZoneVector<Tree*> trees_; | 458   ZoneVector<Value> stack_; | 
| 449   ZoneVector<Production> stack_; | 459   ZoneVector<Control> control_; | 
| 450   ZoneVector<Block> blocks_; | 460   ZoneVector<size_t> blocks_; | 
| 451   ZoneVector<IfEnv> ifs_; |  | 
| 452 | 461 | 
| 453   inline bool build() { return builder_ && ssa_env_->go(); } | 462   inline bool build() { return builder_ && ssa_env_->go(); } | 
| 454 | 463 | 
| 455   void InitSsaEnv() { | 464   void InitSsaEnv() { | 
| 456     TFNode* start = nullptr; | 465     TFNode* start = nullptr; | 
| 457     SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv))); | 466     SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv))); | 
| 458     size_t size = sizeof(TFNode*) * EnvironmentCount(); | 467     size_t size = sizeof(TFNode*) * EnvironmentCount(); | 
| 459     ssa_env->state = SsaEnv::kReached; | 468     ssa_env->state = SsaEnv::kReached; | 
| 460     ssa_env->locals = | 469     ssa_env->locals = | 
| 461         size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr; | 470         size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr; | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 493       case kAstF32: | 502       case kAstF32: | 
| 494         return builder_->Float32Constant(0); | 503         return builder_->Float32Constant(0); | 
| 495       case kAstF64: | 504       case kAstF64: | 
| 496         return builder_->Float64Constant(0); | 505         return builder_->Float64Constant(0); | 
| 497       default: | 506       default: | 
| 498         UNREACHABLE(); | 507         UNREACHABLE(); | 
| 499         return nullptr; | 508         return nullptr; | 
| 500     } | 509     } | 
| 501   } | 510   } | 
| 502 | 511 | 
| 503   void Leaf(LocalType type, TFNode* node = nullptr) { |  | 
| 504     size_t size = sizeof(Tree); |  | 
| 505     Tree* tree = reinterpret_cast<Tree*>(zone_->New(size)); |  | 
| 506     tree->type = type; |  | 
| 507     tree->count = 0; |  | 
| 508     tree->pc = pc_; |  | 
| 509     tree->node = node; |  | 
| 510     tree->children[0] = nullptr; |  | 
| 511     Reduce(tree); |  | 
| 512   } |  | 
| 513 |  | 
| 514   void Shift(LocalType type, uint32_t count) { |  | 
| 515     size_t size = |  | 
| 516         sizeof(Tree) + (count == 0 ? 0 : ((count - 1) * sizeof(Tree*))); |  | 
| 517     Tree* tree = reinterpret_cast<Tree*>(zone_->New(size)); |  | 
| 518     tree->type = type; |  | 
| 519     tree->count = count; |  | 
| 520     tree->pc = pc_; |  | 
| 521     tree->node = nullptr; |  | 
| 522     for (uint32_t i = 0; i < count; i++) tree->children[i] = nullptr; |  | 
| 523     if (count == 0) { |  | 
| 524       Production p = {tree, 0}; |  | 
| 525       Reduce(&p); |  | 
| 526       Reduce(tree); |  | 
| 527     } else { |  | 
| 528       stack_.push_back({tree, 0}); |  | 
| 529     } |  | 
| 530   } |  | 
| 531 |  | 
| 532   void Reduce(Tree* tree) { |  | 
| 533     while (true) { |  | 
| 534       if (stack_.size() == 0) { |  | 
| 535         trees_.push_back(tree); |  | 
| 536         break; |  | 
| 537       } |  | 
| 538       Production* p = &stack_.back(); |  | 
| 539       p->tree->children[p->index++] = tree; |  | 
| 540       Reduce(p); |  | 
| 541       if (p->done()) { |  | 
| 542         tree = p->tree; |  | 
| 543         stack_.pop_back(); |  | 
| 544       } else { |  | 
| 545         break; |  | 
| 546       } |  | 
| 547     } |  | 
| 548   } |  | 
| 549 |  | 
| 550   char* indentation() { | 512   char* indentation() { | 
| 551     static const int kMaxIndent = 64; | 513     static const int kMaxIndent = 64; | 
| 552     static char bytes[kMaxIndent + 1]; | 514     static char bytes[kMaxIndent + 1]; | 
| 553     for (int i = 0; i < kMaxIndent; i++) bytes[i] = ' '; | 515     for (int i = 0; i < kMaxIndent; i++) bytes[i] = ' '; | 
| 554     bytes[kMaxIndent] = 0; | 516     bytes[kMaxIndent] = 0; | 
| 555     if (stack_.size() < kMaxIndent / 2) { | 517     if (stack_.size() < kMaxIndent / 2) { | 
| 556       bytes[stack_.size() * 2] = 0; | 518       bytes[stack_.size() * 2] = 0; | 
| 557     } | 519     } | 
| 558     return bytes; | 520     return bytes; | 
| 559   } | 521   } | 
| (...skipping 30 matching lines...) Expand all  Loading... | 
| 590           break; | 552           break; | 
| 591         default: | 553         default: | 
| 592           error(pc_ - 1, "invalid local type"); | 554           error(pc_ - 1, "invalid local type"); | 
| 593           return; | 555           return; | 
| 594       } | 556       } | 
| 595       local_type_vec_.insert(local_type_vec_.end(), count, type); | 557       local_type_vec_.insert(local_type_vec_.end(), count, type); | 
| 596     } | 558     } | 
| 597     total_locals_ = local_type_vec_.size(); | 559     total_locals_ = local_type_vec_.size(); | 
| 598   } | 560   } | 
| 599 | 561 | 
| 600   // Decodes the body of a function, producing reduced trees into {result}. | 562   // Decodes the body of a function. | 
| 601   void DecodeFunctionBody() { | 563   void DecodeFunctionBody() { | 
| 602     TRACE("wasm-decode %p...%p (%d bytes) %s\n", | 564     TRACE("wasm-decode %p...%p (module+%d, %d bytes) %s\n", | 
| 603           reinterpret_cast<const void*>(start_), | 565           reinterpret_cast<const void*>(start_), | 
| 604           reinterpret_cast<const void*>(limit_), | 566           reinterpret_cast<const void*>(limit_), baserel(pc_), | 
| 605           static_cast<int>(limit_ - start_), builder_ ? "graph building" : ""); | 567           static_cast<int>(limit_ - start_), builder_ ? "graph building" : ""); | 
| 606 | 568 | 
| 607     if (pc_ >= limit_) return;  // Nothing to do. | 569     if (pc_ >= limit_) return;  // Nothing to do. | 
| 608 | 570 | 
| 609     while (true) {  // decoding loop. | 571     while (true) {  // decoding loop. | 
| 610       int len = 1; | 572       int len = 1; | 
| 611       WasmOpcode opcode = static_cast<WasmOpcode>(*pc_); | 573       WasmOpcode opcode = static_cast<WasmOpcode>(*pc_); | 
| 612       TRACE("wasm-decode module+%-6d %s func+%d: 0x%02x %s\n", baserel(pc_), | 574       TRACE("  @%-6d #%02x:%-20s|", startrel(pc_), opcode, | 
| 613             indentation(), startrel(pc_), opcode, | 575             WasmOpcodes::ShortOpcodeName(opcode)); | 
| 614             WasmOpcodes::OpcodeName(opcode)); |  | 
| 615 | 576 | 
| 616       FunctionSig* sig = WasmOpcodes::Signature(opcode); | 577       FunctionSig* sig = WasmOpcodes::Signature(opcode); | 
| 617       if (sig) { | 578       if (sig) { | 
| 618         // A simple expression with a fixed signature. | 579         // Fast case of a simple operator. | 
| 619         Shift(sig->GetReturn(), static_cast<uint32_t>(sig->parameter_count())); | 580         TFNode* node; | 
| 620         pc_ += len; | 581         switch (sig->parameter_count()) { | 
| 621         if (pc_ >= limit_) { | 582           case 1: { | 
| 622           // End of code reached or exceeded. | 583             Value val = Pop(0, sig->GetParam(0)); | 
| 623           if (pc_ > limit_ && ok()) { | 584             node = BUILD(Unop, opcode, val.node); | 
| 624             error("Beyond end of code"); | 585             break; | 
| 625           } | 586           } | 
| 626           return; | 587           case 2: { | 
|  | 588             Value rval = Pop(1, sig->GetParam(1)); | 
|  | 589             Value lval = Pop(0, sig->GetParam(0)); | 
|  | 590             node = BUILD(Binop, opcode, lval.node, rval.node); | 
|  | 591             break; | 
|  | 592           } | 
|  | 593           default: | 
|  | 594             UNREACHABLE(); | 
|  | 595             node = nullptr; | 
|  | 596             break; | 
| 627         } | 597         } | 
| 628         continue;  // back to decoding loop. | 598         Push(GetReturnType(sig), node); | 
| 629       } | 599       } else { | 
| 630 | 600         // Complex bytecode. | 
| 631       switch (opcode) { | 601         switch (opcode) { | 
| 632         case kExprNop: | 602           case kExprNop: | 
| 633           Leaf(kAstStmt); | 603             Push(kAstStmt, nullptr); | 
| 634           break; | 604             break; | 
| 635         case kExprBlock: { | 605           case kExprBlock: { | 
| 636           BlockCountOperand operand(this, pc_); |  | 
| 637           if (operand.count < 1) { |  | 
| 638             Leaf(kAstStmt); |  | 
| 639           } else { |  | 
| 640             Shift(kAstEnd, operand.count); |  | 
| 641             // The break environment is the outer environment. | 606             // The break environment is the outer environment. | 
| 642             SsaEnv* break_env = ssa_env_; | 607             SsaEnv* break_env = ssa_env_; | 
| 643             PushBlock(break_env); | 608             PushBlock(break_env); | 
| 644             SetEnv("block:start", Steal(break_env)); | 609             SetEnv("block:start", Steal(break_env)); | 
|  | 610             break; | 
| 645           } | 611           } | 
| 646           len = 1 + operand.length; | 612           case kExprLoop: { | 
| 647           break; |  | 
| 648         } |  | 
| 649         case kExprLoop: { |  | 
| 650           BlockCountOperand operand(this, pc_); |  | 
| 651           if (operand.count < 1) { |  | 
| 652             Leaf(kAstStmt); |  | 
| 653           } else { |  | 
| 654             Shift(kAstEnd, operand.count); |  | 
| 655             // The break environment is the outer environment. | 613             // The break environment is the outer environment. | 
| 656             SsaEnv* break_env = ssa_env_; | 614             SsaEnv* break_env = ssa_env_; | 
| 657             PushBlock(break_env); | 615             PushBlock(break_env); | 
| 658             SsaEnv* cont_env = Steal(break_env); | 616             SsaEnv* cont_env = Steal(break_env); | 
| 659             // The continue environment is the inner environment. | 617             // The continue environment is the inner environment. | 
| 660             PrepareForLoop(pc_, cont_env); | 618             PrepareForLoop(pc_, cont_env); | 
| 661             SetEnv("loop:start", Split(cont_env)); | 619             SetEnv("loop:start", Split(cont_env)); | 
| 662             if (ssa_env_->go()) ssa_env_->state = SsaEnv::kReached; | 620             ssa_env_->SetNotMerged(); | 
| 663             PushBlock(cont_env); | 621             PushBlock(cont_env, true); | 
| 664             blocks_.back().stack_depth = -1;  // no production for inner block. | 622             break; | 
| 665           } | 623           } | 
| 666           len = 1 + operand.length; | 624           case kExprIf: { | 
| 667           break; | 625             // Condition on top of stack. Split environment for true branch. | 
|  | 626             Value cond = Pop(0, kAstI32); | 
|  | 627             SsaEnv* false_env = ssa_env_; | 
|  | 628             SsaEnv* true_env = Split(ssa_env_); | 
|  | 629             false_env->SetNotMerged(); | 
|  | 630             PushIf(false_env); | 
|  | 631             BUILD(Branch, cond.node, &true_env->control, &false_env->control); | 
|  | 632             SetEnv("if:true", true_env); | 
|  | 633             break; | 
|  | 634           } | 
|  | 635           case kExprElse: { | 
|  | 636             if (control_.empty()) { | 
|  | 637               error(pc_, "else does not match any if"); | 
|  | 638               break; | 
|  | 639             } | 
|  | 640             Control* c = &control_.back(); | 
|  | 641             if (!c->is_if()) { | 
|  | 642               error(pc_, c->pc, "else does not match an if"); | 
|  | 643               break; | 
|  | 644             } | 
|  | 645             if (++c->counter > 1) { | 
|  | 646               error(pc_, c->pc, "else already present for if"); | 
|  | 647               break; | 
|  | 648             } | 
|  | 649             Value val = PopUpTo(c->stack_depth); | 
|  | 650             // The {ssa_env} stores the false env for an if. | 
|  | 651             SsaEnv* false_env = Steal(c->ssa_env); | 
|  | 652             MergeInto(c->ssa_env, &c->node, &c->type, val); | 
|  | 653             // Switch to environment for false branch. | 
|  | 654             SetEnv("if_else:false", false_env); | 
|  | 655             break; | 
|  | 656           } | 
|  | 657           case kExprEnd: { | 
|  | 658             if (control_.empty()) { | 
|  | 659               error(pc_, "end does not match any if or block"); | 
|  | 660               break; | 
|  | 661             } | 
|  | 662             const char* name = "block:end"; | 
|  | 663             Control* c = &control_.back(); | 
|  | 664             if (c->is_loop()) { | 
|  | 665               // Loops always push control in pairs. | 
|  | 666               control_.pop_back(); | 
|  | 667               c = &control_.back(); | 
|  | 668               name = "loop:end"; | 
|  | 669             } | 
|  | 670             Value val = PopUpTo(c->stack_depth); | 
|  | 671             if (c->is_if()) { | 
|  | 672               if (c->counter == 0) { | 
|  | 673                 // End of a one-armed if. | 
|  | 674                 val = {val.pc, nullptr, kAstStmt}; | 
|  | 675                 name = "if:merge"; | 
|  | 676               } else { | 
|  | 677                 // End of a two-armed if. | 
|  | 678                 name = "if_else:merge"; | 
|  | 679               } | 
|  | 680             } | 
|  | 681             if (ssa_env_->go()) { | 
|  | 682               MergeInto(c->ssa_env, &c->node, &c->type, val); | 
|  | 683             } | 
|  | 684             SetEnv(name, c->ssa_env); | 
|  | 685             stack_.resize(c->stack_depth); | 
|  | 686             blocks_.resize(c->block_depth); | 
|  | 687             Push(c->type, c->node); | 
|  | 688             control_.pop_back(); | 
|  | 689             break; | 
|  | 690           } | 
|  | 691           case kExprSelect: { | 
|  | 692             Value cond = Pop(2, kAstI32); | 
|  | 693             Value fval = Pop(); | 
|  | 694             Value tval = Pop(); | 
|  | 695             if (tval.type == kAstStmt || tval.type != fval.type) { | 
|  | 696               if (tval.type != kAstEnd && fval.type != kAstEnd) { | 
|  | 697                 error(pc_, "type mismatch in select"); | 
|  | 698                 break; | 
|  | 699               } | 
|  | 700             } | 
|  | 701             if (build()) { | 
|  | 702               DCHECK(tval.type != kAstEnd); | 
|  | 703               DCHECK(fval.type != kAstEnd); | 
|  | 704               DCHECK(cond.type != kAstEnd); | 
|  | 705               TFNode* controls[2]; | 
|  | 706               builder_->Branch(cond.node, &controls[0], &controls[1]); | 
|  | 707               TFNode* merge = builder_->Merge(2, controls); | 
|  | 708               TFNode* vals[2] = {tval.node, fval.node}; | 
|  | 709               TFNode* phi = builder_->Phi(tval.type, 2, vals, merge); | 
|  | 710               Push(tval.type, phi); | 
|  | 711               ssa_env_->control = merge; | 
|  | 712             } else { | 
|  | 713               Push(tval.type, nullptr); | 
|  | 714             } | 
|  | 715             break; | 
|  | 716           } | 
|  | 717           case kExprBr: { | 
|  | 718             Value val = Pop(); | 
|  | 719             BreakDepthOperand operand(this, pc_); | 
|  | 720             if (Validate(pc_, operand, blocks_, control_)) { | 
|  | 721               BreakTo(operand.target, val); | 
|  | 722             } | 
|  | 723             len = 1 + operand.length; | 
|  | 724             Push(kAstEnd, nullptr); | 
|  | 725             break; | 
|  | 726           } | 
|  | 727           case kExprBrIf: { | 
|  | 728             Value cond = Pop(1, kAstI32); | 
|  | 729             Value val = Pop(); | 
|  | 730             BreakDepthOperand operand(this, pc_); | 
|  | 731             if (Validate(pc_, operand, blocks_, control_)) { | 
|  | 732               SsaEnv* fenv = ssa_env_; | 
|  | 733               SsaEnv* tenv = Split(fenv); | 
|  | 734               fenv->SetNotMerged(); | 
|  | 735               BUILD(Branch, cond.node, &tenv->control, &fenv->control); | 
|  | 736               ssa_env_ = tenv; | 
|  | 737               BreakTo(operand.target, val); | 
|  | 738               ssa_env_ = fenv; | 
|  | 739             } | 
|  | 740             len = 1 + operand.length; | 
|  | 741             Push(kAstStmt, nullptr); | 
|  | 742             break; | 
|  | 743           } | 
|  | 744           case kExprBrTable: { | 
|  | 745             BranchTableOperand operand(this, pc_); | 
|  | 746             if (Validate(pc_, operand, blocks_.size())) { | 
|  | 747               Value key = Pop(0, kAstI32); | 
|  | 748               if (failed()) break; | 
|  | 749 | 
|  | 750               Value voidval = {pc_, nullptr, kAstStmt}; | 
|  | 751               SsaEnv* break_env = ssa_env_; | 
|  | 752               if (operand.table_count > 0) { | 
|  | 753                 // Build branches to the various blocks based on the table. | 
|  | 754                 TFNode* sw = BUILD(Switch, operand.table_count + 1, key.node); | 
|  | 755 | 
|  | 756                 SsaEnv* copy = Steal(break_env); | 
|  | 757                 ssa_env_ = copy; | 
|  | 758                 for (uint32_t i = 0; i < operand.table_count + 1; i++) { | 
|  | 759                   uint16_t target = operand.read_entry(this, i); | 
|  | 760                   ssa_env_ = Split(copy); | 
|  | 761                   ssa_env_->control = (i == operand.table_count) | 
|  | 762                                           ? BUILD(IfDefault, sw) | 
|  | 763                                           : BUILD(IfValue, i, sw); | 
|  | 764                   int depth = target; | 
|  | 765                   size_t block_index = blocks_[blocks_.size() - depth - 1]; | 
|  | 766                   Control* c = &control_[block_index]; | 
|  | 767                   MergeInto(c->ssa_env, &c->node, &c->type, voidval); | 
|  | 768                 } | 
|  | 769               } else { | 
|  | 770                 // Only a default target. Do the equivalent of br. | 
|  | 771                 uint16_t target = operand.read_entry(this, 0); | 
|  | 772                 int depth = target; | 
|  | 773                 size_t block_index = blocks_[blocks_.size() - depth - 1]; | 
|  | 774                 Control* c = &control_[block_index]; | 
|  | 775                 MergeInto(c->ssa_env, &c->node, &c->type, voidval); | 
|  | 776               } | 
|  | 777               // br_table ends the control flow like br. | 
|  | 778               ssa_env_ = break_env; | 
|  | 779               Push(kAstStmt, nullptr); | 
|  | 780             } | 
|  | 781             len = 1 + operand.length; | 
|  | 782             break; | 
|  | 783           } | 
|  | 784           case kExprReturn: { | 
|  | 785             DoReturn(); | 
|  | 786             break; | 
|  | 787           } | 
|  | 788           case kExprUnreachable: { | 
|  | 789             Push(kAstEnd, BUILD0(Unreachable)); | 
|  | 790             ssa_env_->Kill(SsaEnv::kControlEnd); | 
|  | 791             break; | 
|  | 792           } | 
|  | 793           case kExprI8Const: { | 
|  | 794             ImmI8Operand operand(this, pc_); | 
|  | 795             Push(kAstI32, BUILD(Int32Constant, operand.value)); | 
|  | 796             len = 1 + operand.length; | 
|  | 797             break; | 
|  | 798           } | 
|  | 799           case kExprI32Const: { | 
|  | 800             ImmI32Operand operand(this, pc_); | 
|  | 801             Push(kAstI32, BUILD(Int32Constant, operand.value)); | 
|  | 802             len = 1 + operand.length; | 
|  | 803             break; | 
|  | 804           } | 
|  | 805           case kExprI64Const: { | 
|  | 806             ImmI64Operand operand(this, pc_); | 
|  | 807             Push(kAstI64, BUILD(Int64Constant, operand.value)); | 
|  | 808             len = 1 + operand.length; | 
|  | 809             break; | 
|  | 810           } | 
|  | 811           case kExprF32Const: { | 
|  | 812             ImmF32Operand operand(this, pc_); | 
|  | 813             Push(kAstF32, BUILD(Float32Constant, operand.value)); | 
|  | 814             len = 1 + operand.length; | 
|  | 815             break; | 
|  | 816           } | 
|  | 817           case kExprF64Const: { | 
|  | 818             ImmF64Operand operand(this, pc_); | 
|  | 819             Push(kAstF64, BUILD(Float64Constant, operand.value)); | 
|  | 820             len = 1 + operand.length; | 
|  | 821             break; | 
|  | 822           } | 
|  | 823           case kExprGetLocal: { | 
|  | 824             LocalIndexOperand operand(this, pc_); | 
|  | 825             if (Validate(pc_, operand)) { | 
|  | 826               if (build()) { | 
|  | 827                 Push(operand.type, ssa_env_->locals[operand.index]); | 
|  | 828               } else { | 
|  | 829                 Push(operand.type, nullptr); | 
|  | 830               } | 
|  | 831             } | 
|  | 832             len = 1 + operand.length; | 
|  | 833             break; | 
|  | 834           } | 
|  | 835           case kExprSetLocal: { | 
|  | 836             LocalIndexOperand operand(this, pc_); | 
|  | 837             if (Validate(pc_, operand)) { | 
|  | 838               Value val = Pop(0, local_type_vec_[operand.index]); | 
|  | 839               if (ssa_env_->locals) ssa_env_->locals[operand.index] = val.node; | 
|  | 840               Push(val.type, val.node); | 
|  | 841             } | 
|  | 842             len = 1 + operand.length; | 
|  | 843             break; | 
|  | 844           } | 
|  | 845           case kExprLoadGlobal: { | 
|  | 846             GlobalIndexOperand operand(this, pc_); | 
|  | 847             if (Validate(pc_, operand)) { | 
|  | 848               Push(operand.type, BUILD(LoadGlobal, operand.index)); | 
|  | 849             } | 
|  | 850             len = 1 + operand.length; | 
|  | 851             break; | 
|  | 852           } | 
|  | 853           case kExprStoreGlobal: { | 
|  | 854             GlobalIndexOperand operand(this, pc_); | 
|  | 855             if (Validate(pc_, operand)) { | 
|  | 856               Value val = Pop(0, operand.type); | 
|  | 857               BUILD(StoreGlobal, operand.index, val.node); | 
|  | 858               Push(val.type, val.node); | 
|  | 859             } | 
|  | 860             len = 1 + operand.length; | 
|  | 861             break; | 
|  | 862           } | 
|  | 863           case kExprI32LoadMem8S: | 
|  | 864             len = DecodeLoadMem(kAstI32, MachineType::Int8()); | 
|  | 865             break; | 
|  | 866           case kExprI32LoadMem8U: | 
|  | 867             len = DecodeLoadMem(kAstI32, MachineType::Uint8()); | 
|  | 868             break; | 
|  | 869           case kExprI32LoadMem16S: | 
|  | 870             len = DecodeLoadMem(kAstI32, MachineType::Int16()); | 
|  | 871             break; | 
|  | 872           case kExprI32LoadMem16U: | 
|  | 873             len = DecodeLoadMem(kAstI32, MachineType::Uint16()); | 
|  | 874             break; | 
|  | 875           case kExprI32LoadMem: | 
|  | 876             len = DecodeLoadMem(kAstI32, MachineType::Int32()); | 
|  | 877             break; | 
|  | 878 | 
|  | 879           case kExprI64LoadMem8S: | 
|  | 880             len = DecodeLoadMem(kAstI64, MachineType::Int8()); | 
|  | 881             break; | 
|  | 882           case kExprI64LoadMem8U: | 
|  | 883             len = DecodeLoadMem(kAstI64, MachineType::Uint8()); | 
|  | 884             break; | 
|  | 885           case kExprI64LoadMem16S: | 
|  | 886             len = DecodeLoadMem(kAstI64, MachineType::Int16()); | 
|  | 887             break; | 
|  | 888           case kExprI64LoadMem16U: | 
|  | 889             len = DecodeLoadMem(kAstI64, MachineType::Uint16()); | 
|  | 890             break; | 
|  | 891           case kExprI64LoadMem32S: | 
|  | 892             len = DecodeLoadMem(kAstI64, MachineType::Int32()); | 
|  | 893             break; | 
|  | 894           case kExprI64LoadMem32U: | 
|  | 895             len = DecodeLoadMem(kAstI64, MachineType::Uint32()); | 
|  | 896             break; | 
|  | 897           case kExprI64LoadMem: | 
|  | 898             len = DecodeLoadMem(kAstI64, MachineType::Int64()); | 
|  | 899             break; | 
|  | 900           case kExprF32LoadMem: | 
|  | 901             len = DecodeLoadMem(kAstF32, MachineType::Float32()); | 
|  | 902             break; | 
|  | 903           case kExprF64LoadMem: | 
|  | 904             len = DecodeLoadMem(kAstF64, MachineType::Float64()); | 
|  | 905             break; | 
|  | 906           case kExprI32StoreMem8: | 
|  | 907             len = DecodeStoreMem(kAstI32, MachineType::Int8()); | 
|  | 908             break; | 
|  | 909           case kExprI32StoreMem16: | 
|  | 910             len = DecodeStoreMem(kAstI32, MachineType::Int16()); | 
|  | 911             break; | 
|  | 912           case kExprI32StoreMem: | 
|  | 913             len = DecodeStoreMem(kAstI32, MachineType::Int32()); | 
|  | 914             break; | 
|  | 915           case kExprI64StoreMem8: | 
|  | 916             len = DecodeStoreMem(kAstI64, MachineType::Int8()); | 
|  | 917             break; | 
|  | 918           case kExprI64StoreMem16: | 
|  | 919             len = DecodeStoreMem(kAstI64, MachineType::Int16()); | 
|  | 920             break; | 
|  | 921           case kExprI64StoreMem32: | 
|  | 922             len = DecodeStoreMem(kAstI64, MachineType::Int32()); | 
|  | 923             break; | 
|  | 924           case kExprI64StoreMem: | 
|  | 925             len = DecodeStoreMem(kAstI64, MachineType::Int64()); | 
|  | 926             break; | 
|  | 927           case kExprF32StoreMem: | 
|  | 928             len = DecodeStoreMem(kAstF32, MachineType::Float32()); | 
|  | 929             break; | 
|  | 930           case kExprF64StoreMem: | 
|  | 931             len = DecodeStoreMem(kAstF64, MachineType::Float64()); | 
|  | 932             break; | 
|  | 933 | 
|  | 934           case kExprMemorySize: | 
|  | 935             Push(kAstI32, BUILD(MemSize, 0)); | 
|  | 936             break; | 
|  | 937           case kExprGrowMemory: { | 
|  | 938             Value val = Pop(0, kAstI32); | 
|  | 939             USE(val);  // TODO(titzer): build node for grow memory | 
|  | 940             Push(kAstI32, BUILD(Int32Constant, 0)); | 
|  | 941             break; | 
|  | 942           } | 
|  | 943           case kExprCallFunction: { | 
|  | 944             FunctionIndexOperand operand(this, pc_); | 
|  | 945             if (Validate(pc_, operand)) { | 
|  | 946               TFNode** buffer = PopArgs(operand.sig); | 
|  | 947               Push(GetReturnType(operand.sig), | 
|  | 948                    BUILD(CallDirect, operand.index, buffer)); | 
|  | 949             } | 
|  | 950             len = 1 + operand.length; | 
|  | 951             break; | 
|  | 952           } | 
|  | 953           case kExprCallIndirect: { | 
|  | 954             SignatureIndexOperand operand(this, pc_); | 
|  | 955             if (Validate(pc_, operand)) { | 
|  | 956               TFNode** buffer = PopArgs(operand.sig); | 
|  | 957               Value index = Pop(0, kAstI32); | 
|  | 958               if (buffer) buffer[0] = index.node; | 
|  | 959               Push(GetReturnType(operand.sig), | 
|  | 960                    BUILD(CallIndirect, operand.index, buffer)); | 
|  | 961             } | 
|  | 962             len = 1 + operand.length; | 
|  | 963             break; | 
|  | 964           } | 
|  | 965           case kExprCallImport: { | 
|  | 966             ImportIndexOperand operand(this, pc_); | 
|  | 967             if (Validate(pc_, operand)) { | 
|  | 968               TFNode** buffer = PopArgs(operand.sig); | 
|  | 969               Push(GetReturnType(operand.sig), | 
|  | 970                    BUILD(CallImport, operand.index, buffer)); | 
|  | 971             } | 
|  | 972             len = 1 + operand.length; | 
|  | 973             break; | 
|  | 974           } | 
|  | 975           default: | 
|  | 976             error("Invalid opcode"); | 
|  | 977             return; | 
| 668         } | 978         } | 
| 669         case kExprIf: | 979       }  // end complex bytecode | 
| 670           Shift(kAstStmt, 2); | 980 | 
| 671           break; | 981 #if DEBUG | 
| 672         case kExprIfElse: | 982       if (FLAG_trace_wasm_decoder) { | 
| 673           Shift(kAstEnd, 3);  // Result type is typeof(x) in {c ? x : y}. | 983         for (size_t i = 0; i < stack_.size(); i++) { | 
| 674           break; | 984           Value& val = stack_[i]; | 
| 675         case kExprSelect: | 985           PrintF( | 
| 676           Shift(kAstStmt, 3);  // Result type is typeof(x) in {c ? x : y}. | 986               " %c@%d:%s", WasmOpcodes::ShortNameOf(val.type), | 
| 677           break; | 987               static_cast<int>(val.pc - start_), | 
| 678         case kExprBr: { | 988               WasmOpcodes::ShortOpcodeName(static_cast<WasmOpcode>(*val.pc))); | 
| 679           BreakDepthOperand operand(this, pc_); |  | 
| 680           if (Validate(pc_, operand, blocks_)) { |  | 
| 681             Shift(kAstEnd, 1); |  | 
| 682           } |  | 
| 683           len = 1 + operand.length; |  | 
| 684           break; |  | 
| 685         } | 989         } | 
| 686         case kExprBrIf: { | 990         PrintF("\n"); | 
| 687           BreakDepthOperand operand(this, pc_); | 991       } | 
| 688           if (Validate(pc_, operand, blocks_)) { | 992 #endif | 
| 689             Shift(kAstStmt, 2); |  | 
| 690           } |  | 
| 691           len = 1 + operand.length; |  | 
| 692           break; |  | 
| 693         } |  | 
| 694         case kExprBrTable: { |  | 
| 695           BranchTableOperand operand(this, pc_); |  | 
| 696           if (Validate(pc_, operand, blocks_.size())) { |  | 
| 697             Shift(kAstEnd, 1); |  | 
| 698           } |  | 
| 699           len = 1 + operand.length; |  | 
| 700           break; |  | 
| 701         } |  | 
| 702         case kExprReturn: { |  | 
| 703           int count = static_cast<int>(sig_->return_count()); |  | 
| 704           if (count == 0) { |  | 
| 705             BUILD(Return, 0, builder_->Buffer(0)); |  | 
| 706             ssa_env_->Kill(); |  | 
| 707             Leaf(kAstEnd); |  | 
| 708           } else { |  | 
| 709             Shift(kAstEnd, count); |  | 
| 710           } |  | 
| 711           break; |  | 
| 712         } |  | 
| 713         case kExprUnreachable: { |  | 
| 714           BUILD0(Unreachable); |  | 
| 715           ssa_env_->Kill(SsaEnv::kControlEnd); |  | 
| 716           Leaf(kAstEnd, nullptr); |  | 
| 717           break; |  | 
| 718         } |  | 
| 719         case kExprI8Const: { |  | 
| 720           ImmI8Operand operand(this, pc_); |  | 
| 721           Leaf(kAstI32, BUILD(Int32Constant, operand.value)); |  | 
| 722           len = 1 + operand.length; |  | 
| 723           break; |  | 
| 724         } |  | 
| 725         case kExprI32Const: { |  | 
| 726           ImmI32Operand operand(this, pc_); |  | 
| 727           Leaf(kAstI32, BUILD(Int32Constant, operand.value)); |  | 
| 728           len = 1 + operand.length; |  | 
| 729           break; |  | 
| 730         } |  | 
| 731         case kExprI64Const: { |  | 
| 732           ImmI64Operand operand(this, pc_); |  | 
| 733           Leaf(kAstI64, BUILD(Int64Constant, operand.value)); |  | 
| 734           len = 1 + operand.length; |  | 
| 735           break; |  | 
| 736         } |  | 
| 737         case kExprF32Const: { |  | 
| 738           ImmF32Operand operand(this, pc_); |  | 
| 739           Leaf(kAstF32, BUILD(Float32Constant, operand.value)); |  | 
| 740           len = 1 + operand.length; |  | 
| 741           break; |  | 
| 742         } |  | 
| 743         case kExprF64Const: { |  | 
| 744           ImmF64Operand operand(this, pc_); |  | 
| 745           Leaf(kAstF64, BUILD(Float64Constant, operand.value)); |  | 
| 746           len = 1 + operand.length; |  | 
| 747           break; |  | 
| 748         } |  | 
| 749         case kExprGetLocal: { |  | 
| 750           LocalIndexOperand operand(this, pc_); |  | 
| 751           if (Validate(pc_, operand)) { |  | 
| 752             TFNode* val = build() ? ssa_env_->locals[operand.index] : nullptr; |  | 
| 753             Leaf(operand.type, val); |  | 
| 754           } |  | 
| 755           len = 1 + operand.length; |  | 
| 756           break; |  | 
| 757         } |  | 
| 758         case kExprSetLocal: { |  | 
| 759           LocalIndexOperand operand(this, pc_); |  | 
| 760           if (Validate(pc_, operand)) { |  | 
| 761             Shift(operand.type, 1); |  | 
| 762           } |  | 
| 763           len = 1 + operand.length; |  | 
| 764           break; |  | 
| 765         } |  | 
| 766         case kExprLoadGlobal: { |  | 
| 767           GlobalIndexOperand operand(this, pc_); |  | 
| 768           if (Validate(pc_, operand)) { |  | 
| 769             Leaf(operand.type, BUILD(LoadGlobal, operand.index)); |  | 
| 770           } |  | 
| 771           len = 1 + operand.length; |  | 
| 772           break; |  | 
| 773         } |  | 
| 774         case kExprStoreGlobal: { |  | 
| 775           GlobalIndexOperand operand(this, pc_); |  | 
| 776           if (Validate(pc_, operand)) { |  | 
| 777             Shift(operand.type, 1); |  | 
| 778           } |  | 
| 779           len = 1 + operand.length; |  | 
| 780           break; |  | 
| 781         } |  | 
| 782         case kExprI32LoadMem8S: |  | 
| 783         case kExprI32LoadMem8U: |  | 
| 784         case kExprI32LoadMem16S: |  | 
| 785         case kExprI32LoadMem16U: |  | 
| 786         case kExprI32LoadMem: |  | 
| 787           len = DecodeLoadMem(pc_, kAstI32); |  | 
| 788           break; |  | 
| 789         case kExprI64LoadMem8S: |  | 
| 790         case kExprI64LoadMem8U: |  | 
| 791         case kExprI64LoadMem16S: |  | 
| 792         case kExprI64LoadMem16U: |  | 
| 793         case kExprI64LoadMem32S: |  | 
| 794         case kExprI64LoadMem32U: |  | 
| 795         case kExprI64LoadMem: |  | 
| 796           len = DecodeLoadMem(pc_, kAstI64); |  | 
| 797           break; |  | 
| 798         case kExprF32LoadMem: |  | 
| 799           len = DecodeLoadMem(pc_, kAstF32); |  | 
| 800           break; |  | 
| 801         case kExprF64LoadMem: |  | 
| 802           len = DecodeLoadMem(pc_, kAstF64); |  | 
| 803           break; |  | 
| 804         case kExprI32StoreMem8: |  | 
| 805         case kExprI32StoreMem16: |  | 
| 806         case kExprI32StoreMem: |  | 
| 807           len = DecodeStoreMem(pc_, kAstI32); |  | 
| 808           break; |  | 
| 809         case kExprI64StoreMem8: |  | 
| 810         case kExprI64StoreMem16: |  | 
| 811         case kExprI64StoreMem32: |  | 
| 812         case kExprI64StoreMem: |  | 
| 813           len = DecodeStoreMem(pc_, kAstI64); |  | 
| 814           break; |  | 
| 815         case kExprF32StoreMem: |  | 
| 816           len = DecodeStoreMem(pc_, kAstF32); |  | 
| 817           break; |  | 
| 818         case kExprF64StoreMem: |  | 
| 819           len = DecodeStoreMem(pc_, kAstF64); |  | 
| 820           break; |  | 
| 821         case kExprMemorySize: |  | 
| 822           Leaf(kAstI32, BUILD(MemSize, 0)); |  | 
| 823           break; |  | 
| 824         case kExprGrowMemory: |  | 
| 825           Shift(kAstI32, 1); |  | 
| 826           break; |  | 
| 827         case kExprCallFunction: { |  | 
| 828           FunctionIndexOperand operand(this, pc_); |  | 
| 829           if (Validate(pc_, operand)) { |  | 
| 830             LocalType type = operand.sig->return_count() == 0 |  | 
| 831                                  ? kAstStmt |  | 
| 832                                  : operand.sig->GetReturn(); |  | 
| 833             Shift(type, static_cast<int>(operand.sig->parameter_count())); |  | 
| 834           } |  | 
| 835           len = 1 + operand.length; |  | 
| 836           break; |  | 
| 837         } |  | 
| 838         case kExprCallIndirect: { |  | 
| 839           SignatureIndexOperand operand(this, pc_); |  | 
| 840           if (Validate(pc_, operand)) { |  | 
| 841             LocalType type = operand.sig->return_count() == 0 |  | 
| 842                                  ? kAstStmt |  | 
| 843                                  : operand.sig->GetReturn(); |  | 
| 844             Shift(type, static_cast<int>(1 + operand.sig->parameter_count())); |  | 
| 845           } |  | 
| 846           len = 1 + operand.length; |  | 
| 847           break; |  | 
| 848         } |  | 
| 849         case kExprCallImport: { |  | 
| 850           ImportIndexOperand operand(this, pc_); |  | 
| 851           if (Validate(pc_, operand)) { |  | 
| 852             LocalType type = operand.sig->return_count() == 0 |  | 
| 853                                  ? kAstStmt |  | 
| 854                                  : operand.sig->GetReturn(); |  | 
| 855             Shift(type, static_cast<int>(operand.sig->parameter_count())); |  | 
| 856           } |  | 
| 857           len = 1 + operand.length; |  | 
| 858           break; |  | 
| 859         } |  | 
| 860         case kExprDeclLocals: |  | 
| 861         default: |  | 
| 862           error("Invalid opcode"); |  | 
| 863           return; |  | 
| 864       } |  | 
| 865       pc_ += len; | 993       pc_ += len; | 
| 866       if (pc_ >= limit_) { | 994       if (pc_ >= limit_) { | 
| 867         // End of code reached or exceeded. | 995         // End of code reached or exceeded. | 
| 868         if (pc_ > limit_ && ok()) { | 996         if (pc_ > limit_ && ok()) error("Beyond end of code"); | 
| 869           error("Beyond end of code"); |  | 
| 870         } |  | 
| 871         return; | 997         return; | 
| 872       } | 998       } | 
| 873     } | 999     }  // end decode loop | 
| 874   } | 1000   }    // end DecodeFunctionBody() | 
| 875 | 1001 | 
| 876   void PushBlock(SsaEnv* ssa_env) { | 1002   TFNode** PopArgs(FunctionSig* sig) { | 
| 877     blocks_.push_back({ssa_env, static_cast<int>(stack_.size() - 1)}); | 1003     if (build()) { | 
| 878   } | 1004       int count = static_cast<int>(sig->parameter_count()); | 
| 879 | 1005       TFNode** buffer = builder_->Buffer(count + 1); | 
| 880   int DecodeLoadMem(const byte* pc, LocalType type) { | 1006       buffer[0] = nullptr;  // reserved for code object or function index. | 
| 881     MemoryAccessOperand operand(this, pc); | 1007       for (int i = count - 1; i >= 0; i--) { | 
| 882     Shift(type, 1); | 1008         buffer[i + 1] = Pop(i, sig->GetParam(i)).node; | 
|  | 1009       } | 
|  | 1010       return buffer; | 
|  | 1011     } else { | 
|  | 1012       int count = static_cast<int>(sig->parameter_count()); | 
|  | 1013       for (int i = count - 1; i >= 0; i--) { | 
|  | 1014         Pop(i, sig->GetParam(i)); | 
|  | 1015       } | 
|  | 1016       return nullptr; | 
|  | 1017     } | 
|  | 1018   } | 
|  | 1019 | 
|  | 1020   LocalType GetReturnType(FunctionSig* sig) { | 
|  | 1021     return sig->return_count() == 0 ? kAstStmt : sig->GetReturn(); | 
|  | 1022   } | 
|  | 1023 | 
|  | 1024   void PushBlock(SsaEnv* merge_env, bool loop = false) { | 
|  | 1025     int stack_depth = loop ? -1 : static_cast<int>(stack_.size()); | 
|  | 1026     int block_depth = static_cast<int>(blocks_.size()); | 
|  | 1027     control_.push_back( | 
|  | 1028         {pc_, stack_depth, block_depth, merge_env, nullptr, kAstEnd, 0, 0}); | 
|  | 1029     blocks_.push_back(control_.size() - 1); | 
|  | 1030   } | 
|  | 1031 | 
|  | 1032   void PushIf(SsaEnv* merge_env) { | 
|  | 1033     int stack_depth = static_cast<int>(stack_.size()); | 
|  | 1034     int block_depth = static_cast<int>(blocks_.size()); | 
|  | 1035     control_.push_back( | 
|  | 1036         {pc_, stack_depth, block_depth, merge_env, nullptr, kAstStmt, 0, 0}); | 
|  | 1037   } | 
|  | 1038 | 
|  | 1039   int DecodeLoadMem(LocalType type, MachineType mem_type) { | 
|  | 1040     MemoryAccessOperand operand(this, pc_); | 
|  | 1041     Value index = Pop(0, kAstI32); | 
|  | 1042     TFNode* node = BUILD(LoadMem, type, mem_type, index.node, operand.offset); | 
|  | 1043     Push(type, node); | 
| 883     return 1 + operand.length; | 1044     return 1 + operand.length; | 
| 884   } | 1045   } | 
| 885 | 1046 | 
| 886   int DecodeStoreMem(const byte* pc, LocalType type) { | 1047   int DecodeStoreMem(LocalType type, MachineType mem_type) { | 
| 887     MemoryAccessOperand operand(this, pc); | 1048     MemoryAccessOperand operand(this, pc_); | 
| 888     Shift(type, 2); | 1049     Value val = Pop(1, type); | 
|  | 1050     Value index = Pop(0, kAstI32); | 
|  | 1051     BUILD(StoreMem, mem_type, index.node, operand.offset, val.node); | 
|  | 1052     Push(type, val.node); | 
| 889     return 1 + operand.length; | 1053     return 1 + operand.length; | 
| 890   } | 1054   } | 
| 891 | 1055 | 
| 892   void AddImplicitReturnAtEnd() { | 1056   void DoReturn() { | 
| 893     int retcount = static_cast<int>(sig_->return_count()); | 1057     int count = static_cast<int>(sig_->return_count()); | 
| 894     if (retcount == 0) { | 1058     TFNode** buffer = nullptr; | 
| 895       BUILD0(ReturnVoid); | 1059     if (build()) buffer = builder_->Buffer(count); | 
| 896       return; | 1060 | 
| 897     } | 1061     // Pop return values off the stack in reverse order. | 
| 898 | 1062     for (int i = count - 1; i >= 0; i--) { | 
| 899     if (static_cast<int>(trees_.size()) < retcount) { | 1063       Value val = Pop(i, sig_->GetReturn(i)); | 
| 900       error(limit_, nullptr, | 1064       if (buffer) buffer[i] = val.node; | 
| 901             "ImplicitReturn expects %d arguments, only %d remain", retcount, | 1065     } | 
| 902             static_cast<int>(trees_.size())); | 1066 | 
| 903       return; | 1067     Push(kAstEnd, BUILD(Return, count, buffer)); | 
| 904     } | 1068     ssa_env_->Kill(SsaEnv::kControlEnd); | 
| 905 | 1069   } | 
| 906     TRACE("wasm-decode implicit return of %d args\n", retcount); | 1070 | 
| 907 | 1071   void Push(LocalType type, TFNode* node) { | 
| 908     TFNode** buffer = BUILD(Buffer, retcount); | 1072     stack_.push_back({pc_, node, type}); | 
| 909     for (int index = 0; index < retcount; index++) { | 1073   } | 
| 910       Tree* tree = trees_[trees_.size() - 1 - index]; | 1074 | 
| 911       if (buffer) buffer[index] = tree->node; | 1075   Value Pop(int index, LocalType expected) { | 
| 912       LocalType expected = sig_->GetReturn(index); | 1076     Value val = Pop(); | 
| 913       if (tree->type != expected) { | 1077     if (val.type != expected) { | 
| 914         error(limit_, tree->pc, | 1078       if (val.type != kAstEnd) { | 
| 915               "ImplicitReturn[%d] expected type %s, found %s of type %s", index, | 1079         error(pc_, val.pc, "%s[%d] expected type %s, found %s of type %s", | 
| 916               WasmOpcodes::TypeName(expected), | 1080               WasmOpcodes::ShortOpcodeName(static_cast<WasmOpcode>(*pc_)), | 
| 917               WasmOpcodes::OpcodeName(tree->opcode()), | 1081               index, WasmOpcodes::TypeName(expected), | 
| 918               WasmOpcodes::TypeName(tree->type)); | 1082               WasmOpcodes::ShortOpcodeName(static_cast<WasmOpcode>(*val.pc)), | 
| 919         return; | 1083               WasmOpcodes::TypeName(val.type)); | 
| 920       } | 1084       } | 
| 921     } | 1085     } | 
| 922 | 1086     return val; | 
| 923     BUILD(Return, retcount, buffer); | 1087   } | 
|  | 1088 | 
|  | 1089   Value Pop() { | 
|  | 1090     if (stack_.empty()) { | 
|  | 1091       Value val = {pc_, nullptr, kAstStmt}; | 
|  | 1092       error(pc_, pc_, "%s found empty stack", | 
|  | 1093             WasmOpcodes::ShortOpcodeName(static_cast<WasmOpcode>(*pc_))); | 
|  | 1094       return val; | 
|  | 1095     } | 
|  | 1096     Value val = stack_.back(); | 
|  | 1097     stack_.pop_back(); | 
|  | 1098     return val; | 
|  | 1099   } | 
|  | 1100 | 
|  | 1101   Value PopUpTo(int stack_depth) { | 
|  | 1102     if (stack_depth == stack_.size()) { | 
|  | 1103       Value val = {pc_, nullptr, kAstStmt}; | 
|  | 1104       return val; | 
|  | 1105     } else { | 
|  | 1106       DCHECK_LE(stack_depth, static_cast<int>(stack_.size())); | 
|  | 1107       Value val = Pop(); | 
|  | 1108       stack_.resize(stack_depth); | 
|  | 1109       return val; | 
|  | 1110     } | 
| 924   } | 1111   } | 
| 925 | 1112 | 
| 926   int baserel(const byte* ptr) { | 1113   int baserel(const byte* ptr) { | 
| 927     return base_ ? static_cast<int>(ptr - base_) : 0; | 1114     return base_ ? static_cast<int>(ptr - base_) : 0; | 
| 928   } | 1115   } | 
| 929 | 1116 | 
| 930   int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); } | 1117   int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); } | 
| 931 | 1118 | 
| 932   void Reduce(Production* p) { | 1119   void BreakTo(Control* block, Value& val) { | 
| 933     WasmOpcode opcode = p->opcode(); | 1120     DCHECK(!block->is_if()); | 
| 934     TRACE("-----reduce module+%-6d %s func+%d: 0x%02x %s\n", baserel(p->pc()), | 1121     if (block->is_loop()) { | 
| 935           indentation(), startrel(p->pc()), opcode, |  | 
| 936           WasmOpcodes::OpcodeName(opcode)); |  | 
| 937     FunctionSig* sig = WasmOpcodes::Signature(opcode); |  | 
| 938     if (sig) { |  | 
| 939       // A simple expression with a fixed signature. |  | 
| 940       TypeCheckLast(p, sig->GetParam(p->index - 1)); |  | 
| 941       if (p->done() && build()) { |  | 
| 942         if (sig->parameter_count() == 2) { |  | 
| 943           p->tree->node = builder_->Binop(opcode, p->tree->children[0]->node, |  | 
| 944                                           p->tree->children[1]->node); |  | 
| 945         } else if (sig->parameter_count() == 1) { |  | 
| 946           p->tree->node = builder_->Unop(opcode, p->tree->children[0]->node); |  | 
| 947         } else { |  | 
| 948           UNREACHABLE(); |  | 
| 949         } |  | 
| 950       } |  | 
| 951       return; |  | 
| 952     } |  | 
| 953 |  | 
| 954     switch (opcode) { |  | 
| 955       case kExprBlock: { |  | 
| 956         if (p->done()) { |  | 
| 957           Block* last = &blocks_.back(); |  | 
| 958           DCHECK_EQ(stack_.size() - 1, last->stack_depth); |  | 
| 959           // fallthrough with the last expression. |  | 
| 960           ReduceBreakToExprBlock(p, last); |  | 
| 961           SetEnv("block:end", last->ssa_env); |  | 
| 962           blocks_.pop_back(); |  | 
| 963         } |  | 
| 964         break; |  | 
| 965       } |  | 
| 966       case kExprLoop: { |  | 
| 967         if (p->done()) { |  | 
| 968           // Pop the continue environment. |  | 
| 969           blocks_.pop_back(); |  | 
| 970           // Get the break environment. |  | 
| 971           Block* last = &blocks_.back(); |  | 
| 972           DCHECK_EQ(stack_.size() - 1, last->stack_depth); |  | 
| 973           // fallthrough with the last expression. |  | 
| 974           ReduceBreakToExprBlock(p, last); |  | 
| 975           SetEnv("loop:end", last->ssa_env); |  | 
| 976           blocks_.pop_back(); |  | 
| 977         } |  | 
| 978         break; |  | 
| 979       } |  | 
| 980       case kExprIf: { |  | 
| 981         if (p->index == 1) { |  | 
| 982           // Condition done. Split environment for true branch. |  | 
| 983           TypeCheckLast(p, kAstI32); |  | 
| 984           SsaEnv* false_env = ssa_env_; |  | 
| 985           SsaEnv* true_env = Split(ssa_env_); |  | 
| 986           ifs_.push_back({nullptr, false_env, nullptr}); |  | 
| 987           BUILD(Branch, p->last()->node, &true_env->control, |  | 
| 988                 &false_env->control); |  | 
| 989           SetEnv("if:true", true_env); |  | 
| 990         } else if (p->index == 2) { |  | 
| 991           // True block done. Merge true and false environments. |  | 
| 992           IfEnv* env = &ifs_.back(); |  | 
| 993           SsaEnv* merge = env->merge_env; |  | 
| 994           if (merge->go()) { |  | 
| 995             merge->state = SsaEnv::kReached; |  | 
| 996             Goto(ssa_env_, merge); |  | 
| 997           } |  | 
| 998           SetEnv("if:merge", merge); |  | 
| 999           ifs_.pop_back(); |  | 
| 1000         } |  | 
| 1001         break; |  | 
| 1002       } |  | 
| 1003       case kExprIfElse: { |  | 
| 1004         if (p->index == 1) { |  | 
| 1005           // Condition done. Split environment for true and false branches. |  | 
| 1006           TypeCheckLast(p, kAstI32); |  | 
| 1007           SsaEnv* merge_env = ssa_env_; |  | 
| 1008           TFNode* if_true = nullptr; |  | 
| 1009           TFNode* if_false = nullptr; |  | 
| 1010           BUILD(Branch, p->last()->node, &if_true, &if_false); |  | 
| 1011           SsaEnv* false_env = Split(ssa_env_); |  | 
| 1012           SsaEnv* true_env = Steal(ssa_env_); |  | 
| 1013           false_env->control = if_false; |  | 
| 1014           true_env->control = if_true; |  | 
| 1015           ifs_.push_back({false_env, merge_env, nullptr}); |  | 
| 1016           SetEnv("if_else:true", true_env); |  | 
| 1017         } else if (p->index == 2) { |  | 
| 1018           // True expr done. |  | 
| 1019           IfEnv* env = &ifs_.back(); |  | 
| 1020           MergeIntoProduction(p, env->merge_env, p->last()); |  | 
| 1021           // Switch to environment for false branch. |  | 
| 1022           SsaEnv* false_env = ifs_.back().false_env; |  | 
| 1023           SetEnv("if_else:false", false_env); |  | 
| 1024         } else if (p->index == 3) { |  | 
| 1025           // False expr done. |  | 
| 1026           IfEnv* env = &ifs_.back(); |  | 
| 1027           MergeIntoProduction(p, env->merge_env, p->last()); |  | 
| 1028           SetEnv("if_else:merge", env->merge_env); |  | 
| 1029           ifs_.pop_back(); |  | 
| 1030         } |  | 
| 1031         break; |  | 
| 1032       } |  | 
| 1033       case kExprSelect: { |  | 
| 1034         if (p->index == 1) { |  | 
| 1035           // True expression done. |  | 
| 1036           p->tree->type = p->last()->type; |  | 
| 1037           if (p->tree->type == kAstStmt) { |  | 
| 1038             error(p->pc(), p->tree->children[1]->pc, |  | 
| 1039                   "select operand should be expression"); |  | 
| 1040           } |  | 
| 1041         } else if (p->index == 2) { |  | 
| 1042           // False expression done. |  | 
| 1043           TypeCheckLast(p, p->tree->type); |  | 
| 1044         } else { |  | 
| 1045           // Condition done. |  | 
| 1046           DCHECK(p->done()); |  | 
| 1047           TypeCheckLast(p, kAstI32); |  | 
| 1048           if (build()) { |  | 
| 1049             TFNode* controls[2]; |  | 
| 1050             builder_->Branch(p->tree->children[2]->node, &controls[0], |  | 
| 1051                              &controls[1]); |  | 
| 1052             TFNode* merge = builder_->Merge(2, controls); |  | 
| 1053             TFNode* vals[2] = {p->tree->children[0]->node, |  | 
| 1054                                p->tree->children[1]->node}; |  | 
| 1055             TFNode* phi = builder_->Phi(p->tree->type, 2, vals, merge); |  | 
| 1056             p->tree->node = phi; |  | 
| 1057             ssa_env_->control = merge; |  | 
| 1058           } |  | 
| 1059         } |  | 
| 1060         break; |  | 
| 1061       } |  | 
| 1062       case kExprBr: { |  | 
| 1063         BreakDepthOperand operand(this, p->pc()); |  | 
| 1064         CHECK(Validate(p->pc(), operand, blocks_)); |  | 
| 1065         ReduceBreakToExprBlock(p, operand.target); |  | 
| 1066         break; |  | 
| 1067       } |  | 
| 1068       case kExprBrIf: { |  | 
| 1069         if (p->done()) { |  | 
| 1070           TypeCheckLast(p, kAstI32); |  | 
| 1071           BreakDepthOperand operand(this, p->pc()); |  | 
| 1072           CHECK(Validate(p->pc(), operand, blocks_)); |  | 
| 1073           SsaEnv* fenv = ssa_env_; |  | 
| 1074           SsaEnv* tenv = Split(fenv); |  | 
| 1075           BUILD(Branch, p->tree->children[1]->node, &tenv->control, |  | 
| 1076                 &fenv->control); |  | 
| 1077           ssa_env_ = tenv; |  | 
| 1078           ReduceBreakToExprBlock(p, operand.target, p->tree->children[0]); |  | 
| 1079           ssa_env_ = fenv; |  | 
| 1080         } |  | 
| 1081         break; |  | 
| 1082       } |  | 
| 1083       case kExprBrTable: { |  | 
| 1084         if (p->index == 1) { |  | 
| 1085           // Switch key finished. |  | 
| 1086           TypeCheckLast(p, kAstI32); |  | 
| 1087           if (failed()) break; |  | 
| 1088 |  | 
| 1089           BranchTableOperand operand(this, p->pc()); |  | 
| 1090           DCHECK(Validate(p->pc(), operand, blocks_.size())); |  | 
| 1091 |  | 
| 1092           // Build a switch only if it has more than just a default target. |  | 
| 1093           bool build_switch = operand.table_count > 0; |  | 
| 1094           TFNode* sw = nullptr; |  | 
| 1095           if (build_switch) { |  | 
| 1096             sw = BUILD(Switch, operand.table_count + 1, p->last()->node); |  | 
| 1097           } |  | 
| 1098 |  | 
| 1099           // Process the targets of the break table. |  | 
| 1100           SsaEnv* prev = ssa_env_; |  | 
| 1101           SsaEnv* copy = Steal(prev); |  | 
| 1102           for (uint32_t i = 0; i < operand.table_count + 1; i++) { |  | 
| 1103             uint32_t target = operand.read_entry(this, i); |  | 
| 1104             SsaEnv* env = copy; |  | 
| 1105             if (build_switch) { |  | 
| 1106               ssa_env_ = env = Split(env); |  | 
| 1107               env->control = i == operand.table_count ? BUILD(IfDefault, sw) |  | 
| 1108                                                       : BUILD(IfValue, i, sw); |  | 
| 1109             } |  | 
| 1110             SsaEnv* tenv = blocks_[blocks_.size() - target - 1].ssa_env; |  | 
| 1111             Goto(env, tenv); |  | 
| 1112           } |  | 
| 1113           ssa_env_ = prev; |  | 
| 1114         } |  | 
| 1115         break; |  | 
| 1116       } |  | 
| 1117       case kExprReturn: { |  | 
| 1118         TypeCheckLast(p, sig_->GetReturn(p->index - 1)); |  | 
| 1119         if (p->done()) { |  | 
| 1120           if (build()) { |  | 
| 1121             int count = p->tree->count; |  | 
| 1122             TFNode** buffer = builder_->Buffer(count); |  | 
| 1123             for (int i = 0; i < count; i++) { |  | 
| 1124               buffer[i] = p->tree->children[i]->node; |  | 
| 1125             } |  | 
| 1126             BUILD(Return, count, buffer); |  | 
| 1127           } |  | 
| 1128           ssa_env_->Kill(SsaEnv::kControlEnd); |  | 
| 1129         } |  | 
| 1130         break; |  | 
| 1131       } |  | 
| 1132       case kExprSetLocal: { |  | 
| 1133         LocalIndexOperand operand(this, p->pc()); |  | 
| 1134         CHECK(Validate(p->pc(), operand)); |  | 
| 1135         Tree* val = p->last(); |  | 
| 1136         if (operand.type == val->type) { |  | 
| 1137           if (build()) ssa_env_->locals[operand.index] = val->node; |  | 
| 1138           p->tree->node = val->node; |  | 
| 1139         } else { |  | 
| 1140           error(p->pc(), val->pc, "Typecheck failed in SetLocal"); |  | 
| 1141         } |  | 
| 1142         break; |  | 
| 1143       } |  | 
| 1144       case kExprStoreGlobal: { |  | 
| 1145         GlobalIndexOperand operand(this, p->pc()); |  | 
| 1146         CHECK(Validate(p->pc(), operand)); |  | 
| 1147         Tree* val = p->last(); |  | 
| 1148         if (operand.type == val->type) { |  | 
| 1149           BUILD(StoreGlobal, operand.index, val->node); |  | 
| 1150           p->tree->node = val->node; |  | 
| 1151         } else { |  | 
| 1152           error(p->pc(), val->pc, "Typecheck failed in StoreGlobal"); |  | 
| 1153         } |  | 
| 1154         break; |  | 
| 1155       } |  | 
| 1156 |  | 
| 1157       case kExprI32LoadMem8S: |  | 
| 1158         return ReduceLoadMem(p, kAstI32, MachineType::Int8()); |  | 
| 1159       case kExprI32LoadMem8U: |  | 
| 1160         return ReduceLoadMem(p, kAstI32, MachineType::Uint8()); |  | 
| 1161       case kExprI32LoadMem16S: |  | 
| 1162         return ReduceLoadMem(p, kAstI32, MachineType::Int16()); |  | 
| 1163       case kExprI32LoadMem16U: |  | 
| 1164         return ReduceLoadMem(p, kAstI32, MachineType::Uint16()); |  | 
| 1165       case kExprI32LoadMem: |  | 
| 1166         return ReduceLoadMem(p, kAstI32, MachineType::Int32()); |  | 
| 1167 |  | 
| 1168       case kExprI64LoadMem8S: |  | 
| 1169         return ReduceLoadMem(p, kAstI64, MachineType::Int8()); |  | 
| 1170       case kExprI64LoadMem8U: |  | 
| 1171         return ReduceLoadMem(p, kAstI64, MachineType::Uint8()); |  | 
| 1172       case kExprI64LoadMem16S: |  | 
| 1173         return ReduceLoadMem(p, kAstI64, MachineType::Int16()); |  | 
| 1174       case kExprI64LoadMem16U: |  | 
| 1175         return ReduceLoadMem(p, kAstI64, MachineType::Uint16()); |  | 
| 1176       case kExprI64LoadMem32S: |  | 
| 1177         return ReduceLoadMem(p, kAstI64, MachineType::Int32()); |  | 
| 1178       case kExprI64LoadMem32U: |  | 
| 1179         return ReduceLoadMem(p, kAstI64, MachineType::Uint32()); |  | 
| 1180       case kExprI64LoadMem: |  | 
| 1181         return ReduceLoadMem(p, kAstI64, MachineType::Int64()); |  | 
| 1182 |  | 
| 1183       case kExprF32LoadMem: |  | 
| 1184         return ReduceLoadMem(p, kAstF32, MachineType::Float32()); |  | 
| 1185 |  | 
| 1186       case kExprF64LoadMem: |  | 
| 1187         return ReduceLoadMem(p, kAstF64, MachineType::Float64()); |  | 
| 1188 |  | 
| 1189       case kExprI32StoreMem8: |  | 
| 1190         return ReduceStoreMem(p, kAstI32, MachineType::Int8()); |  | 
| 1191       case kExprI32StoreMem16: |  | 
| 1192         return ReduceStoreMem(p, kAstI32, MachineType::Int16()); |  | 
| 1193       case kExprI32StoreMem: |  | 
| 1194         return ReduceStoreMem(p, kAstI32, MachineType::Int32()); |  | 
| 1195 |  | 
| 1196       case kExprI64StoreMem8: |  | 
| 1197         return ReduceStoreMem(p, kAstI64, MachineType::Int8()); |  | 
| 1198       case kExprI64StoreMem16: |  | 
| 1199         return ReduceStoreMem(p, kAstI64, MachineType::Int16()); |  | 
| 1200       case kExprI64StoreMem32: |  | 
| 1201         return ReduceStoreMem(p, kAstI64, MachineType::Int32()); |  | 
| 1202       case kExprI64StoreMem: |  | 
| 1203         return ReduceStoreMem(p, kAstI64, MachineType::Int64()); |  | 
| 1204 |  | 
| 1205       case kExprF32StoreMem: |  | 
| 1206         return ReduceStoreMem(p, kAstF32, MachineType::Float32()); |  | 
| 1207 |  | 
| 1208       case kExprF64StoreMem: |  | 
| 1209         return ReduceStoreMem(p, kAstF64, MachineType::Float64()); |  | 
| 1210 |  | 
| 1211       case kExprGrowMemory: |  | 
| 1212         TypeCheckLast(p, kAstI32); |  | 
| 1213         // TODO(titzer): build node for GrowMemory |  | 
| 1214         p->tree->node = BUILD(Int32Constant, 0); |  | 
| 1215         return; |  | 
| 1216 |  | 
| 1217       case kExprCallFunction: { |  | 
| 1218         FunctionIndexOperand operand(this, p->pc()); |  | 
| 1219         CHECK(Validate(p->pc(), operand)); |  | 
| 1220         if (p->index > 0) { |  | 
| 1221           TypeCheckLast(p, operand.sig->GetParam(p->index - 1)); |  | 
| 1222         } |  | 
| 1223         if (p->done() && build()) { |  | 
| 1224           uint32_t count = p->tree->count + 1; |  | 
| 1225           TFNode** buffer = builder_->Buffer(count); |  | 
| 1226           buffer[0] = nullptr;  // reserved for code object. |  | 
| 1227           for (uint32_t i = 1; i < count; i++) { |  | 
| 1228             buffer[i] = p->tree->children[i - 1]->node; |  | 
| 1229           } |  | 
| 1230           p->tree->node = builder_->CallDirect(operand.index, buffer); |  | 
| 1231         } |  | 
| 1232         break; |  | 
| 1233       } |  | 
| 1234       case kExprCallIndirect: { |  | 
| 1235         SignatureIndexOperand operand(this, p->pc()); |  | 
| 1236         CHECK(Validate(p->pc(), operand)); |  | 
| 1237         if (p->index == 1) { |  | 
| 1238           TypeCheckLast(p, kAstI32); |  | 
| 1239         } else { |  | 
| 1240           TypeCheckLast(p, operand.sig->GetParam(p->index - 2)); |  | 
| 1241         } |  | 
| 1242         if (p->done() && build()) { |  | 
| 1243           uint32_t count = p->tree->count; |  | 
| 1244           TFNode** buffer = builder_->Buffer(count); |  | 
| 1245           for (uint32_t i = 0; i < count; i++) { |  | 
| 1246             buffer[i] = p->tree->children[i]->node; |  | 
| 1247           } |  | 
| 1248           p->tree->node = builder_->CallIndirect(operand.index, buffer); |  | 
| 1249         } |  | 
| 1250         break; |  | 
| 1251       } |  | 
| 1252       case kExprCallImport: { |  | 
| 1253         ImportIndexOperand operand(this, p->pc()); |  | 
| 1254         CHECK(Validate(p->pc(), operand)); |  | 
| 1255         if (p->index > 0) { |  | 
| 1256           TypeCheckLast(p, operand.sig->GetParam(p->index - 1)); |  | 
| 1257         } |  | 
| 1258         if (p->done() && build()) { |  | 
| 1259           uint32_t count = p->tree->count + 1; |  | 
| 1260           TFNode** buffer = builder_->Buffer(count); |  | 
| 1261           buffer[0] = nullptr;  // reserved for code object. |  | 
| 1262           for (uint32_t i = 1; i < count; i++) { |  | 
| 1263             buffer[i] = p->tree->children[i - 1]->node; |  | 
| 1264           } |  | 
| 1265           p->tree->node = builder_->CallImport(operand.index, buffer); |  | 
| 1266         } |  | 
| 1267         break; |  | 
| 1268       } |  | 
| 1269       default: |  | 
| 1270         break; |  | 
| 1271     } |  | 
| 1272   } |  | 
| 1273 |  | 
| 1274   void ReduceBreakToExprBlock(Production* p, Block* block) { |  | 
| 1275     ReduceBreakToExprBlock(p, block, p->tree->count > 0 ? p->last() : nullptr); |  | 
| 1276   } |  | 
| 1277 |  | 
| 1278   void ReduceBreakToExprBlock(Production* p, Block* block, Tree* val) { |  | 
| 1279     if (block->stack_depth < 0) { |  | 
| 1280       // This is the inner loop block, which does not have a value. | 1122       // This is the inner loop block, which does not have a value. | 
| 1281       Goto(ssa_env_, block->ssa_env); | 1123       Goto(ssa_env_, block->ssa_env); | 
| 1282     } else { | 1124     } else { | 
| 1283       // Merge the value into the production for the block. | 1125       // Merge the value into the production for the block. | 
| 1284       Production* bp = &stack_[block->stack_depth]; | 1126       MergeInto(block->ssa_env, &block->node, &block->type, val); | 
| 1285       MergeIntoProduction(bp, block->ssa_env, val); | 1127     } | 
| 1286     } | 1128   } | 
| 1287   } | 1129 | 
| 1288 | 1130   void MergeInto(SsaEnv* target, TFNode** node, LocalType* type, Value& val) { | 
| 1289   void MergeIntoProduction(Production* p, SsaEnv* target, Tree* expr) { |  | 
| 1290     if (!ssa_env_->go()) return; | 1131     if (!ssa_env_->go()) return; | 
|  | 1132     DCHECK_NE(kAstEnd, val.type); | 
| 1291 | 1133 | 
| 1292     bool first = target->state == SsaEnv::kUnreachable; | 1134     bool first = target->state == SsaEnv::kUnreachable; | 
| 1293     Goto(ssa_env_, target); | 1135     Goto(ssa_env_, target); | 
| 1294     if (expr == nullptr || expr->type == kAstEnd) return; |  | 
| 1295 | 1136 | 
| 1296     if (first) { | 1137     if (first) { | 
| 1297       // first merge to this environment; set the type and the node. | 1138       // first merge to this environment; set the type and the node. | 
| 1298       p->tree->type = expr->type; | 1139       *type = val.type; | 
| 1299       p->tree->node = expr->node; | 1140       *node = val.node; | 
|  | 1141     } else if (val.type == *type && val.type != kAstStmt) { | 
|  | 1142       // merge with the existing value for this block. | 
|  | 1143       *node = CreateOrMergeIntoPhi(*type, target->control, *node, val.node); | 
| 1300     } else { | 1144     } else { | 
| 1301       // merge with the existing value for this block. | 1145       // types don't match, or block is already a stmt. | 
| 1302       LocalType type = p->tree->type; | 1146       *type = kAstStmt; | 
| 1303       if (expr->type != type) { | 1147       *node = nullptr; | 
| 1304         type = kAstStmt; |  | 
| 1305         p->tree->type = kAstStmt; |  | 
| 1306         p->tree->node = nullptr; |  | 
| 1307       } else if (type != kAstStmt) { |  | 
| 1308         p->tree->node = CreateOrMergeIntoPhi(type, target->control, |  | 
| 1309                                              p->tree->node, expr->node); |  | 
| 1310       } |  | 
| 1311     } |  | 
| 1312   } |  | 
| 1313 |  | 
| 1314   void ReduceLoadMem(Production* p, LocalType type, MachineType mem_type) { |  | 
| 1315     DCHECK_EQ(1, p->index); |  | 
| 1316     TypeCheckLast(p, kAstI32);  // index |  | 
| 1317     if (build()) { |  | 
| 1318       MemoryAccessOperand operand(this, p->pc()); |  | 
| 1319       p->tree->node = |  | 
| 1320           builder_->LoadMem(type, mem_type, p->last()->node, operand.offset); |  | 
| 1321     } |  | 
| 1322   } |  | 
| 1323 |  | 
| 1324   void ReduceStoreMem(Production* p, LocalType type, MachineType mem_type) { |  | 
| 1325     if (p->index == 1) { |  | 
| 1326       TypeCheckLast(p, kAstI32);  // index |  | 
| 1327     } else { |  | 
| 1328       DCHECK_EQ(2, p->index); |  | 
| 1329       TypeCheckLast(p, type); |  | 
| 1330       if (build()) { |  | 
| 1331         MemoryAccessOperand operand(this, p->pc()); |  | 
| 1332         TFNode* val = p->tree->children[1]->node; |  | 
| 1333         builder_->StoreMem(mem_type, p->tree->children[0]->node, operand.offset, |  | 
| 1334                            val); |  | 
| 1335         p->tree->node = val; |  | 
| 1336       } |  | 
| 1337     } |  | 
| 1338   } |  | 
| 1339 |  | 
| 1340   void TypeCheckLast(Production* p, LocalType expected) { |  | 
| 1341     LocalType result = p->last()->type; |  | 
| 1342     if (result == expected) return; |  | 
| 1343     if (result == kAstEnd) return; |  | 
| 1344     if (expected != kAstStmt) { |  | 
| 1345       error(p->pc(), p->last()->pc, |  | 
| 1346             "%s[%d] expected type %s, found %s of type %s", |  | 
| 1347             WasmOpcodes::OpcodeName(p->opcode()), p->index - 1, |  | 
| 1348             WasmOpcodes::TypeName(expected), |  | 
| 1349             WasmOpcodes::OpcodeName(p->last()->opcode()), |  | 
| 1350             WasmOpcodes::TypeName(p->last()->type)); |  | 
| 1351     } | 1148     } | 
| 1352   } | 1149   } | 
| 1353 | 1150 | 
| 1354   void SetEnv(const char* reason, SsaEnv* env) { | 1151   void SetEnv(const char* reason, SsaEnv* env) { | 
| 1355 #if DEBUG | 1152 #if DEBUG | 
| 1356     TRACE("  env = %p, block depth = %d, reason = %s", static_cast<void*>(env), | 1153     if (FLAG_trace_wasm_decoder) { | 
| 1357           static_cast<int>(blocks_.size()), reason); | 1154       char state = 'X'; | 
| 1358     if (FLAG_trace_wasm_decoder && env && env->control) { | 1155       if (env) { | 
| 1359       TRACE(", control = "); | 1156         switch (env->state) { | 
| 1360       compiler::WasmGraphBuilder::PrintDebugName(env->control); | 1157           case SsaEnv::kReached: | 
| 1361     } | 1158             state = 'R'; | 
| 1362     TRACE("\n"); | 1159             break; | 
|  | 1160           case SsaEnv::kUnreachable: | 
|  | 1161             state = 'U'; | 
|  | 1162             break; | 
|  | 1163           case SsaEnv::kMerged: | 
|  | 1164             state = 'M'; | 
|  | 1165             break; | 
|  | 1166           case SsaEnv::kControlEnd: | 
|  | 1167             state = 'E'; | 
|  | 1168             break; | 
|  | 1169         } | 
|  | 1170       } | 
|  | 1171       PrintF("  env = %p, state = %c, reason = %s", static_cast<void*>(env), | 
|  | 1172              state, reason); | 
|  | 1173       if (env && env->control) { | 
|  | 1174         PrintF(", control = "); | 
|  | 1175         compiler::WasmGraphBuilder::PrintDebugName(env->control); | 
|  | 1176       } | 
|  | 1177       PrintF("\n"); | 
|  | 1178     } | 
| 1363 #endif | 1179 #endif | 
| 1364     ssa_env_ = env; | 1180     ssa_env_ = env; | 
| 1365     if (builder_) { | 1181     if (builder_) { | 
| 1366       builder_->set_control_ptr(&env->control); | 1182       builder_->set_control_ptr(&env->control); | 
| 1367       builder_->set_effect_ptr(&env->effect); | 1183       builder_->set_effect_ptr(&env->effect); | 
| 1368     } | 1184     } | 
| 1369   } | 1185   } | 
| 1370 | 1186 | 
| 1371   void Goto(SsaEnv* from, SsaEnv* to) { | 1187   void Goto(SsaEnv* from, SsaEnv* to) { | 
| 1372     DCHECK_NOT_NULL(to); | 1188     DCHECK_NOT_NULL(to); | 
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1486     } | 1302     } | 
| 1487   } | 1303   } | 
| 1488 | 1304 | 
| 1489   // Create a complete copy of the {from}. | 1305   // Create a complete copy of the {from}. | 
| 1490   SsaEnv* Split(SsaEnv* from) { | 1306   SsaEnv* Split(SsaEnv* from) { | 
| 1491     DCHECK_NOT_NULL(from); | 1307     DCHECK_NOT_NULL(from); | 
| 1492     SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv))); | 1308     SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv))); | 
| 1493     size_t size = sizeof(TFNode*) * EnvironmentCount(); | 1309     size_t size = sizeof(TFNode*) * EnvironmentCount(); | 
| 1494     result->control = from->control; | 1310     result->control = from->control; | 
| 1495     result->effect = from->effect; | 1311     result->effect = from->effect; | 
| 1496     result->state = from->state == SsaEnv::kUnreachable ? SsaEnv::kUnreachable |  | 
| 1497                                                         : SsaEnv::kReached; |  | 
| 1498 | 1312 | 
| 1499     if (from->go()) { | 1313     if (from->go()) { | 
| 1500       result->state = SsaEnv::kReached; | 1314       result->state = SsaEnv::kReached; | 
| 1501       result->locals = | 1315       result->locals = | 
| 1502           size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr; | 1316           size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr; | 
| 1503       memcpy(result->locals, from->locals, size); | 1317       memcpy(result->locals, from->locals, size); | 
| 1504     } else { | 1318     } else { | 
| 1505       result->state = SsaEnv::kUnreachable; | 1319       result->state = SsaEnv::kUnreachable; | 
| 1506       result->locals = nullptr; | 1320       result->locals = nullptr; | 
| 1507     } | 1321     } | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
| 1534   } | 1348   } | 
| 1535 | 1349 | 
| 1536   int EnvironmentCount() { | 1350   int EnvironmentCount() { | 
| 1537     if (builder_) return static_cast<int>(local_type_vec_.size()); | 1351     if (builder_) return static_cast<int>(local_type_vec_.size()); | 
| 1538     return 0;  // if we aren't building a graph, don't bother with SSA renaming. | 1352     return 0;  // if we aren't building a graph, don't bother with SSA renaming. | 
| 1539   } | 1353   } | 
| 1540 | 1354 | 
| 1541   virtual void onFirstError() { | 1355   virtual void onFirstError() { | 
| 1542     limit_ = start_;     // Terminate decoding loop. | 1356     limit_ = start_;     // Terminate decoding loop. | 
| 1543     builder_ = nullptr;  // Don't build any more nodes. | 1357     builder_ = nullptr;  // Don't build any more nodes. | 
| 1544 #if DEBUG | 1358     TRACE(" !%s\n", error_msg_.get()); | 
| 1545     PrintStackForDebugging(); |  | 
| 1546 #endif |  | 
| 1547   } | 1359   } | 
| 1548 |  | 
| 1549 #if DEBUG |  | 
| 1550   void PrintStackForDebugging() { PrintProduction(0); } |  | 
| 1551 |  | 
| 1552   void PrintProduction(size_t depth) { |  | 
| 1553     if (depth >= stack_.size()) return; |  | 
| 1554     Production* p = &stack_[depth]; |  | 
| 1555     for (size_t d = 0; d < depth; d++) PrintF("  "); |  | 
| 1556 |  | 
| 1557     PrintF("@%d %s [%d]\n", static_cast<int>(p->tree->pc - start_), |  | 
| 1558            WasmOpcodes::OpcodeName(p->opcode()), p->tree->count); |  | 
| 1559     for (int i = 0; i < p->index; i++) { |  | 
| 1560       Tree* child = p->tree->children[i]; |  | 
| 1561       for (size_t d = 0; d <= depth; d++) PrintF("  "); |  | 
| 1562       PrintF("@%d %s [%d]", static_cast<int>(child->pc - start_), |  | 
| 1563              WasmOpcodes::OpcodeName(child->opcode()), child->count); |  | 
| 1564       if (child->node) { |  | 
| 1565         PrintF(" => TF"); |  | 
| 1566         compiler::WasmGraphBuilder::PrintDebugName(child->node); |  | 
| 1567       } |  | 
| 1568       PrintF("\n"); |  | 
| 1569     } |  | 
| 1570     PrintProduction(depth + 1); |  | 
| 1571   } |  | 
| 1572 #endif |  | 
| 1573 |  | 
| 1574   BitVector* AnalyzeLoopAssignment(const byte* pc) { | 1360   BitVector* AnalyzeLoopAssignment(const byte* pc) { | 
| 1575     if (pc >= limit_) return nullptr; | 1361     if (pc >= limit_) return nullptr; | 
| 1576     if (*pc != kExprLoop) return nullptr; | 1362     if (*pc != kExprLoop) return nullptr; | 
| 1577 | 1363 | 
| 1578     BitVector* assigned = | 1364     BitVector* assigned = | 
| 1579         new (zone_) BitVector(static_cast<int>(total_locals_), zone_); | 1365         new (zone_) BitVector(static_cast<int>(local_type_vec_.size()), zone_); | 
| 1580     // Keep a stack to model the nesting of expressions. | 1366     int depth = 0; | 
| 1581     std::vector<int> arity_stack; |  | 
| 1582     arity_stack.push_back(OpcodeArity(pc)); |  | 
| 1583     pc += OpcodeLength(pc); |  | 
| 1584 |  | 
| 1585     // Iteratively process all AST nodes nested inside the loop. | 1367     // Iteratively process all AST nodes nested inside the loop. | 
| 1586     while (pc < limit_) { | 1368     while (pc_ < limit_) { | 
| 1587       WasmOpcode opcode = static_cast<WasmOpcode>(*pc); | 1369       WasmOpcode opcode = static_cast<WasmOpcode>(*pc_); | 
| 1588       int arity = 0; |  | 
| 1589       int length = 1; | 1370       int length = 1; | 
| 1590       int assigned_index = -1; | 1371       switch (opcode) { | 
| 1591       if (opcode == kExprSetLocal) { | 1372         case kExprLoop: | 
| 1592         LocalIndexOperand operand(this, pc); | 1373         case kExprIf: | 
| 1593         if (assigned->length() > 0 && | 1374         case kExprBlock: | 
| 1594             static_cast<int>(operand.index) < assigned->length()) { | 1375           depth++; | 
| 1595           // Unverified code might have an out-of-bounds index. | 1376           DCHECK_EQ(1, OpcodeLength(pc_)); | 
| 1596           // Ignore out-of-bounds indices, as the main verification will fail. | 1377           break; | 
| 1597           assigned->Add(operand.index); | 1378         case kExprSetLocal: { | 
| 1598           assigned_index = operand.index; | 1379           LocalIndexOperand operand(this, pc_); | 
|  | 1380           if (assigned->length() > 0 && | 
|  | 1381               static_cast<int>(operand.index) < assigned->length()) { | 
|  | 1382             // Unverified code might have an out-of-bounds index. | 
|  | 1383             assigned->Add(operand.index); | 
|  | 1384           } | 
|  | 1385           length = 1 + operand.length; | 
|  | 1386           break; | 
| 1599         } | 1387         } | 
| 1600         arity = 1; | 1388         case kExprEnd: | 
| 1601         length = 1 + operand.length; | 1389           depth--; | 
| 1602       } else { | 1390           break; | 
| 1603         arity = OpcodeArity(pc); | 1391         default: | 
| 1604         length = OpcodeLength(pc); | 1392           length = OpcodeLength(pc_); | 
|  | 1393           break; | 
| 1605       } | 1394       } | 
| 1606 | 1395       if (depth <= 0) break; | 
| 1607       TRACE("loop-assign module+%-6d %s func+%d: 0x%02x %s", baserel(pc), | 1396       pc_ += length; | 
| 1608             indentation(), startrel(pc), opcode, |  | 
| 1609             WasmOpcodes::OpcodeName(opcode)); |  | 
| 1610 |  | 
| 1611       if (assigned_index >= 0) { |  | 
| 1612         TRACE(" (assigned local #%d)\n", assigned_index); |  | 
| 1613       } else { |  | 
| 1614         TRACE("\n"); |  | 
| 1615       } |  | 
| 1616 |  | 
| 1617       pc += length; |  | 
| 1618       arity_stack.push_back(arity); |  | 
| 1619       while (arity_stack.back() == 0) { |  | 
| 1620         arity_stack.pop_back(); |  | 
| 1621         if (arity_stack.empty()) return assigned;  // reached end of loop |  | 
| 1622         arity_stack.back()--; |  | 
| 1623       } |  | 
| 1624     } | 1397     } | 
| 1625     return assigned; | 1398     return assigned; | 
| 1626   } | 1399   } | 
| 1627 }; | 1400 }; | 
| 1628 | 1401 | 
| 1629 std::vector<LocalType>* DecodeLocalDeclsForTesting(const byte* start, | 1402 std::vector<LocalType>* DecodeLocalDeclsForTesting(const byte* start, | 
| 1630                                                    const byte* end) { | 1403                                                    const byte* end) { | 
| 1631   Zone zone; | 1404   Zone zone; | 
| 1632   FunctionBody body = {nullptr, nullptr, nullptr, start, end}; | 1405   FunctionBody body = {nullptr, nullptr, nullptr, start, end}; | 
| 1633   SR_WasmDecoder decoder(&zone, nullptr, body); | 1406   SR_WasmDecoder decoder(&zone, nullptr, body); | 
| 1634   return decoder.DecodeLocalDeclsForTesting(); | 1407   return decoder.DecodeLocalDeclsForTesting(); | 
| 1635 } | 1408 } | 
| 1636 | 1409 | 
| 1637 TreeResult VerifyWasmCode(FunctionBody& body) { | 1410 TreeResult VerifyWasmCode(FunctionBody& body) { | 
| 1638   Zone zone; | 1411   Zone zone; | 
| 1639   SR_WasmDecoder decoder(&zone, nullptr, body); | 1412   SR_WasmDecoder decoder(&zone, nullptr, body); | 
| 1640   TreeResult result = decoder.Decode(); | 1413   decoder.Decode(); | 
| 1641   return result; | 1414   return decoder.toResult<Tree*>(nullptr); | 
| 1642 } | 1415 } | 
| 1643 | 1416 | 
| 1644 TreeResult BuildTFGraph(TFBuilder* builder, FunctionBody& body) { | 1417 TreeResult BuildTFGraph(TFBuilder* builder, FunctionBody& body) { | 
| 1645   Zone zone; | 1418   Zone zone; | 
| 1646   SR_WasmDecoder decoder(&zone, builder, body); | 1419   SR_WasmDecoder decoder(&zone, builder, body); | 
| 1647   TreeResult result = decoder.Decode(); | 1420   decoder.Decode(); | 
| 1648   return result; | 1421   return decoder.toResult<Tree*>(nullptr); | 
| 1649 } | 1422 } | 
| 1650 | 1423 | 
| 1651 | 1424 | 
| 1652 std::ostream& operator<<(std::ostream& os, const Tree& tree) { | 1425 std::ostream& operator<<(std::ostream& os, const Tree& tree) { | 
| 1653   if (tree.pc == nullptr) { | 1426   if (tree.pc == nullptr) { | 
| 1654     os << "null"; | 1427     os << "null"; | 
| 1655     return os; | 1428     return os; | 
| 1656   } | 1429   } | 
| 1657   PrintF("%s", WasmOpcodes::OpcodeName(tree.opcode())); | 1430   PrintF("%s", WasmOpcodes::OpcodeName(tree.opcode())); | 
| 1658   if (tree.count > 0) os << "("; | 1431   if (tree.count > 0) os << "("; | 
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1783 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, | 1556 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, | 
| 1784                                            const byte* start, const byte* end) { | 1557                                            const byte* start, const byte* end) { | 
| 1785   FunctionBody body = {nullptr, nullptr, nullptr, start, end}; | 1558   FunctionBody body = {nullptr, nullptr, nullptr, start, end}; | 
| 1786   SR_WasmDecoder decoder(zone, nullptr, body); | 1559   SR_WasmDecoder decoder(zone, nullptr, body); | 
| 1787   return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); | 1560   return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); | 
| 1788 } | 1561 } | 
| 1789 | 1562 | 
| 1790 }  // namespace wasm | 1563 }  // namespace wasm | 
| 1791 }  // namespace internal | 1564 }  // namespace internal | 
| 1792 }  // namespace v8 | 1565 }  // namespace v8 | 
| OLD | NEW | 
|---|