[MLton-commit] r6773

Matthew Fluet fluet at mlton.org
Tue Aug 19 17:43:29 PDT 2008


Integrate Nicolas Bertolotti's card-cross-map-in-heap patch.
----------------------------------------------------------------------

U   mlton/trunk/runtime/gc/cheney-copy.c
U   mlton/trunk/runtime/gc/done.c
U   mlton/trunk/runtime/gc/generational.c
U   mlton/trunk/runtime/gc/generational.h
U   mlton/trunk/runtime/gc/heap.c
U   mlton/trunk/runtime/gc/virtual-memory.c
U   mlton/trunk/runtime/gc.h

----------------------------------------------------------------------

Modified: mlton/trunk/runtime/gc/cheney-copy.c
===================================================================
--- mlton/trunk/runtime/gc/cheney-copy.c	2008-08-20 00:08:27 UTC (rev 6772)
+++ mlton/trunk/runtime/gc/cheney-copy.c	2008-08-20 00:43:27 UTC (rev 6773)
@@ -39,6 +39,7 @@
 void swapHeapsForCheneyCopy (GC_state s) {
   struct GC_heap tempHeap;
 
+  copyCardMapAndCrossMap (s, &s->secondaryHeap);
   tempHeap = s->secondaryHeap;
   s->secondaryHeap = s->heap;
   s->heap = tempHeap;

Modified: mlton/trunk/runtime/gc/done.c
===================================================================
--- mlton/trunk/runtime/gc/done.c	2008-08-20 00:08:27 UTC (rev 6772)
+++ mlton/trunk/runtime/gc/done.c	2008-08-20 00:43:27 UTC (rev 6773)
@@ -93,5 +93,4 @@
   }
   releaseHeap (s, &s->heap);
   releaseHeap (s, &s->secondaryHeap);
-  releaseCardMapAndCrossMap (s);
 }

Modified: mlton/trunk/runtime/gc/generational.c
===================================================================
--- mlton/trunk/runtime/gc/generational.c	2008-08-20 00:08:27 UTC (rev 6772)
+++ mlton/trunk/runtime/gc/generational.c	2008-08-20 00:43:27 UTC (rev 6773)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999-2007 Henry Cejtin, Matthew Fluet, Suresh
+/* Copyright (C) 1999-2008 Henry Cejtin, Matthew Fluet, Suresh
  *    Jagannathan, and Stephen Weeks.
  * Copyright (C) 1997-2000 NEC Research Institute.
  *
@@ -119,8 +119,35 @@
           s->generationalMaps.crossMapLength * CROSS_MAP_ELEM_SIZE);
 }
 
-void createCardMapAndCrossMap (GC_state s) {
+/* Compute the number of bytes that are needed to store the card map and
+   cross map at the end of a heap with the given size. */
+size_t computeCardMapAndCrossMapSize (GC_state s, size_t size) {
   unless (s->mutatorMarksCards) {
+    return 0;
+  }
+  assert (isAligned (size, CARD_SIZE));
+
+  GC_cardMapIndex cardMapLength;
+  size_t cardMapSize;
+  GC_crossMapIndex crossMapLength;
+  size_t crossMapSize;
+  size_t totalMapSize;
+
+  cardMapLength = sizeToCardMapIndex (size);
+  cardMapSize = align (cardMapLength * CARD_MAP_ELEM_SIZE, s->sysvals.pageSize);
+  cardMapLength = (GC_cardMapIndex)(cardMapSize / CARD_MAP_ELEM_SIZE);
+
+  crossMapLength = sizeToCardMapIndex (size);
+  crossMapSize = align (crossMapLength * CROSS_MAP_ELEM_SIZE, s->sysvals.pageSize);
+  crossMapLength = (GC_crossMapIndex)(crossMapSize / CROSS_MAP_ELEM_SIZE);
+
+  totalMapSize = cardMapSize + crossMapSize;
+
+  return totalMapSize;
+}
+
+static inline void initCardMapAndCrossMap (GC_state s, GC_heap h, size_t size) {
+  unless (s->mutatorMarksCards) {
     s->generationalMaps.cardMapLength = 0;
     s->generationalMaps.cardMap = NULL;
     s->generationalMaps.cardMapAbsolute = NULL;
@@ -128,7 +155,7 @@
     s->generationalMaps.crossMap = NULL;
     return;
   }
-  assert (isAligned (s->heap.size, CARD_SIZE));
+  assert (isAligned (size, CARD_SIZE));
 
   GC_cardMapIndex cardMapLength;
   size_t cardMapSize;
@@ -136,21 +163,22 @@
   size_t crossMapSize;
   size_t totalMapSize;
 
-  cardMapLength = sizeToCardMapIndex (s->heap.size);
+  cardMapLength = sizeToCardMapIndex (size);
   cardMapSize = align (cardMapLength * CARD_MAP_ELEM_SIZE, s->sysvals.pageSize);
   cardMapLength = (GC_cardMapIndex)(cardMapSize / CARD_MAP_ELEM_SIZE);
   s->generationalMaps.cardMapLength = cardMapLength;
 
-  crossMapLength = sizeToCardMapIndex (s->heap.size);
+  crossMapLength = sizeToCardMapIndex (size);
   crossMapSize = align (crossMapLength * CROSS_MAP_ELEM_SIZE, s->sysvals.pageSize);
   crossMapLength = (GC_crossMapIndex)(crossMapSize / CROSS_MAP_ELEM_SIZE);
   s->generationalMaps.crossMapLength = crossMapLength;
 
   totalMapSize = cardMapSize + crossMapSize;
+  /* The card map starts at the end of the heap. */
   s->generationalMaps.cardMap =
-    GC_mmapAnon_safe (NULL, totalMapSize);
+    (GC_cardMap) (h->start + size);
   s->generationalMaps.crossMap =
-    (s->generationalMaps.cardMap + (cardMapSize / CARD_MAP_ELEM_SIZE));
+    (GC_crossMap) (s->generationalMaps.cardMap + (cardMapSize / CARD_MAP_ELEM_SIZE));
   if (DEBUG_MEM or s->controls.messages)
     fprintf (stderr,
              "[GC: Created card/cross map at "FMTPTR" of size %s bytes.]\n",
@@ -161,64 +189,104 @@
              (uintptr_t)s->generationalMaps.cardMap,
              (uintptr_t)s->generationalMaps.crossMap);
   setCardMapAbsolute (s);
-  clearCardMap (s);
-  clearCrossMap (s);
 }
 
