1 /* -----------------------------------------------------------------------------
2 * $Id: Updates.hc,v 1.36 2001/11/22 14:25:12 simonmar Exp $
4 * (c) The GHC Team, 1998-1999
6 * Code to perform updates.
8 * ---------------------------------------------------------------------------*/
15 #if defined(GRAN) || defined(PAR)
20 The update frame return address must be *polymorphic*, that means
21 we have to cope with both vectored and non-vectored returns. This
22 is done by putting the return vector right before the info table, and
23 having a standard direct return address after the info table (pointed
24 to by the return address itself, as usual).
26 Each entry in the vector table points to a specialised entry code fragment
27 that knows how to return after doing the update. It would be possible to
28 use a single generic piece of code that simply entered the return value
29 to return, but it's quicker this way. The direct return code of course
30 just does another direct return when it's finished.
32 Why is there necessarily an activation underneath us on the stack?
33 Because if we're returning, that means we've got a constructor in
34 our hands. If there were any arguments to be applied to it, that
35 would be a type error. We don't ever return a PAP to an update frame,
36 the update is handled manually by stg_update_PAP.
39 /* on entry to the update code
40 (1) R1 points to the closure being returned
41 (2) R2 contains the tag (if we returned directly, non-vectored)
42 (3) Sp points to the update frame
45 /* Why updatee is placed in a temporary variable here: this helps
46 gcc's aliasing by indicating that the location of the updatee
47 doesn't change across assignments. Saves one instruction in the
52 #define UPD_FRAME_ENTRY_TEMPLATE(label,ret) \
58 Su = (StgUpdateFrame *)((StgUpdateFrame *)Sp)->updatee; \
60 /* Tick - it must be a con, all the paps are handled \
61 * in stg_upd_PAP and PAP_entry below \
63 TICK_UPD_CON_IN_NEW(sizeW_fromITBL(get_itbl(Su))); \
67 /* reset Su to the next update frame */ \
68 Su = ((StgUpdateFrame *)Sp)->link; \
70 /* remove the update frame from the stack */ \
71 Sp += sizeofW(StgUpdateFrame); \
78 #define UPD_FRAME_ENTRY_TEMPLATE(label,ret) \
82 StgClosure *updatee; \
85 updatee = ((StgUpdateFrame *)Sp)->updatee; \
87 /* Tick - it must be a con, all the paps are handled \
88 * in stg_upd_PAP and PAP_entry below \
90 TICK_UPD_CON_IN_NEW(sizeW_fromITBL(get_itbl(updatee))); \
92 UPD_IND(updatee, R1.cl); \
94 /* reset Su to the next update frame */ \
95 Su = ((StgUpdateFrame *)Sp)->link; \
97 /* remove the update frame from the stack */ \
98 Sp += sizeofW(StgUpdateFrame); \
105 UPD_FRAME_ENTRY_TEMPLATE(stg_upd_frame_entry,ENTRY_CODE(Sp[0]));
106 UPD_FRAME_ENTRY_TEMPLATE(stg_upd_frame_0_entry,RET_VEC(Sp[0],0));
107 UPD_FRAME_ENTRY_TEMPLATE(stg_upd_frame_1_entry,RET_VEC(Sp[0],1));
108 UPD_FRAME_ENTRY_TEMPLATE(stg_upd_frame_2_entry,RET_VEC(Sp[0],2));
109 UPD_FRAME_ENTRY_TEMPLATE(stg_upd_frame_3_entry,RET_VEC(Sp[0],3));
110 UPD_FRAME_ENTRY_TEMPLATE(stg_upd_frame_4_entry,RET_VEC(Sp[0],4));
111 UPD_FRAME_ENTRY_TEMPLATE(stg_upd_frame_5_entry,RET_VEC(Sp[0],5));
112 UPD_FRAME_ENTRY_TEMPLATE(stg_upd_frame_6_entry,RET_VEC(Sp[0],6));
113 UPD_FRAME_ENTRY_TEMPLATE(stg_upd_frame_7_entry,RET_VEC(Sp[0],7));
116 Make sure this table is big enough to handle the maximum vectored
120 #if defined(PROFILING)
121 #define UPD_FRAME_BITMAP 7
123 #define UPD_FRAME_BITMAP 1
126 /* this bitmap indicates that the first word of an update frame is a
127 * non-pointer - this is the update frame link. (for profiling,
128 * there's a cost-centre-stack in there too).
131 VEC_POLY_INFO_TABLE(stg_upd_frame,UPD_FRAME_BITMAP, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, UPDATE_FRAME,, EF_);
133 /* -----------------------------------------------------------------------------
134 Entry Code for a PAP.
136 The idea is to copy the chunk of stack from the PAP object and then
137 re-enter the function closure that failed it's args check in the
140 In fact, we do a little optimisation too, by performing the updates
141 for any update frames sitting on top of the stack. (ToDo: is this
142 really an optimisation? --SDM)
143 -------------------------------------------------------------------------- */
145 INFO_TABLE(stg_PAP_info,stg_PAP_entry,/*special layout*/0,0,PAP,,EF_,"PAP","PAP");
146 STGFUN(stg_PAP_entry)
155 pap = (StgPAP *) R1.p;
158 * remove any update frames on the top of the stack, by just
159 * performing the update here.
161 while ((W_)Su - (W_)Sp == 0) {
163 switch (get_itbl(Su)->type) {
166 /* We're sitting on top of an update frame, so let's do the business */
167 UPD_IND(Su->updatee, pap);
169 #if defined(PROFILING)
171 * Restore the Cost Centre too (if required); again see Sansom
172 * thesis p 183. Take the CC out of the update frame if a
176 CCCS = Su->header.prof.ccs;
177 #endif /* PROFILING */
180 Sp += sizeofW(StgUpdateFrame);
184 /* Just pop the seq frame and return to the activation record
185 * underneath us - R1 already contains the address of the PAP.
187 Su = ((StgSeqFrame *)Su)->link;
188 Sp += sizeofW(StgSeqFrame);
189 JMP_(ENTRY_CODE(*Sp));
192 /* can't happen, see stg_update_PAP */
193 barf("PAP_entry: CATCH_FRAME");
196 barf("PAP_entry: strange activation record");
204 * Check for stack overflow.
206 STK_CHK_NP(Words,1,);
212 /* Enter PAP cost centre -- lexical scoping only */
213 ENTER_CCS_PAP_CL(pap);
216 p = (P_)(pap->payload);
218 /* Reload the stack */
219 for (i=0; i<Words; i++) Sp[i] = (W_) *p++;
223 JMP_(GET_ENTRY(R1.cl));
227 /* -----------------------------------------------------------------------------
228 stg_update_PAP: Update the current closure with a partial application.
230 This function is called whenever an argument satisfaction check fails.
231 -------------------------------------------------------------------------- */
233 EXTFUN(__stg_update_PAP)
237 CostCentreStack *CCS_pap;
240 StgClosure *Fun, *Updatee;
246 /* Save the pointer to the function closure that just failed the
247 * argument satisfaction check
251 /* Just copy the whole block of stack between the stack pointer
252 * and the update frame pointer.
254 Words = (P_)Su - (P_)Sp;
255 ASSERT((int)Words >= 0);
257 #if defined(PROFILING)
258 /* pretend we just entered the function closure */
266 * No arguments, only Node. Skip building the PAP and
267 * just plan to update with an indirection.
270 PapClosure = (StgPAP *)Fun;
275 PapSize = Words + sizeofW(StgPAP);
278 * First we need to do a heap check, which involves saving
279 * everything on the stack. We only have one live pointer:
280 * Fun, the function closure that was passed to us. If the
281 * heap check fails, we push the function closure on the stack
282 * and instruct the scheduler to try entering it again when
283 * the garbage collector has run.
285 * It's done this way because there's a possibility that the
286 * garbage collector might have messed around with the stack,
287 * such as removing the update frame.
289 if ((Hp += PapSize) > HpLim) {
292 // Not filling the slop for the object (because there is none), but
293 // filling in the trailing words in the current block.
294 // This is unnecessary because we fills the entire nursery with
295 // zeroes after each garbage collection.
296 // FILL_SLOP(HpLim, PapSize - (Hp - HpLim));
300 JMP_(stg_gc_entertop);
303 TICK_ALLOC_UPD_PAP(1/*fun*/ + Words, 0);
305 CCS_ALLOC(CCS_pap, PapSize);
308 PapClosure = (StgPAP *)(Hp + 1 - PapSize); /* The new PapClosure */
310 SET_HDR(PapClosure,&stg_PAP_info,CCS_pap);
311 PapClosure->n_args = Words;
312 PapClosure->fun = Fun;
314 /* Now fill in the closure fields */
317 for (i = Words; --i >= 0; ) {
323 * Finished constructing PAP closure; now update the updatee.
326 /* ToDo: we'd like to just jump to the code for PAP_entry here,
327 * which deals with a stack of update frames in one go. What to
328 * do about the special ticky and profiling stuff here?
331 switch (get_itbl(Su)->type) {
334 /* Set Sp to just above the SEQ frame (should be an activation rec.)*/
335 Sp = (P_)Su + sizeofW(StgSeqFrame);
338 Su = ((StgSeqFrame *)Su)->link;
340 /* return to the activation record, with the address of the PAP in R1 */
341 R1.p = (P_)PapClosure;
342 JMP_(ENTRY_CODE(*Sp));
345 /* Set Sp to just above the CATCH frame (should be an activation rec.)*/
346 Sp = (P_)Su + sizeofW(StgCatchFrame);
349 Su = ((StgCatchFrame *)Su)->link;
351 /* restart by entering the PAP */
352 R1.p = (P_)PapClosure;
353 JMP_(GET_ENTRY(R1.cl));
357 * Now we have a standard update frame, so we update the updatee with
358 * either the new PAP or Node.
361 Updatee = Su->updatee;
363 #if defined(PROFILING)
365 UPD_IND(Updatee,PapClosure);
366 TICK_UPD_PAP_IN_NEW(Words+1);
368 /* Lexical scoping requires a *permanent* indirection, and we
369 * also have to set the cost centre for the indirection.
371 UPD_PERM_IND(Updatee,PapClosure);
372 TICK_UPD_PAP_IN_PLACE();
373 Updatee->header.prof.ccs = CCS_pap;
376 UPD_IND(Updatee,PapClosure);
378 TICK_UPD_PAP_IN_NEW(Words+1);
380 TICK_UPD_PAP_IN_PLACE();
384 #if defined(PROFILING)
385 CCCS = Su->header.prof.ccs;
386 ENTER_CCS_PAP(CCS_pap);
387 #endif /* PROFILING */
393 * Squeeze out update frame from stack.
395 for (i = Words; --i >= 0; ) {
396 Sp[i+(sizeofW(StgUpdateFrame))] = Sp[i];
398 Sp += sizeofW(StgUpdateFrame);
402 barf("stg_update_PAP: strange activation record");
406 * All done! Restart by re-entering Node
407 * Don't count this entry for ticky-ticky profiling.
409 JMP_(GET_ENTRY(R1.cl));
414 /* -----------------------------------------------------------------------------
415 Entry Code for an AP_UPD.
417 The idea is to copy the chunk of stack from the AP object and then
418 enter the function closure.
420 (This code is a simplified copy of the PAP code - with all the
421 update frame code stripped out.)
422 -------------------------------------------------------------------------- */
425 INFO_TABLE(stg_AP_UPD_info,stg_AP_UPD_entry,/*special layout*/0,0,AP_UPD,,EF_,"AP_UPD","AP_UPD");
426 STGFUN(stg_AP_UPD_entry)
435 ap = (StgAP_UPD *) R1.p;
440 * Check for stack overflow.
442 STK_CHK_GEN(Words+sizeofW(StgUpdateFrame), R1_PTR, stg_AP_UPD_entry, );
444 PUSH_UPD_FRAME(R1.p, 0);
445 Sp -= sizeofW(StgUpdateFrame) + Words;
450 /* Enter PAP cost centre -- lexical scoping only */
451 ENTER_CCS_PAP_CL(ap); /* ToDo: ENTER_CC_AP_UPD_CL */
454 p = (P_)(ap->payload);
456 /* Reload the stack */
457 for (i=0; i<Words; i++) Sp[i] = (W_) *p++;
461 JMP_(GET_ENTRY(R1.cl));
466 /*-----------------------------------------------------------------------------
469 We don't have a primitive seq# operator: it is just a 'case'
470 expression whose scrutinee has either a polymorphic or function type
471 (constructor types can be handled by normal 'case' expressions).
473 To handle a polymorphic/function typed seq, we push a SEQ_FRAME on
474 the stack. This is a polymorphic activation record that just pops
475 itself and returns when entered. The purpose of the SEQ_FRAME is to
476 act as a barrier in case the scrutinee is a partial application - in
477 this way it is just like an update frame, except that it doesn't
479 -------------------------------------------------------------------------- */
481 #define SEQ_FRAME_ENTRY_TEMPLATE(label,ret) \
485 Su = ((StgSeqFrame *)Sp)->link; \
486 Sp += sizeofW(StgSeqFrame); \
491 SEQ_FRAME_ENTRY_TEMPLATE(stg_seq_frame_entry, ENTRY_CODE(Sp[0]));
492 SEQ_FRAME_ENTRY_TEMPLATE(stg_seq_frame_0_entry,ENTRY_CODE(Sp[0]));
493 SEQ_FRAME_ENTRY_TEMPLATE(stg_seq_frame_1_entry,ENTRY_CODE(Sp[0]));
494 SEQ_FRAME_ENTRY_TEMPLATE(stg_seq_frame_2_entry,ENTRY_CODE(Sp[0]));
495 SEQ_FRAME_ENTRY_TEMPLATE(stg_seq_frame_3_entry,ENTRY_CODE(Sp[0]));
496 SEQ_FRAME_ENTRY_TEMPLATE(stg_seq_frame_4_entry,ENTRY_CODE(Sp[0]));
497 SEQ_FRAME_ENTRY_TEMPLATE(stg_seq_frame_5_entry,ENTRY_CODE(Sp[0]));
498 SEQ_FRAME_ENTRY_TEMPLATE(stg_seq_frame_6_entry,ENTRY_CODE(Sp[0]));
499 SEQ_FRAME_ENTRY_TEMPLATE(stg_seq_frame_7_entry,ENTRY_CODE(Sp[0]));
501 VEC_POLY_INFO_TABLE(stg_seq_frame, UPD_FRAME_BITMAP, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, SEQ_FRAME,, EF_);
503 /* -----------------------------------------------------------------------------
506 * This closure takes one argument, which it evaluates and returns the
507 * result with a direct return (never a vectored return!) in R1. It
508 * does this by pushing a SEQ_FRAME on the stack and
509 * entering its argument.
511 * It is used in deleteThread when reverting blackholes.
512 * -------------------------------------------------------------------------- */
514 INFO_TABLE(stg_seq_info,stg_seq_entry,1,0,FUN,,EF_,0,0);
515 STGFUN(stg_seq_entry)
518 STK_CHK_GEN(sizeofW(StgSeqFrame), NO_PTRS, stg_seq_entry, );
519 Sp -= sizeofW(StgSeqFrame);
521 R1.cl = R1.cl->payload[0];
522 JMP_(ENTRY_CODE(*R1.p));