1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-05 19:50:23 +02:00
Commit graph

21828 commits

Author SHA1 Message Date
Andy Wingo
134c3be452 Add ephemeron tables
* libguile/ephemerons.h:
* libguile/ephemerons.c (scm_c_make_ephemeron):
(scm_c_ephemeron_key):
(scm_c_ephemeron_value):
(scm_c_ephemeron_mark_dead_x):
(scm_c_ephemeron_swap_x):
(scm_c_ephemeron_next): Add C ephemeron API.
(scm_make_ephemeron, scm_ephemeron_key, scm_ephemeron_value)
(scm_ephemeron_mark_dead_x): Dispatch to helpers above.
(scm_ephemeron_swap_x, scm_ephemeron_mark_dead_x): New Scheme-exposed
functions.
(scm_c_make_ephemeron_table):
(scm_c_ephemeron_table_length):
(scm_c_ephemeron_table_ref):
(scm_c_ephemeron_table_push_x):
(scm_c_ephemeron_table_try_push_x): New C API for tables of ephemerons.
(scm_ephemeron_table_length):
(scm_ephemeron_table_ref):
(scm_ephemeron_table_push_x):
(scm_ephemeron_table_try_push_x): New Scheme-exposed API.
(scm_c_ephemeron_hash_table_refq):
(scm_c_ephemeron_hash_table_setq_x):
(scm_c_ephemeron_hash_table_copy): New C API for use by internal weak
table users (dynamic states, etc).

* module/ice-9/ephemerons.scm: Add new Scheme API.

* libguile/evalext.c (scm_self_evaluating_p):
* libguile/goops.c (scm_class_of, %goops-early-init):
* libguile/print.c (iprin1):
* module/oop/goops.scm:
* libguile/scm.h (scm_tc7_ephemeron_table): Add new tc7 for ephemeron
tables.

* test-suite/tests/ephemerons.test ("ephemeron tables"): Add tests.
2025-05-12 13:45:21 +02:00
Andy Wingo
67dca3a1f5 Move weak tables out to a module
* module/ice-9/weak-tables.scm: New file.

* am/bootstrap.am (SOURCES): Wire it up.
* module/ice-9/deprecated.scm: Add deprecation shims.
* libguile/init.c (scm_i_init_guile): Don't add weak bindings to default
module.
* libguile/weak-table.h:
* libguile/weak-table.c (scm_init_weak_tables):
(scm_weak_table_prehistory): Arrange to load bindings from the weaks
module.
* module/ice-9/hcons.scm:
* module/ice-9/object-properties.scm:
* module/ice-9/poe.scm:
* module/ice-9/popen.scm:
* module/ice-9/sandbox.scm:
* module/language/ecmascript/function.scm:
* module/oop/goops/save.scm:
* module/srfi/srfi-18.scm:
* module/srfi/srfi-69.scm:
* module/system/foreign.scm:
* test-suite/tests/gc.test:
* test-suite/tests/hash.test:
* test-suite/tests/types.test:
* test-suite/tests/weaks.test: Adapt to use the new module.
2025-05-12 13:45:07 +02:00
Andy Wingo
3a9c0939a0 Move make-object-property out to a module
This will allow for weak tables to be implemented partly in Scheme.

* module/ice-9/object-properties.scm: New file.

* am/bootstrap.am (SOURCES): Add new file.

* module/ice-9/boot-9.scm:
* module/ice-9/deprecated.scm (make-object-property*): Deprecate
make-object-property in default env and add a shim.

* module/ice-9/buffered-input.scm (ice-9):
* module/language/elisp/boot.el (plist-function):
* module/scripts/frisk.scm (scripts):
* module/web/http.scm (web): Adapt users to import the new module.
2025-05-12 13:45:07 +02:00
Andy Wingo
1f96d1bf4b Move to store thread join cond/lock/results directly
* libguile/threads.h: Add join data directly on the thread instead of
using a Scheme-side weak table.  It's less complicated and it will let
the weak table implementation use locks in Scheme; otherwise you would
have threads depending on weak tables and vice versa.
* libguile/threads.c (scm_trace_thread, guilify_self_1): Init and mark
the new members.
(thread_join_cond, thread_join_lock, thread_join_results)
(thread_init_joinable_x, thread_set_join_results_x): New accessors.
* module/ice-9/threads.scm (call-with-new-thread, join-thread): Use the
new accessors.
2025-05-12 13:45:07 +02:00
Andy Wingo
852c0b05c7 Remove module weak observers
If that's what you want, you need to bring your own weak hash table on a
normal observer.

