| 1 | /* Copyright (C) 2012,2016 Matthew Fluet. |
| 2 | * Copyright (C) 1999-2008 Henry Cejtin, Matthew Fluet, Suresh |
| 3 | * Jagannathan, and Stephen Weeks. |
| 4 | * Copyright (C) 1997-2000 NEC Research Institute. |
| 5 | * |
| 6 | * MLton is released under a BSD-style license. |
| 7 | * See the file MLton-LICENSE for details. |
| 8 | */ |
| 9 | |
| 10 | /* ---------------------------------------------------------------- */ |
| 11 | /* Cheney Copying Collection */ |
| 12 | /* ---------------------------------------------------------------- */ |
| 13 | |
| 14 | void updateWeaksForCheneyCopy (GC_state s) { |
| 15 | pointer p; |
| 16 | GC_weak w; |
| 17 | |
| 18 | for (w = s->weaks; w != NULL; w = w->link) { |
| 19 | assert (BOGUS_OBJPTR != w->objptr); |
| 20 | |
| 21 | if (DEBUG_WEAK) |
| 22 | fprintf (stderr, "updateWeaksForCheneyCopy w = "FMTPTR" ", (uintptr_t)w); |
| 23 | p = objptrToPointer (w->objptr, s->heap.start); |
| 24 | if (hasFwdPtr(p)) { |
| 25 | if (DEBUG_WEAK) |
| 26 | fprintf (stderr, "forwarded from "FMTOBJPTR" to "FMTOBJPTR"\n", |
| 27 | w->objptr, getFwdPtr(p)); |
| 28 | w->objptr = getFwdPtr(p); |
| 29 | } else { |
| 30 | if (DEBUG_WEAK) |
| 31 | fprintf (stderr, "cleared\n"); |
| 32 | *(getHeaderp((pointer)w - offsetofWeak (s))) = GC_WEAK_GONE_HEADER; |
| 33 | w->objptr = BOGUS_OBJPTR; |
| 34 | } |
| 35 | } |
| 36 | s->weaks = NULL; |
| 37 | } |
| 38 | |
| 39 | void swapHeapsForCheneyCopy (GC_state s) { |
| 40 | struct GC_heap tempHeap; |
| 41 | |
| 42 | tempHeap = s->secondaryHeap; |
| 43 | s->secondaryHeap = s->heap; |
| 44 | s->heap = tempHeap; |
| 45 | setCardMapAndCrossMap (s); |
| 46 | } |
| 47 | |
| 48 | void majorCheneyCopyGC (GC_state s) { |
| 49 | size_t bytesCopied; |
| 50 | struct rusage ru_start; |
| 51 | pointer toStart; |
| 52 | |
| 53 | assert (s->secondaryHeap.size >= s->heap.oldGenSize); |
| 54 | if (detailedGCTime (s)) |
| 55 | startTiming (&ru_start); |
| 56 | s->cumulativeStatistics.numCopyingGCs++; |
| 57 | s->forwardState.amInMinorGC = FALSE; |
| 58 | if (DEBUG or s->controls.messages) { |
| 59 | fprintf (stderr, |
| 60 | "[GC: Starting major Cheney-copy;]\n"); |
| 61 | fprintf (stderr, |
| 62 | "[GC:\tfrom heap at "FMTPTR" of size %s bytes,]\n", |
| 63 | (uintptr_t)(s->heap.start), |
| 64 | uintmaxToCommaString(s->heap.size)); |
| 65 | fprintf (stderr, |
| 66 | "[GC:\tto heap at "FMTPTR" of size %s bytes.]\n", |
| 67 | (uintptr_t)(s->secondaryHeap.start), |
| 68 | uintmaxToCommaString(s->secondaryHeap.size)); |
| 69 | } |
| 70 | s->forwardState.toStart = s->secondaryHeap.start; |
| 71 | s->forwardState.toLimit = s->secondaryHeap.start + s->secondaryHeap.size; |
| 72 | assert (s->secondaryHeap.start != (pointer)NULL); |
| 73 | /* The next assert ensures there is enough space for the copy to |
| 74 | * succeed. It does not assert |
| 75 | * (s->secondaryHeap.size >= s->heap.size) |
| 76 | * because that is too strong. |
| 77 | */ |
| 78 | assert (s->secondaryHeap.size >= s->heap.oldGenSize); |
| 79 | toStart = alignFrontier (s, s->secondaryHeap.start); |
| 80 | s->forwardState.back = toStart; |
| 81 | foreachGlobalObjptr (s, forwardObjptr); |
| 82 | foreachObjptrInRange (s, toStart, &s->forwardState.back, forwardObjptr, TRUE); |
| 83 | updateWeaksForCheneyCopy (s); |
| 84 | s->secondaryHeap.oldGenSize = (size_t)(s->forwardState.back - s->secondaryHeap.start); |
| 85 | bytesCopied = s->secondaryHeap.oldGenSize; |
| 86 | s->cumulativeStatistics.bytesCopied += bytesCopied; |
| 87 | swapHeapsForCheneyCopy (s); |
| 88 | s->lastMajorStatistics.kind = GC_COPYING; |
| 89 | if (detailedGCTime (s)) |
| 90 | stopTiming (&ru_start, &s->cumulativeStatistics.ru_gcCopying); |
| 91 | if (DEBUG or s->controls.messages) |
| 92 | fprintf (stderr, |
| 93 | "[GC: Finished major Cheney-copy; copied %s bytes.]\n", |
| 94 | uintmaxToCommaString(bytesCopied)); |
| 95 | } |
| 96 | |
| 97 | /* ---------------------------------------------------------------- */ |
| 98 | /* Minor Cheney Copying Collection */ |
| 99 | /* ---------------------------------------------------------------- */ |
| 100 | |
| 101 | void minorCheneyCopyGC (GC_state s) { |
| 102 | size_t bytesAllocated; |
| 103 | size_t bytesCopied; |
| 104 | struct rusage ru_start; |
| 105 | |
| 106 | if (DEBUG_GENERATIONAL) |
| 107 | fprintf (stderr, "minorGC nursery = "FMTPTR" frontier = "FMTPTR"\n", |
| 108 | (uintptr_t)s->heap.nursery, (uintptr_t)s->frontier); |
| 109 | assert (invariantForGC (s)); |
| 110 | bytesAllocated = (size_t)(s->frontier - s->heap.nursery); |
| 111 | if (bytesAllocated == 0) |
| 112 | return; |
| 113 | s->cumulativeStatistics.bytesAllocated += bytesAllocated; |
| 114 | if (not s->canMinor) { |
| 115 | s->heap.oldGenSize += bytesAllocated; |
| 116 | } else { |
| 117 | if (detailedGCTime (s)) |
| 118 | startTiming (&ru_start); |
| 119 | s->cumulativeStatistics.numMinorGCs++; |
| 120 | s->forwardState.amInMinorGC = TRUE; |
| 121 | if (DEBUG_GENERATIONAL or s->controls.messages) { |
| 122 | fprintf (stderr, |
| 123 | "[GC: Starting minor Cheney-copy;]\n"); |
| 124 | fprintf (stderr, |
| 125 | "[GC:\tfrom nursery at "FMTPTR" of size %s bytes.]\n", |
| 126 | (uintptr_t)(s->heap.nursery), |
| 127 | uintmaxToCommaString(bytesAllocated)); |
| 128 | } |
| 129 | s->forwardState.toStart = s->heap.start + s->heap.oldGenSize; |
| 130 | assert (isFrontierAligned (s, s->forwardState.toStart)); |
| 131 | s->forwardState.toLimit = s->forwardState.toStart + bytesAllocated; |
| 132 | assert (invariantForGC (s)); |
| 133 | s->forwardState.back = s->forwardState.toStart; |
| 134 | /* Forward all globals. Would like to avoid doing this once all |
| 135 | * the globals have been assigned. |
| 136 | */ |
| 137 | foreachGlobalObjptr (s, forwardObjptrIfInNursery); |
| 138 | forwardInterGenerationalObjptrs (s); |
| 139 | foreachObjptrInRange (s, s->forwardState.toStart, &s->forwardState.back, |
| 140 | forwardObjptrIfInNursery, TRUE); |
| 141 | updateWeaksForCheneyCopy (s); |
| 142 | bytesCopied = (size_t)(s->forwardState.back - s->forwardState.toStart); |
| 143 | s->cumulativeStatistics.bytesCopiedMinor += bytesCopied; |
| 144 | s->heap.oldGenSize += bytesCopied; |
| 145 | s->lastMajorStatistics.numMinorGCs++; |
| 146 | if (detailedGCTime (s)) |
| 147 | stopTiming (&ru_start, &s->cumulativeStatistics.ru_gcMinor); |
| 148 | if (DEBUG_GENERATIONAL or s->controls.messages) |
| 149 | fprintf (stderr, |
| 150 | "[GC: Finished minor Cheney-copy; copied %s bytes.]\n", |
| 151 | uintmaxToCommaString(bytesCopied)); |
| 152 | } |
| 153 | } |