[MLton-commit] r4114

Matthew Fluet MLton@mlton.org
Tue, 18 Oct 2005 18:28:42 -0700


GC_gc functionality
----------------------------------------------------------------------

U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/atomic.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/cheney-copy.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/debug.c
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/garbage-collection.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_prefix.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_state.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.c
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/profile.h
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/profiling.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/rusage.c
A   mlton/branches/on-20050822-x86_64-branch/runtime/gc/signals.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/statistics.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/thread.h

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

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile	2005-10-18 17:12:55 UTC (rev 4113)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile	2005-10-19 01:28:35 UTC (rev 4114)
@@ -107,6 +107,7 @@
 	dfs-mark.c							\
 	share.c								\
 	mark-compact.c							\
+	garbage-collection.c						\
 	assumptions.c							\
 	gc_suffix.c
 
@@ -131,8 +132,9 @@
 	sysvals.h							\
 	ratios.h							\
 	hash-cons.h							\
+	profiling.h							\
+	signals.h							\
 	gc_state.h							\
-	profile.h							\
 	gc_suffix.h
 
 all: gc.o gc-gdb.o

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/atomic.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/atomic.c	2005-10-18 17:12:55 UTC (rev 4113)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/atomic.c	2005-10-19 01:28:35 UTC (rev 4114)
@@ -14,6 +14,7 @@
 
 static inline void atomicEnd (GC_state s) {
   s->atomicState--;
-  if (0 == s->atomicState and s->signalIsPending)
+  if (0 == s->atomicState 
+      and s->signalsInfo.signalIsPending)
     s->limit = 0;
 }

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-18 17:12:55 UTC (rev 4113)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/cheney-copy.c	2005-10-19 01:28:35 UTC (rev 4114)
@@ -18,6 +18,7 @@
  * It also updates the crossMap.
  */
 struct forwardState {
+  bool amInMinorGC;
   pointer back;
   pointer toStart;
   pointer toLimit;
@@ -127,7 +128,7 @@
         fprintf (stderr, "forwarding weak "FMTPTR" ",
                  (uintptr_t)w);
       if (isObjptr (w->objptr)
-          and (not s->amInMinorGC
+          and (not forwardState.amInMinorGC
                or objptrIsInNursery (s, w->objptr))) {
         if (DEBUG_WEAK)
           fprintf (stderr, "linking\n");
@@ -193,6 +194,7 @@
   if (detailedGCTime (s))
     startTiming (&ru_start);
   s->cumulativeStatistics.numCopyingGCs++;
+  forwardState.amInMinorGC = FALSE;
   forwardState.toStart = s->secondaryHeap.start;
   forwardState.toLimit = s->secondaryHeap.start + s->secondaryHeap.size;
   if (DEBUG or s->controls.messages) {
@@ -360,7 +362,7 @@
       fprintf (stderr, "Minor copying GC.\n");
     if (detailedGCTime (s))
       startTiming (&ru_start);
-    s->amInMinorGC = TRUE;
+    forwardState.amInMinorGC = TRUE;
     forwardState.toStart = s->heap.start + s->heap.oldGenSize;
     if (DEBUG_GENERATIONAL)
       fprintf (stderr, "toStart = "FMTPTR"\n", (uintptr_t)forwardState.toStart);
@@ -381,7 +383,6 @@
     bytesCopied = forwardState.back - forwardState.toStart;
     s->cumulativeStatistics.bytesCopiedMinor += bytesCopied;
     s->heap.oldGenSize += bytesCopied;
-    s->amInMinorGC = FALSE;
     if (detailedGCTime (s))
       stopTiming (&ru_start, &s->cumulativeStatistics.ru_gcMinor);
     if (DEBUG_GENERATIONAL or s->controls.messages)

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/debug.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/debug.c	2005-10-18 17:12:55 UTC (rev 4113)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/debug.c	2005-10-19 01:28:35 UTC (rev 4114)
@@ -22,6 +22,7 @@
   DEBUG_PROFILE = FALSE,
   DEBUG_RESIZING = FALSE,
   DEBUG_SHARE = FALSE,
+  DEBUG_SIGNALS = FALSE,
   DEBUG_SIZE = FALSE,
   DEBUG_STACKS = FALSE,
   DEBUG_THREADS = FALSE,

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/garbage-collection.c (from rev 4113, mlton/branches/on-20050822-x86_64-branch/runtime/gc.c)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc.c	2005-10-18 17:12:55 UTC (rev 4113)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/garbage-collection.c	2005-10-19 01:28:35 UTC (rev 4114)
@@ -0,0 +1,284 @@
+/* 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 void minorGC (GC_state s) {
+  minorCheneyCopyGC (s);
+}
+
+static void majorGC (GC_state s, size_t bytesRequested, bool mayResize) {
+  uintmax_t numGCs;
+  size_t desiredSize;
+
+  s->cumulativeStatistics.numMinorGCs = 0;
+  numGCs = 
+    s->cumulativeStatistics.numCopyingGCs 
+    + s->cumulativeStatistics.numMarkCompactGCs;
+  if (0 < numGCs
+      and ((float)(s->cumulativeStatistics.numHashConsGCs) / (float)(numGCs)
+           < s->ratios.hashCons))
+    s->hashConsDuringGC = TRUE;
+  desiredSize = 
+    heapDesiredSize (s, s->lastMajorStatistics.bytesLive + bytesRequested, 0);
+  if ((not FORCE_MARK_COMPACT)
+      and not s->hashConsDuringGC // only markCompact can hash cons
+      and s->heap.size < s->sysvals.ram
+      and (not heapIsInit (&s->secondaryHeap)
+           or secondaryHeapCreate (s, desiredSize)))
+    majorCheneyCopyGC (s);
+  else
+    majorMarkCompactGC (s);
+  s->hashConsDuringGC = FALSE;
+  s->lastMajorStatistics.bytesLive = s->heap.oldGenSize;
+  if (s->lastMajorStatistics.bytesLive > s->cumulativeStatistics.maxBytesLive)
+    s->cumulativeStatistics.maxBytesLive = s->lastMajorStatistics.bytesLive;
+  /* Notice that the s->bytesLive below is different than the s->bytesLive
+   * used as an argument to heapAllocateSecondSemi above.  Above, it was 
+   * an estimate.  Here, it is exactly how much was live after the GC.
+   */
+  if (mayResize)
+    heapResize (s, s->lastMajorStatistics.bytesLive + bytesRequested);
+  secondaryHeapResize (s);
+  assert (s->heap.oldGenSize + bytesRequested <= s->heap.size);
+}
+
+static inline void enterGC (GC_state s) {
+  if (s->profilingInfo.isOn) {
+    /* We don't need to profileEnter for count profiling because it
+     * has already bumped the counter.  If we did allow the bump, then
+     * the count would look like function(s) had run an extra time.
+     */  
+    if (s->profilingInfo.stack
+        and not (PROFILE_COUNT == s->profilingInfo.kind))
+      GC_profileEnter (s);
+  }
+  s->amInGC = TRUE;
+}
+
+static inline void leaveGC (GC_state s) {
+  if (s->profilingInfo.isOn) {
+    if (s->profilingInfo.stack
+        and not (PROFILE_COUNT == s->profilingInfo.kind))
+      GC_profileLeave (s);
+  }
+  s->amInGC = FALSE;
+}
+
+static inline bool needGCTime (GC_state s) {
+  return 
+    DEBUG 
+    or s->controls.summary 
+    or s->controls.messages 
+    or s->rusageIsEnabled;
+}
+
+static void doGC (GC_state s, 
+                  size_t oldGenBytesRequested,
+                  size_t nurseryBytesRequested, 
+                  bool forceMajor,
+                  bool mayResize) {
+  uintmax_t gcTime;
+  bool stackTopOk;
+  size_t stackBytesRequested;
+  struct rusage ru_start;
+  size_t totalBytesRequested;
+        
+  enterGC (s);
+  if (DEBUG or s->controls.messages)
+    fprintf (stderr, "Starting gc.  Request %zu nursery bytes and %zu old gen bytes.\n",
+             /*uintToCommaString*/(nurseryBytesRequested),
+             /*uintToCommaString*/(oldGenBytesRequested));
+  assert (invariant (s));
+  if (needGCTime (s))
+    startTiming (&ru_start);
+  minorGC (s);
+  stackTopOk = mutatorStackInvariant (s);
+  stackBytesRequested = 
+    stackTopOk ? 0 : stackSizeTotalAligned (s, stackGrowSize (s));
+  totalBytesRequested = 
+    oldGenBytesRequested 
+    + nurseryBytesRequested
+    + stackBytesRequested;
+  if (forceMajor 
+      or totalBytesRequested > s->heap.size - s->heap.oldGenSize)
+    majorGC (s, totalBytesRequested, mayResize);
+  heapSetNursery (s, oldGenBytesRequested + stackBytesRequested, 
+                  nurseryBytesRequested);
+  assert (heapHasBytesFree (s, oldGenBytesRequested + stackBytesRequested,
+                            nurseryBytesRequested));
+  unless (stackTopOk)
+    stackGrow (s);
+  setCurrentStack (s);
+  if (needGCTime (s)) {
+    gcTime = stopTiming (&ru_start, &s->cumulativeStatistics.ru_gc);
+    s->cumulativeStatistics.maxPause = 
+      max (s->cumulativeStatistics.maxPause, gcTime);
+  } else
+    gcTime = 0;  /* Assign gcTime to quell gcc warning. */
+  if (DEBUG or s->controls.messages) {
+    fprintf (stderr, "Finished gc.\n");
+    fprintf (stderr, "time: %"PRIuMAX" ms\n", /*intToCommaString*/(gcTime));
+    fprintf (stderr, "old gen size: %zu bytes (%.1f%%)\n", 
+             /*intToCommaString*/(s->heap.oldGenSize),
+             100.0 * ((double)(s->heap.oldGenSize) 
+                      / (double)(s->heap.size)));
+  }
+  /* Send a GC signal. */
+  if (s->signalsInfo.gcSignalHandled
+      and s->signalHandlerThread != BOGUS_OBJPTR) {
+    if (DEBUG_SIGNALS)
+      fprintf (stderr, "GC Signal pending.\n");
+    s->signalsInfo.gcSignalPending = TRUE;
+    unless (s->signalsInfo.amInSignalHandler) 
+      s->signalsInfo.signalIsPending = TRUE;
+  }
+  if (DEBUG) 
+    displayGCState (s, stderr);
+  assert (heapHasBytesFree (s, oldGenBytesRequested, nurseryBytesRequested));
+  assert (invariant (s));
+  leaveGC (s);
+}
+
+static inline void ensureMutatorInvariant (GC_state s, bool force) {
+  if (force
+      or not (mutatorFrontierInvariant(s))
+      or not (mutatorStackInvariant(s))) {
+    /* This GC will grow the stack, if necessary. */
+    doGC (s, 0, currentThread(s)->bytesNeeded, force, TRUE);
+  }
+  assert (mutatorFrontierInvariant(s));
+  assert (mutatorStackInvariant(s));
+}
+
+/* ensureFree (s, b) ensures that upon return
+ *      b <= s->limitPlusSlop - s->frontier
+ */
+static inline void ensureFree (GC_state s, size_t bytesRequested) {
+  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));
+}
+
+static 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;
+  setCurrentStack (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;     
+}
+
+static inline 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, uint ensureBytesFree) { */
+/*         if (DEBUG_THREADS) */
+/*                 fprintf (stderr, "GC_switchToThread (0x%08x, %u)\n", (uint)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); */
+/*                 s->currentThread->bytesNeeded = ensureBytesFree; */
+/*                 switchToThread (s, t); */
+/*                 s->canHandle--; */
+/*                 maybeSwitchToHandler (s); */
+/*                 ensureMutatorInvariant (s, FALSE); */
+/*                 assert (mutatorFrontierInvariant(s)); */
+/*                 assert (mutatorStackInvariant(s)); */
+/*                 leave (s); */
+/*         } else { */
+/*                 /\* BEGIN: enter(s); *\/ */
+/*                 s->currentThread->stack->used = currentStackUsed (s); */
+/*                 s->currentThread->exnStack = s->exnStack; */
+/*                 atomicBegin (s); */
+/*                 /\* END: enter(s); *\/ */
+/*                 s->currentThread->bytesNeeded = ensureBytesFree; */
+/*                 switchToThread (s, t); */
+/*                 s->canHandle--; */
+/*                 maybeSwitchToHandler (s); */
+/*                 /\* BEGIN: ensureMutatorInvariant *\/ */
+/*                 if (not (mutatorFrontierInvariant(s)) */
+/*                         or not (mutatorStackInvariant(s))) { */
+/*                         /\* This GC will grow the stack, if necessary. *\/ */
+/*                         doGC (s, 0, s->currentThread->bytesNeeded, FALSE, TRUE); */
+/*                 }  */
+/*                 /\* END: ensureMutatorInvariant *\/ */
+/*                 /\* BEGIN: leave(s); *\/ */
+/*                 atomicEnd (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)
+    fprintf (stderr, "%s %d: GC_gc\n", file, line);
+  enter (s);
+  /* When the mutator requests zero bytes, it may actually need as
+   * much as LIMIT_SLOP.
+   */
+  if (0 == bytesRequested)
+    bytesRequested = LIMIT_SLOP;
+  currentThread(s)->bytesNeeded = bytesRequested;
+  maybeSwitchToHandler (s);
+  ensureMutatorInvariant (s, force);
+  assert (mutatorFrontierInvariant(s));
+  assert (mutatorStackInvariant(s));
+  leave (s);
+}

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_prefix.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_prefix.h	2005-10-18 17:12:55 UTC (rev 4113)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_prefix.h	2005-10-19 01:28:35 UTC (rev 4114)
@@ -1,2 +1,5 @@
 #ifndef _MLTON_GC_H_
 #define _MLTON_GC_H_
