-
-#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 )
/* 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: {
int o2 = BCO_NEXT;
StackWord(-1) = StackWord(o1);
StackWord(-2) = StackWord(o2);
- Sp -= 2;
+ iSp -= 2;
goto nextInsn;
}
case bci_PUSH_LLL: {
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");
}
/* ---------------------------------------------------- */
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 */