[MLton-commit] r4110
Matthew Fluet
MLton@mlton.org
Sun, 16 Oct 2005 16:34:23 -0700
More heap manipulation functions
----------------------------------------------------------------------
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c
A mlton/branches/on-20050822-x86_64-branch/runtime/gc/safe.c
U mlton/branches/on-20050822-x86_64-branch/runtime/gc/translate.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-16 22:05:00 UTC (rev 4109)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/Makefile 2005-10-16 23:34:20 UTC (rev 4110)
@@ -74,6 +74,7 @@
CFILES = \
gc_prefix.c \
util.c \
+ safe.c \
debug.c \
align.c \
virtual-memory.c \
@@ -89,6 +90,8 @@
stack_predicates.c \
stack.c \
thread.c \
+ foreach.c \
+ translate.c \
generational.c \
heap_predicates.c \
heap.c \
@@ -96,7 +99,6 @@
new_object.c \
ratios_predicates.c \
current.c \
- foreach.c \
atomic.c \
invariant.c \
enter_leave.c \
@@ -105,7 +107,6 @@
dfs-mark.c \
share.c \
mark-compact.c \
- translate.c \
assumptions.c \
gc_suffix.c
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-16 22:05:00 UTC (rev 4109)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/heap.c 2005-10-16 23:34:20 UTC (rev 4110)
@@ -127,8 +127,140 @@
return FALSE;
}
+/* heapRemap (s, h, desiredSize, minSize)
+ */
+static bool heapRemap (GC_state s, GC_heap h,
+ size_t desiredSize,
+ size_t minSize) {
+ size_t backoff;
+ size_t size;
+#if not HAS_REMAP
+ return FALSE;
+#endif
+ assert (minSize <= desiredSize);
+ assert (desiredSize >= h->size);
+ desiredSize = align (desiredSize, s->sysvals.pageSize);
+ backoff = (desiredSize - minSize) / 20;
+ if (0 == backoff)
+ backoff = 1; /* enough to terminate the loop below */
+ backoff = align (backoff, s->sysvals.pageSize);
+ for (size = desiredSize; size >= minSize; size -= backoff) {
+ pointer new;
+ new = GC_mremap (h->start, h->size, size);
+ unless ((void*)-1 == new) {
+ h->start = new;
+ h->size = size;
+ if (h->size > s->cumulativeStatistics.maxHeapSizeSeen)
+ s->cumulativeStatistics.maxHeapSizeSeen = h->size;
+ assert (minSize <= h->size and h->size <= desiredSize);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+enum {
+ COPY_CHUNK_SIZE = 0x2000000, /* 32M */
+};
+
+/* heapGrow (s, desiredSize, minSize)
+ */
+static void heapGrow (GC_state s, size_t desiredSize, size_t minSize) {
+ GC_heap curHeapp;
+ struct GC_heap newHeap;
+
+ pointer orig;
+ size_t size;
+
+ curHeapp = &s->heap;
+ assert (desiredSize >= s->heap.size);
+ if (DEBUG_RESIZING)
+ fprintf (stderr, "Growing heap at "FMTPTR" of size %zu to %zu bytes.\n",
+ (uintptr_t)s->heap.start,
+ /*uintToCommaString*/(s->heap.size),
+ /*uintToCommaString*/(desiredSize));
+ orig = curHeapp->start;
+ size = curHeapp->oldGenSize;
+ assert (size <= s->heap.size);
+ if (heapRemap (s, curHeapp, desiredSize, minSize))
+ goto done;
+ heapShrink (s, curHeapp, size);
+ heapInit (&newHeap);
+ /* Allocate a space of the desired size. */
+ if (heapCreate (s, &newHeap, desiredSize, minSize)) {
+ pointer from;
+ pointer to;
+ size_t remaining;
+
+ from = curHeapp->start + size;
+ to = newHeap.start + size;
+ remaining = size;
+copy:
+ assert (remaining == (size_t)(from - curHeapp->start)
+ and from >= curHeapp->start
+ and to >= newHeap.start);
+ if (remaining < COPY_CHUNK_SIZE) {
+ GC_memcpy (orig, newHeap.start, remaining);
+ } else {
+ remaining -= COPY_CHUNK_SIZE;
+ from -= COPY_CHUNK_SIZE;
+ to -= COPY_CHUNK_SIZE;
+ GC_memcpy (from, to, COPY_CHUNK_SIZE);
+ heapShrink (s, curHeapp, remaining);
+ goto copy;
+ }
+ heapRelease (s, curHeapp);
+ *curHeapp = newHeap;
+ } else {
+ /* Write the heap to a file and try again. */
+ int fd;
+ FILE *stream;
+ char template[80];
+ char *tmpDefault;
+ char *tmpDir;
+ char *tmpVar;
+
+#if (defined (__MSVCRT__))
+ tmpVar = "TEMP";
+ tmpDefault = "C:/WINNT/TEMP";
+#else
+ tmpVar = "TMPDIR";
+ tmpDefault = "/tmp";
+#endif
+ tmpDir = getenv (tmpVar);
+ strcpy (template, (NULL == tmpDir) ? tmpDefault : tmpDir);
+ strcat (template, "/FromSpaceXXXXXX");
+ fd = mkstemp_safe (template);
+ close_safe (fd);
+ if (s->controls.messages)
+ fprintf (stderr, "Paging heap from "FMTPTR" to %s.\n",
+ (uintptr_t)orig, template);
+ stream = fopen_safe (template, "wb");
+ fwrite_safe (orig, 1, size, stream);
+ fclose_safe (stream);
+ heapRelease (s, curHeapp);
+ if (heapCreate (s, curHeapp, desiredSize, minSize)) {
+ stream = fopen_safe (template, "rb");
+ fread_safe (curHeapp->start, 1, size, stream);
+ fclose_safe (stream);
+ unlink_safe (template);
+ } else {
+ unlink_safe (template);
+ if (s->controls.messages)
+ showMem ();
+ die ("Out of memory. Unable to allocate %zu bytes.\n",
+ /*uintToCommaString*/(minSize));
+ }
+ }
+done:
+ unless (orig == s->heap.start) {
+ translateHeap (s, orig, s->heap.start, s->heap.oldGenSize);
+ setCardMapAbsolute (s);
+ }
+}
+
/* heapDesiredSize (s, l, cs)
*
* returns the desired heap size for a heap with l bytes live, given
Added: mlton/branches/on-20050822-x86_64-branch/runtime/gc/safe.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/safe.c 2005-10-16 22:05:00 UTC (rev 4109)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/safe.c 2005-10-16 23:34:20 UTC (rev 4110)
@@ -0,0 +1,94 @@
+/* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
+ * Jagannathan, and Stephen Weeks.
+ * Copyright (C) 1997-2000 NEC Research Institute.
+ *
+ * MLton is released under a BSD-style license.
+ * See the file MLton-LICENSE for details.
+ */
+
+void *calloc_safe (size_t count, size_t size) {
+ void *res;
+
+ res = calloc (count, size);
+ if (NULL == res)
+ die ("calloc (%zu, %zu) failed.\n",
+ count, size);
+ return res;
+}
+
+void *malloc_safe (size_t size) {
+ void *res;
+
+ res = malloc (size);
+ if (NULL == res)
+ die ("malloc (%zu) failed.\n", size);
+ return res;
+}
+
+int mkstemp_safe (char *template) {
+ int fd;
+
+ fd = mkstemp (template);
+ if (-1 == fd)
+ diee ("mkstemp (%s) failed.\n", template);
+ return fd;
+}
+
+void close_safe (int fd) {
+ int res;
+
+ res = close (fd);
+ if (-1 == res)
+ diee ("close (%d) failed.\n", fd);
+ return;
+}
+
+FILE *fopen_safe (char *fileName, char *mode) {
+ FILE *file;
+
+ file = fopen (fileName, mode);
+ if (NULL == file)
+ diee ("fopen (%s) failed.\n", fileName);
+ return file;
+}
+
+void fwrite_safe (const void *data, size_t size, size_t count, FILE *stream) {
+ size_t bytes;
+ size_t res;
+
+ bytes = size * count;
+ if (0 == bytes) return;
+ res = fwrite (data, bytes, 1, stream);
+ if (1 != res)
+ diee ("fwrite (_, _, _, _) failed.\n");
+ return;
+}
+
+void fclose_safe (FILE *stream) {
+ int res;
+
+ res = fclose (stream);
+ if (-1 == res)
+ diee ("fclose (_) failed.\n");
+ return;
+}
+
+void fread_safe (void *data, size_t size, size_t count, FILE *stream) {
+ size_t bytes;
+ size_t res;
+
+ bytes = size * count;
+ res = fread (data, bytes, 1, stream);
+ if (1 != res)
+ diee ("fread (_, _, _, _) failed.\n");
+ return;
+}
+
+void unlink_safe (const char *pathname) {
+ int res;
+
+ res = unlink (pathname);
+ if (-1 == res)
+ diee ("unlink (%s) failed.\n", pathname);
+ return;
+}
Modified: mlton/branches/on-20050822-x86_64-branch/runtime/gc/translate.c
===================================================================
--- mlton/branches/on-20050822-x86_64-branch/runtime/gc/translate.c 2005-10-16 22:05:00 UTC (rev 4109)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/translate.c 2005-10-16 23:34:20 UTC (rev 4110)
@@ -31,7 +31,7 @@
pointer limit;
if (DEBUG or s->controls.messages)
- fprintf (stderr, "Translating heap of size %zd from "FMTPTR" to "FMTPTR".\n",
+ fprintf (stderr, "Translating heap of size %zu from "FMTPTR" to "FMTPTR".\n",
/*uintToCommaString*/(size),
(uintptr_t)from, (uintptr_t)to);
if (from == to)
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-16 22:05:00 UTC (rev 4109)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/util.h 2005-10-16 23:34:20 UTC (rev 4110)
@@ -26,6 +26,7 @@
#include <stdio.h>
#include <string.h>
#include <math.h>
+#include <unistd.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-16 22:05:00 UTC (rev 4109)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/virtual-memory.c 2005-10-16 23:34:20 UTC (rev 4110)
@@ -29,22 +29,3 @@
}
return result;
}
-
-void *calloc_safe (size_t count, size_t size) {
- void *res;
-
- res = calloc (count, size);
- if (NULL == res)
- die ("calloc (%zu, %zu) failed.\n",
- count, size);
- return res;
-}
-
-void *malloc_safe (size_t size) {
- void *res;
-
- res = malloc (size);
- if (NULL == res)
- die ("malloc (%zu) failed.\n", size);
- return res;
-}
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-16 22:05:00 UTC (rev 4109)
+++ mlton/branches/on-20050822-x86_64-branch/runtime/gc/virtual-memory.h 2005-10-16 23:34:20 UTC (rev 4110)
@@ -14,5 +14,6 @@
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_mremap (void *start, size_t oldLength, size_t newLength);
void GC_release (void *base, size_t length);
void GC_decommit (void *base, size_t length);