[project @ 1996-01-11 14:06:51 by partain]
[ghc-hetmet.git] / ghc / runtime / main / StgUpdate.lhc
1 %************************************************************************
2 %*                                                                      *
3 \section[update-code]{Code required for update abstraction}
4 %*                                                                      *
5 %************************************************************************
6
7 This code is required by the update interface which sits on top of the
8 storage manager interface (See \tr{SMupdate.lh}).
9
10 Some of this stuff has been separated (correctly!) into StgThreads.lhc
11 for version 0.23.  Could someone (Hans?) bring us up to date, please!
12 KH.
13
14 \begin{itemize}
15 \item Indirection entry code and info table.
16 \item Black Hole entry code and info table.
17 \item Update frame code and return vectors.
18 \item PAP update code.
19 \item PAP entry code and info table.
20 \end{itemize}
21
22 System-wide constants need to be included:
23 \begin{code}
24 #define MAIN_REG_MAP        /* STG world */
25
26 #include "rtsdefs.h"
27 #include "SMupdate.h"
28 #if 0
29 #ifdef PAR
30 # include "Statistics.h"
31 #endif
32 #endif
33
34 EXTDATA(Nil_closure);
35
36 #if defined(TICKY_TICKY)
37 void PrintTickyInfo(STG_NO_ARGS);
38 #endif
39 \end{code}
40
41 %************************************************************************
42 %*                                                                      *
43 \subsection[indirection-code]{Indirection code}
44 %*                                                                      *
45 %************************************************************************
46
47 The entry code for indirections and the indirection info-table.
48 \begin{code}
49 STGFUN(Ind_entry)
50 {
51     FB_
52     ENT_IND(Node);      /* Ticky-ticky profiling info */
53
54     Node = (P_) IND_CLOSURE_PTR((P_) Node);
55     ENT_VIA_NODE();
56     InfoPtr=(D_)(INFO_PTR(Node));
57     JMP_(ENTRY_CODE(InfoPtr));
58     FE_
59 }
60
61 IND_ITBL(Ind_info,Ind_entry,const,EF_);
62 \end{code}
63
64 We also need a special @CAF@ indirection info table which is used to
65 indirect @CAF@s to evaluated results in the heap.
66 \begin{code}
67 STGFUN(Caf_entry)       /* same as Ind_entry */
68 {
69     FB_
70     ENT_IND(Node);
71
72     Node = (P_) IND_CLOSURE_PTR((P_) Node);
73     ENT_VIA_NODE();
74     InfoPtr=(D_)(INFO_PTR(Node));
75     JMP_(ENTRY_CODE(InfoPtr));
76     FE_
77 }
78
79 CAF_ITBL(Caf_info,Caf_entry,const,EF_);
80 \end{code}
81
82 %************************************************************************
83 %*                                                                      *
84 \subsection[black-hole-code]{Black Hole code}
85 %*                                                                      *
86 %************************************************************************
87
88 The entry code for black holes abort indicating a cyclic data dependency.
89 It is used to overwrite closures currently being evaluated.
90
91 In the concurrent world, black holes are synchronization points, and they
92 are turned into blocking queues when there are threads waiting for the 
93 evaluation of the closure to finish.
94
95 \begin{code}
96 #ifdef CONCURRENT
97 EXTFUN(EnterNodeCode);
98 EXTFUN(StackUnderflowEnterNode);
99 EXTDATA_RO(BQ_info);
100 #else
101 void raiseError PROTO((StgStablePtr));
102 extern StgStablePtr errorHandler; /* NB: prone to magic-value-ery (WDP 95/12) */
103 #endif
104
105 STGFUN(BH_UPD_entry)
106 {
107 #ifndef CONCURRENT
108     FB_
109     (void) STGCALL1(int,(void *, FILE *),fflush,stdout);
110     (void) STGCALL2(int,(),fprintf,stderr,"Entered a `black hole': the program has a cyclic data dependency.\n");
111
112 # if defined(PROFILING)
113     {
114         CostCentre cc = (CostCentre) CC_HDR(Node);
115         (void) STGCALL5(int,(),fprintf,stderr,"Cost Centre: %s  Module: %s  Group %s\n",cc->label, cc->module, cc->group);
116     }
117 # endif    
118
119 # if defined(TICKY_TICKY)
120     if (RTSflags.TickyFlags.showTickyStats) {
121         (void) STGCALL0(void,(),PrintTickyInfo);
122     }
123 # endif
124
125     (void) STGCALL1(void,(void *, StgStablePtr), raiseError, errorHandler);
126     FE_
127
128 #else /* threads! */
129
130     FB_
131
132 # if 0
133     if ( debug & 0x80 ) 
134       (void) STGCALL4(int,(),fprintf,stderr,"GRAN_CHECK in BH_UPD_entry: Entered a `black hole' @ 0x%x (CurrentTSO @ 0x%x\n ",Node,CurrentTSO);
135 #endif
136
137 # if defined(GRAN)
138     STGCALL0(void,(),GranSimBlock);     /* Do this before losing its TSO_LINK */
139 # endif
140
141     TSO_LINK(CurrentTSO) = Nil_closure;
142     SET_INFO_PTR(Node, BQ_info);
143     BQ_ENTRIES(Node) = (W_) CurrentTSO;
144
145 # if defined(GCap) || defined(GCgn)
146     /* If we modify a black hole in the old generation,
147        we have to make sure it goes on the mutables list */
148
149     if(Node <= StorageMgrInfo.OldLim) {
150         MUT_LINK(Node) = (W_) StorageMgrInfo.OldMutables;
151         StorageMgrInfo.OldMutables = Node;
152     } else
153         MUT_LINK(Node) = MUT_NOT_LINKED;
154 # endif
155
156     LivenessReg = LIVENESS_R1;
157     SaveAllStgRegs();
158     TSO_PC1(CurrentTSO) = EnterNodeCode;
159
160     if (DO_QP_PROF) {
161         QP_Event1("GR", CurrentTSO);
162     }
163
164 # ifdef PAR
165     if(RTSflags.ParFlags.granSimStats) {
166         TIME now = CURRENT_TIME;
167         TSO_EXECTIME(CurrentTSO) += now - TSO_BLOCKEDAT(CurrentTSO);
168         TSO_BLOCKCOUNT(CurrentTSO)++;
169         TSO_QUEUE(CurrentTSO) = Q_BLOCKED;
170         TSO_BLOCKEDAT(CurrentTSO) = now;
171         DumpGranEvent(GR_BLOCK, CurrentTSO);
172     }
173 # endif
174
175 # if defined(GRAN)
176     /* CurrentTSO = Nil_closure; */
177     ReSchedule(NEW_THREAD);
178 # else
179     ReSchedule(0);
180 # endif
181
182     FE_
183
184 #endif /* threads */
185 }
186
187 /* made external so that debugger can get at it more effectively */
188 STGFUN(BH_SINGLE_entry)
189 {
190     FB_
191
192     (void) STGCALL1(int,(void *, FILE *),fflush,stdout);
193     (void) STGCALL2(int,(),fprintf,stderr,"Entered a single-entry `black hole' --\n");
194     (void) STGCALL2(int,(),fprintf,stderr,"either the compiler made a mistake on single-entryness,\n");
195     (void) STGCALL2(int,(),fprintf,stderr,"or the program has a cyclic data dependency.\n");
196
197 #if defined(PROFILING)
198     {
199         CostCentre cc = (CostCentre) CC_HDR(Node);
200         (void) STGCALL5(int,(),fprintf,stderr, "Cost Centre: %s  Module: %s  Group %s\n",cc->label, cc->module, cc->group);
201     }
202 #endif    
203
204 # if defined(TICKY_TICKY)
205     if (RTSflags.TickyFlags.showTickyStats) {
206         (void) STGCALL0(void,(),PrintTickyInfo);
207     }
208 # endif
209
210 #ifndef CONCURRENT
211     (void) STGCALL1(void,(void *, StgStablePtr), raiseError, errorHandler);
212 #else
213     EXIT(EXIT_FAILURE);
214 #endif
215
216     FE_
217 }
218 \end{code}
219
220 Updatable closures are overwritten with a black hole of a fixed size,
221 @MIN_UPD_SIZE@.
222
223 \begin{code}
224 CAT_DECLARE(BH,BH_K,"BH","BH")  /* just one, shared */
225
226 BH_ITBL(BH_UPD_info,BH_UPD_entry,U,const,EF_);
227 \end{code}
228
229 Single-Entry closures, which are not updated, are also overwritten
230 with a black hole. They have size @MIN_NONUPD_SIZE@.
231
232 \begin{code}
233 BH_ITBL(BH_SINGLE_info,BH_SINGLE_entry,N,const,EF_);
234 \end{code}
235
236 %************************************************************************
237 %*                                                                      *
238 \subsection[static-update-code]{Static update code in update frames}
239 %*                                                                      *
240 %************************************************************************
241
242 This code is pointed to from update frames.  It has to cope with
243 any kind of algebraic return: vectored or unvectored.
244
245 See \tr{SMupdate.lh} for a description of the various update frames
246 and the macros defining their layout.
247
248 On entry to this code:
249 \begin{itemize}
250 \item @R1@ points to a recently created heap object (return in heap) or
251 is dead (return in regs).
252 \item @R2@ points to the info table for the constructor.
253 \item When returning in regs, any of the return-regs (@R3@...) may be live,
254 but aren't used by this code.  They must be preserved.
255 \item @SpB@ points to the topmost word of the update frame.
256 \end{itemize}
257
258 NEW update mechanism (Jan '94):
259
260 When returning to an update frame, we want to jump directly to the
261 update code for the constructor in hand.  Because of the various
262 possible return conventions (all of which must be handled by the
263 generic update frame), we actually end up with a somewhat indirect
264 jump.
265
266 \begin{code}
267
268 STGFUN(StdUpdFrameDirectReturn)
269 {
270     FB_
271     JMP_(UPDATE_CODE(InfoPtr));
272     FE_
273 }
274
275 /*
276    NB: For direct returns to work properly, the name of the routine must be
277    the same as the name of the vector table with vtbl_ removed and DirectReturn
278    appended.  This is all the mangler understands.
279 */
280
281 const
282 W_
283 vtbl_StdUpdFrame[] = {
284     /* at least "MAX_VECTORED_RTN" elements (see GhcConstants.lh) */
285     (W_) StdUpdFrameDirectReturn/*0*/,
286     (W_) StdUpdFrameDirectReturn/*1*/,
287     (W_) StdUpdFrameDirectReturn/*2*/,
288     (W_) StdUpdFrameDirectReturn/*3*/,
289     (W_) StdUpdFrameDirectReturn/*4*/,
290     (W_) StdUpdFrameDirectReturn/*5*/,
291     (W_) StdUpdFrameDirectReturn/*6*/,
292     (W_) StdUpdFrameDirectReturn/*7*/
293 };
294
295 \end{code}
296
297 %************************************************************************
298 %*                                                                      *
299 \subsection[existing-con-update-code]{Update code for existing constructors}
300 %*                                                                      *
301 %************************************************************************
302
303 Here is the standard update code for objects that are returned in the
304 heap (or those which are initially returned in registers, but have
305 already been allocated in the heap earlier in the update chain).  In
306 either case, @Node@ points to the heap object.  The update code grabs
307 the address of the updatee out of the partial update frame (the return
308 address has already been popped), makes the updatee an indirection to
309 @Node@, and returns according to the convention for the constructor.
310
311 \begin{code}
312 #define IND_UPD_TEMPLATE(label, retvector)                      \
313   STGFUN(label)                                                 \
314   {                                                             \
315     FB_                                                         \
316     UPD_EXISTING();     /* Ticky-ticky profiling info */        \
317     /* Update thing off stk with an indirection to Node */      \
318     UPD_IND(GRAB_UPDATEE(SpB), Node);                           \
319     /* Pop the standard update frame */                         \
320     POP_STD_UPD_FRAME()                                         \
321                                                                 \
322     JMP_(retvector);                                            \
323     FE_                                                         \
324   }
325
326 IND_UPD_TEMPLATE(IndUpdRetDir, DIRECT(((P_)RetReg)))
327 IND_UPD_TEMPLATE(IndUpdRetV0, ((P_)RetReg)[RVREL(0)])
328 IND_UPD_TEMPLATE(IndUpdRetV1, ((P_)RetReg)[RVREL(1)])
329 IND_UPD_TEMPLATE(IndUpdRetV2, ((P_)RetReg)[RVREL(2)])
330 IND_UPD_TEMPLATE(IndUpdRetV3, ((P_)RetReg)[RVREL(3)])
331 IND_UPD_TEMPLATE(IndUpdRetV4, ((P_)RetReg)[RVREL(4)])
332 IND_UPD_TEMPLATE(IndUpdRetV5, ((P_)RetReg)[RVREL(5)])
333 IND_UPD_TEMPLATE(IndUpdRetV6, ((P_)RetReg)[RVREL(6)])
334 IND_UPD_TEMPLATE(IndUpdRetV7, ((P_)RetReg)[RVREL(7)])
335 \end{code}
336
337 %************************************************************************
338 %*                                                                      *
339 \subsection[no-update-code]{Code for Erroneous Updates}
340 %*                                                                      *
341 %************************************************************************
342
343 \begin{code}
344
345 STGFUN(UpdErr)
346 {
347     FB_
348
349     fflush(stdout);
350     fprintf(stderr, "Update error: not a constructor!\n");
351     abort();
352
353     FE_
354 }
355
356 STGFUN(StdErrorCode)
357 {
358     FB_
359
360     fflush(stdout);
361     fprintf(stderr, "Standard error: should never happen!\n");
362     abort();
363
364     FE_
365 }
366 \end{code}
367
368 %************************************************************************
369 %*                                                                      *
370 \subsection[permanent-indirections]{Lexical Scoping Updates}
371 %*                                                                      *
372 %************************************************************************
373
374 A function entered without any arguments is updated with an
375 indirection. For lexically scoped profiling we still need to set the
376 cost centre if we enter the PAP. As the indirection is removed by the
377 garbage collector this would not be possible.
378
379 To solve this problem we introduce a permanent indirection which sets
380 the cost centre when entered. The heap profiler ignores the space
381 occupied by it as it would not reside in the heap during normal
382 execution.
383
384 In ticky-land: If we are trying to collect update-entry counts
385 (controlled by an RTS flag), then we must use permanent indirections
386 (the shorting-out of regular indirections loses the counts).
387
388 \begin{code}
389 #if defined(PROFILING) || defined(TICKY_TICKY)
390
391 STGFUN(Perm_Ind_entry)
392 {
393     FB_
394
395     /* Don't add INDs to granularity cost */
396
397     /* Dont: ENT_IND(Node); for ticky-ticky; this ind is here only to help ticky */
398
399     /* Enter PAP cost centre -- lexical scoping only */
400     ENTER_CC_PAP_CL(Node);
401
402     Node = (P_) IND_CLOSURE_PTR((P_) Node);
403
404     /* Dont: ENT_VIA_NODE(); for ticky-ticky; as above */
405
406     InfoPtr=(D_)(INFO_PTR(Node));
407
408 # if defined(GRAN)
409     GRAN_EXEC(1,1,2,0,0);
410 # endif
411     JMP_(ENTRY_CODE(InfoPtr));
412     FE_
413 }
414
415 PERM_IND_ITBL(Perm_Ind_info,Perm_Ind_entry,const,EF_);
416
417 #endif /* PROFILING or TICKY */
418 \end{code}
419
420 %************************************************************************
421 %*                                                                      *
422 \subsection[partial-application-updates]{Partial applications}
423 %*                                                                      *
424 %************************************************************************
425
426 See STG paper implementation section of Partial application updates.
427
428 We jump here when the current function fails an argument satisfaction
429 check.  There can be two reasons for this.  In the usual case, there
430 is an update frame blocking our access to anything deeper on the
431 stack.  We then update the updatee in the frame with a partial
432 application node and squeeze out the update frame.  The other
433 possibility is that we are running threaded code, and we are sitting
434 on the bottom of a stack chunk.  In this case, we still build the
435 partial application, but we have nothing in our hands to update, so we
436 underflow the stack (awakening the previous chunk) and enter the
437 partial application node just built.
438
439 On entry to @UpdatePAP@, we assume the following:
440 \begin{itemize}
441 \item SuB points to topmost word of an update frame or to the bottom of a 
442 stack chunk.
443 \item SpA and SpB point to the topmost words of their respective stacks.
444 \item Node points to the closure which needs more arguments than are there.
445 \end{itemize}
446
447 \begin{code}
448 STGFUN(UpdatePAP)
449 {
450     /* 
451      * Use STG registers for these locals which must survive the HEAP_CHK.
452      * Don't squash Node (R1), because it's an implicit argument.
453      */
454
455 #define NNonPtrWords    (R2.i)
456 #define NPtrWords       (R3.i)
457 #define NArgWords       (R4.i)
458 #define PapSize         (R5.i)
459 #if defined(PROFILING)
460 # define CC_pap ((CostCentre)(R7.p))
461 #endif
462
463     /* These other locals do not have to survive a HEAP_CHK */
464
465     P_ PapClosure;
466     P_ Updatee;
467     P_ p;
468     I_ i;
469
470     FB_
471
472 #if defined(COUNT)
473       ++nPAPs;
474 #endif
475
476     NPtrWords    = AREL(SuA - SpA);
477     NNonPtrWords = BREL(SuB - SpB);
478
479     ASSERT(NPtrWords >= 0);
480     ASSERT(NNonPtrWords >= 0);
481
482     NArgWords = NPtrWords + NNonPtrWords + 1;   /* +1 for Node */
483
484 #if defined(PROFILING)
485       /* set "CC_pap" to go in the updatee (see Sansom thesis, p 183) */
486
487     CC_pap /*really cc_enter*/ = (CostCentre) CC_HDR(Node);
488     if (IS_SUBSUMED_CC(CC_pap) /*really cc_enter*/)
489         CC_pap = CCC;
490 #endif
491
492     if (NArgWords == 1) { 
493
494         /* 
495          * No arguments, only Node.  Skip building the PAP and
496          * just plan to update with an indirection.
497          */
498
499         PapClosure = Node;
500
501     } else {
502    
503         /* Build the PAP.  A generic PAP closure is laid out thus:
504          *      code ptr, size, no of words of ptrs, Node, ptrs, non-ptrs 
505          * (i.e. a DYN closure)
506          * ToDo: add stuff for special cases, to omit size and no. of ptrs 
507          *      (Still ToDo?  (JSM))
508          */
509
510         PapSize = NArgWords + DYN_HS;
511     
512         ALLOC_UPD_PAP(DYN_HS, NArgWords, 0, PapSize);
513         CC_ALLOC(CC_pap, PapSize, PAP_K);
514     
515         /* Allocate PapClosure -- Only Node (R1) is live */
516         HEAP_CHK(LIVENESS_R1, PapSize, 0);
517
518         PapClosure = Hp + 1 - PapSize;  /* The new PapClosure */
519
520         SET_DYN_HDR(PapClosure, PAP_info, CC_pap, NArgWords + DYN_VHS, NPtrWords + 1);
521
522         /* Now fill in the closure fields */
523
524         p = Hp;
525         for (i = NNonPtrWords - 1; i >= 0; i--) *p-- = (W_) SpB[BREL(i)];
526         for (i = NPtrWords    - 1; i >= 0; i--) *p-- = (W_) SpA[AREL(i)];
527         *p = (W_) Node;
528         }
529
530     /* 
531      * Finished constructing PAP closure; now update the updatee.  But
532      * wait!  What if there is no updatee?  Then we fall off the
533      * stack.
534      */
535
536 #ifdef CONCURRENT
537     if (SuB < STKO_BSTK_BOT(StkOReg)) {
538             Node = PapClosure;
539 # ifdef PAR
540             LivenessReg = LIVENESS_R1;
541 # endif
542         JMP_(StackUnderflowEnterNode);
543         }
544 #endif
545
546     /* 
547      * Now we have a standard update frame, so we update the updatee with 
548      * either the new PAP or Node.
549      *
550      * Supposedly, it is not possible to get a constructor update frame,
551      * (Why not?  (JSM))
552      * (Because they have *never* been implemented.  (WDP))
553      */
554
555     Updatee = GRAB_UPDATEE(SuB); 
556     UPD_IND(Updatee, PapClosure);   /* Indirect Updatee to PapClosure */
557
558     if (NArgWords != 1) {
559         UPD_PAP_IN_NEW(NArgWords);
560
561     } else {
562         UPD_PAP_IN_PLACE();     
563
564 #if defined(PROFILING)
565         /* 
566          * Lexical scoping requires a *permanent* indirection, and we
567          * also have to set the cost centre for the indirection.
568          */
569         INFO_PTR(Updatee) = (W_) Perm_Ind_info;
570         SET_CC_HDR(Updatee, CC_pap);
571
572 #endif /* PROFILING */
573     }
574
575 #if defined(PROFILING)
576     /* 
577      * Restore the Cost Centre too (if required); again see Sansom thesis p 183.
578      * Take the CC out of the update frame if a CAF/DICT.
579      */
580
581     CCC = (IS_CAF_OR_DICT_CC(CC_pap)) ? GRAB_COST_CENTRE(SuB) : CC_pap;
582
583 #endif /* PROFILING */
584
585     /* Restore SuA, SuB, RetReg */
586     RetReg = GRAB_RET(SuB);
587     SuA = GRAB_SuA(SuB);
588     SuB = GRAB_SuB(SuB);
589
590     /* 
591      * Squeeze out update frame from B stack.  Note that despite our best
592      * efforts with [AB]REL and friends, the loop order depends on the B
593      * stack growing up.
594      */
595     for (i = NNonPtrWords - 1; i >= 0; i--) 
596         SpB[BREL(i+STD_UF_SIZE)] = SpB[BREL(i)];
597
598     SpB += BREL(STD_UF_SIZE);
599
600     /* 
601      * All done!  Restart by re-entering Node
602      * Don't count this entry for ticky-ticky profiling. 
603     */
604
605 #if defined(GRAN)
606     GRAN_EXEC(16,4,7,4,0);
607 #endif
608     InfoPtr=(D_)(INFO_PTR(Node));
609     JMP_(ENTRY_CODE(InfoPtr));
610     FE_
611
612 #undef NNonPtrWords
613 #undef NPtrWords
614 #undef NArgWords
615 #undef PapSize
616 #ifdef PROFILING
617 # undef CC_pap
618 #endif
619 }
620 \end{code}
621
622 The entry code for a generic PAP. @Node@ points to the PAP closure.
623 Reload the stacks from the PAP, and enter the closure stored in the
624 PAP. PAPs are in HNF so no update frame is needed.
625
626 \begin{code}
627 STGFUN(PAP_entry)
628 {
629     /* Use STG registers for these locals which must survive the STK_CHK */
630 #define NPtrWords       (R2.i)
631 #define NNonPtrWords    (R3.i)
632 #if defined(PROFILING)
633 # define CC_pap ((CostCentre)(R7.p))
634 #endif
635
636     /* These locals don't have to survive the STK_CHK */
637     P_ Updatee;
638     P_ p;
639     I_ i;
640     I_ aWords, bWords;
641
642     FB_
643
644     while (AREL(SuA - SpA) == 0 && BREL(SuB - SpB) == 0) {
645 #ifdef CONCURRENT
646         if (SuB < STKO_BSTK_BOT(StkOReg)) {
647 # ifdef PAR
648             LivenessReg = LIVENESS_R1;
649 # endif
650             JMP_(StackUnderflowEnterNode);
651         }
652 #endif
653
654         /* We're sitting on top of an update frame, so let's do the business */
655
656         Updatee = GRAB_UPDATEE(SuB);
657         UPD_IND(Updatee, Node);
658
659 #if defined(PROFILING)
660         /* 
661          * Restore the Cost Centre too (if required); again see Sansom
662          * thesis p 183.  Take the CC out of the update frame if a
663          * CAF/DICT.
664          */
665
666         CC_pap = (CostCentre) CC_HDR(Node);
667         CCC = (IS_CAF_OR_DICT_CC(CC_pap)) ? GRAB_COST_CENTRE(SuB) : CC_pap;
668
669 #endif /* PROFILING */
670
671         RetReg = GRAB_RET(SuB);
672         SuA = GRAB_SuA(SuB);
673         SuB = GRAB_SuB(SuB);
674         SpB += BREL(STD_UF_SIZE);
675     }
676
677     NPtrWords    = DYN_CLOSURE_NoPTRS(Node) - 1; /* The saved Node counts as one */
678     NNonPtrWords = DYN_CLOSURE_NoNONPTRS(Node);
679
680     /* Ticky-ticky profiling info */
681     ENT_PAP(Node);
682
683     /* Enter PAP cost centre -- lexical scoping only */
684     ENTER_CC_PAP_CL(Node);
685
686     /* 
687      * Check for stack overflow.  Ask to take all of the current frame with
688      * us to the new world.  If there is no update frame on the current stack,
689      * bWords will exceed the size of the B stack, but StackOverflow will deal 
690      * with it.
691      */
692
693     aWords = AREL(SuA - SpA);
694     bWords = BREL(SuB - SpB) + STD_UF_SIZE;
695
696     STK_CHK(LIVENESS_R1, NPtrWords, NNonPtrWords, aWords, bWords, 0, 0);
697
698     SpA -= AREL(NPtrWords);
699     SpB -= BREL(NNonPtrWords);
700
701     /* Reload Node */
702     p = Node + DYN_HS;     /* Point to first pointer word */
703     Node = (P_) *p++;
704
705     /* Reload the stacks */
706
707     for (i=0; i<NPtrWords;    i++) SpA[AREL(i)] = (P_) *p++;
708     for (i=0; i<NNonPtrWords; i++) SpB[BREL(i)] = *p++;
709
710     /* Off we go! */
711     ENT_VIA_NODE();
712     InfoPtr=(D_)(INFO_PTR(Node));
713     JMP_(ENTRY_CODE(InfoPtr));
714     FE_
715
716 #undef NPtrWords
717 #undef NNonPtrWords
718 #ifdef PROFILING
719 # undef CC_pap
720 #endif
721 }
722 \end{code}
723
724 The info table for a generic PAP:
725 \begin{code}
726 DYN_ITBL(PAP_info,PAP_entry,UpdErr,0,INFO_OTHER_TAG,0,0,const,EF_,PAP_K,"PAP","->");
727 \end{code}