* module/ice-9/boot-9.scm (module): Remove weak-observers field.
(make-module, make-autoload-interface): Don't pass weak table to
constructor.
(module-observe-weak): Remove.
(module-unobserve, module-call-observers): Remove weak case.
* module/ice-9/deprecated.scm (module-observe-weak): Dispatch to
module-observe.
* test-suite/tests/modules.test ("observers"): Adapt.
2025-05-12 13:45:07 +02:00
Andy Wingo
57f0ce914a Merge remote-tracking branch 'whippet/main' into HEAD 2025-05-12 13:39:27 +02:00
Andy Wingo
cc2a90b494 bdw: Fix detection of objects on free-lists
I am not sure about ephemerons and finalizers, though.
2025-05-12 13:38:49 +02:00
Andy Wingo
d4fd1f3486 Merge remote-tracking branch 'whippet/main' into HEAD 2025-05-12 11:55:04 +02:00
Andy Wingo
3440bb864d bdw: Use BDW lock instead of gc_heap lock; clear dead mutators
This will protect traversal of the mutator list during marking.  Also,
clear dead mutators, so that if they are still reachable, they won't be marked.
2025-05-12 11:52:51 +02:00
Andy Wingo
a5c69fb920 Add try-push, swap-value API to ephemerons
The former allows for knowing whether a push succeeded or not, which is
useful for concurrent hash tables.  The latter makes ephemerons mutable,
if the embedder wants to use them that way.
2025-05-09 09:56:17 +02:00
Andy Wingo
c63f9101f8 Reimplement weak vectors in Scheme using ephemerons
* module/ice-9/weak-vector.scm: New implementation, same interface.

* doc/ref/api-memory.texi (Weak vectors): Default weak vector value was
documented as empty list when it was actually unspecified, but #f is
most useful, so we change documentation and code to match.

* libguile/Makefile.am (libguile_@GUILE_EFFECTIVE_VERSION@_la_SOURCES):
(DOT_X_FILES):
(DOT_DOC_FILES):
(noinst_HEADERS):
(modinclude_HEADERS):
* libguile.h:
* libguile/deprecated.c:
* libguile/deprecated.h:
* libguile/init.c:
* libguile/weak-vector.c:
* libguile/weak-vector.h: Remove C weak vector implementation, replaced
with deprecation stubs that call out to Scheme.

* libguile/weak-set.c:
* libguile/weak-table.c:
* libguile/weak-list.h: Remove unused internal header.

* libguile/eq.c:
* libguile/evalext.c:
* libguile/goops.c:
* libguile/hash.c:
* libguile/scm.h:
* module/system/base/types.scm:
* module/system/base/types/internal.scm:
* module/system/vm/assembler.scm: Remove wvect tc7.
2025-05-05 16:29:24 +02:00
Andy Wingo
96589bd303 Remove all deprecated code from Scheme files
* module/ice-9/boot-9.scm(symbol-property, set-symbol-property!)
(symbol-property-remove!): Remove.
* module/ice-9/boot-9.scm (make-record-type): Name must be symbol.
(record-constructor): Alias record-type-constructor.
(make-module): Require size to be zero.  Should fix this with keyword
args :/
(try-load-module): Inline definition of try-module-autoload.  Remove
try-module-autoload binding.
(make-soft-port): Add deprecation warning, so we can remove it
eventually.
* module/ice-9/save-stack.scm: Remove deprecation comment.
* module/ice-9/top-repl.scm:
* module/ice-9/threads.scm: Export instead of replace bindings.
* module/language/bytecode.scm: Remove instruction-arity et al.
* module/language/tree-il/analyze.scm: Remove deprecated
unbound-variable-analysis and macro-use-before-definition-analysis.
* module/rnrs.scm: Fix syntax-case export now that module and value
namespaces are separate.
* module/system/base/language.scm (invalidate-compilation-cache!):
Remove.
* module/system/base/language.scm (*current-language*): Remove.
2025-05-05 12:33:37 +02:00
Andy Wingo
4c2a8c1dd3 Update tests to use new soft ports interface.
* test-suite/tests/r6rs-ports.test:
* test-suite/tests/web-client.test:
* test-suite/tests/ports.test ("pending EOF behavior"):
("unicode byte-order marks (BOMs)"): Use new soft ports.
2025-05-05 12:33:28 +02:00
Andy Wingo
c1caabaa24 Add ephemeron objects
* module/ice-9/ephemerons.scm:
* libguile/ephemerons.c:
* libguile/ephemerons.h:
* test-suite/tests/ephemerons.test: New files.

