~ chicken-core (master) 70af0feaac3d5463fc6226a8c42522edf291f5a0


commit 70af0feaac3d5463fc6226a8c42522edf291f5a0
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Thu Aug 6 14:19:59 2026 +0200
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Thu Aug 6 14:19:59 2026 +0200

    Add options for closure reuse/sharing

diff --git a/NEWS b/NEWS
index a611642b..254ee75a 100644
--- a/NEWS
+++ b/NEWS
@@ -130,6 +130,12 @@
     computed compiler and linker options.
   - Added scripts/smoke-test.sh to automate basic testing of chicken-core
 
+- Compiler
+  - Added the `-merge-reusable-closures' and `-merge-shareable-closures'
+    options that enable closure reuse and sharing to reduce memory 
+    allocations. These options are enabled automatically by optimization
+    levels 1 (reuse) and 2 (sharing), respectively.
+
 - Build system
   - A "configure" script is now used to prepare the sources for building
     everything. This simplifies the use of "make", allows more elaborate
diff --git a/batch-driver.scm b/batch-driver.scm
index 6b0e8fd2..cb134118 100644
--- a/batch-driver.scm
+++ b/batch-driver.scm
@@ -402,6 +402,10 @@
     (when (memq 'strict-types options)
       (set! strict-variable-types #t)
       (set! enable-specialization #t))
+    (when (memq 'merge-reusable-closures options)
+      (set! merge-reusable-closures #t))
+    (when (memq 'merge-shareable-closures options)
+      (set! merge-shareable-closures #t))
     (when (memq 'no-warnings options)
       (dribble "Warnings are disabled")
       (set! ##sys#warnings-enabled #f)
diff --git a/chicken.mdoc b/chicken.mdoc
index 8bdd9efe..3dfd1f50 100644
--- a/chicken.mdoc
+++ b/chicken.mdoc
@@ -198,6 +198,10 @@ Assume variable do not change their type.
 Perform additional lightweight flow-analysis pass.
 .It Fl unroll-limit Ar LIMIT
 Specifies inlining limit for self-recursive calls.
+.It Fl merge-reusable-closures
+Enables closure reuse.
+.It Fl merge-shareable-closures
+Enables closure sharing.
 .El
 .Pp
 Configuration options:
diff --git a/chicken.scm b/chicken.scm
index b78a6423..96d731b1 100644
--- a/chicken.scm
+++ b/chicken.scm
@@ -97,11 +97,13 @@
 		   ((1)
 		    (set! options
 		      (cons* 'optimize-leaf-routines
+                             'merge-reusable-closures
 			     options)) )
 		   ((2)
 		    (set! options 
 		      (cons* 'optimize-leaf-routines
 			     'inline
+                             'merge-shareable-closures
 			     'lfa2
 			     options)) ) 
 		   ((3)
@@ -110,6 +112,8 @@
 			     'inline
 			     'inline-global
 			     'local
+                             'merge-reusable-closures
+                             'merge-shareable-closures
 			     'lfa2
 			     'specialize
 			     options) ) )
@@ -119,8 +123,11 @@
 			     'inline 
 			     'inline-global
 			     'specialize
+                             'merge-reusable-closures
+                             'merge-shareable-closures
 			     'lfa2
-			     'local 'unsafe
+			     'local 
+                             'unsafe
 			     options) ) )
 		   (else
 		    (when (>= level 5)
@@ -135,6 +142,8 @@
 			       'inline
 			       'inline-global
 			       'lfa2
+                               'merge-reusable-closures
+                               'merge-shareable-closures
 			       options) ) ) ) )
 		 (loop (cdr rest)) ) )
 	      ((eq? 'debug-level o)
diff --git a/core.scm b/core.scm
index 07875f98..b3707cb2 100644
--- a/core.scm
+++ b/core.scm
@@ -308,6 +308,7 @@
      optimize-leaf-routines standalone-executable undefine-shadowed-macros
      verbose-mode local-definitions enable-specialization block-compilation
      inline-locally inline-substitutions-enabled strict-variable-types
+     merge-reusable-closures merge-shareable-closures
      static-extensions emit-link-file types-output-file
 
      ;; These are set by the (batch) driver, and read by the (c) backend
@@ -402,6 +403,8 @@
 (define target-heap-size #f)
 (define target-stack-size #f)
 (define optimize-leaf-routines #f)
+(define merge-reusable-closures #f)
+(define merge-shareable-closures #f)
 (define emit-profile #f)
 (define no-bound-checks #f)
 (define no-argc-checks #f)
@@ -3061,9 +3064,12 @@
     (gather node #f '())
     (when (pair? customizable)
       (debugging 'o "customizable procedures" customizable))
-    (debugging 'p "closure conversion merging of shareables phase...")
-    (merge-shareable node #f)
-    (merge-reusable node #f)
+    (when merge-shareable-closures
+      (debugging 'p "closure conversion merging of shareables phase...")
+      (merge-shareable node #f))
+    (when merge-reusable-closures 
+      (debugging 'p "closure conversion merging of reusables phase...")
+      (merge-reusable node #f))
     (unless (and (zero? sharing-containers)
                  (zero? sharing-users)) ;; Users should always be zero if containers is (but paranoia prevails, helps w/ debugging)
       (debugging 'o "shared closure containers" sharing-containers)
diff --git a/csc.mdoc b/csc.mdoc
index 4be84893..80b806a2 100644
--- a/csc.mdoc
+++ b/csc.mdoc
@@ -201,6 +201,10 @@ Assume variable do not change their type.
 Perform additional lightweight flow-analysis pass.
 .It Fl unroll-limit Ar LIMIT
 Specifies inlining limit for self-recursive calls.
+.It Fl merge-reusable-closures
+Enables closure reuse.
+.It Fl merge-shareable-closures
+Enables closure sharing.
 .El
 .Pp
 Configuration options:
diff --git a/csc.scm b/csc.scm
index 1c0538a6..e7882d63 100644
--- a/csc.scm
+++ b/csc.scm
@@ -152,7 +152,8 @@
     -no-argc-checks -no-bound-checks -no-procedure-checks -no-compiler-syntax
     -emit-all-import-libraries -no-elevation -module-registration -no-module-registration
     -no-procedure-checks-for-usual-bindings -regenerate-import-libraries
-    -specialize -strict-types -lfa2 -debug-info
+    -specialize -strict-types -lfa2 -debug-info -merge-reusable-closures
+    -merge-shareable-closures
     -no-procedure-checks-for-toplevel-bindings))
 
 (define-constant complex-options
@@ -427,7 +428,9 @@ Usage: #{csc} [OPTION ...] [FILENAME ...]
                                     bindings
     -strict-types                  assume variable do not change their type
     -lfa2                          perform additional lightweight flow-analysis pass
-    -unroll-limit LIMIT          specifies inlining limit for self-recursive calls
+    -unroll-limit LIMIT            specifies inlining limit for self-recursive calls
+    -merge-resuable-closures       enables closure resue
+    -merge-shareable-closures      enables closure sharing
 
   Configuration options:
 
diff --git a/manual/Using the compiler b/manual/Using the compiler
index dd8f34b3..7dd935f0 100644
--- a/manual/Using the compiler	
+++ b/manual/Using the compiler	
@@ -117,6 +117,10 @@ the source text should be read from standard input.
 ; -nursery NUMBER :
 ; -stack-size NUMBER : Sets the size of the first heap-generation of the generated executable to {{NUMBER}} bytes. The parameter may be followed by a {{M}} ({{m}}) or {{K}} ({{k}}) suffix.  The default stack-size depends on the target platform.
 
+; -merge-reusable-closures : XXX
+
+; -merge-shareable-closures : XXX
+
 ; -optimize-leaf-routines : Enable leaf routine optimization.
 
 ; -optimize-level LEVEL : Enables certain sets of optimization options. {{LEVEL}} should be an integer.
@@ -130,27 +134,27 @@ the source text should be read from standard input.
 </tr>
 <tr>
 <td>1</td>
-<td>{{-optimize-leaf-routines}}</td>
+<td>{{-optimize-leaf-routines -merge-reusable-closures -merge-shareable-closures}}</td>
 <td>Minimal optimization</td>
 </tr>
 <tr>
 <td>2 '''(Default)'''</td>
-<td>{{-optimize-leaf-routines -inline -lfa2}}</td>
+<td>{{-optimize-leaf-routines -inline -lfa2 -merge-reusable-closures -merge-shareable-closures}}</td>
 <td>Enable optimizations that do not break standard compliance</td>
 </tr>
 <tr>
 <td>3</td>
-<td>{{-optimize-leaf-routines -local -inline -lfa2 -inline-global -specialize}}</td>
+<td>{{-optimize-leaf-routines -local -inline -lfa2 -inline-global -specialize -merge-reusable-closures -merge-shareable-closures}}</td>
 <td>Maximal optimization, while still "safe"</td>
 </tr>
 <tr>
 <td>4</td>
-<td>{{-optimize-leaf-routines -local -inline -lfa2 -inline-global -specialize -unsafe}}</td>
+<td>{{-optimize-leaf-routines -local -inline -lfa2 -inline-global -specialize -unsafe -merge-reusable-closures -merge-shareable-closures}}</td>
 <td>Maximal optimization, "unsafe"</td>
 </tr>
 <tr>
 <td>5 (or higher)</td>
-<td>{{-optimize-leaf-routines -block -inline -lfa2 -inline-global -specialize -unsafe -disable-interrupts -no-trace -no-lambda-info}}</td>
+<td>{{-optimize-leaf-routines -block -inline -lfa2 -inline-global -specialize -unsafe -disable-interrupts -no-trace -no-lambda-info -merge-reusable-closures -merge-shareable-closures}}</td>
 <td>All possible optimizations, "unsafe"</td>
 </tr>
 </table>
diff --git a/support.scm b/support.scm
index 2f55d02f..41d87e22 100644
--- a/support.scm
+++ b/support.scm
@@ -1855,6 +1855,8 @@ Usage: chicken FILENAME [OPTION ...]
     -strict-types                assume variable do not change their type
     -lfa2                        perform additional lightweight flow-analysis pass
     -unroll-limit LIMIT          specifies inlining limit for self-recursive calls
+    -merge-resuable-closures     enables closure resue
+    -merge-shareable-closures    enables closure sharing
 
   Configuration options:
 
Trap