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