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

Side by Side Diff: src/wasm/wasm-interpreter.cc

Issue 2345593003: [wasm] Master CL for Binary 0xC changes. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Minor fixes 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
OLDNEW
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 6
7 #include "src/utils.h" 7 #include "src/utils.h"
8 #include "src/wasm/ast-decoder.h" 8 #include "src/wasm/ast-decoder.h"
9 #include "src/wasm/decoder.h" 9 #include "src/wasm/decoder.h"
10 #include "src/wasm/wasm-external-refs.h" 10 #include "src/wasm/wasm-external-refs.h"
(...skipping 704 matching lines...) Expand 10 before | Expand all | Expand 10 after
715 715
716 static const int kRunSteps = 1000; 716 static const int kRunSteps = 1000;
717 717
718 // A helper class to compute the control transfers for each bytecode offset. 718 // A helper class to compute the control transfers for each bytecode offset.
719 // Control transfers allow Br, BrIf, BrTable, If, Else, and End bytecodes to 719 // Control transfers allow Br, BrIf, BrTable, If, Else, and End bytecodes to
720 // be directly executed without the need to dynamically track blocks. 720 // be directly executed without the need to dynamically track blocks.
721 class ControlTransfers : public ZoneObject { 721 class ControlTransfers : public ZoneObject {
722 public: 722 public:
723 ControlTransferMap map_; 723 ControlTransferMap map_;
724 724
725 ControlTransfers(Zone* zone, size_t locals_encoded_size, const byte* start, 725 ControlTransfers(Zone* zone, ModuleEnv* env, AstLocalDecls* locals,
726 const byte* end) 726 const byte* start, const byte* end)
727 : map_(zone) { 727 : map_(zone) {
728 // A control reference including from PC, from value depth, and whether
729 // a value is explicitly passed (e.g. br/br_if/br_table with value).
730 struct CRef {
731 const byte* pc;
732 sp_t value_depth;
733 bool explicit_value;
734 };
735
736 // Represents a control flow label. 728 // Represents a control flow label.
737 struct CLabel : public ZoneObject { 729 struct CLabel : public ZoneObject {
738 const byte* target; 730 const byte* target;
739 size_t value_depth; 731 ZoneVector<const byte*> refs;
740 ZoneVector<CRef> refs;
741 732
742 CLabel(Zone* zone, size_t v) 733 explicit CLabel(Zone* zone) : target(nullptr), refs(zone) {}
743 : target(nullptr), value_depth(v), refs(zone) {}
744 734
745 // Bind this label to the given PC. 735 // Bind this label to the given PC.
746 void Bind(ControlTransferMap* map, const byte* start, const byte* pc, 736 void Bind(ControlTransferMap* map, const byte* start, const byte* pc) {
747 bool expect_value) {
748 DCHECK_NULL(target); 737 DCHECK_NULL(target);
749 target = pc; 738 target = pc;
750 for (auto from : refs) { 739 for (auto from_pc : refs) {
751 auto pcdiff = static_cast<pcdiff_t>(target - from.pc); 740 auto pcdiff = static_cast<pcdiff_t>(target - from_pc);
ahaas 2016/09/16 13:48:19 pcdiff_t is hardly any longer than auto.
752 auto spdiff = static_cast<spdiff_t>(from.value_depth - value_depth); 741 size_t offset = static_cast<size_t>(from_pc - start);
753 ControlTransfer::StackAction action = ControlTransfer::kNoAction; 742 (*map)[offset] = pcdiff;
754 if (expect_value && !from.explicit_value) {
755 action = spdiff == 0 ? ControlTransfer::kPushVoid
756 : ControlTransfer::kPopAndRepush;
757 }
758 pc_t offset = static_cast<size_t>(from.pc - start);
759 (*map)[offset] = {pcdiff, spdiff, action};
760 } 743 }
761 } 744 }
762 745
763 // Reference this label from the given location. 746 // Reference this label from the given location.
764 void Ref(ControlTransferMap* map, const byte* start, CRef from) { 747 void Ref(ControlTransferMap* map, const byte* start,
765 DCHECK_GE(from.value_depth, value_depth); 748 const byte* from_pc) {
766 if (target) { 749 if (target) {
767 auto pcdiff = static_cast<pcdiff_t>(target - from.pc); 750 // Target being bound before a reference means this is a loop.
768 auto spdiff = static_cast<spdiff_t>(from.value_depth - value_depth); 751 DCHECK_EQ(kExprLoop, *target);
769 pc_t offset = static_cast<size_t>(from.pc - start); 752 auto pcdiff = static_cast<pcdiff_t>(target - from_pc);
770 (*map)[offset] = {pcdiff, spdiff, ControlTransfer::kNoAction}; 753 size_t offset = static_cast<size_t>(from_pc - start);
754 (*map)[offset] = pcdiff;
771 } else { 755 } else {
772 refs.push_back(from); 756 refs.push_back(from_pc);
773 } 757 }
774 } 758 }
775 }; 759 };
776 760
777 // An entry in the control stack. 761 // An entry in the control stack.
778 struct Control { 762 struct Control {
779 const byte* pc; 763 const byte* pc;
780 CLabel* end_label; 764 CLabel* end_label;
781 CLabel* else_label; 765 CLabel* else_label;
782 766
783 void Ref(ControlTransferMap* map, const byte* start, const byte* from_pc, 767 void Ref(ControlTransferMap* map, const byte* start,
784 size_t from_value_depth, bool explicit_value) { 768 const byte* from_pc) {
785 end_label->Ref(map, start, {from_pc, from_value_depth, explicit_value}); 769 end_label->Ref(map, start, from_pc);
786 } 770 }
787 }; 771 };
788 772
789 // Compute the ControlTransfer map. 773 // Compute the ControlTransfer map.
790 // This works by maintaining a stack of control constructs similar to the 774 // This algorithm maintains a stack of control constructs similar to the
791 // AST decoder. The {control_stack} allows matching {br,br_if,br_table} 775 // AST decoder. The {control_stack} allows matching {br,br_if,br_table}
792 // bytecodes with their target, as well as determining whether the current 776 // bytecodes with their target, as well as determining whether the current
793 // bytecodes are within the true or false block of an else. 777 // bytecodes are within the true or false block of an else.
794 // The value stack depth is tracked as {value_depth} and is needed to
795 // determine how many values to pop off the stack for explicit and
796 // implicit control flow.
797
798 std::vector<Control> control_stack; 778 std::vector<Control> control_stack;
799 size_t value_depth = 0; 779 CLabel* func_label = new (zone) CLabel(zone);
800 for (BytecodeIterator i(start + locals_encoded_size, end); i.has_next(); 780 control_stack.push_back({start, func_label, nullptr});
801 i.next()) { 781 for (BytecodeIterator i(start, end, locals); i.has_next(); i.next()) {
802 WasmOpcode opcode = i.current(); 782 WasmOpcode opcode = i.current();
803 TRACE("@%u: control %s (depth = %zu)\n", i.pc_offset(), 783 TRACE("@%u: control %s\n", i.pc_offset(),
804 WasmOpcodes::OpcodeName(opcode), value_depth); 784 WasmOpcodes::OpcodeName(opcode));
805 switch (opcode) { 785 switch (opcode) {
806 case kExprBlock: { 786 case kExprBlock: {
807 TRACE("control @%u $%zu: Block\n", i.pc_offset(), value_depth); 787 TRACE("control @%u: Block\n", i.pc_offset());
808 CLabel* label = new (zone) CLabel(zone, value_depth); 788 CLabel* label = new (zone) CLabel(zone);
809 control_stack.push_back({i.pc(), label, nullptr}); 789 control_stack.push_back({i.pc(), label, nullptr});
810 break; 790 break;
811 } 791 }
812 case kExprLoop: { 792 case kExprLoop: {
813 TRACE("control @%u $%zu: Loop\n", i.pc_offset(), value_depth); 793 TRACE("control @%u: Loop\n", i.pc_offset());
814 CLabel* label1 = new (zone) CLabel(zone, value_depth); 794 CLabel* label = new (zone) CLabel(zone);
815 CLabel* label2 = new (zone) CLabel(zone, value_depth); 795 control_stack.push_back({i.pc(), label, nullptr});
816 control_stack.push_back({i.pc(), label1, nullptr}); 796 label->Bind(&map_, start, i.pc());
817 control_stack.push_back({i.pc(), label2, nullptr});
818 label2->Bind(&map_, start, i.pc(), false);
819 break; 797 break;
820 } 798 }
821 case kExprIf: { 799 case kExprIf: {
822 TRACE("control @%u $%zu: If\n", i.pc_offset(), value_depth); 800 TRACE("control @%u: If\n", i.pc_offset());
823 value_depth--; 801 CLabel* end_label = new (zone) CLabel(zone);
824 CLabel* end_label = new (zone) CLabel(zone, value_depth); 802 CLabel* else_label = new (zone) CLabel(zone);
825 CLabel* else_label = new (zone) CLabel(zone, value_depth);
826 control_stack.push_back({i.pc(), end_label, else_label}); 803 control_stack.push_back({i.pc(), end_label, else_label});
827 else_label->Ref(&map_, start, {i.pc(), value_depth, false}); 804 else_label->Ref(&map_, start, i.pc());
828 break; 805 break;
829 } 806 }
830 case kExprElse: { 807 case kExprElse: {
831 Control* c = &control_stack.back(); 808 Control* c = &control_stack.back();
832 TRACE("control @%u $%zu: Else\n", i.pc_offset(), value_depth); 809 TRACE("control @%u: Else\n", i.pc_offset());
833 c->end_label->Ref(&map_, start, {i.pc(), value_depth, false}); 810 c->end_label->Ref(&map_, start, i.pc());
834 value_depth = c->end_label->value_depth;
835 DCHECK_NOT_NULL(c->else_label); 811 DCHECK_NOT_NULL(c->else_label);
836 c->else_label->Bind(&map_, start, i.pc() + 1, false); 812 c->else_label->Bind(&map_, start, i.pc() + 1);
837 c->else_label = nullptr; 813 c->else_label = nullptr;
838 break; 814 break;
839 } 815 }
840 case kExprEnd: { 816 case kExprEnd: {
841 Control* c = &control_stack.back(); 817 Control* c = &control_stack.back();
842 TRACE("control @%u $%zu: End\n", i.pc_offset(), value_depth); 818 TRACE("control @%u: End\n", i.pc_offset());
843 if (c->end_label->target) { 819 if (c->end_label->target) {
844 // only loops have bound labels. 820 // only loops have bound labels.
845 DCHECK_EQ(kExprLoop, *c->pc); 821 DCHECK_EQ(kExprLoop, *c->pc);
846 control_stack.pop_back(); 822 } else {
847 c = &control_stack.back(); 823 if (c->else_label) c->else_label->Bind(&map_, start, i.pc());
824 c->end_label->Bind(&map_, start, i.pc() + 1);
848 } 825 }
849 if (c->else_label)
850 c->else_label->Bind(&map_, start, i.pc() + 1, true);
851 c->end_label->Ref(&map_, start, {i.pc(), value_depth, false});
852 c->end_label->Bind(&map_, start, i.pc() + 1, true);
853 value_depth = c->end_label->value_depth + 1;
854 control_stack.pop_back(); 826 control_stack.pop_back();
855 break; 827 break;
856 } 828 }
857 case kExprBr: { 829 case kExprBr: {
858 BreakDepthOperand operand(&i, i.pc()); 830 BreakDepthOperand operand(&i, i.pc());
859 TRACE("control @%u $%zu: Br[arity=%u, depth=%u]\n", i.pc_offset(), 831 TRACE("control @%u: Br[depth=%u]\n", i.pc_offset(), operand.depth);
860 value_depth, operand.arity, operand.depth); 832 Control* c = &control_stack[control_stack.size() - operand.depth - 1];
861 value_depth -= operand.arity; 833 c->Ref(&map_, start, i.pc());
862 control_stack[control_stack.size() - operand.depth - 1].Ref(
863 &map_, start, i.pc(), value_depth, operand.arity > 0);
864 value_depth++;
865 break; 834 break;
866 } 835 }
867 case kExprBrIf: { 836 case kExprBrIf: {
868 BreakDepthOperand operand(&i, i.pc()); 837 BreakDepthOperand operand(&i, i.pc());
869 TRACE("control @%u $%zu: BrIf[arity=%u, depth=%u]\n", i.pc_offset(), 838 TRACE("control @%u: BrIf[depth=%u]\n", i.pc_offset(), operand.depth);
870 value_depth, operand.arity, operand.depth); 839 Control* c = &control_stack[control_stack.size() - operand.depth - 1];
871 value_depth -= (operand.arity + 1); 840 c->Ref(&map_, start, i.pc());
872 control_stack[control_stack.size() - operand.depth - 1].Ref(
873 &map_, start, i.pc(), value_depth, operand.arity > 0);
874 value_depth++;
875 break; 841 break;
876 } 842 }
877 case kExprBrTable: { 843 case kExprBrTable: {
878 BranchTableOperand operand(&i, i.pc()); 844 BranchTableOperand operand(&i, i.pc());
879 TRACE("control @%u $%zu: BrTable[arity=%u count=%u]\n", i.pc_offset(), 845 TRACE("control @%u: BrTable[count=%u]\n", i.pc_offset(),
880 value_depth, operand.arity, operand.table_count); 846 operand.table_count);
881 value_depth -= (operand.arity + 1);
882 for (uint32_t j = 0; j < operand.table_count + 1; ++j) { 847 for (uint32_t j = 0; j < operand.table_count + 1; ++j) {
883 uint32_t target = operand.read_entry(&i, j); 848 uint32_t target = operand.read_entry(&i, j);
884 control_stack[control_stack.size() - target - 1].Ref( 849 Control* c = &control_stack[control_stack.size() - target - 1];
885 &map_, start, i.pc() + j, value_depth, operand.arity > 0); 850 c->Ref(&map_, start, i.pc() + j);
886 } 851 }
887 value_depth++;
888 break; 852 break;
889 } 853 }
890 default: { 854 default: {
891 value_depth = value_depth - OpcodeArity(i.pc(), end) + 1;
892 break; 855 break;
893 } 856 }
894 } 857 }
895 } 858 }
859 if (!func_label->target) func_label->Bind(&map_, start, end);
896 } 860 }
897 861
898 ControlTransfer Lookup(pc_t from) { 862 pcdiff_t Lookup(pc_t from) {
899 auto result = map_.find(from); 863 auto result = map_.find(from);
900 if (result == map_.end()) { 864 if (result == map_.end()) {
901 V8_Fatal(__FILE__, __LINE__, "no control target for pc %zu", from); 865 V8_Fatal(__FILE__, __LINE__, "no control target for pc %zu", from);
902 } 866 }
903 return result->second; 867 return result->second;
904 } 868 }
905 }; 869 };
906 870
907 // Code and metadata needed to execute a function. 871 // Code and metadata needed to execute a function.
908 struct InterpreterCode { 872 struct InterpreterCode {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
958 if (entry_index >= table->values.size()) return nullptr; 922 if (entry_index >= table->values.size()) return nullptr;
959 uint32_t index = table->values[entry_index]; 923 uint32_t index = table->values[entry_index];
960 if (index >= interpreter_code_.size()) return nullptr; 924 if (index >= interpreter_code_.size()) return nullptr;
961 return GetCode(index); 925 return GetCode(index);
962 } 926 }
963 927
964 InterpreterCode* Preprocess(InterpreterCode* code) { 928 InterpreterCode* Preprocess(InterpreterCode* code) {
965 if (code->targets == nullptr && code->start) { 929 if (code->targets == nullptr && code->start) {
966 // Compute the control targets map and the local declarations. 930 // Compute the control targets map and the local declarations.
967 CHECK(DecodeLocalDecls(code->locals, code->start, code->end)); 931 CHECK(DecodeLocalDecls(code->locals, code->start, code->end));
968 code->targets = 932 ModuleEnv env = {module_, nullptr, kWasmOrigin};
969 new (zone_) ControlTransfers(zone_, code->locals.decls_encoded_size, 933 code->targets = new (zone_) ControlTransfers(
970 code->orig_start, code->orig_end); 934 zone_, &env, &code->locals, code->orig_start, code->orig_end);
971 } 935 }
972 return code; 936 return code;
973 } 937 }
974 938
975 int AddFunction(const WasmFunction* function, const byte* code_start, 939 int AddFunction(const WasmFunction* function, const byte* code_start,
976 const byte* code_end) { 940 const byte* code_end) {
977 InterpreterCode code = { 941 InterpreterCode code = {
978 function, AstLocalDecls(zone_), code_start, 942 function, AstLocalDecls(zone_), code_start,
979 code_end, const_cast<byte*>(code_start), const_cast<byte*>(code_end), 943 code_end, const_cast<byte*>(code_start), const_cast<byte*>(code_end),
980 nullptr}; 944 nullptr};
(...skipping 18 matching lines...) Expand all
999 }; 963 };
1000 964
1001 // Responsible for executing code directly. 965 // Responsible for executing code directly.
1002 class ThreadImpl : public WasmInterpreter::Thread { 966 class ThreadImpl : public WasmInterpreter::Thread {
1003 public: 967 public:
1004 ThreadImpl(Zone* zone, CodeMap* codemap, WasmModuleInstance* instance) 968 ThreadImpl(Zone* zone, CodeMap* codemap, WasmModuleInstance* instance)
1005 : codemap_(codemap), 969 : codemap_(codemap),
1006 instance_(instance), 970 instance_(instance),
1007 stack_(zone), 971 stack_(zone),
1008 frames_(zone), 972 frames_(zone),
973 blocks_(zone),
1009 state_(WasmInterpreter::STOPPED), 974 state_(WasmInterpreter::STOPPED),
1010 break_pc_(kInvalidPc), 975 break_pc_(kInvalidPc),
1011 trap_reason_(kTrapCount) {} 976 trap_reason_(kTrapCount) {}
1012 977
1013 virtual ~ThreadImpl() {} 978 virtual ~ThreadImpl() {}
1014 979
1015 //========================================================================== 980 //==========================================================================
1016 // Implementation of public interface for WasmInterpreter::Thread. 981 // Implementation of public interface for WasmInterpreter::Thread.
1017 //========================================================================== 982 //==========================================================================
1018 983
1019 virtual WasmInterpreter::State state() { return state_; } 984 virtual WasmInterpreter::State state() { return state_; }
1020 985
1021 virtual void PushFrame(const WasmFunction* function, WasmVal* args) { 986 virtual void PushFrame(const WasmFunction* function, WasmVal* args) {
1022 InterpreterCode* code = codemap()->FindCode(function); 987 InterpreterCode* code = codemap()->FindCode(function);
1023 CHECK_NOT_NULL(code); 988 CHECK_NOT_NULL(code);
1024 frames_.push_back({code, 0, 0, stack_.size()}); 989 frames_.push_back({code, 0, 0, stack_.size()});
1025 for (size_t i = 0; i < function->sig->parameter_count(); ++i) { 990 for (size_t i = 0; i < function->sig->parameter_count(); ++i) {
1026 stack_.push_back(args[i]); 991 stack_.push_back(args[i]);
1027 } 992 }
1028 frames_.back().ret_pc = InitLocals(code); 993 frames_.back().ret_pc = InitLocals(code);
994 blocks_.push_back(
995 {0, stack_.size(), frames_.size(),
996 static_cast<uint32_t>(code->function->sig->return_count())});
1029 TRACE(" => PushFrame(#%u @%zu)\n", code->function->func_index, 997 TRACE(" => PushFrame(#%u @%zu)\n", code->function->func_index,
1030 frames_.back().ret_pc); 998 frames_.back().ret_pc);
1031 } 999 }
1032 1000
1033 virtual WasmInterpreter::State Run() { 1001 virtual WasmInterpreter::State Run() {
1034 do { 1002 do {
1035 TRACE(" => Run()\n"); 1003 TRACE(" => Run()\n");
1036 if (state_ == WasmInterpreter::STOPPED || 1004 if (state_ == WasmInterpreter::STOPPED ||
1037 state_ == WasmInterpreter::PAUSED) { 1005 state_ == WasmInterpreter::PAUSED) {
1038 state_ = WasmInterpreter::RUNNING; 1006 state_ = WasmInterpreter::RUNNING;
(...skipping 28 matching lines...) Expand all
1067 virtual const WasmFrame* GetFrame(int index) { 1035 virtual const WasmFrame* GetFrame(int index) {
1068 UNIMPLEMENTED(); 1036 UNIMPLEMENTED();
1069 return nullptr; 1037 return nullptr;
1070 } 1038 }
1071 1039
1072 virtual WasmFrame* GetMutableFrame(int index) { 1040 virtual WasmFrame* GetMutableFrame(int index) {
1073 UNIMPLEMENTED(); 1041 UNIMPLEMENTED();
1074 return nullptr; 1042 return nullptr;
1075 } 1043 }
1076 1044
1077 virtual WasmVal GetReturnValue() { 1045 virtual WasmVal GetReturnValue(int index) {
1078 if (state_ == WasmInterpreter::TRAPPED) return WasmVal(0xdeadbeef); 1046 if (state_ == WasmInterpreter::TRAPPED) return WasmVal(0xdeadbeef);
1079 CHECK_EQ(WasmInterpreter::FINISHED, state_); 1047 CHECK_EQ(WasmInterpreter::FINISHED, state_);
1080 CHECK_EQ(1, stack_.size()); 1048 CHECK_LT(static_cast<size_t>(index), stack_.size());
1081 return stack_[0]; 1049 return stack_[index];
1082 } 1050 }
1083 1051
1084 virtual pc_t GetBreakpointPc() { return break_pc_; } 1052 virtual pc_t GetBreakpointPc() { return break_pc_; }
1085 1053
1086 bool Terminated() { 1054 bool Terminated() {
1087 return state_ == WasmInterpreter::TRAPPED || 1055 return state_ == WasmInterpreter::TRAPPED ||
1088 state_ == WasmInterpreter::FINISHED; 1056 state_ == WasmInterpreter::FINISHED;
1089 } 1057 }
1090 1058
1091 private: 1059 private:
1092 // Entries on the stack of functions being evaluated. 1060 // Entries on the stack of functions being evaluated.
1093 struct Frame { 1061 struct Frame {
1094 InterpreterCode* code; 1062 InterpreterCode* code;
1095 pc_t call_pc; 1063 pc_t call_pc;
1096 pc_t ret_pc; 1064 pc_t ret_pc;
1097 sp_t sp; 1065 sp_t sp;
1098 1066
1099 // Limit of parameters. 1067 // Limit of parameters.
1100 sp_t plimit() { return sp + code->function->sig->parameter_count(); } 1068 sp_t plimit() { return sp + code->function->sig->parameter_count(); }
1101 // Limit of locals. 1069 // Limit of locals.
1102 sp_t llimit() { return plimit() + code->locals.total_local_count; } 1070 sp_t llimit() { return plimit() + code->locals.total_local_count; }
1103 }; 1071 };
1104 1072
1073 struct Block {
1074 pc_t pc;
1075 sp_t sp;
1076 size_t fp;
1077 unsigned arity;
1078 };
1079
1105 CodeMap* codemap_; 1080 CodeMap* codemap_;
1106 WasmModuleInstance* instance_; 1081 WasmModuleInstance* instance_;
1107 ZoneVector<WasmVal> stack_; 1082 ZoneVector<WasmVal> stack_;
1108 ZoneVector<Frame> frames_; 1083 ZoneVector<Frame> frames_;
1084 ZoneVector<Block> blocks_;
1109 WasmInterpreter::State state_; 1085 WasmInterpreter::State state_;
1110 pc_t break_pc_; 1086 pc_t break_pc_;
1111 TrapReason trap_reason_; 1087 TrapReason trap_reason_;
1112 1088
1113 CodeMap* codemap() { return codemap_; } 1089 CodeMap* codemap() { return codemap_; }
1114 WasmModuleInstance* instance() { return instance_; } 1090 WasmModuleInstance* instance() { return instance_; }
1115 const WasmModule* module() { return instance_->module; } 1091 const WasmModule* module() { return instance_->module; }
1116 1092
1117 void DoTrap(TrapReason trap, pc_t pc) { 1093 void DoTrap(TrapReason trap, pc_t pc) {
1118 state_ = WasmInterpreter::TRAPPED; 1094 state_ = WasmInterpreter::TRAPPED;
1119 trap_reason_ = trap; 1095 trap_reason_ = trap;
1120 CommitPc(pc); 1096 CommitPc(pc);
1121 } 1097 }
1122 1098
1123 // Push a frame with arguments already on the stack. 1099 // Push a frame with arguments already on the stack.
1124 void PushFrame(InterpreterCode* code, pc_t call_pc, pc_t ret_pc) { 1100 void PushFrame(InterpreterCode* code, pc_t call_pc, pc_t ret_pc) {
1125 CHECK_NOT_NULL(code); 1101 CHECK_NOT_NULL(code);
1126 DCHECK(!frames_.empty()); 1102 DCHECK(!frames_.empty());
1127 frames_.back().call_pc = call_pc; 1103 frames_.back().call_pc = call_pc;
1128 frames_.back().ret_pc = ret_pc; 1104 frames_.back().ret_pc = ret_pc;
1129 size_t arity = code->function->sig->parameter_count(); 1105 size_t arity = code->function->sig->parameter_count();
1130 DCHECK_GE(stack_.size(), arity); 1106 DCHECK_GE(stack_.size(), arity);
1131 // The parameters will overlap the arguments already on the stack. 1107 // The parameters will overlap the arguments already on the stack.
1132 frames_.push_back({code, 0, 0, stack_.size() - arity}); 1108 frames_.push_back({code, 0, 0, stack_.size() - arity});
1109 blocks_.push_back(
1110 {0, stack_.size(), frames_.size(),
1111 static_cast<uint32_t>(code->function->sig->return_count())});
1133 frames_.back().ret_pc = InitLocals(code); 1112 frames_.back().ret_pc = InitLocals(code);
1134 TRACE(" => push func#%u @%zu\n", code->function->func_index, 1113 TRACE(" => push func#%u @%zu\n", code->function->func_index,
1135 frames_.back().ret_pc); 1114 frames_.back().ret_pc);
1136 } 1115 }
1137 1116
1138 pc_t InitLocals(InterpreterCode* code) { 1117 pc_t InitLocals(InterpreterCode* code) {
1139 for (auto p : code->locals.local_types) { 1118 for (auto p : code->locals.local_types) {
1140 WasmVal val; 1119 WasmVal val;
1141 switch (p.first) { 1120 switch (p.first) {
1142 case kAstI32: 1121 case kAstI32:
(...skipping 18 matching lines...) Expand all
1161 } 1140 }
1162 1141
1163 void CommitPc(pc_t pc) { 1142 void CommitPc(pc_t pc) {
1164 if (!frames_.empty()) { 1143 if (!frames_.empty()) {
1165 frames_.back().ret_pc = pc; 1144 frames_.back().ret_pc = pc;
1166 } 1145 }
1167 } 1146 }
1168 1147
1169 bool SkipBreakpoint(InterpreterCode* code, pc_t pc) { 1148 bool SkipBreakpoint(InterpreterCode* code, pc_t pc) {
1170 if (pc == break_pc_) { 1149 if (pc == break_pc_) {
1150 // Skip the previously hit breakpoint when resuming.
1171 break_pc_ = kInvalidPc; 1151 break_pc_ = kInvalidPc;
1172 return true; 1152 return true;
1173 } 1153 }
1174 return false; 1154 return false;
1175 } 1155 }
1176 1156
1177 bool DoReturn(InterpreterCode** code, pc_t* pc, pc_t* limit, WasmVal val) { 1157 int LookupTarget(InterpreterCode* code, pc_t pc) {
1158 return static_cast<int>(code->targets->Lookup(pc));
1159 }
1160
1161 int DoBreak(InterpreterCode* code, pc_t pc, size_t depth) {
1162 size_t bp = blocks_.size() - depth - 1;
1163 Block* target = &blocks_[bp];
1164 DoStackTransfer(target->sp, target->arity);
1165 blocks_.resize(bp);
1166 return LookupTarget(code, pc);
1167 }
1168
1169 bool DoReturn(InterpreterCode** code, pc_t* pc, pc_t* limit, size_t arity) {
1178 DCHECK_GT(frames_.size(), 0u); 1170 DCHECK_GT(frames_.size(), 0u);
1179 stack_.resize(frames_.back().sp); 1171 // Pop all blocks for this frame.
1172 while (blocks_.size() > 0 && blocks_.back().fp == frames_.size()) {
1173 blocks_.pop_back();
1174 }
1175
1176 sp_t dest = frames_.back().sp;
1180 frames_.pop_back(); 1177 frames_.pop_back();
1181 if (frames_.size() == 0) { 1178 if (frames_.size() == 0) {
1182 // A return from the top frame terminates the execution. 1179 // A return from the last frame terminates the execution.
1183 state_ = WasmInterpreter::FINISHED; 1180 state_ = WasmInterpreter::FINISHED;
1184 stack_.clear(); 1181 DoStackTransfer(0, arity);
1185 stack_.push_back(val);
1186 TRACE(" => finish\n"); 1182 TRACE(" => finish\n");
1187 return false; 1183 return false;
1188 } else { 1184 } else {
1189 // Return to caller frame. 1185 // Return to caller frame.
1190 Frame* top = &frames_.back(); 1186 Frame* top = &frames_.back();
1191 *code = top->code; 1187 *code = top->code;
1192 *pc = top->ret_pc; 1188 *pc = top->ret_pc;
1193 *limit = top->code->end - top->code->start; 1189 *limit = top->code->end - top->code->start;
1194 if (top->code->start[top->call_pc] == kExprCallIndirect ||
1195 (top->code->orig_start &&
1196 top->code->orig_start[top->call_pc] == kExprCallIndirect)) {
1197 // UGLY: An indirect call has the additional function index on the
1198 // stack.
1199 stack_.pop_back();
1200 }
1201 TRACE(" => pop func#%u @%zu\n", (*code)->function->func_index, *pc); 1190 TRACE(" => pop func#%u @%zu\n", (*code)->function->func_index, *pc);
1202 1191 DoStackTransfer(dest, arity);
1203 stack_.push_back(val);
1204 return true; 1192 return true;
1205 } 1193 }
1206 } 1194 }
1207 1195
1208 void DoCall(InterpreterCode* target, pc_t* pc, pc_t ret_pc, pc_t* limit) { 1196 void DoCall(InterpreterCode* target, pc_t* pc, pc_t ret_pc, pc_t* limit) {
1209 PushFrame(target, *pc, ret_pc); 1197 PushFrame(target, *pc, ret_pc);
1210 *pc = frames_.back().ret_pc; 1198 *pc = frames_.back().ret_pc;
1211 *limit = target->end - target->start; 1199 *limit = target->end - target->start;
1212 } 1200 }
1213 1201
1214 // Adjust the program counter {pc} and the stack contents according to the 1202 // Copies {arity} values on the top of the stack down the stack to {dest},
1215 // code's precomputed control transfer map. Returns the different between 1203 // dropping the values in-between.
1216 // the new pc and the old pc. 1204 void DoStackTransfer(sp_t dest, size_t arity) {
1217 int DoControlTransfer(InterpreterCode* code, pc_t pc) { 1205 // before: |---------------| pop_count | arity |
1218 auto target = code->targets->Lookup(pc); 1206 // ^ 0 ^ dest ^ stack_.size()
1219 switch (target.action) { 1207 //
1220 case ControlTransfer::kNoAction: 1208 // after: |---------------| arity |
1221 TRACE(" action [sp-%u]\n", target.spdiff); 1209 // ^ 0 ^ stack_.size()
1222 PopN(target.spdiff); 1210 DCHECK_LE(dest, stack_.size());
1223 break; 1211 DCHECK_LE(dest + arity, stack_.size());
1224 case ControlTransfer::kPopAndRepush: { 1212 size_t pop_count = stack_.size() - dest - arity;
1225 WasmVal val = Pop(); 1213 for (size_t i = 0; i < arity; i++) {
1226 TRACE(" action [pop x, sp-%u, push x]\n", target.spdiff - 1); 1214 stack_[dest + i] = stack_[dest + pop_count + i];
1227 DCHECK_GE(target.spdiff, 1u);
1228 PopN(target.spdiff - 1);
1229 Push(pc, val);
1230 break;
1231 }
1232 case ControlTransfer::kPushVoid:
1233 TRACE(" action [sp-%u, push void]\n", target.spdiff);
1234 PopN(target.spdiff);
1235 Push(pc, WasmVal());
1236 break;
1237 } 1215 }
1238 return target.pcdiff; 1216 stack_.resize(stack_.size() - pop_count);
1239 } 1217 }
1240 1218
1241 void Execute(InterpreterCode* code, pc_t pc, int max) { 1219 void Execute(InterpreterCode* code, pc_t pc, int max) {
1242 Decoder decoder(code->start, code->end); 1220 Decoder decoder(code->start, code->end);
1243 pc_t limit = code->end - code->start; 1221 pc_t limit = code->end - code->start;
1244 while (true) { 1222 while (true) {
1245 if (max-- <= 0) { 1223 if (max-- <= 0) {
1246 // Maximum number of instructions reached. 1224 // Maximum number of instructions reached.
1247 state_ = WasmInterpreter::PAUSED; 1225 state_ = WasmInterpreter::PAUSED;
1248 return CommitPc(pc); 1226 return CommitPc(pc);
1249 } 1227 }
1250 1228
1251 if (pc >= limit) { 1229 if (pc >= limit) {
1252 // Fell off end of code; do an implicit return. 1230 // Fell off end of code; do an implicit return.
1253 TRACE("@%-3zu: ImplicitReturn\n", pc); 1231 TRACE("@%-3zu: ImplicitReturn\n", pc);
1254 WasmVal val = PopArity(code->function->sig->return_count()); 1232 if (!DoReturn(&code, &pc, &limit, code->function->sig->return_count()))
1255 if (!DoReturn(&code, &pc, &limit, val)) return; 1233 return;
1256 decoder.Reset(code->start, code->end); 1234 decoder.Reset(code->start, code->end);
1257 continue; 1235 continue;
1258 } 1236 }
1259 1237
1260 const char* skip = " "; 1238 const char* skip = " ";
1261 int len = 1; 1239 int len = 1;
1262 byte opcode = code->start[pc]; 1240 byte opcode = code->start[pc];
1263 byte orig = opcode; 1241 byte orig = opcode;
1264 if (opcode == kInternalBreakpoint) { 1242 if (opcode == kInternalBreakpoint) {
1265 orig = code->orig_start[pc]; 1243 orig = code->orig_start[pc];
(...skipping 12 matching lines...) Expand all
1278 } 1256 }
1279 1257
1280 USE(skip); 1258 USE(skip);
1281 TRACE("@%-3zu: %s%-24s:", pc, skip, 1259 TRACE("@%-3zu: %s%-24s:", pc, skip,
1282 WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(orig))); 1260 WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(orig)));
1283 TraceValueStack(); 1261 TraceValueStack();
1284 TRACE("\n"); 1262 TRACE("\n");
1285 1263
1286 switch (orig) { 1264 switch (orig) {
1287 case kExprNop: 1265 case kExprNop:
1288 Push(pc, WasmVal());
1289 break; 1266 break;
1290 case kExprBlock: 1267 case kExprBlock: {
1268 BlockTypeOperand operand(&decoder, code->at(pc));
1269 blocks_.push_back({pc, stack_.size(), frames_.size(), operand.arity});
1270 len = 1 + operand.length;
1271 break;
1272 }
1291 case kExprLoop: { 1273 case kExprLoop: {
1292 // Do nothing. 1274 BlockTypeOperand operand(&decoder, code->at(pc));
1275 blocks_.push_back({pc, stack_.size(), frames_.size(), 0});
1276 len = 1 + operand.length;
1293 break; 1277 break;
1294 } 1278 }
1295 case kExprIf: { 1279 case kExprIf: {
1280 BlockTypeOperand operand(&decoder, code->at(pc));
1296 WasmVal cond = Pop(); 1281 WasmVal cond = Pop();
1297 bool is_true = cond.to<uint32_t>() != 0; 1282 bool is_true = cond.to<uint32_t>() != 0;
1283 blocks_.push_back({pc, stack_.size(), frames_.size(), operand.arity});
1298 if (is_true) { 1284 if (is_true) {
1299 // fall through to the true block. 1285 // fall through to the true block.
1286 len = 1 + operand.length;
1300 TRACE(" true => fallthrough\n"); 1287 TRACE(" true => fallthrough\n");
1301 } else { 1288 } else {
1302 len = DoControlTransfer(code, pc); 1289 len = LookupTarget(code, pc);
1303 TRACE(" false => @%zu\n", pc + len); 1290 TRACE(" false => @%zu\n", pc + len);
1304 } 1291 }
1305 break; 1292 break;
1306 } 1293 }
1307 case kExprElse: { 1294 case kExprElse: {
1308 len = DoControlTransfer(code, pc); 1295 blocks_.pop_back();
1296 len = LookupTarget(code, pc);
1309 TRACE(" end => @%zu\n", pc + len); 1297 TRACE(" end => @%zu\n", pc + len);
1310 break; 1298 break;
1311 } 1299 }
1312 case kExprSelect: { 1300 case kExprSelect: {
1313 WasmVal cond = Pop(); 1301 WasmVal cond = Pop();
1314 WasmVal fval = Pop(); 1302 WasmVal fval = Pop();
1315 WasmVal tval = Pop(); 1303 WasmVal tval = Pop();
1316 Push(pc, cond.to<int32_t>() != 0 ? tval : fval); 1304 Push(pc, cond.to<int32_t>() != 0 ? tval : fval);
1317 break; 1305 break;
1318 } 1306 }
1319 case kExprBr: { 1307 case kExprBr: {
1320 BreakDepthOperand operand(&decoder, code->at(pc)); 1308 BreakDepthOperand operand(&decoder, code->at(pc));
1321 WasmVal val = PopArity(operand.arity); 1309 len = DoBreak(code, pc, operand.depth);
1322 len = DoControlTransfer(code, pc);
1323 TRACE(" br => @%zu\n", pc + len); 1310 TRACE(" br => @%zu\n", pc + len);
1324 if (operand.arity > 0) Push(pc, val);
1325 break; 1311 break;
1326 } 1312 }
1327 case kExprBrIf: { 1313 case kExprBrIf: {
1328 BreakDepthOperand operand(&decoder, code->at(pc)); 1314 BreakDepthOperand operand(&decoder, code->at(pc));
1329 WasmVal cond = Pop(); 1315 WasmVal cond = Pop();
1330 WasmVal val = PopArity(operand.arity);
1331 bool is_true = cond.to<uint32_t>() != 0; 1316 bool is_true = cond.to<uint32_t>() != 0;
1332 if (is_true) { 1317 if (is_true) {
1333 len = DoControlTransfer(code, pc); 1318 len = DoBreak(code, pc, operand.depth);
1334 TRACE(" br_if => @%zu\n", pc + len); 1319 TRACE(" br_if => @%zu\n", pc + len);
1335 if (operand.arity > 0) Push(pc, val);
1336 } else { 1320 } else {
1337 TRACE(" false => fallthrough\n"); 1321 TRACE(" false => fallthrough\n");
1338 len = 1 + operand.length; 1322 len = 1 + operand.length;
1339 Push(pc, WasmVal());
1340 } 1323 }
1341 break; 1324 break;
1342 } 1325 }
1343 case kExprBrTable: { 1326 case kExprBrTable: {
1344 BranchTableOperand operand(&decoder, code->at(pc)); 1327 BranchTableOperand operand(&decoder, code->at(pc));
1345 uint32_t key = Pop().to<uint32_t>(); 1328 uint32_t key = Pop().to<uint32_t>();
1346 WasmVal val = PopArity(operand.arity);
1347 if (key >= operand.table_count) key = operand.table_count; 1329 if (key >= operand.table_count) key = operand.table_count;
1348 len = DoControlTransfer(code, pc + key) + key; 1330 len = key + DoBreak(code, pc + key, operand.table[key]);
1349 TRACE(" br[%u] => @%zu\n", key, pc + len); 1331 TRACE(" br[%u] => @%zu\n", key, pc + key + len);
1350 if (operand.arity > 0) Push(pc, val);
1351 break; 1332 break;
1352 } 1333 }
1353 case kExprReturn: { 1334 case kExprReturn: {
1354 ReturnArityOperand operand(&decoder, code->at(pc)); 1335 size_t arity = code->function->sig->return_count();
1355 WasmVal val = PopArity(operand.arity); 1336 if (!DoReturn(&code, &pc, &limit, arity)) return;
1356 if (!DoReturn(&code, &pc, &limit, val)) return;
1357 decoder.Reset(code->start, code->end); 1337 decoder.Reset(code->start, code->end);
1358 continue; 1338 continue;
1359 } 1339 }
1360 case kExprUnreachable: { 1340 case kExprUnreachable: {
1361 DoTrap(kTrapUnreachable, pc); 1341 DoTrap(kTrapUnreachable, pc);
1362 return CommitPc(pc); 1342 return CommitPc(pc);
1363 } 1343 }
1364 case kExprEnd: { 1344 case kExprEnd: {
1365 len = DoControlTransfer(code, pc); 1345 blocks_.pop_back();
1366 DCHECK_EQ(1, len);
1367 break; 1346 break;
1368 } 1347 }
1369 case kExprI8Const: { 1348 case kExprI8Const: {
1370 ImmI8Operand operand(&decoder, code->at(pc)); 1349 ImmI8Operand operand(&decoder, code->at(pc));
1371 Push(pc, WasmVal(operand.value)); 1350 Push(pc, WasmVal(operand.value));
1372 len = 1 + operand.length; 1351 len = 1 + operand.length;
1373 break; 1352 break;
1374 } 1353 }
1375 case kExprI32Const: { 1354 case kExprI32Const: {
1376 ImmI32Operand operand(&decoder, code->at(pc)); 1355 ImmI32Operand operand(&decoder, code->at(pc));
(...skipping 22 matching lines...) Expand all
1399 case kExprGetLocal: { 1378 case kExprGetLocal: {
1400 LocalIndexOperand operand(&decoder, code->at(pc)); 1379 LocalIndexOperand operand(&decoder, code->at(pc));
1401 Push(pc, stack_[frames_.back().sp + operand.index]); 1380 Push(pc, stack_[frames_.back().sp + operand.index]);
1402 len = 1 + operand.length; 1381 len = 1 + operand.length;
1403 break; 1382 break;
1404 } 1383 }
1405 case kExprSetLocal: { 1384 case kExprSetLocal: {
1406 LocalIndexOperand operand(&decoder, code->at(pc)); 1385 LocalIndexOperand operand(&decoder, code->at(pc));
1407 WasmVal val = Pop(); 1386 WasmVal val = Pop();
1408 stack_[frames_.back().sp + operand.index] = val; 1387 stack_[frames_.back().sp + operand.index] = val;
1388 len = 1 + operand.length;
1389 break;
1390 }
1391 case kExprTeeLocal: {
1392 LocalIndexOperand operand(&decoder, code->at(pc));
1393 WasmVal val = Pop();
1394 stack_[frames_.back().sp + operand.index] = val;
1409 Push(pc, val); 1395 Push(pc, val);
1410 len = 1 + operand.length; 1396 len = 1 + operand.length;
1411 break; 1397 break;
1412 } 1398 }
1399 case kExprDrop: {
1400 Pop();
1401 break;
1402 }
1413 case kExprCallFunction: { 1403 case kExprCallFunction: {
1414 CallFunctionOperand operand(&decoder, code->at(pc)); 1404 CallFunctionOperand operand(&decoder, code->at(pc));
1415 InterpreterCode* target = codemap()->GetCode(operand.index); 1405 InterpreterCode* target = codemap()->GetCode(operand.index);
1416 DoCall(target, &pc, pc + 1 + operand.length, &limit); 1406 DoCall(target, &pc, pc + 1 + operand.length, &limit);
1417 code = target; 1407 code = target;
1418 decoder.Reset(code->start, code->end); 1408 decoder.Reset(code->start, code->end);
1419 continue; 1409 continue;
1420 } 1410 }
1421 case kExprCallIndirect: { 1411 case kExprCallIndirect: {
1422 CallIndirectOperand operand(&decoder, code->at(pc)); 1412 CallIndirectOperand operand(&decoder, code->at(pc));
1423 size_t index = stack_.size() - operand.arity - 1; 1413 uint32_t entry_index = Pop().to<uint32_t>();
1424 DCHECK_LT(index, stack_.size());
1425 uint32_t entry_index = stack_[index].to<uint32_t>();
1426 // Assume only one table for now. 1414 // Assume only one table for now.
1427 DCHECK_LE(module()->function_tables.size(), 1u); 1415 DCHECK_LE(module()->function_tables.size(), 1u);
1428 InterpreterCode* target = codemap()->GetIndirectCode(0, entry_index); 1416 InterpreterCode* target = codemap()->GetIndirectCode(0, entry_index);
1429 if (target == nullptr) { 1417 if (target == nullptr) {
1430 return DoTrap(kTrapFuncInvalid, pc); 1418 return DoTrap(kTrapFuncInvalid, pc);
1431 } else if (target->function->sig_index != operand.index) { 1419 } else if (target->function->sig_index != operand.index) {
1432 return DoTrap(kTrapFuncSigMismatch, pc); 1420 return DoTrap(kTrapFuncSigMismatch, pc);
1433 } 1421 }
1434 1422
1435 DoCall(target, &pc, pc + 1 + operand.length, &limit); 1423 DoCall(target, &pc, pc + 1 + operand.length, &limit);
1436 code = target; 1424 code = target;
1437 decoder.Reset(code->start, code->end); 1425 decoder.Reset(code->start, code->end);
1438 continue; 1426 continue;
1439 } 1427 }
1440 case kExprCallImport: {
1441 UNIMPLEMENTED();
1442 break;
1443 }
1444 case kExprGetGlobal: { 1428 case kExprGetGlobal: {
1445 GlobalIndexOperand operand(&decoder, code->at(pc)); 1429 GlobalIndexOperand operand(&decoder, code->at(pc));
1446 const WasmGlobal* global = &module()->globals[operand.index]; 1430 const WasmGlobal* global = &module()->globals[operand.index];
1447 byte* ptr = instance()->globals_start + global->offset; 1431 byte* ptr = instance()->globals_start + global->offset;
1448 LocalType type = global->type; 1432 LocalType type = global->type;
1449 WasmVal val; 1433 WasmVal val;
1450 if (type == kAstI32) { 1434 if (type == kAstI32) {
1451 val = WasmVal(*reinterpret_cast<int32_t*>(ptr)); 1435 val = WasmVal(*reinterpret_cast<int32_t*>(ptr));
1452 } else if (type == kAstI64) { 1436 } else if (type == kAstI64) {
1453 val = WasmVal(*reinterpret_cast<int64_t*>(ptr)); 1437 val = WasmVal(*reinterpret_cast<int64_t*>(ptr));
(...skipping 18 matching lines...) Expand all
1472 *reinterpret_cast<int32_t*>(ptr) = val.to<int32_t>(); 1456 *reinterpret_cast<int32_t*>(ptr) = val.to<int32_t>();
1473 } else if (type == kAstI64) { 1457 } else if (type == kAstI64) {
1474 *reinterpret_cast<int64_t*>(ptr) = val.to<int64_t>(); 1458 *reinterpret_cast<int64_t*>(ptr) = val.to<int64_t>();
1475 } else if (type == kAstF32) { 1459 } else if (type == kAstF32) {
1476 *reinterpret_cast<float*>(ptr) = val.to<float>(); 1460 *reinterpret_cast<float*>(ptr) = val.to<float>();
1477 } else if (type == kAstF64) { 1461 } else if (type == kAstF64) {
1478 *reinterpret_cast<double*>(ptr) = val.to<double>(); 1462 *reinterpret_cast<double*>(ptr) = val.to<double>();
1479 } else { 1463 } else {
1480 UNREACHABLE(); 1464 UNREACHABLE();
1481 } 1465 }
1482 Push(pc, val);
1483 len = 1 + operand.length; 1466 len = 1 + operand.length;
1484 break; 1467 break;
1485 } 1468 }
1486 1469
1487 #define LOAD_CASE(name, ctype, mtype) \ 1470 #define LOAD_CASE(name, ctype, mtype) \
1488 case kExpr##name: { \ 1471 case kExpr##name: { \
1489 MemoryAccessOperand operand(&decoder, code->at(pc), sizeof(ctype)); \ 1472 MemoryAccessOperand operand(&decoder, code->at(pc), sizeof(ctype)); \
1490 uint32_t index = Pop().to<uint32_t>(); \ 1473 uint32_t index = Pop().to<uint32_t>(); \
1491 size_t effective_mem_size = instance()->mem_size - sizeof(mtype); \ 1474 size_t effective_mem_size = instance()->mem_size - sizeof(mtype); \
1492 if (operand.offset > effective_mem_size || \ 1475 if (operand.offset > effective_mem_size || \
(...skipping 28 matching lines...) Expand all
1521 MemoryAccessOperand operand(&decoder, code->at(pc), sizeof(ctype)); \ 1504 MemoryAccessOperand operand(&decoder, code->at(pc), sizeof(ctype)); \
1522 WasmVal val = Pop(); \ 1505 WasmVal val = Pop(); \
1523 uint32_t index = Pop().to<uint32_t>(); \ 1506 uint32_t index = Pop().to<uint32_t>(); \
1524 size_t effective_mem_size = instance()->mem_size - sizeof(mtype); \ 1507 size_t effective_mem_size = instance()->mem_size - sizeof(mtype); \
1525 if (operand.offset > effective_mem_size || \ 1508 if (operand.offset > effective_mem_size || \
1526 index > (effective_mem_size - operand.offset)) { \ 1509 index > (effective_mem_size - operand.offset)) { \
1527 return DoTrap(kTrapMemOutOfBounds, pc); \ 1510 return DoTrap(kTrapMemOutOfBounds, pc); \
1528 } \ 1511 } \
1529 byte* addr = instance()->mem_start + operand.offset + index; \ 1512 byte* addr = instance()->mem_start + operand.offset + index; \
1530 WriteLittleEndianValue<mtype>(addr, static_cast<mtype>(val.to<ctype>())); \ 1513 WriteLittleEndianValue<mtype>(addr, static_cast<mtype>(val.to<ctype>())); \
1531 Push(pc, val); \
1532 len = 1 + operand.length; \ 1514 len = 1 + operand.length; \
1533 break; \ 1515 break; \
1534 } 1516 }
1535 1517
1536 STORE_CASE(I32StoreMem8, int32_t, int8_t); 1518 STORE_CASE(I32StoreMem8, int32_t, int8_t);
1537 STORE_CASE(I32StoreMem16, int32_t, int16_t); 1519 STORE_CASE(I32StoreMem16, int32_t, int16_t);
1538 STORE_CASE(I64StoreMem8, int64_t, int8_t); 1520 STORE_CASE(I64StoreMem8, int64_t, int8_t);
1539 STORE_CASE(I64StoreMem16, int64_t, int16_t); 1521 STORE_CASE(I64StoreMem16, int64_t, int16_t);
1540 STORE_CASE(I64StoreMem32, int64_t, int32_t); 1522 STORE_CASE(I64StoreMem32, int64_t, int32_t);
1541 STORE_CASE(I32StoreMem, int32_t, int32_t); 1523 STORE_CASE(I32StoreMem, int32_t, int32_t);
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1662 } 1644 }
1663 1645
1664 WasmVal PopArity(size_t arity) { 1646 WasmVal PopArity(size_t arity) {
1665 if (arity == 0) return WasmVal(); 1647 if (arity == 0) return WasmVal();
1666 CHECK_EQ(1, arity); 1648 CHECK_EQ(1, arity);
1667 return Pop(); 1649 return Pop();
1668 } 1650 }
1669 1651
1670 void Push(pc_t pc, WasmVal val) { 1652 void Push(pc_t pc, WasmVal val) {
1671 // TODO(titzer): store PC as well? 1653 // TODO(titzer): store PC as well?
1672 stack_.push_back(val); 1654 if (val.type != kAstStmt) stack_.push_back(val);
1673 } 1655 }
1674 1656
1675 void TraceStack(const char* phase, pc_t pc) { 1657 void TraceStack(const char* phase, pc_t pc) {
1676 if (FLAG_trace_wasm_interpreter) { 1658 if (FLAG_trace_wasm_interpreter) {
1677 PrintF("%s @%zu", phase, pc); 1659 PrintF("%s @%zu", phase, pc);
1678 UNIMPLEMENTED(); 1660 UNIMPLEMENTED();
1679 PrintF("\n"); 1661 PrintF("\n");
1680 } 1662 }
1681 } 1663 }
1682 1664
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1843 } 1825 }
1844 1826
1845 bool WasmInterpreter::SetFunctionCodeForTesting(const WasmFunction* function, 1827 bool WasmInterpreter::SetFunctionCodeForTesting(const WasmFunction* function,
1846 const byte* start, 1828 const byte* start,
1847 const byte* end) { 1829 const byte* end) {
1848 return internals_->codemap_.SetFunctionCode(function, start, end); 1830 return internals_->codemap_.SetFunctionCode(function, start, end);
1849 } 1831 }
1850 1832
1851 ControlTransferMap WasmInterpreter::ComputeControlTransfersForTesting( 1833 ControlTransferMap WasmInterpreter::ComputeControlTransfersForTesting(
1852 Zone* zone, const byte* start, const byte* end) { 1834 Zone* zone, const byte* start, const byte* end) {
1853 ControlTransfers targets(zone, 0, start, end); 1835 ControlTransfers targets(zone, nullptr, nullptr, start, end);
1854 return targets.map_; 1836 return targets.map_;
1855 } 1837 }
1856 1838
1857 } // namespace wasm 1839 } // namespace wasm
1858 } // namespace internal 1840 } // namespace internal
1859 } // namespace v8 1841 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698