@@ -251,9 +251,7 @@ pub fn main() !void {
251251 // No args, no file, no :main — start REPL
252252 var env = Env .init (allocator );
253253 defer env .deinit ();
254- bootstrapFromCache (alloc , & env );
255- gc .threshold = @max (gc .bytes_allocated * 2 , gc .threshold );
256- env .gc = @ptrCast (& gc );
254+ bootstrapFromCache (alloc , & env , & gc );
257255 runRepl (alloc , & env , & gc );
258256 }
259257}
@@ -435,12 +433,7 @@ fn evalAndPrint(gc_alloc: Allocator, infra_alloc: Allocator, gc: *gc_mod.MarkSwe
435433 // bootstrap and evaluation use gc_alloc (MarkSweepGc) for Values.
436434 var env = Env .init (infra_alloc );
437435 defer env .deinit ();
438- bootstrapFromCache (gc_alloc , & env );
439-
440- // Enable GC for user evaluation (bootstrap runs without GC).
441- // Reset threshold to avoid immediate sweep on first safe point.
442- gc .threshold = @max (gc .bytes_allocated * 2 , gc .threshold );
443- env .gc = @ptrCast (gc );
436+ bootstrapFromCache (gc_alloc , & env , gc );
444437
445438 // Dump bytecode if requested (VM only, dump to stderr then exit)
446439 if (dump_bytecode ) {
@@ -486,9 +479,7 @@ fn runMainNs(gc_alloc: Allocator, infra_alloc: Allocator, gc: *gc_mod.MarkSweepG
486479 _ = use_vm ;
487480 var env = Env .init (infra_alloc );
488481 defer env .deinit ();
489- bootstrapFromCache (gc_alloc , & env );
490- gc .threshold = @max (gc .bytes_allocated * 2 , gc .threshold );
491- env .gc = @ptrCast (gc );
482+ bootstrapFromCache (gc_alloc , & env , gc );
492483
493484 // Generate and evaluate (require 'main-ns)
494485 var buf : [4096 ]u8 = undefined ;
@@ -505,7 +496,9 @@ fn runMainNs(gc_alloc: Allocator, infra_alloc: Allocator, gc: *gc_mod.MarkSweepG
505496/// Initialize env from pre-compiled bootstrap cache (D81).
506497/// Registers builtins (Zig function pointers), then restores Clojure-defined
507498/// Vars from the serialized env snapshot embedded at build time.
508- fn bootstrapFromCache (gc_alloc : Allocator , env : * Env ) void {
499+ /// Protocol/ProtocolFn values are now serialized directly in the cache,
500+ /// so no re-evaluation of protocols.clj/reducers.clj is needed.
501+ fn bootstrapFromCache (gc_alloc : Allocator , env : * Env , gc : ? * gc_mod.MarkSweepGc ) void {
509502 registry .registerBuiltins (env ) catch {
510503 std .debug .print ("Error: failed to register builtins\n " , .{});
511504 std .process .exit (1 );
@@ -515,6 +508,12 @@ fn bootstrapFromCache(gc_alloc: Allocator, env: *Env) void {
515508 std .process .exit (1 );
516509 };
517510 markBootstrapLibs ();
511+
512+ // Enable GC after cache restore for subsequent evaluation.
513+ if (gc ) | g | {
514+ g .threshold = @max (g .bytes_allocated * 2 , g .threshold );
515+ env .gc = @ptrCast (g );
516+ }
518517}
519518
520519/// Mark built-in namespaces as loaded so require skips them.
@@ -551,9 +550,7 @@ fn handleTestCommand(gc_alloc: Allocator, infra_alloc: Allocator, gc: *gc_mod.Ma
551550 // Bootstrap
552551 var env = Env .init (infra_alloc );
553552 defer env .deinit ();
554- bootstrapFromCache (gc_alloc , & env );
555- gc .threshold = @max (gc .bytes_allocated * 2 , gc .threshold );
556- env .gc = @ptrCast (gc );
553+ bootstrapFromCache (gc_alloc , & env , gc );
557554
558555 // Load cljw.edn config
559556 var config_arena = std .heap .ArenaAllocator .init (infra_alloc );
@@ -1565,15 +1562,11 @@ fn readEmbeddedSource(allocator: Allocator) ?[]const u8 {
15651562fn evalEmbedded (gc_alloc : Allocator , infra_alloc : Allocator , gc : * gc_mod.MarkSweepGc , source : []const u8 , cli_args : []const [:0 ]const u8 ) void {
15661563 var env = Env .init (infra_alloc );
15671564 defer env .deinit ();
1568- bootstrapFromCache (gc_alloc , & env );
1565+ bootstrapFromCache (gc_alloc , & env , gc );
15691566
15701567 // Set *command-line-args*
15711568 setCommandLineArgs (gc_alloc , & env , cli_args );
15721569
1573- // Enable GC
1574- gc .threshold = @max (gc .bytes_allocated * 2 , gc .threshold );
1575- env .gc = @ptrCast (gc );
1576-
15771570 // Evaluate using VM backend
15781571 _ = bootstrap .evalStringVM (gc_alloc , & env , source ) catch | e | {
15791572 reportError (e );
@@ -1591,10 +1584,7 @@ fn evalEmbedded(gc_alloc: Allocator, infra_alloc: Allocator, gc: *gc_mod.MarkSwe
15911584fn startNreplWithFile (gc_alloc : Allocator , infra_alloc : Allocator , gc : * gc_mod.MarkSweepGc , filepath : []const u8 , nrepl_port : u16 ) void {
15921585 var env = Env .init (infra_alloc );
15931586 defer env .deinit ();
1594- bootstrapFromCache (gc_alloc , & env );
1595-
1596- gc .threshold = @max (gc .bytes_allocated * 2 , gc .threshold );
1597- env .gc = @ptrCast (gc );
1587+ bootstrapFromCache (gc_alloc , & env , gc );
15981588
15991589 // Set up load paths for require resolution
16001590 const dir = std .fs .path .dirname (filepath ) orelse "." ;
@@ -1638,13 +1628,10 @@ fn startNreplWithFile(gc_alloc: Allocator, infra_alloc: Allocator, gc: *gc_mod.M
16381628fn evalEmbeddedWithNrepl (gc_alloc : Allocator , infra_alloc : Allocator , gc : * gc_mod.MarkSweepGc , source : []const u8 , cli_args : []const [:0 ]const u8 , nrepl_port : u16 ) void {
16391629 var env = Env .init (infra_alloc );
16401630 defer env .deinit ();
1641- bootstrapFromCache (gc_alloc , & env );
1631+ bootstrapFromCache (gc_alloc , & env , gc );
16421632
16431633 setCommandLineArgs (gc_alloc , & env , cli_args );
16441634
1645- gc .threshold = @max (gc .bytes_allocated * 2 , gc .threshold );
1646- env .gc = @ptrCast (gc );
1647-
16481635 // HTTP servers should run in background so nREPL can start after eval.
16491636 http_server .background_mode = true ;
16501637
@@ -1725,8 +1712,7 @@ fn handleBuildCommand(gc_alloc: Allocator, infra_alloc: Allocator, gc: *gc_mod.M
17251712 // Bootstrap runtime from cache
17261713 var env = Env .init (infra_alloc );
17271714 defer env .deinit ();
1728- bootstrapFromCache (gc_alloc , & env );
1729- _ = gc ;
1715+ bootstrapFromCache (gc_alloc , & env , gc );
17301716
17311717 // Set up load paths from entry file directory
17321718 const dir = std .fs .path .dirname (source_file .? ) orelse "." ;
@@ -1828,9 +1814,7 @@ fn handleBuildCommand(gc_alloc: Allocator, infra_alloc: Allocator, gc: *gc_mod.M
18281814fn runEmbeddedBytecode (gc_alloc : Allocator , infra_alloc : Allocator , gc : * gc_mod.MarkSweepGc , module_bytes : []const u8 ) void {
18291815 var env = Env .init (infra_alloc );
18301816 defer env .deinit ();
1831- bootstrapFromCache (gc_alloc , & env );
1832- gc .threshold = @max (gc .bytes_allocated * 2 , gc .threshold );
1833- env .gc = @ptrCast (gc );
1817+ bootstrapFromCache (gc_alloc , & env , gc );
18341818
18351819 _ = bootstrap .runBytecodeModule (gc_alloc , & env , module_bytes ) catch | e | {
18361820 reportError (e );
0 commit comments