[project @ 2004-02-12 02:04:59 by mthomas]
[ghc-hetmet.git] / ghc / rts / Interpreter.c
1 /* -----------------------------------------------------------------------------
2  * Bytecode interpreter
3  *
4  * Copyright (c) The GHC Team, 1994-2002.
5  * ---------------------------------------------------------------------------*/
6
7 #if !defined(SMP)
8 #include "PosixSource.h"
9 #else
10 /* Hack and slash.. */
11 #include "Stg.h"
12 #endif
13 #include "Rts.h"
14 #include "RtsAPI.h"
15 #include "RtsUtils.h"
16 #include "Closures.h"
17 #include "TSO.h"
18 #include "Schedule.h"
19 #include "RtsFlags.h"
20 #include "Storage.h"
21 #include "Updates.h"
22 #include "Sanity.h"
23
24 #include "Bytecodes.h"
25 #include "Printer.h"
26 #include "Disassembler.h"
27 #include "Interpreter.h"
28
29 #include <string.h>     /* for memcpy */
30 #ifdef HAVE_ERRNO_H
31 #include <errno.h>
32 #endif
33
34
35 /* --------------------------------------------------------------------------
36  * The bytecode interpreter
37  * ------------------------------------------------------------------------*/
38
39 /* Gather stats about entry, opcode, opcode-pair frequencies.  For
40    tuning the interpreter. */
41
42 /* #define INTERP_STATS */
43
44
45 /* Sp points to the lowest live word on the stack. */
46
47 #define BCO_NEXT      instrs[bciPtr++]
48 #define BCO_PTR(n)    (W_)ptrs[n]
49 #define BCO_LIT(n)    (W_)literals[n]
50 #define BCO_ITBL(n)   itbls[n]
51
52 #define LOAD_STACK_POINTERS                                     \
53     Sp = cap->r.rCurrentTSO->sp;                                \
54     /* We don't change this ... */                              \
55     SpLim = cap->r.rCurrentTSO->stack + RESERVED_STACK_WORDS;
56
57 #define SAVE_STACK_POINTERS                     \
58     cap->r.rCurrentTSO->sp = Sp
59
60 #define RETURN_TO_SCHEDULER(todo,retcode)       \
61    SAVE_STACK_POINTERS;                         \
62    cap->r.rCurrentTSO->what_next = (todo);      \
63    return (retcode);
64
65
66 STATIC_INLINE StgPtr
67 allocate_UPD (int n_words)
68 {
69    return allocate(stg_max(sizeofW(StgHeader)+MIN_UPD_SIZE, n_words));
70 }
71
72 STATIC_INLINE StgPtr
73 allocate_NONUPD (int n_words)
74 {
75     return allocate(stg_max(sizeofW(StgHeader)+MIN_NONUPD_SIZE, n_words));
76 }
77
78
79 #ifdef INTERP_STATS
80
81 /* Hacky stats, for tuning the interpreter ... */
82 int it_unknown_entries[N_CLOSURE_TYPES];
83 int it_total_unknown_entries;
84 int it_total_entries;
85
86 int it_retto_BCO;
87 int it_retto_UPDATE;
88 int it_retto_other;
89
90 int it_slides;
91 int it_insns;
92 int it_BCO_entries;
93
94 int it_ofreq[27];
95 int it_oofreq[27][27];
96 int it_lastopc;
97
98 #define INTERP_TICK(n) (n)++
99
100 void interp_startup ( void )
101 {
102    int i, j;
103    it_retto_BCO = it_retto_UPDATE = it_retto_other = 0;
104    it_total_entries = it_total_unknown_entries = 0;
105    for (i = 0; i < N_CLOSURE_TYPES; i++)
106       it_unknown_entries[i] = 0;
107    it_slides = it_insns = it_BCO_entries = 0;
108    for (i = 0; i < 27; i++) it_ofreq[i] = 0;
109    for (i = 0; i < 27; i++) 
110      for (j = 0; j < 27; j++)
111         it_oofreq[i][j] = 0;
112    it_lastopc = 0;
113 }
114
115 void interp_shutdown ( void )
116 {
117    int i, j, k, o_max, i_max, j_max;
118    fprintf(stderr, "%d constrs entered -> (%d BCO, %d UPD, %d ??? )\n",
119                    it_retto_BCO + it_retto_UPDATE + it_retto_other,
120                    it_retto_BCO, it_retto_UPDATE, it_retto_other );
121    fprintf(stderr, "%d total entries, %d unknown entries \n", 
122                    it_total_entries, it_total_unknown_entries);
123    for (i = 0; i < N_CLOSURE_TYPES; i++) {
124      if (it_unknown_entries[i] == 0) continue;
125      fprintf(stderr, "   type %2d: unknown entries (%4.1f%%) == %d\n",
126              i, 100.0 * ((double)it_unknown_entries[i]) / 
127                         ((double)it_total_unknown_entries),
128              it_unknown_entries[i]);
129    }
130    fprintf(stderr, "%d insns, %d slides, %d BCO_entries\n", 
131                    it_insns, it_slides, it_BCO_entries);
132    for (i = 0; i < 27; i++) 
133       fprintf(stderr, "opcode %2d got %d\n", i, it_ofreq[i] );
134
135    for (k = 1; k < 20; k++) {
136       o_max = 0;
137       i_max = j_max = 0;
138       for (i = 0; i < 27; i++) {
139          for (j = 0; j < 27; j++) {
140             if (it_oofreq[i][j] > o_max) {
141                o_max = it_oofreq[i][j];
142                i_max = i; j_max = j;
143             }
144          }
145       }
146       
147       fprintf ( stderr, "%d:  count (%4.1f%%) %6d   is %d then %d\n",
148                 k, ((double)o_max) * 100.0 / ((double)it_insns), o_max,
149                    i_max, j_max );
150       it_oofreq[i_max][j_max] = 0;
151
152    }
153 }
154
155 #else // !INTERP_STATS
156
157 #define INTERP_TICK(n) /* nothing */
158
159 #endif
160
161 static StgWord app_ptrs_itbl[] = {
162     (W_)&stg_ap_p_info,
163     (W_)&stg_ap_pp_info,
164     (W_)&stg_ap_ppp_info,
165     (W_)&stg_ap_pppp_info,
166     (W_)&stg_ap_ppppp_info,
167     (W_)&stg_ap_pppppp_info,
168     (W_)&stg_ap_ppppppp_info
169 };
170
171 StgThreadReturnCode
172 interpretBCO (Capability* cap)
173 {
174     // Use of register here is primarily to make it clear to compilers
175     // that these entities are non-aliasable.
176     register StgPtr       Sp;    // local state -- stack pointer
177     register StgPtr       SpLim; // local state -- stack lim pointer
178     register StgClosure*  obj;
179     nat n, m;
180
181     LOAD_STACK_POINTERS;
182
183     // ------------------------------------------------------------------------
184     // Case 1:
185     // 
186     //       We have a closure to evaluate.  Stack looks like:
187     //       
188     //          |   XXXX_info   |
189     //          +---------------+
190     //       Sp |      -------------------> closure
191     //          +---------------+
192     //       
193     if (Sp[0] == (W_)&stg_enter_info) {
194         Sp++;
195         goto eval;
196     }
197
198     // ------------------------------------------------------------------------
199     // Case 2:
200     // 
201     //       We have a BCO application to perform.  Stack looks like:
202     //
203     //          |     ....      |
204     //          +---------------+
205     //          |     arg1      |
206     //          +---------------+
207     //          |     BCO       |
208     //          +---------------+
209     //       Sp |   RET_BCO     |
210     //          +---------------+
211     //       
212     else if (Sp[0] == (W_)&stg_apply_interp_info) {
213         obj = (StgClosure *)Sp[1];
214         Sp += 2;
215         goto run_BCO_fun;
216     }
217
218     // ------------------------------------------------------------------------
219     // Case 3:
220     //
221     //       We have an unboxed value to return.  See comment before
222     //       do_return_unboxed, below.
223     //
224     else {
225         goto do_return_unboxed;
226     }
227
228     // Evaluate the object on top of the stack.
229 eval:
230     obj = (StgClosure*)Sp[0]; Sp++;
231
232 eval_obj:
233     INTERP_TICK(it_total_evals);
234
235     IF_DEBUG(interpreter,
236              fprintf(stderr, 
237              "\n---------------------------------------------------------------\n");
238              fprintf(stderr,"Evaluating: "); printObj(obj);
239              fprintf(stderr,"Sp = %p\n", Sp);
240              fprintf(stderr, "\n" );
241
242              printStackChunk(Sp,cap->r.rCurrentTSO->stack+cap->r.rCurrentTSO->stack_size);
243              fprintf(stderr, "\n\n");
244             );
245
246     IF_DEBUG(sanity,checkStackChunk(Sp, cap->r.rCurrentTSO->stack+cap->r.rCurrentTSO->stack_size));
247
248     switch ( get_itbl(obj)->type ) {
249
250     case IND:
251     case IND_OLDGEN:
252     case IND_PERM:
253     case IND_OLDGEN_PERM:
254     case IND_STATIC:
255     { 
256         obj = ((StgInd*)obj)->indirectee;
257         goto eval_obj;
258     }
259     
260     case CONSTR:
261     case CONSTR_1_0:
262     case CONSTR_0_1:
263     case CONSTR_2_0:
264     case CONSTR_1_1:
265     case CONSTR_0_2:
266     case CONSTR_INTLIKE:
267     case CONSTR_CHARLIKE:
268     case CONSTR_STATIC:
269     case CONSTR_NOCAF_STATIC:
270     case FUN:
271     case FUN_1_0:
272     case FUN_0_1:
273     case FUN_2_0:
274     case FUN_1_1:
275     case FUN_0_2:
276     case FUN_STATIC:
277     case PAP:
278         // already in WHNF
279         break;
280         
281     case BCO:
282         ASSERT(((StgBCO *)obj)->arity > 0);
283         break;
284
285     case AP:    /* Copied from stg_AP_entry. */
286     {
287         nat i, words;
288         StgAP *ap;
289         
290         ap = (StgAP*)obj;
291         words = ap->n_args;
292         
293         // Stack check
294         if (Sp - (words+sizeofW(StgUpdateFrame)) < SpLim) {
295             Sp -= 2;
296             Sp[1] = (W_)obj;
297             Sp[0] = (W_)&stg_enter_info;
298             RETURN_TO_SCHEDULER(ThreadInterpret, StackOverflow);
299         }
300         
301         /* Ok; we're safe.  Party on.  Push an update frame. */
302         Sp -= sizeofW(StgUpdateFrame);
303         {
304             StgUpdateFrame *__frame;
305             __frame = (StgUpdateFrame *)Sp;
306             SET_INFO(__frame, (StgInfoTable *)&stg_upd_frame_info);
307             __frame->updatee = (StgClosure *)(ap);
308         }
309         
310         /* Reload the stack */
311         Sp -= words;
312         for (i=0; i < words; i++) {
313             Sp[i] = (W_)ap->payload[i];
314         }
315
316         obj = (StgClosure*)ap->fun;
317         ASSERT(get_itbl(obj)->type == BCO);
318         goto run_BCO_fun;
319     }
320
321     default:
322 #ifdef INTERP_STATS
323     { 
324         int j;
325         
326         j = get_itbl(obj)->type;
327         ASSERT(j >= 0 && j < N_CLOSURE_TYPES);
328         it_unknown_entries[j]++;
329         it_total_unknown_entries++;
330     }
331 #endif
332     {
333         // Can't handle this object; yield to scheduler
334         IF_DEBUG(interpreter,
335                  fprintf(stderr, "evaluating unknown closure -- yielding to sched\n"); 
336                  printObj(obj);
337             );
338         Sp -= 2;
339         Sp[1] = (W_)obj;
340         Sp[0] = (W_)&stg_enter_info;
341         RETURN_TO_SCHEDULER(ThreadRunGHC, ThreadYielding);
342     }
343     }
344
345     // ------------------------------------------------------------------------
346     // We now have an evaluated object (obj).  The next thing to
347     // do is return it to the stack frame on top of the stack.
348 do_return:
349     ASSERT(closure_HNF(obj));
350
351     IF_DEBUG(interpreter,
352              fprintf(stderr, 
353              "\n---------------------------------------------------------------\n");
354              fprintf(stderr,"Returning: "); printObj(obj);
355              fprintf(stderr,"Sp = %p\n", Sp);
356              fprintf(stderr, "\n" );
357              printStackChunk(Sp,cap->r.rCurrentTSO->stack+cap->r.rCurrentTSO->stack_size);
358              fprintf(stderr, "\n\n");
359             );
360
361     IF_DEBUG(sanity,checkStackChunk(Sp, cap->r.rCurrentTSO->stack+cap->r.rCurrentTSO->stack_size));
362
363     switch (get_itbl((StgClosure *)Sp)->type) {
364
365     case RET_SMALL: {
366         const StgInfoTable *info;
367
368         // NOTE: not using get_itbl().
369         info = ((StgClosure *)Sp)->header.info;
370         if (info == (StgInfoTable *)&stg_ap_v_info) {
371             n = 1; m = 0; goto do_apply;
372         }
373         if (info == (StgInfoTable *)&stg_ap_f_info) {
374             n = 1; m = 1; goto do_apply;
375         }
376         if (info == (StgInfoTable *)&stg_ap_d_info) {
377             n = 1; m = sizeofW(StgDouble); goto do_apply;
378         }
379         if (info == (StgInfoTable *)&stg_ap_l_info) {
380             n = 1; m = sizeofW(StgInt64); goto do_apply;
381         }
382         if (info == (StgInfoTable *)&stg_ap_n_info) {
383             n = 1; m = 1; goto do_apply;
384         }
385         if (info == (StgInfoTable *)&stg_ap_p_info) {
386             n = 1; m = 1; goto do_apply;
387         }
388         if (info == (StgInfoTable *)&stg_ap_pp_info) {
389             n = 2; m = 2; goto do_apply;
390         }
391         if (info == (StgInfoTable *)&stg_ap_ppp_info) {
392             n = 3; m = 3; goto do_apply;
393         }
394         if (info == (StgInfoTable *)&stg_ap_pppp_info) {
395             n = 4; m = 4; goto do_apply;
396         }
397         if (info == (StgInfoTable *)&stg_ap_ppppp_info) {
398             n = 5; m = 5; goto do_apply;
399         }
400         if (info == (StgInfoTable *)&stg_ap_pppppp_info) {
401             n = 6; m = 6; goto do_apply;
402         }
403         if (info == (StgInfoTable *)&stg_ap_ppppppp_info) {
404             n = 7; m = 7; goto do_apply;
405         }
406         goto do_return_unrecognised;
407     }
408
409     case UPDATE_FRAME:
410         // Returning to an update frame: do the update, pop the update
411         // frame, and continue with the next stack frame.
412         INTERP_TICK(it_retto_UPDATE);
413         UPD_IND(((StgUpdateFrame *)Sp)->updatee, obj); 
414         Sp += sizeofW(StgUpdateFrame);
415         goto do_return;
416
417     case RET_BCO:
418         // Returning to an interpreted continuation: put the object on
419         // the stack, and start executing the BCO.
420         INTERP_TICK(it_retto_BCO);
421         Sp--;
422         Sp[0] = (W_)obj;
423         obj = (StgClosure*)Sp[2];
424         ASSERT(get_itbl(obj)->type == BCO);
425         goto run_BCO_return;
426
427     default:
428     do_return_unrecognised:
429     {
430         // Can't handle this return address; yield to scheduler
431         INTERP_TICK(it_retto_other);
432         IF_DEBUG(interpreter,
433                  fprintf(stderr, "returning to unknown frame -- yielding to sched\n"); 
434                  printStackChunk(Sp,cap->r.rCurrentTSO->stack+cap->r.rCurrentTSO->stack_size);
435             );
436         Sp -= 2;
437         Sp[1] = (W_)obj;
438         Sp[0] = (W_)&stg_enter_info;
439         RETURN_TO_SCHEDULER(ThreadRunGHC, ThreadYielding);
440     }
441     }
442
443     // -------------------------------------------------------------------------
444     // Returning an unboxed value.  The stack looks like this:
445     //
446     //    |     ....      |
447     //    +---------------+
448     //    |     fv2       |
449     //    +---------------+
450     //    |     fv1       |
451     //    +---------------+
452     //    |     BCO       |
453     //    +---------------+
454     //    | stg_ctoi_ret_ |
455     //    +---------------+
456     //    |    retval     |
457     //    +---------------+
458     //    |   XXXX_info   |
459     //    +---------------+
460     //
461     // where XXXX_info is one of the stg_gc_unbx_r1_info family.
462     //
463     // We're only interested in the case when the real return address
464     // is a BCO; otherwise we'll return to the scheduler.
465
466 do_return_unboxed:
467     { 
468         int offset;
469         
470         ASSERT( Sp[0] == (W_)&stg_gc_unbx_r1_info
471                 || Sp[0] == (W_)&stg_gc_unpt_r1_info
472                 || Sp[0] == (W_)&stg_gc_f1_info
473                 || Sp[0] == (W_)&stg_gc_d1_info
474                 || Sp[0] == (W_)&stg_gc_l1_info
475                 || Sp[0] == (W_)&stg_gc_void_info // VoidRep
476             );
477
478         // get the offset of the stg_ctoi_ret_XXX itbl
479         offset = stack_frame_sizeW((StgClosure *)Sp);
480
481         switch (get_itbl((StgClosure *)Sp+offset)->type) {
482
483         case RET_BCO:
484             // Returning to an interpreted continuation: put the object on
485             // the stack, and start executing the BCO.
486             INTERP_TICK(it_retto_BCO);
487             obj = (StgClosure*)Sp[offset+1];
488             ASSERT(get_itbl(obj)->type == BCO);
489             goto run_BCO_return_unboxed;
490
491         default:
492         {
493             // Can't handle this return address; yield to scheduler
494             INTERP_TICK(it_retto_other);
495             IF_DEBUG(interpreter,
496                      fprintf(stderr, "returning to unknown frame -- yielding to sched\n"); 
497                      printStackChunk(Sp,cap->r.rCurrentTSO->stack+cap->r.rCurrentTSO->stack_size);
498                 );
499             RETURN_TO_SCHEDULER(ThreadRunGHC, ThreadYielding);
500         }
501         }
502     }
503     // not reached.
504
505
506     // -------------------------------------------------------------------------
507     // Application...
508
509 do_apply:
510     // we have a function to apply (obj), and n arguments taking up m
511     // words on the stack.  The info table (stg_ap_pp_info or whatever)
512     // is on top of the arguments on the stack.
513     {
514         switch (get_itbl(obj)->type) {
515
516         case PAP: {
517             StgPAP *pap;
518             nat arity, i;
519
520             pap = (StgPAP *)obj;
521
522             // we only cope with PAPs whose function is a BCO
523             if (get_itbl(pap->fun)->type != BCO) {
524                 goto defer_apply_to_sched;
525             }
526
527             Sp++;
528             arity = pap->arity;
529             ASSERT(arity > 0);
530             if (arity < n) {
531                 // n must be greater than 1, and the only kinds of
532                 // application we support with more than one argument
533                 // are all pointers...
534                 //
535                 // Shuffle the args for this function down, and put
536                 // the appropriate info table in the gap.
537                 for (i = 0; i < arity; i++) {
538                     Sp[i-1] = Sp[i];
539                 }
540                 Sp[arity-1] = app_ptrs_itbl[n-arity-1];
541                 Sp--;
542                 // unpack the PAP's arguments onto the stack
543                 Sp -= pap->n_args;
544                 for (i = 0; i < pap->n_args; i++) {
545                     Sp[i] = (W_)pap->payload[i];
546                 }
547                 obj = pap->fun;
548                 goto run_BCO_fun;
549             } 
550             else if (arity == n) {
551                 Sp -= pap->n_args;
552                 for (i = 0; i < pap->n_args; i++) {
553                     Sp[i] = (W_)pap->payload[i];
554                 }
555                 obj = pap->fun;
556                 goto run_BCO_fun;
557             } 
558             else /* arity > n */ {
559                 // build a new PAP and return it.
560                 StgPAP *new_pap;
561                 nat size;
562                 size = PAP_sizeW(pap->n_args + m);
563                 new_pap = (StgPAP *)allocate(size);
564                 SET_HDR(new_pap,&stg_PAP_info,CCCS);
565                 new_pap->arity = pap->arity - n;
566                 new_pap->n_args = pap->n_args + m;
567                 new_pap->fun = pap->fun;
568                 for (i = 0; i < pap->n_args; i++) {
569                     new_pap->payload[i] = pap->payload[i];
570                 }
571                 for (i = 0; i < m; i++) {
572                     new_pap->payload[pap->n_args + i] = (StgClosure *)Sp[i];
573                 }
574                 obj = (StgClosure *)new_pap;
575                 Sp += m;
576                 goto do_return;
577             }
578         }           
579
580         case BCO: {
581             nat arity, i;
582
583             Sp++;
584             arity = ((StgBCO *)obj)->arity;
585             ASSERT(arity > 0);
586             if (arity < n) {
587                 // n must be greater than 1, and the only kinds of
588                 // application we support with more than one argument
589                 // are all pointers...
590                 //
591                 // Shuffle the args for this function down, and put
592                 // the appropriate info table in the gap.
593                 for (i = 0; i < arity; i++) {
594                     Sp[i-1] = Sp[i];
595                 }
596                 Sp[arity-1] = app_ptrs_itbl[n-arity-1];
597                 Sp--;
598                 goto run_BCO_fun;
599             } 
600             else if (arity == n) {
601                 goto run_BCO_fun;
602             }
603             else /* arity > n */ {
604                 // build a PAP and return it.
605                 StgPAP *pap;
606                 nat size, i;
607                 size = PAP_sizeW(m);
608                 pap = (StgPAP *)allocate(size);
609                 SET_HDR(pap, &stg_PAP_info,CCCS);
610                 pap->arity = arity - n;
611                 pap->fun = obj;
612                 pap->n_args = m;
613                 for (i = 0; i < m; i++) {
614                     pap->payload[i] = (StgClosure *)Sp[i];
615                 }
616                 obj = (StgClosure *)pap;
617                 Sp += m;
618                 goto do_return;
619             }
620         }
621
622         // No point in us applying machine-code functions
623         default:
624         defer_apply_to_sched:
625             Sp -= 2;
626             Sp[1] = (W_)obj;
627             Sp[0] = (W_)&stg_enter_info;
628             RETURN_TO_SCHEDULER(ThreadRunGHC, ThreadYielding);
629     }
630
631     // ------------------------------------------------------------------------
632     // Ok, we now have a bco (obj), and its arguments are all on the
633     // stack.  We can start executing the byte codes.
634     //
635     // The stack is in one of two states.  First, if this BCO is a
636     // function:
637     //
638     //    |     ....      |
639     //    +---------------+
640     //    |     arg2      |
641     //    +---------------+
642     //    |     arg1      |
643     //    +---------------+
644     //
645     // Second, if this BCO is a continuation:
646     //
647     //    |     ....      |
648     //    +---------------+
649     //    |     fv2       |
650     //    +---------------+
651     //    |     fv1       |
652     //    +---------------+
653     //    |     BCO       |
654     //    +---------------+
655     //    | stg_ctoi_ret_ |
656     //    +---------------+
657     //    |    retval     |
658     //    +---------------+
659     // 
660     // where retval is the value being returned to this continuation.
661     // In the event of a stack check, heap check, or context switch,
662     // we need to leave the stack in a sane state so the garbage
663     // collector can find all the pointers.
664     //
665     //  (1) BCO is a function:  the BCO's bitmap describes the
666     //      pointerhood of the arguments.
667     //
668     //  (2) BCO is a continuation: BCO's bitmap describes the
669     //      pointerhood of the free variables.
670     //
671     // Sadly we have three different kinds of stack/heap/cswitch check
672     // to do:
673
674 run_BCO_return:
675     // Heap check
676     if (doYouWantToGC()) {
677         Sp--; Sp[0] = (W_)&stg_enter_info;
678         RETURN_TO_SCHEDULER(ThreadInterpret, HeapOverflow);
679     }
680     // Stack checks aren't necessary at return points, the stack use
681     // is aggregated into the enclosing function entry point.
682     goto run_BCO;
683     
684 run_BCO_return_unboxed:
685     // Heap check
686     if (doYouWantToGC()) {
687         RETURN_TO_SCHEDULER(ThreadInterpret, HeapOverflow);
688     }
689     // Stack checks aren't necessary at return points, the stack use
690     // is aggregated into the enclosing function entry point.
691     goto run_BCO;
692     
693 run_BCO_fun:
694     IF_DEBUG(sanity,
695              Sp -= 2; 
696              Sp[1] = (W_)obj; 
697              Sp[0] = (W_)&stg_apply_interp_info;
698              checkStackChunk(Sp,SpLim);
699              Sp += 2;
700         );
701
702     // Heap check
703     if (doYouWantToGC()) {
704         Sp -= 2; 
705         Sp[1] = (W_)obj; 
706         Sp[0] = (W_)&stg_apply_interp_info; // placeholder, really
707         RETURN_TO_SCHEDULER(ThreadInterpret, HeapOverflow);
708     }
709     
710     // Stack check
711     if (Sp - INTERP_STACK_CHECK_THRESH < SpLim) {
712         Sp -= 2; 
713         Sp[1] = (W_)obj; 
714         Sp[0] = (W_)&stg_apply_interp_info; // placeholder, really
715         RETURN_TO_SCHEDULER(ThreadInterpret, StackOverflow);
716     }
717     goto run_BCO;
718     
719     // Now, actually interpret the BCO... (no returning to the
720     // scheduler again until the stack is in an orderly state).
721 run_BCO:
722     INTERP_TICK(it_BCO_entries);
723     {
724         register int       bciPtr     = 1; /* instruction pointer */
725         register StgBCO*   bco        = (StgBCO*)obj;
726         register StgWord16* instrs    = (StgWord16*)(bco->instrs->payload);
727         register StgWord*  literals   = (StgWord*)(&bco->literals->payload[0]);
728         register StgPtr*   ptrs       = (StgPtr*)(&bco->ptrs->payload[0]);
729         register StgInfoTable** itbls = (StgInfoTable**)
730             (&bco->itbls->payload[0]);
731
732 #ifdef INTERP_STATS
733         it_lastopc = 0; /* no opcode */
734 #endif
735
736     nextInsn:
737         ASSERT(bciPtr <= instrs[0]);
738         IF_DEBUG(interpreter,
739                  //if (do_print_stack) {
740                  //fprintf(stderr, "\n-- BEGIN stack\n");
741                  //printStack(Sp,cap->r.rCurrentTSO->stack+cap->r.rCurrentTSO->stack_size,iSu);
742                  //fprintf(stderr, "-- END stack\n\n");
743                  //}
744                  fprintf(stderr,"Sp = %p   pc = %d      ", Sp, bciPtr);
745                  disInstr(bco,bciPtr);
746                  if (0) { int i;
747                  fprintf(stderr,"\n");
748                  for (i = 8; i >= 0; i--) {
749                      fprintf(stderr, "%d  %p\n", i, (StgPtr)(*(Sp+i)));
750                  }
751                  fprintf(stderr,"\n");
752                  }
753                  //if (do_print_stack) checkStack(Sp,cap->r.rCurrentTSO->stack+cap->r.rCurrentTSO->stack_size,iSu);
754             );
755
756         INTERP_TICK(it_insns);
757
758 #ifdef INTERP_STATS
759         ASSERT( (int)instrs[bciPtr] >= 0 && (int)instrs[bciPtr] < 27 );
760         it_ofreq[ (int)instrs[bciPtr] ] ++;
761         it_oofreq[ it_lastopc ][ (int)instrs[bciPtr] ] ++;
762         it_lastopc = (int)instrs[bciPtr];
763 #endif
764
765         switch (BCO_NEXT) {
766
767         case bci_STKCHECK: {
768             // Explicit stack check at the beginning of a function
769             // *only* (stack checks in case alternatives are
770             // propagated to the enclosing function).
771             int stk_words_reqd = BCO_NEXT + 1;
772             if (Sp - stk_words_reqd < SpLim) {
773                 Sp -= 2; 
774                 Sp[1] = (W_)obj; 
775                 Sp[0] = (W_)&stg_apply_interp_info;
776                 RETURN_TO_SCHEDULER(ThreadInterpret, StackOverflow);
777             } else {
778                 goto nextInsn;
779             }
780         }
781
782         case bci_PUSH_L: {
783             int o1 = BCO_NEXT;
784             Sp[-1] = Sp[o1];
785             Sp--;
786             goto nextInsn;
787         }
788
789         case bci_PUSH_LL: {
790             int o1 = BCO_NEXT;
791             int o2 = BCO_NEXT;
792             Sp[-1] = Sp[o1];
793             Sp[-2] = Sp[o2];
794             Sp -= 2;
795             goto nextInsn;
796         }
797
798         case bci_PUSH_LLL: {
799             int o1 = BCO_NEXT;
800             int o2 = BCO_NEXT;
801             int o3 = BCO_NEXT;
802             Sp[-1] = Sp[o1];
803             Sp[-2] = Sp[o2];
804             Sp[-3] = Sp[o3];
805             Sp -= 3;
806             goto nextInsn;
807         }
808
809         case bci_PUSH_G: {
810             int o1 = BCO_NEXT;
811             Sp[-1] = BCO_PTR(o1);
812             Sp -= 1;
813             goto nextInsn;
814         }
815
816         case bci_PUSH_ALTS: {
817             int o_bco  = BCO_NEXT;
818             Sp[-2] = (W_)&stg_ctoi_ret_R1p_info;
819             Sp[-1] = BCO_PTR(o_bco);
820             Sp -= 2;
821             goto nextInsn;
822         }
823
824         case bci_PUSH_ALTS_P: {
825             int o_bco  = BCO_NEXT;
826             Sp[-2] = (W_)&stg_ctoi_ret_R1unpt_info;
827             Sp[-1] = BCO_PTR(o_bco);
828             Sp -= 2;
829             goto nextInsn;
830         }
831
832         case bci_PUSH_ALTS_N: {
833             int o_bco  = BCO_NEXT;
834             Sp[-2] = (W_)&stg_ctoi_ret_R1n_info;
835             Sp[-1] = BCO_PTR(o_bco);
836             Sp -= 2;
837             goto nextInsn;
838         }
839
840         case bci_PUSH_ALTS_F: {
841             int o_bco  = BCO_NEXT;
842             Sp[-2] = (W_)&stg_ctoi_ret_F1_info;
843             Sp[-1] = BCO_PTR(o_bco);
844             Sp -= 2;
845             goto nextInsn;
846         }
847
848         case bci_PUSH_ALTS_D: {
849             int o_bco  = BCO_NEXT;
850             Sp[-2] = (W_)&stg_ctoi_ret_D1_info;
851             Sp[-1] = BCO_PTR(o_bco);
852             Sp -= 2;
853             goto nextInsn;
854         }
855
856         case bci_PUSH_ALTS_L: {
857             int o_bco  = BCO_NEXT;
858             Sp[-2] = (W_)&stg_ctoi_ret_L1_info;
859             Sp[-1] = BCO_PTR(o_bco);
860             Sp -= 2;
861             goto nextInsn;
862         }
863
864         case bci_PUSH_ALTS_V: {
865             int o_bco  = BCO_NEXT;
866             Sp[-2] = (W_)&stg_ctoi_ret_V_info;
867             Sp[-1] = BCO_PTR(o_bco);
868             Sp -= 2;
869             goto nextInsn;
870         }
871
872         case bci_PUSH_APPLY_N:
873             Sp--; Sp[0] = (W_)&stg_ap_n_info;
874             goto nextInsn;
875         case bci_PUSH_APPLY_V:
876             Sp--; Sp[0] = (W_)&stg_ap_v_info;
877             goto nextInsn;
878         case bci_PUSH_APPLY_F:
879             Sp--; Sp[0] = (W_)&stg_ap_f_info;
880             goto nextInsn;
881         case bci_PUSH_APPLY_D:
882             Sp--; Sp[0] = (W_)&stg_ap_d_info;
883             goto nextInsn;
884         case bci_PUSH_APPLY_L:
885             Sp--; Sp[0] = (W_)&stg_ap_l_info;
886             goto nextInsn;
887         case bci_PUSH_APPLY_P:
888             Sp--; Sp[0] = (W_)&stg_ap_p_info;
889             goto nextInsn;
890         case bci_PUSH_APPLY_PP:
891             Sp--; Sp[0] = (W_)&stg_ap_pp_info;
892             goto nextInsn;
893         case bci_PUSH_APPLY_PPP:
894             Sp--; Sp[0] = (W_)&stg_ap_ppp_info;
895             goto nextInsn;
896         case bci_PUSH_APPLY_PPPP:
897             Sp--; Sp[0] = (W_)&stg_ap_pppp_info;
898             goto nextInsn;
899         case bci_PUSH_APPLY_PPPPP:
900             Sp--; Sp[0] = (W_)&stg_ap_ppppp_info;
901             goto nextInsn;
902         case bci_PUSH_APPLY_PPPPPP:
903             Sp--; Sp[0] = (W_)&stg_ap_pppppp_info;
904             goto nextInsn;
905         case bci_PUSH_APPLY_PPPPPPP:
906             Sp--; Sp[0] = (W_)&stg_ap_ppppppp_info;
907             goto nextInsn;
908             
909         case bci_PUSH_UBX: {
910             int i;
911             int o_lits = BCO_NEXT;
912             int n_words = BCO_NEXT;
913             Sp -= n_words;
914             for (i = 0; i < n_words; i++) {
915                 Sp[i] = BCO_LIT(o_lits+i);
916             }
917             goto nextInsn;
918         }
919
920         case bci_SLIDE: {
921             int n  = BCO_NEXT;
922             int by = BCO_NEXT;
923             /* a_1, .. a_n, b_1, .. b_by, s => a_1, .. a_n, s */
924             while(--n >= 0) {
925                 Sp[n+by] = Sp[n];
926             }
927             Sp += by;
928             INTERP_TICK(it_slides);
929             goto nextInsn;
930         }
931
932         case bci_ALLOC_AP: {
933             StgAP* ap; 
934             int n_payload = BCO_NEXT;
935             int request   = PAP_sizeW(n_payload);
936             ap = (StgAP*)allocate_UPD(request);
937             Sp[-1] = (W_)ap;
938             ap->n_args = n_payload;
939             SET_HDR(ap, &stg_AP_info, CCS_SYSTEM/*ToDo*/)
940             Sp --;
941             goto nextInsn;
942         }
943
944         case bci_ALLOC_PAP: {
945             StgPAP* pap; 
946             int arity = BCO_NEXT;
947             int n_payload = BCO_NEXT;
948             int request   = PAP_sizeW(n_payload);
949             pap = (StgPAP*)allocate_NONUPD(request);
950             Sp[-1] = (W_)pap;
951             pap->n_args = n_payload;
952             pap->arity = arity;
953             SET_HDR(pap, &stg_PAP_info, CCS_SYSTEM/*ToDo*/)
954             Sp --;
955             goto nextInsn;
956         }
957
958         case bci_MKAP: {
959             int i;
960             int stkoff = BCO_NEXT;
961             int n_payload = BCO_NEXT;
962             StgAP* ap = (StgAP*)Sp[stkoff];
963             ASSERT((int)ap->n_args == n_payload);
964             ap->fun = (StgClosure*)Sp[0];
965
966             // The function should be a BCO, and its bitmap should
967             // cover the payload of the AP correctly.
968             ASSERT(get_itbl(ap->fun)->type == BCO
969                    && (get_itbl(ap)->type == PAP || 
970                        BCO_BITMAP_SIZE(ap->fun) == ap->n_args));
971
972             for (i = 0; i < n_payload; i++)
973                 ap->payload[i] = (StgClosure*)Sp[i+1];
974             Sp += n_payload+1;
975             IF_DEBUG(interpreter,
976                      fprintf(stderr,"\tBuilt "); 
977                      printObj((StgClosure*)ap);
978                 );
979             goto nextInsn;
980         }
981
982         case bci_UNPACK: {
983             /* Unpack N ptr words from t.o.s constructor */
984             int i;
985             int n_words = BCO_NEXT;
986             StgClosure* con = (StgClosure*)Sp[0];
987             Sp -= n_words;
988             for (i = 0; i < n_words; i++) {
989                 Sp[i] = (W_)con->payload[i];
990             }
991             goto nextInsn;
992         }
993
994         case bci_PACK: {
995             int i;
996             int o_itbl         = BCO_NEXT;
997             int n_words        = BCO_NEXT;
998             StgInfoTable* itbl = INFO_PTR_TO_STRUCT(BCO_ITBL(o_itbl));
999             int request        = CONSTR_sizeW( itbl->layout.payload.ptrs, 
1000                                                itbl->layout.payload.nptrs );
1001             StgClosure* con = (StgClosure*)allocate_NONUPD(request);
1002             ASSERT( itbl->layout.payload.ptrs + itbl->layout.payload.nptrs > 0);
1003             SET_HDR(con, BCO_ITBL(o_itbl), CCS_SYSTEM/*ToDo*/);
1004             for (i = 0; i < n_words; i++) {
1005                 con->payload[i] = (StgClosure*)Sp[i];
1006             }
1007             Sp += n_words;
1008             Sp --;
1009             Sp[0] = (W_)con;
1010             IF_DEBUG(interpreter,
1011                      fprintf(stderr,"\tBuilt "); 
1012                      printObj((StgClosure*)con);
1013                 );
1014             goto nextInsn;
1015         }
1016
1017         case bci_TESTLT_P: {
1018             int discr  = BCO_NEXT;
1019             int failto = BCO_NEXT;
1020             StgClosure* con = (StgClosure*)Sp[0];
1021             if (constrTag(con) >= discr) {
1022                 bciPtr = failto;
1023             }
1024             goto nextInsn;
1025         }
1026
1027         case bci_TESTEQ_P: {
1028             int discr  = BCO_NEXT;
1029             int failto = BCO_NEXT;
1030             StgClosure* con = (StgClosure*)Sp[0];
1031             if (constrTag(con) != discr) {
1032                 bciPtr = failto;
1033             }
1034             goto nextInsn;
1035         }
1036
1037         case bci_TESTLT_I: {
1038             // There should be an Int at Sp[1], and an info table at Sp[0].
1039             int discr   = BCO_NEXT;
1040             int failto  = BCO_NEXT;
1041             I_ stackInt = (I_)Sp[1];
1042             if (stackInt >= (I_)BCO_LIT(discr))
1043                 bciPtr = failto;
1044             goto nextInsn;
1045         }
1046
1047         case bci_TESTEQ_I: {
1048             // There should be an Int at Sp[1], and an info table at Sp[0].
1049             int discr   = BCO_NEXT;
1050             int failto  = BCO_NEXT;
1051             I_ stackInt = (I_)Sp[1];
1052             if (stackInt != (I_)BCO_LIT(discr)) {
1053                 bciPtr = failto;
1054             }
1055             goto nextInsn;
1056         }
1057
1058         case bci_TESTLT_D: {
1059             // There should be a Double at Sp[1], and an info table at Sp[0].
1060             int discr   = BCO_NEXT;
1061             int failto  = BCO_NEXT;
1062             StgDouble stackDbl, discrDbl;
1063             stackDbl = PK_DBL( & Sp[1] );
1064             discrDbl = PK_DBL( & BCO_LIT(discr) );
1065             if (stackDbl >= discrDbl) {
1066                 bciPtr = failto;
1067             }
1068             goto nextInsn;
1069         }
1070
1071         case bci_TESTEQ_D: {
1072             // There should be a Double at Sp[1], and an info table at Sp[0].
1073             int discr   = BCO_NEXT;
1074             int failto  = BCO_NEXT;
1075             StgDouble stackDbl, discrDbl;
1076             stackDbl = PK_DBL( & Sp[1] );
1077             discrDbl = PK_DBL( & BCO_LIT(discr) );
1078             if (stackDbl != discrDbl) {
1079                 bciPtr = failto;
1080             }
1081             goto nextInsn;
1082         }
1083
1084         case bci_TESTLT_F: {
1085             // There should be a Float at Sp[1], and an info table at Sp[0].
1086             int discr   = BCO_NEXT;
1087             int failto  = BCO_NEXT;
1088             StgFloat stackFlt, discrFlt;
1089             stackFlt = PK_FLT( & Sp[1] );
1090             discrFlt = PK_FLT( & BCO_LIT(discr) );
1091             if (stackFlt >= discrFlt) {
1092                 bciPtr = failto;
1093             }
1094             goto nextInsn;
1095         }
1096
1097         case bci_TESTEQ_F: {
1098             // There should be a Float at Sp[1], and an info table at Sp[0].
1099             int discr   = BCO_NEXT;
1100             int failto  = BCO_NEXT;
1101             StgFloat stackFlt, discrFlt;
1102             stackFlt = PK_FLT( & Sp[1] );
1103             discrFlt = PK_FLT( & BCO_LIT(discr) );
1104             if (stackFlt != discrFlt) {
1105                 bciPtr = failto;
1106             }
1107             goto nextInsn;
1108         }
1109
1110         // Control-flow ish things
1111         case bci_ENTER:
1112             // Context-switch check.  We put it here to ensure that
1113             // the interpreter has done at least *some* work before
1114             // context switching: sometimes the scheduler can invoke
1115             // the interpreter with context_switch == 1, particularly
1116             // if the -C0 flag has been given on the cmd line.
1117             if (context_switch) {
1118                 Sp--; Sp[0] = (W_)&stg_enter_info;
1119                 RETURN_TO_SCHEDULER(ThreadInterpret, ThreadYielding);
1120             }
1121             goto eval;
1122
1123         case bci_RETURN:
1124             obj = (StgClosure *)Sp[0];
1125             Sp++;
1126             goto do_return;
1127
1128         case bci_RETURN_P:
1129             Sp--;
1130             Sp[0] = (W_)&stg_gc_unpt_r1_info;
1131             goto do_return_unboxed;
1132         case bci_RETURN_N:
1133             Sp--;
1134             Sp[0] = (W_)&stg_gc_unbx_r1_info;
1135             goto do_return_unboxed;
1136         case bci_RETURN_F:
1137             Sp--;
1138             Sp[0] = (W_)&stg_gc_f1_info;
1139             goto do_return_unboxed;
1140         case bci_RETURN_D:
1141             Sp--;
1142             Sp[0] = (W_)&stg_gc_d1_info;
1143             goto do_return_unboxed;
1144         case bci_RETURN_L:
1145             Sp--;
1146             Sp[0] = (W_)&stg_gc_l1_info;
1147             goto do_return_unboxed;
1148         case bci_RETURN_V:
1149             Sp--;
1150             Sp[0] = (W_)&stg_gc_void_info;
1151             goto do_return_unboxed;
1152
1153         case bci_SWIZZLE: {
1154             int stkoff = BCO_NEXT;
1155             signed short n = (signed short)(BCO_NEXT);
1156             Sp[stkoff] += (W_)n;
1157             goto nextInsn;
1158         }
1159
1160         case bci_CCALL: {
1161             StgInt tok;
1162             int stk_offset            = BCO_NEXT;
1163             int o_itbl                = BCO_NEXT;
1164             void(*marshall_fn)(void*) = (void (*)(void*))BCO_LIT(o_itbl);
1165             int ret_dyn_size = 
1166                 RET_DYN_BITMAP_SIZE + RET_DYN_NONPTR_REGS_SIZE
1167                 + sizeofW(StgRetDyn);
1168
1169 #ifdef RTS_SUPPORTS_THREADS
1170             // Threaded RTS:
1171             // Arguments on the TSO stack are not good, because garbage
1172             // collection might move the TSO as soon as we call
1173             // suspendThread below.
1174
1175             W_ arguments[stk_offset];
1176             
1177             memcpy(arguments, Sp, sizeof(W_) * stk_offset);
1178 #endif
1179
1180             // Restore the Haskell thread's current value of errno
1181             errno = cap->r.rCurrentTSO->saved_errno;
1182
1183             // There are a bunch of non-ptr words on the stack (the
1184             // ccall args, the ccall fun address and space for the
1185             // result), which we need to cover with an info table
1186             // since we might GC during this call.
1187             //
1188             // We know how many (non-ptr) words there are before the
1189             // next valid stack frame: it is the stk_offset arg to the
1190             // CCALL instruction.   So we build a RET_DYN stack frame
1191             // on the stack frame to describe this chunk of stack.
1192             //
1193             Sp -= ret_dyn_size;
1194             ((StgRetDyn *)Sp)->liveness = ALL_NON_PTRS | N_NONPTRS(stk_offset);
1195             ((StgRetDyn *)Sp)->info = (StgInfoTable *)&stg_gc_gen_info;
1196
1197             SAVE_STACK_POINTERS;
1198             tok = suspendThread(&cap->r,rtsFalse);
1199
1200 #ifndef RTS_SUPPORTS_THREADS
1201             // Careful:
1202             // suspendThread might have shifted the stack
1203             // around (stack squeezing), so we have to grab the real
1204             // Sp out of the TSO to find the ccall args again.
1205
1206             marshall_fn ( (void*)(cap->r.rCurrentTSO->sp + ret_dyn_size) );
1207 #else
1208             // Threaded RTS:
1209             // We already made a copy of the arguments above.
1210
1211             marshall_fn ( arguments );
1212 #endif
1213
1214             // And restart the thread again, popping the RET_DYN frame.
1215             cap = (Capability *)((void *)((unsigned char*)resumeThread(tok,rtsFalse) - sizeof(StgFunTable)));
1216             LOAD_STACK_POINTERS;
1217             Sp += ret_dyn_size;
1218             
1219             // Save the Haskell thread's current value of errno
1220             cap->r.rCurrentTSO->saved_errno = errno;
1221                 
1222 #ifdef RTS_SUPPORTS_THREADS
1223             // Threaded RTS:
1224             // Copy the "arguments", which might include a return value,
1225             // back to the TSO stack. It would of course be enough to
1226             // just copy the return value, but we don't know the offset.
1227             memcpy(Sp, arguments, sizeof(W_) * stk_offset);
1228 #endif
1229
1230             goto nextInsn;
1231         }
1232
1233         case bci_JMP: {
1234             /* BCO_NEXT modifies bciPtr, so be conservative. */
1235             int nextpc = BCO_NEXT;
1236             bciPtr     = nextpc;
1237             goto nextInsn;
1238         }
1239
1240         case bci_CASEFAIL:
1241             barf("interpretBCO: hit a CASEFAIL");
1242             
1243             // Errors
1244         default: 
1245             barf("interpretBCO: unknown or unimplemented opcode");
1246
1247         } /* switch on opcode */
1248     }
1249     }
1250
1251     barf("interpretBCO: fell off end of the interpreter");
1252 }