Commit ded96fb3 authored by Ömer Sinan Ağacan's avatar Ömer Sinan Ağacan Committed by Marge Bot

Document MIN_PAYLOAD_SIZE and mark-compact GC mark bits

This updates the documentation of the MIN_PAYLOAD_SIZE constant and adds
a new Note [Mark bits in mark-compact collector] explaning why the
mark-compact collector uses two bits per objet and why we need
MIN_PAYLOAD_SIZE.
parent 1ea8c451
Pipeline #10414 passed with stages
in 461 minutes and 50 seconds
...@@ -22,9 +22,11 @@ ...@@ -22,9 +22,11 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Minimum closure sizes Minimum closure sizes
This is the minimum number of words in the payload of a This is the minimum number of words in the payload of a heap-allocated
heap-allocated closure, so that the closure has enough room to be closure, so that the closure has two bits in the bitmap for mark-compact
overwritten with a forwarding pointer during garbage collection. collection.
See Note [Mark bits in mark-compact collector] in rts/sm/Compact.h
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
#define MIN_PAYLOAD_SIZE 1 #define MIN_PAYLOAD_SIZE 1
......
...@@ -830,10 +830,11 @@ update_fwd_compact( bdescr *blocks ) ...@@ -830,10 +830,11 @@ update_fwd_compact( bdescr *blocks )
size = p - q; size = p - q;
if (free + size > free_bd->start + BLOCK_SIZE_W) { if (free + size > free_bd->start + BLOCK_SIZE_W) {
// set the next bit in the bitmap to indicate that // set the next bit in the bitmap to indicate that this object
// this object needs to be pushed into the next // needs to be pushed into the next block. This saves us having
// block. This saves us having to run down the // to run down the threaded info pointer list twice during the
// threaded info pointer list twice during the next pass. // next pass. See Note [Mark bits in mark-compact collector] in
// Compact.h.
mark(q+1,bd); mark(q+1,bd);
free_bd = free_bd->link; free_bd = free_bd->link;
free = free_bd->start; free = free_bd->start;
......
...@@ -15,6 +15,45 @@ ...@@ -15,6 +15,45 @@
#include "BeginPrivate.h" #include "BeginPrivate.h"
/* -----------------------------------------------------------------------------
Note [Mark bits in mark-compact collector]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In mark-compact collector each closure has two mark bits:
- Liveness bit: not marked == unreachable (dead)
- "Too large" bit: when this is set it means that the closure won't fit in
the current heap block and we need to move it to the next block in the
heap.
Why do we need the second bit? We only know a closure's size *before*
threading it, because after threading the info table pointer will be end of
the chain. So by the time we do the second pass to move the closures and
unthread chains we'd have to do two passes, one for to get the info table
pointer at the end of the chain to compute the closure size and update the
free pointer if it's too large to fit in the current block, and then another
pass to actually unthread.
To avoid this we update the second bit when we first visit an object (in the
"forward" pass) and realize that it won't fit in the current block, and check
that bit in the second pass (where we actually move the object and update all
references). If the bit is set we move the object to the free location in the
next block in heap chain, otherwise we use the free pointer in the current
block.
Instead of allocating two bits per object, we use the fact that most heap
closures will be at least two words (as one-word closures will mostly be
static objects), and allocate one bit per word in the heap. In the rare cases
where we allocate single-word heap objects (e.g. a non-top-level FUN with
empty payload) we add one non-pointer field to the payload so that the object
will have two words. The minimum amount of words in the payload is defined in
includes/rts/Constants.h as MIN_PAYLOAD_SIZE.
(See also !1701 where we discussed lifting this restriction and allocating
two bits per object)
-------------------------------------------------------------------------- */
INLINE_HEADER void INLINE_HEADER void
mark(StgPtr p, bdescr *bd) mark(StgPtr p, bdescr *bd)
{ {
......
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