+
+struct GC_state;
+typedef struct GC_state *GC_state;

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-18 17:12:55 UTC (rev 4113)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_state.h	2005-10-19 01:28:35 UTC (rev 4114)
@@ -1,8 +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.
+ */
 
-typedef struct GC_state {
+struct GC_state {
   size_t alignment; /* */
   bool amInGC;
-  bool amInMinorGC;
   uint32_t atomicState;
   objptr callFromCHandlerThread; /* Handler for exported C calls (in heap). */
   bool canMinor; /* TRUE iff there is space for a minor gc. */
@@ -26,17 +32,19 @@
   GC_objectHashTable objectHashTable;
   GC_objectType *objectTypes; /* Array of object types. */
   uint32_t objectTypesLength; /* Cardinality of objectTypes array. */
+  struct GC_profilingInfo profilingInfo;
   uint32_t (*returnAddressToFrameIndex) (GC_returnAddress ra);
   struct GC_ratios ratios;
+  bool rusageIsEnabled;
   objptr savedThread; /* Result of GC_copyCurrentThread.
                        * Thread interrupted by arrival of signal.
                        */
   struct GC_heap secondaryHeap; /* Used for major copying collection. */
   objptr signalHandlerThread; /* Handler for signals (in heap). */
-  /*Bool*/bool signalIsPending;
+  struct GC_signalsInfo signalsInfo;
   pointer stackBottom; /* Bottom of stack in current thread. */
   pointer stackLimit; /* stackBottom + stackSize - maxFrameSize */
   pointer stackTop; /* Top of stack in current thread. */
   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/heap.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c	2005-10-18 17:12:55 UTC (rev 4113)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c	2005-10-19 01:28:35 UTC (rev 4114)
@@ -127,6 +127,17 @@
   return FALSE;
 }
 
+/* secondaryHeapCreate (s, desiredSize)
+ */
+static bool secondaryHeapCreate (GC_state s, size_t desiredSize) {
+  if ((s->controls.fixedHeap > 0 
+       and s->heap.size + desiredSize > s->controls.fixedHeap)
+      or (s->controls.maxHeap > 0 
+          and s->heap.size + desiredSize > s->controls.maxHeap))
+    return FALSE;
+  return heapCreate (s, &s->secondaryHeap, desiredSize, s->heap.oldGenSize);
+}
+
 /* heapRemap (s, h, desiredSize, minSize)
  */
 static bool heapRemap (GC_state s, GC_heap h, 
@@ -346,7 +357,7 @@
   size_t nurserySize;
 
   if (DEBUG_DETAILED)
-    fprintf (stderr, "setNursery(%zu, %zu)\n",
+    fprintf (stderr, "heapSetNursery(%zu, %zu)\n",
              /*uintToCommaString*/(oldGenBytesRequested),
              /*uintToCommaString*/(nurseryBytesRequested));
   h = &s->heap;
@@ -449,14 +460,3 @@
   assert (0 == s->secondaryHeap.size 
           or s->heap.size == s->secondaryHeap.size);
 }
-
-/* secondaryHeapCreate (s, desiredSize)
- */
-static bool secondaryHeapCreate (GC_state s, size_t desiredSize) {
-  if ((s->controls.fixedHeap > 0 
-       and s->heap.size + desiredSize > s->controls.fixedHeap)
-      or (s->controls.maxHeap > 0 
-          and s->heap.size + desiredSize > s->controls.maxHeap))
-    return FALSE;
-  return heapCreate (s, &s->secondaryHeap, desiredSize, s->heap.oldGenSize);
-}

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-18 17:12:55 UTC (rev 4113)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.c	2005-10-19 01:28:35 UTC (rev 4114)
@@ -81,6 +81,8 @@
   return TRUE;
 }
 
+#endif /* #if ASSERT */
+
 static bool mutatorFrontierInvariant (GC_state s) {
   GC_thread ct = currentThread(s);
   return (ct->bytesNeeded <= (size_t)(s->limitPlusSlop - s->frontier));
@@ -101,5 +103,3 @@
   assert (invariant (s));
   return TRUE;
 }
-
-#endif /* #if ASSERT */

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/profile.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/profile.h	2005-10-18 17:12:55 UTC (rev 4113)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/profile.h	2005-10-19 01:28:35 UTC (rev 4114)
@@ -6,18 +6,66 @@
  * See the file MLton-LICENSE for details.
  */
 
-void GC_profileAllocInc (GC_state s, size_t bytes);
+typedef enum {
+  PROFILE_ALLOC,
+  PROFILE_COUNT,
+  PROFILE_NONE,
+  PROFILE_TIME,
+} GC_profileKind;
 
-void GC_profileDone (GC_state s);
+typedef struct GC_source {
+  uint32_t nameIndex;
+  uint32_t successorsIndex;
+} *GC_source;
 
-void GC_profileEnter (GC_state s);
+typedef struct GC_sourceLabel {
+  pointer label;
+  uint32_t sourceSeqsIndex;
+} *GC_sourceLabel;
 
-// void GC_profileFree (GC_state s, GC_profile p);
 
-void GC_profileInc (GC_state s, size_t bytes);
+/* If profileStack, then there is one struct GC_profileStack for each
+ * function.
+ */
+typedef struct GC_profileStack {
+  /* ticks counts ticks while the function was on the stack. */
+  uintmax_t ticks;
+  /* ticksInGC counts ticks in GC while the function was on the stack. */
+  uintmax_t ticksInGC; 
+  /* lastTotal is the value of total when the oldest occurrence of f
+   * on the stack was pushed, i.e., the most recent time that
+   * numTimesOnStack changed from 0 to 1.  lastTotal is used to
+   * compute the amount to attribute to f when the oldest occurrence
+   * is finally popped.
+   */
+  uintmax_t lastTotal;
+  /* lastTotalGC is like lastTotal, but for GC ticks. */
+  uintmax_t lastTotalGC;
+  /* numOccurrences is the number of times this function is on the
+   * stack.
+   */
+  uintmax_t numOccurrences;
+} *GC_profileStack;
 
-void GC_profileLeave (GC_state s);
-
-// GC_profile GC_profileNew (GC_state s);
-
-// void GC_profileWrite (GC_state s, GC_profile p, int fd);
+/* GC_profile is used for both time and allocation profiling.
+ * In the comments below, "ticks" mean clock ticks with time profiling and
+ * bytes allocated with allocation profiling.
+ *
+ * All of the arrays in GC_profile are of length sourcesSize + sourceNamesSize.
+ * The first sourceSizes entries are for handling the duplicate copies of 
+ * functions, and the next sourceNamesSize entries are for the master versions.
+ */
+typedef struct GC_profile {
+  /* countTop is an array that counts for each function the number of
+   * ticks that occurred while the function was on top of the stack.
+   */
+  uintmax_t *countTop;
+  /* stack is an array that gives stack info for each function.  It is
+   * only used if profileStack.
+   */
+  struct GC_profileStack *stack;
+  /* The total number of mutator ticks. */
+  uintmax_t total;
+  /* The total number of GC ticks. */
+  uintmax_t totalGC;
+} *GC_profile;

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/profiling.h (from rev 4113, mlton/branches/on-20050822-x86_64-branch/runtime/gc/profile.h)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/profile.h	2005-10-18 17:12:55 UTC (rev 4113)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/profiling.h	2005-10-19 01:28:35 UTC (rev 4114)
@@ -0,0 +1,95 @@
+/* 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.
+ */
+
+typedef enum {
+  PROFILE_ALLOC,
+  PROFILE_COUNT,
+  PROFILE_NONE,
+  PROFILE_TIME,
+} GC_profileKind;
+
+typedef struct GC_source {
+  uint32_t nameIndex;
+  uint32_t successorsIndex;
+} *GC_source;
+
+typedef struct GC_sourceLabel {
+  pointer label;
+  uint32_t sourceSeqsIndex;
+} *GC_sourceLabel;
+
+
+/* If profileStack, then there is one struct GC_profileStack for each
+ * function.
+ */
+typedef struct GC_profileStack {
+  /* ticks counts ticks while the function was on the stack. */
+  uintmax_t ticks;
+  /* ticksInGC counts ticks in GC while the function was on the stack. */
+  uintmax_t ticksInGC; 
+  /* lastTotal is the value of total when the oldest occurrence of f
+   * on the stack was pushed, i.e., the most recent time that
+   * numTimesOnStack changed from 0 to 1.  lastTotal is used to
+   * compute the amount to attribute to f when the oldest occurrence
+   * is finally popped.
+   */
+  uintmax_t lastTotal;
+  /* lastTotalGC is like lastTotal, but for GC ticks. */
+  uintmax_t lastTotalGC;
+  /* numOccurrences is the number of times this function is on the
+   * stack.
+   */
+  uintmax_t numOccurrences;
+} *GC_profileStack;
+
+/* GC_profile is used for both time and allocation profiling.
+ * In the comments below, "ticks" mean clock ticks with time profiling and
+ * bytes allocated with allocation profiling.
+ *
+ * All of the arrays in GC_profile are of length sourcesSize + sourceNamesSize.
+ * The first sourceSizes entries are for handling the duplicate copies of 
+ * functions, and the next sourceNamesSize entries are for the master versions.
+ */
+typedef struct GC_profile {
+  /* countTop is an array that counts for each function the number of
+   * ticks that occurred while the function was on top of the stack.
+   */
+  uintmax_t *countTop;
+  /* stack is an array that gives stack info for each function.  It is
+   * only used if profileStack.
+   */
+  struct GC_profileStack *stack;
+  /* The total number of mutator ticks. */
+  uintmax_t total;
+  /* The total number of GC ticks. */
+  uintmax_t totalGC;
+} *GC_profile;
+
+struct GC_profilingInfo {
+  bool isOn;
+  GC_profile profile;
+  GC_profileKind kind;
+  bool stack;
+};
+
+
+void GC_profileAllocInc (GC_state s, size_t bytes);
+
+void GC_profileDone (GC_state s);
+
+void GC_profileEnter (GC_state s);
+
+void GC_profileFree (GC_state s, GC_profile p);
+
+void GC_profileInc (GC_state s, size_t bytes);
+
+void GC_profileLeave (GC_state s);
+
+GC_profile GC_profileNew (GC_state s);
+
+void GC_profileWrite (GC_state s, GC_profile p, int fd);

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.h	2005-10-18 17:12:55 UTC (rev 4113)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.h	2005-10-19 01:28:35 UTC (rev 4114)
@@ -14,6 +14,7 @@
   /* Minimum live ratio to use copying GC. */
   float copy; 
   float grow; 
+  float hashCons;
   /* Desired ratio of heap size to live data. */
   float live; 
   /* Minimum live ratio to us mark-compact GC. */

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/rusage.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/rusage.c	2005-10-18 17:12:55 UTC (rev 4113)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/rusage.c	2005-10-19 01:28:35 UTC (rev 4114)
@@ -77,7 +77,7 @@
   getrusage (RUSAGE_SELF, ru_start);
 }
 
