aad6dc162967fae307319eac0b013325070a76ea
[ghc-hetmet.git] / ghc / rts / Updates.hc
1 /* -----------------------------------------------------------------------------
2  * $Id: Updates.hc,v 1.19 1999/09/14 12:16:36 simonmar 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 "RtsFlags.h"
13 #include "HeapStackCheck.h"
14 #include "Storage.h"
15 #include "ProfRts.h"
16
17 /*
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).
23
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.
29
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.
35 */
36
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
41    */
42
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
46    update code. 
47    */
48
49 #define UPD_FRAME_ENTRY_TEMPLATE(label,ret)                             \
50         STGFUN(label);                                                  \
51         STGFUN(label)                                                   \
52         {                                                               \
53           StgClosure *updatee;                                          \
54           FB_                                                           \
55                                                                         \
56           updatee = ((StgUpdateFrame *)Sp)->updatee;                    \
57                                                                         \
58           /* Tick - it must be a con, all the paps are handled          \
59            * in stg_upd_PAP and PAP_entry below                         \
60            */                                                           \
61           TICK_UPD_CON_IN_NEW(sizeW_fromITBL(get_itbl(updatee)));       \
62                                                                         \
63           /* update the updatee with an indirection to the return value */\
64           UPD_IND(updatee,R1.p);                                        \
65                                                                         \
66           /* reset Su to the next update frame */                       \
67           Su = ((StgUpdateFrame *)Sp)->link;                            \
68                                                                         \
69           /* remove the update frame from the stack */                  \
70           Sp += sizeofW(StgUpdateFrame);                                \
71                                                                         \
72           JMP_(ret);                                                    \
73           FE_                                                           \
74         }
75
76 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_entry,ENTRY_CODE(Sp[0]));
77 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_0_entry,RET_VEC(Sp[0],0));
78 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_1_entry,RET_VEC(Sp[0],1));
79 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_2_entry,RET_VEC(Sp[0],2));
80 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_3_entry,RET_VEC(Sp[0],3));
81 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_4_entry,RET_VEC(Sp[0],4));
82 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_5_entry,RET_VEC(Sp[0],5));
83 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_6_entry,RET_VEC(Sp[0],6));
84 UPD_FRAME_ENTRY_TEMPLATE(Upd_frame_7_entry,RET_VEC(Sp[0],7));
85
86 /*
87   Make sure this table is big enough to handle the maximum vectored
88   return size!
89   */
90
91 #ifdef PROFILING
92 #define UPD_FRAME_BITMAP 3
93 #else
94 #define UPD_FRAME_BITMAP 1
95 #endif
96
97 /* this bitmap indicates that the first word of an update frame is a
98  * non-pointer - this is the update frame link.  (for profiling,
99  * there's a cost-centre-stack in there too).
100  */
101
102 VEC_POLY_INFO_TABLE(Upd_frame,UPD_FRAME_BITMAP, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, UPDATE_FRAME,, EF_);
103
104 /* -----------------------------------------------------------------------------
105    Entry Code for a PAP.
106
107    The idea is to copy the chunk of stack from the PAP object and then
108    re-enter the function closure that failed it's args check in the
109    first place.
110
111    In fact, we do a little optimisation too, by performing the updates
112    for any update frames sitting on top of the stack. (ToDo: is this
113    really an optimisation? --SDM)
114    -------------------------------------------------------------------------- */
115
116 INFO_TABLE(PAP_info,PAP_entry,/*special layout*/0,0,PAP,,EF_,0,0);
117 STGFUN(PAP_entry)
118 {
119   nat Words;
120   P_ p;
121   nat i;
122   StgPAP *pap;
123
124   FB_
125     
126   pap = (StgPAP *) R1.p;
127   
128   /*
129    * remove any update frames on the top of the stack, by just
130    * performing the update here.
131    */
132   while ((W_)Su - (W_)Sp == 0) {
133
134     switch (get_itbl(Su)->type) {
135
136     case UPDATE_FRAME:
137       /* We're sitting on top of an update frame, so let's do the business */
138       UPD_IND(Su->updatee, pap);
139
140 #if defined(PROFILING)
141       /* 
142        * Restore the Cost Centre too (if required); again see Sansom
143        * thesis p 183.  Take the CC out of the update frame if a
144        * CAF/DICT.
145        */
146       
147       CCCS = Su->header.prof.ccs;
148 #endif /* PROFILING */
149       
150       Su = Su->link;
151       Sp += sizeofW(StgUpdateFrame);
152       continue;
153
154     case SEQ_FRAME:
155       /* Just pop the seq frame and return to the activation record
156        * underneath us - R1 already contains the address of the PAP.
157        */
158       Su = ((StgSeqFrame *)Su)->link;
159       Sp += sizeofW(StgSeqFrame);
160       JMP_(ENTRY_CODE(*Sp));
161
162     case CATCH_FRAME:
163       /* can't happen, see stg_update_PAP */
164       barf("PAP_entry: CATCH_FRAME");
165
166     default:
167       barf("PAP_entry: strange activation record");
168     }
169
170   }
171
172   Words = pap->n_args;
173
174   /* 
175    * Check for stack overflow.
176    */
177   STK_CHK_NP(Words,1,);
178   Sp -= Words;
179
180   TICK_ENT_PAP(pap);
181
182   /* Enter PAP cost centre -- lexical scoping only */
183   ENTER_CCS_PAP_CL(pap);
184
185   R1.cl = pap->fun;
186   p = (P_)(pap->payload);
187
188   /* Reload the stack */
189   for (i=0; i<Words; i++) Sp[i] = (W_) *p++;
190
191   /* Off we go! */
192   TICK_ENT_VIA_NODE();
193   JMP_(GET_ENTRY(R1.cl));
194   FE_
195 }
196
197 /* -----------------------------------------------------------------------------
198    stg_update_PAP: Update the current closure with a partial application.
199
200    This function is called whenever an argument satisfaction check fails.
201    -------------------------------------------------------------------------- */
202
203 EXTFUN(stg_update_PAP)
204 {
205   nat Words, PapSize;
206 #ifdef PROFILING
207   CostCentreStack *CCS_pap;
208 #endif
209   StgPAP* PapClosure;
210   StgClosure *Fun, *Updatee;
211   P_ p;
212   I_ i;
213   
214   FB_
215
216     /* Save the pointer to the function closure that just failed the
217      * argument satisfaction check
218      */
219     Fun = R1.cl;
220
221 #if defined(GRAN_COUNT)
222 #error Fixme.
223       ++nPAPs;
224 #endif
225
226     /* Just copy the whole block of stack between the stack pointer
227      * and the update frame pointer.
228      */
229     Words    = (P_)Su - (P_)Sp;
230     ASSERT((int)Words >= 0);
231
232 #if defined(PROFILING)
233     /* pretend we just entered the function closure */
234     ENTER_CCS_FCL(Fun);
235     CCS_pap = CCCS;
236 #endif
237
238     if (Words == 0) { 
239
240         /* 
241          * No arguments, only Node.  Skip building the PAP and
242          * just plan to update with an indirection.
243          */
244
245         PapClosure = (StgPAP *)Fun;
246
247     } else {
248            /* Build the PAP */
249
250         PapSize = Words + sizeofW(StgPAP);
251     
252         /*
253          * First we need to do a heap check, which involves saving
254          * everything on the stack.  We only have one live pointer:
255          * Fun, the function closure that was passed to us.  If the
256          * heap check fails, we push the function closure on the stack
257          * and instruct the scheduler to try entering it again when
258          * the garbage collector has run.
259          *
260          * It's done this way because there's a possibility that the
261          * garbage collector might have messed around with the stack,
262          * such as removing the update frame.
263          */
264         if ((Hp += PapSize) > HpLim) {
265           Sp -= 1;
266           Sp[0] = (W_)Fun;          
267           JMP_(stg_gc_entertop);
268         }
269
270         TICK_ALLOC_UPD_PAP(1/*fun*/ + Words, 0);
271 #ifdef PROFILING
272         CCS_ALLOC(CCS_pap, PapSize);
273 #endif
274
275         PapClosure = (StgPAP *)(Hp + 1 - PapSize); /* The new PapClosure */
276
277         SET_HDR(PapClosure,&PAP_info,CCS_pap);
278         PapClosure->n_args = Words;
279         PapClosure->fun = Fun;
280
281         /* Now fill in the closure fields */
282
283         p = Hp;
284         for (i = Words-1; i >= 0; i--) {
285            *p-- = (W_) Sp[i];
286         }
287     }
288
289     /* 
290      * Finished constructing PAP closure; now update the updatee. 
291      */
292
293     /* ToDo: we'd like to just jump to the code for PAP_entry here,
294      * which deals with a stack of update frames in one go.  What to
295      * do about the special ticky and profiling stuff here?
296      */
297
298     switch (get_itbl(Su)->type) {
299
300     case SEQ_FRAME:
301       /* Set Sp to just above the SEQ frame (should be an activation rec.)*/
302       Sp = (P_)Su + sizeofW(StgSeqFrame);
303
304       /* restore Su */
305       Su = ((StgSeqFrame *)Su)->link;
306         
307       /* return to the activation record, with the address of the PAP in R1 */
308       R1.p = (P_)PapClosure;
309       JMP_(ENTRY_CODE(*Sp));
310       
311     case CATCH_FRAME:
312       /* Set Sp to just above the CATCH frame (should be an activation rec.)*/
313       Sp = (P_)Su + sizeofW(StgCatchFrame);
314
315       /* restore Su */
316       Su = ((StgCatchFrame *)Su)->link;
317         
318       /* restart by entering the PAP */
319       R1.p = (P_)PapClosure;
320       JMP_(GET_ENTRY(R1.cl));
321       
322     case UPDATE_FRAME:
323       /* 
324        * Now we have a standard update frame, so we update the updatee with 
325        * either the new PAP or Node.
326        */
327       
328       Updatee = Su->updatee; 
329
330 #if defined(PROFILING)
331       if (Words != 0) {
332         UPD_IND(Updatee,PapClosure);
333         TICK_UPD_PAP_IN_NEW(Words+1);
334       } else {
335         /* Lexical scoping requires a *permanent* indirection, and we
336          * also have to set the cost centre for the indirection.
337          */
338         UPD_PERM_IND(Updatee,PapClosure);
339         TICK_UPD_PAP_IN_PLACE();
340         Updatee->header.prof.ccs = CCS_pap;
341       }
342 #else
343       UPD_IND(Updatee,PapClosure);
344       if (Words != 0) {
345         TICK_UPD_PAP_IN_NEW(Words+1);
346       } else {
347         TICK_UPD_PAP_IN_PLACE();
348       }
349 #endif  
350
351 #if defined(PROFILING)
352       CCCS = Su->header.prof.ccs;
353       ENTER_CCS_PAP(CCS_pap);
354 #endif /* PROFILING */
355       
356       /* Restore Su */
357       Su = Su->link;
358       
359       /* 
360        * Squeeze out update frame from stack.
361        */
362       for (i = Words-1; i >= 0; i--) {
363         Sp[i+(sizeofW(StgUpdateFrame))] = Sp[i];
364       }
365       Sp += sizeofW(StgUpdateFrame);
366       break;
367       
368     default:
369       barf("stg_update_PAP: strange activation record");
370     }   
371
372     /* 
373      * All done!  Restart by re-entering Node
374      * Don't count this entry for ticky-ticky profiling. 
375      */
376     JMP_(GET_ENTRY(R1.cl));
377     FE_
378 }
379
380
381 /* -----------------------------------------------------------------------------
382    Entry Code for an AP_UPD.
383
384    The idea is to copy the chunk of stack from the AP object and then
385    enter the function closure.
386
387    (This code is a simplified copy of the PAP code - with all the 
388     update frame code stripped out.)
389    -------------------------------------------------------------------------- */
390
391
392 INFO_TABLE(AP_UPD_info,AP_UPD_entry,/*special layout*/0,0,AP_UPD,,EF_,0,0);
393 STGFUN(AP_UPD_entry)
394 {
395   nat Words;
396   P_ p;
397   nat i;
398   StgAP_UPD *ap;
399
400   FB_
401     
402   ap = (StgAP_UPD *) R1.p;
403   
404   Words = ap->n_args;
405
406   /* 
407    * Check for stack overflow.
408    */
409   STK_CHK(Words+sizeofW(StgUpdateFrame),AP_UPD_entry,R2.p,1,);
410
411   PUSH_UPD_FRAME(R1.p, 0);
412   Sp -= sizeofW(StgUpdateFrame) + Words;
413
414   TICK_ENT_AP_UPD(ap);
415
416   /* Enter PAP cost centre -- lexical scoping only */
417   ENTER_CCS_PAP_CL(ap);   /* ToDo: ENTER_CC_AP_UPD_CL */
418
419   R1.cl = ap->fun;
420   p = (P_)(ap->payload);
421
422   /* Reload the stack */
423   for (i=0; i<Words; i++) Sp[i] = (W_) *p++;
424
425   /* Off we go! */
426   TICK_ENT_VIA_NODE();
427   JMP_(GET_ENTRY(R1.cl));
428   FE_
429 }
430
431
432 /*-----------------------------------------------------------------------------
433   Seq frames 
434
435   We don't have a primitive seq# operator: it is just a 'case'
436   expression whose scrutinee has either a polymorphic or function type
437   (constructor types can be handled by normal 'case' expressions).
438
439   To handle a polymorphic/function typed seq, we push a SEQ_FRAME on
440   the stack.  This is a polymorphic activation record that just pops
441   itself and returns when entered.  The purpose of the SEQ_FRAME is to
442   act as a barrier in case the scrutinee is a partial application - in
443   this way it is just like an update frame, except that it doesn't
444   update anything.
445   -------------------------------------------------------------------------- */
446
447 #define SEQ_FRAME_ENTRY_TEMPLATE(label,ret)     \
448    IFN_(label)                                  \
449    {                                            \
450       FB_                                       \
451       Su = ((StgSeqFrame *)Sp)->link;   \
452       Sp += sizeofW(StgSeqFrame);               \
453       JMP_(ret);                                \
454       FE_                                       \
455    }
456
457 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_entry,  ENTRY_CODE(Sp[0]));
458 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_0_entry,ENTRY_CODE(Sp[0]));
459 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_1_entry,ENTRY_CODE(Sp[0]));
460 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_2_entry,ENTRY_CODE(Sp[0]));
461 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_3_entry,ENTRY_CODE(Sp[0]));
462 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_4_entry,ENTRY_CODE(Sp[0]));
463 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_5_entry,ENTRY_CODE(Sp[0]));
464 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_6_entry,ENTRY_CODE(Sp[0]));
465 SEQ_FRAME_ENTRY_TEMPLATE(seq_frame_7_entry,ENTRY_CODE(Sp[0]));
466
467 VEC_POLY_INFO_TABLE(seq_frame, UPD_FRAME_BITMAP, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, SEQ_FRAME,, EF_);
468
469 /* -----------------------------------------------------------------------------
470  * The seq infotable
471  *
472  * This closure takes one argument, which it evaluates and returns the
473  * result with a direct return (never a vectored return!) in R1.  It
474  * does this by pushing a SEQ_FRAME on the stack and
475  * entering its argument.
476  *
477  * It is used in deleteThread when reverting blackholes.
478  * -------------------------------------------------------------------------- */
479
480 INFO_TABLE(seq_info,seq_entry,1,0,FUN,,EF_,0,0);
481 STGFUN(seq_entry)
482 {
483   FB_
484   STK_CHK_GEN(sizeofW(StgSeqFrame), NO_PTRS, seq_entry, );
485   Sp -= sizeofW(StgSeqFrame);
486   PUSH_SEQ_FRAME(Sp);
487   R1.cl = R1.cl->payload[0];
488   JMP_(ENTRY_CODE(*R1.p));         
489   FE_
490 }
491
492
493 /* -----------------------------------------------------------------------------
494    Exception Primitives
495    -------------------------------------------------------------------------- */
496
497 FN_(catchzh_fast);
498 FN_(raisezh_fast);
499
500 #define CATCH_FRAME_ENTRY_TEMPLATE(label,ret)   \
501    FN_(label);                                  \
502    FN_(label)                                   \
503    {                                            \
504       FB_                                       \
505       Su = ((StgCatchFrame *)Sp)->link;         \
506       Sp += sizeofW(StgCatchFrame);             \
507       JMP_(ret);                                \
508       FE_                                       \
509    }
510
511 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_entry,ENTRY_CODE(Sp[0]));
512 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_0_entry,RET_VEC(Sp[0],0));
513 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_1_entry,RET_VEC(Sp[0],1));
514 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_2_entry,RET_VEC(Sp[0],2));
515 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_3_entry,RET_VEC(Sp[0],3));
516 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_4_entry,RET_VEC(Sp[0],4));
517 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_5_entry,RET_VEC(Sp[0],5));
518 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_6_entry,RET_VEC(Sp[0],6));
519 CATCH_FRAME_ENTRY_TEMPLATE(catch_frame_7_entry,RET_VEC(Sp[0],7));
520
521 #ifdef PROFILING
522 #define CATCH_FRAME_BITMAP 3
523 #else
524 #define CATCH_FRAME_BITMAP 1
525 #endif
526
527 /* Catch frames are very similar to update frames, but when entering
528  * one we just pop the frame off the stack and perform the correct
529  * kind of return to the activation record underneath us on the stack.
530  */
531
532 VEC_POLY_INFO_TABLE(catch_frame, CATCH_FRAME_BITMAP, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, CATCH_FRAME,, EF_);
533
534 /* -----------------------------------------------------------------------------
535  * The catch infotable
536  *
537  * This should be exactly the same as would be generated by this STG code
538  *
539  * catch = {x,h} \n {} -> catch#{x,h}
540  *
541  * It is used in deleteThread when reverting blackholes.
542  * -------------------------------------------------------------------------- */
543
544 INFO_TABLE(catch_info,catch_entry,2,0,FUN,,EF_,0,0);
545 STGFUN(catch_entry)
546 {
547   FB_
548   R2.cl = payloadCPtr(R1.cl,1); /* h */
549   R1.cl = payloadCPtr(R1.cl,0); /* x */
550   JMP_(catchzh_fast);
551   FE_
552 }
553
554 FN_(catchzh_fast)
555 {
556   StgCatchFrame *fp;
557   FB_
558
559     /* args: R1 = m, R2 = k */
560     STK_CHK_GEN(sizeofW(StgCatchFrame), R1_PTR | R2_PTR, catchzh_fast, );
561     Sp -= sizeofW(StgCatchFrame);
562     fp = (StgCatchFrame *)Sp;
563     SET_HDR(fp,(StgInfoTable *)&catch_frame_info,CCCS);
564     fp -> handler = R2.cl;
565     fp -> link = Su;
566     Su = (StgUpdateFrame *)fp;
567     TICK_CATCHF_PUSHED();
568     TICK_ENT_VIA_NODE();
569     JMP_(ENTRY_CODE(*R1.p));         
570     
571   FE_
572 }      
573
574 /* -----------------------------------------------------------------------------
575  * The raise infotable
576  * 
577  * This should be exactly the same as would be generated by this STG code
578  *
579  *   raise = {err} \n {} -> raise#{err}
580  *
581  * It is used in raisezh_fast to update thunks on the update list
582  * -------------------------------------------------------------------------- */
583
584 INFO_TABLE(raise_info,raise_entry,1,0,FUN,,EF_,0,0);
585 STGFUN(raise_entry)
586 {
587   FB_
588   R1.cl = R1.cl->payload[0];
589   JMP_(raisezh_fast);
590   FE_
591 }
592
593 FN_(raisezh_fast)
594 {
595   StgClosure *handler;
596   StgUpdateFrame *p;
597   StgClosure *raise_closure;
598   FB_
599     /* args : R1 = error */
600
601     p = Su;
602
603     /* This closure represents the expression 'raise# E' where E
604      * is the exception raise.  It is used to overwrite all the
605      * thunks which are currently under evaluataion.
606      */
607     raise_closure = (StgClosure *)RET_STGCALL1(P_,allocate,
608                                                sizeofW(StgClosure)+1);
609     raise_closure->header.info = &raise_info;
610     raise_closure->payload[0] = R1.cl;
611
612     while (1) {
613
614       switch (get_itbl(p)->type) {
615
616       case UPDATE_FRAME:
617         UPD_IND(p->updatee,raise_closure);
618         p = p->link;
619         continue;
620
621       case SEQ_FRAME:
622         p = ((StgSeqFrame *)p)->link;
623         continue;
624
625       case CATCH_FRAME:
626         /* found it! */
627         break;
628
629       case STOP_FRAME:
630         barf("raisezh_fast: STOP_FRAME");
631
632       default:
633         barf("raisezh_fast: weird activation record");
634       }
635       
636       break;
637
638     }
639     
640     /* Ok, p points to the enclosing CATCH_FRAME.  Pop everything down to
641      * and including this frame, update Su, push R1, and enter the handler.
642      */
643     Su = ((StgCatchFrame *)p)->link; 
644     handler = ((StgCatchFrame *)p)->handler;
645     
646     Sp = (P_)p + sizeofW(StgCatchFrame) - 1;
647     *Sp = R1.w;
648
649     TICK_ENT_VIA_NODE();
650     R1.cl = handler;
651     JMP_(ENTRY_CODE(handler->header.info));
652     
653   FE_
654 }
655