diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-01-01 02:31:39 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-01-01 02:31:39 -0800 |
commit | 3edc515f91586cb5bb7bc666fb9222c67eabfdb2 (patch) | |
tree | 76aaba7401a703e7f30f38d47b507c3f3203ec38 /txr.1 | |
parent | 6bd452f024f0e60ef8a3994d371e13d3469db1cc (diff) | |
download | txr-3edc515f91586cb5bb7bc666fb9222c67eabfdb2.tar.gz txr-3edc515f91586cb5bb7bc666fb9222c67eabfdb2.tar.bz2 txr-3edc515f91586cb5bb7bc666fb9222c67eabfdb2.zip |
gc: do finalizers completely on one phase.
* gc.c (call_finalizers_impl): Iterate over the finalizer
registrations until no more finalizers are identified,
performing additional rounds, as necessary. Thus if finalizers
register more finalizers that are eligible for processing
according to the criteria of he current phase, those are done
in the current phase.
(gc_finalize): We must now carefully set the reachable flag to
1 for a new finalization entry. This was always the right
thing to do and is logically correct: if an object is being
passed to finalize, it is necessarily reachable. Leaving the
0 initialization would do bad things now, as follows. If any
object whatsoever has a finalizer registered against it during
GC-driven finalization, its finalizer will be called. This is
bad if the object isn't garbage. Secondly, the object may be
moved into generation 0, and put into the freshobj list. This
is extremely bad if the object is reachable by generation 1
objects, which is now a wrong-way reference.
* txr.1: Updated.
Diffstat (limited to 'txr.1')
-rw-r--r-- | txr.1 | 30 |
1 files changed, 24 insertions, 6 deletions
@@ -66814,9 +66814,17 @@ A finalizer is itself permitted to call .code finalize to register the original .code object -or any other object for finalization. Such registrations made during -finalization execution are not eligible for the current phase of finalization -processing; they will be processed in a later garbage collection pass. +or any other object for finalization. Finalization processing can be +understood as taking place in one or more rounds. At the start of each round, +finalizers are identified that are to be called, arranged in order, and removed +from the registration list. If this identification stage produces no +finalizers, then finalization ends. Otherwise, those finalizers are processed, +and then another round is initiated, to look for finalizers that may have been +registered during the previous round. + +Note: it is possible for the application to create an infinite finalization +loop, if one or more objects have finalizers that register new finalizers, +which register new finalizers and so on. .coNP Function @ call-finalizers .synb @@ -66832,12 +66840,22 @@ If any finalizers are called, it returns otherwise .codn nil . +Finalization performed by +.code call-finalizers +works in the manner described under the specification of he +.code finalize +function. + It is permissible for a finalizer function itself to call .codn call-finalizers . -Such a call can happen in two possible contexts: during actual -reclamation driven by garbage collection, or under the scope of a +Such a call can happen in two possible contexts: finalization +initiated by by garbage collection, or under the scope of a .code call-finalizers -invocation from application code. +invocation from application code. Doing so is safe, since the finalization +logic may be re-entered recursively. When finalizers are being called during a +round of processing, those finalizers have already been removed from the +registration list, and will not be redundantly invoked by a recursive +invocation of finalization. Under the scope of garbage-collection-driven reclamation, the order of finalizer calls may not be what the application logic |