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

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

Issue 2330073002: Revert "[v8][wasm] Handles finally in try/finally blocks." (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: 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
97 // An entry on the control stack (i.e. if, block, loop). 71 // An entry on the control stack (i.e. if, block, loop).
98 struct Control { 72 struct Control {
99 const byte* pc; 73 const byte* pc;
100 int stack_depth; // stack height at the beginning of the construct. 74 int stack_depth; // stack height at the beginning of the construct.
101 SsaEnv* end_env; // end environment for the construct. 75 SsaEnv* end_env; // end environment for the construct.
102 SsaEnv* false_env; // false environment (only for if). 76 SsaEnv* false_env; // false environment (only for if).
103 TryInfo* try_info; // exception handling stuff. See TryInfo above. 77 SsaEnv* catch_env; // catch environment (only for try with catch).
104 int32_t prev_finally; // previous control (on stack) that has a finally. 78 SsaEnv* finish_try_env; // the environment where a try with finally lives.
105 TFNode* node; // result node for the construct. 79 TFNode* node; // result node for the construct.
106 LocalType type; // result type for the construct. 80 LocalType type; // result type for the construct.
107 bool is_loop; // true if this is the inner label of a loop. 81 bool is_loop; // true if this is the inner label of a loop.
108 82
109 bool is_if() const { return *pc == kExprIf; } 83 bool is_if() const { return *pc == kExprIf; }
110 84
111 bool is_try() const { 85 bool is_try() const {
112 return *pc == kExprTryCatch || *pc == kExprTryCatchFinally || 86 return *pc == kExprTryCatch || *pc == kExprTryCatchFinally ||
113 *pc == kExprTryFinally; 87 *pc == kExprTryFinally;
114 } 88 }
115 89
116 bool has_catch() const { 90 bool has_catch() const {
117 return *pc == kExprTryCatch || *pc == kExprTryCatchFinally; 91 return *pc == kExprTryCatch || *pc == kExprTryCatchFinally;
118 } 92 }
119 93
120 bool has_finally() const { 94 bool has_finally() const {
121 return *pc == kExprTryCatchFinally || *pc == kExprTryFinally; 95 return *pc == kExprTryCatchFinally || *pc == kExprTryFinally;
122 } 96 }
123 97
124 // Named constructors. 98 // Named constructors.
125 static Control Block(const byte* pc, int stack_depth, 99 static Control Block(const byte* pc, int stack_depth, SsaEnv* end_env) {
126 int32_t most_recent_finally, SsaEnv* end_env) { 100 return {pc, stack_depth, end_env, nullptr, nullptr,
127 return {pc, stack_depth, end_env, 101 nullptr, nullptr, kAstEnd, false};
128 nullptr, nullptr, most_recent_finally,
129 nullptr, kAstEnd, false};
130 } 102 }
131 103
132 static Control If(const byte* pc, int stack_depth, 104 static Control If(const byte* pc, int stack_depth, SsaEnv* end_env,
133 int32_t most_recent_finally, SsaEnv* end_env,
134 SsaEnv* false_env) { 105 SsaEnv* false_env) {
135 return {pc, stack_depth, end_env, 106 return {pc, stack_depth, end_env, false_env, nullptr,
136 false_env, nullptr, most_recent_finally, 107 nullptr, nullptr, kAstStmt, false};
137 nullptr, kAstStmt, false};
138 } 108 }
139 109
140 static Control Loop(const byte* pc, int stack_depth, 110 static Control Loop(const byte* pc, int stack_depth, SsaEnv* end_env) {
141 int32_t most_recent_finally, SsaEnv* end_env) { 111 return {pc, stack_depth, end_env, nullptr, nullptr,
142 return {pc, stack_depth, end_env, 112 nullptr, nullptr, kAstEnd, true};
143 nullptr, nullptr, most_recent_finally,
144 nullptr, kAstEnd, true};
145 } 113 }
146 114
147 static Control Try(const byte* pc, int stack_depth, 115 static Control Try(const byte* pc, int stack_depth, SsaEnv* end_env,
148 int32_t most_recent_finally, Zone* zone, SsaEnv* end_env,
149 SsaEnv* catch_env, SsaEnv* finish_try_env) { 116 SsaEnv* catch_env, SsaEnv* finish_try_env) {
150 return {pc, 117 return {pc, stack_depth, end_env, nullptr, catch_env, finish_try_env,
151 stack_depth, 118 nullptr, kAstEnd, false};
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};
159 } 119 }
160 }; 120 };
161 121
162 // Macros that build nodes only if there is a graph and the current SSA 122 // Macros that build nodes only if there is a graph and the current SSA
163 // environment is reachable from start. This avoids problems with malformed 123 // environment is reachable from start. This avoids problems with malformed
164 // TF graphs when decoding inputs that have unreachable code. 124 // TF graphs when decoding inputs that have unreachable code.
165 #define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr) 125 #define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr)
166 #define BUILD0(func) (build() ? builder_->func() : nullptr) 126 #define BUILD0(func) (build() ? builder_->func() : nullptr)
167 127
168 // Generic Wasm bytecode decoder with utilities for decoding operands, 128 // Generic Wasm bytecode decoder with utilities for decoding operands,
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: 423 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
464 FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE) { return 2; } 424 FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE) { return 2; }
465 FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE) { return 3; } 425 FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE) { return 3; }
466 #undef DECLARE_OPCODE_CASE 426 #undef DECLARE_OPCODE_CASE
467 default: 427 default:
468 return 1; 428 return 1;
469 } 429 }
470 } 430 }
471 }; 431 };
472 432
473 static const int32_t kFirstFinallyToken = 1;
474 static const int32_t kFallthroughToken = 0;
475 static const int32_t kNullFinallyToken = -1;
476
477 // The full WASM decoder for bytecode. Both verifies bytecode and generates 433 // The full WASM decoder for bytecode. Both verifies bytecode and generates
478 // a TurboFan IR graph. 434 // a TurboFan IR graph.
479 class WasmFullDecoder : public WasmDecoder { 435 class WasmFullDecoder : public WasmDecoder {
480 public: 436 public:
481 WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body) 437 WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body)
482 : WasmDecoder(body.module, body.sig, body.start, body.end), 438 : WasmDecoder(body.module, body.sig, body.start, body.end),
483 zone_(zone), 439 zone_(zone),
484 builder_(builder), 440 builder_(builder),
485 base_(body.base), 441 base_(body.base),
486 local_type_vec_(zone), 442 local_type_vec_(zone),
487 stack_(zone), 443 stack_(zone),
488 control_(zone), 444 control_(zone) {
489 most_recent_finally_(-1),
490 finally_token_val_(kFirstFinallyToken) {
491 local_types_ = &local_type_vec_; 445 local_types_ = &local_type_vec_;
492 } 446 }
493 447
494 bool Decode() { 448 bool Decode() {
495 base::ElapsedTimer decode_timer; 449 base::ElapsedTimer decode_timer;
496 if (FLAG_trace_wasm_decode_time) { 450 if (FLAG_trace_wasm_decode_time) {
497 decode_timer.Start(); 451 decode_timer.Start();
498 } 452 }
499 stack_.clear(); 453 stack_.clear();
500 control_.clear(); 454 control_.clear();
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 Zone* zone_; 527 Zone* zone_;
574 TFBuilder* builder_; 528 TFBuilder* builder_;
575 const byte* base_; 529 const byte* base_;
576 530
577 SsaEnv* ssa_env_; 531 SsaEnv* ssa_env_;
578 532
579 ZoneVector<LocalType> local_type_vec_; // types of local variables. 533 ZoneVector<LocalType> local_type_vec_; // types of local variables.
580 ZoneVector<Value> stack_; // stack of values. 534 ZoneVector<Value> stack_; // stack of values.
581 ZoneVector<Control> control_; // stack of blocks, loops, and ifs. 535 ZoneVector<Control> control_; // stack of blocks, loops, and ifs.
582 536
583 int32_t most_recent_finally_;
584 int32_t finally_token_val_;
585
586 int32_t FallthroughTokenForFinally() {
587 // Any number < kFirstFinallyToken would work.
588 return kFallthroughToken;
589 }
590
591 int32_t NewTokenForFinally() { return finally_token_val_++; }
592
593 inline bool build() { return builder_ && ssa_env_->go(); } 537 inline bool build() { return builder_ && ssa_env_->go(); }
594 538
595 void InitSsaEnv() { 539 void InitSsaEnv() {
596 TFNode* start = nullptr; 540 TFNode* start = nullptr;
597 SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv))); 541 SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
598 size_t size = sizeof(TFNode*) * EnvironmentCount(); 542 size_t size = sizeof(TFNode*) * EnvironmentCount();
599 ssa_env->state = SsaEnv::kReached; 543 ssa_env->state = SsaEnv::kReached;
600 ssa_env->locals = 544 ssa_env->locals =
601 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr; 545 size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
602 546
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
779 error(pc_, "catch does not match a any try"); 723 error(pc_, "catch does not match a any try");
780 break; 724 break;
781 } 725 }
782 726
783 Control* c = &control_.back(); 727 Control* c = &control_.back();
784 if (!c->has_catch()) { 728 if (!c->has_catch()) {
785 error(pc_, "catch does not match a try with catch"); 729 error(pc_, "catch does not match a try with catch");
786 break; 730 break;
787 } 731 }
788 732
789 if (c->try_info->catch_env == nullptr) { 733 if (c->catch_env == nullptr) {
790 error(pc_, "catch already present for try with catch"); 734 error(pc_, "catch already present for try with catch");
791 break; 735 break;
792 } 736 }
793 737
794 Goto(ssa_env_, c->end_env); 738 Goto(ssa_env_, c->end_env);
795 739
796 SsaEnv* catch_env = c->try_info->catch_env; 740 SsaEnv* catch_env = c->catch_env;
797 c->try_info->catch_env = nullptr; 741 c->catch_env = nullptr;
798 SetEnv("catch:begin", catch_env); 742 SetEnv("catch:begin", catch_env);
799 743
800 if (Validate(pc_, operand)) { 744 if (Validate(pc_, operand)) {
801 // TODO(jpp): figure out how thrown value is propagated. It is 745 // TODO(jpp): figure out how thrown value is propagated. It is
802 // unlikely to be a value on the stack. 746 // unlikely to be a value on the stack.
803 if (ssa_env_->locals) { 747 if (ssa_env_->locals) {
804 ssa_env_->locals[operand.index] = nullptr; 748 ssa_env_->locals[operand.index] = nullptr;
805 } 749 }
806 } 750 }
807 751
808 PopUpTo(c->stack_depth); 752 PopUpTo(c->stack_depth);
809 753
810 break; 754 break;
811 } 755 }
812 case kExprFinally: { 756 case kExprFinally: {
813 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); 757 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
814 if (control_.empty()) { 758 if (control_.empty()) {
815 error(pc_, "finally does not match a any try"); 759 error(pc_, "finally does not match a any try");
816 break; 760 break;
817 } 761 }
818 762
819 Control* c = &control_.back(); 763 Control* c = &control_.back();
820 if (c->has_catch() && c->try_info->catch_env != nullptr) { 764 if (c->has_catch() && c->catch_env != nullptr) {
821 error(pc_, "missing catch for try with catch and finally"); 765 error(pc_, "missing catch for try with catch and finally");
822 break; 766 break;
823 } 767 }
824 768
825 if (!c->has_finally()) { 769 if (!c->has_finally()) {
826 error(pc_, "finally does not match a try with finally"); 770 error(pc_, "finally does not match a try with finally");
827 break; 771 break;
828 } 772 }
829 773
830 if (c->try_info->finish_try_env == nullptr) { 774 if (c->finish_try_env == nullptr) {
831 error(pc_, "finally already present for try with finally"); 775 error(pc_, "finally already present for try with finally");
832 break; 776 break;
833 } 777 }
834 778
835 // ssa_env_ is either the env for either the try or the catch, but 779 // ssa_env_ is either the env for either the try or the catch, but
836 // it does not matter: either way we need to direct the control flow 780 // it does not matter: either way we need to direct the control flow
837 // to the end_env, which is the env for the finally. 781 // to the end_env, which is the env for the finally.
838 // c->try_info->finish_try_env is the the environment enclosing the 782 // c->finish_try_env is the the environment enclosing the try block.
839 // try block. 783 Goto(ssa_env_, c->end_env);
840 const bool has_fallthrough = ssa_env_->go(); 784
841 Value val = PopUpTo(c->stack_depth); 785 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 }
846 786
847 // The current environment becomes end_env, and finish_try_env 787 // The current environment becomes end_env, and finish_try_env
848 // becomes the new end_env. This ensures that any control flow 788 // becomes the new end_env. This ensures that any control flow
849 // leaving a try block up to now will do so by branching to the 789 // leaving a try block up to now will do so by branching to the
850 // finally block. Setting the end_env to be finish_try_env ensures 790 // finally block. Setting the end_env to be finish_try_env ensures
851 // that kExprEnd below can handle the try block as it would any 791 // that kExprEnd below can handle the try block as it would any
852 // other block construct. 792 // other block construct.
853 SsaEnv* finally_env = c->end_env; 793 SsaEnv* finally_env = c->end_env;
854 c->end_env = c->try_info->finish_try_env; 794 c->end_env = c->finish_try_env;
855 SetEnv("finally:begin", finally_env); 795 SetEnv("finally:begin", finally_env);
856 c->try_info->finish_try_env = nullptr; 796 c->finish_try_env = nullptr;
857 797
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;
870 break; 798 break;
871 } 799 }
872 case kExprLoop: { 800 case kExprLoop: {
873 // The break environment is the outer environment. 801 // The break environment is the outer environment.
874 SsaEnv* break_env = ssa_env_; 802 SsaEnv* break_env = ssa_env_;
875 PushBlock(break_env); 803 PushBlock(break_env);
876 SsaEnv* finish_try_env = Steal(break_env); 804 SsaEnv* finish_try_env = Steal(break_env);
877 // The continue environment is the inner environment. 805 // The continue environment is the inner environment.
878 PrepareForLoop(pc_, finish_try_env); 806 PrepareForLoop(pc_, finish_try_env);
879 SetEnv("loop:start", Split(finish_try_env)); 807 SetEnv("loop:start", Split(finish_try_env));
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
912 } 840 }
913 Value val = PopUpTo(c->stack_depth); 841 Value val = PopUpTo(c->stack_depth);
914 MergeInto(c->end_env, &c->node, &c->type, val); 842 MergeInto(c->end_env, &c->node, &c->type, val);
915 // Switch to environment for false branch. 843 // Switch to environment for false branch.
916 SetEnv("if_else:false", c->false_env); 844 SetEnv("if_else:false", c->false_env);
917 c->false_env = nullptr; // record that an else is already seen 845 c->false_env = nullptr; // record that an else is already seen
918 break; 846 break;
919 } 847 }
920 case kExprEnd: { 848 case kExprEnd: {
921 if (control_.empty()) { 849 if (control_.empty()) {
922 error(pc_, "end does not match any if, try, or block"); 850 error(pc_, "end does not match any if or block");
923 break; 851 break;
924 } 852 }
925 const char* name = "block:end"; 853 const char* name = "block:end";
926 Control* c = &control_.back(); 854 Control* c = &control_.back();
927 Value val = PopUpTo(c->stack_depth); 855 Value val = PopUpTo(c->stack_depth);
928 if (c->is_loop) { 856 if (c->is_loop) {
929 // Loops always push control in pairs. 857 // Loops always push control in pairs.
930 PopControl(); 858 control_.pop_back();
931 c = &control_.back(); 859 c = &control_.back();
932 name = "loop:end"; 860 name = "loop:end";
933 } else if (c->is_if()) { 861 } else if (c->is_if()) {
934 if (c->false_env != nullptr) { 862 if (c->false_env != nullptr) {
935 // End the true branch of a one-armed if. 863 // End the true branch of a one-armed if.
936 Goto(c->false_env, c->end_env); 864 Goto(c->false_env, c->end_env);
937 val = {val.pc, nullptr, kAstStmt}; 865 val = {val.pc, nullptr, kAstStmt};
938 name = "if:merge"; 866 name = "if:merge";
939 } else { 867 } else {
940 // End the false branch of a two-armed if. 868 // End the false branch of a two-armed if.
941 name = "if_else:merge"; 869 name = "if_else:merge";
942 } 870 }
943 } else if (c->is_try()) { 871 } else if (c->is_try()) {
944 name = "try:end"; 872 name = "try:end";
945 873
874 // try blocks do not yield a value.
875 val = {val.pc, nullptr, kAstStmt};
876
946 // validate that catch/finally were seen. 877 // validate that catch/finally were seen.
947 if (c->try_info->catch_env != nullptr) { 878 if (c->catch_env != nullptr) {
948 error(pc_, "missing catch in try with catch"); 879 error(pc_, "missing catch in try with catch");
949 break; 880 break;
950 } 881 }
951 882
952 if (c->try_info->finish_try_env != nullptr) { 883 if (c->finish_try_env != nullptr) {
953 error(pc_, "missing finally in try with finally"); 884 error(pc_, "missing finally in try with finally");
954 break; 885 break;
955 } 886 }
956
957 if (c->has_finally() && ssa_env_->go()) {
958 DispatchToTargets(c, val);
959 }
960 } 887 }
961 888
962 if (ssa_env_->go()) { 889 if (ssa_env_->go()) {
963 // Adds a fallthrough edge to the next control block.
964 MergeInto(c->end_env, &c->node, &c->type, val); 890 MergeInto(c->end_env, &c->node, &c->type, val);
965 } 891 }
966 SetEnv(name, c->end_env); 892 SetEnv(name, c->end_env);
967 stack_.resize(c->stack_depth); 893 stack_.resize(c->stack_depth);
968 Push(c->type, c->node); 894 Push(c->type, c->node);
969 PopControl(); 895 control_.pop_back();
970 break; 896 break;
971 } 897 }
972 case kExprSelect: { 898 case kExprSelect: {
973 Value cond = Pop(2, kAstI32); 899 Value cond = Pop(2, kAstI32);
974 Value fval = Pop(); 900 Value fval = Pop();
975 Value tval = Pop(); 901 Value tval = Pop();
976 if (tval.type == kAstStmt || tval.type != fval.type) { 902 if (tval.type == kAstStmt || tval.type != fval.type) {
977 if (tval.type != kAstEnd && fval.type != kAstEnd) { 903 if (tval.type != kAstEnd && fval.type != kAstEnd) {
978 error(pc_, "type mismatch in select"); 904 error(pc_, "type mismatch in select");
979 break; 905 break;
(...skipping 13 matching lines...) Expand all
993 } else { 919 } else {
994 Push(tval.type, nullptr); 920 Push(tval.type, nullptr);
995 } 921 }
996 break; 922 break;
997 } 923 }
998 case kExprBr: { 924 case kExprBr: {
999 BreakDepthOperand operand(this, pc_); 925 BreakDepthOperand operand(this, pc_);
1000 Value val = {pc_, nullptr, kAstStmt}; 926 Value val = {pc_, nullptr, kAstStmt};
1001 if (operand.arity) val = Pop(); 927 if (operand.arity) val = Pop();
1002 if (Validate(pc_, operand, control_)) { 928 if (Validate(pc_, operand, control_)) {
1003 BreakTo(operand, val); 929 BreakTo(operand.target, val);
1004 } 930 }
1005 len = 1 + operand.length; 931 len = 1 + operand.length;
1006 Push(kAstEnd, nullptr); 932 Push(kAstEnd, nullptr);
1007 break; 933 break;
1008 } 934 }
1009 case kExprBrIf: { 935 case kExprBrIf: {
1010 BreakDepthOperand operand(this, pc_); 936 BreakDepthOperand operand(this, pc_);
1011 Value cond = Pop(operand.arity, kAstI32); 937 Value cond = Pop(operand.arity, kAstI32);
1012 Value val = {pc_, nullptr, kAstStmt}; 938 Value val = {pc_, nullptr, kAstStmt};
1013 if (operand.arity == 1) val = Pop(); 939 if (operand.arity == 1) val = Pop();
1014 if (ok() && Validate(pc_, operand, control_)) { 940 if (ok() && Validate(pc_, operand, control_)) {
1015 SsaEnv* fenv = ssa_env_; 941 SsaEnv* fenv = ssa_env_;
1016 SsaEnv* tenv = Split(fenv); 942 SsaEnv* tenv = Split(fenv);
1017 fenv->SetNotMerged(); 943 fenv->SetNotMerged();
1018 BUILD(Branch, cond.node, &tenv->control, &fenv->control); 944 BUILD(Branch, cond.node, &tenv->control, &fenv->control);
1019 ssa_env_ = tenv; 945 ssa_env_ = tenv;
1020 BreakTo(operand, val); 946 BreakTo(operand.target, val);
1021 ssa_env_ = fenv; 947 ssa_env_ = fenv;
1022 } 948 }
1023 len = 1 + operand.length; 949 len = 1 + operand.length;
1024 Push(kAstStmt, nullptr); 950 Push(kAstStmt, nullptr);
1025 break; 951 break;
1026 } 952 }
1027 case kExprBrTable: { 953 case kExprBrTable: {
1028 BranchTableOperand operand(this, pc_); 954 BranchTableOperand operand(this, pc_);
1029 if (Validate(pc_, operand, control_.size())) { 955 if (Validate(pc_, operand, control_.size())) {
1030 Value key = Pop(operand.arity, kAstI32); 956 Value key = Pop(operand.arity, kAstI32);
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
1347 return nullptr; 1273 return nullptr;
1348 } 1274 }
1349 } 1275 }
1350 1276
1351 LocalType GetReturnType(FunctionSig* sig) { 1277 LocalType GetReturnType(FunctionSig* sig) {
1352 return sig->return_count() == 0 ? kAstStmt : sig->GetReturn(); 1278 return sig->return_count() == 0 ? kAstStmt : sig->GetReturn();
1353 } 1279 }
1354 1280
1355 void PushBlock(SsaEnv* end_env) { 1281 void PushBlock(SsaEnv* end_env) {
1356 const int stack_depth = static_cast<int>(stack_.size()); 1282 const int stack_depth = static_cast<int>(stack_.size());
1357 control_.emplace_back( 1283 control_.emplace_back(Control::Block(pc_, stack_depth, end_env));
1358 Control::Block(pc_, stack_depth, most_recent_finally_, end_env));
1359 } 1284 }
1360 1285
1361 void PushLoop(SsaEnv* end_env) { 1286 void PushLoop(SsaEnv* end_env) {
1362 const int stack_depth = static_cast<int>(stack_.size()); 1287 const int stack_depth = static_cast<int>(stack_.size());
1363 control_.emplace_back( 1288 control_.emplace_back(Control::Loop(pc_, stack_depth, end_env));
1364 Control::Loop(pc_, stack_depth, most_recent_finally_, end_env));
1365 } 1289 }
1366 1290
1367 void PushIf(SsaEnv* end_env, SsaEnv* false_env) { 1291 void PushIf(SsaEnv* end_env, SsaEnv* false_env) {
1368 const int stack_depth = static_cast<int>(stack_.size()); 1292 const int stack_depth = static_cast<int>(stack_.size());
1369 control_.emplace_back(Control::If(pc_, stack_depth, most_recent_finally_, 1293 control_.emplace_back(Control::If(pc_, stack_depth, end_env, false_env));
1370 end_env, false_env));
1371 } 1294 }
1372 1295
1373 void PushTry(SsaEnv* end_env, SsaEnv* catch_env, SsaEnv* finish_try_env) { 1296 void PushTry(SsaEnv* end_env, SsaEnv* catch_env, SsaEnv* finish_try_env) {
1374 const int stack_depth = static_cast<int>(stack_.size()); 1297 const int stack_depth = static_cast<int>(stack_.size());
1375 control_.emplace_back(Control::Try(pc_, stack_depth, most_recent_finally_, 1298 control_.emplace_back(
1376 zone_, end_env, catch_env, 1299 Control::Try(pc_, stack_depth, end_env, catch_env, finish_try_env));
1377 finish_try_env));
1378 if (control_.back().has_finally()) {
1379 most_recent_finally_ = static_cast<uint32_t>(control_.size() - 1);
1380 }
1381 }
1382
1383 void PopControl() {
1384 const Control& c = control_.back();
1385 most_recent_finally_ = c.prev_finally;
1386 control_.pop_back();
1387 // No more accesses to (danging pointer) c
1388 } 1300 }
1389 1301
1390 int DecodeLoadMem(LocalType type, MachineType mem_type) { 1302 int DecodeLoadMem(LocalType type, MachineType mem_type) {
1391 MemoryAccessOperand operand(this, pc_, 1303 MemoryAccessOperand operand(this, pc_,
1392 ElementSizeLog2Of(mem_type.representation())); 1304 ElementSizeLog2Of(mem_type.representation()));
1393 1305
1394 Value index = Pop(0, kAstI32); 1306 Value index = Pop(0, kAstI32);
1395 TFNode* node = BUILD(LoadMem, type, mem_type, index.node, operand.offset, 1307 TFNode* node = BUILD(LoadMem, type, mem_type, index.node, operand.offset,
1396 operand.alignment, position()); 1308 operand.alignment, position());
1397 Push(type, node); 1309 Push(type, node);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1434 TFNode* node = BUILD(SimdOp, opcode, inputs); 1346 TFNode* node = BUILD(SimdOp, opcode, inputs);
1435 Push(GetReturnType(sig), node); 1347 Push(GetReturnType(sig), node);
1436 } else { 1348 } else {
1437 error(pc_, pc_, "invalid simd opcode"); 1349 error(pc_, pc_, "invalid simd opcode");
1438 } 1350 }
1439 } 1351 }
1440 } 1352 }
1441 return len; 1353 return len;
1442 } 1354 }
1443 1355
1444 void DispatchToTargets(Control* next_block, const Value& val) {
1445 const ZoneVector<IncomingBranch>& incoming_branches =
1446 next_block->try_info->incoming_branches;
1447 // Counts how many successors are not current control block.
1448 uint32_t targets = 0;
1449 for (const auto& path_token : incoming_branches) {
1450 if (path_token.target != next_block) ++targets;
1451 }
1452
1453 if (targets == 0) {
1454 // Nothing to do here: the control flow should just fall
1455 // through to the next control block.
1456 return;
1457 }
1458
1459 TFNode* sw = BUILD(Switch, static_cast<uint32_t>(targets + 1),
1460 next_block->try_info->token);
1461
1462 SsaEnv* break_env = ssa_env_;
1463 SsaEnv* copy = Steal(break_env);
1464 for (uint32_t ii = 0; ii < incoming_branches.size(); ++ii) {
1465 Control* t = incoming_branches[ii].target;
1466 if (t != next_block) {
1467 const int32_t token_value = incoming_branches[ii].token_value;
1468 ssa_env_ = Split(copy);
1469 ssa_env_->control = BUILD(IfValue, token_value, sw);
1470 MergeInto(t->end_env, &t->node, &t->type, incoming_branches[ii].val);
1471 // We only need to merge the finally token if t is both a
1472 // try-with-finally and its finally hasn't yet been found
1473 // in the instruction stream. Otherwise we just need to
1474 // branch to t.
1475 if (t->has_finally() && !t->try_info->has_handled_finally) {
1476 MergeFinallyToken(ssa_env_, t, token_value);
1477 }
1478 }
1479 }
1480 ssa_env_ = Split(copy);
1481 ssa_env_->control = BUILD(IfDefault, sw);
1482 MergeInto(next_block->end_env, &next_block->node, &next_block->type, val);
1483 // Not a finally env; no fallthrough token.
1484
1485 ssa_env_ = break_env;
1486 }
1487
1488 void DoReturn() { 1356 void DoReturn() {
1489 int count = static_cast<int>(sig_->return_count()); 1357 int count = static_cast<int>(sig_->return_count());
1490 TFNode** buffer = nullptr; 1358 TFNode** buffer = nullptr;
1491 if (build()) buffer = builder_->Buffer(count); 1359 if (build()) buffer = builder_->Buffer(count);
1492 1360
1493 // Pop return values off the stack in reverse order. 1361 // Pop return values off the stack in reverse order.
1494 for (int i = count - 1; i >= 0; i--) { 1362 for (int i = count - 1; i >= 0; i--) {
1495 Value val = Pop(i, sig_->GetReturn(i)); 1363 Value val = Pop(i, sig_->GetReturn(i));
1496 if (buffer) buffer[i] = val.node; 1364 if (buffer) buffer[i] = val.node;
1497 } 1365 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1544 return val; 1412 return val;
1545 } 1413 }
1546 } 1414 }
1547 1415
1548 int baserel(const byte* ptr) { 1416 int baserel(const byte* ptr) {
1549 return base_ ? static_cast<int>(ptr - base_) : 0; 1417 return base_ ? static_cast<int>(ptr - base_) : 0;
1550 } 1418 }
1551 1419
1552 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); } 1420 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); }
1553 1421
1554 Control* BuildFinallyChain(const BreakDepthOperand& operand, const Value& val, 1422 void BreakTo(Control* block, Value& val) {
1555 int32_t* token) {
1556 DCHECK_LE(operand.depth, control_.size());
1557 const int32_t target_index =
1558 static_cast<uint32_t>(control_.size() - operand.depth - 1);
1559
1560 if (most_recent_finally_ == kNullFinallyToken || // No finallies.
1561 most_recent_finally_ < target_index) { // Does not cross any finally.
1562 *token = kNullFinallyToken;
1563 return operand.target;
1564 }
1565
1566 Control* previous_control = &control_[most_recent_finally_];
1567 *token = NewTokenForFinally();
1568
1569 for (int32_t ii = previous_control->prev_finally; ii >= target_index;
1570 ii = previous_control->prev_finally) {
1571 Control* current_finally = &control_[ii];
1572
1573 DCHECK(!current_finally->try_info->has_handled_finally);
1574 previous_control->try_info->incoming_branches.push_back(
1575 {*token, current_finally, val});
1576 previous_control = current_finally;
1577 }
1578
1579 if (operand.target != previous_control) {
1580 DCHECK_NOT_NULL(previous_control);
1581 DCHECK(previous_control->has_finally());
1582 DCHECK_NE(*token, kNullFinallyToken);
1583 previous_control->try_info->incoming_branches.push_back(
1584 {*token, operand.target, val});
1585 }
1586
1587 return &control_[most_recent_finally_];
1588 }
1589
1590 void BreakTo(const BreakDepthOperand& operand, const Value& val) {
1591 int32_t finally_token;
1592 Control* block = BuildFinallyChain(operand, val, &finally_token);
1593
1594 if (block->is_loop) { 1423 if (block->is_loop) {
1595 // This is the inner loop block, which does not have a value. 1424 // This is the inner loop block, which does not have a value.
1596 Goto(ssa_env_, block->end_env); 1425 Goto(ssa_env_, block->end_env);
1597 } else { 1426 } else {
1598 // Merge the value into the production for the block. 1427 // Merge the value into the production for the block.
1599 MergeInto(block->end_env, &block->node, &block->type, val); 1428 MergeInto(block->end_env, &block->node, &block->type, val);
1600 } 1429 }
1601
1602 if (finally_token != kNullFinallyToken) {
1603 MergeFinallyToken(ssa_env_, block, finally_token);
1604 }
1605 } 1430 }
1606 1431
1607 void MergeInto(SsaEnv* target, TFNode** node, LocalType* type, 1432 void MergeInto(SsaEnv* target, TFNode** node, LocalType* type, Value& val) {
1608 const Value& val) {
1609 if (!ssa_env_->go()) return; 1433 if (!ssa_env_->go()) return;
1610 DCHECK_NE(kAstEnd, val.type); 1434 DCHECK_NE(kAstEnd, val.type);
1611 1435
1612 bool first = target->state == SsaEnv::kUnreachable; 1436 bool first = target->state == SsaEnv::kUnreachable;
1613 Goto(ssa_env_, target); 1437 Goto(ssa_env_, target);
1614 1438
1615 if (first) { 1439 if (first) {
1616 // first merge to this environment; set the type and the node. 1440 // first merge to this environment; set the type and the node.
1617 *type = val.type; 1441 *type = val.type;
1618 *node = val.node; 1442 *node = val.node;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1655 PrintF("\n"); 1479 PrintF("\n");
1656 } 1480 }
1657 #endif 1481 #endif
1658 ssa_env_ = env; 1482 ssa_env_ = env;
1659 if (builder_) { 1483 if (builder_) {
1660 builder_->set_control_ptr(&env->control); 1484 builder_->set_control_ptr(&env->control);
1661 builder_->set_effect_ptr(&env->effect); 1485 builder_->set_effect_ptr(&env->effect);
1662 } 1486 }
1663 } 1487 }
1664 1488
1665 void MergeFinallyToken(SsaEnv*, Control* to, int32_t new_token) {
1666 DCHECK(to->has_finally());
1667 DCHECK(!to->try_info->has_handled_finally);
1668 if (builder_ == nullptr) {
1669 return;
1670 }
1671
1672 switch (to->end_env->state) {
1673 case SsaEnv::kReached:
1674 DCHECK(to->try_info->token == nullptr);
1675 to->try_info->token = builder_->Int32Constant(new_token);
1676 break;
1677 case SsaEnv::kMerged:
1678 DCHECK_NOT_NULL(to->try_info->token);
1679 to->try_info->token = CreateOrMergeIntoPhi(
1680 kAstI32, to->end_env->control, to->try_info->token,
1681 builder_->Int32Constant(new_token));
1682 break;
1683 case SsaEnv::kUnreachable:
1684 UNREACHABLE();
1685 // fallthrough intended.
1686 default:
1687 break;
1688 }
1689 }
1690
1691 void Goto(SsaEnv* from, SsaEnv* to) { 1489 void Goto(SsaEnv* from, SsaEnv* to) {
1692 DCHECK_NOT_NULL(to); 1490 DCHECK_NOT_NULL(to);
1693 if (!from->go()) return; 1491 if (!from->go()) return;
1694 switch (to->state) { 1492 switch (to->state) {
1695 case SsaEnv::kUnreachable: { // Overwrite destination. 1493 case SsaEnv::kUnreachable: { // Overwrite destination.
1696 to->state = SsaEnv::kReached; 1494 to->state = SsaEnv::kReached;
1697 to->locals = from->locals; 1495 to->locals = from->locals;
1698 to->control = from->control; 1496 to->control = from->control;
1699 to->effect = from->effect; 1497 to->effect = from->effect;
1700 break; 1498 break;
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
2120 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, 1918 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
2121 const byte* start, const byte* end) { 1919 const byte* start, const byte* end) {
2122 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; 1920 FunctionBody body = {nullptr, nullptr, nullptr, start, end};
2123 WasmFullDecoder decoder(zone, nullptr, body); 1921 WasmFullDecoder decoder(zone, nullptr, body);
2124 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); 1922 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals);
2125 } 1923 }
2126 1924
2127 } // namespace wasm 1925 } // namespace wasm
2128 } // namespace internal 1926 } // namespace internal
2129 } // namespace v8 1927 } // 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