[MLton-commit] r4100

Matthew Fluet MLton@mlton.org
Sun, 9 Oct 2005 18:54:40 -0700


Some reorganization; additional heap functions, including model agnostic heapCreate; ported Depth-First mark
----------------------------------------------------------------------

U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile
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
D   mlton/branches/on-20050822-x86_64-branch/runtime/gc/array_defs.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/cheney-copy.c
D   mlton/branches/on-20050822-x86_64-branch/runtime/gc/control.h
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/controls.h
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/dfs-mark.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_prefix.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
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/hash-cons.c
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/hash-cons.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap_predicates.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/major.h
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-compact.c
D   mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-sweep.c
D   mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-sweep.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.c
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/model_predicates.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/new_object.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/object.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/object_size.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/pointer.c
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/pointer_predicates.c
D   mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.c
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios_predicates.c
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/rusage.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack.c
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack_predicates.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/statistics.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.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.c
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-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile	2005-10-10 01:54:23 UTC (rev 4100)
@@ -49,7 +49,7 @@
 endif
 
 CC = gcc -std=gnu99
-CWFLAGS = -pedantic -Wall -Wextra -Wno-unused-parameter \
+CWFLAGS = -pedantic -Wall -Wextra -Wno-unused-parameter -Wno-unused-function \
 	-Wformat-nonliteral \
 	-Wuninitialized -Winit-self \
 	-Wstrict-aliasing=2 \
@@ -77,25 +77,31 @@
 	debug.c								\
 	align.c								\
 	virtual-memory.c						\
+	rusage.c							\
+	pointer_predicates.c						\
 	pointer.c							\
+	model_predicates.c						\
 	model.c								\
 	object.c							\
 	array.c								\
 	object_size.c							\
 	frame.c								\
+	stack_predicates.c						\
 	stack.c								\
 	thread.c							\
 	generational.c							\
-	heap.c   							\
+	heap_predicates.c						\
+	heap.c								\
 	gc_state.c   							\
 	new_object.c   							\
-	ratios.c   							\
+	ratios_predicates.c						\
 	current.c   							\
 	foreach.c							\
 	atomic.c							\
 	invariant.c   							\
 	enter_leave.c							\
 	cheney-copy.c							\
+	dfs-mark.c							\
 	assumptions.c							\
 	gc_suffix.c
 
@@ -116,10 +122,11 @@
 	major.h								\
 	generational.h							\
 	statistics.h							\
-	control.h							\
+	controls.h							\
 	sysvals.h							\
 	ratios.h							\
 	gc_state.h							\
+	hash-cons.h							\
 	profile.h							\
 	gc_suffix.h
 

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/align.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/align.c	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/align.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -6,45 +6,64 @@
  * See the file MLton-LICENSE for details.
  */
 
