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. |
titzer
2016/09/28 17:09:14
This will of course, require rebase onto 0xC.
John
2016/09/29 13:28:31
Oh, this was painful... <rant />
| |
105 int32_t previous_catch; // The previous Control (on the stack) with a catch. | |
106 TFNode* node; // result node for the construct. | |
107 LocalType type; // result type for the construct. | |
107 | 108 |
108 // Values merged into the end of this control construct. | 109 // Values merged into the end of this control construct. |
109 MergeValues merge; | 110 MergeValues merge; |
110 | 111 |
111 inline bool is_if() const { return kind == kControlIf; } | 112 inline bool is_if() const { return kind == kControlIf; } |
112 inline bool is_block() const { return kind == kControlBlock; } | 113 inline bool is_block() const { return kind == kControlBlock; } |
113 inline bool is_loop() const { return kind == kControlLoop; } | 114 inline bool is_loop() const { return kind == kControlLoop; } |
114 inline bool is_try() const { return kind == kControlTry; } | 115 inline bool is_try() const { return kind == kControlTry; } |
115 | 116 |
116 // Named constructors. | 117 // Named constructors. |
117 static Control Block(const byte* pc, int stack_depth, SsaEnv* end_env) { | 118 static Control Block(const byte* pc, int stack_depth, SsaEnv* end_env, |
118 return {pc, kControlBlock, stack_depth, end_env, | 119 int32_t previous_catch) { |
119 nullptr, nullptr, {0, {NO_VALUE}}}; | 120 return {pc, kControlBlock, stack_depth, end_env, nullptr, |
121 nullptr, previous_catch, nullptr, kAstEnd, {0, {NO_VALUE}}}; | |
120 } | 122 } |
121 | 123 |
122 static Control If(const byte* pc, int stack_depth, SsaEnv* end_env, | 124 static Control If(const byte* pc, int stack_depth, SsaEnv* end_env, |
123 SsaEnv* false_env) { | 125 SsaEnv* false_env, int32_t previous_catch) { |
124 return {pc, kControlIf, stack_depth, end_env, | 126 return {pc, kControlIf, stack_depth, end_env, false_env, |
125 false_env, nullptr, {0, {NO_VALUE}}}; | 127 nullptr, previous_catch, nullptr, kAstStmt, {0, {NO_VALUE}}}; |
126 } | 128 } |
127 | 129 |
128 static Control Loop(const byte* pc, int stack_depth, SsaEnv* end_env) { | 130 static Control Loop(const byte* pc, int stack_depth, SsaEnv* end_env, |
129 return {pc, kControlLoop, stack_depth, end_env, | 131 int32_t previous_catch) { |
130 nullptr, nullptr, {0, {NO_VALUE}}}; | 132 return {pc, kControlLoop, stack_depth, end_env, nullptr, |
133 nullptr, previous_catch, nullptr, kAstEnd, {0, {NO_VALUE}}}; | |
131 } | 134 } |
132 | 135 |
133 static Control Try(const byte* pc, int stack_depth, SsaEnv* end_env, | 136 static Control Try(const byte* pc, int stack_depth, SsaEnv* end_env, |
134 SsaEnv* catch_env) { | 137 Zone* zone, SsaEnv* catch_env, int32_t previous_catch) { |
135 return {pc, kControlTry, stack_depth, end_env, | 138 DCHECK_NOT_NULL(catch_env); |
136 nullptr, catch_env, {0, {NO_VALUE}}}; | 139 return {pc, |
140 kControlTry, | |
141 stack_depth, | |
142 end_env, | |
143 nullptr, | |
144 new (zone) TryInfo(catch_env), | |
145 previous_catch, | |
146 nullptr, | |
147 kAstEnd, | |
148 {0, {NO_VALUE}}}; | |
137 } | 149 } |
138 }; | 150 }; |
139 | 151 |
140 // Macros that build nodes only if there is a graph and the current SSA | 152 // 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 | 153 // environment is reachable from start. This avoids problems with malformed |
142 // TF graphs when decoding inputs that have unreachable code. | 154 // TF graphs when decoding inputs that have unreachable code. |
143 #define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr) | 155 #define BUILD(func, ...) \ |
144 #define BUILD0(func) (build() ? builder_->func() : nullptr) | 156 (build() ? CheckForException(builder_->func(__VA_ARGS__)) : nullptr) |
157 #define BUILD0(func) (build() ? CheckForException(builder_->func()) : nullptr) | |
145 | 158 |
146 // Generic Wasm bytecode decoder with utilities for decoding operands, | 159 // Generic Wasm bytecode decoder with utilities for decoding operands, |
147 // lengths, etc. | 160 // lengths, etc. |
148 class WasmDecoder : public Decoder { | 161 class WasmDecoder : public Decoder { |
149 public: | 162 public: |
150 WasmDecoder(ModuleEnv* module, FunctionSig* sig, const byte* start, | 163 WasmDecoder(ModuleEnv* module, FunctionSig* sig, const byte* start, |
151 const byte* end) | 164 const byte* end) |
152 : Decoder(start, end), | 165 : Decoder(start, end), |
153 module_(module), | 166 module_(module), |
154 sig_(sig), | 167 sig_(sig), |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
296 case kExprF32Const: | 309 case kExprF32Const: |
297 return 5; | 310 return 5; |
298 case kExprF64Const: | 311 case kExprF64Const: |
299 return 9; | 312 return 9; |
300 default: | 313 default: |
301 return 1; | 314 return 1; |
302 } | 315 } |
303 } | 316 } |
304 }; | 317 }; |
305 | 318 |
319 static const int32_t kNullCatch = -1; | |
320 | |
306 // The full WASM decoder for bytecode. Both verifies bytecode and generates | 321 // The full WASM decoder for bytecode. Both verifies bytecode and generates |
307 // a TurboFan IR graph. | 322 // a TurboFan IR graph. |
308 class WasmFullDecoder : public WasmDecoder { | 323 class WasmFullDecoder : public WasmDecoder { |
309 public: | 324 public: |
310 WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body) | 325 WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body) |
311 : WasmDecoder(body.module, body.sig, body.start, body.end), | 326 : WasmDecoder(body.module, body.sig, body.start, body.end), |
312 zone_(zone), | 327 zone_(zone), |
313 builder_(builder), | 328 builder_(builder), |
314 base_(body.base), | 329 base_(body.base), |
315 local_type_vec_(zone), | 330 local_type_vec_(zone), |
316 stack_(zone), | 331 stack_(zone), |
317 control_(zone), | 332 control_(zone), |
318 last_end_found_(false) { | 333 last_end_found_(false), |
334 current_catch_(kNullCatch) { | |
319 local_types_ = &local_type_vec_; | 335 local_types_ = &local_type_vec_; |
320 } | 336 } |
321 | 337 |
322 bool Decode() { | 338 bool Decode() { |
323 base::ElapsedTimer decode_timer; | 339 base::ElapsedTimer decode_timer; |
324 if (FLAG_trace_wasm_decode_time) { | 340 if (FLAG_trace_wasm_decode_time) { |
325 decode_timer.Start(); | 341 decode_timer.Start(); |
326 } | 342 } |
327 stack_.clear(); | 343 stack_.clear(); |
328 control_.clear(); | 344 control_.clear(); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
434 TFBuilder* builder_; | 450 TFBuilder* builder_; |
435 const byte* base_; | 451 const byte* base_; |
436 | 452 |
437 SsaEnv* ssa_env_; | 453 SsaEnv* ssa_env_; |
438 | 454 |
439 ZoneVector<LocalType> local_type_vec_; // types of local variables. | 455 ZoneVector<LocalType> local_type_vec_; // types of local variables. |
440 ZoneVector<Value> stack_; // stack of values. | 456 ZoneVector<Value> stack_; // stack of values. |
441 ZoneVector<Control> control_; // stack of blocks, loops, and ifs. | 457 ZoneVector<Control> control_; // stack of blocks, loops, and ifs. |
442 bool last_end_found_; | 458 bool last_end_found_; |
443 | 459 |
460 int32_t current_catch_; | |
461 | |
462 TryInfo* current_try_info() { return control_[current_catch_].try_info; } | |
463 | |
444 inline bool build() { return builder_ && ssa_env_->go(); } | 464 inline bool build() { return builder_ && ssa_env_->go(); } |
445 | 465 |
446 void InitSsaEnv() { | 466 void InitSsaEnv() { |
447 TFNode* start = nullptr; | 467 TFNode* start = nullptr; |
448 SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv))); | 468 SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv))); |
449 size_t size = sizeof(TFNode*) * EnvironmentCount(); | 469 size_t size = sizeof(TFNode*) * EnvironmentCount(); |
450 ssa_env->state = SsaEnv::kReached; | 470 ssa_env->state = SsaEnv::kReached; |
451 ssa_env->locals = | 471 ssa_env->locals = |
452 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr; | 472 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr; |
453 | 473 |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
610 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); | 630 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); |
611 Value value = Pop(0, kAstI32); | 631 Value value = Pop(0, kAstI32); |
612 BUILD(Throw, value.node); | 632 BUILD(Throw, value.node); |
613 break; | 633 break; |
614 } | 634 } |
615 case kExprTry: { | 635 case kExprTry: { |
616 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); | 636 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); |
617 BlockTypeOperand operand(this, pc_); | 637 BlockTypeOperand operand(this, pc_); |
618 SsaEnv* outer_env = ssa_env_; | 638 SsaEnv* outer_env = ssa_env_; |
619 SsaEnv* try_env = Steal(outer_env); | 639 SsaEnv* try_env = Steal(outer_env); |
620 SsaEnv* catch_env = Split(try_env); | 640 SsaEnv* catch_env = UnreachableEnv(); |
621 PushTry(outer_env, catch_env); | 641 PushTry(outer_env, catch_env); |
622 SetEnv("try_catch:start", try_env); | 642 SetEnv("try_catch:start", try_env); |
623 SetBlockType(&control_.back(), operand); | 643 SetBlockType(&control_.back(), operand); |
624 len = 1 + operand.length; | 644 len = 1 + operand.length; |
625 break; | 645 break; |
626 } | 646 } |
627 case kExprCatch: { | 647 case kExprCatch: { |
628 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); | 648 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); |
629 LocalIndexOperand operand(this, pc_); | 649 LocalIndexOperand operand(this, pc_); |
630 len = 1 + operand.length; | 650 len = 1 + operand.length; |
631 | 651 |
632 if (control_.empty()) { | 652 if (control_.empty()) { |
633 error("catch does not match any try"); | 653 error("catch does not match any try"); |
634 break; | 654 break; |
635 } | 655 } |
636 | 656 |
637 Control* c = &control_.back(); | 657 Control* c = &control_.back(); |
638 if (!c->is_try()) { | 658 if (!c->is_try()) { |
639 error("catch does not match any try"); | 659 error("catch does not match any try"); |
640 break; | 660 break; |
641 } | 661 } |
642 | 662 |
643 if (c->catch_env == nullptr) { | 663 if (c->try_info->catch_env == nullptr) { |
644 error("catch already present for try with catch"); | 664 error(pc_, "catch already present for try with catch"); |
645 break; | 665 break; |
646 } | 666 } |
647 | 667 |
648 Goto(ssa_env_, c->end_env); | 668 if (ssa_env_->go()) { |
669 MergeValuesInto(c); | |
670 } | |
671 stack_.resize(c->stack_depth); | |
649 | 672 |
650 SsaEnv* catch_env = c->catch_env; | 673 DCHECK_NOT_NULL(c->try_info); |
651 c->catch_env = nullptr; | 674 SsaEnv* catch_env = c->try_info->catch_env; |
675 c->try_info->catch_env = nullptr; | |
652 SetEnv("catch:begin", catch_env); | 676 SetEnv("catch:begin", catch_env); |
677 current_catch_ = c->previous_catch; | |
653 | 678 |
654 if (Validate(pc_, operand)) { | 679 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) { | 680 if (ssa_env_->locals) { |
658 ssa_env_->locals[operand.index] = nullptr; | 681 TFNode* exception_as_i32 = |
682 BUILD(Catch, c->try_info->exception, position()); | |
683 ssa_env_->locals[operand.index] = exception_as_i32; | |
659 } | 684 } |
660 } | 685 } |
661 | 686 |
662 PopUpTo(c->stack_depth); | |
663 break; | 687 break; |
664 } | 688 } |
665 case kExprLoop: { | 689 case kExprLoop: { |
666 BlockTypeOperand operand(this, pc_); | 690 BlockTypeOperand operand(this, pc_); |
667 SsaEnv* finish_try_env = Steal(ssa_env_); | 691 SsaEnv* finish_try_env = Steal(ssa_env_); |
668 // The continue environment is the inner environment. | 692 // The continue environment is the inner environment. |
669 PrepareForLoop(pc_, finish_try_env); | 693 PrepareForLoop(pc_, finish_try_env); |
670 SetEnv("loop:start", Split(finish_try_env)); | 694 SetEnv("loop:start", Split(finish_try_env)); |
671 ssa_env_->SetNotMerged(); | 695 ssa_env_->SetNotMerged(); |
672 PushLoop(finish_try_env); | 696 PushLoop(finish_try_env); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
740 } | 764 } |
741 name = "if:merge"; | 765 name = "if:merge"; |
742 } else { | 766 } else { |
743 // End the false branch of a two-armed if. | 767 // End the false branch of a two-armed if. |
744 name = "if_else:merge"; | 768 name = "if_else:merge"; |
745 } | 769 } |
746 } else if (c->is_try()) { | 770 } else if (c->is_try()) { |
747 name = "try:end"; | 771 name = "try:end"; |
748 | 772 |
749 // validate that catch was seen. | 773 // validate that catch was seen. |
750 if (c->catch_env != nullptr) { | 774 if (c->try_info->catch_env != nullptr) { |
751 error("missing catch in try"); | 775 error(pc_, "missing catch in try"); |
752 break; | 776 break; |
753 } | 777 } |
754 } | 778 } |
755 FallThruTo(c); | 779 FallThruTo(c); |
756 SetEnv(name, c->end_env); | 780 SetEnv(name, c->end_env); |
757 | 781 |
758 // Push the end values onto the stack. | 782 // Push the end values onto the stack. |
759 stack_.resize(c->stack_depth); | 783 stack_.resize(c->stack_depth); |
760 if (c->merge.arity == 1) { | 784 if (c->merge.arity == 1) { |
761 stack_.push_back(c->merge.vals.first); | 785 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"); | 1074 error("grow_memory is not supported for asmjs modules"); |
1051 } | 1075 } |
1052 break; | 1076 break; |
1053 case kExprMemorySize: | 1077 case kExprMemorySize: |
1054 Push(kAstI32, BUILD(CurrentMemoryPages)); | 1078 Push(kAstI32, BUILD(CurrentMemoryPages)); |
1055 break; | 1079 break; |
1056 case kExprCallFunction: { | 1080 case kExprCallFunction: { |
1057 CallFunctionOperand operand(this, pc_); | 1081 CallFunctionOperand operand(this, pc_); |
1058 if (Validate(pc_, operand)) { | 1082 if (Validate(pc_, operand)) { |
1059 TFNode** buffer = PopArgs(operand.sig); | 1083 TFNode** buffer = PopArgs(operand.sig); |
1060 TFNode** rets = | 1084 TFNode** rets = nullptr; |
1061 BUILD(CallDirect, operand.index, buffer, position()); | 1085 BUILD(CallDirect, operand.index, buffer, &rets, position()); |
1062 PushReturns(operand.sig, rets); | 1086 PushReturns(operand.sig, rets); |
1063 } | 1087 } |
1064 len = 1 + operand.length; | 1088 len = 1 + operand.length; |
1065 break; | 1089 break; |
1066 } | 1090 } |
1067 case kExprCallIndirect: { | 1091 case kExprCallIndirect: { |
1068 CallIndirectOperand operand(this, pc_); | 1092 CallIndirectOperand operand(this, pc_); |
1069 if (Validate(pc_, operand)) { | 1093 if (Validate(pc_, operand)) { |
1070 Value index = Pop(0, kAstI32); | 1094 Value index = Pop(0, kAstI32); |
1071 TFNode** buffer = PopArgs(operand.sig); | 1095 TFNode** buffer = PopArgs(operand.sig); |
1072 if (buffer) buffer[0] = index.node; | 1096 if (buffer) buffer[0] = index.node; |
1073 TFNode** rets = | 1097 TFNode** rets = nullptr; |
1074 BUILD(CallIndirect, operand.index, buffer, position()); | 1098 BUILD(CallIndirect, operand.index, buffer, &rets, position()); |
1075 PushReturns(operand.sig, rets); | 1099 PushReturns(operand.sig, rets); |
1076 } | 1100 } |
1077 len = 1 + operand.length; | 1101 len = 1 + operand.length; |
1078 break; | 1102 break; |
1079 } | 1103 } |
1080 case kSimdPrefix: { | 1104 case kSimdPrefix: { |
1081 CHECK_PROTOTYPE_OPCODE(wasm_simd_prototype); | 1105 CHECK_PROTOTYPE_OPCODE(wasm_simd_prototype); |
1082 len++; | 1106 len++; |
1083 byte simd_index = *(pc_ + 1); | 1107 byte simd_index = *(pc_ + 1); |
1084 opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index); | 1108 opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1177 return nullptr; | 1201 return nullptr; |
1178 } | 1202 } |
1179 } | 1203 } |
1180 | 1204 |
1181 LocalType GetReturnType(FunctionSig* sig) { | 1205 LocalType GetReturnType(FunctionSig* sig) { |
1182 return sig->return_count() == 0 ? kAstStmt : sig->GetReturn(); | 1206 return sig->return_count() == 0 ? kAstStmt : sig->GetReturn(); |
1183 } | 1207 } |
1184 | 1208 |
1185 void PushBlock(SsaEnv* end_env) { | 1209 void PushBlock(SsaEnv* end_env) { |
1186 const int stack_depth = static_cast<int>(stack_.size()); | 1210 const int stack_depth = static_cast<int>(stack_.size()); |
1187 control_.emplace_back(Control::Block(pc_, stack_depth, end_env)); | 1211 control_.emplace_back( |
1212 Control::Block(pc_, stack_depth, end_env, current_catch_)); | |
1188 } | 1213 } |
1189 | 1214 |
1190 void PushLoop(SsaEnv* end_env) { | 1215 void PushLoop(SsaEnv* end_env) { |
1191 const int stack_depth = static_cast<int>(stack_.size()); | 1216 const int stack_depth = static_cast<int>(stack_.size()); |
1192 control_.emplace_back(Control::Loop(pc_, stack_depth, end_env)); | 1217 control_.emplace_back( |
1218 Control::Loop(pc_, stack_depth, end_env, current_catch_)); | |
1193 } | 1219 } |
1194 | 1220 |
1195 void PushIf(SsaEnv* end_env, SsaEnv* false_env) { | 1221 void PushIf(SsaEnv* end_env, SsaEnv* false_env) { |
1196 const int stack_depth = static_cast<int>(stack_.size()); | 1222 const int stack_depth = static_cast<int>(stack_.size()); |
1197 control_.emplace_back(Control::If(pc_, stack_depth, end_env, false_env)); | 1223 control_.emplace_back( |
1224 Control::If(pc_, stack_depth, end_env, false_env, current_catch_)); | |
1198 } | 1225 } |
1199 | 1226 |
1200 void PushTry(SsaEnv* end_env, SsaEnv* catch_env) { | 1227 void PushTry(SsaEnv* end_env, SsaEnv* catch_env) { |
1201 const int stack_depth = static_cast<int>(stack_.size()); | 1228 const int stack_depth = static_cast<int>(stack_.size()); |
1202 control_.emplace_back(Control::Try(pc_, stack_depth, end_env, catch_env)); | 1229 control_.emplace_back(Control::Try(pc_, stack_depth, end_env, zone_, |
1230 catch_env, current_catch_)); | |
1231 current_catch_ = static_cast<int32_t>(control_.size() - 1); | |
1203 } | 1232 } |
1204 | 1233 |
1205 void PopControl() { control_.pop_back(); } | 1234 void PopControl() { control_.pop_back(); } |
1206 | 1235 |
1207 int DecodeLoadMem(LocalType type, MachineType mem_type) { | 1236 int DecodeLoadMem(LocalType type, MachineType mem_type) { |
1208 MemoryAccessOperand operand(this, pc_, | 1237 MemoryAccessOperand operand(this, pc_, |
1209 ElementSizeLog2Of(mem_type.representation())); | 1238 ElementSizeLog2Of(mem_type.representation())); |
1210 | 1239 |
1211 Value index = Pop(0, kAstI32); | 1240 Value index = Pop(0, kAstI32); |
1212 TFNode* node = BUILD(LoadMem, type, mem_type, index.node, operand.offset, | 1241 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"); | 1481 PrintF("\n"); |
1453 } | 1482 } |
1454 #endif | 1483 #endif |
1455 ssa_env_ = env; | 1484 ssa_env_ = env; |
1456 if (builder_) { | 1485 if (builder_) { |
1457 builder_->set_control_ptr(&env->control); | 1486 builder_->set_control_ptr(&env->control); |
1458 builder_->set_effect_ptr(&env->effect); | 1487 builder_->set_effect_ptr(&env->effect); |
1459 } | 1488 } |
1460 } | 1489 } |
1461 | 1490 |
1491 TFNode* CheckForException(TFNode* node) { | |
1492 if (node == nullptr) { | |
1493 return nullptr; | |
1494 } | |
1495 | |
1496 if (builder_->DoesNotThrow(node)) { | |
1497 return node; | |
1498 } | |
1499 | |
1500 const bool inside_try_scope = current_catch_ != kNullCatch; | |
1501 | |
1502 if (!inside_try_scope) { | |
1503 return node; | |
1504 } | |
1505 | |
1506 SsaEnv* success_env = Steal(ssa_env_); | |
1507 TFNode* if_success = builder_->IfSuccess(node); | |
1508 success_env->control = if_success; | |
1509 | |
1510 SsaEnv* exception_env = Split(success_env); | |
1511 TFNode* if_exception = builder_->IfException(node); | |
1512 exception_env->control = if_exception; | |
1513 TryInfo* try_info = current_try_info(); | |
1514 Goto(exception_env, try_info->catch_env); | |
1515 TFNode* exception = try_info->exception; | |
1516 if (exception == nullptr) { | |
1517 DCHECK_EQ(SsaEnv::kReached, try_info->catch_env->state); | |
1518 try_info->exception = if_exception; | |
1519 } else { | |
1520 DCHECK_EQ(SsaEnv::kMerged, try_info->catch_env->state); | |
1521 try_info->exception = | |
1522 CreateOrMergeIntoPhi(kAstI32, try_info->catch_env->control, | |
1523 try_info->exception, if_exception); | |
1524 } | |
1525 | |
1526 SetEnv("if_success", success_env); | |
1527 return node; | |
1528 } | |
1529 | |
1462 void Goto(SsaEnv* from, SsaEnv* to) { | 1530 void Goto(SsaEnv* from, SsaEnv* to) { |
1463 DCHECK_NOT_NULL(to); | 1531 DCHECK_NOT_NULL(to); |
1464 if (!from->go()) return; | 1532 if (!from->go()) return; |
1465 switch (to->state) { | 1533 switch (to->state) { |
1466 case SsaEnv::kUnreachable: { // Overwrite destination. | 1534 case SsaEnv::kUnreachable: { // Overwrite destination. |
1467 to->state = SsaEnv::kReached; | 1535 to->state = SsaEnv::kReached; |
1468 to->locals = from->locals; | 1536 to->locals = from->locals; |
1469 to->control = from->control; | 1537 to->control = from->control; |
1470 to->effect = from->effect; | 1538 to->effect = from->effect; |
1471 break; | 1539 break; |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1874 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, | 1942 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, |
1875 const byte* start, const byte* end) { | 1943 const byte* start, const byte* end) { |
1876 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; | 1944 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; |
1877 WasmFullDecoder decoder(zone, nullptr, body); | 1945 WasmFullDecoder decoder(zone, nullptr, body); |
1878 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); | 1946 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); |
1879 } | 1947 } |
1880 | 1948 |
1881 } // namespace wasm | 1949 } // namespace wasm |
1882 } // namespace internal | 1950 } // namespace internal |
1883 } // namespace v8 | 1951 } // namespace v8 |
OLD | NEW |