1 /* -----------------------------------------------------------------------------
2 * $Id: Updates.hc,v 1.23 1999/11/29 12:02:46 keithw Exp $
4 * (c) The GHC Team, 1998-1999
6 * Code to perform updates.
8 * ---------------------------------------------------------------------------*/
13 #include "HeapStackCheck.h"
18 The update frame return address must be *polymorphic*, that means
19 we have to cope with both vectored and non-vectored returns. This
20 is done by putting the return vector right before the info table, and
21 having a standard direct return address after the info table (pointed
22 to by the return address itself, as usual).
24 Each entry in the vector table points to a specialised entry code fragment
25 that knows how to return after doing the update. It would be possible to
26 use a single generic piece of code that simply entered the return value
27 to return, but it's quicker this way. The direct return code of course
28 just does another direct return when it's finished.
30 Why is there necessarily an activation underneath us on the stack?
31 Because if we're returning, that means we've got a constructor in
32 our hands. If there were any arguments to be applied to it, that
33 would be a type error. We don't ever return a PAP to an update frame,
34 the update is handled manually by stg_update_PAP.
37 /* on entry to the update code
38 (1) R1 points to the closure being returned
39 (2) R2 contains the tag (if we returned directly, non-vectored)
40 (3) Sp points to the update frame
43 /* Why updatee is placed in a temporary variable here: this helps
44 gcc's aliasing by indicating that the location of the updatee
45 doesn't change across assignments. Saves one instruction in the
50 #define UPD_FRAME_ENTRY_TEMPLATE(label,ret) \
56 Su = (StgUpdateFrame *)((StgUpdateFrame *)Sp)->updatee; \
58 /* Tick - it must be a con, all the paps are handled \
59 * in stg_upd_PAP and PAP_entry below \
61 TICK_UPD_CON_IN_NEW(sizeW_fromITBL(get_itbl(Su))); \
65 /* reset Su to the next update frame */ \
66 Su = ((StgUpdateFrame *)Sp)->link; \
68 /* remove the update frame from the stack */ \
69 Sp += sizeofW(StgUpdateFrame); \
76 #define UPD_FRAME_ENTRY_TEMPLATE(label,ret) \
80 StgClosure *updatee; \
83 updatee = ((StgUpdateFrame *)Sp)->updatee; \
85 /* Tick - it must be a con, all the paps are handled \
86 * in stg_upd_PAP and PAP_entry below \
88 TICK_UPD_CON_IN_NEW(sizeW_fromITBL(get_itbl(updatee))); \
90 UPD_IND(updatee, R1.cl); \
92 /* reset Su to the next update frame */ \
93 Su = ((StgUpdateFrame *)Sp)->link; \
95 /* remove the update frame from the stack */ \
96 Sp += sizeofW(StgUpdateFrame); \
103 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_entry,ENTRY_CODE(Sp[0]));
104 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_0_entry,RET_VEC(Sp[0],0));
105 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_1_entry,RET_VEC(Sp[0],1));
106 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_2_entry,RET_VEC(Sp[0],2));
107 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_3_entry,RET_VEC(Sp[0],3));
108 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_4_entry,RET_VEC(Sp[0],4));
109 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_5_entry,RET_VEC(Sp[0],5));
110 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_6_entry,RET_VEC(Sp[0],6));
111 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_7_entry,RET_VEC(Sp[0],7));
114 Make sure this table is big enough to handle the maximum vectored
119 #define UPD_FRAME_BITMAP 3
121 #define UPD_FRAME_BITMAP 1
124 /* this bitmap indicates that the first word of an update frame is a
125 * non-pointer - this is the update frame link. (for profiling,
126 * there's a cost-centre-stack in there too).
129 VEC_POLY_INFO_TABLE(Upd_frame,UPD_FRAME_BITMAP, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, UPDATE_FRAME,, EF_);
131 /* -----------------------------------------------------------------------------
132 Entry Code for a PAP.
134 The idea is to copy the chunk of stack from the PAP object and then
135 re-enter the function closure that failed it's args check in the
138 In fact, we do a little optimisation too, by performing the updates
139 for any update frames sitting on top of the stack. (ToDo: is this
140 really an optimisation? --SDM)
141 -------------------------------------------------------------------------- */
143 INFO_TABLE(PAP_info,PAP_entry,/*special layout*/0,0,PAP,,EF_,0,0);
153 pap = (StgPAP *) R1.p;
156 * remove any update frames on the top of the stack, by just
157 * performing the update here.
159 while ((W_)Su - (W_)Sp == 0) {
161 switch (get_itbl(Su)->type) {
164 /* We're sitting on top of an update frame, so let's do the business */
165 UPD_IND(Su->updatee, pap);
167 #if defined(PROFILING)
169 * Restore the Cost Centre too (if required); again see Sansom
170 * thesis p 183. Take the CC out of the update frame if a
174 CCCS = Su->header.prof.ccs;
175 #endif /* PROFILING */
178 Sp += sizeofW(StgUpdateFrame);
182 /* Just pop the seq frame and return to the activation record
183 * underneath us - R1 already contains the address of the PAP.
185 Su = ((StgSeqFrame *)Su)->link;
186 Sp += sizeofW(StgSeqFrame);
187 JMP_(ENTRY_CODE(*Sp));
190 /* can't happen, see stg_update_PAP */
191 barf("PAP_entry: CATCH_FRAME");
194 barf("PAP_entry: strange activation record");
202 * Check for stack overflow.
204 STK_CHK_NP(Words,1,);
209 /* Enter PAP cost centre -- lexical scoping only */
210 ENTER_CCS_PAP_CL(pap);
213 p = (P_)(pap->payload);
215 /* Reload the stack */
216 for (i=0; i<Words; i++) Sp[i] = (W_) *p++;
220 JMP_(GET_ENTRY(R1.cl));
224 /* -----------------------------------------------------------------------------
225 stg_update_PAP: Update the current closure with a partial application.
227 This function is called whenever an argument satisfaction check fails.
228 -------------------------------------------------------------------------- */
230 EXTFUN(stg_update_PAP)
234 CostCentreStack *CCS_pap;
237 StgClosure *Fun, *Updatee;
243 /* Save the pointer to the function closure that just failed the
244 * argument satisfaction check
248 #if defined(GRAN_COUNT)
253 /* Just copy the whole block of stack between the stack pointer
254 * and the update frame pointer.
256 Words = (P_)Su - (P_)Sp;
257 ASSERT((int)Words >= 0);
259 #if defined(PROFILING)
260 /* pretend we just entered the function closure */
268 * No arguments, only Node. Skip building the PAP and
269 * just plan to update with an indirection.
272 PapClosure = (StgPAP *)Fun;
277 PapSize = Words + sizeofW(StgPAP);
280 * First we need to do a heap check, which involves saving
281 * everything on the stack. We only have one live pointer:
282 * Fun, the function closure that was passed to us. If the
283 * heap check fails, we push the function closure on the stack
284 * and instruct the scheduler to try entering it again when
285 * the garbage collector has run.
287 * It's done this way because there's a possibility that the
288 * garbage collector might have messed around with the stack,
289 * such as removing the update frame.
291 if ((Hp += PapSize) > HpLim) {
294 JMP_(stg_gc_entertop);
297 TICK_ALLOC_UPD_PAP(1/*fun*/ + Words, 0);
299 CCS_ALLOC(CCS_pap, PapSize);
302 PapClosure = (StgPAP *)(Hp + 1 - PapSize); /* The new PapClosure */
304 SET_HDR(PapClosure,&PAP_info,CCS_pap);
305 PapClosure->n_args = Words;
306 PapClosure->fun = Fun;
308 /* Now fill in the closure fields */
311 for (i = Words-1; i >= 0; i--) {
317 * Finished constructing PAP closure; now update the updatee.
320 /* ToDo: we'd like to just jump to the code for PAP_entry here,
321 * which deals with a stack of update frames in one go. What to
322 * do about the special ticky and profiling stuff here?
325 switch (get_itbl(Su)->type) {
328 /* Set Sp to just above the SEQ frame (should be an activation rec.)*/
329 Sp = (P_)Su + sizeofW(StgSeqFrame);
332 Su = ((StgSeqFrame *)Su)->link;
334 /* return to the activation record, with the address of the PAP in R1 */
335 R1.p = (P_)PapClosure;
336 JMP_(ENTRY_CODE(*Sp));
339 /* Set Sp to just above the CATCH frame (should be an activation rec.)*/
340 Sp = (P_)Su + sizeofW(StgCatchFrame);
343 Su = ((StgCatchFrame *)Su)->link;
345 /* restart by entering the PAP */
346 R1.p = (P_)PapClosure;
347 JMP_(GET_ENTRY(R1.cl));
351 * Now we have a standard update frame, so we update the updatee with
352 * either the new PAP or Node.
355 Updatee = Su->updatee;
357 #if defined(PROFILING)
359 UPD_IND(Updatee,PapClosure);
360 TICK_UPD_PAP_IN_NEW(Words+1);
362 /* Lexical scoping requires a *permanent* indirection, and we
363 * also have to set the cost centre for the indirection.
365 UPD_PERM_IND(Updatee,PapClosure);
366 TICK_UPD_PAP_IN_PLACE();
367 Updatee->header.prof.ccs = CCS_pap;
370 UPD_IND(Updatee,PapClosure);
372 TICK_UPD_PAP_IN_NEW(Words+1);
374 TICK_UPD_PAP_IN_PLACE();
378 #if defined(PROFILING)
379 CCCS = Su->header.prof.ccs;
380 ENTER_CCS_PAP(CCS_pap);
381 #endif /* PROFILING */
387 * Squeeze out update frame from stack.
389 for (i = Words-1; i >= 0; i--) {
390 Sp[i+(sizeofW(StgUpdateFrame))] = Sp[i];
392 Sp += sizeofW(StgUpdateFrame);
396 barf("stg_update_PAP: strange activation record");
400 * All done! Restart by re-entering Node
401 * Don't count this entry for ticky-ticky profiling.
403 JMP_(GET_ENTRY(R1.cl));
408 /* -----------------------------------------------------------------------------
409 Entry Code for an AP_UPD.
411 The idea is to copy the chunk of stack from the AP object and then
412 enter the function closure.
414 (This code is a simplified copy of the PAP code - with all the
415 update frame code stripped out.)
416 -------------------------------------------------------------------------- */
419 INFO_TABLE(AP_UPD_info,AP_UPD_entry,/*special layout*/0,0,AP_UPD,,EF_,0,0);
429 ap = (StgAP_UPD *) R1.p;
434 * Check for stack overflow.
436 STK_CHK(Words+sizeofW(StgUpdateFrame),AP_UPD_entry,R2.p,1,);
438 PUSH_UPD_FRAME(R1.p, 0);
439 Sp -= sizeofW(StgUpdateFrame) + Words;
443 /* Enter PAP cost centre -- lexical scoping only */
444 ENTER_CCS_PAP_CL(ap); /* ToDo: ENTER_CC_AP_UPD_CL */
447 p = (P_)(ap->payload);
449 /* Reload the stack */
450 for (i=0; i<Words; i++) Sp[i] = (W_) *p++;
454 JMP_(GET_ENTRY(R1.cl));
459 /*-----------------------------------------------------------------------------
462 We don't have a primitive seq# operator: it is just a 'case'
463 expression whose scrutinee has either a polymorphic or function type
464 (constructor types can be handled by normal 'case' expressions).
466 To handle a polymorphic/function typed seq, we push a SEQ_FRAME on
467 the stack. This is a polymorphic activation record that just pops
468 itself and returns when entered. The purpose of the SEQ_FRAME is to
469 act as a barrier in case the scrutinee is a partial application - in
470 this way it is just like an update frame, except that it doesn't
472 -------------------------------------------------------------------------- */
474 #define SEQ_FRAME_ENTRY_TEMPLATE(label,ret) \
478 Su = ((StgSeqFrame *)Sp)->link; \
479 Sp += sizeofW(StgSeqFrame); \
484 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_entry, ENTRY_CODE(Sp[0]));
485 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_0_entry,ENTRY_CODE(Sp[0]));
486 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_1_entry,ENTRY_CODE(Sp[0]));
487 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_2_entry,ENTRY_CODE(Sp[0]));
488 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_3_entry,ENTRY_CODE(Sp[0]));
489 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_4_entry,ENTRY_CODE(Sp[0]));
490 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_5_entry,ENTRY_CODE(Sp[0]));
491 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_6_entry,ENTRY_CODE(Sp[0]));
492 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_7_entry,ENTRY_CODE(Sp[0]));
494 VEC_POLY_INFO_TABLE(seq_frame, UPD_FRAME_BITMAP, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, SEQ_FRAME,, EF_);
496 /* -----------------------------------------------------------------------------
499 * This closure takes one argument, which it evaluates and returns the
500 * result with a direct return (never a vectored return!) in R1. It
501 * does this by pushing a SEQ_FRAME on the stack and
502 * entering its argument.
504 * It is used in deleteThread when reverting blackholes.
505 * -------------------------------------------------------------------------- */
507 INFO_TABLE(seq_info,seq_entry,1,0,FUN,,EF_,0,0);
511 STK_CHK_GEN(sizeofW(StgSeqFrame), NO_PTRS, seq_entry, );
512 Sp -= sizeofW(StgSeqFrame);
514 R1.cl = R1.cl->payload[0];
515 JMP_(ENTRY_CODE(*R1.p));
520 /* -----------------------------------------------------------------------------
522 -------------------------------------------------------------------------- */
527 #define CATCH_FRAME_ENTRY_TEMPLATE(label,ret) \
532 Su = ((StgCatchFrame *)Sp)->link; \
533 Sp += sizeofW(StgCatchFrame); \
538 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_entry,ENTRY_CODE(Sp[0]));
539 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_0_entry,RET_VEC(Sp[0],0));
540 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_1_entry,RET_VEC(Sp[0],1));
541 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_2_entry,RET_VEC(Sp[0],2));
542 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_3_entry,RET_VEC(Sp[0],3));
543 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_4_entry,RET_VEC(Sp[0],4));
544 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_5_entry,RET_VEC(Sp[0],5));
545 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_6_entry,RET_VEC(Sp[0],6));
546 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_7_entry,RET_VEC(Sp[0],7));
549 #define CATCH_FRAME_BITMAP 3
551 #define CATCH_FRAME_BITMAP 1
554 /* Catch frames are very similar to update frames, but when entering
555 * one we just pop the frame off the stack and perform the correct
556 * kind of return to the activation record underneath us on the stack.
559 VEC_POLY_INFO_TABLE(catch_frame, CATCH_FRAME_BITMAP, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, CATCH_FRAME,, EF_);
561 /* -----------------------------------------------------------------------------
562 * The catch infotable
564 * This should be exactly the same as would be generated by this STG code
566 * catch = {x,h} \n {} -> catch#{x,h}
568 * It is used in deleteThread when reverting blackholes.
569 * -------------------------------------------------------------------------- */
571 INFO_TABLE(catch_info,catch_entry,2,0,FUN,,EF_,0,0);
575 R2.cl = payloadCPtr(R1.cl,1); /* h */
576 R1.cl = payloadCPtr(R1.cl,0); /* x */
586 /* args: R1 = m, R2 = k */
587 STK_CHK_GEN(sizeofW(StgCatchFrame), R1_PTR | R2_PTR, catchzh_fast, );
588 Sp -= sizeofW(StgCatchFrame);
589 fp = (StgCatchFrame *)Sp;
590 SET_HDR(fp,(StgInfoTable *)&catch_frame_info,CCCS);
591 fp -> handler = R2.cl;
593 Su = (StgUpdateFrame *)fp;
594 TICK_CATCHF_PUSHED();
596 JMP_(ENTRY_CODE(*R1.p));
601 /* -----------------------------------------------------------------------------
602 * The raise infotable
604 * This should be exactly the same as would be generated by this STG code
606 * raise = {err} \n {} -> raise#{err}
608 * It is used in raisezh_fast to update thunks on the update list
609 * -------------------------------------------------------------------------- */
611 INFO_TABLE(raise_info,raise_entry,1,0,FUN,,EF_,0,0);
615 R1.cl = R1.cl->payload[0];
624 StgClosure *raise_closure;
626 /* args : R1 = error */
628 #if defined(PROFILING)
630 /* Debugging tool: on raising an exception, show where we are. */
632 /* ToDo: currently this is a hack. Would be much better if
633 * the info was only displayed for an *uncaught* exception.
635 if (RtsFlags.ProfFlags.showCCSOnException) {
636 STGCALL2(print_ccs,stderr,CCCS);
643 /* This closure represents the expression 'raise# E' where E
644 * is the exception raise. It is used to overwrite all the
645 * thunks which are currently under evaluataion.
647 raise_closure = (StgClosure *)RET_STGCALL1(P_,allocate,
648 sizeofW(StgClosure)+1);
649 raise_closure->header.info = &raise_info;
650 raise_closure->payload[0] = R1.cl;
654 switch (get_itbl(p)->type) {
657 UPD_IND(p->updatee,raise_closure);
662 p = ((StgSeqFrame *)p)->link;
670 barf("raisezh_fast: STOP_FRAME");
673 barf("raisezh_fast: weird activation record");
680 /* Ok, p points to the enclosing CATCH_FRAME. Pop everything down to
681 * and including this frame, update Su, push R1, and enter the handler.
683 Su = ((StgCatchFrame *)p)->link;
684 handler = ((StgCatchFrame *)p)->handler;
686 Sp = (P_)p + sizeofW(StgCatchFrame) - 1;
691 JMP_(ENTRY_CODE(handler->header.info));