[project @ 2001-01-17 12:14:30 by simonmar]
[ghc-hetmet.git] / ghc / rts / Interpreter.c
index eb6fd24..07c89e2 100644 (file)
@@ -1,67 +1,71 @@
 
-
-#if 0
 /* -----------------------------------------------------------------------------
  * Bytecode evaluator
  *
  * Copyright (c) 1994-2000.
  *
  * $RCSfile: Interpreter.c,v $
- * $Revision: 1.3 $
- * $Date: 2000/12/14 15:19:48 $
+ * $Revision: 1.13 $
+ * $Date: 2001/01/15 16:55:25 $
  * ---------------------------------------------------------------------------*/
 
-#include "Rts.h"
-
-
+#ifdef GHCI
 
-#include "RtsFlags.h"
+#include "Rts.h"
+#include "RtsAPI.h"
 #include "RtsUtils.h"
-#include "Updates.h"
+#include "Closures.h"
+#include "TSO.h"
+#include "Schedule.h"
+#include "RtsFlags.h"
 #include "Storage.h"
-#include "SchedAPI.h" /* for createGenThread */
-#include "Schedule.h" /* for context_switch  */
+#include "Updates.h"
+
 #include "Bytecodes.h"
-#include "ForeignCall.h"
-#include "PrimOps.h"   /* for __{encode,decode}{Float,Double} */
-#include "Prelude.h"
-#include "Itimer.h"
-#include "Evaluator.h"
-#include "sainteger.h"
-
-#ifdef DEBUG
 #include "Printer.h"
 #include "Disassembler.h"
-#include "Sanity.h"
-#include "StgRun.h"
-#endif
+#include "Interpreter.h"
 
-#include <math.h>    /* These are for primops */
-#include <limits.h>  /* These are for primops */
-#include <float.h>   /* These are for primops */
-#ifdef HAVE_IEEE754_H
-#include <ieee754.h> /* These are for primops */
-#endif
-
-#endif /* 0 */
-
-#include <stdio.h>
-int /*StgThreadReturnCode*/ interpretBCO ( void* /* Capability* */ cap )
-{
-   fprintf(stderr, "Greetings, earthlings.  I am not yet implemented.  Bye!\n");
-   exit(1);
-}
 
-#if 0
 /* --------------------------------------------------------------------------
  * The new bytecode interpreter
  * ------------------------------------------------------------------------*/
 
 /* Sp points to the lowest live word on the stack. */
 
-#define StackWord(n)  ((W_*)iSp)[n]
-#define BCO_NEXT      bco_instrs[bciPtr++]
-#define BCO_PTR(n)    bco_ptrs[n]
+#define StackWord(n)  iSp[n]
+#define BCO_NEXT      instrs[bciPtr++]
+#define BCO_PTR(n)    (W_)ptrs[n]
+#define BCO_LIT(n)    (W_)literals[n]
+#define BCO_ITBL(n)   itbls[n]
+
+#define LOAD_STACK_POINTERS \
+    iSp = cap->rCurrentTSO->sp; iSu = cap->rCurrentTSO->su;
+
+#define SAVE_STACK_POINTERS \
+    cap->rCurrentTSO->sp = iSp; cap->rCurrentTSO->su = iSu;
+
+#define RETURN(retcode) \
+   SAVE_STACK_POINTERS; return retcode;
+
+
+static __inline__ StgPtr allocate_UPD ( int n_words )
+{
+  //fprintf(stderr, "alloc_UPD    %d -> ", n_words );
+   if (n_words - sizeofW(StgHeader) < MIN_UPD_SIZE)
+      n_words = MIN_UPD_SIZE + sizeofW(StgHeader);
+   //fprintf(stderr, "%d\n", n_words );
+   return allocate(n_words);
+}
+
+static __inline__ StgPtr allocate_NONUPD ( int n_words )
+{
+  //fprintf(stderr, "alloc_NONUPD %d -> ", n_words );
+   if (n_words - sizeofW(StgHeader) < MIN_NONUPD_SIZE)
+      n_words = MIN_NONUPD_SIZE + sizeofW(StgHeader);
+   //fprintf(stderr, "%d\n", n_words );
+   return allocate(n_words);
+}
 
 
 StgThreadReturnCode interpretBCO ( Capability* cap )
