[MLton-commit] r4098

Matthew Fluet MLton@mlton.org
Sat, 8 Oct 2005 13:36:27 -0700


More invariant and heap functions
----------------------------------------------------------------------

U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/TODO
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/align.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/cheney-copy.c
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/control.h
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/current.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/debug.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/foreach.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_state.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_state.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/generational.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/major.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/object.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/pointer.h
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.c
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/statistics.h
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/sysvals.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/thread.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/virtual-memory.h

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

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile	2005-10-08 20:36:15 UTC (rev 4098)
@@ -49,14 +49,24 @@
 endif
 
 CC = gcc -std=gnu99
-CWFLAGS = -Wall -pedantic -Wextra -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wconversion -Wsign-compare -Wstrict-prototypes -Wredundant-decls -Winline
-CWFLAGS = -pedantic -Wall -Wextra -Wno-unused \
-##	-Wshadow \
+CWFLAGS = -pedantic -Wall -Wextra -Wno-unused-parameter \
+	-Wformat-nonliteral \
+	-Wuninitialized -Winit-self \
+	-Wstrict-aliasing=2 \
+	-Wfloat-equal \
+	-Wpointer-arith \
+	-Wbad-function-cast -Wcast-qual -Wcast-align \
+	-Waggregate-return \
+	-Wstrict-prototypes \
+	-Wmissing-noreturn -Wmissing-format-attribute \
+	-Wpacked \
 	-Wredundant-decls \
-	-Wpointer-arith -Wcast-qual -Wcast-align \
-##	-Wconversion \
-	-Wstrict-prototypes \
-	-Winline
+	-Wnested-externs 
+##	-Wshadow
+##	-Wconversion 
+##	-Wmissing-prototypes
+##	-Wmissing-declarations
+##	-Winline -Wdisabled-optimization
 CFLAGS = -O2 $(CWFLAGS) -I. -D_FILE_OFFSET_BITS=64 $(FLAGS)
 DEBUGFLAGS = $(CFLAGS) -Wunused -gstabs+ -g2
 
@@ -74,9 +84,11 @@
 	thread.c							\
 	generational.c							\
 	heap.c   							\
+	ratios.c   							\
 	gc_state.c   							\
+	current.c   							\
+	foreach.c							\
 	invariant.c   							\
-	foreach.c							\
 	cheney-copy.c							\
 	assumptions.c							\
 	gc_suffix.c
@@ -98,6 +110,9 @@
 	generational.h							\
 	statistics.h							\
 	heap.h								\
+	control.h							\
+	sysvals.h							\
+	ratios.h							\
 	gc_state.h							\
 	gc_suffix.h
 

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/TODO
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/TODO	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/TODO	2005-10-08 20:36:15 UTC (rev 4098)
@@ -15,3 +15,5 @@
         codegen in thread.h is still true; it used to be the case when
         GC_switchToThread was implemented in codegens.  Now it should
         be implemented in Backend.
+* the "skipObjects" loop in forwardInterGenerationalObjptrs appears to
+        be unnecessary.

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/align.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/align.c	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/align.c	2005-10-08 20:36:15 UTC (rev 4098)
@@ -6,6 +6,10 @@
  * See the file MLton-LICENSE for details.
  */
 
+static inline size_t roundDown (size_t a, size_t b) {
+  return a - (a % b);
+}
+
 static inline size_t align (size_t a, size_t b) {
   assert (b >= 1);
   a += b - 1;
@@ -36,12 +40,10 @@
   return isAligned ((uintptr_t)p + GC_NORMAL_HEADER_SIZE, s->alignment);
 }
 
