[MLton-commit] r4145

Matthew Fluet MLton@mlton.org
Thu, 3 Nov 2005 19:53:13 -0800


Yet more cleanup
----------------------------------------------------------------------

U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/TODO
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/array-allocate.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/cheney-copy.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/controls.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/controls.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/copy-thread.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/copy-thread.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/dfs-mark.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/dfs-mark.h
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/done.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/enter_leave.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/garbage-collection.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/garbage-collection.h
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/handler.c
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/handler.h
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/init-world.c
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/init-world.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/init.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/init.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-compact.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-compact.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/new-object.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/new-object.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/pack.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/profiling.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/profiling.h
D   mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/rusage.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/share.c
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/signals.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/signals.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/size.c
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/switch-thread.c
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/switch-thread.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/thread.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/weak.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/weak.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/world.c

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

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile	2005-11-04 03:52:55 UTC (rev 4145)
@@ -88,6 +88,7 @@
 	copy-thread.c							\
 	current.c   							\
 	dfs-mark.c							\
+	done.c								\
 	enter_leave.c							\
 	foreach.c							\
 	forward.c							\
@@ -95,30 +96,33 @@
 	garbage-collection.c						\
 	gc_state.c   							\
 	generational.c							\
+	handler.c							\
 	hash-cons.c							\
 	heap.c								\
 	heap_predicates.c						\
+	init-world.c							\
+	init.c								\
 	invariant.c   							\
 	mark-compact.c							\
 	model.c								\
 	model_predicates.c						\
 	new-object.c   							\
+	object-size.c							\
 	object.c							\
-	object-size.c							\
 	pack.c								\
 	pointer.c							\
 	pointer_predicates.c						\
+	profiling.c							\
 	share.c								\
+	signals.c							\
 	size.c								\
 	stack.c								\
 	stack_predicates.c						\
+	switch-thread.c							\
 	thread.c							\
 	translate.c							\
 	weak.c								\
 	world.c								\
-	profiling.c							\
-	init.c								\
-	done.c								\
 	assumptions.c							\
 	gc_suffix.c
 
@@ -138,38 +142,41 @@
 	stack.h								\
 	thread.h							\
 	weak.h								\
+	int-inf.h							\
 	object-size.h							\
-	int-inf.h							\
+	generational.h							\
 	heap.h								\
-	major.h								\
-	generational.h							\
 	current.h							\
 	foreach.h							\
-	statistics.h							\
+	translate.h							\
 	sysvals.h							\
-	ratios.h							\
 	controls.h							\
+	major.h								\
+	statistics.h							\
 	forward.h							\
 	cheney-copy.h							\
 	hash-cons.h							\
-	profiling.h							\
-	signals.h							\
-	world.h								\
-	init.h								\
-	gc_state.h							\
-	translate.h							\
+	dfs-mark.h							\
+	mark-compact.h							\
+	invariant.h							\
 	atomic.h							\
-	invariant.h							\
 	enter_leave.h							\
-	dfs-mark.h							\
-	mark-compact.h							\
+	signals.h							\
+	handler.h							\
+	switch-thread.h							\
+	garbage-collection.h						\
 	new-object.h							\
-	garbage-collection.h						\
 	array-allocate.h						\
+	profiling.h							\
+	init-world.h							\
+	world.h								\
+	init.h								\
+	done.h								\
 	copy-thread.h							\
 	pack.h								\
 	share.h								\
 	size.h								\
+	gc_state.h							\
 	gc_suffix.h
 
 all: libgc.o libgc-gdb.o

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/TODO
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/TODO	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/TODO	2005-11-04 03:52:55 UTC (rev 4145)
@@ -18,3 +18,5 @@
 * the "skipObjects" loop in forwardInterGenerationalObjptrs appears to
         be unnecessary.
 * Why do {load,save}Globals differ in the representation of the file?
