Commit 55f67029 authored by Ben Gamari's avatar Ben Gamari 🐢

Track filled epoch

parent 9ea1f029
......@@ -38,6 +38,7 @@ struct NonmovingSegment {
struct NonmovingSegment *link; // for linking together segments into lists
struct NonmovingSegment *todo_link; // NULL when not in todo list
nonmoving_block_idx next_free; // index of the next unallocated block
uint8_t filled_epoch;
uint8_t bitmap[]; // liveness bitmap
// After the liveness bitmap comes the data blocks. Note that we need to
// ensure that the size of this struct (including the bitmap) is a multiple
......@@ -109,6 +110,8 @@ extern memcount nonmoving_live_words;
extern bool concurrent_coll_running;
#endif
extern uint8_t nonmovingMarkEpoch;
void nonmovingInit(void);
void nonmovingStop(void);
void nonmovingExit(void);
......@@ -166,6 +169,7 @@ INLINE_HEADER void nonmovingPushFilledSegment(struct NonmovingSegment *seg)
nonmovingHeap.allocators[nonmovingSegmentLogBlockSize(seg) - NONMOVING_ALLOCA0];
ACQUIRE_LOCK(&alloc->mutex);
seg->filled_epoch = nonmovingMarkEpoch;
seg->link = alloc->new_filled;
alloc->new_filled = seg;
RELEASE_LOCK(&alloc->mutex);
......@@ -253,9 +257,6 @@ INLINE_HEADER nonmoving_block_idx nonmovingGetBlockIdx(StgPtr p)
return (nonmoving_block_idx) (offset >> nonmovingSegmentLogBlockSize(seg));
}
// TODO: Eliminate this
extern uint8_t nonmovingMarkEpoch;
INLINE_HEADER void nonmovingSetMark(struct NonmovingSegment *seg, nonmoving_block_idx i)
{
seg->bitmap[i] = nonmovingMarkEpoch;
......
......@@ -1771,6 +1771,21 @@ bool nonmovingIsAlive (StgClosure *p)
// all objects alive in the snapshot would be marked.
//
return mark == nonmovingMarkEpoch || mark == 0;
} else if (seg->next_free == nonmovingSegmentBlockCount(seg)) {
// If the segment is filled then we check whether it was filled
// during the current GC cycle.
//
// * If so, then we must consider the object to be alive since we
// cleared the bitmap when the segment was filled but haven't
// yet marked it.
// * If it was filled in the previous cycle then the object's
// liveness is reflected by its bitmap bit.
//
if (seg->filled_epoch == nonmovingMarkEpoch) {
return true;
} else {
return mark == nonmovingMarkEpoch;
}
} else {
// If the object is below next_free_snap then the snapshot
// invariant guarantees that it is marked if reachable.
......
......@@ -141,10 +141,12 @@ GNUC_ATTR_HOT void nonmovingSweep(void)
switch (ret) {
case SEGMENT_FREE:
IF_DEBUG(sanity, clear_segment(seg));
seg->filled_epoch = 0;
nonmovingPushFreeSegment(seg);
break;
case SEGMENT_PARTIAL:
IF_DEBUG(sanity, clear_segment_free_blocks(seg));
seg->filled_epoch = 0;
nonmovingPushActiveSegment(seg);
break;
case SEGMENT_FILLED:
......@@ -152,6 +154,7 @@ GNUC_ATTR_HOT void nonmovingSweep(void)
nonmovingClearBitmap(seg);
// Set snapshot
nonmovingSegmentInfo(seg)->next_free_snap = seg->next_free;
seg->filled_epoch = nonmovingMarkEpoch;
seg->link = new_sweep_list;
new_sweep_list = seg;
break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment