1 /* -----------------------------------------------------------------------------
2 * $Id: Updates.hc,v 1.13 1999/03/26 10:29:06 simonm Exp $
4 * (c) The GHC Team, 1998-1999
6 * Code to perform updates.
8 * ---------------------------------------------------------------------------*/
12 #include "HeapStackCheck.h"
16 The update frame return address must be *polymorphic*, that means
17 we have to cope with both vectored and non-vectored returns. This
18 is done by putting the return vector right before the info table, and
19 having a standard direct return address after the info table (pointed
20 to by the return address itself, as usual).
22 Each entry in the vector table points to a specialised entry code fragment
23 that knows how to return after doing the update. It would be possible to
24 use a single generic piece of code that simply entered the return value
25 to return, but it's quicker this way. The direct return code of course
26 just does another direct return when it's finished.
28 Why is there necessarily an activation underneath us on the stack?
29 Because if we're returning, that means we've got a constructor in
30 our hands. If there were any arguments to be applied to it, that
31 would be a type error. We don't ever return a PAP to an update frame,
32 the update is handled manually by stg_update_PAP.
35 /* on entry to the update code
36 (1) R1 points to the closure being returned
37 (2) R2 contains the tag (if we returned directly, non-vectored)
38 (3) Sp points to the update frame
41 /* Why updatee is placed in a temporary variable here: this helps
42 gcc's aliasing by indicating that the location of the updatee
43 doesn't change across assignments. Saves one instruction in the
47 #define UPD_FRAME_ENTRY_TEMPLATE(label,ret) \
51 StgClosure *updatee; \
53 /* tick - ToDo: check this is right */ \
54 TICK_UPD_EXISTING(); \
56 updatee = ((StgUpdateFrame *)Sp)->updatee; \
58 /* update the updatee with an indirection to the return value */\
59 UPD_IND(updatee,R1.p); \
61 /* reset Su to the next update frame */ \
62 Su = ((StgUpdateFrame *)Sp)->link; \
64 /* remove the update frame from the stack */ \
65 Sp += sizeofW(StgUpdateFrame); \
71 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_entry,ENTRY_CODE(Sp[0]));
72 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_0_entry,RET_VEC(Sp[0],0));
73 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_1_entry,RET_VEC(Sp[0],1));
74 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_2_entry,RET_VEC(Sp[0],2));
75 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_3_entry,RET_VEC(Sp[0],3));
76 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_4_entry,RET_VEC(Sp[0],4));
77 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_5_entry,RET_VEC(Sp[0],5));
78 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_6_entry,RET_VEC(Sp[0],6));
79 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_7_entry,RET_VEC(Sp[0],7));
82 Make sure this table is big enough to handle the maximum vectored
87 #define UPD_FRAME_BITMAP 3
89 #define UPD_FRAME_BITMAP 1
92 /* this bitmap indicates that the first word of an update frame is a
93 * non-pointer - this is the update frame link. (for profiling,
94 * there's a cost-centre-stack in there too).
97 VEC_POLY_INFO_TABLE(Upd_frame,UPD_FRAME_BITMAP, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, UPDATE_FRAME);
99 /* -----------------------------------------------------------------------------
100 Entry Code for a PAP.
102 The idea is to copy the chunk of stack from the PAP object and then
103 re-enter the function closure that failed it's args check in the
106 In fact, we do a little optimisation too, by performing the updates
107 for any update frames sitting on top of the stack. (ToDo: is this
108 really an optimisation? --SDM)
109 -------------------------------------------------------------------------- */
111 INFO_TABLE(PAP_info,PAP_entry,/*special layout*/0,0,PAP,const,EF_,0,0);
121 pap = (StgPAP *) R1.p;
124 * remove any update frames on the top of the stack, by just
125 * performing the update here.
127 while ((W_)Su - (W_)Sp == 0) {
129 switch (get_itbl(Su)->type) {
132 /* We're sitting on top of an update frame, so let's do the business */
133 UPD_IND(Su->updatee, pap);
135 #if defined(PROFILING)
137 * Restore the Cost Centre too (if required); again see Sansom
138 * thesis p 183. Take the CC out of the update frame if a
142 CCCS = Su->header.prof.ccs;
143 ENTER_CCS_PAP(pap->header.prof.ccs);
144 #endif /* PROFILING */
147 Sp += sizeofW(StgUpdateFrame);
151 /* Just pop the seq frame and return to the activation record
152 * underneath us - R1 already contains the address of the PAP.
154 Su = ((StgSeqFrame *)Su)->link;
155 Sp += sizeofW(StgSeqFrame);
156 JMP_(ENTRY_CODE(*Sp));
159 /* can't happen, see stg_update_PAP */
160 barf("PAP_entry: CATCH_FRAME");
163 barf("PAP_entry: strange activation record");
171 * Check for stack overflow.
173 STK_CHK_NP(Words,1,);
178 /* Enter PAP cost centre -- lexical scoping only */
179 ENTER_CCS_PAP_CL(pap);
182 p = (P_)(pap->payload);
184 /* Reload the stack */
185 for (i=0; i<Words; i++) Sp[i] = (W_) *p++;
189 JMP_(GET_ENTRY(R1.cl));
193 /* -----------------------------------------------------------------------------
194 stg_update_PAP: Update the current closure with a partial application.
196 This function is called whenever an argument satisfaction check fails.
197 -------------------------------------------------------------------------- */
199 EXTFUN(stg_update_PAP)
203 CostCentreStack *CCS_pap;
206 StgClosure *Fun, *Updatee;
212 /* Save the pointer to the function closure that just failed the
213 * argument satisfaction check
217 #if defined(GRAN_COUNT)
222 /* Just copy the whole block of stack between the stack pointer
223 * and the update frame pointer.
225 Words = (P_)Su - (P_)Sp;
226 ASSERT((int)Words >= 0);
228 #if defined(PROFILING)
229 /* set "CC_pap" to go in the updatee (see Sansom thesis, p 183) */
230 CCS_pap = Fun->header.prof.ccs;
236 * No arguments, only Node. Skip building the PAP and
237 * just plan to update with an indirection.
240 PapClosure = (StgPAP *)Fun;
245 PapSize = Words + sizeofW(StgPAP);
248 * First we need to do a heap check, which involves saving
249 * everything on the stack. We only have one live pointer:
250 * Fun, the function closure that was passed to us. If the
251 * heap check fails, we push the function closure on the stack
252 * and instruct the scheduler to try entering it again when
253 * the garbage collector has run.
255 * It's done this way because there's a possibility that the
256 * garbage collector might have messed around with the stack,
257 * such as removing the update frame.
259 if ((Hp += PapSize) > HpLim) {
262 JMP_(stg_gc_entertop);
265 TICK_ALLOC_UPD_PAP(1/*fun*/ + Words, 0);
267 CCS_ALLOC(CCS_pap, PapSize);
270 PapClosure = (StgPAP *)(Hp + 1 - PapSize); /* The new PapClosure */
272 SET_HDR(PapClosure,&PAP_info,CCS_pap);
273 PapClosure->n_args = Words;
274 PapClosure->fun = Fun;
276 /* Now fill in the closure fields */
279 for (i = Words-1; i >= 0; i--) {
285 * Finished constructing PAP closure; now update the updatee.
288 /* ToDo: we'd like to just jump to the code for PAP_entry here,
289 * which deals with a stack of update frames in one go. What to
290 * do about the special ticky and profiling stuff here?
293 switch (get_itbl(Su)->type) {
296 /* Set Sp to just above the SEQ frame (should be an activation rec.)*/
297 Sp = (P_)Su + sizeofW(StgSeqFrame);
300 Su = ((StgSeqFrame *)Su)->link;
302 /* return to the activation record, with the address of the PAP in R1 */
303 R1.p = (P_)PapClosure;
304 JMP_(ENTRY_CODE(*Sp));
307 /* Set Sp to just above the CATCH frame (should be an activation rec.)*/
308 Sp = (P_)Su + sizeofW(StgCatchFrame);
311 Su = ((StgCatchFrame *)Su)->link;
313 /* restart by entering the PAP */
314 R1.p = (P_)PapClosure;
315 JMP_(GET_ENTRY(R1.cl));
319 * Now we have a standard update frame, so we update the updatee with
320 * either the new PAP or Node.
323 Updatee = Su->updatee;
325 #if defined(PROFILING)
327 UPD_IND(Updatee,PapClosure);
328 TICK_UPD_PAP_IN_NEW(Words+1);
330 /* Lexical scoping requires a *permanent* indirection, and we
331 * also have to set the cost centre for the indirection.
333 UPD_PERM_IND(Updatee,PapClosure);
334 TICK_UPD_PAP_IN_PLACE();
335 Updatee->header.prof.ccs = CCS_pap;
338 UPD_IND(Updatee,PapClosure);
340 TICK_UPD_PAP_IN_NEW(Words+1);
342 TICK_UPD_PAP_IN_PLACE();
346 #if defined(PROFILING)
348 * Restore the Cost Centre too (if required); again see Sansom
349 * thesis p 183. Take the CC out of the update frame if a CAF/DICT.
351 CCCS = Su->header.prof.ccs;
352 ENTER_CCS_PAP(CCS_pap);
353 #endif /* PROFILING */
359 * Squeeze out update frame from stack.
361 for (i = Words-1; i >= 0; i--) {
362 Sp[i+(sizeofW(StgUpdateFrame))] = Sp[i];
364 Sp += sizeofW(StgUpdateFrame);
368 barf("stg_update_PAP: strange activation record");
372 * All done! Restart by re-entering Node
373 * Don't count this entry for ticky-ticky profiling.
375 JMP_(GET_ENTRY(R1.cl));
380 /* -----------------------------------------------------------------------------
381 Entry Code for an AP_UPD.
383 The idea is to copy the chunk of stack from the AP object and then
384 enter the function closure.
386 (This code is a simplified copy of the PAP code - with all the
387 update frame code stripped out.)
388 -------------------------------------------------------------------------- */
391 INFO_TABLE(AP_UPD_info,AP_UPD_entry,/*special layout*/0,0,AP_UPD,const,EF_,0,0);
401 ap = (StgAP_UPD *) R1.p;
406 * Check for stack overflow.
408 STK_CHK(Words+sizeofW(StgUpdateFrame),AP_UPD_entry,R2.p,1,);
410 PUSH_UPD_FRAME(R1.p, 0);
411 Sp -= sizeofW(StgUpdateFrame) + Words;
415 /* Enter PAP cost centre -- lexical scoping only */
416 ENTER_CCS_PAP_CL(ap); /* ToDo: ENTER_CC_AP_UPD_CL */
419 p = (P_)(ap->payload);
421 /* Reload the stack */
422 for (i=0; i<Words; i++) Sp[i] = (W_) *p++;
426 JMP_(GET_ENTRY(R1.cl));
431 /*-----------------------------------------------------------------------------
434 We don't have a primitive seq# operator: it is just a 'case'
435 expression whose scrutinee has either a polymorphic or function type
436 (constructor types can be handled by normal 'case' expressions).
438 To handle a polymorphic/function typed seq, we push a SEQ_FRAME on
439 the stack. This is a polymorphic activation record that just pops
440 itself and returns when entered. The purpose of the SEQ_FRAME is to
441 act as a barrier in case the scrutinee is a partial application - in
442 this way it is just like an update frame, except that it doesn't
444 -------------------------------------------------------------------------- */
446 #define SEQ_FRAME_ENTRY_TEMPLATE(label,ret) \
450 Su = ((StgSeqFrame *)Sp)->link; \
451 Sp += sizeofW(StgSeqFrame); \
456 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_entry, ENTRY_CODE(Sp[0]));
457 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_0_entry,ENTRY_CODE(Sp[0]));
458 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_1_entry,ENTRY_CODE(Sp[0]));
459 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_2_entry,ENTRY_CODE(Sp[0]));
460 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_3_entry,ENTRY_CODE(Sp[0]));
461 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_4_entry,ENTRY_CODE(Sp[0]));
462 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_5_entry,ENTRY_CODE(Sp[0]));
463 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_6_entry,ENTRY_CODE(Sp[0]));
464 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_7_entry,ENTRY_CODE(Sp[0]));
466 VEC_POLY_INFO_TABLE(seq_frame, UPD_FRAME_BITMAP, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, SEQ_FRAME);
468 /* -----------------------------------------------------------------------------
471 * This closure takes one argument, which it evaluates and returns the
472 * result with a direct return (never a vectored return!) in R1. It
473 * does this by pushing a SEQ_FRAME on the stack and
474 * entering its argument.
476 * It is used in deleteThread when reverting blackholes.
477 * -------------------------------------------------------------------------- */
479 INFO_TABLE(seq_info,seq_entry,1,0,FUN,const,EF_,0,0);
483 STK_CHK_GEN(sizeofW(StgSeqFrame), NO_PTRS, seq_entry, );
484 Sp -= sizeofW(StgSeqFrame);
486 R1.cl = R1.cl->payload[0];
487 JMP_(ENTRY_CODE(*R1.p));
492 /* -----------------------------------------------------------------------------
494 -------------------------------------------------------------------------- */
499 #define CATCH_FRAME_ENTRY_TEMPLATE(label,ret) \
504 Su = ((StgCatchFrame *)Sp)->link; \
505 Sp += sizeofW(StgCatchFrame); \
510 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_entry,ENTRY_CODE(Sp[0]));
511 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_0_entry,RET_VEC(Sp[0],0));
512 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_1_entry,RET_VEC(Sp[0],1));
513 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_2_entry,RET_VEC(Sp[0],2));
514 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_3_entry,RET_VEC(Sp[0],3));
515 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_4_entry,RET_VEC(Sp[0],4));
516 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_5_entry,RET_VEC(Sp[0],5));
517 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_6_entry,RET_VEC(Sp[0],6));
518 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_7_entry,RET_VEC(Sp[0],7));
521 #define CATCH_FRAME_BITMAP 3
523 #define CATCH_FRAME_BITMAP 1
526 /* Catch frames are very similar to update frames, but when entering
527 * one we just pop the frame off the stack and perform the correct
528 * kind of return to the activation record underneath us on the stack.
531 VEC_POLY_INFO_TABLE(catch_frame, CATCH_FRAME_BITMAP, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, CATCH_FRAME);
533 /* -----------------------------------------------------------------------------
534 * The catch infotable
536 * This should be exactly the same as would be generated by this STG code
538 * catch = {x,h} \n {} -> catch#{x,h}
540 * It is used in deleteThread when reverting blackholes.
541 * -------------------------------------------------------------------------- */
543 INFO_TABLE(catch_info,catch_entry,2,0,FUN,const,EF_,0,0);
547 R2.cl = payloadCPtr(R1.cl,1); /* h */
548 R1.cl = payloadCPtr(R1.cl,0); /* x */
558 /* args: R1 = m, R2 = k */
559 STK_CHK_GEN(sizeofW(StgCatchFrame), R1_PTR | R2_PTR, catchzh_fast, );
560 Sp -= sizeofW(StgCatchFrame);
561 fp = (StgCatchFrame *)Sp;
562 SET_HDR(fp,(StgInfoTable *)&catch_frame_info,CCCS);
563 fp -> handler = R2.cl;
565 Su = (StgUpdateFrame *)fp;
566 TICK_CATCHF_PUSHED();
568 JMP_(ENTRY_CODE(*R1.p));
573 /* -----------------------------------------------------------------------------
574 * The raise infotable
576 * This should be exactly the same as would be generated by this STG code
578 * raise = {err} \n {} -> raise#{err}
580 * It is used in raisezh_fast to update thunks on the update list
581 * -------------------------------------------------------------------------- */
583 INFO_TABLE(raise_info,raise_entry,1,0,FUN,const,EF_,0,0);
587 R1.cl = R1.cl->payload[0];
596 StgClosure *raise_closure;
598 /* args : R1 = error */
602 /* This closure represents the expression 'raise# E' where E
603 * is the exception raise. It is used to overwrite all the
604 * thunks which are currently under evaluataion.
606 raise_closure = (StgClosure *)RET_STGCALL1(P_,allocate,
607 sizeofW(StgClosure)+1);
608 raise_closure->header.info = &raise_info;
609 raise_closure->payload[0] = R1.cl;
613 switch (get_itbl(p)->type) {
616 UPD_IND(p->updatee,raise_closure);
621 p = ((StgSeqFrame *)p)->link;
629 barf("raisezh_fast: STOP_FRAME");
632 barf("raisezh_fast: weird activation record");
639 /* Ok, p points to the enclosing CATCH_FRAME. Pop everything down to
640 * and including this frame, update Su, push R1, and enter the handler.
642 Su = ((StgCatchFrame *)p)->link;
643 handler = ((StgCatchFrame *)p)->handler;
645 Sp = (P_)p + sizeofW(StgCatchFrame) - 1;
650 JMP_(ENTRY_CODE(handler->header.info));