summaryrefslogtreecommitdiff
path: root/rts/sm/Evac.c
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2019-04-18 14:08:32 -0400
committerBen Gamari <ben@smart-cactus.org>2019-10-22 12:18:33 -0400
commit13dd78ddb158f98b35ad2eda50d0a7af63920ece (patch)
tree66958e2c9593ff7009e255c6a064789b06d1acbf /rts/sm/Evac.c
parent06d51c4ef776ee1bf66e3603b4c6e4e2acf8ba3c (diff)
downloadhaskell-13dd78ddb158f98b35ad2eda50d0a7af63920ece.tar.gz
Nonmoving: Allow aging and refactor static objects logic
This commit does two things: * Allow aging of objects during the preparatory minor GC * Refactor handling of static objects to avoid the use of a hashtable
Diffstat (limited to 'rts/sm/Evac.c')
-rw-r--r--rts/sm/Evac.c50
1 files changed, 40 insertions, 10 deletions
diff --git a/rts/sm/Evac.c b/rts/sm/Evac.c
index c2aaaacffa..b4e35849ba 100644
--- a/rts/sm/Evac.c
+++ b/rts/sm/Evac.c
@@ -69,12 +69,6 @@ alloc_for_copy (uint32_t size, uint32_t gen_no)
{
ASSERT(gen_no < RtsFlags.GcFlags.generations);
- if (RtsFlags.GcFlags.useNonmoving && major_gc) {
- // unconditionally promote to non-moving heap in major gc
- gct->copied += size;
- return nonmovingAllocate(gct->cap, size);
- }
-
StgPtr to;
gen_workspace *ws;
@@ -93,7 +87,20 @@ alloc_for_copy (uint32_t size, uint32_t gen_no)
if (RtsFlags.GcFlags.useNonmoving && gen_no == oldest_gen->no) {
gct->copied += size;
- return nonmovingAllocate(gct->cap, size);
+ to = nonmovingAllocate(gct->cap, size);
+
+ // Add segment to the todo list unless it's already there
+ // current->todo_link == NULL means not in todo list
+ struct NonmovingSegment *seg = nonmovingGetSegment(to);
+ if (!seg->todo_link) {
+ gen_workspace *ws = &gct->gens[oldest_gen->no];
+ seg->todo_link = ws->todo_seg;
+ ws->todo_seg = seg;
+ }
+
+ if (major_gc)
+ markQueuePushClosureGC(&gct->cap->upd_rem_set.queue, (StgClosure *) to);
+ return to;
}
ws = &gct->gens[gen_no]; // zero memory references here
@@ -312,9 +319,7 @@ evacuate_large(StgPtr p)
*/
new_gen_no = bd->dest_no;
- if (RtsFlags.GcFlags.useNonmoving && major_gc) {
- new_gen_no = oldest_gen->no;
- } else if (new_gen_no < gct->evac_gen_no) {
+ if (new_gen_no < gct->evac_gen_no) {
if (gct->eager_promotion) {
new_gen_no = gct->evac_gen_no;
} else {
@@ -363,6 +368,13 @@ evacuate_large(StgPtr p)
STATIC_INLINE void
evacuate_static_object (StgClosure **link_field, StgClosure *q)
{
+ if (RTS_UNLIKELY(RtsFlags.GcFlags.useNonmoving)) {
+ // See Note [Static objects under the nonmoving collector] in Storage.c.
+ if (major_gc)
+ markQueuePushClosureGC(&gct->cap->upd_rem_set.queue, q);
+ return;
+ }
+
StgWord link = (StgWord)*link_field;
// See Note [STATIC_LINK fields] for how the link field bits work
@@ -603,6 +615,8 @@ loop:
// NOTE: large objects in nonmoving heap are also marked with
// BF_NONMOVING. Those are moved to scavenged_large_objects list in
// mark phase.
+ if (major_gc)
+ markQueuePushClosureGC(&gct->cap->upd_rem_set.queue, q);
return;
}
@@ -629,6 +643,13 @@ loop:
// they are not)
if (bd->flags & BF_COMPACT) {
evacuate_compact((P_)q);
+
+ // We may have evacuated the block to the nonmoving generation. If so
+ // we need to make sure it is added to the mark queue since the only
+ // reference to it may be from the moving heap.
+ if (major_gc && bd->flags & BF_NONMOVING) {
+ markQueuePushClosureGC(&gct->cap->upd_rem_set.queue, q);
+ }
return;
}
@@ -636,6 +657,13 @@ loop:
*/
if (bd->flags & BF_LARGE) {
evacuate_large((P_)q);
+
+ // We may have evacuated the block to the nonmoving generation. If so
+ // we need to make sure it is added to the mark queue since the only
+ // reference to it may be from the moving heap.
+ if (major_gc && bd->flags & BF_NONMOVING) {
+ markQueuePushClosureGC(&gct->cap->upd_rem_set.queue, q);
+ }
return;
}
@@ -937,6 +965,8 @@ evacuate_BLACKHOLE(StgClosure **p)
ASSERT((bd->flags & BF_COMPACT) == 0);
if (bd->flags & BF_NONMOVING) {
+ if (major_gc)
+ markQueuePushClosureGC(&gct->cap->upd_rem_set.queue, q);
return;
}