-/*
-static bool isAlignedReserved (GC_state s, uint r) {
-  return isAligned (STACK_HEADER_SIZE + sizeof (struct GC_stack) + r, 
+static bool isAlignedReserved (GC_state s, size_t reserved) {
+  return isAligned (GC_STACK_HEADER_SIZE + sizeof (struct GC_stack) + reserved, 
                     s->alignment);
 }
-*/
 #endif
 
 static inline size_t pad (GC_state s, size_t bytes, size_t extra) {
@@ -49,7 +51,11 @@
 }
 
 static inline pointer alignFrontier (GC_state s, pointer p) {
-  return (pointer) pad (s, (size_t)p, GC_NORMAL_HEADER_SIZE);
+  size_t bytes, res;
+
+  bytes = (size_t) p;
+  res = pad (s, (size_t)p, GC_NORMAL_HEADER_SIZE);
+  return (pointer)res;
 }
 
 pointer GC_alignFrontier (GC_state s, pointer p) {

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.c	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.c	2005-10-08 20:36:15 UTC (rev 4098)
@@ -42,7 +42,7 @@
   GC_arrayLength numElements;
   size_t result;
         
-  numElements = arrayNumElements (p);
+  numElements = getArrayLength (p);
   bytesPerElement = 
     numNonObjptrsToBytes(numNonObjptrs, ARRAY_TAG) 
     + (numObjptrs * OBJPTR_SIZE);

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.h	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.h	2005-10-08 20:36:15 UTC (rev 4098)
@@ -23,10 +23,18 @@
 #define GC_ARRAY_COUNTER_SIZE GC_ARRAY_LENGTH_SIZE
 #define GC_ARRAY_HEADER_SIZE (GC_ARRAY_COUNTER_SIZE + GC_ARRAY_LENGTH_SIZE + GC_HEADER_SIZE)
 
-static inline GC_arrayLength* arrayNumElementsp (pointer a) {
+/* getArrayNumElementsp (p)
+ *
+ * Returns a pointer to the length for the array pointed to by p.
+ */
+static inline GC_arrayLength* getArrayLengthp (pointer a) {
   return (GC_arrayLength*)(a - GC_HEADER_SIZE - GC_ARRAY_LENGTH_SIZE);
 }
 
-static inline GC_arrayLength arrayNumElements (pointer a) {
-  return *(arrayNumElementsp (a));
+/* getArrayNumElements (p)
+ *
+ * Returns the length for the array pointed to by p.
+ */
+static inline GC_arrayLength getArrayLength (pointer a) {
+  return *(getArrayLengthp (a));
 }

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/cheney-copy.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/cheney-copy.c	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/cheney-copy.c	2005-10-08 20:36:15 UTC (rev 4098)
@@ -24,14 +24,6 @@
 };
 static struct forwardState forwardState;
 
-static inline bool pointerIsInFromSpace (GC_state s, pointer p) {
-  return (pointerIsInOldGen (s, p) or pointerIsInNursery (s, p));
-}
-
-static inline bool objptrIsInFromSpace (GC_state s, objptr op) {
-  return (objptrIsInOldGen (s, op) or objptrIsInNursery (s, op));
-}
-
 static inline bool pointerIsInToSpace (pointer p) {
   return (not (isPointer (p))
           or (forwardState.toStart <= p and p < forwardState.toLimit));
@@ -87,7 +79,7 @@
       headerBytes = GC_STACK_HEADER_SIZE;
       stack = (GC_stack)p;
 
-      if (currentThreadStack(s) == op) {
+      if (currentThreadStackObjptr(s) == op) {
         /* Shrink stacks that don't use a lot of their reserved space;
          * but don't violate the stack invariant.
          */
@@ -111,7 +103,7 @@
       } else {
         /* Shrink heap stacks. */
         stack->reserved = 
-          stackReserved (s, maxZ((size_t)(s->threadShrinkRatio * stack->reserved),
+          stackReserved (s, maxZ((size_t)(s->ratios.threadShrink * stack->reserved),
                                  stack->used));
         if (DEBUG_STACKS)
           fprintf (stderr, "Shrinking stack to size %zd.\n",
@@ -204,7 +196,7 @@
   assert (s->secondaryHeap.size >= s->heap.oldGenSize);
 /*   if (detailedGCTime (s)) */
 /*     startTiming (&ru_start); */
-  s->cumulative.numCopyingGCs++;
+  s->cumulativeStatistics.numCopyingGCs++;
   forwardState.toStart = s->secondaryHeap.start;
   forwardState.toLimit = s->secondaryHeap.start + s->secondaryHeap.size;
   if (DEBUG or s->messages) {
@@ -229,13 +221,13 @@
   foreachObjptrInRange (s, toStart, &forwardState.back, TRUE, forward);
   updateWeaks (s);
   s->secondaryHeap.oldGenSize = forwardState.back - s->secondaryHeap.start;
-  s->cumulative.bytesCopied += s->secondaryHeap.oldGenSize;
+  s->cumulativeStatistics.bytesCopied += s->secondaryHeap.oldGenSize;
   if (DEBUG)
     fprintf (stderr, "%zd bytes live.\n",
              /*uintToCommaString*/(s->secondaryHeap.oldGenSize));
   swapHeaps (s);
   clearCrossMap (s);
-  s->lastMajor.kind = GC_COPYING;
+  s->lastMajorStatistics.kind = GC_COPYING;
 /*   if (detailedGCTime (s)) */
 /*     stopTiming (&ru_start, &s->ru_gcCopy); */
   if (DEBUG or s->messages)
@@ -276,8 +268,8 @@
     fprintf (stderr, "Forwarding inter-generational pointers.\n");
   updateCrossMap (s);
   /* Constants. */
-  cardMap = s->generational.cardMap;
-  crossMap = s->generational.crossMap;
+  cardMap = s->generationalMaps.cardMap;
+  crossMap = s->generationalMaps.crossMap;
   maxCardIndex = sizeToCardIndex (align (s->heap.oldGenSize, CARD_SIZE));
   oldGenStart = s->heap.start;
   oldGenEnd = oldGenStart + s->heap.oldGenSize;
@@ -299,7 +291,7 @@
     pointer lastObject;
     size_t size;
     
-    s->cumulative.markedCards++;
+    s->cumulativeStatistics.markedCards++;
     if (DEBUG_GENERATIONAL)
       fprintf (stderr, "card %zu is marked  objectStart = "FMTPTR"\n", 
                cardIndex, (uintptr_t)objectStart);
@@ -311,7 +303,7 @@
       objectStart += size;
       goto skipObjects;
     }
-    s->cumulative.minorBytesSkipped += objectStart - lastObject;
+    s->cumulativeStatistics.minorBytesSkipped += objectStart - lastObject;
     cardEnd = cardStart + CARD_SIZE;
     if (oldGenEnd < cardEnd) 
       cardEnd = oldGenEnd;
@@ -325,7 +317,7 @@
      */
     objectStart = foreachObjptrInRange (s, objectStart, &cardEnd, 
                                         FALSE, forwardIfInNursery);
-    s->cumulative.minorBytesScanned += objectStart - lastObject;
+    s->cumulativeStatistics.minorBytesScanned += objectStart - lastObject;
     if (objectStart == oldGenEnd)
       goto done;
     cardIndex = sizeToCardIndex (objectStart - oldGenStart);
@@ -363,7 +355,7 @@
   bytesAllocated = s->frontier - s->heap.nursery;
   if (bytesAllocated == 0)
     return;
-  s->cumulative.bytesAllocated += bytesAllocated;
+  s->cumulativeStatistics.bytesAllocated += bytesAllocated;
   if (not s->canMinor) {
     s->heap.oldGenSize += bytesAllocated;
     bytesCopied = 0;
@@ -379,8 +371,8 @@
     assert (isAlignedFrontier (s, forwardState.toStart));
     forwardState.toLimit = forwardState.toStart + bytesAllocated;
     assert (invariant (s));
-    s->cumulative.numMinorGCs++;
-    s->lastMajor.numMinorsGCs++;
+    s->cumulativeStatistics.numMinorGCs++;
+    s->lastMajorStatistics.numMinorsGCs++;
     forwardState.back = forwardState.toStart;
     /* Forward all globals.  Would like to avoid doing this once all
      * the globals have been assigned.
@@ -391,7 +383,7 @@
                           TRUE, forwardIfInNursery);
     updateWeaks (s);
     bytesCopied = forwardState.back - forwardState.toStart;
-    s->cumulative.bytesCopiedMinor += bytesCopied;
+    s->cumulativeStatistics.bytesCopiedMinor += bytesCopied;
     s->heap.oldGenSize += bytesCopied;
     s->amInMinorGC = FALSE;
 /*     if (detailedGCTime (s)) */

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/control.h (from rev 4097, mlton/branches/on-20050822-x86_64-branch/runtime/gc.h)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc.h	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/control.h	2005-10-08 20:36:15 UTC (rev 4098)
@@ -0,0 +1,12 @@
+/* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
+ *    Jagannathan, and Stephen Weeks.
+ * Copyright (C) 1997-2000 NEC Research Institute.
+ *
+ * MLton is released under a BSD-style license.
+ * See the file MLton-LICENSE for details.
+ */
+
+struct GC_control {
+  size_t fixedHeap; /* If 0, then no fixed heap. */
+  size_t maxHeap; /* if zero, then unlimited, else limit total heap */
+};

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/current.c (from rev 4097, mlton/branches/on-20050822-x86_64-branch/runtime/gc.c)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc.c	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/current.c	2005-10-08 20:36:15 UTC (rev 4098)
@@ -0,0 +1,30 @@
+/* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
+ *    Jagannathan, and Stephen Weeks.
+ * Copyright (C) 1997-2000 NEC Research Institute.
+ *
+ * MLton is released under a BSD-style license.
+ * See the file MLton-LICENSE for details.
+ */
+
+static inline objptr currentThreadObjptr (GC_state s) {
+  return s->currentThread;
+}
+
+static inline GC_thread currentThread (GC_state s) {
+  pointer p = objptrToPointer(currentThreadObjptr(s), s->heap.start);
+  return (GC_thread)p;
+}
+
+static inline objptr currentThreadStackObjptr (GC_state s) {
+  GC_thread ct = currentThread (s);
+  return ct->stack;
+}
+
+static inline GC_stack currentThreadStack (GC_state s) {
+  pointer p = objptrToPointer(currentThreadStackObjptr(s), s->heap.start);
+  return (GC_stack)p;
+}
+
+static inline size_t currentStackUsed (GC_state s) {
+  return s->stackTop - s->stackBottom;
+}

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/debug.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/debug.c	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/debug.c	2005-10-08 20:36:15 UTC (rev 4098)
@@ -11,20 +11,22 @@
 #endif
 
 enum {
-        DEBUG_ARRAY = FALSE,
-        DEBUG_CALL_STACK = FALSE,
-        DEBUG_CARD_MARKING = FALSE,
-        DEBUG_DETAILED = FALSE,
-        DEBUG_ENTER_LEAVE = FALSE,
-        DEBUG_GENERATIONAL = FALSE,
-        DEBUG_MARK_COMPACT = FALSE,
-        DEBUG_MEM = FALSE,
-        DEBUG_PROFILE = FALSE,
-        DEBUG_RESIZING = FALSE,
-        DEBUG_SHARE = FALSE,
-        DEBUG_SIZE = FALSE,
-        DEBUG_STACKS = FALSE,
-        DEBUG_THREADS = FALSE,
-        DEBUG_WEAK = FALSE,
-        DEBUG_WORLD = FALSE,
+  DEBUG_ARRAY = FALSE,
+  DEBUG_CALL_STACK = FALSE,
+  DEBUG_CARD_MARKING = FALSE,
+  DEBUG_DETAILED = FALSE,
+  DEBUG_ENTER_LEAVE = FALSE,
+  DEBUG_GENERATIONAL = FALSE,
+  DEBUG_MARK_COMPACT = FALSE,
+  DEBUG_MEM = FALSE,
+  DEBUG_PROFILE = FALSE,
+  DEBUG_RESIZING = FALSE,
+  DEBUG_SHARE = FALSE,
+  DEBUG_SIZE = FALSE,
+  DEBUG_STACKS = FALSE,
+  DEBUG_THREADS = FALSE,
+  DEBUG_WEAK = FALSE,
+  DEBUG_WORLD = FALSE,
+  FORCE_GENERATIONAL = FALSE,
+  FORCE_MARK_COMPACT = FALSE,
 };

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/foreach.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/foreach.c	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/foreach.c	2005-10-08 20:36:15 UTC (rev 4098)
@@ -27,10 +27,10 @@
   }
   if (DEBUG_DETAILED)
     fprintf (stderr, "foreachGlobal threads\n");
-  maybeCall (f, s, &s->callFromCHandler);
+  maybeCall (f, s, &s->callFromCHandlerThread);
   maybeCall (f, s, &s->currentThread);
   maybeCall (f, s, &s->savedThread);
-  maybeCall (f, s, &s->signalHandler);
+  maybeCall (f, s, &s->signalHandlerThread);
 }
 
 
@@ -84,7 +84,7 @@
     pointer max;
     GC_arrayLength numElements;
     
-    numElements = arrayNumElements (p);
+    numElements = getArrayLength (p);
     bytesPerElement = 
       numNonObjptrsToBytes(numNonObjptrs, ARRAY_TAG) 
       + (numObjptrs * OBJPTR_SIZE);

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.c	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.c	2005-10-08 20:36:15 UTC (rev 4098)
@@ -12,7 +12,7 @@
 
   res = s->returnAddressToFrameIndex (ra);
   if (DEBUG_DETAILED)
-    fprintf (stderr, "%"PRIu32" = getFrameIndex ("FMTRA")\n",
+    fprintf (stderr, "%"PRIu32" = getFrameIndexFromReturnAddress ("FMTRA")\n",
              res, ra);
   return res;
 }
@@ -23,7 +23,7 @@
 
   if (DEBUG_DETAILED)
     fprintf (stderr, 
-             "index = %"PRIx32
+             "index = %"PRIu32
              "  frameLayoutsLength = %"PRIu32"\n",
             index, s->frameLayoutsLength);
   assert (index < s->frameLayoutsLength);

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.h	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.h	2005-10-08 20:36:15 UTC (rev 4098)
@@ -16,10 +16,10 @@
  * 
  * The frameLayouts pointer is initialized to point to a static array
  * of frame layouts that is emitted for each compiled program.  The
- * isC field identified whether or not the frame is for a C
- * call. (Note: The ML stack is distinct from the system stack.  A C
- * call executes on the system stack.  The frame left on the ML stack
- * is just a marker.)  The size field indicates the size of the frame,
+ * kind field identifies whether or not the frame is for a C call.
+ * (Note: The ML stack is distinct from the system stack.  A C call
+ * executes on the system stack.  The frame left on the ML stack is
+ * just a marker.)  The size field indicates the size of the frame,
  * including space for the return address.  The offsets field points
  * to an array (the zeroeth element recording the size of the array)
  * whose elements record byte offsets from the bottom of the frame at
@@ -27,8 +27,13 @@
  */
 typedef uint16_t *GC_frameOffsets;
 
+typedef enum {
+  C_FRAME,
+  ML_FRAME
+} GC_frameKind;
+
 typedef struct GC_frameLayout {
-  bool isC;
+  GC_frameKind kind;
   uint16_t size;
   GC_frameOffsets offsets;
 } GC_frameLayout;

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_state.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_state.c	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_state.c	2005-10-08 20:36:15 UTC (rev 4098)
@@ -13,7 +13,7 @@
   displayThread (s, (GC_thread)(objptrToPointer (s->currentThread, s->heap.start)), 
                  stream);
   fprintf (stream, "\tgenerational\n");
-  displayGenerationalMaps (s, &s->generational, 
+  displayGenerationalMaps (s, &s->generationalMaps, 
                            stream);
   fprintf (stream, "\theap\n");
   displayHeap (s, &s->heap, 

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_state.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_state.h	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_state.h	2005-10-08 20:36:15 UTC (rev 4098)
@@ -3,35 +3,38 @@
   size_t alignment; /* */
   bool amInGC;
   bool amInMinorGC;
-  objptr callFromCHandler; /* Handler for exported C calls (in heap). */
+  objptr callFromCHandlerThread; /* Handler for exported C calls (in heap). */
   bool canMinor; /* TRUE iff there is space for a minor gc. */
-  struct GC_cumulativeStatistics cumulative;
+  struct GC_control control;
+  struct GC_cumulativeStatistics cumulativeStatistics;
   objptr currentThread; /* Currently executing thread (in heap). */
   GC_frameLayout *frameLayouts; /* Array of frame layouts. */
   uint32_t frameLayoutsLength; /* Cardinality of frameLayouts array. */
   pointer frontier; /* heap.start <= frontier < limit */
-  struct GC_generationalMaps generational;
+  struct GC_generationalMaps generationalMaps;
   objptr *globals;
   uint32_t globalsLength;
   struct GC_heap heap;
-  struct GC_lastMajorStatistics lastMajor;
+  struct GC_lastMajorStatistics lastMajorStatistics;
   pointer limit; /* limit = heap.start + heap.totalBytes */
   pointer limitPlusSlop; /* limit + LIMIT_SLOP */
   uint32_t maxFrameSize;
+  /*Bool*/bool messages; /* Print a message at the start and end of each gc. */
   /*Bool*/bool mutatorMarksCards;
   GC_objectType *objectTypes; /* Array of object types. */
   uint32_t objectTypesLength; /* Cardinality of objectTypes array. */
   size_t pageSize;
   uint32_t (*returnAddressToFrameIndex) (GC_returnAddress ra);
+  struct GC_ratios ratios;
   objptr savedThread; /* Result of GC_copyCurrentThread.
                        * Thread interrupted by arrival of signal.
                        */
   struct GC_heap secondaryHeap; /* Used for major copying collection. */
-  objptr signalHandler; /* Handler for signals (in heap). */
+  objptr signalHandlerThread; /* Handler for signals (in heap). */
   pointer stackBottom; /* Bottom of stack in current thread. */
+  pointer stackLimit; /* stackBottom + stackSize - maxFrameSize */
   pointer stackTop; /* Top of stack in current thread. */
   /*Bool*/bool summary; /* Print a summary of gc info when program exits. */
-  /*Bool*/bool messages; /* Print a message at the start and end of each gc. */
-  float threadShrinkRatio;
+  struct GC_sysvals sysvals;
   GC_weak weaks; /* Linked list of (live) weak pointers */
 } *GC_state;

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/generational.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/generational.c	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/generational.c	2005-10-08 20:36:15 UTC (rev 4098)
@@ -21,7 +21,7 @@
 static inline pointer pointerToCardMapAddr (GC_state s, pointer p) {
   pointer res;
   
-  res = &s->generational.cardMapAbsolute [pointerToCardIndex (p)];
+  res = &s->generationalMaps.cardMapAbsolute [pointerToCardIndex (p)];
   if (DEBUG_CARD_MARKING)
     fprintf (stderr, "pointerToCardMapAddr ("FMTPTR") = "FMTPTR"\n",
              (uintptr_t)p, (uintptr_t)res);
@@ -42,16 +42,16 @@
 static inline void clearCardMap (GC_state s) {
   if (DEBUG_GENERATIONAL and DEBUG_DETAILED)
     fprintf (stderr, "clearCardMap ()\n");
-  memset (s->generational.cardMap, 0, 
-          s->generational.cardMapLength * CARD_MAP_ELEM_SIZE);
+  memset (s->generationalMaps.cardMap, 0, 
+          s->generationalMaps.cardMapLength * CARD_MAP_ELEM_SIZE);
 }
 
 static inline void clearCrossMap (GC_state s) {
   if (DEBUG_GENERATIONAL and DEBUG_DETAILED)
     fprintf (stderr, "clearCrossMap ()\n");
-  s->generational.crossMapValidSize = 0;
-  memset (s->generational.crossMap, CROSS_MAP_EMPTY, 
-          s->generational.crossMapLength * CROSS_MAP_ELEM_SIZE);
+  s->generationalMaps.crossMapValidSize = 0;
+  memset (s->generationalMaps.crossMap, CROSS_MAP_EMPTY, 
+          s->generationalMaps.crossMapLength * CROSS_MAP_ELEM_SIZE);
 }
 
 static inline void setCardMapAbsolute (GC_state s) {
@@ -61,20 +61,20 @@
    * subsequent additions to mark the cards will overflow and put us
    * in the right place.
    */
-  s->generational.cardMapAbsolute = 
+  s->generationalMaps.cardMapAbsolute = 
     pointerToCardMapAddr (s, s->heap.start);
   if (DEBUG_CARD_MARKING)
     fprintf (stderr, "cardMapAbsolute = "FMTPTR"\n",
-             (uintptr_t)s->generational.cardMapAbsolute);
+             (uintptr_t)s->generationalMaps.cardMapAbsolute);
 }
 
 static inline void createCardMapAndCrossMap (GC_state s) {
   unless (s->mutatorMarksCards) {
-    s->generational.cardMapLength = 0;
-    s->generational.cardMap = NULL;
-    s->generational.cardMapAbsolute = NULL;
-    s->generational.crossMapLength = 0;
-    s->generational.crossMap = NULL;
+    s->generationalMaps.cardMapLength = 0;
+    s->generationalMaps.cardMap = NULL;
+    s->generationalMaps.cardMapAbsolute = NULL;
+    s->generationalMaps.crossMapLength = 0;
+    s->generationalMaps.crossMap = NULL;
     return;
   }
   assert (isAligned (s->heap.size, CARD_SIZE));
@@ -86,25 +86,25 @@
   cardMapLength = sizeToCardIndex (s->heap.size);
   cardMapSize = align (cardMapLength * CARD_MAP_ELEM_SIZE, s->pageSize);
   cardMapLength = cardMapSize / CARD_MAP_ELEM_SIZE;
-  s->generational.cardMapLength = cardMapLength;
+  s->generationalMaps.cardMapLength = cardMapLength;
 
   crossMapLength = sizeToCardIndex (s->heap.size);
   crossMapSize = align (crossMapLength * CROSS_MAP_ELEM_SIZE, s->pageSize);
   crossMapLength = crossMapSize / CROSS_MAP_ELEM_SIZE;
-  s->generational.crossMapLength = crossMapLength;
+  s->generationalMaps.crossMapLength = crossMapLength;
 
   totalMapSize = cardMapSize + crossMapSize;
   if (DEBUG_MEM)
     fprintf (stderr, "Creating card/cross map of size %zd\n",
              /*uintToCommaString*/(totalMapSize));
-  s->generational.cardMap = 
+  s->generationalMaps.cardMap = 
     GC_mmapAnon (totalMapSize);
-  s->generational.crossMap = 
-    (GC_crossMapElem*)((pointer)s->generational.cardMap + cardMapSize);
+  s->generationalMaps.crossMap = 
+    (GC_crossMapElem*)((pointer)s->generationalMaps.cardMap + cardMapSize);
   if (DEBUG_CARD_MARKING)
     fprintf (stderr, "cardMap = "FMTPTR"  crossMap = "FMTPTR"\n",
-             (uintptr_t)s->generational.cardMap,
-             (uintptr_t)s->generational.crossMap);
+             (uintptr_t)s->generationalMaps.cardMap,
+             (uintptr_t)s->generationalMaps.crossMap);
   setCardMapAbsolute (s);
   clearCardMap (s);
   clearCrossMap (s);
@@ -139,7 +139,7 @@
   
   if (DEBUG)
     fprintf (stderr, "crossMapIsOK ()\n");
-  mapSize = s->generational.crossMapLength * CROSS_MAP_ELEM_SIZE;
+  mapSize = s->generationalMaps.crossMapLength * CROSS_MAP_ELEM_SIZE;
   map = GC_mmapAnon (mapSize);
   memset (map, CROSS_MAP_EMPTY, mapSize);
   back = s->heap.start + s->heap.oldGenSize;
@@ -155,7 +155,7 @@
     goto loopObjects;
   }
   for (size_t i = 0; i < cardIndex; ++i)
-    assert (map[i] == s->generational.crossMap[i]);
+    assert (map[i] == s->generationalMaps.crossMap[i]);
   GC_munmap (map, mapSize);
   return TRUE;
 }
@@ -169,10 +169,10 @@
   pointer nextObject, objectStart;
   pointer oldGenEnd;
   
-  if (s->generational.crossMapValidSize == s->heap.oldGenSize)
+  if (s->generationalMaps.crossMapValidSize == s->heap.oldGenSize)
     goto done;
   oldGenEnd = s->heap.start + s->heap.oldGenSize;
-  objectStart = s->heap.start + s->generational.crossMapValidSize;
+  objectStart = s->heap.start + s->generationalMaps.crossMapValidSize;
   if (objectStart == s->heap.start) {
     cardIndex = 0;
     objectStart = alignFrontier (s, objectStart);
@@ -197,7 +197,7 @@
     if (DEBUG_GENERATIONAL)
       fprintf (stderr, "crossMap[%zu] = %zu\n",
                cardIndex, offset);
-    s->generational.crossMap[cardIndex] = (GC_crossMapElem)offset;
+    s->generationalMaps.crossMap[cardIndex] = (GC_crossMapElem)offset;
     cardIndex = sizeToCardIndex (nextObject - 1 - s->heap.start);
     cardStart = s->heap.start + cardIndexToSize (cardIndex);
     cardEnd = cardStart + CARD_SIZE;
@@ -206,29 +206,29 @@
   if (objectStart < oldGenEnd)
     goto loopObjects;
   assert (objectStart == oldGenEnd);
-  s->generational.crossMap[cardIndex] = (GC_crossMapElem)(oldGenEnd - cardStart);
-  s->generational.crossMapValidSize = s->heap.oldGenSize;
+  s->generationalMaps.crossMap[cardIndex] = (GC_crossMapElem)(oldGenEnd - cardStart);
+  s->generationalMaps.crossMapValidSize = s->heap.oldGenSize;
 done:
-  assert (s->generational.crossMapValidSize == s->heap.oldGenSize);
+  assert (s->generationalMaps.crossMapValidSize == s->heap.oldGenSize);
   assert (crossMapIsOK (s));
 }
 
 static inline void resizeCardMapAndCrossMap (GC_state s) {
   if (s->mutatorMarksCards
-      and (s->generational.cardMapLength * CARD_MAP_ELEM_SIZE)
+      and (s->generationalMaps.cardMapLength * CARD_MAP_ELEM_SIZE)
           != align (sizeToCardIndex (s->heap.size), s->pageSize)) {
     GC_cardMapElem *oldCardMap;
     size_t oldCardMapSize;
     GC_crossMapElem *oldCrossMap;
     size_t oldCrossMapSize;
     
-    oldCardMap = s->generational.cardMap;
-    oldCardMapSize = s->generational.cardMapLength * CARD_MAP_ELEM_SIZE;
-    oldCrossMap = s->generational.crossMap;
-    oldCrossMapSize = s->generational.crossMapLength * CROSS_MAP_ELEM_SIZE;
+    oldCardMap = s->generationalMaps.cardMap;
+    oldCardMapSize = s->generationalMaps.cardMapLength * CARD_MAP_ELEM_SIZE;
+    oldCrossMap = s->generationalMaps.crossMap;
+    oldCrossMapSize = s->generationalMaps.crossMapLength * CROSS_MAP_ELEM_SIZE;
     createCardMapAndCrossMap (s);
-    GC_memcpy ((pointer)oldCrossMap, (pointer)s->generational.crossMap,
-               min (s->generational.crossMapLength * CROSS_MAP_ELEM_SIZE, 
+    GC_memcpy ((pointer)oldCrossMap, (pointer)s->generationalMaps.crossMap,
+               min (s->generationalMaps.crossMapLength * CROSS_MAP_ELEM_SIZE, 
                     oldCrossMapSize));
     if (DEBUG_MEM)
       fprintf (stderr, "Releasing card/cross map.\n");
@@ -236,7 +236,7 @@
   }
 }
 
-void displayGenerationalMaps (GC_state s,
+void displayGenerationalMaps (__attribute__ ((unused)) GC_state s,
                               struct GC_generationalMaps *generational,
                               FILE *stream) {
   fprintf(stream,

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c	2005-10-08 20:36:15 UTC (rev 4098)
@@ -46,7 +46,35 @@
   return pointerIsInNursery (s, p);
 }
 
-void displayHeap (GC_state s,
+static inline bool pointerIsInFromSpace (GC_state s, pointer p) {
+  return (pointerIsInOldGen (s, p) or pointerIsInNursery (s, p));
+}
+
+static inline bool objptrIsInFromSpace (GC_state s, objptr op) {
+  return (objptrIsInOldGen (s, op) or objptrIsInNursery (s, op));
+}
+
+#if ASSERT
+static bool hasBytesFree (GC_state s, size_t oldGen, size_t nursery) {
+  size_t total;
+  bool res;
+
+  total =
+    s->heap.oldGenSize + oldGen 
+    + (s->canMinor ? 2 : 1) * (s->limitPlusSlop - s->heap.nursery);
+  res = 
+    (total <= s->heap.size) 
+    and (nursery <= (size_t)(s->limitPlusSlop - s->frontier));
+  if (DEBUG_DETAILED)
+    fprintf (stderr, "%s = hasBytesFree (%zd, %zd)\n",
+             res ? "true" : "false",
+             /*uintToCommaString*/(oldGen),
+             /*uintToCommaString*/(nursery));
+  return res;
+}
+#endif
+
+void displayHeap (__attribute__ ((unused)) GC_state s,
                   GC_heap heap,
                   FILE *stream) {
   fprintf(stream,
@@ -59,3 +87,186 @@
           (uintptr_t)heap->start,
           heap->size);
 }
+
+/* heapDesiredSize (s, l, c) returns the desired heap size for a heap
+ * with l bytes live, given that the current heap size is c.
+ */
+static size_t heapDesiredSize (GC_state s, size_t live, size_t currentSize) {
+  size_t res;
+  float ratio;
+
+  ratio = (float)s->sysvals.ram / (float)live;
+  if (ratio >= s->ratios.live + s->ratios.grow) {
+    /* Cheney copying fits in RAM with desired ratios.live. */
+    res = live * s->ratios.live;
+    /* If the heap is currently close in size to what we want, leave
+     * it alone.  Favor growing over shrinking.
+     */
+    unless (1.1 * currentSize <= res
+            or res <= .5 * currentSize)
+      res = currentSize;
+  } else if (s->ratios.grow >= s->ratios.copy
+             and ratio >= 2 * s->ratios.copy) {
+    /* Split RAM in half.  Round down by pageSize so that the total
+     * amount of space taken isn't greater than RAM once rounding
+     * happens.  This is so resizeHeap2 doesn't get confused and free
+     * a semispace in a misguided attempt to avoid paging.
+     */
+    res = roundDown (s->sysvals.ram / 2, s->sysvals.pageSize);
+  } else if (ratio >= s->ratios.copy + s->ratios.grow) {
+    /* Cheney copying fits in RAM. */
+    res = s->sysvals.ram - s->ratios.grow * live;
+    /* If the heap isn't too much smaller than what we want, leave it
+     * alone.  On the other hand, if it is bigger we want to leave res
+     * as is so that the heap is shrunk, to try to avoid paging.
+     */
+    if (currentSize <= res 
+        and res <= 1.1 * currentSize)
+      res = currentSize;
+  } else if (ratio >= s->ratios.markCompact) {
+    /* Mark compact fits in RAM.  It doesn't matter what the current
+     * size is.  If the heap is currently smaller, we are using
+     * copying and should switch to mark-compact.  If the heap is
+     * currently bigger, we want to shrink back to RAM to avoid
+     * paging.
+     */
+    res = s->sysvals.ram;
+  } else { /* Required live ratio. */
+    res = live * s->ratios.markCompact;
+    /* If the current heap is bigger than res, the shrinking always
+     * sounds like a good idea.  However, depending on what pages the
+     * VM keeps around, growing could be very expensive, if it
+     * involves paging the entire heap.  Hopefully the copy loop in
+     * growFromSpace will make the right thing happen.
+     */ 
+  }
+  if (s->control.fixedHeap > 0) {
+    if (res > s->control.fixedHeap / 2)
+      res = s->control.fixedHeap;
+    else
+      res = s->control.fixedHeap / 2;
+    if (res < live)
+      die ("Out of memory with fixed heap size %zd.",
+           /*uintToCommaString*/(s->control.fixedHeap));
+  } else if (s->control.maxHeap > 0) {
+    if (res > s->control.maxHeap)
+      res = s->control.maxHeap;
+    if (res < live)
+      die ("Out of memory with max heap size %zd.",
+           /*uintToCommaString*/(s->control.maxHeap));
+  }
+  if (DEBUG_RESIZING)
+    fprintf (stderr, "%zd = heapDesiredSize (%zd, %zd)\n",
+             /*uintToCommaString*/(res),
+             /*uintToCommaString*/(live),
+             /*uintToCommaString*/(currentSize));
+  assert (res >= live);
+  return res;
+}
+
+static inline void heapInit (GC_heap h) {
+  h->start = NULL;
+  h->size = 0;
+  h->oldGenSize = 0;
+  h->nursery = NULL;
+}
+
+static inline bool heapIsInit (GC_heap h) {
+  return 0 == h->size;
+}
+
+static void heapRelease (GC_state s, GC_heap h) {
+  if (NULL == h->start)
+    return;
+  if (DEBUG or s->messages)
+    fprintf (stderr, "Releasing heap at "FMTPTR" of size %zd.\n",
+             (uintptr_t)h->start,
+             /*uintToCommaString*/(h->size));
+  GC_release (h->start, h->size);
+  heapInit (h);
+}
+
+static void heapShrink (GC_state s, GC_heap h, size_t keep) {
+  assert (keep <= h->size);
+  if (0 == keep) {
+    heapRelease (s, h);
+    return;
+  }
+  keep = align (keep, s->pageSize);
+  if (keep < h->size) {
+    if (DEBUG or s->messages)
+      fprintf (stderr,
+               "Shrinking heap at "FMTPTR" of size %zd to %zd bytes.\n",
+               (uintptr_t)h->start,
+               /*uintToCommaString*/(h->size),
+               /*uintToCommaString*/(keep));
+    GC_decommit (h->start + keep, h->size - keep);
+    h->size = keep;
+  }
+}
+
+static void heapSetNursery (GC_state s, 
+                            size_t oldGenBytesRequested,
+                            size_t nurseryBytesRequested) {
+  GC_heap h;
+  size_t nurserySize;
+
+  if (DEBUG_DETAILED)
+    fprintf (stderr, "setNursery(%zd, %zd)\n",
+             /*uintToCommaString*/(oldGenBytesRequested),
+             /*uintToCommaString*/(nurseryBytesRequested));
+  h = &s->heap;
+  assert (isAlignedFrontier (s, h->start + h->oldGenSize + oldGenBytesRequested));
+  nurserySize = h->size - h->oldGenSize - oldGenBytesRequested;
+  s->limitPlusSlop = h->start + h->size;
+  s->limit = s->limitPlusSlop - LIMIT_SLOP;
+  assert (isAligned (nurserySize, WORD_SIZE)); // FIXME
+  if (/* The mutator marks cards. */
+      s->mutatorMarksCards
+      /* There is enough space in the nursery. */
+      and (nurseryBytesRequested
+           <= (size_t)(s->limitPlusSlop
+                       - alignFrontier (s, (s->limitPlusSlop 
+                                            - nurserySize / 2 + 2))))
+      /* The nursery is large enough to be worth it. */
+      and (((float)(h->size - s->lastMajorStatistics.bytesLive) 
+            / (float)nurserySize) 
+           <= s->ratios.nursery)
+      and /* There is a reason to use generational GC. */
+      (
+       /* We must use it for debugging pruposes. */
+       FORCE_GENERATIONAL
+       /* We just did a mark compact, so it will be advantageous to to
+        * use it.
+        */
+       or (s->lastMajorStatistics.kind == GC_MARK_COMPACT)
+       /* The live ratio is low enough to make it worthwhile. */
+       or ((float)h->size / (float)s->lastMajorStatistics.bytesLive
+           <= (h->size < s->sysvals.ram
+               ? s->ratios.copyGenerational
+               : s->ratios.markCompactGenerational))
+       )) {
+    s->canMinor = TRUE;
+    nurserySize /= 2;
+    while (not (isAligned (nurserySize, WORD_SIZE))) {
+      nurserySize -= 2;
+    }
+    clearCardMap (s);
+  } else {
+    unless (nurseryBytesRequested
+            <= (size_t)(s->limitPlusSlop
+                        - alignFrontier (s, s->limitPlusSlop
+                                         - nurserySize)))
+      die ("Out of memory.  Insufficient space in nursery.");
+    s->canMinor = FALSE;
+  }
+  assert (nurseryBytesRequested
+          <= (size_t)(s->limitPlusSlop
+                      - alignFrontier (s, s->limitPlusSlop
+                                       - nurserySize)));
+  s->heap.nursery = alignFrontier (s, s->limitPlusSlop - nurserySize);
+  s->frontier = s->heap.nursery;
+  assert (nurseryBytesRequested <= (size_t)(s->limitPlusSlop - s->frontier));
+  assert (isAlignedFrontier (s, s->heap.nursery));
+  assert (hasBytesFree (s, oldGenBytesRequested, nurseryBytesRequested));
+}

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.h	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.h	2005-10-08 20:36:15 UTC (rev 4098)
@@ -18,10 +18,10 @@
 */
 
 typedef struct GC_heap {
-  pointer nursery; /* start of nursery */
-  size_t oldGenSize; /* size of old generation */
   pointer start; /* start of heap (and old generation) */
   size_t size; /* size of heap */
+  size_t oldGenSize; /* size of old generation */
+  pointer nursery; /* start of nursery */
 } *GC_heap;
 
 #define LIMIT_SLOP 512

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.c	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.c	2005-10-08 20:36:15 UTC (rev 4098)
@@ -8,10 +8,18 @@
 
 #if ASSERT
 
+static inline void assertObjptrIsInFromSpace (GC_state s, objptr *opp) {
+  unless (objptrIsInFromSpace (s, *opp))
+    die ("gc.c: assertObjptrIsInFromSpace "
+         "opp = "FMTPTR"  "
+         "*opp = "FMTOBJPTR"\n",
+         (uintptr_t)opp, *opp);
+}
+
 static bool invariant (GC_state s) {
   if (DEBUG)
     fprintf (stderr, "invariant\n");
-  // assert (ratiosOk (s));
+  assert (ratiosOk (s->ratios));
   /* Frame layouts */
   for (unsigned int i = 0; i < s->frameLayoutsLength; ++i) {
     GC_frameLayout *layout;
@@ -22,22 +30,17 @@
       
       assert (layout->size <= s->maxFrameSize);
       offsets = layout->offsets;
-      /* No longer correct, since handler frames have a "size"
-       * (i.e. return address) pointing into the middle of the frame.
-       */
-/*       for (unsigned int j = 0; j < offsets[0]; ++j) */
-/*         assert (offsets[j + 1] < layout->numBytes); */
     }
   }
   /* Generational */
   if (s->mutatorMarksCards) {
-    assert (s->generational.cardMap == 
-            &(s->generational.cardMapAbsolute
+    assert (s->generationalMaps.cardMap == 
+            &(s->generationalMaps.cardMapAbsolute
               [pointerToCardIndex(s->heap.start)]));
-    assert (&(s->generational.cardMapAbsolute
+    assert (&(s->generationalMaps.cardMapAbsolute
               [pointerToCardIndex(s->heap.start + s->heap.size - 1)])
-            < (s->generational.cardMap 
-               + (s->generational.cardMapLength * CARD_MAP_ELEM_SIZE)));
+            < (s->generationalMaps.cardMap 
+               + (s->generationalMaps.cardMapLength * CARD_MAP_ELEM_SIZE)));
   }
   assert (isAligned (s->heap.size, s->pageSize));
   assert (isAligned ((size_t)s->heap.start, CARD_SIZE));
@@ -49,43 +52,52 @@
     assert (s->heap.nursery <= s->frontier);
     assert (s->frontier <= s->limitPlusSlop);
     assert (s->limit == s->limitPlusSlop - LIMIT_SLOP);
-/*     assert (hasBytesFree (s, 0, 0)); */
+    assert (hasBytesFree (s, 0, 0));
   }
-  assert (s->secondaryHeap.start == NULL or s->heap.size == s->secondaryHeap.size);
-/*   /\* Check that all pointers are into from space. *\/ */
-/*   foreachGlobal (s, assertIsInFromSpace); */
-/*   back = s->heap.start + s->oldGenSize; */
-/*   if (DEBUG_DETAILED) */
-/*     fprintf (stderr, "Checking old generation.\n"); */
-/*   foreachPointerInRange (s, alignFrontier (s, s->heap.start), &back, FALSE, */
-/*                          assertIsInFromSpace); */
-/*   if (DEBUG_DETAILED) */
-/*     fprintf (stderr, "Checking nursery.\n"); */
-/*   foreachPointerInRange (s, s->nursery, &s->frontier, FALSE, */
-/*                          assertIsInFromSpace); */
-/*   /\* Current thread. *\/ */
-/*   stack = s->currentThread->stack; */
-/*   assert (isAlignedReserved (s, stack->reserved)); */
-/*   assert (s->stackBottom == stackBottom (s, stack)); */
-/*   assert (s->stackTop == stackTop (s, stack)); */
-/*   assert (s->stackLimit == stackLimit (s, stack)); */
-/*   assert (stack->used == currentStackUsed (s)); */
-/*   assert (stack->used <= stack->reserved); */
-/*   assert (s->stackBottom <= s->stackTop); */
+  assert (s->secondaryHeap.start == NULL 
+          or s->heap.size == s->secondaryHeap.size);
+  /* Check that all pointers are into from space. */
+  foreachGlobalObjptr (s, assertObjptrIsInFromSpace);
+  pointer back = s->heap.start + s->heap.oldGenSize;
+  if (DEBUG_DETAILED)
+    fprintf (stderr, "Checking old generation.\n");
+  foreachObjptrInRange (s, alignFrontier (s, s->heap.start), &back, 
+                        FALSE, assertObjptrIsInFromSpace);
+  if (DEBUG_DETAILED)
+    fprintf (stderr, "Checking nursery.\n");
+  foreachObjptrInRange (s, s->heap.nursery, &s->frontier, 
+                        FALSE, assertObjptrIsInFromSpace);
+  /* Current thread. */
+  GC_stack stack = currentThreadStack(s);
+  assert (isAlignedReserved (s, stack->reserved));
+  assert (s->stackBottom == stackBottom (s, stack));
+  assert (s->stackTop == stackTop (s, stack));
+  assert (s->stackLimit == stackLimit (s, stack));
+  assert (s->stackBottom <= s->stackTop);
+  assert (stack->used == currentStackUsed (s));
+  assert (stack->used <= stack->reserved);
   if (DEBUG)
     fprintf (stderr, "invariant passed\n");
   return TRUE;
 }
 
+static bool mutatorFrontierInvariant (GC_state s) {
+  GC_thread ct = currentThread(s);
+  return (ct->bytesNeeded <= s->limitPlusSlop - s->frontier);
+}
+
+static bool mutatorStackInvariant (GC_state s) {
+  GC_stack sk = currentThreadStack(s);
+  return (stackTop (s, sk) <= stackLimit (s, sk) + topFrameSize (s, sk));
+}
+
 static bool mutatorInvariant (GC_state s, bool frontier, bool stack) {
-#if FALSE
   if (DEBUG)
-    GC_display (s, stderr);
+    displayGCState (s, stderr);
   if (frontier)
     assert (mutatorFrontierInvariant(s));
   if (stack)
     assert (mutatorStackInvariant(s));
-#endif
   assert (invariant (s));
   return TRUE;
 }

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/major.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/major.h	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/major.h	2005-10-08 20:36:15 UTC (rev 4098)
@@ -9,4 +9,4 @@
 typedef enum {
         GC_COPYING,
         GC_MARK_COMPACT,
-} GC_MajorKind;
+} GC_majorKind;

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.c	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.c	2005-10-08 20:36:15 UTC (rev 4098)
@@ -49,7 +49,7 @@
 
 /* isObjptr returns true if p looks like an object pointer. */
 static inline bool isObjptr (objptr p) {
-  if GC_MODEL_NONPTR {
+  if GC_MODEL_NONOBJPTR {
     unsigned int shift = GC_MODEL_MINALIGN_SHIFT - GC_MODEL_SHIFT;
     objptr mask = ~((~((objptr)0)) << shift);
     return (0 == (p & mask));

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.h	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.h	2005-10-08 20:36:15 UTC (rev 4098)
@@ -203,7 +203,7 @@
 #else 
 #error gc model unknown
 #endif
-#define GC_MODEL_NONPTR ((GC_MODEL_MINALIGN_SHIFT - GC_MODEL_SHIFT) > 0)
+#define GC_MODEL_NONOBJPTR ((GC_MODEL_MINALIGN_SHIFT - GC_MODEL_SHIFT) > 0)
 #define GC_MODEL_MINALIGN TWOPOWER(GC_MODEL_MINALIGN_SHIFT)
 
 #define OBJPTR_TYPE__(z) uint ## z ## _t
@@ -216,7 +216,7 @@
 #define PRIxOBJPTR PRIxOBJPTR_(GC_MODEL_BITSIZE)
 #define FMTOBJPTR "0x%016"PRIxOBJPTR
 
-#if GC_MODEL_NONPTR
+#if GC_MODEL_NONOBJPTR
 #define BOGUS_OBJPTR (objptr)0x1
 #else
 #error gc model does not admit bogus object pointer

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/object.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/object.h	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/object.h	2005-10-08 20:36:15 UTC (rev 4098)
@@ -11,10 +11,10 @@
  *   array, normal (fixed size), stack, and weak.
  */
 typedef enum { 
-        ARRAY_TAG,
-        NORMAL_TAG,
-        STACK_TAG,
-        WEAK_TAG,
+  ARRAY_TAG,
+  NORMAL_TAG,
+  STACK_TAG,
+  WEAK_TAG,
 } GC_objectTypeTag;
 
 /*
@@ -40,7 +40,7 @@
 #define COUNTER_SHIFT      20
 #define MARK_BITS          1
 #define MARK_MASK          0x80000000
-#define MARK_SHIFT         3
+#define MARK_SHIFT         31
 
 /* getHeaderp (p)
  *
@@ -103,11 +103,11 @@
  * object (and, hence, must be (2,1) or (3,0)).
 */
 typedef struct {
-        /* Keep tag first, at zero offset, since it is referenced most often. */
-        GC_objectTypeTag tag;
-        bool hasIdentity;
-        uint16_t numNonObjptrs;
-        uint16_t numObjptrs;
+  /* Keep tag first, at zero offset, since it is referenced most often. */
+  GC_objectTypeTag tag;
+  bool hasIdentity;
+  uint16_t numNonObjptrs;
+  uint16_t numObjptrs;
 } GC_objectType;
 enum {
   /* The type indices here must agree with those in backend/rep-type.fun. */

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/pointer.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/pointer.h	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/pointer.h	2005-10-08 20:36:15 UTC (rev 4098)
@@ -7,6 +7,8 @@
  */
 
 typedef unsigned char* pointer;
-#define POINTER_SIZE sizeof(pointer);
+#define POINTER_SIZE sizeof(pointer)
 #define FMTPTR "0x%016"PRIxPTR
 #define BOGUS_POINTER (pointer)0x1
+
+#define WORD_SIZE POINTER_SIZE

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.c (from rev 4097, mlton/branches/on-20050822-x86_64-branch/runtime/gc.c)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc.c	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.c	2005-10-08 20:36:15 UTC (rev 4098)
@@ -0,0 +1,15 @@
+/* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
+ *    Jagannathan, and Stephen Weeks.
+ * Copyright (C) 1997-2000 NEC Research Institute.
+ *
+ * MLton is released under a BSD-style license.
+ * See the file MLton-LICENSE for details.
+ */
+
+static bool ratiosOk (struct GC_ratios ratios) {
+  return 1.0 < ratios.grow
+    and 1.0 < ratios.nursery
+    and 1.0 < ratios.markCompact
+    and ratios.markCompact <= ratios.copy
+    and ratios.copy <= ratios.live;
+}

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.h (from rev 4097, mlton/branches/on-20050822-x86_64-branch/runtime/gc.h)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc.h	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.h	2005-10-08 20:36:15 UTC (rev 4098)
@@ -0,0 +1,31 @@
+/* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
+ *    Jagannathan, and Stephen Weeks.
+ * Copyright (C) 1997-2000 NEC Research Institute.
+ *
+ * MLton is released under a BSD-style license.
+ * See the file MLton-LICENSE for details.
+ */
+
+struct GC_ratios {
+  /* Only use generational GC with copying collection if the ratio of
+   * heap size to live data size is below copyGenerational.
+   */
+  float copyGenerational; 
+  /* Minimum live ratio to use copying GC. */
+  float copy; 
+  float grow; 
+  /* Desired ratio of heap size to live data. */
+  float live; 
+  /* Minimum live ratio to us mark-compact GC. */
+  float markCompact; 
+  /* Only use generational GC with mark-compact collection if the
+   * ratio of heap size to live data size is below
+   * markCompactGenerational.
+   */
+  float markCompactGenerational; 
+  /* As long as the ratio of bytes live to nursery size is greater
+   * than nurseryRatio, use minor GCs.
+   */
+  float nursery; 
+  float threadShrink; 
+};

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack.c	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack.c	2005-10-08 20:36:15 UTC (rev 4098)
@@ -7,7 +7,7 @@
  */
 
 static inline bool stackIsEmpty (GC_stack stack) {
-        return 0 == stack->used;
+  return 0 == stack->used;
 }
 
 /* stackSlop returns the amount of "slop" space needed between the top
@@ -21,32 +21,42 @@
   return stackSlop (s);
 }
 
-static inline size_t stackBytes (GC_state s, size_t size) {
+static inline size_t stackNumBytes (GC_state s, size_t size) {
   size_t res;
   
   res = align (GC_STACK_HEADER_SIZE + sizeof (struct GC_stack) + size,
                s->alignment);
   if (DEBUG_STACKS)
-    fprintf (stderr, "%zu = stackBytes (%zu)\n", res, size);
+    fprintf (stderr, "%zu = stackNumBytes (%zu)\n", res, size);
   return res;
 }
 
 static inline pointer stackBottom (GC_state s, GC_stack stack) {
-        pointer res;
-
-        res = ((pointer)stack) + sizeof (struct GC_stack);
-        assert (isAligned ((uintptr_t)res, s->alignment));
-        return res;
+  pointer res;
+  
+  res = ((pointer)stack) + sizeof (struct GC_stack);
+  assert (isAligned ((uintptr_t)res, s->alignment));
+  return res;
 }
 
 /* Pointer to the topmost word in use on the stack. */
 static inline pointer stackTop (GC_state s, GC_stack stack) {
-        return stackBottom (s, stack) + stack->used;
+  return stackBottom (s, stack) + stack->used;
 }
 
+/* Pointer to the end of stack. */
+static inline pointer stackLimitPlusSlop (GC_state s, GC_stack stack) {
+  return stackBottom (s, stack) + stack->reserved;
+}
+
+/* The maximum value stackTop may take on. */
+static inline pointer stackLimit (GC_state s, GC_stack stack) {
+  return stackLimitPlusSlop (s, stack) - stackSlop (s);
+}
+
 static inline uint32_t topFrameIndex (GC_state s, GC_stack stack) {
   uint32_t res;
-
+  
   res = 
     getFrameIndexFromReturnAddress 
     (s, *(GC_returnAddress*)(stackTop (s, stack) - GC_RETURNADDRESS_SIZE));
@@ -72,7 +82,7 @@
 
 static inline size_t stackReserved (GC_state s, size_t r) {
   size_t res;
-
+  
   res = pad (s, r, GC_STACK_HEADER_SIZE + sizeof (struct GC_stack));
   if (DEBUG_STACKS)
     fprintf (stderr, "%zu = stackReserved (%zu)\n", res, r);
@@ -83,7 +93,7 @@
   return stack->used + stackSlop (s) - topFrameSize(s, stack);
 }
 
-void displayStack (GC_state s,
+void displayStack (__attribute__ ((unused)) GC_state s,
                    GC_stack stack, 
                    FILE *stream) {
   fprintf(stream,

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/statistics.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/statistics.h	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/statistics.h	2005-10-08 20:36:15 UTC (rev 4098)
@@ -24,10 +24,10 @@
 
   uintmax_t numLimitChecks;
 
-  unsigned int numCopyingGCs;
-  unsigned int numHashConsGCs;
-  unsigned int numMarkCompactGCs;
-  unsigned int numMinorGCs;
+  uintmax_t numCopyingGCs;
+  uintmax_t numHashConsGCs;
+  uintmax_t numMarkCompactGCs;
+  uintmax_t numMinorGCs;
 
 /*   struct rusage ru_gc; /\* total resource usage spent in gc *\/ */
 /*   struct rusage ru_gcCopy; /\* resource usage in major copying gcs. *\/ */
@@ -37,6 +37,6 @@
 
 struct GC_lastMajorStatistics {
   size_t bytesLive; /* Number of bytes live at most recent major GC. */
-  GC_MajorKind kind;
-  unsigned int numMinorsGCs;
+  GC_majorKind kind;
+  uintmax_t numMinorsGCs;
 };

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/sysvals.h (from rev 4097, mlton/branches/on-20050822-x86_64-branch/runtime/gc.h)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc.h	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/sysvals.h	2005-10-08 20:36:15 UTC (rev 4098)
@@ -0,0 +1,14 @@
+/* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
+ *    Jagannathan, and Stephen Weeks.
+ * Copyright (C) 1997-2000 NEC Research Institute.
+ *
+ * MLton is released under a BSD-style license.
+ * See the file MLton-LICENSE for details.
+ */
+
+struct GC_sysvals {
+  size_t ram;
+  size_t availRam;
+  size_t totalRam;
+  size_t pageSize;
+};

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/thread.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/thread.c	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/thread.c	2005-10-08 20:36:15 UTC (rev 4098)
@@ -6,16 +6,6 @@
  * See the file MLton-LICENSE for details.
  */
 
-static inline GC_thread currentThread (GC_state s) {
-  pointer p = objptrToPointer(s->currentThread, s->heap.start);
-  return (GC_thread)p;
-}
-
-static inline objptr currentThreadStack (GC_state s) {
-  GC_thread ct = currentThread (s);
-  return ct->stack;
-}
-
 void displayThread (GC_state s,
                     GC_thread thread, 
                     FILE *stream) {

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.h	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.h	2005-10-08 20:36:15 UTC (rev 4098)
@@ -19,11 +19,11 @@
 #include <stddef.h>
 #include <stdbool.h>
 #include <iso646.h>
-#include <stdio.h>
 #include <stdint.h>
 #include <inttypes.h>
+#include <limits.h>
 #include <stdlib.h>
-#include <limits.h>
+#include <stdio.h>
 #include <string.h>
 
 #include "../assert.h"

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/virtual-memory.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/virtual-memory.h	2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/virtual-memory.h	2005-10-08 20:36:15 UTC (rev 4098)
@@ -6,6 +6,8 @@
  * See the file MLton-LICENSE for details.
  */
 
+void *GC_mmapAnon (size_t length);
 void *GC_mmap (void *start, size_t length);
-void *GC_mmapAnon (size_t length);
 void *GC_munmap (void *base, size_t length);
+void GC_release (void *base, size_t length);
+void GC_decommit (void *base, size_t length);