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

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: Fixes broken windows build Created 4 years, 4 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/wasm/test-run-wasm.cc » ('j') | test/cctest/wasm/test-run-wasm.cc » ('J')
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 // PathToken is used by exception handling code for managing finally's.
74 struct PathToken {
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.
John 2016/08/22 13:36:34 s/EH/TryInfo/g
82 struct EH {
83 SsaEnv* catch_env; // catch environment (only for try with catch).
84 SsaEnv* finish_try_env; // the environment where a try with finally lives.
John 2016/08/22 13:36:34 Well, this is not the environment for the finally,
85 ZoneVector<PathToken> path_tokens;
86 TFNode* token;
87 bool has_handled_finally;
88
89 EH(Zone* zone, SsaEnv* c, SsaEnv* f)
90 : catch_env(c),
91 finish_try_env(f),
92 path_tokens(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 EH* eh; // exception handling stuff. See EH 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->New(sizeof(EH))) EH(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 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 // a TurboFan IR graph. 467 // a TurboFan IR graph.
428 class WasmFullDecoder : public WasmDecoder { 468 class WasmFullDecoder : public WasmDecoder {
429 public: 469 public:
430 WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body) 470 WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body)
431 : WasmDecoder(body.module, body.sig, body.start, body.end), 471 : WasmDecoder(body.module, body.sig, body.start, body.end),
432 zone_(zone), 472 zone_(zone),
433 builder_(builder), 473 builder_(builder),
434 base_(body.base), 474 base_(body.base),
435 local_type_vec_(zone), 475 local_type_vec_(zone),
436 stack_(zone), 476 stack_(zone),
437 control_(zone) { 477 control_(zone),
478 most_recent_finally_(-1),
479 finally_token_val_(kFirstFinallyToken) {
438 local_types_ = &local_type_vec_; 480 local_types_ = &local_type_vec_;
439 } 481 }
440 482
441 bool Decode() { 483 bool Decode() {
442 base::ElapsedTimer decode_timer; 484 base::ElapsedTimer decode_timer;
443 if (FLAG_trace_wasm_decode_time) { 485 if (FLAG_trace_wasm_decode_time) {
444 decode_timer.Start(); 486 decode_timer.Start();
445 } 487 }
446 stack_.clear(); 488 stack_.clear();
447 control_.clear(); 489 control_.clear();
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 Zone* zone_; 562 Zone* zone_;
521 TFBuilder* builder_; 563 TFBuilder* builder_;
522 const byte* base_; 564 const byte* base_;
523 565
524 SsaEnv* ssa_env_; 566 SsaEnv* ssa_env_;
525 567
526 ZoneVector<LocalType> local_type_vec_; // types of local variables. 568 ZoneVector<LocalType> local_type_vec_; // types of local variables.
527 ZoneVector<Value> stack_; // stack of values. 569 ZoneVector<Value> stack_; // stack of values.
528 ZoneVector<Control> control_; // stack of blocks, loops, and ifs. 570 ZoneVector<Control> control_; // stack of blocks, loops, and ifs.
529 571
572 int32_t most_recent_finally_;
573 int32_t finally_token_val_;
574 static const int32_t kFirstFinallyToken;
575 static const int32_t kFallthroughToken;
576 static const int32_t kNullFinallyToken;
577
578 int32_t FallthroughTokenForFinally() {
579 // Any number < kFirstFinallyToken would work.
580 return kFallthroughToken;
581 }
582
583 int32_t NewPathTokenForFinally() { return finally_token_val_++; }
584
530 inline bool build() { return builder_ && ssa_env_->go(); } 585 inline bool build() { return builder_ && ssa_env_->go(); }
531 586
532 void InitSsaEnv() { 587 void InitSsaEnv() {
533 TFNode* start = nullptr; 588 TFNode* start = nullptr;
534 SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv))); 589 SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
535 size_t size = sizeof(TFNode*) * EnvironmentCount(); 590 size_t size = sizeof(TFNode*) * EnvironmentCount();
536 ssa_env->state = SsaEnv::kReached; 591 ssa_env->state = SsaEnv::kReached;
537 ssa_env->locals = 592 ssa_env->locals =
538 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr; 593 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
539 594
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 error(pc_, "catch does not match a any try"); 778 error(pc_, "catch does not match a any try");
724 break; 779 break;
725 } 780 }
726 781
727 Control* c = &control_.back(); 782 Control* c = &control_.back();
728 if (!c->has_catch()) { 783 if (!c->has_catch()) {
729 error(pc_, "catch does not match a try with catch"); 784 error(pc_, "catch does not match a try with catch");
730 break; 785 break;
731 } 786 }
732 787
733 if (c->catch_env == nullptr) { 788 if (c->eh->catch_env == nullptr) {
734 error(pc_, "catch already present for try with catch"); 789 error(pc_, "catch already present for try with catch");
735 break; 790 break;
736 } 791 }
737 792
738 Goto(ssa_env_, c->end_env); 793 Goto(ssa_env_, c->end_env);
739 794
740 SsaEnv* catch_env = c->catch_env; 795 SsaEnv* catch_env = c->eh->catch_env;
741 c->catch_env = nullptr; 796 c->eh->catch_env = nullptr;
742 SetEnv("catch:begin", catch_env); 797 SetEnv("catch:begin", catch_env);
743 798
744 if (Validate(pc_, operand)) { 799 if (Validate(pc_, operand)) {
745 // TODO(jpp): figure out how thrown value is propagated. It is 800 // TODO(jpp): figure out how thrown value is propagated. It is
746 // unlikely to be a value on the stack. 801 // unlikely to be a value on the stack.
747 if (ssa_env_->locals) { 802 if (ssa_env_->locals) {
748 ssa_env_->locals[operand.index] = nullptr; 803 ssa_env_->locals[operand.index] = nullptr;
749 } 804 }
750 } 805 }
751 806
752 PopUpTo(c->stack_depth); 807 PopUpTo(c->stack_depth);
753 808
754 break; 809 break;
755 } 810 }
756 case kExprFinally: { 811 case kExprFinally: {
757 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); 812 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
758 if (control_.empty()) { 813 if (control_.empty()) {
759 error(pc_, "finally does not match a any try"); 814 error(pc_, "finally does not match a any try");
760 break; 815 break;
761 } 816 }
762 817
763 Control* c = &control_.back(); 818 Control* c = &control_.back();
764 if (c->has_catch() && c->catch_env != nullptr) { 819 if (c->has_catch() && c->eh->catch_env != nullptr) {
765 error(pc_, "missing catch for try with catch and finally"); 820 error(pc_, "missing catch for try with catch and finally");
766 break; 821 break;
767 } 822 }
768 823
769 if (!c->has_finally()) { 824 if (!c->has_finally()) {
770 error(pc_, "finally does not match a try with finally"); 825 error(pc_, "finally does not match a try with finally");
771 break; 826 break;
772 } 827 }
773 828
774 if (c->finish_try_env == nullptr) { 829 if (c->eh->finish_try_env == nullptr) {
775 error(pc_, "finally already present for try with finally"); 830 error(pc_, "finally already present for try with finally");
776 break; 831 break;
777 } 832 }
778 833
779 // ssa_env_ is either the env for either the try or the catch, but 834 // 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 835 // 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. 836 // to the end_env, which is the env for the finally.
782 // c->finish_try_env is the the environment enclosing the try block. 837 // c->eh->finish_try_env is the the environment enclosing the try
783 Goto(ssa_env_, c->end_env); 838 // block.
784 839 const bool has_fallthrough = ssa_env_->go();
785 PopUpTo(c->stack_depth); 840 Value val = PopUpTo(c->stack_depth);
841 if (has_fallthrough) {
842 MergeInto(c->end_env, &c->node, &c->type, val);
843 MergeFinallyToken(ssa_env_, c, FallthroughTokenForFinally());
844 }
786 845
787 // The current environment becomes end_env, and finish_try_env 846 // The current environment becomes end_env, and finish_try_env
788 // becomes the new end_env. This ensures that any control flow 847 // 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 848 // 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 849 // 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 850 // that kExprEnd below can handle the try block as it would any
792 // other block construct. 851 // other block construct.
793 SsaEnv* finally_env = c->end_env; 852 SsaEnv* finally_env = c->end_env;
794 c->end_env = c->finish_try_env; 853 c->end_env = c->eh->finish_try_env;
795 SetEnv("finally:begin", finally_env); 854 SetEnv("finally:begin", finally_env);
796 c->finish_try_env = nullptr; 855 c->eh->finish_try_env = nullptr;
797 856
857 if (has_fallthrough) {
858 LocalType c_type = c->type;
859 if (c->node == nullptr) {
860 c_type = kAstStmt;
861 }
862 Push(c_type, c->node);
863 }
864
865 c->eh->has_handled_finally = true;
866 // There's no more need to keep the current control scope in the
867 // finally chain as no more predecessors will be added to c.
868 most_recent_finally_ = c->prev_finally;
798 break; 869 break;
799 } 870 }
800 case kExprLoop: { 871 case kExprLoop: {
801 // The break environment is the outer environment. 872 // The break environment is the outer environment.
802 SsaEnv* break_env = ssa_env_; 873 SsaEnv* break_env = ssa_env_;
803 PushBlock(break_env); 874 PushBlock(break_env);
804 SsaEnv* finish_try_env = Steal(break_env); 875 SsaEnv* finish_try_env = Steal(break_env);
805 // The continue environment is the inner environment. 876 // The continue environment is the inner environment.
806 PrepareForLoop(pc_, finish_try_env); 877 PrepareForLoop(pc_, finish_try_env);
807 SetEnv("loop:start", Split(finish_try_env)); 878 SetEnv("loop:start", Split(finish_try_env));
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 } 911 }
841 Value val = PopUpTo(c->stack_depth); 912 Value val = PopUpTo(c->stack_depth);
842 MergeInto(c->end_env, &c->node, &c->type, val); 913 MergeInto(c->end_env, &c->node, &c->type, val);
843 // Switch to environment for false branch. 914 // Switch to environment for false branch.
844 SetEnv("if_else:false", c->false_env); 915 SetEnv("if_else:false", c->false_env);
845 c->false_env = nullptr; // record that an else is already seen 916 c->false_env = nullptr; // record that an else is already seen
846 break; 917 break;
847 } 918 }
848 case kExprEnd: { 919 case kExprEnd: {
849 if (control_.empty()) { 920 if (control_.empty()) {
850 error(pc_, "end does not match any if or block"); 921 error(pc_, "end does not match any if, try, or block");
851 break; 922 break;
852 } 923 }
853 const char* name = "block:end"; 924 const char* name = "block:end";
854 Control* c = &control_.back(); 925 Control* c = &control_.back();
855 Value val = PopUpTo(c->stack_depth); 926 Value val = PopUpTo(c->stack_depth);
856 if (c->is_loop) { 927 if (c->is_loop) {
857 // Loops always push control in pairs. 928 // Loops always push control in pairs.
858 control_.pop_back(); 929 PopControl();
859 c = &control_.back(); 930 c = &control_.back();
860 name = "loop:end"; 931 name = "loop:end";
861 } else if (c->is_if()) { 932 } else if (c->is_if()) {
862 if (c->false_env != nullptr) { 933 if (c->false_env != nullptr) {
863 // End the true branch of a one-armed if. 934 // End the true branch of a one-armed if.
864 Goto(c->false_env, c->end_env); 935 Goto(c->false_env, c->end_env);
865 val = {val.pc, nullptr, kAstStmt}; 936 val = {val.pc, nullptr, kAstStmt};
866 name = "if:merge"; 937 name = "if:merge";
867 } else { 938 } else {
868 // End the false branch of a two-armed if. 939 // End the false branch of a two-armed if.
869 name = "if_else:merge"; 940 name = "if_else:merge";
870 } 941 }
871 } else if (c->is_try()) { 942 } else if (c->is_try()) {
872 name = "try:end"; 943 name = "try:end";
873 944
874 // try blocks do not yield a value.
875 val = {val.pc, nullptr, kAstStmt};
876
877 // validate that catch/finally were seen. 945 // validate that catch/finally were seen.
878 if (c->catch_env != nullptr) { 946 if (c->eh->catch_env != nullptr) {
879 error(pc_, "missing catch in try with catch"); 947 error(pc_, "missing catch in try with catch");
880 break; 948 break;
881 } 949 }
882 950
883 if (c->finish_try_env != nullptr) { 951 if (c->eh->finish_try_env != nullptr) {
884 error(pc_, "missing finally in try with finally"); 952 error(pc_, "missing finally in try with finally");
885 break; 953 break;
886 } 954 }
955
956 if (c->has_finally() && ssa_env_->go()) {
957 // finally -> dispatch on the path token
958 const ZoneVector<PathToken>& path_tokens = c->eh->path_tokens;
959 uint32_t targets = 0;
960 for (const auto& path_token : path_tokens) {
961 if (path_token.target != c) ++targets;
962 }
963
964 SsaEnv* break_env = ssa_env_;
965 if (targets == 0) {
966 // Nothing to do
967 } else {
968 TFNode* sw = BUILD(Switch, static_cast<uint32_t>(targets + 1),
969 c->eh->token);
970
971 SsaEnv* copy = Steal(break_env);
972 for (uint32_t ii = 0; ii < path_tokens.size(); ++ii) {
973 Control* t = path_tokens[ii].target;
974 if (t != c) {
975 const int32_t token_value = path_tokens[ii].token_value;
976 ssa_env_ = Split(copy);
977 ssa_env_->control = BUILD(IfValue, token_value, sw);
978 MergeInto(t->end_env, &t->node, &t->type,
979 path_tokens[ii].val);
980 MergeFinallyToken(ssa_env_, t, token_value);
981 }
982 }
983 ssa_env_ = Split(copy);
984 ssa_env_->control = BUILD(IfDefault, sw);
985 Control* t = c;
986 MergeInto(t->end_env, &t->node, &t->type, val);
987 // Not a finally env; no fallthrough token.
988 }
989 ssa_env_ = break_env;
990 }
887 } 991 }
888 992
889 if (ssa_env_->go()) { 993 if (ssa_env_->go()) {
890 MergeInto(c->end_env, &c->node, &c->type, val); 994 MergeInto(c->end_env, &c->node, &c->type, val);
891 } 995 }
892 SetEnv(name, c->end_env); 996 SetEnv(name, c->end_env);
893 stack_.resize(c->stack_depth); 997 stack_.resize(c->stack_depth);
894 Push(c->type, c->node); 998 Push(c->type, c->node);
895 control_.pop_back(); 999 PopControl();
896 break; 1000 break;
897 } 1001 }
898 case kExprSelect: { 1002 case kExprSelect: {
899 Value cond = Pop(2, kAstI32); 1003 Value cond = Pop(2, kAstI32);
900 Value fval = Pop(); 1004 Value fval = Pop();
901 Value tval = Pop(); 1005 Value tval = Pop();
902 if (tval.type == kAstStmt || tval.type != fval.type) { 1006 if (tval.type == kAstStmt || tval.type != fval.type) {
903 if (tval.type != kAstEnd && fval.type != kAstEnd) { 1007 if (tval.type != kAstEnd && fval.type != kAstEnd) {
904 error(pc_, "type mismatch in select"); 1008 error(pc_, "type mismatch in select");
905 break; 1009 break;
(...skipping 13 matching lines...) Expand all
919 } else { 1023 } else {
920 Push(tval.type, nullptr); 1024 Push(tval.type, nullptr);
921 } 1025 }
922 break; 1026 break;
923 } 1027 }
924 case kExprBr: { 1028 case kExprBr: {
925 BreakDepthOperand operand(this, pc_); 1029 BreakDepthOperand operand(this, pc_);
926 Value val = {pc_, nullptr, kAstStmt}; 1030 Value val = {pc_, nullptr, kAstStmt};
927 if (operand.arity) val = Pop(); 1031 if (operand.arity) val = Pop();
928 if (Validate(pc_, operand, control_)) { 1032 if (Validate(pc_, operand, control_)) {
929 BreakTo(operand.target, val); 1033 BreakTo(operand, val);
930 } 1034 }
931 len = 1 + operand.length; 1035 len = 1 + operand.length;
932 Push(kAstEnd, nullptr); 1036 Push(kAstEnd, nullptr);
933 break; 1037 break;
934 } 1038 }
935 case kExprBrIf: { 1039 case kExprBrIf: {
936 BreakDepthOperand operand(this, pc_); 1040 BreakDepthOperand operand(this, pc_);
937 Value cond = Pop(operand.arity, kAstI32); 1041 Value cond = Pop(operand.arity, kAstI32);
938 Value val = {pc_, nullptr, kAstStmt}; 1042 Value val = {pc_, nullptr, kAstStmt};
939 if (operand.arity == 1) val = Pop(); 1043 if (operand.arity == 1) val = Pop();
940 if (Validate(pc_, operand, control_)) { 1044 if (Validate(pc_, operand, control_)) {
941 SsaEnv* fenv = ssa_env_; 1045 SsaEnv* fenv = ssa_env_;
942 SsaEnv* tenv = Split(fenv); 1046 SsaEnv* tenv = Split(fenv);
943 fenv->SetNotMerged(); 1047 fenv->SetNotMerged();
944 BUILD(Branch, cond.node, &tenv->control, &fenv->control); 1048 BUILD(Branch, cond.node, &tenv->control, &fenv->control);
945 ssa_env_ = tenv; 1049 ssa_env_ = tenv;
946 BreakTo(operand.target, val); 1050 BreakTo(operand, val);
947 ssa_env_ = fenv; 1051 ssa_env_ = fenv;
948 } 1052 }
949 len = 1 + operand.length; 1053 len = 1 + operand.length;
950 Push(kAstStmt, nullptr); 1054 Push(kAstStmt, nullptr);
951 break; 1055 break;
952 } 1056 }
953 case kExprBrTable: { 1057 case kExprBrTable: {
954 BranchTableOperand operand(this, pc_); 1058 BranchTableOperand operand(this, pc_);
955 if (Validate(pc_, operand, control_.size())) { 1059 if (Validate(pc_, operand, control_.size())) {
956 Value key = Pop(operand.arity, kAstI32); 1060 Value key = Pop(operand.arity, kAstI32);
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
1253 return nullptr; 1357 return nullptr;
1254 } 1358 }
1255 } 1359 }
1256 1360
1257 LocalType GetReturnType(FunctionSig* sig) { 1361 LocalType GetReturnType(FunctionSig* sig) {
1258 return sig->return_count() == 0 ? kAstStmt : sig->GetReturn(); 1362 return sig->return_count() == 0 ? kAstStmt : sig->GetReturn();
1259 } 1363 }
1260 1364
1261 void PushBlock(SsaEnv* end_env) { 1365 void PushBlock(SsaEnv* end_env) {
1262 const int stack_depth = static_cast<int>(stack_.size()); 1366 const int stack_depth = static_cast<int>(stack_.size());
1263 control_.emplace_back(Control::Block(pc_, stack_depth, end_env)); 1367 control_.emplace_back(
1368 Control::Block(pc_, stack_depth, most_recent_finally_, end_env));
1264 } 1369 }
1265 1370
1266 void PushLoop(SsaEnv* end_env) { 1371 void PushLoop(SsaEnv* end_env) {
1267 const int stack_depth = static_cast<int>(stack_.size()); 1372 const int stack_depth = static_cast<int>(stack_.size());
1268 control_.emplace_back(Control::Loop(pc_, stack_depth, end_env)); 1373 control_.emplace_back(
1374 Control::Loop(pc_, stack_depth, most_recent_finally_, end_env));
1269 } 1375 }
1270 1376
1271 void PushIf(SsaEnv* end_env, SsaEnv* false_env) { 1377 void PushIf(SsaEnv* end_env, SsaEnv* false_env) {
1272 const int stack_depth = static_cast<int>(stack_.size()); 1378 const int stack_depth = static_cast<int>(stack_.size());
1273 control_.emplace_back(Control::If(pc_, stack_depth, end_env, false_env)); 1379 control_.emplace_back(Control::If(pc_, stack_depth, most_recent_finally_,
1380 end_env, false_env));
1274 } 1381 }
1275 1382
1276 void PushTry(SsaEnv* end_env, SsaEnv* catch_env, SsaEnv* finish_try_env) { 1383 void PushTry(SsaEnv* end_env, SsaEnv* catch_env, SsaEnv* finish_try_env) {
1277 const int stack_depth = static_cast<int>(stack_.size()); 1384 const int stack_depth = static_cast<int>(stack_.size());
1278 control_.emplace_back( 1385 control_.emplace_back(Control::Try(pc_, stack_depth, most_recent_finally_,
1279 Control::Try(pc_, stack_depth, end_env, catch_env, finish_try_env)); 1386 zone_, end_env, catch_env,
1387 finish_try_env));
1388 if (control_.back().has_finally()) {
1389 most_recent_finally_ = static_cast<uint32_t>(control_.size() - 1);
1390 }
1391 }
1392
1393 void PopControl() {
1394 const Control& c = control_.back();
1395 most_recent_finally_ = c.prev_finally;
1396 control_.pop_back();
1397 // No more accesses to (danging pointer) c
1280 } 1398 }
1281 1399
1282 int DecodeLoadMem(LocalType type, MachineType mem_type) { 1400 int DecodeLoadMem(LocalType type, MachineType mem_type) {
1283 MemoryAccessOperand operand(this, pc_); 1401 MemoryAccessOperand operand(this, pc_);
1284 Value index = Pop(0, kAstI32); 1402 Value index = Pop(0, kAstI32);
1285 TFNode* node = BUILD(LoadMem, type, mem_type, index.node, operand.offset, 1403 TFNode* node = BUILD(LoadMem, type, mem_type, index.node, operand.offset,
1286 operand.alignment, position()); 1404 operand.alignment, position());
1287 Push(type, node); 1405 Push(type, node);
1288 return 1 + operand.length; 1406 return 1 + operand.length;
1289 } 1407 }
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1368 return val; 1486 return val;
1369 } 1487 }
1370 } 1488 }
1371 1489
1372 int baserel(const byte* ptr) { 1490 int baserel(const byte* ptr) {
1373 return base_ ? static_cast<int>(ptr - base_) : 0; 1491 return base_ ? static_cast<int>(ptr - base_) : 0;
1374 } 1492 }
1375 1493
1376 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); } 1494 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); }
1377 1495
1378 void BreakTo(Control* block, Value& val) { 1496 Control* StichFinallyChain(const BreakDepthOperand& operand, const Value& val,
John 2016/08/22 13:36:34 This method builds the finally chain. s/StichFinal
1497 int32_t* token) {
1498 const int32_t target_index =
1499 static_cast<uint32_t>(control_.size() - operand.depth - 1);
1500
1501 *token = kNullFinallyToken;
1502 Control* first_control = nullptr;
1503 Control* previous_control = nullptr;
1504
1505 for (int32_t ii = most_recent_finally_; ii >= target_index;
1506 ii = previous_control->prev_finally) {
1507 Control* current_finally = &control_[ii];
1508
1509 DCHECK(!current_finally->eh->has_handled_finally);
1510 if (first_control == nullptr) {
1511 *token = NewPathTokenForFinally();
1512 first_control = current_finally;
1513 } else {
1514 previous_control->eh->path_tokens.push_back(
1515 {*token, current_finally, val});
1516 }
1517 previous_control = current_finally;
1518 }
1519
1520 if (first_control == nullptr) {
1521 // No finally between ssa_env_ and operand.target.
1522 DCHECK(!operand.target->has_finally());
1523 DCHECK_EQ(*token, kNullFinallyToken);
1524 return operand.target;
1525 }
1526
1527 if (operand.target != previous_control) {
1528 DCHECK_NOT_NULL(previous_control);
1529 DCHECK(previous_control->has_finally());
1530 DCHECK_NE(*token, kNullFinallyToken);
1531 previous_control->eh->path_tokens.push_back(
1532 {*token, operand.target, val});
1533 }
1534
1535 return first_control;
1536 }
1537
1538 void BreakTo(const BreakDepthOperand& operand, const Value& val) {
1539 int32_t finally_token;
1540 Control* block = StichFinallyChain(operand, val, &finally_token);
1541
1379 if (block->is_loop) { 1542 if (block->is_loop) {
1380 // This is the inner loop block, which does not have a value. 1543 // This is the inner loop block, which does not have a value.
1381 Goto(ssa_env_, block->end_env); 1544 Goto(ssa_env_, block->end_env);
1382 } else { 1545 } else {
1383 // Merge the value into the production for the block. 1546 // Merge the value into the production for the block.
1384 MergeInto(block->end_env, &block->node, &block->type, val); 1547 MergeInto(block->end_env, &block->node, &block->type, val);
1385 } 1548 }
1549
1550 if (finally_token != kNullFinallyToken) {
1551 MergeFinallyToken(ssa_env_, block, finally_token);
1552 }
1386 } 1553 }
1387 1554
1388 void MergeInto(SsaEnv* target, TFNode** node, LocalType* type, Value& val) { 1555 void MergeInto(SsaEnv* target, TFNode** node, LocalType* type,
1556 const Value& val) {
1389 if (!ssa_env_->go()) return; 1557 if (!ssa_env_->go()) return;
1390 DCHECK_NE(kAstEnd, val.type); 1558 DCHECK_NE(kAstEnd, val.type);
1391 1559
1392 bool first = target->state == SsaEnv::kUnreachable; 1560 bool first = target->state == SsaEnv::kUnreachable;
1393 Goto(ssa_env_, target); 1561 Goto(ssa_env_, target);
1394 1562
1395 if (first) { 1563 if (first) {
1396 // first merge to this environment; set the type and the node. 1564 // first merge to this environment; set the type and the node.
1397 *type = val.type; 1565 *type = val.type;
1398 *node = val.node; 1566 *node = val.node;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1435 PrintF("\n"); 1603 PrintF("\n");
1436 } 1604 }
1437 #endif 1605 #endif
1438 ssa_env_ = env; 1606 ssa_env_ = env;
1439 if (builder_) { 1607 if (builder_) {
1440 builder_->set_control_ptr(&env->control); 1608 builder_->set_control_ptr(&env->control);
1441 builder_->set_effect_ptr(&env->effect); 1609 builder_->set_effect_ptr(&env->effect);
1442 } 1610 }
1443 } 1611 }
1444 1612
1613 void MergeFinallyToken(SsaEnv*, Control* to, int32_t new_token) {
1614 DCHECK(to->has_finally());
1615 DCHECK(!to->eh->has_handled_finally);
1616 if (builder_ == nullptr) {
1617 return;
1618 }
1619
1620 switch (to->end_env->state) {
1621 case SsaEnv::kReached:
1622 DCHECK(to->eh->token == nullptr);
1623 to->eh->token = builder_->Int32Constant(new_token);
1624 break;
1625 case SsaEnv::kMerged:
1626 DCHECK_NOT_NULL(to->eh->token);
1627 to->eh->token =
1628 CreateOrMergeIntoPhi(kAstI32, to->end_env->control, to->eh->token,
1629 builder_->Int32Constant(new_token));
1630 break;
1631 case SsaEnv::kUnreachable:
1632 UNREACHABLE();
1633 // fallthrough intended.
1634 default:
1635 break;
1636 }
1637 }
1638
1445 void Goto(SsaEnv* from, SsaEnv* to) { 1639 void Goto(SsaEnv* from, SsaEnv* to) {
1446 DCHECK_NOT_NULL(to); 1640 DCHECK_NOT_NULL(to);
1447 if (!from->go()) return; 1641 if (!from->go()) return;
1448 switch (to->state) { 1642 switch (to->state) {
1449 case SsaEnv::kUnreachable: { // Overwrite destination. 1643 case SsaEnv::kUnreachable: { // Overwrite destination.
1450 to->state = SsaEnv::kReached; 1644 to->state = SsaEnv::kReached;
1451 to->locals = from->locals; 1645 to->locals = from->locals;
1452 to->control = from->control; 1646 to->control = from->control;
1453 to->effect = from->effect; 1647 to->effect = from->effect;
1454 break; 1648 break;
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
1659 return ok() ? assigned : nullptr; 1853 return ok() ? assigned : nullptr;
1660 } 1854 }
1661 1855
1662 inline wasm::WasmCodePosition position() { 1856 inline wasm::WasmCodePosition position() {
1663 int offset = static_cast<int>(pc_ - start_); 1857 int offset = static_cast<int>(pc_ - start_);
1664 DCHECK_EQ(pc_ - start_, offset); // overflows cannot happen 1858 DCHECK_EQ(pc_ - start_, offset); // overflows cannot happen
1665 return offset; 1859 return offset;
1666 } 1860 }
1667 }; 1861 };
1668 1862
1863 const int32_t WasmFullDecoder::kFirstFinallyToken = 1000;
John 2016/08/22 13:36:34 I can make them local, but having them "inside" th
1864 const int32_t WasmFullDecoder::kFallthroughToken = 100;
1865 const int32_t WasmFullDecoder::kNullFinallyToken = -1;
1866
1669 bool DecodeLocalDecls(AstLocalDecls& decls, const byte* start, 1867 bool DecodeLocalDecls(AstLocalDecls& decls, const byte* start,
1670 const byte* end) { 1868 const byte* end) {
1671 base::AccountingAllocator allocator; 1869 base::AccountingAllocator allocator;
1672 Zone tmp(&allocator); 1870 Zone tmp(&allocator);
1673 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; 1871 FunctionBody body = {nullptr, nullptr, nullptr, start, end};
1674 WasmFullDecoder decoder(&tmp, nullptr, body); 1872 WasmFullDecoder decoder(&tmp, nullptr, body);
1675 return decoder.DecodeLocalDecls(decls); 1873 return decoder.DecodeLocalDecls(decls);
1676 } 1874 }
1677 1875
1678 BytecodeIterator::BytecodeIterator(const byte* start, const byte* end, 1876 BytecodeIterator::BytecodeIterator(const byte* start, const byte* end,
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
1852 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, 2050 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
1853 const byte* start, const byte* end) { 2051 const byte* start, const byte* end) {
1854 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; 2052 FunctionBody body = {nullptr, nullptr, nullptr, start, end};
1855 WasmFullDecoder decoder(zone, nullptr, body); 2053 WasmFullDecoder decoder(zone, nullptr, body);
1856 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); 2054 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals);
1857 } 2055 }
1858 2056
1859 } // namespace wasm 2057 } // namespace wasm
1860 } // namespace internal 2058 } // namespace internal
1861 } // namespace v8 2059 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | test/cctest/wasm/test-run-wasm.cc » ('j') | test/cctest/wasm/test-run-wasm.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698