-static inline size_t roundDown (size_t a, size_t b) {
-  return a - (a % b);
+static inline bool isAligned (size_t a, size_t b) {
+  return 0 == a % b;
 }
 
+static inline size_t alignDown (size_t a, size_t b) {
+  assert (b >= 1);
+  a -= a % b;
+  assert (isAligned (a, b));
+  return a;
+}
+
 static inline size_t align (size_t a, size_t b) {
   assert (b >= 1);
   a += b - 1;
   a -= a % b;
+  assert (isAligned (a, b));
   return a;       
 }
 
-static inline bool isAligned (size_t a, size_t b) {
-  return 0 == a % b;
+static inline size_t pad (GC_state s, size_t bytes, size_t extra) {
+  return align (bytes + extra, s->alignment) - extra;
 }
 
 #if ASSERT
 static inline bool isAlignedFrontier (GC_state s, pointer p) {
-  return isAligned ((uintptr_t)p + GC_NORMAL_HEADER_SIZE, 
+  return isAligned ((size_t)p + GC_NORMAL_HEADER_SIZE, 
                     s->alignment);
 }
-
-static inline 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) {
-  return align (bytes + extra, s->alignment) - extra;
-}
-
 static inline pointer alignFrontier (GC_state s, pointer p) {
-  size_t bytes, res;
+  size_t res;
 
-  bytes = (size_t) p;
   res = pad (s, (size_t)p, GC_NORMAL_HEADER_SIZE);
+  if (DEBUG_STACKS)
+    fprintf (stderr, FMTPTR" = stackReserved ("FMTPTR")\n", 
+             (uintptr_t)p, (uintptr_t)res);
+  assert (isAlignedFrontier (s, (pointer)res));
   return (pointer)res;
 }
 
 pointer GC_alignFrontier (GC_state s, pointer p) {
   return alignFrontier (s, p);
 }
+
+#if ASSERT
+static inline bool isAlignedStackReserved (GC_state s, size_t reserved) {
+  return isAligned (GC_STACK_HEADER_SIZE + sizeof (struct GC_stack) + reserved, 
+                    s->alignment);
+}
+#endif
+
+static inline size_t alignStackReserved (GC_state s, size_t reserved) {
+  size_t res;
+  
+  res = pad (s, reserved, GC_STACK_HEADER_SIZE + sizeof (struct GC_stack));
+  if (DEBUG_STACKS)
+    fprintf (stderr, "%zu = stackReserved (%zu)\n", res, reserved);
+  assert (isAlignedStackReserved (s, res));
+  return res;
+}

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.c	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -6,49 +6,19 @@
  * See the file MLton-LICENSE for details.
  */
 
-#if ASSERT
-static inline pointer arrayIndexAtPointer (GC_state s, 
-                                           pointer a, 
-                                           uint32_t arrayIndex, 
-                                           uint32_t pointerIndex) {
-  GC_header header;
-  uint16_t numNonObjptrs;
-  uint16_t numObjptrs;
-  GC_objectTypeTag tag;
-  
-  header = getHeader (a);
-  splitHeader(s, header, &tag, NULL, &numNonObjptrs, &numObjptrs);
-  assert (tag == ARRAY_TAG);
-
-  size_t nonObjptrBytesPerElement =
-    numNonObjptrsToBytes(numNonObjptrs, ARRAY_TAG);
-  size_t bytesPerElement = 
-    nonObjptrBytesPerElement
-    + (numObjptrs * OBJPTR_SIZE);
-
-  return a
-    + arrayIndex * bytesPerElement
-    + nonObjptrBytesPerElement
-    + pointerIndex * OBJPTR_SIZE;
+/* getArrayCounterp (p)
+ *
+ * Returns a pointer to the counter for the array pointed to by p.
+ */
+static inline GC_arrayCounter* getArrayCounterp (pointer a) {
+  return (GC_arrayCounter*)(a - GC_HEADER_SIZE 
+                            - GC_ARRAY_LENGTH_SIZE - GC_ARRAY_COUNTER_SIZE);
 }
-#endif
 
-/* The number of bytes in an array, not including the header. */
-static inline size_t arrayNumBytes (GC_state s,
-                                    pointer p, 
-                                    uint16_t numNonObjptrs,
-                                    uint16_t numObjptrs) {
-  size_t bytesPerElement;
-  GC_arrayLength numElements;
-  size_t result;
-        
-  numElements = getArrayLength (p);
-  bytesPerElement = 
-    numNonObjptrsToBytes(numNonObjptrs, ARRAY_TAG) 
-    + (numObjptrs * OBJPTR_SIZE);
-  result = numElements * bytesPerElement;
-  /* Empty arrays have OBJPTR_SIZE bytes for the forwarding pointer. */
-  if (0 == result) 
-    result = OBJPTR_SIZE;
-  return pad (s, result, GC_ARRAY_HEADER_SIZE);
+/* getArrayCounter (p)
+ *
+ * Returns the counter for the array pointed to by p.
+ */
+static inline GC_arrayCounter getArrayCounter (pointer a) {
+  return *(getArrayCounterp (a));
 }

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.h	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.h	2005-10-10 01:54:23 UTC (rev 4100)
@@ -20,18 +20,20 @@
  */
 typedef uint32_t GC_arrayLength;
 #define GC_ARRAY_LENGTH_SIZE sizeof(GC_arrayLength)
+typedef GC_arrayLength GC_arrayCounter;
 #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)
 
-/* getArrayNumElementsp (p)
+/* getArrayLengthp (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);
+  return (GC_arrayLength*)(a - GC_HEADER_SIZE 
+                           - GC_ARRAY_LENGTH_SIZE);
 }
 
-/* getArrayNumElements (p)
+/* getArrayLength (p)
  *
  * Returns the length for the array pointed to by p.
  */

Deleted: mlton/branches/on-20050822-x86_64-branch/runtime/gc/array_defs.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/array_defs.c	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/array_defs.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -1,54 +0,0 @@
-/* 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.
- */
-
-#if ASSERT
-static inline pointer arrayIndexAtPointer (GC_state s, 
-                                           pointer a, 
-                                           uint32_t arrayIndex, 
-                                           uint32_t pointerIndex) {
-  GC_header header;
-  uint16_t numNonObjptrs;
-  uint16_t numObjptrs;
-  GC_objectTypeTag tag;
-  
-  header = getHeader (a);
-  splitHeader(s, header, &tag, NULL, &numNonObjptrs, &numObjptrs);
-  assert (tag == ARRAY_TAG);
-
-  size_t nonObjptrBytesPerElement =
-    numNonObjptrsToBytes(numNonObjptrs, ARRAY_TAG);
-  size_t bytesPerElement = 
-    nonObjptrBytesPerElement
-    + (numObjptrs * OBJPTR_SIZE);
-
-  return a
-    + arrayIndex * bytesPerElement
-    + nonObjptrBytesPerElement
-    + pointerIndex * OBJPTR_SIZE;
-}
-#endif
-
-/* The number of bytes in an array, not including the header. */
-static inline size_t arrayNumBytes (GC_state s,
-                                    pointer p, 
-                                    uint16_t numNonObjptrs,
-                                    uint16_t numObjptrs) {
-  size_t bytesPerElement;
-  GC_arrayLength numElements;
-  size_t result;
-        
-  numElements = getArrayLength (p);
-  bytesPerElement = 
-    numNonObjptrsToBytes(numNonObjptrs, ARRAY_TAG) 
-    + (numObjptrs * OBJPTR_SIZE);
-  result = numElements * bytesPerElement;
-  /* Empty arrays have OBJPTR_SIZE bytes for the forwarding pointer. */
-  if (0 == result) 
-    result = OBJPTR_SIZE;
-  return pad (s, result, GC_ARRAY_HEADER_SIZE);
-}

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-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/cheney-copy.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -70,7 +70,7 @@
       skip = 0;
     } else if (ARRAY_TAG == tag) {
       headerBytes = GC_ARRAY_HEADER_SIZE;
-      objectBytes = arrayNumBytes (s, p, numNonObjptrs, numObjptrs);
+      objectBytes = arraySizeNoHeader (s, p, numNonObjptrs, numObjptrs);
       skip = 0;
     } else { /* Stack. */
       GC_stack stack;
@@ -85,8 +85,8 @@
          */
         if (stack->used <= stack->reserved / 4) {
           size_t new = 
-            stackReserved (s, maxZ (stack->reserved / 2,
-                                    stackNeedsReserved (s, stack)));
+            alignStackReserved 
+            (s, max (stack->reserved / 2, stackMinimumReserved (s, stack)));
           /* It's possible that new > stack->reserved 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
@@ -96,17 +96,17 @@
           if (new <= stack->reserved) {
             stack->reserved = new;
             if (DEBUG_STACKS)
-              fprintf (stderr, "Shrinking stack to size %zd.\n",
+              fprintf (stderr, "Shrinking stack to size %zu.\n",
                        /*uintToCommaString*/(stack->reserved));
           }
         }
       } else {
         /* Shrink heap stacks. */
         stack->reserved = 
-          stackReserved (s, maxZ((size_t)(s->ratios.threadShrink * stack->reserved),
-                                 stack->used));
+          alignStackReserved 
+          (s, max((size_t)(s->ratios.threadShrink * stack->reserved), stack->used));
         if (DEBUG_STACKS)
-          fprintf (stderr, "Shrinking stack to size %zd.\n",
+          fprintf (stderr, "Shrinking stack to size %zu.\n",
                    /*uintToCommaString*/(stack->reserved));
       }
       objectBytes = sizeof (struct GC_stack) + stack->used;
@@ -143,7 +143,7 @@
     *(objptr*)p = pointerToObjptr(forwardState.back + headerBytes, forwardState.toStart);
     /* Update the back of the queue. */
     forwardState.back += size + skip;
-    assert (isAligned ((uintptr_t)forwardState.back + GC_NORMAL_HEADER_SIZE, 
+    assert (isAligned ((size_t)forwardState.back + GC_NORMAL_HEADER_SIZE, 
                        s->alignment));
   }
   *opp = *(objptr*)p;
@@ -185,26 +185,22 @@
   setCardMapAbsolute (s);
 }
 
-/* static inline bool detailedGCTime (GC_state s) { */
-/*         return s->summary; */
-/* } */
-
 static void majorCheneyCopyGC (GC_state s) {
-  // struct rusage ru_start;
+  struct rusage ru_start;
   pointer toStart;
 
   assert (s->secondaryHeap.size >= s->heap.oldGenSize);
-/*   if (detailedGCTime (s)) */
-/*     startTiming (&ru_start); */
+  if (detailedGCTime (s))
+    startTiming (&ru_start);
   s->cumulativeStatistics.numCopyingGCs++;
   forwardState.toStart = s->secondaryHeap.start;
   forwardState.toLimit = s->secondaryHeap.start + s->secondaryHeap.size;
-  if (DEBUG or s->messages) {
+  if (DEBUG or s->controls.messages) {
     fprintf (stderr, "Major copying GC.\n");
-    fprintf (stderr, "fromSpace = "FMTPTR" of size %zd\n",
+    fprintf (stderr, "fromSpace = "FMTPTR" of size %zu\n",
              (uintptr_t) s->heap.start, 
              /*uintToCommaString*/(s->heap.size));
-    fprintf (stderr, "toSpace = "FMTPTR" of size %zd\n",
+    fprintf (stderr, "toSpace = "FMTPTR" of size %zu\n",
              (uintptr_t) s->secondaryHeap.start, 
              /*uintToCommaString*/(s->secondaryHeap.size));
   }
@@ -223,14 +219,14 @@
   s->secondaryHeap.oldGenSize = forwardState.back - s->secondaryHeap.start;
   s->cumulativeStatistics.bytesCopied += s->secondaryHeap.oldGenSize;
   if (DEBUG)
-    fprintf (stderr, "%zd bytes live.\n",
+    fprintf (stderr, "%zu bytes live.\n",
              /*uintToCommaString*/(s->secondaryHeap.oldGenSize));
   swapHeaps (s);
   clearCrossMap (s);
   s->lastMajorStatistics.kind = GC_COPYING;
-/*   if (detailedGCTime (s)) */
-/*     stopTiming (&ru_start, &s->ru_gcCopy); */
-  if (DEBUG or s->messages)
+  if (detailedGCTime (s))
+    stopTiming (&ru_start, &s->cumulativeStatistics.ru_gcCopy);
+  if (DEBUG or s->controls.messages)
     fprintf (stderr, "Major copying GC done.\n");
 }
 
@@ -346,7 +342,7 @@
 static void minorGC (GC_state s) {
   size_t bytesAllocated;
   size_t bytesCopied;
-  // struct rusage ru_start;
+  struct rusage ru_start;
 
   if (DEBUG_GENERATIONAL)
     fprintf (stderr, "minorGC  nursery = "FMTPTR"  frontier = "FMTPTR"\n",
@@ -360,10 +356,10 @@
     s->heap.oldGenSize += bytesAllocated;
     bytesCopied = 0;
   } else {
-    if (DEBUG_GENERATIONAL or s->messages)
+    if (DEBUG_GENERATIONAL or s->controls.messages)
       fprintf (stderr, "Minor GC.\n");
-/*     if (detailedGCTime (s)) */
-/*       startTiming (&ru_start); */
+    if (detailedGCTime (s))
+      startTiming (&ru_start);
     s->amInMinorGC = TRUE;
     forwardState.toStart = s->heap.start + s->heap.oldGenSize;
     if (DEBUG_GENERATIONAL)
@@ -386,10 +382,10 @@
     s->cumulativeStatistics.bytesCopiedMinor += bytesCopied;
     s->heap.oldGenSize += bytesCopied;
     s->amInMinorGC = FALSE;
-/*     if (detailedGCTime (s)) */
-/*       stopTiming (&ru_start, &s->ru_gcMinor); */
-    if (DEBUG_GENERATIONAL or s->messages)
-      fprintf (stderr, "Minor GC done.  %zd bytes copied.\n",
+    if (detailedGCTime (s))
+      stopTiming (&ru_start, &s->cumulativeStatistics.ru_gcMinor);
+    if (DEBUG_GENERATIONAL or s->controls.messages)
+      fprintf (stderr, "Minor GC done.  %zu bytes copied.\n",
                /*uintToCommaString*/(bytesCopied));
   }
 }

Deleted: mlton/branches/on-20050822-x86_64-branch/runtime/gc/control.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/control.h	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/control.h	2005-10-10 01:54:23 UTC (rev 4100)
@@ -1,12 +0,0 @@
-/* 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/controls.h (from rev 4098, mlton/branches/on-20050822-x86_64-branch/runtime/gc/control.h)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/control.h	2005-10-08 20:36:15 UTC (rev 4098)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/controls.h	2005-10-10 01:54:23 UTC (rev 4100)
@@ -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_controls {
+  size_t fixedHeap; /* If 0, then no fixed heap. */
+  size_t maxHeap; /* if zero, then unlimited, else limit total heap */
+  bool messages;
+  bool summary;
+};

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/dfs-mark.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/dfs-mark.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -0,0 +1,362 @@
+/* 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.
+ */
+
+/* ---------------------------------------------------------------- */
+/*                       Depth-first Marking                        */
+/* ---------------------------------------------------------------- */
+
+typedef enum {
+  MARK_MODE,
+  UNMARK_MODE,
+} GC_markMode;
+
+static inline bool isMarked (pointer p) {
+  return MARK_MASK & getHeader (p);
+}
+
+static bool isMarkedMode (GC_markMode m, pointer p) {
+  switch (m) {
+  case MARK_MODE:
+    return isMarked (p);
+  case UNMARK_MODE:
+    return not isMarked (p);
+  default:
+    die ("bad mark mode %u", m);
+  }
+}
+
+#if ASSERT
+static inline pointer arrayIndexAtPointer (GC_state s,
+                                           pointer a,
+                                           GC_arrayCounter arrayIndex,
+                                           uint32_t pointerIndex) {
+  GC_header header;
+  uint16_t numNonObjptrs;
+  uint16_t numObjptrs;
+  GC_objectTypeTag tag;
+  
+  header = getHeader (a);
+  splitHeader(s, header, &tag, NULL, &numNonObjptrs, &numObjptrs);
+  assert (tag == ARRAY_TAG);
+
+  size_t nonObjptrBytesPerElement =
+    numNonObjptrsToBytes(numNonObjptrs, ARRAY_TAG);
+  size_t bytesPerElement =
+    nonObjptrBytesPerElement
+    + (numObjptrs * OBJPTR_SIZE);
+
+  return a
+    + arrayIndex * bytesPerElement
+    + nonObjptrBytesPerElement
+    + pointerIndex * OBJPTR_SIZE;
+}
+#endif
+
+/* mark (s, r, m, shc) 
+ *
+ * Sets all the mark bits in the object graph pointed to by r. 
+ *
+ * If m is MARK_MODE, it sets the bits to 1.
+ * If m is UNMARK_MODE, it sets the bits to 0.
+ *
+ * If shc, it hash-conses the objects marked.
+ *
+ * It returns the total size in bytes of the objects marked.
+ */
+size_t mark (GC_state s, pointer root,
+             GC_markMode mode, bool shouldHashCons) {
+  GC_header mark; /* Used to set or clear the mark bit. */
+  size_t size; /* Total number of bytes marked. */
+  pointer cur; /* The current object being marked. */
+  pointer prev; /* The previous object on the mark stack. */
+  pointer next; /* The next object to mark. */
+  pointer todo; /* A pointer to the pointer in cur to next. */
+  GC_header header;
+  GC_header* headerp;
+  uint16_t numNonObjptrs;
+  uint16_t numObjptrs;
+  GC_objectTypeTag tag;
+  uint32_t index; /* The i'th pointer in the object (element) being marked. */
+  GC_header nextHeader;
+  GC_header* nextHeaderp;
+  GC_arrayCounter arrayIndex;
+  pointer top; /* The top of the next stack frame to mark. */
+  GC_returnAddress returnAddress; 
+  GC_frameLayout *frameLayout;
+  GC_frameOffsets frameOffsets;
+
+  if (isMarkedMode (mode, root))
+    /* Object has already been marked. */
+    return 0;
+  mark = (MARK_MODE == mode) ? MARK_MASK : 0;
+  size = 0;
+  cur = root;
+  prev = NULL;
+  headerp = getHeaderp (cur);
+  header = *headerp;
+  goto mark;      
+markNext:
+  /* cur is the object that was being marked.
+   * prev is the mark stack.
+   * next is the unmarked object to be marked.
+   * nextHeaderp points to the header of next.
+   * nextHeader is the header of next.
+   * todo is a pointer to the pointer inside cur that points to next.
+   */
+  if (DEBUG_MARK_COMPACT)
+    fprintf (stderr, 
+             "markNext"
+             "  cur = "FMTPTR"  next = "FMTPTR
+             "  prev = "FMTPTR"  todo = "FMTPTR"\n",
+             (uintptr_t)cur, (uintptr_t)next, 
+             (uintptr_t)prev, (uintptr_t)todo);
+  assert (not isMarkedMode (mode, next));
+  assert (nextHeaderp == getHeaderp (next));
+  assert (nextHeader == getHeader (next));
+  // assert (*(pointer*) todo == next);
+  assert (fetchObjptrFromPointer (todo, s->heap.start) == next);
+  headerp = nextHeaderp;
+  header = nextHeader;
+  // *(pointer*)todo = prev;
+  storeObjptrFromPointer (todo, prev, s->heap.start);
+  prev = cur;
+  cur = next;
+mark:
+  if (DEBUG_MARK_COMPACT)
+    fprintf (stderr, "mark  cur = "FMTPTR"  prev = "FMTPTR"  mode = %s\n",
+             (uintptr_t)cur, (uintptr_t)prev,
+             (mode == MARK_MODE) ? "mark" : "unmark");
+  /* cur is the object to mark. 
+   * prev is the mark stack.
+   * headerp points to the header of cur.
+   * header is the header of cur.
+   */
+  assert (not isMarkedMode (mode, cur));
+  assert (header == getHeader (cur));
+  assert (headerp == getHeaderp (cur));
+  header ^= MARK_MASK;
+  /* Store the mark.  In the case of an object that contains a pointer to
+   * itself, it is essential that we store the marked header before marking
+   * the internal pointers (markInNormal below).  If we didn't, then we
+   * would see the object as unmarked and traverse it again.
+   */
+  *headerp = header;
+  splitHeader (s, header, &tag, NULL, &numNonObjptrs, &numObjptrs);
+  if (NORMAL_TAG == tag) {
+    size += 
+      GC_NORMAL_HEADER_SIZE 
+      + numNonObjptrsToBytes (numNonObjptrs, tag) 
+      + (numObjptrs * OBJPTR_SIZE);
+    if (0 == numObjptrs) {
+      /* There is nothing to mark. */
+normalDone:
+      if (shouldHashCons)
+        cur = hashCons (s, cur, TRUE);
+      goto ret;
+    }
+    todo = cur + numNonObjptrsToBytes (numNonObjptrs, NORMAL_TAG);
+    index = 0;
+markInNormal:
+    if (DEBUG_MARK_COMPACT)
+      fprintf (stderr, "markInNormal  index = %d\n", index);
+    assert (index < numObjptrs);
+    // next = *(pointer*)todo;
+    next = fetchObjptrToPointer (todo, s->heap.start);
+    if (not isPointer (next)) {
+markNextInNormal:
+      assert (index < numObjptrs);
+      index++;
+      if (index == numObjptrs) {
+        /* Done.  Clear out the counters and return. */
+        *headerp = header & ~COUNTER_MASK;
+        goto normalDone;
+      }
+      todo += OBJPTR_SIZE;
+      goto markInNormal;
+    }
+    nextHeaderp = getHeaderp (next);
+    nextHeader = *nextHeaderp;
+    if (mark == (nextHeader & MARK_MASK)) {
+      maybeShareObjptr (s, (objptr*)todo, shouldHashCons);
+      goto markNextInNormal;
+    }
+    *headerp = (header & ~COUNTER_MASK) | (index << COUNTER_SHIFT);
+    goto markNext;
+  } else if (WEAK_TAG == tag) {
+    /* Store the marked header and don't follow any pointers. */
+    goto ret;
+  } else if (ARRAY_TAG == tag) {
+    /* When marking arrays:
+     *   arrayIndex is the index of the element to mark.
+     *   cur is the pointer to the array.
+     *   index is the index of the pointer within the element
+     *     (i.e. the i'th pointer is at index i).
+     *   todo is the start of the element.
+     */
+    size += 
+      GC_ARRAY_HEADER_SIZE
+      + arraySizeNoHeader (s, cur, numNonObjptrs, numObjptrs);
+    if (0 == numObjptrs or 0 == getArrayLength (cur)) {
+      /* There is nothing to mark. */
+arrayDone:
+      if (shouldHashCons)
+        cur = hashCons (s, cur, TRUE);
+      goto ret;
+    }
+    /* Begin marking first element. */
+    arrayIndex = 0;
+    todo = cur;
+markArrayElt:
+    assert (arrayIndex < getArrayLength (cur));
+    index = 0;
+    /* Skip to the first pointer. */
+    todo += numNonObjptrsToBytes (numNonObjptrs, ARRAY_TAG);
+markInArray:
+    if (DEBUG_MARK_COMPACT)
+      fprintf (stderr, "markInArray arrayIndex = %u index = %u\n",
+               arrayIndex, index);
+    assert (arrayIndex < getArrayLength (cur));
+    assert (index < numObjptrs);
+    assert (todo == arrayIndexAtPointer (s, cur, arrayIndex, index));
+    // next = *(pointer*)todo;
+    next = fetchObjptrToPointer (todo, s->heap.start);
+    if (not (isPointer(next))) {
+markNextInArray:
+      assert (arrayIndex < getArrayLength (cur));
+      assert (index < numObjptrs);
+      assert (todo == arrayIndexAtPointer (s, cur, arrayIndex, index));
+      todo += OBJPTR_SIZE;
+      index++;
+      if (index < numObjptrs)
+        goto markInArray;
+      arrayIndex++;
+      if (arrayIndex < getArrayLength (cur))
+        goto markArrayElt;
+      /* Done.  Clear out the counters and return. */
+      *getArrayCounterp (cur) = 0;
+      *headerp = header & ~COUNTER_MASK;
+      goto arrayDone;
+    }
+    nextHeaderp = getHeaderp (next);
+    nextHeader = *nextHeaderp;
+    if (mark == (nextHeader & MARK_MASK)) {
+      maybeShareObjptr (s, (objptr*)todo, shouldHashCons);
+      goto markNextInArray;
+    }
+    /* Recur and mark next. */
+    *getArrayCounterp (cur) = arrayIndex;
+    *headerp = (header & ~COUNTER_MASK) | (index << COUNTER_SHIFT);
+    goto markNext;
+  } else {
+    assert (STACK_TAG == tag);
+    size += 
+      GC_STACK_HEADER_SIZE
+      + sizeof (struct GC_stack) + ((GC_stack)cur)->reserved;
+    top = stackTop (s, (GC_stack)cur);
+    assert (((GC_stack)cur)->used <= ((GC_stack)cur)->reserved);
+markInStack:
+    /* Invariant: top points just past the return address of the frame
+     * to be marked.
+     */
+    assert (stackBottom (s, (GC_stack)cur) <= top);
+    if (DEBUG_MARK_COMPACT)
+      fprintf (stderr, "markInStack  top = %zu\n",
+               (size_t)(top - stackBottom (s, (GC_stack)cur)));
+    if (top == stackBottom (s, (GC_stack)(cur)))
+      goto ret;
+    index = 0;
+    returnAddress = *(GC_returnAddress*) (top - GC_RETURNADDRESS_SIZE);
+    frameLayout = getFrameLayoutFromReturnAddress (s, returnAddress);
+    frameOffsets = frameLayout->offsets;
+    ((GC_stack)cur)->markTop = top;
+markInFrame:
+    if (index == frameOffsets [0]) {
+      top -= frameLayout->size;
+      goto markInStack;
+    }
+    todo = top - frameLayout->size + frameOffsets [index + 1];
+    // next = *(pointer*)todo;
+    next = fetchObjptrToPointer (todo, s->heap.start);
+    if (DEBUG_MARK_COMPACT)
+      fprintf (stderr,
+               "    offset %u  todo "FMTPTR"  next = "FMTPTR"\n",
+               frameOffsets [index + 1],
+               (uintptr_t)todo, (uintptr_t)next);
+    if (not isPointer (next)) {
+      index++;
+      goto markInFrame;
+    }
+    nextHeaderp = getHeaderp (next);
+    nextHeader = *nextHeaderp;
+    if (mark == (nextHeader & MARK_MASK)) {
+      index++;
+      maybeShareObjptr (s, (objptr*)todo, shouldHashCons);
+      goto markInFrame;
+    }
+    ((GC_stack)cur)->markIndex = index;
+    goto markNext;
+  }
+  assert (FALSE);
+ret:
+  /* Done marking cur, continue with prev.
+   * Need to set the pointer in the prev object that pointed to cur 
+   * to point back to prev, and restore prev.
+   */
+  if (DEBUG_MARK_COMPACT)
+    fprintf (stderr, "return  cur = "FMTPTR"  prev = "FMTPTR"\n",
+             (uintptr_t)cur, (uintptr_t)prev);
+  assert (isMarkedMode (mode, cur));
+  if (NULL == prev)
+    return size;
+  next = cur;
+  cur = prev;
+  headerp = getHeaderp (cur);
+  header = *headerp;
+  splitHeader (s, header, &tag, NULL, &numNonObjptrs, &numObjptrs);
+  /* It's impossible to get a WEAK_TAG here, since we would never
+   * follow the weak object pointer.
+   */
+  assert (WEAK_TAG != tag);
+  if (NORMAL_TAG == tag) {
+    todo = cur + numNonObjptrsToBytes (numNonObjptrs, tag);
+    index = (header & COUNTER_MASK) >> COUNTER_SHIFT;
+    todo += index * OBJPTR_SIZE;
+    // prev = *(pointer*)todo;
+    prev = fetchObjptrToPointer (todo, s->heap.start);
+    // *(pointer*)todo = next;
+    storeObjptrFromPointer (todo, next, s->heap.start);
+    goto markNextInNormal;
+  } else if (ARRAY_TAG == tag) {
+    arrayIndex = getArrayCounter (cur);
+    todo = cur + arrayIndex * (numNonObjptrsToBytes (numNonObjptrs, ARRAY_TAG)
+                               + (numObjptrs * OBJPTR_SIZE));
+    index = (header & COUNTER_MASK) >> COUNTER_SHIFT;
+    todo += numNonObjptrsToBytes (numNonObjptrs, ARRAY_TAG) + index * OBJPTR_SIZE;
+    // prev = *(pointer*)todo;
+    prev = fetchObjptrToPointer (todo, s->heap.start);
+    // *(pointer*)todo = next;
+    storeObjptrFromPointer (todo, next, s->heap.start);
+    goto markNextInArray;
+  } else {
+    assert (STACK_TAG == tag);
+    index = ((GC_stack)cur)->markIndex;
+    top = ((GC_stack)cur)->markTop;
+    /* Invariant: top points just past a "return address". */
+    returnAddress = *(GC_returnAddress*) (top - GC_RETURNADDRESS_SIZE);
+    frameLayout = getFrameLayoutFromReturnAddress (s, returnAddress);
+    frameOffsets = frameLayout->offsets;
+    todo = top - frameLayout->size + frameOffsets [index + 1];
+    // prev = *(pointer*)todo;
+    prev = fetchObjptrToPointer (todo, s->heap.start);
+    // *(pointer*)todo = next;
+    storeObjptrFromPointer (todo, next, s->heap.start);
+    index++;
+    goto markInFrame;
+  }
+  assert (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-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/foreach.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -196,7 +196,7 @@
   assert (front <= b);
   while (front < b) {
     while (front < b) {
-      assert (isAligned ((uintptr_t)front, GC_MODEL_MINALIGN));
+      assert (isAligned ((size_t)front, GC_MODEL_MINALIGN));
       if (DEBUG_DETAILED)
         fprintf (stderr, 
                  "  front = "FMTPTR"  *back = "FMTPTR"\n",

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.c	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -6,24 +6,24 @@
  * See the file MLton-LICENSE for details.
  */
 
-static inline uint32_t 
+static inline GC_frameIndex
 getFrameIndexFromReturnAddress (GC_state s, GC_returnAddress ra) {
-  uint32_t res;
+  GC_frameIndex res;
 
   res = s->returnAddressToFrameIndex (ra);
   if (DEBUG_DETAILED)
-    fprintf (stderr, "%"PRIu32" = getFrameIndexFromReturnAddress ("FMTRA")\n",
+    fprintf (stderr, FMTFI" = getFrameIndexFromReturnAddress ("FMTRA")\n",
              res, ra);
   return res;
 }
 
 static inline GC_frameLayout * 
-getFrameLayoutFromFrameIndex (GC_state s, uint32_t index) {
+getFrameLayoutFromFrameIndex (GC_state s, GC_frameIndex index) {
   GC_frameLayout *layout;
 
   if (DEBUG_DETAILED)
     fprintf (stderr, 
-             "index = %"PRIu32
+             "index = "FMTFI
              "  frameLayoutsLength = %"PRIu32"\n",
             index, s->frameLayoutsLength);
   assert (index < s->frameLayoutsLength);
@@ -35,7 +35,7 @@
 static inline GC_frameLayout * 
 getFrameLayoutFromReturnAddress (GC_state s, GC_returnAddress ra) {
   GC_frameLayout *layout;
-  uint32_t index;
+  GC_frameIndex index;
   
   index = getFrameIndexFromReturnAddress (s, ra);
   layout = getFrameLayoutFromFrameIndex(s, index);

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.h	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.h	2005-10-10 01:54:23 UTC (rev 4100)
@@ -37,6 +37,9 @@
   uint16_t size;
   GC_frameOffsets offsets;
 } GC_frameLayout;
+typedef uint32_t GC_frameIndex;
+#define PRIFI PRIu32
+#define FMTFI "%"PRIFI
 
 typedef uintptr_t GC_returnAddress;
 #define GC_RETURNADDRESS_SIZE sizeof(GC_returnAddress)

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_prefix.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_prefix.c	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_prefix.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -1,9 +1,5 @@
 #include "gc.h"
 
-static inline size_t maxZ (size_t x, size_t y) {
-  return ((x < y) ? x : y);
-}
-
 static inline size_t meg (size_t n) {
   return n / (1024ul * 1024ul);
 }

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-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_state.h	2005-10-10 01:54:23 UTC (rev 4100)
@@ -6,7 +6,7 @@
   uint32_t atomicState;
   objptr callFromCHandlerThread; /* Handler for exported C calls (in heap). */
   bool canMinor; /* TRUE iff there is space for a minor gc. */
-  struct GC_control control;
+  struct GC_controls controls;
   struct GC_cumulativeStatistics cumulativeStatistics;
   objptr currentThread; /* Currently executing thread (in heap). */
   uint32_t exnStack;
@@ -21,11 +21,9 @@
   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.
@@ -37,7 +35,6 @@
   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. */
   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-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/generational.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -8,6 +8,34 @@
 
 #define CROSS_MAP_EMPTY ((GC_crossMapElem)255)
 
+void displayGenerationalMaps (__attribute__ ((unused)) GC_state s,
+                              struct GC_generationalMaps *generational,
+                              FILE *stream) {
+  fprintf(stream,
+          "\t\tcardMap ="FMTPTR"\n"
+          "\t\tcardMapAbsolute = "FMTPTR"\n"
+          "\t\tcardMapLength = %zu\n"
+          "\t\tcrossMap = "FMTPTR"\n"
+          "\t\tcrossMapLength = %zu\n"
+          "\t\tcrossMapValidSize = %zu\n",
+          (uintptr_t)generational->cardMap, 
+          (uintptr_t)generational->cardMapAbsolute,
+          generational->cardMapLength, 
+          (uintptr_t)generational->crossMap,
+          generational->crossMapLength,
+          generational->crossMapValidSize);
+  if (DEBUG_GENERATIONAL and DEBUG_DETAILED) {
+    unsigned int i;
+
+    fprintf (stderr, "crossMap trues\n");
+    for (i = 0; i < generational->crossMapLength; ++i)
+      unless (CROSS_MAP_EMPTY == generational->crossMap[i])
+        fprintf (stderr, "\t%u\n", i);
+    fprintf (stderr, "\n");
+  }               
+}
+
+
 static inline uintptr_t pointerToCardIndex (pointer p) {
   return (uintptr_t)p >> CARD_SIZE_LOG2;
 }
@@ -84,21 +112,21 @@
   size_t totalMapSize;
 
   cardMapLength = sizeToCardIndex (s->heap.size);
-  cardMapSize = align (cardMapLength * CARD_MAP_ELEM_SIZE, s->pageSize);
+  cardMapSize = align (cardMapLength * CARD_MAP_ELEM_SIZE, s->sysvals.pageSize);
   cardMapLength = cardMapSize / CARD_MAP_ELEM_SIZE;
   s->generationalMaps.cardMapLength = cardMapLength;
 
   crossMapLength = sizeToCardIndex (s->heap.size);
-  crossMapSize = align (crossMapLength * CROSS_MAP_ELEM_SIZE, s->pageSize);
+  crossMapSize = align (crossMapLength * CROSS_MAP_ELEM_SIZE, s->sysvals.pageSize);
   crossMapLength = crossMapSize / CROSS_MAP_ELEM_SIZE;
   s->generationalMaps.crossMapLength = crossMapLength;
 
   totalMapSize = cardMapSize + crossMapSize;
   if (DEBUG_MEM)
-    fprintf (stderr, "Creating card/cross map of size %zd\n",
+    fprintf (stderr, "Creating card/cross map of size %zu\n",
              /*uintToCommaString*/(totalMapSize));
   s->generationalMaps.cardMap = 
-    GC_mmapAnon (totalMapSize);
+    GC_mmapAnon_safe (NULL, totalMapSize);
   s->generationalMaps.crossMap = 
     (GC_crossMapElem*)((pointer)s->generationalMaps.cardMap + cardMapSize);
   if (DEBUG_CARD_MARKING)
@@ -140,7 +168,7 @@
   if (DEBUG)
     fprintf (stderr, "crossMapIsOK ()\n");
   mapSize = s->generationalMaps.crossMapLength * CROSS_MAP_ELEM_SIZE;
-  map = GC_mmapAnon (mapSize);
+  map = GC_mmapAnon_safe (NULL, mapSize);
   memset (map, CROSS_MAP_EMPTY, mapSize);
   back = s->heap.start + s->heap.oldGenSize;
   cardIndex = 0;
@@ -216,7 +244,7 @@
 static inline void resizeCardMapAndCrossMap (GC_state s) {
   if (s->mutatorMarksCards
       and (s->generationalMaps.cardMapLength * CARD_MAP_ELEM_SIZE)
-          != align (sizeToCardIndex (s->heap.size), s->pageSize)) {
+          != align (sizeToCardIndex (s->heap.size), s->sysvals.pageSize)) {
     GC_cardMapElem *oldCardMap;
     size_t oldCardMapSize;
     GC_crossMapElem *oldCrossMap;
@@ -235,30 +263,3 @@
     GC_munmap (oldCardMap, oldCardMapSize + oldCrossMapSize);
   }
 }
-
-void displayGenerationalMaps (__attribute__ ((unused)) GC_state s,
-                              struct GC_generationalMaps *generational,
-                              FILE *stream) {
-  fprintf(stream,
-          "\t\tcardMap ="FMTPTR"\n"
-          "\t\tcardMapAbsolute = "FMTPTR"\n"
-          "\t\tcardMapLength = %zu\n"
-          "\t\tcrossMap = "FMTPTR"\n"
-          "\t\tcrossMapLength = %zu\n"
-          "\t\tcrossMapValidSize = %zu\n",
-          (uintptr_t)generational->cardMap, 
-          (uintptr_t)generational->cardMapAbsolute,
-          generational->cardMapLength, 
-          (uintptr_t)generational->crossMap,
-          generational->crossMapLength,
-          generational->crossMapValidSize);
-  if (DEBUG_GENERATIONAL and DEBUG_DETAILED) {
-    unsigned int i;
-
-    fprintf (stderr, "crossMap trues\n");
-    for (i = 0; i < generational->crossMapLength; ++i)
-      unless (CROSS_MAP_EMPTY == generational->crossMap[i])
-        fprintf (stderr, "\t%u\n", i);
-    fprintf (stderr, "\n");
-  }               
-}

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/hash-cons.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/hash-cons.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -0,0 +1,301 @@
+/* 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.
+ */
+
+/* ---------------------------------------------------------------- */
+/*                       Object hash consing                        */
+/* ---------------------------------------------------------------- */
+
+/* Hashing based on Introduction to Algorithms by Cormen, Leiserson, and Rivest.
+ * Section numbers in parens.
+ * k is key to be hashed.
+ * table is of size 2^p  (it must be a power of two)
+ * Open addressing (12.4), meaning that we stick the entries directly in the 
+ *   table and probe until we find what we want.
+ * Multiplication method (12.3.2), meaning that we compute the hash by 
+ *   multiplying by a magic number, chosen by Knuth, and take the high-order p
+ *   bits of the low order 32 bits.
+ * Double hashing (12.4), meaning that we use two hash functions, the first to
+ *   decide where to start looking and a second to decide at what offset to
+ *   probe.  The second hash must be relatively prime to the table size, which
+ *   we ensure by making it odd and keeping the table size as a power of 2.
+ */
+
+static GC_ObjectHashTable newTable (GC_state s) {
+        int i;
+        uint maxElementsSize;
+        pointer regionStart;
+        pointer regionEnd;
+        GC_ObjectHashTable t;
+
+        NEW (GC_ObjectHashTable, t);
+        // Try to use space in the heap for the elements.
+        if (not (heapIsInit (&s->heap2))) {
+                if (DEBUG_SHARE)
+                        fprintf (stderr, "using heap2\n");
+                // We have all of heap2 available.  Use it.
+                regionStart = s->heap2.start;
+                regionEnd = s->heap2.start + s->heap2.size;
+        } else if (s->amInGC or not s->canMinor) {
+                if (DEBUG_SHARE)
+                        fprintf (stderr, "using end of heap\n");
+                regionStart = s->frontier;
+                regionEnd = s->limitPlusSlop;
+        } else {
+                if (DEBUG_SHARE)
+                        fprintf (stderr, "using minor space\n");
+                // Use the space available for a minor GC.
+                assert (s->canMinor);
+                regionStart = s->heap.start + s->oldGenSize;
+                regionEnd = s->nursery;
+        }
+        maxElementsSize = (regionEnd - regionStart) / sizeof (*(t->elements));
+        if (DEBUG_SHARE)
+                fprintf (stderr, "maxElementsSize = %u\n", maxElementsSize);
+        t->elementsSize = 64;  // some small power of two
+        t->log2ElementsSize = 6;  // and its log base 2
+        if (maxElementsSize < t->elementsSize) {
+                if (DEBUG_SHARE)
+                        fprintf (stderr, "too small -- using malloc\n");
+                t->elementsIsInHeap = FALSE;
+                ARRAY (struct GC_ObjectHashElement *, t->elements, t->elementsSize);
+        } else {
+                t->elementsIsInHeap = TRUE;
+                t->elements = (struct GC_ObjectHashElement*)regionStart;
+                // Find the largest power of two that fits.
+                for (; t->elementsSize <= maxElementsSize; 
+                        t->elementsSize <<= 1, t->log2ElementsSize++)
+                        ; // nothing
+                t->elementsSize >>= 1;
+                t->log2ElementsSize--;
+                assert (t->elementsSize <= maxElementsSize);
+                for (i = 0; i < t->elementsSize; ++i)
+                        t->elements[i].object = NULL;
+        }
+        t->numElements = 0;
+        t->mayInsert = TRUE;
+        if (DEBUG_SHARE) {
+                fprintf (stderr, "elementsIsInHeap = %s\n", 
+                                boolToString (t->elementsIsInHeap));
+                fprintf (stderr, "elementsSize = %u\n", t->elementsSize);
+                fprintf (stderr, "0x%08x = newTable ()\n", (uint)t);
+        }
+        return t;
+}
+
+static void destroyTable (GC_ObjectHashTable t) {
+        unless (t->elementsIsInHeap)
+                free (t->elements);
+        free (t);
+}
+
+static inline Pointer tableInsert 
+        (GC_state s, GC_ObjectHashTable t, W32 hash, Pointer object, 
+                Bool mightBeThere, Header header, W32 tag, Pointer max) {
+        GC_ObjectHashElement e;
+        Header header2;
+        static Bool init = FALSE;
+        static int maxNumProbes = 0;
+        static W64 mult; // magic multiplier for hashing
+        int numProbes;
+        W32 probe;
+        word *p;
+        word *p2;
+        W32 slot; // slot in hash table we are considering
+
+        if (DEBUG_SHARE)
+                fprintf (stderr, "tableInsert (%u, 0x%08x, %s, 0x%08x, 0x%08x)\n",
+                                (uint)hash, (uint)object, 
+                                boolToString (mightBeThere),
+                                (uint)header, (uint)max);
+        if (! init) {
+                init = TRUE;
+                mult = floor (((sqrt (5.0) - 1.0) / 2.0)
+                                * (double)0x100000000llu);
+        }
+        slot = (W32)(mult * (W64)hash) >> (32 - t->log2ElementsSize);
+        probe = (1 == slot % 2) ? slot : slot - 1;
+        if (DEBUG_SHARE)
+                fprintf (stderr, "probe = 0x%08x\n", (uint)probe);
+        assert (1 == probe % 2);
+        numProbes = 0;
+look:
+        if (DEBUG_SHARE)
+                fprintf (stderr, "slot = 0x%08x\n", (uint)slot);
+        assert (0 <= slot and slot < t->elementsSize);
+        numProbes++;
+        e = &t->elements[slot];
+        if (NULL == e->object) {
+                /* It's not in the table.  Add it. */
+                unless (t->mayInsert) {
+                        if (DEBUG_SHARE)
+                                fprintf (stderr, "not inserting\n");
+                        return object;
+                }
+                e->hash = hash;
+                e->object = object;
+                t->numElements++;
+                if (numProbes > maxNumProbes) {
+                        maxNumProbes = numProbes;
+                        if (DEBUG_SHARE)
+                                fprintf (stderr, "numProbes = %d\n", numProbes);
+                }
+                return object;
+        }
+        unless (hash == e->hash) {
+lookNext:
+                slot = (slot + probe) % t->elementsSize;
+                goto look;
+        }
+        unless (mightBeThere)
+                goto lookNext;
+        if (DEBUG_SHARE)
+                fprintf (stderr, "comparing 0x%08x to 0x%08x\n",
+                                (uint)object, (uint)e->object);
+        /* Compare object to e->object. */
+        unless (object == e->object) {
+                header2 = GC_getHeader (e->object);
+                unless (header == header2)
+                        goto lookNext;
+                for (p = (word*)object, p2 = (word*)e->object; 
+                                p < (word*)max; 
+                                ++p, ++p2)
+                        unless (*p == *p2)
+                                goto lookNext;
+                if (ARRAY_TAG == tag
+                        and (GC_arrayNumElements (object)
+                                != GC_arrayNumElements (e->object)))
+                        goto lookNext;
+        }
+        /* object is equal to e->object. */
+        return e->object;
+}
+
+static void maybeGrowTable (GC_state s, GC_ObjectHashTable t) { 
+        int i;
+        GC_ObjectHashElement oldElement;
+        struct GC_ObjectHashElement *oldElements;
+        uint oldSize;
+        uint newSize;
+
+        if (not t->mayInsert or t->numElements * 2 <= t->elementsSize)
+                return;
+        oldElements = t->elements;
+        oldSize = t->elementsSize;
+        newSize = oldSize * 2;
+        if (DEBUG_SHARE)
+                fprintf (stderr, "trying to grow table to size %d\n", newSize);
+        // Try to alocate the new table.
+        ARRAY_UNSAFE (struct GC_ObjectHashElement *, t->elements, newSize);
+        if (NULL == t->elements) {
+                t->mayInsert = FALSE;
+                t->elements = oldElements;
+                if (DEBUG_SHARE)
+                        fprintf (stderr, "unable to grow table\n");
+                return;
+        }
+        t->elementsSize = newSize;
+        t->log2ElementsSize++;
+        for (i = 0; i < oldSize; ++i) {
+                oldElement = &oldElements[i];
+                unless (NULL == oldElement->object)
+                        tableInsert (s, t, oldElement->hash, oldElement->object,
+                                        FALSE, 0, 0, 0);
+        }
+        if (t->elementsIsInHeap)
+                t->elementsIsInHeap = FALSE;
+        else
+                free (oldElements);
+        if (DEBUG_SHARE)
+                fprintf (stderr, "done growing table\n");
+}
+
+static Pointer hashCons (GC_state s, Pointer object, Bool countBytesHashConsed) {
+        Bool hasIdentity;
+        Word32 hash;
+        Header header;
+        pointer max;
+        uint numNonPointers;
+        uint numPointers;
+        word *p;
+        Pointer res;
+        GC_ObjectHashTable t;
+        uint tag;
+
+        if (DEBUG_SHARE)
+                fprintf (stderr, "hashCons (0x%08x)\n", (uint)object);
+        t = s->objectHashTable;
+        header = GC_getHeader (object);
+        SPLIT_HEADER ();
+        if (hasIdentity) {
+                /* Don't hash cons. */
+                res = object;
+                goto done;
+        }
+        assert (ARRAY_TAG == tag or NORMAL_TAG == tag);
+        max = object
+                + (ARRAY_TAG == tag
+                        ? arrayNumBytes (s, object,
+                                                numPointers, numNonPointers)
+                        : toBytes (numPointers + numNonPointers));
+        // Compute the hash.
+        hash = header;
+        for (p = (word*)object; p < (word*)max; ++p)
+                hash = hash * 31 + *p;
+        /* Insert into table. */
+        res = tableInsert (s, t, hash, object, TRUE, header, tag, (Pointer)max);
+        maybeGrowTable (s, t);
+        if (countBytesHashConsed and res != object) {
+                uint amount;
+
+                amount = max - object;
+                if (ARRAY_TAG == tag)
+                        amount += GC_ARRAY_HEADER_SIZE;
+                else
+                        amount += GC_NORMAL_HEADER_SIZE;
+                s->bytesHashConsed += amount;
+        }
+done:
+        if (DEBUG_SHARE)
+                fprintf (stderr, "0x%08x = hashCons (0x%08x)\n", 
+                                (uint)res, (uint)object);
+        return res;
+}
+
+static inline void maybeSharePointer (GC_state s,
+                                        Pointer *pp, 
+                                        Bool shouldHashCons) {
+        unless (shouldHashCons)
+                return;
+        if (DEBUG_SHARE)
+                fprintf (stderr, "maybeSharePointer  pp = 0x%08x  *pp = 0x%08x\n",
+                                (uint)pp, (uint)*pp);
+        *pp = hashCons (s, *pp, FALSE); 
+}
+
+static void bytesHashConsedMessage (GC_state s, ullong total) {
+        fprintf (stderr, "%s bytes hash consed (%.1f%%).\n",
+                ullongToCommaString (s->bytesHashConsed),
+                100.0 * ((double)s->bytesHashConsed / (double)total));
+}
+
+void GC_share (GC_state s, Pointer object) {
+        W32 total;
+
+        if (DEBUG_SHARE)
+                fprintf (stderr, "GC_share 0x%08x\n", (uint)object);
+        if (DEBUG_SHARE or s->messages)
+                s->bytesHashConsed = 0;
+        // Don't hash cons during the first round of marking.
+        total = mark (s, object, MARK_MODE, FALSE);
+        s->objectHashTable = newTable (s);
+        // Hash cons during the second round of marking.
+        mark (s, object, UNMARK_MODE, TRUE);
+        destroyTable (s->objectHashTable);
+        if (DEBUG_SHARE or s->messages)
+                bytesHashConsedMessage (s, total);
+}

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/hash-cons.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/hash-cons.h	2005-10-10 01:54:23 UTC (rev 4100)
@@ -0,0 +1,33 @@
+/* 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.
+ */
+
+/* ---------------------------------------------------------------- */
+/*                       Object hash consing                        */
+/* ---------------------------------------------------------------- */
+
+typedef uint32_t GC_hash;
+
+typedef struct GC_objectHashElement {
+  GC_hash hash;
+  pointer object;
+} *GC_objectHashElement;
+
+typedef struct GC_objectHashTable {
+  struct GC_objectHashElement *elements;
+  bool elementsIsInHeap;
+  size_t elementsSize;
+  int log2ElementsSize;
+  bool mayInsert;
+  int32_t numElements;
+} *GC_ObjectHashTable;
+
+pointer hashCons (GC_state s, pointer object,
+                  bool countBytesHashConsed);
+void maybeShareObjptr (GC_state s,
+                       objptr *opp,
+                       bool shouldHashCons);

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -5,91 +5,134 @@
  * See the file MLton-LICENSE for details.
  */
 
-static inline bool pointerIsInHeap (GC_state s, pointer p) {
-  return (not (isPointer (p))
-          or (s->heap.start <= p 
-              and p < s->frontier));
+void displayHeap (__attribute__ ((unused)) GC_state s,
+                  GC_heap heap,
+                  FILE *stream) {
+  fprintf(stream,
+          "\t\tnursery ="FMTPTR"\n"
+          "\t\toldGenSize = %zu\n"
+          "\t\tstart = "FMTPTR"\n"
+          "\t\tsize = %zu\n",
+          (uintptr_t)heap->nursery,
+          heap->oldGenSize,
+          (uintptr_t)heap->start,
+          heap->size);
 }
 
-static inline bool objptrIsInHeap (GC_state s, objptr op) {
-  pointer p;
-  if (not (isObjptr(op)))
-    return TRUE;
-  p = objptrToPointer (op, s->heap.start);
-  return pointerIsInHeap (s, p);
-}
 
-static inline bool pointerIsInOldGen (GC_state s, pointer p) {
-  return (not (isPointer (p))
-          or (s->heap.start <= p 
-              and p < s->heap.start + s->heap.oldGenSize));
+static inline void heapInit (GC_heap h) {
+  h->start = NULL;
+  h->size = 0;
+  h->oldGenSize = 0;
+  h->nursery = NULL;
 }
 
-static inline bool objptrIsInOldGen (GC_state s, objptr op) {
-  pointer p;
-  if (not (isObjptr(op)))
-    return TRUE;
-  p = objptrToPointer (op, s->heap.start);
-  return pointerIsInOldGen (s, p);
+static void heapRelease (GC_state s, GC_heap h) {
+  if (NULL == h->start)
+    return;
+  if (DEBUG or s->controls.messages)
+    fprintf (stderr, "Releasing heap at "FMTPTR" of size %zu.\n",
+             (uintptr_t)h->start,
+             /*uintToCommaString*/(h->size));
+  GC_release (h->start, h->size);
+  heapInit (h);
 }
 
-static inline bool pointerIsInNursery (GC_state s, pointer p) {
-  return (not (isPointer (p))
-          or (s->heap.nursery <= p and p < s->frontier));
+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->sysvals.pageSize);
+  if (keep < h->size) {
+    if (DEBUG or s->controls.messages)
+      fprintf (stderr,
+               "Shrinking heap at "FMTPTR" of size %zu to %zu bytes.\n",
+               (uintptr_t)h->start,
+               /*uintToCommaString*/(h->size),
+               /*uintToCommaString*/(keep));
+    GC_decommit (h->start + keep, h->size - keep);
+    h->size = keep;
+  }
 }
 
-static inline bool objptrIsInNursery (GC_state s, objptr op) {
-  pointer p;
-  if (not (isObjptr(op)))
-    return TRUE;
-  p = objptrToPointer (op, s->heap.start);
-  return pointerIsInNursery (s, p);
-}
+/* heapCreate (s, h, desiredSize, minSize) 
+ * 
+ * allocates a heap of the size necessary to work with desiredSize
+ * live data, and ensures that at least minSize is available.  It
+ * returns TRUE if it is able to allocate the space, and returns FALSE
+ * if it is unable.  If a reasonable size to space is already there,
+ * then heapCreate leaves it.
+ */
+static bool heapCreate (GC_state s, GC_heap h, 
+                        size_t desiredSize, 
+                        size_t minSize) {
+  size_t backoff;
 
-static inline bool pointerIsInFromSpace (GC_state s, pointer p) {
-  return (pointerIsInOldGen (s, p) or pointerIsInNursery (s, p));
-}
+  if (DEBUG_MEM)
+    fprintf (stderr, "heapCreate  desired size = %zu  min size = %zu\n",
+             /*uintToCommaString*/(desiredSize),
+             /*uintToCommaString*/(minSize));
+  assert (heapIsInit (h));
+  if (desiredSize < minSize)
+    desiredSize = minSize;
+  desiredSize = align (desiredSize, s->sysvals.pageSize);
+  assert (0 == h->size and NULL == h->start);
+  backoff = (desiredSize - minSize) / 20;
+  if (0 == backoff)
+    backoff = 1; /* enough to terminate the loop below */
+  backoff = align (backoff, s->sysvals.pageSize);
+  /* mmap toggling back and forth between high and low addresses to
+   * decrease the chance of virtual memory fragmentation causing an mmap
+   * to fail.  This is important for large heaps.
+   */
+  for (h->size = desiredSize; h->size >= minSize; h->size -= backoff) {
+    const size_t highAddress = ((size_t)0xf8) << ((POINTER_SIZE - 1) * 8);
+    const size_t step = (size_t)0x08000000;
+    const size_t count = highAddress / step;
 
-static inline bool objptrIsInFromSpace (GC_state s, objptr op) {
-  return (objptrIsInOldGen (s, op) or objptrIsInNursery (s, op));
-}
+    static bool direction = TRUE;
+    unsigned int i;
 
-#if ASSERT
-static bool heapHasBytesFree (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",
-             boolToString (res),
-             /*uintToCommaString*/(oldGen),
-             /*uintToCommaString*/(nursery));
-  return res;
+    assert (isAligned (h->size, s->sysvals.pageSize));
+    for (i = 0; i <= count; i++) {
+      size_t address;
+      
+      address = i * step;
+      if (direction)
+        address = highAddress - address;
+      h->start = GC_mmapAnon ((pointer)address, h->size);
+      if ((void*)-1 == h->start)
+        h->start = (void*)NULL;
+      unless ((void*)NULL == h->start) {
+        direction = not direction;
+        if (h->size > s->cumulativeStatistics.maxHeapSizeSeen)
+          s->cumulativeStatistics.maxHeapSizeSeen = h->size;
+        if (DEBUG or s->controls.messages)
+          fprintf (stderr, "Created heap of size %zu at "FMTPTR".\n",
+                   /*uintToCommaString*/(h->size),
+                   (uintptr_t)h->start);
+        assert (h->size >= minSize);
+        return TRUE;
+      }
+    }
+    if (s->controls.messages)
+      fprintf(stderr, 
+              "[Requested %zuM cannot be satisfied, "
+              "backing off by %zuM (min size = %zuM).\n",
+              meg (h->size), meg (backoff), meg (minSize));
+  }
+  h->size = 0;
+  return FALSE;
 }
-#endif
 
-void displayHeap (__attribute__ ((unused)) GC_state s,
-                  GC_heap heap,
-                  FILE *stream) {
-  fprintf(stream,
-          "\t\tnursery ="FMTPTR"\n"
-          "\t\toldGenSize = %zu\n"
-          "\t\tstart = "FMTPTR"\n"
-          "\t\tsize = %zu\n",
-          (uintptr_t)heap->nursery,
-          heap->oldGenSize,
-          (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.
+
+/* heapDesiredSize (s, l, cs) 
+ *
+ * returns the desired heap size for a heap with l bytes live, given
+ * that the current heap size is cs.
  */
 static size_t heapDesiredSize (GC_state s, size_t live, size_t currentSize) {
   size_t res;
@@ -112,7 +155,7 @@
      * 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);
+    res = alignDown (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;
@@ -140,23 +183,23 @@
      * growFromSpace will make the right thing happen.
      */ 
   }
-  if (s->control.fixedHeap > 0) {
-    if (res > s->control.fixedHeap / 2)
-      res = s->control.fixedHeap;
+  if (s->controls.fixedHeap > 0) {
+    if (res > s->controls.fixedHeap / 2)
+      res = s->controls.fixedHeap;
     else
-      res = s->control.fixedHeap / 2;
+      res = s->controls.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;
+      die ("Out of memory with fixed heap size %zu.",
+           /*uintToCommaString*/(s->controls.fixedHeap));
+  } else if (s->controls.maxHeap > 0) {
+    if (res > s->controls.maxHeap)
+      res = s->controls.maxHeap;
     if (res < live)
-      die ("Out of memory with max heap size %zd.",
-           /*uintToCommaString*/(s->control.maxHeap));
+      die ("Out of memory with max heap size %zu.",
+           /*uintToCommaString*/(s->controls.maxHeap));
   }
   if (DEBUG_RESIZING)
-    fprintf (stderr, "%zd = heapDesiredSize (%zd, %zd)\n",
+    fprintf (stderr, "%zu = heapDesiredSize (%zu, %zu)\n",
              /*uintToCommaString*/(res),
              /*uintToCommaString*/(live),
              /*uintToCommaString*/(currentSize));
@@ -164,47 +207,6 @@
   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) {
@@ -212,7 +214,7 @@
   size_t nurserySize;
 
   if (DEBUG_DETAILED)
-    fprintf (stderr, "setNursery(%zd, %zd)\n",
+    fprintf (stderr, "setNursery(%zu, %zu)\n",
              /*uintToCommaString*/(oldGenBytesRequested),
              /*uintToCommaString*/(nurseryBytesRequested));
   h = &s->heap;
@@ -271,66 +273,3 @@
   assert (heapHasBytesFree (s, oldGenBytesRequested, nurseryBytesRequested));
 }
 
-/* heapCreate (s, h, desiredSize, minSize) 
- * 
- * allocates a heap of the size necessary to work with desiredSize
- * live data, and ensures that at least minSize is available.  It
- * returns TRUE if it is able to allocate the space, and returns FALSE
- * if it is unable.  If a reasonable size to space is already there,
- * then heapCreate leaves it.
- */
-static bool heapCreate (GC_state s, GC_heap h, 
-                        size_t desiredSize, 
-                        size_t minSize) {
-  size_t backoff;
-
-  if (DEBUG_MEM)
-    fprintf (stderr, "heapCreate  desired size = %zd  min size = %zd\n",
-             /*uintToCommaString*/(desiredSize),
-             /*uintToCommaString*/(minSize));
-  assert (heapIsInit (h));
-  if (desiredSize < minSize)
-    desiredSize = minSize;
-  desiredSize = align (desiredSize, s->sysvals.pageSize);
-  assert (0 == h->size and NULL == h->start);
-  backoff = (desiredSize - minSize) / 20;
-  if (0 == backoff)
-    backoff = 1; /* enough to terminate the loop below */
-  backoff = align (backoff, s->sysvals.pageSize);
-  /* mmap toggling back and forth between high and low addresses to
-   * decrease the chance of virtual memory fragmentation causing an mmap
-   * to fail.  This is important for large heaps.
-   */
-  for (h->size = desiredSize; h->size >= minSize; h->size -= backoff) {
-    static bool direction = TRUE;
-    unsigned int i;
-
-    assert (isAligned (h->size, s->sysvals.pageSize));
-    for (i = 0; i < 32; i++) {
-      size_t address;
-      
-      address = i * 0x08000000ul;
-      if (direction)
-        address = 0xf8000000ul - address;
-      h->start = GC_mmap ((void*)address, h->size);
-      if ((void*)-1 == h->start)
-        h->start = (void*)NULL;
-      unless ((void*)NULL == h->start) {
-        direction = not direction;
-        if (h->size > s->cumulativeStatistics.maxHeapSizeSeen)
-          s->cumulativeStatistics.maxHeapSizeSeen = h->size;
-        if (DEBUG or s->messages)
-          fprintf (stderr, "Created heap of size %zd at "FMTPTR".\n",
-                   /*uintToCommaString*/(h->size),
-                   (uintptr_t)h->start);
-        assert (h->size >= minSize);
-        return TRUE;
-      }
-    }
-    if (s->messages)
-      fprintf(stderr, "[Requested %zuM cannot be satisfied, backing off by %zuM (min size = %zuM).\n",
-              meg (h->size), meg (backoff), meg (minSize));
-  }
-  h->size = 0;
-  return FALSE;
-}

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap_predicates.c (from rev 4099, mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap_predicates.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -0,0 +1,79 @@
+/* Copyright (C) 2005-2005 Henry Cejtin, Matthew Fluet, Suresh
+ *    Jagannathan, and Stephen Weeks.
+ *
+ * MLton is released under a BSD-style license.
+ * See the file MLton-LICENSE for details.
+ */
+
+static inline bool pointerIsInHeap (GC_state s, pointer p) {
+  return (not (isPointer (p))
+          or (s->heap.start <= p 
+              and p < s->frontier));
+}
+
+static inline bool objptrIsInHeap (GC_state s, objptr op) {
+  pointer p;
+  if (not (isObjptr(op)))
+    return TRUE;
+  p = objptrToPointer (op, s->heap.start);
+  return pointerIsInHeap (s, p);
+}
+
+static inline bool pointerIsInOldGen (GC_state s, pointer p) {
+  return (not (isPointer (p))
+          or (s->heap.start <= p 
+              and p < s->heap.start + s->heap.oldGenSize));
+}
+
+static inline bool objptrIsInOldGen (GC_state s, objptr op) {
+  pointer p;
+  if (not (isObjptr(op)))
+    return TRUE;
+  p = objptrToPointer (op, s->heap.start);
+  return pointerIsInOldGen (s, p);
+}
+
+static inline bool pointerIsInNursery (GC_state s, pointer p) {
+  return (not (isPointer (p))
+          or (s->heap.nursery <= p and p < s->frontier));
+}
+
+static inline bool objptrIsInNursery (GC_state s, objptr op) {
+  pointer p;
+  if (not (isObjptr(op)))
+    return TRUE;
+  p = objptrToPointer (op, s->heap.start);
+  return pointerIsInNursery (s, p);
+}
+
+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 heapHasBytesFree (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 (%zu, %zu)\n",
+             boolToString (res),
+             /*uintToCommaString*/(oldGen),
+             /*uintToCommaString*/(nursery));
+  return res;
+}
+#endif
+
+static inline bool heapIsInit (GC_heap h) {
+  return 0 == h->size;
+}

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.c	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -42,7 +42,7 @@
             < (s->generationalMaps.cardMap 
                + (s->generationalMaps.cardMapLength * CARD_MAP_ELEM_SIZE)));
   }
-  assert (isAligned (s->heap.size, s->pageSize));
+  assert (isAligned (s->heap.size, s->sysvals.pageSize));
   assert (isAligned ((size_t)s->heap.start, CARD_SIZE));
   assert (isAlignedFrontier (s, s->heap.start + s->heap.oldGenSize));
   assert (isAlignedFrontier (s, s->heap.nursery));
@@ -69,7 +69,7 @@
                         FALSE, assertObjptrIsInFromSpace);
   /* Current thread. */
   GC_stack stack = currentThreadStack(s);
-  assert (isAlignedReserved (s, stack->reserved));
+  assert (isAlignedStackReserved (s, stack->reserved));
   assert (s->stackBottom == stackBottom (s, stack));
   assert (s->stackTop == stackTop (s, stack));
   assert (s->stackLimit == stackLimit (s, stack));

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/major.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/major.h	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/major.h	2005-10-10 01:54:23 UTC (rev 4100)
@@ -7,6 +7,6 @@
  */
 
 typedef enum {
-        GC_COPYING,
-        GC_MARK_COMPACT,
+  GC_COPYING,
+  GC_MARK_COMPACT,
 } GC_majorKind;

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-compact.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/mark-compact.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -0,0 +1,282 @@
+/* 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.
+ */
+
+/* ---------------------------------------------------------------- */
+/*                 Jonkers Mark-compact Collection                  */
+/* ---------------------------------------------------------------- */
+
+static inline void markGlobalTrue (GC_state s, pointer *pp) {
+        mark (s, *pp, MARK_MODE, TRUE);
+}
+
+static inline void markGlobalFalse (GC_state s, pointer *pp) {
+        mark (s, *pp, MARK_MODE, FALSE);
+}
+
+static inline void unmarkGlobal (GC_state s, pointer *pp) {
+        mark (s, *pp, UNMARK_MODE, FALSE);
+}
+
+static inline void threadInternal (GC_state s, pointer *pp) {
+        Header *headerp;
+
+        if (FALSE)
+                fprintf (stderr, "threadInternal pp = 0x%08x  *pp = 0x%08x  header = 0x%08x\n",
+                                (uint)pp, *(uint*)pp, (uint)GC_getHeader (*pp));
+        headerp = GC_getHeaderp (*pp);
+        *(Header*)pp = *headerp;
+        *headerp = (Header)pp;
+}
+
+/* If p is weak, the object pointer was valid, and points to an unmarked object,
+ * then clear the object pointer.
+ */
+static inline void maybeClearWeak (GC_state s, pointer p) {
+        Bool hasIdentity;
+        Header header;
+        Header *headerp;
+        uint numPointers;
+        uint numNonPointers;
+        uint tag;
+
+        headerp = GC_getHeaderp (p);
+        header = *headerp;
+        SPLIT_HEADER();
+        if (WEAK_TAG == tag and 1 == numPointers) { 
+                Header h2;
+
+                if (DEBUG_WEAK)
+                        fprintf (stderr, "maybeClearWeak (0x%08x)  header = 0x%08x\n",
+                                        (uint)p, (uint)header);
+                h2 = GC_getHeader (((GC_weak)p)->object);
+                /* If it's unmarked not threaded, clear the weak pointer. */
+                if (1 == ((MARK_MASK | 1) & h2)) {
+                        ((GC_weak)p)->object = (pointer)BOGUS_POINTER;
+                        header = WEAK_GONE_HEADER | MARK_MASK;
+                        if (DEBUG_WEAK)
+                                fprintf (stderr, "cleared.  new header = 0x%08x\n",
+                                                (uint)header);
+                        *headerp = header;
+                }
+        }
+}
+
+static void updateForwardPointers (GC_state s) {
+        pointer back;
+        pointer front;
+        uint gap;
+        pointer endOfLastMarked;
+        Header header;
+        Header *headerp;
+        pointer p;
+        uint size;
+
+        if (DEBUG_MARK_COMPACT)
+                fprintf (stderr, "Update forward pointers.\n");
+        front = alignFrontier (s, s->heap.start);
+        back = s->heap.start + s->oldGenSize;
+        endOfLastMarked = front;
+        gap = 0;
+updateObject:
+        if (DEBUG_MARK_COMPACT)
+                fprintf (stderr, "updateObject  front = 0x%08x  back = 0x%08x\n",
+                                (uint)front, (uint)back);
+        if (front == back)
+                goto done;
+        headerp = (Header*)front;
+        header = *headerp;
+        if (0 == header) {
+                /* We're looking at an array.  Move to the header. */
+                p = front + 3 * WORD_SIZE;
+                headerp = (Header*)(p - WORD_SIZE);
+                header = *headerp;
+        } else 
+                p = front + WORD_SIZE;
+        if (1 == (1 & header)) {
+                /* It's a header */
+                if (MARK_MASK & header) {
+                        /* It is marked, but has no forward pointers. 
+                         * Thread internal pointers.
+                         */
+thread:
+                        maybeClearWeak (s, p);
+                        size = objectSize (s, p);
+                        if (DEBUG_MARK_COMPACT)
+                                fprintf (stderr, "threading 0x%08x of size %u\n", 
+                                                (uint)p, size);
+                        if (front - endOfLastMarked >= 4 * WORD_SIZE) {
+                                /* Compress all of the unmarked into one string.
+                                 * We require 4 * WORD_SIZE space to be available
+                                 * because that is the smallest possible array.
+                                 * You cannot use 3 * WORD_SIZE because even
+                                 * zero-length arrays require an extra word for
+                                 * the forwarding pointer.  If you did use
+                                 * 3 * WORD_SIZE, updateBackwardPointersAndSlide
+                                 * would skip the extra word and be completely
+                                 * busted.
+                                 */
+                                if (DEBUG_MARK_COMPACT)
+                                        fprintf (stderr, "compressing from 0x%08x to 0x%08x (length = %u)\n",
+                                                        (uint)endOfLastMarked,
+                                                        (uint)front,
+                                                        front - endOfLastMarked);
+                                *(uint*)endOfLastMarked = 0;
+                                *(uint*)(endOfLastMarked + WORD_SIZE) = 
+                                        front - endOfLastMarked - 3 * WORD_SIZE;
+                                *(uint*)(endOfLastMarked + 2 * WORD_SIZE) =
+                                        GC_objectHeader (STRING_TYPE_INDEX);
+                        }
+                        front += size;
+                        endOfLastMarked = front;
+                        foreachPointerInObject (s, p, FALSE, threadInternal);
+                        goto updateObject;
+                } else {
+                        /* It's not marked. */
+                        size = objectSize (s, p);
+                        gap += size;
+                        front += size;
+                        goto updateObject;
+                }
+        } else {
+                pointer new;
+
+                assert (0 == (3 & header));
+                /* It's a pointer.  This object must be live.  Fix all the
+                 * forward pointers to it, store its header, then thread
+                 * its internal pointers.
+                 */
+                new = p - gap;
+                do {
+                        pointer cur;
+
+                        cur = (pointer)header;
+                        header = *(word*)cur;
+                        *(word*)cur = (word)new;
+                } while (0 == (1 & header));
+                *headerp = header;
+                goto thread;
+        }
+        assert (FALSE);
+done:
+        return;
+}
+
+static void updateBackwardPointersAndSlide (GC_state s) {
+        pointer back;
+        pointer front;
+        uint gap;
+        Header header;
+        pointer p;
+        uint size;
+
+        if (DEBUG_MARK_COMPACT)
+                fprintf (stderr, "Update backward pointers and slide.\n");
+        front = alignFrontier (s, s->heap.start);
+        back = s->heap.start + s->oldGenSize;
+        gap = 0;
+updateObject:
+        if (DEBUG_MARK_COMPACT)
+                fprintf (stderr, "updateObject  front = 0x%08x  back = 0x%08x\n",
+                                (uint)front, (uint)back);
+        if (front == back)
+                goto done;
+        header = *(word*)front;
+        if (0 == header) {
+                /* We're looking at an array.  Move to the header. */
+                p = front + 3 * WORD_SIZE;
+                header = *(Header*)(p - WORD_SIZE);
+        } else 
+                p = front + WORD_SIZE;
+        if (1 == (1 & header)) {
+                /* It's a header */
+                if (MARK_MASK & header) {
+                        /* It is marked, but has no backward pointers to it.
+                         * Unmark it.
+                         */
+unmark:
+                        *GC_getHeaderp (p) = header & ~MARK_MASK;
+                        size = objectSize (s, p);
+                        if (DEBUG_MARK_COMPACT)
+                                fprintf (stderr, "unmarking 0x%08x of size %u\n", 
+                                                (uint)p, size);
+                        /* slide */
+                        if (DEBUG_MARK_COMPACT)
+                                fprintf (stderr, "sliding 0x%08x down %u\n",
+                                                (uint)front, gap);
+                        copy (front, front - gap, size);
+                        front += size;
+                        goto updateObject;
+                } else {
+                        /* It's not marked. */
+                        size = objectSize (s, p);
+                        if (DEBUG_MARK_COMPACT)
+                                fprintf (stderr, "skipping 0x%08x of size %u\n",
+                                                (uint)p, size);
+                        gap += size;
+                        front += size;
+                        goto updateObject;
+                }
+        } else {
+                pointer new;
+
+                /* It's a pointer.  This object must be live.  Fix all the
+                 * backward pointers to it.  Then unmark it.
+                 */
+                new = p - gap;
+                do {
+                        pointer cur;
+
+                        assert (0 == (3 & header));
+                        cur = (pointer)header;
+                        header = *(word*)cur;
+                        *(word*)cur = (word)new;
+                } while (0 == (1 & header));
+                /* The header will be stored by unmark. */
+                goto unmark;
+        }
+        assert (FALSE);
+done:
+        s->oldGenSize = front - gap - s->heap.start;
+        if (DEBUG_MARK_COMPACT)
+                fprintf (stderr, "bytesLive = %u\n", s->bytesLive);
+        return;
+}
+
+static void markCompact (GC_state s) {
+        struct rusage ru_start;
+
+        if (DEBUG or s->messages)
+                fprintf (stderr, "Major mark-compact GC.\n");
+        if (detailedGCTime (s))
+                startTiming (&ru_start);
+        s->numMarkCompactGCs++;
+        if (s->hashConsDuringGC) {
+                s->bytesHashConsed = 0;
+                s->numHashConsGCs++;
+                s->objectHashTable = newTable (s);
+        }
+        foreachGlobal (s, s->hashConsDuringGC 
+                                ? markGlobalTrue 
+                                : markGlobalFalse);
+        if (s->hashConsDuringGC)
+                destroyTable (s->objectHashTable);
+        foreachGlobal (s, threadInternal);
+        updateForwardPointers (s);
+        updateBackwardPointersAndSlide (s);
+        clearCrossMap (s);
+        s->bytesMarkCompacted += s->oldGenSize;
+        s->lastMajor = GC_MARK_COMPACT;
+        if (detailedGCTime (s))
+                stopTiming (&ru_start, &s->ru_gcMarkCompact);
+        if (DEBUG or s->messages) {
+                fprintf (stderr, "Major mark-compact GC done.\n");
+                if (s->hashConsDuringGC)
+                        bytesHashConsedMessage 
+                                (s, s->bytesHashConsed + s->oldGenSize);
+        }
+}

Deleted: mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-sweep.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-sweep.c	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-sweep.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -1,7 +0,0 @@
-/* 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.
- */

Deleted: mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-sweep.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-sweep.h	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-sweep.h	2005-10-10 01:54:23 UTC (rev 4100)
@@ -1,7 +0,0 @@
-/* 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.
- */

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.c	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -47,17 +47,6 @@
   return O;
 }
 
-/* isObjptr returns true if p looks like an object pointer. */
-static inline bool isObjptr (objptr p) {
-  if GC_MODEL_NONOBJPTR {
-    unsigned int shift = GC_MODEL_MINALIGN_SHIFT - GC_MODEL_SHIFT;
-    objptr mask = ~((~((objptr)0)) << shift);
-    return (0 == (p & mask));
-  } else {
-    return TRUE;
-  }
-}
-
 /*
  * Note that by indirectly fetching and storing object pointers, the
  * following functions admit implementations that behave according to

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/model_predicates.c (from rev 4098, mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.c)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.c	2005-10-08 20:36:15 UTC (rev 4098)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/model_predicates.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -0,0 +1,17 @@
+/* Copyright (C) 2005-2005 Henry Cejtin, Matthew Fluet, Suresh
+ *    Jagannathan, and Stephen Weeks.
+ *
+ * MLton is released under a BSD-style license.
+ * See the file MLton-LICENSE for details.
+ */
+
+/* isObjptr returns true if p looks like an object pointer. */
+static inline bool isObjptr (objptr p) {
+  if GC_MODEL_NONOBJPTR {
+    unsigned int shift = GC_MODEL_MINALIGN_SHIFT - GC_MODEL_SHIFT;
+    objptr mask = ~((~((objptr)0)) << shift);
+    return (0 == (p & mask));
+  } else {
+    return TRUE;
+  }
+}

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/new_object.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/new_object.c	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/new_object.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -38,7 +38,7 @@
   *(GC_header*)(frontier) = header;
   result = frontier + GC_NORMAL_HEADER_SIZE;
   if (DEBUG)
-    fprintf (stderr, FMTPTR " = newObject ("FMTHDR", %zd, %s)\n",
+    fprintf (stderr, FMTPTR " = newObject ("FMTHDR", %zu, %s)\n",
              (uintptr_t)result,
              header, 
              bytesRequested,
@@ -51,7 +51,7 @@
                           bool allocInOldGen) {
   GC_stack stack;
 
-  reserved = stackReserved (s, reserved);
+  reserved = alignStackReserved (s, reserved);
   if (reserved > s->cumulativeStatistics.maxStackSizeSeen)
     s->cumulativeStatistics.maxStackSizeSeen = reserved;
   stack = (GC_stack) newObject (s, GC_STACK_HEADER, 
@@ -60,7 +60,7 @@
   stack->reserved = reserved;
   stack->used = 0;
   if (DEBUG_STACKS)
-    fprintf (stderr, FMTPTR " = newStack (%zd)\n", 
+    fprintf (stderr, FMTPTR " = newStack (%zu)\n", 
              (uintptr_t)stack, 
              reserved);
   return stack;

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/object.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/object.c	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/object.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -6,7 +6,6 @@
  * See the file MLton-LICENSE for details.
  */
 
-
 static char* objectTypeTagToString (GC_objectTypeTag tag) {
   switch (tag) {
   case ARRAY_TAG:
@@ -25,16 +24,16 @@
 /*
  * Build the header for an object, given the index to its type info.
  */
-static inline GC_header GC_objectHeader (uint32_t t) {
+static inline GC_header objectHeader (uint32_t t) {
         assert (t < TWOPOWER (TYPE_INDEX_BITS));
         return 1 | (t << 1);
 }
 
-#define GC_STACK_HEADER GC_objectHeader (STACK_TYPE_INDEX)
-#define GC_STRING_HEADER GC_objectHeader (STRING_TYPE_INDEX)
-#define GC_THREAD_HEADER GC_objectHeader (THREAD_TYPE_INDEX)
-#define GC_WEAK_GONE_HEADER GC_objectHeader (WEAK_GONE_TYPE_INDEX)
-#define GC_WORD8_VECTOR_HEADER GC_objectHeader (WORD8_TYPE_INDEX)
+#define GC_STACK_HEADER objectHeader (STACK_TYPE_INDEX)
+#define GC_STRING_HEADER objectHeader (STRING_TYPE_INDEX)
+#define GC_THREAD_HEADER objectHeader (THREAD_TYPE_INDEX)
+#define GC_WEAK_GONE_HEADER objectHeader (WEAK_GONE_TYPE_INDEX)
+#define GC_WORD8_VECTOR_HEADER objectHeader (WORD8_TYPE_INDEX)
 
 static inline void splitHeader(GC_state s, GC_header header,
                                GC_objectTypeTag *tagRet, bool *hasIdentityRet,
@@ -74,20 +73,6 @@
     *numObjptrsRet = numObjptrs;
 }
 
-static inline size_t numNonObjptrsToBytes (uint16_t numNonObjptrs, 
-                                           GC_objectTypeTag tag) {
-  switch (tag) {
-  case ARRAY_TAG:
-    return (size_t)(numNonObjptrs);
-  case NORMAL_TAG:
-    return (size_t)(numNonObjptrs) * 4;
-  case WEAK_TAG:
-    return (size_t)(numNonObjptrs) * 4;
-  default:
-    die ("bad tag %u", tag);
-  }
-}
-
 /* objectData (s, p)
  *
  * If p points at the beginning of an object, then objectData returns

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/object_size.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/object_size.c	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/object_size.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -6,6 +6,39 @@
  * See the file MLton-LICENSE for details.
  */
 
+static inline size_t numNonObjptrsToBytes (uint16_t numNonObjptrs, 
+                                           GC_objectTypeTag tag) {
+  switch (tag) {
+  case ARRAY_TAG:
+    return (size_t)(numNonObjptrs);
+  case NORMAL_TAG:
+    return (size_t)(numNonObjptrs) * 4;
+  case WEAK_TAG:
+    return (size_t)(numNonObjptrs) * 4;
+  default:
+    die ("bad tag %u", tag);
+  }
+}
+
+static inline size_t arraySizeNoHeader (GC_state s,
+                                        pointer p, 
+                                        uint16_t numNonObjptrs,
+                                        uint16_t numObjptrs) {
+  size_t bytesPerElement;
+  GC_arrayLength numElements;
+  size_t result;
+        
+  numElements = getArrayLength (p);
+  bytesPerElement = 
+    numNonObjptrsToBytes(numNonObjptrs, ARRAY_TAG) 
+    + (numObjptrs * OBJPTR_SIZE);
+  result = numElements * bytesPerElement;
+  /* Empty arrays have OBJPTR_SIZE bytes for the forwarding pointer. */
+  if (0 == result) 
+    result = OBJPTR_SIZE;
+  return pad (s, result, GC_ARRAY_HEADER_SIZE);
+}
+
 static inline size_t objectSize (GC_state s, pointer p) {
   size_t headerBytes, objectBytes;
   GC_header header;
@@ -21,7 +54,7 @@
       + (numObjptrs * OBJPTR_SIZE);
   } else if (ARRAY_TAG == tag) {
     headerBytes = GC_ARRAY_HEADER_SIZE;
-    objectBytes = arrayNumBytes (s, p, numNonObjptrs, numObjptrs);
+    objectBytes = arraySizeNoHeader (s, p, numNonObjptrs, numObjptrs);
   } else if (WEAK_TAG == tag) {
     headerBytes = GC_NORMAL_HEADER_SIZE;
     objectBytes = 
@@ -34,3 +67,14 @@
   }
   return headerBytes + objectBytes;
 }
+
+
+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 = stackNumBytes (%zu)\n", res, size);
+  return res;
+}

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/pointer.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/pointer.c	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/pointer.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -5,9 +5,3 @@
  * MLton is released under a BSD-style license.
  * See the file MLton-LICENSE for details.
  */
-
-/* isPointer returns true if p looks like a pointer. */
-static inline bool isPointer (pointer p) {
-  uintptr_t mask = ~((~((uintptr_t)0)) << GC_MODEL_MINALIGN_SHIFT);
-  return (0 == ((uintptr_t)p & mask));
-}

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/pointer_predicates.c (from rev 4099, mlton/branches/on-20050822-x86_64-branch/runtime/gc/pointer.c)

Deleted: mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.c	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -1,15 +0,0 @@
-/* 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_predicates.c (from rev 4098, mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.c)

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/rusage.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/rusage.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -0,0 +1,92 @@
+/* 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 void rusageZero (struct rusage *ru) {
+  memset (ru, 0, sizeof (*ru));
+}
+
+static void rusagePlusMax (struct rusage *ru1,
+                           struct rusage *ru2,
+                           struct rusage *ru) {
+  const int       million = 1000000;
+  time_t          sec,
+                  usec;
+
+  sec = ru1->ru_utime.tv_sec + ru2->ru_utime.tv_sec;
+  usec = ru1->ru_utime.tv_usec + ru2->ru_utime.tv_usec;
+  sec += (usec / million);
+  usec %= million;
+  ru->ru_utime.tv_sec = sec;
+  ru->ru_utime.tv_usec = usec;
+  
+  sec = ru1->ru_stime.tv_sec + ru2->ru_stime.tv_sec;
+  usec = ru1->ru_stime.tv_usec + ru2->ru_stime.tv_usec;
+  sec += (usec / million);
+  usec %= million;
+  ru->ru_stime.tv_sec = sec;
+  ru->ru_stime.tv_usec = usec;
+}
+
+static void rusageMinusMax (struct rusage *ru1,
+                            struct rusage *ru2,
+                            struct rusage *ru) {
+  const int       million = 1000000;
+  time_t          sec,
+                  usec;
+
+  sec = (ru1->ru_utime.tv_sec - ru2->ru_utime.tv_sec) - 1;
+  usec = ru1->ru_utime.tv_usec + million - ru2->ru_utime.tv_usec;
+  sec += (usec / million);
+  usec %= million;
+  ru->ru_utime.tv_sec = sec;
+  ru->ru_utime.tv_usec = usec;
+  
+  sec = (ru1->ru_stime.tv_sec - ru2->ru_stime.tv_sec) - 1;
+  usec = ru1->ru_stime.tv_usec + million - ru2->ru_stime.tv_usec;
+  sec += (usec / million);
+  usec %= million;
+  ru->ru_stime.tv_sec = sec;
+  ru->ru_stime.tv_usec = usec;
+}
+
+static uintmax_t rusageTime (struct rusage *ru) {
+  uintmax_t result;
+
+  result = 0;
+  result += 1000 * ru->ru_utime.tv_sec;
+  result += 1000 * ru->ru_stime.tv_sec;
+  result += ru->ru_utime.tv_usec / 1000;
+  result += ru->ru_stime.tv_usec / 1000;
+  return result;
+}
+
+/* Return time as number of milliseconds. */
+static uintmax_t currentTime (void) {
+  struct rusage ru;
+  
+  getrusage (RUSAGE_SELF, &ru);
+  return rusageTime (&ru);
+}
+
+static inline void startTiming (struct rusage *ru_start) {
+  getrusage (RUSAGE_SELF, ru_start);
+}
+
+static uint stopTiming (struct rusage *ru_start, struct rusage *ru_gc) {
+  struct rusage ru_finish, ru_total;
+
+  getrusage (RUSAGE_SELF, &ru_finish);
+  rusageMinusMax (&ru_finish, ru_start, &ru_total);
+  rusagePlusMax (ru_gc, &ru_total, ru_gc);
+  return rusageTime (&ru_total);
+}
+
+
+static inline bool detailedGCTime (GC_state s) {
+  return s->controls.summary;
+}

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack.c	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -6,8 +6,14 @@
  * See the file MLton-LICENSE for details.
  */
 
-static inline bool stackIsEmpty (GC_stack stack) {
-  return 0 == stack->used;
+void displayStack (__attribute__ ((unused)) GC_state s,
+                   GC_stack stack, 
+                   FILE *stream) {
+  fprintf(stream,
+          "\t\treserved = %zu\n"
+          "\t\tused = %zu\n",
+          stack->reserved,
+          stack->used);
 }
 
 /* stackSlop returns the amount of "slop" space needed between the top
@@ -21,21 +27,12 @@
   return stackSlop (s);
 }
 
-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 = stackNumBytes (%zu)\n", res, size);
-  return res;
-}
-
+/* Pointer to the bottommost word in use on the stack. */
 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));
+  assert (isAligned ((size_t)res, s->alignment));
   return res;
 }
 
@@ -49,19 +46,20 @@
   return stackBottom (s, stack) + stack->reserved;
 }
 
-/* The maximum value stackTop may take on. */
+/* The maximum value which is valid for stackTop. */
 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;
+
+static inline GC_frameIndex topFrameIndex (GC_state s, GC_stack stack) {
+  GC_frameIndex res;
   
   res = 
     getFrameIndexFromReturnAddress 
     (s, *(GC_returnAddress*)(stackTop (s, stack) - GC_RETURNADDRESS_SIZE));
   if (DEBUG_PROFILE)
-    fprintf (stderr, "topFrameIndex = %"PRIu32"\n", res);
+    fprintf (stderr, "topFrameIndex = "FMTFI"\n", res);
   return res;
 }
 
@@ -80,16 +78,7 @@
   return layout->size;
 }
 
-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);
-  return res;
-}
-
-static inline size_t stackNeedsReserved (GC_state s, GC_stack stack) {
+static inline size_t stackMinimumReserved (GC_state s, GC_stack stack) {
   return stack->used + stackSlop (s) - topFrameSize(s, stack);
 }
 
@@ -101,19 +90,9 @@
   assert (from->used <= to->reserved);
   to->used = from->used;
   if (DEBUG_STACKS)
-    fprintf (stderr, "stackCopy from "FMTPTR" to "FMTPTR" of length %zd\n",
+    fprintf (stderr, "stackCopy from "FMTPTR" to "FMTPTR" of length %zu\n",
              (uintptr_t) fromBottom, 
              (uintptr_t) toBottom,
              from->used);
-  memcpy (fromBottom, toBottom, from->used);
+  GC_memcpy (fromBottom, toBottom, from->used);
 }
-
-void displayStack (__attribute__ ((unused)) GC_state s,
-                   GC_stack stack, 
-                   FILE *stream) {
-  fprintf(stream,
-          "\t\treserved = %zu\n"
-          "\t\tused = %zu\n",
-          stack->reserved,
-          stack->used);
-}

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack_predicates.c (from rev 4099, mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack.c)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack.c	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack_predicates.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -0,0 +1,11 @@
+/* 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 bool stackIsEmpty (GC_stack stack) {
+  return 0 == stack->used;
+}

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/statistics.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/statistics.h	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/statistics.h	2005-10-10 01:54:23 UTC (rev 4100)
@@ -29,10 +29,10 @@
   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. *\/ */
-/*   struct rusage ru_gcMarkCompact; /\* resource usage in mark-compact gcs. *\/ */
-/*   struct rusage ru_gcMinor; /\* resource usage in minor gcs. *\/ */
+  struct rusage ru_gc; /* total resource usage spent in gc */
+  struct rusage ru_gcCopy; /* resource usage in major copying gcs. */
+  struct rusage ru_gcMarkCompact; /* resource usage in mark-compact gcs. */
+  struct rusage ru_gcMinor; /* resource usage in minor gcs. */
 };
 
 struct GC_lastMajorStatistics {

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.c	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -5,6 +5,6 @@
  * See the file MLton-LICENSE for details.
  */
 
-char* boolToString (bool b) {
+const char* boolToString (bool b) {
         return b ? "TRUE" : "FALSE";
 }

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.h	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.h	2005-10-10 01:54:23 UTC (rev 4100)
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <sys/resource.h>
 
 #include "../assert.h"
 

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/virtual-memory.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/virtual-memory.c	2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/virtual-memory.c	2005-10-10 01:54:23 UTC (rev 4100)
@@ -10,11 +10,22 @@
   if (DEBUG_DETAILED)
     fprintf (stderr, "GC_memcpy ("FMTPTR", "FMTPTR", %zu)\n",
              (uintptr_t)src, (uintptr_t)dst, size);
-  assert (isAligned ((uintptr_t)src, sizeof(unsigned int)));
-  assert (isAligned ((uintptr_t)dst, sizeof(unsigned int)));
+  assert (isAligned ((size_t)src, sizeof(unsigned int)));
+  assert (isAligned ((size_t)dst, sizeof(unsigned int)));
   assert (isAligned (size, sizeof(unsigned int)));
   assert (dst <= src or src + size <= dst);
   if (src == dst)
     return;
   memcpy (dst, src, size);
 }
+
+void *GC_mmapAnon_safe (pointer p, size_t length) {
+  void *result;
+
+  result = GC_mmapAnon (p, length);
+  if ((void*)-1 == result) {
+    showMem ();
+    die ("Out of memory.");
+  }
+  return result;
+}

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-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/virtual-memory.h	2005-10-10 01:54:23 UTC (rev 4100)
@@ -6,7 +6,12 @@
  * See the file MLton-LICENSE for details.
  */
 
-void *GC_mmapAnon (size_t length);
+/* showMem displays the virtual memory mapping to stdout.  
+ * It is used to diagnose memory problems. 
+ */
+void showMem (void);
+
+void *GC_mmapAnon (void *start, size_t length);
 void *GC_mmap (void *start, size_t length);
 void GC_munmap (void *start, size_t length);
 void GC_release (void *base, size_t length);