@@ -183,11 +183,6 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
183183 // Used in debug mode to assert that we only have one executor at a time
184184 has_executor : if (builtin.mode == .Debug ) bool else void = if (builtin .mode == .Debug ) false else {},
185185
186- // See the Executor's call_arena and scope_arena allocators. Having these
187- // here allows the arena to be re-used by different executors.
188- call_arena : ArenaAllocator ,
189- scope_arena : ArenaAllocator ,
190-
191186 const Self = @This ();
192187
193188 const State = S ;
@@ -223,8 +218,6 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
223218 .gc_hints = opts .gc_hints ,
224219 .global_scope = global_scope ,
225220 .prototype_lookup = undefined ,
226- .call_arena = ArenaAllocator .init (allocator ),
227- .scope_arena = ArenaAllocator .init (allocator ),
228221 .executor_pool = std .heap .MemoryPool (Executor ).init (allocator ),
229222 };
230223
@@ -260,8 +253,6 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
260253 }
261254
262255 pub fn deinit (self : * Self ) void {
263- self .call_arena .deinit ();
264- self .scope_arena .deinit ();
265256 self .global_scope .deinit ();
266257 self .isolate .exit ();
267258 self .isolate .deinit ();
@@ -357,14 +348,22 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
357348 .isolate = isolate ,
358349 .templates = templates ,
359350 .handle_scope = handle_scope ,
360- .call_arena = self .call_arena .allocator (),
361- .scope_arena = self .scope_arena .allocator (),
351+ .call_arena = undefined ,
352+ .scope_arena = undefined ,
353+ ._call_arena_instance = std .heap .ArenaAllocator .init (self .allocator ),
354+ ._scope_arena_instance = std .heap .ArenaAllocator .init (self .allocator ),
362355 .module_loader = .{
363356 .ptr = @ptrCast (module_loader ),
364357 .func = @TypeOf (module_loader .* ).fetchModuleSource ,
365358 },
366359 };
367360
361+ // We do it this way, just to present a slightly nicer API. Many
362+ // things want one of these two allocator from the executor. Now they
363+ // can do `executor.call_arena` instead of `executor.call_arena.allocator`.
364+ executor .call_arena = executor ._call_arena_instance .allocator ();
365+ executor .scope_arena = executor ._scope_arena_instance .allocator ();
366+
368367 errdefer self .stopExecutor (executor );
369368
370369 // Custom exception
@@ -397,8 +396,6 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
397396 std .debug .assert (self .has_executor == true );
398397 self .has_executor = false ;
399398 }
400- _ = self .call_arena .reset (.{ .retain_with_limit = CALL_ARENA_RETAIN });
401- _ = self .scope_arena .reset (.{ .retain_with_limit = SCOPE_ARENA_RETAIN });
402399 }
403400
404401 // Give it a Zig struct, get back a v8.FunctionTemplate.
@@ -791,13 +788,15 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
791788 // arena itself is owned by the Executor so that we can re-use it
792789 // from scope to scope.
793790 call_arena : Allocator ,
791+ _call_arena_instance : std.heap.ArenaAllocator ,
794792
795793 // Arena whose lifetime is for a single page load, aka a Scope. Where
796794 // the call_arena lives for a single function call, the scope_arena
797795 // lives for the lifetime of the entire page. The allocator will be
798796 // owned by the Scope, but the arena itself is owned by the Executor
799797 // so that we can re-use it from scope to scope.
800798 scope_arena : Allocator ,
799+ _scope_arena_instance : std.heap.ArenaAllocator ,
801800
802801 // When we need to load a resource (i.e. an external script), we call
803802 // this function to get the source. This is always a reference to the
@@ -825,6 +824,9 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
825824 }
826825 self .context .exit ();
827826 self .handle_scope .deinit ();
827+
828+ self ._call_arena_instance .deinit ();
829+ self ._scope_arena_instance .deinit ();
828830 }
829831
830832 // Executes the src
@@ -925,8 +927,7 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
925927 pub fn endScope (self : * Executor ) void {
926928 self .scope .? .deinit ();
927929 self .scope = null ;
928- const scope_arena : * std.heap.ArenaAllocator = @ptrCast (@alignCast (self .scope_arena .ptr ));
929- _ = scope_arena .reset (.{ .retain_with_limit = SCOPE_ARENA_RETAIN });
930+ _ = self ._scope_arena_instance .reset (.{ .retain_with_limit = SCOPE_ARENA_RETAIN });
930931 }
931932
932933 // Given an anytype, turns it into a v8.Object. The anytype could be:
@@ -1540,8 +1541,9 @@ fn Caller(comptime E: type) type {
15401541 }
15411542
15421543 fn deinit (self : * Self ) void {
1543- const call_depth = self .executor .call_depth - 1 ;
1544- self .executor .call_depth = call_depth ;
1544+ const executor = self .executor ;
1545+ const call_depth = executor .call_depth - 1 ;
1546+ executor .call_depth = call_depth ;
15451547
15461548 // Because of callbacks, calls can be nested. Because of this, we
15471549 // can't clear the call_arena after _every_ call. Imagine we have
@@ -1555,8 +1557,7 @@ fn Caller(comptime E: type) type {
15551557 // Therefore, we keep a call_depth, and only reset the call_arena
15561558 // when a top-level (call_depth == 0) function ends.
15571559 if (call_depth == 0 ) {
1558- const call_arena : * std.heap.ArenaAllocator = @ptrCast (@alignCast (self .call_arena .ptr ));
1559- _ = call_arena .reset (.{ .retain_with_limit = CALL_ARENA_RETAIN });
1560+ _ = executor ._call_arena_instance .reset (.{ .retain_with_limit = CALL_ARENA_RETAIN });
15601561 }
15611562 }
15621563
0 commit comments