* frequently after each object is copied, to achieve better locality and cache
* usage.
*
- * max_objs is the maximum number of objects to scan, or -1 to scan until the stack is
- * empty.
*/
gboolean
-sgen_drain_gray_stack (int max_objs, ScanCopyContext ctx)
+sgen_drain_gray_stack (ScanCopyContext ctx)
{
ScanObjectFunc scan_func = ctx.ops->scan_object;
GrayQueue *queue = ctx.queue;
- if (current_collection_generation == GENERATION_OLD && major_collector.drain_gray_stack)
- return major_collector.drain_gray_stack (ctx);
+ if (ctx.ops->drain_gray_stack)
+ return ctx.ops->drain_gray_stack (queue);
- do {
- int i;
- for (i = 0; i != max_objs; ++i) {
- GCObject *obj;
- SgenDescriptor desc;
- GRAY_OBJECT_DEQUEUE (queue, &obj, &desc);
- if (!obj)
- return TRUE;
- SGEN_LOG (9, "Precise gray object scan %p (%s)", obj, sgen_client_vtable_get_name (SGEN_LOAD_VTABLE (obj)));
- scan_func (obj, desc, queue);
- }
- } while (max_objs < 0);
+ for (;;) {
+ GCObject *obj;
+ SgenDescriptor desc;
+ GRAY_OBJECT_DEQUEUE (queue, &obj, &desc);
+ if (!obj)
+ return TRUE;
+ SGEN_LOG (9, "Precise gray object scan %p (%s)", obj, sgen_client_vtable_get_name (SGEN_LOAD_VTABLE (obj)));
+ scan_func (obj, desc, queue);
+ }
return FALSE;
}
* To achieve better cache locality and cache usage, we drain the gray stack
* frequently, after each object is copied, and just finish the work here.
*/
- sgen_drain_gray_stack (-1, ctx);
+ sgen_drain_gray_stack (ctx);
TV_GETTIME (atv);
SGEN_LOG (2, "%s generation done", generation_name (generation));
done_with_ephemerons = 0;
do {
done_with_ephemerons = sgen_client_mark_ephemerons (ctx);
- sgen_drain_gray_stack (-1, ctx);
+ sgen_drain_gray_stack (ctx);
++ephemeron_rounds;
} while (!done_with_ephemerons);
if (sgen_client_bridge_need_processing ()) {
/*Make sure the gray stack is empty before we process bridge objects so we get liveness right*/
- sgen_drain_gray_stack (-1, ctx);
+ sgen_drain_gray_stack (ctx);
sgen_collect_bridge_objects (generation, ctx);
if (generation == GENERATION_OLD)
sgen_collect_bridge_objects (GENERATION_NURSERY, ctx);
Make sure we drain the gray stack before processing disappearing links and finalizers.
If we don't make sure it is empty we might wrongly see a live object as dead.
*/
- sgen_drain_gray_stack (-1, ctx);
+ sgen_drain_gray_stack (ctx);
/*
We must clear weak links that don't track resurrection before processing object ready for
sgen_finalize_in_range (GENERATION_NURSERY, ctx);
/* drain the new stack that might have been created */
SGEN_LOG (6, "Precise scan of gray area post fin");
- sgen_drain_gray_stack (-1, ctx);
+ sgen_drain_gray_stack (ctx);
/*
* This must be done again after processing finalizable objects since CWL slots are cleared only after the key is finalized.
done_with_ephemerons = 0;
do {
done_with_ephemerons = sgen_client_mark_ephemerons (ctx);
- sgen_drain_gray_stack (-1, ctx);
+ sgen_drain_gray_stack (ctx);
++ephemeron_rounds;
} while (!done_with_ephemerons);
sgen_null_link_in_range (GENERATION_NURSERY, ctx, TRUE);
if (sgen_gray_object_queue_is_empty (queue))
break;
- sgen_drain_gray_stack (-1, ctx);
+ sgen_drain_gray_stack (ctx);
}
g_assert (sgen_gray_object_queue_is_empty (queue));
sgen_pin_stats_print_class_stats ();
- sgen_drain_gray_stack (-1, ctx);
+ sgen_drain_gray_stack (ctx);
/* FIXME: Why do we do this at this specific, seemingly random, point? */
sgen_client_collecting_minor (&fin_ready_queue, &critical_fin_queue);
generation_to_collect = GENERATION_OLD;
}
} else if (sgen_need_major_collection (size)) {
- reason = "Minor allowance";
+ reason = concurrent_collection_in_progress ? "Forced finish concurrent collection" : "Minor allowance";
generation_to_collect = GENERATION_OLD;
} else {
generation_to_collect = GENERATION_NURSERY;
if (concurrent_collection_in_progress) {
/*
- * We update the concurrent collection. If it finished, we're done. If
- * not, and we've been asked to do a nursery collection, we do that.
+ * If the concurrent worker is finished or we are asked to do a major collection
+ * then we finish the concurrent collection.
*/
- gboolean finish = major_should_finish_concurrent_collection () || (wait_to_finish && generation_to_collect == GENERATION_OLD);
+ gboolean finish = major_should_finish_concurrent_collection () || generation_to_collect == GENERATION_OLD;
if (finish) {
major_finish_concurrent_collection (wait_to_finish);
oldest_generation_collected = GENERATION_OLD;
} else {
+ SGEN_ASSERT (0, generation_to_collect == GENERATION_NURSERY, "Why aren't we finishing the concurrent collection?");
major_update_concurrent_collection ();
- if (generation_to_collect == GENERATION_NURSERY)
- collect_nursery (NULL, FALSE);
+ collect_nursery (NULL, FALSE);
}
goto done;