[project @ 1996-01-11 14:06:51 by partain]
[ghc-hetmet.git] / ghc / runtime / storage / SMscan.lc
1 /*************************************************************************
2                              SCANNING CODE
3
4 This file contains the basic routines required for inplace compacting
5 garbage collection. It is based on Jonkers's algorithm.
6
7 There is a compacting routine as well as all the basic routines which
8 are placed in the info tables of the appropriate closures.
9
10   ToDo: Remove Fillers -- Compiler
11         Remove Dummy Filler Macros -- SMupdate.lh
12         Remove special "shrinking" info_upd stuff -- Compiler
13         Remove special "shrinking" info_upd stuff -- SMinterface.lh
14
15         Updateable closure size can now be relaxed
16           MinUpdSize is now 1
17           May want to allocate larger closures to enable updates inplace
18             eg  Int     1    MkInt etc fit
19                 List    2    Nil,List fit
20                 STree   3    Leaf(2) Branch(3) fit
21                 STree   2    Leaf(2) fits, Branch(3) fails
22                 Tuple4  1    MkTuple4 fails
23
24         Need BHs of appropriate sizes (reserve BHed space for update)
25         For Appel will require BH_1 to grow to size 2 when collected.
26
27 *************************************************************************/
28
29 \begin{code}
30
31 #define SCAN_REG_MAP
32 #include "SMinternal.h"
33
34 #if defined(_INFO_COMPACTING)
35
36 /* Define appropriate global variables as potential register variables */
37 /* Assume GC code saves and restores global registers used */
38
39 RegisterTable ScanRegTable;
40
41 #ifndef PAR
42 /* As we perform compaction, those CHP's which are still alive get
43    added to this list. [ADR] */
44 StgPtr NewMallocPtrList;
45 #endif /* !PAR */
46
47 P_
48 Inplace_Compaction(base, lim, scanbase, scanlim, bit_array, bit_array_words
49 #ifndef PAR
50 , MallocPtrList
51 #endif
52 )
53     P_  base;
54     P_  lim;
55     P_  scanbase;
56     P_  scanlim;
57     BitWord *bit_array;
58     I_  bit_array_words;
59 #ifndef PAR
60     StgPtr *MallocPtrList;
61 #endif
62 {
63     BitWord *bit_array_ptr, *bit_array_end;
64     P_ scan_w_start, info;
65     I_ size;
66
67     LinkLim = lim;  /* Only checked for generational collection */
68
69 #if defined(GCgn)
70
71     /* Scan collected new gen semi-space linking pointers to old gen */
72     /* No closures to unlink (no new ptrs will be linked)            */
73     /* Have to reset closure to unmarked if it has been marked       */
74     /* If not marked, we will still link (and unlink) as we need to  */
75     /*   get the size to find next closure.                          */
76     /*   It will be collected next minor collection as no root exists*/
77
78     DEBUG_SCAN("Scan Link Area: Base", scanbase, "Lim", scanlim);
79
80     Scan = scanbase;
81     New  = 0; /* unused -- except by debugging message */
82
83     while (Scan < scanlim) {
84         info = (P_) UNMARK_LOCATION(INFO_PTR(Scan));
85             Scan += (*SCAN_LINK_CODE(info))();
86         }
87 #endif /* GCgn */
88
89     DEBUG_SCAN("Scan Link Bits: Base", base, "Bits", bit_array);
90
91     bit_array_ptr = bit_array;
92     bit_array_end = bit_array + bit_array_words;
93     scan_w_start = base;
94     New = base; /* used to unwind */
95
96 #ifndef PAR
97     NewMallocPtrList = NULL; /* initialise new MallocPtrList */
98              /* As we move MallocPtrs over, we'll add them to this list. */
99 #endif /* !PAR */
100
101     while (bit_array_ptr < bit_array_end) {
102         BitWord w = *(bit_array_ptr++);
103
104         Scan = scan_w_start;
105         while (w) {
106
107             if (! (w & 0x1)) { /* bit not set */
108                 Scan++;        /* look at next bit */
109                 w >>= 1;
110
111             } else { /* Bit Set -- Enter ScanLink for closure */
112                 info = (P_) INFO_PTR(Scan);
113                 while (MARKED_LOCATION(info)) {
114                     P_ next;
115                     info = UNMARK_LOCATION(info);
116                     next = (P_) *info;
117                     DEBUG_UNLINK_LOCATION(info, Scan, New);
118                     *info = (W_) New;
119                     info = next;
120                 }
121                 INFO_PTR(Scan) = (W_) info;
122
123                 size = (*SCAN_LINK_CODE(info))();
124
125                 ASSERT( size >= 0 );
126                 New  += size;  /* set New address of next closure */
127
128                 Scan += size;  /* skip size bits */ 
129
130                 if (size >= BITS_IN(BitWord)) break;
131                     /* NOTA BENE: if size >= # bits in BitWord, then the result
132                         of this operation is undefined!  Hence the need for
133                         this break! */
134                 w >>= size;
135             }
136         }
137         scan_w_start += BITS_IN(BitWord);
138     }
139     DEBUG_SCAN("Scan Link Bits: End", Scan, "New", New);
140
141     bit_array_ptr = bit_array;
142     bit_array_end = bit_array + bit_array_words;
143     scan_w_start  = base;       /* Points to the heap word corresponding to the
144                                    first bit of *bit_array_ptr */
145
146     New = base; /* used to unwind and move */
147
148     DEBUG_SCAN("Scan Move Bits: Base", base, "Bits", bit_array);
149     while (bit_array_ptr < bit_array_end) {
150
151         /* Grab bit word and clear (its the last scan) */
152         /* Dont need to clear for Appel or Generational major collection */
153         /* Why not???  I think it's because they have a pass which zaps all
154            the bit array to zero.  But why do they need it?  Or, why
155            doesn't dual-mode need it? 
156
157            It's probably easier just to *always* to zap at the beginning of
158            GC, and remove this conditional compilation here.  */
159 #if defined(GCap) || defined(GCgn)
160         BitWord w = (I_) *(bit_array_ptr++);
161 #else
162         BitWord w = (I_) *bit_array_ptr;
163         *(bit_array_ptr++) = 0;
164 #endif
165
166         Scan = scan_w_start;
167         while (w) {
168             if (! (w & 0x1)) { /* bit not set */
169                 Scan++;        /* look at next bit */
170                 w >>= 1;
171
172             } else {    /* Bit Set -- Enter ScanMove for closure*/
173                 info = (P_) INFO_PTR(Scan);
174                 while (MARKED_LOCATION(info)) {
175                     P_ next;
176                     info = UNMARK_LOCATION(info);
177                     next = (P_) *info;
178                     DEBUG_UNLINK_LOCATION(info, Scan, New);
179                     *info = (W_) New;
180                     info = next;
181                 }
182                 INFO_PTR(New) = (W_) info;
183
184                 size = (*SCAN_MOVE_CODE(info))();
185                 New  += size;  /* set New address of next closure */
186                 Scan += size;  /* skip size bits */  
187
188                 if (size >= BITS_IN(BitWord)) break;
189                     /* NOTA BENE: if size >= # bits in BitWord, then the result
190                         of this operation is undefined!  Hence the need for
191                         this break! */
192                 w   >>= size;  /* NB: comment above about shifts */
193             }
194         }
195
196         /* At this point we've exhausted one word of mark bits */
197         /* Make scan_w_start point to the heap word corresponding to the
198            first bit of the next word of mark bits */
199         scan_w_start += BITS_IN(BitWord);
200     }
201     DEBUG_SCAN("Scan Link Bits: End", Scan, "New", New);
202
203 #ifdef PAR
204     RebuildLAGAtable();
205 #else
206     VALIDATE_MallocPtrList( NewMallocPtrList );
207     *MallocPtrList = NewMallocPtrList;
208 #endif /* PAR */
209
210     return(New);
211 }
212
213 \end{code}
214
215 /*************************************************************************
216                    Basic SCAN LINK and SCAN MOVE Routines
217
218 First Scan on Closures
219   _ScanLink_S_N
220
221   Retrieved using SCAN_LINK_CODE(infoptr)  (for a true unmarked infoptr)
222
223 Links the closure's ptr locations to the info pointer of the closure's
224 they actually point. Returns the size of the closure so New can be updated
225 to point to next closure. This also allows sequential scan (if there are no
226 holes i.e. it has already been collected).
227
228 Must first unwind the locations linked to this closure updating with
229 the new location of this closure before entering the code. The code
230 can only be access from the info pointer at the end of this location
231 list, which must be restored before entering.
232
233   Calling Conventions (After unwinding and updating locations pointed to):
234     Scan  -- points to this closure
235     LinkLim -- points to end of heap are requiring pointer to be linked
236
237     New (optional) -- points to the new location that this closure will reside
238                       this is only required for meaningful debugging meassge
239
240 Second Scan on Closures
241   _ScanMove_S
242
243   Retrieved using SCAN_MOVE_CODE(infoptr)  (for a true unmarked infoptr)
244  
245 Slides the closure down to its new location, New. Returns the size of
246 the closure so New can be updated to point to the next closure.
247
248 Must first unwind the locations linked to this closure updating with
249 the new location of this closure before entering the code. The code
250 can only be access from the info pointer at the end of this location
251 list, which must be restored before entering.
252
253   Calling Conventions (After unwinding and updating locations pointed to):
254     Scan  -- points to this closure
255     New   -- points to the new location that this closure will reside
256
257
258 Will have  MARKING  routines in info tables as well:
259
260 Marking A Closure: 
261   _PRStart_N
262
263   Retrieved using PRMARK_CODE(infoptr)
264
265 Returning To A Closure Being Marked:
266   _PRIn_I
267   _PRInLast_N
268
269   Retrieved using PRRETURN_CODE(infoptr)
270
271
272
273 May have  COPYING  routines in info tables as well:
274
275 Evacuation code:  _Evacuate_S
276 Scavenging code:  _Scavenge_S_N
277
278     See GCscav.lhc GCevac.lc
279
280
281
282 The following registers are used by the Compacting collection:
283
284 New     -- The new address of a closure
285 Scan    -- The current address of a closure
286 LinkLim -- The limit of the heap requiring to be linked & moved
287
288 **************************************************************************/
289
290 \begin{code}
291
292 #if defined(GCgn)
293 #define LINK_LOCATION(i) LINK_LOCATION_TO_CLOSURE((Scan+(i)),LinkLim)
294 #else /* ! GCgn */
295 #define LINK_LOCATION(i) LINK_LOCATION_TO_CLOSURE(Scan+(i))
296 #endif /* ! GCgn */
297
298 /* Link location of nth pointer in SPEC/STKO closure (starting at 1) */
299 #define SPEC_LINK_LOCATION(ptr) LINK_LOCATION((SPEC_HS-1) + (ptr))
300 #define STKO_LINK_LOCATION(ptr) LINK_LOCATION((STKO_HS-1) + (ptr))
301
302
303 /* Slide the ith word (starting at 0) */
304 #define SLIDE_WORD(position)    New[position] = Scan[position]
305
306 /* Slide the ith ptr (starting at 0), adjusting by offset */
307 #define ADJUST_WORD(pos,off)    ((PP_)New)[pos] += (off)
308
309 /* Slide the nth free var word in a SPEC closure (starting at 1) */
310 #define SPEC_SLIDE_WORD(n)      SLIDE_WORD((SPEC_HS-1) + (n))
311
312 #ifndef PAR
313 /* Don't slide the MallocPtr list link - instead link moved object into
314    @NewMallocPtrList@ */
315
316 #define MallocPtr_SLIDE_DATA \
317         MallocPtr_CLOSURE_DATA(New) = MallocPtr_CLOSURE_DATA(Scan)
318 #define MallocPtr_RELINK                                \
319 {                                                       \
320         MallocPtr_CLOSURE_LINK(New) = NewMallocPtrList; \
321         NewMallocPtrList = New;                         \
322 }
323 #endif /* !PAR */
324
325 /* The SLIDE_FIXED_HDR macro is dependent on the No of FIXED_HS */
326
327 #if FIXED_HS == 1
328 #define SLIDE_FIXED_HDR         /* Already Assigned INFO_PTR */
329 #else
330 #if FIXED_HS == 2
331 #define SLIDE_FIXED_HDR         SLIDE_WORD(1)
332 #else
333 #if FIXED_HS == 3
334 #define SLIDE_FIXED_HDR         SLIDE_WORD(1);SLIDE_WORD(2)
335 #else
336 /* I don't think this will be needed (ToDo: #error?) */
337 #endif                               
338 #endif                               
339 #endif                               
340
341
342 #if defined(DEBUG)
343
344 #define DEBUG_SCAN_LINK(type, sizevar, ptrvar) \
345     if (RTSflags.GcFlags.trace & DEBUG_TRACE_MINOR_GC)                  \
346         fprintf(stderr, "Scan Link (%s): 0x%lx -> 0x%lx, info 0x%lx, size %ld, ptrs %ld\n", \
347                 type, Scan, New, INFO_PTR(Scan), sizevar, ptrvar)
348
349 #define DEBUG_SCAN_MOVE(type, sizevar) \
350     if (RTSflags.GcFlags.trace & DEBUG_TRACE_MINOR_GC)            \
351         fprintf(stderr, "Scan Move (%s): 0x%lx -> 0x%lx, info 0x%lx, size %ld\n", \
352                 type, Scan, New, INFO_PTR(New), sizevar)
353
354
355 #else
356
357 #define DEBUG_SCAN_LINK(type, sizevar, ptrvar)
358 #define DEBUG_SCAN_MOVE(type, sizevar)
359
360 #endif
361
362 /*** LINKING CLOSURES ***/
363
364 #ifdef TICKY_TICKY
365 I_
366 _ScanLink_0_0(STG_NO_ARGS) {
367     I_ size = 0; /* NB: SPEC_VHS is *defined* to be zero */
368     DEBUG_SCAN_LINK("SPEC", size, 0);
369     return(FIXED_HS + size);
370 }
371 #endif
372
373 I_
374 _ScanLink_1_0(STG_NO_ARGS) {
375     I_ size = 1; /* NB: SPEC_VHS is *defined* to be zero */
376     DEBUG_SCAN_LINK("SPEC", size, 0);
377     return(FIXED_HS + size);
378 }
379 I_
380 _ScanLink_1_1(STG_NO_ARGS) {
381     I_ size = 1;
382     DEBUG_SCAN_LINK("SPEC", size, 1);
383     SPEC_LINK_LOCATION(1);
384     return(FIXED_HS + size);
385 }
386 I_
387 _ScanLink_2_0(STG_NO_ARGS) {
388     I_ size = 2;
389     DEBUG_SCAN_LINK("SPEC", size, 0);
390     return(FIXED_HS + size);
391 }
392 I_
393 _ScanLink_2_1(STG_NO_ARGS) {
394     I_ size = 2;
395     DEBUG_SCAN_LINK("SPEC", size, 1);
396     SPEC_LINK_LOCATION(1);
397     return(FIXED_HS + size);
398 }
399 I_
400 _ScanLink_2_2(STG_NO_ARGS) {
401     I_ size = 2;
402     DEBUG_SCAN_LINK("SPEC", size, 2);
403     SPEC_LINK_LOCATION(1);
404     SPEC_LINK_LOCATION(2);
405     return(FIXED_HS + size);
406 }
407 I_
408 _ScanLink_3_0(STG_NO_ARGS) {
409     I_ size = 3;
410     DEBUG_SCAN_LINK("SPEC", size, 0);
411     return(FIXED_HS + size);
412 }
413 I_
414 _ScanLink_3_1(STG_NO_ARGS) {
415     I_ size = 3;
416     DEBUG_SCAN_LINK("SPEC", size, 1);
417     SPEC_LINK_LOCATION(1);
418     return(FIXED_HS + size);
419 }
420 I_
421 _ScanLink_3_2(STG_NO_ARGS) {
422     I_ size = 3;
423     DEBUG_SCAN_LINK("SPEC", size, 2);
424     SPEC_LINK_LOCATION(1);
425     SPEC_LINK_LOCATION(2);
426     return(FIXED_HS + size);
427 }
428 I_
429 _ScanLink_3_3(STG_NO_ARGS) {
430     I_ size = 3;
431     DEBUG_SCAN_LINK("SPEC", size, 3);
432     SPEC_LINK_LOCATION(1);
433     SPEC_LINK_LOCATION(2);
434     SPEC_LINK_LOCATION(3);
435     return(FIXED_HS + size);
436 }
437 I_
438 _ScanLink_4_0(STG_NO_ARGS) {
439     I_ size = 4;
440     DEBUG_SCAN_LINK("SPEC", size, 0);
441     return(FIXED_HS + size);
442 }
443 I_
444 _ScanLink_4_4(STG_NO_ARGS) {
445     I_ size = 4;
446     DEBUG_SCAN_LINK("SPEC", size, 4);
447     SPEC_LINK_LOCATION(1);
448     SPEC_LINK_LOCATION(2);
449     SPEC_LINK_LOCATION(3);
450     SPEC_LINK_LOCATION(4);
451     return(FIXED_HS + size);
452 }
453 I_
454 _ScanLink_5_0(STG_NO_ARGS) {
455     I_ size = 5;
456     DEBUG_SCAN_LINK("SPEC", size, 0);
457     return(FIXED_HS + size);
458 }
459 I_
460 _ScanLink_5_5(STG_NO_ARGS) {
461     I_ size = 5;
462     DEBUG_SCAN_LINK("SPEC", size, 5);
463     SPEC_LINK_LOCATION(1);
464     SPEC_LINK_LOCATION(2);
465     SPEC_LINK_LOCATION(3);
466     SPEC_LINK_LOCATION(4);
467     SPEC_LINK_LOCATION(5);
468     return(FIXED_HS + size);
469 }
470 I_
471 _ScanLink_6_6(STG_NO_ARGS) {
472     I_ size = 6;
473     DEBUG_SCAN_LINK("SPEC", size, 6);
474     SPEC_LINK_LOCATION(1);
475     SPEC_LINK_LOCATION(2);
476     SPEC_LINK_LOCATION(3);
477     SPEC_LINK_LOCATION(4);
478     SPEC_LINK_LOCATION(5);
479     SPEC_LINK_LOCATION(6);
480     return(FIXED_HS + size);
481 }
482 I_
483 _ScanLink_7_7(STG_NO_ARGS) {
484     I_ size = 7;
485     DEBUG_SCAN_LINK("SPEC", size, 7);
486     SPEC_LINK_LOCATION(1);
487     SPEC_LINK_LOCATION(2);
488     SPEC_LINK_LOCATION(3);
489     SPEC_LINK_LOCATION(4);
490     SPEC_LINK_LOCATION(5);
491     SPEC_LINK_LOCATION(6);
492     SPEC_LINK_LOCATION(7);
493     return(FIXED_HS + size);
494 }
495 I_
496 _ScanLink_8_8(STG_NO_ARGS) {
497     I_ size = 8;
498     DEBUG_SCAN_LINK("SPEC", size, 8);
499     SPEC_LINK_LOCATION(1);
500     SPEC_LINK_LOCATION(2);
501     SPEC_LINK_LOCATION(3);
502     SPEC_LINK_LOCATION(4);
503     SPEC_LINK_LOCATION(5);
504     SPEC_LINK_LOCATION(6);
505     SPEC_LINK_LOCATION(7);
506     SPEC_LINK_LOCATION(8);
507     return(FIXED_HS + size);
508 }
509 I_
510 _ScanLink_9_9(STG_NO_ARGS) {
511     I_ size = 9;
512     DEBUG_SCAN_LINK("SPEC", size, 9);
513     SPEC_LINK_LOCATION(1);
514     SPEC_LINK_LOCATION(2);
515     SPEC_LINK_LOCATION(3);
516     SPEC_LINK_LOCATION(4);
517     SPEC_LINK_LOCATION(5);
518     SPEC_LINK_LOCATION(6);
519     SPEC_LINK_LOCATION(7);
520     SPEC_LINK_LOCATION(8);
521     SPEC_LINK_LOCATION(9);
522     return(FIXED_HS + size);
523 }
524 I_
525 _ScanLink_10_10(STG_NO_ARGS) {
526     I_ size = 10;
527     DEBUG_SCAN_LINK("SPEC", size, 10);
528     SPEC_LINK_LOCATION(1);
529     SPEC_LINK_LOCATION(2);
530     SPEC_LINK_LOCATION(3);
531     SPEC_LINK_LOCATION(4);
532     SPEC_LINK_LOCATION(5);
533     SPEC_LINK_LOCATION(6);
534     SPEC_LINK_LOCATION(7);
535     SPEC_LINK_LOCATION(8);
536     SPEC_LINK_LOCATION(9);
537     SPEC_LINK_LOCATION(10);
538     return(FIXED_HS + size);
539 }
540 I_
541 _ScanLink_11_11(STG_NO_ARGS) {
542     I_ size = 11;
543     DEBUG_SCAN_LINK("SPEC", size, 11);
544     SPEC_LINK_LOCATION(1);
545     SPEC_LINK_LOCATION(2);
546     SPEC_LINK_LOCATION(3);
547     SPEC_LINK_LOCATION(4);
548     SPEC_LINK_LOCATION(5);
549     SPEC_LINK_LOCATION(6);
550     SPEC_LINK_LOCATION(7);
551     SPEC_LINK_LOCATION(8);
552     SPEC_LINK_LOCATION(9);
553     SPEC_LINK_LOCATION(10);
554     SPEC_LINK_LOCATION(11);
555     return(FIXED_HS + size);
556 }
557 I_
558 _ScanLink_12_12(STG_NO_ARGS) {
559     I_ size = 12;
560     DEBUG_SCAN_LINK("SPEC", size, 12);
561     SPEC_LINK_LOCATION(1);
562     SPEC_LINK_LOCATION(2);
563     SPEC_LINK_LOCATION(3);
564     SPEC_LINK_LOCATION(4);
565     SPEC_LINK_LOCATION(5);
566     SPEC_LINK_LOCATION(6);
567     SPEC_LINK_LOCATION(7);
568     SPEC_LINK_LOCATION(8);
569     SPEC_LINK_LOCATION(9);
570     SPEC_LINK_LOCATION(10);
571     SPEC_LINK_LOCATION(11);
572     SPEC_LINK_LOCATION(12);
573     return(FIXED_HS + size);
574 }
575 \end{code}
576
577 Scan-linking revertible black holes with underlying @SPEC@ closures.
578
579 \begin{code}
580
581 #ifdef PAR
582 I_ 
583 _ScanLink_RBH_2_1(STG_NO_ARGS)
584 {
585     I_ size = 2 + SPEC_RBH_VHS;
586     DEBUG_SCAN_LINK("SRBH", size, 1);
587     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
588     return(FIXED_HS + size);
589 }
590 I_ 
591 _ScanLink_RBH_3_1(STG_NO_ARGS)
592 {
593     I_ size = 3 + SPEC_RBH_VHS;
594     DEBUG_SCAN_LINK("SRBH", size, 1);
595     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
596     return(FIXED_HS + size);
597 }
598 I_ 
599 _ScanLink_RBH_3_3(STG_NO_ARGS)
600 {
601     I_ size = 3 + SPEC_RBH_VHS;
602     DEBUG_SCAN_LINK("SRBH", size, 3);
603     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
604     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
605     return(FIXED_HS + size);
606 }
607 I_ 
608 _ScanLink_RBH_4_1(STG_NO_ARGS)
609 {
610     I_ size = 4 + SPEC_RBH_VHS;
611     DEBUG_SCAN_LINK("SRBH", size, 1);
612     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
613     return(FIXED_HS + size);
614 }
615 I_ 
616 _ScanLink_RBH_4_4(STG_NO_ARGS)
617 {
618     I_ size = 4 + SPEC_RBH_VHS;
619     DEBUG_SCAN_LINK("SRBH", size, 4);
620     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
621     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
622     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 2);
623     return(FIXED_HS + size);
624 }
625 I_ 
626 _ScanLink_RBH_5_1(STG_NO_ARGS)
627 {
628     I_ size = 5 + SPEC_RBH_VHS;
629     DEBUG_SCAN_LINK("SRBH", size, 1);
630     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
631     return(FIXED_HS + size);
632 }
633 I_ 
634 _ScanLink_RBH_5_5(STG_NO_ARGS)
635 {
636     I_ size = 5 + SPEC_RBH_VHS;
637     DEBUG_SCAN_LINK("SRBH", size, 5);
638     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
639     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
640     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 2);
641     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 3);
642     return(FIXED_HS + size);
643 }
644 I_ 
645 _ScanLink_RBH_6_6(STG_NO_ARGS)
646 {
647     I_ size = 6 + SPEC_RBH_VHS;
648     DEBUG_SCAN_LINK("SRBH", size, 6);
649     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
650     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
651     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 2);
652     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 3);
653     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 4);
654     return(FIXED_HS + size);
655 }
656 I_ 
657 _ScanLink_RBH_7_7(STG_NO_ARGS)
658 {
659     I_ size = 7 + SPEC_RBH_VHS;
660     DEBUG_SCAN_LINK("SRBH", size, 7);
661     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
662     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
663     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 2);
664     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 3);
665     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 4);
666     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 5);
667     return(FIXED_HS + size);
668 }
669 I_ 
670 _ScanLink_RBH_8_8(STG_NO_ARGS)
671 {
672     I_ size = 8 + SPEC_RBH_VHS;
673     DEBUG_SCAN_LINK("SRBH", size, 8);
674     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
675     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
676     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 2);
677     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 3);
678     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 4);
679     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 5);
680     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 6);
681     return(FIXED_HS + size);
682 }
683 I_ 
684 _ScanLink_RBH_9_9(STG_NO_ARGS)
685 {
686     I_ size = 9 + SPEC_RBH_VHS;
687     DEBUG_SCAN_LINK("SRBH", size, 9);
688     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
689     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
690     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 2);
691     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 3);
692     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 4);
693     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 5);
694     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 6);
695     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 7);
696     return(FIXED_HS + size);
697 }
698 I_ 
699 _ScanLink_RBH_10_10(STG_NO_ARGS)
700 {
701     I_ size = 10 + SPEC_RBH_VHS;
702     DEBUG_SCAN_LINK("SRBH", size, 10);
703     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
704     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
705     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 2);
706     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 3);
707     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 4);
708     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 5);
709     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 6);
710     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 7);
711     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 8);
712     return(FIXED_HS + size);
713 }
714 I_ 
715 _ScanLink_RBH_11_11(STG_NO_ARGS)
716 {
717     I_ size = 11 + SPEC_RBH_VHS;
718     DEBUG_SCAN_LINK("SRBH", size, 11);
719     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
720     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
721     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 2);
722     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 3);
723     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 4);
724     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 5);
725     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 6);
726     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 7);
727     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 8);
728     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 9);
729     return(FIXED_HS + size);
730 }
731 I_ 
732 _ScanLink_RBH_12_12(STG_NO_ARGS)
733 {
734     I_ size = 12 + SPEC_RBH_VHS;
735     DEBUG_SCAN_LINK("SRBH", size, 12);
736     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
737     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
738     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 2);
739     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 3);
740     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 4);
741     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 5);
742     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 6);
743     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 7);
744     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 8);
745     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 9);
746     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 10);
747     return(FIXED_HS + size);
748 }
749 #endif
750 \end{code}
751
752 Scan-linking a MallocPtr is straightforward: exactly the same as
753 @_ScanLink_[MallocPtr_SIZE]_0@.
754
755 \begin{code}
756 #ifndef PAR
757 I_
758 _ScanLink_MallocPtr(STG_NO_ARGS) {
759     I_ size = MallocPtr_SIZE;
760     DEBUG_SCAN_LINK("MallocPtr", size, 0);
761     return(FIXED_HS + size);
762 }
763 #endif /* !PAR */
764 \end{code}
765
766 Back to the main feature...
767
768 \begin{code}
769
770 /*** MOVING CLOSURES ***/
771
772 #ifdef TICKY_TICKY
773 I_
774 _ScanMove_0(STG_NO_ARGS) {
775     I_ size = 0; /* NB: SPEC_VHS defined to be zero, so 0 really is the "size" */
776     DEBUG_SCAN_MOVE("CONST", size);
777     SLIDE_FIXED_HDR;
778     return(FIXED_HS + size);
779 }
780 #endif
781 I_
782 _ScanMove_1(STG_NO_ARGS) {
783     I_ size = 1; /* NB: SPEC_VHS defined to be zero, so 1 really is the "size" */
784     DEBUG_SCAN_MOVE("SPEC", size);
785     SLIDE_FIXED_HDR;
786     SPEC_SLIDE_WORD(1);
787     return(FIXED_HS + size);
788 }
789 I_
790 _ScanMove_2(STG_NO_ARGS) {
791     I_ size = 2;
792     DEBUG_SCAN_MOVE("SPEC", size);
793     SLIDE_FIXED_HDR;
794     SPEC_SLIDE_WORD(1);
795     SPEC_SLIDE_WORD(2);
796     return(FIXED_HS + size);
797 }
798 I_
799 _ScanMove_3(STG_NO_ARGS) {
800     I_ size = 3;
801     DEBUG_SCAN_MOVE("SPEC", size);
802     SLIDE_FIXED_HDR;
803     SPEC_SLIDE_WORD(1);
804     SPEC_SLIDE_WORD(2);
805     SPEC_SLIDE_WORD(3);
806     return(FIXED_HS + size);
807 }
808 I_
809 _ScanMove_4(STG_NO_ARGS) {
810     I_ size = 4;
811     DEBUG_SCAN_MOVE("SPEC", size);
812     SLIDE_FIXED_HDR;
813     SPEC_SLIDE_WORD(1);
814     SPEC_SLIDE_WORD(2);
815     SPEC_SLIDE_WORD(3);
816     SPEC_SLIDE_WORD(4);
817     return(FIXED_HS + size);
818 }
819 I_
820 _ScanMove_5(STG_NO_ARGS) {
821     I_ size = 5;
822     DEBUG_SCAN_MOVE("SPEC", size);
823     SLIDE_FIXED_HDR;
824     SPEC_SLIDE_WORD(1);
825     SPEC_SLIDE_WORD(2);
826     SPEC_SLIDE_WORD(3);
827     SPEC_SLIDE_WORD(4);
828     SPEC_SLIDE_WORD(5);
829     return(FIXED_HS + size);
830 }
831 I_
832 _ScanMove_6(STG_NO_ARGS) {
833     I_ size = 6;
834     DEBUG_SCAN_MOVE("SPEC", size);
835     SLIDE_FIXED_HDR;
836     SPEC_SLIDE_WORD(1);
837     SPEC_SLIDE_WORD(2);
838     SPEC_SLIDE_WORD(3);
839     SPEC_SLIDE_WORD(4);
840     SPEC_SLIDE_WORD(5);
841     SPEC_SLIDE_WORD(6);
842     return(FIXED_HS + size);
843 }
844 I_
845 _ScanMove_7(STG_NO_ARGS) {
846     I_ size = 7;
847     DEBUG_SCAN_MOVE("SPEC", size);
848     SLIDE_FIXED_HDR;
849     SPEC_SLIDE_WORD(1);
850     SPEC_SLIDE_WORD(2);
851     SPEC_SLIDE_WORD(3);
852     SPEC_SLIDE_WORD(4);
853     SPEC_SLIDE_WORD(5);
854     SPEC_SLIDE_WORD(6);
855     SPEC_SLIDE_WORD(7);
856     return(FIXED_HS + size);
857 }
858 I_
859 _ScanMove_8(STG_NO_ARGS) {
860     I_ size = 8;
861     DEBUG_SCAN_MOVE("SPEC", size);
862     SLIDE_FIXED_HDR;
863     SPEC_SLIDE_WORD(1);
864     SPEC_SLIDE_WORD(2);
865     SPEC_SLIDE_WORD(3);
866     SPEC_SLIDE_WORD(4);
867     SPEC_SLIDE_WORD(5);
868     SPEC_SLIDE_WORD(6);
869     SPEC_SLIDE_WORD(7);
870     SPEC_SLIDE_WORD(8);
871     return(FIXED_HS + size);
872 }
873 I_
874 _ScanMove_9(STG_NO_ARGS) {
875     I_ size = 9;
876     DEBUG_SCAN_MOVE("SPEC", size);
877     SLIDE_FIXED_HDR;
878     SPEC_SLIDE_WORD(1);
879     SPEC_SLIDE_WORD(2);
880     SPEC_SLIDE_WORD(3);
881     SPEC_SLIDE_WORD(4);
882     SPEC_SLIDE_WORD(5);
883     SPEC_SLIDE_WORD(6);
884     SPEC_SLIDE_WORD(7);
885     SPEC_SLIDE_WORD(8);
886     SPEC_SLIDE_WORD(9);
887     return(FIXED_HS + size);
888 }
889 I_
890 _ScanMove_10(STG_NO_ARGS) {
891     I_ size = 10;
892     DEBUG_SCAN_MOVE("SPEC", size);
893     SLIDE_FIXED_HDR;
894     SPEC_SLIDE_WORD(1);
895     SPEC_SLIDE_WORD(2);
896     SPEC_SLIDE_WORD(3);
897     SPEC_SLIDE_WORD(4);
898     SPEC_SLIDE_WORD(5);
899     SPEC_SLIDE_WORD(6);
900     SPEC_SLIDE_WORD(7);
901     SPEC_SLIDE_WORD(8);
902     SPEC_SLIDE_WORD(9);
903     SPEC_SLIDE_WORD(10);
904     return(FIXED_HS + size);
905 }
906 I_
907 _ScanMove_11(STG_NO_ARGS) {
908     I_ size = 11;
909     DEBUG_SCAN_MOVE("SPEC", size);
910     SLIDE_FIXED_HDR;
911     SPEC_SLIDE_WORD(1);
912     SPEC_SLIDE_WORD(2);
913     SPEC_SLIDE_WORD(3);
914     SPEC_SLIDE_WORD(4);
915     SPEC_SLIDE_WORD(5);
916     SPEC_SLIDE_WORD(6);
917     SPEC_SLIDE_WORD(7);
918     SPEC_SLIDE_WORD(8);
919     SPEC_SLIDE_WORD(9);
920     SPEC_SLIDE_WORD(10);
921     SPEC_SLIDE_WORD(11);
922     return(FIXED_HS + size);
923 }
924 I_
925 _ScanMove_12(STG_NO_ARGS) {
926     I_ size = 12;
927     DEBUG_SCAN_MOVE("SPEC", size);
928     SLIDE_FIXED_HDR;
929     SPEC_SLIDE_WORD(1);
930     SPEC_SLIDE_WORD(2);
931     SPEC_SLIDE_WORD(3);
932     SPEC_SLIDE_WORD(4);
933     SPEC_SLIDE_WORD(5);
934     SPEC_SLIDE_WORD(6);
935     SPEC_SLIDE_WORD(7);
936     SPEC_SLIDE_WORD(8);
937     SPEC_SLIDE_WORD(9);
938     SPEC_SLIDE_WORD(10);
939     SPEC_SLIDE_WORD(11);
940     SPEC_SLIDE_WORD(12);
941     return(FIXED_HS + size);
942 }
943
944 #if defined(PAR) && defined(GC_MUT_REQUIRED)
945 I_
946 _ScanMove_RBH_2(STG_NO_ARGS) {
947     I_ size = 2 + SPEC_RBH_VHS;
948     DEBUG_SCAN_MOVE("SRBH", size);
949     SLIDE_FIXED_HDR;
950     SLIDE_WORD(SPEC_RBH_HS + 0);
951
952     /* Build new OldMutables list */
953     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
954     StorageMgrInfo.OldMutables = (P_) New;
955
956     return(FIXED_HS + size);
957 }
958 I_
959 _ScanMove_RBH_3(STG_NO_ARGS) {
960     I_ size = 3 + SPEC_RBH_VHS;
961     DEBUG_SCAN_MOVE("SRBH", size);
962     SLIDE_FIXED_HDR;
963     SLIDE_WORD(SPEC_RBH_HS + 0);
964     SLIDE_WORD(SPEC_RBH_HS + 1);
965
966     /* Build new OldMutables list */
967     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
968     StorageMgrInfo.OldMutables = (P_) New;
969
970     return(FIXED_HS + size);
971 }
972 I_
973 _ScanMove_RBH_4(STG_NO_ARGS) {
974     I_ size = 4 + SPEC_RBH_VHS;
975     DEBUG_SCAN_MOVE("SRBH", size);
976     SLIDE_FIXED_HDR;
977     SLIDE_WORD(SPEC_RBH_HS + 0);
978     SLIDE_WORD(SPEC_RBH_HS + 1);
979     SLIDE_WORD(SPEC_RBH_HS + 2);
980
981     /* Build new OldMutables list */
982     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
983     StorageMgrInfo.OldMutables = (P_) New;
984
985     return(FIXED_HS + size);
986 }
987 I_
988 _ScanMove_RBH_5(STG_NO_ARGS) {
989     I_ size = 5 + SPEC_RBH_VHS;
990     DEBUG_SCAN_MOVE("SRBH", size);
991     SLIDE_FIXED_HDR;
992     SLIDE_WORD(SPEC_RBH_HS + 0);
993     SLIDE_WORD(SPEC_RBH_HS + 1);
994     SLIDE_WORD(SPEC_RBH_HS + 2);
995     SLIDE_WORD(SPEC_RBH_HS + 3);
996
997     /* Build new OldMutables list */
998     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
999     StorageMgrInfo.OldMutables = (P_) New;
1000
1001     return(FIXED_HS + size);
1002 }
1003 I_
1004 _ScanMove_RBH_6(STG_NO_ARGS) {
1005     I_ size = 6 + SPEC_RBH_VHS;
1006     DEBUG_SCAN_MOVE("SRBH", size);
1007     SLIDE_FIXED_HDR;
1008     SLIDE_WORD(SPEC_RBH_HS + 0);
1009     SLIDE_WORD(SPEC_RBH_HS + 1);
1010     SLIDE_WORD(SPEC_RBH_HS + 2);
1011     SLIDE_WORD(SPEC_RBH_HS + 3);
1012     SLIDE_WORD(SPEC_RBH_HS + 4);
1013
1014     /* Build new OldMutables list */
1015     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1016     StorageMgrInfo.OldMutables = (P_) New;
1017
1018     return(FIXED_HS + size);
1019 }
1020 I_
1021 _ScanMove_RBH_7(STG_NO_ARGS) {
1022     I_ size = 7 + SPEC_RBH_VHS;
1023     DEBUG_SCAN_MOVE("SRBH", size);
1024     SLIDE_FIXED_HDR;
1025     SLIDE_WORD(SPEC_RBH_HS + 0);
1026     SLIDE_WORD(SPEC_RBH_HS + 1);
1027     SLIDE_WORD(SPEC_RBH_HS + 2);
1028     SLIDE_WORD(SPEC_RBH_HS + 3);
1029     SLIDE_WORD(SPEC_RBH_HS + 4);
1030     SLIDE_WORD(SPEC_RBH_HS + 5);
1031
1032     /* Build new OldMutables list */
1033     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1034     StorageMgrInfo.OldMutables = (P_) New;
1035
1036     return(FIXED_HS + size);
1037 }
1038 I_
1039 _ScanMove_RBH_8(STG_NO_ARGS) {
1040     I_ size = 8 + SPEC_RBH_VHS;
1041     DEBUG_SCAN_MOVE("SRBH", size);
1042     SLIDE_FIXED_HDR;
1043     SLIDE_WORD(SPEC_RBH_HS + 0);
1044     SLIDE_WORD(SPEC_RBH_HS + 1);
1045     SLIDE_WORD(SPEC_RBH_HS + 2);
1046     SLIDE_WORD(SPEC_RBH_HS + 3);
1047     SLIDE_WORD(SPEC_RBH_HS + 4);
1048     SLIDE_WORD(SPEC_RBH_HS + 5);
1049     SLIDE_WORD(SPEC_RBH_HS + 6);
1050
1051     /* Build new OldMutables list */
1052     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1053     StorageMgrInfo.OldMutables = (P_) New;
1054
1055     return(FIXED_HS + size);
1056 }
1057 I_
1058 _ScanMove_RBH_9(STG_NO_ARGS) {
1059     I_ size = 9 + SPEC_RBH_VHS;
1060     DEBUG_SCAN_MOVE("SRBH", size);
1061     SLIDE_FIXED_HDR;
1062     SLIDE_WORD(SPEC_RBH_HS + 0);
1063     SLIDE_WORD(SPEC_RBH_HS + 1);
1064     SLIDE_WORD(SPEC_RBH_HS + 2);
1065     SLIDE_WORD(SPEC_RBH_HS + 3);
1066     SLIDE_WORD(SPEC_RBH_HS + 4);
1067     SLIDE_WORD(SPEC_RBH_HS + 5);
1068     SLIDE_WORD(SPEC_RBH_HS + 6);
1069     SLIDE_WORD(SPEC_RBH_HS + 7);
1070
1071     /* Build new OldMutables list */
1072     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1073     StorageMgrInfo.OldMutables = (P_) New;
1074
1075     return(FIXED_HS + size);
1076 }
1077 I_
1078 _ScanMove_RBH_10(STG_NO_ARGS) {
1079     I_ size = 10 + SPEC_RBH_VHS;
1080     DEBUG_SCAN_MOVE("SRBH", size);
1081     SLIDE_FIXED_HDR;
1082     SLIDE_WORD(SPEC_RBH_HS + 0);
1083     SLIDE_WORD(SPEC_RBH_HS + 1);
1084     SLIDE_WORD(SPEC_RBH_HS + 2);
1085     SLIDE_WORD(SPEC_RBH_HS + 3);
1086     SLIDE_WORD(SPEC_RBH_HS + 4);
1087     SLIDE_WORD(SPEC_RBH_HS + 5);
1088     SLIDE_WORD(SPEC_RBH_HS + 6);
1089     SLIDE_WORD(SPEC_RBH_HS + 7);
1090     SLIDE_WORD(SPEC_RBH_HS + 8);
1091
1092     /* Build new OldMutables list */
1093     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1094     StorageMgrInfo.OldMutables = (P_) New;
1095
1096     return(FIXED_HS + size);
1097 }
1098 I_
1099 _ScanMove_RBH_11(STG_NO_ARGS) {
1100     I_ size = 11 + SPEC_RBH_VHS;
1101     DEBUG_SCAN_MOVE("SRBH", size);
1102     SLIDE_FIXED_HDR;
1103     SLIDE_WORD(SPEC_RBH_HS + 0);
1104     SLIDE_WORD(SPEC_RBH_HS + 1);
1105     SLIDE_WORD(SPEC_RBH_HS + 2);
1106     SLIDE_WORD(SPEC_RBH_HS + 3);
1107     SLIDE_WORD(SPEC_RBH_HS + 4);
1108     SLIDE_WORD(SPEC_RBH_HS + 5);
1109     SLIDE_WORD(SPEC_RBH_HS + 6);
1110     SLIDE_WORD(SPEC_RBH_HS + 7);
1111     SLIDE_WORD(SPEC_RBH_HS + 8);
1112     SLIDE_WORD(SPEC_RBH_HS + 9);
1113
1114     /* Build new OldMutables list */
1115     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1116     StorageMgrInfo.OldMutables = (P_) New;
1117
1118     return(FIXED_HS + size);
1119 }
1120 I_
1121 _ScanMove_RBH_12(STG_NO_ARGS) {
1122     I_ size = 12 + SPEC_RBH_VHS;
1123     DEBUG_SCAN_MOVE("SRBH", size);
1124     SLIDE_FIXED_HDR;
1125     SLIDE_WORD(SPEC_RBH_HS + 0);
1126     SLIDE_WORD(SPEC_RBH_HS + 1);
1127     SLIDE_WORD(SPEC_RBH_HS + 2);
1128     SLIDE_WORD(SPEC_RBH_HS + 3);
1129     SLIDE_WORD(SPEC_RBH_HS + 4);
1130     SLIDE_WORD(SPEC_RBH_HS + 5);
1131     SLIDE_WORD(SPEC_RBH_HS + 6);
1132     SLIDE_WORD(SPEC_RBH_HS + 7);
1133     SLIDE_WORD(SPEC_RBH_HS + 8);
1134     SLIDE_WORD(SPEC_RBH_HS + 9);
1135     SLIDE_WORD(SPEC_RBH_HS + 10);
1136
1137     /* Build new OldMutables list */
1138     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1139     StorageMgrInfo.OldMutables = (P_) New;
1140
1141     return(FIXED_HS + size);
1142 }
1143 #endif
1144 \end{code}
1145
1146 Moving a Malloc Pointer is a little tricky: we want to copy the actual
1147 pointer unchanged (easy) but we want to link the MallocPtr into the
1148 new MallocPtr list.
1149
1150 \begin{code}
1151 #ifndef PAR
1152 I_
1153 _ScanMove_MallocPtr(STG_NO_ARGS) {
1154     I_ size = MallocPtr_SIZE;
1155     DEBUG_SCAN_MOVE("MallocPtr", size);
1156
1157 #if defined(DEBUG)
1158     if (RTSflags.GcFlags.trace & DEBUG_TRACE_MALLOCPTRS) {
1159       printf("Moving MallocPtr(%x)=<%x,%x,%x>", Scan, Scan[0], Scan[1], Scan[2]);
1160       printf(" Data = %x, Next = %x\n", 
1161              MallocPtr_CLOSURE_DATA(Scan), MallocPtr_CLOSURE_LINK(Scan) );
1162     }
1163 #endif
1164
1165     SLIDE_FIXED_HDR;
1166     MallocPtr_SLIDE_DATA;
1167     MallocPtr_RELINK;
1168
1169 #if defined(DEBUG)
1170     if (RTSflags.GcFlags.trace & DEBUG_TRACE_MALLOCPTRS) {
1171       printf("Moved MallocPtr(%x)=<%x,_,%x,%x,%x>", New, New[0], New[1], New[2], New[3]);
1172       printf(" Data = %x, Next = %x", 
1173              MallocPtr_CLOSURE_DATA(New), MallocPtr_CLOSURE_LINK(New) );
1174       printf(", NewMallocPtrList = %x\n", NewMallocPtrList );
1175     }
1176 #endif
1177
1178     return(FIXED_HS + size);
1179 }
1180 #endif /* !PAR */
1181 \end{code}
1182
1183 Now back to the main feature...
1184
1185 \begin{code}
1186
1187 /*** GENERIC Linking and Marking Routines */
1188
1189 I_
1190 _ScanLink_S_N(STG_NO_ARGS) {
1191     I_ count = GEN_HS - 1;
1192                    /* Offset of first ptr word, less 1 */
1193     I_ ptrs  = count + GEN_CLOSURE_NoPTRS(Scan);
1194                    /* Offset of last ptr word */
1195     I_ size  = GEN_CLOSURE_SIZE(Scan);
1196
1197     DEBUG_SCAN_LINK("GEN ", size, ptrs);
1198     while (++count <= ptrs) {
1199         LINK_LOCATION(count);
1200     }
1201     return(FIXED_HS + size);
1202 }
1203
1204 I_
1205 _ScanMove_S(STG_NO_ARGS) {
1206     I_ count = FIXED_HS - 1;
1207     I_ size  = GEN_CLOSURE_SIZE(New);
1208
1209     DEBUG_SCAN_MOVE("GEN ", size);
1210
1211     SLIDE_FIXED_HDR;
1212     while (++count <= size + (FIXED_HS - 1)) {
1213         SLIDE_WORD(count);
1214     }
1215     return(FIXED_HS + size);
1216 }
1217
1218 \end{code}
1219
1220 The linking code for revertible black holes with underlying @GEN@ closures.
1221
1222 \begin{code}
1223 #ifdef PAR
1224
1225 I_ 
1226 _ScanLink_RBH_N(STG_NO_ARGS)
1227 {
1228     I_ count = GEN_RBH_HS - 1;  /* Offset of first ptr word, less 1 */
1229     I_ ptrs  = GEN_RBH_CLOSURE_NoPTRS(Scan);
1230     I_ size  = GEN_RBH_CLOSURE_SIZE(Scan);
1231
1232     /* 
1233      * Get pointer count from original closure and adjust for one pointer 
1234      * in the first two words of the RBH.
1235      */
1236     if (ptrs < 2)
1237         ptrs = 1;
1238     else
1239         ptrs--;
1240
1241     ptrs += count;          /* Offset of last ptr word */
1242
1243     DEBUG_SCAN_LINK("GRBH", size, ptrs);
1244     while (++count <= ptrs) {
1245         LINK_LOCATION(count);
1246     }
1247     return(FIXED_HS + size);
1248 }
1249
1250 #ifdef GC_MUT_REQUIRED
1251
1252 I_
1253 _ScanMove_RBH_S(STG_NO_ARGS) {
1254     I_ count = GEN_RBH_HS - 1;
1255     I_ size  = GEN_RBH_CLOSURE_SIZE(New);
1256
1257     DEBUG_SCAN_MOVE("GRBH", size);
1258
1259     SLIDE_FIXED_HDR;
1260     while (++count <= size + (FIXED_HS - 1)) {
1261         SLIDE_WORD(count);
1262     }
1263
1264     /* Build new OldMutables list */
1265     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1266     StorageMgrInfo.OldMutables = (P_) New;
1267
1268     return(FIXED_HS + size);
1269 }
1270
1271 #endif
1272
1273 #endif
1274
1275 \end{code}
1276
1277 \begin{code}
1278 I_
1279 _ScanLink_Dyn(STG_NO_ARGS) {
1280     I_ count = DYN_HS - 1;
1281                    /* Offset of first ptr word, less 1 */
1282     I_ ptrs = count + DYN_CLOSURE_NoPTRS(Scan);
1283                    /* Offset of last ptr word */
1284     I_ size = DYN_CLOSURE_SIZE(Scan);
1285
1286     DEBUG_SCAN_LINK("DYN ", size, ptrs-count);
1287
1288     while (++count <= ptrs) {
1289         LINK_LOCATION(count);
1290     }
1291     return(FIXED_HS + size);
1292 }
1293
1294 I_
1295 _ScanMove_Dyn(STG_NO_ARGS) {
1296     I_ count = FIXED_HS - 1;
1297     I_ size  = DYN_CLOSURE_SIZE(Scan);
1298
1299     DEBUG_SCAN_MOVE("DYN ", size);
1300
1301     SLIDE_FIXED_HDR;
1302     while (++count <= size + (FIXED_HS - 1)) {
1303         SLIDE_WORD(count);
1304     }
1305     return(FIXED_HS + size);
1306 }
1307
1308 I_
1309 _ScanLink_Tuple(STG_NO_ARGS) {
1310     I_ count = TUPLE_HS - 1;
1311                    /* Offset of first ptr word, less 1 */
1312     I_ ptrs = count + TUPLE_CLOSURE_NoPTRS(Scan);
1313                    /* Offset of last ptr word */
1314     I_ size = TUPLE_CLOSURE_SIZE(Scan);
1315
1316     DEBUG_SCAN_LINK("TUPL", size, ptrs-count);
1317
1318     while (++count <= ptrs) {
1319         LINK_LOCATION(count);
1320     }
1321     return(FIXED_HS + size);
1322 }
1323
1324 I_
1325 _ScanMove_Tuple(STG_NO_ARGS) {
1326     I_ count = FIXED_HS - 1;
1327     I_ size  = TUPLE_CLOSURE_SIZE(Scan);
1328
1329     DEBUG_SCAN_MOVE("TUPL", size);
1330
1331     SLIDE_FIXED_HDR;
1332     while (++count <= size + (FIXED_HS - 1)) {
1333         SLIDE_WORD(count);
1334     }
1335     return(FIXED_HS + size);
1336 }
1337
1338 /*** MUTUPLE CLOSURE -- NO PTRS STORED IN CLOSURE -- NO DATA ***/
1339 /*             Only if special GC treatment required           */
1340
1341 #ifdef GC_MUT_REQUIRED
1342 I_
1343 _ScanLink_MuTuple(STG_NO_ARGS) {
1344     I_ count = MUTUPLE_HS - 1;
1345                    /* Offset of first ptr word, less 1 */
1346     I_ ptrs = count + MUTUPLE_CLOSURE_NoPTRS(Scan);
1347                    /* Offset of last ptr word */
1348     I_ size = MUTUPLE_CLOSURE_SIZE(Scan);
1349
1350     DEBUG_SCAN_LINK("MUT ", size, ptrs-count);
1351
1352     while (++count <= ptrs) {
1353         LINK_LOCATION(count);
1354     }
1355     return(FIXED_HS + size);
1356 }
1357
1358 I_
1359 _ScanMove_MuTuple(STG_NO_ARGS) {
1360     I_ count = FIXED_HS - 1;
1361     I_ size  = MUTUPLE_CLOSURE_SIZE(Scan);
1362
1363     DEBUG_SCAN_MOVE("MUT ", size);
1364
1365     SLIDE_FIXED_HDR;
1366     while (++count <= size + (FIXED_HS - 1)) {
1367         SLIDE_WORD(count);
1368     }
1369
1370     /* Build new OldMutables list */
1371     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1372     StorageMgrInfo.OldMutables = (P_) New;
1373
1374     return(FIXED_HS + size);
1375 }
1376
1377 I_
1378 _ScanMove_ImmuTuple(STG_NO_ARGS) {
1379     I_ count = FIXED_HS - 1;
1380     I_ size  = MUTUPLE_CLOSURE_SIZE(Scan);
1381
1382     DEBUG_SCAN_MOVE("IMUT", size);
1383
1384     SLIDE_FIXED_HDR;
1385     while (++count <= size + (FIXED_HS - 1)) {
1386         SLIDE_WORD(count);
1387     }
1388
1389     /* Dont add to OldMutables list */
1390
1391     return(FIXED_HS + size);
1392 }
1393 #endif /* GCap || GCgn */
1394
1395
1396 I_
1397 _ScanLink_Data(STG_NO_ARGS) {
1398     I_ size  = DATA_CLOSURE_SIZE(Scan);
1399     DEBUG_SCAN_LINK("DATA", size, 0);
1400     return(FIXED_HS + size);
1401 }
1402
1403 I_
1404 _ScanMove_Data(STG_NO_ARGS) {
1405     I_ count = FIXED_HS - 1;
1406     I_ size  = DATA_CLOSURE_SIZE(Scan);
1407
1408     DEBUG_SCAN_MOVE("DATA", size);
1409
1410     SLIDE_FIXED_HDR;
1411     while (++count <= size + (FIXED_HS - 1)) {
1412         SLIDE_WORD(count);
1413     }
1414     return(FIXED_HS + size);
1415 }
1416
1417
1418 I_
1419 _ScanLink_BH_U(STG_NO_ARGS) {
1420     I_ size = BH_U_SIZE;
1421     DEBUG_SCAN_LINK("BH  ", size, 0);
1422     return(FIXED_HS + size);
1423 }
1424
1425 I_
1426 _ScanMove_BH_U(STG_NO_ARGS) {
1427     I_ size = BH_U_SIZE;
1428     DEBUG_SCAN_MOVE("BH  ", size);
1429     SLIDE_FIXED_HDR;
1430     return(FIXED_HS + size);
1431 }
1432
1433 I_
1434 _ScanLink_BH_N(STG_NO_ARGS) {
1435     I_ size = BH_N_SIZE;
1436     DEBUG_SCAN_LINK("BH N", size, 0);
1437     return(FIXED_HS + size);
1438 }
1439
1440 I_
1441 _ScanMove_BH_N(STG_NO_ARGS) {
1442     I_ size = BH_N_SIZE;
1443     DEBUG_SCAN_MOVE("BH N", size);
1444     SLIDE_FIXED_HDR;
1445     return(FIXED_HS + size);
1446 }
1447
1448 #if defined(PROFILING) || defined(TICKY_TICKY)
1449 I_
1450 _ScanLink_PI(STG_NO_ARGS) {
1451     I_ size = IND_CLOSURE_SIZE(dummy);
1452     DEBUG_SCAN_LINK("PI  ", size, 1);
1453     LINK_LOCATION(IND_HS);
1454     return(FIXED_HS + size);
1455 }
1456
1457 I_
1458 _ScanMove_PI(STG_NO_ARGS) {
1459     I_ size = IND_CLOSURE_SIZE(dummy);
1460     DEBUG_SCAN_MOVE("PI  ", size);
1461     SLIDE_FIXED_HDR;
1462     SLIDE_WORD(IND_HS);
1463     return(FIXED_HS + size);
1464 }
1465 #endif
1466
1467 \end{code}
1468
1469 Linking and Marking Routines for FetchMes and stack objects.
1470
1471 \begin{code}
1472
1473 #if defined(CONCURRENT)
1474
1475 #if defined(PAR)
1476
1477 I_
1478 _ScanLink_FetchMe(STG_NO_ARGS) {
1479     I_ size = FETCHME_CLOSURE_SIZE(dummy);
1480     DEBUG_SCAN_LINK("FME ", size, 0);
1481     return(FIXED_HS + size);
1482 }
1483
1484 I_
1485 _ScanMove_FetchMe(STG_NO_ARGS) {
1486     I_ size = FETCHME_CLOSURE_SIZE(dummy);
1487     DEBUG_SCAN_MOVE("FME ", size);
1488     SLIDE_FIXED_HDR;
1489     SLIDE_WORD(FETCHME_GA_LOCN);
1490     ASSERT(GALAlookup(FETCHME_GA(New)) != NULL);
1491
1492 #ifdef GC_MUT_REQUIRED
1493     /* Build new OldMutables list */
1494     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1495     StorageMgrInfo.OldMutables = (P_) New;
1496 #endif
1497
1498     return(FIXED_HS + size);
1499 }
1500
1501 I_
1502 _ScanLink_BF(STG_NO_ARGS) 
1503 {
1504     I_ size = BF_CLOSURE_SIZE(dummy);
1505     DEBUG_SCAN_LINK("BF", size, 2);
1506
1507     LINK_LOCATION(BF_LINK_LOCN);
1508     LINK_LOCATION(BF_NODE_LOCN);
1509     return(FIXED_HS + size);
1510 }
1511
1512 I_
1513 _ScanMove_BF(STG_NO_ARGS) 
1514 {
1515     I_ count;
1516     I_ size = BF_CLOSURE_SIZE(dummy);
1517
1518     SLIDE_FIXED_HDR;
1519     for (count = FIXED_HS; count < FIXED_HS + BF_VHS; count++) {
1520         SLIDE_WORD(count);
1521     }
1522     SLIDE_WORD(BF_LINK_LOCN);
1523     SLIDE_WORD(BF_NODE_LOCN);
1524     SLIDE_WORD(BF_GTID_LOCN);
1525     SLIDE_WORD(BF_SLOT_LOCN);
1526     SLIDE_WORD(BF_WEIGHT_LOCN);
1527
1528 #ifdef GC_MUT_REQUIRED
1529     /* Build new OldMutables list */
1530     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1531     StorageMgrInfo.OldMutables = (P_) New;
1532 #endif
1533
1534     return(FIXED_HS + size);
1535 }
1536
1537 #endif  /* PAR */
1538
1539 I_
1540 _ScanLink_BQ(STG_NO_ARGS) {
1541     I_ size = BQ_CLOSURE_SIZE(dummy);
1542     DEBUG_SCAN_LINK("BQ  ", size, BQ_CLOSURE_NoPTRS(Scan));
1543     LINK_LOCATION(BQ_HS);
1544     return(FIXED_HS + size);
1545 }
1546
1547 I_
1548 _ScanMove_BQ(STG_NO_ARGS) {
1549     I_ size = BQ_CLOSURE_SIZE(dummy);
1550     DEBUG_SCAN_MOVE("BQ  ", size);
1551
1552     SLIDE_FIXED_HDR;
1553     SLIDE_WORD(BQ_HS);
1554
1555 #ifdef GC_MUT_REQUIRED
1556     /* Build new OldMutables list */
1557     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1558     StorageMgrInfo.OldMutables = (P_) New;
1559 #endif
1560
1561     return(FIXED_HS + size);
1562 }
1563
1564 I_
1565 _ScanLink_TSO(STG_NO_ARGS) 
1566 {
1567     STGRegisterTable *r = TSO_INTERNAL_PTR(Scan);
1568     W_ liveness = r->rLiveness;
1569     I_ i;
1570     I_ size = TSO_VHS + TSO_CTS_SIZE;
1571
1572     DEBUG_SCAN_LINK("TSO", size, 0/*wrong*/);
1573
1574     LINK_LOCATION(TSO_LINK_LOCN);
1575     LINK_LOCATION(((P_) &r->rStkO) - Scan);
1576     for(i = 0; liveness != 0; liveness >>= 1, i++) {
1577         if (liveness & 1) {
1578             LINK_LOCATION(((P_) &r->rR[i].p) - Scan)
1579         }
1580     }
1581     return(FIXED_HS + size);
1582 }
1583
1584 I_
1585 _ScanMove_TSO(STG_NO_ARGS) 
1586 {
1587     I_ count;
1588     I_ size = TSO_VHS + TSO_CTS_SIZE;
1589
1590     SLIDE_FIXED_HDR;
1591     for (count = FIXED_HS; count < FIXED_HS + TSO_VHS; count++) {
1592         SLIDE_WORD(count);
1593     }
1594
1595     for(count = 0; count < BYTES_TO_STGWORDS(sizeof(STGRegisterTable)); count++)
1596         /* Do it this way in case there's a shift of just one word */
1597         ((P_) TSO_INTERNAL_PTR(New))[count] = ((P_) TSO_INTERNAL_PTR(Scan))[count];
1598
1599 #ifdef GC_MUT_REQUIRED
1600     /* Build new OldMutables list */
1601     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1602     StorageMgrInfo.OldMutables = (P_) New;
1603 #endif
1604
1605     return(FIXED_HS + size);
1606 }
1607
1608 I_
1609 _ScanLink_StkO(STG_NO_ARGS) {
1610     I_ count;
1611     I_ size = STKO_CLOSURE_SIZE(Scan);
1612     I_ cts_size = STKO_CLOSURE_CTS_SIZE(Scan);
1613     I_ sub = STKO_SuB_OFFSET(Scan);     /* Offset of first update frame in B stack */
1614
1615     /* Link the link */
1616     LINK_LOCATION(STKO_LINK_LOCN);
1617
1618     /* Link the locations in the A stack */
1619     DEBUG_SCAN_LINK("STKO", size, cts_size - STKO_SpA_OFFSET(Scan) + 1);
1620     for (count = STKO_SpA_OFFSET(Scan); count <= cts_size; count++) {
1621         STKO_LINK_LOCATION(count);
1622     }
1623
1624     /* Now link the updatees in the update stack */
1625     while(sub > 0) {
1626         P_ subptr;
1627
1628         STKO_LINK_LOCATION(sub + BREL(UF_UPDATEE));
1629         subptr = GRAB_SuB(STKO_CLOSURE_ADDR(Scan,sub));
1630         sub = STKO_CLOSURE_OFFSET(Scan, subptr);
1631     }
1632
1633     ASSERT(sanityChk_StkO(Scan));
1634
1635     return(FIXED_HS + size);
1636 }
1637
1638 /* We move first and then repair, so that we can handle an overlapping source 
1639    and destination.
1640  */
1641
1642 I_
1643 _ScanMove_StkO(STG_NO_ARGS) {
1644     I_ count;
1645     I_ size  = STKO_CLOSURE_SIZE(Scan);
1646     I_ cts_size   = STKO_CLOSURE_CTS_SIZE(Scan);
1647     I_ spa_offset = STKO_SpA_OFFSET(Scan);
1648     I_ spb_offset = STKO_SpB_OFFSET(Scan);
1649     I_ sub_offset = STKO_SuB_OFFSET(Scan);
1650     I_ offset;
1651     
1652     DEBUG_SCAN_MOVE("STKO", size);
1653
1654     SLIDE_FIXED_HDR;
1655 #ifdef TICKY_TICKY
1656     SLIDE_WORD(STKO_ADEP_LOCN);
1657     SLIDE_WORD(STKO_BDEP_LOCN);
1658 #endif
1659     SLIDE_WORD(STKO_SIZE_LOCN);
1660     SLIDE_WORD(STKO_RETURN_LOCN);
1661     SLIDE_WORD(STKO_LINK_LOCN);
1662
1663     /* Adjust the four stack pointers...*IN ORDER* */
1664     offset = New - Scan;
1665     STKO_SuB(New) = STKO_SuB(Scan) + offset;
1666     STKO_SpB(New) = STKO_SpB(Scan) + offset;
1667     STKO_SpA(New) = STKO_SpA(Scan) + offset;
1668     STKO_SuA(New) = STKO_SuA(Scan) + offset;
1669
1670     /* Slide the B stack */
1671     for (count = 1; count <= spb_offset; count++) {
1672         SLIDE_WORD((STKO_HS-1) + count);
1673     }
1674
1675     /* Slide the A stack */
1676     for (count = spa_offset; count <= cts_size; count++) {
1677         SLIDE_WORD((STKO_HS-1) + count);
1678     }
1679
1680     /* Repair internal pointers */
1681     while (sub_offset > 0) {
1682             P_ subptr;
1683             ADJUST_WORD((STKO_HS-1) + sub_offset + BREL(UF_SUA),offset);
1684             ADJUST_WORD((STKO_HS-1) + sub_offset + BREL(UF_SUB),offset);
1685             subptr = GRAB_SuB(STKO_CLOSURE_ADDR(New,sub_offset));
1686             sub_offset = STKO_CLOSURE_OFFSET(New, subptr);
1687     }
1688
1689 #ifdef GC_MUT_REQUIRED
1690     /* Build new OldMutables list */
1691     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1692     StorageMgrInfo.OldMutables = (P_) New;
1693 #endif
1694
1695     /* ToDo: ASSERT(sanityChk_StkO(Scan or New)); ??? */
1696
1697     return(FIXED_HS + size);
1698 }
1699
1700 #endif /* CONCURRENT */
1701
1702 \end{code}
1703
1704 \begin{code}
1705 /*** Dummy Entries -- Should not be entered ***/
1706
1707 /* Should not be in a .lc file either...  --JSM */
1708
1709 STGFUN(_Dummy_Static_entry) {
1710     fprintf(stderr,"Called _Dummy_Static_entry\nShould never occur!\n");
1711     abort();
1712 }
1713
1714 STGFUN(_Dummy_Ind_entry) {
1715     fprintf(stderr,"Called _Dummy_Ind_entry\nShould never occur!\n");
1716     abort();
1717 }
1718
1719 STGFUN(_Dummy_Caf_entry) {
1720     fprintf(stderr,"Called _Dummy_Caf_Ind_entry\nShould never occur!\n");
1721     abort();
1722 }
1723
1724 STGFUN(_Dummy_Const_entry) {
1725     fprintf(stderr,"Called _Dummy_Const_entry\nShould never occur!\n");
1726     abort();
1727 }
1728
1729 STGFUN(_Dummy_CharLike_entry) {
1730     fprintf(stderr,"Called _Dummy_CharLike_entry\nShould never occur!\n");
1731     abort();
1732 }
1733
1734 #endif /* _INFO_COMPACTING */
1735 \end{code}