[MLton-commit] r4108

Matthew Fluet MLton@mlton.org
Sat, 15 Oct 2005 18:46:10 -0700


Very preliminary mark-compact code
----------------------------------------------------------------------

U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_state.h
U   mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-compact.c

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

Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile	2005-10-16 00:47:35 UTC (rev 4107)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile	2005-10-16 01:46:06 UTC (rev 4108)
@@ -104,6 +104,7 @@
 	hash-cons.c							\
 	dfs-mark.c							\
 	share.c								\
+	mark-compact.c							\
 	assumptions.c							\
 	gc_suffix.c
 

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-16 00:47:35 UTC (rev 4107)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_state.h	2005-10-16 01:46:06 UTC (rev 4108)
@@ -16,6 +16,7 @@
   struct GC_generationalMaps generationalMaps;
   objptr *globals;
   uint32_t globalsLength;
+  /*Bool*/bool hashConsDuringGC;
   struct GC_heap heap;
   struct GC_lastMajorStatistics lastMajorStatistics;
   pointer limit; /* limit = heap.start + heap.totalBytes */

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