e0dd5c28a0ecb7f2552a1ad68d3f8157647f1157
[ghc-hetmet.git] / ghc / rts / Updates.hc
1 /* -----------------------------------------------------------------------------
2  * $Id: Updates.hc,v 1.12 1999/03/25 13:14:08 simonm Exp $
3  *
4  * (c) The GHC Team, 1998-1999
5  *
6  * Code to perform updates.
7  *
8  * ---------------------------------------------------------------------------*/
9
10 #include "Rts.h"
11 #include "RtsUtils.h"
12 #include "HeapStackCheck.h"
13 #include "Storage.h"
14
15 /*
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).
21
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.
27
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.
33 */
34
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
39    */
40
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
44    update code. 
45    */
46
47 #define UPD_FRAME_ENTRY_TEMPLATE(label,ret)                             \
48         STGFUN(label);                                                  \
49         STGFUN(label)                                                   \
50         {                                                               \
51           StgClosure *updatee;                                          \
52           FB_                                                           \
53           /* tick - ToDo: check this is right */                        \
54           TICK_UPD_EXISTING();                                          \
55                                                                         \
56           updatee = ((StgUpdateFrame *)Sp)->updatee;                    \
57                                                 \
58           /* update the updatee with an indirection to the return value */\
59           UPD_IND(updatee,R1.p);                                        \
60                                                                         \
61           /* reset Su to the next update frame */                       \
62           Su = ((StgUpdateFrame *)Sp)->link;                            \
63                                                                         \
64           /* remove the update frame from the stack */                  \
65           Sp += sizeofW(StgUpdateFrame);                                \
66                                                                         \
67           JMP_(ret);                                                    \
68           FE_                                                           \
69         }
70
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));
80
81 /*
82   Make sure this table is big enough to handle the maximum vectored
83   return size!
84   */
85
86 #ifdef PROFILING
87 #define UPD_FRAME_BITMAP 3
88 #else
89 #define UPD_FRAME_BITMAP 1
90 #endif
91
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).
95  */
96
97 VEC_POLY_INFO_TABLE(Upd_frame,UPD_FRAME_BITMAP, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, UPDATE_FRAME);
98
99 /* -----------------------------------------------------------------------------
100    Entry Code for a PAP.
101
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
104    first place.
105
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    -------------------------------------------------------------------------- */
110
111 INFO_TABLE(PAP_info,PAP_entry,/*special layout*/0,0,PAP,const,EF_,0,0);
112 STGFUN(PAP_entry)
113 {
114   nat Words;
115   P_ p;
116   nat i;
117   StgPAP *pap;
118
119   FB_
120     
121   pap = (StgPAP *) R1.p;
122   
123   /*
124    * remove any update frames on the top of the stack, by just
125    * performing the update here.
126    */
127   while ((W_)Su - (W_)Sp == 0) {
128
129     switch (get_itbl(Su)->type) {
130
131     case UPDATE_FRAME:
132       /* We're sitting on top of an update frame, so let's do the business */
133       UPD_IND(Su->updatee, pap);
134
135 #if defined(PROFILING)
136       /* 
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
139        * CAF/DICT.
140        */
141       
142       CCCS = Su->header.prof.ccs;
143       ENTER_CCS_PAP(pap->header.prof.ccs);
144 #endif /* PROFILING */
145       
146       Su = Su->link;
147       Sp += sizeofW(StgUpdateFrame);
148       continue;
149
150     case SEQ_FRAME:
151       /* Just pop the seq frame and return to the activation record
152        * underneath us - R1 already contains the address of the PAP.
153        */
154       Su = ((StgSeqFrame *)Su)->link;
155       Sp += sizeofW(StgSeqFrame);
156       JMP_(ENTRY_CODE(*Sp));
157
158     case CATCH_FRAME:
159       /* can't happen, see stg_update_PAP */
160       barf("PAP_entry: CATCH_FRAME");
161
162     default:
163       barf("PAP_entry: strange activation record");
164     }
165
166   }
167
168   Words = pap->n_args;
169
170   /* 
171    * Check for stack overflow.
172    */
173   STK_CHK_NP(Words,1,);
174   Sp -= Words;
175
176   TICK_ENT_PAP(pap);
177
178   /* Enter PAP cost centre -- lexical scoping only */
179   ENTER_CCS_PAP_CL(pap);
180
181   R1.cl = pap->fun;
182   p = (P_)(pap->payload);
183
184   /* Reload the stack */
185   for (i=0; i<Words; i++) Sp[i] = (W_) *p++;
186
187   /* Off we go! */
188   TICK_ENT_VIA_NODE();
189   JMP_(GET_ENTRY(R1.cl));
190   FE_
191 }
192
193 /* -----------------------------------------------------------------------------
194    stg_update_PAP: Update the current closure with a partial application.
195
196    This function is called whenever an argument satisfaction check fails.
197    -------------------------------------------------------------------------- */
198
199 EXTFUN(stg_update_PAP)
200 {
201   nat Words, PapSize;
202 #ifdef PROFILING
203   CostCentreStack *CCS_pap;
204 #endif
205   StgPAP* PapClosure;
206   StgClosure *Fun, *Updatee;
207   P_ p;
208   I_ i;
209   
210   FB_
211
212     /* Save the pointer to the function closure that just failed the
213      * argument satisfaction check
214      */
215     Fun = R1.cl;
216
217 #if defined(GRAN_COUNT)
218 #error Fixme.
219       ++nPAPs;
220 #endif
221
222     /* Just copy the whole block of stack between the stack pointer
223      * and the update frame pointer.
224      */
225     Words    = (P_)Su - (P_)Sp;
226     ASSERT((int)Words >= 0);
227
228 #if defined(PROFILING)
229     /* set "CC_pap" to go in the updatee (see Sansom thesis, p 183) */
230
231     CCS_pap = (CostCentreStack *) Fun->header.prof.ccs;
232     if (IS_CAF_OR_SUB_CCS(CCS_pap)) {
233         CCS_pap = CCCS;
234     }
235 #endif
236
237     if (Words == 0) { 
238
239         /* 
240          * No arguments, only Node.  Skip building the PAP and
241          * just plan to update with an indirection.
242          */
243
244         PapClosure = (StgPAP *)Fun;
245
246     } else {
247            /* Build the PAP */
248
249         PapSize = Words + sizeofW(StgPAP);
250     
251         /*
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.
258          *
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.
262          */
263         if ((Hp += PapSize) > HpLim) {
264           Sp -= 1;
265           Sp[0] = (W_)Fun;          
266           JMP_(stg_gc_entertop);
267         }
268
269         TICK_ALLOC_UPD_PAP(1/*fun*/ + Words, 0);
270 #ifdef PROFILING
271         CCS_ALLOC(CCS_pap, PapSize);
272 #endif
273
274         PapClosure = (StgPAP *)(Hp + 1 - PapSize); /* The new PapClosure */
275
276         SET_HDR(PapClosure,&PAP_info,CCS_pap);
277         PapClosure->n_args = Words;
278         PapClosure->fun = Fun;
279
280         /* Now fill in the closure fields */
281
282         p = Hp;
283         for (i = Words-1; i >= 0; i--) {
284            *p-- = (W_) Sp[i];
285         }
286     }
287
288     /* 
289      * Finished constructing PAP closure; now update the updatee. 
290      */
291
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?
295      */
296
297     switch (get_itbl(Su)->type) {
298
299     case SEQ_FRAME:
300       /* Set Sp to just above the SEQ frame (should be an activation rec.)*/
301       Sp = (P_)Su + sizeofW(StgSeqFrame);
302
303       /* restore Su */
304       Su = ((StgSeqFrame *)Su)->link;
305         
306       /* return to the activation record, with the address of the PAP in R1 */
307       R1.p = (P_)PapClosure;
308       JMP_(ENTRY_CODE(*Sp));
309       
310     case CATCH_FRAME:
311       /* Set Sp to just above the CATCH frame (should be an activation rec.)*/
312       Sp = (P_)Su + sizeofW(StgCatchFrame);
313
314       /* restore Su */
315       Su = ((StgCatchFrame *)Su)->link;
316         
317       /* restart by entering the PAP */
318       R1.p = (P_)PapClosure;
319       JMP_(GET_ENTRY(R1.cl));
320       
321     case UPDATE_FRAME:
322       /* 
323        * Now we have a standard update frame, so we update the updatee with 
324        * either the new PAP or Node.
325        */
326       
327       Updatee = Su->updatee;
328
329 #if defined(PROFILING)
330       if (Words != 0) {
331         UPD_IND(Updatee,PapClosure);
332         TICK_UPD_PAP_IN_NEW(Words+1);
333       } else {
334         /* Lexical scoping requires a *permanent* indirection, and we
335          * also have to set the cost centre for the indirection.
336          */
337         UPD_PERM_IND(Updatee,PapClosure);
338         TICK_UPD_PAP_IN_PLACE();
339         Updatee->header.prof.ccs = CCS_pap;
340       }
341 #else
342       UPD_IND(Updatee,PapClosure);
343       if (Words != 0) {
344         TICK_UPD_PAP_IN_NEW(Words+1);
345       } else {
346         TICK_UPD_PAP_IN_PLACE();
347       }
348 #endif  
349
350 #if defined(PROFILING)
351       /* 
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.
354        */
355       CCCS = Su->header.prof.ccs;
356       ENTER_CCS_PAP(CCS_pap);
357 #endif /* PROFILING */
358       
359       /* Restore Su */
360       Su = Su->link;
361       
362       /* 
363        * Squeeze out update frame from stack.
364        */
365       for (i = Words-1; i >= 0; i--) {
366         Sp[i+(sizeofW(StgUpdateFrame))] = Sp[i];
367       }
368       Sp += sizeofW(StgUpdateFrame);
369       break;
370       
371     default:
372       barf("stg_update_PAP: strange activation record");
373     }   
374
375     /* 
376      * All done!  Restart by re-entering Node
377      * Don't count this entry for ticky-ticky profiling. 
378      */
379     JMP_(GET_ENTRY(R1.cl));
380     FE_
381
382
383
384 /* -----------------------------------------------------------------------------
385    Entry Code for an AP_UPD.
386
387    The idea is to copy the chunk of stack from the AP object and then
388    enter the function closure.
389
390    (This code is a simplified copy of the PAP code - with all the 
391     update frame code stripped out.)
392    -------------------------------------------------------------------------- */
393
394
395 INFO_TABLE(AP_UPD_info,AP_UPD_entry,/*special layout*/0,0,AP_UPD,const,EF_,0,0);
396 STGFUN(AP_UPD_entry)
397 {
398   nat Words;
399   P_ p;
400   nat i;
401   StgAP_UPD *ap;
402
403   FB_
404     
405   ap = (StgAP_UPD *) R1.p;
406   
407   Words = ap->n_args;
408
409   /* 
410    * Check for stack overflow.
411    */
412   STK_CHK(Words+sizeofW(StgUpdateFrame),AP_UPD_entry,R2.p,1,);
413
414   PUSH_UPD_FRAME(R1.p, 0);
415   Sp -= sizeofW(StgUpdateFrame) + Words;
416
417   TICK_ENT_AP_UPD(ap);
418
419   /* Enter PAP cost centre -- lexical scoping only */
420   ENTER_CCS_PAP_CL(ap);   /* ToDo: ENTER_CC_AP_UPD_CL */
421
422   R1.cl = ap->fun;
423   p = (P_)(ap->payload);
424
425   /* Reload the stack */
426   for (i=0; i<Words; i++) Sp[i] = (W_) *p++;
427
428   /* Off we go! */
429   TICK_ENT_VIA_NODE();
430   JMP_(GET_ENTRY(R1.cl));
431   FE_
432 }
433
434
435 /*-----------------------------------------------------------------------------
436   Seq frames 
437
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).
441
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
447   update anything.
448   -------------------------------------------------------------------------- */
449
450 #define SEQ_FRAME_ENTRY_TEMPLATE(label,ret)     \
451    IFN_(label)                                  \
452    {                                            \
453       FB_                                       \
454       Su = ((StgSeqFrame *)Sp)->link;   \
455       Sp += sizeofW(StgSeqFrame);               \
456       JMP_(ret);                                \
457       FE_                                       \
458    }
459
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]));
469
470 VEC_POLY_INFO_TABLE(seq_frame,1, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, SEQ_FRAME);
471
472 /* -----------------------------------------------------------------------------
473  * The seq infotable
474  *
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.
479  *
480  * It is used in deleteThread when reverting blackholes.
481  * -------------------------------------------------------------------------- */
482
483 INFO_TABLE(seq_info,seq_entry,1,0,FUN,const,EF_,0,0);
484 STGFUN(seq_entry)
485 {
486   FB_
487   STK_CHK_GEN(sizeofW(StgSeqFrame), NO_PTRS, seq_entry, );
488   Sp -= sizeof(StgSeqFrame);
489   PUSH_SEQ_FRAME(Sp);
490   R1.cl = R1.cl->payload[0];
491   JMP_(ENTRY_CODE(*R1.p));         
492   FE_
493 }
494
495
496 /* -----------------------------------------------------------------------------
497    Exception Primitives
498    -------------------------------------------------------------------------- */
499
500 FN_(catchzh_fast);
501 FN_(raisezh_fast);
502
503 #define CATCH_FRAME_ENTRY_TEMPLATE(label,ret)   \
504    FN_(label);                                  \
505    FN_(label)                                   \
506    {                                            \
507       FB_                                       \
508       Su = ((StgCatchFrame *)Sp)->link;         \
509       Sp += sizeofW(StgCatchFrame);             \
510       JMP_(ret);                                \
511       FE_                                       \
512    }
513
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));
523
524 #ifdef PROFILING
525 #define CATCH_FRAME_BITMAP 3
526 #else
527 #define CATCH_FRAME_BITMAP 1
528 #endif
529
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.
533  */
534
535 VEC_POLY_INFO_TABLE(catch_frame, CATCH_FRAME_BITMAP, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, CATCH_FRAME);
536
537 /* -----------------------------------------------------------------------------
538  * The catch infotable
539  *
540  * This should be exactly the same as would be generated by this STG code
541  *
542  * catch = {x,h} \n {} -> catch#{x,h}
543  *
544  * It is used in deleteThread when reverting blackholes.
545  * -------------------------------------------------------------------------- */
546
547 INFO_TABLE(catch_info,catch_entry,2,0,FUN,const,EF_,0,0);
548 STGFUN(catch_entry)
549 {
550   FB_
551   R2.cl = payloadCPtr(R1.cl,1); /* h */
552   R1.cl = payloadCPtr(R1.cl,0); /* x */
553   JMP_(catchzh_fast);
554   FE_
555 }
556
557 FN_(catchzh_fast)
558 {
559   StgCatchFrame *fp;
560   FB_
561
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;
568     fp -> link = Su;
569     Su = (StgUpdateFrame *)fp;
570     TICK_CATCHF_PUSHED();
571     TICK_ENT_VIA_NODE();
572     JMP_(ENTRY_CODE(*R1.p));         
573     
574   FE_
575 }      
576
577 /* -----------------------------------------------------------------------------
578  * The raise infotable
579  * 
580  * This should be exactly the same as would be generated by this STG code
581  *
582  *   raise = {err} \n {} -> raise#{err}
583  *
584  * It is used in raisezh_fast to update thunks on the update list
585  * -------------------------------------------------------------------------- */
586
587 INFO_TABLE(raise_info,raise_entry,1,0,FUN,const,EF_,0,0);
588 STGFUN(raise_entry)
589 {
590   FB_
591   R1.cl = R1.cl->payload[0];
592   JMP_(raisezh_fast);
593   FE_
594 }
595
596 FN_(raisezh_fast)
597 {
598   StgClosure *handler;
599   StgUpdateFrame *p;
600   StgClosure *raise_closure;
601   FB_
602     /* args : R1 = error */
603
604     p = Su;
605
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.
609      */
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;
614
615     while (1) {
616
617       switch (get_itbl(p)->type) {
618
619       case UPDATE_FRAME:
620         UPD_IND(p->updatee,raise_closure);
621         p = p->link;
622         continue;
623
624       case SEQ_FRAME:
625         p = ((StgSeqFrame *)p)->link;
626         continue;
627
628       case CATCH_FRAME:
629         /* found it! */
630         break;
631
632       case STOP_FRAME:
633         barf("raisezh_fast: STOP_FRAME");
634
635       default:
636         barf("raisezh_fast: weird activation record");
637       }
638       
639       break;
640
641     }
642     
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.
645      */
646     Su = ((StgCatchFrame *)p)->link; 
647     handler = ((StgCatchFrame *)p)->handler;
648     
649     Sp = (P_)p + sizeofW(StgCatchFrame) - 1;
650     *Sp = R1.w;
651
652     TICK_ENT_VIA_NODE();
653     R1.cl = handler;
654     JMP_(ENTRY_CODE(handler->header.info));
655     
656   FE_
657 }
658