@@ -12,6 +12,24 @@ namespace fizzy
12
12
{
13
13
// / The storage for information shared by calls in the same execution "thread".
14
14
// / Users may decide how to allocate the execution context, but some good defaults are available.
15
+ // /
16
+ // / The ExecutionContext manages WebAssembly stack space shared between calls in the same execution
17
+ // / thread. The shared stack space is allocated and managed by create_local_context() and
18
+ // / LocalContext objects.
19
+ // /
20
+ // / The shared stack space is conceptually implemented as linked list of stack space segments.
21
+ // / If the required stack space for a new call fits in the current segment no new
22
+ // / allocation is needed. Otherwise new segment is allocated. The size of the new segment is
23
+ // / at least DefaultStackSpaceSegmentSize but can be larger if the call's requires stack space
24
+ // / exceeds the default size (in this case the call occupies the segment exclusively).
25
+ // /
26
+ // / When the LocalContext which allocated new stack segment is being destroyed (i.e. when the first
27
+ // / call occupying this stack segment ends) this segment is freed. This may not be the optimal
28
+ // / strategy in case the same segment is going to be allocated multiple times.
29
+ // / There is alternative design when segments are not freed when not used any more and can be reused
30
+ // / when more stack space is needed. However, this requires additional housekeeping (e.g. having
31
+ // / forward pointer to the next segment) and handling some additional edge-cases (e.g. reallocate
32
+ // / an unused segment in case it is smaller then the required stack space).
15
33
class ExecutionContext
16
34
{
17
35
static constexpr size_t DefaultStackSpaceSegmentSize = 100 ;
@@ -21,11 +39,20 @@ class ExecutionContext
21
39
// / when going out of scope.
22
40
class [[nodiscard]] LocalContext
23
41
{
24
- ExecutionContext& m_shared_ctx; // /< Reference to the shared execution context.
42
+ // / Reference to the shared execution context.
43
+ ExecutionContext& m_shared_ctx;
25
44
26
45
public:
46
+ // / Pointer to the reserved "required" stack space.
27
47
Value* stack_space = nullptr ;
48
+
49
+ // / Pointer to the previous segment.
50
+ // / This is not null only for LocalContexts which allocated new segment.
28
51
Value* prev_stack_space_segment = nullptr ;
52
+
53
+ // / Amount of free stack space before this LocalContext has been created.
54
+ // / This is used to restore "free" space information in ExecutionContext (m_shared_ctx)
55
+ // / when this LocalContext object is destroyed.
29
56
size_t prev_free_stack_space = 0 ;
30
57
31
58
LocalContext (const LocalContext&) = delete ;
@@ -73,14 +100,25 @@ class ExecutionContext
73
100
};
74
101
75
102
public:
103
+ // / Pre-allocated first segment of the shared stack space.
76
104
Value first_stack_space_segment[DefaultStackSpaceSegmentSize];
105
+
106
+ // / Point to the current stack space segment.
77
107
Value* stack_space_segment = first_stack_space_segment;
108
+
109
+ // / Amount of free stack space remaining in the current segment.
110
+ // / It is better to keep information about "free" than "used" space
111
+ // / because then we don't need to know the current segment size.
78
112
size_t free_stack_space = DefaultStackSpaceSegmentSize;
79
113
80
- int depth = 0 ; // /< Current call depth.
114
+ // / Current call depth.
115
+ int depth = 0 ;
81
116
82
117
// / Increments the call depth and returns the local call context which
83
118
// / decrements the call depth back to the original value when going out of scope.
119
+ // / This also allocates and manages the shared stack space.
120
+ // / @param required_stack_space Size of the required stack space in bytes.
121
+ // / @see ExecutionContext
84
122
LocalContext create_local_context (size_t required_stack_space = 0 )
85
123
{
86
124
return LocalContext{*this , required_stack_space};
0 commit comments