[project @ 1998-11-26 09:17:22 by sof]
[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 ForeignObjs which are still alive get
43    added to this list. [ADR] */
44 StgPtr NewForeignObjList;
45 #endif /* !PAR */
46
47 P_
48 Inplace_Compaction(base, lim, scanbase, scanlim, bit_array, bit_array_words
49 #ifndef PAR
50 , ForeignObjList
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 *ForeignObjList;
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     NewForeignObjList = NULL; /* initialise new ForeignObjList */
98              /* As we move ForeignObjs 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 ((W_) 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 ((W_) 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_ForeignObjList( NewForeignObjList );
207     *ForeignObjList = NewForeignObjList;
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 ForeignObj list link - instead link moved object into
314    @NewForeignObjList@ */
315
316 #define ForeignObj_SLIDE_DATA \
317         ForeignObj_CLOSURE_DATA(New) = ForeignObj_CLOSURE_DATA(Scan); \
318         ForeignObj_CLOSURE_FINALISER(New) = ForeignObj_CLOSURE_FINALISER(Scan)
319 #define ForeignObj_RELINK                                 \
320 {                                                         \
321         ForeignObj_CLOSURE_LINK(New) = NewForeignObjList; \
322         NewForeignObjList = New;                          \
323 }
324 #endif /* !PAR */
325
326 /* The SLIDE_FIXED_HDR macro is dependent on the No of FIXED_HS */
327
328 #if FIXED_HS == 1
329 #define SLIDE_FIXED_HDR         /* Already Assigned INFO_PTR */
330 #else
331 #if FIXED_HS == 2
332 #define SLIDE_FIXED_HDR         SLIDE_WORD(1)
333 #else
334 #if FIXED_HS == 3
335 #define SLIDE_FIXED_HDR         SLIDE_WORD(1);SLIDE_WORD(2)
336 #else
337 /* I don't think this will be needed (ToDo: #error?) */
338 #endif                               
339 #endif                               
340 #endif                               
341
342
343 #if defined(DEBUG)
344
345 #define DEBUG_SCAN_LINK(type, sizevar, ptrvar) \
346     if (RTSflags.GcFlags.trace & DEBUG_TRACE_MINOR_GC)                  \
347         fprintf(stderr, "Scan Link (%s): 0x%lx -> 0x%lx, info 0x%lx, size %ld, ptrs %ld\n", \
348                 type, Scan, New, INFO_PTR(Scan), sizevar, ptrvar)
349
350 #define DEBUG_SCAN_MOVE(type, sizevar) \
351     if (RTSflags.GcFlags.trace & DEBUG_TRACE_MINOR_GC)            \
352         fprintf(stderr, "Scan Move (%s): 0x%lx -> 0x%lx, info 0x%lx, size %ld\n", \
353                 type, Scan, New, INFO_PTR(New), sizevar)
354
355
356 #else
357
358 #define DEBUG_SCAN_LINK(type, sizevar, ptrvar)
359 #define DEBUG_SCAN_MOVE(type, sizevar)
360
361 #endif
362
363 /*** LINKING CLOSURES ***/
364
365 #ifdef TICKY_TICKY
366 I_
367 _ScanLink_0_0(STG_NO_ARGS) {
368     I_ size = 0; /* NB: SPEC_VHS is *defined* to be zero */
369     DEBUG_SCAN_LINK("SPEC", size, 0);
370     return(FIXED_HS + size);
371 }
372 #endif
373
374 I_
375 _ScanLink_1_0(STG_NO_ARGS) {
376     I_ size = 1; /* NB: SPEC_VHS is *defined* to be zero */
377     DEBUG_SCAN_LINK("SPEC", size, 0);
378     return(FIXED_HS + size);
379 }
380 I_
381 _ScanLink_1_1(STG_NO_ARGS) {
382     I_ size = 1;
383     DEBUG_SCAN_LINK("SPEC", size, 1);
384     SPEC_LINK_LOCATION(1);
385     return(FIXED_HS + size);
386 }
387 I_
388 _ScanLink_2_0(STG_NO_ARGS) {
389     I_ size = 2;
390     DEBUG_SCAN_LINK("SPEC", size, 0);
391     return(FIXED_HS + size);
392 }
393 I_
394 _ScanLink_2_1(STG_NO_ARGS) {
395     I_ size = 2;
396     DEBUG_SCAN_LINK("SPEC", size, 1);
397     SPEC_LINK_LOCATION(1);
398     return(FIXED_HS + size);
399 }
400 I_
401 _ScanLink_2_2(STG_NO_ARGS) {
402     I_ size = 2;
403     DEBUG_SCAN_LINK("SPEC", size, 2);
404     SPEC_LINK_LOCATION(1);
405     SPEC_LINK_LOCATION(2);
406     return(FIXED_HS + size);
407 }
408 I_
409 _ScanLink_3_0(STG_NO_ARGS) {
410     I_ size = 3;
411     DEBUG_SCAN_LINK("SPEC", size, 0);
412     return(FIXED_HS + size);
413 }
414 I_
415 _ScanLink_3_1(STG_NO_ARGS) {
416     I_ size = 3;
417     DEBUG_SCAN_LINK("SPEC", size, 1);
418     SPEC_LINK_LOCATION(1);
419     return(FIXED_HS + size);
420 }
421 I_
422 _ScanLink_3_2(STG_NO_ARGS) {
423     I_ size = 3;
424     DEBUG_SCAN_LINK("SPEC", size, 2);
425     SPEC_LINK_LOCATION(1);
426     SPEC_LINK_LOCATION(2);
427     return(FIXED_HS + size);
428 }
429 I_
430 _ScanLink_3_3(STG_NO_ARGS) {
431     I_ size = 3;
432     DEBUG_SCAN_LINK("SPEC", size, 3);
433     SPEC_LINK_LOCATION(1);
434     SPEC_LINK_LOCATION(2);
435     SPEC_LINK_LOCATION(3);
436     return(FIXED_HS + size);
437 }
438 I_
439 _ScanLink_4_0(STG_NO_ARGS) {
440     I_ size = 4;
441     DEBUG_SCAN_LINK("SPEC", size, 0);
442     return(FIXED_HS + size);
443 }
444 I_
445 _ScanLink_4_4(STG_NO_ARGS) {
446     I_ size = 4;
447     DEBUG_SCAN_LINK("SPEC", size, 4);
448     SPEC_LINK_LOCATION(1);
449     SPEC_LINK_LOCATION(2);
450     SPEC_LINK_LOCATION(3);
451     SPEC_LINK_LOCATION(4);
452     return(FIXED_HS + size);
453 }
454 I_
455 _ScanLink_5_0(STG_NO_ARGS) {
456     I_ size = 5;
457     DEBUG_SCAN_LINK("SPEC", size, 0);
458     return(FIXED_HS + size);
459 }
460 I_
461 _ScanLink_5_5(STG_NO_ARGS) {
462     I_ size = 5;
463     DEBUG_SCAN_LINK("SPEC", size, 5);
464     SPEC_LINK_LOCATION(1);
465     SPEC_LINK_LOCATION(2);
466     SPEC_LINK_LOCATION(3);
467     SPEC_LINK_LOCATION(4);
468     SPEC_LINK_LOCATION(5);
469     return(FIXED_HS + size);
470 }
471 I_
472 _ScanLink_6_6(STG_NO_ARGS) {
473     I_ size = 6;
474     DEBUG_SCAN_LINK("SPEC", size, 6);
475     SPEC_LINK_LOCATION(1);
476     SPEC_LINK_LOCATION(2);
477     SPEC_LINK_LOCATION(3);
478     SPEC_LINK_LOCATION(4);
479     SPEC_LINK_LOCATION(5);
480     SPEC_LINK_LOCATION(6);
481     return(FIXED_HS + size);
482 }
483 I_
484 _ScanLink_7_7(STG_NO_ARGS) {
485     I_ size = 7;
486     DEBUG_SCAN_LINK("SPEC", size, 7);
487     SPEC_LINK_LOCATION(1);
488     SPEC_LINK_LOCATION(2);
489     SPEC_LINK_LOCATION(3);
490     SPEC_LINK_LOCATION(4);
491     SPEC_LINK_LOCATION(5);
492     SPEC_LINK_LOCATION(6);
493     SPEC_LINK_LOCATION(7);
494     return(FIXED_HS + size);
495 }
496 I_
497 _ScanLink_8_8(STG_NO_ARGS) {
498     I_ size = 8;
499     DEBUG_SCAN_LINK("SPEC", size, 8);
500     SPEC_LINK_LOCATION(1);
501     SPEC_LINK_LOCATION(2);
502     SPEC_LINK_LOCATION(3);
503     SPEC_LINK_LOCATION(4);
504     SPEC_LINK_LOCATION(5);
505     SPEC_LINK_LOCATION(6);
506     SPEC_LINK_LOCATION(7);
507     SPEC_LINK_LOCATION(8);
508     return(FIXED_HS + size);
509 }
510 I_
511 _ScanLink_9_9(STG_NO_ARGS) {
512     I_ size = 9;
513     DEBUG_SCAN_LINK("SPEC", size, 9);
514     SPEC_LINK_LOCATION(1);
515     SPEC_LINK_LOCATION(2);
516     SPEC_LINK_LOCATION(3);
517     SPEC_LINK_LOCATION(4);
518     SPEC_LINK_LOCATION(5);
519     SPEC_LINK_LOCATION(6);
520     SPEC_LINK_LOCATION(7);
521     SPEC_LINK_LOCATION(8);
522     SPEC_LINK_LOCATION(9);
523     return(FIXED_HS + size);
524 }
525 I_
526 _ScanLink_10_10(STG_NO_ARGS) {
527     I_ size = 10;
528     DEBUG_SCAN_LINK("SPEC", size, 10);
529     SPEC_LINK_LOCATION(1);
530     SPEC_LINK_LOCATION(2);
531     SPEC_LINK_LOCATION(3);
532     SPEC_LINK_LOCATION(4);
533     SPEC_LINK_LOCATION(5);
534     SPEC_LINK_LOCATION(6);
535     SPEC_LINK_LOCATION(7);
536     SPEC_LINK_LOCATION(8);
537     SPEC_LINK_LOCATION(9);
538     SPEC_LINK_LOCATION(10);
539     return(FIXED_HS + size);
540 }
541 I_
542 _ScanLink_11_11(STG_NO_ARGS) {
543     I_ size = 11;
544     DEBUG_SCAN_LINK("SPEC", size, 11);
545     SPEC_LINK_LOCATION(1);
546     SPEC_LINK_LOCATION(2);
547     SPEC_LINK_LOCATION(3);
548     SPEC_LINK_LOCATION(4);
549     SPEC_LINK_LOCATION(5);
550     SPEC_LINK_LOCATION(6);
551     SPEC_LINK_LOCATION(7);
552     SPEC_LINK_LOCATION(8);
553     SPEC_LINK_LOCATION(9);
554     SPEC_LINK_LOCATION(10);
555     SPEC_LINK_LOCATION(11);
556     return(FIXED_HS + size);
557 }
558 I_
559 _ScanLink_12_12(STG_NO_ARGS) {
560     I_ size = 12;
561     DEBUG_SCAN_LINK("SPEC", size, 12);
562     SPEC_LINK_LOCATION(1);
563     SPEC_LINK_LOCATION(2);
564     SPEC_LINK_LOCATION(3);
565     SPEC_LINK_LOCATION(4);
566     SPEC_LINK_LOCATION(5);
567     SPEC_LINK_LOCATION(6);
568     SPEC_LINK_LOCATION(7);
569     SPEC_LINK_LOCATION(8);
570     SPEC_LINK_LOCATION(9);
571     SPEC_LINK_LOCATION(10);
572     SPEC_LINK_LOCATION(11);
573     SPEC_LINK_LOCATION(12);
574     return(FIXED_HS + size);
575 }
576 \end{code}
577
578 Scan-linking revertible black holes with underlying @SPEC@ closures.
579
580 \begin{code}
581
582 #if defined(PAR) || defined(GRAN)
583 I_ 
584 _ScanLink_RBH_2_1(STG_NO_ARGS)
585 {
586     I_ size = 2 + SPEC_RBH_VHS;
587     DEBUG_SCAN_LINK("SRBH", size, 1);
588     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
589     return(FIXED_HS + size);
590 }
591 I_ 
592 _ScanLink_RBH_3_1(STG_NO_ARGS)
593 {
594     I_ size = 3 + SPEC_RBH_VHS;
595     DEBUG_SCAN_LINK("SRBH", size, 1);
596     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
597     return(FIXED_HS + size);
598 }
599 I_ 
600 _ScanLink_RBH_3_3(STG_NO_ARGS)
601 {
602     I_ size = 3 + SPEC_RBH_VHS;
603     DEBUG_SCAN_LINK("SRBH", size, 3);
604     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
605     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
606     return(FIXED_HS + size);
607 }
608 I_ 
609 _ScanLink_RBH_4_1(STG_NO_ARGS)
610 {
611     I_ size = 4 + SPEC_RBH_VHS;
612     DEBUG_SCAN_LINK("SRBH", size, 1);
613     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
614     return(FIXED_HS + size);
615 }
616 I_ 
617 _ScanLink_RBH_4_4(STG_NO_ARGS)
618 {
619     I_ size = 4 + SPEC_RBH_VHS;
620     DEBUG_SCAN_LINK("SRBH", size, 4);
621     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
622     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
623     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 2);
624     return(FIXED_HS + size);
625 }
626 I_ 
627 _ScanLink_RBH_5_1(STG_NO_ARGS)
628 {
629     I_ size = 5 + SPEC_RBH_VHS;
630     DEBUG_SCAN_LINK("SRBH", size, 1);
631     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
632     return(FIXED_HS + size);
633 }
634 I_ 
635 _ScanLink_RBH_5_5(STG_NO_ARGS)
636 {
637     I_ size = 5 + SPEC_RBH_VHS;
638     DEBUG_SCAN_LINK("SRBH", size, 5);
639     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
640     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
641     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 2);
642     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 3);
643     return(FIXED_HS + size);
644 }
645 I_ 
646 _ScanLink_RBH_6_6(STG_NO_ARGS)
647 {
648     I_ size = 6 + SPEC_RBH_VHS;
649     DEBUG_SCAN_LINK("SRBH", size, 6);
650     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
651     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
652     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 2);
653     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 3);
654     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 4);
655     return(FIXED_HS + size);
656 }
657 I_ 
658 _ScanLink_RBH_7_7(STG_NO_ARGS)
659 {
660     I_ size = 7 + SPEC_RBH_VHS;
661     DEBUG_SCAN_LINK("SRBH", size, 7);
662     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
663     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
664     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 2);
665     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 3);
666     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 4);
667     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 5);
668     return(FIXED_HS + size);
669 }
670 I_ 
671 _ScanLink_RBH_8_8(STG_NO_ARGS)
672 {
673     I_ size = 8 + SPEC_RBH_VHS;
674     DEBUG_SCAN_LINK("SRBH", size, 8);
675     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
676     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
677     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 2);
678     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 3);
679     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 4);
680     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 5);
681     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 6);
682     return(FIXED_HS + size);
683 }
684 I_ 
685 _ScanLink_RBH_9_9(STG_NO_ARGS)
686 {
687     I_ size = 9 + SPEC_RBH_VHS;
688     DEBUG_SCAN_LINK("SRBH", size, 9);
689     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
690     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
691     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 2);
692     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 3);
693     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 4);
694     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 5);
695     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 6);
696     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 7);
697     return(FIXED_HS + size);
698 }
699 I_ 
700 _ScanLink_RBH_10_10(STG_NO_ARGS)
701 {
702     I_ size = 10 + SPEC_RBH_VHS;
703     DEBUG_SCAN_LINK("SRBH", size, 10);
704     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
705     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
706     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 2);
707     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 3);
708     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 4);
709     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 5);
710     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 6);
711     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 7);
712     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 8);
713     return(FIXED_HS + size);
714 }
715 I_ 
716 _ScanLink_RBH_11_11(STG_NO_ARGS)
717 {
718     I_ size = 11 + SPEC_RBH_VHS;
719     DEBUG_SCAN_LINK("SRBH", size, 11);
720     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
721     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
722     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 2);
723     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 3);
724     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 4);
725     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 5);
726     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 6);
727     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 7);
728     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 8);
729     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 9);
730     return(FIXED_HS + size);
731 }
732 I_ 
733 _ScanLink_RBH_12_12(STG_NO_ARGS)
734 {
735     I_ size = 12 + SPEC_RBH_VHS;
736     DEBUG_SCAN_LINK("SRBH", size, 12);
737     LINK_LOCATION(SPEC_RBH_BQ_LOCN);
738     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 1);
739     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 2);
740     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 3);
741     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 4);
742     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 5);
743     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 6);
744     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 7);
745     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 8);
746     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 9);
747     LINK_LOCATION(SPEC_RBH_BQ_LOCN + 10);
748     return(FIXED_HS + size);
749 }
750 #endif
751 \end{code}
752
753 Scan-linking a ForeignObj is straightforward: exactly the same as
754 @_ScanLink_[ForeignObj_SIZE]_0@.
755
756 \begin{code}
757 #ifndef PAR
758 I_
759 _ScanLink_ForeignObj(STG_NO_ARGS) {
760     I_ size = ForeignObj_SIZE;
761     DEBUG_SCAN_LINK("ForeignObj", size, 0);
762     return(FIXED_HS + size);
763 }
764 #endif /* !PAR */
765 \end{code}
766
767 Back to the main feature...
768
769 \begin{code}
770
771 /*** MOVING CLOSURES ***/
772
773 #ifdef TICKY_TICKY
774 I_
775 _ScanMove_0(STG_NO_ARGS) {
776     I_ size = 0; /* NB: SPEC_VHS defined to be zero, so 0 really is the "size" */
777     DEBUG_SCAN_MOVE("CONST", size);
778     SLIDE_FIXED_HDR;
779     return(FIXED_HS + size);
780 }
781 #endif
782 I_
783 _ScanMove_1(STG_NO_ARGS) {
784     I_ size = 1; /* NB: SPEC_VHS defined to be zero, so 1 really is the "size" */
785     DEBUG_SCAN_MOVE("SPEC", size);
786     SLIDE_FIXED_HDR;
787     SPEC_SLIDE_WORD(1);
788     return(FIXED_HS + size);
789 }
790 I_
791 _ScanMove_2(STG_NO_ARGS) {
792     I_ size = 2;
793     DEBUG_SCAN_MOVE("SPEC", size);
794     SLIDE_FIXED_HDR;
795     SPEC_SLIDE_WORD(1);
796     SPEC_SLIDE_WORD(2);
797     return(FIXED_HS + size);
798 }
799 I_
800 _ScanMove_3(STG_NO_ARGS) {
801     I_ size = 3;
802     DEBUG_SCAN_MOVE("SPEC", size);
803     SLIDE_FIXED_HDR;
804     SPEC_SLIDE_WORD(1);
805     SPEC_SLIDE_WORD(2);
806     SPEC_SLIDE_WORD(3);
807     return(FIXED_HS + size);
808 }
809 I_
810 _ScanMove_4(STG_NO_ARGS) {
811     I_ size = 4;
812     DEBUG_SCAN_MOVE("SPEC", size);
813     SLIDE_FIXED_HDR;
814     SPEC_SLIDE_WORD(1);
815     SPEC_SLIDE_WORD(2);
816     SPEC_SLIDE_WORD(3);
817     SPEC_SLIDE_WORD(4);
818     return(FIXED_HS + size);
819 }
820 I_
821 _ScanMove_5(STG_NO_ARGS) {
822     I_ size = 5;
823     DEBUG_SCAN_MOVE("SPEC", size);
824     SLIDE_FIXED_HDR;
825     SPEC_SLIDE_WORD(1);
826     SPEC_SLIDE_WORD(2);
827     SPEC_SLIDE_WORD(3);
828     SPEC_SLIDE_WORD(4);
829     SPEC_SLIDE_WORD(5);
830     return(FIXED_HS + size);
831 }
832 I_
833 _ScanMove_6(STG_NO_ARGS) {
834     I_ size = 6;
835     DEBUG_SCAN_MOVE("SPEC", size);
836     SLIDE_FIXED_HDR;
837     SPEC_SLIDE_WORD(1);
838     SPEC_SLIDE_WORD(2);
839     SPEC_SLIDE_WORD(3);
840     SPEC_SLIDE_WORD(4);
841     SPEC_SLIDE_WORD(5);
842     SPEC_SLIDE_WORD(6);
843     return(FIXED_HS + size);
844 }
845 I_
846 _ScanMove_7(STG_NO_ARGS) {
847     I_ size = 7;
848     DEBUG_SCAN_MOVE("SPEC", size);
849     SLIDE_FIXED_HDR;
850     SPEC_SLIDE_WORD(1);
851     SPEC_SLIDE_WORD(2);
852     SPEC_SLIDE_WORD(3);
853     SPEC_SLIDE_WORD(4);
854     SPEC_SLIDE_WORD(5);
855     SPEC_SLIDE_WORD(6);
856     SPEC_SLIDE_WORD(7);
857     return(FIXED_HS + size);
858 }
859 I_
860 _ScanMove_8(STG_NO_ARGS) {
861     I_ size = 8;
862     DEBUG_SCAN_MOVE("SPEC", size);
863     SLIDE_FIXED_HDR;
864     SPEC_SLIDE_WORD(1);
865     SPEC_SLIDE_WORD(2);
866     SPEC_SLIDE_WORD(3);
867     SPEC_SLIDE_WORD(4);
868     SPEC_SLIDE_WORD(5);
869     SPEC_SLIDE_WORD(6);
870     SPEC_SLIDE_WORD(7);
871     SPEC_SLIDE_WORD(8);
872     return(FIXED_HS + size);
873 }
874 I_
875 _ScanMove_9(STG_NO_ARGS) {
876     I_ size = 9;
877     DEBUG_SCAN_MOVE("SPEC", size);
878     SLIDE_FIXED_HDR;
879     SPEC_SLIDE_WORD(1);
880     SPEC_SLIDE_WORD(2);
881     SPEC_SLIDE_WORD(3);
882     SPEC_SLIDE_WORD(4);
883     SPEC_SLIDE_WORD(5);
884     SPEC_SLIDE_WORD(6);
885     SPEC_SLIDE_WORD(7);
886     SPEC_SLIDE_WORD(8);
887     SPEC_SLIDE_WORD(9);
888     return(FIXED_HS + size);
889 }
890 I_
891 _ScanMove_10(STG_NO_ARGS) {
892     I_ size = 10;
893     DEBUG_SCAN_MOVE("SPEC", size);
894     SLIDE_FIXED_HDR;
895     SPEC_SLIDE_WORD(1);
896     SPEC_SLIDE_WORD(2);
897     SPEC_SLIDE_WORD(3);
898     SPEC_SLIDE_WORD(4);
899     SPEC_SLIDE_WORD(5);
900     SPEC_SLIDE_WORD(6);
901     SPEC_SLIDE_WORD(7);
902     SPEC_SLIDE_WORD(8);
903     SPEC_SLIDE_WORD(9);
904     SPEC_SLIDE_WORD(10);
905     return(FIXED_HS + size);
906 }
907 I_
908 _ScanMove_11(STG_NO_ARGS) {
909     I_ size = 11;
910     DEBUG_SCAN_MOVE("SPEC", size);
911     SLIDE_FIXED_HDR;
912     SPEC_SLIDE_WORD(1);
913     SPEC_SLIDE_WORD(2);
914     SPEC_SLIDE_WORD(3);
915     SPEC_SLIDE_WORD(4);
916     SPEC_SLIDE_WORD(5);
917     SPEC_SLIDE_WORD(6);
918     SPEC_SLIDE_WORD(7);
919     SPEC_SLIDE_WORD(8);
920     SPEC_SLIDE_WORD(9);
921     SPEC_SLIDE_WORD(10);
922     SPEC_SLIDE_WORD(11);
923     return(FIXED_HS + size);
924 }
925 I_
926 _ScanMove_12(STG_NO_ARGS) {
927     I_ size = 12;
928     DEBUG_SCAN_MOVE("SPEC", size);
929     SLIDE_FIXED_HDR;
930     SPEC_SLIDE_WORD(1);
931     SPEC_SLIDE_WORD(2);
932     SPEC_SLIDE_WORD(3);
933     SPEC_SLIDE_WORD(4);
934     SPEC_SLIDE_WORD(5);
935     SPEC_SLIDE_WORD(6);
936     SPEC_SLIDE_WORD(7);
937     SPEC_SLIDE_WORD(8);
938     SPEC_SLIDE_WORD(9);
939     SPEC_SLIDE_WORD(10);
940     SPEC_SLIDE_WORD(11);
941     SPEC_SLIDE_WORD(12);
942     return(FIXED_HS + size);
943 }
944
945 #if (defined(PAR) || defined(GRAN)) && defined(GC_MUT_REQUIRED)
946 I_
947 _ScanMove_RBH_2(STG_NO_ARGS) {
948     I_ size = 2 + SPEC_RBH_VHS;
949     DEBUG_SCAN_MOVE("SRBH", size);
950     SLIDE_FIXED_HDR;
951     SLIDE_WORD(SPEC_RBH_HS + 0);
952
953     /* Build new OldMutables list */
954     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
955     StorageMgrInfo.OldMutables = (P_) New;
956
957     return(FIXED_HS + size);
958 }
959 I_
960 _ScanMove_RBH_3(STG_NO_ARGS) {
961     I_ size = 3 + SPEC_RBH_VHS;
962     DEBUG_SCAN_MOVE("SRBH", size);
963     SLIDE_FIXED_HDR;
964     SLIDE_WORD(SPEC_RBH_HS + 0);
965     SLIDE_WORD(SPEC_RBH_HS + 1);
966
967     /* Build new OldMutables list */
968     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
969     StorageMgrInfo.OldMutables = (P_) New;
970
971     return(FIXED_HS + size);
972 }
973 I_
974 _ScanMove_RBH_4(STG_NO_ARGS) {
975     I_ size = 4 + SPEC_RBH_VHS;
976     DEBUG_SCAN_MOVE("SRBH", size);
977     SLIDE_FIXED_HDR;
978     SLIDE_WORD(SPEC_RBH_HS + 0);
979     SLIDE_WORD(SPEC_RBH_HS + 1);
980     SLIDE_WORD(SPEC_RBH_HS + 2);
981
982     /* Build new OldMutables list */
983     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
984     StorageMgrInfo.OldMutables = (P_) New;
985
986     return(FIXED_HS + size);
987 }
988 I_
989 _ScanMove_RBH_5(STG_NO_ARGS) {
990     I_ size = 5 + SPEC_RBH_VHS;
991     DEBUG_SCAN_MOVE("SRBH", size);
992     SLIDE_FIXED_HDR;
993     SLIDE_WORD(SPEC_RBH_HS + 0);
994     SLIDE_WORD(SPEC_RBH_HS + 1);
995     SLIDE_WORD(SPEC_RBH_HS + 2);
996     SLIDE_WORD(SPEC_RBH_HS + 3);
997
998     /* Build new OldMutables list */
999     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1000     StorageMgrInfo.OldMutables = (P_) New;
1001
1002     return(FIXED_HS + size);
1003 }
1004 I_
1005 _ScanMove_RBH_6(STG_NO_ARGS) {
1006     I_ size = 6 + SPEC_RBH_VHS;
1007     DEBUG_SCAN_MOVE("SRBH", size);
1008     SLIDE_FIXED_HDR;
1009     SLIDE_WORD(SPEC_RBH_HS + 0);
1010     SLIDE_WORD(SPEC_RBH_HS + 1);
1011     SLIDE_WORD(SPEC_RBH_HS + 2);
1012     SLIDE_WORD(SPEC_RBH_HS + 3);
1013     SLIDE_WORD(SPEC_RBH_HS + 4);
1014
1015     /* Build new OldMutables list */
1016     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1017     StorageMgrInfo.OldMutables = (P_) New;
1018
1019     return(FIXED_HS + size);
1020 }
1021 I_
1022 _ScanMove_RBH_7(STG_NO_ARGS) {
1023     I_ size = 7 + SPEC_RBH_VHS;
1024     DEBUG_SCAN_MOVE("SRBH", size);
1025     SLIDE_FIXED_HDR;
1026     SLIDE_WORD(SPEC_RBH_HS + 0);
1027     SLIDE_WORD(SPEC_RBH_HS + 1);
1028     SLIDE_WORD(SPEC_RBH_HS + 2);
1029     SLIDE_WORD(SPEC_RBH_HS + 3);
1030     SLIDE_WORD(SPEC_RBH_HS + 4);
1031     SLIDE_WORD(SPEC_RBH_HS + 5);
1032
1033     /* Build new OldMutables list */
1034     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1035     StorageMgrInfo.OldMutables = (P_) New;
1036
1037     return(FIXED_HS + size);
1038 }
1039 I_
1040 _ScanMove_RBH_8(STG_NO_ARGS) {
1041     I_ size = 8 + SPEC_RBH_VHS;
1042     DEBUG_SCAN_MOVE("SRBH", size);
1043     SLIDE_FIXED_HDR;
1044     SLIDE_WORD(SPEC_RBH_HS + 0);
1045     SLIDE_WORD(SPEC_RBH_HS + 1);
1046     SLIDE_WORD(SPEC_RBH_HS + 2);
1047     SLIDE_WORD(SPEC_RBH_HS + 3);
1048     SLIDE_WORD(SPEC_RBH_HS + 4);
1049     SLIDE_WORD(SPEC_RBH_HS + 5);
1050     SLIDE_WORD(SPEC_RBH_HS + 6);
1051
1052     /* Build new OldMutables list */
1053     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1054     StorageMgrInfo.OldMutables = (P_) New;
1055
1056     return(FIXED_HS + size);
1057 }
1058 I_
1059 _ScanMove_RBH_9(STG_NO_ARGS) {
1060     I_ size = 9 + SPEC_RBH_VHS;
1061     DEBUG_SCAN_MOVE("SRBH", size);
1062     SLIDE_FIXED_HDR;
1063     SLIDE_WORD(SPEC_RBH_HS + 0);
1064     SLIDE_WORD(SPEC_RBH_HS + 1);
1065     SLIDE_WORD(SPEC_RBH_HS + 2);
1066     SLIDE_WORD(SPEC_RBH_HS + 3);
1067     SLIDE_WORD(SPEC_RBH_HS + 4);
1068     SLIDE_WORD(SPEC_RBH_HS + 5);
1069     SLIDE_WORD(SPEC_RBH_HS + 6);
1070     SLIDE_WORD(SPEC_RBH_HS + 7);
1071
1072     /* Build new OldMutables list */
1073     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1074     StorageMgrInfo.OldMutables = (P_) New;
1075
1076     return(FIXED_HS + size);
1077 }
1078 I_
1079 _ScanMove_RBH_10(STG_NO_ARGS) {
1080     I_ size = 10 + SPEC_RBH_VHS;
1081     DEBUG_SCAN_MOVE("SRBH", size);
1082     SLIDE_FIXED_HDR;
1083     SLIDE_WORD(SPEC_RBH_HS + 0);
1084     SLIDE_WORD(SPEC_RBH_HS + 1);
1085     SLIDE_WORD(SPEC_RBH_HS + 2);
1086     SLIDE_WORD(SPEC_RBH_HS + 3);
1087     SLIDE_WORD(SPEC_RBH_HS + 4);
1088     SLIDE_WORD(SPEC_RBH_HS + 5);
1089     SLIDE_WORD(SPEC_RBH_HS + 6);
1090     SLIDE_WORD(SPEC_RBH_HS + 7);
1091     SLIDE_WORD(SPEC_RBH_HS + 8);
1092
1093     /* Build new OldMutables list */
1094     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1095     StorageMgrInfo.OldMutables = (P_) New;
1096
1097     return(FIXED_HS + size);
1098 }
1099 I_
1100 _ScanMove_RBH_11(STG_NO_ARGS) {
1101     I_ size = 11 + SPEC_RBH_VHS;
1102     DEBUG_SCAN_MOVE("SRBH", size);
1103     SLIDE_FIXED_HDR;
1104     SLIDE_WORD(SPEC_RBH_HS + 0);
1105     SLIDE_WORD(SPEC_RBH_HS + 1);
1106     SLIDE_WORD(SPEC_RBH_HS + 2);
1107     SLIDE_WORD(SPEC_RBH_HS + 3);
1108     SLIDE_WORD(SPEC_RBH_HS + 4);
1109     SLIDE_WORD(SPEC_RBH_HS + 5);
1110     SLIDE_WORD(SPEC_RBH_HS + 6);
1111     SLIDE_WORD(SPEC_RBH_HS + 7);
1112     SLIDE_WORD(SPEC_RBH_HS + 8);
1113     SLIDE_WORD(SPEC_RBH_HS + 9);
1114
1115     /* Build new OldMutables list */
1116     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1117     StorageMgrInfo.OldMutables = (P_) New;
1118
1119     return(FIXED_HS + size);
1120 }
1121 I_
1122 _ScanMove_RBH_12(STG_NO_ARGS) {
1123     I_ size = 12 + SPEC_RBH_VHS;
1124     DEBUG_SCAN_MOVE("SRBH", size);
1125     SLIDE_FIXED_HDR;
1126     SLIDE_WORD(SPEC_RBH_HS + 0);
1127     SLIDE_WORD(SPEC_RBH_HS + 1);
1128     SLIDE_WORD(SPEC_RBH_HS + 2);
1129     SLIDE_WORD(SPEC_RBH_HS + 3);
1130     SLIDE_WORD(SPEC_RBH_HS + 4);
1131     SLIDE_WORD(SPEC_RBH_HS + 5);
1132     SLIDE_WORD(SPEC_RBH_HS + 6);
1133     SLIDE_WORD(SPEC_RBH_HS + 7);
1134     SLIDE_WORD(SPEC_RBH_HS + 8);
1135     SLIDE_WORD(SPEC_RBH_HS + 9);
1136     SLIDE_WORD(SPEC_RBH_HS + 10);
1137
1138     /* Build new OldMutables list */
1139     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1140     StorageMgrInfo.OldMutables = (P_) New;
1141
1142     return(FIXED_HS + size);
1143 }
1144 #endif
1145 \end{code}
1146
1147 Moving a Foreign Object is a little tricky: we want to copy the actual
1148 pointer unchanged (easy) but we want to link the ForeignObj into the
1149 new ForeignObj list.
1150
1151 \begin{code}
1152 #ifndef PAR
1153 I_
1154 _ScanMove_ForeignObj(STG_NO_ARGS) {
1155     I_ size = ForeignObj_SIZE;
1156     DEBUG_SCAN_MOVE("ForeignObj", size);
1157
1158 #if defined(DEBUG)
1159     if (RTSflags.GcFlags.trace & DEBUG_TRACE_FOREIGNOBJS) {
1160       fprintf(stderr,"Moving ForeignObj(%x)=<%x,%x,%x>", Scan, Scan[0], Scan[1], Scan[2]);
1161       fprintf(stderr," Data = %x, Finaliser = %x, Next = %x\n", 
1162               ForeignObj_CLOSURE_DATA(Scan), 
1163               ForeignObj_CLOSURE_FINALISER(Scan), 
1164               ForeignObj_CLOSURE_LINK(Scan) );
1165     }
1166 #endif
1167
1168     SLIDE_FIXED_HDR;
1169     ForeignObj_SLIDE_DATA;
1170     ForeignObj_RELINK;
1171
1172 #if defined(DEBUG)
1173     if (RTSflags.GcFlags.trace & DEBUG_TRACE_FOREIGNOBJS) {
1174       fprintf(stderr,"Moved ForeignObj(%x)=<%x,_,%x,%x,%x>", New, New[0], New[1], New[2], New[3]);
1175       fprintf(stderr," Data = %x, Finaliser = %x, Next = %x", 
1176              ForeignObj_CLOSURE_DATA(New), 
1177              ForeignObj_CLOSURE_FINALISER(New), 
1178              ForeignObj_CLOSURE_LINK(New) );
1179       fprintf(stderr,", NewForeignObjList = %x\n", NewForeignObjList );
1180     }
1181 #endif
1182
1183     return(FIXED_HS + size);
1184 }
1185 #endif /* !PAR */
1186 \end{code}
1187
1188 Now back to the main feature...
1189
1190 \begin{code}
1191
1192 /*** GENERIC Linking and Marking Routines */
1193
1194 I_
1195 _ScanLink_S_N(STG_NO_ARGS) {
1196     I_ count = GEN_HS - 1;
1197                    /* Offset of first ptr word, less 1 */
1198     I_ ptrs  = count + GEN_CLOSURE_NoPTRS(Scan);
1199                    /* Offset of last ptr word */
1200     I_ size  = GEN_CLOSURE_SIZE(Scan);
1201
1202     DEBUG_SCAN_LINK("GEN ", size, ptrs);
1203     while (++count <= ptrs) {
1204         LINK_LOCATION(count);
1205     }
1206     return(FIXED_HS + size);
1207 }
1208
1209 I_
1210 _ScanMove_S(STG_NO_ARGS) {
1211     I_ count = FIXED_HS - 1;
1212     I_ size  = GEN_CLOSURE_SIZE(New);
1213
1214     DEBUG_SCAN_MOVE("GEN ", size);
1215
1216     SLIDE_FIXED_HDR;
1217     while (++count <= size + (FIXED_HS - 1)) {
1218         SLIDE_WORD(count);
1219     }
1220     return(FIXED_HS + size);
1221 }
1222
1223 \end{code}
1224
1225 The linking code for revertible black holes with underlying @GEN@ closures.
1226
1227 \begin{code}
1228 #if defined(PAR) || defined(GRAN)
1229
1230 I_ 
1231 _ScanLink_RBH_N(STG_NO_ARGS)
1232 {
1233     I_ count = GEN_RBH_HS - 1;  /* Offset of first ptr word, less 1 */
1234     I_ ptrs  = GEN_RBH_CLOSURE_NoPTRS(Scan);
1235     I_ size  = GEN_RBH_CLOSURE_SIZE(Scan);
1236
1237     /* 
1238      * Get pointer count from original closure and adjust for one pointer 
1239      * in the first two words of the RBH.
1240      */
1241     if (ptrs < 2)
1242         ptrs = 1;
1243     else
1244         ptrs--;
1245
1246     ptrs += count;          /* Offset of last ptr word */
1247
1248     DEBUG_SCAN_LINK("GRBH", size, ptrs);
1249     while (++count <= ptrs) {
1250         LINK_LOCATION(count);
1251     }
1252     return(FIXED_HS + size);
1253 }
1254
1255 #ifdef GC_MUT_REQUIRED
1256
1257 I_
1258 _ScanMove_RBH_S(STG_NO_ARGS) {
1259     I_ count = GEN_RBH_HS - 1;
1260     I_ size  = GEN_RBH_CLOSURE_SIZE(New);
1261
1262     DEBUG_SCAN_MOVE("GRBH", size);
1263
1264     SLIDE_FIXED_HDR;
1265     while (++count <= size + (FIXED_HS - 1)) {
1266         SLIDE_WORD(count);
1267     }
1268
1269     /* Build new OldMutables list */
1270     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1271     StorageMgrInfo.OldMutables = (P_) New;
1272
1273     return(FIXED_HS + size);
1274 }
1275
1276 #endif
1277
1278 #endif
1279
1280 \end{code}
1281
1282 \begin{code}
1283 I_
1284 _ScanLink_Dyn(STG_NO_ARGS) {
1285     I_ count = DYN_HS - 1;
1286                    /* Offset of first ptr word, less 1 */
1287     I_ ptrs = count + DYN_CLOSURE_NoPTRS(Scan);
1288                    /* Offset of last ptr word */
1289     I_ size = DYN_CLOSURE_SIZE(Scan);
1290
1291     DEBUG_SCAN_LINK("DYN ", size, ptrs-count);
1292
1293     while (++count <= ptrs) {
1294         LINK_LOCATION(count);
1295     }
1296     return(FIXED_HS + size);
1297 }
1298
1299 I_
1300 _ScanMove_Dyn(STG_NO_ARGS) {
1301     I_ count = FIXED_HS - 1;
1302     I_ size  = DYN_CLOSURE_SIZE(Scan);
1303
1304     DEBUG_SCAN_MOVE("DYN ", size);
1305
1306     SLIDE_FIXED_HDR;
1307     while (++count <= size + (FIXED_HS - 1)) {
1308         SLIDE_WORD(count);
1309     }
1310     return(FIXED_HS + size);
1311 }
1312
1313 I_
1314 _ScanLink_Tuple(STG_NO_ARGS) {
1315     I_ count = TUPLE_HS - 1;
1316                    /* Offset of first ptr word, less 1 */
1317     I_ ptrs = count + TUPLE_CLOSURE_NoPTRS(Scan);
1318                    /* Offset of last ptr word */
1319     I_ size = TUPLE_CLOSURE_SIZE(Scan);
1320
1321     DEBUG_SCAN_LINK("TUPL", size, ptrs-count);
1322
1323     while (++count <= ptrs) {
1324         LINK_LOCATION(count);
1325     }
1326     return(FIXED_HS + size);
1327 }
1328
1329 I_
1330 _ScanMove_Tuple(STG_NO_ARGS) {
1331     I_ count = FIXED_HS - 1;
1332     I_ size  = TUPLE_CLOSURE_SIZE(Scan);
1333
1334     DEBUG_SCAN_MOVE("TUPL", size);
1335
1336     SLIDE_FIXED_HDR;
1337     while (++count <= size + (FIXED_HS - 1)) {
1338         SLIDE_WORD(count);
1339     }
1340     return(FIXED_HS + size);
1341 }
1342
1343 /*** MUTUPLE CLOSURE -- NO PTRS STORED IN CLOSURE -- NO DATA ***/
1344 /*             Only if special GC treatment required           */
1345
1346 #ifdef GC_MUT_REQUIRED
1347 I_
1348 _ScanLink_MuTuple(STG_NO_ARGS) {
1349     I_ count = MUTUPLE_HS - 1;
1350                    /* Offset of first ptr word, less 1 */
1351     I_ ptrs = count + MUTUPLE_CLOSURE_NoPTRS(Scan);
1352                    /* Offset of last ptr word */
1353     I_ size = MUTUPLE_CLOSURE_SIZE(Scan);
1354
1355     DEBUG_SCAN_LINK("MUT ", size, ptrs-count);
1356
1357     while (++count <= ptrs) {
1358         LINK_LOCATION(count);
1359     }
1360     return(FIXED_HS + size);
1361 }
1362
1363 I_
1364 _ScanMove_MuTuple(STG_NO_ARGS) {
1365     I_ count = FIXED_HS - 1;
1366     I_ size  = MUTUPLE_CLOSURE_SIZE(Scan);
1367
1368     DEBUG_SCAN_MOVE("MUT ", size);
1369
1370     SLIDE_FIXED_HDR;
1371     while (++count <= size + (FIXED_HS - 1)) {
1372         SLIDE_WORD(count);
1373     }
1374
1375     /* Build new OldMutables list */
1376     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1377     StorageMgrInfo.OldMutables = (P_) New;
1378
1379     return(FIXED_HS + size);
1380 }
1381
1382 I_
1383 _ScanMove_ImmuTuple(STG_NO_ARGS) {
1384     I_ count = FIXED_HS - 1;
1385     I_ size  = MUTUPLE_CLOSURE_SIZE(Scan);
1386
1387     DEBUG_SCAN_MOVE("IMUT", size);
1388
1389     SLIDE_FIXED_HDR;
1390     while (++count <= size + (FIXED_HS - 1)) {
1391         SLIDE_WORD(count);
1392     }
1393
1394     /* Dont add to OldMutables list */
1395
1396     return(FIXED_HS + size);
1397 }
1398 #endif /* GCap || GCgn */
1399
1400
1401 I_
1402 _ScanLink_Data(STG_NO_ARGS) {
1403     I_ size  = DATA_CLOSURE_SIZE(Scan);
1404     DEBUG_SCAN_LINK("DATA", size, 0);
1405     return(FIXED_HS + size);
1406 }
1407
1408 I_
1409 _ScanMove_Data(STG_NO_ARGS) {
1410     I_ count = FIXED_HS - 1;
1411     I_ size  = DATA_CLOSURE_SIZE(Scan);
1412
1413     DEBUG_SCAN_MOVE("DATA", size);
1414
1415     SLIDE_FIXED_HDR;
1416     while (++count <= size + (FIXED_HS - 1)) {
1417         SLIDE_WORD(count);
1418     }
1419     return(FIXED_HS + size);
1420 }
1421
1422
1423 I_
1424 _ScanLink_BH_U(STG_NO_ARGS) {
1425     I_ size = BH_U_SIZE;
1426     DEBUG_SCAN_LINK("BH  ", size, 0);
1427     return(FIXED_HS + size);
1428 }
1429
1430 I_
1431 _ScanMove_BH_U(STG_NO_ARGS) {
1432     I_ size = BH_U_SIZE;
1433     DEBUG_SCAN_MOVE("BH  ", size);
1434     SLIDE_FIXED_HDR;
1435     return(FIXED_HS + size);
1436 }
1437
1438 I_
1439 _ScanLink_BH_N(STG_NO_ARGS) {
1440     I_ size = BH_N_SIZE;
1441     DEBUG_SCAN_LINK("BH N", size, 0);
1442     return(FIXED_HS + size);
1443 }
1444
1445 I_
1446 _ScanMove_BH_N(STG_NO_ARGS) {
1447     I_ size = BH_N_SIZE;
1448     DEBUG_SCAN_MOVE("BH N", size);
1449     SLIDE_FIXED_HDR;
1450     return(FIXED_HS + size);
1451 }
1452
1453 #if defined(PROFILING) || defined(TICKY_TICKY)
1454 I_
1455 _ScanLink_PI(STG_NO_ARGS) {
1456     I_ size = IND_CLOSURE_SIZE(dummy);
1457     DEBUG_SCAN_LINK("PI  ", size, 1);
1458     LINK_LOCATION(IND_HS);
1459     return(FIXED_HS + size);
1460 }
1461
1462 I_
1463 _ScanMove_PI(STG_NO_ARGS) {
1464     I_ size = IND_CLOSURE_SIZE(dummy);
1465     DEBUG_SCAN_MOVE("PI  ", size);
1466     SLIDE_FIXED_HDR;
1467     SLIDE_WORD(IND_HS);
1468     return(FIXED_HS + size);
1469 }
1470 #endif
1471
1472 \end{code}
1473
1474 Linking and Marking Routines for FetchMes and stack objects.
1475
1476 \begin{code}
1477
1478 #if defined(CONCURRENT)
1479
1480 #if defined(PAR)
1481
1482 I_
1483 _ScanLink_FetchMe(STG_NO_ARGS) {
1484     I_ size = FETCHME_CLOSURE_SIZE(dummy);
1485     DEBUG_SCAN_LINK("FME ", size, 0);
1486     return(FIXED_HS + size);
1487 }
1488
1489 I_
1490 _ScanMove_FetchMe(STG_NO_ARGS) {
1491     I_ size = FETCHME_CLOSURE_SIZE(dummy);
1492     DEBUG_SCAN_MOVE("FME ", size);
1493     SLIDE_FIXED_HDR;
1494     SLIDE_WORD(FETCHME_GA_LOCN);
1495     ASSERT(GALAlookup(FETCHME_GA(New)) != NULL);
1496
1497 #ifdef GC_MUT_REQUIRED
1498     /* Build new OldMutables list */
1499     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1500     StorageMgrInfo.OldMutables = (P_) New;
1501 #endif
1502
1503     return(FIXED_HS + size);
1504 }
1505
1506 I_
1507 _ScanLink_BF(STG_NO_ARGS) 
1508 {
1509     I_ size = BF_CLOSURE_SIZE(dummy);
1510     DEBUG_SCAN_LINK("BF", size, 2);
1511
1512     LINK_LOCATION(BF_LINK_LOCN);
1513     LINK_LOCATION(BF_NODE_LOCN);
1514     return(FIXED_HS + size);
1515 }
1516
1517 I_
1518 _ScanMove_BF(STG_NO_ARGS) 
1519 {
1520     I_ count;
1521     I_ size = BF_CLOSURE_SIZE(dummy);
1522
1523     SLIDE_FIXED_HDR;
1524     for (count = FIXED_HS; count < FIXED_HS + BF_VHS; count++) {
1525         SLIDE_WORD(count);
1526     }
1527     SLIDE_WORD(BF_LINK_LOCN);
1528     SLIDE_WORD(BF_NODE_LOCN);
1529     SLIDE_WORD(BF_GTID_LOCN);
1530     SLIDE_WORD(BF_SLOT_LOCN);
1531     SLIDE_WORD(BF_WEIGHT_LOCN);
1532
1533 #ifdef GC_MUT_REQUIRED
1534     /* Build new OldMutables list */
1535     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1536     StorageMgrInfo.OldMutables = (P_) New;
1537 #endif
1538
1539     return(FIXED_HS + size);
1540 }
1541
1542 #endif  /* PAR */
1543
1544 I_
1545 _ScanLink_BQ(STG_NO_ARGS) {
1546     I_ size = BQ_CLOSURE_SIZE(dummy);
1547     DEBUG_SCAN_LINK("BQ  ", size, BQ_CLOSURE_NoPTRS(Scan));
1548     LINK_LOCATION(BQ_HS);
1549     return(FIXED_HS + size);
1550 }
1551
1552 I_
1553 _ScanMove_BQ(STG_NO_ARGS) {
1554     I_ size = BQ_CLOSURE_SIZE(dummy);
1555     DEBUG_SCAN_MOVE("BQ  ", size);
1556
1557     SLIDE_FIXED_HDR;
1558     SLIDE_WORD(BQ_HS);
1559
1560 #ifdef GC_MUT_REQUIRED
1561     /* Build new OldMutables list */
1562     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1563     StorageMgrInfo.OldMutables = (P_) New;
1564 #endif
1565
1566     return(FIXED_HS + size);
1567 }
1568
1569 I_
1570 _ScanLink_TSO(STG_NO_ARGS) 
1571 {
1572     STGRegisterTable *r = TSO_INTERNAL_PTR(Scan);
1573     W_ liveness = r->rLiveness;
1574     I_ i;
1575     I_ size = TSO_VHS + TSO_CTS_SIZE;
1576
1577     DEBUG_SCAN_LINK("TSO", size, 0/*wrong*/);
1578
1579     LINK_LOCATION(TSO_LINK_LOCN);
1580     LINK_LOCATION(((P_) &r->rStkO) - Scan);
1581     for(i = 0; liveness != 0; liveness >>= 1, i++) {
1582         if (liveness & 1) {
1583             LINK_LOCATION(((P_) &r->rR[i].p) - Scan)
1584         }
1585     }
1586     return(FIXED_HS + size);
1587 }
1588
1589 I_
1590 _ScanMove_TSO(STG_NO_ARGS) 
1591 {
1592     I_ count;
1593     I_ size = TSO_VHS + TSO_CTS_SIZE;
1594
1595     SLIDE_FIXED_HDR;
1596     for (count = FIXED_HS; count < FIXED_HS + TSO_VHS; count++) {
1597         SLIDE_WORD(count);
1598     }
1599
1600     for(count = 0; count < BYTES_TO_STGWORDS(sizeof(STGRegisterTable)); count++)
1601         /* Do it this way in case there's a shift of just one word */
1602         ((P_) TSO_INTERNAL_PTR(New))[count] = ((P_) TSO_INTERNAL_PTR(Scan))[count];
1603
1604 #ifdef GC_MUT_REQUIRED
1605     /* Build new OldMutables list */
1606     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1607     StorageMgrInfo.OldMutables = (P_) New;
1608 #endif
1609
1610     return(FIXED_HS + size);
1611 }
1612
1613 I_
1614 _ScanLink_StkO(STG_NO_ARGS) {
1615     I_ count;
1616     I_ size = STKO_CLOSURE_SIZE(Scan);
1617     I_ cts_size = STKO_CLOSURE_CTS_SIZE(Scan);
1618     I_ sub = STKO_SuB_OFFSET(Scan);     /* Offset of first update frame in B stack */
1619
1620     /* Link the link */
1621     LINK_LOCATION(STKO_LINK_LOCN);
1622
1623     /* Link the locations in the A stack */
1624     DEBUG_SCAN_LINK("STKO", size, cts_size - STKO_SpA_OFFSET(Scan) + 1);
1625     for (count = STKO_SpA_OFFSET(Scan); count <= cts_size; count++) {
1626         STKO_LINK_LOCATION(count);
1627     }
1628
1629     /* Now link the updatees in the update stack */
1630     while(sub > 0) {
1631         P_ subptr;
1632
1633         STKO_LINK_LOCATION(sub + BREL(UF_UPDATEE));
1634         subptr = GRAB_SuB(STKO_CLOSURE_ADDR(Scan,sub));
1635         sub = STKO_CLOSURE_OFFSET(Scan, subptr);
1636     }
1637
1638     ASSERT(sanityChk_StkO(Scan));
1639
1640     return(FIXED_HS + size);
1641 }
1642
1643 /* We move first and then repair, so that we can handle an overlapping source 
1644    and destination.
1645  */
1646
1647 I_
1648 _ScanMove_StkO(STG_NO_ARGS) {
1649     I_ count;
1650     I_ size  = STKO_CLOSURE_SIZE(Scan);
1651     I_ cts_size   = STKO_CLOSURE_CTS_SIZE(Scan);
1652     I_ spa_offset = STKO_SpA_OFFSET(Scan);
1653     I_ spb_offset = STKO_SpB_OFFSET(Scan);
1654     I_ sub_offset = STKO_SuB_OFFSET(Scan);
1655     I_ offset;
1656     
1657     DEBUG_SCAN_MOVE("STKO", size);
1658
1659     SLIDE_FIXED_HDR;
1660 #ifdef TICKY_TICKY
1661     SLIDE_WORD(STKO_ADEP_LOCN);
1662     SLIDE_WORD(STKO_BDEP_LOCN);
1663 #endif
1664     SLIDE_WORD(STKO_SIZE_LOCN);
1665     SLIDE_WORD(STKO_RETURN_LOCN);
1666     SLIDE_WORD(STKO_LINK_LOCN);
1667
1668     /* Adjust the four stack pointers...*IN ORDER* */
1669     offset = New - Scan;
1670     STKO_SuB(New) = STKO_SuB(Scan) + offset;
1671     STKO_SpB(New) = STKO_SpB(Scan) + offset;
1672     STKO_SpA(New) = STKO_SpA(Scan) + offset;
1673     STKO_SuA(New) = STKO_SuA(Scan) + offset;
1674
1675     /* Slide the B stack */
1676     for (count = 1; count <= spb_offset; count++) {
1677         SLIDE_WORD((STKO_HS-1) + count);
1678     }
1679
1680     /* Slide the A stack */
1681     for (count = spa_offset; count <= cts_size; count++) {
1682         SLIDE_WORD((STKO_HS-1) + count);
1683     }
1684
1685     /* Repair internal pointers */
1686     while (sub_offset > 0) {
1687             P_ subptr;
1688             ADJUST_WORD((STKO_HS-1) + sub_offset + BREL(UF_SUA),offset);
1689             ADJUST_WORD((STKO_HS-1) + sub_offset + BREL(UF_SUB),offset);
1690             subptr = GRAB_SuB(STKO_CLOSURE_ADDR(New,sub_offset));
1691             sub_offset = STKO_CLOSURE_OFFSET(New, subptr);
1692     }
1693
1694 #ifdef GC_MUT_REQUIRED
1695     /* Build new OldMutables list */
1696     MUT_LINK(New) = (W_) StorageMgrInfo.OldMutables;
1697     StorageMgrInfo.OldMutables = (P_) New;
1698 #endif
1699
1700     /* ToDo: ASSERT(sanityChk_StkO(Scan or New)); ??? */
1701
1702     return(FIXED_HS + size);
1703 }
1704
1705 #endif /* CONCURRENT */
1706
1707 \end{code}
1708
1709 \begin{code}
1710 /*** Dummy Entries -- Should not be entered ***/
1711
1712 /* Should not be in a .lc file either...  --JSM */
1713
1714 STGFUN(_Dummy_Static_entry) {
1715     fprintf(stderr,"Called _Dummy_Static_entry\nShould never occur!\n");
1716     abort();
1717 }
1718
1719 STGFUN(_Dummy_Ind_entry) {
1720     fprintf(stderr,"Called _Dummy_Ind_entry\nShould never occur!\n");
1721     abort();
1722 }
1723
1724 STGFUN(_Dummy_Caf_entry) {
1725     fprintf(stderr,"Called _Dummy_Caf_Ind_entry\nShould never occur!\n");
1726     abort();
1727 }
1728
1729 STGFUN(_Dummy_Const_entry) {
1730     fprintf(stderr,"Called _Dummy_Const_entry\nShould never occur!\n");
1731     abort();
1732 }
1733
1734 STGFUN(_Dummy_CharLike_entry) {
1735     fprintf(stderr,"Called _Dummy_CharLike_entry\nShould never occur!\n");
1736     abort();
1737 }
1738
1739 #endif /* _INFO_COMPACTING */
1740 \end{code}