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/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 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
714 | 714 |
715 static const int kRunSteps = 1000; | 715 static const int kRunSteps = 1000; |
716 | 716 |
717 // A helper class to compute the control transfers for each bytecode offset. | 717 // A helper class to compute the control transfers for each bytecode offset. |
718 // Control transfers allow Br, BrIf, BrTable, If, Else, and End bytecodes to | 718 // Control transfers allow Br, BrIf, BrTable, If, Else, and End bytecodes to |
719 // be directly executed without the need to dynamically track blocks. | 719 // be directly executed without the need to dynamically track blocks. |
720 class ControlTransfers : public ZoneObject { | 720 class ControlTransfers : public ZoneObject { |
721 public: | 721 public: |
722 ControlTransferMap map_; | 722 ControlTransferMap map_; |
723 | 723 |
724 ControlTransfers(Zone* zone, ModuleEnv* env, AstLocalDecls* locals, | 724 ControlTransfers(Zone* zone, AstLocalDecls* locals, const byte* start, |
725 const byte* start, const byte* end) | 725 const byte* end) |
726 : map_(zone) { | 726 : map_(zone) { |
727 // Represents a control flow label. | 727 // Represents a control flow label. |
728 struct CLabel : public ZoneObject { | 728 struct CLabel : public ZoneObject { |
729 const byte* target; | 729 const byte* target; |
730 ZoneVector<const byte*> refs; | 730 ZoneVector<const byte*> refs; |
731 | 731 |
732 explicit CLabel(Zone* zone) : target(nullptr), refs(zone) {} | 732 explicit CLabel(Zone* zone) : target(nullptr), refs(zone) {} |
733 | 733 |
734 // Bind this label to the given PC. | 734 // Bind this label to the given PC. |
735 void Bind(ControlTransferMap* map, const byte* start, const byte* pc) { | 735 void Bind(ControlTransferMap* map, const byte* start, const byte* pc) { |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
883 }; | 883 }; |
884 | 884 |
885 // The main storage for interpreter code. It maps {WasmFunction} to the | 885 // The main storage for interpreter code. It maps {WasmFunction} to the |
886 // metadata needed to execute each function. | 886 // metadata needed to execute each function. |
887 class CodeMap { | 887 class CodeMap { |
888 public: | 888 public: |
889 Zone* zone_; | 889 Zone* zone_; |
890 const WasmModule* module_; | 890 const WasmModule* module_; |
891 ZoneVector<InterpreterCode> interpreter_code_; | 891 ZoneVector<InterpreterCode> interpreter_code_; |
892 | 892 |
893 CodeMap(const WasmModule* module, Zone* zone) | 893 CodeMap(const WasmModule* module, const uint8_t* module_start, Zone* zone) |
894 : zone_(zone), module_(module), interpreter_code_(zone) { | 894 : zone_(zone), module_(module), interpreter_code_(zone) { |
895 if (module == nullptr) return; | 895 if (module == nullptr) return; |
896 for (size_t i = 0; i < module->functions.size(); ++i) { | 896 for (size_t i = 0; i < module->functions.size(); ++i) { |
897 const WasmFunction* function = &module->functions[i]; | 897 const WasmFunction* function = &module->functions[i]; |
898 const byte* code_start = | 898 const byte* code_start = module_start + function->code_start_offset; |
899 module->module_start + function->code_start_offset; | 899 const byte* code_end = module_start + function->code_end_offset; |
900 const byte* code_end = module->module_start + function->code_end_offset; | |
901 AddFunction(function, code_start, code_end); | 900 AddFunction(function, code_start, code_end); |
902 } | 901 } |
903 } | 902 } |
904 | 903 |
905 InterpreterCode* FindCode(const WasmFunction* function) { | 904 InterpreterCode* FindCode(const WasmFunction* function) { |
906 if (function->func_index < interpreter_code_.size()) { | 905 if (function->func_index < interpreter_code_.size()) { |
907 InterpreterCode* code = &interpreter_code_[function->func_index]; | 906 InterpreterCode* code = &interpreter_code_[function->func_index]; |
908 DCHECK_EQ(function, code->function); | 907 DCHECK_EQ(function, code->function); |
909 return Preprocess(code); | 908 return Preprocess(code); |
910 } | 909 } |
(...skipping 12 matching lines...) Expand all Loading... |
923 if (entry_index >= table->values.size()) return nullptr; | 922 if (entry_index >= table->values.size()) return nullptr; |
924 uint32_t index = table->values[entry_index]; | 923 uint32_t index = table->values[entry_index]; |
925 if (index >= interpreter_code_.size()) return nullptr; | 924 if (index >= interpreter_code_.size()) return nullptr; |
926 return GetCode(index); | 925 return GetCode(index); |
927 } | 926 } |
928 | 927 |
929 InterpreterCode* Preprocess(InterpreterCode* code) { | 928 InterpreterCode* Preprocess(InterpreterCode* code) { |
930 if (code->targets == nullptr && code->start) { | 929 if (code->targets == nullptr && code->start) { |
931 // Compute the control targets map and the local declarations. | 930 // Compute the control targets map and the local declarations. |
932 CHECK(DecodeLocalDecls(code->locals, code->start, code->end)); | 931 CHECK(DecodeLocalDecls(code->locals, code->start, code->end)); |
933 ModuleEnv env = {module_, nullptr, kWasmOrigin}; | |
934 code->targets = new (zone_) ControlTransfers( | 932 code->targets = new (zone_) ControlTransfers( |
935 zone_, &env, &code->locals, code->orig_start, code->orig_end); | 933 zone_, &code->locals, code->orig_start, code->orig_end); |
936 } | 934 } |
937 return code; | 935 return code; |
938 } | 936 } |
939 | 937 |
940 int AddFunction(const WasmFunction* function, const byte* code_start, | 938 int AddFunction(const WasmFunction* function, const byte* code_start, |
941 const byte* code_end) { | 939 const byte* code_end) { |
942 InterpreterCode code = { | 940 InterpreterCode code = { |
943 function, AstLocalDecls(zone_), code_start, | 941 function, AstLocalDecls(zone_), code_start, |
944 code_end, const_cast<byte*>(code_start), const_cast<byte*>(code_end), | 942 code_end, const_cast<byte*>(code_start), const_cast<byte*>(code_end), |
945 nullptr}; | 943 nullptr}; |
(...skipping 807 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1753 } | 1751 } |
1754 } | 1752 } |
1755 }; | 1753 }; |
1756 | 1754 |
1757 //============================================================================ | 1755 //============================================================================ |
1758 // The implementation details of the interpreter. | 1756 // The implementation details of the interpreter. |
1759 //============================================================================ | 1757 //============================================================================ |
1760 class WasmInterpreterInternals : public ZoneObject { | 1758 class WasmInterpreterInternals : public ZoneObject { |
1761 public: | 1759 public: |
1762 WasmInstance* instance_; | 1760 WasmInstance* instance_; |
| 1761 // Create a copy of the module bytes for the interpreter, since the passed |
| 1762 // pointer might be invalidated after constructing the interpreter. |
| 1763 const ZoneVector<uint8_t> module_bytes_; |
1763 CodeMap codemap_; | 1764 CodeMap codemap_; |
1764 ZoneVector<ThreadImpl*> threads_; | 1765 ZoneVector<ThreadImpl*> threads_; |
1765 | 1766 |
1766 WasmInterpreterInternals(Zone* zone, WasmInstance* instance) | 1767 WasmInterpreterInternals(Zone* zone, const ModuleBytesEnv& env) |
1767 : instance_(instance), | 1768 : instance_(env.instance), |
1768 codemap_(instance_ ? instance_->module : nullptr, zone), | 1769 module_bytes_(env.module_bytes.start(), env.module_bytes.end(), zone), |
| 1770 codemap_(env.instance ? env.instance->module : nullptr, |
| 1771 module_bytes_.data(), zone), |
1769 threads_(zone) { | 1772 threads_(zone) { |
1770 threads_.push_back(new ThreadImpl(zone, &codemap_, instance)); | 1773 threads_.push_back(new ThreadImpl(zone, &codemap_, env.instance)); |
1771 } | 1774 } |
1772 | 1775 |
1773 void Delete() { | 1776 void Delete() { |
1774 // TODO(titzer): CFI doesn't like threads in the ZoneVector. | 1777 // TODO(titzer): CFI doesn't like threads in the ZoneVector. |
1775 for (auto t : threads_) delete t; | 1778 for (auto t : threads_) delete t; |
1776 threads_.resize(0); | 1779 threads_.resize(0); |
1777 } | 1780 } |
1778 }; | 1781 }; |
1779 | 1782 |
1780 //============================================================================ | 1783 //============================================================================ |
1781 // Implementation of the public interface of the interpreter. | 1784 // Implementation of the public interface of the interpreter. |
1782 //============================================================================ | 1785 //============================================================================ |
1783 WasmInterpreter::WasmInterpreter(WasmInstance* instance, | 1786 WasmInterpreter::WasmInterpreter(const ModuleBytesEnv& env, |
1784 AccountingAllocator* allocator) | 1787 AccountingAllocator* allocator) |
1785 : zone_(allocator, ZONE_NAME), | 1788 : zone_(allocator, ZONE_NAME), |
1786 internals_(new (&zone_) WasmInterpreterInternals(&zone_, instance)) {} | 1789 internals_(new (&zone_) WasmInterpreterInternals(&zone_, env)) {} |
1787 | 1790 |
1788 WasmInterpreter::~WasmInterpreter() { internals_->Delete(); } | 1791 WasmInterpreter::~WasmInterpreter() { internals_->Delete(); } |
1789 | 1792 |
1790 void WasmInterpreter::Run() { internals_->threads_[0]->Run(); } | 1793 void WasmInterpreter::Run() { internals_->threads_[0]->Run(); } |
1791 | 1794 |
1792 void WasmInterpreter::Pause() { internals_->threads_[0]->Pause(); } | 1795 void WasmInterpreter::Pause() { internals_->threads_[0]->Pause(); } |
1793 | 1796 |
1794 bool WasmInterpreter::SetBreakpoint(const WasmFunction* function, pc_t pc, | 1797 bool WasmInterpreter::SetBreakpoint(const WasmFunction* function, pc_t pc, |
1795 bool enabled) { | 1798 bool enabled) { |
1796 InterpreterCode* code = internals_->codemap_.FindCode(function); | 1799 InterpreterCode* code = internals_->codemap_.FindCode(function); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1878 } | 1881 } |
1879 | 1882 |
1880 bool WasmInterpreter::SetFunctionCodeForTesting(const WasmFunction* function, | 1883 bool WasmInterpreter::SetFunctionCodeForTesting(const WasmFunction* function, |
1881 const byte* start, | 1884 const byte* start, |
1882 const byte* end) { | 1885 const byte* end) { |
1883 return internals_->codemap_.SetFunctionCode(function, start, end); | 1886 return internals_->codemap_.SetFunctionCode(function, start, end); |
1884 } | 1887 } |
1885 | 1888 |
1886 ControlTransferMap WasmInterpreter::ComputeControlTransfersForTesting( | 1889 ControlTransferMap WasmInterpreter::ComputeControlTransfersForTesting( |
1887 Zone* zone, const byte* start, const byte* end) { | 1890 Zone* zone, const byte* start, const byte* end) { |
1888 ControlTransfers targets(zone, nullptr, nullptr, start, end); | 1891 ControlTransfers targets(zone, nullptr, start, end); |
1889 return targets.map_; | 1892 return targets.map_; |
1890 } | 1893 } |
1891 | 1894 |
1892 } // namespace wasm | 1895 } // namespace wasm |
1893 } // namespace internal | 1896 } // namespace internal |
1894 } // namespace v8 | 1897 } // namespace v8 |
OLD | NEW |