@@ -72,69 +76,147 @@ StgThreadReturnCode interpretBCO ( Capability* cap )
    /* Use of register here is primarily to make it clear to compilers
       that these entities are non-aliasable.
    */
-    register StgPtr           iSp;    /* local state -- stack pointer */
+    register W_*              iSp;    /* local state -- stack pointer */
     register StgUpdateFrame*  iSu;    /* local state -- frame pointer */
     register StgPtr           iSpLim; /* local state -- stack lim pointer */
     register StgClosure*      obj;
 
-    iSp    = cap->rCurrentTSO->sp;
-    iSu    = cap->rCurrentTSO->su;
+    LOAD_STACK_POINTERS;
+
     iSpLim = cap->rCurrentTSO->stack + RESERVED_STACK_WORDS;
 
+    /* Main object-entering loop.  Object to be entered is on top of
+       stack. */
+    nextEnter:
+
+    obj = (StgClosure*)StackWord(0); iSp++;
+
     IF_DEBUG(evaluator,
-             enterCountI++;
              fprintf(stderr, 
              "\n---------------------------------------------------------------\n");
-             fprintf(stderr,"Entering: ",); printObj(obj);
-             fprintf(stderr,"xSp = %p\txSu = %p\n", xSp, xSu);
+             fprintf(stderr,"Entering: "); printObj(obj);
+             fprintf(stderr,"iSp = %p\tiSu = %p\n", iSp, iSu);
              fprintf(stderr, "\n" );
+
+            //      checkSanity(1);
+            //             iSp--; StackWord(0) = obj;
+            //             checkStack(iSp,cap->rCurrentTSO->stack+cap->rCurrentTSO->stack_size,iSu);
+            //             iSp++;
+
              printStack(iSp,cap->rCurrentTSO->stack+cap->rCurrentTSO->stack_size,iSu);
              fprintf(stderr, "\n\n");
             );
 
