Skip to content

Commit

Permalink
wasm: use the new rust bindings of wasmtime
Browse files Browse the repository at this point in the history
This patch replaces all dependencies on the wasmtime
C++ bindings with our new ones.
The wasmtime.hh and wasm_engine.hh files are deleted.
The libwasmtime.a library is no longer required by
configure.py. The SCYLLA_ENABLE_WASMTIME macro is
removed and wasm udfs are now compiled by default
on all architectures.
In terms of implementation, most of code using
wasmtime was moved to the Rust source files. The
remaining code uses names from the new bindings
(which are mostly unchanged). Most of wasmtime objects
are now stored as a rust::Box<>, to make it compatible
with rust lifetime requirements.

Signed-off-by: Wojciech Mitros <wojciech.mitros@scylladb.com>
  • Loading branch information
wmitros committed Aug 29, 2022
1 parent bc91707 commit 4bc21e3
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 3,017 deletions.
17 changes: 1 addition & 16 deletions configure.py
Expand Up @@ -1052,6 +1052,7 @@ def find_headers(repodir, excluded_dirs):
'service/raft/raft_group0.cc',
'direct_failure_detector/failure_detector.cc',
'service/raft/raft_group0_client.cc',
'rust/wasmtime_bindings/src/lib.rs',
] + [Antlr3Grammar('cql3/Cql.g')] + [Thrift('interface/cassandra.thrift', 'Cassandra')] \
+ scylla_raft_core
)
Expand Down Expand Up @@ -1418,18 +1419,6 @@ def clang_inline_threshold():
for mode in modes:
modes[mode]['cxxflags'] += f' -Wstack-usage={modes[mode]["stack-usage-threshold"]} -Wno-error=stack-usage='

has_wasmtime = False

if has_wasmtime:
if platform.machine() == 'aarch64':
print("wasmtime is temporarily not supported on aarch64. Ref: issue #9387")
has_wasmtime = False
else:
for mode in modes:
modes[mode]['cxxflags'] += ' -DSCYLLA_ENABLE_WASMTIME'
else:
print("wasmtime not found - WASM support will not be enabled in this build")

linker_flags = linker_flags(compiler=args.cxx)

dbgflag = '-g -gz' if args.debuginfo else ''
Expand Down Expand Up @@ -1747,8 +1736,6 @@ def configure_abseil(build_dir, mode, mode_config):
maybe_static(args.staticboost, '-lboost_date_time -lboost_regex -licuuc -licui18n'),
'-lxxhash',
])
if has_wasmtime:
print("Found wasmtime dependency, linking with libwasmtime")

if not args.staticboost:
args.user_cflags += ' -DBOOST_TEST_DYN_LINK'
Expand Down Expand Up @@ -1934,8 +1921,6 @@ def configure_abseil(build_dir, mode, mode_config):
for src in srcs
if src.endswith('.cc')]
objs.append('$builddir/../utils/arch/powerpc/crc32-vpmsum/crc32.S')
if has_wasmtime:
objs.append('/usr/lib64/libwasmtime.a')
has_thrift = False
has_rust = False
for dep in deps[binary]:
Expand Down
269 changes: 93 additions & 176 deletions lang/wasm.cc

Large diffs are not rendered by default.

31 changes: 4 additions & 27 deletions lang/wasm.hh
Expand Up @@ -10,8 +10,8 @@

#include "types.hh"
#include <seastar/core/future.hh>
#include "lang/wasm_engine.hh"
#include "db/functions/function_name.hh"
#include "rust/wasmtime_bindings.hh"

