| 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 |