* am/bootstrap.am (SOURCES):
* test-suite/Makefile.am (SCM_TESTS):
* libguile/Makefile.am (libguile_@GUILE_EFFECTIVE_VERSION@_la_SOURCES):
(DOT_X_FILES, DOT_DOC_FILES, noinst_HEADERS):  Wire ephemerons into build.

* libguile/scm.h (scm_tc7_ephemeron): New tc7.

* module/oop/goops.scm (<ephemeron>):
* module/system/base/types/internal.scm (heap-tags):
* module/system/vm/assembler.scm (system):
* libguile/evalext.c (scm_self_evaluating_p):
* libguile/goops.c (scm_class_of):
* libguile/init.c (scm_i_init_guile):
* libguile/print.c (iprin1): Add cases for new tc7.
2025-05-05 11:04:44 +02:00
Andy Wingo
e6f550697f Merge remote-tracking branch 'whippet/main' into wip-whippet 2025-05-05 10:43:27 +02:00
Andy Wingo
c86408a33c Fix ephemeron death for bdw
* src/bdw.c (gc_ephemeron_init): Fix misuse of disappearing-link API.
2025-05-05 10:42:28 +02:00
Andy Wingo
4c76332570 guardians: speed up atomic fifo
* module/ice-9/guardians.scm (make-atomic-fifo): Instead of transferring
the last element to the outbox, just return it.
2025-05-04 20:54:15 +02:00
Andy Wingo
8b46c321e5 Add finalizers at the guardian priority
This doesn't do anything yet for BDW.

* module/ice-9/guardians.scm (make-guardian): Fix add-finalizer!
invocation.
2025-05-04 20:51:05 +02:00
Andy Wingo
95856446f5 Trim (ice-9 guardians) module use list
* module/ice-9/guardians.scm: Remove useless include.
2025-05-04 20:49:44 +02:00
Andy Wingo
66f9815c3f Reimplement guardians in Scheme
Also, shunt them off to a module, and deprecate the C interface.

* module/ice-9/guardians.scm: New file.
* am/bootstrap.am (SOURCES): Add new file.

* libguile.h: Remove guardians.h include.
* libguile/Makefile.am (libguile_@GUILE_EFFECTIVE_VERSION@_la_SOURCES):
(DOT_X_FILES):
(DOT_DOC_FILES):
(modinclude_HEADERS): Remove guardians.[ch] files.
* libguile/init.c (scm_i_init_guile): Remove guardians.

* libguile/deprecated.h:
* libguile/deprecated.c (scm_make_guardian): Deprecate.
* module/ice-9/deprecated.scm: Add make-guardian shim.

* module/oop/goops.scm (<guardian>): Remove class; they no longer have a
tc16.

* module/ice-9/popen.scm: Add guardians module.
* test-suite/tests/eval.test:
* test-suite/tests/fluids.test:
* test-suite/tests/gc.test:
* test-suite/tests/guardians.test:
* test-suite/tests/threads.test:
* test-suite/tests/types.test: Use the guardians module.
2025-05-04 20:41:16 +02:00
Andy Wingo
b1d7d3538a SCM_GC_MALLOC avoids BDW API
* libguile/gc.h (SCM_GC_MALLOC, SCM_GC_MALLOC_POINTERLESS): Always
redirect to scm_gc_malloc{,_pointerless}.  Don't include bdw-gc.h.
* libguile/gc-malloc.c (scm_realloc): Use Whippet gc_collect API.
* libguile/loader.c:
* libguile/scmsigs.c:
* libguile/weak-vector.c: Include bdw-gc.
2025-05-04 15:58:50 +02:00
Andy Wingo
fcf8fa3d10 Reimplement scm_is_mutable_pair using gc_heap_contains
* libguile/pairs.c (scm_to_ref): Copy this stub around again; we should
fix this...
(scm_is_mutable_pair): Use gc_heap_contains.
2025-05-04 15:15:41 +02:00
Andy Wingo
fd921be76c Merge remote-tracking branch 'whippet/main' into wip-whippet 2025-05-04 12:11:13 +02:00
Andy Wingo
c7fe77de0e Add gc_heap_contains API 2025-05-04 12:10:03 +02:00
Andy Wingo
8cb15a9e1b More refactors off BDW API
* libguile/gc.c (gc): Use Guile finalization API, not BDW.
* libguile/threads.c (guilify_self_2): Don't finalize here.
2025-05-04 10:01:50 +02:00
Andy Wingo
17ca7a928e Don't run finalizers until Guile is initialized
Prevents a problem where with-exception-handler isn't defined yet by the
time the first finalizer gets kicked off (it's a file port, probably one
that is closed already...)

