* Copyright (c) 1994-1998.
*
* $RCSfile: Evaluator.c,v $
- * $Revision: 1.57 $
- * $Date: 2000/10/09 10:28:33 $
+ * $Revision: 1.58 $
+ * $Date: 2000/10/09 11:20:16 $
* ---------------------------------------------------------------------------*/
#include "Rts.h"
xPushPtr(p);
Continue;
}
-#ifdef XMLAMBDA
- /* allocate rows, implemented on top of Arrays */
- Case(i_ALLOC_ROW):
- {
- StgMutArrPtrs* p;
- int n = BCO_INSTR_8;
- SSS; p = stgCast(StgMutArrPtrs*,grabHpNonUpd(sizeofW(StgMutArrPtrs) + n)); LLL;
- SET_HDR(p,&MUT_ARR_PTRS_FROZEN_info,CCCS);
- p->ptrs = n;
- xPushPtr(p);
- Continue;
- }
- Case(i_ALLOC_ROW_big):
- {
- StgMutArrPtrs* p;
- int n = BCO_INSTR_16;
- SSS; p = stgCast(StgMutArrPtrs*,grabHpNonUpd(sizeofW(StgMutArrPtrs) + n)); LLL;
- SET_HDR(p,&MUT_ARR_PTRS_FROZEN_info,CCCS);
- p->ptrs = n;
- xPushPtr(p);
- Continue;
- }
-#endif
Case(i_MKAP):
{
int x = BCO_INSTR_8; /* ToDo: Word not Int! */
);
Continue;
}
+ Case(i_SLIDE):
+ {
+ int x = BCO_INSTR_8;
+ int y = BCO_INSTR_8;
+ ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
+ /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
+ while(--x >= 0) {
+ xSetStackWord(x+y,xStackWord(x));
+ }
+ xSp += y;
+ Continue;
+ }
+ Case(i_SLIDE_big):
+ {
+ int x, y;
+ x = BCO_INSTR_16;
+ y = BCO_INSTR_16;
+ ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
+ /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
+ while(--x >= 0) {
+ xSetStackWord(x+y,xStackWord(x));
+ }
+ xSp += y;
+ Continue;
+ }
+ Case(i_ENTER):
+ {
+ obj = xPopCPtr();
+ goto enterLoop;
+ }
+ Case(i_RETADDR):
+ {
+ xPushPtr(bcoConstPtr(bco,BCO_INSTR_8));
+ xPushPtr(stgCast(StgPtr,&ret_bco_info));
+ Continue;
+ }
+ Case(i_TEST):
+ {
+ int tag = BCO_INSTR_8;
+ StgWord offset = BCO_INSTR_16;
+ if (constrTag( (StgClosure*)xStackPtr(0) ) != tag) {
+ bciPtr += offset;
+ }
+ Continue;
+ }
+ Case(i_UNPACK):
+ {
+ StgClosure* o = stgCast(StgClosure*,xStackPtr(0));
+ const StgInfoTable* itbl = get_itbl(o);
+ int i = itbl->layout.payload.ptrs;
+ ASSERT( itbl->type == CONSTR
+ || itbl->type == CONSTR_STATIC
+ || itbl->type == CONSTR_NOCAF_STATIC
+ || itbl->type == CONSTR_1_0
+ || itbl->type == CONSTR_0_1
+ || itbl->type == CONSTR_2_0
+ || itbl->type == CONSTR_1_1
+ || itbl->type == CONSTR_0_2
+ );
+ while (--i>=0) {
+ xPushCPtr(o->payload[i]);
+ }
+ Continue;
+ }
+ Case(i_VAR_big):
+ {
+ int n = BCO_INSTR_16;
+ StgPtr p = xStackPtr(n);
+ xPushPtr(p);
+ Continue;
+ }
+ Case(i_VAR):
+ {
+ StgPtr p = xStackPtr(BCO_INSTR_8);
+ xPushPtr(p);
+ Continue;
+ }
+ Case(i_CONST):
+ {
+ xPushPtr(stgCast(StgPtr,bcoConstPtr(bco,BCO_INSTR_8)));
+ Continue;
+ }
+ Case(i_CONST_big):
+ {
+ int n = BCO_INSTR_16;
+ xPushPtr(stgCast(StgPtr,bcoConstPtr(bco,n)));
+ Continue;
+ }
#ifdef XMLAMBDA
+ /* allocate rows, implemented on top of (frozen) Arrays */
+ Case(i_ALLOC_ROW):
+ {
+ StgMutArrPtrs* p;
+ StgWord n = BCO_INSTR_8;
+ SSS; p = stgCast(StgMutArrPtrs*,grabHpNonUpd(sizeofW(StgMutArrPtrs) + n)); LLL;
+ SET_HDR(p,&MUT_ARR_PTRS_FROZEN_info,CCCS);
+ p->ptrs = n;
+ xPushPtr(p);
+ Continue;
+ }
+ Case(i_ALLOC_ROW_big):
+ {
+ StgMutArrPtrs* p;
+ StgWord n = BCO_INSTR_16;
+ SSS; p = stgCast(StgMutArrPtrs*,grabHpNonUpd(sizeofW(StgMutArrPtrs) + n)); LLL;
+ SET_HDR(p,&MUT_ARR_PTRS_FROZEN_info,CCCS);
+ p->ptrs = n;
+ xPushPtr(p);
+ Continue;
+ }
+
/* pack values into a row. */
Case(i_PACK_ROW):
{
- int offset = BCO_INSTR_8;
+ StgWord offset = BCO_INSTR_8;
StgMutArrPtrs* p = stgCast(StgMutArrPtrs*,xStackPtr(offset));
StgWord n = p->ptrs;
- nat i;
+ StgWord i;
for (i=0; i<n; ++i)
{
}
Case(i_PACK_ROW_big):
{
- int offset = BCO_INSTR_16;
+ StgWord offset = BCO_INSTR_16;
StgMutArrPtrs* p = stgCast(StgMutArrPtrs*,xStackPtr(offset));
StgWord n = p->ptrs;
- nat i;
+ StgWord i;
for (i=0; i<n; ++i)
{
);
Continue;
}
+
+ /* extract all fields of a row */
+ Case(i_UNPACK_ROW):
+ {
+ StgMutArrPtrs* p = stgCast(StgMutArrPtrs*,xStackPtr(0));
+ nat i = p->ptrs;
+ while (i > 0)
+ {
+ i--;
+ xPushCPtr(p->payload[i]);
+ }
+ Continue;
+ }
+
+ /* Trivial row (unit) */
+ Case(i_CONST_ROW_TRIV):
+ {
+ StgMutArrPtrs* p;
+ SSS; p = stgCast(StgMutArrPtrs*,grabHpNonUpd(sizeofW(StgMutArrPtrs) + 0)); LLL;
+ SET_HDR(p,&MUT_ARR_PTRS_FROZEN_info,CCCS);
+ p->ptrs = 0;
+ xPushPtr(p);
+ Continue;
+ }
+
/* pack values into an Inj */
- Case(i_PACK_INJ):
+ Case(i_PACK_INJ_VAR):
{
- const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgInt));
- int offset = BCO_INSTR_8;
+ const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgWord));
+ StgWord offset = BCO_INSTR_8;
StgClosure* o;
SSS; o = (StgClosure*)grabHpNonUpd(size); LLL;
SET_HDR(o,Inj_con_info,??);
- payloadWord(o,sizeofW(StgPtr)) = xTaggedStackInt(offset);
+ payloadWord(o,sizeofW(StgPtr)) = xTaggedStackWord(offset);
payloadPtr(o,0) = xPopPtr();
IF_DEBUG(evaluator,
xPushPtr(stgCast(StgPtr,o));
Continue;
}
- Case(i_PACK_INJ_big):
+ Case(i_PACK_INJ_VAR_big):
{
- const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgInt));
- int offset = BCO_INSTR_16;
+ const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgWord));
+ StgWord offset = BCO_INSTR_16;
StgClosure* o;
SSS; o = (StgClosure*)grabHpNonUpd(size); LLL;
SET_HDR(o,Inj_con_info,??);
- payloadWord(o,sizeofW(StgPtr)) = xTaggedStackInt(offset);
+ payloadWord(o,sizeofW(StgPtr)) = xTaggedStackWord(offset);
payloadPtr(o,0) = xPopPtr();
IF_DEBUG(evaluator,
xPushPtr(stgCast(StgPtr,o));
Continue;
}
- Case(i_PACK_INJ_CONST):
+ Case(i_PACK_INJ_CONST_8):
{
- const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgInt));
- int index = BCO_INSTR_8;
+ const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgWord));
+ StgWord witness = BCO_INSTR_8;
StgClosure* o;
SSS; o = (StgClosure*)grabHpNonUpd(size); LLL;
SET_HDR(o,Inj_con_info,??);
- payloadWord(o,sizeofW(StgPtr)) = index;
+ payloadWord(o,sizeofW(StgPtr)) = witness;
payloadPtr(o,0) = xPopPtr();
IF_DEBUG(evaluator,
xPushPtr(stgCast(StgPtr,o));
Continue;
}
-
-#endif /* XMLAMBDA */
- Case(i_SLIDE):
+ Case(i_PACK_INJ_REL_8):
{
- int x = BCO_INSTR_8;
- int y = BCO_INSTR_8;
- ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
- /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
- while(--x >= 0) {
- xSetStackWord(x+y,xStackWord(x));
- }
- xSp += y;
- Continue;
- }
- Case(i_SLIDE_big):
- {
- int x, y;
- x = BCO_INSTR_16;
- y = BCO_INSTR_16;
- ASSERT(xSp+x+y <= stgCast(StgPtr,xSu));
- /* a_1, .. a_x, b_1, .. b_y, s => a_1, .. a_x, s */
- while(--x >= 0) {
- xSetStackWord(x+y,xStackWord(x));
- }
- xSp += y;
- Continue;
- }
- Case(i_ENTER):
- {
- obj = xPopCPtr();
- goto enterLoop;
- }
- Case(i_RETADDR):
- {
- xPushPtr(bcoConstPtr(bco,BCO_INSTR_8));
- xPushPtr(stgCast(StgPtr,&ret_bco_info));
+ const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgWord));
+ StgWord offset = BCO_INSTR_8;
+ StgWord cwitness = BCO_INSTR_8;
+
+ StgClosure* o;
+ SSS; o = (StgClosure*)grabHpNonUpd(size); LLL;
+ SET_HDR(o,Inj_con_info,??);
+
+ payloadWord(o,sizeofW(StgPtr)) = xTaggedStackWord(offset) + cwitness;
+ payloadPtr(o,0) = xPopPtr();
+
+ IF_DEBUG(evaluator,
+ fprintf(stderr,"\tBuilt ");
+ SSS;
+ printObj(stgCast(StgClosure*,o));
+ LLL;
+ );
+ xPushPtr(stgCast(StgPtr,o));
Continue;
}
- Case(i_TEST):
+ Case(i_PACK_INJ):
{
- int tag = BCO_INSTR_8;
- StgWord offset = BCO_INSTR_16;
- if (constrTag( (StgClosure*)xStackPtr(0) ) != tag) {
- bciPtr += offset;
- }
+ const int size = CONSTR_sizeW(sizeofW(StgPtr),sizeofW(StgWord));
+
+ StgClosure* o;
+ SSS; o = (StgClosure*)grabHpNonUpd(size); LLL;
+ SET_HDR(o,Inj_con_info,??);
+
+ payloadWord(o,sizeofW(StgPtr)) = xPopTaggedWord();
+ payloadPtr(o,0) = xPopPtr();
+
+ IF_DEBUG(evaluator,
+ fprintf(stderr,"\tBuilt ");
+ SSS;
+ printObj(stgCast(StgClosure*,o));
+ LLL;
+ );
+ xPushPtr(stgCast(StgPtr,o));
Continue;
}
-#ifdef XMLAMBDA
- /* Test Inj indices. */
- Case(i_TEST_INJ):
+
+ /* Test Inj witnesses. */
+ Case(i_TEST_INJ_VAR):
{
- int offset = BCO_INSTR_8;
+ StgWord offset = BCO_INSTR_8;
StgWord jump = BCO_INSTR_16;
- int index = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
- if (index != xTaggedStackInt(offset) )
+ StgWord index = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
+ if (index != xTaggedStackWord(offset) )
{
bciPtr += jump;
}
Continue;
}
- Case(i_TEST_INJ_big):
+ Case(i_TEST_INJ_VAR_big):
{
- int offset = BCO_INSTR_16;
+ StgWord offset = BCO_INSTR_16;
StgWord jump = BCO_INSTR_16;
- int index = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
- if (index != xTaggedStackInt(offset) )
+ StgWord index = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
+ if (index != xTaggedStackWord(offset) )
{
bciPtr += jump;
}
Continue;
}
- Case(i_TEST_INJ_CONST):
+ Case(i_TEST_INJ_CONST_8):
{
- int value = BCO_INSTR_8;
- StgWord jump = BCO_INSTR_16;
+ StgWord cwitness = BCO_INSTR_8;
+ StgWord jump = BCO_INSTR_16;
- int index = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
- if (index != value )
+ StgWord witness = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
+ if (witness != cwitness )
{
bciPtr += jump;
}
Continue;
}
-#endif /* XMLAMBDA */
- Case(i_UNPACK):
+ Case(i_TEST_INJ_REL_8):
{
- StgClosure* o = stgCast(StgClosure*,xStackPtr(0));
- const StgInfoTable* itbl = get_itbl(o);
- int i = itbl->layout.payload.ptrs;
- ASSERT( itbl->type == CONSTR
- || itbl->type == CONSTR_STATIC
- || itbl->type == CONSTR_NOCAF_STATIC
- || itbl->type == CONSTR_1_0
- || itbl->type == CONSTR_0_1
- || itbl->type == CONSTR_2_0
- || itbl->type == CONSTR_1_1
- || itbl->type == CONSTR_0_2
- );
- while (--i>=0) {
- xPushCPtr(o->payload[i]);
+ StgWord offset = BCO_INSTR_8;
+ StgWord cwitness = BCO_INSTR_8;
+ StgWord jump = BCO_INSTR_16;
+
+ StgWord witness = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
+ if (witness != xTaggedStackWord(offset) + cwitness )
+ {
+ bciPtr += jump;
}
- Continue;
+ Continue;
}
-#ifdef XMLAMBDA
- /* extract all fields of a row */
- Case(i_UNPACK_ROW):
+ Case(i_TEST_INJ):
{
- StgMutArrPtrs* p = stgCast(StgMutArrPtrs*,xStackPtr(0));
- int i = p->ptrs;
- while (--i >= 0)
+ StgWord jump = BCO_INSTR_16;
+ StgWord cwitness = xPopTaggedWord();
+
+ StgWord witness = payloadWord( (StgClosure*)xStackPtr(0), sizeofW(StgPtr) );
+ if (witness != cwitness )
{
- xPushCPtr(p->payload[i]);
+ bciPtr += jump;
}
Continue;
- }
+ }
+
/* extract the value of an INJ */
Case(i_UNPACK_INJ):
{
xPushPtr(payloadPtr(con,0));
Continue;
}
-#endif /* XMLAMBA */
- Case(i_VAR_big):
+
+ /* optimized witness (word) operations */
+ Case(i_CONST_WORD_8):
{
- int n = BCO_INSTR_16;
- StgPtr p = xStackPtr(n);
- xPushPtr(p);
+ xPushTaggedWord(BCO_INSTR_8);
Continue;
}
- Case(i_VAR):
+ Case(i_ADD_WORD_VAR):
{
- StgPtr p = xStackPtr(BCO_INSTR_8);
- xPushPtr(p);
+ StgWord offset = BCO_INSTR_8;
+ StgWord witness = xTaggedStackWord(offset);
+ witness += xPopTaggedWord();
+ xPushTaggedWord(witness);
Continue;
}
- Case(i_CONST):
+ Case(i_ADD_WORD_VAR_big):
{
- xPushPtr(stgCast(StgPtr,bcoConstPtr(bco,BCO_INSTR_8)));
+ StgWord offset = BCO_INSTR_16;
+ StgWord witness = xTaggedStackWord(offset);
+ witness += xPopTaggedWord();
+ xPushTaggedWord(witness);
Continue;
- }
- Case(i_CONST_big):
- {
- int n = BCO_INSTR_16;
- xPushPtr(stgCast(StgPtr,bcoConstPtr(bco,n)));
+ }
+ Case(i_ADD_WORD_VAR_8):
+ {
+ StgWord offset = BCO_INSTR_8;
+ StgWord inc = BCO_INSTR_8;
+ StgWord witness = xTaggedStackWord(offset);
+ xPushTaggedWord(witness + inc);
Continue;
}
+#endif /* XMLAMBA */
+
Case(i_VOID):
{
SSS; PushTaggedRealWorld(); LLL;
xPushTaggedWord(bcoConstWord(bco,BCO_INSTR_8));
Continue;
}
+ Case(i_CONST_WORD_big):
+ {
+ StgWord n = BCO_INSTR_16;
+ xPushTaggedWord(bcoConstWord(bco,n));
+ Continue;
+ }
Case(i_PACK_WORD):
{
StgClosure* o;
}
#ifdef XMLAMBDA
/*------------------------------------------------------------------------
- Insert and Remove primitives on Rows
+ Insert and Remove primitives on Rows. This is important stuff for
+ XMlambda, these prims are called *all* the time. That's the reason
+ for all the specialized versions of the basic instructions.
+ note: A Gc might move rows around => allocate first, than pop the arguments.
+------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------
+ i_rowInsertAt: insert an element into a row
------------------------------------------------------------------------*/
case i_rowInsertAt:
{
- nat j;
- /* get: row, index and value */
- StgMutArrPtrs* row = stgCast(StgMutArrPtrs*,PopPtr());
- nat i = PopTaggedInt();
- StgClosure* x = PopCPtr();
-
- /* allocate new row */
- StgWord n = row->ptrs;
+ StgWord j;
+ StgWord i;
+ StgWord n;
+ StgClosure* x;
+
+ /* allocate a new row before popping arguments */
+ StgMutArrPtrs* row = stgCast(StgMutArrPtrs*,stackPtr(0));
StgMutArrPtrs* newRow
- = stgCast(StgMutArrPtrs*,allocate(sizeofW(StgMutArrPtrs) + n + 1));
+ = stgCast(StgMutArrPtrs*,allocate(sizeofW(StgMutArrPtrs) + row->ptrs + 1));
SET_HDR(newRow,&MUT_ARR_PTRS_FROZEN_info,CCCS);
+
+ /* pop row again and pop index and value */
+ row = stgCast(StgMutArrPtrs*,PopPtr());
+ n = row->ptrs;
newRow->ptrs = n+1;
+ i = PopTaggedWord();
+ x = PopCPtr();
+
ASSERT(i <= n);
/* copy the fields, inserting the new value */
break;
}
- case i_rowRemoveAt:
+/*------------------------------------------------------------------------
+ i_rowChainInsert: behaves like a chain of [i_rowInsertAt] calls. This
+ instruction is vital for XMLambda since we would otherwise allocate
+ a lot of intermediate rows.
+ It assumes that the RTS has no NULL pointers.
+ It behaves 'optimal' if the witnesses are ordered, (lowest on the
+ bottom of the stack).
+------------------------------------------------------------------------*/
+#define ROW_HOLE 0
+ case i_rowChainInsert:
{
- nat j;
- /* get row and index */
- StgMutArrPtrs* row = stgCast(StgMutArrPtrs*,PopPtr());
- nat i = PopTaggedInt(); /* or Word?? */
+ StgWord witness, topWitness;
+ StgClosure* value;
+ StgWord j;
+ StgWord i;
+
+ /* pop the number of arguments (=witness/value pairs) */
+ StgWord n = PopTaggedWord();
+
+ /* allocate a new row before popping boxed arguments */
+ StgMutArrPtrs* row = stgCast(StgMutArrPtrs*,stackPtr(0));
+ StgMutArrPtrs* newRow
+ = stgCast(StgMutArrPtrs*,allocate(sizeofW(StgMutArrPtrs) + n + row->ptrs));
+ SET_HDR(newRow,&MUT_ARR_PTRS_FROZEN_info,CCCS);
+
+ /* pop the row and assign again (it may have moved during gc!) */
+ row = stgCast(StgMutArrPtrs*,PopPtr());
+ newRow->ptrs = n + row->ptrs;
+
+ /* zero the fields */
+ for (i = 0; i < newRow->ptrs; i++)
+ {
+ newRow->payload[i] = ROW_HOLE;
+ }
+
+ /* insert all values */
+ topWitness = 0; /*invariant: 1 + maximal witness */
+ for (i = 0; i < n; i++)
+ {
+ witness = PopTaggedWord();
+ value = PopCPtr();
+ if (witness < topWitness)
+ {
+ /* shoot, unordered witnesses, we have to bump up everything */
+ for (j = topWitness; j > witness; j--)
+ {
+ newRow->payload[j] = newRow->payload[j-1];
+ }
+ topWitness += 1;
+ }
+ else
+ {
+ topWitness = witness+1;
+ }
+
+ ASSERT(topWitness <= n);
+ ASSERT(witness < n);
+ newRow->payload[witness] = value;
+ }
+
+ /* copy the values from the old row into the holes */
+ for (j =0, i = 0; i < row->ptrs; j++,i++)
+ {
+ while (newRow->payload[j] != ROW_HOLE) j++;
+ ASSERT(j < n);
+ newRow->payload[j] = row->payload[i];
+ }
+
+ /* push the result */
+ PushPtr(stgCast(StgPtr,newRow));
+ break;
+ }
+
+/*------------------------------------------------------------------------
+ i_rowChainBuild: exactly as [i_rowChainInsert] but builds a row from scratch.
+------------------------------------------------------------------------*/
+ case i_rowChainBuild:
+ {
+ StgWord witness, topWitness;
+ StgClosure* value;
+ StgWord j;
+ StgWord i;
+
+ /* pop the number of arguments (=witness/value pairs) */
+ StgWord n = PopTaggedWord();
+
+ /* allocate a new row before popping boxed arguments */
+ StgMutArrPtrs* newRow
+ = stgCast(StgMutArrPtrs*,allocate(sizeofW(StgMutArrPtrs) + n));
+ SET_HDR(newRow,&MUT_ARR_PTRS_FROZEN_info,CCCS);
+ newRow->ptrs = n;
+
+ /* insert all values */
+ topWitness = 0; /*invariant: 1 + maximal witness */
+ for (i = 0; i < n; i++)
+ {
+ witness = PopTaggedWord();
+ value = PopCPtr();
+ if (witness < topWitness)
+ {
+ /* shoot, unordered witnesses, we have to bump up everything */
+ for (j = topWitness; j > witness; j--)
+ {
+ newRow->payload[j] = newRow->payload[j-1];
+ }
+ topWitness += 1;
+ }
+ else
+ {
+ topWitness = witness+1;
+ }
+
+ ASSERT(topWitness <= n);
+ ASSERT(witness < n);
+ newRow->payload[witness] = value;
+ }
- /* allocate new row */
- StgWord n = row->ptrs;
+ /* push the result */
+ PushPtr(stgCast(StgPtr,newRow));
+ break;
+ }
+
+/*------------------------------------------------------------------------
+ i_rowRemoveAt: remove an element from a row
+------------------------------------------------------------------------*/
+ case i_rowRemoveAt:
+ {
+ StgWord j;
+ StgWord i;
+ StgWord n;
+
+ /* allocate new row before popping the arguments */
+ StgMutArrPtrs* row = stgCast(StgMutArrPtrs*,stackPtr(0));
StgMutArrPtrs* newRow
- = stgCast(StgMutArrPtrs*,allocate(sizeofW(StgMutArrPtrs) + n - 1));
+ = stgCast(StgMutArrPtrs*,allocate(sizeofW(StgMutArrPtrs) + row->ptrs - 1));
SET_HDR(newRow,&MUT_ARR_PTRS_FROZEN_info,CCCS);
+
+ /* pop row again and pop the index */
+ row = stgCast(StgMutArrPtrs*,PopPtr());
+ n = row->ptrs;
newRow->ptrs = n-1;
-
+
+ i = PopTaggedWord();
+
ASSERT(i < n);
/* copy the fields, except for the removed value. */
PushPtr(stgCast(StgPtr,newRow));
break;
}
+
+/*------------------------------------------------------------------------
+ i_rowChainRemove: behaves like a chain of [i_rowRemoveAt] calls. Again,
+ this is a vital instruction to avoid lots of intermediate rows.
+ It behaves 'optimal' if the witnessses are ordered, lowest on the
+ bottom of the stack.
+ The implementation is quite dirty, blame Daan for this :-)
+ (It overwrites witnesses on the stack with results and marks pointers
+ using their lowest bit.)
+------------------------------------------------------------------------*/
+#define MARK(p) (stgCast(StgClosure*,(stgCast(StgWord,(p)) | 0x01)))
+#define UNMARK(p) (stgCast(StgClosure*,(stgCast(StgWord,(p)) & ~0x01)))
+#define ISMARKED(p) ((stgCast(StgWord,(p)) & 0x01) == 0x01)
+
+ case i_rowChainRemove:
+ {
+ const nat sizeofTaggedWord = sizeofW(StgWord) + sizeofW(StackTag);
+ StgWord i;
+ StgWord j;
+ StgWord minWitness;
+ nat base;
+ StgClosure* value;
+
+
+ /* pop number of arguments (=witnesses) */
+ StgWord n = PopTaggedWord();
+
+ /* allocate new row before popping boxed arguments */
+ StgMutArrPtrs* row = stgCast(StgMutArrPtrs*,stackPtr(0));
+ StgMutArrPtrs* newRow
+ = stgCast(StgMutArrPtrs*,allocate(sizeofW(StgMutArrPtrs) + row->ptrs - n));
+ SET_HDR(newRow,&MUT_ARR_PTRS_FROZEN_info,CCCS);
+
+ /* pop row and assign again (gc might have moved it) */
+ row = stgCast(StgMutArrPtrs*,PopPtr());
+ newRow->ptrs = row->ptrs - n;
+ ASSERT( row->ptrs > n );
+
+ /* 'push' all elements that are removed */
+ base = n*sizeofTaggedWord;
+ minWitness = row->ptrs;
+ for (i = 1; i <= n; i++)
+ {
+ StgWord witness;
+
+ witness = taggedStackWord( base - i*sizeofTaggedWord );
+ if (witness >= minWitness)
+ {
+ /* shoot, unordered witnesses, we have to search for the value */
+ nat count;
+
+ count = witness - minWitness;
+ witness = minWitness;
+ while (1)
+ {
+ do{ witness++; } while (ISMARKED(row->payload[witness]));
+ if (count == 0) break;
+ count--;
+ }
+ }
+ else
+ {
+ minWitness = witness;
+ }
+ ASSERT( witness < row->ptrs );
+ ASSERT( !ISMARKED(row->payload[witness]) );
+
+ /* mark the element */
+ value = row->payload[witness];
+ row->payload[witness] = MARK(value);
+
+ /* set the value in the stack (overwriting old witnesses!) */
+ setStackPtr( base - i*sizeofW(StgPtr), stgCast(StgPtr,value) );
+ }
+
+ /* pop the garbage from the stack */
+ gSp = gSp + base - n*sizeofW(StgPtr);
+
+ /* copy all remaining elements and clear the marks */
+ for (j = 0, i = 0; i < newRow->ptrs; j++,i++)
+ {
+ while (ISMARKED(row->payload[j]))
+ {
+ row->payload[j] = UNMARK(row->payload[j]);
+ j++;
+ }
+ newRow->payload[i] = row->payload[j];
+ }
+
+ /* unmark tail */
+ while (j < row->ptrs)
+ {
+ value = row->payload[j];
+ if (ISMARKED(value)) row->payload[j] = UNMARK(value);
+ j++;
+ }
+
+#ifdef DEBUG
+ for (i = 0; i < row->ptrs; i++)
+ {
+ ASSERT(!ISMARKED(row->payload[i]));
+ }
+#endif
+
+ /* and push the result row */
+ PushPtr(stgCast(StgPtr,newRow));
+ break;
+ }
+
+/*------------------------------------------------------------------------
+ i_rowChainSelect: behaves exactly like [i_rowChainRemove] but doesn't return
+ the resulting row, only the removed elements.
+------------------------------------------------------------------------*/
+ case i_rowChainSelect:
+ {
+ const nat sizeofTaggedWord = sizeofW(StgWord) + sizeofW(StackTag);
+ StgWord i;
+ StgWord minWitness;
+ nat base;
+ StgClosure* value;
+
+ /* pop number of arguments (=witnesses) and row*/
+ StgWord n = PopTaggedWord();
+ StgMutArrPtrs* row = stgCast(StgMutArrPtrs*,PopPtr());
+ ASSERT( row->ptrs > n );
+
+ /* 'push' all elements that are removed */
+ base = n*sizeofTaggedWord;
+ minWitness = row->ptrs;
+ for (i = 1; i <= n; i++)
+ {
+ StgWord witness;
+
+ witness = taggedStackWord( base - i*sizeofTaggedWord );
+ if (witness >= minWitness)
+ {
+ /* shoot, unordered witnesses, we have to search for the value */
+ nat count;
+
+ count = witness - minWitness;
+ witness = minWitness;
+ while (1)
+ {
+ do{ witness++; } while (ISMARKED(row->payload[witness]));
+ if (count == 0) break;
+ count--;
+ }
+ }
+ else
+ {
+ minWitness = witness;
+ }
+ ASSERT( witness < row->ptrs );
+ ASSERT( !ISMARKED(row->payload[witness]) );
+
+ /* mark the element */
+ value = row->payload[witness];
+ row->payload[witness] = MARK(value);
+
+ /* set the value in the stack (overwriting old witnesses!) */
+ setStackPtr( base - i*sizeofW(StgPtr), stgCast(StgPtr,value) );
+ }
+
+ /* pop the garbage from the stack */
+ gSp = gSp + base - n*sizeofW(StgPtr);
+
+ /* unmark elements */
+ for( i = 0; i < row->ptrs; i++)
+ {
+ value = row->payload[i];
+ if (ISMARKED(value)) row->payload[i] = UNMARK(value);
+ }
+
+#ifdef DEBUG
+ for (i = 0; i < row->ptrs; i++)
+ {
+ ASSERT(!ISMARKED(row->payload[i]));
+ }
+#endif
+ break;
+ }
+
#endif /* XMLAMBDA */
case i_newRef:
break;
}
#endif /* PROVIDE_CONCURRENT */
+#ifdef XMLAMBDA
+ case i_ccall:
+ {
+ CallInfo callInfo;
+ CFunDescriptor descriptor;
+ void (*funPtr)(void);
+
+ StgWord offset = PopTaggedWord(); /* offset into bco nonptr section */
+ funPtr = PopTaggedAddr();
+
+ ASSERT(funPtr != NULL);
+
+ /* copy the complete callinfo, the bco might move during GC! */
+ callInfo = *stgCast(CallInfo*, (*bco)->payload + (*bco)->n_ptrs + offset);
+
+ /* copy info to a CFunDescriptor. just for compatibility. */
+ descriptor.num_args = callInfo.argCount;
+ descriptor.arg_tys = callInfo.data;
+ descriptor.num_results = callInfo.resultCount;
+ descriptor.result_tys = callInfo.data + callInfo.argCount + 1;
+
+ /* call out */
+ switch (ccall( &descriptor, funPtr, bco, callInfo.callConv, cap ))
+ {
+ case 0: break;
+ case 1: barf( "unhandled type or too many args/results in ccall"); break;
+ case 2: barf("ccall not configured correctly for this platform"); break;
+ default: barf("unknown return code from ccall"); break;
+ }
+
+ break;
+ }
+#endif
case i_ccall_ccall_Id:
case i_ccall_ccall_IO: