OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/wasm/wasm-interpreter.h" | 5 #include "src/wasm/wasm-interpreter.h" |
6 #include "src/wasm/ast-decoder.h" | 6 #include "src/wasm/ast-decoder.h" |
7 #include "src/wasm/decoder.h" | 7 #include "src/wasm/decoder.h" |
8 #include "src/wasm/wasm-external-refs.h" | 8 #include "src/wasm/wasm-external-refs.h" |
9 #include "src/wasm/wasm-module.h" | 9 #include "src/wasm/wasm-module.h" |
10 | 10 |
(...skipping 909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
920 | 920 |
921 // Responsible for executing code directly. | 921 // Responsible for executing code directly. |
922 class ThreadImpl : public WasmInterpreter::Thread { | 922 class ThreadImpl : public WasmInterpreter::Thread { |
923 public: | 923 public: |
924 ThreadImpl(Zone* zone, CodeMap* codemap, WasmModuleInstance* instance) | 924 ThreadImpl(Zone* zone, CodeMap* codemap, WasmModuleInstance* instance) |
925 : codemap_(codemap), | 925 : codemap_(codemap), |
926 instance_(instance), | 926 instance_(instance), |
927 stack_(zone), | 927 stack_(zone), |
928 frames_(zone), | 928 frames_(zone), |
929 state_(WasmInterpreter::STOPPED), | 929 state_(WasmInterpreter::STOPPED), |
| 930 break_pc_(kInvalidPc), |
930 trap_reason_(kTrapCount) {} | 931 trap_reason_(kTrapCount) {} |
931 | 932 |
932 virtual ~ThreadImpl() {} | 933 virtual ~ThreadImpl() {} |
933 | 934 |
934 //========================================================================== | 935 //========================================================================== |
935 // Implementation of public interface for WasmInterpreter::Thread. | 936 // Implementation of public interface for WasmInterpreter::Thread. |
936 //========================================================================== | 937 //========================================================================== |
937 | 938 |
938 virtual WasmInterpreter::State state() { return state_; } | 939 virtual WasmInterpreter::State state() { return state_; } |
939 | 940 |
940 virtual void PushFrame(const WasmFunction* function, WasmVal* args) { | 941 virtual void PushFrame(const WasmFunction* function, WasmVal* args) { |
941 InterpreterCode* code = codemap()->FindCode(function); | 942 InterpreterCode* code = codemap()->FindCode(function); |
942 CHECK_NOT_NULL(code); | 943 CHECK_NOT_NULL(code); |
943 frames_.push_back({code, 0, 0, stack_.size()}); | 944 frames_.push_back({code, 0, 0, stack_.size()}); |
944 for (size_t i = 0; i < function->sig->parameter_count(); i++) { | 945 for (size_t i = 0; i < function->sig->parameter_count(); i++) { |
945 stack_.push_back(args[i]); | 946 stack_.push_back(args[i]); |
946 } | 947 } |
947 frames_.back().ret_pc = InitLocals(code); | 948 frames_.back().ret_pc = InitLocals(code); |
948 TRACE(" => push func#%u @%zu\n", code->function->func_index, | 949 TRACE(" => PushFrame(#%u @%zu)\n", code->function->func_index, |
949 frames_.back().ret_pc); | 950 frames_.back().ret_pc); |
950 } | 951 } |
951 | 952 |
952 virtual WasmInterpreter::State Run() { | 953 virtual WasmInterpreter::State Run() { |
953 do { | 954 do { |
| 955 TRACE(" => Run()\n"); |
954 if (state_ == WasmInterpreter::STOPPED || | 956 if (state_ == WasmInterpreter::STOPPED || |
955 state_ == WasmInterpreter::PAUSED) { | 957 state_ == WasmInterpreter::PAUSED) { |
956 state_ = WasmInterpreter::RUNNING; | 958 state_ = WasmInterpreter::RUNNING; |
957 Execute(frames_.back().code, frames_.back().ret_pc, kRunSteps); | 959 Execute(frames_.back().code, frames_.back().ret_pc, kRunSteps); |
958 } | 960 } |
959 } while (state_ == WasmInterpreter::STOPPED); | 961 } while (state_ == WasmInterpreter::STOPPED); |
960 return state_; | 962 return state_; |
961 } | 963 } |
962 | 964 |
963 virtual WasmInterpreter::State Step() { | 965 virtual WasmInterpreter::State Step() { |
964 UNIMPLEMENTED(); | 966 TRACE(" => Step()\n"); |
965 return WasmInterpreter::STOPPED; | 967 if (state_ == WasmInterpreter::STOPPED || |
| 968 state_ == WasmInterpreter::PAUSED) { |
| 969 state_ = WasmInterpreter::RUNNING; |
| 970 Execute(frames_.back().code, frames_.back().ret_pc, 1); |
| 971 } |
| 972 return state_; |
966 } | 973 } |
967 | 974 |
968 virtual void Pause() { UNIMPLEMENTED(); } | 975 virtual void Pause() { UNIMPLEMENTED(); } |
969 | 976 |
970 virtual void Reset() { | 977 virtual void Reset() { |
971 TRACE("----- RESET -----\n"); | 978 TRACE("----- RESET -----\n"); |
972 stack_.clear(); | 979 stack_.clear(); |
973 frames_.clear(); | 980 frames_.clear(); |
974 state_ = WasmInterpreter::STOPPED; | 981 state_ = WasmInterpreter::STOPPED; |
975 trap_reason_ = kTrapCount; | 982 trap_reason_ = kTrapCount; |
(...skipping 11 matching lines...) Expand all Loading... |
987 return nullptr; | 994 return nullptr; |
988 } | 995 } |
989 | 996 |
990 virtual WasmVal GetReturnValue() { | 997 virtual WasmVal GetReturnValue() { |
991 if (state_ == WasmInterpreter::TRAPPED) return WasmVal(0xdeadbeef); | 998 if (state_ == WasmInterpreter::TRAPPED) return WasmVal(0xdeadbeef); |
992 CHECK_EQ(WasmInterpreter::FINISHED, state_); | 999 CHECK_EQ(WasmInterpreter::FINISHED, state_); |
993 CHECK_EQ(1, stack_.size()); | 1000 CHECK_EQ(1, stack_.size()); |
994 return stack_[0]; | 1001 return stack_[0]; |
995 } | 1002 } |
996 | 1003 |
| 1004 virtual pc_t GetBreakpointPc() { return break_pc_; } |
| 1005 |
997 bool Terminated() { | 1006 bool Terminated() { |
998 return state_ == WasmInterpreter::TRAPPED || | 1007 return state_ == WasmInterpreter::TRAPPED || |
999 state_ == WasmInterpreter::FINISHED; | 1008 state_ == WasmInterpreter::FINISHED; |
1000 } | 1009 } |
1001 | 1010 |
1002 private: | 1011 private: |
1003 // Entries on the stack of functions being evaluated. | 1012 // Entries on the stack of functions being evaluated. |
1004 struct Frame { | 1013 struct Frame { |
1005 InterpreterCode* code; | 1014 InterpreterCode* code; |
1006 pc_t call_pc; | 1015 pc_t call_pc; |
1007 pc_t ret_pc; | 1016 pc_t ret_pc; |
1008 sp_t sp; | 1017 sp_t sp; |
1009 | 1018 |
1010 // Limit of parameters. | 1019 // Limit of parameters. |
1011 sp_t plimit() { return sp + code->function->sig->parameter_count(); } | 1020 sp_t plimit() { return sp + code->function->sig->parameter_count(); } |
1012 // Limit of locals. | 1021 // Limit of locals. |
1013 sp_t llimit() { return plimit() + code->locals.total_local_count; } | 1022 sp_t llimit() { return plimit() + code->locals.total_local_count; } |
1014 }; | 1023 }; |
1015 | 1024 |
1016 CodeMap* codemap_; | 1025 CodeMap* codemap_; |
1017 WasmModuleInstance* instance_; | 1026 WasmModuleInstance* instance_; |
1018 ZoneVector<WasmVal> stack_; | 1027 ZoneVector<WasmVal> stack_; |
1019 ZoneVector<Frame> frames_; | 1028 ZoneVector<Frame> frames_; |
1020 WasmInterpreter::State state_; | 1029 WasmInterpreter::State state_; |
| 1030 pc_t break_pc_; |
1021 TrapReason trap_reason_; | 1031 TrapReason trap_reason_; |
1022 | 1032 |
1023 CodeMap* codemap() { return codemap_; } | 1033 CodeMap* codemap() { return codemap_; } |
1024 WasmModuleInstance* instance() { return instance_; } | 1034 WasmModuleInstance* instance() { return instance_; } |
1025 const WasmModule* module() { return instance_->module; } | 1035 const WasmModule* module() { return instance_->module; } |
1026 | 1036 |
1027 void DoTrap(TrapReason trap, pc_t pc) { | 1037 void DoTrap(TrapReason trap, pc_t pc) { |
1028 state_ = WasmInterpreter::TRAPPED; | 1038 state_ = WasmInterpreter::TRAPPED; |
1029 trap_reason_ = trap; | 1039 trap_reason_ = trap; |
1030 CommitPc(pc); | 1040 CommitPc(pc); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1070 return code->locals.decls_encoded_size; | 1080 return code->locals.decls_encoded_size; |
1071 } | 1081 } |
1072 | 1082 |
1073 void CommitPc(pc_t pc) { | 1083 void CommitPc(pc_t pc) { |
1074 if (!frames_.empty()) { | 1084 if (!frames_.empty()) { |
1075 frames_.back().ret_pc = pc; | 1085 frames_.back().ret_pc = pc; |
1076 } | 1086 } |
1077 } | 1087 } |
1078 | 1088 |
1079 bool SkipBreakpoint(InterpreterCode* code, pc_t pc) { | 1089 bool SkipBreakpoint(InterpreterCode* code, pc_t pc) { |
1080 // TODO(titzer): skip a breakpoint if we are resuming from it, or it | 1090 if (pc == break_pc_) { |
1081 // is set for another thread only. | 1091 break_pc_ = kInvalidPc; |
| 1092 return true; |
| 1093 } |
1082 return false; | 1094 return false; |
1083 } | 1095 } |
1084 | 1096 |
1085 bool DoReturn(InterpreterCode** code, pc_t* pc, pc_t* limit, WasmVal val) { | 1097 bool DoReturn(InterpreterCode** code, pc_t* pc, pc_t* limit, WasmVal val) { |
1086 DCHECK_GT(frames_.size(), 0u); | 1098 DCHECK_GT(frames_.size(), 0u); |
1087 stack_.resize(frames_.back().sp); | 1099 stack_.resize(frames_.back().sp); |
1088 frames_.pop_back(); | 1100 frames_.pop_back(); |
1089 if (frames_.size() == 0) { | 1101 if (frames_.size() == 0) { |
1090 // A return from the top frame terminates the execution. | 1102 // A return from the top frame terminates the execution. |
1091 state_ = WasmInterpreter::FINISHED; | 1103 state_ = WasmInterpreter::FINISHED; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1158 | 1170 |
1159 if (pc >= limit) { | 1171 if (pc >= limit) { |
1160 // Fell off end of code; do an implicit return. | 1172 // Fell off end of code; do an implicit return. |
1161 TRACE("@%-3zu: ImplicitReturn\n", pc); | 1173 TRACE("@%-3zu: ImplicitReturn\n", pc); |
1162 WasmVal val = PopArity(code->function->sig->return_count()); | 1174 WasmVal val = PopArity(code->function->sig->return_count()); |
1163 if (!DoReturn(&code, &pc, &limit, val)) return; | 1175 if (!DoReturn(&code, &pc, &limit, val)) return; |
1164 decoder.Reset(code->start, code->end); | 1176 decoder.Reset(code->start, code->end); |
1165 continue; | 1177 continue; |
1166 } | 1178 } |
1167 | 1179 |
1168 const char* skip = ""; | 1180 const char* skip = " "; |
1169 int len = 1; | 1181 int len = 1; |
1170 byte opcode = code->start[pc]; | 1182 byte opcode = code->start[pc]; |
1171 byte orig = opcode; | 1183 byte orig = opcode; |
1172 if (opcode == kInternalBreakpoint) { | 1184 if (opcode == kInternalBreakpoint) { |
| 1185 orig = code->orig_start[pc]; |
1173 if (SkipBreakpoint(code, pc)) { | 1186 if (SkipBreakpoint(code, pc)) { |
1174 // skip breakpoint by switching on original code. | 1187 // skip breakpoint by switching on original code. |
1175 orig = code->orig_start[pc]; | 1188 skip = "[skip] "; |
1176 skip = "[skip] "; | |
1177 } else { | 1189 } else { |
1178 state_ = WasmInterpreter::PAUSED; | 1190 state_ = WasmInterpreter::PAUSED; |
| 1191 TRACE("@%-3zu: [break] %-24s:", pc, |
| 1192 WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(orig))); |
| 1193 TraceValueStack(); |
| 1194 TRACE("\n"); |
| 1195 break_pc_ = pc; |
1179 return CommitPc(pc); | 1196 return CommitPc(pc); |
1180 } | 1197 } |
1181 } | 1198 } |
1182 | 1199 |
1183 USE(skip); | 1200 USE(skip); |
1184 TRACE("@%-3zu: %s%-24s:", pc, skip, | 1201 TRACE("@%-3zu: %s%-24s:", pc, skip, |
1185 WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(orig))); | 1202 WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(orig))); |
1186 TraceValueStack(); | 1203 TraceValueStack(); |
1187 TRACE("\n"); | 1204 TRACE("\n"); |
1188 | 1205 |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1677 base::AccountingAllocator* allocator) | 1694 base::AccountingAllocator* allocator) |
1678 : zone_(allocator), | 1695 : zone_(allocator), |
1679 internals_(new (&zone_) WasmInterpreterInternals(&zone_, instance)) {} | 1696 internals_(new (&zone_) WasmInterpreterInternals(&zone_, instance)) {} |
1680 | 1697 |
1681 WasmInterpreter::~WasmInterpreter() {} | 1698 WasmInterpreter::~WasmInterpreter() {} |
1682 | 1699 |
1683 void WasmInterpreter::Run() { internals_->threads_[0].Run(); } | 1700 void WasmInterpreter::Run() { internals_->threads_[0].Run(); } |
1684 | 1701 |
1685 void WasmInterpreter::Pause() { internals_->threads_[0].Pause(); } | 1702 void WasmInterpreter::Pause() { internals_->threads_[0].Pause(); } |
1686 | 1703 |
1687 bool WasmInterpreter::SetBreakpoint(const WasmFunction* function, int pc, | 1704 bool WasmInterpreter::SetBreakpoint(const WasmFunction* function, pc_t pc, |
1688 bool enabled) { | 1705 bool enabled) { |
1689 InterpreterCode* code = internals_->codemap_.FindCode(function); | 1706 InterpreterCode* code = internals_->codemap_.FindCode(function); |
1690 if (!code) return false; | 1707 if (!code) return false; |
1691 int size = static_cast<int>(code->end - code->start); | 1708 size_t size = static_cast<size_t>(code->end - code->start); |
1692 // Check bounds for {pc}. | 1709 // Check bounds for {pc}. |
1693 if (pc < 0 || pc >= size) return false; | 1710 if (pc < code->locals.decls_encoded_size || pc >= size) return false; |
1694 // Make a copy of the code before enabling a breakpoint. | 1711 // Make a copy of the code before enabling a breakpoint. |
1695 if (enabled && code->orig_start == code->start) { | 1712 if (enabled && code->orig_start == code->start) { |
1696 code->start = reinterpret_cast<byte*>(zone_.New(size)); | 1713 code->start = reinterpret_cast<byte*>(zone_.New(size)); |
1697 memcpy(code->start, code->orig_start, size); | 1714 memcpy(code->start, code->orig_start, size); |
1698 code->end = code->start + size; | 1715 code->end = code->start + size; |
1699 } | 1716 } |
1700 bool prev = code->start[pc] == kInternalBreakpoint; | 1717 bool prev = code->start[pc] == kInternalBreakpoint; |
1701 if (enabled) { | 1718 if (enabled) { |
1702 code->start[pc] = kInternalBreakpoint; | 1719 code->start[pc] = kInternalBreakpoint; |
1703 } else { | 1720 } else { |
1704 code->start[pc] = code->orig_start[pc]; | 1721 code->start[pc] = code->orig_start[pc]; |
1705 } | 1722 } |
1706 return prev; | 1723 return prev; |
1707 } | 1724 } |
1708 | 1725 |
1709 bool WasmInterpreter::GetBreakpoint(const WasmFunction* function, int pc) { | 1726 bool WasmInterpreter::GetBreakpoint(const WasmFunction* function, pc_t pc) { |
1710 InterpreterCode* code = internals_->codemap_.FindCode(function); | 1727 InterpreterCode* code = internals_->codemap_.FindCode(function); |
1711 if (!code) return false; | 1728 if (!code) return false; |
1712 int size = static_cast<int>(code->end - code->start); | 1729 size_t size = static_cast<size_t>(code->end - code->start); |
1713 // Check bounds for {pc}. | 1730 // Check bounds for {pc}. |
1714 if (pc < 0 || pc >= size) return false; | 1731 if (pc < code->locals.decls_encoded_size || pc >= size) return false; |
1715 // Check if a breakpoint is present at that place in the code. | 1732 // Check if a breakpoint is present at that place in the code. |
1716 return code->start[pc] == kInternalBreakpoint; | 1733 return code->start[pc] == kInternalBreakpoint; |
1717 } | 1734 } |
1718 | 1735 |
1719 bool WasmInterpreter::SetTracing(const WasmFunction* function, bool enabled) { | 1736 bool WasmInterpreter::SetTracing(const WasmFunction* function, bool enabled) { |
1720 UNIMPLEMENTED(); | 1737 UNIMPLEMENTED(); |
1721 return false; | 1738 return false; |
1722 } | 1739 } |
1723 | 1740 |
1724 int WasmInterpreter::GetThreadCount() { | 1741 int WasmInterpreter::GetThreadCount() { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1778 | 1795 |
1779 ControlTransferMap WasmInterpreter::ComputeControlTransfersForTesting( | 1796 ControlTransferMap WasmInterpreter::ComputeControlTransfersForTesting( |
1780 Zone* zone, const byte* start, const byte* end) { | 1797 Zone* zone, const byte* start, const byte* end) { |
1781 ControlTransfers targets(zone, 0, start, end); | 1798 ControlTransfers targets(zone, 0, start, end); |
1782 return targets.map_; | 1799 return targets.map_; |
1783 } | 1800 } |
1784 | 1801 |
1785 } // namespace wasm | 1802 } // namespace wasm |
1786 } // namespace internal | 1803 } // namespace internal |
1787 } // namespace v8 | 1804 } // namespace v8 |
OLD | NEW |