1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
/* -----------------------------------------------------------------------------
*
* (c) The GHC Team 2008
*
* Simple mark/sweep, collecting whole blocks.
*
* Documentation on the architecture of the Garbage Collector can be
* found in the online commentary:
*
* http://ghc.haskell.org/trac/ghc/wiki/Commentary/Rts/Storage/GC
*
* ---------------------------------------------------------------------------*/
#include "PosixSource.h"
#include "Rts.h"
#include "BlockAlloc.h"
#include "Sweep.h"
#include "Trace.h"
void
sweep(generation *gen)
{
bdescr *bd, *prev, *next;
nat i;
W_ freed, resid, fragd, blocks, live;
ASSERT(countBlocks(gen->old_blocks) == gen->n_old_blocks);
live = 0; // estimate of live data in this gen
freed = 0;
fragd = 0;
blocks = 0;
prev = NULL;
for (bd = gen->old_blocks; bd != NULL; bd = next)
{
next = bd->link;
if (!(bd->flags & BF_MARKED)) {
prev = bd;
continue;
}
blocks++;
resid = 0;
for (i = 0; i < BLOCK_SIZE_W / BITS_IN(W_); i++)
{
if (bd->u.bitmap[i] != 0) resid++;
}
live += resid * BITS_IN(W_);
if (resid == 0)
{
freed++;
gen->n_old_blocks--;
if (prev == NULL) {
gen->old_blocks = next;
} else {
prev->link = next;
}
freeGroup(bd);
}
else
{
prev = bd;
if (resid < (BLOCK_SIZE_W * 3) / (BITS_IN(W_) * 4)) {
fragd++;
bd->flags |= BF_FRAGMENTED;
}
bd->flags |= BF_SWEPT;
}
}
gen->live_estimate = live;
debugTrace(DEBUG_gc, "sweeping: %d blocks, %d were copied, %d freed (%d%%), %d are fragmented, live estimate: %ld%%",
gen->n_old_blocks + freed,
gen->n_old_blocks - blocks + freed,
freed,
blocks == 0 ? 0 : (freed * 100) / blocks,
fragd,
(unsigned long)((blocks - freed) == 0 ? 0 : ((live / BLOCK_SIZE_W) * 100) / (blocks - freed)));
ASSERT(countBlocks(gen->old_blocks) == gen->n_old_blocks);
}
|