1 %************************************************************************
3 \section[update-code]{Code required for update abstraction}
5 %************************************************************************
7 This code is required by the update interface which sits on top of the
8 storage manager interface (See \tr{SMupdate.lh}).
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!
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.
22 System-wide constants need to be included:
24 #define MAIN_REG_MAP /* STG world */
30 # include "Statistics.h"
36 #if defined(DO_REDN_COUNTING)
37 extern void PrintRednCountInfo(STG_NO_ARGS);
38 extern I_ showRednCountStats;
42 %************************************************************************
44 \subsection[indirection-code]{Indirection code}
46 %************************************************************************
48 The entry code for indirections and the indirection info-table.
53 ENT_IND(Node); /* Ticky-ticky profiling info */
54 SET_ACTIVITY(ACT_INDIRECT); /* SPAT profiling */
56 Node = (P_) IND_CLOSURE_PTR((P_) Node);
58 InfoPtr=(D_)(INFO_PTR(Node));
59 JMP_(ENTRY_CODE(InfoPtr));
63 IND_ITBL(Ind_info,Ind_entry,const,EF_);
67 We also need a special @CAF@ indirection info table which is used to
68 indirect @CAF@s to evaluated results in the heap.
70 STGFUN(Caf_entry) /* same as Ind_entry */
74 SET_ACTIVITY(ACT_INDIRECT); /* SPAT profiling */
76 Node = (P_) IND_CLOSURE_PTR((P_) Node);
78 InfoPtr=(D_)(INFO_PTR(Node));
79 JMP_(ENTRY_CODE(InfoPtr));
83 CAF_ITBL(Caf_info,Caf_entry,const,EF_);
86 %************************************************************************
88 \subsection[black-hole-code]{Black Hole code}
90 %************************************************************************
92 The entry code for black holes abort indicating a cyclic data dependency.
93 It is used to overwrite closures currently being evaluated.
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.
101 EXTFUN(EnterNodeCode);
102 EXTFUN(StackUnderflowEnterNode);
105 extern StgStablePtr errorHandler;
106 extern void raiseError PROTO((StgStablePtr));
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");
116 # if defined(USE_COST_CENTRES)
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);
123 # if defined(DO_REDN_COUNTING)
124 if (showRednCountStats) {
125 (void) STGCALL0(void,(),PrintRednCountInfo);
129 (void) STGCALL1(void,(void *, StgStablePtr), raiseError, errorHandler);
138 (void) STGCALL4(int,(),fprintf,stderr,"GRAN_CHECK in BH_UPD_entry: Entered a `black hole' @ 0x%x (CurrentTSO @ 0x%x\n ",Node,CurrentTSO);
142 STGCALL0(void,(),GranSimBlock); /* Do this before losing its TSO_LINK */
145 TSO_LINK(CurrentTSO) = Nil_closure;
146 SET_INFO_PTR(Node, BQ_info);
147 BQ_ENTRIES(Node) = (W_) CurrentTSO;
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 */
153 if(Node <= StorageMgrInfo.OldLim) {
154 MUT_LINK(Node) = (W_) StorageMgrInfo.OldMutables;
155 StorageMgrInfo.OldMutables = Node;
157 MUT_LINK(Node) = MUT_NOT_LINKED;
160 LivenessReg = LIVENESS_R1;
162 TSO_PC1(CurrentTSO) = EnterNodeCode;
165 QP_Event1("GR", CurrentTSO);
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);
180 /* CurrentTSO = Nil_closure; */
181 ReSchedule(NEW_THREAD);
190 /* made external so that debugger can get at it more effectively */
191 STGFUN(BH_SINGLE_entry)
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");
200 #if defined(USE_COST_CENTRES)
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);
207 # if defined(DO_REDN_COUNTING)
208 if (showRednCountStats) {
209 (void) STGCALL0(void,(),PrintRednCountInfo);
214 (void) STGCALL1(void,(void *, StgStablePtr), raiseError, errorHandler);
223 Updatable closures are overwritten with a black hole of a fixed size,
227 CAT_DECLARE(BH,BH_K,"BH","BH") /* just one, shared */
229 BH_ITBL(BH_UPD_info,BH_UPD_entry,U,const,EF_);
232 Single-Entry closures, which are not updated, are also overwritten
233 with a black hole. They have size @MIN_NONUPD_SIZE@.
236 BH_ITBL(BH_SINGLE_info,BH_SINGLE_entry,N,const,EF_);
239 %************************************************************************
241 \subsection[static-update-code]{Static update code in update frames}
243 %************************************************************************
245 This code is pointed to from update frames. It has to cope with
246 any kind of algebraic return: vectored or unvectored.
248 See \tr{SMupdate.lh} for a description of the various update frames
249 and the macros defining their layout.
251 On entry to this code:
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.
261 NEW update mechanism (Jan '94):
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
271 STGFUN(StdUpdFrameDirectReturn)
274 JMP_(UPDATE_CODE(InfoPtr));
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.
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*/
300 %************************************************************************
302 \subsection[existing-con-update-code]{Update code for existing constructors}
304 %************************************************************************
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
315 #define IND_UPD_TEMPLATE(label, retvector) \
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() \
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)])
341 %************************************************************************
343 \subsection[no-update-code]{Code for Erroneous Updates}
345 %************************************************************************
354 fprintf(stderr, "Update error: not a constructor!\n");
365 fprintf(stderr, "Standard error: should never happen!\n");
372 %************************************************************************
374 \subsection[permanent-indirections]{Lexical Scoping Updates}
376 %************************************************************************
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.
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
389 #if defined(USE_COST_CENTRES)
391 STGFUN(Perm_Ind_entry)
395 /* Don't add INDs to granularity cost */
397 ENT_IND(Node); /* Ticky-ticky profiling info */
399 /* Enter PAP cost centre -- lexical scoping only */
400 ENTER_CC_PAP_CL(Node);
402 Node = (P_) IND_CLOSURE_PTR((P_) Node);
403 ENT_VIA_NODE(); /* Ticky-ticky profiling info */
405 InfoPtr=(D_)(INFO_PTR(Node));
407 GRAN_EXEC(1,1,2,0,0);
409 JMP_(ENTRY_CODE(InfoPtr));
413 PERM_IND_ITBL(Perm_Ind_info,Perm_Ind_entry,const,EF_);
415 #endif /* USE_COST_CENTRES */
418 %************************************************************************
420 \subsection[partial-application-updates]{Partial applications}
422 %************************************************************************
424 See STG paper implementation section of Partial application updates.
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.
437 On entry to @UpdatePAP@, we assume the following:
439 \item SuB points to topmost word of an update frame or to the bottom of a
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.
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.
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))
462 /* These other locals do not have to survive a HEAP_CHK */
475 SET_ACTIVITY(ACT_UPDATE_PAP); /* SPAT profiling */
477 NPtrWords = AREL(SuA - SpA);
478 NNonPtrWords = BREL(SuB - SpB);
480 ASSERT(NPtrWords >= 0);
481 ASSERT(NNonPtrWords >= 0);
483 NArgWords = NPtrWords + NNonPtrWords + 1; /* +1 for Node */
485 #if defined(USE_COST_CENTRES)
486 /* set "CC_pap" to go in the updatee (see Sansom thesis, p 183) */
488 CC_pap /*really cc_enter*/ = (CostCentre) CC_HDR(Node);
489 if (IS_SUBSUMED_CC(CC_pap) /*really cc_enter*/)
493 if (NArgWords == 1) {
496 * No arguments, only Node. Skip building the PAP and
497 * just plan to update with an indirection.
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))
511 PapSize = NArgWords + DYN_HS;
513 ALLOC_UPD_PAP(DYN_HS, NArgWords, 0, PapSize);
514 CC_ALLOC(CC_pap, PapSize, PAP_K);
516 /* Allocate PapClosure -- Only Node (R1) is live */
517 HEAP_CHK(LIVENESS_R1, PapSize, 0);
519 SET_ACTIVITY(ACT_UPDATE_PAP); /* back to it (for SPAT profiling) */
521 PapClosure = Hp + 1 - PapSize; /* The new PapClosure */
523 SET_DYN_HDR(PapClosure, PAP_info, CC_pap, NArgWords + DYN_VHS, NPtrWords + 1);
525 /* Now fill in the closure fields */
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)];
534 * Finished constructing PAP closure; now update the updatee.
535 * But wait! What if there is no updatee? Then we fall off the stack.
539 if (SuB < STKO_BSTK_BOT(StkOReg)) {
542 LivenessReg = LIVENESS_R1;
544 JMP_(StackUnderflowEnterNode);
549 * Now we have a standard update frame, so we update the updatee with
550 * either the new PAP or Node.
552 * Supposedly, it is not possible to get a constructor update frame,
554 * (Because they have *never* been implemented. (WDP))
557 Updatee = GRAB_UPDATEE(SuB);
558 UPD_IND(Updatee, PapClosure); /* Indirect Updatee to PapClosure */
560 if (NArgWords != 1) {
566 #if defined(USE_COST_CENTRES)
568 * Lexical scoping requires a *permanent* indirection, and we
569 * also have to set the cost centre for the indirection.
571 INFO_PTR(Updatee) = (W_) Perm_Ind_info;
572 SET_CC_HDR(Updatee, CC_pap);
574 #endif /* USE_COST_CENTRES */
577 #if defined(USE_COST_CENTRES)
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.
583 CCC = (IS_CAF_OR_DICT_CC(CC_pap)) ? GRAB_COST_CENTRE(SuB) : CC_pap;
585 #endif /* USE_COST_CENTRES */
587 /* Restore SuA, SuB, RetReg */
588 RetReg = GRAB_RET(SuB);
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
597 for (i = NNonPtrWords - 1; i >= 0; i--)
598 SpB[BREL(i+STD_UF_SIZE)] = SpB[BREL(i)];
600 SpB += BREL(STD_UF_SIZE);
603 * All done! Restart by re-entering Node
604 * Don't count this entry for ticky-ticky profiling.
608 GRAN_EXEC(16,4,7,4,0);
610 InfoPtr=(D_)(INFO_PTR(Node));
611 JMP_(ENTRY_CODE(InfoPtr));
618 #ifdef USE_COST_CENTRES
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.
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))
638 /* These locals don't have to survive a HEAP_CHK */
646 SET_ACTIVITY(ACT_UPDATE_PAP); /* SPAT profiling */
648 while (AREL(SuA - SpA) == 0 && BREL(SuB - SpB) == 0) {
650 if (SuB < STKO_BSTK_BOT(StkOReg)) {
652 LivenessReg = LIVENESS_R1;
654 JMP_(StackUnderflowEnterNode);
658 /* We're sitting on top of an update frame, so let's do the business */
660 Updatee = GRAB_UPDATEE(SuB);
661 UPD_IND(Updatee, Node);
663 #if defined(USE_COST_CENTRES)
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.
669 CC_pap = (CostCentre) CC_HDR(Node);
670 CCC = (IS_CAF_OR_DICT_CC(CC_pap)) ? GRAB_COST_CENTRE(SuB) : CC_pap;
672 #endif /* USE_COST_CENTRES */
674 RetReg = GRAB_RET(SuB);
677 SpB += BREL(STD_UF_SIZE);
680 NPtrWords = DYN_CLOSURE_NoPTRS(Node) - 1; /* The saved Node counts as one */
681 NNonPtrWords = DYN_CLOSURE_NoNONPTRS(Node);
683 /* Ticky-ticky profiling info */
686 /* Enter PAP cost centre -- lexical scoping only */
687 ENTER_CC_PAP_CL(Node);
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
696 aWords = AREL(SuA - SpA);
697 bWords = BREL(SuB - SpB) + STD_UF_SIZE;
699 STK_CHK(LIVENESS_R1, NPtrWords, NNonPtrWords, aWords, bWords, 0, 0);
701 SpA -= AREL(NPtrWords);
702 SpB -= BREL(NNonPtrWords);
705 p = Node + DYN_HS; /* Point to first pointer word */
708 /* Reload the stacks */
710 for (i=0; i<NPtrWords; i++) SpA[AREL(i)] = (P_) *p++;
711 for (i=0; i<NNonPtrWords; i++) SpB[BREL(i)] = *p++;
715 InfoPtr=(D_)(INFO_PTR(Node));
716 JMP_(ENTRY_CODE(InfoPtr));
721 #ifdef USE_COST_CENTRES
727 The info table for a generic PAP:
729 DYN_ITBL(PAP_info,PAP_entry,UpdErr,0,INFO_OTHER_TAG,0,0,const,EF_,PAP_K,"PAP","->");