[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);