| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/signature.h" | 5 #include "src/signature.h" |
| 6 | 6 |
| 7 #include "src/bit-vector.h" | 7 #include "src/bit-vector.h" |
| 8 #include "src/flags.h" | 8 #include "src/flags.h" |
| 9 #include "src/handles.h" | 9 #include "src/handles.h" |
| 10 #include "src/zone-containers.h" | 10 #include "src/zone-containers.h" |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 // An entry on the control stack (i.e. if, block, loop). | 71 struct Control; |
| 72 |
| 73 // An entry on the control stack (i.e. if, block, loop, try). |
| 72 struct Control { | 74 struct Control { |
| 73 const byte* pc; | 75 const byte* pc; |
| 74 int stack_depth; // stack height at the beginning of the construct. | 76 int stack_depth; // stack height at the beginning of the construct. |
| 75 SsaEnv* end_env; // end environment for the construct. | 77 SsaEnv* end_env; // end environment for the construct. |
| 76 SsaEnv* false_env; // false environment (only for if). | 78 SsaEnv* false_env; // false environment (only for if). |
| 77 SsaEnv* catch_env; // catch environment (only for try with catch). | 79 SsaEnv* catch_env; // catch environment (only for try). |
| 78 SsaEnv* finish_try_env; // the environment where a try with finally lives. | 80 TFNode* node; // result node for the construct. |
| 79 TFNode* node; // result node for the construct. | 81 LocalType type; // result type for the construct. |
| 80 LocalType type; // result type for the construct. | 82 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. | |
| 82 | 83 |
| 83 bool is_if() const { return *pc == kExprIf; } | 84 bool is_if() const { return *pc == kExprIf; } |
| 84 | 85 |
| 85 bool is_try() const { | 86 bool is_try() const { return *pc == kExprTry; } |
| 86 return *pc == kExprTryCatch || *pc == kExprTryCatchFinally || | |
| 87 *pc == kExprTryFinally; | |
| 88 } | |
| 89 | |
| 90 bool has_catch() const { | |
| 91 return *pc == kExprTryCatch || *pc == kExprTryCatchFinally; | |
| 92 } | |
| 93 | |
| 94 bool has_finally() const { | |
| 95 return *pc == kExprTryCatchFinally || *pc == kExprTryFinally; | |
| 96 } | |
| 97 | 87 |
| 98 // Named constructors. | 88 // Named constructors. |
| 99 static Control Block(const byte* pc, int stack_depth, SsaEnv* end_env) { | 89 static Control Block(const byte* pc, int stack_depth, SsaEnv* end_env) { |
| 100 return {pc, stack_depth, end_env, nullptr, nullptr, | 90 return {pc, stack_depth, end_env, nullptr, |
| 101 nullptr, nullptr, kAstEnd, false}; | 91 nullptr, nullptr, kAstEnd, false}; |
| 102 } | 92 } |
| 103 | 93 |
| 104 static Control If(const byte* pc, int stack_depth, SsaEnv* end_env, | 94 static Control If(const byte* pc, int stack_depth, SsaEnv* end_env, |
| 105 SsaEnv* false_env) { | 95 SsaEnv* false_env) { |
| 106 return {pc, stack_depth, end_env, false_env, nullptr, | 96 return {pc, stack_depth, end_env, false_env, |
| 107 nullptr, nullptr, kAstStmt, false}; | 97 nullptr, nullptr, kAstStmt, false}; |
| 108 } | 98 } |
| 109 | 99 |
| 110 static Control Loop(const byte* pc, int stack_depth, SsaEnv* end_env) { | 100 static Control Loop(const byte* pc, int stack_depth, SsaEnv* end_env) { |
| 111 return {pc, stack_depth, end_env, nullptr, nullptr, | 101 return {pc, stack_depth, end_env, nullptr, nullptr, nullptr, kAstEnd, true}; |
| 112 nullptr, nullptr, kAstEnd, true}; | |
| 113 } | 102 } |
| 114 | 103 |
| 115 static Control Try(const byte* pc, int stack_depth, SsaEnv* end_env, | 104 static Control Try(const byte* pc, int stack_depth, SsaEnv* end_env, |
| 116 SsaEnv* catch_env, SsaEnv* finish_try_env) { | 105 SsaEnv* catch_env) { |
| 117 return {pc, stack_depth, end_env, nullptr, catch_env, finish_try_env, | 106 return {pc, stack_depth, end_env, nullptr, |
| 118 nullptr, kAstEnd, false}; | 107 catch_env, nullptr, kAstEnd, false}; |
| 119 } | 108 } |
| 120 }; | 109 }; |
| 121 | 110 |
| 122 // Macros that build nodes only if there is a graph and the current SSA | 111 // 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 | 112 // environment is reachable from start. This avoids problems with malformed |
| 124 // TF graphs when decoding inputs that have unreachable code. | 113 // TF graphs when decoding inputs that have unreachable code. |
| 125 #define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr) | 114 #define BUILD(func, ...) (build() ? builder_->func(__VA_ARGS__) : nullptr) |
| 126 #define BUILD0(func) (build() ? builder_->func() : nullptr) | 115 #define BUILD0(func) (build() ? builder_->func() : nullptr) |
| 127 | 116 |
| 128 // Generic Wasm bytecode decoder with utilities for decoding operands, | 117 // Generic Wasm bytecode decoder with utilities for decoding operands, |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 281 case kExprI64Const: | 270 case kExprI64Const: |
| 282 case kExprF64Const: | 271 case kExprF64Const: |
| 283 case kExprF32Const: | 272 case kExprF32Const: |
| 284 case kExprGetLocal: | 273 case kExprGetLocal: |
| 285 case kExprGetGlobal: | 274 case kExprGetGlobal: |
| 286 case kExprNop: | 275 case kExprNop: |
| 287 case kExprUnreachable: | 276 case kExprUnreachable: |
| 288 case kExprEnd: | 277 case kExprEnd: |
| 289 case kExprBlock: | 278 case kExprBlock: |
| 290 case kExprThrow: | 279 case kExprThrow: |
| 291 case kExprTryCatch: | 280 case kExprTry: |
| 292 case kExprTryCatchFinally: | |
| 293 case kExprTryFinally: | |
| 294 case kExprFinally: | |
| 295 case kExprLoop: | 281 case kExprLoop: |
| 296 return 0; | 282 return 0; |
| 297 | 283 |
| 298 case kExprSetGlobal: | 284 case kExprSetGlobal: |
| 299 case kExprSetLocal: | 285 case kExprSetLocal: |
| 300 case kExprElse: | 286 case kExprElse: |
| 301 case kExprCatch: | 287 case kExprCatch: |
| 302 return 1; | 288 return 1; |
| 303 | 289 |
| 304 case kExprBr: { | 290 case kExprBr: { |
| (...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 SetEnv("block:start", Steal(break_env)); | 665 SetEnv("block:start", Steal(break_env)); |
| 680 break; | 666 break; |
| 681 } | 667 } |
| 682 case kExprThrow: { | 668 case kExprThrow: { |
| 683 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); | 669 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); |
| 684 Pop(0, kAstI32); | 670 Pop(0, kAstI32); |
| 685 | 671 |
| 686 // TODO(jpp): start exception propagation. | 672 // TODO(jpp): start exception propagation. |
| 687 break; | 673 break; |
| 688 } | 674 } |
| 689 case kExprTryCatch: { | 675 case kExprTry: { |
| 690 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); | 676 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); |
| 691 SsaEnv* outer_env = ssa_env_; | 677 SsaEnv* outer_env = ssa_env_; |
| 692 SsaEnv* try_env = Steal(outer_env); | 678 SsaEnv* try_env = Steal(outer_env); |
| 693 SsaEnv* catch_env = Split(try_env); | 679 SsaEnv* catch_env = Split(try_env); |
| 694 PushTry(outer_env, catch_env, nullptr); | 680 PushTry(outer_env, catch_env); |
| 695 SetEnv("try_catch:start", try_env); | 681 SetEnv("try:start", try_env); |
| 696 break; | |
| 697 } | |
| 698 case kExprTryCatchFinally: { | |
| 699 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); | |
| 700 SsaEnv* outer_env = ssa_env_; | |
| 701 SsaEnv* try_env = Steal(outer_env); | |
| 702 SsaEnv* catch_env = Split(try_env); | |
| 703 SsaEnv* finally_env = Split(try_env); | |
| 704 PushTry(finally_env, catch_env, outer_env); | |
| 705 SetEnv("try_catch_finally:start", try_env); | |
| 706 break; | |
| 707 } | |
| 708 case kExprTryFinally: { | |
| 709 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); | |
| 710 SsaEnv* outer_env = ssa_env_; | |
| 711 SsaEnv* try_env = Steal(outer_env); | |
| 712 SsaEnv* finally_env = Split(outer_env); | |
| 713 PushTry(finally_env, nullptr, outer_env); | |
| 714 SetEnv("try_finally:start", try_env); | |
| 715 break; | 682 break; |
| 716 } | 683 } |
| 717 case kExprCatch: { | 684 case kExprCatch: { |
| 718 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); | 685 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); |
| 719 LocalIndexOperand operand(this, pc_); | 686 LocalIndexOperand operand(this, pc_); |
| 720 len = 1 + operand.length; | 687 len = 1 + operand.length; |
| 721 | 688 |
| 722 if (control_.empty()) { | 689 if (control_.empty()) { |
| 723 error(pc_, "catch does not match a any try"); | 690 error(pc_, "catch does not match a any try"); |
| 724 break; | 691 break; |
| 725 } | 692 } |
| 726 | 693 |
| 727 Control* c = &control_.back(); | 694 Control* c = &control_.back(); |
| 728 if (!c->has_catch()) { | 695 if (!c->is_try()) { |
| 729 error(pc_, "catch does not match a try with catch"); | 696 error(pc_, "catch does not match a try"); |
| 730 break; | 697 break; |
| 731 } | 698 } |
| 732 | 699 |
| 733 if (c->catch_env == nullptr) { | 700 if (c->catch_env == nullptr) { |
| 734 error(pc_, "catch already present for try with catch"); | 701 error(pc_, "catch already present for try with catch"); |
| 735 break; | 702 break; |
| 736 } | 703 } |
| 737 | 704 |
| 738 Goto(ssa_env_, c->end_env); | 705 Goto(ssa_env_, c->end_env); |
| 739 | 706 |
| 740 SsaEnv* catch_env = c->catch_env; | 707 SsaEnv* catch_env = c->catch_env; |
| 741 c->catch_env = nullptr; | 708 c->catch_env = nullptr; |
| 742 SetEnv("catch:begin", catch_env); | 709 SetEnv("catch:begin", catch_env); |
| 743 | 710 |
| 744 if (Validate(pc_, operand)) { | 711 if (Validate(pc_, operand)) { |
| 745 // TODO(jpp): figure out how thrown value is propagated. It is | 712 // TODO(jpp): figure out how thrown value is propagated. It is |
| 746 // unlikely to be a value on the stack. | 713 // unlikely to be a value on the stack. |
| 747 if (ssa_env_->locals) { | 714 if (ssa_env_->locals) { |
| 748 ssa_env_->locals[operand.index] = nullptr; | 715 ssa_env_->locals[operand.index] = nullptr; |
| 749 } | 716 } |
| 750 } | 717 } |
| 751 | 718 |
| 752 PopUpTo(c->stack_depth); | 719 PopUpTo(c->stack_depth); |
| 753 | 720 |
| 754 break; | 721 break; |
| 755 } | 722 } |
| 756 case kExprFinally: { | |
| 757 CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype); | |
| 758 if (control_.empty()) { | |
| 759 error(pc_, "finally does not match a any try"); | |
| 760 break; | |
| 761 } | |
| 762 | |
| 763 Control* c = &control_.back(); | |
| 764 if (c->has_catch() && c->catch_env != nullptr) { | |
| 765 error(pc_, "missing catch for try with catch and finally"); | |
| 766 break; | |
| 767 } | |
| 768 | |
| 769 if (!c->has_finally()) { | |
| 770 error(pc_, "finally does not match a try with finally"); | |
| 771 break; | |
| 772 } | |
| 773 | |
| 774 if (c->finish_try_env == nullptr) { | |
| 775 error(pc_, "finally already present for try with finally"); | |
| 776 break; | |
| 777 } | |
| 778 | |
| 779 // 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 | |
| 781 // to the end_env, which is the env for the finally. | |
| 782 // c->finish_try_env is the the environment enclosing the try block. | |
| 783 Goto(ssa_env_, c->end_env); | |
| 784 | |
| 785 PopUpTo(c->stack_depth); | |
| 786 | |
| 787 // The current environment becomes end_env, and finish_try_env | |
| 788 // 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 | |
| 790 // 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 | |
| 792 // other block construct. | |
| 793 SsaEnv* finally_env = c->end_env; | |
| 794 c->end_env = c->finish_try_env; | |
| 795 SetEnv("finally:begin", finally_env); | |
| 796 c->finish_try_env = nullptr; | |
| 797 | |
| 798 break; | |
| 799 } | |
| 800 case kExprLoop: { | 723 case kExprLoop: { |
| 801 // The break environment is the outer environment. | 724 // The break environment is the outer environment. |
| 802 SsaEnv* break_env = ssa_env_; | 725 SsaEnv* break_env = ssa_env_; |
| 803 PushBlock(break_env); | 726 PushBlock(break_env); |
| 804 SsaEnv* finish_try_env = Steal(break_env); | 727 SsaEnv* finish_try_env = Steal(break_env); |
| 805 // The continue environment is the inner environment. | 728 // The continue environment is the inner environment. |
| 806 PrepareForLoop(pc_, finish_try_env); | 729 PrepareForLoop(pc_, finish_try_env); |
| 807 SetEnv("loop:start", Split(finish_try_env)); | 730 SetEnv("loop:start", Split(finish_try_env)); |
| 808 ssa_env_->SetNotMerged(); | 731 ssa_env_->SetNotMerged(); |
| 809 PushLoop(finish_try_env); | 732 PushLoop(finish_try_env); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 840 } | 763 } |
| 841 Value val = PopUpTo(c->stack_depth); | 764 Value val = PopUpTo(c->stack_depth); |
| 842 MergeInto(c->end_env, &c->node, &c->type, val); | 765 MergeInto(c->end_env, &c->node, &c->type, val); |
| 843 // Switch to environment for false branch. | 766 // Switch to environment for false branch. |
| 844 SetEnv("if_else:false", c->false_env); | 767 SetEnv("if_else:false", c->false_env); |
| 845 c->false_env = nullptr; // record that an else is already seen | 768 c->false_env = nullptr; // record that an else is already seen |
| 846 break; | 769 break; |
| 847 } | 770 } |
| 848 case kExprEnd: { | 771 case kExprEnd: { |
| 849 if (control_.empty()) { | 772 if (control_.empty()) { |
| 850 error(pc_, "end does not match any if or block"); | 773 error(pc_, "end does not match any if, try, or block"); |
| 851 break; | 774 break; |
| 852 } | 775 } |
| 853 const char* name = "block:end"; | 776 const char* name = "block:end"; |
| 854 Control* c = &control_.back(); | 777 Control* c = &control_.back(); |
| 855 Value val = PopUpTo(c->stack_depth); | 778 Value val = PopUpTo(c->stack_depth); |
| 856 if (c->is_loop) { | 779 if (c->is_loop) { |
| 857 // Loops always push control in pairs. | 780 // Loops always push control in pairs. |
| 858 control_.pop_back(); | 781 PopControl(); |
| 859 c = &control_.back(); | 782 c = &control_.back(); |
| 860 name = "loop:end"; | 783 name = "loop:end"; |
| 861 } else if (c->is_if()) { | 784 } else if (c->is_if()) { |
| 862 if (c->false_env != nullptr) { | 785 if (c->false_env != nullptr) { |
| 863 // End the true branch of a one-armed if. | 786 // End the true branch of a one-armed if. |
| 864 Goto(c->false_env, c->end_env); | 787 Goto(c->false_env, c->end_env); |
| 865 val = {val.pc, nullptr, kAstStmt}; | 788 val = {val.pc, nullptr, kAstStmt}; |
| 866 name = "if:merge"; | 789 name = "if:merge"; |
| 867 } else { | 790 } else { |
| 868 // End the false branch of a two-armed if. | 791 // End the false branch of a two-armed if. |
| 869 name = "if_else:merge"; | 792 name = "if_else:merge"; |
| 870 } | 793 } |
| 871 } else if (c->is_try()) { | 794 } else if (c->is_try()) { |
| 872 name = "try:end"; | 795 name = "try:end"; |
| 873 | 796 |
| 874 // try blocks do not yield a value. | 797 // validate that catch was seen. |
| 875 val = {val.pc, nullptr, kAstStmt}; | |
| 876 | |
| 877 // validate that catch/finally were seen. | |
| 878 if (c->catch_env != nullptr) { | 798 if (c->catch_env != nullptr) { |
| 879 error(pc_, "missing catch in try with catch"); | 799 error(pc_, "missing catch in try"); |
| 880 break; | |
| 881 } | |
| 882 | |
| 883 if (c->finish_try_env != nullptr) { | |
| 884 error(pc_, "missing finally in try with finally"); | |
| 885 break; | 800 break; |
| 886 } | 801 } |
| 887 } | 802 } |
| 888 | 803 |
| 889 if (ssa_env_->go()) { | 804 if (ssa_env_->go()) { |
| 805 // Adds a fallthrough edge to the next control block. |
| 890 MergeInto(c->end_env, &c->node, &c->type, val); | 806 MergeInto(c->end_env, &c->node, &c->type, val); |
| 891 } | 807 } |
| 892 SetEnv(name, c->end_env); | 808 SetEnv(name, c->end_env); |
| 893 stack_.resize(c->stack_depth); | 809 stack_.resize(c->stack_depth); |
| 894 Push(c->type, c->node); | 810 Push(c->type, c->node); |
| 895 control_.pop_back(); | 811 PopControl(); |
| 896 break; | 812 break; |
| 897 } | 813 } |
| 898 case kExprSelect: { | 814 case kExprSelect: { |
| 899 Value cond = Pop(2, kAstI32); | 815 Value cond = Pop(2, kAstI32); |
| 900 Value fval = Pop(); | 816 Value fval = Pop(); |
| 901 Value tval = Pop(); | 817 Value tval = Pop(); |
| 902 if (tval.type == kAstStmt || tval.type != fval.type) { | 818 if (tval.type == kAstStmt || tval.type != fval.type) { |
| 903 if (tval.type != kAstEnd && fval.type != kAstEnd) { | 819 if (tval.type != kAstEnd && fval.type != kAstEnd) { |
| 904 error(pc_, "type mismatch in select"); | 820 error(pc_, "type mismatch in select"); |
| 905 break; | 821 break; |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1286 void PushLoop(SsaEnv* end_env) { | 1202 void PushLoop(SsaEnv* end_env) { |
| 1287 const int stack_depth = static_cast<int>(stack_.size()); | 1203 const int stack_depth = static_cast<int>(stack_.size()); |
| 1288 control_.emplace_back(Control::Loop(pc_, stack_depth, end_env)); | 1204 control_.emplace_back(Control::Loop(pc_, stack_depth, end_env)); |
| 1289 } | 1205 } |
| 1290 | 1206 |
| 1291 void PushIf(SsaEnv* end_env, SsaEnv* false_env) { | 1207 void PushIf(SsaEnv* end_env, SsaEnv* false_env) { |
| 1292 const int stack_depth = static_cast<int>(stack_.size()); | 1208 const int stack_depth = static_cast<int>(stack_.size()); |
| 1293 control_.emplace_back(Control::If(pc_, stack_depth, end_env, false_env)); | 1209 control_.emplace_back(Control::If(pc_, stack_depth, end_env, false_env)); |
| 1294 } | 1210 } |
| 1295 | 1211 |
| 1296 void PushTry(SsaEnv* end_env, SsaEnv* catch_env, SsaEnv* finish_try_env) { | 1212 void PushTry(SsaEnv* end_env, SsaEnv* catch_env) { |
| 1297 const int stack_depth = static_cast<int>(stack_.size()); | 1213 const int stack_depth = static_cast<int>(stack_.size()); |
| 1298 control_.emplace_back( | 1214 control_.emplace_back(Control::Try(pc_, stack_depth, end_env, catch_env)); |
| 1299 Control::Try(pc_, stack_depth, end_env, catch_env, finish_try_env)); | |
| 1300 } | 1215 } |
| 1301 | 1216 |
| 1217 void PopControl() { control_.pop_back(); } |
| 1218 |
| 1302 int DecodeLoadMem(LocalType type, MachineType mem_type) { | 1219 int DecodeLoadMem(LocalType type, MachineType mem_type) { |
| 1303 MemoryAccessOperand operand(this, pc_, | 1220 MemoryAccessOperand operand(this, pc_, |
| 1304 ElementSizeLog2Of(mem_type.representation())); | 1221 ElementSizeLog2Of(mem_type.representation())); |
| 1305 | 1222 |
| 1306 Value index = Pop(0, kAstI32); | 1223 Value index = Pop(0, kAstI32); |
| 1307 TFNode* node = BUILD(LoadMem, type, mem_type, index.node, operand.offset, | 1224 TFNode* node = BUILD(LoadMem, type, mem_type, index.node, operand.offset, |
| 1308 operand.alignment, position()); | 1225 operand.alignment, position()); |
| 1309 Push(type, node); | 1226 Push(type, node); |
| 1310 return 1 + operand.length; | 1227 return 1 + operand.length; |
| 1311 } | 1228 } |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1412 return val; | 1329 return val; |
| 1413 } | 1330 } |
| 1414 } | 1331 } |
| 1415 | 1332 |
| 1416 int baserel(const byte* ptr) { | 1333 int baserel(const byte* ptr) { |
| 1417 return base_ ? static_cast<int>(ptr - base_) : 0; | 1334 return base_ ? static_cast<int>(ptr - base_) : 0; |
| 1418 } | 1335 } |
| 1419 | 1336 |
| 1420 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); } | 1337 int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); } |
| 1421 | 1338 |
| 1422 void BreakTo(Control* block, Value& val) { | 1339 void BreakTo(Control* block, const Value& val) { |
| 1423 if (block->is_loop) { | 1340 if (block->is_loop) { |
| 1424 // This is the inner loop block, which does not have a value. | 1341 // This is the inner loop block, which does not have a value. |
| 1425 Goto(ssa_env_, block->end_env); | 1342 Goto(ssa_env_, block->end_env); |
| 1426 } else { | 1343 } else { |
| 1427 // Merge the value into the production for the block. | 1344 // Merge the value into the production for the block. |
| 1428 MergeInto(block->end_env, &block->node, &block->type, val); | 1345 MergeInto(block->end_env, &block->node, &block->type, val); |
| 1429 } | 1346 } |
| 1430 } | 1347 } |
| 1431 | 1348 |
| 1432 void MergeInto(SsaEnv* target, TFNode** node, LocalType* type, Value& val) { | 1349 void MergeInto(SsaEnv* target, TFNode** node, LocalType* type, |
| 1350 const Value& val) { |
| 1433 if (!ssa_env_->go()) return; | 1351 if (!ssa_env_->go()) return; |
| 1434 DCHECK_NE(kAstEnd, val.type); | 1352 DCHECK_NE(kAstEnd, val.type); |
| 1435 | 1353 |
| 1436 bool first = target->state == SsaEnv::kUnreachable; | 1354 bool first = target->state == SsaEnv::kUnreachable; |
| 1437 Goto(ssa_env_, target); | 1355 Goto(ssa_env_, target); |
| 1438 | 1356 |
| 1439 if (first) { | 1357 if (first) { |
| 1440 // first merge to this environment; set the type and the node. | 1358 // first merge to this environment; set the type and the node. |
| 1441 *type = val.type; | 1359 *type = val.type; |
| 1442 *node = val.node; | 1360 *node = val.node; |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1667 new (zone_) BitVector(static_cast<int>(local_type_vec_.size()), zone_); | 1585 new (zone_) BitVector(static_cast<int>(local_type_vec_.size()), zone_); |
| 1668 int depth = 0; | 1586 int depth = 0; |
| 1669 // Iteratively process all AST nodes nested inside the loop. | 1587 // Iteratively process all AST nodes nested inside the loop. |
| 1670 while (pc < limit_ && ok()) { | 1588 while (pc < limit_ && ok()) { |
| 1671 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); | 1589 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); |
| 1672 unsigned length = 1; | 1590 unsigned length = 1; |
| 1673 switch (opcode) { | 1591 switch (opcode) { |
| 1674 case kExprLoop: | 1592 case kExprLoop: |
| 1675 case kExprIf: | 1593 case kExprIf: |
| 1676 case kExprBlock: | 1594 case kExprBlock: |
| 1677 case kExprTryCatch: | 1595 case kExprTry: |
| 1678 case kExprTryCatchFinally: | |
| 1679 case kExprTryFinally: | |
| 1680 depth++; | 1596 depth++; |
| 1681 DCHECK_EQ(1, OpcodeLength(pc)); | 1597 DCHECK_EQ(1, OpcodeLength(pc)); |
| 1682 break; | 1598 break; |
| 1683 case kExprSetLocal: { | 1599 case kExprSetLocal: { |
| 1684 LocalIndexOperand operand(this, pc); | 1600 LocalIndexOperand operand(this, pc); |
| 1685 if (assigned->length() > 0 && | 1601 if (assigned->length() > 0 && |
| 1686 operand.index < static_cast<uint32_t>(assigned->length())) { | 1602 operand.index < static_cast<uint32_t>(assigned->length())) { |
| 1687 // Unverified code might have an out-of-bounds index. | 1603 // Unverified code might have an out-of-bounds index. |
| 1688 assigned->Add(operand.index); | 1604 assigned->Add(operand.index); |
| 1689 } | 1605 } |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1840 | 1756 |
| 1841 for (size_t j = 1; j < length; ++j) { | 1757 for (size_t j = 1; j < length; ++j) { |
| 1842 os << " " << AsHex(i.pc()[j], 2) << ","; | 1758 os << " " << AsHex(i.pc()[j], 2) << ","; |
| 1843 } | 1759 } |
| 1844 | 1760 |
| 1845 switch (opcode) { | 1761 switch (opcode) { |
| 1846 case kExprIf: | 1762 case kExprIf: |
| 1847 case kExprElse: | 1763 case kExprElse: |
| 1848 case kExprLoop: | 1764 case kExprLoop: |
| 1849 case kExprBlock: | 1765 case kExprBlock: |
| 1850 case kExprTryCatch: | 1766 case kExprTry: |
| 1851 case kExprTryCatchFinally: | |
| 1852 case kExprTryFinally: | |
| 1853 os << " // @" << i.pc_offset(); | 1767 os << " // @" << i.pc_offset(); |
| 1854 control_depth++; | 1768 control_depth++; |
| 1855 break; | 1769 break; |
| 1856 case kExprEnd: | 1770 case kExprEnd: |
| 1857 os << " // @" << i.pc_offset(); | 1771 os << " // @" << i.pc_offset(); |
| 1858 control_depth--; | 1772 control_depth--; |
| 1859 break; | 1773 break; |
| 1860 case kExprBr: { | 1774 case kExprBr: { |
| 1861 BreakDepthOperand operand(&i, i.pc()); | 1775 BreakDepthOperand operand(&i, i.pc()); |
| 1862 os << " // arity=" << operand.arity << " depth=" << operand.depth; | 1776 os << " // arity=" << operand.arity << " depth=" << operand.depth; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1918 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, | 1832 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, |
| 1919 const byte* start, const byte* end) { | 1833 const byte* start, const byte* end) { |
| 1920 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; | 1834 FunctionBody body = {nullptr, nullptr, nullptr, start, end}; |
| 1921 WasmFullDecoder decoder(zone, nullptr, body); | 1835 WasmFullDecoder decoder(zone, nullptr, body); |
| 1922 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); | 1836 return decoder.AnalyzeLoopAssignmentForTesting(start, num_locals); |
| 1923 } | 1837 } |
| 1924 | 1838 |
| 1925 } // namespace wasm | 1839 } // namespace wasm |
| 1926 } // namespace internal | 1840 } // namespace internal |
| 1927 } // namespace v8 | 1841 } // namespace v8 |
| OLD | NEW |