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 | 6 |
7 #include "src/utils.h" | 7 #include "src/utils.h" |
8 #include "src/wasm/decoder.h" | 8 #include "src/wasm/decoder.h" |
9 #include "src/wasm/function-body-decoder.h" | 9 #include "src/wasm/function-body-decoder.h" |
10 #include "src/wasm/wasm-external-refs.h" | 10 #include "src/wasm/wasm-external-refs.h" |
(...skipping 901 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
912 code->orig_start = start; | 912 code->orig_start = start; |
913 code->orig_end = end; | 913 code->orig_end = end; |
914 code->start = const_cast<byte*>(start); | 914 code->start = const_cast<byte*>(start); |
915 code->end = const_cast<byte*>(end); | 915 code->end = const_cast<byte*>(end); |
916 Preprocess(code); | 916 Preprocess(code); |
917 return true; | 917 return true; |
918 } | 918 } |
919 }; | 919 }; |
920 | 920 |
921 // Responsible for executing code directly. | 921 // Responsible for executing code directly. |
922 class ThreadImpl : public WasmInterpreter::Thread { | 922 class WasmInterpreter::ThreadImpl : public ZoneObject { |
923 public: | 923 public: |
924 ThreadImpl(Zone* zone, CodeMap* codemap, WasmInstance* instance) | 924 ThreadImpl(Zone* zone, CodeMap* codemap, WasmInstance* 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 blocks_(zone), | 929 blocks_(zone), |
930 state_(WasmInterpreter::STOPPED), | 930 state_(WasmInterpreter::STOPPED), |
931 break_pc_(kInvalidPc), | 931 break_pc_(kInvalidPc), |
932 trap_reason_(kTrapCount), | 932 trap_reason_(kTrapCount), |
933 possible_nondeterminism_(false) {} | 933 possible_nondeterminism_(false) {} |
934 | 934 |
935 virtual ~ThreadImpl() {} | 935 ~ThreadImpl() {} |
936 | 936 |
937 //========================================================================== | 937 //========================================================================== |
938 // Implementation of public interface for WasmInterpreter::Thread. | 938 // Implementation of public interface for WasmInterpreter::Thread. |
939 //========================================================================== | 939 //========================================================================== |
940 | 940 |
941 virtual WasmInterpreter::State state() { return state_; } | 941 WasmInterpreter::State state() { return state_; } |
942 | 942 |
943 virtual void PushFrame(const WasmFunction* function, WasmVal* args) { | 943 void PushFrame(const WasmFunction* function, WasmVal* args) { |
944 InterpreterCode* code = codemap()->FindCode(function); | 944 InterpreterCode* code = codemap()->FindCode(function); |
945 CHECK_NOT_NULL(code); | 945 CHECK_NOT_NULL(code); |
946 frames_.push_back({code, 0, 0, stack_.size()}); | 946 frames_.push_back({code, 0, 0, stack_.size()}); |
947 for (size_t i = 0; i < function->sig->parameter_count(); ++i) { | 947 for (size_t i = 0; i < function->sig->parameter_count(); ++i) { |
948 stack_.push_back(args[i]); | 948 stack_.push_back(args[i]); |
949 } | 949 } |
950 frames_.back().ret_pc = InitLocals(code); | 950 frames_.back().ret_pc = InitLocals(code); |
951 blocks_.push_back( | 951 blocks_.push_back( |
952 {0, stack_.size(), frames_.size(), | 952 {0, stack_.size(), frames_.size(), |
953 static_cast<uint32_t>(code->function->sig->return_count())}); | 953 static_cast<uint32_t>(code->function->sig->return_count())}); |
954 TRACE(" => PushFrame(#%u @%zu)\n", code->function->func_index, | 954 TRACE(" => PushFrame(#%u @%zu)\n", code->function->func_index, |
955 frames_.back().ret_pc); | 955 frames_.back().ret_pc); |
956 } | 956 } |
957 | 957 |
958 virtual WasmInterpreter::State Run() { | 958 WasmInterpreter::State Run() { |
959 do { | 959 do { |
960 TRACE(" => Run()\n"); | 960 TRACE(" => Run()\n"); |
961 if (state_ == WasmInterpreter::STOPPED || | 961 if (state_ == WasmInterpreter::STOPPED || |
962 state_ == WasmInterpreter::PAUSED) { | 962 state_ == WasmInterpreter::PAUSED) { |
963 state_ = WasmInterpreter::RUNNING; | 963 state_ = WasmInterpreter::RUNNING; |
964 Execute(frames_.back().code, frames_.back().ret_pc, kRunSteps); | 964 Execute(frames_.back().code, frames_.back().ret_pc, kRunSteps); |
965 } | 965 } |
966 } while (state_ == WasmInterpreter::STOPPED); | 966 } while (state_ == WasmInterpreter::STOPPED); |
967 return state_; | 967 return state_; |
968 } | 968 } |
969 | 969 |
970 virtual WasmInterpreter::State Step() { | 970 WasmInterpreter::State Step() { |
971 TRACE(" => Step()\n"); | 971 TRACE(" => Step()\n"); |
972 if (state_ == WasmInterpreter::STOPPED || | 972 if (state_ == WasmInterpreter::STOPPED || |
973 state_ == WasmInterpreter::PAUSED) { | 973 state_ == WasmInterpreter::PAUSED) { |
974 state_ = WasmInterpreter::RUNNING; | 974 state_ = WasmInterpreter::RUNNING; |
975 Execute(frames_.back().code, frames_.back().ret_pc, 1); | 975 Execute(frames_.back().code, frames_.back().ret_pc, 1); |
976 } | 976 } |
977 return state_; | 977 return state_; |
978 } | 978 } |
979 | 979 |
980 virtual void Pause() { UNIMPLEMENTED(); } | 980 void Pause() { UNIMPLEMENTED(); } |
981 | 981 |
982 virtual void Reset() { | 982 void Reset() { |
983 TRACE("----- RESET -----\n"); | 983 TRACE("----- RESET -----\n"); |
984 stack_.clear(); | 984 stack_.clear(); |
985 frames_.clear(); | 985 frames_.clear(); |
986 state_ = WasmInterpreter::STOPPED; | 986 state_ = WasmInterpreter::STOPPED; |
987 trap_reason_ = kTrapCount; | 987 trap_reason_ = kTrapCount; |
988 possible_nondeterminism_ = false; | 988 possible_nondeterminism_ = false; |
989 } | 989 } |
990 | 990 |
991 virtual int GetFrameCount() { return static_cast<int>(frames_.size()); } | 991 int GetFrameCount() { return static_cast<int>(frames_.size()); } |
992 | 992 |
993 virtual const WasmFrame* GetFrame(int index) { | 993 const WasmFrame* GetFrame(int index) { |
994 UNIMPLEMENTED(); | 994 UNIMPLEMENTED(); |
995 return nullptr; | 995 return nullptr; |
996 } | 996 } |
997 | 997 |
998 virtual WasmFrame* GetMutableFrame(int index) { | 998 WasmFrame* GetMutableFrame(int index) { |
999 UNIMPLEMENTED(); | 999 UNIMPLEMENTED(); |
1000 return nullptr; | 1000 return nullptr; |
1001 } | 1001 } |
1002 | 1002 |
1003 virtual WasmVal GetReturnValue(int index) { | 1003 WasmVal GetReturnValue(int index) { |
1004 if (state_ == WasmInterpreter::TRAPPED) return WasmVal(0xdeadbeef); | 1004 if (state_ == WasmInterpreter::TRAPPED) return WasmVal(0xdeadbeef); |
1005 CHECK_EQ(WasmInterpreter::FINISHED, state_); | 1005 CHECK_EQ(WasmInterpreter::FINISHED, state_); |
1006 CHECK_LT(static_cast<size_t>(index), stack_.size()); | 1006 CHECK_LT(static_cast<size_t>(index), stack_.size()); |
1007 return stack_[index]; | 1007 return stack_[index]; |
1008 } | 1008 } |
1009 | 1009 |
1010 virtual pc_t GetBreakpointPc() { return break_pc_; } | 1010 pc_t GetBreakpointPc() { return break_pc_; } |
1011 | 1011 |
1012 virtual bool PossibleNondeterminism() { return possible_nondeterminism_; } | 1012 bool PossibleNondeterminism() { return possible_nondeterminism_; } |
1013 | |
1014 bool Terminated() { | |
1015 return state_ == WasmInterpreter::TRAPPED || | |
1016 state_ == WasmInterpreter::FINISHED; | |
1017 } | |
1018 | 1013 |
1019 private: | 1014 private: |
1020 // Entries on the stack of functions being evaluated. | 1015 // Entries on the stack of functions being evaluated. |
1021 struct Frame { | 1016 struct Frame { |
1022 InterpreterCode* code; | 1017 InterpreterCode* code; |
1023 pc_t call_pc; | 1018 pc_t call_pc; |
1024 pc_t ret_pc; | 1019 pc_t ret_pc; |
1025 sp_t sp; | 1020 sp_t sp; |
1026 | 1021 |
1027 // Limit of parameters. | 1022 // Limit of parameters. |
(...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1697 default: | 1692 default: |
1698 UNREACHABLE(); | 1693 UNREACHABLE(); |
1699 break; | 1694 break; |
1700 } | 1695 } |
1701 } | 1696 } |
1702 } | 1697 } |
1703 } | 1698 } |
1704 }; | 1699 }; |
1705 | 1700 |
1706 //============================================================================ | 1701 //============================================================================ |
| 1702 // Forwarding functions of WasmInterpreter::Thread (pimpl idiom). |
| 1703 //============================================================================ |
| 1704 WasmInterpreter::Thread::Thread(ThreadImpl* impl) : impl_(impl) {} |
| 1705 WasmInterpreter::State WasmInterpreter::Thread::state() { |
| 1706 return impl_->state(); |
| 1707 } |
| 1708 void WasmInterpreter::Thread::PushFrame(const WasmFunction* function, |
| 1709 WasmVal* args) { |
| 1710 return impl_->PushFrame(function, args); |
| 1711 } |
| 1712 WasmInterpreter::State WasmInterpreter::Thread::Run() { return impl_->Run(); } |
| 1713 WasmInterpreter::State WasmInterpreter::Thread::Step() { return impl_->Step(); } |
| 1714 void WasmInterpreter::Thread::Pause() { return impl_->Pause(); } |
| 1715 void WasmInterpreter::Thread::Reset() { return impl_->Reset(); } |
| 1716 pc_t WasmInterpreter::Thread::GetBreakpointPc() { |
| 1717 return impl_->GetBreakpointPc(); |
| 1718 } |
| 1719 int WasmInterpreter::Thread::GetFrameCount() { return impl_->GetFrameCount(); } |
| 1720 const WasmFrame* WasmInterpreter::Thread::GetFrame(int index) { |
| 1721 return impl_->GetFrame(index); |
| 1722 } |
| 1723 WasmFrame* WasmInterpreter::Thread::GetMutableFrame(int index) { |
| 1724 return impl_->GetMutableFrame(index); |
| 1725 } |
| 1726 WasmVal WasmInterpreter::Thread::GetReturnValue(int index) { |
| 1727 return impl_->GetReturnValue(index); |
| 1728 } |
| 1729 bool WasmInterpreter::Thread::PossibleNondeterminism() { |
| 1730 return impl_->PossibleNondeterminism(); |
| 1731 } |
| 1732 |
| 1733 //============================================================================ |
1707 // The implementation details of the interpreter. | 1734 // The implementation details of the interpreter. |
1708 //============================================================================ | 1735 //============================================================================ |
1709 class WasmInterpreterInternals : public ZoneObject { | 1736 class WasmInterpreterInternals : public ZoneObject { |
1710 public: | 1737 public: |
1711 WasmInstance* instance_; | 1738 WasmInstance* instance_; |
1712 // Create a copy of the module bytes for the interpreter, since the passed | 1739 // Create a copy of the module bytes for the interpreter, since the passed |
1713 // pointer might be invalidated after constructing the interpreter. | 1740 // pointer might be invalidated after constructing the interpreter. |
1714 const ZoneVector<uint8_t> module_bytes_; | 1741 const ZoneVector<uint8_t> module_bytes_; |
1715 CodeMap codemap_; | 1742 CodeMap codemap_; |
1716 ZoneVector<ThreadImpl*> threads_; | 1743 ZoneVector<WasmInterpreter::Thread> threads_; |
1717 | 1744 |
1718 WasmInterpreterInternals(Zone* zone, const ModuleBytesEnv& env) | 1745 WasmInterpreterInternals(Zone* zone, const ModuleBytesEnv& env) |
1719 : instance_(env.instance), | 1746 : instance_(env.instance), |
1720 module_bytes_(env.module_bytes.start(), env.module_bytes.end(), zone), | 1747 module_bytes_(env.module_bytes.start(), env.module_bytes.end(), zone), |
1721 codemap_(env.instance ? env.instance->module : nullptr, | 1748 codemap_(env.instance ? env.instance->module : nullptr, |
1722 module_bytes_.data(), zone), | 1749 module_bytes_.data(), zone), |
1723 threads_(zone) { | 1750 threads_(zone) { |
1724 threads_.push_back(new ThreadImpl(zone, &codemap_, env.instance)); | 1751 threads_.push_back(WasmInterpreter::Thread( |
| 1752 new (zone) WasmInterpreter::ThreadImpl(zone, &codemap_, env.instance))); |
1725 } | 1753 } |
1726 | 1754 |
1727 void Delete() { | 1755 void Delete() { threads_.clear(); } |
1728 // TODO(titzer): CFI doesn't like threads in the ZoneVector. | |
1729 for (auto t : threads_) delete t; | |
1730 threads_.resize(0); | |
1731 } | |
1732 }; | 1756 }; |
1733 | 1757 |
1734 //============================================================================ | 1758 //============================================================================ |
1735 // Implementation of the public interface of the interpreter. | 1759 // Implementation of the public interface of the interpreter. |
1736 //============================================================================ | 1760 //============================================================================ |
1737 WasmInterpreter::WasmInterpreter(const ModuleBytesEnv& env, | 1761 WasmInterpreter::WasmInterpreter(const ModuleBytesEnv& env, |
1738 AccountingAllocator* allocator) | 1762 AccountingAllocator* allocator) |
1739 : zone_(allocator, ZONE_NAME), | 1763 : zone_(allocator, ZONE_NAME), |
1740 internals_(new (&zone_) WasmInterpreterInternals(&zone_, env)) {} | 1764 internals_(new (&zone_) WasmInterpreterInternals(&zone_, env)) {} |
1741 | 1765 |
1742 WasmInterpreter::~WasmInterpreter() { internals_->Delete(); } | 1766 WasmInterpreter::~WasmInterpreter() { internals_->Delete(); } |
1743 | 1767 |
1744 void WasmInterpreter::Run() { internals_->threads_[0]->Run(); } | 1768 void WasmInterpreter::Run() { internals_->threads_[0].Run(); } |
1745 | 1769 |
1746 void WasmInterpreter::Pause() { internals_->threads_[0]->Pause(); } | 1770 void WasmInterpreter::Pause() { internals_->threads_[0].Pause(); } |
1747 | 1771 |
1748 bool WasmInterpreter::SetBreakpoint(const WasmFunction* function, pc_t pc, | 1772 bool WasmInterpreter::SetBreakpoint(const WasmFunction* function, pc_t pc, |
1749 bool enabled) { | 1773 bool enabled) { |
1750 InterpreterCode* code = internals_->codemap_.FindCode(function); | 1774 InterpreterCode* code = internals_->codemap_.FindCode(function); |
1751 if (!code) return false; | 1775 if (!code) return false; |
1752 size_t size = static_cast<size_t>(code->end - code->start); | 1776 size_t size = static_cast<size_t>(code->end - code->start); |
1753 // Check bounds for {pc}. | 1777 // Check bounds for {pc}. |
1754 if (pc < code->locals.encoded_size || pc >= size) return false; | 1778 if (pc < code->locals.encoded_size || pc >= size) return false; |
1755 // Make a copy of the code before enabling a breakpoint. | 1779 // Make a copy of the code before enabling a breakpoint. |
1756 if (enabled && code->orig_start == code->start) { | 1780 if (enabled && code->orig_start == code->start) { |
(...skipping 24 matching lines...) Expand all Loading... |
1781 UNIMPLEMENTED(); | 1805 UNIMPLEMENTED(); |
1782 return false; | 1806 return false; |
1783 } | 1807 } |
1784 | 1808 |
1785 int WasmInterpreter::GetThreadCount() { | 1809 int WasmInterpreter::GetThreadCount() { |
1786 return 1; // only one thread for now. | 1810 return 1; // only one thread for now. |
1787 } | 1811 } |
1788 | 1812 |
1789 WasmInterpreter::Thread* WasmInterpreter::GetThread(int id) { | 1813 WasmInterpreter::Thread* WasmInterpreter::GetThread(int id) { |
1790 CHECK_EQ(0, id); // only one thread for now. | 1814 CHECK_EQ(0, id); // only one thread for now. |
1791 return internals_->threads_[id]; | 1815 return &internals_->threads_[id]; |
1792 } | 1816 } |
1793 | 1817 |
1794 WasmVal WasmInterpreter::GetLocalVal(const WasmFrame* frame, int index) { | 1818 WasmVal WasmInterpreter::GetLocalVal(const WasmFrame* frame, int index) { |
1795 CHECK_GE(index, 0); | 1819 CHECK_GE(index, 0); |
1796 UNIMPLEMENTED(); | 1820 UNIMPLEMENTED(); |
1797 WasmVal none; | 1821 WasmVal none; |
1798 none.type = kWasmStmt; | 1822 none.type = kWasmStmt; |
1799 return none; | 1823 return none; |
1800 } | 1824 } |
1801 | 1825 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1839 | 1863 |
1840 ControlTransferMap WasmInterpreter::ComputeControlTransfersForTesting( | 1864 ControlTransferMap WasmInterpreter::ComputeControlTransfersForTesting( |
1841 Zone* zone, const byte* start, const byte* end) { | 1865 Zone* zone, const byte* start, const byte* end) { |
1842 ControlTransfers targets(zone, nullptr, start, end); | 1866 ControlTransfers targets(zone, nullptr, start, end); |
1843 return targets.map_; | 1867 return targets.map_; |
1844 } | 1868 } |
1845 | 1869 |
1846 } // namespace wasm | 1870 } // namespace wasm |
1847 } // namespace internal | 1871 } // namespace internal |
1848 } // namespace v8 | 1872 } // namespace v8 |
OLD | NEW |