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 |