1 /* -----------------------------------------------------------------------------
2 * $Id: Updates.hc,v 1.12 1999/03/25 13:14:08 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) */
231 CCS_pap = (CostCentreStack *) Fun->header.prof.ccs;
232 if (IS_CAF_OR_SUB_CCS(CCS_pap)) {
240 * No arguments, only Node. Skip building the PAP and
241 * just plan to update with an indirection.
244 PapClosure = (StgPAP *)Fun;
249 PapSize = Words + sizeofW(StgPAP);
252 * First we need to do a heap check, which involves saving
253 * everything on the stack. We only have one live pointer:
254 * Fun, the function closure that was passed to us. If the
255 * heap check fails, we push the function closure on the stack
256 * and instruct the scheduler to try entering it again when
257 * the garbage collector has run.
259 * It's done this way because there's a possibility that the
260 * garbage collector might have messed around with the stack,
261 * such as removing the update frame.
263 if ((Hp += PapSize) > HpLim) {
266 JMP_(stg_gc_entertop);
269 TICK_ALLOC_UPD_PAP(1/*fun*/ + Words, 0);
271 CCS_ALLOC(CCS_pap, PapSize);
274 PapClosure = (StgPAP *)(Hp + 1 - PapSize); /* The new PapClosure */
276 SET_HDR(PapClosure,&PAP_info,CCS_pap);
277 PapClosure->n_args = Words;
278 PapClosure->fun = Fun;
280 /* Now fill in the closure fields */
283 for (i = Words-1; i >= 0; i--) {
289 * Finished constructing PAP closure; now update the updatee.
292 /* ToDo: we'd like to just jump to the code for PAP_entry here,
293 * which deals with a stack of update frames in one go. What to
294 * do about the special ticky and profiling stuff here?
297 switch (get_itbl(Su)->type) {
300 /* Set Sp to just above the SEQ frame (should be an activation rec.)*/
301 Sp = (P_)Su + sizeofW(StgSeqFrame);
304 Su = ((StgSeqFrame *)Su)->link;
306 /* return to the activation record, with the address of the PAP in R1 */
307 R1.p = (P_)PapClosure;
308 JMP_(ENTRY_CODE(*Sp));
311 /* Set Sp to just above the CATCH frame (should be an activation rec.)*/
312 Sp = (P_)Su + sizeofW(StgCatchFrame);
315 Su = ((StgCatchFrame *)Su)->link;
317 /* restart by entering the PAP */
318 R1.p = (P_)PapClosure;
319 JMP_(GET_ENTRY(R1.cl));
323 * Now we have a standard update frame, so we update the updatee with
324 * either the new PAP or Node.
327 Updatee = Su->updatee;
329 #if defined(PROFILING)
331 UPD_IND(Updatee,PapClosure);
332 TICK_UPD_PAP_IN_NEW(Words+1);
334 /* Lexical scoping requires a *permanent* indirection, and we
335 * also have to set the cost centre for the indirection.
337 UPD_PERM_IND(Updatee,PapClosure);
338 TICK_UPD_PAP_IN_PLACE();
339 Updatee->header.prof.ccs = CCS_pap;
342 UPD_IND(Updatee,PapClosure);
344 TICK_UPD_PAP_IN_NEW(Words+1);
346 TICK_UPD_PAP_IN_PLACE();
350 #if defined(PROFILING)
352 * Restore the Cost Centre too (if required); again see Sansom
353 * thesis p 183. Take the CC out of the update frame if a CAF/DICT.
355 CCCS = Su->header.prof.ccs;
356 ENTER_CCS_PAP(CCS_pap);
357 #endif /* PROFILING */
363 * Squeeze out update frame from stack.
365 for (i = Words-1; i >= 0; i--) {
366 Sp[i+(sizeofW(StgUpdateFrame))] = Sp[i];
368 Sp += sizeofW(StgUpdateFrame);
372 barf("stg_update_PAP: strange activation record");
376 * All done! Restart by re-entering Node
377 * Don't count this entry for ticky-ticky profiling.
379 JMP_(GET_ENTRY(R1.cl));
384 /* -----------------------------------------------------------------------------
385 Entry Code for an AP_UPD.
387 The idea is to copy the chunk of stack from the AP object and then
388 enter the function closure.
390 (This code is a simplified copy of the PAP code - with all the
391 update frame code stripped out.)
392 -------------------------------------------------------------------------- */
395 INFO_TABLE(AP_UPD_info,AP_UPD_entry,/*special layout*/0,0,AP_UPD,const,EF_,0,0);
405 ap = (StgAP_UPD *) R1.p;
410 * Check for stack overflow.
412 STK_CHK(Words+sizeofW(StgUpdateFrame),AP_UPD_entry,R2.p,1,);
414 PUSH_UPD_FRAME(R1.p, 0);
415 Sp -= sizeofW(StgUpdateFrame) + Words;
419 /* Enter PAP cost centre -- lexical scoping only */
420 ENTER_CCS_PAP_CL(ap); /* ToDo: ENTER_CC_AP_UPD_CL */
423 p = (P_)(ap->payload);
425 /* Reload the stack */
426 for (i=0; i<Words; i++) Sp[i] = (W_) *p++;
430 JMP_(GET_ENTRY(R1.cl));
435 /*-----------------------------------------------------------------------------
438 We don't have a primitive seq# operator: it is just a 'case'
439 expression whose scrutinee has either a polymorphic or function type
440 (constructor types can be handled by normal 'case' expressions).
442 To handle a polymorphic/function typed seq, we push a SEQ_FRAME on
443 the stack. This is a polymorphic activation record that just pops
444 itself and returns when entered. The purpose of the SEQ_FRAME is to
445 act as a barrier in case the scrutinee is a partial application - in
446 this way it is just like an update frame, except that it doesn't
448 -------------------------------------------------------------------------- */
450 #define SEQ_FRAME_ENTRY_TEMPLATE(label,ret) \
454 Su = ((StgSeqFrame *)Sp)->link; \
455 Sp += sizeofW(StgSeqFrame); \
460 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_entry, ENTRY_CODE(Sp[0]));
461 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_0_entry,ENTRY_CODE(Sp[0]));
462 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_1_entry,ENTRY_CODE(Sp[0]));
463 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_2_entry,ENTRY_CODE(Sp[0]));
464 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_3_entry,ENTRY_CODE(Sp[0]));
465 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_4_entry,ENTRY_CODE(Sp[0]));
466 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_5_entry,ENTRY_CODE(Sp[0]));
467 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_6_entry,ENTRY_CODE(Sp[0]));
468 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_7_entry,ENTRY_CODE(Sp[0]));
470 VEC_POLY_INFO_TABLE(seq_frame,1, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, SEQ_FRAME);
472 /* -----------------------------------------------------------------------------
475 * This closure takes one argument, which it evaluates and returns the
476 * result with a direct return (never a vectored return!) in R1. It
477 * does this by pushing a SEQ_FRAME on the stack and
478 * entering its argument.
480 * It is used in deleteThread when reverting blackholes.
481 * -------------------------------------------------------------------------- */
483 INFO_TABLE(seq_info,seq_entry,1,0,FUN,const,EF_,0,0);
487 STK_CHK_GEN(sizeofW(StgSeqFrame), NO_PTRS, seq_entry, );
488 Sp -= sizeof(StgSeqFrame);
490 R1.cl = R1.cl->payload[0];
491 JMP_(ENTRY_CODE(*R1.p));
496 /* -----------------------------------------------------------------------------
498 -------------------------------------------------------------------------- */
503 #define CATCH_FRAME_ENTRY_TEMPLATE(label,ret) \
508 Su = ((StgCatchFrame *)Sp)->link; \
509 Sp += sizeofW(StgCatchFrame); \
514 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_entry,ENTRY_CODE(Sp[0]));
515 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_0_entry,RET_VEC(Sp[0],0));
516 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_1_entry,RET_VEC(Sp[0],1));
517 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_2_entry,RET_VEC(Sp[0],2));
518 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_3_entry,RET_VEC(Sp[0],3));
519 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_4_entry,RET_VEC(Sp[0],4));
520 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_5_entry,RET_VEC(Sp[0],5));
521 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_6_entry,RET_VEC(Sp[0],6));
522 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_7_entry,RET_VEC(Sp[0],7));
525 #define CATCH_FRAME_BITMAP 3
527 #define CATCH_FRAME_BITMAP 1
530 /* Catch frames are very similar to update frames, but when entering
531 * one we just pop the frame off the stack and perform the correct
532 * kind of return to the activation record underneath us on the stack.
535 VEC_POLY_INFO_TABLE(catch_frame, CATCH_FRAME_BITMAP, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, CATCH_FRAME);
537 /* -----------------------------------------------------------------------------
538 * The catch infotable
540 * This should be exactly the same as would be generated by this STG code
542 * catch = {x,h} \n {} -> catch#{x,h}
544 * It is used in deleteThread when reverting blackholes.
545 * -------------------------------------------------------------------------- */
547 INFO_TABLE(catch_info,catch_entry,2,0,FUN,const,EF_,0,0);
551 R2.cl = payloadCPtr(R1.cl,1); /* h */
552 R1.cl = payloadCPtr(R1.cl,0); /* x */
562 /* args: R1 = m, R2 = k */
563 STK_CHK_GEN(sizeofW(StgCatchFrame), R1_PTR | R2_PTR, catchzh_fast, );
564 Sp -= sizeofW(StgCatchFrame);
565 fp = (StgCatchFrame *)Sp;
566 SET_HDR(fp,(StgInfoTable *)&catch_frame_info,CCCS);
567 fp -> handler = R2.cl;
569 Su = (StgUpdateFrame *)fp;
570 TICK_CATCHF_PUSHED();
572 JMP_(ENTRY_CODE(*R1.p));
577 /* -----------------------------------------------------------------------------
578 * The raise infotable
580 * This should be exactly the same as would be generated by this STG code
582 * raise = {err} \n {} -> raise#{err}
584 * It is used in raisezh_fast to update thunks on the update list
585 * -------------------------------------------------------------------------- */
587 INFO_TABLE(raise_info,raise_entry,1,0,FUN,const,EF_,0,0);
591 R1.cl = R1.cl->payload[0];
600 StgClosure *raise_closure;
602 /* args : R1 = error */
606 /* This closure represents the expression 'raise# E' where E
607 * is the exception raise. It is used to overwrite all the
608 * thunks which are currently under evaluataion.
610 raise_closure = (StgClosure *)RET_STGCALL1(P_,allocate,
611 sizeofW(StgClosure)+1);
612 raise_closure->header.info = &raise_info;
613 raise_closure->payload[0] = R1.cl;
617 switch (get_itbl(p)->type) {
620 UPD_IND(p->updatee,raise_closure);
625 p = ((StgSeqFrame *)p)->link;
633 barf("raisezh_fast: STOP_FRAME");
636 barf("raisezh_fast: weird activation record");
643 /* Ok, p points to the enclosing CATCH_FRAME. Pop everything down to
644 * and including this frame, update Su, push R1, and enter the handler.
646 Su = ((StgCatchFrame *)p)->link;
647 handler = ((StgCatchFrame *)p)->handler;
649 Sp = (P_)p + sizeofW(StgCatchFrame) - 1;
654 JMP_(ENTRY_CODE(handler->header.info));