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