summaryrefslogtreecommitdiff
path: root/ghc/runtime/storage/SMcompacting.lc
diff options
context:
space:
mode:
Diffstat (limited to 'ghc/runtime/storage/SMcompacting.lc')
-rw-r--r--ghc/runtime/storage/SMcompacting.lc234
1 files changed, 234 insertions, 0 deletions
diff --git a/ghc/runtime/storage/SMcompacting.lc b/ghc/runtime/storage/SMcompacting.lc
new file mode 100644
index 0000000000..60942d3b41
--- /dev/null
+++ b/ghc/runtime/storage/SMcompacting.lc
@@ -0,0 +1,234 @@
+\section[SM-compacting]{Compacting Collector Subroutines}
+
+This is a collection of C functions used in implementing the compacting
+collectors.
+
+The motivation for making this a separate file/section is twofold:
+
+1) It lets us focus on one thing.
+
+2) If we don't do this, there will be a huge amount of repetition
+ between the various GC schemes --- a maintenance nightmare.
+
+The second is the major motivation.
+
+ToDo ADR: trash contents of other semispace after GC in debugging version
+
+\begin{code}
+#if defined(GC1s) || defined(GCdu) || defined(GCap) || defined(GCgn)
+ /* to the end */
+
+#if defined(GC1s)
+
+#define SCAN_REG_DUMP
+#include "SMinternal.h"
+REGDUMP(ScanRegDump);
+
+#else /* GCdu, GCap, GCgn */
+
+#define SCAV_REG_MAP
+#include "SMinternal.h"
+REGDUMP(ScavRegDump);
+
+#endif
+
+#include "SMcompacting.h"
+\end{code}
+
+\begin{code}
+void
+LinkRoots(roots, rootno)
+P_ roots[];
+I_ rootno;
+{
+ I_ root;
+
+ DEBUG_STRING("Linking Roots:");
+ for (root = 0; root < rootno; root++) {
+ LINK_LOCATION_TO_CLOSURE(&(roots[root]));
+ }
+}
+
+\end{code}
+
+\begin{code}
+
+#ifdef CONCURRENT
+void
+LinkSparks(STG_NO_ARGS)
+{
+ PP_ sparkptr;
+ int pool;
+
+ DEBUG_STRING("Linking Sparks:");
+ for (pool = 0; pool < SPARK_POOLS; pool++) {
+ for (sparkptr = PendingSparksHd[pool];
+ sparkptr < PendingSparksTl[pool]; sparkptr++) {
+ LINK_LOCATION_TO_CLOSURE(sparkptr);
+ }
+ }
+}
+#endif
+
+\end{code}
+
+\begin{code}
+
+#ifdef PAR
+
+void
+LinkLiveGAs(base, bits)
+P_ base;
+BitWord *bits;
+{
+ GALA *gala;
+ GALA *next;
+ GALA *prev;
+ long _hp_word, bit_index, bit;
+
+ DEBUG_STRING("Linking Live GAs:");
+
+ for (gala = liveIndirections, prev = NULL; gala != NULL; gala = next) {
+ next = gala->next;
+ ASSERT(gala->ga.loc.gc.gtid == mytid);
+ if (gala->ga.weight != MAX_GA_WEIGHT) {
+ LINK_LOCATION_TO_CLOSURE(&gala->la);
+ gala->next = prev;
+ prev = gala;
+ } else {
+ /* Since we have all of the weight, this GA is no longer needed */
+ W_ pga = PACK_GA(thisPE, gala->ga.loc.gc.slot);
+
+#ifdef FREE_DEBUG
+ fprintf(stderr, "Freeing slot %d\n", gala->ga.loc.gc.slot);
+#endif
+ gala->next = freeIndirections;
+ freeIndirections->next = gala;
+ (void) removeHashTable(pGAtoGALAtable, pga, (void *) gala);
+#ifdef DEBUG
+ gala->ga.weight = 0x0d0d0d0d;
+ gala->la = (P_) 0xbadbad;
+#endif
+ }
+ }
+ liveIndirections = prev;
+
+ prepareFreeMsgBuffers();
+
+ for (gala = liveRemoteGAs, prev = NULL; gala != NULL; gala = next) {
+ next = gala->next;
+ ASSERT(gala->ga.loc.gc.gtid != mytid);
+
+ _hp_word = gala->la - base;
+ bit_index = _hp_word / BITS_IN(BitWord);
+ bit = 1L << (_hp_word & (BITS_IN(BitWord) - 1));
+ if (!(bits[bit_index] & bit)) {
+ int pe = taskIDtoPE(gala->ga.loc.gc.gtid);
+ W_ pga = PACK_GA(pe, gala->ga.loc.gc.slot);
+ int i;
+
+ (void) removeHashTable(pGAtoGALAtable, pga, (void *) gala);
+ freeRemoteGA(pe, &(gala->ga));
+ gala->next = freeGALAList;
+ freeGALAList = gala;
+ } else {
+ LINK_LOCATION_TO_CLOSURE(&gala->la);
+ gala->next = prev;
+ prev = gala;
+ }
+ }
+ liveRemoteGAs = prev;
+
+ /* If we have any remaining FREE messages to send off, do so now */
+ sendFreeMessages();
+}
+
+#else
+
+\end{code}
+
+Note: no \tr{Link[AB]Stack} for ``parallel'' systems, because they
+don't have a single main stack.
+
+\begin{code}
+
+void
+LinkAStack(stackA, botA)
+PP_ stackA;
+PP_ botA;
+{
+ PP_ stackptr;
+
+ DEBUG_STRING("Linking A Stack:");
+ for (stackptr = stackA;
+ SUBTRACT_A_STK(stackptr, botA) >= 0;
+ stackptr = stackptr + AREL(1)) {
+ LINK_LOCATION_TO_CLOSURE(stackptr);
+ }
+}
+#endif /* PAR */
+\end{code}
+
+ToDo (Patrick?): Dont explicitly mark & compact unmarked Bstack frames
+
+\begin{code}
+#if ! defined(PAR)
+void
+LinkBStack(stackB, botB)
+P_ stackB;
+P_ botB; /* stackB points to topmost update frame */
+{
+ P_ updateFramePtr;
+
+ DEBUG_STRING("Linking B Stack:");
+ for (updateFramePtr = stackB;
+ SUBTRACT_B_STK(updateFramePtr, botB) > 0;
+ /* re-initialiser given explicitly */ ) {
+
+ P_ updateClosurePtr = updateFramePtr + BREL(UF_UPDATEE);
+
+ LINK_LOCATION_TO_CLOSURE(updateClosurePtr);
+
+ updateFramePtr = GRAB_SuB(updateFramePtr);
+ }
+}
+#endif /* not PAR */
+\end{code}
+
+\begin{code}
+I_
+CountCAFs(CAFlist)
+P_ CAFlist;
+{
+ I_ caf_no = 0;
+
+ for (caf_no = 0; CAFlist != NULL; CAFlist = (P_) IND_CLOSURE_LINK(CAFlist))
+ caf_no++;
+
+ return caf_no;
+}
+\end{code}
+
+\begin{code}
+void
+LinkCAFs(CAFlist)
+P_ CAFlist;
+{
+ DEBUG_STRING("Linking CAF Ptr Locations:");
+ while(CAFlist != NULL) {
+ DEBUG_LINK_CAF(CAFlist);
+ LINK_LOCATION_TO_CLOSURE(&IND_CLOSURE_PTR(CAFlist));
+ CAFlist = (P_) IND_CLOSURE_LINK(CAFlist);
+ }
+}
+
+\end{code}
+
+\begin{code}
+
+#ifdef PAR
+
+#endif /* PAR */
+
+#endif /* defined(_INFO_COMPACTING) */
+\end{code}