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