* libguile/finalizers.h:
* libguile/init.c (scm_i_init_guile):
* libguile/finalizers.c (queue_finalizer_async): Mark maybe-unused.
(scm_init_finalizers): Rework to only enable notification when Guile is
finished initializing.
2025-05-04 09:12:52 +02:00
Andy Wingo
4f8d4e6c34 Rework finalizers implementation to use Whippet API
* libguile/finalizers.c (ref_to_scm, scm_to_ref): New helpers.
(add_finalizer): New helper; returns the finalizer object.
(add_builtin_finalizer): New helper for structs, smobs, ports.
(scm_i_add_struct_finalizer):
(scm_i_add_smob_finalizer):
(scm_i_add_port_finalizer):
(scm_i_add_pointer_finalizer):
(scm_i_add_finalizer): Use new helpers.
(scm_i_add_guardian_finalizer): New helper.
(run_finalizer, run_finalizers, scm_run_finalizers): Reimplement.
(%add-finalizer!): Use new helpers.
(queue_finalizer_async):
(notify_finalizers_to_run):
(start_finalization_thread):
(spawn_finalizer_thread):
(scm_i_finalizer_pre_fork):
(scm_set_automatic_finalization_enabled):
(scm_init_finalizers):
(scm_init_finalizer_thread): Use Whippet API.
* libguile/finalizers.h (scm_i_set_finalizer, scm_i_add_resuscitator):
Remove.
2025-05-02 17:06:55 +02:00
Andy Wingo
3a6be6457d Rework pointer implementation to avoid weak tables
Instead of storing keep-alive edges in weak tables, just add extra
fields on pointer objects.

* libguile/foreign.c (make_pointer, pointer_extra_word_count)
(set_pointer_extra_word, make_pointer_0, make_pointer_1, make_pointer_3)
(attach_finalizer): New helpers.
(scm_make_pointer): Never attach finalizers on the null pointer object.
(scm_from_pointer): Likewise.
(scm_bytevector_to_pointer, scm_procedure_to_pointer): Store keep-alive
links in extra words.
(scm_init_foreign, scm_register_foreign): Rework init for null, free,
and ffi_closure_free pointers.
2025-05-02 17:02:11 +02:00
Andy Wingo
67c572ba6c Move pointers to new finalization API
* libguile/finalizers.h:
* libguile/finalizers.c (pointer_finalizer_trampoline)
(scm_i_add_pointer_finalizer): New helpers.
* libguile/foreign.c (scm_i_finalize_pointer, scm_from_pointer)
(scm_set_pointer_finalizer_x): Use new API.
2025-05-02 16:45:41 +02:00
Andy Wingo
43903ba138 Move ports towards new finalization API
* libguile/finalizers.h:
* libguile/finalizers.c (port_finalizer_trampoline):
(scm_i_add_port_finalizer): New functions.

* libguile/ports.c (scm_i_finalize_port): New helper.
(scm_c_make_port_with_encoding):
(prepare_iconv_descriptors): Call scm_i_add_port_finalizer.
2025-05-02 16:30:01 +02:00
Andy Wingo
cf25a94745 Add tc7 for finalizer objects
Whippet will need this.

