[project @ 1999-03-26 10:29:02 by simonm]
[ghc-hetmet.git] / ghc / rts / Updates.hc
1 /* -----------------------------------------------------------------------------
2  * $Id: Updates.hc,v 1.13 1999/03/26 10:29:06 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     CCS_pap = Fun->header.prof.ccs;
231 #endif
232
233     if (Words == 0) { 
234
235         /* 
236          * No arguments, only Node.  Skip building the PAP and
237          * just plan to update with an indirection.
238          */
239
240         PapClosure = (StgPAP *)Fun;
241
242     } else {
243            /* Build the PAP */
244
245         PapSize = Words + sizeofW(StgPAP);
246     
247         /*
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.
254          *
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.
258          */
259         if ((Hp += PapSize) > HpLim) {
260           Sp -= 1;
261           Sp[0] = (W_)Fun;          
262           JMP_(stg_gc_entertop);
263         }
264
265         TICK_ALLOC_UPD_PAP(1/*fun*/ + Words, 0);
266 #ifdef PROFILING
267         CCS_ALLOC(CCS_pap, PapSize);
268 #endif
269
270         PapClosure = (StgPAP *)(Hp + 1 - PapSize); /* The new PapClosure */
271
272         SET_HDR(PapClosure,&PAP_info,CCS_pap);
273         PapClosure->n_args = Words;
274         PapClosure->fun = Fun;
275
276         /* Now fill in the closure fields */
277
278         p = Hp;
279         for (i = Words-1; i >= 0; i--) {
280            *p-- = (W_) Sp[i];
281         }
282     }
283
284     /* 
285      * Finished constructing PAP closure; now update the updatee. 
286      */
287
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?
291      */
292
293     switch (get_itbl(Su)->type) {
294
295     case SEQ_FRAME:
296       /* Set Sp to just above the SEQ frame (should be an activation rec.)*/
297       Sp = (P_)Su + sizeofW(StgSeqFrame);
298
299       /* restore Su */
300       Su = ((StgSeqFrame *)Su)->link;
301         
302       /* return to the activation record, with the address of the PAP in R1 */
303       R1.p = (P_)PapClosure;
304       JMP_(ENTRY_CODE(*Sp));
305       
306     case CATCH_FRAME:
307       /* Set Sp to just above the CATCH frame (should be an activation rec.)*/
308       Sp = (P_)Su + sizeofW(StgCatchFrame);
309
310       /* restore Su */
311       Su = ((StgCatchFrame *)Su)->link;
312         
313       /* restart by entering the PAP */
314       R1.p = (P_)PapClosure;
315       JMP_(GET_ENTRY(R1.cl));
316       
317     case UPDATE_FRAME:
318       /* 
319        * Now we have a standard update frame, so we update the updatee with 
320        * either the new PAP or Node.
321        */
322       
323       Updatee = Su->updatee;
324
325 #if defined(PROFILING)
326       if (Words != 0) {
327         UPD_IND(Updatee,PapClosure);
328         TICK_UPD_PAP_IN_NEW(Words+1);
329       } else {
330         /* Lexical scoping requires a *permanent* indirection, and we
331          * also have to set the cost centre for the indirection.
332          */
333         UPD_PERM_IND(Updatee,PapClosure);
334         TICK_UPD_PAP_IN_PLACE();
335         Updatee->header.prof.ccs = CCS_pap;
336       }
337 #else
338       UPD_IND(Updatee,PapClosure);
339       if (Words != 0) {
340         TICK_UPD_PAP_IN_NEW(Words+1);
341       } else {
342         TICK_UPD_PAP_IN_PLACE();
343       }
344 #endif  
345
346 #if defined(PROFILING)
347       /* 
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.
350        */
351       CCCS = Su->header.prof.ccs;
352       ENTER_CCS_PAP(CCS_pap);
353 #endif /* PROFILING */
354       
355       /* Restore Su */
356       Su = Su->link;
357       
358       /* 
359        * Squeeze out update frame from stack.
360        */
361       for (i = Words-1; i >= 0; i--) {
362         Sp[i+(sizeofW(StgUpdateFrame))] = Sp[i];
363       }
364       Sp += sizeofW(StgUpdateFrame);
365       break;
366       
367     default:
368       barf("stg_update_PAP: strange activation record");
369     }   
370
371     /* 
372      * All done!  Restart by re-entering Node
373      * Don't count this entry for ticky-ticky profiling. 
374      */
375     JMP_(GET_ENTRY(R1.cl));
376     FE_
377
378
379
380 /* -----------------------------------------------------------------------------
381    Entry Code for an AP_UPD.
382
383    The idea is to copy the chunk of stack from the AP object and then
384    enter the function closure.
385
386    (This code is a simplified copy of the PAP code - with all the 
387     update frame code stripped out.)
388    -------------------------------------------------------------------------- */
389
390
391 INFO_TABLE(AP_UPD_info,AP_UPD_entry,/*special layout*/0,0,AP_UPD,const,EF_,0,0);
392 STGFUN(AP_UPD_entry)
393 {
394   nat Words;
395   P_ p;
396   nat i;
397   StgAP_UPD *ap;
398
399   FB_
400     
401   ap = (StgAP_UPD *) R1.p;
402   
403   Words = ap->n_args;
404
405   /* 
406    * Check for stack overflow.
407    */
408   STK_CHK(Words+sizeofW(StgUpdateFrame),AP_UPD_entry,R2.p,1,);
409
410   PUSH_UPD_FRAME(R1.p, 0);
411   Sp -= sizeofW(StgUpdateFrame) + Words;
412
413   TICK_ENT_AP_UPD(ap);
414
415   /* Enter PAP cost centre -- lexical scoping only */
416   ENTER_CCS_PAP_CL(ap);   /* ToDo: ENTER_CC_AP_UPD_CL */
417
418   R1.cl = ap->fun;
419   p = (P_)(ap->payload);
420
421   /* Reload the stack */
422   for (i=0; i<Words; i++) Sp[i] = (W_) *p++;
423
424   /* Off we go! */
425   TICK_ENT_VIA_NODE();
426   JMP_(GET_ENTRY(R1.cl));
427   FE_
428 }
429
430
431 /*-----------------------------------------------------------------------------
432   Seq frames 
433
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).
437
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
443   update anything.
444   -------------------------------------------------------------------------- */
445
446 #define SEQ_FRAME_ENTRY_TEMPLATE(label,ret)     \
447    IFN_(label)                                  \
448    {                                            \
449       FB_                                       \
450       Su = ((StgSeqFrame *)Sp)->link;   \
451       Sp += sizeofW(StgSeqFrame);               \
452       JMP_(ret);                                \
453       FE_                                       \
454    }
455
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]));
465
466 VEC_POLY_INFO_TABLE(seq_frame, UPD_FRAME_BITMAP, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, SEQ_FRAME);
467
468 /* -----------------------------------------------------------------------------
469  * The seq infotable
470  *
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.
475  *
476  * It is used in deleteThread when reverting blackholes.
477  * -------------------------------------------------------------------------- */
478
479 INFO_TABLE(seq_info,seq_entry,1,0,FUN,const,EF_,0,0);
480 STGFUN(seq_entry)
481 {
482   FB_
483   STK_CHK_GEN(sizeofW(StgSeqFrame), NO_PTRS, seq_entry, );
484   Sp -= sizeofW(StgSeqFrame);
485   PUSH_SEQ_FRAME(Sp);
486   R1.cl = R1.cl->payload[0];
487   JMP_(ENTRY_CODE(*R1.p));         
488   FE_
489 }
490
491
492 /* -----------------------------------------------------------------------------
493    Exception Primitives
494    -------------------------------------------------------------------------- */
495
496 FN_(catchzh_fast);
497 FN_(raisezh_fast);
498
499 #define CATCH_FRAME_ENTRY_TEMPLATE(label,ret)   \
500    FN_(label);                                  \
501    FN_(label)                                   \
502    {                                            \
503       FB_                                       \
504       Su = ((StgCatchFrame *)Sp)->link;         \
505       Sp += sizeofW(StgCatchFrame);             \
506       JMP_(ret);                                \
507       FE_                                       \
508    }
509
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));
519
520 #ifdef PROFILING
521 #define CATCH_FRAME_BITMAP 3
522 #else
523 #define CATCH_FRAME_BITMAP 1
524 #endif
525
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.
529  */
530
531 VEC_POLY_INFO_TABLE(catch_frame, CATCH_FRAME_BITMAP, NULL/*srt*/, 0/*srt_off*/, 0/*srt_len*/, CATCH_FRAME);
532
533 /* -----------------------------------------------------------------------------
534  * The catch infotable
535  *
536  * This should be exactly the same as would be generated by this STG code
537  *
538  * catch = {x,h} \n {} -> catch#{x,h}
539  *
540  * It is used in deleteThread when reverting blackholes.
541  * -------------------------------------------------------------------------- */
542
543 INFO_TABLE(catch_info,catch_entry,2,0,FUN,const,EF_,0,0);
544 STGFUN(catch_entry)
545 {
546   FB_
547   R2.cl = payloadCPtr(R1.cl,1); /* h */
548   R1.cl = payloadCPtr(R1.cl,0); /* x */
549   JMP_(catchzh_fast);
550   FE_
551 }
552
553 FN_(catchzh_fast)
554 {
555   StgCatchFrame *fp;
556   FB_
557
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;
564     fp -> link = Su;
565     Su = (StgUpdateFrame *)fp;
566     TICK_CATCHF_PUSHED();
567     TICK_ENT_VIA_NODE();
568     JMP_(ENTRY_CODE(*R1.p));         
569     
570   FE_
571 }      
572
573 /* -----------------------------------------------------------------------------
574  * The raise infotable
575  * 
576  * This should be exactly the same as would be generated by this STG code
577  *
578  *   raise = {err} \n {} -> raise#{err}
579  *
580  * It is used in raisezh_fast to update thunks on the update list
581  * -------------------------------------------------------------------------- */
582
583 INFO_TABLE(raise_info,raise_entry,1,0,FUN,const,EF_,0,0);
584 STGFUN(raise_entry)
585 {
586   FB_
587   R1.cl = R1.cl->payload[0];
588   JMP_(raisezh_fast);
589   FE_
590 }
591
592 FN_(raisezh_fast)
593 {
594   StgClosure *handler;
595   StgUpdateFrame *p;
596   StgClosure *raise_closure;
597   FB_
598     /* args : R1 = error */
599
600     p = Su;
601
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.
605      */
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;
610
611     while (1) {
612
613       switch (get_itbl(p)->type) {
614
615       case UPDATE_FRAME:
616         UPD_IND(p->updatee,raise_closure);
617         p = p->link;
618         continue;
619
620       case SEQ_FRAME:
621         p = ((StgSeqFrame *)p)->link;
622         continue;
623
624       case CATCH_FRAME:
625         /* found it! */
626         break;
627
628       case STOP_FRAME:
629         barf("raisezh_fast: STOP_FRAME");
630
631       default:
632         barf("raisezh_fast: weird activation record");
633       }
634       
635       break;
636
637     }
638     
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.
641      */
642     Su = ((StgCatchFrame *)p)->link; 
643     handler = ((StgCatchFrame *)p)->handler;
644     
645     Sp = (P_)p + sizeofW(StgCatchFrame) - 1;
646     *Sp = R1.w;
647
648     TICK_ENT_VIA_NODE();
649     R1.cl = handler;
650     JMP_(ENTRY_CODE(handler->header.info));
651     
652   FE_
653 }
654