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

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

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

Powered by Google App Engine
This is Rietveld 408576698