namespace wasm {

Expand All @@ -30,15 +30,13 @@ struct instance_corrupting_exception : public exception {
explicit instance_corrupting_exception(std::string_view msg) : exception(msg) {}
};

#ifdef SCYLLA_ENABLE_WASMTIME

struct context {
wasm::engine* engine_ptr;
std::optional<wasmtime::Module> module;
rust::Box<wasmtime::Engine>* engine_ptr;
std::optional<rust::Box<wasmtime::Module>> module;
std::string function_name;
instance_cache* cache;

context(wasm::engine* engine_ptr, std::string name, instance_cache* cache);
context(rust::Box<wasmtime::Engine>* engine_ptr, std::string name, instance_cache* cache);
};

void compile(context& ctx, const std::vector<sstring>& arg_names, std::string script);
Expand All @@ -47,25 +45,4 @@ seastar::future<bytes_opt> run_script(context& ctx, const std::vector<data_type>

seastar::future<bytes_opt> run_script(const db::functions::function_name& name, context& ctx, const std::vector<data_type>& arg_types, const std::vector<bytes_opt>& params, data_type return_type, bool allow_null_input);

#else

struct context {
context(wasm::engine*, std::string, instance_cache*) {
throw wasm::exception("WASM support was not enabled during compilation!");
}
};

inline void compile(context&, const std::vector<sstring>&, std::string) {
throw wasm::exception("WASM support was not enabled during compilation!");
}

inline seastar::future<bytes_opt> run_script(context&, const std::vector<data_type>&, const std::vector<bytes_opt>&, data_type, bool) {
throw wasm::exception("WASM support was not enabled during compilation!");
}

inline seastar::future<bytes_opt> run_script(const db::functions::function_name& name, context& ctx, const std::vector<data_type>& arg_types, const std::vector<bytes_opt>& params, data_type return_type, bool allow_null_input) {
throw wasm::exception("WASM support was not enabled during compilation!");
}
#endif

}
59 changes: 0 additions & 59 deletions lang/wasm_engine.hh

This file was deleted.

42 changes: 6 additions & 36 deletions lang/wasm_instance_cache.cc
Expand Up @@ -6,8 +6,6 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

#ifdef SCYLLA_ENABLE_WASMTIME

#include "lang/wasm_instance_cache.hh"
#include "seastar/core/metrics.hh"
#include "seastar/core/scheduling.hh"
Expand Down Expand Up @@ -49,37 +47,11 @@ instance_cache::instance_cache(size_t size, seastar::lowres_clock::duration time
}

wasm_instance instance_cache::load(wasm::context& ctx) {
auto store = wasmtime::Store(ctx.engine_ptr->get());
auto linker = wasmtime::Linker(ctx.engine_ptr->get());
auto wasi_def = linker.define_wasi();
if (!wasi_def) {
throw wasm::exception(format("Setting up wasi failed: {}", wasi_def.err().message()));
}
auto cfg = wasmtime::WasiConfig();
auto set_cfg = store.context().set_wasi(std::move(cfg));
if (!set_cfg) {
throw wasm::exception(format("Setting up wasi failed: {}", set_cfg.err().message()));
}
auto instance_res = linker.instantiate(store, *ctx.module);
if (!instance_res) {
throw wasm::exception(format("Creating a wasm runtime instance failed: {}", instance_res.err().message()));
}
auto instance = instance_res.unwrap();
auto function_obj = instance.get(store, ctx.function_name);
if (!function_obj) {
throw wasm::exception(format("Function {} was not found in given wasm source code", ctx.function_name));
}
wasmtime::Func* func = std::get_if<wasmtime::Func>(&*function_obj);
if (!func) {
throw wasm::exception(format("Exported object {} is not a function", ctx.function_name));
}
auto memory_export = instance.get(store, "memory");
if (!memory_export) {
throw wasm::exception("memory export not found - please export `memory` in the wasm module");
}
auto memory = std::get<wasmtime::Memory>(*memory_export);

return wasm::wasm_instance{.store=std::move(store), .instance=std::move(instance), .func=std::move(*func), .memory=std::move(memory)};
auto store = wasmtime::create_store(**ctx.engine_ptr);
auto instance = wasmtime::create_instance(**ctx.engine_ptr, **ctx.module, *store);
auto func = wasmtime::create_func(*instance, *store, ctx.function_name);
auto memory = wasmtime::get_memory(*instance, *store);
return wasm_instance{.store=std::move(store), .instance=std::move(instance), .func=std::move(func), .memory=std::move(memory)};
}

// lru must not be empty, and its elements must refer to entries in _cache
Expand All @@ -100,7 +72,7 @@ void instance_cache::on_timer() noexcept {

static uint32_t get_instance_size(wasm_instance& instance) {
// reserve 1 wasm page for instance data other than the wasm memory
return WASM_PAGE_SIZE * (1 + instance.memory.size(instance.store));
return WASM_PAGE_SIZE * (1 + instance.memory->size(*instance.store));
}

seastar::future<instance_cache::value_type> instance_cache::get(const db::functions::function_name& name, const std::vector<data_type>& arg_types, wasm::context& ctx) {
Expand Down Expand Up @@ -222,5 +194,3 @@ struct equal_to<seastar::scheduling_group> {
};

}

#endif
37 changes: 6 additions & 31 deletions lang/wasm_instance_cache.hh
Expand Up @@ -8,30 +8,6 @@

#pragma once

#ifndef SCYLLA_ENABLE_WASMTIME

#include <cstddef>
#include <seastar/core/lowres_clock.hh>
#include "lang/wasm.hh"

namespace wasm {

struct instance_cache {
explicit instance_cache(size_t size, seastar::lowres_clock::duration timer_period) {}

void remove(const db::functions::function_name& name, const std::vector<data_type>& arg_types) {
throw wasm::exception("WASM support was not enabled during compilation!");
}

future<> stop() {
return seastar::make_ready_future<>();
}
};

}

#else

#include "db/functions/function_name.hh"
#include <list>
#include <seastar/core/metrics_registration.hh>
Expand All @@ -41,15 +17,16 @@ struct instance_cache {
#include <seastar/core/timer.hh>
#include <unordered_map>
#include "lang/wasm.hh"
#include "wasmtime.hh"
#include "rust/cxx.h"
#include "rust/wasmtime_bindings.hh"

namespace wasm {

struct wasm_instance {
wasmtime::Store store;
wasmtime::Instance instance;
wasmtime::Func func;
wasmtime::Memory memory;
rust::Box<wasmtime::Store> store;
rust::Box<wasmtime::Instance> instance;
rust::Box<wasmtime::Func> func;
rust::Box<wasmtime::Memory> memory;
};

// For each UDF full name and a scheduling group, we store a wasmtime instance
Expand Down Expand Up @@ -145,5 +122,3 @@ public:
};

}

#endif

0 comments on commit 4bc21e3

Please sign in to comment.