3#include <sysio/vm/allocator.hpp>
4#include <sysio/vm/bitcode_writer.hpp>
5#include <sysio/vm/config.hpp>
6#include <sysio/vm/debug_visitor.hpp>
7#include <sysio/vm/execution_context.hpp>
8#include <sysio/vm/interpret_visitor.hpp>
9#include <sysio/vm/null_writer.hpp>
10#include <sysio/vm/parser.hpp>
11#include <sysio/vm/types.hpp>
14#include <sysio/vm/x86_64.hpp>
22#include <system_error>
25namespace sysio {
namespace vm {
29 template<
typename Host>
30 using context = jit_execution_context<Host>;
31 template<
typename Host,
typename Options,
typename DebugInfo>
32 using parser = binary_parser<machine_code_writer<jit_execution_context<Host>>, Options, DebugInfo>;
33 static constexpr bool is_jit =
true;
37 template<
typename Host>
38 using context = jit_execution_context<Host, true>;
39 template<
typename Host,
typename Options,
typename DebugInfo>
40 using parser = binary_parser<machine_code_writer<context<Host>>, Options, DebugInfo>;
41 static constexpr bool is_jit =
true;
46 template<
typename Host>
48 template<
typename Host,
typename Options,
typename DebugInfo>
50 static constexpr bool is_jit =
false;
54 template<
typename Host>
56 template<
typename Host,
typename Options,
typename DebugInfo>
58 static constexpr bool is_jit =
false;
61 template <
typename HostFunctions = std::
nullptr_t,
typename Impl =
interpreter,
typename Options = default_options,
typename DebugInfo = null_debug_info>
65 using parser_t =
typename Impl::template parser<HostFunctions, Options, DebugInfo>;
66 void construct(host_t* host=
nullptr) {
68 ctx.set_wasm_allocator(memory_alloc);
69 if constexpr (!std::is_same_v<HostFunctions, std::nullptr_t>)
70 HostFunctions::resolve(mod);
72 if constexpr (!std::is_same_v<Impl, null_backend>)
78 ctx.set_max_pages(detail::get_max_pages(
options));
83 ctx.set_max_pages(detail::get_max_pages(
options));
88 ctx.set_max_pages(detail::get_max_pages(
options));
93 ctx.set_max_pages(detail::get_max_pages(
options));
98 ctx.set_max_pages(detail::get_max_pages(
options));
103 ctx.set_max_pages(detail::get_max_pages(
options));
107 template <
typename... Args>
108 inline auto operator()(host_t& host,
const std::string_view& mod,
const std::string_view&
func, Args... args) {
109 return call(host, mod,
func, args...);
112 template <
typename... Args>
113 inline bool operator()(
const std::string_view& mod,
const std::string_view&
func, Args... args) {
119 ctx.set_max_call_depth(detail::get_max_call_depth(new_options));
120 ctx.set_max_pages(detail::get_max_pages(new_options));
137 template <
typename... Args>
140 ctx.execute_func_table(host,
debug_visitor(ctx), func_index, args...);
147 template <
typename... Args>
157 template <
typename... Args>
158 inline bool call(host_t& host,
const std::string_view& mod,
const std::string_view&
func, Args... args) {
167 template <
typename... Args>
168 inline bool call(
const std::string_view& mod,
const std::string_view&
func, Args... args) {
177 template <
typename... Args>
178 inline auto call_with_return(host_t& host,
const std::string_view& mod,
const std::string_view&
func, Args... args ) {
186 template <
typename... Args>
195 template<
typename Watchdog,
typename F>
197 std::atomic<bool> _timed_out =
false;
200 mod.allocator.enable_code(Impl::is_jit);
204 auto wd_guard =
wd.scoped_run([
this,&_timed_out]() {
206 mod.allocator.disable_code();
208 static_cast<F&&
>(
f)();
209 }
catch(wasm_memory_exception&) {
211 throw timeout_exception{
"execution timed out" };
218 template <
typename Watchdog>
221 for (
int i = 0; i < mod.exports.size(); i++) {
222 if (mod.exports[i].kind == external_kind::Function) {
223 std::string
s{ (
const char*)mod.exports[i].field_str.raw(), mod.exports[i].field_str.size() };
230 template <
typename Watchdog>
233 for (
int i = 0; i < mod.exports.size(); i++) {
234 if (mod.exports[i].kind == external_kind::Function) {
235 std::string
s{ (
const char*)mod.exports[i].field_str.raw(), mod.exports[i].field_str.size() };
243 memory_alloc = alloc;
244 ctx.set_wasm_allocator(memory_alloc);
248 inline module& get_module() { return mod; }
249 inline void exit(
const std::error_code& ec) { ctx.exit(ec); }
backend(wasm_code &code, host_t &host, wasm_allocator *alloc, const Options &options=Options{})
const DebugInfo & get_debug() const
auto call_with_return(const std::string_view &mod, const std::string_view &func, Args... args)
bool call_indirect(host_t *host, uint32_t func_index, Args... args)
backend(wasm_code &&code, host_t &host, wasm_allocator *alloc, const Options &options=Options{})
backend(wasm_code &code, wasm_allocator *alloc, const Options &options=Options{})
backend(wasm_code_ptr &ptr, size_t sz, wasm_allocator *alloc, const Options &options=Options{})
void execute_all(Watchdog &&wd)
backend & initialize(host_t *host=nullptr)
backend(wasm_code &&code, wasm_allocator *alloc, const Options &options=Options{})
bool call(host_t *host, uint32_t func_index, Args... args)
void execute_all(Watchdog &&wd, host_t &host)
backend & initialize(host_t &host)
auto operator()(host_t &host, const std::string_view &mod, const std::string_view &func, Args... args)
backend(wasm_code_ptr &ptr, size_t sz, host_t &host, wasm_allocator *alloc, const Options &options=Options{})
bool call(const std::string_view &mod, const std::string_view &func, Args... args)
void exit(const std::error_code &ec)
void timed_run(Watchdog &&wd, F &&f)
bool call(host_t &host, const std::string_view &mod, const std::string_view &func, Args... args)
backend & initialize(host_t *host, const Options &new_options)
bool operator()(const std::string_view &mod, const std::string_view &func, Args... args)
wasm_allocator * get_wasm_allocator()
auto call_with_return(host_t &host, const std::string_view &mod, const std::string_view &func, Args... args)
void set_wasm_allocator(wasm_allocator *alloc)
bip::allocator< T, pinnable_mapped_file::segment_manager > allocator
typename host_type< HF >::type host_type_t
constexpr bool eos_vm_debug
std::vector< uint8_t > wasm_code
static constexpr bool is_jit
static constexpr bool is_jit