* libguile/scm.h (scm_tc7_finalizer): Reserve.
* libguile/evalext.c (scm_self_evaluating_p): Add finalizer case.
* libguile/print.c (iprin1):
* libguile/finalizers.h:
* libguile/finalizers.c (scm_i_print_finalizer): Arrange to print
finalizers.
* module/oop/goops.scm (<finalizer>):
* libguile/goops.c (class_finalizer, scm_class_of)
(scm_sys_goops_early_init): Wire up support for <finalizer>.
* module/system/base/types/internal.scm (heap-tags): Add finalizers.
* module/system/vm/assembler.scm (system): Add emit-finalizer?.
2025-05-02 16:26:17 +02:00
Andy Wingo
532df66e07 Refactor to how struct and smob finalization works
* libguile/finalizers.h:
* libguile/finalizers.c (scm_i_add_struct_finalizer):
(scm_i_add_smob_finalizer): New internal API.
* libguile/smob.c (scm_i_new_smob):
(scm_i_new_double_smob):
* libguile/struct.c (scm_i_alloc_struct): Use it.
2025-05-02 16:16:57 +02:00
Andy Wingo
6ffddf5dae Remove scm_i_register_async_gc_callback
* libguile/finalizers.h:
* libguile/finalizers.c (async_gc_finalizer):
(scm_i_register_async_gc_callback): Remove.
2025-05-02 16:06:09 +02:00
Andy Wingo
75c7f79abc Add (system finalizers)
This will replace an internal interface in (system foreign-objects).

* module/system/finalizers.scm: New file.
* am/bootstrap.am (SOURCES): Add new file.
* libguile/foreign-object.h:
* libguile/foreign-object.c (invoke_finalizer):
(sys_add_finalizer_x):
(scm_init_foreign_object):
(scm_register_foreign_object): Remove.
* libguile/init.c (scm_i_init_guile): Register finalizers instead of
foreign-object.
* module/system/foreign-object.scm (allocate-instance): Use finalizers
module.
* libguile/finalizers.c (invoke_finalizer):
(scm_sys_add_finalizer): New helper.
2025-05-02 16:03:13 +02:00
Andy Wingo
604a8e8540 Weak sets and tables no longer vacuum after GC
These tables will be implemented differently after Whippet.

* libguile/weak-set.c (do_vacuum_weak_set, vacuum_all_weak_sets):
Remove.
(scm_c_make_weak_set, scm_init_weak_set): Don't keep a table of all weak
sets.
* libguile/weak-table.c (do_vacuum_weak_table, vacuum_all_weak_tables):
Remove.
(scm_c_make_weak_table, scm_init_weak_table): No table of all tables.
2025-05-02 15:50:49 +02:00
Andy Wingo
9774b3e551 Prepare structs for new finalization API
* libguile/struct.h:
* libguile/struct.c (scm_i_finalize_struct): New helper.
(struct_finalizer_trampoline): Implement as shim.
2025-05-02 15:50:49 +02:00
Andy Wingo
5e97645b81 Prepare SMOBs for new finalization API
* libguile/atomics-internal.h (scm_atomic_set_bits): New routine.
* libguile/smob.c (scm_i_finalize_smob): Use atomics to clear the first
word instead of the GC alloc lock.
(finalize_smob): Implement as shim.
2025-05-02 15:50:49 +02:00
Andy Wingo
1a3f427d4e Remove all deprecated interfaces
We're on a new version series, let's remove deprecated things.  Also
reduces the amount of work we need to do in adapting to a new GC,
notably for bignums.

* configure.ac (--disable-tmpnam): Remove flag, tmpnam is gone.
* doc/ref/posix.texi (File System): Remove tmpnam docs.
* libguile/bitvectors.c (scm_bitvector_to_list): Remove deprecated
branch treating arrays as bitvectors.
* libguile/deprecated.c: Remove all deprecated code.  Whee!
* libguile/deprecated.h: Remove deprecated decls.
* libguile/posix.c (scm_tmpnam): Remove.
* libguile/struct.c (scm_is_valid_vtable_layout): Remove support for 'r'
fields.
* libguile/vectors.c (scm_vector_copy_partial, scm_vector_to_list)
(scm_vector_move_left_x, scm_vector_move_right_x): Remove generalized
array cases.
* test-suite/tests/vectors.test ("vector->list"): Remove shared array
test
2025-05-02 15:50:42 +02:00
Andy Wingo
dd0e455755 Remove scm_gc_realloc
Whippet may add a shrink interface, if it is needed.