+* Why does hash-table use malloc/free while generational maps use mmap/munmap?
+

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/array-allocate.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/array-allocate.c	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/array-allocate.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -42,9 +42,11 @@
              /*uintToCommaString*/(arraySize),
              /*uintToCommaString*/(ensureBytesFree));
   if (arraySize >= s->controls.oldGenArraySize) {
-    enter (s);
-    doGC (s,  arraySize, ensureBytesFree, FALSE, TRUE);
-    leave (s);
+    if (not hasHeapBytesFree (s, arraySize, ensureBytesFree)) {
+      enter (s);
+      performGC (s, arraySize, ensureBytesFree, FALSE, TRUE);
+      leave (s);
+    }
     frontier = s->heap.start + s->heap.oldGenSize;
     last = frontier + arraySize;
     s->heap.oldGenSize += arraySize;
@@ -53,9 +55,9 @@
     size_t bytesRequested;
     
     bytesRequested = arraySize + ensureBytesFree;
-    if (bytesRequested > (size_t)(s->limitPlusSlop - s->frontier)) {
+    if (not hasHeapBytesFree (s, 0, bytesRequested)) {
       enter (s);
-      doGC (s, 0, bytesRequested, FALSE, TRUE);
+      performGC (s, 0, bytesRequested, FALSE, TRUE);
       leave (s);
     }
     frontier = s->frontier;

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.c	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -42,3 +42,27 @@
 GC_arrayCounter getArrayCounter (pointer a) {
   return *(getArrayCounterp (a));
 }
+
+pointer indexArrayAtPointerIndex (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 =
+    sizeofNumNonObjptrs (ARRAY_TAG, numNonObjptrs);
+  size_t bytesPerElement =
+    nonObjptrBytesPerElement
+    + (numObjptrs * OBJPTR_SIZE);
+
+  return a
+    + arrayIndex * bytesPerElement
+    + nonObjptrBytesPerElement
+    + pointerIndex * OBJPTR_SIZE;
+}

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.h	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.h	2005-11-04 03:52:55 UTC (rev 4145)
@@ -32,3 +32,6 @@
 GC_arrayLength getArrayLength (pointer a);
 GC_arrayCounter* getArrayCounterp (pointer a);
 GC_arrayCounter getArrayCounter (pointer a);
+pointer indexArrayAtPointerIndex (GC_state s, pointer a,
+                                  GC_arrayCounter arrayIndex,
+                                  uint32_t pointerIndex);

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-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/cheney-copy.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -103,7 +103,7 @@
   if (DEBUG_GENERATIONAL)
     fprintf (stderr, "minorGC  nursery = "FMTPTR"  frontier = "FMTPTR"\n",
              (uintptr_t)s->heap.nursery, (uintptr_t)s->frontier);
-  assert (invariant (s));
+  assert (invariantForGC (s));
   bytesAllocated = s->frontier - s->heap.nursery;
   if (bytesAllocated == 0)
     return;
@@ -122,7 +122,7 @@
       fprintf (stderr, "toStart = "FMTPTR"\n", (uintptr_t)s->forwardState.toStart);
     assert (isAlignedFrontier (s, s->forwardState.toStart));
     s->forwardState.toLimit = s->forwardState.toStart + bytesAllocated;
-    assert (invariant (s));
+    assert (invariantForGC (s));
     s->cumulativeStatistics.numMinorGCs++;
     s->lastMajorStatistics.numMinorGCs++;
     s->forwardState.back = s->forwardState.toStart;

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/controls.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/controls.c	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/controls.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -14,5 +14,6 @@
   return 
     DEBUG 
     or s->controls.summary 
-    or s->controls.messages;
+    or s->controls.messages
+    or s->controls.rusageMeasureGC;
 }

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/controls.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/controls.h	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/controls.h	2005-11-04 03:52:55 UTC (rev 4145)
@@ -6,6 +6,32 @@
  * See the file MLton-LICENSE for details.
  */
 
+struct GC_ratios {
+  /* Minimum live ratio to use copying GC. */
+  float copy; 
+  /* Only use generational GC with copying collection if the ratio of
+   * heap size to live data size is below copyGenerational.
+   */
+  float copyGenerational; 
+  float grow; 
+  float hashCons;
+  /* Desired ratio of heap size to live data. */
+  float live; 
+  /* Minimum live ratio to us mark-compact GC. */
+  float markCompact; 
+  /* Only use generational GC with mark-compact collection if the
+   * ratio of heap size to live data size is below
+   * markCompactGenerational.
+   */
+  float markCompactGenerational; 
+  /* As long as the ratio of bytes live to nursery size is greater
+   * than nurseryRatio, use minor GCs.
+   */
+  float nursery; 
+  float ramSlop;
+  float threadShrink; 
+};
+
 struct GC_controls {
   size_t fixedHeap; /* If 0, then no fixed heap. */
   size_t maxHeap; /* if zero, then unlimited, else limit total heap */
@@ -14,6 +40,7 @@
   bool messages; /* Print a message at the start and end of each gc. */
   size_t oldGenArraySize; /* Arrays larger are allocated in old gen, if possible. */
   struct GC_ratios ratios;
+  bool rusageMeasureGC;
   bool summary; /* Print a summary of gc info when program exits. */
 };
 

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/copy-thread.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/copy-thread.c	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/copy-thread.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -6,24 +6,6 @@
  * See the file MLton-LICENSE for details.
  */
 
-GC_thread newThread (GC_state s, size_t reserved) {
-  GC_stack stack;
-  GC_thread thread;
-
-  ensureFree (s, sizeofStackWithHeaderAligned (s, reserved) + sizeofThread (s));
-  stack = newStack (s, reserved, FALSE);
-  thread = (GC_thread) newObject (s, GC_THREAD_HEADER, 
-                                  sizeofThread (s), 
-                                  FALSE);
-  thread->bytesNeeded = 0;
-  thread->exnStack = BOGUS_EXN_STACK;
-  thread->stack = pointerToObjptr((pointer)stack, s->heap.start);
-  if (DEBUG_THREADS)
-    fprintf (stderr, FMTPTR" = newThreadOfSize (%zu)\n",
-             (uintptr_t)thread, reserved);;
-  return thread;
-}
-
 GC_thread copyThread (GC_state s, GC_thread from, size_t size) {
   GC_thread to;
 

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/copy-thread.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/copy-thread.h	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/copy-thread.h	2005-11-04 03:52:55 UTC (rev 4145)
@@ -6,7 +6,6 @@
  * See the file MLton-LICENSE for details.
  */
 
-GC_thread newThread (GC_state s, size_t stackSize);
 GC_thread copyThread (GC_state s, GC_thread from, size_t size);
 void GC_copyCurrentThread (GC_state s);
 pointer GC_copyThread (GC_state s, pointer p);

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/dfs-mark.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/dfs-mark.c	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/dfs-mark.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -10,46 +10,22 @@
 /*                       Depth-first Marking                        */
 /* ---------------------------------------------------------------- */
 
-bool isMarked (pointer p) {
+bool isPointerMarked (pointer p) {
   return MARK_MASK & getHeader (p);
 }
 
-bool isMarkedMode (GC_markMode m, pointer p) {
+bool isPointerMarkedByMode (pointer p, GC_markMode m) {
   switch (m) {
   case MARK_MODE:
-    return isMarked (p);
+    return isPointerMarked (p);
   case UNMARK_MODE:
-    return not isMarked (p);
+    return not isPointerMarked (p);
   default:
     die ("bad mark mode %u", m);
   }
 }
 
-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 =
-    sizeofNumNonObjptrs (ARRAY_TAG, numNonObjptrs);
-  size_t bytesPerElement =
-    nonObjptrBytesPerElement
-    + (numObjptrs * OBJPTR_SIZE);
-
-  return a
-    + arrayIndex * bytesPerElement
-    + nonObjptrBytesPerElement
-    + pointerIndex * OBJPTR_SIZE;
-}
-
-/* dfsMark (s, r, m, shc) 
+/* dfsMarkByMode (s, r, m, shc) 
  *
  * Sets all the mark bits in the object graph pointed to by r. 
  *
@@ -60,8 +36,8 @@
  *
  * It returns the total size in bytes of the objects marked.
  */
-size_t dfsMark (GC_state s, pointer root,
-                GC_markMode mode, bool shouldHashCons) {
+size_t dfsMarkByMode (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. */
@@ -82,7 +58,7 @@
   GC_frameLayout frameLayout;
   GC_frameOffsets frameOffsets;
 
-  if (isMarkedMode (mode, root))
+  if (isPointerMarkedByMode (root, mode))
     /* Object has already been marked. */
     return 0;
   mark = (MARK_MODE == mode) ? MARK_MASK : 0;
@@ -107,7 +83,7 @@
              "  prev = "FMTPTR"  todo = "FMTPTR"\n",
              (uintptr_t)cur, (uintptr_t)next, 
              (uintptr_t)prev, (uintptr_t)todo);
-  assert (not isMarkedMode (mode, next));
+  assert (not isPointerMarkedByMode (next, mode));
   assert (nextHeaderp == getHeaderp (next));
   assert (nextHeader == getHeader (next));
   // assert (*(pointer*) todo == next);
@@ -128,7 +104,7 @@
    * headerp points to the header of cur.
    * header is the header of cur.
    */
-  assert (not isMarkedMode (mode, cur));
+  assert (not isPointerMarkedByMode (cur, mode));
   assert (header == getHeader (cur));
   assert (headerp == getHeaderp (cur));
   header ^= MARK_MASK;
@@ -215,14 +191,14 @@
                arrayIndex, index);
     assert (arrayIndex < getArrayLength (cur));
     assert (index < numObjptrs);
-    assert (todo == arrayIndexAtPointer (s, cur, arrayIndex, index));
+    assert (todo == indexArrayAtPointerIndex (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));
+      assert (todo == indexArrayAtPointerIndex (s, cur, arrayIndex, index));
       todo += OBJPTR_SIZE;
       index++;
       if (index < numObjptrs)
@@ -305,7 +281,7 @@
   if (DEBUG_MARK_COMPACT)
     fprintf (stderr, "return  cur = "FMTPTR"  prev = "FMTPTR"\n",
              (uintptr_t)cur, (uintptr_t)prev);
-  assert (isMarkedMode (mode, cur));
+  assert (isPointerMarkedByMode (cur, mode));
   if (NULL == prev)
     return size;
   next = cur;
@@ -356,23 +332,23 @@
   assert (FALSE);
 }
 
-void dfsMarkTrue (GC_state s, objptr *opp) {
+void dfsMarkWithHashCons (GC_state s, objptr *opp) {
   pointer p;
 
   p = objptrToPointer (*opp, s->heap.start);
-  dfsMark (s, p, MARK_MODE, TRUE);
+  dfsMarkByMode (s, p, MARK_MODE, TRUE);
 }
 
-void dfsMarkFalse (GC_state s, objptr *opp) {
+void dfsMarkWithoutHashCons (GC_state s, objptr *opp) {
   pointer p;
 
   p = objptrToPointer (*opp, s->heap.start);
-  dfsMark (s, p, MARK_MODE, FALSE);
+  dfsMarkByMode (s, p, MARK_MODE, FALSE);
 }
 
 void dfsUnmark (GC_state s, objptr *opp) {
   pointer p;
 
   p = objptrToPointer (*opp, s->heap.start);
-  dfsMark (s, p, UNMARK_MODE, FALSE);
+  dfsMarkByMode (s, p, UNMARK_MODE, FALSE);
 }

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/dfs-mark.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/dfs-mark.h	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/dfs-mark.h	2005-11-04 03:52:55 UTC (rev 4145)
@@ -11,14 +11,10 @@
   UNMARK_MODE,
 } GC_markMode;
 
-bool isMarked (pointer p);
-bool isMarkedMode (GC_markMode m, pointer p);
-pointer arrayIndexAtPointer (GC_state s,
-                             pointer a,
-                             GC_arrayCounter arrayIndex,
-                             uint32_t pointerIndex);
-size_t dfsMark (GC_state s, pointer root,
-                GC_markMode mode, bool shouldHashCons);
-void dfsMarkTrue (GC_state s, objptr *opp);
-void dfsMarkFalse (GC_state s, objptr *opp);
+bool isPointerMarked (pointer p);
+bool isPointerMarkedByMode (pointer p, GC_markMode m);
+size_t dfsMarkByMode (GC_state s, pointer root,
+                      GC_markMode mode, bool shouldHashCons);
+void dfsMarkWithHashCons (GC_state s, objptr *opp);
+void dfsMarkWithoutHashCons (GC_state s, objptr *opp);
 void dfsUnmark (GC_state s, objptr *opp);

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/done.h (from rev 4143, mlton/branches/on-20050822-x86_64-branch/runtime/gc/done.c)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/done.c	2005-11-04 00:12:48 UTC (rev 4143)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/done.h	2005-11-04 03:52:55 UTC (rev 4145)
@@ -0,0 +1,9 @@
+/* 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.
+ */
+
+void GC_done (GC_state s);

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/enter_leave.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/enter_leave.c	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/enter_leave.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -20,7 +20,7 @@
   if (DEBUG) 
     displayGCState (s, stderr);
   beginAtomic (s);
-  assert (invariant (s));
+  assert (invariantForGC (s));
   if (DEBUG)
     fprintf (stderr, "enter ok\n");
 }
@@ -31,7 +31,7 @@
   /* The mutator frontier invariant may not hold
    * for functions that don't ensureBytesFree.
    */
-  assert (mutatorInvariant (s, FALSE, TRUE));
+  assert (invariantForMutator (s, FALSE, TRUE));
   endAtomic (s);
   if (DEBUG)
     fprintf (stderr, "leave ok\n");

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/garbage-collection.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/garbage-collection.c	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/garbage-collection.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -47,6 +47,21 @@
   assert (s->heap.oldGenSize + bytesRequested <= s->heap.size);
 }
 
+void growStackCurrent (GC_state s) {
+  size_t size;
+  GC_stack stack;
+
+  size = sizeofStackGrow (s, getStackCurrent(s));
+  if (DEBUG_STACKS or s->controls.messages)
+    fprintf (stderr, "Growing stack to size %zu.\n",
+             /*uintToCommaString*/(sizeofStackWithHeaderAligned (s, size)));
+  assert (hasHeapBytesFree (s, sizeofStackWithHeaderAligned (s, size), 0));
+  stack = newStack (s, size, TRUE);
+  copyStack (s, getStackCurrent(s), stack);
+  getThreadCurrent(s)->stack = pointerToObjptr ((pointer)stack, s->heap.start);
+  markCard (s, objptrToPointer (getThreadCurrentObjptr(s), s->heap.start));
+}
+
 void enterGC (GC_state s) {
   if (s->profiling.isOn) {
     /* We don't need to profileEnter for count profiling because it
@@ -69,11 +84,11 @@
   s->amInGC = FALSE;
 }
 
-void doGC (GC_state s, 
-           size_t oldGenBytesRequested,
-           size_t nurseryBytesRequested, 
-           bool forceMajor,
-           bool mayResize) {
+void performGC (GC_state s, 
+                size_t oldGenBytesRequested,
+                size_t nurseryBytesRequested, 
+                bool forceMajor,
+                bool mayResize) {
   uintmax_t gcTime;
   bool stackTopOk;
   size_t stackBytesRequested;
@@ -85,11 +100,11 @@
     fprintf (stderr, "Starting gc.  Request %zu nursery bytes and %zu old gen bytes.\n",
              /*uintToCommaString*/(nurseryBytesRequested),
              /*uintToCommaString*/(oldGenBytesRequested));
-  assert (invariant (s));
+  assert (invariantForGC (s));
   if (needGCTime (s))
     startTiming (&ru_start);
   minorGC (s);
-  stackTopOk = mutatorStackInvariant (s);
+  stackTopOk = invariantForMutatorStack (s);
   stackBytesRequested = 
     stackTopOk 
     ? 0 
@@ -106,7 +121,7 @@
   assert (hasHeapBytesFree (s, oldGenBytesRequested + stackBytesRequested,
                             nurseryBytesRequested));
   unless (stackTopOk)
-    growStack (s);
+    growStackCurrent (s);
   setGCStateCurrentThreadAndStack (s);
   if (needGCTime (s)) {
     gcTime = stopTiming (&ru_start, &s->cumulativeStatistics.ru_gc);
@@ -134,133 +149,33 @@
   if (DEBUG) 
     displayGCState (s, stderr);
   assert (hasHeapBytesFree (s, oldGenBytesRequested, nurseryBytesRequested));
-  assert (invariant (s));
+  assert (invariantForGC (s));
   leaveGC (s);
 }
 
-void ensureMutatorInvariant (GC_state s, bool force) {
+void ensureInvariantForMutator (GC_state s, bool force) {
   if (force
-      or not (mutatorFrontierInvariant(s))
-      or not (mutatorStackInvariant(s))) {
+      or not (invariantForMutatorFrontier(s))
+      or not (invariantForMutatorStack(s))) {
     /* This GC will grow the stack, if necessary. */
-    doGC (s, 0, getThreadCurrent(s)->bytesNeeded, force, TRUE);
+    performGC (s, 0, getThreadCurrent(s)->bytesNeeded, force, TRUE);
   }
-  assert (mutatorFrontierInvariant(s));
-  assert (mutatorStackInvariant(s));
+  assert (invariantForMutatorFrontier(s));
+  assert (invariantForMutatorStack(s));
 }
 
-/* ensureFree (s, b) ensures that upon return
- *      b <= s->limitPlusSlop - s->frontier
+/* ensureHasHeapBytesFree (s, oldGen, nursery) 
  */
-void ensureFree (GC_state s, size_t bytesRequested) {
+void ensureHasHeapBytesFree (GC_state s, 
+                             size_t oldGenBytesRequested,
+                             size_t nurseryBytesRequested) {
+  assert (s->heap.nursery <= s->limitPlusSlop);
   assert (s->frontier <= s->limitPlusSlop);
-  if (bytesRequested > (size_t)(s->limitPlusSlop - s->frontier))
-    doGC (s, 0, bytesRequested, FALSE, TRUE);
-  assert (bytesRequested <= (size_t)(s->limitPlusSlop - s->frontier));
+  if (not hasHeapBytesFree (s, oldGenBytesRequested, nurseryBytesRequested))
+    performGC (s, oldGenBytesRequested, nurseryBytesRequested, FALSE, TRUE);
+  assert (hasHeapBytesFree (s, oldGenBytesRequested, nurseryBytesRequested));
 }
 
-void switchToThread (GC_state s, objptr op) {
-  if (DEBUG_THREADS) {
-    GC_thread thread;
-    GC_stack stack;
-    
-    thread = (GC_thread)(objptrToPointer (op, s->heap.start));
-    stack = (GC_stack)(objptrToPointer (thread->stack, s->heap.start));
-    
-    fprintf (stderr, "switchToThread ("FMTOBJPTR")  used = %zu  reserved = %zu\n",
-             op, stack->used, stack->reserved);
-  }
-  s->currentThread = op;
-  setGCStateCurrentThreadAndStack (s);
-}
-
-/* GC_startHandler does not do an enter()/leave(), even though it is
- * exported.  The basis library uses it via _import, not _prim, and so
- * does not treat it as a runtime call -- so the invariant in enter
- * would fail miserably.  It is OK because GC_startHandler must be
- * called from within a critical section.
- *
- * Don't make it inline, because it is also called in basis/Thread.c,
- * and when compiling with COMPILE_FAST, they may appear out of order.
- */
-void GC_startHandler (GC_state s) {
-  /* Switch to the signal handler thread. */
-  if (DEBUG_SIGNALS) {
-    fprintf (stderr, "GC_startHandler\n");
-  }
-  assert (s->atomicState == 1);
-  assert (s->signalsInfo.signalIsPending);
-  s->signalsInfo.signalIsPending = FALSE;
-  s->signalsInfo.amInSignalHandler = TRUE;
-  s->savedThread = s->currentThread;
-  /* Set s->atomicState to 2 when switching to the signal handler
-   * thread; leaving the runtime will decrement s->atomicState to 1,
-   * the signal handler will then run atomically and will finish by
-   * switching to the thread to continue with, which will decrement
-   * s->atomicState to 0.
-   */
-  s->atomicState = 2;
-}
-
-void GC_finishHandler (GC_state s) {
-  if (DEBUG_SIGNALS)
-    fprintf (stderr, "GC_finishHandler ()\n");
-  assert (s->atomicState == 1);
-  s->signalsInfo.amInSignalHandler = FALSE;     
-}
-
-void maybeSwitchToHandler (GC_state s) {
-  if (s->atomicState == 1 
-      and s->signalsInfo.signalIsPending) {
-    GC_startHandler (s);
-    switchToThread (s, s->signalHandlerThread);
-  }
-}
-
-void GC_switchToThread (GC_state s, GC_thread t, size_t ensureBytesFree) {
-  if (DEBUG_THREADS)
-    fprintf (stderr, "GC_switchToThread ("FMTPTR", %zu)\n", 
-             (uintptr_t)t, ensureBytesFree);
-  if (FALSE) {
-    /* This branch is slower than the else branch, especially
-     * when debugging is turned on, because it does an invariant
-     * check on every thread switch.
-     * So, we'll stick with the else branch for now.
-     */
-    enter (s);
-    getThreadCurrent(s)->bytesNeeded = ensureBytesFree;
-    switchToThread (s, pointerToObjptr((pointer)t, s->heap.start));
-    s->atomicState--;
-    maybeSwitchToHandler (s);
-    ensureMutatorInvariant (s, FALSE);
-    assert (mutatorFrontierInvariant(s));
-    assert (mutatorStackInvariant(s));
-    leave (s);
-  } else {
-    /* BEGIN: enter(s); */
-    getStackCurrent(s)->used = sizeofGCStateCurrentStackUsed (s);
-    getThreadCurrent(s)->exnStack = s->exnStack;
-    beginAtomic (s);
-    /* END: enter(s); */
-    getThreadCurrent(s)->bytesNeeded = ensureBytesFree;
-    switchToThread (s, pointerToObjptr((pointer)t, s->heap.start));
-    s->atomicState--;
-    maybeSwitchToHandler (s);
-    /* BEGIN: ensureMutatorInvariant */
-    if (not (mutatorFrontierInvariant(s))
-        or not (mutatorStackInvariant(s))) {
-      /* This GC will grow the stack, if necessary. */
-      doGC (s, 0, getThreadCurrent(s)->bytesNeeded, FALSE, TRUE);
-    }
-    /* END: ensureMutatorInvariant */
-    /* BEGIN: leave(s); */
-    endAtomic (s);
-    /* END: leave(s); */
-  }
-  assert (mutatorFrontierInvariant(s));
-  assert (mutatorStackInvariant(s));
-}
-
 void GC_gc (GC_state s, size_t bytesRequested, bool force,
             char *file, int line) {
   if (DEBUG or s->controls.messages)
@@ -272,9 +187,9 @@
   if (0 == bytesRequested)
     bytesRequested = GC_HEAP_LIMIT_SLOP;
   getThreadCurrent(s)->bytesNeeded = bytesRequested;
-  maybeSwitchToHandler (s);
-  ensureMutatorInvariant (s, force);
-  assert (mutatorFrontierInvariant(s));
-  assert (mutatorStackInvariant(s));
+  switchToHandlerThreadIfNonAtomicAndSignalPending (s);
+  ensureInvariantForMutator (s, force);
+  assert (invariantForMutatorFrontier(s));
+  assert (invariantForMutatorStack(s));
   leave (s);
 }

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/garbage-collection.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/garbage-collection.h	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/garbage-collection.h	2005-11-04 03:52:55 UTC (rev 4145)
@@ -8,19 +8,17 @@
 
 void minorGC (GC_state s);
 void majorGC (GC_state s, size_t bytesRequested, bool mayResize);
+void growStackCurrent (GC_state s);
 void enterGC (GC_state s);
 void leaveGC (GC_state s);
-void doGC (GC_state s, 
-           size_t oldGenBytesRequested,
-           size_t nurseryBytesRequested, 
-           bool forceMajor,
-           bool mayResize);
-void ensureMutatorInvariant (GC_state s, bool force);
-void ensureFree (GC_state s, size_t bytesRequested);
-void switchToThread (GC_state s, objptr op);
-void GC_startHandler (GC_state s);
-void GC_finishHandler (GC_state s);
-void maybeSwitchToHandler (GC_state s);
-void GC_switchToThread (GC_state s, GC_thread t, size_t ensureBytesFree);
+void performGC (GC_state s, 
+                size_t oldGenBytesRequested,
+                size_t nurseryBytesRequested, 
+                bool forceMajor,
+                bool mayResize);
+void ensureInvariantForMutator (GC_state s, bool force);
+void ensureHasHeapBytesFree (GC_state s, 
+                             size_t oldGenBytesRequested,
+                             size_t nurseryBytesRequested);
 void GC_gc (GC_state s, size_t bytesRequested, bool force,
             char *file, int line);

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/handler.c (from rev 4143, mlton/branches/on-20050822-x86_64-branch/runtime/gc/garbage-collection.c)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/garbage-collection.c	2005-11-04 00:12:48 UTC (rev 4143)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/handler.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -0,0 +1,68 @@
+/* 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.
+ */
+
+/* GC_startHandler does not do an enter()/leave(), even though it is
+ * exported.  The basis library uses it via _import, not _prim, and so
+ * does not treat it as a runtime call -- so the invariant in enter
+ * would fail miserably.  It is OK because GC_startHandler must be
+ * called from within a critical section.
+ *
+ * Don't make it inline, because it is also called in basis/Thread.c,
+ * and when compiling with COMPILE_FAST, they may appear out of order.
+ */
+void GC_startHandler (GC_state s) {
+  /* Switch to the signal handler thread. */
+  if (DEBUG_SIGNALS) {
+    fprintf (stderr, "GC_startHandler\n");
+  }
+  assert (s->atomicState == 1);
+  assert (s->signalsInfo.signalIsPending);
+  s->signalsInfo.signalIsPending = FALSE;
+  s->signalsInfo.amInSignalHandler = TRUE;
+  s->savedThread = s->currentThread;
+  /* Set s->atomicState to 2 when switching to the signal handler
+   * thread; leaving the runtime will decrement s->atomicState to 1,
+   * the signal handler will then run atomically and will finish by
+   * switching to the thread to continue with, which will decrement
+   * s->atomicState to 0.
+   */
+  s->atomicState = 2;
+}
+
+void GC_finishHandler (GC_state s) {
+  if (DEBUG_SIGNALS)
+    fprintf (stderr, "GC_finishHandler ()\n");
+  assert (s->atomicState == 1);
+  s->signalsInfo.amInSignalHandler = FALSE;     
+}
+
+void switchToHandlerThreadIfNonAtomicAndSignalPending (GC_state s) {
+  if (s->atomicState == 1 
+      and s->signalsInfo.signalIsPending) {
+    GC_startHandler (s);
+    switchToThread (s, s->signalHandlerThread);
+  }
+}
+
+/* GC_handler sets s->limit = 0 so that the next limit check will
+ * fail.  Signals need to be blocked during the handler (i.e. it
+ * should run atomically) because sigaddset does both a read and a
+ * write of s->signalsInfo.signalsPending.  The signals are blocked
+ * by Posix_Signal_handle (see Posix/Signal/Signal.c).
+ */
+void GC_handler (GC_state s, int signum) {
+  if (DEBUG_SIGNALS)
+    fprintf (stderr, "GC_handler signum = %d\n", signum);
+  assert (sigismember (&s->signalsInfo.signalsHandled, signum));
+  if (s->atomicState == 0)
+    s->limit = 0;
+  s->signalsInfo.signalIsPending = TRUE;
+  sigaddset (&s->signalsInfo.signalsPending, signum);
+  if (DEBUG_SIGNALS)
+    fprintf (stderr, "GC_handler done\n");
+}

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/handler.h (from rev 4143, mlton/branches/on-20050822-x86_64-branch/runtime/gc/garbage-collection.h)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/garbage-collection.h	2005-11-04 00:12:48 UTC (rev 4143)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/handler.h	2005-11-04 03:52:55 UTC (rev 4145)
@@ -0,0 +1,12 @@
+/* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
+ *    Jagannathan, and Stephen Weeks.
+ * Copyright (C) 1997-2000 NEC Research Institute.
+ *
+ * MLton is released under a BSD-style license.
+ * See the file MLton-LICENSE for details.
+ */
+
+void GC_startHandler (GC_state s);
+void GC_finishHandler (GC_state s);
+void switchToHandlerThreadIfNonAtomicAndSignalPending (GC_state s);
+void GC_handler (GC_state s, int signum);

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/init-world.c (from rev 4143, mlton/branches/on-20050822-x86_64-branch/runtime/gc/init.c)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/init.c	2005-11-04 00:12:48 UTC (rev 4143)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/init-world.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -0,0 +1,200 @@
+/* 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.
+ */
+
+/* ---------------------------------------------------------------- */
+/*                          Initialization                          */
+/* ---------------------------------------------------------------- */
+
+
+size_t sizeofInitialBytesLive (GC_state s) {
+  uint32_t i;
+  size_t numBytes;
+  size_t total;
+  
+  total = 0;
+  for (i = 0; i < s->intInfInitsLength; ++i) {
+    numBytes = 
+      sizeof(uint32_t) // for the sign
+      + strlen (s->intInfInits[i].mlstr);
+    total += align (GC_ARRAY_HEADER_SIZE 
+                    + numBytes, 
+                    s->alignment);
+  }
+  for (i = 0; i < s->vectorInitsLength; ++i) {
+    numBytes = 
+      s->vectorInits[i].bytesPerElement
+      * s->vectorInits[i].numElements;
+    total += align (GC_ARRAY_HEADER_SIZE
+                    + ((0 == numBytes)
+                       ? OBJPTR_SIZE
+                       : numBytes),
+                    s->alignment);
+  }
+  return total;
+}
+
+void initIntInfs (GC_state s) {
+  struct GC_intInfInit *inits;
+  pointer frontier;
+  char *str;
+  size_t slen, llen;
+  mp_size_t alen;
+  uint32_t i, j;
+  bool neg, hex;
+  GC_intInf bp;
+  unsigned char *cp;
+
+  assert (isAlignedFrontier (s, s->frontier));
+  frontier = s->frontier;
+  for (i= 0; i < s->intInfInitsLength; i++) {
+    inits = &s->intInfInits[i];
+    str = inits->mlstr;
+    assert (inits->globalIndex < s->globalsLength);
+    neg = *str == '~';
+    if (neg)
+      str++;
+    slen = strlen (str);
+    hex = str[0] == '0' && str[1] == 'x';
+    if (hex) {
+      str += 2;
+      slen -= 2;
+      llen = (slen + 7) / 8;
+    } else
+      llen = (slen + 8) / 9;
+    assert (slen > 0);
+    bp = (GC_intInf)frontier;
+    cp = (unsigned char *)&bp->limbs[llen];
+
+    for (j = 0; j != slen; j++)
+      if ('0' <= str[j] && str[j] <= '9')
+        cp[j] = str[j] - '0' + 0;
+      else if ('a' <= str[j] && str[j] <= 'f')
+        cp[j] = str[j] - 'a' + 0xa;
+      else {
+        assert('A' <= str[j] && str[j] <= 'F');
+        cp[j] = str[j] - 'A' + 0xA;
+      }
+    alen = mpn_set_str ((mp_limb_t*)(bp->limbs), cp, slen, hex ? 0x10 : 10);
+    assert ((size_t)alen <= llen);
+    if (alen <= 1) {
+      uint32_t val, ans;
+      
+      if (alen == 0)
+        val = 0;
+      else
+        val = bp->limbs[0];
+      if (neg) {
+        /*
+         * We only fit if val in [1, 2^30].
+         */
+        ans = - val;
+        val = val - 1;
+      } else
+        /* 
+         * We only fit if val in [0, 2^30 - 1].
+         */
+        ans = val;
+      if (val < (uint32_t)1<<30) {
+        s->globals[inits->globalIndex] = (objptr)(ans<<1 | 1);
+        continue;
+      }
+    }
+    s->globals[inits->globalIndex] = pointerToObjptr((pointer)(&bp->isneg), s->heap.start);
+    bp->counter = 0;
+    bp->length = alen + 1;
+    bp->header = buildHeaderFromTypeIndex (WORD32_VECTOR_TYPE_INDEX);
+    bp->isneg = neg;
+    frontier = alignFrontier (s, (pointer)&bp->limbs[alen]);
+  }
+  assert (isAlignedFrontier (s, frontier));
+  GC_profileAllocInc (s, (size_t)(frontier - s->frontier));
+  s->frontier = frontier;
+  s->cumulativeStatistics.bytesAllocated += frontier - s->frontier;
+}
+
+void initVectors (GC_state s) {
+  struct GC_vectorInit *inits;
+  pointer frontier;
+  uint32_t i;
+
+  assert (isAlignedFrontier (s, s->frontier));
+  inits = s->vectorInits;
+  frontier = s->frontier;
+  for (i = 0; i < s->vectorInitsLength; i++) {
+    size_t bytesPerElement;
+    size_t dataBytes;
+    size_t objectSize;
+    uint32_t typeIndex;
+
+    bytesPerElement = inits[i].bytesPerElement;
+    dataBytes = bytesPerElement * inits[i].numElements;
+    objectSize = align (GC_ARRAY_HEADER_SIZE
+                        + ((0 == dataBytes)
+                           ? POINTER_SIZE
+                           : dataBytes),
+                        s->alignment);
+    assert (objectSize <= (size_t)(s->heap.start + s->heap.size - frontier));
+    *((GC_arrayCounter*)(frontier)) = 0;
+    frontier = frontier + GC_ARRAY_COUNTER_SIZE;
+    *((GC_arrayLength*)(frontier)) = inits[i].numElements;
+    frontier = frontier + GC_ARRAY_LENGTH_SIZE;
+    switch (bytesPerElement) {
+    case 1:
+      typeIndex = WORD8_VECTOR_TYPE_INDEX;
+      break;
+    case 2:
+      typeIndex = WORD16_VECTOR_TYPE_INDEX;
+      break;
+    case 4:
+      typeIndex = WORD32_VECTOR_TYPE_INDEX;
+      break;
+    default:
+      die ("unknown bytes per element in vectorInit: %zu",
+           bytesPerElement);
+    }
+    *((GC_header*)(frontier)) = buildHeaderFromTypeIndex (typeIndex);
+    frontier = frontier + GC_HEADER_SIZE;
+    s->globals[inits[i].globalIndex] = pointerToObjptr(frontier, s->heap.start);
+    if (DEBUG_DETAILED)
+      fprintf (stderr, "allocated vector at "FMTPTR"\n",
+               (uintptr_t)(s->globals[inits[i].globalIndex]));
+    GC_memcpy (inits[i].bytes, frontier, dataBytes);
+    frontier += objectSize - GC_ARRAY_HEADER_SIZE;
+  }
+  if (DEBUG_DETAILED)
+    fprintf (stderr, "frontier after string allocation is "FMTPTR"\n",
+             (uintptr_t)frontier);
+  GC_profileAllocInc (s, (size_t)(frontier - s->frontier));
+  s->cumulativeStatistics.bytesAllocated += (size_t)(frontier - s->frontier);
+  assert (isAlignedFrontier (s, frontier));
+  s->frontier = frontier;
+}
+
+void initWorld (GC_state s) {
+  uint32_t i;
+  pointer start;
+  GC_thread thread;
+  
+  for (i = 0; i < s->globalsLength; ++i)
+    s->globals[i] = BOGUS_OBJPTR;
+  s->lastMajorStatistics.bytesLive = sizeofInitialBytesLive (s);
+  createHeap (s, &s->heap, 
+              sizeofHeapDesired (s, s->lastMajorStatistics.bytesLive, 0),
+              s->lastMajorStatistics.bytesLive);
+  createCardMapAndCrossMap (s);
+  start = alignFrontier (s, s->heap.start);
+  s->frontier = start;
+  initIntInfs (s);
+  initVectors (s);
+  assert ((size_t)(s->frontier - start) <= s->lastMajorStatistics.bytesLive);
+  s->heap.oldGenSize = s->frontier - s->heap.start;
+  setGCStateCurrentHeap (s, 0, 0);
+  thread = newThread (s, sizeofStackInitial (s));
+  switchToThread (s, pointerToObjptr((pointer)thread, s->heap.start));
+}
+

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/init-world.h (from rev 4143, mlton/branches/on-20050822-x86_64-branch/runtime/gc/init.h)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/init.h	2005-11-04 00:12:48 UTC (rev 4143)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/init-world.h	2005-11-04 03:52:55 UTC (rev 4145)
@@ -0,0 +1,36 @@
+/* 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.
+ */
+
+/* GC_init uses the array of struct intInfInits in s at program start
+ * to allocate intInfs.  
+ * The globalIndex'th entry of the globals array in s is set to the
+ * IntInf.int whose value corresponds to the mlstr string.
+ *
+ * The strings pointed to by the mlstr fields consist of
+ *      an optional ~
+ *      either one or more of [0-9] or
+ *             0x followed by one or more of [0-9a-fA-F]
+ *      a trailing EOS
+ */
+struct GC_intInfInit {
+  uint32_t globalIndex;
+  char *mlstr;
+};
+
+/* GC_init allocates a collection of arrays/vectors in the heap. */
+struct GC_vectorInit {
+  pointer bytes;
+  size_t bytesPerElement;
+  uint32_t globalIndex;
+  GC_arrayLength numElements;
+};
+
+size_t sizeofInitialBytesLive (GC_state s);
+void initIntInfs (GC_state s);
+void initVectors (GC_state s);
+void initWorld (GC_state s);

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/init.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/init.c	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/init.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -10,19 +10,6 @@
 /*                          Initialization                          */
 /* ---------------------------------------------------------------- */
 
-static void initSignalStack (GC_state s) {
-#if HAS_SIGALTSTACK
-  static stack_t altstack;
-  size_t ss_size = align (SIGSTKSZ, s->sysvals.pageSize);
-  size_t psize = s->sysvals.pageSize;
-  void *ss_sp = GC_mmap_safe_protect (NULL, 2 * ss_size, psize, psize);
-  altstack.ss_sp = (unsigned char*)ss_sp + ss_size;
-  altstack.ss_size = ss_size;
-  altstack.ss_flags = 0;
-  sigaltstack (&altstack, NULL);
-#endif
-}
-
 #if FALSE
 static bool stringToBool (char *s) {
   if (0 == strcmp (s, "false"))
@@ -77,200 +64,14 @@
   die ("Invalid @MLton memory amount: %s.", s);
 }
 
-static void setInitialBytesLive (GC_state s) {
-  uint32_t i;
-  size_t numBytes;
-  
-  s->lastMajorStatistics.bytesLive = 0;
-  for (i = 0; i < s->intInfInitsLength; ++i) {
-    numBytes = 
-      sizeof(uint32_t) // for the sign
-      + strlen (s->intInfInits[i].mlstr);
-    s->lastMajorStatistics.bytesLive +=
-      align (GC_ARRAY_HEADER_SIZE + numBytes,
-             s->alignment);
-  }
-  for (i = 0; i < s->vectorInitsLength; ++i) {
-    numBytes = 
-      s->vectorInits[i].bytesPerElement
-      * s->vectorInits[i].numElements;
-    s->lastMajorStatistics.bytesLive +=
-      align (GC_ARRAY_HEADER_SIZE
-             + ((0 == numBytes)
-                ? OBJPTR_SIZE
-                : numBytes),
-             s->alignment);
-  }
-}
-
-static void initIntInfs (GC_state s) {
-  struct GC_intInfInit *inits;
-  pointer frontier;
-  char *str;
-  size_t slen, llen;
-  mp_size_t alen;
-  uint32_t i, j;
-  bool neg, hex;
-  GC_intInf bp;
-  unsigned char *cp;
-
-  assert (isAlignedFrontier (s, s->frontier));
-  frontier = s->frontier;
-  for (i= 0; i < s->intInfInitsLength; i++) {
-    inits = &s->intInfInits[i];
-    str = inits->mlstr;
-    assert (inits->globalIndex < s->globalsLength);
-    neg = *str == '~';
-    if (neg)
-      str++;
-    slen = strlen (str);
-    hex = str[0] == '0' && str[1] == 'x';
-    if (hex) {
-      str += 2;
-      slen -= 2;
-      llen = (slen + 7) / 8;
-    } else
-      llen = (slen + 8) / 9;
-    assert (slen > 0);
-    bp = (GC_intInf)frontier;
-    cp = (unsigned char *)&bp->limbs[llen];
-
-    for (j = 0; j != slen; j++)
-      if ('0' <= str[j] && str[j] <= '9')
-        cp[j] = str[j] - '0' + 0;
-      else if ('a' <= str[j] && str[j] <= 'f')
-        cp[j] = str[j] - 'a' + 0xa;
-      else {
-        assert('A' <= str[j] && str[j] <= 'F');
-        cp[j] = str[j] - 'A' + 0xA;
-      }
-    alen = mpn_set_str ((mp_limb_t*)(bp->limbs), cp, slen, hex ? 0x10 : 10);
-    assert ((size_t)alen <= llen);
-    if (alen <= 1) {
-      uint32_t val, ans;
-      
-      if (alen == 0)
-        val = 0;
-      else
-        val = bp->limbs[0];
-      if (neg) {
-        /*
-         * We only fit if val in [1, 2^30].
-         */
-        ans = - val;
-        val = val - 1;
-      } else
-        /* 
-         * We only fit if val in [0, 2^30 - 1].
-         */
-        ans = val;
-      if (val < (uint32_t)1<<30) {
-        s->globals[inits->globalIndex] = (objptr)(ans<<1 | 1);
-        continue;
-      }
-    }
-    s->globals[inits->globalIndex] = pointerToObjptr((pointer)(&bp->isneg), s->heap.start);
-    bp->counter = 0;
-    bp->length = alen + 1;
-    bp->header = buildHeaderFromTypeIndex (WORD32_VECTOR_TYPE_INDEX);
-    bp->isneg = neg;
-    frontier = alignFrontier (s, (pointer)&bp->limbs[alen]);
-  }
-  assert (isAlignedFrontier (s, frontier));
-  GC_profileAllocInc (s, (size_t)(frontier - s->frontier));
-  s->frontier = frontier;
-  s->cumulativeStatistics.bytesAllocated += frontier - s->frontier;
-}
-
-static void initVectors (GC_state s) {
-  struct GC_vectorInit *inits;
-  pointer frontier;
-  uint32_t i;
-
-  assert (isAlignedFrontier (s, s->frontier));
-  inits = s->vectorInits;
-  frontier = s->frontier;
-  for (i = 0; i < s->vectorInitsLength; i++) {
-    size_t bytesPerElement;
-    size_t dataBytes;
-    size_t objectSize;
-    uint32_t typeIndex;
-
-    bytesPerElement = inits[i].bytesPerElement;
-    dataBytes = bytesPerElement * inits[i].numElements;
-    objectSize = align (GC_ARRAY_HEADER_SIZE
-                        + ((0 == dataBytes)
-                           ? POINTER_SIZE
-                           : dataBytes),
-                        s->alignment);
-    assert (objectSize <= (size_t)(s->heap.start + s->heap.size - frontier));
-    *((GC_arrayCounter*)(frontier)) = 0;
-    frontier = frontier + GC_ARRAY_COUNTER_SIZE;
-    *((GC_arrayLength*)(frontier)) = inits[i].numElements;
-    frontier = frontier + GC_ARRAY_LENGTH_SIZE;
-    switch (bytesPerElement) {
-    case 1:
-      typeIndex = WORD8_VECTOR_TYPE_INDEX;
-      break;
-    case 2:
-      typeIndex = WORD16_VECTOR_TYPE_INDEX;
-      break;
-    case 4:
-      typeIndex = WORD32_VECTOR_TYPE_INDEX;
-      break;
-    default:
-      die ("unknown bytes per element in vectorInit: %zu",
-           bytesPerElement);
-    }
-    *((GC_header*)(frontier)) = buildHeaderFromTypeIndex (typeIndex);
-    frontier = frontier + GC_HEADER_SIZE;
-    s->globals[inits[i].globalIndex] = pointerToObjptr(frontier, s->heap.start);
-    if (DEBUG_DETAILED)
-      fprintf (stderr, "allocated vector at "FMTPTR"\n",
-               (uintptr_t)(s->globals[inits[i].globalIndex]));
-    GC_memcpy (inits[i].bytes, frontier, dataBytes);
-    frontier += objectSize - GC_ARRAY_HEADER_SIZE;
-  }
-  if (DEBUG_DETAILED)
-    fprintf (stderr, "frontier after string allocation is "FMTPTR"\n",
-             (uintptr_t)frontier);
-  GC_profileAllocInc (s, (size_t)(frontier - s->frontier));
-  s->cumulativeStatistics.bytesAllocated += (size_t)(frontier - s->frontier);
-  assert (isAlignedFrontier (s, frontier));
-  s->frontier = frontier;
-}
-
-static void newWorld (GC_state s) {
-  uint32_t i;
-  pointer start;
-  GC_thread thread;
-  
-  for (i = 0; i < s->globalsLength; ++i)
-    s->globals[i] = BOGUS_OBJPTR;
-  setInitialBytesLive (s);
-  createHeap (s, &s->heap, 
-              sizeofHeapDesired (s, s->lastMajorStatistics.bytesLive, 0),
-              s->lastMajorStatistics.bytesLive);
-  createCardMapAndCrossMap (s);
-  start = alignFrontier (s, s->heap.start);
-  s->frontier = start;
-  initIntInfs (s);
-  initVectors (s);
-  assert ((size_t)(s->frontier - start) <= s->lastMajorStatistics.bytesLive);
-  s->heap.oldGenSize = s->frontier - s->heap.start;
-  setGCStateCurrentHeap (s, 0, 0);
-  thread = newThread (s, sizeofStackInitial (s));
-  switchToThread (s, pointerToObjptr((pointer)thread, s->heap.start));
-}
-
 /* ---------------------------------------------------------------- */
 /*                             GC_init                              */
 /* ---------------------------------------------------------------- */
 
 bool MLton_Platform_CygwinUseMmap;
 
-static int processAtMLton (GC_state s, int argc, char **argv,
-                           char **worldFile) {
+int processAtMLton (GC_state s, int argc, char **argv,
+                    char **worldFile) {
   int i;
 
   i = 1;
@@ -479,7 +280,7 @@
   s->signalsInfo.signalIsPending = FALSE;
   sigemptyset (&s->signalsInfo.signalsHandled);
   sigemptyset (&s->signalsInfo.signalsPending);
-  s->startTime = currentTime ();
+  s->startTime = getCurrentTime ();
   // s->sysvals.availRam = ;
   // s->sysvals.totalRam = ;
   // s->sysvals.pageSize = ;
@@ -497,7 +298,6 @@
   unless (s->controls.ratios.markCompact <= s->controls.ratios.copy
           and s->controls.ratios.copy <= s->controls.ratios.live)
     die ("Ratios must satisfy mark-compact-ratio <= copy-ratio <= live-ratio");
-  // s->totalRam = totalRam (s);
   /* We align s->ram by pageSize so that we can test whether or not we
    * we are using mark-compact by comparing heap size to ram size.  If
    * we didn't round, the size might be slightly off.
@@ -524,36 +324,18 @@
    * command-line arguments, because those may just be doing a show
    * prof, in which case we don't want to initialize the atExit.
    */
-  if (PROFILE_NONE == s->profiling.kind)
-    s->profiling.isOn = FALSE;
-  else {
-    s->profiling.isOn = TRUE;
-    assert (s->profiling.frameSourcesLength == s->frameLayoutsLength);
-    switch (s->profiling.kind) {
-    case PROFILE_ALLOC:
-    case PROFILE_COUNT:
-      s->profiling.data = GC_profileNew (s);
-      break;
-    case PROFILE_NONE:
-      die ("impossible PROFILE_NONE");
-    case PROFILE_TIME:
-      profileTimeInit (s);
-      break;
-    }
-    profileEndState = s;
-    atexit (profileEnd);
-  }
+  initProfiling (s);
   if (s->amOriginal) {
-    newWorld (s);
+    initWorld (s);
     /* The mutator stack invariant doesn't hold,
      * because the mutator has yet to run.
      */
-    assert (mutatorInvariant (s, TRUE, FALSE));
+    assert (invariantForMutator (s, TRUE, FALSE));
   } else {
     loadWorldFromFileName (s, worldFile);
     if (s->profiling.isOn and s->profiling.stack)
       foreachStackFrame (s, enterFrame);
-    assert (mutatorInvariant (s, TRUE, TRUE));
+    assert (invariantForMutator (s, TRUE, TRUE));
   }
   s->amInGC = FALSE;
   return res;

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/init.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/init.h	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/init.h	2005-11-04 03:52:55 UTC (rev 4145)
@@ -6,27 +6,6 @@
  * See the file MLton-LICENSE for details.
  */
 
-
-/* GC_init uses the array of struct intInfInits in s at program start
- * to allocate intInfs.  
- * The globalIndex'th entry of the globals array in s is set to the
- * IntInf.int whose value corresponds to the mlstr string.
- *
- * The strings pointed to by the mlstr fields consist of
- *      an optional ~
- *      either one or more of [0-9] or
- *             0x followed by one or more of [0-9a-fA-F]
- *      a trailing EOS
- */
-struct GC_intInfInit {
-  uint32_t globalIndex;
-  char *mlstr;
-};
-
-/* GC_init allocates a collection of arrays/vectors in the heap. */
-struct GC_vectorInit {
-  pointer bytes;
-  size_t bytesPerElement;
-  uint32_t globalIndex;
-  GC_arrayLength numElements;
-};
+int processAtMLton (GC_state s, int argc,
+                    char **argv, char **worldFile);
+int GC_init (GC_state s, int argc, char **argv);

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.c	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -14,9 +14,9 @@
          (uintptr_t)opp, *opp);
 }
 
-bool invariant (GC_state s) {
+bool invariantForGC (GC_state s) {
   if (DEBUG)
-    fprintf (stderr, "invariant\n");
+    fprintf (stderr, "invariantForGC\n");
   /* Frame layouts */
   for (unsigned int i = 0; i < s->frameLayoutsLength; ++i) {
     GC_frameLayout layout;
@@ -54,16 +54,16 @@
   assert (s->secondaryHeap.start == NULL 
           or s->heap.size == s->secondaryHeap.size);
   /* Check that all pointers are into from space. */
-  foreachGlobalObjptr (s, assertObjptrIsInFromSpace);
+  foreachGlobalObjptr (s, assertIsObjptrInFromSpace);
   pointer back = s->heap.start + s->heap.oldGenSize;
   if (DEBUG_DETAILED)
     fprintf (stderr, "Checking old generation.\n");
   foreachObjptrInRange (s, alignFrontier (s, s->heap.start), &back, 
-                        assertObjptrIsInFromSpace, FALSE);
+                        assertIsObjptrInFromSpace, FALSE);
   if (DEBUG_DETAILED)
     fprintf (stderr, "Checking nursery.\n");
   foreachObjptrInRange (s, s->heap.nursery, &s->frontier, 
-                        assertObjptrIsInFromSpace, FALSE);
+                        assertIsObjptrInFromSpace, FALSE);
   /* Current thread. */
   GC_stack stack = getStackCurrent(s);
   assert (isAlignedStackReserved (s, stack->reserved));
@@ -74,29 +74,29 @@
   assert (stack->used == sizeofGCStateCurrentStackUsed (s));
   assert (stack->used <= stack->reserved);
   if (DEBUG)
-    fprintf (stderr, "invariant passed\n");
+    fprintf (stderr, "invariantForGC passed\n");
   return TRUE;
 }
 
-bool mutatorFrontierInvariant (GC_state s) {
+bool invariantForMutatorFrontier (GC_state s) {
   GC_thread thread = getThreadCurrent(s);
   return (thread->bytesNeeded 
           <= (size_t)(s->limitPlusSlop - s->frontier));
 }
 
-bool mutatorStackInvariant (GC_state s) {
+bool invariantForMutatorStack (GC_state s) {
   GC_stack stack = getStackCurrent(s);
   return (getStackTop (s, stack) 
           <= getStackLimit (s, stack) + getStackTopFrameSize (s, stack));
 }
 
-bool mutatorInvariant (GC_state s, bool frontier, bool stack) {
+bool invariantForMutator (GC_state s, bool frontier, bool stack) {
   if (DEBUG)
     displayGCState (s, stderr);
   if (frontier)
-    assert (mutatorFrontierInvariant(s));
+    assert (invariantForMutatorFrontier(s));
   if (stack)
-    assert (mutatorStackInvariant(s));
-  assert (invariant (s));
+    assert (invariantForMutatorStack(s));
+  assert (invariantForGC (s));
   return TRUE;
 }

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.h	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.h	2005-11-04 03:52:55 UTC (rev 4145)
@@ -6,8 +6,8 @@
  * See the file MLton-LICENSE for details.
  */
 
-void assertObjptrIsInFromSpace (GC_state s, objptr *opp);
-bool invariant (GC_state s);
-bool mutatorFrontierInvariant (GC_state s);
-bool mutatorStackInvariant (GC_state s);
-bool mutatorInvariant (GC_state s, bool frontier, bool stack);
+void assertIsObjptrInFromSpace (GC_state s, objptr *opp);
+bool invariantForGC (GC_state s);
+bool invariantForMutatorFrontier (GC_state s);
+bool invariantForMutatorStack (GC_state s);
+bool invariantForMutator (GC_state s, bool frontier, bool stack);

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-compact.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-compact.c	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-compact.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -12,8 +12,11 @@
 
 /* An object pointer might be larger than a header.
  */ 
-void threadInternalCopy (pointer dst, pointer src) {
-  size_t count = (OBJPTR_SIZE - GC_HEADER_SIZE) / GC_HEADER_SIZE;
+void copyForThreadInternal (pointer dst, pointer src) {
+  size_t count;
+
+  assert (0 == (OBJPTR_SIZE % GC_HEADER_SIZE));
+  count = (OBJPTR_SIZE - GC_HEADER_SIZE) / GC_HEADER_SIZE;
   src = src + GC_HEADER_SIZE * count;
 
   for (size_t i = 0; i <= count; i++) {
@@ -35,14 +38,14 @@
              "threadInternal opp = "FMTPTR"  p = "FMTPTR"  header = "FMTHDR"\n",
              (uintptr_t)opp, (uintptr_t)p, getHeader (p));
   headerp = getHeaderp (p);
-  threadInternalCopy ((pointer)(opp), (pointer)(headerp));
-  threadInternalCopy ((pointer)(headerp), (pointer)(&opop));
+  copyForThreadInternal ((pointer)(opp), (pointer)(headerp));
+  copyForThreadInternal ((pointer)(headerp), (pointer)(&opop));
 }
 
-/* If p is weak, the object pointer was valid, and points to an unmarked object,
- * then clear the object pointer.
+/* If p is weak, the object pointer was valid, and points to an
+ * unmarked object, then clear the object pointer.
  */
-void maybeClearWeak (GC_state s, pointer p) {
+void clearIfWeakAndUnmarkedForMarkCompact (GC_state s, pointer p) {
   GC_header header;
   GC_header *headerp;
   uint16_t numNonObjptrs, numObjptrs;
@@ -52,14 +55,15 @@
   header = *headerp;
   splitHeader(s, *headerp, &tag, NULL, &numNonObjptrs, &numObjptrs);
   if (WEAK_TAG == tag and 1 == numObjptrs) {
-    GC_header h2;
+    GC_header objptrHeader;
     
     if (DEBUG_WEAK)
-      fprintf (stderr, "maybeClearWeak ("FMTPTR")  header = "FMTHDR"\n",
+      fprintf (stderr, "clearIfWeakAndUnmarkedForMarkCompact ("FMTPTR")  header = "FMTHDR"\n",
                (uintptr_t)p, header);
-    h2 = getHeader (objptrToPointer(((GC_weak)p)->objptr, s->heap.start));
-    /* If it's unmarked not threaded, clear the weak pointer. */
-    if (1 == ((MARK_MASK | 1) & h2)) {
+    objptrHeader = getHeader (objptrToPointer(((GC_weak)p)->objptr, s->heap.start));
+    /* If it's not threaded and unmarked, clear the weak pointer. */
+    if ((GC_VALID_HEADER_MASK & objptrHeader)
+        and not (MARK_MASK & objptrHeader)) {
       ((GC_weak)p)->objptr = BOGUS_OBJPTR;
       header = GC_WEAK_GONE_HEADER | MARK_MASK;
       if (DEBUG_WEAK)
@@ -70,7 +74,7 @@
   }
 }
 
-void updateForwardPointers (GC_state s) {
+void updateForwardPointersForMarkCompact (GC_state s) {
   pointer back;
   pointer endOfLastMarked;
   pointer front;
@@ -95,14 +99,14 @@
   p = advanceToObjectData (s, front);
   headerp = getHeaderp (p);
   header = *headerp;
-  if (1 == (1 & header)) {
+  if (GC_VALID_HEADER_MASK & header) {
     /* It's a header */
     if (MARK_MASK & header) {
       /* It is marked, but has no forward pointers.
        * Thread internal pointers.
        */
 thread:
-      maybeClearWeak (s, p);
+      clearIfWeakAndUnmarkedForMarkCompact (s, p);
       size = sizeofObject (s, p);
       if (DEBUG_MARK_COMPACT)
         fprintf (stderr, "threading "FMTPTR" of size %zu\n",
@@ -112,10 +116,10 @@
          * (GC_ARRAY_HEADER_SIZE + OBJPTR_SIZE) space to be available
          * because that is the smallest possible array.  You cannot
          * use GC_ARRAY_HEADER_SIZE because even zero-length arrays
-         * require an extra word for the forwarding pointer.  If you
-         * did use GC_ARRAY_HEADER_SIZE,
-         * updateBackwardPointersAndSlide would skip the extra word
-         * and be completely busted.
+         * require extra space for the forwarding pointer.  If you did
+         * use GC_ARRAY_HEADER_SIZE,
+         * updateBackwardPointersAndSlideForMarkCompact would skip the
+         * extra space and be completely busted.
          */
         if (DEBUG_MARK_COMPACT)
           fprintf (stderr, "compressing from "FMTPTR" to "FMTPTR" (length = %zu)\n",
@@ -142,7 +146,7 @@
     pointer new;
     objptr newObjptr;
 
-    assert (0 == (1 & header));
+    assert (not (GC_VALID_HEADER_MASK & 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.
@@ -153,10 +157,10 @@
       pointer cur;
       objptr curObjptr;
 
-      threadInternalCopy ((pointer)(&curObjptr), (pointer)headerp);
+      copyForThreadInternal ((pointer)(&curObjptr), (pointer)headerp);
       cur = objptrToPointer (curObjptr, s->heap.start);
 
-      threadInternalCopy ((pointer)headerp, cur);
+      copyForThreadInternal ((pointer)headerp, cur);
       *((objptr*)cur) = newObjptr;
 
       header = *headerp;
@@ -168,7 +172,7 @@
   return;
 }
 
-void updateBackwardPointersAndSlide (GC_state s) {
+void updateBackwardPointersAndSlideForMarkCompact (GC_state s) {
   pointer back;
   pointer front;
   size_t gap;
@@ -191,7 +195,7 @@
   p = advanceToObjectData (s, front);
   headerp = getHeaderp (p);
   header = *headerp;
-  if (1 == (1 & header)) {
+  if (GC_VALID_HEADER_MASK & header) {
     /* It's a header */
     if (MARK_MASK & header) {
       /* It is marked, but has no backward pointers to it.
@@ -225,7 +229,7 @@
     pointer new;
     objptr newObjptr;
 
-    assert (0 == (1 & header));
+    assert (not (GC_VALID_HEADER_MASK & header));
     /* It's a pointer.  This object must be live.  Fix all the
      * backward pointers to it.  Then unmark it.
      */
@@ -235,10 +239,10 @@
       pointer cur;
       objptr curObjptr;
       
-      threadInternalCopy ((pointer)(&curObjptr), (pointer)headerp);
+      copyForThreadInternal ((pointer)(&curObjptr), (pointer)headerp);
       cur = objptrToPointer (curObjptr, s->heap.start);
 
-      threadInternalCopy ((pointer)headerp, cur);
+      copyForThreadInternal ((pointer)headerp, cur);
       *((objptr*)cur) = newObjptr;
 
       header = *headerp;
@@ -270,14 +274,14 @@
     s->lastMajorStatistics.bytesHashConsed = 0;
     s->cumulativeStatistics.numHashConsGCs++;
     s->objectHashTable = allocHashTable (s);
-    foreachGlobalObjptr (s, dfsMarkTrue);
+    foreachGlobalObjptr (s, dfsMarkWithHashCons);
     freeHashTable (s->objectHashTable);
   } else {
-    foreachGlobalObjptr (s, dfsMarkFalse);
+    foreachGlobalObjptr (s, dfsMarkWithoutHashCons);
   }
   foreachGlobalObjptr (s, threadInternalObjptr);
-  updateForwardPointers (s);
-  updateBackwardPointersAndSlide (s);
+  updateForwardPointersForMarkCompact (s);
+  updateBackwardPointersAndSlideForMarkCompact (s);
   clearCrossMap (s);
   s->cumulativeStatistics.bytesMarkCompacted += s->heap.oldGenSize;
   s->lastMajorStatistics.kind = GC_MARK_COMPACT;

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-compact.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-compact.h	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-compact.h	2005-11-04 03:52:55 UTC (rev 4145)
@@ -6,9 +6,9 @@
  * See the file MLton-LICENSE for details.
  */
 
-void threadInternalCopy (pointer dst, pointer src);
+void copyForThreadInternal (pointer dst, pointer src);
 void threadInternalObjptr (GC_state s, objptr *opp);
-void maybeClearWeak (GC_state s, pointer p);
-void updateForwardPointers (GC_state s);
-void updateBackwardPointersAndSlide (GC_state s);
+void clearIfWeakAndUnmarkedForMarkCompact (GC_state s, pointer p);
+void updateForwardPointersForMarkCompact (GC_state s);
+void updateBackwardPointersAndSlideForMarkComact (GC_state s);
 void majorMarkCompactGC (GC_state s);

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-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/new-object.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -54,9 +54,9 @@
   reserved = alignStackReserved (s, reserved);
   if (reserved > s->cumulativeStatistics.maxStackSizeSeen)
     s->cumulativeStatistics.maxStackSizeSeen = reserved;
-  stack = (GC_stack) newObject (s, GC_STACK_HEADER, 
+  stack = (GC_stack)(newObject (s, GC_STACK_HEADER, 
                                 sizeofStackWithHeaderAligned (s, reserved),
-                                allocInOldGen);
+                                allocInOldGen));
   stack->reserved = reserved;
   stack->used = 0;
   if (DEBUG_STACKS)
@@ -66,17 +66,20 @@
   return stack;
 }
 
-void growStack (GC_state s) {
-  size_t size;
+GC_thread newThread (GC_state s, size_t reserved) {
   GC_stack stack;
+  GC_thread thread;
 
-  size = sizeofStackGrow (s, getStackCurrent(s));
-  if (DEBUG_STACKS or s->controls.messages)
-    fprintf (stderr, "Growing stack to size %zu.\n",
-             /*uintToCommaString*/(sizeofStackWithHeaderAligned (s, size)));
-  assert (hasHeapBytesFree (s, sizeofStackWithHeaderAligned (s, size), 0));
-  stack = newStack (s, size, TRUE);
-  copyStack (s, getStackCurrent(s), stack);
-  getThreadCurrent(s)->stack = pointerToObjptr ((pointer)stack, s->heap.start);
-  markCard (s, objptrToPointer (getThreadCurrentObjptr(s), s->heap.start));
+  ensureHasHeapBytesFree (s, 0, sizeofStackWithHeaderAligned (s, reserved) + sizeofThread (s));
+  stack = newStack (s, reserved, FALSE);
+  thread = (GC_thread)(newObject (s, GC_THREAD_HEADER, 
+                                  sizeofThread (s), 
+                                  FALSE));
+  thread->bytesNeeded = 0;
+  thread->exnStack = BOGUS_EXN_STACK;
+  thread->stack = pointerToObjptr((pointer)stack, s->heap.start);
+  if (DEBUG_THREADS)
+    fprintf (stderr, FMTPTR" = newThreadOfSize (%zu)\n",
+             (uintptr_t)thread, reserved);;
+  return thread;
 }

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/new-object.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/new-object.h	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/new-object.h	2005-11-04 03:52:55 UTC (rev 4145)
@@ -9,4 +9,4 @@
 pointer newObject (GC_state s, GC_header header, 
                    size_t bytesRequested, bool allocInOldGen);
 GC_stack newStack (GC_state s, size_t reserved, bool allocInOldGen);
-void growStack (GC_state s);
+GC_thread newThread (GC_state s, size_t stackSize);

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/pack.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/pack.c	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/pack.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -17,7 +17,7 @@
    * allocated since the last collection.  But you would still need to
    * do a minor GC to make all objects contiguous.
    */
-  doGC (s, 0, 0, TRUE, FALSE);
+  performGC (s, 0, 0, TRUE, FALSE);
   keep = s->heap.oldGenSize * 1.1;
   if (keep <= s->heap.size) {
     shrinkHeap (s, &s->heap, keep);

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/profiling.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/profiling.c	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/profiling.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -520,3 +520,25 @@
     GC_profileWrite (s, s->profiling.data, fd);
   }
 }
+
+void initProfiling (GC_state s) {
+  if (PROFILE_NONE == s->profiling.kind)
+    s->profiling.isOn = FALSE;
+  else {
+    s->profiling.isOn = TRUE;
+    assert (s->profiling.frameSourcesLength == s->frameLayoutsLength);
+    switch (s->profiling.kind) {
+    case PROFILE_ALLOC:
+    case PROFILE_COUNT:
+      s->profiling.data = GC_profileNew (s);
+      break;
+    case PROFILE_NONE:
+      die ("impossible PROFILE_NONE");
+    case PROFILE_TIME:
+      profileTimeInit (s);
+      break;
+    }
+    profileEndState = s;
+    atexit (profileEnd);
+  }
+}

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/profiling.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/profiling.h	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/profiling.h	2005-11-04 03:52:55 UTC (rev 4145)
@@ -103,7 +103,11 @@
   pointer textStart;
 };
 
+static void showProf (GC_state s);
+void initProfiling (GC_state s);
+static void enterFrame (GC_state s, uint32_t i);
 
+
 void GC_profileAllocInc (GC_state s, size_t bytes);
 
 void GC_profileEnter (GC_state s);

Deleted: mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.h	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.h	2005-11-04 03:52:55 UTC (rev 4145)
@@ -1,33 +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_ratios {
-  /* Minimum live ratio to use copying GC. */
-  float copy; 
-  /* Only use generational GC with copying collection if the ratio of
-   * heap size to live data size is below copyGenerational.
-   */
-  float copyGenerational; 
-  float grow; 
-  float hashCons;
-  /* Desired ratio of heap size to live data. */
-  float live; 
-  /* Minimum live ratio to us mark-compact GC. */
-  float markCompact; 
-  /* Only use generational GC with mark-compact collection if the
-   * ratio of heap size to live data size is below
-   * markCompactGenerational.
-   */
-  float markCompactGenerational; 
-  /* As long as the ratio of bytes live to nursery size is greater
-   * than nurseryRatio, use minor GCs.
-   */
-  float nursery; 
-  float ramSlop;
-  float threadShrink; 
-};

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/rusage.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/rusage.c	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/rusage.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -66,7 +66,7 @@
 }
 
 /* Return time as number of milliseconds. */
-uintmax_t currentTime (void) {
+uintmax_t getCurrentTime (void) {
   struct rusage ru;
   
   getrusage (RUSAGE_SELF, &ru);

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/share.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/share.c	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/share.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -14,10 +14,10 @@
   if (DEBUG_SHARE or s->controls.messages)
     s->lastMajorStatistics.bytesHashConsed = 0;
   // Don't hash cons during the first round of marking.
-  total = dfsMark (s, object, MARK_MODE, FALSE);
+  total = dfsMarkByMode (s, object, MARK_MODE, FALSE);
   s->objectHashTable = allocHashTable (s);
   // Hash cons during the second round of marking.
-  dfsMark (s, object, UNMARK_MODE, TRUE);
+  dfsMarkByMode (s, object, UNMARK_MODE, TRUE);
   freeHashTable (s->objectHashTable);
   if (DEBUG_SHARE or s->controls.messages)
     printBytesHashConsedMessage (s, total);

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/signals.c (from rev 4143, mlton/branches/on-20050822-x86_64-branch/runtime/gc/init.c)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/init.c	2005-11-04 00:12:48 UTC (rev 4143)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/signals.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -0,0 +1,24 @@
+/* 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.
+ */
+
+/* ---------------------------------------------------------------- */
+/*                          Initialization                          */
+/* ---------------------------------------------------------------- */
+
+void initSignalStack (GC_state s) {
+#if HAS_SIGALTSTACK
+  static stack_t altstack;
+  size_t ss_size = align (SIGSTKSZ, s->sysvals.pageSize);
+  size_t psize = s->sysvals.pageSize;
+  void *ss_sp = GC_mmap_safe_protect (NULL, 2 * ss_size, psize, psize);
+  altstack.ss_sp = (unsigned char*)ss_sp + ss_size;
+  altstack.ss_size = ss_size;
+  altstack.ss_flags = 0;
+  sigaltstack (&altstack, NULL);
+#endif
+}

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/signals.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/signals.h	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/signals.h	2005-11-04 03:52:55 UTC (rev 4145)
@@ -24,3 +24,5 @@
    */
   sigset_t signalsPending;
 };
+
+void initSignalStack (GC_state s);

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/size.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/size.c	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/size.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -11,9 +11,9 @@
 
   if (DEBUG_SIZE)
     fprintf (stderr, "GC_size marking\n");
-  res = dfsMark (s, root, MARK_MODE, FALSE);
+  res = dfsMarkByMode (s, root, MARK_MODE, FALSE);
   if (DEBUG_SIZE)
     fprintf (stderr, "GC_size unmarking\n");
-  dfsMark (s, root, UNMARK_MODE, FALSE);
+  dfsMarkByMode (s, root, UNMARK_MODE, FALSE);
   return res;
 }

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/switch-thread.c (from rev 4143, mlton/branches/on-20050822-x86_64-branch/runtime/gc/garbage-collection.c)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/garbage-collection.c	2005-11-04 00:12:48 UTC (rev 4143)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/switch-thread.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -0,0 +1,66 @@
+/* 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.
+ */
+
+void switchToThread (GC_state s, objptr op) {
+  if (DEBUG_THREADS) {
+    GC_thread thread;
+    GC_stack stack;
+    
+    thread = (GC_thread)(objptrToPointer (op, s->heap.start));
+    stack = (GC_stack)(objptrToPointer (thread->stack, s->heap.start));
+    
+    fprintf (stderr, "switchToThread ("FMTOBJPTR")  used = %zu  reserved = %zu\n",
+             op, stack->used, stack->reserved);
+  }
+  s->currentThread = op;
+  setGCStateCurrentThreadAndStack (s);
+}
+
+void GC_switchToThread (GC_state s, GC_thread t, size_t ensureBytesFree) {
+  if (DEBUG_THREADS)
+    fprintf (stderr, "GC_switchToThread ("FMTPTR", %zu)\n", 
+             (uintptr_t)t, ensureBytesFree);
+  if (FALSE) {
+    /* This branch is slower than the else branch, especially
+     * when debugging is turned on, because it does an invariant
+     * check on every thread switch.
+     * So, we'll stick with the else branch for now.
+     */
+    enter (s);
+    getThreadCurrent(s)->bytesNeeded = ensureBytesFree;
+    switchToThread (s, pointerToObjptr((pointer)t, s->heap.start));
+    s->atomicState--;
+    switchToHandlerThreadIfNonAtomicAndSignalPending (s);
+    ensureInvariantForMutator (s, FALSE);
+    assert (invariantForMutatorFrontier(s));
+    assert (invariantForMutatorStack(s));
+    leave (s);
+  } else {
+    /* BEGIN: enter(s); */
+    getStackCurrent(s)->used = sizeofGCStateCurrentStackUsed (s);
+    getThreadCurrent(s)->exnStack = s->exnStack;
+    beginAtomic (s);
+    /* END: enter(s); */
+    getThreadCurrent(s)->bytesNeeded = ensureBytesFree;
+    switchToThread (s, pointerToObjptr((pointer)t, s->heap.start));
+    s->atomicState--;
+    switchToHandlerThreadIfNonAtomicAndSignalPending (s);
+    /* BEGIN: ensureInvariantForMutator */
+    if (not (invariantForMutatorFrontier(s))
+        or not (invariantForMutatorStack(s))) {
+      /* This GC will grow the stack, if necessary. */
+      performGC (s, 0, getThreadCurrent(s)->bytesNeeded, FALSE, TRUE);
+    }
+    /* END: ensureInvariantForMutator */
+    /* BEGIN: leave(s); */
+    endAtomic (s);
+    /* END: leave(s); */
+  }
+  assert (invariantForMutatorFrontier(s));
+  assert (invariantForMutatorStack(s));
+}

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/switch-thread.h (from rev 4143, mlton/branches/on-20050822-x86_64-branch/runtime/gc/garbage-collection.h)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/garbage-collection.h	2005-11-04 00:12:48 UTC (rev 4143)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/switch-thread.h	2005-11-04 03:52:55 UTC (rev 4145)
@@ -0,0 +1,10 @@
+/* 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.
+ */
+
+void switchToThread (GC_state s, objptr op);
+void GC_switchToThread (GC_state s, GC_thread t, size_t ensureBytesFree);

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/thread.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/thread.c	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/thread.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -24,6 +24,14 @@
   size_t res;
 
   res = GC_NORMAL_HEADER_SIZE + sizeof (struct GC_thread);
+  if (DEBUG) {
+    size_t check;
+    uint16_t numNonObjptrs, numObjptrs;
+
+    splitHeader (s, GC_THREAD_HEADER, NULL, NULL, &numNonObjptrs, &numObjptrs);
+    check = GC_NORMAL_HEADER_SIZE + sizeofNormalNoHeader (s, numNonObjptrs, numObjptrs);
+    assert (check == res);
+  }
   /* The following assert depends on struct GC_thread being the right
    * size.  Right now, it happens that res = 16, which is aligned mod
    * 4 and mod 8, which is all that we need.  If the struct ever

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/weak.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/weak.c	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/weak.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -6,7 +6,28 @@
  * See the file MLton-LICENSE for details.
  */
 
+size_t sizeofWeak (GC_state s) {
+  size_t res;
 
+  res = GC_NORMAL_HEADER_SIZE + sizeof (struct GC_weak);
+  if (DEBUG) {
+    size_t check;
+    uint16_t numNonObjptrs, numObjptrs;
+
+    splitHeader (s, GC_WEAK_GONE_HEADER, NULL, NULL, &numNonObjptrs, &numObjptrs);
+    check = GC_NORMAL_HEADER_SIZE + sizeofNormalNoHeader (s, numNonObjptrs, numObjptrs);
+    assert (check == res);
+  }
+  /* The following assert depends on struct GC_weak being the right
+   * size.  Right now, it happens that res = 16, which is aligned mod
+   * 4 and mod 8, which is all that we need.  If the struct ever
+   * changes (possible) or we need more alignment (doubtful), we may
+   * need to put some padding at the beginning.
+   */
+  assert (isAligned (res, s->alignment));
+  return res;
+}
+
 uint32_t GC_weakCanGet (GC_state s, pointer p) {
   uint32_t res;
 
@@ -28,14 +49,14 @@
 }
 
 pointer GC_weakNew (GC_state s, GC_header header, pointer p) {
-  pointer res;
+  GC_weak res;
 
-  res = newObject (s, header, 
-                   GC_NORMAL_HEADER_SIZE + sizeof(struct GC_weak), 
-                   FALSE);
-  ((GC_weak)res)->objptr = pointerToObjptr(p, s->heap.start);
+  res = (GC_weak)(newObject (s, header, 
+                             sizeofWeak (s),
+                             FALSE));
+  res->objptr = pointerToObjptr(p, s->heap.start);
   if (DEBUG_WEAK)
     fprintf (stderr, FMTPTR" = GC_weakNew ("FMTHDR", "FMTPTR")\n",
              (uintptr_t)res, header, (uintptr_t)p);
-  return res;
+  return (pointer)res;
 }

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/weak.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/weak.h	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/weak.h	2005-11-04 03:52:55 UTC (rev 4145)
@@ -31,3 +31,9 @@
   struct GC_weak *link;
   objptr objptr;
 } *GC_weak;
+
+size_t sizeofWeak (GC_state s);
+uint32_t GC_weakCanGet (GC_state s, pointer p);
+pointer GC_weakGet (GC_state s, pointer p);
+pointer GC_weakNew (GC_state s, GC_header header, pointer p);
+

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/world.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/world.c	2005-11-04 01:38:08 UTC (rev 4144)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/world.c	2005-11-04 03:52:55 UTC (rev 4145)
@@ -54,7 +54,7 @@
   if (DEBUG_WORLD)
     fprintf (stderr, "saveWorld (%d).\n", fd);
   /* Compact the heap. */
-  doGC (s, 0, 0, TRUE, TRUE);
+  performGC (s, 0, 0, TRUE, TRUE);
   sprintf (buf,
            "Heap file created by MLton.\nheap.start = "FMTPTR"\nbytesLive = %zu\n",
            (uintptr_t)s->heap.start,