fix an integer overflow (#5086), and pre-emptively avoid more of these
authorSimon Marlow <marlowsd@gmail.com>
Tue, 24 May 2011 15:56:23 +0000 (16:56 +0100)
committerSimon Marlow <marlowsd@gmail.com>
Wed, 25 May 2011 07:49:17 +0000 (08:49 +0100)
in the future.

includes/rts/storage/GC.h
rts/Stats.c
rts/sm/GC.c

index bbed216..3c6e6f6 100644 (file)
  *
  * ------------------------------------------------------------------------- */
 
+// A count of blocks needs to store anything up to the size of memory
+// divided by the block size.  The safest thing is therefore to use a
+// type that can store the full range of memory addresses,
+// ie. StgWord.  Note that we have had some tricky int overflows in a
+// couple of cases caused by using ints rather than longs (e.g. #5086)
+
+typedef StgWord memcount;
+
 typedef struct nursery_ {
     bdescr *       blocks;
-    unsigned int   n_blocks;
+    memcount       n_blocks;
 } nursery;
 
 typedef struct generation_ {
     unsigned int   no;                 // generation number
 
     bdescr *       blocks;             // blocks in this gen
-    unsigned int   n_blocks;           // number of blocks
-    unsigned int   n_words;             // number of used words
+    memcount       n_blocks;            // number of blocks
+    memcount       n_words;             // number of used words
 
     bdescr *       large_objects;      // large objects (doubly linked)
-    unsigned int   n_large_blocks;      // no. of blocks used by large objs
-    unsigned long  n_new_large_words;   // words of new large objects
+    memcount       n_large_blocks;      // no. of blocks used by large objs
+    memcount       n_new_large_words;   // words of new large objects
                                         // (for allocation stats)
 
-    unsigned int   max_blocks;         // max blocks
+    memcount       max_blocks;          // max blocks
 
     StgTSO *       threads;             // threads in this gen
                                         // linked via global_link
@@ -98,11 +106,11 @@ typedef struct generation_ {
     // are copied into the following two fields.  After GC, these blocks
     // are freed.
     bdescr *     old_blocks;           // bdescr of first from-space block
-    unsigned int n_old_blocks;         // number of blocks in from-space
-    unsigned int live_estimate;         // for sweeping: estimate of live data
+    memcount     n_old_blocks;         // number of blocks in from-space
+    memcount     live_estimate;         // for sweeping: estimate of live data
     
     bdescr *     scavenged_large_objects;  // live large objs after GC (d-link)
-    unsigned int n_scavenged_large_blocks; // size (not count) of above
+    memcount     n_scavenged_large_blocks; // size (not count) of above
 
     bdescr *     bitmap;               // bitmap for compacting collection
 
index 3036ed7..8366bf4 100644 (file)
@@ -817,7 +817,7 @@ statDescribeGens(void)
           gen_blocks += gcThreadLiveBlocks(i,g);
       }
 
-      debugBelch("%5d %7d %9d", g, gen->max_blocks, mut);
+      debugBelch("%5d %7ld %9d", g, (lnat)gen->max_blocks, mut);
 
       gen_slop = gen_blocks * BLOCK_SIZE_W - gen_live;
 
index fb73180..51eab4e 100644 (file)
@@ -1247,7 +1247,7 @@ prepare_collected_gen (generation *gen)
 
     // for a compacted generation, we need to allocate the bitmap
     if (gen->mark) {
-        nat bitmap_size; // in bytes
+        lnat bitmap_size; // in bytes
         bdescr *bitmap_bdescr;
         StgWord *bitmap;