AbstractMachine.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. /*
  2. * Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Function.h>
  8. #include <AK/HashMap.h>
  9. #include <AK/HashTable.h>
  10. #include <AK/OwnPtr.h>
  11. #include <AK/Result.h>
  12. #include <AK/StackInfo.h>
  13. #include <AK/UFixedBigInt.h>
  14. #include <LibWasm/Types.h>
  15. // NOTE: Special case for Wasm::Result.
  16. #include <LibJS/Runtime/Completion.h>
  17. namespace Wasm {
  18. class Configuration;
  19. struct Interpreter;
  20. struct InstantiationError {
  21. ByteString error { "Unknown error" };
  22. };
  23. struct LinkError {
  24. enum OtherErrors {
  25. InvalidImportedModule,
  26. };
  27. Vector<ByteString> missing_imports;
  28. Vector<OtherErrors> other_errors;
  29. };
  30. AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, FunctionAddress, Arithmetic, Comparison, Increment);
  31. AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, ExternAddress, Arithmetic, Comparison, Increment);
  32. AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, TableAddress, Arithmetic, Comparison, Increment);
  33. AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, GlobalAddress, Arithmetic, Comparison, Increment);
  34. AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, ElementAddress, Arithmetic, Comparison, Increment);
  35. AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, DataAddress, Arithmetic, Comparison, Increment);
  36. AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, MemoryAddress, Arithmetic, Comparison, Increment);
  37. // FIXME: These should probably be made generic/virtual if/when we decide to do something more
  38. // fancy than just a dumb interpreter.
  39. class Reference {
  40. public:
  41. struct Null {
  42. ValueType type;
  43. };
  44. struct Func {
  45. FunctionAddress address;
  46. };
  47. struct Extern {
  48. ExternAddress address;
  49. };
  50. using RefType = Variant<Null, Func, Extern>;
  51. explicit Reference(RefType ref)
  52. : m_ref(move(ref))
  53. {
  54. }
  55. explicit Reference()
  56. : m_ref(Reference::Null { ValueType(ValueType::Kind::FunctionReference) })
  57. {
  58. }
  59. auto& ref() const { return m_ref; }
  60. private:
  61. RefType m_ref;
  62. };
  63. class Value {
  64. public:
  65. Value()
  66. : m_value(0)
  67. {
  68. }
  69. using AnyValueType = Variant<i32, i64, float, double, u128, Reference>;
  70. explicit Value(AnyValueType value)
  71. : m_value(move(value))
  72. {
  73. }
  74. template<typename T>
  75. requires(sizeof(T) == sizeof(u64)) explicit Value(ValueType type, T raw_value)
  76. : m_value(0)
  77. {
  78. switch (type.kind()) {
  79. case ValueType::Kind::ExternReference:
  80. m_value = Reference { Reference::Extern { { bit_cast<u64>(raw_value) } } };
  81. break;
  82. case ValueType::Kind::FunctionReference:
  83. m_value = Reference { Reference::Func { { bit_cast<u64>(raw_value) } } };
  84. break;
  85. case ValueType::Kind::I32:
  86. m_value = static_cast<i32>(bit_cast<i64>(raw_value));
  87. break;
  88. case ValueType::Kind::I64:
  89. m_value = static_cast<i64>(bit_cast<u64>(raw_value));
  90. break;
  91. case ValueType::Kind::F32:
  92. m_value = static_cast<float>(bit_cast<double>(raw_value));
  93. break;
  94. case ValueType::Kind::F64:
  95. m_value = bit_cast<double>(raw_value);
  96. break;
  97. case ValueType::Kind::V128:
  98. m_value = u128(0ull, bit_cast<u64>(raw_value));
  99. break;
  100. default:
  101. VERIFY_NOT_REACHED();
  102. }
  103. }
  104. template<SameAs<u128> T>
  105. explicit Value(T raw_value)
  106. : m_value(raw_value)
  107. {
  108. }
  109. ALWAYS_INLINE Value(Value const& value) = default;
  110. ALWAYS_INLINE Value(Value&& value) = default;
  111. ALWAYS_INLINE Value& operator=(Value&& value) = default;
  112. ALWAYS_INLINE Value& operator=(Value const& value) = default;
  113. template<typename T>
  114. ALWAYS_INLINE Optional<T> to() const
  115. {
  116. Optional<T> result;
  117. m_value.visit(
  118. [&](auto value) {
  119. if constexpr (IsSame<T, decltype(value)> || (!IsFloatingPoint<T> && IsSame<decltype(value), MakeSigned<T>>)) {
  120. result = static_cast<T>(value);
  121. } else if constexpr (!IsFloatingPoint<T> && IsConvertible<decltype(value), T>) {
  122. // NOTE: No implicit vector <-> scalar conversion.
  123. if constexpr (!IsSame<T, u128>) {
  124. if (AK::is_within_range<T>(value))
  125. result = static_cast<T>(value);
  126. }
  127. }
  128. },
  129. [&](u128 value) {
  130. if constexpr (IsSame<T, u128>)
  131. result = value;
  132. },
  133. [&](Reference const& value) {
  134. if constexpr (IsSame<T, Reference>) {
  135. result = value;
  136. } else if constexpr (IsSame<T, Reference::Func>) {
  137. if (auto ptr = value.ref().template get_pointer<Reference::Func>())
  138. result = *ptr;
  139. } else if constexpr (IsSame<T, Reference::Extern>) {
  140. if (auto ptr = value.ref().template get_pointer<Reference::Extern>())
  141. result = *ptr;
  142. } else if constexpr (IsSame<T, Reference::Null>) {
  143. if (auto ptr = value.ref().template get_pointer<Reference::Null>())
  144. result = *ptr;
  145. }
  146. });
  147. return result;
  148. }
  149. ValueType type() const
  150. {
  151. return ValueType(m_value.visit(
  152. [](i32) { return ValueType::Kind::I32; },
  153. [](i64) { return ValueType::Kind::I64; },
  154. [](float) { return ValueType::Kind::F32; },
  155. [](double) { return ValueType::Kind::F64; },
  156. [](u128) { return ValueType::Kind::V128; },
  157. [&](Reference const& type) {
  158. return type.ref().visit(
  159. [](Reference::Func const&) { return ValueType::Kind::FunctionReference; },
  160. [](Reference::Null const& null_type) {
  161. return null_type.type.kind();
  162. },
  163. [](Reference::Extern const&) { return ValueType::Kind::ExternReference; });
  164. }));
  165. }
  166. auto& value() const { return m_value; }
  167. private:
  168. AnyValueType m_value;
  169. };
  170. struct Trap {
  171. ByteString reason;
  172. };
  173. // A variant of Result that does not include external reasons for error (JS::Completion, for now).
  174. class PureResult {
  175. public:
  176. explicit PureResult(Vector<Value> values)
  177. : m_result(move(values))
  178. {
  179. }
  180. PureResult(Trap trap)
  181. : m_result(move(trap))
  182. {
  183. }
  184. auto is_trap() const { return m_result.has<Trap>(); }
  185. auto& values() const { return m_result.get<Vector<Value>>(); }
  186. auto& values() { return m_result.get<Vector<Value>>(); }
  187. auto& trap() const { return m_result.get<Trap>(); }
  188. auto& trap() { return m_result.get<Trap>(); }
  189. private:
  190. friend class Result;
  191. explicit PureResult(Variant<Vector<Value>, Trap>&& result)
  192. : m_result(move(result))
  193. {
  194. }
  195. Variant<Vector<Value>, Trap> m_result;
  196. };
  197. class Result {
  198. public:
  199. explicit Result(Vector<Value> values)
  200. : m_result(move(values))
  201. {
  202. }
  203. Result(Trap trap)
  204. : m_result(move(trap))
  205. {
  206. }
  207. Result(JS::Completion completion)
  208. : m_result(move(completion))
  209. {
  210. VERIFY(m_result.get<JS::Completion>().is_abrupt());
  211. }
  212. Result(PureResult&& result)
  213. : m_result(result.m_result.downcast<decltype(m_result)>())
  214. {
  215. }
  216. auto is_trap() const { return m_result.has<Trap>(); }
  217. auto is_completion() const { return m_result.has<JS::Completion>(); }
  218. auto& values() const { return m_result.get<Vector<Value>>(); }
  219. auto& values() { return m_result.get<Vector<Value>>(); }
  220. auto& trap() const { return m_result.get<Trap>(); }
  221. auto& trap() { return m_result.get<Trap>(); }
  222. auto& completion() { return m_result.get<JS::Completion>(); }
  223. auto& completion() const { return m_result.get<JS::Completion>(); }
  224. PureResult assert_wasm_result() &&
  225. {
  226. VERIFY(!is_completion());
  227. return PureResult(move(m_result).downcast<Vector<Value>, Trap>());
  228. }
  229. private:
  230. Variant<Vector<Value>, Trap, JS::Completion> m_result;
  231. };
  232. using ExternValue = Variant<FunctionAddress, TableAddress, MemoryAddress, GlobalAddress>;
  233. class ExportInstance {
  234. public:
  235. explicit ExportInstance(ByteString name, ExternValue value)
  236. : m_name(move(name))
  237. , m_value(move(value))
  238. {
  239. }
  240. auto& name() const { return m_name; }
  241. auto& value() const { return m_value; }
  242. private:
  243. ByteString m_name;
  244. ExternValue m_value;
  245. };
  246. class ModuleInstance {
  247. public:
  248. explicit ModuleInstance(
  249. Vector<FunctionType> types, Vector<FunctionAddress> function_addresses, Vector<TableAddress> table_addresses,
  250. Vector<MemoryAddress> memory_addresses, Vector<GlobalAddress> global_addresses, Vector<DataAddress> data_addresses,
  251. Vector<ExportInstance> exports)
  252. : m_types(move(types))
  253. , m_functions(move(function_addresses))
  254. , m_tables(move(table_addresses))
  255. , m_memories(move(memory_addresses))
  256. , m_globals(move(global_addresses))
  257. , m_datas(move(data_addresses))
  258. , m_exports(move(exports))
  259. {
  260. }
  261. ModuleInstance() = default;
  262. auto& types() const { return m_types; }
  263. auto& functions() const { return m_functions; }
  264. auto& tables() const { return m_tables; }
  265. auto& memories() const { return m_memories; }
  266. auto& globals() const { return m_globals; }
  267. auto& elements() const { return m_elements; }
  268. auto& datas() const { return m_datas; }
  269. auto& exports() const { return m_exports; }
  270. auto& types() { return m_types; }
  271. auto& functions() { return m_functions; }
  272. auto& tables() { return m_tables; }
  273. auto& memories() { return m_memories; }
  274. auto& globals() { return m_globals; }
  275. auto& elements() { return m_elements; }
  276. auto& datas() { return m_datas; }
  277. auto& exports() { return m_exports; }
  278. private:
  279. Vector<FunctionType> m_types;
  280. Vector<FunctionAddress> m_functions;
  281. Vector<TableAddress> m_tables;
  282. Vector<MemoryAddress> m_memories;
  283. Vector<GlobalAddress> m_globals;
  284. Vector<ElementAddress> m_elements;
  285. Vector<DataAddress> m_datas;
  286. Vector<ExportInstance> m_exports;
  287. };
  288. class WasmFunction {
  289. public:
  290. explicit WasmFunction(FunctionType const& type, ModuleInstance const& module, Module::Function const& code)
  291. : m_type(type)
  292. , m_module(module)
  293. , m_code(code)
  294. {
  295. }
  296. auto& type() const { return m_type; }
  297. auto& module() const { return m_module; }
  298. auto& code() const { return m_code; }
  299. private:
  300. FunctionType m_type;
  301. ModuleInstance const& m_module;
  302. Module::Function const& m_code;
  303. };
  304. class HostFunction {
  305. public:
  306. explicit HostFunction(AK::Function<Result(Configuration&, Vector<Value>&)> function, FunctionType const& type, ByteString name)
  307. : m_function(move(function))
  308. , m_type(type)
  309. , m_name(move(name))
  310. {
  311. }
  312. auto& function() { return m_function; }
  313. auto& type() const { return m_type; }
  314. auto& name() const { return m_name; }
  315. private:
  316. AK::Function<Result(Configuration&, Vector<Value>&)> m_function;
  317. FunctionType m_type;
  318. ByteString m_name;
  319. };
  320. using FunctionInstance = Variant<WasmFunction, HostFunction>;
  321. class TableInstance {
  322. public:
  323. explicit TableInstance(TableType const& type, Vector<Reference> elements)
  324. : m_elements(move(elements))
  325. , m_type(type)
  326. {
  327. }
  328. auto& elements() const { return m_elements; }
  329. auto& elements() { return m_elements; }
  330. auto& type() const { return m_type; }
  331. bool grow(u32 size_to_grow, Reference const& fill_value)
  332. {
  333. if (size_to_grow == 0)
  334. return true;
  335. size_t new_size = m_elements.size() + size_to_grow;
  336. if (auto max = m_type.limits().max(); max.has_value()) {
  337. if (max.value() < new_size)
  338. return false;
  339. }
  340. if (new_size >= NumericLimits<u32>::max()) {
  341. return false;
  342. }
  343. auto previous_size = m_elements.size();
  344. if (m_elements.try_resize(new_size).is_error())
  345. return false;
  346. for (size_t i = previous_size; i < m_elements.size(); ++i)
  347. m_elements[i] = fill_value;
  348. return true;
  349. }
  350. private:
  351. Vector<Reference> m_elements;
  352. TableType m_type;
  353. };
  354. class MemoryInstance {
  355. public:
  356. static ErrorOr<MemoryInstance> create(MemoryType const& type)
  357. {
  358. MemoryInstance instance { type };
  359. if (!instance.grow(type.limits().min() * Constants::page_size))
  360. return Error::from_string_literal("Failed to grow to requested size");
  361. return { move(instance) };
  362. }
  363. auto& type() const { return m_type; }
  364. auto size() const { return m_size; }
  365. auto& data() const { return m_data; }
  366. auto& data() { return m_data; }
  367. enum class InhibitGrowCallback {
  368. No,
  369. Yes,
  370. };
  371. bool grow(size_t size_to_grow, InhibitGrowCallback inhibit_callback = InhibitGrowCallback::No)
  372. {
  373. if (size_to_grow == 0)
  374. return true;
  375. u64 new_size = m_data.size() + size_to_grow;
  376. // Can't grow past 2^16 pages.
  377. if (new_size >= Constants::page_size * 65536)
  378. return false;
  379. if (auto max = m_type.limits().max(); max.has_value()) {
  380. if (max.value() * Constants::page_size < new_size)
  381. return false;
  382. }
  383. auto previous_size = m_size;
  384. if (m_data.try_resize(new_size).is_error())
  385. return false;
  386. m_size = new_size;
  387. // The spec requires that we zero out everything on grow
  388. __builtin_memset(m_data.offset_pointer(previous_size), 0, size_to_grow);
  389. // NOTE: This exists because wasm-js-api wants to execute code after a successful grow,
  390. // See [this issue](https://github.com/WebAssembly/spec/issues/1635) for more details.
  391. if (inhibit_callback == InhibitGrowCallback::No && successful_grow_hook)
  392. successful_grow_hook();
  393. return true;
  394. }
  395. Function<void()> successful_grow_hook;
  396. private:
  397. explicit MemoryInstance(MemoryType const& type)
  398. : m_type(type)
  399. {
  400. }
  401. MemoryType m_type;
  402. size_t m_size { 0 };
  403. ByteBuffer m_data;
  404. };
  405. class GlobalInstance {
  406. public:
  407. explicit GlobalInstance(Value value, bool is_mutable)
  408. : m_mutable(is_mutable)
  409. , m_value(move(value))
  410. {
  411. }
  412. auto is_mutable() const { return m_mutable; }
  413. auto& value() const { return m_value; }
  414. GlobalType type() const { return { m_value.type(), is_mutable() }; }
  415. void set_value(Value value)
  416. {
  417. VERIFY(is_mutable());
  418. m_value = move(value);
  419. }
  420. private:
  421. bool m_mutable { false };
  422. Value m_value;
  423. };
  424. class DataInstance {
  425. public:
  426. explicit DataInstance(Vector<u8> data)
  427. : m_data(move(data))
  428. {
  429. }
  430. size_t size() const { return m_data.size(); }
  431. Vector<u8>& data() { return m_data; }
  432. Vector<u8> const& data() const { return m_data; }
  433. private:
  434. Vector<u8> m_data;
  435. };
  436. class ElementInstance {
  437. public:
  438. explicit ElementInstance(ValueType type, Vector<Reference> references)
  439. : m_type(move(type))
  440. , m_references(move(references))
  441. {
  442. }
  443. auto& type() const { return m_type; }
  444. auto& references() const { return m_references; }
  445. private:
  446. ValueType m_type;
  447. Vector<Reference> m_references;
  448. };
  449. class Store {
  450. public:
  451. Store() = default;
  452. Optional<FunctionAddress> allocate(ModuleInstance& module, Module::Function const& function);
  453. Optional<FunctionAddress> allocate(HostFunction&&);
  454. Optional<TableAddress> allocate(TableType const&);
  455. Optional<MemoryAddress> allocate(MemoryType const&);
  456. Optional<DataAddress> allocate_data(Vector<u8>);
  457. Optional<GlobalAddress> allocate(GlobalType const&, Value);
  458. Optional<ElementAddress> allocate(ValueType const&, Vector<Reference>);
  459. FunctionInstance* get(FunctionAddress);
  460. TableInstance* get(TableAddress);
  461. MemoryInstance* get(MemoryAddress);
  462. GlobalInstance* get(GlobalAddress);
  463. DataInstance* get(DataAddress);
  464. ElementInstance* get(ElementAddress);
  465. private:
  466. Vector<FunctionInstance> m_functions;
  467. Vector<TableInstance> m_tables;
  468. Vector<MemoryInstance> m_memories;
  469. Vector<GlobalInstance> m_globals;
  470. Vector<ElementInstance> m_elements;
  471. Vector<DataInstance> m_datas;
  472. };
  473. class Label {
  474. public:
  475. explicit Label(size_t arity, InstructionPointer continuation)
  476. : m_arity(arity)
  477. , m_continuation(continuation)
  478. {
  479. }
  480. auto continuation() const { return m_continuation; }
  481. auto arity() const { return m_arity; }
  482. private:
  483. size_t m_arity { 0 };
  484. InstructionPointer m_continuation { 0 };
  485. };
  486. class Frame {
  487. public:
  488. explicit Frame(ModuleInstance const& module, Vector<Value> locals, Expression const& expression, size_t arity)
  489. : m_module(module)
  490. , m_locals(move(locals))
  491. , m_expression(expression)
  492. , m_arity(arity)
  493. {
  494. }
  495. auto& module() const { return m_module; }
  496. auto& locals() const { return m_locals; }
  497. auto& locals() { return m_locals; }
  498. auto& expression() const { return m_expression; }
  499. auto arity() const { return m_arity; }
  500. private:
  501. ModuleInstance const& m_module;
  502. Vector<Value> m_locals;
  503. Expression const& m_expression;
  504. size_t m_arity { 0 };
  505. };
  506. class Stack {
  507. public:
  508. using EntryType = Variant<Value, Label, Frame>;
  509. Stack() = default;
  510. [[nodiscard]] ALWAYS_INLINE bool is_empty() const { return m_data.is_empty(); }
  511. ALWAYS_INLINE void push(EntryType entry) { m_data.append(move(entry)); }
  512. ALWAYS_INLINE auto pop() { return m_data.take_last(); }
  513. ALWAYS_INLINE auto& peek() const { return m_data.last(); }
  514. ALWAYS_INLINE auto& peek() { return m_data.last(); }
  515. ALWAYS_INLINE auto size() const { return m_data.size(); }
  516. ALWAYS_INLINE auto& entries() const { return m_data; }
  517. ALWAYS_INLINE auto& entries() { return m_data; }
  518. private:
  519. Vector<EntryType, 1024> m_data;
  520. };
  521. using InstantiationResult = AK::ErrorOr<NonnullOwnPtr<ModuleInstance>, InstantiationError>;
  522. class AbstractMachine {
  523. public:
  524. explicit AbstractMachine() = default;
  525. // Validate a module; permanently sets the module's validity status.
  526. ErrorOr<void, ValidationError> validate(Module&);
  527. // Load and instantiate a module, and link it into this interpreter.
  528. InstantiationResult instantiate(Module const&, Vector<ExternValue>);
  529. Result invoke(FunctionAddress, Vector<Value>);
  530. Result invoke(Interpreter&, FunctionAddress, Vector<Value>);
  531. auto& store() const { return m_store; }
  532. auto& store() { return m_store; }
  533. void enable_instruction_count_limit() { m_should_limit_instruction_count = true; }
  534. private:
  535. Optional<InstantiationError> allocate_all_initial_phase(Module const&, ModuleInstance&, Vector<ExternValue>&, Vector<Value>& global_values, Vector<FunctionAddress>& own_functions);
  536. Optional<InstantiationError> allocate_all_final_phase(Module const&, ModuleInstance&, Vector<Vector<Reference>>& elements);
  537. Store m_store;
  538. StackInfo m_stack_info;
  539. bool m_should_limit_instruction_count { false };
  540. };
  541. class Linker {
  542. public:
  543. struct Name {
  544. ByteString module;
  545. ByteString name;
  546. ImportSection::Import::ImportDesc type;
  547. };
  548. explicit Linker(Module const& module)
  549. : m_module(module)
  550. {
  551. }
  552. // Link a module, the import 'module name' is ignored with this.
  553. void link(ModuleInstance const&);
  554. // Link a bunch of qualified values, also matches 'module name'.
  555. void link(HashMap<Name, ExternValue> const&);
  556. auto& unresolved_imports()
  557. {
  558. populate();
  559. return m_unresolved_imports;
  560. }
  561. AK::ErrorOr<Vector<ExternValue>, LinkError> finish();
  562. private:
  563. void populate();
  564. Module const& m_module;
  565. HashMap<Name, ExternValue> m_resolved_imports;
  566. HashTable<Name> m_unresolved_imports;
  567. Vector<Name> m_ordered_imports;
  568. Optional<LinkError> m_error;
  569. };
  570. }
  571. template<>
  572. struct AK::Traits<Wasm::Linker::Name> : public AK::DefaultTraits<Wasm::Linker::Name> {
  573. static constexpr bool is_trivial() { return false; }
  574. static unsigned hash(Wasm::Linker::Name const& entry) { return pair_int_hash(entry.module.hash(), entry.name.hash()); }
  575. static bool equals(Wasm::Linker::Name const& a, Wasm::Linker::Name const& b) { return a.name == b.name && a.module == b.module; }
  576. };