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

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

Issue 2096863003: [wasm] prototype for breakpoint support. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@extend-script-functionality
Patch Set: Created 4 years, 5 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-module.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 #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 833 matching lines...) Expand 10 before | Expand all | Expand 10 after
844 auto result = map_.find(from); 844 auto result = map_.find(from);
845 if (result == map_.end()) { 845 if (result == map_.end()) {
846 V8_Fatal(__FILE__, __LINE__, "no control target for pc %zu", from); 846 V8_Fatal(__FILE__, __LINE__, "no control target for pc %zu", from);
847 } 847 }
848 return result->second; 848 return result->second;
849 } 849 }
850 }; 850 };
851 851
852 // Code and metadata needed to execute a function. 852 // Code and metadata needed to execute a function.
853 struct InterpreterCode { 853 struct InterpreterCode {
854 const WasmFunction* function; // wasm function 854 const WasmFunction* function; // wasm function
855 AstLocalDecls locals; // local declarations 855 AstLocalDecls locals; // local declarations
856 const byte* orig_start; // start of original code 856 const byte* orig_start; // start of original code
857 const byte* orig_end; // end of original code 857 const byte* orig_end; // end of original code
858 byte* start; // start of (maybe altered) code 858 byte* start; // start of (maybe altered) code
859 byte* end; // end of (maybe altered) code 859 byte* end; // end of (maybe altered) code
860 ControlTransfers* targets; // helper for control flow. 860 ControlTransfers* targets; // helper for control flow.
861 BoolVector instruction_offsets; // valid instruction offsets
861 862
862 const byte* at(pc_t pc) { return start + pc; } 863 const byte* at(pc_t pc) { return start + pc; }
863 }; 864 };
864 865
866 namespace {
867
868 pc_t FindPreviousInstruction(InterpreterCode* code, pc_t pc) {
869 BoolVector& offsets = code->instruction_offsets;
870 DCHECK(offsets[pc]);
871 while (!offsets[--pc]) DCHECK_LE(0U, pc);
872 return pc;
873 }
874
875 } // namespace
876
865 // The main storage for interpreter code. It maps {WasmFunction} to the 877 // The main storage for interpreter code. It maps {WasmFunction} to the
866 // metadata needed to execute each function. 878 // metadata needed to execute each function.
867 class CodeMap { 879 class CodeMap {
868 public: 880 public:
869 Zone* zone_; 881 Zone* zone_;
870 const WasmModule* module_; 882 const WasmModule* module_;
871 ZoneVector<InterpreterCode> interpreter_code_; 883 ZoneVector<InterpreterCode> interpreter_code_;
872 884
873 CodeMap(const WasmModule* module, Zone* zone) 885 CodeMap(const WasmModule* module, Zone* zone)
874 : zone_(zone), module_(module), interpreter_code_(zone) { 886 : zone_(zone), module_(module), interpreter_code_(zone) {
(...skipping 28 matching lines...) Expand all
903 return GetCode(index); 915 return GetCode(index);
904 } 916 }
905 917
906 InterpreterCode* Preprocess(InterpreterCode* code) { 918 InterpreterCode* Preprocess(InterpreterCode* code) {
907 if (code->targets == nullptr && code->start) { 919 if (code->targets == nullptr && code->start) {
908 // Compute the control targets map and the local declarations. 920 // Compute the control targets map and the local declarations.
909 CHECK(DecodeLocalDecls(code->locals, code->start, code->end)); 921 CHECK(DecodeLocalDecls(code->locals, code->start, code->end));
910 code->targets = 922 code->targets =
911 new (zone_) ControlTransfers(zone_, code->locals.decls_encoded_size, 923 new (zone_) ControlTransfers(zone_, code->locals.decls_encoded_size,
912 code->orig_start, code->orig_end); 924 code->orig_start, code->orig_end);
925
926 // Initialize the instruction_offsets bitset.
927 DCHECK(code->instruction_offsets.empty());
928 code->instruction_offsets.resize(code->end - code->start);
929 const byte* pc = code->orig_start + code->locals.decls_encoded_size;
930 while (pc < code->orig_end) {
931 code->instruction_offsets[pc - code->orig_start] = 1;
932 pc += OpcodeLength(pc, code->orig_end);
933 }
913 } 934 }
914 return code; 935 return code;
915 } 936 }
916 937
917 int AddFunction(const WasmFunction* function, const byte* code_start, 938 int AddFunction(const WasmFunction* function, const byte* code_start,
918 const byte* code_end) { 939 const byte* code_end) {
919 InterpreterCode code = { 940 InterpreterCode code = {function,
920 function, AstLocalDecls(zone_), code_start, 941 AstLocalDecls(zone_),
921 code_end, const_cast<byte*>(code_start), const_cast<byte*>(code_end), 942 code_start,
922 nullptr}; 943 code_end,
944 const_cast<byte*>(code_start),
945 const_cast<byte*>(code_end),
946 nullptr,
947 BoolVector(zone_)};
923 948
924 DCHECK_EQ(interpreter_code_.size(), function->func_index); 949 DCHECK_EQ(interpreter_code_.size(), function->func_index);
925 interpreter_code_.push_back(code); 950 interpreter_code_.push_back(code);
926 return static_cast<int>(interpreter_code_.size()) - 1; 951 return static_cast<int>(interpreter_code_.size()) - 1;
927 } 952 }
928 953
929 bool SetFunctionCode(const WasmFunction* function, const byte* start, 954 bool SetFunctionCode(const WasmFunction* function, const byte* start,
930 const byte* end) { 955 const byte* end) {
931 InterpreterCode* code = FindCode(function); 956 InterpreterCode* code = FindCode(function);
932 if (code == nullptr) return false; 957 if (code == nullptr) return false;
(...skipping 23 matching lines...) Expand all
956 981
957 //========================================================================== 982 //==========================================================================
958 // Implementation of public interface for WasmInterpreter::Thread. 983 // Implementation of public interface for WasmInterpreter::Thread.
959 //========================================================================== 984 //==========================================================================
960 985
961 virtual WasmInterpreter::State state() { return state_; } 986 virtual WasmInterpreter::State state() { return state_; }
962 987
963 virtual void PushFrame(const WasmFunction* function, WasmVal* args) { 988 virtual void PushFrame(const WasmFunction* function, WasmVal* args) {
964 InterpreterCode* code = codemap()->FindCode(function); 989 InterpreterCode* code = codemap()->FindCode(function);
965 CHECK_NOT_NULL(code); 990 CHECK_NOT_NULL(code);
991 codemap()->Preprocess(code);
966 frames_.push_back({code, 0, 0, stack_.size()}); 992 frames_.push_back({code, 0, 0, stack_.size()});
967 for (size_t i = 0; i < function->sig->parameter_count(); ++i) { 993 for (size_t i = 0; i < function->sig->parameter_count(); ++i) {
968 stack_.push_back(args[i]); 994 stack_.push_back(args[i]);
969 } 995 }
970 frames_.back().ret_pc = InitLocals(code); 996 frames_.back().ret_pc = InitLocals(code);
971 TRACE(" => PushFrame(#%u @%zu)\n", code->function->func_index, 997 TRACE(" => PushFrame(#%u @%zu)\n", code->function->func_index,
972 frames_.back().ret_pc); 998 frames_.back().ret_pc);
973 } 999 }
974 1000
975 virtual WasmInterpreter::State Run() { 1001 virtual WasmInterpreter::State Run() {
(...skipping 23 matching lines...) Expand all
999 virtual void Reset() { 1025 virtual void Reset() {
1000 TRACE("----- RESET -----\n"); 1026 TRACE("----- RESET -----\n");
1001 stack_.clear(); 1027 stack_.clear();
1002 frames_.clear(); 1028 frames_.clear();
1003 state_ = WasmInterpreter::STOPPED; 1029 state_ = WasmInterpreter::STOPPED;
1004 trap_reason_ = kTrapCount; 1030 trap_reason_ = kTrapCount;
1005 } 1031 }
1006 1032
1007 virtual int GetFrameCount() { return static_cast<int>(frames_.size()); } 1033 virtual int GetFrameCount() { return static_cast<int>(frames_.size()); }
1008 1034
1009 virtual const WasmFrame* GetFrame(int index) { 1035 virtual const WasmInterpreterFrame* GetFrame(int index) {
1036 Frame* frame = &frames_[index];
1037 DCHECK_LE(frame->sp, stack_.size());
1038 DCHECK_LE(stack_.size(), static_cast<size_t>(kMaxInt));
1039 // For all but the top frame, the pc is one behine the call instruction.
1040 bool top_frame = static_cast<size_t>(index) == frames_.size() - 1;
1041 pc_t pc = top_frame ? frame->ret_pc
1042 : FindPreviousInstruction(frame->code, frame->ret_pc);
1043 return new WasmInterpreterFrame(frame->code->function, // wasm function
1044 static_cast<int>(pc), // pc
1045 static_cast<int>(frame->sp), // fp
1046 static_cast<int>(stack_.size())); // sp
1047 }
1048
1049 virtual WasmInterpreterFrame* GetMutableFrame(int index) {
1010 UNIMPLEMENTED(); 1050 UNIMPLEMENTED();
1011 return nullptr; 1051 return nullptr;
1012 } 1052 }
1013
1014 virtual WasmFrame* GetMutableFrame(int index) {
1015 UNIMPLEMENTED();
1016 return nullptr;
1017 }
1018 1053
1019 virtual WasmVal GetReturnValue() { 1054 virtual WasmVal GetReturnValue() {
1020 if (state_ == WasmInterpreter::TRAPPED) return WasmVal(0xdeadbeef); 1055 if (state_ == WasmInterpreter::TRAPPED) return WasmVal(0xdeadbeef);
1021 CHECK_EQ(WasmInterpreter::FINISHED, state_); 1056 CHECK_EQ(WasmInterpreter::FINISHED, state_);
1022 CHECK_EQ(1, stack_.size()); 1057 CHECK_EQ(1, stack_.size());
1023 return stack_[0]; 1058 return stack_[0];
1024 } 1059 }
1025 1060
1026 virtual pc_t GetBreakpointPc() { return break_pc_; } 1061 virtual pc_t GetBreakpointPc() { return break_pc_; }
1027 1062
(...skipping 617 matching lines...) Expand 10 before | Expand all | Expand 10 after
1645 1680
1646 void TraceStack(const char* phase, pc_t pc) { 1681 void TraceStack(const char* phase, pc_t pc) {
1647 if (FLAG_trace_wasm_interpreter) { 1682 if (FLAG_trace_wasm_interpreter) {
1648 PrintF("%s @%zu", phase, pc); 1683 PrintF("%s @%zu", phase, pc);
1649 UNIMPLEMENTED(); 1684 UNIMPLEMENTED();
1650 PrintF("\n"); 1685 PrintF("\n");
1651 } 1686 }
1652 } 1687 }
1653 1688
1654 void TraceValueStack() { 1689 void TraceValueStack() {
1690 #if DEBUG
1655 Frame* top = frames_.size() > 0 ? &frames_.back() : nullptr; 1691 Frame* top = frames_.size() > 0 ? &frames_.back() : nullptr;
1656 sp_t sp = top ? top->sp : 0; 1692 sp_t sp = top ? top->sp : 0;
1657 sp_t plimit = top ? top->plimit() : 0; 1693 sp_t plimit = top ? top->plimit() : 0;
1658 sp_t llimit = top ? top->llimit() : 0; 1694 sp_t llimit = top ? top->llimit() : 0;
1659 if (FLAG_trace_wasm_interpreter) { 1695 if (FLAG_trace_wasm_interpreter) {
1660 for (size_t i = sp; i < stack_.size(); ++i) { 1696 for (size_t i = sp; i < stack_.size(); ++i) {
1661 if (i < plimit) 1697 if (i < plimit)
1662 PrintF(" p%zu:", i); 1698 PrintF(" p%zu:", i);
1663 else if (i < llimit) 1699 else if (i < llimit)
1664 PrintF(" l%zu:", i); 1700 PrintF(" l%zu:", i);
(...skipping 15 matching lines...) Expand all
1680 break; 1716 break;
1681 case kAstStmt: 1717 case kAstStmt:
1682 PrintF("void"); 1718 PrintF("void");
1683 break; 1719 break;
1684 default: 1720 default:
1685 UNREACHABLE(); 1721 UNREACHABLE();
1686 break; 1722 break;
1687 } 1723 }
1688 } 1724 }
1689 } 1725 }
1726 #endif
1690 } 1727 }
1691 }; 1728 };
1692 1729
1693 //============================================================================ 1730 //============================================================================
1694 // The implementation details of the interpreter. 1731 // The implementation details of the interpreter.
1695 //============================================================================ 1732 //============================================================================
1696 class WasmInterpreterInternals : public ZoneObject { 1733 class WasmInterpreterInternals : public ZoneObject {
1697 public: 1734 public:
1698 WasmModuleInstance* instance_; 1735 WasmModuleInstance* instance_;
1699 CodeMap codemap_; 1736 CodeMap codemap_;
1700 ZoneVector<ThreadImpl*> threads_; 1737 ZoneVector<ThreadImpl*> threads_;
1701 1738
1702 WasmInterpreterInternals(Zone* zone, WasmModuleInstance* instance) 1739 WasmInterpreterInternals(Zone* zone, WasmModuleInstance* instance)
1703 : instance_(instance), 1740 : instance_(instance),
1704 codemap_(instance_ ? instance_->module : nullptr, zone), 1741 codemap_(instance_ ? instance_->module : nullptr, zone),
1705 threads_(zone) { 1742 threads_(zone) {
1706 threads_.push_back(new ThreadImpl(zone, &codemap_, instance)); 1743 threads_.push_back(new ThreadImpl(zone, &codemap_, instance));
1707 } 1744 }
1708 1745
1709 void Delete() { 1746 void Delete() {
1710 // TODO(titzer): CFI doesn't like threads in the ZoneVector. 1747 // TODO(titzer): CFI doesn't like threads in the ZoneVector.
1711 for (auto t : threads_) delete t; 1748 for (auto t : threads_) delete t;
1712 threads_.resize(0); 1749 threads_.resize(0);
1713 } 1750 }
1714 }; 1751 };
1715 1752
1716 //============================================================================ 1753 //============================================================================
1717 // Implementation of the public interface of the interpreter. 1754 // Implementation of the public interface of the interpreter.
1718 //============================================================================ 1755 //============================================================================
1719 WasmInterpreter::WasmInterpreter(WasmModuleInstance* instance, 1756 WasmInterpreter::WasmInterpreter(WasmModuleInstance* instance, Zone* zone)
1720 base::AccountingAllocator* allocator) 1757 : zone_(zone),
1721 : zone_(allocator), 1758 internals_(new (zone_) WasmInterpreterInternals(zone_, instance)) {}
1722 internals_(new (&zone_) WasmInterpreterInternals(&zone_, instance)) {}
1723 1759
1724 WasmInterpreter::~WasmInterpreter() { internals_->Delete(); } 1760 WasmInterpreter::~WasmInterpreter() { internals_->Delete(); }
1725 1761
1726 void WasmInterpreter::Run() { internals_->threads_[0]->Run(); } 1762 void WasmInterpreter::Run() { internals_->threads_[0]->Run(); }
1727 1763
1728 void WasmInterpreter::Pause() { internals_->threads_[0]->Pause(); } 1764 void WasmInterpreter::Pause() { internals_->threads_[0]->Pause(); }
1729 1765
1730 bool WasmInterpreter::SetBreakpoint(const WasmFunction* function, pc_t pc, 1766 bool WasmInterpreter::SetBreakpoint(uint32_t function_index, pc_t pc,
1731 bool enabled) { 1767 bool enabled) {
1732 InterpreterCode* code = internals_->codemap_.FindCode(function); 1768 auto interpreter_code = internals_->codemap_.interpreter_code_;
1733 if (!code) return false; 1769 if (function_index > interpreter_code.size()) return false;
1770 InterpreterCode* code = internals_->codemap_.GetCode(function_index);
1734 size_t size = static_cast<size_t>(code->end - code->start); 1771 size_t size = static_cast<size_t>(code->end - code->start);
1735 // Check bounds for {pc}. 1772 // Check bounds for {pc}.
1736 if (pc < code->locals.decls_encoded_size || pc >= size) return false; 1773 if (pc >= size) return false;
1774 // Check that it's a valid instruction offset.
1775 DCHECK_LE(pc, code->instruction_offsets.size());
1776 if (!code->instruction_offsets[pc]) return false;
1737 // Make a copy of the code before enabling a breakpoint. 1777 // Make a copy of the code before enabling a breakpoint.
1738 if (enabled && code->orig_start == code->start) { 1778 if (enabled && code->orig_start == code->start) {
1739 code->start = reinterpret_cast<byte*>(zone_.New(size)); 1779 code->start = reinterpret_cast<byte*>(zone_->New(size));
1740 memcpy(code->start, code->orig_start, size); 1780 memcpy(code->start, code->orig_start, size);
1741 code->end = code->start + size; 1781 code->end = code->start + size;
1742 } 1782 }
1743 bool prev = code->start[pc] == kInternalBreakpoint; 1783 bool prev = code->start[pc] == kInternalBreakpoint;
1744 if (enabled) { 1784 code->start[pc] = enabled ? kInternalBreakpoint : code->orig_start[pc];
1745 code->start[pc] = kInternalBreakpoint;
1746 } else {
1747 code->start[pc] = code->orig_start[pc];
1748 }
1749 return prev; 1785 return prev;
1750 } 1786 }
1751 1787
1752 bool WasmInterpreter::GetBreakpoint(const WasmFunction* function, pc_t pc) { 1788 bool WasmInterpreter::GetBreakpoint(uint32_t function_index, pc_t pc) {
1753 InterpreterCode* code = internals_->codemap_.FindCode(function); 1789 auto interpreter_code = internals_->codemap_.interpreter_code_;
1754 if (!code) return false; 1790 if (function_index > interpreter_code.size()) return false;
1791 InterpreterCode* code = internals_->codemap_.GetCode(function_index);
1755 size_t size = static_cast<size_t>(code->end - code->start); 1792 size_t size = static_cast<size_t>(code->end - code->start);
1756 // Check bounds for {pc}. 1793 // Check bounds for {pc}.
1757 if (pc < code->locals.decls_encoded_size || pc >= size) return false; 1794 if (pc >= size) return false;
1795 // Check that it's a valid instruction offset.
1796 DCHECK_LE(pc, code->instruction_offsets.size());
1797 if (!code->instruction_offsets[pc]) return false;
1758 // Check if a breakpoint is present at that place in the code. 1798 // Check if a breakpoint is present at that place in the code.
1759 return code->start[pc] == kInternalBreakpoint; 1799 return code->start[pc] == kInternalBreakpoint;
1760 } 1800 }
1761 1801
1762 bool WasmInterpreter::SetTracing(const WasmFunction* function, bool enabled) { 1802 bool WasmInterpreter::SetTracing(const WasmFunction* function, bool enabled) {
1763 UNIMPLEMENTED(); 1803 UNIMPLEMENTED();
1764 return false; 1804 return false;
1765 } 1805 }
1766 1806
1767 int WasmInterpreter::GetThreadCount() { 1807 int WasmInterpreter::GetThreadCount() {
1768 return 1; // only one thread for now. 1808 return 1; // only one thread for now.
1769 } 1809 }
1770 1810
1771 WasmInterpreter::Thread* WasmInterpreter::GetThread(int id) { 1811 WasmInterpreter::Thread* WasmInterpreter::GetThread(int id) {
1772 CHECK_EQ(0, id); // only one thread for now. 1812 CHECK_EQ(0, id); // only one thread for now.
1773 return internals_->threads_[id]; 1813 return internals_->threads_[id];
1774 } 1814 }
1775 1815
1776 WasmVal WasmInterpreter::GetLocalVal(const WasmFrame* frame, int index) { 1816 WasmVal WasmInterpreter::GetLocalVal(const WasmInterpreterFrame* frame,
1817 int index) {
1777 CHECK_GE(index, 0); 1818 CHECK_GE(index, 0);
1778 UNIMPLEMENTED(); 1819 UNIMPLEMENTED();
1820 USE(frame->fp_);
1821 USE(frame->sp_);
1822 WasmVal none;
1823 none.type = kAstStmt;
1824 return none;
1825 }
1826
1827 WasmVal WasmInterpreter::GetExprVal(const WasmInterpreterFrame* frame, int pc) {
1828 UNIMPLEMENTED();
1779 WasmVal none; 1829 WasmVal none;
1780 none.type = kAstStmt; 1830 none.type = kAstStmt;
1781 return none; 1831 return none;
1782 } 1832 }
1783 1833
1784 WasmVal WasmInterpreter::GetExprVal(const WasmFrame* frame, int pc) { 1834 void WasmInterpreter::SetLocalVal(WasmInterpreterFrame* frame, int index,
1785 UNIMPLEMENTED(); 1835 WasmVal val) {
1786 WasmVal none;
1787 none.type = kAstStmt;
1788 return none;
1789 }
1790
1791 void WasmInterpreter::SetLocalVal(WasmFrame* frame, int index, WasmVal val) {
1792 UNIMPLEMENTED(); 1836 UNIMPLEMENTED();
1793 } 1837 }
1794 1838
1795 void WasmInterpreter::SetExprVal(WasmFrame* frame, int pc, WasmVal val) { 1839 void WasmInterpreter::SetExprVal(WasmInterpreterFrame* frame, int pc,
1840 WasmVal val) {
1796 UNIMPLEMENTED(); 1841 UNIMPLEMENTED();
1797 } 1842 }
1798 1843
1799 size_t WasmInterpreter::GetMemorySize() { 1844 size_t WasmInterpreter::GetMemorySize() {
1800 return internals_->instance_->mem_size; 1845 return internals_->instance_->mem_size;
1801 } 1846 }
1802 1847
1803 WasmVal WasmInterpreter::ReadMemory(size_t offset) { 1848 WasmVal WasmInterpreter::ReadMemory(size_t offset) {
1804 UNIMPLEMENTED(); 1849 UNIMPLEMENTED();
1805 return WasmVal(); 1850 return WasmVal();
(...skipping 15 matching lines...) Expand all
1821 1866
1822 ControlTransferMap WasmInterpreter::ComputeControlTransfersForTesting( 1867 ControlTransferMap WasmInterpreter::ComputeControlTransfersForTesting(
1823 Zone* zone, const byte* start, const byte* end) { 1868 Zone* zone, const byte* start, const byte* end) {
1824 ControlTransfers targets(zone, 0, start, end); 1869 ControlTransfers targets(zone, 0, start, end);
1825 return targets.map_; 1870 return targets.map_;
1826 } 1871 }
1827 1872
1828 } // namespace wasm 1873 } // namespace wasm
1829 } // namespace internal 1874 } // namespace internal
1830 } // namespace v8 1875 } // namespace v8
OLDNEW
« no previous file with comments | « src/wasm/wasm-interpreter.h ('k') | src/wasm/wasm-module.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698