cleaned up code a bit

This commit is contained in:
hyunghwan.chung 2015-06-25 13:37:50 +00:00
parent 54aa947bab
commit 0427879198
5 changed files with 215 additions and 138 deletions

View File

@ -56,12 +56,15 @@
#define ACTIVE_STACK_ISEMPTY(stix) ((stix)->sp <= -1) #define ACTIVE_STACK_ISEMPTY(stix) ((stix)->sp <= -1)
#define SWITCH_ACTIVE_CONTEXT(stix,v_ctx) \ #define SWITCH_ACTIVE_CONTEXT(stix,v_ctx) \
do \ do \
{ \ { \
STORE_ACTIVE_IP (stix); \ STORE_ACTIVE_IP (stix); \
STORE_ACTIVE_SP (stix); \ STORE_ACTIVE_SP (stix); \
(stix)->active_context = (v_ctx); \ (stix)->active_context = (v_ctx); \
(stix)->active_method = (stix_oop_method_t)(stix)->active_context->origin->method_or_nargs; \
(stix)->active_code = (stix)->active_method->code; \
LOAD_ACTIVE_IP (stix); \ LOAD_ACTIVE_IP (stix); \
LOAD_ACTIVE_SP (stix); \ LOAD_ACTIVE_SP (stix); \
} while (0) \ } while (0) \
@ -73,10 +76,10 @@ static STIX_INLINE int activate_new_method (stix_t* stix, stix_oop_method_t mth,
stix_ooi_t i; stix_ooi_t i;
stix_ooi_t ntmprs, nargs; stix_ooi_t ntmprs, nargs;
stack_size = 256; /* TODO: make the stack size configurable or let the compiler choose the rightr value and store it in the compiled method. if it's stored in the compiled method, the code here can take it*/ stack_size = 256; /* TODO: make the stack size configurable or let the compiler choose the right value and store it in the compiled method. if it's stored in the compiled method, the code here can take it*/
stix_pushtmp (stix, (stix_oop_t*)&mth); stix_pushtmp (stix, (stix_oop_t*)&mth);
ctx = (stix_oop_context_t)stix_instantiate (stix, stix->_context, STIX_NULL, stack_size); ctx = (stix_oop_context_t)stix_instantiate (stix, stix->_method_context, STIX_NULL, stack_size);
stix_poptmp (stix); stix_poptmp (stix);
if (!ctx) return -1; if (!ctx) return -1;
@ -102,14 +105,23 @@ static STIX_INLINE int activate_new_method (stix_t* stix, stix_oop_method_t mth,
* | | slot[stack_size - 1] * | | slot[stack_size - 1]
* +---------------------+ * +---------------------+
*/ */
ntmprs = STIX_OOP_TO_SMINT (mth->tmpr_count); ntmprs = STIX_OOP_TO_SMINT(mth->tmpr_count);
nargs = STIX_OOP_TO_SMINT (mth->tmpr_nargs); nargs = STIX_OOP_TO_SMINT(mth->tmpr_nargs);
STIX_ASSERT (ntmprs >= 0); STIX_ASSERT (ntmprs >= 0);
STIX_ASSERT (nargs <= ntmprs); STIX_ASSERT (nargs <= ntmprs);
STIX_ASSERT (stix->sp >= 0); STIX_ASSERT (stix->sp >= 0);
STIX_ASSERT (stix->sp >= nargs); STIX_ASSERT (stix->sp >= nargs);
#if 0
if (stix->option.trait & STIX_NOTCO)
{
#endif
ctx->sender = (stix_oop_t)stix->active_context;
#if 0
}
else
{
switch (next_inst) switch (next_inst)
{ {
case (CODE_POP_STACKTOP << 8) | CODE_RETURN_STACKTOP: case (CODE_POP_STACKTOP << 8) | CODE_RETURN_STACKTOP:
@ -117,7 +129,7 @@ static STIX_INLINE int activate_new_method (stix_t* stix, stix_oop_method_t mth,
case CODE_RETURN_STACKTOP: case CODE_RETURN_STACKTOP:
case CODE_RETURN_RECEIVER: case CODE_RETURN_RECEIVER:
/* tail-call optimization */ /* tail-call optimization */
/* TODO: is this correct? */ /* TODO: is this correct? */
ctx->sender = stix->active_context->sender; ctx->sender = stix->active_context->sender;
break; break;
@ -131,6 +143,8 @@ static STIX_INLINE int activate_new_method (stix_t* stix, stix_oop_method_t mth,
ctx->sender = (stix_oop_t)stix->active_context; ctx->sender = (stix_oop_t)stix->active_context;
break; break;
} }
}
#endif
ctx->ip = 0; ctx->ip = 0;
@ -158,8 +172,9 @@ static STIX_INLINE int activate_new_method (stix_t* stix, stix_oop_method_t mth,
*/ */
ctx->sp = STIX_OOP_FROM_SMINT(ntmprs - 1); ctx->sp = STIX_OOP_FROM_SMINT(ntmprs - 1);
ctx->ntmprs = STIX_OOP_FROM_SMINT(ntmprs); ctx->ntmprs = STIX_OOP_FROM_SMINT(ntmprs);
ctx->method = mth; ctx->method_or_nargs = (stix_oop_t)mth;
/*ctx->home = stix->_nil;*/ /* the 'home' fiedl is stix->_nil for a method context.
ctx->home = stix->_nil;*/
ctx->origin = ctx; /* point to self */ ctx->origin = ctx; /* point to self */
/* /*
@ -190,7 +205,7 @@ static STIX_INLINE int activate_new_method (stix_t* stix, stix_oop_method_t mth,
ACTIVE_STACK_POP (stix); ACTIVE_STACK_POP (stix);
} }
/* copy receiver */ /* copy receiver */
ctx->receiver = ACTIVE_STACK_GETTOP (stix); ctx->receiver_or_source = ACTIVE_STACK_GETTOP (stix);
ACTIVE_STACK_POP (stix); ACTIVE_STACK_POP (stix);
STIX_ASSERT (stix->sp >= -1); STIX_ASSERT (stix->sp >= -1);
@ -281,7 +296,7 @@ static int activate_initial_context (stix_t* stix, const stix_ucs_t* objname, co
stix_oop_method_t mth; stix_oop_method_t mth;
/* create a fake initial context */ /* create a fake initial context */
ctx = (stix_oop_context_t)stix_instantiate (stix, stix->_context, STIX_NULL, 1); ctx = (stix_oop_context_t)stix_instantiate (stix, stix->_method_context, STIX_NULL, 1);
if (!ctx) return -1; if (!ctx) return -1;
ass = stix_lookupsysdic (stix, objname); ass = stix_lookupsysdic (stix, objname);
@ -302,16 +317,16 @@ TODO: overcome this problem
/* TODO: handle preamble */ /* TODO: handle preamble */
/* the initial context starts the life of the entire VM /* the initial context starts the life of the entire VM
* and is not really worked on except that it is used to call the * and is not really worked on except that it is used to call the
* initial method. so it doesn't really require any extra stack space. * initial method. so it doesn't really require any extra stack space.
* TODO: verify my theory above is true */ * TODO: verify my theory above is true */
stix->ip = 0; stix->ip = 0;
stix->sp = -1; stix->sp = -1;
/* receiver, sender, method are nils */
ctx->origin = ctx;
ctx->method_or_nargs = (stix_oop_t)mth; /* fake. help SWITCH_ACTIVE_CONTEXT() not fail*/
/* receiver, sender of ctx are nils */
STIX_ASSERT (stix->active_context == STIX_NULL); STIX_ASSERT (stix->active_context == STIX_NULL);
/* i can't use SWITCH_ACTIVE_CONTEXT() macro as there is no active context before switching */ /* i can't use SWITCH_ACTIVE_CONTEXT() macro as there is no active context before switching */
@ -324,7 +339,6 @@ TODO: overcome this problem
return activate_new_method (stix, mth, CODE_NOOP); return activate_new_method (stix, mth, CODE_NOOP);
} }
static int primitive_dump (stix_t* stix, stix_ooi_t nargs) static int primitive_dump (stix_t* stix, stix_ooi_t nargs)
{ {
stix_ooi_t i; stix_ooi_t i;
@ -570,7 +584,7 @@ static int primitive_basic_at_put (stix_t* stix, stix_ooi_t nargs)
static int primitive_block_context_value (stix_t* stix, stix_ooi_t nargs) static int primitive_block_context_value (stix_t* stix, stix_ooi_t nargs)
{ {
stix_oop_block_context_t blkctx, org_blkctx; stix_oop_context_t blkctx, org_blkctx;
stix_ooi_t local_ntmprs, i; stix_ooi_t local_ntmprs, i;
/* TODO: find a better way to support a reentrant block context. */ /* TODO: find a better way to support a reentrant block context. */
@ -583,10 +597,23 @@ static int primitive_block_context_value (stix_t* stix, stix_ooi_t nargs)
* itself. Let me simply clone a block context to allow reentrancy like this * itself. Let me simply clone a block context to allow reentrancy like this
* while the block context is active * while the block context is active
*/ */
org_blkctx = (stix_oop_block_context_t)ACTIVE_STACK_GET(stix, stix->sp - nargs); org_blkctx = (stix_oop_context_t)ACTIVE_STACK_GET(stix, stix->sp - nargs);
STIX_ASSERT (STIX_CLASSOF(stix, org_blkctx) == stix->_block_context); STIX_ASSERT (STIX_CLASSOF(stix, org_blkctx) == stix->_block_context);
if (STIX_OOP_TO_SMINT(org_blkctx->nargs) != nargs) if (org_blkctx->receiver_or_source != stix->_nil)
{
/* this block context has already been activated once.
* you can't send 'value' again to reactivate it.
* For example, [thisContext value] value.
*/
STIX_ASSERT (STIX_OBJ_GET_SIZE(org_blkctx) > STIX_CONTEXT_NAMED_INSTVARS);
printf ("PRIM REVALUING AN BLOCKCONTEXT\n");
return 0;
}
STIX_ASSERT (STIX_OBJ_GET_SIZE(org_blkctx) == STIX_CONTEXT_NAMED_INSTVARS);
if (STIX_OOP_TO_SMINT(org_blkctx->method_or_nargs) != nargs)
{ {
/* the number of argument doesn't match */ /* the number of argument doesn't match */
/* TODO: better handling of primitive failure */ /* TODO: better handling of primitive failure */
@ -596,20 +623,30 @@ printf ("PRIM BlockContext value FAIL - NARGS MISMATCH\n");
/* TODO: what is the right stack size? is 255 too large? any good way to determine it? */ /* TODO: what is the right stack size? is 255 too large? any good way to determine it? */
/* create a new block context to clone org_blkctx */ /* create a new block context to clone org_blkctx */
blkctx = (stix_oop_block_context_t) stix_instantiate (stix, stix->_block_context, STIX_NULL, 255); blkctx = (stix_oop_context_t) stix_instantiate (stix, stix->_block_context, STIX_NULL, 255);
if (!blkctx) return -1; if (!blkctx) return -1;
org_blkctx = (stix_oop_block_context_t)ACTIVE_STACK_GET(stix, stix->sp - nargs); /* to be GC-safe */ /* getting org_blkctx again to be GC-safe for stix_instantiate() above */
org_blkctx = (stix_oop_context_t)ACTIVE_STACK_GET(stix, stix->sp - nargs);
STIX_ASSERT (STIX_CLASSOF(stix, org_blkctx) == stix->_block_context); STIX_ASSERT (STIX_CLASSOF(stix, org_blkctx) == stix->_block_context);
/* shallow-copy the named part. leave the stack part untouched. #if 0
* the stack is set up futher down */ /* shallow-copy the named part including home, origin, etc. */
for (i = 0; i < STIX_BLOCK_CONTEXT_NAMED_INSTVARS; i++) for (i = 0; i < STIX_CONTEXT_NAMED_INSTVARS; i++)
{ {
((stix_oop_oop_t)blkctx)->slot[i] = ((stix_oop_oop_t)org_blkctx)->slot[i]; ((stix_oop_oop_t)blkctx)->slot[i] = ((stix_oop_oop_t)org_blkctx)->slot[i];
} }
#else
blkctx->ip = org_blkctx->ip;
blkctx->ntmprs = org_blkctx->ntmprs;
blkctx->method_or_nargs = org_blkctx->method_or_nargs;
blkctx->receiver_or_source = (stix_oop_t)org_blkctx;
blkctx->home = org_blkctx->home;
blkctx->origin = org_blkctx->origin;
#endif
/* TODO: check the stack size of a block context to see if it's large enough to hold arguments */ /* TODO: check the stack size of a block context to see if it's large enough to hold arguments */
/* copy the arguments to the stack */
for (i = 0; i < nargs; i++) for (i = 0; i < nargs; i++)
{ {
blkctx->slot[i] = ACTIVE_STACK_GET(stix, stix->sp - nargs + i + 1); blkctx->slot[i] = ACTIVE_STACK_GET(stix, stix->sp - nargs + i + 1);
@ -628,7 +665,7 @@ printf ("PRIM BlockContext value FAIL - NARGS MISMATCH\n");
STIX_ASSERT (local_ntmprs >= nargs); STIX_ASSERT (local_ntmprs >= nargs);
blkctx->sp = STIX_OOP_FROM_SMINT(local_ntmprs); blkctx->sp = STIX_OOP_FROM_SMINT(local_ntmprs);
blkctx->caller = (stix_oop_t)stix->active_context; blkctx->sender = (stix_oop_t)stix->active_context;
SWITCH_ACTIVE_CONTEXT (stix, (stix_oop_context_t)blkctx); SWITCH_ACTIVE_CONTEXT (stix, (stix_oop_context_t)blkctx);
return 1; return 1;
@ -764,32 +801,31 @@ static primitive_t primitives[] =
}; };
#define FETCH_BYTE_CODE_TO(stix, v_ooi) (v_ooi = (stix)->active_code->slot[(stix)->ip++])
#if (STIX_CODE_EXTEND_SIZE == 2) #if (STIX_CODE_EXTEND_SIZE == 2)
#define FETCH_UNSIGNED_CODE_TO(stix, v_code, v_ooi) \ #define FETCH_UNSIGNED_CODE_TO(stix, v_ooi) \
do { \ do { \
v_ooi = (v_code)->slot[(stix)->ip++]; \ v_ooi = (stix)->active_code->slot[(stix)->ip++]; \
v_ooi = (v_ooi << 8) | (v_code)->slot[stix->ip++]; \ v_ooi = (v_ooi << 8) | (stix)->active_code->slot[stix->ip++]; \
} while (0) } while (0)
#define FETCH_SIGNED_CODE_TO(stix, v_code, v_ooi) \ #define FETCH_SIGNED_CODE_TO(stix, v_ooi) \
do { \ do { \
v_ooi = (v_code)->slot[(stix)->ip++]; \ v_ooi = (stix)->active_code->slot[(stix)->ip++]; \
v_ooi = (stix_int16_t)((v_ooi << 8) | (v_code)->slot[stix->ip++]); \ v_ooi = (stix_int16_t)((v_ooi << 8) | (stix)->active_code->slot[stix->ip++]); \
} while (0) } while (0)
#else /* STIX_CODE_EXTEND_SIZE == 2 */ #else /* STIX_CODE_EXTEND_SIZE == 2 */
#define FETCH_UNSIGNED_CODE_TO(stix, v_code, v_ooi) (v_ooi = (v_code)->slot[(stix)->ip++]) #define FETCH_UNSIGNED_CODE_TO(stix, v_ooi) (v_ooi = (stix)->active_code->slot[(stix)->ip++])
#define FETCH_SIGNED_CODE_TO(stix, v_code, v_ooi) (v_ooi = (stix_int8_t)(v_code)->slot[(stix)->ip++]) #define FETCH_SIGNED_CODE_TO(stix, v_ooi) (v_ooi = (stix_int8_t)(stix)->active_code->slot[(stix)->ip++])
#endif /* STIX_CODE_EXTEND_SIZE == 2 */ #endif /* STIX_CODE_EXTEND_SIZE == 2 */
int stix_execute (stix_t* stix) int stix_execute (stix_t* stix)
{ {
stix_oop_method_t mth;
stix_oop_byte_t code;
stix_byte_t bc, cmd; stix_byte_t bc, cmd;
stix_ooi_t b1, b2; stix_ooi_t b1, b2;
@ -801,14 +837,11 @@ int stix_execute (stix_t* stix)
while (1) while (1)
{ {
mth = stix->active_context->origin->method;
code = mth->code;
#if 0 #if 0
printf ("IP => %d ", (int)stix->ip); printf ("IP => %d ", (int)stix->ip);
#endif #endif
bc = code->slot[stix->ip++]; FETCH_BYTE_CODE_TO (stix, bc);
while (bc == CODE_NOOP) while (bc == CODE_NOOP) FETCH_BYTE_CODE_TO (stix, bc);
bc = code->slot[stix->ip++];
cmd = bc >> 4; cmd = bc >> 4;
if (cmd == CMD_EXTEND) if (cmd == CMD_EXTEND)
@ -818,19 +851,19 @@ printf ("IP => %d ", (int)stix->ip);
{ {
case CMD_JUMP: case CMD_JUMP:
case CMD_JUMP_IF_FALSE: case CMD_JUMP_IF_FALSE:
FETCH_SIGNED_CODE_TO (stix, code, b1); FETCH_SIGNED_CODE_TO (stix, b1);
break; break;
case CMD_PUSH_OBJVAR: case CMD_PUSH_OBJVAR:
case CMD_STORE_INTO_OBJVAR: case CMD_STORE_INTO_OBJVAR:
case CMD_SEND_MESSAGE: case CMD_SEND_MESSAGE:
case CMD_SEND_MESSAGE_TO_SUPER: case CMD_SEND_MESSAGE_TO_SUPER:
FETCH_UNSIGNED_CODE_TO (stix, code, b1); FETCH_UNSIGNED_CODE_TO (stix, b1);
FETCH_UNSIGNED_CODE_TO (stix, code, b2); FETCH_UNSIGNED_CODE_TO (stix, b2);
break; break;
default: default:
FETCH_UNSIGNED_CODE_TO (stix, code, b1); FETCH_UNSIGNED_CODE_TO (stix, b1);
break; break;
} }
} }
@ -848,7 +881,7 @@ printf ("IP => %d ", (int)stix->ip);
case CMD_SEND_MESSAGE: case CMD_SEND_MESSAGE:
case CMD_SEND_MESSAGE_TO_SUPER: case CMD_SEND_MESSAGE_TO_SUPER:
b1 = bc & 0xF; b1 = bc & 0xF;
b2 = code->slot[stix->ip++]; FETCH_BYTE_CODE_TO (stix, b2);
break; break;
default: default:
@ -866,8 +899,8 @@ printf ("CMD => %d, B1 = %d, SP = %d, IP AFTER INC %d\n", (int)cmd, (int)b1, (in
case CMD_PUSH_INSTVAR: case CMD_PUSH_INSTVAR:
printf ("PUSH_INSTVAR %d\n", (int)b1); printf ("PUSH_INSTVAR %d\n", (int)b1);
STIX_ASSERT (STIX_OBJ_GET_FLAGS_TYPE(stix->active_context->receiver) == STIX_OBJ_TYPE_OOP); STIX_ASSERT (STIX_OBJ_GET_FLAGS_TYPE(stix->active_context->origin->receiver_or_source) == STIX_OBJ_TYPE_OOP);
ACTIVE_STACK_PUSH (stix, ((stix_oop_oop_t)stix->active_context->origin->receiver)->slot[b1]); ACTIVE_STACK_PUSH (stix, ((stix_oop_oop_t)stix->active_context->origin->receiver_or_source)->slot[b1]);
break; break;
case CMD_PUSH_TEMPVAR: case CMD_PUSH_TEMPVAR:
@ -919,15 +952,15 @@ printf (" YYCTX %p STACK TEMPVAR PTR=>%p ADJOFF=%d\n", stix->active_context,
case CMD_PUSH_LITERAL: case CMD_PUSH_LITERAL:
printf ("PUSH_LITERAL idx=%d - ", (int)b1); printf ("PUSH_LITERAL idx=%d - ", (int)b1);
print_object (stix, stix->active_context->origin->method->slot[b1]); print_object (stix, stix->active_method->slot[b1]);
printf ("\n"); printf ("\n");
ACTIVE_STACK_PUSH (stix, stix->active_context->origin->method->slot[b1]); ACTIVE_STACK_PUSH (stix, stix->active_method->slot[b1]);
break; break;
case CMD_STORE_INTO_INSTVAR: case CMD_STORE_INTO_INSTVAR:
printf ("STORE_INSTVAR %d\n", (int)b1); printf ("STORE_INSTVAR %d\n", (int)b1);
STIX_ASSERT (STIX_OBJ_GET_FLAGS_TYPE(stix->active_context->receiver) == STIX_OBJ_TYPE_OOP); STIX_ASSERT (STIX_OBJ_GET_FLAGS_TYPE(stix->active_context->receiver_or_source) == STIX_OBJ_TYPE_OOP);
((stix_oop_oop_t)stix->active_context->origin->receiver)->slot[b1] = ACTIVE_STACK_GETTOP(stix); ((stix_oop_oop_t)stix->active_context->origin->receiver_or_source)->slot[b1] = ACTIVE_STACK_GETTOP(stix);
break; break;
case CMD_STORE_INTO_TEMPVAR: case CMD_STORE_INTO_TEMPVAR:
@ -989,7 +1022,7 @@ printf ("JUMP %d\n", (int)b1);
stix_oop_oop_t obj; stix_oop_oop_t obj;
printf ("PUSH OBJVAR index=%d object_index_in_literal_frame=%d - ", (int)b1, (int)b2); printf ("PUSH OBJVAR index=%d object_index_in_literal_frame=%d - ", (int)b1, (int)b2);
obj = (stix_oop_oop_t)stix->active_context->origin->method->slot[b2]; obj = (stix_oop_oop_t)stix->active_method->slot[b2];
STIX_ASSERT (STIX_OBJ_GET_FLAGS_TYPE(obj) == STIX_OBJ_TYPE_OOP); STIX_ASSERT (STIX_OBJ_GET_FLAGS_TYPE(obj) == STIX_OBJ_TYPE_OOP);
STIX_ASSERT (b1 < STIX_OBJ_GET_SIZE(obj)); STIX_ASSERT (b1 < STIX_OBJ_GET_SIZE(obj));
@ -1003,7 +1036,7 @@ printf ("\n");
{ {
stix_oop_oop_t obj; stix_oop_oop_t obj;
printf ("STORE OBJVAR index=%d object_index_in_literal_frame=%d - ", (int)b1, (int)b2); printf ("STORE OBJVAR index=%d object_index_in_literal_frame=%d - ", (int)b1, (int)b2);
obj = (stix_oop_oop_t)stix->active_context->origin->method->slot[b2]; obj = (stix_oop_oop_t)stix->active_method->slot[b2];
STIX_ASSERT (STIX_OBJ_GET_FLAGS_TYPE(obj) == STIX_OBJ_TYPE_OOP); STIX_ASSERT (STIX_OBJ_GET_FLAGS_TYPE(obj) == STIX_OBJ_TYPE_OOP);
STIX_ASSERT (b1 < STIX_OBJ_GET_SIZE(obj)); STIX_ASSERT (b1 < STIX_OBJ_GET_SIZE(obj));
@ -1029,13 +1062,8 @@ printf ("\n");
stix_ooi_t preamble; stix_ooi_t preamble;
stix_uint16_t next_inst; stix_uint16_t next_inst;
/* read ahead the next instruction for tail-call optimization */
next_inst = ((stix_oop_byte_t)stix->active_context->origin->method->code)->slot[stix->ip];
if (next_inst == CODE_POP_STACKTOP)
next_inst |= (next_inst << 8) + ((stix_oop_byte_t)stix->active_context->origin->method->code)->slot[stix->ip + 1];
/* get the selector from the literal frame */ /* get the selector from the literal frame */
selector = (stix_oop_char_t)stix->active_context->origin->method->slot[b2]; selector = (stix_oop_char_t)stix->active_method->slot[b2];
if (cmd == CMD_SEND_MESSAGE) if (cmd == CMD_SEND_MESSAGE)
printf ("SEND_MESSAGE TO RECEIVER AT STACKPOS=%d NARGS=%d RECEIER=", (int)(stix->sp - b1), (int)b1); printf ("SEND_MESSAGE TO RECEIVER AT STACKPOS=%d NARGS=%d RECEIER=", (int)(stix->sp - b1), (int)b1);
@ -1085,13 +1113,14 @@ printf ("RETURN INSTVAR AT PREAMBLE\n");
case STIX_METHOD_PREAMBLE_PRIMITIVE: case STIX_METHOD_PREAMBLE_PRIMITIVE:
{ {
int n;
stix_ooi_t prim_no; stix_ooi_t prim_no;
prim_no = STIX_METHOD_GET_PREAMBLE_INDEX(preamble); prim_no = STIX_METHOD_GET_PREAMBLE_INDEX(preamble);
if (prim_no >= 0 && prim_no < STIX_COUNTOF(primitives) && if (prim_no >= 0 && prim_no < STIX_COUNTOF(primitives) &&
(primitives[prim_no].nargs < 0 || primitives[prim_no].nargs == b1)) (primitives[prim_no].nargs < 0 || primitives[prim_no].nargs == b1))
{ {
int n;
stix_pushtmp (stix, (stix_oop_t*)&newmth); stix_pushtmp (stix, (stix_oop_t*)&newmth);
n = primitives[prim_no].handler (stix, b1); n = primitives[prim_no].handler (stix, b1);
stix_poptmp (stix); stix_poptmp (stix);
@ -1103,6 +1132,11 @@ printf ("RETURN INSTVAR AT PREAMBLE\n");
} }
default: default:
/* read ahead the next instruction for tail-call optimization */
next_inst = stix->active_code->slot[stix->ip];
if (next_inst == CODE_POP_STACKTOP)
next_inst |= (next_inst << 8) + stix->active_code->slot[stix->ip + 1];
if (activate_new_method (stix, newmth, next_inst) <= -1) goto oops; if (activate_new_method (stix, newmth, next_inst) <= -1) goto oops;
break; break;
} }
@ -1116,8 +1150,8 @@ printf ("RETURN INSTVAR AT PREAMBLE\n");
switch (b1) switch (b1)
{ {
case SUBCMD_PUSH_RECEIVER: case SUBCMD_PUSH_RECEIVER:
printf ("PUSH_RECEIVER %p TO STACK INDEX %d\n", stix->active_context->origin->receiver, (int)stix->sp); printf ("PUSH_RECEIVER %p TO STACK INDEX %d\n", stix->active_context->origin->receiver_or_source, (int)stix->sp);
ACTIVE_STACK_PUSH (stix, stix->active_context->origin->receiver); ACTIVE_STACK_PUSH (stix, stix->active_context->origin->receiver_or_source);
break; break;
case SUBCMD_PUSH_NIL: case SUBCMD_PUSH_NIL:
@ -1189,27 +1223,22 @@ printf ("RETURN_STACKTOP\n");
case SUBCMD_RETURN_RECEIVER: case SUBCMD_RETURN_RECEIVER:
printf ("RETURN_RECEIVER\n"); printf ("RETURN_RECEIVER\n");
return_value = stix->active_context->origin->receiver; return_value = stix->active_context->origin->receiver_or_source;
goto handle_return; goto handle_return;
case SUBCMD_RETURN_FROM_BLOCK: case SUBCMD_RETURN_FROM_BLOCK:
{
stix_oop_block_context_t blkctx;
STIX_ASSERT(STIX_CLASSOF(stix, stix->active_context) == stix->_block_context); STIX_ASSERT(STIX_CLASSOF(stix, stix->active_context) == stix->_block_context);
return_value = ACTIVE_STACK_GETTOP(stix); return_value = ACTIVE_STACK_GETTOP(stix);
blkctx = (stix_oop_block_context_t)stix->active_context; SWITCH_ACTIVE_CONTEXT (stix, (stix_oop_context_t)stix->active_context->sender);
SWITCH_ACTIVE_CONTEXT (stix, (stix_oop_context_t)blkctx->caller);
ACTIVE_STACK_PUSH (stix, return_value); ACTIVE_STACK_PUSH (stix, return_value);
break; break;
}
case SUBCMD_SEND_BLOCK_COPY: case SUBCMD_SEND_BLOCK_COPY:
{ {
stix_ooi_t nargs, ntmprs; stix_ooi_t nargs, ntmprs;
stix_oop_t rctx; stix_oop_context_t rctx;
stix_oop_block_context_t blkctx; stix_oop_context_t blkctx;
printf ("SEND_BLOCK_COPY\n"); printf ("SEND_BLOCK_COPY\n");
/* it emulates thisContext blockCopy: nargs ofTmprCount: ntmprs */ /* it emulates thisContext blockCopy: nargs ofTmprCount: ntmprs */
STIX_ASSERT (stix->sp >= 2); STIX_ASSERT (stix->sp >= 2);
@ -1231,15 +1260,27 @@ printf ("SEND_BLOCK_COPY\n");
* context and activates the cloned context. * context and activates the cloned context.
* this base block context is created with no * this base block context is created with no
* stack for this reason. */ * stack for this reason. */
blkctx = (stix_oop_block_context_t)stix_instantiate (stix, stix->_block_context, STIX_NULL, 0); blkctx = (stix_oop_context_t)stix_instantiate (stix, stix->_block_context, STIX_NULL, 0);
if (!blkctx) return -1; if (!blkctx) return -1;
/* get the receiver to the block copy message after block context instantiation /* get the receiver to the block copy message after block context instantiation
* not to get affected by potential GC */ * not to get affected by potential GC */
rctx = ACTIVE_STACK_GETTOP(stix); rctx = (stix_oop_context_t)ACTIVE_STACK_GETTOP(stix);
/* blkctx->caller is left to nil */ /* [NOTE]
/*blkctx->iip = STIX_OOP_FROM_SMINT(stix->ip + STIX_CODE_EXTEND_SIZE + 1); */ * blkctx->caller is left to nil. it is set to the
* active context before it gets activated. see
* primitive_block_context_value().
*
* blkctx->home is set here to the active context.
* it's redundant to have them pushed to the stack
* though it is to emulate the message sending of
* blockCopy:withNtmprs:.
* TODO: devise a new byte code to eliminate stack pushing.
*
* blkctx->origin is set here by copying the origin
* of the active context.
*/
/* the extended jump instruction has the format of /* the extended jump instruction has the format of
* 0000XXXX KKKKKKKK or 0000XXXX KKKKKKKK KKKKKKKK * 0000XXXX KKKKKKKK or 0000XXXX KKKKKKKK KKKKKKKK
@ -1248,25 +1289,37 @@ printf ("SEND_BLOCK_COPY\n");
blkctx->ip = STIX_OOP_FROM_SMINT(stix->ip + STIX_CODE_EXTEND_SIZE + 1); blkctx->ip = STIX_OOP_FROM_SMINT(stix->ip + STIX_CODE_EXTEND_SIZE + 1);
blkctx->sp = STIX_OOP_FROM_SMINT(-1); blkctx->sp = STIX_OOP_FROM_SMINT(-1);
/* the number of arguments for a block context is local to the block */ /* the number of arguments for a block context is local to the block */
blkctx->nargs = STIX_OOP_FROM_SMINT(nargs); blkctx->method_or_nargs = STIX_OOP_FROM_SMINT(nargs);
/* the number of temporaries here is an accumulated count including /* the number of temporaries here is an accumulated count including
* the number of temporaries of a home context */ * the number of temporaries of a home context */
blkctx->ntmprs = STIX_OOP_FROM_SMINT(ntmprs); blkctx->ntmprs = STIX_OOP_FROM_SMINT(ntmprs);
blkctx->home = rctx; blkctx->home = (stix_oop_t)rctx;
if (((stix_oop_context_t)rctx)->home == stix->_nil) blkctx->receiver_or_source = stix->_nil;
#if 0
if (rctx->home == stix->_nil)
{ {
/* the context that receives the blockCopy message is a method context */ /* the context that receives the blockCopy message is a method context */
STIX_ASSERT (STIX_CLASSOF(stix, rctx) == stix->_context); STIX_ASSERT (STIX_CLASSOF(stix, rctx) == stix->_method_context);
STIX_ASSERT (rctx == (stix_oop_t)stix->active_context); STIX_ASSERT (rctx == (stix_oop_t)stix->active_context);
blkctx->origin = (stix_oop_context_t)rctx; blkctx->origin = (stix_oop_context_t)rctx;
} }
else else
{ {
/* block context is active */ /* a block context is active */
STIX_ASSERT (STIX_CLASSOF(stix, rctx) == stix->_block_context); STIX_ASSERT (STIX_CLASSOF(stix, rctx) == stix->_block_context);
blkctx->origin = ((stix_oop_block_context_t)rctx)->origin; blkctx->origin = ((stix_oop_block_context_t)rctx)->origin;
} }
#else
/* [NOTE]
* the origin of a method context is set to itself
* when it's created. so it's safe to simply copy
* the origin field this way.
*/
blkctx->origin = rctx->origin;
#endif
ACTIVE_STACK_SETTOP (stix, (stix_oop_t)blkctx); ACTIVE_STACK_SETTOP (stix, (stix_oop_t)blkctx);
break; break;
@ -1278,6 +1331,7 @@ printf ("SEND_BLOCK_COPY\n");
handle_return: handle_return:
#if 0
if (stix->active_context->home == stix->_nil) if (stix->active_context->home == stix->_nil)
{ {
/* a method context is active. */ /* a method context is active. */
@ -1288,6 +1342,10 @@ printf ("SEND_BLOCK_COPY\n");
/* a block context is active */ /* a block context is active */
SWITCH_ACTIVE_CONTEXT (stix, (stix_oop_context_t)stix->active_context->origin->sender); SWITCH_ACTIVE_CONTEXT (stix, (stix_oop_context_t)stix->active_context->origin->sender);
} }
#else
SWITCH_ACTIVE_CONTEXT (stix, (stix_oop_context_t)stix->active_context->origin->sender);
#endif
/* push the return value to the stack of the new active context */ /* push the return value to the stack of the new active context */
ACTIVE_STACK_PUSH (stix, return_value); ACTIVE_STACK_PUSH (stix, return_value);
@ -1297,6 +1355,8 @@ printf ("<<LEAVING>>\n");
{ {
/* the sending context of the intial context has been set to nil. /* the sending context of the intial context has been set to nil.
* use this fact to tell an initial context from a normal context. */ * use this fact to tell an initial context from a normal context. */
STIX_ASSERT (stix->active_context->receiver_or_source == stix->_nil);
printf ("<<<RETURNIGN TO THE INITIAL CONTEXT>>>\n"); printf ("<<<RETURNIGN TO THE INITIAL CONTEXT>>>\n");
STIX_ASSERT (stix->sp == 0); STIX_ASSERT (stix->sp == 0);
goto done; goto done;

View File

@ -162,7 +162,8 @@ static stix_uint8_t* scan_new_heap (stix_t* stix, stix_uint8_t* ptr)
stix_oop_oop_t xtmp; stix_oop_oop_t xtmp;
stix_oow_t size; stix_oow_t size;
if (stix->_context && STIX_OBJ_GET_CLASS(oop) == stix->_context) if ((stix->_method_context && STIX_OBJ_GET_CLASS(oop) == stix->_method_context) ||
(stix->_block_context && STIX_OBJ_GET_CLASS(oop) == stix->_block_context))
{ {
/* the stack in the context object doesn't need to be /* the stack in the context object doesn't need to be
* scanned in full. the slots above the stack pointer * scanned in full. the slots above the stack pointer
@ -170,11 +171,6 @@ static stix_uint8_t* scan_new_heap (stix_t* stix, stix_uint8_t* ptr)
size = STIX_CONTEXT_NAMED_INSTVARS + size = STIX_CONTEXT_NAMED_INSTVARS +
STIX_OOP_TO_SMINT(((stix_oop_context_t)oop)->sp) + 1; STIX_OOP_TO_SMINT(((stix_oop_context_t)oop)->sp) + 1;
} }
else if (stix->_block_context && STIX_OBJ_GET_CLASS(oop) == stix->_block_context)
{
size = STIX_BLOCK_CONTEXT_NAMED_INSTVARS +
STIX_OOP_TO_SMINT(((stix_oop_block_context_t)oop)->sp) + 1;
}
else else
{ {
size = STIX_OBJ_GET_SIZE(oop); size = STIX_OBJ_GET_SIZE(oop);
@ -243,7 +239,7 @@ void stix_gc (stix_t* stix)
stix->_method_dictionary = stix_moveoop (stix, stix->_method_dictionary); stix->_method_dictionary = stix_moveoop (stix, stix->_method_dictionary);
stix->_method = stix_moveoop (stix, stix->_method); stix->_method = stix_moveoop (stix, stix->_method);
stix->_association = stix_moveoop (stix, stix->_association); stix->_association = stix_moveoop (stix, stix->_association);
stix->_context = stix_moveoop (stix, stix->_context); stix->_method_context = stix_moveoop (stix, stix->_method_context);
stix->_block_context = stix_moveoop (stix, stix->_block_context); stix->_block_context = stix_moveoop (stix, stix->_block_context);
stix->_true_class = stix_moveoop (stix, stix->_true_class); stix->_true_class = stix_moveoop (stix, stix->_true_class);
stix->_false_class = stix_moveoop (stix, stix->_false_class); stix->_false_class = stix_moveoop (stix, stix->_false_class);
@ -258,6 +254,8 @@ void stix_gc (stix_t* stix)
} }
stix->active_context = (stix_oop_context_t)stix_moveoop (stix, (stix_oop_t)stix->active_context); stix->active_context = (stix_oop_context_t)stix_moveoop (stix, (stix_oop_t)stix->active_context);
stix->active_method = (stix_oop_method_t)stix_moveoop (stix, (stix_oop_t)stix->active_method);
stix->active_code = (stix_oop_byte_t)stix_moveoop (stix, (stix_oop_t)stix->active_code);
for (cb = stix->cblist; cb; cb = cb->next) for (cb = stix->cblist; cb; cb = cb->next)
{ {

View File

@ -129,8 +129,8 @@ static int ignite_1 (stix_t* stix)
stix->_method_dictionary = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(STIX_SET_NAMED_INSTVARS, 0, STIX_OBJ_TYPE_OOP)); stix->_method_dictionary = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(STIX_SET_NAMED_INSTVARS, 0, STIX_OBJ_TYPE_OOP));
stix->_method = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(STIX_METHOD_NAMED_INSTVARS, 1, STIX_OBJ_TYPE_OOP)); stix->_method = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(STIX_METHOD_NAMED_INSTVARS, 1, STIX_OBJ_TYPE_OOP));
stix->_association = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(STIX_ASSOCIATION_NAMED_INSTVARS, 0, STIX_OBJ_TYPE_OOP)); stix->_association = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(STIX_ASSOCIATION_NAMED_INSTVARS, 0, STIX_OBJ_TYPE_OOP));
stix->_context = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(STIX_CONTEXT_NAMED_INSTVARS, 1, STIX_OBJ_TYPE_OOP)); stix->_method_context = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(STIX_CONTEXT_NAMED_INSTVARS, 1, STIX_OBJ_TYPE_OOP));
stix->_block_context = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(STIX_BLOCK_CONTEXT_NAMED_INSTVARS, 1, STIX_OBJ_TYPE_OOP)); stix->_block_context = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(STIX_CONTEXT_NAMED_INSTVARS, 1, STIX_OBJ_TYPE_OOP));
stix->_true_class = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(0, 0, STIX_OBJ_TYPE_OOP)); stix->_true_class = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(0, 0, STIX_OBJ_TYPE_OOP));
stix->_false_class = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(0, 0, STIX_OBJ_TYPE_OOP)); stix->_false_class = alloc_kernel_class (stix, 0, STIX_CLASS_SPEC_MAKE(0, 0, STIX_OBJ_TYPE_OOP));
@ -148,7 +148,7 @@ static int ignite_1 (stix_t* stix)
!stix->_system_dictionary || !stix->_system_dictionary ||
!stix->_method_dictionary || !stix->_method || !stix->_method_dictionary || !stix->_method ||
!stix->_association || !stix->_context || !stix->_association || !stix->_method_context ||
!stix->_block_context || !stix->_block_context ||
!stix->_true_class || !stix->_false_class || !stix->_true_class || !stix->_false_class ||

View File

@ -503,9 +503,12 @@ enum stix_cmdcode_t
CMD_PUSH_LITERAL = 0x3, CMD_PUSH_LITERAL = 0x3,
CMD_STORE_INTO_INSTVAR = 0x4, CMD_STORE_INTO_INSTVAR = 0x4,
CMD_STORE_INTO_TEMPVAR = 0x5, CMD_STORE_INTO_TEMPVAR = 0x5,
/*
CMD_POP_INTO_INSTVAR = 0x6, CMD_POP_INTO_INSTVAR = 0x6,
CMD_POP_INTO_TEMPVAR = 0x7, CMD_POP_INTO_TEMPVAR = 0x7,
CMD_POP_INTO_OBJVAR = 0xXXX,
*/
/* Jump is a single positional instructions. /* Jump is a single positional instructions.
* JJJJJJJJ in the extended format is encoded as a signed offset * JJJJJJJJ in the extended format is encoded as a signed offset
* while JJJJ in the compact format is an unsigned offset. */ * while JJJJ in the compact format is an unsigned offset. */

View File

@ -235,7 +235,7 @@ struct stix_cmgr_t
* MACROS THAT CHANGES THE BEHAVIORS OF THE C COMPILER/LINKER * MACROS THAT CHANGES THE BEHAVIORS OF THE C COMPILER/LINKER
* =========================================================================*/ * =========================================================================*/
#if defined(_WIN32) || defined(__WATCOMC__) #if defined(_WIN32) || (defined(__WATCOMC__) && !defined(__WINDOWS_386__))
# define STIX_IMPORT __declspec(dllimport) # define STIX_IMPORT __declspec(dllimport)
# define STIX_EXPORT __declspec(dllexport) # define STIX_EXPORT __declspec(dllexport)
# define STIX_PRIVATE # define STIX_PRIVATE
@ -301,7 +301,10 @@ enum stix_trait_t
{ {
/* perform no garbage collection when the heap is full. /* perform no garbage collection when the heap is full.
* you still can use stix_gc() explicitly. */ * you still can use stix_gc() explicitly. */
STIX_NOGC = (1 << 0) STIX_NOGC = (1 << 0),
/* no tail call optimization */
STIX_NOTCO = (1 << 1),
}; };
typedef enum stix_trait_t stix_trait_t; typedef enum stix_trait_t stix_trait_t;
@ -604,34 +607,45 @@ struct stix_context_t
{ {
STIX_OBJ_HEADER; STIX_OBJ_HEADER;
stix_oop_t sender; /* message sending context - active context before new context activation*/ /* it points to the active context at the moment when
stix_oop_t ip; /* instruction pointer */ * this context object has been activated. a new method context
* is activated as a result of normal message sending and a block
* context is activated when it is sent 'value'. it's set to
* nil if a block context created haven't received 'value'. */
stix_oop_t sender;
/* SmallInteger, instruction pointer */
stix_oop_t ip;
/* SmallInteger, stack pointer */
stix_oop_t sp; /* stack pointer */ stix_oop_t sp; /* stack pointer */
/* SmallInteger. Number of temporaries.
* For a block context, it's inclusive of the temporaries
* defined its 'home'. */
stix_oop_t ntmprs; /* SmallInteger. */ stix_oop_t ntmprs; /* SmallInteger. */
stix_oop_method_t method; /* CompiledMethod */
stix_oop_t receiver; /* receiver of the message. For a statement '#xxx do: #yyyy', #xxx is the receiver.*/
stix_oop_t home; /* nil */
stix_oop_context_t origin; /* nil */
/* variable indexed part */ /* CompiledMethod for a method context,
stix_oop_t slot[1]; /* stack */ * SmallInteger for a block context */
}; stix_oop_t method_or_nargs;
#define STIX_BLOCK_CONTEXT_NAMED_INSTVARS 8 /* it points to the receiver of the message for a method context.
typedef struct stix_block_context_t stix_block_context_t; * a block context created but not activated has nil in this field.
typedef struct stix_block_context_t* stix_oop_block_context_t; * if a block context is activated by 'value', it points to the
struct stix_block_context_t * block context object used as a base for shallow-copy. */
{ stix_oop_t receiver_or_source;
STIX_OBJ_HEADER;
stix_oop_t caller; /* it is set to nil for a method context.
stix_oop_t ip; /* SmallInteger. instruction pointer */ * for a block context, it points to the active context at the
stix_oop_t sp; /* SmallInteger. stack pointer */ * moment the block context was created. */
stix_oop_t ntmprs; /* SmallInteger. total number of temporaries */ stix_oop_t home;
stix_oop_t nargs; /* SmallInteger */
stix_oop_t unused/*iip*/; /* SmallInteger. initial instruction pointer */ /* when a method context is craeted, it is set to itself.
stix_oop_t home; /* MethodContext or BlockContext */ * no change is made when the method context is activated.
stix_oop_context_t origin; /* MethodContext */ * when a block context is created, it is set to nil.
* when the block context is shallow-copied for activation,
* it is set to the origin of the active context at that moment */
stix_oop_context_t origin;
/* variable indexed part */ /* variable indexed part */
stix_oop_t slot[1]; /* stack */ stix_oop_t slot[1]; /* stack */
@ -724,7 +738,7 @@ struct stix_t
stix_oop_t _method_dictionary; /* MethodDictionary */ stix_oop_t _method_dictionary; /* MethodDictionary */
stix_oop_t _method; /* CompiledMethod */ stix_oop_t _method; /* CompiledMethod */
stix_oop_t _association; /* Association */ stix_oop_t _association; /* Association */
stix_oop_t _context; /* MethodContext */ stix_oop_t _method_context; /* MethodContext */
stix_oop_t _block_context; /* BlockContext */ stix_oop_t _block_context; /* BlockContext */
stix_oop_t _true_class; /* True */ stix_oop_t _true_class; /* True */
@ -740,7 +754,9 @@ struct stix_t
stix_oow_t tmp_count; stix_oow_t tmp_count;
/* == EXECUTION REGISTERS == */ /* == EXECUTION REGISTERS == */
stix_oop_context_t active_context; /* TODO: this could be either MethodContext or BlockContext. Some redefintion of stix_oop_context_t might be needed after having removed stix-oop_block-context. */ stix_oop_context_t active_context;
stix_oop_method_t active_method;
stix_oop_byte_t active_code;
stix_ooi_t sp; stix_ooi_t sp;
stix_ooi_t ip; stix_ooi_t ip;
/* == END EXECUTION REGISTERS == */ /* == END EXECUTION REGISTERS == */