OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/wasm/wasm-interpreter.h" | 5 #include "src/wasm/wasm-interpreter.h" |
6 #include "src/wasm/ast-decoder.h" | 6 #include "src/wasm/ast-decoder.h" |
7 #include "src/wasm/decoder.h" | 7 #include "src/wasm/decoder.h" |
8 #include "src/wasm/wasm-external-refs.h" | 8 #include "src/wasm/wasm-external-refs.h" |
9 #include "src/wasm/wasm-module.h" | 9 #include "src/wasm/wasm-module.h" |
10 | 10 |
(...skipping 743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 // This works by maintaining a stack of control constructs similar to the | 754 // This works by maintaining a stack of control constructs similar to the |
755 // AST decoder. The {control_stack} allows matching {br,br_if,br_table} | 755 // AST decoder. The {control_stack} allows matching {br,br_if,br_table} |
756 // bytecodes with their target, as well as determining whether the current | 756 // bytecodes with their target, as well as determining whether the current |
757 // bytecodes are within the true or false block of an else. | 757 // bytecodes are within the true or false block of an else. |
758 // The value stack depth is tracked as {value_depth} and is needed to | 758 // The value stack depth is tracked as {value_depth} and is needed to |
759 // determine how many values to pop off the stack for explicit and | 759 // determine how many values to pop off the stack for explicit and |
760 // implicit control flow. | 760 // implicit control flow. |
761 | 761 |
762 std::vector<Control> control_stack; | 762 std::vector<Control> control_stack; |
763 size_t value_depth = 0; | 763 size_t value_depth = 0; |
764 Decoder decoder(start, end); // for reading operands. | 764 for (BytecodeIterator i(start + locals_encoded_size, end); i.has_next(); |
765 const byte* pc = start + locals_encoded_size; | 765 i.next()) { |
766 | 766 WasmOpcode opcode = i.current(); |
767 while (pc < end) { | 767 TRACE("@%u: control %s (depth = %zu)\n", i.pc_offset(), |
768 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); | |
769 TRACE("@%td: control %s (depth = %zu)\n", (pc - start), | |
770 WasmOpcodes::OpcodeName(opcode), value_depth); | 768 WasmOpcodes::OpcodeName(opcode), value_depth); |
771 switch (opcode) { | 769 switch (opcode) { |
772 case kExprBlock: { | 770 case kExprBlock: { |
773 TRACE("control @%td $%zu: Block\n", (pc - start), value_depth); | 771 TRACE("control @%u $%zu: Block\n", i.pc_offset(), value_depth); |
774 CLabel* label = new (zone) CLabel(zone, value_depth); | 772 CLabel* label = new (zone) CLabel(zone, value_depth); |
775 control_stack.push_back({pc, label, nullptr}); | 773 control_stack.push_back({i.pc(), label, nullptr}); |
776 break; | 774 break; |
777 } | 775 } |
778 case kExprLoop: { | 776 case kExprLoop: { |
779 TRACE("control @%td $%zu: Loop\n", (pc - start), value_depth); | 777 TRACE("control @%u $%zu: Loop\n", i.pc_offset(), value_depth); |
780 CLabel* label1 = new (zone) CLabel(zone, value_depth); | 778 CLabel* label1 = new (zone) CLabel(zone, value_depth); |
781 CLabel* label2 = new (zone) CLabel(zone, value_depth); | 779 CLabel* label2 = new (zone) CLabel(zone, value_depth); |
782 control_stack.push_back({pc, label1, nullptr}); | 780 control_stack.push_back({i.pc(), label1, nullptr}); |
783 control_stack.push_back({pc, label2, nullptr}); | 781 control_stack.push_back({i.pc(), label2, nullptr}); |
784 label2->Bind(&map_, start, pc, false); | 782 label2->Bind(&map_, start, i.pc(), false); |
785 break; | 783 break; |
786 } | 784 } |
787 case kExprIf: { | 785 case kExprIf: { |
788 TRACE("control @%td $%zu: If\n", (pc - start), value_depth); | 786 TRACE("control @%u $%zu: If\n", i.pc_offset(), value_depth); |
789 value_depth--; | 787 value_depth--; |
790 CLabel* end_label = new (zone) CLabel(zone, value_depth); | 788 CLabel* end_label = new (zone) CLabel(zone, value_depth); |
791 CLabel* else_label = new (zone) CLabel(zone, value_depth); | 789 CLabel* else_label = new (zone) CLabel(zone, value_depth); |
792 control_stack.push_back({pc, end_label, else_label}); | 790 control_stack.push_back({i.pc(), end_label, else_label}); |
793 else_label->Ref(&map_, start, {pc, value_depth, false}); | 791 else_label->Ref(&map_, start, {i.pc(), value_depth, false}); |
794 break; | 792 break; |
795 } | 793 } |
796 case kExprElse: { | 794 case kExprElse: { |
797 Control* c = &control_stack.back(); | 795 Control* c = &control_stack.back(); |
798 TRACE("control @%td $%zu: Else\n", (pc - start), value_depth); | 796 TRACE("control @%u $%zu: Else\n", i.pc_offset(), value_depth); |
799 c->end_label->Ref(&map_, start, {pc, value_depth, false}); | 797 c->end_label->Ref(&map_, start, {i.pc(), value_depth, false}); |
800 value_depth = c->end_label->value_depth; | 798 value_depth = c->end_label->value_depth; |
801 DCHECK_NOT_NULL(c->else_label); | 799 DCHECK_NOT_NULL(c->else_label); |
802 c->else_label->Bind(&map_, start, pc + 1, false); | 800 c->else_label->Bind(&map_, start, i.pc() + 1, false); |
803 c->else_label = nullptr; | 801 c->else_label = nullptr; |
804 break; | 802 break; |
805 } | 803 } |
806 case kExprEnd: { | 804 case kExprEnd: { |
807 Control* c = &control_stack.back(); | 805 Control* c = &control_stack.back(); |
808 TRACE("control @%td $%zu: End\n", (pc - start), value_depth); | 806 TRACE("control @%u $%zu: End\n", i.pc_offset(), value_depth); |
809 if (c->end_label->target) { | 807 if (c->end_label->target) { |
810 // only loops have bound labels. | 808 // only loops have bound labels. |
811 DCHECK_EQ(kExprLoop, *c->pc); | 809 DCHECK_EQ(kExprLoop, *c->pc); |
812 control_stack.pop_back(); | 810 control_stack.pop_back(); |
813 c = &control_stack.back(); | 811 c = &control_stack.back(); |
814 } | 812 } |
815 if (c->else_label) c->else_label->Bind(&map_, start, pc + 1, true); | 813 if (c->else_label) |
816 c->end_label->Ref(&map_, start, {pc, value_depth, false}); | 814 c->else_label->Bind(&map_, start, i.pc() + 1, true); |
817 c->end_label->Bind(&map_, start, pc + 1, true); | 815 c->end_label->Ref(&map_, start, {i.pc(), value_depth, false}); |
| 816 c->end_label->Bind(&map_, start, i.pc() + 1, true); |
818 value_depth = c->end_label->value_depth + 1; | 817 value_depth = c->end_label->value_depth + 1; |
819 control_stack.pop_back(); | 818 control_stack.pop_back(); |
820 break; | 819 break; |
821 } | 820 } |
822 case kExprBr: { | 821 case kExprBr: { |
823 BreakDepthOperand operand(&decoder, pc); | 822 BreakDepthOperand operand(&i, i.pc()); |
824 TRACE("control @%td $%zu: Br[arity=%u, depth=%u]\n", (pc - start), | 823 TRACE("control @%u $%zu: Br[arity=%u, depth=%u]\n", i.pc_offset(), |
825 value_depth, operand.arity, operand.depth); | 824 value_depth, operand.arity, operand.depth); |
826 value_depth -= operand.arity; | 825 value_depth -= operand.arity; |
827 control_stack[control_stack.size() - operand.depth - 1].Ref( | 826 control_stack[control_stack.size() - operand.depth - 1].Ref( |
828 &map_, start, pc, value_depth, operand.arity > 0); | 827 &map_, start, i.pc(), value_depth, operand.arity > 0); |
829 value_depth++; | 828 value_depth++; |
830 break; | 829 break; |
831 } | 830 } |
832 case kExprBrIf: { | 831 case kExprBrIf: { |
833 BreakDepthOperand operand(&decoder, pc); | 832 BreakDepthOperand operand(&i, i.pc()); |
834 TRACE("control @%td $%zu: BrIf[arity=%u, depth=%u]\n", (pc - start), | 833 TRACE("control @%u $%zu: BrIf[arity=%u, depth=%u]\n", i.pc_offset(), |
835 value_depth, operand.arity, operand.depth); | 834 value_depth, operand.arity, operand.depth); |
836 value_depth -= (operand.arity + 1); | 835 value_depth -= (operand.arity + 1); |
837 control_stack[control_stack.size() - operand.depth - 1].Ref( | 836 control_stack[control_stack.size() - operand.depth - 1].Ref( |
838 &map_, start, pc, value_depth, operand.arity > 0); | 837 &map_, start, i.pc(), value_depth, operand.arity > 0); |
839 value_depth++; | 838 value_depth++; |
840 break; | 839 break; |
841 } | 840 } |
842 case kExprBrTable: { | 841 case kExprBrTable: { |
843 BranchTableOperand operand(&decoder, pc); | 842 BranchTableOperand operand(&i, i.pc()); |
844 TRACE("control @%td $%zu: BrTable[arity=%u count=%u]\n", (pc - start), | 843 TRACE("control @%u $%zu: BrTable[arity=%u count=%u]\n", i.pc_offset(), |
845 value_depth, operand.arity, operand.table_count); | 844 value_depth, operand.arity, operand.table_count); |
846 value_depth -= (operand.arity + 1); | 845 value_depth -= (operand.arity + 1); |
847 for (uint32_t i = 0; i < operand.table_count + 1; ++i) { | 846 for (uint32_t j = 0; j < operand.table_count + 1; ++j) { |
848 uint32_t target = operand.read_entry(&decoder, i); | 847 uint32_t target = operand.read_entry(&i, j); |
849 control_stack[control_stack.size() - target - 1].Ref( | 848 control_stack[control_stack.size() - target - 1].Ref( |
850 &map_, start, pc + i, value_depth, operand.arity > 0); | 849 &map_, start, i.pc() + j, value_depth, operand.arity > 0); |
851 } | 850 } |
852 value_depth++; | 851 value_depth++; |
853 break; | 852 break; |
854 } | 853 } |
855 default: { | 854 default: { |
856 value_depth = value_depth - OpcodeArity(pc, end) + 1; | 855 value_depth = value_depth - OpcodeArity(i.pc(), end) + 1; |
857 break; | 856 break; |
858 } | 857 } |
859 } | 858 } |
860 | |
861 pc += OpcodeLength(pc, end); | |
862 } | 859 } |
863 } | 860 } |
864 | 861 |
865 ControlTransfer Lookup(pc_t from) { | 862 ControlTransfer Lookup(pc_t from) { |
866 auto result = map_.find(from); | 863 auto result = map_.find(from); |
867 if (result == map_.end()) { | 864 if (result == map_.end()) { |
868 V8_Fatal(__FILE__, __LINE__, "no control target for pc %zu", from); | 865 V8_Fatal(__FILE__, __LINE__, "no control target for pc %zu", from); |
869 } | 866 } |
870 return result->second; | 867 return result->second; |
871 } | 868 } |
(...skipping 971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1843 | 1840 |
1844 ControlTransferMap WasmInterpreter::ComputeControlTransfersForTesting( | 1841 ControlTransferMap WasmInterpreter::ComputeControlTransfersForTesting( |
1845 Zone* zone, const byte* start, const byte* end) { | 1842 Zone* zone, const byte* start, const byte* end) { |
1846 ControlTransfers targets(zone, 0, start, end); | 1843 ControlTransfers targets(zone, 0, start, end); |
1847 return targets.map_; | 1844 return targets.map_; |
1848 } | 1845 } |
1849 | 1846 |
1850 } // namespace wasm | 1847 } // namespace wasm |
1851 } // namespace internal | 1848 } // namespace internal |
1852 } // namespace v8 | 1849 } // namespace v8 |
OLD | NEW |