NonMoving: Move block size to block descriptor
authorBen Gamari <ben@smart-cactus.org>
Fri, 17 May 2019 17:28:53 +0000 (13:28 -0400)
committerBen Gamari <ben@smart-cactus.org>
Wed, 19 Jun 2019 01:42:57 +0000 (21:42 -0400)
includes/rts/storage/Block.h
rts/sm/NonMoving.c
rts/sm/NonMoving.h
rts/sm/NonMovingMark.c

index 32cf989..3887ac2 100644 (file)
@@ -88,17 +88,22 @@ typedef struct bdescr_ {
 
     StgPtr start;              // [READ ONLY] start addr of memory
 
-    StgPtr free;               // First free byte of memory.
-                               // allocGroup() sets this to the value of start.
-                               // NB. during use this value should lie
-                               // between start and start + blocks *
-                               // BLOCK_SIZE.  Values outside this
-                               // range are reserved for use by the
-                               // block allocator.  In particular, the
-                               // value (StgPtr)(-1) is used to
-                               // indicate that a block is unallocated.
-                               //
-                               // Unused by the non-moving allocator.
+    union {
+        StgPtr free;               // First free byte of memory.
+                                   // allocGroup() sets this to the value of start.
+                                   // NB. during use this value should lie
+                                   // between start and start + blocks *
+                                   // BLOCK_SIZE.  Values outside this
+                                   // range are reserved for use by the
+                                   // block allocator.  In particular, the
+                                   // value (StgPtr)(-1) is used to
+                                   // indicate that a block is unallocated.
+                                   //
+                                   // Unused by the non-moving allocator.
+        struct NonmovingSegmentInfo {
+            StgWord8 log_block_size;
+        } nonmoving_segment;
+    };
 
     struct bdescr_ *link;      // used for chaining blocks together
 
index 45f4e1e..0cad2f4 100644 (file)
@@ -205,13 +205,14 @@ static void nonmovingMark_(MarkQueue *mark_queue, StgWeak **dead_weaks, StgTSO *
 
 static void nonmovingInitSegment(struct NonmovingSegment *seg, uint8_t log_block_size)
 {
+    bdescr *bd = Bdescr((P_) seg);
     seg->link = NULL;
     seg->todo_link = NULL;
     seg->next_free = 0;
     seg->next_free_snap = 0;
-    seg->log_block_size = log_block_size;
     nonmovingClearBitmap(seg);
-    Bdescr((P_)seg)->u.scan = nonmovingSegmentGetBlock(seg, 0);
+    bd->nonmoving_segment.log_block_size = log_block_size;
+    bd->u.scan = nonmovingSegmentGetBlock(seg, 0);
 }
 
 // Add a segment to the free list.
index 3143d72..9cf001e 100644 (file)
@@ -39,12 +39,16 @@ struct NonmovingSegment {
     struct NonmovingSegment *todo_link; // NULL when not in todo list
     nonmoving_block_idx next_free;      // index of the next unallocated block
     nonmoving_block_idx next_free_snap; // snapshot of next_free
-    uint8_t log_block_size;             // log2 of block size in bytes
     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
     // of the word size since GHC assumes that all object pointers are
     // so-aligned.
+
+    // N.B. There are also bits of information which are stored in the
+    // NonmovingBlockInfo stored in the segment's block descriptor. Namely:
+    //
+    //  * the block size can be found in nonmovingBlockInfo(seg)->log_block_size.
 };
 
 // This is how we mark end of todo lists. Not NULL because todo_link == NULL
@@ -121,8 +125,13 @@ void *nonmovingAllocate(Capability *cap, StgWord sz);
 void nonmovingAddCapabilities(uint32_t new_n_caps);
 void nonmovingPushFreeSegment(struct NonmovingSegment *seg);
 
+
+INLINE_HEADER struct NonmovingSegmentInfo *nonmovingSegmentInfo(struct NonmovingSegment *seg) {
+    return &Bdescr((StgPtr) seg)->nonmoving_segment;
+}
+
 INLINE_HEADER uint8_t nonmovingSegmentLogBlockSize(struct NonmovingSegment *seg) {
-    return seg->log_block_size;
+    return nonmovingSegmentInfo(seg)->log_block_size;
 }
 
 // Add a segment to the appropriate active list.
index 4997de1..f85e636 100644 (file)
@@ -769,7 +769,7 @@ static MarkQueueEnt markQueuePop (MarkQueue *q)
         // MarkQueueEnt encoding always places the pointer to the object to be
         // marked first.
         prefetchForRead(&new.mark_closure.p->header.info);
-        prefetchForRead(&nonmovingGetSegment_unchecked((StgPtr) new.mark_closure.p)->log_block_size);
+        prefetchForRead(Bdescr((StgPtr) new.mark_closure.p));
         q->prefetch_queue[i] = new;
         i = (i + 1) % MARK_PREFETCH_QUEUE_DEPTH;
     }