summaryrefslogtreecommitdiff
path: root/gc.c
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@ruby-lang.org>2023-04-04 09:49:26 -0700
committerJean Boussier <jean.boussier@gmail.com>2023-04-04 19:49:08 +0200
commit87253d047ce35e7836b6f97edbb4f819879a3b25 (patch)
treeb73daf26597364f210eeffd5676fdbcbfa07635c /gc.c
parentba6ccd871442f55080bffd53e33678c0726787d2 (diff)
downloadruby-87253d047ce35e7836b6f97edbb4f819879a3b25.tar.gz
Fix transient heap mode
Make sure the transient heap is in the right mode when we finish warming the heap. Also ensure the GC isn't allowed to run while we iterate and mutate the heap.
Diffstat (limited to 'gc.c')
-rw-r--r--gc.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/gc.c b/gc.c
index e52e3fc35b..4050c47edf 100644
--- a/gc.c
+++ b/gc.c
@@ -9885,10 +9885,26 @@ rb_gc_prepare_heap(void)
{
gc_start_internal(NULL, Qtrue, Qtrue, Qtrue, Qtrue, Qtrue);
- /* The transient heap need to be evacuated before we promote objects */
+ /* Flush any postponed jobs.
+ * Transient heap uses postponed jobs to mark things, so we need to
+ * give it a chance to finish what it was doing. */
+ rb_postponed_job_flush(GET_VM());
+
+ /* The transient heap need to be evacuated before we promote objects.
+ * First put the transient heap in marking mode so that we can
+ * evacuate everything. Then evacuate everything. Then finish up
+ * marking mode so that the transient heap is in the right mode
+ * for the next GC. */
rb_transient_heap_start_marking(true);
rb_transient_heap_evacuate();
+ rb_transient_heap_finish_marking();
+
+ /* Finally, promote everyone to old gen, but don't let the GC run
+ * while we iterate over the heap. */
+ VALUE gc_disabled = rb_gc_disable_no_rest();
rb_objspace_each_objects(gc_promote_object_i, NULL);
+ if (gc_disabled != Qtrue) rb_gc_enable();
+ rb_transient_heap_verify();
}
static int