* doc/ref/api-memory.texi (Memory Blocks): Remove some 1.8 references.
Remove discussion of scm_gc_malloc.  Remove discussion of scm_gc_free.
* libguile/gc.h:
* libguile/gc-malloc.c (scm_gc_malloc): Remove.
2025-04-30 11:30:52 +02:00
Andy Wingo
a13c30eeba Remove GUILE_DEBUG_MALLOC configuration
* configure.ac: Remove --enable-debug-malloc.
* doc/ref/api-memory.texi (Memory Blocks): Remove malloc-stats mention.
* libguile/debug-malloc.c:
* libguile/debug-malloc.h: Remove.
* libguile/Makefile.am (EXTRA_libguile_@GUILE_EFFECTIVE_VERSION@_la_SOURCES):
(modinclude_HEADERS): Remove debug-malloc mentions.
* libguile/gc-malloc.c (scm_gc_register_collectable_memory):
(scm_calloc):
* libguile/init.c (scm_i_init_guile): Remove debug-malloc things.
2025-04-30 11:21:52 +02:00
Andy Wingo
f3649d7d1b Move scm_c_shrink_bytevector off realloc
* libguile/bytevectors.c (scm_c_shrink_bytevector): Return buf as is if
length is more than half of previous.  Otherwise make a fresh buffer and
copy.
2025-04-30 11:01:14 +02:00
Andy Wingo
337eaec77d Refactor srfi-14.c to use malloc instead of realloc
* libguile/srfi-14.c (char_ranges_insert, char_ranges_delete): New
helpers.
(scm_i_charset_set, scm_i_charset_set_range, scm_i_charset_unset): Use
the new helpers.
2025-04-30 10:42:07 +02:00
Andy Wingo
53dda2ecec Remove accidental chars in srfi-14.h
* libguile/srfi-14.h: Remove typo
2025-04-30 10:42:07 +02:00
Andy Wingo
ec8d08fc4f Move atomic primitive registration to (language tree-il)
* module/ice-9/atomic.scm: Don't add-interesting-primitive! here.
* module/language/tree-il/primitives.scm
(*interesting-primitive-names*): Instead, import atomics here and
register the primitives as usual.  This will let atomics be used earlier
in the boot graph.
2025-04-30 10:41:44 +02:00
Andy Wingo
2bfc1779c5 Move r6rs-ports off scm_gc_realloc
* libguile/r6rs-ports.c (grow_byte_buffer, shrink_byte_buffer): New
helpers.
* libguile/r6rs-ports.c (bytevector_output_port_buffer_grow):
(bytevector_output_port_procedure): Use new helpers.
2025-04-30 10:39:20 +02:00
Andy Wingo
4ccd57aca8 Use scm_inline_gc_malloc for scm_gc_malloc
* libguile/gc-malloc.c (do_realloc, do_calloc): Remove.
(scm_gc_malloc): Dispatch to scm_inline_gc_malloc.
(scm_gc_calloc): Dispatch to scm_gc_malloc.
(scm_gc_realloc): Mark for removal.  The issue is that the realloc'd
object should have the same kind.  We could add Whippet API but it would
be nice to not do that.
2025-04-23 17:39:40 +02:00
Andy Wingo
1b6055dbbd Adapt to Whippet inline allocation changes
* libguile/jit.c (compile_allocate_words_immediate):
(compile_allocate_words_immediate_slow):
(compile_allocate_pointerless_words_immediate):
(compile_allocate_pointerless_words_immediate_slow): Update for new API.
2025-04-23 17:35:27 +02:00
Andy Wingo
975860e5e2 Merge remote-tracking branch 'whippet/main' into wip-whippet 2025-04-23 17:30:27 +02:00
Andy Wingo
c9063b8027 bdw: Disable thread-local freelists for pointerless allocations
There was a race between GC and popping the head off freelists.  We
could have separate freelists for tagged and untagged normal allocations
though.
2025-04-23 17:28:46 +02:00
Andy Wingo
06b53470f4 For freelist allocators, clear the freelist link on the returned obj
* api/gc-api.h (gc_allocate_small_fast_freelist):
* src/bdw.c (allocate_small): Clear freelist link, so the object is
completely zeroed.  In some cases the embedder / compiler / JIT will be
able to elide this write.
2025-04-23 16:44:59 +02:00