diff --git a/lib/fizzy/CMakeLists.txt b/lib/fizzy/CMakeLists.txt index c25f92408..d70e1698a 100644 --- a/lib/fizzy/CMakeLists.txt +++ b/lib/fizzy/CMakeLists.txt @@ -21,6 +21,7 @@ target_sources( exceptions.hpp execute.cpp execute.hpp + execution_context.hpp instantiate.cpp instantiate.hpp instructions.cpp diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index 577207e92..447ff8650 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -537,7 +537,6 @@ inline bool invoke_function(const FuncType& func_type, uint32_t func_idx, Instan assert(stack.size() >= num_args); const auto call_args = stack.rend() - num_args; - const auto ctx_guard = ctx.increment_call_depth(); const auto ret = execute(instance, func_idx, call_args, ctx); // Bubble up traps if (ret.trapped) @@ -574,6 +573,8 @@ ExecutionResult execute( const auto& code = instance.module->get_code(func_idx); auto* const memory = instance.memory.get(); + const auto local_ctx = ctx.create_local_context(); + OperandStack stack(args, func_type.inputs.size(), code.local_count, static_cast(code.max_stack_height)); diff --git a/lib/fizzy/execute.hpp b/lib/fizzy/execute.hpp index 959cf68e0..680f513c8 100644 --- a/lib/fizzy/execute.hpp +++ b/lib/fizzy/execute.hpp @@ -6,6 +6,7 @@ #include "cxx20/span.hpp" #include "exceptions.hpp" +#include "execution_context.hpp" #include "instantiate.hpp" #include "limits.hpp" #include "module.hpp" @@ -41,33 +42,6 @@ constexpr ExecutionResult Void{true}; /// Shortcut for execution that resulted in a trap. constexpr ExecutionResult Trap{false}; -/// The storage for information shared by calls in the same execution "thread". -/// Users may decide how to allocate the execution context, but some good defaults are available. -class ExecutionContext -{ - /// Call depth increment guard. - /// It will automatically decrement the call depth to the original value - /// when going out of scope. - class [[nodiscard]] Guard - { - ExecutionContext& m_execution_context; ///< Reference to the guarded execution context. - - public: - explicit Guard(ExecutionContext& ctx) noexcept : m_execution_context{ctx} {} - ~Guard() noexcept { --m_execution_context.depth; } - }; - -public: - int depth = 0; ///< Current call depth. - - /// Increments the call depth and returns the guard object which decrements - /// the call depth back to the original value when going out of scope. - Guard increment_call_depth() noexcept - { - ++depth; - return Guard{*this}; - } -}; /// Execute a function from an instance. /// diff --git a/lib/fizzy/execution_context.hpp b/lib/fizzy/execution_context.hpp new file mode 100644 index 000000000..0b9be912d --- /dev/null +++ b/lib/fizzy/execution_context.hpp @@ -0,0 +1,41 @@ +// Fizzy: A fast WebAssembly interpreter +// Copyright 2021 The Fizzy Authors. +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +namespace fizzy +{ +/// The storage for information shared by calls in the same execution "thread". +/// Users may decide how to allocate the execution context, but some good defaults are available. +class ExecutionContext +{ + /// Call local execution context. + /// It will automatically decrement the call depth to the original value + /// when going out of scope. + class [[nodiscard]] LocalContext + { + ExecutionContext& m_shared_ctx; ///< Reference to the shared execution context. + + public: + LocalContext(const LocalContext&) = delete; + LocalContext(LocalContext&&) = delete; + LocalContext& operator=(const LocalContext&) = delete; + LocalContext& operator=(LocalContext&&) = delete; + + explicit LocalContext(ExecutionContext& ctx) noexcept : m_shared_ctx{ctx} + { + ++m_shared_ctx.depth; + } + + ~LocalContext() noexcept { --m_shared_ctx.depth; } + }; + +public: + int depth = 0; ///< Current call depth. + + /// Increments the call depth and returns the local call context which + /// decrements the call depth back to the original value when going out of scope. + LocalContext create_local_context() noexcept { return LocalContext{*this}; } +}; +} // namespace fizzy diff --git a/test/unittests/execute_call_depth_test.cpp b/test/unittests/execute_call_depth_test.cpp index aa59a4937..1558bf674 100644 --- a/test/unittests/execute_call_depth_test.cpp +++ b/test/unittests/execute_call_depth_test.cpp @@ -213,7 +213,7 @@ TEST(execute_call_depth, call_host_function_calling_wasm_function_inclusive) constexpr auto host_f = [](std::any&, Instance& instance, const Value*, ExecutionContext& ctx) noexcept { recorded_depth = ctx.depth; - const auto ctx_guard = ctx.increment_call_depth(); + const auto local_ctx = ctx.create_local_context(); return fizzy::execute(instance, 2 /* $leaf */, {}, ctx); }; @@ -304,7 +304,7 @@ TEST(execute_call_depth, call_host_function_calling_another_wasm_module) ExecutionContext& ctx) noexcept { recorded_depth = ctx.depth; auto instance = *std::any_cast(&host_context); - const auto ctx_guard = ctx.increment_call_depth(); + const auto local_ctx = ctx.create_local_context(); return fizzy::execute(*instance, 0, {}, ctx); }; @@ -466,7 +466,7 @@ TEST(execute_call_depth, execute_host_function_within_wasm_recursion_limit) constexpr auto host_f = [](std::any&, Instance& instance, const Value*, ExecutionContext& ctx) noexcept { max_recorded_wasm_recursion_depth = std::max(max_recorded_wasm_recursion_depth, ctx.depth); - const auto ctx_guard = ctx.increment_call_depth(); + const auto local_ctx = ctx.create_local_context(); return fizzy::execute(instance, 0, {}, ctx); }; @@ -537,7 +537,7 @@ TEST(execute_call, call_host_function_calling_wasm_interleaved_infinite_recursio ExecutionContext& ctx) noexcept { EXPECT_LT(ctx.depth, DepthLimit); ++counter; - const auto ctx_guard = ctx.increment_call_depth(); + const auto local_ctx = ctx.create_local_context(); return fizzy::execute(instance, 1, {}, ctx); };