[MLton-commit] r4100
Matthew Fluet
MLton@mlton.org
Sun, 9 Oct 2005 18:54:40 -0700
Some reorganization; additional heap functions, including model agnostic heapCreate; ported Depth-First mark
----------------------------------------------------------------------
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/align.c
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.c
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.h
D mlton/branches/on-20050822-x86_64-branch/runtime/gc/array_defs.c
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/cheney-copy.c
D mlton/branches/on-20050822-x86_64-branch/runtime/gc/control.h
A mlton/branches/on-20050822-x86_64-branch/runtime/gc/controls.h
A mlton/branches/on-20050822-x86_64-branch/runtime/gc/dfs-mark.c
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/foreach.c
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.c
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.h
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_prefix.c
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_state.h
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/generational.c
A mlton/branches/on-20050822-x86_64-branch/runtime/gc/hash-cons.c
A mlton/branches/on-20050822-x86_64-branch/runtime/gc/hash-cons.h
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c
A mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap_predicates.c
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.c
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/major.h
A mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-compact.c
D mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-sweep.c
D mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-sweep.h
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.c
A mlton/branches/on-20050822-x86_64-branch/runtime/gc/model_predicates.c
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/new_object.c
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/object.c
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/object_size.c
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/pointer.c
A mlton/branches/on-20050822-x86_64-branch/runtime/gc/pointer_predicates.c
D mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.c
A mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios_predicates.c
A mlton/branches/on-20050822-x86_64-branch/runtime/gc/rusage.c
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack.c
A mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack_predicates.c
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/statistics.h
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.c
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.h
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/virtual-memory.c
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/virtual-memory.h
----------------------------------------------------------------------
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile 2005-10-10 01:54:23 UTC (rev 4100)
@@ -49,7 +49,7 @@
endif
CC = gcc -std=gnu99
-CWFLAGS = -pedantic -Wall -Wextra -Wno-unused-parameter \
+CWFLAGS = -pedantic -Wall -Wextra -Wno-unused-parameter -Wno-unused-function \
-Wformat-nonliteral \
-Wuninitialized -Winit-self \
-Wstrict-aliasing=2 \
@@ -77,25 +77,31 @@
debug.c \
align.c \
virtual-memory.c \
+ rusage.c \
+ pointer_predicates.c \
pointer.c \
+ model_predicates.c \
model.c \
object.c \
array.c \
object_size.c \
frame.c \
+ stack_predicates.c \
stack.c \
thread.c \
generational.c \
- heap.c \
+ heap_predicates.c \
+ heap.c \
gc_state.c \
new_object.c \
- ratios.c \
+ ratios_predicates.c \
current.c \
foreach.c \
atomic.c \
invariant.c \
enter_leave.c \
cheney-copy.c \
+ dfs-mark.c \
assumptions.c \
gc_suffix.c
@@ -116,10 +122,11 @@
major.h \
generational.h \
statistics.h \
- control.h \
+ controls.h \
sysvals.h \
ratios.h \
gc_state.h \
+ hash-cons.h \
profile.h \
gc_suffix.h
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/align.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/align.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/align.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -6,45 +6,64 @@
* See the file MLton-LICENSE for details.
*/
-static inline size_t roundDown (size_t a, size_t b) {
- return a - (a % b);
+static inline bool isAligned (size_t a, size_t b) {
+ return 0 == a % b;
}
+static inline size_t alignDown (size_t a, size_t b) {
+ assert (b >= 1);
+ a -= a % b;
+ assert (isAligned (a, b));
+ return a;
+}
+
static inline size_t align (size_t a, size_t b) {
assert (b >= 1);
a += b - 1;
a -= a % b;
+ assert (isAligned (a, b));
return a;
}
-static inline bool isAligned (size_t a, size_t b) {
- return 0 == a % b;
+static inline size_t pad (GC_state s, size_t bytes, size_t extra) {
+ return align (bytes + extra, s->alignment) - extra;
}
#if ASSERT
static inline bool isAlignedFrontier (GC_state s, pointer p) {
- return isAligned ((uintptr_t)p + GC_NORMAL_HEADER_SIZE,
+ return isAligned ((size_t)p + GC_NORMAL_HEADER_SIZE,
s->alignment);
}
-
-static inline bool isAlignedReserved (GC_state s, size_t reserved) {
- return isAligned (GC_STACK_HEADER_SIZE + sizeof (struct GC_stack) + reserved,
- s->alignment);
-}
#endif
-static inline size_t pad (GC_state s, size_t bytes, size_t extra) {
- return align (bytes + extra, s->alignment) - extra;
-}
-
static inline pointer alignFrontier (GC_state s, pointer p) {
- size_t bytes, res;
+ size_t res;
- bytes = (size_t) p;
res = pad (s, (size_t)p, GC_NORMAL_HEADER_SIZE);
+ if (DEBUG_STACKS)
+ fprintf (stderr, FMTPTR" = stackReserved ("FMTPTR")\n",
+ (uintptr_t)p, (uintptr_t)res);
+ assert (isAlignedFrontier (s, (pointer)res));
return (pointer)res;
}
pointer GC_alignFrontier (GC_state s, pointer p) {
return alignFrontier (s, p);
}
+
+#if ASSERT
+static inline bool isAlignedStackReserved (GC_state s, size_t reserved) {
+ return isAligned (GC_STACK_HEADER_SIZE + sizeof (struct GC_stack) + reserved,
+ s->alignment);
+}
+#endif
+
+static inline size_t alignStackReserved (GC_state s, size_t reserved) {
+ size_t res;
+
+ res = pad (s, reserved, GC_STACK_HEADER_SIZE + sizeof (struct GC_stack));
+ if (DEBUG_STACKS)
+ fprintf (stderr, "%zu = stackReserved (%zu)\n", res, reserved);
+ assert (isAlignedStackReserved (s, res));
+ return res;
+}
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -6,49 +6,19 @@
* See the file MLton-LICENSE for details.
*/
-#if ASSERT
-static inline pointer arrayIndexAtPointer (GC_state s,
- pointer a,
- uint32_t arrayIndex,
- uint32_t pointerIndex) {
- GC_header header;
- uint16_t numNonObjptrs;
- uint16_t numObjptrs;
- GC_objectTypeTag tag;
-
- header = getHeader (a);
- splitHeader(s, header, &tag, NULL, &numNonObjptrs, &numObjptrs);
- assert (tag == ARRAY_TAG);
-
- size_t nonObjptrBytesPerElement =
- numNonObjptrsToBytes(numNonObjptrs, ARRAY_TAG);
- size_t bytesPerElement =
- nonObjptrBytesPerElement
- + (numObjptrs * OBJPTR_SIZE);
-
- return a
- + arrayIndex * bytesPerElement
- + nonObjptrBytesPerElement
- + pointerIndex * OBJPTR_SIZE;
+/* getArrayCounterp (p)
+ *
+ * Returns a pointer to the counter for the array pointed to by p.
+ */
+static inline GC_arrayCounter* getArrayCounterp (pointer a) {
+ return (GC_arrayCounter*)(a - GC_HEADER_SIZE
+ - GC_ARRAY_LENGTH_SIZE - GC_ARRAY_COUNTER_SIZE);
}
-#endif
-/* The number of bytes in an array, not including the header. */
-static inline size_t arrayNumBytes (GC_state s,
- pointer p,
- uint16_t numNonObjptrs,
- uint16_t numObjptrs) {
- size_t bytesPerElement;
- GC_arrayLength numElements;
- size_t result;
-
- numElements = getArrayLength (p);
- bytesPerElement =
- numNonObjptrsToBytes(numNonObjptrs, ARRAY_TAG)
- + (numObjptrs * OBJPTR_SIZE);
- result = numElements * bytesPerElement;
- /* Empty arrays have OBJPTR_SIZE bytes for the forwarding pointer. */
- if (0 == result)
- result = OBJPTR_SIZE;
- return pad (s, result, GC_ARRAY_HEADER_SIZE);
+/* getArrayCounter (p)
+ *
+ * Returns the counter for the array pointed to by p.
+ */
+static inline GC_arrayCounter getArrayCounter (pointer a) {
+ return *(getArrayCounterp (a));
}
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.h 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/array.h 2005-10-10 01:54:23 UTC (rev 4100)
@@ -20,18 +20,20 @@
*/
typedef uint32_t GC_arrayLength;
#define GC_ARRAY_LENGTH_SIZE sizeof(GC_arrayLength)
+typedef GC_arrayLength GC_arrayCounter;
#define GC_ARRAY_COUNTER_SIZE GC_ARRAY_LENGTH_SIZE
#define GC_ARRAY_HEADER_SIZE (GC_ARRAY_COUNTER_SIZE + GC_ARRAY_LENGTH_SIZE + GC_HEADER_SIZE)
-/* getArrayNumElementsp (p)
+/* getArrayLengthp (p)
*
* Returns a pointer to the length for the array pointed to by p.
*/
static inline GC_arrayLength* getArrayLengthp (pointer a) {
- return (GC_arrayLength*)(a - GC_HEADER_SIZE - GC_ARRAY_LENGTH_SIZE);
+ return (GC_arrayLength*)(a - GC_HEADER_SIZE
+ - GC_ARRAY_LENGTH_SIZE);
}
-/* getArrayNumElements (p)
+/* getArrayLength (p)
*
* Returns the length for the array pointed to by p.
*/
Deleted: mlton/branches/on-20050822-x86_64-branch/runtime/gc/array_defs.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/array_defs.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/array_defs.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -1,54 +0,0 @@
-/* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
- * Jagannathan, and Stephen Weeks.
- * Copyright (C) 1997-2000 NEC Research Institute.
- *
- * MLton is released under a BSD-style license.
- * See the file MLton-LICENSE for details.
- */
-
-#if ASSERT
-static inline pointer arrayIndexAtPointer (GC_state s,
- pointer a,
- uint32_t arrayIndex,
- uint32_t pointerIndex) {
- GC_header header;
- uint16_t numNonObjptrs;
- uint16_t numObjptrs;
- GC_objectTypeTag tag;
-
- header = getHeader (a);
- splitHeader(s, header, &tag, NULL, &numNonObjptrs, &numObjptrs);
- assert (tag == ARRAY_TAG);
-
- size_t nonObjptrBytesPerElement =
- numNonObjptrsToBytes(numNonObjptrs, ARRAY_TAG);
- size_t bytesPerElement =
- nonObjptrBytesPerElement
- + (numObjptrs * OBJPTR_SIZE);
-
- return a
- + arrayIndex * bytesPerElement
- + nonObjptrBytesPerElement
- + pointerIndex * OBJPTR_SIZE;
-}
-#endif
-
-/* The number of bytes in an array, not including the header. */
-static inline size_t arrayNumBytes (GC_state s,
- pointer p,
- uint16_t numNonObjptrs,
- uint16_t numObjptrs) {
- size_t bytesPerElement;
- GC_arrayLength numElements;
- size_t result;
-
- numElements = getArrayLength (p);
- bytesPerElement =
- numNonObjptrsToBytes(numNonObjptrs, ARRAY_TAG)
- + (numObjptrs * OBJPTR_SIZE);
- result = numElements * bytesPerElement;
- /* Empty arrays have OBJPTR_SIZE bytes for the forwarding pointer. */
- if (0 == result)
- result = OBJPTR_SIZE;
- return pad (s, result, GC_ARRAY_HEADER_SIZE);
-}
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/cheney-copy.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/cheney-copy.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/cheney-copy.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -70,7 +70,7 @@
skip = 0;
} else if (ARRAY_TAG == tag) {
headerBytes = GC_ARRAY_HEADER_SIZE;
- objectBytes = arrayNumBytes (s, p, numNonObjptrs, numObjptrs);
+ objectBytes = arraySizeNoHeader (s, p, numNonObjptrs, numObjptrs);
skip = 0;
} else { /* Stack. */
GC_stack stack;
@@ -85,8 +85,8 @@
*/
if (stack->used <= stack->reserved / 4) {
size_t new =
- stackReserved (s, maxZ (stack->reserved / 2,
- stackNeedsReserved (s, stack)));
+ alignStackReserved
+ (s, max (stack->reserved / 2, stackMinimumReserved (s, stack)));
/* It's possible that new > stack->reserved if the stack
* invariant is violated. In that case, we want to leave the
* stack alone, because some other part of the gc will grow
@@ -96,17 +96,17 @@
if (new <= stack->reserved) {
stack->reserved = new;
if (DEBUG_STACKS)
- fprintf (stderr, "Shrinking stack to size %zd.\n",
+ fprintf (stderr, "Shrinking stack to size %zu.\n",
/*uintToCommaString*/(stack->reserved));
}
}
} else {
/* Shrink heap stacks. */
stack->reserved =
- stackReserved (s, maxZ((size_t)(s->ratios.threadShrink * stack->reserved),
- stack->used));
+ alignStackReserved
+ (s, max((size_t)(s->ratios.threadShrink * stack->reserved), stack->used));
if (DEBUG_STACKS)
- fprintf (stderr, "Shrinking stack to size %zd.\n",
+ fprintf (stderr, "Shrinking stack to size %zu.\n",
/*uintToCommaString*/(stack->reserved));
}
objectBytes = sizeof (struct GC_stack) + stack->used;
@@ -143,7 +143,7 @@
*(objptr*)p = pointerToObjptr(forwardState.back + headerBytes, forwardState.toStart);
/* Update the back of the queue. */
forwardState.back += size + skip;
- assert (isAligned ((uintptr_t)forwardState.back + GC_NORMAL_HEADER_SIZE,
+ assert (isAligned ((size_t)forwardState.back + GC_NORMAL_HEADER_SIZE,
s->alignment));
}
*opp = *(objptr*)p;
@@ -185,26 +185,22 @@
setCardMapAbsolute (s);
}
-/* static inline bool detailedGCTime (GC_state s) { */
-/* return s->summary; */
-/* } */
-
static void majorCheneyCopyGC (GC_state s) {
- // struct rusage ru_start;
+ struct rusage ru_start;
pointer toStart;
assert (s->secondaryHeap.size >= s->heap.oldGenSize);
-/* if (detailedGCTime (s)) */
-/* startTiming (&ru_start); */
+ if (detailedGCTime (s))
+ startTiming (&ru_start);
s->cumulativeStatistics.numCopyingGCs++;
forwardState.toStart = s->secondaryHeap.start;
forwardState.toLimit = s->secondaryHeap.start + s->secondaryHeap.size;
- if (DEBUG or s->messages) {
+ if (DEBUG or s->controls.messages) {
fprintf (stderr, "Major copying GC.\n");
- fprintf (stderr, "fromSpace = "FMTPTR" of size %zd\n",
+ fprintf (stderr, "fromSpace = "FMTPTR" of size %zu\n",
(uintptr_t) s->heap.start,
/*uintToCommaString*/(s->heap.size));
- fprintf (stderr, "toSpace = "FMTPTR" of size %zd\n",
+ fprintf (stderr, "toSpace = "FMTPTR" of size %zu\n",
(uintptr_t) s->secondaryHeap.start,
/*uintToCommaString*/(s->secondaryHeap.size));
}
@@ -223,14 +219,14 @@
s->secondaryHeap.oldGenSize = forwardState.back - s->secondaryHeap.start;
s->cumulativeStatistics.bytesCopied += s->secondaryHeap.oldGenSize;
if (DEBUG)
- fprintf (stderr, "%zd bytes live.\n",
+ fprintf (stderr, "%zu bytes live.\n",
/*uintToCommaString*/(s->secondaryHeap.oldGenSize));
swapHeaps (s);
clearCrossMap (s);
s->lastMajorStatistics.kind = GC_COPYING;
-/* if (detailedGCTime (s)) */
-/* stopTiming (&ru_start, &s->ru_gcCopy); */
- if (DEBUG or s->messages)
+ if (detailedGCTime (s))
+ stopTiming (&ru_start, &s->cumulativeStatistics.ru_gcCopy);
+ if (DEBUG or s->controls.messages)
fprintf (stderr, "Major copying GC done.\n");
}
@@ -346,7 +342,7 @@
static void minorGC (GC_state s) {
size_t bytesAllocated;
size_t bytesCopied;
- // struct rusage ru_start;
+ struct rusage ru_start;
if (DEBUG_GENERATIONAL)
fprintf (stderr, "minorGC nursery = "FMTPTR" frontier = "FMTPTR"\n",
@@ -360,10 +356,10 @@
s->heap.oldGenSize += bytesAllocated;
bytesCopied = 0;
} else {
- if (DEBUG_GENERATIONAL or s->messages)
+ if (DEBUG_GENERATIONAL or s->controls.messages)
fprintf (stderr, "Minor GC.\n");
-/* if (detailedGCTime (s)) */
-/* startTiming (&ru_start); */
+ if (detailedGCTime (s))
+ startTiming (&ru_start);
s->amInMinorGC = TRUE;
forwardState.toStart = s->heap.start + s->heap.oldGenSize;
if (DEBUG_GENERATIONAL)
@@ -386,10 +382,10 @@
s->cumulativeStatistics.bytesCopiedMinor += bytesCopied;
s->heap.oldGenSize += bytesCopied;
s->amInMinorGC = FALSE;
-/* if (detailedGCTime (s)) */
-/* stopTiming (&ru_start, &s->ru_gcMinor); */
- if (DEBUG_GENERATIONAL or s->messages)
- fprintf (stderr, "Minor GC done. %zd bytes copied.\n",
+ if (detailedGCTime (s))
+ stopTiming (&ru_start, &s->cumulativeStatistics.ru_gcMinor);
+ if (DEBUG_GENERATIONAL or s->controls.messages)
+ fprintf (stderr, "Minor GC done. %zu bytes copied.\n",
/*uintToCommaString*/(bytesCopied));
}
}
Deleted: mlton/branches/on-20050822-x86_64-branch/runtime/gc/control.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/control.h 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/control.h 2005-10-10 01:54:23 UTC (rev 4100)
@@ -1,12 +0,0 @@
-/* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
- * Jagannathan, and Stephen Weeks.
- * Copyright (C) 1997-2000 NEC Research Institute.
- *
- * MLton is released under a BSD-style license.
- * See the file MLton-LICENSE for details.
- */
-
-struct GC_control {
- size_t fixedHeap; /* If 0, then no fixed heap. */
- size_t maxHeap; /* if zero, then unlimited, else limit total heap */
-};
Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/controls.h (from rev 4098, mlton/branches/on-20050822-x86_64-branch/runtime/gc/control.h)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/control.h 2005-10-08 20:36:15 UTC (rev 4098)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/controls.h 2005-10-10 01:54:23 UTC (rev 4100)
@@ -0,0 +1,14 @@
+/* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
+ * Jagannathan, and Stephen Weeks.
+ * Copyright (C) 1997-2000 NEC Research Institute.
+ *
+ * MLton is released under a BSD-style license.
+ * See the file MLton-LICENSE for details.
+ */
+
+struct GC_controls {
+ size_t fixedHeap; /* If 0, then no fixed heap. */
+ size_t maxHeap; /* if zero, then unlimited, else limit total heap */
+ bool messages;
+ bool summary;
+};
Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/dfs-mark.c (from rev 4097, mlton/branches/on-20050822-x86_64-branch/runtime/gc.c)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc.c 2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/dfs-mark.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -0,0 +1,362 @@
+/* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
+ * Jagannathan, and Stephen Weeks.
+ * Copyright (C) 1997-2000 NEC Research Institute.
+ *
+ * MLton is released under a BSD-style license.
+ * See the file MLton-LICENSE for details.
+ */
+
+/* ---------------------------------------------------------------- */
+/* Depth-first Marking */
+/* ---------------------------------------------------------------- */
+
+typedef enum {
+ MARK_MODE,
+ UNMARK_MODE,
+} GC_markMode;
+
+static inline bool isMarked (pointer p) {
+ return MARK_MASK & getHeader (p);
+}
+
+static bool isMarkedMode (GC_markMode m, pointer p) {
+ switch (m) {
+ case MARK_MODE:
+ return isMarked (p);
+ case UNMARK_MODE:
+ return not isMarked (p);
+ default:
+ die ("bad mark mode %u", m);
+ }
+}
+
+#if ASSERT
+static inline pointer arrayIndexAtPointer (GC_state s,
+ pointer a,
+ GC_arrayCounter arrayIndex,
+ uint32_t pointerIndex) {
+ GC_header header;
+ uint16_t numNonObjptrs;
+ uint16_t numObjptrs;
+ GC_objectTypeTag tag;
+
+ header = getHeader (a);
+ splitHeader(s, header, &tag, NULL, &numNonObjptrs, &numObjptrs);
+ assert (tag == ARRAY_TAG);
+
+ size_t nonObjptrBytesPerElement =
+ numNonObjptrsToBytes(numNonObjptrs, ARRAY_TAG);
+ size_t bytesPerElement =
+ nonObjptrBytesPerElement
+ + (numObjptrs * OBJPTR_SIZE);
+
+ return a
+ + arrayIndex * bytesPerElement
+ + nonObjptrBytesPerElement
+ + pointerIndex * OBJPTR_SIZE;
+}
+#endif
+
+/* mark (s, r, m, shc)
+ *
+ * Sets all the mark bits in the object graph pointed to by r.
+ *
+ * If m is MARK_MODE, it sets the bits to 1.
+ * If m is UNMARK_MODE, it sets the bits to 0.
+ *
+ * If shc, it hash-conses the objects marked.
+ *
+ * It returns the total size in bytes of the objects marked.
+ */
+size_t mark (GC_state s, pointer root,
+ GC_markMode mode, bool shouldHashCons) {
+ GC_header mark; /* Used to set or clear the mark bit. */
+ size_t size; /* Total number of bytes marked. */
+ pointer cur; /* The current object being marked. */
+ pointer prev; /* The previous object on the mark stack. */
+ pointer next; /* The next object to mark. */
+ pointer todo; /* A pointer to the pointer in cur to next. */
+ GC_header header;
+ GC_header* headerp;
+ uint16_t numNonObjptrs;
+ uint16_t numObjptrs;
+ GC_objectTypeTag tag;
+ uint32_t index; /* The i'th pointer in the object (element) being marked. */
+ GC_header nextHeader;
+ GC_header* nextHeaderp;
+ GC_arrayCounter arrayIndex;
+ pointer top; /* The top of the next stack frame to mark. */
+ GC_returnAddress returnAddress;
+ GC_frameLayout *frameLayout;
+ GC_frameOffsets frameOffsets;
+
+ if (isMarkedMode (mode, root))
+ /* Object has already been marked. */
+ return 0;
+ mark = (MARK_MODE == mode) ? MARK_MASK : 0;
+ size = 0;
+ cur = root;
+ prev = NULL;
+ headerp = getHeaderp (cur);
+ header = *headerp;
+ goto mark;
+markNext:
+ /* cur is the object that was being marked.
+ * prev is the mark stack.
+ * next is the unmarked object to be marked.
+ * nextHeaderp points to the header of next.
+ * nextHeader is the header of next.
+ * todo is a pointer to the pointer inside cur that points to next.
+ */
+ if (DEBUG_MARK_COMPACT)
+ fprintf (stderr,
+ "markNext"
+ " cur = "FMTPTR" next = "FMTPTR
+ " prev = "FMTPTR" todo = "FMTPTR"\n",
+ (uintptr_t)cur, (uintptr_t)next,
+ (uintptr_t)prev, (uintptr_t)todo);
+ assert (not isMarkedMode (mode, next));
+ assert (nextHeaderp == getHeaderp (next));
+ assert (nextHeader == getHeader (next));
+ // assert (*(pointer*) todo == next);
+ assert (fetchObjptrFromPointer (todo, s->heap.start) == next);
+ headerp = nextHeaderp;
+ header = nextHeader;
+ // *(pointer*)todo = prev;
+ storeObjptrFromPointer (todo, prev, s->heap.start);
+ prev = cur;
+ cur = next;
+mark:
+ if (DEBUG_MARK_COMPACT)
+ fprintf (stderr, "mark cur = "FMTPTR" prev = "FMTPTR" mode = %s\n",
+ (uintptr_t)cur, (uintptr_t)prev,
+ (mode == MARK_MODE) ? "mark" : "unmark");
+ /* cur is the object to mark.
+ * prev is the mark stack.
+ * headerp points to the header of cur.
+ * header is the header of cur.
+ */
+ assert (not isMarkedMode (mode, cur));
+ assert (header == getHeader (cur));
+ assert (headerp == getHeaderp (cur));
+ header ^= MARK_MASK;
+ /* Store the mark. In the case of an object that contains a pointer to
+ * itself, it is essential that we store the marked header before marking
+ * the internal pointers (markInNormal below). If we didn't, then we
+ * would see the object as unmarked and traverse it again.
+ */
+ *headerp = header;
+ splitHeader (s, header, &tag, NULL, &numNonObjptrs, &numObjptrs);
+ if (NORMAL_TAG == tag) {
+ size +=
+ GC_NORMAL_HEADER_SIZE
+ + numNonObjptrsToBytes (numNonObjptrs, tag)
+ + (numObjptrs * OBJPTR_SIZE);
+ if (0 == numObjptrs) {
+ /* There is nothing to mark. */
+normalDone:
+ if (shouldHashCons)
+ cur = hashCons (s, cur, TRUE);
+ goto ret;
+ }
+ todo = cur + numNonObjptrsToBytes (numNonObjptrs, NORMAL_TAG);
+ index = 0;
+markInNormal:
+ if (DEBUG_MARK_COMPACT)
+ fprintf (stderr, "markInNormal index = %d\n", index);
+ assert (index < numObjptrs);
+ // next = *(pointer*)todo;
+ next = fetchObjptrToPointer (todo, s->heap.start);
+ if (not isPointer (next)) {
+markNextInNormal:
+ assert (index < numObjptrs);
+ index++;
+ if (index == numObjptrs) {
+ /* Done. Clear out the counters and return. */
+ *headerp = header & ~COUNTER_MASK;
+ goto normalDone;
+ }
+ todo += OBJPTR_SIZE;
+ goto markInNormal;
+ }
+ nextHeaderp = getHeaderp (next);
+ nextHeader = *nextHeaderp;
+ if (mark == (nextHeader & MARK_MASK)) {
+ maybeShareObjptr (s, (objptr*)todo, shouldHashCons);
+ goto markNextInNormal;
+ }
+ *headerp = (header & ~COUNTER_MASK) | (index << COUNTER_SHIFT);
+ goto markNext;
+ } else if (WEAK_TAG == tag) {
+ /* Store the marked header and don't follow any pointers. */
+ goto ret;
+ } else if (ARRAY_TAG == tag) {
+ /* When marking arrays:
+ * arrayIndex is the index of the element to mark.
+ * cur is the pointer to the array.
+ * index is the index of the pointer within the element
+ * (i.e. the i'th pointer is at index i).
+ * todo is the start of the element.
+ */
+ size +=
+ GC_ARRAY_HEADER_SIZE
+ + arraySizeNoHeader (s, cur, numNonObjptrs, numObjptrs);
+ if (0 == numObjptrs or 0 == getArrayLength (cur)) {
+ /* There is nothing to mark. */
+arrayDone:
+ if (shouldHashCons)
+ cur = hashCons (s, cur, TRUE);
+ goto ret;
+ }
+ /* Begin marking first element. */
+ arrayIndex = 0;
+ todo = cur;
+markArrayElt:
+ assert (arrayIndex < getArrayLength (cur));
+ index = 0;
+ /* Skip to the first pointer. */
+ todo += numNonObjptrsToBytes (numNonObjptrs, ARRAY_TAG);
+markInArray:
+ if (DEBUG_MARK_COMPACT)
+ fprintf (stderr, "markInArray arrayIndex = %u index = %u\n",
+ arrayIndex, index);
+ assert (arrayIndex < getArrayLength (cur));
+ assert (index < numObjptrs);
+ assert (todo == arrayIndexAtPointer (s, cur, arrayIndex, index));
+ // next = *(pointer*)todo;
+ next = fetchObjptrToPointer (todo, s->heap.start);
+ if (not (isPointer(next))) {
+markNextInArray:
+ assert (arrayIndex < getArrayLength (cur));
+ assert (index < numObjptrs);
+ assert (todo == arrayIndexAtPointer (s, cur, arrayIndex, index));
+ todo += OBJPTR_SIZE;
+ index++;
+ if (index < numObjptrs)
+ goto markInArray;
+ arrayIndex++;
+ if (arrayIndex < getArrayLength (cur))
+ goto markArrayElt;
+ /* Done. Clear out the counters and return. */
+ *getArrayCounterp (cur) = 0;
+ *headerp = header & ~COUNTER_MASK;
+ goto arrayDone;
+ }
+ nextHeaderp = getHeaderp (next);
+ nextHeader = *nextHeaderp;
+ if (mark == (nextHeader & MARK_MASK)) {
+ maybeShareObjptr (s, (objptr*)todo, shouldHashCons);
+ goto markNextInArray;
+ }
+ /* Recur and mark next. */
+ *getArrayCounterp (cur) = arrayIndex;
+ *headerp = (header & ~COUNTER_MASK) | (index << COUNTER_SHIFT);
+ goto markNext;
+ } else {
+ assert (STACK_TAG == tag);
+ size +=
+ GC_STACK_HEADER_SIZE
+ + sizeof (struct GC_stack) + ((GC_stack)cur)->reserved;
+ top = stackTop (s, (GC_stack)cur);
+ assert (((GC_stack)cur)->used <= ((GC_stack)cur)->reserved);
+markInStack:
+ /* Invariant: top points just past the return address of the frame
+ * to be marked.
+ */
+ assert (stackBottom (s, (GC_stack)cur) <= top);
+ if (DEBUG_MARK_COMPACT)
+ fprintf (stderr, "markInStack top = %zu\n",
+ (size_t)(top - stackBottom (s, (GC_stack)cur)));
+ if (top == stackBottom (s, (GC_stack)(cur)))
+ goto ret;
+ index = 0;
+ returnAddress = *(GC_returnAddress*) (top - GC_RETURNADDRESS_SIZE);
+ frameLayout = getFrameLayoutFromReturnAddress (s, returnAddress);
+ frameOffsets = frameLayout->offsets;
+ ((GC_stack)cur)->markTop = top;
+markInFrame:
+ if (index == frameOffsets [0]) {
+ top -= frameLayout->size;
+ goto markInStack;
+ }
+ todo = top - frameLayout->size + frameOffsets [index + 1];
+ // next = *(pointer*)todo;
+ next = fetchObjptrToPointer (todo, s->heap.start);
+ if (DEBUG_MARK_COMPACT)
+ fprintf (stderr,
+ " offset %u todo "FMTPTR" next = "FMTPTR"\n",
+ frameOffsets [index + 1],
+ (uintptr_t)todo, (uintptr_t)next);
+ if (not isPointer (next)) {
+ index++;
+ goto markInFrame;
+ }
+ nextHeaderp = getHeaderp (next);
+ nextHeader = *nextHeaderp;
+ if (mark == (nextHeader & MARK_MASK)) {
+ index++;
+ maybeShareObjptr (s, (objptr*)todo, shouldHashCons);
+ goto markInFrame;
+ }
+ ((GC_stack)cur)->markIndex = index;
+ goto markNext;
+ }
+ assert (FALSE);
+ret:
+ /* Done marking cur, continue with prev.
+ * Need to set the pointer in the prev object that pointed to cur
+ * to point back to prev, and restore prev.
+ */
+ if (DEBUG_MARK_COMPACT)
+ fprintf (stderr, "return cur = "FMTPTR" prev = "FMTPTR"\n",
+ (uintptr_t)cur, (uintptr_t)prev);
+ assert (isMarkedMode (mode, cur));
+ if (NULL == prev)
+ return size;
+ next = cur;
+ cur = prev;
+ headerp = getHeaderp (cur);
+ header = *headerp;
+ splitHeader (s, header, &tag, NULL, &numNonObjptrs, &numObjptrs);
+ /* It's impossible to get a WEAK_TAG here, since we would never
+ * follow the weak object pointer.
+ */
+ assert (WEAK_TAG != tag);
+ if (NORMAL_TAG == tag) {
+ todo = cur + numNonObjptrsToBytes (numNonObjptrs, tag);
+ index = (header & COUNTER_MASK) >> COUNTER_SHIFT;
+ todo += index * OBJPTR_SIZE;
+ // prev = *(pointer*)todo;
+ prev = fetchObjptrToPointer (todo, s->heap.start);
+ // *(pointer*)todo = next;
+ storeObjptrFromPointer (todo, next, s->heap.start);
+ goto markNextInNormal;
+ } else if (ARRAY_TAG == tag) {
+ arrayIndex = getArrayCounter (cur);
+ todo = cur + arrayIndex * (numNonObjptrsToBytes (numNonObjptrs, ARRAY_TAG)
+ + (numObjptrs * OBJPTR_SIZE));
+ index = (header & COUNTER_MASK) >> COUNTER_SHIFT;
+ todo += numNonObjptrsToBytes (numNonObjptrs, ARRAY_TAG) + index * OBJPTR_SIZE;
+ // prev = *(pointer*)todo;
+ prev = fetchObjptrToPointer (todo, s->heap.start);
+ // *(pointer*)todo = next;
+ storeObjptrFromPointer (todo, next, s->heap.start);
+ goto markNextInArray;
+ } else {
+ assert (STACK_TAG == tag);
+ index = ((GC_stack)cur)->markIndex;
+ top = ((GC_stack)cur)->markTop;
+ /* Invariant: top points just past a "return address". */
+ returnAddress = *(GC_returnAddress*) (top - GC_RETURNADDRESS_SIZE);
+ frameLayout = getFrameLayoutFromReturnAddress (s, returnAddress);
+ frameOffsets = frameLayout->offsets;
+ todo = top - frameLayout->size + frameOffsets [index + 1];
+ // prev = *(pointer*)todo;
+ prev = fetchObjptrToPointer (todo, s->heap.start);
+ // *(pointer*)todo = next;
+ storeObjptrFromPointer (todo, next, s->heap.start);
+ index++;
+ goto markInFrame;
+ }
+ assert (FALSE);
+}
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/foreach.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/foreach.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/foreach.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -196,7 +196,7 @@
assert (front <= b);
while (front < b) {
while (front < b) {
- assert (isAligned ((uintptr_t)front, GC_MODEL_MINALIGN));
+ assert (isAligned ((size_t)front, GC_MODEL_MINALIGN));
if (DEBUG_DETAILED)
fprintf (stderr,
" front = "FMTPTR" *back = "FMTPTR"\n",
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -6,24 +6,24 @@
* See the file MLton-LICENSE for details.
*/
-static inline uint32_t
+static inline GC_frameIndex
getFrameIndexFromReturnAddress (GC_state s, GC_returnAddress ra) {
- uint32_t res;
+ GC_frameIndex res;
res = s->returnAddressToFrameIndex (ra);
if (DEBUG_DETAILED)
- fprintf (stderr, "%"PRIu32" = getFrameIndexFromReturnAddress ("FMTRA")\n",
+ fprintf (stderr, FMTFI" = getFrameIndexFromReturnAddress ("FMTRA")\n",
res, ra);
return res;
}
static inline GC_frameLayout *
-getFrameLayoutFromFrameIndex (GC_state s, uint32_t index) {
+getFrameLayoutFromFrameIndex (GC_state s, GC_frameIndex index) {
GC_frameLayout *layout;
if (DEBUG_DETAILED)
fprintf (stderr,
- "index = %"PRIu32
+ "index = "FMTFI
" frameLayoutsLength = %"PRIu32"\n",
index, s->frameLayoutsLength);
assert (index < s->frameLayoutsLength);
@@ -35,7 +35,7 @@
static inline GC_frameLayout *
getFrameLayoutFromReturnAddress (GC_state s, GC_returnAddress ra) {
GC_frameLayout *layout;
- uint32_t index;
+ GC_frameIndex index;
index = getFrameIndexFromReturnAddress (s, ra);
layout = getFrameLayoutFromFrameIndex(s, index);
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.h 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/frame.h 2005-10-10 01:54:23 UTC (rev 4100)
@@ -37,6 +37,9 @@
uint16_t size;
GC_frameOffsets offsets;
} GC_frameLayout;
+typedef uint32_t GC_frameIndex;
+#define PRIFI PRIu32
+#define FMTFI "%"PRIFI
typedef uintptr_t GC_returnAddress;
#define GC_RETURNADDRESS_SIZE sizeof(GC_returnAddress)
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_prefix.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_prefix.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_prefix.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -1,9 +1,5 @@
#include "gc.h"
-static inline size_t maxZ (size_t x, size_t y) {
- return ((x < y) ? x : y);
-}
-
static inline size_t meg (size_t n) {
return n / (1024ul * 1024ul);
}
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_state.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_state.h 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/gc_state.h 2005-10-10 01:54:23 UTC (rev 4100)
@@ -6,7 +6,7 @@
uint32_t atomicState;
objptr callFromCHandlerThread; /* Handler for exported C calls (in heap). */
bool canMinor; /* TRUE iff there is space for a minor gc. */
- struct GC_control control;
+ struct GC_controls controls;
struct GC_cumulativeStatistics cumulativeStatistics;
objptr currentThread; /* Currently executing thread (in heap). */
uint32_t exnStack;
@@ -21,11 +21,9 @@
pointer limit; /* limit = heap.start + heap.totalBytes */
pointer limitPlusSlop; /* limit + LIMIT_SLOP */
uint32_t maxFrameSize;
- /*Bool*/bool messages; /* Print a message at the start and end of each gc. */
/*Bool*/bool mutatorMarksCards;
GC_objectType *objectTypes; /* Array of object types. */
uint32_t objectTypesLength; /* Cardinality of objectTypes array. */
- size_t pageSize;
uint32_t (*returnAddressToFrameIndex) (GC_returnAddress ra);
struct GC_ratios ratios;
objptr savedThread; /* Result of GC_copyCurrentThread.
@@ -37,7 +35,6 @@
pointer stackBottom; /* Bottom of stack in current thread. */
pointer stackLimit; /* stackBottom + stackSize - maxFrameSize */
pointer stackTop; /* Top of stack in current thread. */
- /*Bool*/bool summary; /* Print a summary of gc info when program exits. */
struct GC_sysvals sysvals;
GC_weak weaks; /* Linked list of (live) weak pointers */
} *GC_state;
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/generational.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/generational.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/generational.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -8,6 +8,34 @@
#define CROSS_MAP_EMPTY ((GC_crossMapElem)255)
+void displayGenerationalMaps (__attribute__ ((unused)) GC_state s,
+ struct GC_generationalMaps *generational,
+ FILE *stream) {
+ fprintf(stream,
+ "\t\tcardMap ="FMTPTR"\n"
+ "\t\tcardMapAbsolute = "FMTPTR"\n"
+ "\t\tcardMapLength = %zu\n"
+ "\t\tcrossMap = "FMTPTR"\n"
+ "\t\tcrossMapLength = %zu\n"
+ "\t\tcrossMapValidSize = %zu\n",
+ (uintptr_t)generational->cardMap,
+ (uintptr_t)generational->cardMapAbsolute,
+ generational->cardMapLength,
+ (uintptr_t)generational->crossMap,
+ generational->crossMapLength,
+ generational->crossMapValidSize);
+ if (DEBUG_GENERATIONAL and DEBUG_DETAILED) {
+ unsigned int i;
+
+ fprintf (stderr, "crossMap trues\n");
+ for (i = 0; i < generational->crossMapLength; ++i)
+ unless (CROSS_MAP_EMPTY == generational->crossMap[i])
+ fprintf (stderr, "\t%u\n", i);
+ fprintf (stderr, "\n");
+ }
+}
+
+
static inline uintptr_t pointerToCardIndex (pointer p) {
return (uintptr_t)p >> CARD_SIZE_LOG2;
}
@@ -84,21 +112,21 @@
size_t totalMapSize;
cardMapLength = sizeToCardIndex (s->heap.size);
- cardMapSize = align (cardMapLength * CARD_MAP_ELEM_SIZE, s->pageSize);
+ cardMapSize = align (cardMapLength * CARD_MAP_ELEM_SIZE, s->sysvals.pageSize);
cardMapLength = cardMapSize / CARD_MAP_ELEM_SIZE;
s->generationalMaps.cardMapLength = cardMapLength;
crossMapLength = sizeToCardIndex (s->heap.size);
- crossMapSize = align (crossMapLength * CROSS_MAP_ELEM_SIZE, s->pageSize);
+ crossMapSize = align (crossMapLength * CROSS_MAP_ELEM_SIZE, s->sysvals.pageSize);
crossMapLength = crossMapSize / CROSS_MAP_ELEM_SIZE;
s->generationalMaps.crossMapLength = crossMapLength;
totalMapSize = cardMapSize + crossMapSize;
if (DEBUG_MEM)
- fprintf (stderr, "Creating card/cross map of size %zd\n",
+ fprintf (stderr, "Creating card/cross map of size %zu\n",
/*uintToCommaString*/(totalMapSize));
s->generationalMaps.cardMap =
- GC_mmapAnon (totalMapSize);
+ GC_mmapAnon_safe (NULL, totalMapSize);
s->generationalMaps.crossMap =
(GC_crossMapElem*)((pointer)s->generationalMaps.cardMap + cardMapSize);
if (DEBUG_CARD_MARKING)
@@ -140,7 +168,7 @@
if (DEBUG)
fprintf (stderr, "crossMapIsOK ()\n");
mapSize = s->generationalMaps.crossMapLength * CROSS_MAP_ELEM_SIZE;
- map = GC_mmapAnon (mapSize);
+ map = GC_mmapAnon_safe (NULL, mapSize);
memset (map, CROSS_MAP_EMPTY, mapSize);
back = s->heap.start + s->heap.oldGenSize;
cardIndex = 0;
@@ -216,7 +244,7 @@
static inline void resizeCardMapAndCrossMap (GC_state s) {
if (s->mutatorMarksCards
and (s->generationalMaps.cardMapLength * CARD_MAP_ELEM_SIZE)
- != align (sizeToCardIndex (s->heap.size), s->pageSize)) {
+ != align (sizeToCardIndex (s->heap.size), s->sysvals.pageSize)) {
GC_cardMapElem *oldCardMap;
size_t oldCardMapSize;
GC_crossMapElem *oldCrossMap;
@@ -235,30 +263,3 @@
GC_munmap (oldCardMap, oldCardMapSize + oldCrossMapSize);
}
}
-
-void displayGenerationalMaps (__attribute__ ((unused)) GC_state s,
- struct GC_generationalMaps *generational,
- FILE *stream) {
- fprintf(stream,
- "\t\tcardMap ="FMTPTR"\n"
- "\t\tcardMapAbsolute = "FMTPTR"\n"
- "\t\tcardMapLength = %zu\n"
- "\t\tcrossMap = "FMTPTR"\n"
- "\t\tcrossMapLength = %zu\n"
- "\t\tcrossMapValidSize = %zu\n",
- (uintptr_t)generational->cardMap,
- (uintptr_t)generational->cardMapAbsolute,
- generational->cardMapLength,
- (uintptr_t)generational->crossMap,
- generational->crossMapLength,
- generational->crossMapValidSize);
- if (DEBUG_GENERATIONAL and DEBUG_DETAILED) {
- unsigned int i;
-
- fprintf (stderr, "crossMap trues\n");
- for (i = 0; i < generational->crossMapLength; ++i)
- unless (CROSS_MAP_EMPTY == generational->crossMap[i])
- fprintf (stderr, "\t%u\n", i);
- fprintf (stderr, "\n");
- }
-}
Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/hash-cons.c (from rev 4097, mlton/branches/on-20050822-x86_64-branch/runtime/gc.c)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc.c 2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/hash-cons.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -0,0 +1,301 @@
+/* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
+ * Jagannathan, and Stephen Weeks.
+ * Copyright (C) 1997-2000 NEC Research Institute.
+ *
+ * MLton is released under a BSD-style license.
+ * See the file MLton-LICENSE for details.
+ */
+
+/* ---------------------------------------------------------------- */
+/* Object hash consing */
+/* ---------------------------------------------------------------- */
+
+/* Hashing based on Introduction to Algorithms by Cormen, Leiserson, and Rivest.
+ * Section numbers in parens.
+ * k is key to be hashed.
+ * table is of size 2^p (it must be a power of two)
+ * Open addressing (12.4), meaning that we stick the entries directly in the
+ * table and probe until we find what we want.
+ * Multiplication method (12.3.2), meaning that we compute the hash by
+ * multiplying by a magic number, chosen by Knuth, and take the high-order p
+ * bits of the low order 32 bits.
+ * Double hashing (12.4), meaning that we use two hash functions, the first to
+ * decide where to start looking and a second to decide at what offset to
+ * probe. The second hash must be relatively prime to the table size, which
+ * we ensure by making it odd and keeping the table size as a power of 2.
+ */
+
+static GC_ObjectHashTable newTable (GC_state s) {
+ int i;
+ uint maxElementsSize;
+ pointer regionStart;
+ pointer regionEnd;
+ GC_ObjectHashTable t;
+
+ NEW (GC_ObjectHashTable, t);
+ // Try to use space in the heap for the elements.
+ if (not (heapIsInit (&s->heap2))) {
+ if (DEBUG_SHARE)
+ fprintf (stderr, "using heap2\n");
+ // We have all of heap2 available. Use it.
+ regionStart = s->heap2.start;
+ regionEnd = s->heap2.start + s->heap2.size;
+ } else if (s->amInGC or not s->canMinor) {
+ if (DEBUG_SHARE)
+ fprintf (stderr, "using end of heap\n");
+ regionStart = s->frontier;
+ regionEnd = s->limitPlusSlop;
+ } else {
+ if (DEBUG_SHARE)
+ fprintf (stderr, "using minor space\n");
+ // Use the space available for a minor GC.
+ assert (s->canMinor);
+ regionStart = s->heap.start + s->oldGenSize;
+ regionEnd = s->nursery;
+ }
+ maxElementsSize = (regionEnd - regionStart) / sizeof (*(t->elements));
+ if (DEBUG_SHARE)
+ fprintf (stderr, "maxElementsSize = %u\n", maxElementsSize);
+ t->elementsSize = 64; // some small power of two
+ t->log2ElementsSize = 6; // and its log base 2
+ if (maxElementsSize < t->elementsSize) {
+ if (DEBUG_SHARE)
+ fprintf (stderr, "too small -- using malloc\n");
+ t->elementsIsInHeap = FALSE;
+ ARRAY (struct GC_ObjectHashElement *, t->elements, t->elementsSize);
+ } else {
+ t->elementsIsInHeap = TRUE;
+ t->elements = (struct GC_ObjectHashElement*)regionStart;
+ // Find the largest power of two that fits.
+ for (; t->elementsSize <= maxElementsSize;
+ t->elementsSize <<= 1, t->log2ElementsSize++)
+ ; // nothing
+ t->elementsSize >>= 1;
+ t->log2ElementsSize--;
+ assert (t->elementsSize <= maxElementsSize);
+ for (i = 0; i < t->elementsSize; ++i)
+ t->elements[i].object = NULL;
+ }
+ t->numElements = 0;
+ t->mayInsert = TRUE;
+ if (DEBUG_SHARE) {
+ fprintf (stderr, "elementsIsInHeap = %s\n",
+ boolToString (t->elementsIsInHeap));
+ fprintf (stderr, "elementsSize = %u\n", t->elementsSize);
+ fprintf (stderr, "0x%08x = newTable ()\n", (uint)t);
+ }
+ return t;
+}
+
+static void destroyTable (GC_ObjectHashTable t) {
+ unless (t->elementsIsInHeap)
+ free (t->elements);
+ free (t);
+}
+
+static inline Pointer tableInsert
+ (GC_state s, GC_ObjectHashTable t, W32 hash, Pointer object,
+ Bool mightBeThere, Header header, W32 tag, Pointer max) {
+ GC_ObjectHashElement e;
+ Header header2;
+ static Bool init = FALSE;
+ static int maxNumProbes = 0;
+ static W64 mult; // magic multiplier for hashing
+ int numProbes;
+ W32 probe;
+ word *p;
+ word *p2;
+ W32 slot; // slot in hash table we are considering
+
+ if (DEBUG_SHARE)
+ fprintf (stderr, "tableInsert (%u, 0x%08x, %s, 0x%08x, 0x%08x)\n",
+ (uint)hash, (uint)object,
+ boolToString (mightBeThere),
+ (uint)header, (uint)max);
+ if (! init) {
+ init = TRUE;
+ mult = floor (((sqrt (5.0) - 1.0) / 2.0)
+ * (double)0x100000000llu);
+ }
+ slot = (W32)(mult * (W64)hash) >> (32 - t->log2ElementsSize);
+ probe = (1 == slot % 2) ? slot : slot - 1;
+ if (DEBUG_SHARE)
+ fprintf (stderr, "probe = 0x%08x\n", (uint)probe);
+ assert (1 == probe % 2);
+ numProbes = 0;
+look:
+ if (DEBUG_SHARE)
+ fprintf (stderr, "slot = 0x%08x\n", (uint)slot);
+ assert (0 <= slot and slot < t->elementsSize);
+ numProbes++;
+ e = &t->elements[slot];
+ if (NULL == e->object) {
+ /* It's not in the table. Add it. */
+ unless (t->mayInsert) {
+ if (DEBUG_SHARE)
+ fprintf (stderr, "not inserting\n");
+ return object;
+ }
+ e->hash = hash;
+ e->object = object;
+ t->numElements++;
+ if (numProbes > maxNumProbes) {
+ maxNumProbes = numProbes;
+ if (DEBUG_SHARE)
+ fprintf (stderr, "numProbes = %d\n", numProbes);
+ }
+ return object;
+ }
+ unless (hash == e->hash) {
+lookNext:
+ slot = (slot + probe) % t->elementsSize;
+ goto look;
+ }
+ unless (mightBeThere)
+ goto lookNext;
+ if (DEBUG_SHARE)
+ fprintf (stderr, "comparing 0x%08x to 0x%08x\n",
+ (uint)object, (uint)e->object);
+ /* Compare object to e->object. */
+ unless (object == e->object) {
+ header2 = GC_getHeader (e->object);
+ unless (header == header2)
+ goto lookNext;
+ for (p = (word*)object, p2 = (word*)e->object;
+ p < (word*)max;
+ ++p, ++p2)
+ unless (*p == *p2)
+ goto lookNext;
+ if (ARRAY_TAG == tag
+ and (GC_arrayNumElements (object)
+ != GC_arrayNumElements (e->object)))
+ goto lookNext;
+ }
+ /* object is equal to e->object. */
+ return e->object;
+}
+
+static void maybeGrowTable (GC_state s, GC_ObjectHashTable t) {
+ int i;
+ GC_ObjectHashElement oldElement;
+ struct GC_ObjectHashElement *oldElements;
+ uint oldSize;
+ uint newSize;
+
+ if (not t->mayInsert or t->numElements * 2 <= t->elementsSize)
+ return;
+ oldElements = t->elements;
+ oldSize = t->elementsSize;
+ newSize = oldSize * 2;
+ if (DEBUG_SHARE)
+ fprintf (stderr, "trying to grow table to size %d\n", newSize);
+ // Try to alocate the new table.
+ ARRAY_UNSAFE (struct GC_ObjectHashElement *, t->elements, newSize);
+ if (NULL == t->elements) {
+ t->mayInsert = FALSE;
+ t->elements = oldElements;
+ if (DEBUG_SHARE)
+ fprintf (stderr, "unable to grow table\n");
+ return;
+ }
+ t->elementsSize = newSize;
+ t->log2ElementsSize++;
+ for (i = 0; i < oldSize; ++i) {
+ oldElement = &oldElements[i];
+ unless (NULL == oldElement->object)
+ tableInsert (s, t, oldElement->hash, oldElement->object,
+ FALSE, 0, 0, 0);
+ }
+ if (t->elementsIsInHeap)
+ t->elementsIsInHeap = FALSE;
+ else
+ free (oldElements);
+ if (DEBUG_SHARE)
+ fprintf (stderr, "done growing table\n");
+}
+
+static Pointer hashCons (GC_state s, Pointer object, Bool countBytesHashConsed) {
+ Bool hasIdentity;
+ Word32 hash;
+ Header header;
+ pointer max;
+ uint numNonPointers;
+ uint numPointers;
+ word *p;
+ Pointer res;
+ GC_ObjectHashTable t;
+ uint tag;
+
+ if (DEBUG_SHARE)
+ fprintf (stderr, "hashCons (0x%08x)\n", (uint)object);
+ t = s->objectHashTable;
+ header = GC_getHeader (object);
+ SPLIT_HEADER ();
+ if (hasIdentity) {
+ /* Don't hash cons. */
+ res = object;
+ goto done;
+ }
+ assert (ARRAY_TAG == tag or NORMAL_TAG == tag);
+ max = object
+ + (ARRAY_TAG == tag
+ ? arrayNumBytes (s, object,
+ numPointers, numNonPointers)
+ : toBytes (numPointers + numNonPointers));
+ // Compute the hash.
+ hash = header;
+ for (p = (word*)object; p < (word*)max; ++p)
+ hash = hash * 31 + *p;
+ /* Insert into table. */
+ res = tableInsert (s, t, hash, object, TRUE, header, tag, (Pointer)max);
+ maybeGrowTable (s, t);
+ if (countBytesHashConsed and res != object) {
+ uint amount;
+
+ amount = max - object;
+ if (ARRAY_TAG == tag)
+ amount += GC_ARRAY_HEADER_SIZE;
+ else
+ amount += GC_NORMAL_HEADER_SIZE;
+ s->bytesHashConsed += amount;
+ }
+done:
+ if (DEBUG_SHARE)
+ fprintf (stderr, "0x%08x = hashCons (0x%08x)\n",
+ (uint)res, (uint)object);
+ return res;
+}
+
+static inline void maybeSharePointer (GC_state s,
+ Pointer *pp,
+ Bool shouldHashCons) {
+ unless (shouldHashCons)
+ return;
+ if (DEBUG_SHARE)
+ fprintf (stderr, "maybeSharePointer pp = 0x%08x *pp = 0x%08x\n",
+ (uint)pp, (uint)*pp);
+ *pp = hashCons (s, *pp, FALSE);
+}
+
+static void bytesHashConsedMessage (GC_state s, ullong total) {
+ fprintf (stderr, "%s bytes hash consed (%.1f%%).\n",
+ ullongToCommaString (s->bytesHashConsed),
+ 100.0 * ((double)s->bytesHashConsed / (double)total));
+}
+
+void GC_share (GC_state s, Pointer object) {
+ W32 total;
+
+ if (DEBUG_SHARE)
+ fprintf (stderr, "GC_share 0x%08x\n", (uint)object);
+ if (DEBUG_SHARE or s->messages)
+ s->bytesHashConsed = 0;
+ // Don't hash cons during the first round of marking.
+ total = mark (s, object, MARK_MODE, FALSE);
+ s->objectHashTable = newTable (s);
+ // Hash cons during the second round of marking.
+ mark (s, object, UNMARK_MODE, TRUE);
+ destroyTable (s->objectHashTable);
+ if (DEBUG_SHARE or s->messages)
+ bytesHashConsedMessage (s, total);
+}
Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/hash-cons.h (from rev 4097, mlton/branches/on-20050822-x86_64-branch/runtime/gc.h)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc.h 2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/hash-cons.h 2005-10-10 01:54:23 UTC (rev 4100)
@@ -0,0 +1,33 @@
+/* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
+ * Jagannathan, and Stephen Weeks.
+ * Copyright (C) 1997-2000 NEC Research Institute.
+ *
+ * MLton is released under a BSD-style license.
+ * See the file MLton-LICENSE for details.
+ */
+
+/* ---------------------------------------------------------------- */
+/* Object hash consing */
+/* ---------------------------------------------------------------- */
+
+typedef uint32_t GC_hash;
+
+typedef struct GC_objectHashElement {
+ GC_hash hash;
+ pointer object;
+} *GC_objectHashElement;
+
+typedef struct GC_objectHashTable {
+ struct GC_objectHashElement *elements;
+ bool elementsIsInHeap;
+ size_t elementsSize;
+ int log2ElementsSize;
+ bool mayInsert;
+ int32_t numElements;
+} *GC_ObjectHashTable;
+
+pointer hashCons (GC_state s, pointer object,
+ bool countBytesHashConsed);
+void maybeShareObjptr (GC_state s,
+ objptr *opp,
+ bool shouldHashCons);
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -5,91 +5,134 @@
* See the file MLton-LICENSE for details.
*/
-static inline bool pointerIsInHeap (GC_state s, pointer p) {
- return (not (isPointer (p))
- or (s->heap.start <= p
- and p < s->frontier));
+void displayHeap (__attribute__ ((unused)) GC_state s,
+ GC_heap heap,
+ FILE *stream) {
+ fprintf(stream,
+ "\t\tnursery ="FMTPTR"\n"
+ "\t\toldGenSize = %zu\n"
+ "\t\tstart = "FMTPTR"\n"
+ "\t\tsize = %zu\n",
+ (uintptr_t)heap->nursery,
+ heap->oldGenSize,
+ (uintptr_t)heap->start,
+ heap->size);
}
-static inline bool objptrIsInHeap (GC_state s, objptr op) {
- pointer p;
- if (not (isObjptr(op)))
- return TRUE;
- p = objptrToPointer (op, s->heap.start);
- return pointerIsInHeap (s, p);
-}
-static inline bool pointerIsInOldGen (GC_state s, pointer p) {
- return (not (isPointer (p))
- or (s->heap.start <= p
- and p < s->heap.start + s->heap.oldGenSize));
+static inline void heapInit (GC_heap h) {
+ h->start = NULL;
+ h->size = 0;
+ h->oldGenSize = 0;
+ h->nursery = NULL;
}
-static inline bool objptrIsInOldGen (GC_state s, objptr op) {
- pointer p;
- if (not (isObjptr(op)))
- return TRUE;
- p = objptrToPointer (op, s->heap.start);
- return pointerIsInOldGen (s, p);
+static void heapRelease (GC_state s, GC_heap h) {
+ if (NULL == h->start)
+ return;
+ if (DEBUG or s->controls.messages)
+ fprintf (stderr, "Releasing heap at "FMTPTR" of size %zu.\n",
+ (uintptr_t)h->start,
+ /*uintToCommaString*/(h->size));
+ GC_release (h->start, h->size);
+ heapInit (h);
}
-static inline bool pointerIsInNursery (GC_state s, pointer p) {
- return (not (isPointer (p))
- or (s->heap.nursery <= p and p < s->frontier));
+static void heapShrink (GC_state s, GC_heap h, size_t keep) {
+ assert (keep <= h->size);
+ if (0 == keep) {
+ heapRelease (s, h);
+ return;
+ }
+ keep = align (keep, s->sysvals.pageSize);
+ if (keep < h->size) {
+ if (DEBUG or s->controls.messages)
+ fprintf (stderr,
+ "Shrinking heap at "FMTPTR" of size %zu to %zu bytes.\n",
+ (uintptr_t)h->start,
+ /*uintToCommaString*/(h->size),
+ /*uintToCommaString*/(keep));
+ GC_decommit (h->start + keep, h->size - keep);
+ h->size = keep;
+ }
}
-static inline bool objptrIsInNursery (GC_state s, objptr op) {
- pointer p;
- if (not (isObjptr(op)))
- return TRUE;
- p = objptrToPointer (op, s->heap.start);
- return pointerIsInNursery (s, p);
-}
+/* heapCreate (s, h, desiredSize, minSize)
+ *
+ * allocates a heap of the size necessary to work with desiredSize
+ * live data, and ensures that at least minSize is available. It
+ * returns TRUE if it is able to allocate the space, and returns FALSE
+ * if it is unable. If a reasonable size to space is already there,
+ * then heapCreate leaves it.
+ */
+static bool heapCreate (GC_state s, GC_heap h,
+ size_t desiredSize,
+ size_t minSize) {
+ size_t backoff;
-static inline bool pointerIsInFromSpace (GC_state s, pointer p) {
- return (pointerIsInOldGen (s, p) or pointerIsInNursery (s, p));
-}
+ if (DEBUG_MEM)
+ fprintf (stderr, "heapCreate desired size = %zu min size = %zu\n",
+ /*uintToCommaString*/(desiredSize),
+ /*uintToCommaString*/(minSize));
+ assert (heapIsInit (h));
+ if (desiredSize < minSize)
+ desiredSize = minSize;
+ desiredSize = align (desiredSize, s->sysvals.pageSize);
+ assert (0 == h->size and NULL == h->start);
+ backoff = (desiredSize - minSize) / 20;
+ if (0 == backoff)
+ backoff = 1; /* enough to terminate the loop below */
+ backoff = align (backoff, s->sysvals.pageSize);
+ /* mmap toggling back and forth between high and low addresses to
+ * decrease the chance of virtual memory fragmentation causing an mmap
+ * to fail. This is important for large heaps.
+ */
+ for (h->size = desiredSize; h->size >= minSize; h->size -= backoff) {
+ const size_t highAddress = ((size_t)0xf8) << ((POINTER_SIZE - 1) * 8);
+ const size_t step = (size_t)0x08000000;
+ const size_t count = highAddress / step;
-static inline bool objptrIsInFromSpace (GC_state s, objptr op) {
- return (objptrIsInOldGen (s, op) or objptrIsInNursery (s, op));
-}
+ static bool direction = TRUE;
+ unsigned int i;
-#if ASSERT
-static bool heapHasBytesFree (GC_state s, size_t oldGen, size_t nursery) {
- size_t total;
- bool res;
-
- total =
- s->heap.oldGenSize + oldGen
- + (s->canMinor ? 2 : 1) * (s->limitPlusSlop - s->heap.nursery);
- res =
- (total <= s->heap.size)
- and (nursery <= (size_t)(s->limitPlusSlop - s->frontier));
- if (DEBUG_DETAILED)
- fprintf (stderr, "%s = hasBytesFree (%zd, %zd)\n",
- boolToString (res),
- /*uintToCommaString*/(oldGen),
- /*uintToCommaString*/(nursery));
- return res;
+ assert (isAligned (h->size, s->sysvals.pageSize));
+ for (i = 0; i <= count; i++) {
+ size_t address;
+
+ address = i * step;
+ if (direction)
+ address = highAddress - address;
+ h->start = GC_mmapAnon ((pointer)address, h->size);
+ if ((void*)-1 == h->start)
+ h->start = (void*)NULL;
+ unless ((void*)NULL == h->start) {
+ direction = not direction;
+ if (h->size > s->cumulativeStatistics.maxHeapSizeSeen)
+ s->cumulativeStatistics.maxHeapSizeSeen = h->size;
+ if (DEBUG or s->controls.messages)
+ fprintf (stderr, "Created heap of size %zu at "FMTPTR".\n",
+ /*uintToCommaString*/(h->size),
+ (uintptr_t)h->start);
+ assert (h->size >= minSize);
+ return TRUE;
+ }
+ }
+ if (s->controls.messages)
+ fprintf(stderr,
+ "[Requested %zuM cannot be satisfied, "
+ "backing off by %zuM (min size = %zuM).\n",
+ meg (h->size), meg (backoff), meg (minSize));
+ }
+ h->size = 0;
+ return FALSE;
}
-#endif
-void displayHeap (__attribute__ ((unused)) GC_state s,
- GC_heap heap,
- FILE *stream) {
- fprintf(stream,
- "\t\tnursery ="FMTPTR"\n"
- "\t\toldGenSize = %zu\n"
- "\t\tstart = "FMTPTR"\n"
- "\t\tsize = %zu\n",
- (uintptr_t)heap->nursery,
- heap->oldGenSize,
- (uintptr_t)heap->start,
- heap->size);
-}
-/* heapDesiredSize (s, l, c) returns the desired heap size for a heap
- * with l bytes live, given that the current heap size is c.
+
+/* heapDesiredSize (s, l, cs)
+ *
+ * returns the desired heap size for a heap with l bytes live, given
+ * that the current heap size is cs.
*/
static size_t heapDesiredSize (GC_state s, size_t live, size_t currentSize) {
size_t res;
@@ -112,7 +155,7 @@
* happens. This is so resizeHeap2 doesn't get confused and free
* a semispace in a misguided attempt to avoid paging.
*/
- res = roundDown (s->sysvals.ram / 2, s->sysvals.pageSize);
+ res = alignDown (s->sysvals.ram / 2, s->sysvals.pageSize);
} else if (ratio >= s->ratios.copy + s->ratios.grow) {
/* Cheney copying fits in RAM. */
res = s->sysvals.ram - s->ratios.grow * live;
@@ -140,23 +183,23 @@
* growFromSpace will make the right thing happen.
*/
}
- if (s->control.fixedHeap > 0) {
- if (res > s->control.fixedHeap / 2)
- res = s->control.fixedHeap;
+ if (s->controls.fixedHeap > 0) {
+ if (res > s->controls.fixedHeap / 2)
+ res = s->controls.fixedHeap;
else
- res = s->control.fixedHeap / 2;
+ res = s->controls.fixedHeap / 2;
if (res < live)
- die ("Out of memory with fixed heap size %zd.",
- /*uintToCommaString*/(s->control.fixedHeap));
- } else if (s->control.maxHeap > 0) {
- if (res > s->control.maxHeap)
- res = s->control.maxHeap;
+ die ("Out of memory with fixed heap size %zu.",
+ /*uintToCommaString*/(s->controls.fixedHeap));
+ } else if (s->controls.maxHeap > 0) {
+ if (res > s->controls.maxHeap)
+ res = s->controls.maxHeap;
if (res < live)
- die ("Out of memory with max heap size %zd.",
- /*uintToCommaString*/(s->control.maxHeap));
+ die ("Out of memory with max heap size %zu.",
+ /*uintToCommaString*/(s->controls.maxHeap));
}
if (DEBUG_RESIZING)
- fprintf (stderr, "%zd = heapDesiredSize (%zd, %zd)\n",
+ fprintf (stderr, "%zu = heapDesiredSize (%zu, %zu)\n",
/*uintToCommaString*/(res),
/*uintToCommaString*/(live),
/*uintToCommaString*/(currentSize));
@@ -164,47 +207,6 @@
return res;
}
-static inline void heapInit (GC_heap h) {
- h->start = NULL;
- h->size = 0;
- h->oldGenSize = 0;
- h->nursery = NULL;
-}
-
-static inline bool heapIsInit (GC_heap h) {
- return 0 == h->size;
-}
-
-static void heapRelease (GC_state s, GC_heap h) {
- if (NULL == h->start)
- return;
- if (DEBUG or s->messages)
- fprintf (stderr, "Releasing heap at "FMTPTR" of size %zd.\n",
- (uintptr_t)h->start,
- /*uintToCommaString*/(h->size));
- GC_release (h->start, h->size);
- heapInit (h);
-}
-
-static void heapShrink (GC_state s, GC_heap h, size_t keep) {
- assert (keep <= h->size);
- if (0 == keep) {
- heapRelease (s, h);
- return;
- }
- keep = align (keep, s->pageSize);
- if (keep < h->size) {
- if (DEBUG or s->messages)
- fprintf (stderr,
- "Shrinking heap at "FMTPTR" of size %zd to %zd bytes.\n",
- (uintptr_t)h->start,
- /*uintToCommaString*/(h->size),
- /*uintToCommaString*/(keep));
- GC_decommit (h->start + keep, h->size - keep);
- h->size = keep;
- }
-}
-
static void heapSetNursery (GC_state s,
size_t oldGenBytesRequested,
size_t nurseryBytesRequested) {
@@ -212,7 +214,7 @@
size_t nurserySize;
if (DEBUG_DETAILED)
- fprintf (stderr, "setNursery(%zd, %zd)\n",
+ fprintf (stderr, "setNursery(%zu, %zu)\n",
/*uintToCommaString*/(oldGenBytesRequested),
/*uintToCommaString*/(nurseryBytesRequested));
h = &s->heap;
@@ -271,66 +273,3 @@
assert (heapHasBytesFree (s, oldGenBytesRequested, nurseryBytesRequested));
}
-/* heapCreate (s, h, desiredSize, minSize)
- *
- * allocates a heap of the size necessary to work with desiredSize
- * live data, and ensures that at least minSize is available. It
- * returns TRUE if it is able to allocate the space, and returns FALSE
- * if it is unable. If a reasonable size to space is already there,
- * then heapCreate leaves it.
- */
-static bool heapCreate (GC_state s, GC_heap h,
- size_t desiredSize,
- size_t minSize) {
- size_t backoff;
-
- if (DEBUG_MEM)
- fprintf (stderr, "heapCreate desired size = %zd min size = %zd\n",
- /*uintToCommaString*/(desiredSize),
- /*uintToCommaString*/(minSize));
- assert (heapIsInit (h));
- if (desiredSize < minSize)
- desiredSize = minSize;
- desiredSize = align (desiredSize, s->sysvals.pageSize);
- assert (0 == h->size and NULL == h->start);
- backoff = (desiredSize - minSize) / 20;
- if (0 == backoff)
- backoff = 1; /* enough to terminate the loop below */
- backoff = align (backoff, s->sysvals.pageSize);
- /* mmap toggling back and forth between high and low addresses to
- * decrease the chance of virtual memory fragmentation causing an mmap
- * to fail. This is important for large heaps.
- */
- for (h->size = desiredSize; h->size >= minSize; h->size -= backoff) {
- static bool direction = TRUE;
- unsigned int i;
-
- assert (isAligned (h->size, s->sysvals.pageSize));
- for (i = 0; i < 32; i++) {
- size_t address;
-
- address = i * 0x08000000ul;
- if (direction)
- address = 0xf8000000ul - address;
- h->start = GC_mmap ((void*)address, h->size);
- if ((void*)-1 == h->start)
- h->start = (void*)NULL;
- unless ((void*)NULL == h->start) {
- direction = not direction;
- if (h->size > s->cumulativeStatistics.maxHeapSizeSeen)
- s->cumulativeStatistics.maxHeapSizeSeen = h->size;
- if (DEBUG or s->messages)
- fprintf (stderr, "Created heap of size %zd at "FMTPTR".\n",
- /*uintToCommaString*/(h->size),
- (uintptr_t)h->start);
- assert (h->size >= minSize);
- return TRUE;
- }
- }
- if (s->messages)
- fprintf(stderr, "[Requested %zuM cannot be satisfied, backing off by %zuM (min size = %zuM).\n",
- meg (h->size), meg (backoff), meg (minSize));
- }
- h->size = 0;
- return FALSE;
-}
Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap_predicates.c (from rev 4099, mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap_predicates.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -0,0 +1,79 @@
+/* Copyright (C) 2005-2005 Henry Cejtin, Matthew Fluet, Suresh
+ * Jagannathan, and Stephen Weeks.
+ *
+ * MLton is released under a BSD-style license.
+ * See the file MLton-LICENSE for details.
+ */
+
+static inline bool pointerIsInHeap (GC_state s, pointer p) {
+ return (not (isPointer (p))
+ or (s->heap.start <= p
+ and p < s->frontier));
+}
+
+static inline bool objptrIsInHeap (GC_state s, objptr op) {
+ pointer p;
+ if (not (isObjptr(op)))
+ return TRUE;
+ p = objptrToPointer (op, s->heap.start);
+ return pointerIsInHeap (s, p);
+}
+
+static inline bool pointerIsInOldGen (GC_state s, pointer p) {
+ return (not (isPointer (p))
+ or (s->heap.start <= p
+ and p < s->heap.start + s->heap.oldGenSize));
+}
+
+static inline bool objptrIsInOldGen (GC_state s, objptr op) {
+ pointer p;
+ if (not (isObjptr(op)))
+ return TRUE;
+ p = objptrToPointer (op, s->heap.start);
+ return pointerIsInOldGen (s, p);
+}
+
+static inline bool pointerIsInNursery (GC_state s, pointer p) {
+ return (not (isPointer (p))
+ or (s->heap.nursery <= p and p < s->frontier));
+}
+
+static inline bool objptrIsInNursery (GC_state s, objptr op) {
+ pointer p;
+ if (not (isObjptr(op)))
+ return TRUE;
+ p = objptrToPointer (op, s->heap.start);
+ return pointerIsInNursery (s, p);
+}
+
+static inline bool pointerIsInFromSpace (GC_state s, pointer p) {
+ return (pointerIsInOldGen (s, p) or pointerIsInNursery (s, p));
+}
+
+static inline bool objptrIsInFromSpace (GC_state s, objptr op) {
+ return (objptrIsInOldGen (s, op) or objptrIsInNursery (s, op));
+}
+
+#if ASSERT
+static bool heapHasBytesFree (GC_state s, size_t oldGen, size_t nursery) {
+ size_t total;
+ bool res;
+
+ total =
+ s->heap.oldGenSize + oldGen
+ + (s->canMinor ? 2 : 1) * (s->limitPlusSlop - s->heap.nursery);
+ res =
+ (total <= s->heap.size)
+ and (nursery <= (size_t)(s->limitPlusSlop - s->frontier));
+ if (DEBUG_DETAILED)
+ fprintf (stderr, "%s = hasBytesFree (%zu, %zu)\n",
+ boolToString (res),
+ /*uintToCommaString*/(oldGen),
+ /*uintToCommaString*/(nursery));
+ return res;
+}
+#endif
+
+static inline bool heapIsInit (GC_heap h) {
+ return 0 == h->size;
+}
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/invariant.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -42,7 +42,7 @@
< (s->generationalMaps.cardMap
+ (s->generationalMaps.cardMapLength * CARD_MAP_ELEM_SIZE)));
}
- assert (isAligned (s->heap.size, s->pageSize));
+ assert (isAligned (s->heap.size, s->sysvals.pageSize));
assert (isAligned ((size_t)s->heap.start, CARD_SIZE));
assert (isAlignedFrontier (s, s->heap.start + s->heap.oldGenSize));
assert (isAlignedFrontier (s, s->heap.nursery));
@@ -69,7 +69,7 @@
FALSE, assertObjptrIsInFromSpace);
/* Current thread. */
GC_stack stack = currentThreadStack(s);
- assert (isAlignedReserved (s, stack->reserved));
+ assert (isAlignedStackReserved (s, stack->reserved));
assert (s->stackBottom == stackBottom (s, stack));
assert (s->stackTop == stackTop (s, stack));
assert (s->stackLimit == stackLimit (s, stack));
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/major.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/major.h 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/major.h 2005-10-10 01:54:23 UTC (rev 4100)
@@ -7,6 +7,6 @@
*/
typedef enum {
- GC_COPYING,
- GC_MARK_COMPACT,
+ GC_COPYING,
+ GC_MARK_COMPACT,
} GC_majorKind;
Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-compact.c (from rev 4097, mlton/branches/on-20050822-x86_64-branch/runtime/gc.c)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc.c 2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-compact.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -0,0 +1,282 @@
+/* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
+ * Jagannathan, and Stephen Weeks.
+ * Copyright (C) 1997-2000 NEC Research Institute.
+ *
+ * MLton is released under a BSD-style license.
+ * See the file MLton-LICENSE for details.
+ */
+
+/* ---------------------------------------------------------------- */
+/* Jonkers Mark-compact Collection */
+/* ---------------------------------------------------------------- */
+
+static inline void markGlobalTrue (GC_state s, pointer *pp) {
+ mark (s, *pp, MARK_MODE, TRUE);
+}
+
+static inline void markGlobalFalse (GC_state s, pointer *pp) {
+ mark (s, *pp, MARK_MODE, FALSE);
+}
+
+static inline void unmarkGlobal (GC_state s, pointer *pp) {
+ mark (s, *pp, UNMARK_MODE, FALSE);
+}
+
+static inline void threadInternal (GC_state s, pointer *pp) {
+ Header *headerp;
+
+ if (FALSE)
+ fprintf (stderr, "threadInternal pp = 0x%08x *pp = 0x%08x header = 0x%08x\n",
+ (uint)pp, *(uint*)pp, (uint)GC_getHeader (*pp));
+ headerp = GC_getHeaderp (*pp);
+ *(Header*)pp = *headerp;
+ *headerp = (Header)pp;
+}
+
+/* If p is weak, the object pointer was valid, and points to an unmarked object,
+ * then clear the object pointer.
+ */
+static inline void maybeClearWeak (GC_state s, pointer p) {
+ Bool hasIdentity;
+ Header header;
+ Header *headerp;
+ uint numPointers;
+ uint numNonPointers;
+ uint tag;
+
+ headerp = GC_getHeaderp (p);
+ header = *headerp;
+ SPLIT_HEADER();
+ if (WEAK_TAG == tag and 1 == numPointers) {
+ Header h2;
+
+ if (DEBUG_WEAK)
+ fprintf (stderr, "maybeClearWeak (0x%08x) header = 0x%08x\n",
+ (uint)p, (uint)header);
+ h2 = GC_getHeader (((GC_weak)p)->object);
+ /* If it's unmarked not threaded, clear the weak pointer. */
+ if (1 == ((MARK_MASK | 1) & h2)) {
+ ((GC_weak)p)->object = (pointer)BOGUS_POINTER;
+ header = WEAK_GONE_HEADER | MARK_MASK;
+ if (DEBUG_WEAK)
+ fprintf (stderr, "cleared. new header = 0x%08x\n",
+ (uint)header);
+ *headerp = header;
+ }
+ }
+}
+
+static void updateForwardPointers (GC_state s) {
+ pointer back;
+ pointer front;
+ uint gap;
+ pointer endOfLastMarked;
+ Header header;
+ Header *headerp;
+ pointer p;
+ uint size;
+
+ if (DEBUG_MARK_COMPACT)
+ fprintf (stderr, "Update forward pointers.\n");
+ front = alignFrontier (s, s->heap.start);
+ back = s->heap.start + s->oldGenSize;
+ endOfLastMarked = front;
+ gap = 0;
+updateObject:
+ if (DEBUG_MARK_COMPACT)
+ fprintf (stderr, "updateObject front = 0x%08x back = 0x%08x\n",
+ (uint)front, (uint)back);
+ if (front == back)
+ goto done;
+ headerp = (Header*)front;
+ header = *headerp;
+ if (0 == header) {
+ /* We're looking at an array. Move to the header. */
+ p = front + 3 * WORD_SIZE;
+ headerp = (Header*)(p - WORD_SIZE);
+ header = *headerp;
+ } else
+ p = front + WORD_SIZE;
+ if (1 == (1 & header)) {
+ /* It's a header */
+ if (MARK_MASK & header) {
+ /* It is marked, but has no forward pointers.
+ * Thread internal pointers.
+ */
+thread:
+ maybeClearWeak (s, p);
+ size = objectSize (s, p);
+ if (DEBUG_MARK_COMPACT)
+ fprintf (stderr, "threading 0x%08x of size %u\n",
+ (uint)p, size);
+ if (front - endOfLastMarked >= 4 * WORD_SIZE) {
+ /* Compress all of the unmarked into one string.
+ * We require 4 * WORD_SIZE space to be available
+ * because that is the smallest possible array.
+ * You cannot use 3 * WORD_SIZE because even
+ * zero-length arrays require an extra word for
+ * the forwarding pointer. If you did use
+ * 3 * WORD_SIZE, updateBackwardPointersAndSlide
+ * would skip the extra word and be completely
+ * busted.
+ */
+ if (DEBUG_MARK_COMPACT)
+ fprintf (stderr, "compressing from 0x%08x to 0x%08x (length = %u)\n",
+ (uint)endOfLastMarked,
+ (uint)front,
+ front - endOfLastMarked);
+ *(uint*)endOfLastMarked = 0;
+ *(uint*)(endOfLastMarked + WORD_SIZE) =
+ front - endOfLastMarked - 3 * WORD_SIZE;
+ *(uint*)(endOfLastMarked + 2 * WORD_SIZE) =
+ GC_objectHeader (STRING_TYPE_INDEX);
+ }
+ front += size;
+ endOfLastMarked = front;
+ foreachPointerInObject (s, p, FALSE, threadInternal);
+ goto updateObject;
+ } else {
+ /* It's not marked. */
+ size = objectSize (s, p);
+ gap += size;
+ front += size;
+ goto updateObject;
+ }
+ } else {
+ pointer new;
+
+ assert (0 == (3 & header));
+ /* It's a pointer. This object must be live. Fix all the
+ * forward pointers to it, store its header, then thread
+ * its internal pointers.
+ */
+ new = p - gap;
+ do {
+ pointer cur;
+
+ cur = (pointer)header;
+ header = *(word*)cur;
+ *(word*)cur = (word)new;
+ } while (0 == (1 & header));
+ *headerp = header;
+ goto thread;
+ }
+ assert (FALSE);
+done:
+ return;
+}
+
+static void updateBackwardPointersAndSlide (GC_state s) {
+ pointer back;
+ pointer front;
+ uint gap;
+ Header header;
+ pointer p;
+ uint size;
+
+ if (DEBUG_MARK_COMPACT)
+ fprintf (stderr, "Update backward pointers and slide.\n");
+ front = alignFrontier (s, s->heap.start);
+ back = s->heap.start + s->oldGenSize;
+ gap = 0;
+updateObject:
+ if (DEBUG_MARK_COMPACT)
+ fprintf (stderr, "updateObject front = 0x%08x back = 0x%08x\n",
+ (uint)front, (uint)back);
+ if (front == back)
+ goto done;
+ header = *(word*)front;
+ if (0 == header) {
+ /* We're looking at an array. Move to the header. */
+ p = front + 3 * WORD_SIZE;
+ header = *(Header*)(p - WORD_SIZE);
+ } else
+ p = front + WORD_SIZE;
+ if (1 == (1 & header)) {
+ /* It's a header */
+ if (MARK_MASK & header) {
+ /* It is marked, but has no backward pointers to it.
+ * Unmark it.
+ */
+unmark:
+ *GC_getHeaderp (p) = header & ~MARK_MASK;
+ size = objectSize (s, p);
+ if (DEBUG_MARK_COMPACT)
+ fprintf (stderr, "unmarking 0x%08x of size %u\n",
+ (uint)p, size);
+ /* slide */
+ if (DEBUG_MARK_COMPACT)
+ fprintf (stderr, "sliding 0x%08x down %u\n",
+ (uint)front, gap);
+ copy (front, front - gap, size);
+ front += size;
+ goto updateObject;
+ } else {
+ /* It's not marked. */
+ size = objectSize (s, p);
+ if (DEBUG_MARK_COMPACT)
+ fprintf (stderr, "skipping 0x%08x of size %u\n",
+ (uint)p, size);
+ gap += size;
+ front += size;
+ goto updateObject;
+ }
+ } else {
+ pointer new;
+
+ /* It's a pointer. This object must be live. Fix all the
+ * backward pointers to it. Then unmark it.
+ */
+ new = p - gap;
+ do {
+ pointer cur;
+
+ assert (0 == (3 & header));
+ cur = (pointer)header;
+ header = *(word*)cur;
+ *(word*)cur = (word)new;
+ } while (0 == (1 & header));
+ /* The header will be stored by unmark. */
+ goto unmark;
+ }
+ assert (FALSE);
+done:
+ s->oldGenSize = front - gap - s->heap.start;
+ if (DEBUG_MARK_COMPACT)
+ fprintf (stderr, "bytesLive = %u\n", s->bytesLive);
+ return;
+}
+
+static void markCompact (GC_state s) {
+ struct rusage ru_start;
+
+ if (DEBUG or s->messages)
+ fprintf (stderr, "Major mark-compact GC.\n");
+ if (detailedGCTime (s))
+ startTiming (&ru_start);
+ s->numMarkCompactGCs++;
+ if (s->hashConsDuringGC) {
+ s->bytesHashConsed = 0;
+ s->numHashConsGCs++;
+ s->objectHashTable = newTable (s);
+ }
+ foreachGlobal (s, s->hashConsDuringGC
+ ? markGlobalTrue
+ : markGlobalFalse);
+ if (s->hashConsDuringGC)
+ destroyTable (s->objectHashTable);
+ foreachGlobal (s, threadInternal);
+ updateForwardPointers (s);
+ updateBackwardPointersAndSlide (s);
+ clearCrossMap (s);
+ s->bytesMarkCompacted += s->oldGenSize;
+ s->lastMajor = GC_MARK_COMPACT;
+ if (detailedGCTime (s))
+ stopTiming (&ru_start, &s->ru_gcMarkCompact);
+ if (DEBUG or s->messages) {
+ fprintf (stderr, "Major mark-compact GC done.\n");
+ if (s->hashConsDuringGC)
+ bytesHashConsedMessage
+ (s, s->bytesHashConsed + s->oldGenSize);
+ }
+}
Deleted: mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-sweep.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-sweep.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-sweep.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -1,7 +0,0 @@
-/* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
- * Jagannathan, and Stephen Weeks.
- * Copyright (C) 1997-2000 NEC Research Institute.
- *
- * MLton is released under a BSD-style license.
- * See the file MLton-LICENSE for details.
- */
Deleted: mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-sweep.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-sweep.h 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/mark-sweep.h 2005-10-10 01:54:23 UTC (rev 4100)
@@ -1,7 +0,0 @@
-/* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
- * Jagannathan, and Stephen Weeks.
- * Copyright (C) 1997-2000 NEC Research Institute.
- *
- * MLton is released under a BSD-style license.
- * See the file MLton-LICENSE for details.
- */
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -47,17 +47,6 @@
return O;
}
-/* isObjptr returns true if p looks like an object pointer. */
-static inline bool isObjptr (objptr p) {
- if GC_MODEL_NONOBJPTR {
- unsigned int shift = GC_MODEL_MINALIGN_SHIFT - GC_MODEL_SHIFT;
- objptr mask = ~((~((objptr)0)) << shift);
- return (0 == (p & mask));
- } else {
- return TRUE;
- }
-}
-
/*
* Note that by indirectly fetching and storing object pointers, the
* following functions admit implementations that behave according to
Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/model_predicates.c (from rev 4098, mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.c)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/model.c 2005-10-08 20:36:15 UTC (rev 4098)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/model_predicates.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -0,0 +1,17 @@
+/* Copyright (C) 2005-2005 Henry Cejtin, Matthew Fluet, Suresh
+ * Jagannathan, and Stephen Weeks.
+ *
+ * MLton is released under a BSD-style license.
+ * See the file MLton-LICENSE for details.
+ */
+
+/* isObjptr returns true if p looks like an object pointer. */
+static inline bool isObjptr (objptr p) {
+ if GC_MODEL_NONOBJPTR {
+ unsigned int shift = GC_MODEL_MINALIGN_SHIFT - GC_MODEL_SHIFT;
+ objptr mask = ~((~((objptr)0)) << shift);
+ return (0 == (p & mask));
+ } else {
+ return TRUE;
+ }
+}
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/new_object.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/new_object.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/new_object.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -38,7 +38,7 @@
*(GC_header*)(frontier) = header;
result = frontier + GC_NORMAL_HEADER_SIZE;
if (DEBUG)
- fprintf (stderr, FMTPTR " = newObject ("FMTHDR", %zd, %s)\n",
+ fprintf (stderr, FMTPTR " = newObject ("FMTHDR", %zu, %s)\n",
(uintptr_t)result,
header,
bytesRequested,
@@ -51,7 +51,7 @@
bool allocInOldGen) {
GC_stack stack;
- reserved = stackReserved (s, reserved);
+ reserved = alignStackReserved (s, reserved);
if (reserved > s->cumulativeStatistics.maxStackSizeSeen)
s->cumulativeStatistics.maxStackSizeSeen = reserved;
stack = (GC_stack) newObject (s, GC_STACK_HEADER,
@@ -60,7 +60,7 @@
stack->reserved = reserved;
stack->used = 0;
if (DEBUG_STACKS)
- fprintf (stderr, FMTPTR " = newStack (%zd)\n",
+ fprintf (stderr, FMTPTR " = newStack (%zu)\n",
(uintptr_t)stack,
reserved);
return stack;
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/object.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/object.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/object.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -6,7 +6,6 @@
* See the file MLton-LICENSE for details.
*/
-
static char* objectTypeTagToString (GC_objectTypeTag tag) {
switch (tag) {
case ARRAY_TAG:
@@ -25,16 +24,16 @@
/*
* Build the header for an object, given the index to its type info.
*/
-static inline GC_header GC_objectHeader (uint32_t t) {
+static inline GC_header objectHeader (uint32_t t) {
assert (t < TWOPOWER (TYPE_INDEX_BITS));
return 1 | (t << 1);
}
-#define GC_STACK_HEADER GC_objectHeader (STACK_TYPE_INDEX)
-#define GC_STRING_HEADER GC_objectHeader (STRING_TYPE_INDEX)
-#define GC_THREAD_HEADER GC_objectHeader (THREAD_TYPE_INDEX)
-#define GC_WEAK_GONE_HEADER GC_objectHeader (WEAK_GONE_TYPE_INDEX)
-#define GC_WORD8_VECTOR_HEADER GC_objectHeader (WORD8_TYPE_INDEX)
+#define GC_STACK_HEADER objectHeader (STACK_TYPE_INDEX)
+#define GC_STRING_HEADER objectHeader (STRING_TYPE_INDEX)
+#define GC_THREAD_HEADER objectHeader (THREAD_TYPE_INDEX)
+#define GC_WEAK_GONE_HEADER objectHeader (WEAK_GONE_TYPE_INDEX)
+#define GC_WORD8_VECTOR_HEADER objectHeader (WORD8_TYPE_INDEX)
static inline void splitHeader(GC_state s, GC_header header,
GC_objectTypeTag *tagRet, bool *hasIdentityRet,
@@ -74,20 +73,6 @@
*numObjptrsRet = numObjptrs;
}
-static inline size_t numNonObjptrsToBytes (uint16_t numNonObjptrs,
- GC_objectTypeTag tag) {
- switch (tag) {
- case ARRAY_TAG:
- return (size_t)(numNonObjptrs);
- case NORMAL_TAG:
- return (size_t)(numNonObjptrs) * 4;
- case WEAK_TAG:
- return (size_t)(numNonObjptrs) * 4;
- default:
- die ("bad tag %u", tag);
- }
-}
-
/* objectData (s, p)
*
* If p points at the beginning of an object, then objectData returns
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/object_size.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/object_size.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/object_size.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -6,6 +6,39 @@
* See the file MLton-LICENSE for details.
*/
+static inline size_t numNonObjptrsToBytes (uint16_t numNonObjptrs,
+ GC_objectTypeTag tag) {
+ switch (tag) {
+ case ARRAY_TAG:
+ return (size_t)(numNonObjptrs);
+ case NORMAL_TAG:
+ return (size_t)(numNonObjptrs) * 4;
+ case WEAK_TAG:
+ return (size_t)(numNonObjptrs) * 4;
+ default:
+ die ("bad tag %u", tag);
+ }
+}
+
+static inline size_t arraySizeNoHeader (GC_state s,
+ pointer p,
+ uint16_t numNonObjptrs,
+ uint16_t numObjptrs) {
+ size_t bytesPerElement;
+ GC_arrayLength numElements;
+ size_t result;
+
+ numElements = getArrayLength (p);
+ bytesPerElement =
+ numNonObjptrsToBytes(numNonObjptrs, ARRAY_TAG)
+ + (numObjptrs * OBJPTR_SIZE);
+ result = numElements * bytesPerElement;
+ /* Empty arrays have OBJPTR_SIZE bytes for the forwarding pointer. */
+ if (0 == result)
+ result = OBJPTR_SIZE;
+ return pad (s, result, GC_ARRAY_HEADER_SIZE);
+}
+
static inline size_t objectSize (GC_state s, pointer p) {
size_t headerBytes, objectBytes;
GC_header header;
@@ -21,7 +54,7 @@
+ (numObjptrs * OBJPTR_SIZE);
} else if (ARRAY_TAG == tag) {
headerBytes = GC_ARRAY_HEADER_SIZE;
- objectBytes = arrayNumBytes (s, p, numNonObjptrs, numObjptrs);
+ objectBytes = arraySizeNoHeader (s, p, numNonObjptrs, numObjptrs);
} else if (WEAK_TAG == tag) {
headerBytes = GC_NORMAL_HEADER_SIZE;
objectBytes =
@@ -34,3 +67,14 @@
}
return headerBytes + objectBytes;
}
+
+
+static inline size_t stackNumBytes (GC_state s, size_t size) {
+ size_t res;
+
+ res = align (GC_STACK_HEADER_SIZE + sizeof (struct GC_stack) + size,
+ s->alignment);
+ if (DEBUG_STACKS)
+ fprintf (stderr, "%zu = stackNumBytes (%zu)\n", res, size);
+ return res;
+}
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/pointer.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/pointer.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/pointer.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -5,9 +5,3 @@
* MLton is released under a BSD-style license.
* See the file MLton-LICENSE for details.
*/
-
-/* isPointer returns true if p looks like a pointer. */
-static inline bool isPointer (pointer p) {
- uintptr_t mask = ~((~((uintptr_t)0)) << GC_MODEL_MINALIGN_SHIFT);
- return (0 == ((uintptr_t)p & mask));
-}
Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/pointer_predicates.c (from rev 4099, mlton/branches/on-20050822-x86_64-branch/runtime/gc/pointer.c)
Deleted: mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -1,15 +0,0 @@
-/* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
- * Jagannathan, and Stephen Weeks.
- * Copyright (C) 1997-2000 NEC Research Institute.
- *
- * MLton is released under a BSD-style license.
- * See the file MLton-LICENSE for details.
- */
-
-static bool ratiosOk (struct GC_ratios ratios) {
- return 1.0 < ratios.grow
- and 1.0 < ratios.nursery
- and 1.0 < ratios.markCompact
- and ratios.markCompact <= ratios.copy
- and ratios.copy <= ratios.live;
-}
Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios_predicates.c (from rev 4098, mlton/branches/on-20050822-x86_64-branch/runtime/gc/ratios.c)
Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/rusage.c (from rev 4097, mlton/branches/on-20050822-x86_64-branch/runtime/gc.c)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc.c 2005-09-22 22:02:42 UTC (rev 4097)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/rusage.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -0,0 +1,92 @@
+/* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
+ * Jagannathan, and Stephen Weeks.
+ * Copyright (C) 1997-2000 NEC Research Institute.
+ *
+ * MLton is released under a BSD-style license.
+ * See the file MLton-LICENSE for details.
+ */
+
+static inline void rusageZero (struct rusage *ru) {
+ memset (ru, 0, sizeof (*ru));
+}
+
+static void rusagePlusMax (struct rusage *ru1,
+ struct rusage *ru2,
+ struct rusage *ru) {
+ const int million = 1000000;
+ time_t sec,
+ usec;
+
+ sec = ru1->ru_utime.tv_sec + ru2->ru_utime.tv_sec;
+ usec = ru1->ru_utime.tv_usec + ru2->ru_utime.tv_usec;
+ sec += (usec / million);
+ usec %= million;
+ ru->ru_utime.tv_sec = sec;
+ ru->ru_utime.tv_usec = usec;
+
+ sec = ru1->ru_stime.tv_sec + ru2->ru_stime.tv_sec;
+ usec = ru1->ru_stime.tv_usec + ru2->ru_stime.tv_usec;
+ sec += (usec / million);
+ usec %= million;
+ ru->ru_stime.tv_sec = sec;
+ ru->ru_stime.tv_usec = usec;
+}
+
+static void rusageMinusMax (struct rusage *ru1,
+ struct rusage *ru2,
+ struct rusage *ru) {
+ const int million = 1000000;
+ time_t sec,
+ usec;
+
+ sec = (ru1->ru_utime.tv_sec - ru2->ru_utime.tv_sec) - 1;
+ usec = ru1->ru_utime.tv_usec + million - ru2->ru_utime.tv_usec;
+ sec += (usec / million);
+ usec %= million;
+ ru->ru_utime.tv_sec = sec;
+ ru->ru_utime.tv_usec = usec;
+
+ sec = (ru1->ru_stime.tv_sec - ru2->ru_stime.tv_sec) - 1;
+ usec = ru1->ru_stime.tv_usec + million - ru2->ru_stime.tv_usec;
+ sec += (usec / million);
+ usec %= million;
+ ru->ru_stime.tv_sec = sec;
+ ru->ru_stime.tv_usec = usec;
+}
+
+static uintmax_t rusageTime (struct rusage *ru) {
+ uintmax_t result;
+
+ result = 0;
+ result += 1000 * ru->ru_utime.tv_sec;
+ result += 1000 * ru->ru_stime.tv_sec;
+ result += ru->ru_utime.tv_usec / 1000;
+ result += ru->ru_stime.tv_usec / 1000;
+ return result;
+}
+
+/* Return time as number of milliseconds. */
+static uintmax_t currentTime (void) {
+ struct rusage ru;
+
+ getrusage (RUSAGE_SELF, &ru);
+ return rusageTime (&ru);
+}
+
+static inline void startTiming (struct rusage *ru_start) {
+ getrusage (RUSAGE_SELF, ru_start);
+}
+
+static uint stopTiming (struct rusage *ru_start, struct rusage *ru_gc) {
+ struct rusage ru_finish, ru_total;
+
+ getrusage (RUSAGE_SELF, &ru_finish);
+ rusageMinusMax (&ru_finish, ru_start, &ru_total);
+ rusagePlusMax (ru_gc, &ru_total, ru_gc);
+ return rusageTime (&ru_total);
+}
+
+
+static inline bool detailedGCTime (GC_state s) {
+ return s->controls.summary;
+}
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -6,8 +6,14 @@
* See the file MLton-LICENSE for details.
*/
-static inline bool stackIsEmpty (GC_stack stack) {
- return 0 == stack->used;
+void displayStack (__attribute__ ((unused)) GC_state s,
+ GC_stack stack,
+ FILE *stream) {
+ fprintf(stream,
+ "\t\treserved = %zu\n"
+ "\t\tused = %zu\n",
+ stack->reserved,
+ stack->used);
}
/* stackSlop returns the amount of "slop" space needed between the top
@@ -21,21 +27,12 @@
return stackSlop (s);
}
-static inline size_t stackNumBytes (GC_state s, size_t size) {
- size_t res;
-
- res = align (GC_STACK_HEADER_SIZE + sizeof (struct GC_stack) + size,
- s->alignment);
- if (DEBUG_STACKS)
- fprintf (stderr, "%zu = stackNumBytes (%zu)\n", res, size);
- return res;
-}
-
+/* Pointer to the bottommost word in use on the stack. */
static inline pointer stackBottom (GC_state s, GC_stack stack) {
pointer res;
res = ((pointer)stack) + sizeof (struct GC_stack);
- assert (isAligned ((uintptr_t)res, s->alignment));
+ assert (isAligned ((size_t)res, s->alignment));
return res;
}
@@ -49,19 +46,20 @@
return stackBottom (s, stack) + stack->reserved;
}
-/* The maximum value stackTop may take on. */
+/* The maximum value which is valid for stackTop. */
static inline pointer stackLimit (GC_state s, GC_stack stack) {
return stackLimitPlusSlop (s, stack) - stackSlop (s);
}
-static inline uint32_t topFrameIndex (GC_state s, GC_stack stack) {
- uint32_t res;
+
+static inline GC_frameIndex topFrameIndex (GC_state s, GC_stack stack) {
+ GC_frameIndex res;
res =
getFrameIndexFromReturnAddress
(s, *(GC_returnAddress*)(stackTop (s, stack) - GC_RETURNADDRESS_SIZE));
if (DEBUG_PROFILE)
- fprintf (stderr, "topFrameIndex = %"PRIu32"\n", res);
+ fprintf (stderr, "topFrameIndex = "FMTFI"\n", res);
return res;
}
@@ -80,16 +78,7 @@
return layout->size;
}
-static inline size_t stackReserved (GC_state s, size_t r) {
- size_t res;
-
- res = pad (s, r, GC_STACK_HEADER_SIZE + sizeof (struct GC_stack));
- if (DEBUG_STACKS)
- fprintf (stderr, "%zu = stackReserved (%zu)\n", res, r);
- return res;
-}
-
-static inline size_t stackNeedsReserved (GC_state s, GC_stack stack) {
+static inline size_t stackMinimumReserved (GC_state s, GC_stack stack) {
return stack->used + stackSlop (s) - topFrameSize(s, stack);
}
@@ -101,19 +90,9 @@
assert (from->used <= to->reserved);
to->used = from->used;
if (DEBUG_STACKS)
- fprintf (stderr, "stackCopy from "FMTPTR" to "FMTPTR" of length %zd\n",
+ fprintf (stderr, "stackCopy from "FMTPTR" to "FMTPTR" of length %zu\n",
(uintptr_t) fromBottom,
(uintptr_t) toBottom,
from->used);
- memcpy (fromBottom, toBottom, from->used);
+ GC_memcpy (fromBottom, toBottom, from->used);
}
-
-void displayStack (__attribute__ ((unused)) GC_state s,
- GC_stack stack,
- FILE *stream) {
- fprintf(stream,
- "\t\treserved = %zu\n"
- "\t\tused = %zu\n",
- stack->reserved,
- stack->used);
-}
Copied: mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack_predicates.c (from rev 4099, mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack.c)
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/stack_predicates.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -0,0 +1,11 @@
+/* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
+ * Jagannathan, and Stephen Weeks.
+ * Copyright (C) 1997-2000 NEC Research Institute.
+ *
+ * MLton is released under a BSD-style license.
+ * See the file MLton-LICENSE for details.
+ */
+
+static inline bool stackIsEmpty (GC_stack stack) {
+ return 0 == stack->used;
+}
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/statistics.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/statistics.h 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/statistics.h 2005-10-10 01:54:23 UTC (rev 4100)
@@ -29,10 +29,10 @@
uintmax_t numMarkCompactGCs;
uintmax_t numMinorGCs;
-/* struct rusage ru_gc; /\* total resource usage spent in gc *\/ */
-/* struct rusage ru_gcCopy; /\* resource usage in major copying gcs. *\/ */
-/* struct rusage ru_gcMarkCompact; /\* resource usage in mark-compact gcs. *\/ */
-/* struct rusage ru_gcMinor; /\* resource usage in minor gcs. *\/ */
+ struct rusage ru_gc; /* total resource usage spent in gc */
+ struct rusage ru_gcCopy; /* resource usage in major copying gcs. */
+ struct rusage ru_gcMarkCompact; /* resource usage in mark-compact gcs. */
+ struct rusage ru_gcMinor; /* resource usage in minor gcs. */
};
struct GC_lastMajorStatistics {
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -5,6 +5,6 @@
* See the file MLton-LICENSE for details.
*/
-char* boolToString (bool b) {
+const char* boolToString (bool b) {
return b ? "TRUE" : "FALSE";
}
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.h 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.h 2005-10-10 01:54:23 UTC (rev 4100)
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <sys/resource.h>
#include "../assert.h"
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/virtual-memory.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/virtual-memory.c 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/virtual-memory.c 2005-10-10 01:54:23 UTC (rev 4100)
@@ -10,11 +10,22 @@
if (DEBUG_DETAILED)
fprintf (stderr, "GC_memcpy ("FMTPTR", "FMTPTR", %zu)\n",
(uintptr_t)src, (uintptr_t)dst, size);
- assert (isAligned ((uintptr_t)src, sizeof(unsigned int)));
- assert (isAligned ((uintptr_t)dst, sizeof(unsigned int)));
+ assert (isAligned ((size_t)src, sizeof(unsigned int)));
+ assert (isAligned ((size_t)dst, sizeof(unsigned int)));
assert (isAligned (size, sizeof(unsigned int)));
assert (dst <= src or src + size <= dst);
if (src == dst)
return;
memcpy (dst, src, size);
}
+
+void *GC_mmapAnon_safe (pointer p, size_t length) {
+ void *result;
+
+ result = GC_mmapAnon (p, length);
+ if ((void*)-1 == result) {
+ showMem ();
+ die ("Out of memory.");
+ }
+ return result;
+}
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/virtual-memory.h
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/virtual-memory.h 2005-10-09 19:59:19 UTC (rev 4099)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/virtual-memory.h 2005-10-10 01:54:23 UTC (rev 4100)
@@ -6,7 +6,12 @@
* See the file MLton-LICENSE for details.
*/
-void *GC_mmapAnon (size_t length);
+/* showMem displays the virtual memory mapping to stdout.
+ * It is used to diagnose memory problems.
+ */
+void showMem (void);
+
+void *GC_mmapAnon (void *start, size_t length);
void *GC_mmap (void *start, size_t length);
void GC_munmap (void *start, size_t length);
void GC_release (void *base, size_t length);