| 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 |