Skip to content

Commit

Permalink
Add ExecutionContext documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Apr 14, 2021
1 parent 0e1b315 commit 31f44e0
Showing 1 changed file with 40 additions and 2 deletions.
42 changes: 40 additions & 2 deletions lib/fizzy/execution_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,24 @@ 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.
///
/// The ExecutionContext manages WebAssembly stack space shared between calls in the same execution
/// thread. The shared stack space is allocated and managed by create_local_context() and
/// LocalContext objects.
///
/// The shared stack space is conceptually implemented as linked list of stack space segments.
/// If the required stack space for a new call fits in the current segment no new
/// allocation is needed. Otherwise new segment is allocated. The size of the new segment is
/// at least DefaultStackSpaceSegmentSize but can be larger if the call's requires stack space
/// exceeds the default size (in this case the call occupies the segment exclusively).
///
/// When the LocalContext which allocated new stack segment is being destroyed (i.e. when the first
/// call occupying this stack segment ends) this segment is freed. This may not be the optimal
/// strategy in case the same segment is going to be allocated multiple times.
/// There is alternative design when segments are not freed when not used any more and can be reused
/// when more stack space is needed. However, this requires additional housekeeping (e.g. having
/// forward pointer to the next segment) and handling some additional edge-cases (e.g. reallocate
/// an unused segment in case it is smaller then the required stack space).
class ExecutionContext
{
static constexpr size_t DefaultStackSpaceSegmentSize = 100;
Expand All @@ -21,11 +39,20 @@ class ExecutionContext
/// when going out of scope.
class [[nodiscard]] LocalContext
{
ExecutionContext& m_shared_ctx; ///< Reference to the shared execution context.
/// Reference to the shared execution context.
ExecutionContext& m_shared_ctx;

public:
/// Pointer to the reserved "required" stack space.
Value* stack_space = nullptr;

/// Pointer to the previous segment.
/// This is not null only for LocalContexts which allocated new segment.
Value* prev_stack_space_segment = nullptr;

/// Amount of free stack space before this LocalContext has been created.
/// This is used to restore "free" space information in ExecutionContext (m_shared_ctx)
/// when this LocalContext object is destroyed.
size_t prev_free_stack_space = 0;

LocalContext(const LocalContext&) = delete;
Expand Down Expand Up @@ -73,14 +100,25 @@ class ExecutionContext
};

public:
/// Pre-allocated first segment of the shared stack space.
Value first_stack_space_segment[DefaultStackSpaceSegmentSize];

/// Point to the current stack space segment.
Value* stack_space_segment = first_stack_space_segment;

/// Amount of free stack space remaining in the current segment.
/// It is better to keep information about "free" than "used" space
/// because then we don't need to know the current segment size.
size_t free_stack_space = DefaultStackSpaceSegmentSize;

int depth = 0; ///< Current call depth.
/// Current call depth.
int depth = 0;

/// 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.
/// This also allocates and manages the shared stack space.
/// @param required_stack_space Size of the required stack space in bytes.
/// @see ExecutionContext
LocalContext create_local_context(size_t required_stack_space = 0)
{
return LocalContext{*this, required_stack_space};
Expand Down

0 comments on commit 31f44e0

Please sign in to comment.