~ 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