| 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/zone-containers.h" | 10 #include "src/zone/zone-containers.h" |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 } | 63 } |
| 64 }; | 64 }; |
| 65 | 65 |
| 66 // An entry on the value stack. | 66 // An entry on the value stack. |
| 67 struct Value { | 67 struct Value { |
| 68 const byte* pc; | 68 const byte* pc; |
| 69 TFNode* node; | 69 TFNode* node; |
| 70 LocalType type; | 70 LocalType type; |
| 71 }; | 71 }; |
| 72 | 72 |
| 73 struct TryInfo : public ZoneObject { | 73 struct Control; |
| 74 SsaEnv* catch_env; | |
| 75 TFNode* exception; | |
| 76 | |
| 77 explicit TryInfo(SsaEnv* c) : catch_env(c), exception(nullptr) {} | |
| 78 }; | |
| 79 | 74 |
| 80 struct MergeValues { | 75 struct MergeValues { |
| 81 uint32_t arity; | 76 uint32_t arity; |
| 82 union { | 77 union { |
| 83 Value* array; | 78 Value* array; |
| 84 Value first; | 79 Value first; |
| 85 } vals; // Either multiple values or a single value. | 80 } vals; // Either multiple values or a single value. |
| 86 | 81 |
| 87 Value& first() { | 82 Value& first() { |
| 88 DCHECK_GT(arity, 0u); | 83 DCHECK_GT(arity, 0u); |
| 89 return arity == 1 ? vals.first : vals.array[0]; | 84 return arity == 1 ? vals.first : vals.array[0]; |
| 90 } | 85 } |
| 91 }; | 86 }; |
| 92 | 87 |
| 88 // IncomingBranch is used by exception handling code for managing finally's. |
| 89 struct IncomingBranch { |
| 90 int32_t token_value; |
| 91 Control* target; |
| 92 MergeValues merge; |
| 93 }; |
| 94 |
| 93 static Value* NO_VALUE = nullptr; | 95 static Value* NO_VALUE = nullptr; |
| 94 | 96 |
| 95 enum ControlKind { kControlIf, kControlBlock, kControlLoop, kControlTry }; | 97 enum ControlKind { kControlIf, kControlBlock, kControlLoop, kControlTry }; |
| 96 | 98 |
| 97 // An entry on the control stack (i.e. if, block, loop). | 99 // An entry on the control stack (i.e. if, block, loop). |
| 98 struct Control { | 100 struct Control { |
| 99 const byte* pc; | 101 const byte* pc; |
| 100 ControlKind kind; | 102 ControlKind kind; |
| 101 int stack_depth; // stack height at the beginning of the construct. | 103 int stack_depth; // stack height at the beginning of the construct. |
| 102 SsaEnv* end_env; // end environment for the construct. | 104 SsaEnv* end_env; // end environment for the construct. |
| 103 SsaEnv* false_env; // false environment (only for if). | 105 SsaEnv* false_env; // false environment (only for if). |
| 104 TryInfo* try_info; // Information used for compiling try statements. | 106 SsaEnv* catch_env; // catch environment (only for try). |
| 105 int32_t previous_catch; // The previous Control (on the stack) with a catch. | |
| 106 | 107 |
| 107 // Values merged into the end of this control construct. | 108 // Values merged into the end of this control construct. |
| 108 MergeValues merge; | 109 MergeValues merge; |
| 109 | 110 |
| 110 inline bool is_if() const { return kind == kControlIf; } | 111 inline bool is_if() const { return kind == kControlIf; } |
| 111 inline bool is_block() const { return kind == kControlBlock; } | 112 inline bool is_block() const { return kind == kControlBlock; } |
| 112 inline bool is_loop() const { return kind == kControlLoop; } | 113 inline bool is_loop() const { return kind == kControlLoop; } |
| 113 inline bool is_try() const { return kind == kControlTry; } | 114 inline bool is_try() const { return kind == kControlTry; } |
| 114 | 115 |
| 115 // Named constructors. | 116 // Named constructors. |
| 116 static Control Block(const byte* pc, int stack_depth, SsaEnv* end_env, | 117 static Control Block(const byte* pc, int stack_depth, SsaEnv* end_env) { |
| 117 int32_t previous_catch) { | |
| 118 return {pc, kControlBlock, stack_depth, end_env, | 118 return {pc, kControlBlock, stack_depth, end_env, |
| 119 nullptr, nullptr, previous_catch, {0, {NO_VALUE}}}; | 119 nullptr, nullptr, {0, {NO_VALUE}}}; |
| 120 } | 120 } |
| 121 | 121 |
| 122 static Control If(const byte* pc, int stack_depth, SsaEnv* end_env, | 122 static Control If(const byte* pc, int stack_depth, SsaEnv* end_env, |
| 123 SsaEnv* false_env, int32_t previous_catch) { | 123 SsaEnv* false_env) { |
| 124 return {pc, kControlIf, stack_depth, end_env, | 124 return {pc, kControlIf, stack_depth, end_env, |
| 125 false_env, nullptr, previous_catch, {0, {NO_VALUE}}}; | 125 false_env, nullptr, {0, {NO_VALUE}}}; |
| 126 } | 126 } |
| 127 | 127 |
| 128 static Control Loop(const byte* pc, int stack_depth, SsaEnv* end_env, | 128 static Control Loop(const byte* pc, int stack_depth, SsaEnv* end_env) { |
| 129 int32_t previous_catch) { | |
| 130 return {pc, kControlLoop, stack_depth, end_env, | 129 return {pc, kControlLoop, stack_depth, end_env, |
| 131 nullptr, nullptr, previous_catch, {0, {NO_VALUE}}}; | 130 nullptr, nullptr, {0, {NO_VALUE}}}; |
| 132 } | 131 } |
| 133 | 132 |
| 134 static Control Try(const byte* pc, int stack_depth, SsaEnv* end_env, | 133 static Control Try(const byte* pc, int stack_depth, SsaEnv* end_env, |
| 135 Zone* zone, SsaEnv* catch_env, int32_t previous_catch) { | 134 SsaEnv* catch_env) { |
| 136 DCHECK_NOT_NULL(catch_env); | |
| 137 TryInfo* try_info = new (zone) TryInfo(catch_env); | |
| 138 return {pc, kControlTry, stack_depth, end_env, | 135 return {pc, kControlTry, stack_depth, end_env, |
| 139 nullptr, try_info, previous_catch, {0, {NO_VALUE}}}; | 136 nullptr, catch_env, {0, {NO_VALUE}}}; |
| 140 } | 137 } |
| 141 }; | 138 }; |
| 142 | 139 |
| 143 // Macros that build nodes only if there is a graph and the current SSA | 140 // Macros that build nodes only if there is a graph and the current SSA |
| 144 // environment is reachable from start. This avoids problems with malformed | 141 // environment is reachable from start. This avoids problems with malformed |
| 145 // TF graphs when decoding inputs that have unreachable code. | 142 // TF graphs when decoding inputs that have unreachable code. |
| 146 #define BUILD(func, ...) \ | 143 #define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr) |
| 147 (build() ? CheckForException(builder_->func(__VA_ARGS__)) : nullptr) | 144 #define BUILD0(func) (build() ? builder_->func() : nullptr) |
| 148 #define BUILD0(func) (build() ? CheckForException(builder_->func()) : nullptr) | |
| 149 | 145 |
| 150 // Generic Wasm bytecode decoder with utilities for decoding operands, | 146 // Generic Wasm bytecode decoder with utilities for decoding operands, |
| 151 // lengths, etc. | 147 // lengths, etc. |
| 152 class WasmDecoder : public Decoder { | 148 class WasmDecoder : public Decoder { |
| 153 public: | 149 public: |
| 154 WasmDecoder(ModuleEnv* module, FunctionSig* sig, const byte* start, | 150 WasmDecoder(ModuleEnv* module, FunctionSig* sig, const byte* start, |
| 155 const byte* end) | 151 const byte* end) |
| 156 : Decoder(start, end), | 152 : Decoder(start, end), |
| 157 module_(module), | 153 module_(module), |
| 158 sig_(sig), | 154 sig_(sig), |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 case kExprF32Const: | 296 case kExprF32Const: |
| 301 return 5; | 297 return 5; |
| 302 case kExprF64Const: | 298 case kExprF64Const: |
| 303 return 9; | 299 return 9; |
| 304 default: | 300 default: |
| 305 return 1; | 301 return 1; |
| 306 } | 302 } |
| 307 } | 303 } |
| 308 }; | 304 }; |
| 309 | 305 |
| 310 static const int32_t kNullCatch = -1; | |
| 311 | |
| 312 // The full WASM decoder for bytecode. Both verifies bytecode and generates | 306 // The full WASM decoder for bytecode. Both verifies bytecode and generates |
| 313 // a TurboFan IR graph. | 307 // a TurboFan IR graph. |
| 314 class WasmFullDecoder : public WasmDecoder { | 308 class WasmFullDecoder : public WasmDecoder { |
| 315 public: | 309 public: |
| 316 WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body) | 310 WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body) |
| 317 : WasmDecoder(body.module, body.sig, body.start, body.end), | 311 : WasmDecoder(body.module, body.sig, body.start, body.end), |
| 318 zone_(zone), | 312 zone_(zone), |
| 319 builder_(builder), | 313 builder_(builder), |
| 320 base_(body.base), | 314 base_(body.base), |
| 321 local_type_vec_(zone), | 315 local_type_vec_(zone), |
| 322 stack_(zone), | 316 stack_(zone), |
| 323 control_(zone), | 317 control_(zone), |
| 324 last_end_found_(false), | 318 last_end_found_(false) { |
| 325 current_catch_(kNullCatch) { | |
| 326 local_types_ = &local_type_vec_; | 319 local_types_ = &local_type_vec_; |
| 327 } | 320 } |
| 328 | 321 |
| 329 bool Decode() { | 322 bool Decode() { |
| 330 base::ElapsedTimer decode_timer; | 323 base::ElapsedTimer decode_timer; |
| 331 if (FLAG_trace_wasm_decode_time) { | 324 if (FLAG_trace_wasm_decode_time) { |
| 332 decode_timer.Start(); | 325 decode_timer.Start(); |
| 333 } | 326 } |
| 334 stack_.clear(); | 327 stack_.clear(); |
| 335 control_.clear(); | 328 control_.clear(); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 TFBuilder* builder_; | 434 TFBuilder* builder_; |
| 442 const byte* base_; | 435 const byte* base_; |
| 443 | 436 |
| 444 SsaEnv* ssa_env_; | 437 SsaEnv* ssa_env_; |
| 445 | 438 |
| 446 ZoneVector<LocalType> local_type_vec_; // types of local variables. | 439 ZoneVector<LocalType> local_type_vec_; // types of local variables. |
| 447 ZoneVector<Value> stack_; // stack of values. | 440 ZoneVector<Value> stack_; // stack of values. |
| 448 ZoneVector<Control> control_; // stack of blocks, loops, and ifs. | 441 ZoneVector<Control> control_; // stack of blocks, loops, and ifs. |
| 449 bool last_end_found_; | 442 bool last_end_found_; |
| 450 | 443 |
| 451 int32_t current_catch_; | |
| 452 | |
| 453 TryInfo* current_try_info() { return control_[current_catch_].try_info; } | |
| 454 | |
| 455 inline bool build() { return builder_ && ssa_env_->go(); } | 444 inline bool build() { return builder_ && ssa_env_->go(); } |
| 456 | 445 |
| 457 void InitSsaEnv() { | 446 void InitSsaEnv() { |
| 458 TFNode* start = nullptr; | 447 TFNode* start = nullptr; |
| 459 SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv))); | 448 SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv))); |
| 460 size_t size = sizeof(TFNode*) * EnvironmentCount(); | 449 size_t size = sizeof(TFNode*) * EnvironmentCount(); |
| 461 ssa_env->state = SsaEnv::kReached; | 450 ssa_env->state = SsaEnv::kReached; |
| 462 ssa_env->locals = | 451 ssa_env->locals = |
| 463 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr; | 452 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr; |
| 464 | 453 |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 621 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); | 610 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); |
| 622 Value value = Pop(0, kAstI32); | 611 Value value = Pop(0, kAstI32); |
| 623 BUILD(Throw, value.node); | 612 BUILD(Throw, value.node); |
| 624 break; | 613 break; |
| 625 } | 614 } |
| 626 case kExprTry: { | 615 case kExprTry: { |
| 627 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); | 616 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); |
| 628 BlockTypeOperand operand(this, pc_); | 617 BlockTypeOperand operand(this, pc_); |
| 629 SsaEnv* outer_env = ssa_env_; | 618 SsaEnv* outer_env = ssa_env_; |
| 630 SsaEnv* try_env = Steal(outer_env); | 619 SsaEnv* try_env = Steal(outer_env); |
| 631 SsaEnv* catch_env = UnreachableEnv(); | 620 SsaEnv* catch_env = Split(try_env); |
| 632 PushTry(outer_env, catch_env); | 621 PushTry(outer_env, catch_env); |
| 633 SetEnv("try_catch:start", try_env); | 622 SetEnv("try_catch:start", try_env); |
| 634 SetBlockType(&control_.back(), operand); | 623 SetBlockType(&control_.back(), operand); |
| 635 len = 1 + operand.length; | 624 len = 1 + operand.length; |
| 636 break; | 625 break; |
| 637 } | 626 } |
| 638 case kExprCatch: { | 627 case kExprCatch: { |
| 639 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); | 628 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); |
| 640 LocalIndexOperand operand(this, pc_); | 629 LocalIndexOperand operand(this, pc_); |
| 641 len = 1 + operand.length; | 630 len = 1 + operand.length; |
| 642 | 631 |
| 643 if (control_.empty()) { | 632 if (control_.empty()) { |
| 644 error("catch does not match any try"); | 633 error("catch does not match any try"); |
| 645 break; | 634 break; |
| 646 } | 635 } |
| 647 | 636 |
| 648 Control* c = &control_.back(); | 637 Control* c = &control_.back(); |
| 649 if (!c->is_try()) { | 638 if (!c->is_try()) { |
| 650 error("catch does not match any try"); | 639 error("catch does not match any try"); |
| 651 break; | 640 break; |
| 652 } | 641 } |
| 653 | 642 |
| 654 if (c->try_info->catch_env == nullptr) { | 643 if (c->catch_env == nullptr) { |
| 655 error(pc_, "catch already present for try with catch"); | 644 error("catch already present for try with catch"); |
| 656 break; | 645 break; |
| 657 } | 646 } |
| 658 | 647 |
| 659 if (ssa_env_->go()) { | 648 Goto(ssa_env_, c->end_env); |
| 660 MergeValuesInto(c); | |
| 661 } | |
| 662 stack_.resize(c->stack_depth); | |
| 663 | 649 |
| 664 DCHECK_NOT_NULL(c->try_info); | 650 SsaEnv* catch_env = c->catch_env; |
| 665 SsaEnv* catch_env = c->try_info->catch_env; | 651 c->catch_env = nullptr; |
| 666 c->try_info->catch_env = nullptr; | |
| 667 SetEnv("catch:begin", catch_env); | 652 SetEnv("catch:begin", catch_env); |
| 668 current_catch_ = c->previous_catch; | |
| 669 | 653 |
| 670 if (Validate(pc_, operand)) { | 654 if (Validate(pc_, operand)) { |
| 655 // TODO(jpp): figure out how thrown value is propagated. It is |
| 656 // unlikely to be a value on the stack. |
| 671 if (ssa_env_->locals) { | 657 if (ssa_env_->locals) { |
| 672 TFNode* exception_as_i32 = | 658 ssa_env_->locals[operand.index] = nullptr; |
| 673 BUILD(Catch, c->try_info->exception, position()); | |
| 674 ssa_env_->locals[operand.index] = exception_as_i32; | |
| 675 } | 659 } |
| 676 } | 660 } |
| 677 | 661 |
| 662 PopUpTo(c->stack_depth); |
| 678 break; | 663 break; |
| 679 } | 664 } |
| 680 case kExprLoop: { | 665 case kExprLoop: { |
| 681 BlockTypeOperand operand(this, pc_); | 666 BlockTypeOperand operand(this, pc_); |
| 682 SsaEnv* finish_try_env = Steal(ssa_env_); | 667 SsaEnv* finish_try_env = Steal(ssa_env_); |
| 683 // The continue environment is the inner environment. | 668 // The continue environment is the inner environment. |
| 684 PrepareForLoop(pc_, finish_try_env); | 669 PrepareForLoop(pc_, finish_try_env); |
| 685 SetEnv("loop:start", Split(finish_try_env)); | 670 SetEnv("loop:start", Split(finish_try_env)); |
| 686 ssa_env_->SetNotMerged(); | 671 ssa_env_->SetNotMerged(); |
| 687 PushLoop(finish_try_env); | 672 PushLoop(finish_try_env); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 } | 740 } |
| 756 name = "if:merge"; | 741 name = "if:merge"; |
| 757 } else { | 742 } else { |
| 758 // End the false branch of a two-armed if. | 743 // End the false branch of a two-armed if. |
| 759 name = "if_else:merge"; | 744 name = "if_else:merge"; |
| 760 } | 745 } |
| 761 } else if (c->is_try()) { | 746 } else if (c->is_try()) { |
| 762 name = "try:end"; | 747 name = "try:end"; |
| 763 | 748 |
| 764 // validate that catch was seen. | 749 // validate that catch was seen. |
| 765 if (c->try_info->catch_env != nullptr) { | 750 if (c->catch_env != nullptr) { |
| 766 error(pc_, "missing catch in try"); | 751 error("missing catch in try"); |
| 767 break; | 752 break; |
| 768 } | 753 } |
| 769 } | 754 } |
| 770 FallThruTo(c); | 755 FallThruTo(c); |
| 771 SetEnv(name, c->end_env); | 756 SetEnv(name, c->end_env); |
| 772 | 757 |
| 773 // Push the end values onto the stack. | 758 // Push the end values onto the stack. |
| 774 stack_.resize(c->stack_depth); | 759 stack_.resize(c->stack_depth); |
| 775 if (c->merge.arity == 1) { | 760 if (c->merge.arity == 1) { |
| 776 stack_.push_back(c->merge.vals.first); | 761 stack_.push_back(c->merge.vals.first); |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1065 error("grow_memory is not supported for asmjs modules"); | 1050 error("grow_memory is not supported for asmjs modules"); |
| 1066 } | 1051 } |
| 1067 break; | 1052 break; |
| 1068 case kExprMemorySize: | 1053 case kExprMemorySize: |
| 1069 Push(kAstI32, BUILD(CurrentMemoryPages)); | 1054 Push(kAstI32, BUILD(CurrentMemoryPages)); |
| 1070 break; | 1055 break; |
| 1071 case kExprCallFunction: { | 1056 case kExprCallFunction: { |
| 1072 CallFunctionOperand operand(this, pc_); | 1057 CallFunctionOperand operand(this, pc_); |
| 1073 if (Validate(pc_, operand)) { | 1058 if (Validate(pc_, operand)) { |
| 1074 TFNode** buffer = PopArgs(operand.sig); | 1059 TFNode** buffer = PopArgs(operand.sig); |
| 1075 TFNode** rets = nullptr; | 1060 TFNode** rets = |
| 1076 BUILD(CallDirect, operand.index, buffer, &rets, position()); | 1061 BUILD(CallDirect, operand.index, buffer, position()); |
| 1077 PushReturns(operand.sig, rets); | 1062 PushReturns(operand.sig, rets); |
| 1078 } | 1063 } |
| 1079 len = 1 + operand.length; | 1064 len = 1 + operand.length; |
| 1080 break; | 1065 break; |
| 1081 } | 1066 } |
| 1082 case kExprCallIndirect: { | 1067 case kExprCallIndirect: { |
| 1083 CallIndirectOperand operand(this, pc_); | 1068 CallIndirectOperand operand(this, pc_); |
| 1084 if (Validate(pc_, operand)) { | 1069 if (Validate(pc_, operand)) { |
| 1085 Value index = Pop(0, kAstI32); | 1070 Value index = Pop(0, kAstI32); |
| 1086 TFNode** buffer = PopArgs(operand.sig); | 1071 TFNode** buffer = PopArgs(operand.sig); |
| 1087 if (buffer) buffer[0] = index.node; | 1072 if (buffer) buffer[0] = index.node; |
| 1088 TFNode** rets = nullptr; | 1073 TFNode** rets = |
| 1089 BUILD(CallIndirect, operand.index, buffer, &rets, position()); | 1074 BUILD(CallIndirect, operand.index, buffer, position()); |
| 1090 PushReturns(operand.sig, rets); | 1075 PushReturns(operand.sig, rets); |
| 1091 } | 1076 } |
| 1092 len = 1 + operand.length; | 1077 len = 1 + operand.length; |
| 1093 break; | 1078 break; |
| 1094 } | 1079 } |
| 1095 case kSimdPrefix: { | 1080 case kSimdPrefix: { |
| 1096 CHECK_PROTOTYPE_OPCODE(wasm_simd_prototype); | 1081 CHECK_PROTOTYPE_OPCODE(wasm_simd_prototype); |
| 1097 len++; | 1082 len++; |
| 1098 byte simd_index = *(pc_ + 1); | 1083 byte simd_index = *(pc_ + 1); |
| 1099 opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index); | 1084 opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1192 return nullptr; | 1177 return nullptr; |
| 1193 } | 1178 } |
| 1194 } | 1179 } |
| 1195 | 1180 |
| 1196 LocalType GetReturnType(FunctionSig* sig) { | 1181 LocalType GetReturnType(FunctionSig* sig) { |
| 1197 return sig->return_count() == 0 ? kAstStmt : sig->GetReturn(); | 1182 return sig->return_count() == 0 ? kAstStmt : sig->GetReturn(); |
| 1198 } | 1183 } |
| 1199 | 1184 |
| 1200 void PushBlock(SsaEnv* end_env) { | 1185 void PushBlock(SsaEnv* end_env) { |
| 1201 const int stack_depth = static_cast<int>(stack_.size()); | 1186 const int stack_depth = static_cast<int>(stack_.size()); |
| 1202 control_.emplace_back( | 1187 control_.emplace_back(Control::Block(pc_, stack_depth, end_env)); |
| 1203 Control::Block(pc_, stack_depth, end_env, current_catch_)); | |
| 1204 } | 1188 } |
| 1205 | 1189 |
| 1206 void PushLoop(SsaEnv* end_env) { | 1190 void PushLoop(SsaEnv* end_env) { |
| 1207 const int stack_depth = static_cast<int>(stack_.size()); | 1191 const int stack_depth = static_cast<int>(stack_.size()); |
| 1208 control_.emplace_back( | 1192 control_.emplace_back(Control::Loop(pc_, stack_depth, end_env)); |
| 1209 Control::Loop(pc_, stack_depth, end_env, current_catch_)); | |
| 1210 } | 1193 } |
| 1211 | 1194 |
| 1212 void PushIf(SsaEnv* end_env, SsaEnv* false_env) { | 1195 void PushIf(SsaEnv* end_env, SsaEnv* false_env) { |
| 1213 const int stack_depth = static_cast<int>(stack_.size()); | 1196 const int stack_depth = static_cast<int>(stack_.size()); |
| 1214 control_.emplace_back( | 1197 control_.emplace_back(Control::If(pc_, stack_depth, end_env, false_env)); |
| 1215 Control::If(pc_, stack_depth, end_env, false_env, current_catch_)); | |
| 1216 } | 1198 } |
| 1217 | 1199 |
| 1218 void PushTry(SsaEnv* end_env, SsaEnv* catch_env) { | 1200 void PushTry(SsaEnv* end_env, SsaEnv* catch_env) { |
| 1219 const int stack_depth = static_cast<int>(stack_.size()); | 1201 const int stack_depth = static_cast<int>(stack_.size()); |
| 1220 control_.emplace_back(Control::Try(pc_, stack_depth, end_env, zone_, | 1202 control_.emplace_back(Control::Try(pc_, stack_depth, end_env, catch_env)); |
| 1221 catch_env, current_catch_)); | |
| 1222 current_catch_ = static_cast<int32_t>(control_.size() - 1); | |
| 1223 } | 1203 } |
| 1224 | 1204 |
| 1225 void PopControl() { control_.pop_back(); } | 1205 void PopControl() { control_.pop_back(); } |
| 1226 | 1206 |
| 1227 int DecodeLoadMem(LocalType type, MachineType mem_type) { | 1207 int DecodeLoadMem(LocalType type, MachineType mem_type) { |
| 1228 MemoryAccessOperand operand(this, pc_, | 1208 MemoryAccessOperand operand(this, pc_, |
| 1229 ElementSizeLog2Of(mem_type.representation())); | 1209 ElementSizeLog2Of(mem_type.representation())); |
| 1230 | 1210 |
| 1231 Value index = Pop(0, kAstI32); | 1211 Value index = Pop(0, kAstI32); |
| 1232 TFNode* node = BUILD(LoadMem, type, mem_type, index.node, operand.offset, | 1212 TFNode* node = BUILD(LoadMem, type, mem_type, index.node, operand.offset, |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1472 PrintF("\n"); | 1452 PrintF("\n"); |
| 1473 } | 1453 } |
| 1474 #endif | 1454 #endif |
| 1475 ssa_env_ = env; | 1455 ssa_env_ = env; |
| 1476 if (builder_) { | 1456 if (builder_) { |
| 1477 builder_->set_control_ptr(&env->control); | 1457 builder_->set_control_ptr(&env->control); |
| 1478 builder_->set_effect_ptr(&env->effect); | 1458 builder_->set_effect_ptr(&env->effect); |
| 1479 } | 1459 } |
| 1480 } | 1460 } |
| 1481 | 1461 |
| 1482 TFNode* CheckForException(TFNode* node) { | |
| 1483 if (node == nullptr) { | |
| 1484 return nullptr; | |
| 1485 } | |
| 1486 | |
| 1487 const bool inside_try_scope = current_catch_ != kNullCatch; | |
| 1488 | |
| 1489 if (!inside_try_scope) { | |
| 1490 return node; | |
| 1491 } | |
| 1492 | |
| 1493 TFNode* if_success = nullptr; | |
| 1494 TFNode* if_exception = nullptr; | |
| 1495 if (!builder_->ThrowsException(node, &if_success, &if_exception)) { | |
| 1496 return node; | |
| 1497 } | |
| 1498 | |
| 1499 SsaEnv* success_env = Steal(ssa_env_); | |
| 1500 success_env->control = if_success; | |
| 1501 | |
| 1502 SsaEnv* exception_env = Split(success_env); | |
| 1503 exception_env->control = if_exception; | |
| 1504 TryInfo* try_info = current_try_info(); | |
| 1505 Goto(exception_env, try_info->catch_env); | |
| 1506 TFNode* exception = try_info->exception; | |
| 1507 if (exception == nullptr) { | |
| 1508 DCHECK_EQ(SsaEnv::kReached, try_info->catch_env->state); | |
| 1509 try_info->exception = if_exception; | |
| 1510 } else { | |
| 1511 DCHECK_EQ(SsaEnv::kMerged, try_info->catch_env->state); | |
| 1512 try_info->exception = | |
| 1513 CreateOrMergeIntoPhi(kAstI32, try_info->catch_env->control, | |
| 1514 try_info->exception, if_exception); | |
| 1515 } | |
| 1516 | |
| 1517 SetEnv("if_success", success_env); | |
| 1518 return node; | |
| 1519 } | |
| 1520 | |
| 1521 void Goto(SsaEnv* from, SsaEnv* to) { | 1462 void Goto(SsaEnv* from, SsaEnv* to) { |
| 1522 DCHECK_NOT_NULL(to); | 1463 DCHECK_NOT_NULL(to); |
| 1523 if (!from->go()) return; | 1464 if (!from->go()) return; |
| 1524 switch (to->state) { | 1465 switch (to->state) { |
| 1525 case SsaEnv::kUnreachable: { // Overwrite destination. | 1466 case SsaEnv::kUnreachable: { // Overwrite destination. |
| 1526 to->state = SsaEnv::kReached; | 1467 to->state = SsaEnv::kReached; |
| 1527 to->locals = from->locals; | 1468 to->locals = from->locals; |
| 1528 to->control = from->control; | 1469 to->control = from->control; |
| 1529 to->effect = from->effect; | 1470 to->effect = from->effect; |
| 1530 break; | 1471 break; |
| (...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1933 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, | 1874 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, |
| 1934 const byte* start, const byte* end) { | 1875 const byte* start, const byte* end) { |
| 1935 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; | 1876 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; |
| 1936 WasmFullDecoder decoder(zone, nullptr, body); | 1877 WasmFullDecoder decoder(zone, nullptr, body); |
| 1937 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); | 1878 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); |
| 1938 } | 1879 } |
| 1939 | 1880 |
| 1940 } // namespace wasm | 1881 } // namespace wasm |
| 1941 } // namespace internal | 1882 } // namespace internal |
| 1942 } // namespace v8 | 1883 } // namespace v8 |
| OLD | NEW |