* Copyright (c) 1994-1998.
*
* $RCSfile: Evaluator.c,v $
- * $Revision: 1.33 $
- * $Date: 2000/02/15 13:16:20 $
+ * $Revision: 1.44 $
+ * $Date: 2000/03/20 09:42:49 $
* ---------------------------------------------------------------------------*/
#include "Rts.h"
#include "Assembler.h" /* for CFun stuff */
#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 <ieee754.h> /* These are for primops */
#endif
-#ifdef STANDALONE_INTEGER
-#include "sainteger.h"
-#else
-#error Non-standalone integer not yet supported
-#endif
+
+/* Allegedly useful macro, taken from ClosureMacros.h */
+#define payloadWord( c, i ) (*stgCast(StgWord*, ((c)->payload+(i))))
+#define payloadPtr( c, i ) (*stgCast(StgPtr*, ((c)->payload+(i))))
/* An incredibly useful abbreviation.
* Interestingly, there are some uses of END_TSO_QUEUE_closure that
}
+
void cp_enter ( StgBCO* b )
{
int is_ret_cont;
}
+typedef struct {
+ StgTSOBlockReason reason;
+ unsigned int delay;
+} HugsBlock;
+
+
/* --------------------------------------------------------------------------
* Entering-objects and bytecode interpreter part of evaluator
* ------------------------------------------------------------------------*/
/* Forward decls ... */
static void* enterBCO_primop1 ( int );
static void* enterBCO_primop2 ( int , int* /*StgThreadReturnCode* */,
- StgBCO**, Capability* );
+ StgBCO**, Capability*, HugsBlock * );
static inline void PopUpdateFrame ( StgClosure* obj );
static inline void PopCatchFrame ( void );
static inline void PopSeqFrame ( void );
static int enterCountI = 0;
-#ifdef STANDALONE_INTEGER
StgDouble B__encodeDouble (B* s, I_ e);
void B__decodeDouble (B* man, I_* exp, StgDouble dbl);
#if ! FLOATS_AS_DOUBLES
B* IntegerInsideByteArray ( StgPtr );
void SloppifyIntegerEnd ( StgPtr );
#endif
-#endif
register StgClosure* obj; /* object currently under evaluation */
char eCount; /* enter counter, for context switching */
+
+ HugsBlock hugsBlock = { NotBlocked, 0 };
+
+
#ifdef DEBUG
StgPtr tSp; StgUpdateFrame* tSu; StgPtr tSpLim;
#endif
#endif
) {
if (context_switch) {
- xPushCPtr(obj); /* code to restart with */
- RETURN(ThreadYielding);
+ switch(hugsBlock.reason) {
+ case NotBlocked: {
+ xPushCPtr(obj); /* code to restart with */
+ RETURN(ThreadYielding);
+ }
+ case BlockedOnDelay: /* fall through */
+ case BlockedOnRead: /* fall through */
+ case BlockedOnWrite: {
+ ASSERT(cap->rCurrentTSO->why_blocked == NotBlocked);
+ cap->rCurrentTSO->why_blocked = BlockedOnDelay;
+ ACQUIRE_LOCK(&sched_mutex);
+
+#if defined(HAVE_SETITIMER)
+ cap->rCurrentTSO->block_info.delay
+ = hugsBlock.delay + ticks_since_select;
+#else
+ cap->rCurrentTSO->block_info.target
+ = hugsBlock.delay + getourtimeofday();
+#endif
+ APPEND_TO_BLOCKED_QUEUE(cap->rCurrentTSO);
+
+ RELEASE_LOCK(&sched_mutex);
+
+ xPushCPtr(obj); /* code to restart with */
+ RETURN(ThreadBlocked);
+ }
+ default:
+ barf("Unknown context switch reasoning");
+ }
}
}
nat np = info->layout.payload.nptrs;
nat i;
for(i=0; i < p; ++i) {
- payloadCPtr(o,i) = xPopCPtr();
+ o->payload[i] = xPopCPtr();
}
for(i=0; i < np; ++i) {
payloadWord(o,p+i) = 0xdeadbeef;
nat np = info->layout.payload.nptrs;
nat i;
for(i=0; i < p; ++i) {
- payloadCPtr(o,i) = xPopCPtr();
+ o->payload[i] = xPopCPtr();
}
for(i=0; i < np; ++i) {
payloadWord(o,p+i) = 0xdeadbeef;
|| itbl->type == CONSTR_0_2
);
while (--i>=0) {
- xPushCPtr(payloadCPtr(o,i));
+ xPushCPtr(o->payload[i]);
}
Continue;
}
xPushTaggedInt(bcoConstInt(bco,BCO_INSTR_8));
Continue;
}
+ Case(i_CONST_INT_big):
+ {
+ int n = BCO_INSTR_16;
+ xPushTaggedInt(bcoConstInt(bco,n));
+ Continue;
+ }
Case(i_PACK_INT):
{
StgClosure* o;
SSS; o = (StgClosure*)grabHpNonUpd(Izh_sizeW); LLL;
- SET_HDR(o,&Izh_con_info,??);
+ SET_HDR(o,Izh_con_info,??);
payloadWord(o,0) = xPopTaggedInt();
IF_DEBUG(evaluator,
fprintf(stderr,"\tBuilt ");
{
StgClosure* o;
SSS; o = (StgClosure*)grabHpNonUpd(Wzh_sizeW); LLL;
- SET_HDR(o,&Wzh_con_info,??);
+ SET_HDR(o,Wzh_con_info,??);
payloadWord(o,0) = xPopTaggedWord();
IF_DEBUG(evaluator,
fprintf(stderr,"\tBuilt ");
xPushTaggedAddr(bcoConstAddr(bco,BCO_INSTR_8));
Continue;
}
+ Case(i_CONST_ADDR_big):
+ {
+ int n = BCO_INSTR_16;
+ xPushTaggedAddr(bcoConstAddr(bco,n));
+ Continue;
+ }
Case(i_PACK_ADDR):
{
StgClosure* o;
SSS; o = (StgClosure*)grabHpNonUpd(Azh_sizeW); LLL;
- SET_HDR(o,&Azh_con_info,??);
+ SET_HDR(o,Azh_con_info,??);
payloadPtr(o,0) = xPopTaggedAddr();
IF_DEBUG(evaluator,
fprintf(stderr,"\tBuilt ");
{
StgClosure* o;
SSS; o = (StgClosure*)grabHpNonUpd(Czh_sizeW); LLL;
- SET_HDR(o,&Czh_con_info,??);
+ SET_HDR(o,Czh_con_info,??);
payloadWord(o,0) = xPopTaggedChar();
xPushPtr(stgCast(StgPtr,o));
IF_DEBUG(evaluator,
{
StgClosure* o;
SSS; o = (StgClosure*)grabHpNonUpd(Fzh_sizeW); LLL;
- SET_HDR(o,&Fzh_con_info,??);
+ SET_HDR(o,Fzh_con_info,??);
ASSIGN_FLT(&payloadWord(o,0),xPopTaggedFloat());
IF_DEBUG(evaluator,
fprintf(stderr,"\tBuilt ");
{
StgClosure* o;
SSS; o = (StgClosure*)grabHpNonUpd(Dzh_sizeW); LLL;
- SET_HDR(o,&Dzh_con_info,??);
+ SET_HDR(o,Dzh_con_info,??);
ASSIGN_DBL(&payloadWord(o,0),xPopTaggedDouble());
IF_DEBUG(evaluator,
fprintf(stderr,"\tBuilt ");
{
StgClosure* o;
SSS; o = (StgClosure*)grabHpNonUpd(Stablezh_sizeW); LLL;
- SET_HDR(o,&StablePtr_con_info,??);
+ SET_HDR(o,StablePtr_con_info,??);
payloadWord(o,0) = xPopTaggedStable();
IF_DEBUG(evaluator,
fprintf(stderr,"\tBuilt ");
pc_saved = PC;
bco_tmp = bco;
SSS;
- p = enterBCO_primop2 ( i, &trc, &bco_tmp, cap );
+ p = enterBCO_primop2 ( i, &trc, &bco_tmp, cap,
+ &hugsBlock );
LLL;
bco = bco_tmp;
bciPtr = &(bcoInstr(bco,pc_saved));
/* we want to enter p */
obj = p; goto enterLoop;
} else {
- /* trc is the the StgThreadReturnCode for this thread */
- RETURN((StgThreadReturnCode)trc);
+ /* trc is the the StgThreadReturnCode for
+ * this thread */
+ RETURN((StgThreadReturnCode)trc);
};
}
Continue;
Case(i_VAR_FLOAT_big):
Case(i_CONST_CHAR_big):
Case(i_VAR_CHAR_big):
- Case(i_CONST_ADDR_big):
Case(i_VAR_ADDR_big):
Case(i_VAR_STABLE_big):
Case(i_CONST_INTEGER_big):
- Case(i_CONST_INT_big):
Case(i_VAR_INT_big):
Case(i_VAR_WORD_big):
Case(i_RETADDR_big):
case SE_CAF_BLACKHOLE:
{
/* Let the scheduler figure out what to do :-) */
- cap->rCurrentTSO->whatNext = ThreadEnterGHC;
+ cap->rCurrentTSO->what_next = ThreadEnterGHC;
xPushCPtr(obj);
RETURN(ThreadYielding);
}
case RET_VEC_SMALL:
case RET_BIG:
case RET_VEC_BIG:
- cap->rCurrentTSO->whatNext = ThreadEnterGHC;
+ cap->rCurrentTSO->what_next = ThreadEnterGHC;
xPushCPtr(obj);
RETURN(ThreadYielding);
default:
//fprintf(stderr, "entering unknown closure -- yielding to sched\n");
//printObj(obj);
//LLL;
- cap->rCurrentTSO->whatNext = ThreadEnterGHC;
+ cap->rCurrentTSO->what_next = ThreadEnterGHC;
xPushCPtr(obj); /* code to restart with */
RETURN(ThreadYielding);
}
HaskellObj error
= asmClosureOfObject(getHugs_AsmObject_for("error"));
HaskellObj unpack
- = asmClosureOfObject(getHugs_AsmObject_for("primUnpackString"));
+ = asmClosureOfObject(getHugs_AsmObject_for("hugsprimUnpackString"));
HaskellObj thunk
= rts_apply ( unpack, rts_mkAddr ( (void*)msg ) );
thunk
}
-#ifdef STANDALONE_INTEGER
StgPtr CreateByteArrayToHoldInteger ( int nbytes )
{
- StgInt words = (nbytes+sizeof(W_)-1)/sizeof(W_);
+ StgWord words = (nbytes+sizeof(W_)-1)/sizeof(W_);
StgWord size = sizeofW(StgArrWords) + words;
StgArrWords* arr = (StgArrWords*)allocate(size);
SET_HDR(arr,&ARR_WORDS_info,CCCS);
arr->words = words;
- ASSERT(nbytes <= arr->words * sizeof(W_));
+ ASSERT((W_)nbytes <= arr->words * sizeof(W_));
#ifdef DEBUG
- {nat i;
+ {StgWord i;
for (i = 0; i < words; ++i) {
arr->payload[i] = 0xdeadbeef;
}}
SloppifyIntegerEnd(p); \
PushPtr(p); \
}
-#endif
}
-void myStackCheck ( Capability* cap )
+static void myStackCheck ( Capability* cap )
{
/* fprintf(stderr, "myStackCheck\n"); */
if (!(gSpLim <= gSp && gSp <= stgCast(StgPtr,gSu))) {
assert(0);
}
while (1) {
- if (!(gSu >= cap->rCurrentTSO->stack
- && gSu <= cap->rCurrentTSO->stack
- + cap->rCurrentTSO->stack_size)) {
+ if (!( (P_)gSu >= (P_)cap->rCurrentTSO->stack
+ &&
+ (P_)gSu <= (P_)(cap->rCurrentTSO->stack
+ + cap->rCurrentTSO->stack_size))) {
fprintf ( stderr, "myStackCheck: gSu out of stack\n" );
assert(0);
}
switch (get_itbl(stgCast(StgClosure*,gSu))->type) {
case CATCH_FRAME:
- gSu = (StgPtr) ((StgCatchFrame*)(gSu))->link;
+ gSu = (StgUpdateFrame*) ((StgCatchFrame*)(gSu))->link;
break;
case UPDATE_FRAME:
- gSu = (StgPtr) ((StgUpdateFrame*)(gSu))->link;
+ gSu = (StgUpdateFrame*) ((StgUpdateFrame*)(gSu))->link;
break;
case SEQ_FRAME:
- gSu = (StgPtr) ((StgSeqFrame*)(gSu))->link;
+ gSu = (StgUpdateFrame*) ((StgSeqFrame*)(gSu))->link;
break;
case STOP_FRAME:
goto postloop;
case i_readStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
case i_writeStableOffAddr: OP_AIs_(writeStablePtrOffAddrzh(x,y,z)); break;
-#ifdef STANDALONE_INTEGER
case i_compareInteger:
{
B* x = IntegerInsideByteArray(PopPtr());
IntegerInsideByteArray(PopPtr())
));
break;
-#else
-#error Non-standalone integer not yet implemented
-#endif /* STANDALONE_INTEGER */
case i_gtFloat: OP_FF_B(x>y); break;
case i_geFloat: OP_FF_B(x>=y); break;
case i_tanhFloat: OP_F_F(tanh(x)); break;
case i_powerFloat: OP_FF_F(pow(x,y)); break;
-#ifdef STANDALONE_INTEGER
case i_encodeFloatZ:
{
StgPtr sig = PopPtr();
PushPtr(sig);
}
break;
-#else
-#error encode/decodeFloatZ not yet implemented for GHC ints
-#endif
+
case i_isNaNFloat: OP_F_B(isFloatNaN(x)); break;
case i_isInfiniteFloat: OP_F_B(isFloatInfinite(x)); break;
case i_isNegativeZeroFloat: OP_F_B(isFloatNegativeZero(x)); break;
case i_tanhDouble: OP_D_D(tanh(x)); break;
case i_powerDouble: OP_DD_D(pow(x,y)); break;
-#ifdef STANDALONE_INTEGER
case i_encodeDoubleZ:
{
StgPtr sig = PopPtr();
PushPtr(sig);
}
break;
-#else
-#error encode/decodeDoubleZ not yet implemented for GHC ints
-#endif
+
case i_isNaNDouble: OP_D_B(isDoubleNaN(x)); break;
case i_isInfiniteDouble: OP_D_B(isDoubleInfinite(x)); break;
case i_isNegativeZeroDouble: OP_D_B(isDoubleNegativeZero(x)); break;
return the address of it and leave *return2 unchanged.
To return a StgThreadReturnCode to the scheduler,
set *return2 to it and return a non-NULL value.
+ To cause a context switch, set context_switch (its a global),
+ and optionally set hugsBlock to your rational.
*/
static void* enterBCO_primop2 ( int primop2code,
int* /*StgThreadReturnCode* */ return2,
StgBCO** bco,
- Capability* cap )
+ Capability* cap,
+ HugsBlock *hugsBlock )
{
- if (combined)
- barf("enterBCO_primop1 in combined mode");
+ if (combined) {
+ /* A small concession: we need to allow ccalls,
+ even in combined mode.
+ */
+ if (primop2code != i_ccall_ccall_IO &&
+ primop2code != i_ccall_stdcall_IO)
+ barf("enterBCO_primop2 in combined mode");
+ }
switch (primop2code) {
case i_raise: /* raise#{err} */
*/
PushCPtr((StgClosure*)(*bco));
*return2 = ThreadBlocked;
- return (void*)(1+(NULL));
+ return (void*)(1+(char*)(NULL));
} else {
PushCPtr(mvar->value);
PushTaggedBool(x==y);
break;
}
- case i_getThreadId:
- {
- StgWord tid = cap->rCurrentTSO->id;
- PushTaggedWord(tid);
- break;
- }
- case i_cmpThreadIds:
- {
- StgWord tid1 = PopTaggedWord();
- StgWord tid2 = PopTaggedWord();
- if (tid1 < tid2) PushTaggedInt(-1);
- else if (tid1 > tid2) PushTaggedInt(1);
- else PushTaggedInt(0);
- break;
- }
+#ifdef PROVIDE_CONCURRENT
case i_forkIO:
{
StgClosure* closure;
tid = tso->id;
scheduleThread(tso);
context_switch = 1;
+ /* Later: Change to use tso as the ThreadId */
PushTaggedWord(tid);
break;
}
-#ifdef PROVIDE_CONCURRENT
case i_killThread:
{
- StgTSO* tso = stgCast(StgTSO*,PopPtr());
+ StgWord n = PopTaggedWord();
+ StgTSO* tso = 0;
+ StgTSO *t;
+
+ // Map from ThreadId to Thread Structure */
+ for (t = all_threads; t != END_TSO_QUEUE; t = t->global_link) {
+ if (n == t->id)
+ tso = t;
+ }
+ if (tso == 0) {
+ // Already dead
+ break;
+ }
+
+ while (tso->what_next == ThreadRelocated) {
+ tso = tso->link;
+ }
+
deleteThread(tso);
if (tso == cap->rCurrentTSO) { /* suicide */
*return2 = ThreadFinished;
}
break;
}
-
-#if 1
-#if 0
-ToDo: another way out of the problem might be to add an explicit
-continuation to primTakeMVar: takeMVar v = primTakeMVar v takeMVar.
-The problem with this plan is that now I dont know how much to chop
-off the stack.
-#endif
-#endif
+ case i_raiseInThread:
+ ASSERT(0); /* not (yet) supported */
case i_delay:
+ {
+ StgInt n = PopTaggedInt();
+ context_switch = 1;
+ hugsBlock->reason = BlockedOnDelay;
+ hugsBlock->delay = n;
+ break;
+ }
case i_waitRead:
+ {
+ StgInt n = PopTaggedInt();
+ context_switch = 1;
+ hugsBlock->reason = BlockedOnRead;
+ hugsBlock->delay = n;
+ break;
+ }
case i_waitWrite:
- /* As PrimOps.h says: Hmm, I'll think about these later. */
- ASSERT(0);
+ {
+ StgInt n = PopTaggedInt();
+ context_switch = 1;
+ hugsBlock->reason = BlockedOnWrite;
+ hugsBlock->delay = n;
+ break;
+ }
+ case i_yield:
+ {
+ /* The definition of yield include an enter right after
+ * the primYield, at which time context_switch is tested.
+ */
+ context_switch = 1;
+ break;
+ }
+ case i_getThreadId:
+ {
+ StgWord tid = cap->rCurrentTSO->id;
+ PushTaggedWord(tid);
break;
+ }
+ case i_cmpThreadIds:
+ {
+ StgWord tid1 = PopTaggedWord();
+ StgWord tid2 = PopTaggedWord();
+ if (tid1 < tid2) PushTaggedInt(-1);
+ else if (tid1 > tid2) PushTaggedInt(1);
+ else PushTaggedInt(0);
+ break;
+ }
#endif /* PROVIDE_CONCURRENT */
case i_ccall_ccall_Id:
case INT_REP:
PushTaggedInt(*((int*)arg));
return ARG_SIZE(INT_TAG);
-#ifdef TODO_STANDALONE_INTEGER
+#if 0
case INTEGER_REP:
PushTaggedInteger(*((mpz_ptr*)arg));
return ARG_SIZE(INTEGER_TAG);
case INT_REP:
*((int*)res) = PopTaggedInt();
return ARG_SIZE(INT_TAG);
-#ifdef TODO_STANDALONE_INTEGER
+#if 0
case INTEGER_REP:
*((mpz_ptr*)res) = PopTaggedInteger();
return ARG_SIZE(INTEGER_TAG);
case INT_REP:
sz += sizeof(StgWord) * ARG_SIZE(INT_TAG);
break;
-#ifdef TODO_STANDALONE_INTEGER
+#if 0
case INTEGER_REP:
sz += sizeof(StgWord) * ARG_SIZE(INTEGER_TAG);
break;
* (ghc/rts/StgPrimFloat.c)
* ---------------------------------------------------------------------------*/
-#ifdef STANDALONE_INTEGER
-
#if IEEE_FLOATING_POINT
#define MY_DMINEXP ((DBL_MIN_EXP) - (DBL_MANT_DIG) - 1)
/* DMINEXP is defined in values.h on Linux (for example) */
#endif /* FLOATS_AS_DOUBLES */
-#endif /* STANDALONE_INTEGER */
-
#endif /* INTERPRETER */