-    /* Main object-entering loop.  Object to be entered is on top of
-       stack. */
-    nextEnter:
-
-    obj = StackWord(0); iSp++;
-
     switch ( get_itbl(obj)->type ) {
        case INVALID_OBJECT:
-               barf("Invalid object %p",obj);
+               barf("Invalid object %p",(StgPtr)obj);
+
+#if 0
+       case AP_UPD:
+        { nat Words;
+          nat i;
+          StgAP_UPD *ap = (StgAP_UPD*)obj;
+          Words = ap->n_args;
+
+         /* WARNING: do a stack overflow check here !
+             This code (copied from stg_AP_UPD_entry) is not correct without it. */
+
+          iSp -= sizeofW(StgUpdateFrame);
+
+          {
+              StgUpdateFrame *__frame;
+              __frame = (StgUpdateFrame *)iSp;
+              SET_INFO(__frame, (StgInfoTable *)&stg_upd_frame_info);
+              __frame->link = iSu;
+              __frame->updatee = (StgClosure *)(ap);
+              iSu = __frame;
+          }
+
+          iSp -= Words;
 
-       case BCO: bco_entry:
+          /* Reload the stack */
+          for (i=0; i<Words; i++) StackWord(i) = (W_)ap->payload[i];
+
+          iSp--; StackWord(0) = (W_)ap->fun;
+          goto nextEnter;
+        }
+#endif
+
+       case BCO:
 
        /* ---------------------------------------------------- */
        /* Start of the bytecode interpreter                    */
        /* ---------------------------------------------------- */
        {
-          register StgWord8* bciPtr; /* instruction pointer */
-          register StgBCO*   bco = (StgBCO*)obj;
+          int do_print_stack = 1;
+          register int       bciPtr     = 1; /* instruction pointer */
+          register StgBCO*   bco        = (StgBCO*)obj;
+          register UShort*   instrs     = (UShort*)(&bco->instrs->payload[0]);
+          register StgWord*  literals   = (StgWord*)(&bco->literals->payload[0]);
+          register StgPtr*   ptrs       = (StgPtr*)(&bco->ptrs->payload[0]);
+          register StgInfoTable** itbls = (StgInfoTable**)
+                                             (&bco->itbls->payload[0]);
+
           if (doYouWantToGC()) {
-            iSp--; StackWord(0) = bco;
-             return HeapOverflow;
+            iSp--; StackWord(0) = (W_)bco;
+             RETURN(HeapOverflow);
           }
 
           nextInsn:
 
-          ASSERT((StgWord)(PC) < bco->n_instrs);
+          ASSERT(bciPtr <= instrs[0]);
           IF_DEBUG(evaluator,
-          fprintf(stderr,"Sp = %p\tSu = %p\tpc = %d\t", xSp, xSu, PC);
-                  disInstr(bco,PC);
-                  if (0) { int i;
-                           fprintf(stderr,"\n");
-                           for (i = 8; i >= 0; i--) 
-                              fprintf(stderr, "%d  %p\n", i, (StgPtr)(*(gSp+i)));
-                         }
-                  fprintf(stderr,"\n");
-                 );
+                  //if (do_print_stack) {
+                  //fprintf(stderr, "\n-- BEGIN stack\n");
+                  //printStack(iSp,cap->rCurrentTSO->stack+cap->rCurrentTSO->stack_size,iSu);
+                  //fprintf(stderr, "-- END stack\n\n");
+                  //}
+                   do_print_stack = 1;
+                  fprintf(stderr,"iSp = %p   iSu = %p   pc = %d      ", iSp, iSu, bciPtr);
+                   disInstr(bco,bciPtr);
+                    if (0) { int i;
+                             fprintf(stderr,"\n");
+                             for (i = 8; i >= 0; i--) 
+                                fprintf(stderr, "%d  %p\n", i, (StgPtr)(*(iSp+i)));
+                             fprintf(stderr,"\n");
+                           }
+                   //if (do_print_stack) checkStack(iSp,cap->rCurrentTSO->stack+cap->rCurrentTSO->stack_size,iSu);
+                  );
+
 
           switch (BCO_NEXT) {
 
+              case bci_ARGCHECK: {
+                 int i;
+                 StgPAP* pap;
+                 int arg_words_reqd = BCO_NEXT;
+                 int arg_words_avail = ((W_*)iSu) - ((W_*)iSp);
+                 if (arg_words_avail >= arg_words_reqd) goto nextInsn;
+                 /* Handle arg check failure.  Copy the spare args
+                    into a PAP frame. */
+                /* fprintf(stderr, "arg check fail %d %d\n", arg_words_reqd, arg_words_avail ); */
+                 pap = (StgPAP*)allocate_UPD(PAP_sizeW(arg_words_avail));
+                 SET_HDR(pap,&stg_PAP_info,CCS_SYSTEM/*ToDo*/);
+                 pap->n_args = arg_words_avail;
+                 pap->fun = obj;
+                 for (i = 0; i < arg_words_avail; i++)
+                    pap->payload[i] = (StgClosure*)StackWord(i);
+                 /* Push on the stack and defer to the scheduler. */
+                 iSp = (StgPtr)iSu;
+                 iSp --;
+                 StackWord(0) = (W_)pap;
+                IF_DEBUG(evaluator,
+                          fprintf(stderr,"\tBuilt "); 
+                          printObj((StgClosure*)pap);
+                        );
+                 RETURN(ThreadEnterGHC);
+              }
               case bci_PUSH_L: {
                  int o1 = BCO_NEXT;
+                 ASSERT((W_*)iSp+o1 < (W_*)iSu);
                  StackWord(-1) = StackWord(o1);
-                 Sp--;
+                 iSp--;
+                 do_print_stack = 0;
                  goto nextInsn;
               }
               case bci_PUSH_LL: {
@@ -142,7 +224,7 @@ StgThreadReturnCode interpretBCO ( Capability* cap )
                  int o2 = BCO_NEXT;
                  StackWord(-1) = StackWord(o1);
                  StackWord(-2) = StackWord(o2);
-                 Sp -= 2;
+                 iSp -= 2;
                  goto nextInsn;
               }
               case bci_PUSH_LLL: {
@@ -152,112 +234,237 @@ StgThreadReturnCode interpretBCO ( Capability* cap )
                  StackWord(-1) = StackWord(o1);
                  StackWord(-2) = StackWord(o2);
                  StackWord(-3) = StackWord(o3);
-                 Sp -= 3;
+                 iSp -= 3;
                  goto nextInsn;
               }
               case bci_PUSH_G: {
                  int o1 = BCO_NEXT;
                  StackWord(-1) = BCO_PTR(o1);
-                 Sp -= 3;
+                 iSp -= 1;
                  goto nextInsn;
               }
               case bci_PUSH_AS: {
                  int o_bco  = BCO_NEXT;
                  int o_itbl = BCO_NEXT;
-                 StackWord(-1) = BCO_LIT(o_itbl);
-                 StackWord(-2) = BCO_PTR(o_bco);
-                 Sp -= 2;
+                 StackWord(-2) = BCO_LIT(o_itbl);
+                 StackWord(-1) = BCO_PTR(o_bco);
+                 iSp -= 2;
+                 goto nextInsn;
+              }
+              case bci_PUSH_UBX: {
+                 int i;
+                 int o_lits = BCO_NEXT;
+                 int n_words = BCO_NEXT;
+                 iSp -= n_words;
+                 for (i = 0; i < n_words; i++)
+                    StackWord(i) = BCO_LIT(o_lits+i);
+                 do_print_stack = 0;
                  goto nextInsn;
               }
               case bci_PUSH_TAG: {
                  W_ tag = (W_)(BCO_NEXT);
                  StackWord(-1) = tag;
-                 Sp --;
-                 goto nextInsn;
-              }
-              case bci_PUSH_LIT:{
-                 int o = BCO_NEXT;
-                 StackWord(-1) = BCO_LIT(o);
-                 Sp --;
+                 iSp --;
                  goto nextInsn;
               }
               case bci_SLIDE: {
                  int n  = BCO_NEXT;
                  int by = BCO_NEXT;
-                 ASSERT(Sp+n+by <= (StgPtr)xSu);
+                 ASSERT((W_*)iSp+n+by <= (W_*)iSu);
                  /* a_1, .. a_n, b_1, .. b_by, s => a_1, .. a_n, s */
                  while(--n >= 0) {
                     StackWord(n+by) = StackWord(n);
                  }
-                 Sp += by;
+                 iSp += by;
                  goto nextInsn;
               }
               case bci_ALLOC: {
-                 int n_payload = BCO_NEXT;
-                 P_ p = allocate(AP_sizeW(n_payload));
-                 StackWord(-1) = p;
-                 Sp --;
+                 StgAP_UPD* ap; 
+                 int n_payload = BCO_NEXT - 1;
+                 int request   = AP_sizeW(n_payload);
+                 ap = (StgAP_UPD*)allocate_UPD(request);
+                 StackWord(-1) = (W_)ap;
+                 ap->n_args = n_payload;
+                 SET_HDR(ap, &stg_AP_UPD_info, ??)
+                 iSp --;
                  goto nextInsn;
               }
-              case bci_MKAP:        {
-                 int off = BCO_NEXT;
+              case bci_MKAP: {
+                 int i;
+                 int stkoff = BCO_NEXT;
                  int n_payload = BCO_NEXT - 1;
-                 StgAP_UPD* ap = StackWord(off);
-                 ap->n_args = n_payload;
+                 StgAP_UPD* ap = (StgAP_UPD*)StackWord(stkoff);
+                 ASSERT((int)ap->n_args == n_payload);
                  ap->fun = (StgClosure*)StackWord(0);
                  for (i = 0; i < n_payload; i++)
-                    ap->payload[i] = StackWord(i+1);
-                 Sp += n_payload+1;
+                    ap->payload[i] = (StgClosure*)StackWord(i+1);
+                 iSp += n_payload+1;
+                IF_DEBUG(evaluator,
+                          fprintf(stderr,"\tBuilt "); 
+                          printObj((StgClosure*)ap);
+                        );
                  goto nextInsn;
               }
               case bci_UNPACK: {
                  /* Unpack N ptr words from t.o.s constructor */
                  /* The common case ! */
+                 int i;
                  int n_words = BCO_NEXT;
-                 StgClosure* con = StackWord(0);
-                 Sp -= n_words;
+                 StgClosure* con = (StgClosure*)StackWord(0);
+                 iSp -= n_words;
                  for (i = 0; i < n_words; i++)
-                    StackWord(i) = con->payload[i];
+                    StackWord(i) = (W_)con->payload[i];
                  goto nextInsn;
               }
-              case bci_UNPACK_BX: {
+              case bci_UPK_TAG: {
                  /* Unpack N (non-ptr) words from offset M in the
                     constructor K words down the stack, and then push
                     N as a tag, on top of it.  Slow but general; we
                     hope it will be the rare case. */
+                 int i;                
                  int n_words = BCO_NEXT;
                  int con_off = BCO_NEXT;
                  int stk_off = BCO_NEXT;
-                 StgClosure* con = StackWord(stk_off);
-                 Sp -= n_words;
+                 StgClosure* con = (StgClosure*)StackWord(stk_off);
+                 iSp -= n_words;
                  for (i = 0; i < n_words; i++) 
-                    StackWord(i) = con->payload[con_off + i];
-                 Sp --;
+                    StackWord(i) = (W_)con->payload[con_off + i];
+                 iSp --;
                  StackWord(0) = n_words;
                  goto nextInsn;
               }
-              case bci_PACK:
-              case bci_TESTLT_I:
-              case bci_TESTEQ_I:
-              case bci_TESTLT_F:
-              case bci_TESTEQ_F:
-              case bci_TESTLT_D:
-              case bci_TESTEQ_D:
-              case bci_TESTLT_P:
-              case bci_TESTEQ_P:
-              case bci_CASEFAIL:
-   
+              case bci_PACK: {
+                 int i;
+                 int o_itbl         = BCO_NEXT;
+                 int n_words        = BCO_NEXT;
+                 StgInfoTable* itbl = INFO_PTR_TO_STRUCT(BCO_ITBL(o_itbl));
+                 int request        = CONSTR_sizeW( itbl->layout.payload.ptrs, 
+                                                    itbl->layout.payload.nptrs );
+                 StgClosure* con = (StgClosure*)allocate_NONUPD(request);
+                //fprintf(stderr, "---PACK p %d, np %d\n",
+                //      (int) itbl->layout.payload.ptrs,
+                //      (int) itbl->layout.payload.nptrs );
+                 ASSERT( itbl->layout.payload.ptrs + itbl->layout.payload.nptrs > 0);
+                 SET_HDR(con, BCO_ITBL(o_itbl), CCS_SYSTEM/*ToDo*/);
+                 for (i = 0; i < n_words; i++)
+                    con->payload[i] = (StgClosure*)StackWord(i);
+                 iSp += n_words;
+                 iSp --;
+                 StackWord(0) = (W_)con;
+                IF_DEBUG(evaluator,
+                          fprintf(stderr,"\tBuilt "); 
+                          printObj((StgClosure*)con);
+                        );
+                 goto nextInsn;
+              }
+              case bci_TESTLT_P: {
+                 int discr  = BCO_NEXT;
+                 int failto = BCO_NEXT;
+                 StgClosure* con = (StgClosure*)StackWord(0);
+                 if (constrTag(con) >= discr)
+                    bciPtr = failto;
+                 goto nextInsn;
+              }
+              case bci_TESTEQ_P: {
+                 int discr  = BCO_NEXT;
+                 int failto = BCO_NEXT;
+                 StgClosure* con = (StgClosure*)StackWord(0);
+                 if (constrTag(con) != discr)
+                    bciPtr = failto;
+                 goto nextInsn;
+              }
+              case bci_TESTLT_I: {
+                 /* The top thing on the stack should be a tagged int. */
+                 int discr   = BCO_NEXT;
+                 int failto  = BCO_NEXT;
+                 I_ stackInt = (I_)StackWord(1);
+                 ASSERT(1 == StackWord(0));
+                 if (stackInt >= (I_)BCO_LIT(discr))
+                    bciPtr = failto;
+                 goto nextInsn;
+              }
+              case bci_TESTEQ_I: {
+                 /* The top thing on the stack should be a tagged int. */
+                 int discr   = BCO_NEXT;
+                 int failto  = BCO_NEXT;
+                 I_ stackInt = (I_)StackWord(1);
+                 ASSERT(1 == StackWord(0));
+                 if (stackInt != (I_)BCO_LIT(discr))
+                    bciPtr = failto;
+                 goto nextInsn;
+              }
+              case bci_TESTLT_D: {
+                 /* The top thing on the stack should be a tagged double. */
+                 int discr   = BCO_NEXT;
+                 int failto  = BCO_NEXT;
+                 StgDouble stackDbl, discrDbl;
+                 ASSERT(sizeofW(StgDouble) == StackWord(0));
+                 stackDbl = PK_DBL( & StackWord(1) );
+                 discrDbl = PK_DBL( & BCO_LIT(discr) );
+                 if (stackDbl >= discrDbl)
+                    bciPtr = failto;
+                 goto nextInsn;
+              }
+              case bci_TESTEQ_D: {
+                 /* The top thing on the stack should be a tagged double. */
+                 int discr   = BCO_NEXT;
+                 int failto  = BCO_NEXT;
+                 StgDouble stackDbl, discrDbl;
+                 ASSERT(sizeofW(StgDouble) == StackWord(0));
+                 stackDbl = PK_DBL( & StackWord(1) );
+                 discrDbl = PK_DBL( & BCO_LIT(discr) );
+                 if (stackDbl != discrDbl)
+                    bciPtr = failto;
+                 goto nextInsn;
+              }
+
               /* Control-flow ish things */
-              case bci_ARGCHECK:
-              case bci_ENTER:
-              case bci_RETURN:
+              case bci_ENTER: {
+                 goto nextEnter;
+              }
+              case bci_RETURN: {
+                 /* Figure out whether returning to interpreted or
+                    compiled code. */
+                 int           o_itoc_itbl = BCO_NEXT;
+                 int           tag         = StackWord(0);
+                 StgInfoTable* ret_itbl    = (StgInfoTable*)StackWord(tag +1);
+                 ASSERT(tag <= 2); /* say ... */
+                 if (ret_itbl == (StgInfoTable*)&stg_ctoi_ret_R1p_info
+                     || ret_itbl == (StgInfoTable*)&stg_ctoi_ret_R1n_info
+                     || ret_itbl == (StgInfoTable*)&stg_ctoi_ret_F1_info
+                     || ret_itbl == (StgInfoTable*)&stg_ctoi_ret_D1_info) {
+                     /* Returning to interpreted code.  Interpret the BCO 
+                        immediately underneath the itbl. */
+                     StgBCO* ret_bco = (StgBCO*)StackWord(tag +1+1);
+                     iSp --;
+                     StackWord(0) = (W_)ret_bco;
+                     goto nextEnter;
+                 } else {
+                     /* Returning (unboxed value) to compiled code.
+                        Replace tag with a suitable itbl and ask the
+                        scheduler to run it.  The itbl code will copy
+                        the TOS value into R1/F1/D1 and do a standard
+                        compiled-code return. */
+                     StgInfoTable* magic_itbl = BCO_ITBL(o_itoc_itbl);
+                     StackWord(0) = (W_)magic_itbl;
+                     RETURN(ThreadRunGHC);
+                 }
+              }
         
+              case bci_CASEFAIL:
+                 barf("interpretBCO: hit a CASEFAIL");
+
+              /* As yet unimplemented */
+              case bci_TESTLT_F:
+              case bci_TESTEQ_F:
+
               /* Errors */
-              case bci_LABEL:
-              default: barf
+              default: 
+                 barf("interpretBCO: unknown or unimplemented opcode");
 
           } /* switch on opcode */
-         goto nextEnter;
+
+         barf("interpretBCO: fell off end of insn loop");
 
        }
        /* ---------------------------------------------------- */
@@ -266,16 +473,17 @@ StgThreadReturnCode interpretBCO ( Capability* cap )
 
        default: {
           /* Can't handle this object; yield to sched. */
-          fprintf(stderr, "entering unknown closure -- yielding to sched\n"); 
-          printObj(obj);
+          IF_DEBUG(evaluator,
+                   fprintf(stderr, "entering unknown closure -- yielding to sched\n"); 
+                   printObj(obj);
+                  )
           cap->rCurrentTSO->what_next = ThreadEnterGHC;
-          iSp--; StackWord(0) = obj;
-          return ThreadYielding;
+          iSp--; StackWord(0) = (W_)obj;
+          RETURN(ThreadYielding);
        }
     } /* switch on object kind */
 
-    barf("fallen off end of switch in enter()");
+    barf("fallen off end of object-type switch in interpretBCO()");
 }
 
-
-#endif /* 0 */
+#endif /* GHCI */