-static uint stopTiming (struct rusage *ru_start, struct rusage *ru_gc) {
+static uintmax_t stopTiming (struct rusage *ru_start, struct rusage *ru_gc) {
   struct rusage ru_finish, ru_total;
 
   getrusage (RUSAGE_SELF, &ru_finish);

Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/signals.h (from rev 4113, mlton/branches/on-20050822-x86_64-branch/runtime/gc.h)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc.h	2005-10-18 17:12:55 UTC (rev 4113)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/signals.h	2005-10-19 01:28:35 UTC (rev 4114)
@@ -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.
+ */
+
+struct GC_signalsInfo {
+  bool amInSignalHandler;   /* TRUE iff a signal handler is running. */
+  bool gcSignalHandled;
+  bool gcSignalPending;
+  volatile bool signalIsPending; /* TRUE iff a signal has been received 
+                                  * but not handled by the mutator.
+                                  */
+  /* signalsHandled is the set of signals for which a mutator signal
+   * handler needs to run in order to handle the signal.
+   */
+  sigset_t signalsHandled;
+  /* The signals that have been recieved but not processed by the mutator
+   * signal handler.
+   */
+  sigset_t signalsPending;
+};

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-18 17:12:55 UTC (rev 4113)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/statistics.h	2005-10-19 01:28:35 UTC (rev 4114)
@@ -29,6 +29,7 @@
   uintmax_t numMarkCompactGCs;
   uintmax_t numMinorGCs;
 
+  uintmax_t maxPause;
   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. */

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/thread.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/thread.h	2005-10-18 17:12:55 UTC (rev 4113)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/thread.h	2005-10-19 01:28:35 UTC (rev 4114)
@@ -21,5 +21,3 @@
                           */
   objptr stack;          /* The stack for this thread. */
 } *GC_thread;
-
-#define BOGUS_THREAD (GC_thread)BOGUS_POINTER