[MLton-commit] r6569

Matthew Fluet fluet at mlton.org
Mon Apr 7 11:56:04 PDT 2008


Apply stack resizing policy during mark-compact GC.

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

U   mlton/trunk/runtime/gc/mark-compact.c
U   mlton/trunk/runtime/gc/mark-compact.h

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

Modified: mlton/trunk/runtime/gc/mark-compact.c
===================================================================
--- mlton/trunk/runtime/gc/mark-compact.c	2008-04-07 18:56:01 UTC (rev 6568)
+++ mlton/trunk/runtime/gc/mark-compact.c	2008-04-07 18:56:03 UTC (rev 6569)
@@ -87,7 +87,7 @@
   s->weaks = NULL;
 }
 
-void updateForwardPointersForMarkCompact (GC_state s) {
+void updateForwardPointersForMarkCompact (GC_state s, GC_stack currentStack) {
   pointer back;
   pointer endOfLastMarked;
   pointer front;
@@ -95,14 +95,14 @@
   GC_header header;
   GC_header *headerp;
   pointer p;
-  size_t size;
+  size_t size, skipFront, skipGap;
 
   if (DEBUG_MARK_COMPACT)
     fprintf (stderr, "Update forward pointers.\n");
   front = alignFrontier (s, s->heap.start);
   back = s->heap.start + s->heap.oldGenSize;
+  gap = 0;
   endOfLastMarked = front;
-  gap = 0;
 updateObject:
   if (DEBUG_MARK_COMPACT)
     fprintf (stderr, "updateObject  front = "FMTPTR"  back = "FMTPTR"\n",
@@ -119,7 +119,78 @@
        * Thread internal pointers.
        */
 thread:
-      size = sizeofObject (s, p);
+      assert (GC_VALID_HEADER_MASK & header);
+      assert (MARK_MASK & header);
+
+      size_t headerBytes, objectBytes;
+      GC_objectTypeTag tag;
+      uint16_t bytesNonObjptrs, numObjptrs;
+
+      assert (header == getHeader (p));
+      splitHeader(s, header, &tag, NULL, &bytesNonObjptrs, &numObjptrs);
+
+      /* Compute the space taken by the header and object body. */
+      if ((NORMAL_TAG == tag) or (WEAK_TAG == tag)) { /* Fixed size object. */
+        headerBytes = GC_NORMAL_HEADER_SIZE;
+        objectBytes = bytesNonObjptrs + (numObjptrs * OBJPTR_SIZE);
+        skipFront = 0;
+        skipGap = 0;
+      } else if (ARRAY_TAG == tag) {
+        headerBytes = GC_ARRAY_HEADER_SIZE;
+        objectBytes = sizeofArrayNoHeader (s, getArrayLength (p),
+                                           bytesNonObjptrs, numObjptrs);
+        skipFront = 0;
+        skipGap = 0;
+      } else { /* Stack. */
+        bool active;
+        GC_stack stack;
+
+        assert (STACK_TAG == tag);
+        headerBytes = GC_STACK_HEADER_SIZE;
+        stack = (GC_stack)p;
+        active = currentStack == stack;
+
+        size_t reservedMax, reservedShrink, reservedMin, reservedNew, reservedOld;
+
+        reservedOld = stack->reserved;
+        if (active) {
+          /* Shrink active stacks. */
+          reservedMax =
+            (size_t)(s->controls.ratios.stackCurrentMaxReserved * stack->used);
+          size_t reservedPermit =
+            (size_t)(s->controls.ratios.stackCurrentPermitReserved * stack->used);
+          reservedShrink =
+            (reservedPermit >= stack->reserved)
+            ? stack->reserved
+            : (size_t)(s->controls.ratios.stackCurrentShrink * stack->used);
+          reservedMin = sizeofStackMinimumReserved (s, stack);
+        } else {
+          /* Shrink paused stacks. */
+          reservedMax =
+            (size_t)(s->controls.ratios.stackMaxReserved * stack->used);
+          reservedShrink =
+            (size_t)(s->controls.ratios.stackShrink * stack->reserved);
+          reservedMin= stack->used;
+        }
+        reservedNew =
+          alignStackReserved
+          (s, max(min(reservedMax,reservedShrink),reservedMin));
+        /* It's possible that new > stack->reserved for the active stack
+         * if the stack invariant is violated.  In that case, we want to
+         * leave the stack alone, because some other part of the gc will
+         * grow the stack.  We cannot do any growing here because we may
+         * run out of to space.
+         */
+        assert (active or reservedNew <= stack->reserved);
+        if (reservedNew < stack->reserved) {
+        } else {
+          reservedNew = stack->reserved;
+        }
+        objectBytes = sizeof (struct GC_stack) + stack->used;
+        skipFront = reservedOld - stack->used;
+        skipGap = reservedOld - reservedNew;
+      }
+      size = headerBytes + objectBytes;
       if (DEBUG_MARK_COMPACT)
         fprintf (stderr, "threading "FMTPTR" of size %"PRIuMAX"\n",
                  (uintptr_t)p, (uintmax_t)size);
@@ -145,7 +216,8 @@
         newArray += GC_ARRAY_LENGTH_SIZE;
         *((GC_header*)(newArray)) = GC_WORD8_VECTOR_HEADER;
       }
-      front += size;
+      gap += skipGap;
+      front += size + skipFront;
       endOfLastMarked = front;
       foreachObjptrInObject (s, p, threadInternalObjptr, FALSE);
       goto updateObject;
@@ -186,14 +258,14 @@
   return;
 }
 
-void updateBackwardPointersAndSlideForMarkCompact (GC_state s) {
+void updateBackwardPointersAndSlideForMarkCompact (GC_state s, GC_stack currentStack) {
   pointer back;
   pointer front;
   size_t gap;
   GC_header header;
   GC_header *headerp;
   pointer p;
-  size_t size;
+  size_t size, skipFront, skipGap;
 
   if (DEBUG_MARK_COMPACT)
     fprintf (stderr, "Update backward pointers and slide.\n");
@@ -216,7 +288,85 @@
        * Unmark it.
        */
 unmark:
-      size = sizeofObject (s, p);
+      assert (GC_VALID_HEADER_MASK & header);
+      assert (MARK_MASK & header);
+
+      size_t headerBytes, objectBytes;
+      GC_objectTypeTag tag;
+      uint16_t bytesNonObjptrs, numObjptrs;
+
+      assert (header == getHeader (p));
+      splitHeader(s, header, &tag, NULL, &bytesNonObjptrs, &numObjptrs);
+
+      /* Compute the space taken by the header and object body. */
+      if ((NORMAL_TAG == tag) or (WEAK_TAG == tag)) { /* Fixed size object. */
+        headerBytes = GC_NORMAL_HEADER_SIZE;
+        objectBytes = bytesNonObjptrs + (numObjptrs * OBJPTR_SIZE);
+        skipFront = 0;
+        skipGap = 0;
+      } else if (ARRAY_TAG == tag) {
+        headerBytes = GC_ARRAY_HEADER_SIZE;
+        objectBytes = sizeofArrayNoHeader (s, getArrayLength (p),
+                                           bytesNonObjptrs, numObjptrs);
+        skipFront = 0;
+        skipGap = 0;
+      } else { /* Stack. */
+        bool active;
+        GC_stack stack;
+
+        assert (STACK_TAG == tag);
+        headerBytes = GC_STACK_HEADER_SIZE;
+        stack = (GC_stack)p;
+        active = currentStack == stack;
+
+        size_t reservedMax, reservedShrink, reservedMin, reservedNew, reservedOld;
+
+        reservedOld = stack->reserved;
+        if (active) {
+          /* Shrink active stacks. */
+          reservedMax =
+            (size_t)(s->controls.ratios.stackCurrentMaxReserved * stack->used);
+          size_t reservedPermit =
+            (size_t)(s->controls.ratios.stackCurrentPermitReserved * stack->used);
+          reservedShrink =
+            (reservedPermit >= stack->reserved)
+            ? stack->reserved
+            : (size_t)(s->controls.ratios.stackCurrentShrink * stack->used);
+          reservedMin = sizeofStackMinimumReserved (s, stack);
+        } else {
+          /* Shrink paused stacks. */
+          reservedMax =
+            (size_t)(s->controls.ratios.stackMaxReserved * stack->used);
+          reservedShrink =
+            (size_t)(s->controls.ratios.stackShrink * stack->reserved);
+          reservedMin= stack->used;
+        }
+        reservedNew =
+          alignStackReserved
+          (s, max(min(reservedMax,reservedShrink),reservedMin));
+        /* It's possible that new > stack->reserved for the active stack
+         * if the stack invariant is violated.  In that case, we want to
+         * leave the stack alone, because some other part of the gc will
+         * grow the stack.  We cannot do any growing here because we may
+         * run out of to space.
+         */
+        assert (active or reservedNew <= stack->reserved);
+        if (reservedNew < stack->reserved) {
+          if (DEBUG_STACKS or s->controls.messages)
+            fprintf (stderr,
+                     "[GC: Shrinking stack of size %s bytes to size %s bytes, using %s bytes.]\n",
+                     uintmaxToCommaString(stack->reserved),
+                     uintmaxToCommaString(reservedNew),
+                     uintmaxToCommaString(stack->used));
+          stack->reserved = reservedNew;
+        } else {
+          reservedNew = stack->reserved;
+        }
+        objectBytes = sizeof (struct GC_stack) + stack->used;
+        skipFront = reservedOld - stack->used;
+        skipGap = reservedOld - reservedNew;
+      }
+      size = headerBytes + objectBytes;
       /* unmark */
       if (DEBUG_MARK_COMPACT)
         fprintf (stderr, "unmarking "FMTPTR" of size %"PRIuMAX"\n",
@@ -227,7 +377,8 @@
         fprintf (stderr, "sliding "FMTPTR" down %"PRIuMAX"\n",
                  (uintptr_t)front, (uintmax_t)gap);
       GC_memcpy (front, front - gap, size);
-      front += size;
+      gap += skipGap;
+      front += size + skipFront;
       goto updateObject;
     } else {
       /* It's not marked. */
@@ -276,6 +427,7 @@
 void majorMarkCompactGC (GC_state s) {
   size_t bytesHashConsed;
   size_t bytesMarkCompacted;
+  GC_stack currentStack;
   struct rusage ru_start;
 
   if (detailedGCTime (s))
@@ -289,6 +441,7 @@
              (uintptr_t)(s->heap.start),
              uintmaxToCommaString(s->heap.size));
   }
+  currentStack = getStackCurrent (s);
   if (s->hashConsDuringGC) {
     s->lastMajorStatistics.bytesHashConsed = 0;
     s->cumulativeStatistics.numHashConsGCs++;
@@ -300,8 +453,8 @@
   }
   updateWeaksForMarkCompact (s);
   foreachGlobalObjptr (s, threadInternalObjptr);
-  updateForwardPointersForMarkCompact (s);
-  updateBackwardPointersAndSlideForMarkCompact (s);
+  updateForwardPointersForMarkCompact (s, currentStack);
+  updateBackwardPointersAndSlideForMarkCompact (s, currentStack);
   clearCrossMap (s);
   bytesHashConsed = s->lastMajorStatistics.bytesHashConsed;
   s->cumulativeStatistics.bytesHashConsed += bytesHashConsed;

Modified: mlton/trunk/runtime/gc/mark-compact.h
===================================================================
--- mlton/trunk/runtime/gc/mark-compact.h	2008-04-07 18:56:01 UTC (rev 6568)
+++ mlton/trunk/runtime/gc/mark-compact.h	2008-04-07 18:56:03 UTC (rev 6569)
@@ -11,8 +11,8 @@
 static inline void copyForThreadInternal (pointer dst, pointer src);
 static inline void threadInternalObjptr (GC_state s, objptr *opp);
 static inline void updateWeaksForMarkCompact (GC_state s);
-static void updateForwardPointersForMarkCompact (GC_state s);
-static void updateBackwardPointersAndSlideForMarkCompact (GC_state s);
+static void updateForwardPointersForMarkCompact (GC_state s, GC_stack currentStack);
+static void updateBackwardPointersAndSlideForMarkCompact (GC_state s, GC_stack currentStack);
 static void majorMarkCompactGC (GC_state s);
 
 #endif /* (defined (MLTON_GC_INTERNAL_FUNCS)) */




More information about the MLton-commit mailing list