summaryrefslogtreecommitdiff
path: root/ghc/runtime/storage/SM1s.lc
diff options
context:
space:
mode:
Diffstat (limited to 'ghc/runtime/storage/SM1s.lc')
-rw-r--r--ghc/runtime/storage/SM1s.lc197
1 files changed, 197 insertions, 0 deletions
diff --git a/ghc/runtime/storage/SM1s.lc b/ghc/runtime/storage/SM1s.lc
new file mode 100644
index 0000000000..51265e5959
--- /dev/null
+++ b/ghc/runtime/storage/SM1s.lc
@@ -0,0 +1,197 @@
+***************************************************************************
+
+ COMPACTING GARBAGE COLLECTION
+
+Additional Global Data Requirements:
+ ++ All the root locations are in malloced space (and info tables in
+ static data space). This is to simplify the location list end test.
+
+***************************************************************************
+
+[Someone needs to document this too. KH]
+
+\begin{code}
+#if defined(GC1s)
+
+ToDo: Soft heap limits
+
+#define SCAN_REG_DUMP
+#include "SMinternal.h"
+#include "SMcompacting.h"
+#include "SMextn.h"
+
+REGDUMP(ScanRegDump);
+
+compactingData compactingInfo = {0, 0, 0, 0, 0};
+
+P_ heap_space = 0; /* Address of first word of slab
+ of memory allocated for heap */
+
+P_ hp_start; /* Value of Hp when reduction was resumed */
+
+I_
+initHeap( sm )
+ smInfo *sm;
+{
+ if (heap_space == 0) { /* allocates if it doesn't already exist */
+
+ /* Allocate the roots space */
+ sm->roots = (P_ *) xmalloc( SM_MAXROOTS * sizeof(W_) );
+
+ /* Allocate the heap */
+ heap_space = (P_) xmalloc((SM_word_heap_size + EXTRA_HEAP_WORDS) * sizeof(W_));
+
+ compactingInfo.bit_words = (SM_word_heap_size + BITS_IN(BitWord) - 1) / BITS_IN(BitWord);
+ compactingInfo.bits = (BitWord *)(heap_space + SM_word_heap_size) - compactingInfo.bit_words;
+
+ compactingInfo.heap_words = SM_word_heap_size - compactingInfo.bit_words;
+ compactingInfo.base = HEAP_FRAME_BASE(heap_space, compactingInfo.heap_words);
+ compactingInfo.lim = HEAP_FRAME_LIMIT(heap_space, compactingInfo.heap_words);
+
+ stat_init("COMPACTING", "", "");
+ }
+
+ sm->hp = hp_start = compactingInfo.base - 1;
+
+ if (SM_alloc_size) {
+ sm->hplim = sm->hp + SM_alloc_size;
+ SM_alloc_min = 0; /* No min; alloc size specified */
+
+ if (sm->hplim > compactingInfo.lim) {
+ fprintf(stderr, "Not enough heap for requested alloc size\n");
+ return -1;
+ }
+ } else {
+ sm->hplim = compactingInfo.lim;
+ }
+
+ sm->CAFlist = NULL;
+
+#ifndef PAR
+ initExtensions( sm );
+#endif /* !PAR */
+
+ if (SM_trace) {
+ fprintf(stderr, "COMPACTING Heap: Base 0x%lx, Lim 0x%lx, Bits 0x%lx, bit words 0x%lx\n",
+ (W_) compactingInfo.base, (W_) compactingInfo.lim,
+ (W_) compactingInfo.bits, (W_) compactingInfo.bit_words);
+ fprintf(stderr, "COMPACTING Initial: base 0x%lx, lim 0x%lx\n hp 0x%lx, hplim 0x%lx, free %lu\n",
+ (W_) compactingInfo.base,
+ (W_) compactingInfo.lim,
+ (W_) sm->hp, (W_) sm->hplim, (W_) (sm->hplim - sm->hp) * sizeof(W_));
+ }
+
+ return 0;
+}
+
+I_
+collectHeap(reqsize, sm, do_full_collection)
+ W_ reqsize;
+ smInfo *sm;
+ rtsBool do_full_collection; /* ignored */
+{
+ I_ free_space, /* No of words of free space following GC */
+ alloc, /* Number of words allocated since last GC */
+ resident; /* Number of words remaining after GC */
+
+ SAVE_REGS(&ScanRegDump); /* Save registers */
+
+ if (SM_trace)
+ {
+ fflush(stdout); /* Flush stdout at start of GC */
+ fprintf(stderr, "COMPACTING Start: base 0x%lx, lim 0x%lx\n hp 0x%lx, hplim 0x%lx, req %lu\n",
+ (W_) compactingInfo.base, (W_) compactingInfo.lim,
+ (W_) sm->hp, (W_) sm->hplim, (W_) (reqsize * sizeof(W_)));
+ }
+
+ alloc = sm->hp - hp_start;
+
+ stat_startGC(alloc);
+
+ /* bracket use of MARK_REG_MAP with RESTORE/SAVE of SCAN_REG_MAP */
+ RESTORE_REGS(&ScanRegDump);
+
+ markHeapRoots(sm, sm->CAFlist, 0,
+ compactingInfo.base,
+ compactingInfo.lim,
+ compactingInfo.bits);
+
+ SAVE_REGS(&ScanRegDump);
+ /* end of bracket */
+
+#ifndef PAR
+ sweepUpDeadMallocPtrs(sm->MallocPtrList,
+ compactingInfo.base,
+ compactingInfo.bits );
+#endif
+
+ LinkCAFs(sm->CAFlist);
+
+ LinkRoots( sm->roots, sm->rootno );
+#ifdef CONCURRENT
+ LinkSparks();
+#endif
+#ifdef PAR
+ LinkLiveGAs(compactingInfo.base, compactingInfo.bits);
+#else
+ DEBUG_STRING("Linking Stable Pointer Table:");
+ LINK_LOCATION_TO_CLOSURE(&sm->StablePointerTable);
+ LinkAStack( MAIN_SpA, stackInfo.botA );
+ LinkBStack( MAIN_SuB, stackInfo.botB );
+#endif /* parallel */
+
+ /* Do Inplace Compaction */
+ /* Returns start of next closure, -1 gives last allocated word */
+
+ sm->hp = Inplace_Compaction(compactingInfo.base,
+ compactingInfo.lim,
+ 0, 0,
+ compactingInfo.bits,
+ compactingInfo.bit_words
+#if ! defined(PAR)
+ , &(sm->MallocPtrList)
+#endif
+ ) - 1;
+
+ resident = sm->hp - (compactingInfo.base - 1);
+ DO_MAX_RESIDENCY(resident); /* stats only */
+
+ if (SM_alloc_size) {
+ sm->hplim = sm->hp + SM_alloc_size;
+ if (sm->hplim > compactingInfo.lim) {
+ free_space = 0;
+ } else {
+ free_space = SM_alloc_size;
+ }
+ } else {
+ sm->hplim = compactingInfo.lim;
+ free_space = sm->hplim - sm->hp;
+ }
+
+ hp_start = sm->hp;
+
+ stat_endGC(alloc, compactingInfo.heap_words, resident, "");
+
+ if (SM_trace)
+ fprintf(stderr, "COMPACTING Done: base 0x%lx, lim 0x%lx\n hp 0x%lx, hplim 0x%lx, free %lu\n",
+ (W_) compactingInfo.base, (W_) compactingInfo.lim,
+ (W_) sm->hp, (W_) sm->hplim, (W_) (free_space * sizeof(W_)));
+
+#ifdef DEBUG
+ /* To help flush out bugs, we trash the part of the heap from
+ which we're about to start allocating. */
+ TrashMem(sm->hp+1, sm->hplim);
+#endif /* DEBUG */
+
+ RESTORE_REGS(&ScanRegDump); /* Restore Registers */
+
+ if ((SM_alloc_min > free_space) || (reqsize > free_space))
+ return GC_HARD_LIMIT_EXCEEDED; /* Heap exhausted */
+ else
+ return GC_SUCCESS; /* Heap OK */
+}
+
+#endif /* GC1s */
+
+\end{code}
+