summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÖmer Sinan Ağacan <omeragacan@gmail.com>2020-03-10 16:44:03 +0300
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-03-11 08:20:27 -0400
commit3aa9b35fcc417ab39d8da633482fe64dc9f898b1 (patch)
tree95014bf686a263a34349092f3c7b1e5a82de0570
parentc61b9b02925acf248cde1ec0f67730c1a6f6c6e5 (diff)
downloadhaskell-3aa9b35fcc417ab39d8da633482fe64dc9f898b1.tar.gz
Zero any slop after compaction in compacting GC
In copying GC, with the relevant debug flags enabled, we release the old blocks after a GC, and the block allocator zeroes the space before releasing a block. This effectively zeros the old heap. In compacting GC we reuse the blocks and previously we didn't zero the unused space in a compacting generation after compaction. With this patch we zero the slop between the free pointer and the end of the block when we're done with compaction and when switching to a new block (because the current block doesn't have enough space for the next object we're shifting).
-rw-r--r--rts/sm/Compact.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/rts/sm/Compact.c b/rts/sm/Compact.c
index 1193fd765c..fee9cf02fa 100644
--- a/rts/sm/Compact.c
+++ b/rts/sm/Compact.c
@@ -829,18 +829,27 @@ update_bkwd_compact( generation *gen )
for (; bd != NULL; bd = bd->link) {
P_ p = bd->start;
- while (p < bd->free ) {
+ while (p < bd->free) {
- while ( p < bd->free && !is_marked(p,bd) ) {
+ while (p < bd->free && !is_marked(p,bd)) {
p++;
}
+
if (p >= bd->free) {
break;
}
if (is_marked(p+1,bd)) {
- // don't forget to update the free ptr in the block desc.
+ // Don't forget to update the free ptr in the block desc
free_bd->free = free;
+
+ // Zero the remaining bytes of this block before moving on to
+ // the next block
+ IF_DEBUG(zero_on_gc, {
+ memset(free_bd->free, 0xaa,
+ BLOCK_SIZE - ((W_)(free_bd->free - free_bd->start) * sizeof(W_)));
+ });
+
free_bd = free_bd->link;
free = free_bd->start;
free_blocks++;
@@ -867,13 +876,21 @@ update_bkwd_compact( generation *gen )
}
}
- // free the remaining blocks and count what's left.
+ // Free the remaining blocks and count what's left.
free_bd->free = free;
if (free_bd->link != NULL) {
freeChain(free_bd->link);
free_bd->link = NULL;
}
+ // Zero the free bits of the last used block.
+ IF_DEBUG(zero_on_gc, {
+ W_ block_size_bytes = free_bd->blocks * BLOCK_SIZE;
+ W_ block_in_use_bytes = (free_bd->free - free_bd->start) * sizeof(W_);
+ W_ block_free_bytes = block_size_bytes - block_in_use_bytes;
+ memset(free_bd->free, 0xaa, block_free_bytes);
+ });
+
return free_blocks;
}