[MLton-commit] r7051
Matthew Fluet
fluet at mlton.org
Wed Apr 8 05:31:33 PDT 2009
Make sizeofHeapDesired based on heap size with maps. Avoid overflow in computaton of desired heap size.
----------------------------------------------------------------------
U mlton/trunk/runtime/gc/heap.c
----------------------------------------------------------------------
Modified: mlton/trunk/runtime/gc/heap.c
===================================================================
--- mlton/trunk/runtime/gc/heap.c 2009-04-08 12:31:28 UTC (rev 7050)
+++ mlton/trunk/runtime/gc/heap.c 2009-04-08 12:31:31 UTC (rev 7051)
@@ -1,4 +1,5 @@
-/* Copyright (C) 2005-2008 Henry Cejtin, Matthew Fluet, Suresh
+/* Copyright (C) 2009 Matthew Fluet.
+ * Copyright (C) 2005-2008 Henry Cejtin, Matthew Fluet, Suresh
* Jagannathan, and Stephen Weeks.
*
* MLton is released under a BSD-style license.
@@ -37,80 +38,109 @@
* given that the current heap size is cs.
*/
size_t sizeofHeapDesired (GC_state s, size_t liveSize, size_t currentSize) {
- size_t liveWithMapsSize;
- size_t res;
- float withMapsRatio;
+ size_t liveMapsSize, liveWithMapsSize;
+ size_t currentMapsSize, currentWithMapsSize;
+ size_t resSize, resWithMapsSize;
+ size_t syslimSize, syslimMapsSize, syslimWithMapsSize;
+ double ratio;
+ syslimWithMapsSize = alignDown (SIZE_MAX, s->sysvals.pageSize);
+ syslimSize = invertSizeofCardMapAndCrossMap (s, syslimWithMapsSize);
+ syslimMapsSize = sizeofCardMapAndCrossMap (s, syslimSize);
+ assert (syslimSize + syslimMapsSize <= syslimWithMapsSize);
+
liveSize = align (liveSize, s->sysvals.pageSize);
- liveWithMapsSize = liveSize + sizeofCardMapAndCrossMap (s, liveSize);
+ if (syslimSize < liveSize)
+ die ("Out of memory with system-limit heap size %s.\n",
+ uintmaxToCommaString(syslimSize));
+ liveMapsSize = sizeofCardMapAndCrossMap (s, liveSize);
+ liveWithMapsSize = liveSize + liveMapsSize;
- withMapsRatio = (float)s->sysvals.ram / (float)liveWithMapsSize;
- if (withMapsRatio >= s->controls.ratios.live + s->controls.ratios.grow) {
+ assert (isAligned (currentSize, s->sysvals.pageSize));
+ currentMapsSize = sizeofCardMapAndCrossMap (s, currentSize);
+ currentWithMapsSize = currentSize + currentMapsSize;
+
+ ratio = (double)s->sysvals.ram / (double)liveWithMapsSize;
+
+ if (ratio >= s->controls.ratios.live + s->controls.ratios.grow) {
/* Cheney copying fits in RAM with desired ratios.live. */
- res = liveSize * s->controls.ratios.live;
+ resWithMapsSize = liveWithMapsSize * s->controls.ratios.live;
/* If the heap is currently close in size to what we want, leave
* it alone. Favor growing over shrinking.
*/
- unless (1.1 * currentSize <= res
- or res <= .5 * currentSize)
- res = currentSize;
+ if (0.5 * currentWithMapsSize <= resWithMapsSize
+ and resWithMapsSize <= 1.1 * currentWithMapsSize) {
+ resWithMapsSize = currentWithMapsSize;
+ } else {
+ resWithMapsSize = align (resWithMapsSize, s->sysvals.pageSize);
+ }
} else if (s->controls.ratios.grow >= s->controls.ratios.copy
- and withMapsRatio >= 2 * s->controls.ratios.copy) {
+ and ratio >= 2.0 * s->controls.ratios.copy) {
/* Split RAM in half. Round down by pageSize so that the total
* amount of space taken isn't greater than RAM once rounding
* happens. This is so resizeHeapSecondary doesn't get confused
* and free a semispace in a misguided attempt to avoid paging.
*/
- res = alignDown (s->sysvals.ram / 2, s->sysvals.pageSize);
- } else if (withMapsRatio >= s->controls.ratios.copy + s->controls.ratios.grow) {
+ resWithMapsSize = alignDown (s->sysvals.ram / 2, s->sysvals.pageSize);
+ } else if (ratio >= s->controls.ratios.copy + s->controls.ratios.grow) {
/* Cheney copying fits in RAM. */
- res = s->sysvals.ram - s->controls.ratios.grow * liveSize;
+ resWithMapsSize = s->sysvals.ram - s->controls.ratios.grow * liveWithMapsSize;
/* If the heap isn't too much smaller than what we want, leave it
- * alone. On the other hand, if it is bigger we want to leave res
- * as is so that the heap is shrunk, to try to avoid paging.
+ * alone. On the other hand, if it is bigger we want to leave
+ * resWithMapsSize as is so that the heap is shrunk, to try to
+ * avoid paging.
*/
- if (currentSize <= res
- and res <= 1.1 * currentSize)
- res = currentSize;
- } else if (withMapsRatio >= s->controls.ratios.markCompact) {
+ if (1.0 * currentWithMapsSize <= resWithMapsSize
+ and resWithMapsSize <= 1.1 * currentWithMapsSize) {
+ resWithMapsSize = currentWithMapsSize;
+ } else {
+ resWithMapsSize = align (resWithMapsSize, s->sysvals.pageSize);
+ }
+ } else if (ratio >= s->controls.ratios.markCompact) {
/* Mark compact fits in RAM. It doesn't matter what the current
* size is. If the heap is currently smaller, we are using
* copying and should switch to mark-compact. If the heap is
* currently bigger, we want to shrink back to RAM to avoid
* paging.
*/
- res = s->sysvals.ram;
+ resWithMapsSize = s->sysvals.ram;
} else { /* Required live ratio. */
- res = liveSize * s->controls.ratios.markCompact;
- /* If the current heap is bigger than res, then shrinking always
- * sounds like a good idea. However, depending on what pages the
- * VM keeps around, growing could be very expensive, if it
- * involves paging the entire heap. Hopefully the copy loop in
- * growHeap will make the right thing happen.
+ double resWithMapsSizeD = liveWithMapsSize * (double)(s->controls.ratios.markCompact);
+ if (resWithMapsSizeD > (double)syslimWithMapsSize) {
+ resWithMapsSize = syslimWithMapsSize;
+ } else {
+ resWithMapsSize = align ((size_t)resWithMapsSizeD, s->sysvals.pageSize);
+ }
+ /* If the current heap is bigger than resWithMapsSize, then
+ * shrinking always sounds like a good idea. However, depending
+ * on what pages the VM keeps around, growing could be very
+ * expensive, if it involves paging the entire heap. Hopefully
+ * the copy loop in growHeap will make the right thing happen.
*/
}
if (s->controls.fixedHeap > 0) {
- if (res > s->controls.fixedHeap / 2)
- res = s->controls.fixedHeap;
+ if (resWithMapsSize > s->controls.fixedHeap / 2)
+ resWithMapsSize = s->controls.fixedHeap;
else
- res = s->controls.fixedHeap / 2;
- if (res < liveSize)
+ resWithMapsSize = s->controls.fixedHeap / 2;
+ if (resWithMapsSize < liveWithMapsSize)
die ("Out of memory with fixed heap size %s.",
uintmaxToCommaString(s->controls.fixedHeap));
} else if (s->controls.maxHeap > 0) {
- if (res > s->controls.maxHeap)
- res = s->controls.maxHeap;
- if (res < liveSize)
+ if (resWithMapsSize > s->controls.maxHeap)
+ resWithMapsSize = s->controls.maxHeap;
+ if (resWithMapsSize < liveWithMapsSize)
die ("Out of memory with max heap size %s.",
uintmaxToCommaString(s->controls.maxHeap));
}
+ resSize = invertSizeofCardMapAndCrossMap (s, resWithMapsSize);
if (DEBUG_RESIZING)
fprintf (stderr, "%s = sizeofHeapDesired (%s, %s)\n",
- uintmaxToCommaString(res),
+ uintmaxToCommaString(resSize),
uintmaxToCommaString(liveSize),
uintmaxToCommaString(currentSize));
- assert (res >= liveSize);
- return res;
+ assert (resSize >= liveSize);
+ return resSize;
}
void releaseHeap (GC_state s, GC_heap h) {
More information about the MLton-commit
mailing list