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