Skip to content

Commit

Permalink
Pass host_context by reference to avoid extra allocations
Browse files Browse the repository at this point in the history
  • Loading branch information
gumb0 committed Feb 19, 2021
1 parent b035078 commit 7e78d7b
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 39 deletions.
2 changes: 1 addition & 1 deletion lib/fizzy/capi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ inline fizzy::ExecutionResult unwrap(const FizzyExecutionResult& result) noexcep
inline fizzy::ExecuteFunction unwrap(FizzyExternalFn c_function, void* c_host_context)
{
static constexpr fizzy::HostFunctionPtr function =
[](std::any host_context, fizzy::Instance& instance, const fizzy::Value* args, int depth) {
[](std::any& host_context, fizzy::Instance& instance, const fizzy::Value* args, int depth) {
const auto [c_func, c_host_ctx] =
std::any_cast<std::pair<FizzyExternalFn, void*>>(host_context);
return unwrap(c_func(c_host_ctx, wrap(&instance), wrap(args), depth));
Expand Down
5 changes: 3 additions & 2 deletions lib/fizzy/instantiate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct Instance;

/// Function pointer to the execution function.
using HostFunctionPtr = ExecutionResult (*)(
std::any host_context, Instance&, const Value* args, int depth);
std::any& host_context, Instance&, const Value* args, int depth);

/// Function representing either WebAssembly or host function execution.
class ExecuteFunction
Expand Down Expand Up @@ -56,7 +56,8 @@ class ExecuteFunction
ExecuteFunction(HostFunctionPtr f) noexcept : m_host_function{f} {}

/// Host function constructor with context.
/// The function will be called with a copy of @a host_context.
/// The function will be called with a reference to @a host_context.
/// Copies of the function will have their own copy of @a host_context.
ExecuteFunction(HostFunctionPtr f, std::any host_context)
: m_host_function{f}, m_host_context{std::move(host_context)}
{}
Expand Down
8 changes: 4 additions & 4 deletions test/unittests/api_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ namespace
{
ExecuteFunction function_returning_value(Value value)
{
static constexpr HostFunctionPtr func = [](std::any host_context, Instance&, const Value*,
static constexpr HostFunctionPtr func = [](std::any& host_context, Instance&, const Value*,
int) -> ExecutionResult {
return std::any_cast<Value>(host_context);
};

return {func, std::make_any<Value>(value)};
}

ExecutionResult function_returning_void(std::any, Instance&, const Value*, int) noexcept
ExecutionResult function_returning_void(std::any&, Instance&, const Value*, int) noexcept
{
return Void;
}
Expand Down Expand Up @@ -227,7 +227,7 @@ TEST(api, resolve_imported_function_duplicate_with_context)
"0061736d01000000010401600000021902046d6f643104666f6f310000046d6f643104666f6f310000");
const auto module = parse(wasm);

constexpr auto host_func = [](std::any context, Instance&, const Value*, int) {
constexpr auto host_func = [](std::any& context, Instance&, const Value*, int) {
auto* counter = std::any_cast<int*>(context);
++(*counter);
return Void;
Expand Down Expand Up @@ -466,7 +466,7 @@ TEST(api, find_exported_function)
"0061736d010000000105016000017f021001087370656374657374036261720000040401700000050401010102"
"0606017f0041000b07170403666f6f000001670300037461620100036d656d0200");

constexpr auto bar = [](std::any, Instance&, const Value*, int) -> ExecutionResult {
constexpr auto bar = [](std::any&, Instance&, const Value*, int) -> ExecutionResult {
return Value{42};
};
const auto bar_type = FuncType{{}, {ValType::i32}};
Expand Down
26 changes: 13 additions & 13 deletions test/unittests/execute_call_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ TEST(execute_call, imported_function_call)

const auto module = parse(wasm);

constexpr auto host_foo = [](std::any, Instance&, const Value*, int) -> ExecutionResult {
constexpr auto host_foo = [](std::any&, Instance&, const Value*, int) -> ExecutionResult {
return Value{42};
};
const auto& host_foo_type = module->typesec[0];
Expand All @@ -364,7 +364,7 @@ TEST(execute_call, imported_function_call_void)
const auto module = parse(wasm);

static bool called = false;
constexpr auto host_foo = [](std::any, Instance&, const Value*, int) {
constexpr auto host_foo = [](std::any&, Instance&, const Value*, int) {
called = true;
return Void;
};
Expand Down Expand Up @@ -392,7 +392,7 @@ TEST(execute_call, imported_function_call_with_arguments)

const auto module = parse(wasm);

constexpr auto host_foo = [](std::any, Instance&, const Value* args, int) -> ExecutionResult {
constexpr auto host_foo = [](std::any&, Instance&, const Value* args, int) -> ExecutionResult {
return Value{args[0].i32 * 2};
};
const auto host_foo_type = module->typesec[0];
Expand Down Expand Up @@ -436,11 +436,11 @@ TEST(execute_call, imported_functions_call_indirect)
ASSERT_EQ(module->importsec.size(), 2);
ASSERT_EQ(module->codesec.size(), 2);

constexpr auto sqr = [](std::any, Instance&, const Value* args, int) -> ExecutionResult {
constexpr auto sqr = [](std::any&, Instance&, const Value* args, int) -> ExecutionResult {
const auto x = args[0].i32;
return Value{uint64_t{x} * uint64_t{x}};
};
constexpr auto isqrt = [](std::any, Instance&, const Value* args, int) -> ExecutionResult {
constexpr auto isqrt = [](std::any&, Instance&, const Value* args, int) -> ExecutionResult {
const auto x = args[0].i32;
return Value{(11 + uint64_t{x} / 11) / 2};
};
Expand Down Expand Up @@ -563,7 +563,7 @@ TEST(execute_call, imported_function_from_another_module_via_host_function)
const auto func_idx = fizzy::find_exported_function(*module1, "sub");
ASSERT_TRUE(func_idx.has_value());

constexpr auto sub = [](std::any host_context, Instance&, const Value* args, int depth) {
constexpr auto sub = [](std::any& host_context, Instance&, const Value* args, int depth) {
auto [inst1, idx] = std::any_cast<std::pair<Instance*, FuncIdx>>(host_context);
return fizzy::execute(*inst1, idx, args, depth);
};
Expand Down Expand Up @@ -703,7 +703,7 @@ TEST(execute_call, call_initial_depth)
const auto wasm = from_hex("0061736d01000000010401600000020b01036d6f6403666f6f0000");

auto module = parse(wasm);
constexpr auto host_foo = [](std::any, Instance&, const Value*, int depth) {
constexpr auto host_foo = [](std::any&, Instance&, const Value*, int depth) {
EXPECT_EQ(depth, 0);
return Void;
};
Expand Down Expand Up @@ -740,7 +740,7 @@ TEST(execute_call, execute_imported_max_depth)
from_hex("0061736d01000000010401600000020b01036d6f6403666f6f0000030201000a040102000b");

auto module = parse(wasm);
constexpr auto host_foo = [](std::any, Instance&, const Value*, int depth) {
constexpr auto host_foo = [](std::any&, Instance&, const Value*, int depth) {
EXPECT_LE(depth, TestCallStackLimit - 1);
return Void;
};
Expand Down Expand Up @@ -782,7 +782,7 @@ TEST(execute_call, imported_function_from_another_module_max_depth)
const auto func_idx = fizzy::find_exported_function(*instance1->module, "f");
ASSERT_TRUE(func_idx.has_value());

constexpr auto sub = [](std::any host_context, Instance&, const Value* args, int depth) {
constexpr auto sub = [](std::any& host_context, Instance&, const Value* args, int depth) {
auto [inst1, idx] = std::any_cast<std::pair<Instance*, FuncIdx>>(host_context);
return fizzy::execute(*inst1, idx, args, depth + 1);
};
Expand Down Expand Up @@ -862,7 +862,7 @@ TEST(execute_call, call_imported_infinite_recursion)

const auto module = parse(wasm);
static int counter = 0;
constexpr auto host_foo = [](std::any, Instance& instance, const Value* args, int depth) {
constexpr auto host_foo = [](std::any&, Instance& instance, const Value* args, int depth) {
++counter;
return execute(instance, 0, args, depth + 1);
};
Expand Down Expand Up @@ -892,7 +892,7 @@ TEST(execute_call, call_imported_interleaved_infinite_recursion)

const auto module = parse(wasm);
static int counter = 0;
constexpr auto host_foo = [](std::any, Instance& instance, const Value* args, int depth) {
constexpr auto host_foo = [](std::any&, Instance& instance, const Value* args, int depth) {
// Function $f will increase depth. This means each iteration goes 2 steps deeper.
EXPECT_LT(depth, CallStackLimit);
++counter;
Expand Down Expand Up @@ -921,7 +921,7 @@ TEST(execute_call, call_imported_max_depth_recursion)
const auto wasm = from_hex("0061736d010000000105016000017f020b01036d6f6403666f6f0000");

const auto module = parse(wasm);
constexpr auto host_foo = [](std::any, Instance& instance, const Value* args,
constexpr auto host_foo = [](std::any&, Instance& instance, const Value* args,
int depth) -> ExecutionResult {
if (depth == TestCallStackLimit - 1)
return Value{uint32_t{1}}; // Terminate recursion on the max depth.
Expand All @@ -946,7 +946,7 @@ TEST(execute_call, call_via_imported_max_depth_recursion)
"0061736d010000000105016000017f020b01036d6f6403666f6f0000030201000a0601040010000b");

const auto module = parse(wasm);
auto host_foo = [](std::any, Instance& instance, const Value* args,
auto host_foo = [](std::any&, Instance& instance, const Value* args,
int depth) -> ExecutionResult {
// Function $f will increase depth. This means each iteration goes 2 steps deeper.
if (depth == TestCallStackLimit - 1)
Expand Down
16 changes: 8 additions & 8 deletions test/unittests/execute_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ TEST(execute, imported_function)
const auto module = parse(wasm);
ASSERT_EQ(module->typesec.size(), 1);

constexpr auto host_foo = [](std::any, Instance&, const Value* args, int) -> ExecutionResult {
constexpr auto host_foo = [](std::any&, Instance&, const Value* args, int) -> ExecutionResult {
return Value{args[0].i32 + args[1].i32};
};

Expand All @@ -830,10 +830,10 @@ TEST(execute, imported_two_functions)
const auto module = parse(wasm);
ASSERT_EQ(module->typesec.size(), 1);

constexpr auto host_foo1 = [](std::any, Instance&, const Value* args, int) -> ExecutionResult {
constexpr auto host_foo1 = [](std::any&, Instance&, const Value* args, int) -> ExecutionResult {
return Value{args[0].i32 + args[1].i32};
};
constexpr auto host_foo2 = [](std::any, Instance&, const Value* args, int) -> ExecutionResult {
constexpr auto host_foo2 = [](std::any&, Instance&, const Value* args, int) -> ExecutionResult {
return Value{args[0].i32 * args[1].i32};
};

Expand All @@ -857,10 +857,10 @@ TEST(execute, imported_functions_and_regular_one)
"0061736d0100000001070160027f7f017f021702036d6f6404666f6f310000036d6f6404666f6f320000030201"
"000a0901070041aa80a8010b");

constexpr auto host_foo1 = [](std::any, Instance&, const Value* args, int) -> ExecutionResult {
constexpr auto host_foo1 = [](std::any&, Instance&, const Value* args, int) -> ExecutionResult {
return Value{args[0].i32 + args[1].i32};
};
constexpr auto host_foo2 = [](std::any, Instance&, const Value* args, int) -> ExecutionResult {
constexpr auto host_foo2 = [](std::any&, Instance&, const Value* args, int) -> ExecutionResult {
return Value{args[0].i32 * args[1].i32};
};

Expand All @@ -887,10 +887,10 @@ TEST(execute, imported_two_functions_different_type)
"0061736d01000000010c0260027f7f017f60017e017e021702036d6f6404666f6f310000036d6f6404666f6f32"
"0001030201010a0901070042aa80a8010b");

constexpr auto host_foo1 = [](std::any, Instance&, const Value* args, int) -> ExecutionResult {
constexpr auto host_foo1 = [](std::any&, Instance&, const Value* args, int) -> ExecutionResult {
return Value{args[0].i32 + args[1].i32};
};
constexpr auto host_foo2 = [](std::any, Instance&, const Value* args, int) -> ExecutionResult {
constexpr auto host_foo2 = [](std::any&, Instance&, const Value* args, int) -> ExecutionResult {
return Value{args[0].i64 * args[0].i64};
};

Expand All @@ -911,7 +911,7 @@ TEST(execute, imported_function_traps)
*/
const auto wasm = from_hex("0061736d0100000001070160027f7f017f020b01036d6f6403666f6f0000");

constexpr auto host_foo = [](std::any, Instance&, const Value*, int) { return Trap; };
constexpr auto host_foo = [](std::any&, Instance&, const Value*, int) { return Trap; };

const auto module = parse(wasm);
auto instance = instantiate(*module, {{{host_foo}, module->typesec[0]}});
Expand Down
10 changes: 6 additions & 4 deletions test/unittests/instantiate_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ using namespace fizzy::test;

namespace
{
ExecutionResult host_fn_1(std::any, Instance&, const Value*, int) noexcept
ExecutionResult host_fn_1(std::any&, Instance&, const Value*, int) noexcept
{
return Trap;
}

ExecutionResult host_fn_2(std::any, Instance&, const Value*, int) noexcept
ExecutionResult host_fn_2(std::any&, Instance&, const Value*, int) noexcept
{
return Trap;
}
Expand All @@ -37,8 +37,10 @@ uint32_t call_table_func(Instance& instance, size_t idx)
TEST(instantiate, check_test_host_functions)
{
Instance instance{{}, {nullptr, nullptr}, {}, {}, {nullptr, nullptr}, {}, {}, {}, {}};
EXPECT_THAT(host_fn_1(nullptr, instance, nullptr, 0), Traps());
EXPECT_THAT(host_fn_2(nullptr, instance, nullptr, 0), Traps());
std::any context1;
EXPECT_THAT(host_fn_1(context1, instance, nullptr, 0), Traps());
std::any context2;
EXPECT_THAT(host_fn_2(context2, instance, nullptr, 0), Traps());
}

TEST(instantiate, imported_functions)
Expand Down
2 changes: 1 addition & 1 deletion test/utils/fizzy_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ FuncType translate_signature(std::string_view signature)
}

fizzy::ExecutionResult env_adler32(
std::any, fizzy::Instance& instance, const fizzy::Value* args, int)
std::any&, fizzy::Instance& instance, const fizzy::Value* args, int)
{
assert(instance.memory != nullptr);
const auto ret = fizzy::test::adler32(
Expand Down
12 changes: 6 additions & 6 deletions tools/wasi/wasi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,20 @@ namespace
// and we are a single-run tool. This may change in the future and should reevaluate.
uvwasi_t state;

fizzy::ExecutionResult wasi_return_enosys(std::any, fizzy::Instance&, const fizzy::Value*, int)
fizzy::ExecutionResult wasi_return_enosys(std::any&, fizzy::Instance&, const fizzy::Value*, int)
{
return fizzy::Value{uint32_t{UVWASI_ENOSYS}};
}

fizzy::ExecutionResult wasi_proc_exit(std::any, fizzy::Instance&, const fizzy::Value* args, int)
fizzy::ExecutionResult wasi_proc_exit(std::any&, fizzy::Instance&, const fizzy::Value* args, int)
{
uvwasi_proc_exit(&state, static_cast<uvwasi_exitcode_t>(args[0].as<uint32_t>()));
// Should not reach this.
return fizzy::Trap;
}

fizzy::ExecutionResult wasi_fd_write(
std::any, fizzy::Instance& instance, const fizzy::Value* args, int)
std::any&, fizzy::Instance& instance, const fizzy::Value* args, int)
{
const auto fd = args[0].as<uint32_t>();
const auto iov_ptr = args[1].as<uint32_t>();
Expand All @@ -53,7 +53,7 @@ fizzy::ExecutionResult wasi_fd_write(
}

fizzy::ExecutionResult wasi_fd_read(
std::any, fizzy::Instance& instance, const fizzy::Value* args, int)
std::any&, fizzy::Instance& instance, const fizzy::Value* args, int)
{
const auto fd = args[0].as<uint32_t>();
const auto iov_ptr = args[1].as<uint32_t>();
Expand All @@ -75,7 +75,7 @@ fizzy::ExecutionResult wasi_fd_read(
}

fizzy::ExecutionResult wasi_fd_prestat_get(
std::any, fizzy::Instance& instance, const fizzy::Value* args, int)
std::any&, fizzy::Instance& instance, const fizzy::Value* args, int)
{
const auto fd = args[0].as<uint32_t>();
const auto prestat_ptr = args[1].as<uint32_t>();
Expand All @@ -89,7 +89,7 @@ fizzy::ExecutionResult wasi_fd_prestat_get(
}

fizzy::ExecutionResult wasi_environ_sizes_get(
std::any, fizzy::Instance& instance, const fizzy::Value* args, int)
std::any&, fizzy::Instance& instance, const fizzy::Value* args, int)
{
const auto environc = args[0].as<uint32_t>();
const auto environ_buf_size = args[1].as<uint32_t>();
Expand Down

0 comments on commit 7e78d7b

Please sign in to comment.