-void releaseCardMapAndCrossMapAux (GC_state s,
-                                   GC_cardMap cardMap,
-                                   size_t cardMapSize,
-                                   __attribute__ ((unused)) GC_crossMap crossMap,
-                                   size_t crossMapSize) {
+void createCardMapAndCrossMap (GC_state s) {
+  initCardMapAndCrossMap (s, &s->heap, s->heap.size);
+  if (s->mutatorMarksCards) {
+    clearCardMap (s);
+    clearCrossMap (s);
+  }
+}
 
-  size_t totalMapSize;
+/* This function is called before the given heap becomes the new current heap
+   used to store the program datas.
+   The 2 heaps can have a different size. */
+void copyCardMapAndCrossMap (GC_state s, GC_heap h) {
+  if (s->mutatorMarksCards) {
+    GC_cardMap oldCardMap;
+    size_t oldCardMapSize;
+    GC_crossMap oldCrossMap;
+    size_t oldCrossMapSize;
 
-  assert (crossMap == cardMap + (cardMapSize / CARD_MAP_ELEM_SIZE));
-  totalMapSize = cardMapSize + crossMapSize;
-  if (DEBUG_MEM or s->controls.messages)
-    fprintf (stderr,
-             "[GC: Releasing card/cross map at "FMTPTR" of size %s bytes.]\n",
-             (uintptr_t)cardMap,
-             uintmaxToCommaString(totalMapSize));
-  GC_release (cardMap, totalMapSize);
+    oldCardMap = s->generationalMaps.cardMap;
+    oldCardMapSize = s->generationalMaps.cardMapLength * CARD_MAP_ELEM_SIZE;
+    oldCrossMap = s->generationalMaps.crossMap;
+    oldCrossMapSize = s->generationalMaps.crossMapLength * CROSS_MAP_ELEM_SIZE;
+
+    initCardMapAndCrossMap (s, h, h->size);
+
+    clearCardMap (s);
+    GC_memcpy ((pointer)oldCardMap, (pointer)s->generationalMaps.cardMap,
+               min (s->generationalMaps.cardMapLength * CARD_MAP_ELEM_SIZE,
+                    oldCardMapSize));
+    clearCrossMap (s);
+    GC_memcpy ((pointer)oldCrossMap, (pointer)s->generationalMaps.crossMap,
+               min (s->generationalMaps.crossMapLength * CROSS_MAP_ELEM_SIZE,
+                    oldCrossMapSize));
+  }
 }
 
-void releaseCardMapAndCrossMap (GC_state s) {
-  unless (s->mutatorMarksCards)
-    return;
+/* This function is called before we shrink the heap buffer which contains the
+   card/cross map datas. */
+void shrinkCardMapAndCrossMap (GC_state s, size_t keep) {
+  if (s->mutatorMarksCards) {
+    GC_crossMap oldCrossMap;
 
-  GC_cardMap cardMap;
-  size_t cardMapSize;
-  GC_crossMap crossMap;
-  size_t crossMapSize;
+    oldCrossMap = s->generationalMaps.crossMap;
 
-  cardMap = s->generationalMaps.cardMap;
-  cardMapSize = s->generationalMaps.cardMapLength * CARD_MAP_ELEM_SIZE;
-  crossMap = s->generationalMaps.crossMap;
-  crossMapSize = s->generationalMaps.crossMapLength * CROSS_MAP_ELEM_SIZE;
-  releaseCardMapAndCrossMapAux (s, cardMap, cardMapSize, crossMap, crossMapSize);
+    initCardMapAndCrossMap (s, &s->heap, keep);
+
+    GC_memmove ((pointer)oldCrossMap, (pointer)s->generationalMaps.crossMap,
+                s->generationalMaps.crossMapLength * CROSS_MAP_ELEM_SIZE);
+    clearCardMap (s);
+  }
 }
 
-void resizeCardMapAndCrossMap (GC_state s) {
-  if (s->mutatorMarksCards
-      and (s->generationalMaps.cardMapLength * CARD_MAP_ELEM_SIZE)
-          != align (sizeToCardMapIndex (s->heap.size), s->sysvals.pageSize)) {
+/* This function is called after we remap the heap buffer which contains the
+   card/cross map datas.
+   The remapped heap must be bigger than the original one. */
+void remapCardMapAndCrossMap (GC_state s, pointer orig) {
+  if (s->mutatorMarksCards) {
     GC_cardMap oldCardMap;
     size_t oldCardMapSize;
     GC_crossMap oldCrossMap;
     size_t oldCrossMapSize;
 
-    oldCardMap = s->generationalMaps.cardMap;
+    oldCardMap = (GC_cardMap) ((pointer) s->generationalMaps.cardMap + (s->heap.start - orig));
     oldCardMapSize = s->generationalMaps.cardMapLength * CARD_MAP_ELEM_SIZE;
-    oldCrossMap = s->generationalMaps.crossMap;
+    oldCrossMap = (GC_crossMap) (oldCardMap + (oldCardMapSize / CARD_MAP_ELEM_SIZE));
     oldCrossMapSize = s->generationalMaps.crossMapLength * CROSS_MAP_ELEM_SIZE;
-    createCardMapAndCrossMap (s);
-    GC_memcpy ((pointer)oldCrossMap, (pointer)s->generationalMaps.crossMap,
-               min (s->generationalMaps.crossMapLength * CROSS_MAP_ELEM_SIZE,
-                    oldCrossMapSize));
-    releaseCardMapAndCrossMapAux (s,
-                                  oldCardMap, oldCardMapSize,
-                                  oldCrossMap, oldCrossMapSize);
+
+    initCardMapAndCrossMap (s, &s->heap, s->heap.size);
+
+    if (DEBUG_MEM or s->controls.messages) {
+      fprintf (stderr, "[GC: oldCardMap = "FMTPTR"  oldCrossMap = "FMTPTR"]\n",
+               (uintptr_t)oldCardMap,
+               (uintptr_t)oldCrossMap);
+      fprintf (stderr,
+               "[GC: oldCardMapSize = %s bytes  oldCrossMapSize = %s bytes]\n",
+               uintmaxToCommaString(oldCardMapSize), uintmaxToCommaString(oldCrossMapSize));
+      fprintf (stderr, "[GC: cardMap = "FMTPTR"  crossMap = "FMTPTR"]\n",
+               (uintptr_t)s->generationalMaps.cardMap,
+               (uintptr_t)s->generationalMaps.crossMap);
+    }
+    GC_memmove ((pointer)oldCrossMap, (pointer)s->generationalMaps.crossMap,
+                oldCrossMapSize);
+    if (DEBUG_MEM or s->controls.messages) {
+      fprintf (stderr,
+               "[GC: crossMapSize = %s bytes]\n",
+               uintmaxToCommaString(s->generationalMaps.crossMapLength * CROSS_MAP_ELEM_SIZE));
+    }
+    memset((pointer)s->generationalMaps.crossMap + oldCrossMapSize, CROSS_MAP_EMPTY,
+           s->generationalMaps.crossMapLength * CROSS_MAP_ELEM_SIZE - oldCrossMapSize);
+    if (DEBUG_MEM or s->controls.messages) {
+      fprintf(stderr, "[GC: cross map OK]\n");
+    }
+    clearCardMap (s);
+    if (DEBUG_MEM or s->controls.messages) {
+      fprintf(stderr, "[GC: card map OK]\n");
+    }
   }
 }
 

Modified: mlton/trunk/runtime/gc/generational.h
===================================================================
--- mlton/trunk/runtime/gc/generational.h	2008-08-20 00:08:27 UTC (rev 6772)
+++ mlton/trunk/runtime/gc/generational.h	2008-08-20 00:43:27 UTC (rev 6773)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999-2007 Henry Cejtin, Matthew Fluet, Suresh
+/* Copyright (C) 1999-2008 Henry Cejtin, Matthew Fluet, Suresh
  *    Jagannathan, and Stephen Weeks.
  * Copyright (C) 1997-2000 NEC Research Institute.
  *
@@ -76,12 +76,11 @@
 
 static inline void clearCardMap (GC_state s);
 static inline void clearCrossMap (GC_state s);
+static size_t computeCardMapAndCrossMapSize (GC_state s, size_t size);
 static void createCardMapAndCrossMap (GC_state s);
-static void releaseCardMapAndCrossMap (GC_state s);
-static void releaseCardMapAndCrossMapAux (GC_state s,
-                                          GC_cardMap cardMap, size_t cardMapSize,
-                                          GC_crossMap crossMap, size_t crossMapSize);
-static void resizeCardMapAndCrossMap (GC_state s);
+static void copyCardMapAndCrossMap (GC_state s, GC_heap h);
+static void shrinkCardMapAndCrossMap (GC_state s, size_t keep);
+static void remapCardMapAndCrossMap (GC_state s, pointer orig);
 
 #if ASSERT
 static bool isCrossMapOk (GC_state s);

Modified: mlton/trunk/runtime/gc/heap.c
===================================================================
--- mlton/trunk/runtime/gc/heap.c	2008-08-20 00:08:27 UTC (rev 6772)
+++ mlton/trunk/runtime/gc/heap.c	2008-08-20 00:43:27 UTC (rev 6773)
@@ -114,7 +114,7 @@
              "[GC: Releasing heap at "FMTPTR" of size %s bytes.]\n",
              (uintptr_t)(h->start),
              uintmaxToCommaString(h->size));
-  GC_release (h->start, h->size);
+  GC_release (h->start, h->size + computeCardMapAndCrossMapSize(s, h->size));
   initHeap (s, h);
 }
 
@@ -126,13 +126,17 @@
   }
   keep = align (keep, s->sysvals.pageSize);
   if (keep < h->size) {
+    size_t oldMapSize, newMapSize;
     if (DEBUG or s->controls.messages)
       fprintf (stderr,
                "[GC: Shrinking heap at "FMTPTR" of size %s bytes to size %s bytes.]\n",
                (uintptr_t)(h->start),
                uintmaxToCommaString(h->size),
                uintmaxToCommaString(keep));
-    GC_decommit (h->start + keep, h->size - keep);
+    shrinkCardMapAndCrossMap(s, keep);
+    oldMapSize = computeCardMapAndCrossMapSize(s, h->size);
+    newMapSize = computeCardMapAndCrossMapSize(s, keep);
+    GC_decommit (h->start + keep + newMapSize, h->size - keep + oldMapSize - newMapSize);
     h->size = keep;
   }
 }
@@ -149,6 +153,7 @@
                  size_t minSize) {
   size_t backoff;
   size_t newSize;
+  size_t newWithMapsSize;
 
   if (DEBUG_MEM)
     fprintf (stderr, "createHeap  desired size = %s  min size = %s\n",
@@ -183,8 +188,10 @@
     static bool direction = TRUE;
     unsigned int i;
 
-    assert (isAligned (newSize, s->sysvals.pageSize));
+    newWithMapsSize = newSize + computeCardMapAndCrossMapSize (s, newSize);
 
+    assert (isAligned (newWithMapsSize, s->sysvals.pageSize));
+
     for (i = 1; i <= count; i++) {
       size_t address;
       pointer newStart;
@@ -196,7 +203,7 @@
       if (i == count)
         address = 0;
 
-      newStart = GC_mmapAnon ((pointer)address, newSize);
+      newStart = GC_mmapAnon ((pointer)address, newWithMapsSize);
       unless ((void*)-1 == newStart) {
         direction = not direction;
         h->start = newStart;
@@ -249,7 +256,9 @@
                 size_t minSize) {
   size_t backoff;
   size_t newSize;
+  size_t newWithMapsSize;
   size_t origSize;
+  size_t origWithMapsSize;
 
 #if not HAS_REMAP
   return FALSE;
@@ -260,19 +269,23 @@
              uintmaxToCommaString(minSize));
   assert (minSize <= desiredSize);
   assert (desiredSize >= h->size);
+  minSize = align (minSize, s->sysvals.pageSize);
   desiredSize = align (desiredSize, s->sysvals.pageSize);
   backoff = (desiredSize - minSize) / 20;
   if (0 == backoff)
     backoff = 1; /* enough to terminate the loop below */
   backoff = align (backoff, s->sysvals.pageSize);
   origSize = h->size;
+  origWithMapsSize = origSize + computeCardMapAndCrossMapSize (s, origSize);
   newSize = desiredSize;
   do {
     pointer newStart;
 
-    assert (isAligned (newSize, s->sysvals.pageSize));
+    newWithMapsSize = newSize + computeCardMapAndCrossMapSize (s, newSize);
 
-    newStart = GC_mremap (h->start, origSize, newSize);
+    assert (isAligned (newWithMapsSize, s->sysvals.pageSize));
+
+    newStart = GC_mremap (h->start, origWithMapsSize, newWithMapsSize);
     unless ((void*)-1 == newStart) {
       h->start = newStart;
       h->size = newSize;
@@ -319,6 +332,10 @@
   size_t size;
 
   assert (desiredSize >= s->heap.size);
+  /* Now the card/cross map is stored at the end of the heap buffer, make sure we
+     won't actually shrink the heap. */
+  if (minSize < s->heap.size)
+    minSize = s->heap.size;
   if (DEBUG_RESIZING or s->controls.messages) {
     fprintf (stderr,
              "[GC: Growing heap at "FMTPTR" of size %s bytes,]\n",
@@ -333,8 +350,10 @@
   orig = curHeapp->start;
   size = curHeapp->oldGenSize;
   assert (size <= s->heap.size);
-  if (remapHeap (s, curHeapp, desiredSize, minSize))
+  if (remapHeap (s, curHeapp, desiredSize, minSize)) {
+    remapCardMapAndCrossMap (s, orig);
     goto done;
+  }
   shrinkHeap (s, curHeapp, size);
   initHeap (s, &newHeap);
   /* Allocate a space of the desired size. */
@@ -346,21 +365,26 @@
     from = curHeapp->start + size;
     to = newHeap.start + size;
     remaining = size;
+    copyCardMapAndCrossMap(s, &newHeap);
+    GC_decommit(orig + curHeapp->size, computeCardMapAndCrossMapSize(s, curHeapp->size));
 copy:
     assert (remaining == (size_t)(from - curHeapp->start)
             and from >= curHeapp->start
             and to >= newHeap.start);
     if (remaining < COPY_CHUNK_SIZE) {
       GC_memcpy (orig, newHeap.start, remaining);
+      GC_release (orig, curHeapp->size);
     } else {
+      size_t keep;
       remaining -= COPY_CHUNK_SIZE;
       from -= COPY_CHUNK_SIZE;
       to -= COPY_CHUNK_SIZE;
       GC_memcpy (from, to, COPY_CHUNK_SIZE);
-      shrinkHeap (s, curHeapp, remaining);
+      keep = align (remaining, s->sysvals.pageSize);
+      GC_decommit (orig + keep, (size_t)(curHeapp->size - keep));
+      curHeapp->size = keep;
       goto copy;
     }
-    releaseHeap (s, curHeapp);
     newHeap.oldGenSize = size;
     *curHeapp = newHeap;
   } else if (s->controls.mayPageHeap) {
@@ -375,7 +399,6 @@
     }
     data = GC_diskBack_write (orig, size);
     releaseHeap (s, curHeapp);
-    releaseCardMapAndCrossMap (s);
     if (createHeap (s, curHeapp, desiredSize, minSize)) {
       if (DEBUG or s->controls.messages) {
         fprintf (stderr,
@@ -421,13 +444,12 @@
              uintmaxToCommaString(s->heap.size));
   desiredSize = sizeofHeapDesired (s, minSize, s->heap.size);
   assert (minSize <= desiredSize);
-  if (desiredSize <= s->heap.size)
+  if (desiredSize <= s->heap.size) {
     shrinkHeap (s, &s->heap, desiredSize);
-  else {
+  } else {
     releaseHeap (s, &s->secondaryHeap);
     growHeap (s, desiredSize, minSize);
   }
-  resizeCardMapAndCrossMap (s);
   assert (s->heap.size >= minSize);
 }
 

Modified: mlton/trunk/runtime/gc/virtual-memory.c
===================================================================
--- mlton/trunk/runtime/gc/virtual-memory.c	2008-08-20 00:08:27 UTC (rev 6772)
+++ mlton/trunk/runtime/gc/virtual-memory.c	2008-08-20 00:43:27 UTC (rev 6773)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999-2007 Henry Cejtin, Matthew Fluet, Suresh
+/* Copyright (C) 1999-2008 Henry Cejtin, Matthew Fluet, Suresh
  *    Jagannathan, and Stephen Weeks.
  * Copyright (C) 1997-2000 NEC Research Institute.
  *
@@ -12,7 +12,7 @@
         result = GC_mmapAnon (p, length);
         if ((void*)-1 == result) {
                 GC_displayMem ();
-                die ("Out of memory.");
+                die ("Out of memory (2).  Unable to allocate %s bytes.\n", uintmaxToCommaString(length));
         }
         return result;
 }
@@ -29,3 +29,10 @@
     return;
   memcpy (dst, src, size);
 }
+
+static inline void GC_memmove (pointer src, pointer dst, size_t size) {
+  if (DEBUG_DETAILED)
+    fprintf (stderr, "GC_memmove ("FMTPTR", "FMTPTR", %"PRIuMAX")\n",
+             (uintptr_t)src, (uintptr_t)dst, (uintmax_t)size);
+  memmove (dst, src, size);
+}

Modified: mlton/trunk/runtime/gc.h
===================================================================
--- mlton/trunk/runtime/gc.h	2008-08-20 00:08:27 UTC (rev 6772)
+++ mlton/trunk/runtime/gc.h	2008-08-20 00:43:27 UTC (rev 6773)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999-2007 Henry Cejtin, Matthew Fluet, Suresh
+/* Copyright (C) 1999-2008 Henry Cejtin, Matthew Fluet, Suresh
  *    Jagannathan, and Stephen Weeks.
  * Copyright (C) 1997-2000 NEC Research Institute.
  *
@@ -38,8 +38,8 @@
 #include "gc/int-inf.h"
 #include "gc/string.h"
 #include "gc/object-size.h"
+#include "gc/heap.h"
 #include "gc/generational.h"
-#include "gc/heap.h"
 #include "gc/current.h"
 #include "gc/foreach.h"
 #include "gc/translate.h"




More information about the MLton-commit mailing list