Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(343)

Side by Side Diff: src/wasm/ast-decoder.cc

Issue 2240743003: [v8][wasm] Handles finally in try/finally blocks. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addresses comments. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/cctest/cctest.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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-containers.h" 10 #include "src/zone-containers.h"
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 } 61 }
62 }; 62 };
63 63
64 // An entry on the value stack. 64 // An entry on the value stack.
65 struct Value { 65 struct Value {
66 const byte* pc; 66 const byte* pc;
67 TFNode* node; 67 TFNode* node;
68 LocalType type; 68 LocalType type;
69 }; 69 };
70 70
71 struct Control;
72
73 // IncomingBranch is used by exception handling code for managing finally's.
74 struct IncomingBranch {
75 int32_t token_value;
76 Control* target;
77 Value val;
78 };
79
80 // Auxiliary data for exception handling. Most scopes don't need any of this so
81 // we group everything into a separate struct.
82 struct TryInfo : public ZoneObject {
83 SsaEnv* catch_env; // catch environment (only for try with catch).
84 SsaEnv* finish_try_env; // the environment where a try with finally lives.
85 ZoneVector<IncomingBranch> incoming_branches;
86 TFNode* token;
87 bool has_handled_finally;
88
89 TryInfo(Zone* zone, SsaEnv* c, SsaEnv* f)
90 : catch_env(c),
91 finish_try_env(f),
92 incoming_branches(zone),
93 token(nullptr),
94 has_handled_finally(false) {}
95 };
96
71 // An entry on the control stack (i.e. if, block, loop). 97 // An entry on the control stack (i.e. if, block, loop).
72 struct Control { 98 struct Control {
73 const byte* pc; 99 const byte* pc;
74 int stack_depth; // stack height at the beginning of the construct. 100 int stack_depth; // stack height at the beginning of the construct.
75 SsaEnv* end_env; // end environment for the construct. 101 SsaEnv* end_env; // end environment for the construct.
76 SsaEnv* false_env; // false environment (only for if). 102 SsaEnv* false_env; // false environment (only for if).
77 SsaEnv* catch_env; // catch environment (only for try with catch). 103 TryInfo* try_info; // exception handling stuff. See TryInfo above.
78 SsaEnv* finish_try_env; // the environment where a try with finally lives. 104 int32_t prev_finally; // previous control (on stack) that has a finally.
79 TFNode* node; // result node for the construct. 105 TFNode* node; // result node for the construct.
80 LocalType type; // result type for the construct. 106 LocalType type; // result type for the construct.
81 bool is_loop; // true if this is the inner label of a loop. 107 bool is_loop; // true if this is the inner label of a loop.
82 108
83 bool is_if() const { return *pc == kExprIf; } 109 bool is_if() const { return *pc == kExprIf; }
84 110
85 bool is_try() const { 111 bool is_try() const {
86 return *pc == kExprTryCatch || *pc == kExprTryCatchFinally || 112 return *pc == kExprTryCatch || *pc == kExprTryCatchFinally ||
87 *pc == kExprTryFinally; 113 *pc == kExprTryFinally;
88 } 114 }
89 115
90 bool has_catch() const { 116 bool has_catch() const {
91 return *pc == kExprTryCatch || *pc == kExprTryCatchFinally; 117 return *pc == kExprTryCatch || *pc == kExprTryCatchFinally;
92 } 118 }
93 119
94 bool has_finally() const { 120 bool has_finally() const {
95 return *pc == kExprTryCatchFinally || *pc == kExprTryFinally; 121 return *pc == kExprTryCatchFinally || *pc == kExprTryFinally;
96 } 122 }
97 123
98 // Named constructors. 124 // Named constructors.
99 static Control Block(const byte* pc, int stack_depth, SsaEnv* end_env) { 125 static Control Block(const byte* pc, int stack_depth,
100 return {pc, stack_depth, end_env, nullptr, nullptr, 126 int32_t most_recent_finally, SsaEnv* end_env) {
101 nullptr, nullptr, kAstEnd, false}; 127 return {pc, stack_depth, end_env,
128 nullptr, nullptr, most_recent_finally,
129 nullptr, kAstEnd, false};
102 } 130 }
103 131
104 static Control If(const byte* pc, int stack_depth, SsaEnv* end_env, 132 static Control If(const byte* pc, int stack_depth,
133 int32_t most_recent_finally, SsaEnv* end_env,
105 SsaEnv* false_env) { 134 SsaEnv* false_env) {
106 return {pc, stack_depth, end_env, false_env, nullptr, 135 return {pc, stack_depth, end_env,
107 nullptr, nullptr, kAstStmt, false}; 136 false_env, nullptr, most_recent_finally,
137 nullptr, kAstStmt, false};
108 } 138 }
109 139
110 static Control Loop(const byte* pc, int stack_depth, SsaEnv* end_env) { 140 static Control Loop(const byte* pc, int stack_depth,
111 return {pc, stack_depth, end_env, nullptr, nullptr, 141 int32_t most_recent_finally, SsaEnv* end_env) {
112 nullptr, nullptr, kAstEnd, true}; 142 return {pc, stack_depth, end_env,
143 nullptr, nullptr, most_recent_finally,
144 nullptr, kAstEnd, true};
113 } 145 }
114 146
115 static Control Try(const byte* pc, int stack_depth, SsaEnv* end_env, 147 static Control Try(const byte* pc, int stack_depth,
148 int32_t most_recent_finally, Zone* zone, SsaEnv* end_env,
116 SsaEnv* catch_env, SsaEnv* finish_try_env) { 149 SsaEnv* catch_env, SsaEnv* finish_try_env) {
117 return {pc, stack_depth, end_env, nullptr, catch_env, finish_try_env, 150 return {pc,
118 nullptr, kAstEnd, false}; 151 stack_depth,
152 end_env,
153 nullptr,
154 new (zone) TryInfo(zone, catch_env, finish_try_env),
155 most_recent_finally,
156 nullptr,
157 kAstEnd,
158 false};
119 } 159 }
120 }; 160 };
121 161
122 // Macros that build nodes only if there is a graph and the current SSA 162 // Macros that build nodes only if there is a graph and the current SSA
123 // environment is reachable from start. This avoids problems with malformed 163 // environment is reachable from start. This avoids problems with malformed
124 // TF graphs when decoding inputs that have unreachable code. 164 // TF graphs when decoding inputs that have unreachable code.
125 #define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr) 165 #define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr)
126 #define BUILD0(func) (build() ? builder_->func() : nullptr) 166 #define BUILD0(func) (build() ? builder_->func() : nullptr)
127 167
128 // Generic Wasm bytecode decoder with utilities for decoding operands, 168 // Generic Wasm bytecode decoder with utilities for decoding operands,
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 ReturnArityOperand operand(this, pc); 456 ReturnArityOperand operand(this, pc);
417 return 1 + operand.length; 457 return 1 + operand.length;
418 } 458 }
419 459
420 default: 460 default:
421 return 1; 461 return 1;
422 } 462 }
423 } 463 }
424 }; 464 };
425 465
466 static const int32_t kFirstFinallyToken = 1;
467 static const int32_t kFallthroughToken = 0;
468 static const int32_t kNullFinallyToken = -1;
469
426 // The full WASM decoder for bytecode. Both verifies bytecode and generates 470 // The full WASM decoder for bytecode. Both verifies bytecode and generates
427 // a TurboFan IR graph. 471 // a TurboFan IR graph.
428 class WasmFullDecoder : public WasmDecoder { 472 class WasmFullDecoder : public WasmDecoder {
429 public: 473 public:
430 WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body) 474 WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body)
431 : WasmDecoder(body.module, body.sig, body.start, body.end), 475 : WasmDecoder(body.module, body.sig, body.start, body.end),
432 zone_(zone), 476 zone_(zone),
433 builder_(builder), 477 builder_(builder),
434 base_(body.base), 478 base_(body.base),
435 local_type_vec_(zone), 479 local_type_vec_(zone),
436 stack_(zone), 480 stack_(zone),
437 control_(zone) { 481 control_(zone),
482 most_recent_finally_(-1),
483 finally_token_val_(kFirstFinallyToken) {
438 local_types_ = &local_type_vec_; 484 local_types_ = &local_type_vec_;
439 } 485 }
440 486
441 bool Decode() { 487 bool Decode() {
442 base::ElapsedTimer decode_timer; 488 base::ElapsedTimer decode_timer;
443 if (FLAG_trace_wasm_decode_time) { 489 if (FLAG_trace_wasm_decode_time) {
444 decode_timer.Start(); 490 decode_timer.Start();
445 } 491 }
446 stack_.clear(); 492 stack_.clear();
447 control_.clear(); 493 control_.clear();
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 Zone* zone_; 566 Zone* zone_;
521 TFBuilder* builder_; 567 TFBuilder* builder_;
522 const byte* base_; 568 const byte* base_;
523 569
524 SsaEnv* ssa_env_; 570 SsaEnv* ssa_env_;
525 571
526 ZoneVector<LocalType> local_type_vec_; // types of local variables. 572 ZoneVector<LocalType> local_type_vec_; // types of local variables.
527 ZoneVector<Value> stack_; // stack of values. 573 ZoneVector<Value> stack_; // stack of values.
528 ZoneVector<Control> control_; // stack of blocks, loops, and ifs. 574 ZoneVector<Control> control_; // stack of blocks, loops, and ifs.
529 575
576 int32_t most_recent_finally_;
577 int32_t finally_token_val_;
578
579 int32_t FallthroughTokenForFinally() {
580 // Any number < kFirstFinallyToken would work.
581 return kFallthroughToken;
582 }
583
584 int32_t NewTokenForFinally() { return finally_token_val_++; }
585
530 inline bool build() { return builder_ && ssa_env_->go(); } 586 inline bool build() { return builder_ && ssa_env_->go(); }
531 587
532 void InitSsaEnv() { 588 void InitSsaEnv() {
533 TFNode* start = nullptr; 589 TFNode* start = nullptr;
534 SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv))); 590 SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
535 size_t size = sizeof(TFNode*) * EnvironmentCount(); 591 size_t size = sizeof(TFNode*) * EnvironmentCount();
536 ssa_env->state = SsaEnv::kReached; 592 ssa_env->state = SsaEnv::kReached;
537 ssa_env->locals = 593 ssa_env->locals =
538 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr; 594 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
539 595
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 error(pc_, "catch does not match a any try"); 779 error(pc_, "catch does not match a any try");
724 break; 780 break;
725 } 781 }
726 782
727 Control* c = &control_.back(); 783 Control* c = &control_.back();
728 if (!c->has_catch()) { 784 if (!c->has_catch()) {
729 error(pc_, "catch does not match a try with catch"); 785 error(pc_, "catch does not match a try with catch");
730 break; 786 break;
731 } 787 }
732 788
733 if (c->catch_env == nullptr) { 789 if (c->try_info->catch_env == nullptr) {
734 error(pc_, "catch already present for try with catch"); 790 error(pc_, "catch already present for try with catch");
735 break; 791 break;
736 } 792 }
737 793
738 Goto(ssa_env_, c->end_env); 794 Goto(ssa_env_, c->end_env);
739 795
740 SsaEnv* catch_env = c->catch_env; 796 SsaEnv* catch_env = c->try_info->catch_env;
741 c->catch_env = nullptr; 797 c->try_info->catch_env = nullptr;
742 SetEnv("catch:begin", catch_env); 798 SetEnv("catch:begin", catch_env);
743 799
744 if (Validate(pc_, operand)) { 800 if (Validate(pc_, operand)) {
745 // TODO(jpp): figure out how thrown value is propagated. It is 801 // TODO(jpp): figure out how thrown value is propagated. It is
746 // unlikely to be a value on the stack. 802 // unlikely to be a value on the stack.
747 if (ssa_env_->locals) { 803 if (ssa_env_->locals) {
748 ssa_env_->locals[operand.index] = nullptr; 804 ssa_env_->locals[operand.index] = nullptr;
749 } 805 }
750 } 806 }
751 807
752 PopUpTo(c->stack_depth); 808 PopUpTo(c->stack_depth);
753 809
754 break; 810 break;
755 } 811 }
756 case kExprFinally: { 812 case kExprFinally: {
757 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); 813 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
758 if (control_.empty()) { 814 if (control_.empty()) {
759 error(pc_, "finally does not match a any try"); 815 error(pc_, "finally does not match a any try");
760 break; 816 break;
761 } 817 }
762 818
763 Control* c = &control_.back(); 819 Control* c = &control_.back();
764 if (c->has_catch() && c->catch_env != nullptr) { 820 if (c->has_catch() && c->try_info->catch_env != nullptr) {
765 error(pc_, "missing catch for try with catch and finally"); 821 error(pc_, "missing catch for try with catch and finally");
766 break; 822 break;
767 } 823 }
768 824
769 if (!c->has_finally()) { 825 if (!c->has_finally()) {
770 error(pc_, "finally does not match a try with finally"); 826 error(pc_, "finally does not match a try with finally");
771 break; 827 break;
772 } 828 }
773 829
774 if (c->finish_try_env == nullptr) { 830 if (c->try_info->finish_try_env == nullptr) {
775 error(pc_, "finally already present for try with finally"); 831 error(pc_, "finally already present for try with finally");
776 break; 832 break;
777 } 833 }
778 834
779 // ssa_env_ is either the env for either the try or the catch, but 835 // ssa_env_ is either the env for either the try or the catch, but
780 // it does not matter: either way we need to direct the control flow 836 // it does not matter: either way we need to direct the control flow
781 // to the end_env, which is the env for the finally. 837 // to the end_env, which is the env for the finally.
782 // c->finish_try_env is the the environment enclosing the try block. 838 // c->try_info->finish_try_env is the the environment enclosing the
783 Goto(ssa_env_, c->end_env); 839 // try block.
784 840 const bool has_fallthrough = ssa_env_->go();
785 PopUpTo(c->stack_depth); 841 Value val = PopUpTo(c->stack_depth);
842 if (has_fallthrough) {
843 MergeInto(c->end_env, &c->node, &c->type, val);
844 MergeFinallyToken(ssa_env_, c, FallthroughTokenForFinally());
845 }
786 846
787 // The current environment becomes end_env, and finish_try_env 847 // The current environment becomes end_env, and finish_try_env
788 // becomes the new end_env. This ensures that any control flow 848 // becomes the new end_env. This ensures that any control flow
789 // leaving a try block up to now will do so by branching to the 849 // leaving a try block up to now will do so by branching to the
790 // finally block. Setting the end_env to be finish_try_env ensures 850 // finally block. Setting the end_env to be finish_try_env ensures
791 // that kExprEnd below can handle the try block as it would any 851 // that kExprEnd below can handle the try block as it would any
792 // other block construct. 852 // other block construct.
793 SsaEnv* finally_env = c->end_env; 853 SsaEnv* finally_env = c->end_env;
794 c->end_env = c->finish_try_env; 854 c->end_env = c->try_info->finish_try_env;
795 SetEnv("finally:begin", finally_env); 855 SetEnv("finally:begin", finally_env);
796 c->finish_try_env = nullptr; 856 c->try_info->finish_try_env = nullptr;
797 857
858 if (has_fallthrough) {
859 LocalType c_type = c->type;
860 if (c->node == nullptr) {
861 c_type = kAstStmt;
862 }
863 Push(c_type, c->node);
864 }
865
866 c->try_info->has_handled_finally = true;
867 // There's no more need to keep the current control scope in the
868 // finally chain as no more predecessors will be added to c.
869 most_recent_finally_ = c->prev_finally;
798 break; 870 break;
799 } 871 }
800 case kExprLoop: { 872 case kExprLoop: {
801 // The break environment is the outer environment. 873 // The break environment is the outer environment.
802 SsaEnv* break_env = ssa_env_; 874 SsaEnv* break_env = ssa_env_;
803 PushBlock(break_env); 875 PushBlock(break_env);
804 SsaEnv* finish_try_env = Steal(break_env); 876 SsaEnv* finish_try_env = Steal(break_env);
805 // The continue environment is the inner environment. 877 // The continue environment is the inner environment.
806 PrepareForLoop(pc_, finish_try_env); 878 PrepareForLoop(pc_, finish_try_env);
807 SetEnv("loop:start", Split(finish_try_env)); 879 SetEnv("loop:start", Split(finish_try_env));
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 } 912 }
841 Value val = PopUpTo(c->stack_depth); 913 Value val = PopUpTo(c->stack_depth);
842 MergeInto(c->end_env, &c->node, &c->type, val); 914 MergeInto(c->end_env, &c->node, &c->type, val);
843 // Switch to environment for false branch. 915 // Switch to environment for false branch.
844 SetEnv("if_else:false", c->false_env); 916 SetEnv("if_else:false", c->false_env);
845 c->false_env = nullptr; // record that an else is already seen 917 c->false_env = nullptr; // record that an else is already seen
846 break; 918 break;
847 } 919 }
848 case kExprEnd: { 920 case kExprEnd: {
849 if (control_.empty()) { 921 if (control_.empty()) {
850 error(pc_, "end does not match any if or block"); 922 error(pc_, "end does not match any if, try, or block");
851 break; 923 break;
852 } 924 }
853 const char* name = "block:end"; 925 const char* name = "block:end";
854 Control* c = &control_.back(); 926 Control* c = &control_.back();
855 Value val = PopUpTo(c->stack_depth); 927 Value val = PopUpTo(c->stack_depth);
856 if (c->is_loop) { 928 if (c->is_loop) {
857 // Loops always push control in pairs. 929 // Loops always push control in pairs.
858 control_.pop_back(); 930 PopControl();
859 c = &control_.back(); 931 c = &control_.back();
860 name = "loop:end"; 932 name = "loop:end";
861 } else if (c->is_if()) { 933 } else if (c->is_if()) {
862 if (c->false_env != nullptr) { 934 if (c->false_env != nullptr) {
863 // End the true branch of a one-armed if. 935 // End the true branch of a one-armed if.
864 Goto(c->false_env, c->end_env); 936 Goto(c->false_env, c->end_env);
865 val = {val.pc, nullptr, kAstStmt}; 937 val = {val.pc, nullptr, kAstStmt};
866 name = "if:merge"; 938 name = "if:merge";
867 } else { 939 } else {
868 // End the false branch of a two-armed if. 940 // End the false branch of a two-armed if.
869 name = "if_else:merge"; 941 name = "if_else:merge";
870 } 942 }
871 } else if (c->is_try()) { 943 } else if (c->is_try()) {
872 name = "try:end"; 944 name = "try:end";
873 945
874 // try blocks do not yield a value.
875 val = {val.pc, nullptr, kAstStmt};
876
877 // validate that catch/finally were seen. 946 // validate that catch/finally were seen.
878 if (c->catch_env != nullptr) { 947 if (c->try_info->catch_env != nullptr) {
879 error(pc_, "missing catch in try with catch"); 948 error(pc_, "missing catch in try with catch");
880 break; 949 break;
881 } 950 }
882 951
883 if (c->finish_try_env != nullptr) { 952 if (c->try_info->finish_try_env != nullptr) {
884 error(pc_, "missing finally in try with finally"); 953 error(pc_, "missing finally in try with finally");
885 break; 954 break;
886 } 955 }
956
957 if (c->has_finally() && ssa_env_->go()) {
958 DispatchToTargets(c, val);
959 }
887 } 960 }
888 961
889 if (ssa_env_->go()) { 962 if (ssa_env_->go()) {
963 // Adds a fallthrough edge to the next control block.
890 MergeInto(c->end_env, &c->node, &c->type, val); 964 MergeInto(c->end_env, &c->node, &c->type, val);
891 } 965 }
892 SetEnv(name, c->end_env); 966 SetEnv(name, c->end_env);
893 stack_.resize(c->stack_depth); 967 stack_.resize(c->stack_depth);
894 Push(c->type, c->node); 968 Push(c->type, c->node);
895 control_.pop_back(); 969 PopControl();
896 break; 970 break;
897 } 971 }
898 case kExprSelect: { 972 case kExprSelect: {
899 Value cond = Pop(2, kAstI32); 973 Value cond = Pop(2, kAstI32);
900 Value fval = Pop(); 974 Value fval = Pop();
901 Value tval = Pop(); 975 Value tval = Pop();
902 if (tval.type == kAstStmt || tval.type != fval.type) { 976 if (tval.type == kAstStmt || tval.type != fval.type) {
903 if (tval.type != kAstEnd && fval.type != kAstEnd) { 977 if (tval.type != kAstEnd && fval.type != kAstEnd) {
904 error(pc_, "type mismatch in select"); 978 error(pc_, "type mismatch in select");
905 break; 979 break;
(...skipping 13 matching lines...) Expand all
919 } else { 993 } else {
920 Push(tval.type, nullptr); 994 Push(tval.type, nullptr);
921 } 995 }
922 break; 996 break;
923 } 997 }
924 case kExprBr: { 998 case kExprBr: {
925 BreakDepthOperand operand(this, pc_); 999 BreakDepthOperand operand(this, pc_);
926 Value val = {pc_, nullptr, kAstStmt}; 1000 Value val = {pc_, nullptr, kAstStmt};
927 if (operand.arity) val = Pop(); 1001 if (operand.arity) val = Pop();
928 if (Validate(pc_, operand, control_)) { 1002 if (Validate(pc_, operand, control_)) {
929 BreakTo(operand.target, val); 1003 BreakTo(operand, val);
930 } 1004 }
931 len = 1 + operand.length; 1005 len = 1 + operand.length;
932 Push(kAstEnd, nullptr); 1006 Push(kAstEnd, nullptr);
933 break; 1007 break;
934 } 1008 }
935 case kExprBrIf: { 1009 case kExprBrIf: {
936 BreakDepthOperand operand(this, pc_); 1010 BreakDepthOperand operand(this, pc_);
937 Value cond = Pop(operand.arity, kAstI32); 1011 Value cond = Pop(operand.arity, kAstI32);
938 Value val = {pc_, nullptr, kAstStmt}; 1012 Value val = {pc_, nullptr, kAstStmt};
939 if (operand.arity == 1) val = Pop(); 1013 if (operand.arity == 1) val = Pop();
940 if (Validate(pc_, operand, control_)) { 1014 if (Validate(pc_, operand, control_)) {
941 SsaEnv* fenv = ssa_env_; 1015 SsaEnv* fenv = ssa_env_;
942 SsaEnv* tenv = Split(fenv); 1016 SsaEnv* tenv = Split(fenv);
943 fenv->SetNotMerged(); 1017 fenv->SetNotMerged();
944 BUILD(Branch, cond.node, &tenv->control, &fenv->control); 1018 BUILD(Branch, cond.node, &tenv->control, &fenv->control);
945 ssa_env_ = tenv; 1019 ssa_env_ = tenv;
946 BreakTo(operand.target, val); 1020 BreakTo(operand, val);
947 ssa_env_ = fenv; 1021 ssa_env_ = fenv;
948 } 1022 }
949 len = 1 + operand.length; 1023 len = 1 + operand.length;
950 Push(kAstStmt, nullptr); 1024 Push(kAstStmt, nullptr);
951 break; 1025 break;
952 } 1026 }
953 case kExprBrTable: { 1027 case kExprBrTable: {
954 BranchTableOperand operand(this, pc_); 1028 BranchTableOperand operand(this, pc_);
955 if (Validate(pc_, operand, control_.size())) { 1029 if (Validate(pc_, operand, control_.size())) {
956 Value key = Pop(operand.arity, kAstI32); 1030 Value key = Pop(operand.arity, kAstI32);
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
1253 return nullptr; 1327 return nullptr;
1254 } 1328 }
1255 } 1329 }
1256 1330
1257 LocalType GetReturnType(FunctionSig* sig) { 1331 LocalType GetReturnType(FunctionSig* sig) {
1258 return sig->return_count() == 0 ? kAstStmt : sig->GetReturn(); 1332 return sig->return_count() == 0 ? kAstStmt : sig->GetReturn();
1259 } 1333 }
1260 1334
1261 void PushBlock(SsaEnv* end_env) { 1335 void PushBlock(SsaEnv* end_env) {
1262 const int stack_depth = static_cast<int>(stack_.size()); 1336 const int stack_depth = static_cast<int>(stack_.size());
1263 control_.emplace_back(Control::Block(pc_, stack_depth, end_env)); 1337 control_.emplace_back(
1338 Control::Block(pc_, stack_depth, most_recent_finally_, end_env));
1264 } 1339 }
1265 1340
1266 void PushLoop(SsaEnv* end_env) { 1341 void PushLoop(SsaEnv* end_env) {
1267 const int stack_depth = static_cast<int>(stack_.size()); 1342 const int stack_depth = static_cast<int>(stack_.size());
1268 control_.emplace_back(Control::Loop(pc_, stack_depth, end_env)); 1343 control_.emplace_back(
1344 Control::Loop(pc_, stack_depth, most_recent_finally_, end_env));
1269 } 1345 }
1270 1346
1271 void PushIf(SsaEnv* end_env, SsaEnv* false_env) { 1347 void PushIf(SsaEnv* end_env, SsaEnv* false_env) {
1272 const int stack_depth = static_cast<int>(stack_.size()); 1348 const int stack_depth = static_cast<int>(stack_.size());
1273 control_.emplace_back(Control::If(pc_, stack_depth, end_env, false_env)); 1349 control_.emplace_back(Control::If(pc_, stack_depth, most_recent_finally_,
1350 end_env, false_env));
1274 } 1351 }
1275 1352
1276 void PushTry(SsaEnv* end_env, SsaEnv* catch_env, SsaEnv* finish_try_env) { 1353 void PushTry(SsaEnv* end_env, SsaEnv* catch_env, SsaEnv* finish_try_env) {
1277 const int stack_depth = static_cast<int>(stack_.size()); 1354 const int stack_depth = static_cast<int>(stack_.size());
1278 control_.emplace_back( 1355 control_.emplace_back(Control::Try(pc_, stack_depth, most_recent_finally_,
1279 Control::Try(pc_, stack_depth, end_env, catch_env, finish_try_env)); 1356 zone_, end_env, catch_env,
1357 finish_try_env));
1358 if (control_.back().has_finally()) {
1359 most_recent_finally_ = static_cast<uint32_t>(control_.size() - 1);
1360 }
1361 }
1362
1363 void PopControl() {
1364 const Control& c = control_.back();
1365 most_recent_finally_ = c.prev_finally;
1366 control_.pop_back();
1367 // No more accesses to (danging pointer) c
1280 } 1368 }
1281 1369
1282 int DecodeLoadMem(LocalType type, MachineType mem_type) { 1370 int DecodeLoadMem(LocalType type, MachineType mem_type) {
1283 MemoryAccessOperand operand(this, pc_); 1371 MemoryAccessOperand operand(this, pc_);
1284 Value index = Pop(0, kAstI32); 1372 Value index = Pop(0, kAstI32);
1285 TFNode* node = BUILD(LoadMem, type, mem_type, index.node, operand.offset, 1373 TFNode* node = BUILD(LoadMem, type, mem_type, index.node, operand.offset,
1286 operand.alignment, position()); 1374 operand.alignment, position());
1287 Push(type, node); 1375 Push(type, node);
1288 return 1 + operand.length; 1376 return 1 + operand.length;
1289 } 1377 }
(...skipping 12 matching lines...) Expand all
1302 FunctionSig* sig = WasmOpcodes::Signature(opcode); 1390 FunctionSig* sig = WasmOpcodes::Signature(opcode);
1303 compiler::NodeVector inputs(sig->parameter_count(), zone_); 1391 compiler::NodeVector inputs(sig->parameter_count(), zone_);
1304 for (size_t i = sig->parameter_count(); i > 0; i--) { 1392 for (size_t i = sig->parameter_count(); i > 0; i--) {
1305 Value val = Pop(static_cast<int>(i - 1), sig->GetParam(i - 1)); 1393 Value val = Pop(static_cast<int>(i - 1), sig->GetParam(i - 1));
1306 inputs[i - 1] = val.node; 1394 inputs[i - 1] = val.node;
1307 } 1395 }
1308 TFNode* node = BUILD(SimdOp, opcode, inputs); 1396 TFNode* node = BUILD(SimdOp, opcode, inputs);
1309 Push(GetReturnType(sig), node); 1397 Push(GetReturnType(sig), node);
1310 } 1398 }
1311 1399
1400 void DispatchToTargets(Control* next_block, const Value& val) {
1401 const ZoneVector<IncomingBranch>& incoming_branches =
1402 next_block->try_info->incoming_branches;
1403 // Counts how many successors are not current control block.
1404 uint32_t targets = 0;
1405 for (const auto& path_token : incoming_branches) {
1406 if (path_token.target != next_block) ++targets;
1407 }
1408
1409 if (targets == 0) {
1410 // Nothing to do here: the control flow should just fall
1411 // through to the next control block.
1412 return;
1413 }
1414
1415 TFNode* sw = BUILD(Switch, static_cast<uint32_t>(targets + 1),
1416 next_block->try_info->token);
1417
1418 SsaEnv* break_env = ssa_env_;
1419 SsaEnv* copy = Steal(break_env);
1420 for (uint32_t ii = 0; ii < incoming_branches.size(); ++ii) {
1421 Control* t = incoming_branches[ii].target;
1422 if (t != next_block) {
1423 const int32_t token_value = incoming_branches[ii].token_value;
1424 ssa_env_ = Split(copy);
1425 ssa_env_->control = BUILD(IfValue, token_value, sw);
1426 MergeInto(t->end_env, &t->node, &t->type, incoming_branches[ii].val);
1427 // We only need to merge the finally token if t is both a
1428 // try-with-finally and its finally hasn't yet been found
1429 // in the instruction stream. Otherwise we just need to
1430 // branch to t.
1431 if (t->has_finally() && !t->try_info->has_handled_finally) {
1432 MergeFinallyToken(ssa_env_, t, token_value);
1433 }
1434 }
1435 }
1436 ssa_env_ = Split(copy);
1437 ssa_env_->control = BUILD(IfDefault, sw);
1438 MergeInto(next_block->end_env, &next_block->node, &next_block->type, val);
1439 // Not a finally env; no fallthrough token.
1440
1441 ssa_env_ = break_env;
1442 }
1443
1312 void DoReturn() { 1444 void DoReturn() {
1313 int count = static_cast<int>(sig_->return_count()); 1445 int count = static_cast<int>(sig_->return_count());
1314 TFNode** buffer = nullptr; 1446 TFNode** buffer = nullptr;
1315 if (build()) buffer = builder_->Buffer(count); 1447 if (build()) buffer = builder_->Buffer(count);
1316 1448
1317 // Pop return values off the stack in reverse order. 1449 // Pop return values off the stack in reverse order.
1318 for (int i = count - 1; i >= 0; i--) { 1450 for (int i = count - 1; i >= 0; i--) {
1319 Value val = Pop(i, sig_->GetReturn(i)); 1451 Value val = Pop(i, sig_->GetReturn(i));
1320 if (buffer) buffer[i] = val.node; 1452 if (buffer) buffer[i] = val.node;
1321 } 1453 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1368 return val; 1500 return val;
1369 } 1501 }
1370 } 1502 }
1371 1503
1372 int baserel(const byte* ptr) { 1504 int baserel(const byte* ptr) {
1373 return base_ ? static_cast<int>(ptr - base_) : 0; 1505 return base_ ? static_cast<int>(ptr - base_) : 0;
1374 } 1506 }
1375 1507
1376 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); } 1508 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); }
1377 1509
1378 void BreakTo(Control* block, Value& val) { 1510 Control* BuildFinallyChain(const BreakDepthOperand& operand, const Value& val,
1511 int32_t* token) {
1512 DCHECK_LE(operand.depth, control_.size());
1513 const int32_t target_index =
1514 static_cast<uint32_t>(control_.size() - operand.depth - 1);
1515
1516 if (most_recent_finally_ == kNullFinallyToken || // No finallies.
1517 most_recent_finally_ < target_index) { // Does not cross any finally.
1518 *token = kNullFinallyToken;
1519 return operand.target;
1520 }
1521
1522 Control* previous_control = &control_[most_recent_finally_];
1523 *token = NewTokenForFinally();
1524
1525 for (int32_t ii = previous_control->prev_finally; ii >= target_index;
1526 ii = previous_control->prev_finally) {
1527 Control* current_finally = &control_[ii];
1528
1529 DCHECK(!current_finally->try_info->has_handled_finally);
1530 previous_control->try_info->incoming_branches.push_back(
1531 {*token, current_finally, val});
1532 previous_control = current_finally;
1533 }
1534
1535 if (operand.target != previous_control) {
1536 DCHECK_NOT_NULL(previous_control);
1537 DCHECK(previous_control->has_finally());
1538 DCHECK_NE(*token, kNullFinallyToken);
1539 previous_control->try_info->incoming_branches.push_back(
1540 {*token, operand.target, val});
1541 }
1542
1543 return &control_[most_recent_finally_];
1544 }
1545
1546 void BreakTo(const BreakDepthOperand& operand, const Value& val) {
1547 int32_t finally_token;
1548 Control* block = BuildFinallyChain(operand, val, &finally_token);
1549
1379 if (block->is_loop) { 1550 if (block->is_loop) {
1380 // This is the inner loop block, which does not have a value. 1551 // This is the inner loop block, which does not have a value.
1381 Goto(ssa_env_, block->end_env); 1552 Goto(ssa_env_, block->end_env);
1382 } else { 1553 } else {
1383 // Merge the value into the production for the block. 1554 // Merge the value into the production for the block.
1384 MergeInto(block->end_env, &block->node, &block->type, val); 1555 MergeInto(block->end_env, &block->node, &block->type, val);
1385 } 1556 }
1557
1558 if (finally_token != kNullFinallyToken) {
1559 MergeFinallyToken(ssa_env_, block, finally_token);
1560 }
1386 } 1561 }
1387 1562
1388 void MergeInto(SsaEnv* target, TFNode** node, LocalType* type, Value& val) { 1563 void MergeInto(SsaEnv* target, TFNode** node, LocalType* type,
1564 const Value& val) {
1389 if (!ssa_env_->go()) return; 1565 if (!ssa_env_->go()) return;
1390 DCHECK_NE(kAstEnd, val.type); 1566 DCHECK_NE(kAstEnd, val.type);
1391 1567
1392 bool first = target->state == SsaEnv::kUnreachable; 1568 bool first = target->state == SsaEnv::kUnreachable;
1393 Goto(ssa_env_, target); 1569 Goto(ssa_env_, target);
1394 1570
1395 if (first) { 1571 if (first) {
1396 // first merge to this environment; set the type and the node. 1572 // first merge to this environment; set the type and the node.
1397 *type = val.type; 1573 *type = val.type;
1398 *node = val.node; 1574 *node = val.node;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1435 PrintF("\n"); 1611 PrintF("\n");
1436 } 1612 }
1437 #endif 1613 #endif
1438 ssa_env_ = env; 1614 ssa_env_ = env;
1439 if (builder_) { 1615 if (builder_) {
1440 builder_->set_control_ptr(&env->control); 1616 builder_->set_control_ptr(&env->control);
1441 builder_->set_effect_ptr(&env->effect); 1617 builder_->set_effect_ptr(&env->effect);
1442 } 1618 }
1443 } 1619 }
1444 1620
1621 void MergeFinallyToken(SsaEnv*, Control* to, int32_t new_token) {
1622 DCHECK(to->has_finally());
1623 DCHECK(!to->try_info->has_handled_finally);
1624 if (builder_ == nullptr) {
1625 return;
1626 }
1627
1628 switch (to->end_env->state) {
1629 case SsaEnv::kReached:
1630 DCHECK(to->try_info->token == nullptr);
1631 to->try_info->token = builder_->Int32Constant(new_token);
1632 break;
1633 case SsaEnv::kMerged:
1634 DCHECK_NOT_NULL(to->try_info->token);
1635 to->try_info->token = CreateOrMergeIntoPhi(
1636 kAstI32, to->end_env->control, to->try_info->token,
1637 builder_->Int32Constant(new_token));
1638 break;
1639 case SsaEnv::kUnreachable:
1640 UNREACHABLE();
1641 // fallthrough intended.
1642 default:
1643 break;
1644 }
1645 }
1646
1445 void Goto(SsaEnv* from, SsaEnv* to) { 1647 void Goto(SsaEnv* from, SsaEnv* to) {
1446 DCHECK_NOT_NULL(to); 1648 DCHECK_NOT_NULL(to);
1447 if (!from->go()) return; 1649 if (!from->go()) return;
1448 switch (to->state) { 1650 switch (to->state) {
1449 case SsaEnv::kUnreachable: { // Overwrite destination. 1651 case SsaEnv::kUnreachable: { // Overwrite destination.
1450 to->state = SsaEnv::kReached; 1652 to->state = SsaEnv::kReached;
1451 to->locals = from->locals; 1653 to->locals = from->locals;
1452 to->control = from->control; 1654 to->control = from->control;
1453 to->effect = from->effect; 1655 to->effect = from->effect;
1454 break; 1656 break;
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after
1852 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, 2054 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
1853 const byte* start, const byte* end) { 2055 const byte* start, const byte* end) {
1854 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; 2056 FunctionBody body = {nullptr, nullptr, nullptr, start, end};
1855 WasmFullDecoder decoder(zone, nullptr, body); 2057 WasmFullDecoder decoder(zone, nullptr, body);
1856 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); 2058 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals);
1857 } 2059 }
1858 2060
1859 } // namespace wasm 2061 } // namespace wasm
1860 } // namespace internal 2062 } // namespace internal
1861 } // namespace v8 2063 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | test/cctest/cctest.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698