fixed a parameter range check bug in a compiler.
fixed a wrong goto label location for send_message
This commit is contained in:
parent
649a78472b
commit
fff2af4762
@ -198,10 +198,28 @@
|
|||||||
|
|
||||||
#class(#liword) LargePositiveInteger(LargeInteger)
|
#class(#liword) LargePositiveInteger(LargeInteger)
|
||||||
{
|
{
|
||||||
|
#method abs
|
||||||
|
{
|
||||||
|
^self.
|
||||||
|
}
|
||||||
|
|
||||||
|
#method sign
|
||||||
|
{
|
||||||
|
^1.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#class(#liword) LargeNegativeInteger(LargeInteger)
|
#class(#liword) LargeNegativeInteger(LargeInteger)
|
||||||
{
|
{
|
||||||
|
#method abs
|
||||||
|
{
|
||||||
|
^self negated.
|
||||||
|
}
|
||||||
|
|
||||||
|
#method sign
|
||||||
|
{
|
||||||
|
^-1.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -229,6 +229,19 @@
|
|||||||
<primitive: #snd_open>
|
<primitive: #snd_open>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#method(#class) a: a b: b c: c
|
||||||
|
{
|
||||||
|
c dump.
|
||||||
|
}
|
||||||
|
|
||||||
|
#method(#class) a: a b: b c: c d: d e: e f: f g: g h: h
|
||||||
|
{
|
||||||
|
h dump.
|
||||||
|
}
|
||||||
|
#method(#class) a: a b: b c: c d: d e: e f: f g: g
|
||||||
|
{
|
||||||
|
g dump.
|
||||||
|
}
|
||||||
#method(#class) main
|
#method(#class) main
|
||||||
{
|
{
|
||||||
"
|
"
|
||||||
@ -392,6 +405,8 @@ PROCESS TESTING
|
|||||||
(2r1000000000000000000000000000100000000000000000000000000000000000000000000000 bitAt: 129) dump.
|
(2r1000000000000000000000000000100000000000000000000000000000000000000000000000 bitAt: 129) dump.
|
||||||
(2r1000000000000000000000000000100000000000000000000000000000000000000000000000 bitAt: 16rFFFFFFFFFFFFFFFF1) dump.
|
(2r1000000000000000000000000000100000000000000000000000000000000000000000000000 bitAt: 16rFFFFFFFFFFFFFFFF1) dump.
|
||||||
|
|
||||||
|
##self a: 1 b: 2 c: 3 d: 4 e: 5 f: 6 g: 7.
|
||||||
|
##self a: 1 b: 2 c: 3.
|
||||||
"
|
"
|
||||||
FFI isNil dump.
|
FFI isNil dump.
|
||||||
FFI notNil dump.
|
FFI notNil dump.
|
||||||
|
@ -1659,6 +1659,7 @@ static int emit_single_param_instruction (stix_t* stix, int cmd, stix_oow_t para
|
|||||||
case BCODE_PUSH_LITERAL_0:
|
case BCODE_PUSH_LITERAL_0:
|
||||||
if (param_1 < 8)
|
if (param_1 < 8)
|
||||||
{
|
{
|
||||||
|
/* low 3 bits to hold the parameter */
|
||||||
bc = (stix_oob_t)(cmd & 0xF8) | (stix_oob_t)param_1;
|
bc = (stix_oob_t)(cmd & 0xF8) | (stix_oob_t)param_1;
|
||||||
goto write_short;
|
goto write_short;
|
||||||
}
|
}
|
||||||
@ -1678,6 +1679,7 @@ static int emit_single_param_instruction (stix_t* stix, int cmd, stix_oow_t para
|
|||||||
case BCODE_JUMP_IF_FALSE_0:
|
case BCODE_JUMP_IF_FALSE_0:
|
||||||
if (param_1 < 4)
|
if (param_1 < 4)
|
||||||
{
|
{
|
||||||
|
/* low 2 bits to hold the parameter */
|
||||||
bc = (stix_oob_t)(cmd & 0xFC) | (stix_oob_t)param_1;
|
bc = (stix_oob_t)(cmd & 0xFC) | (stix_oob_t)param_1;
|
||||||
goto write_short;
|
goto write_short;
|
||||||
}
|
}
|
||||||
@ -1730,7 +1732,7 @@ static int emit_double_param_instruction (stix_t* stix, int cmd, stix_oow_t para
|
|||||||
case BCODE_POP_INTO_OBJVAR_0:
|
case BCODE_POP_INTO_OBJVAR_0:
|
||||||
case BCODE_SEND_MESSAGE_0:
|
case BCODE_SEND_MESSAGE_0:
|
||||||
case BCODE_SEND_MESSAGE_TO_SUPER_0:
|
case BCODE_SEND_MESSAGE_TO_SUPER_0:
|
||||||
if (param_1 < 8 && param_2 < 0xFF)
|
if (param_1 < 4 && param_2 < 0xFF)
|
||||||
{
|
{
|
||||||
/* low 2 bits of the instruction code is the first parameter */
|
/* low 2 bits of the instruction code is the first parameter */
|
||||||
bc = (stix_oob_t)(cmd & 0xFC) | (stix_oob_t)param_1;
|
bc = (stix_oob_t)(cmd & 0xFC) | (stix_oob_t)param_1;
|
||||||
|
379
stix/lib/exec.c
379
stix/lib/exec.c
@ -2034,6 +2034,195 @@ done:
|
|||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
static int send_message (stix_t* stix, stix_oop_char_t selector, int to_super, stix_ooi_t nargs)
|
||||||
|
{
|
||||||
|
stix_oocs_t mthname;
|
||||||
|
stix_oop_t receiver;
|
||||||
|
stix_oop_method_t method;
|
||||||
|
stix_ooi_t preamble, preamble_code;
|
||||||
|
|
||||||
|
STIX_ASSERT (STIX_OOP_IS_POINTER(selector));
|
||||||
|
STIX_ASSERT (STIX_OBJ_GET_FLAGS_TYPE(selector) == STIX_OBJ_TYPE_CHAR);
|
||||||
|
STIX_ASSERT (STIX_CLASSOF(stix, selector) == stix->_symbol);
|
||||||
|
|
||||||
|
receiver = ACTIVE_STACK_GET(stix, stix->sp - nargs);
|
||||||
|
#if defined(STIX_DEBUG_EXEC)
|
||||||
|
printf (" RECEIVER = ");
|
||||||
|
print_object(stix, receiver);
|
||||||
|
printf ("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mthname.ptr = selector->slot;
|
||||||
|
mthname.len = STIX_OBJ_GET_SIZE(selector);
|
||||||
|
method = find_method (stix, receiver, &mthname, to_super);
|
||||||
|
if (!method)
|
||||||
|
{
|
||||||
|
/* TODO: implement doesNotUnderstand: XXXXX instead of returning -1. */
|
||||||
|
stix_oop_t c;
|
||||||
|
|
||||||
|
c = STIX_CLASSOF(stix,receiver);
|
||||||
|
printf ("ERROR [NOT IMPLEMENTED YET] - receiver [");
|
||||||
|
print_object (stix, receiver);
|
||||||
|
printf ("] class ");
|
||||||
|
print_object (stix, c);
|
||||||
|
printf (" doesNotUnderstand: [");
|
||||||
|
print_oocs (&mthname);
|
||||||
|
printf ("]\n");
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
STIX_ASSERT (STIX_OOP_TO_SMOOI(method->tmpr_nargs) == nargs);
|
||||||
|
|
||||||
|
preamble = STIX_OOP_TO_SMOOI(method->preamble);
|
||||||
|
preamble_code = STIX_METHOD_GET_PREAMBLE_CODE(preamble);
|
||||||
|
switch (preamble_code)
|
||||||
|
{
|
||||||
|
case STIX_METHOD_PREAMBLE_RETURN_RECEIVER:
|
||||||
|
DBGOUT_EXEC_0 ("METHOD_PREAMBLE_RETURN_RECEIVER");
|
||||||
|
ACTIVE_STACK_POPS (stix, nargs); /* pop arguments only*/
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STIX_METHOD_PREAMBLE_RETURN_NIL:
|
||||||
|
DBGOUT_EXEC_0 ("METHOD_PREAMBLE_RETURN_NIL");
|
||||||
|
ACTIVE_STACK_POPS (stix, nargs);
|
||||||
|
ACTIVE_STACK_SETTOP (stix, stix->_nil);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STIX_METHOD_PREAMBLE_RETURN_TRUE:
|
||||||
|
DBGOUT_EXEC_0 ("METHOD_PREAMBLE_RETURN_TRUE");
|
||||||
|
ACTIVE_STACK_POPS (stix, nargs);
|
||||||
|
ACTIVE_STACK_SETTOP (stix, stix->_true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STIX_METHOD_PREAMBLE_RETURN_FALSE:
|
||||||
|
DBGOUT_EXEC_0 ("METHOD_PREAMBLE_RETURN_FALSE");
|
||||||
|
ACTIVE_STACK_POPS (stix, nargs);
|
||||||
|
ACTIVE_STACK_SETTOP (stix, stix->_false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STIX_METHOD_PREAMBLE_RETURN_INDEX:
|
||||||
|
DBGOUT_EXEC_1 ("METHOD_PREAMBLE_RETURN_INDEX %d", (int)STIX_METHOD_GET_PREAMBLE_INDEX(preamble));
|
||||||
|
ACTIVE_STACK_POPS (stix, nargs);
|
||||||
|
ACTIVE_STACK_SETTOP (stix, STIX_SMOOI_TO_OOP(STIX_METHOD_GET_PREAMBLE_INDEX(preamble)));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STIX_METHOD_PREAMBLE_RETURN_NEGINDEX:
|
||||||
|
DBGOUT_EXEC_1 ("METHOD_PREAMBLE_RETURN_NEGINDEX %d", (int)STIX_METHOD_GET_PREAMBLE_INDEX(preamble));
|
||||||
|
ACTIVE_STACK_POPS (stix, nargs);
|
||||||
|
ACTIVE_STACK_SETTOP (stix, STIX_SMOOI_TO_OOP(-STIX_METHOD_GET_PREAMBLE_INDEX(preamble)));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STIX_METHOD_PREAMBLE_RETURN_INSTVAR:
|
||||||
|
{
|
||||||
|
stix_oop_oop_t rcv;
|
||||||
|
|
||||||
|
ACTIVE_STACK_POPS (stix, nargs); /* pop arguments only */
|
||||||
|
|
||||||
|
DBGOUT_EXEC_1 ("METHOD_PREAMBLE_RETURN_INSTVAR %d", (int)STIX_METHOD_GET_PREAMBLE_INDEX(preamble));
|
||||||
|
|
||||||
|
/* replace the receiver by an instance variable of the receiver */
|
||||||
|
rcv = (stix_oop_oop_t)ACTIVE_STACK_GETTOP(stix);
|
||||||
|
STIX_ASSERT (STIX_OBJ_GET_FLAGS_TYPE(rcv) == STIX_OBJ_TYPE_OOP);
|
||||||
|
STIX_ASSERT (STIX_OBJ_GET_SIZE(rcv) > STIX_METHOD_GET_PREAMBLE_INDEX(preamble));
|
||||||
|
|
||||||
|
if (rcv == (stix_oop_oop_t)stix->active_context)
|
||||||
|
{
|
||||||
|
/* the active context object doesn't keep
|
||||||
|
* the most up-to-date information in the
|
||||||
|
* 'ip' and 'sp' field. commit these fields
|
||||||
|
* when the object to be accessed is
|
||||||
|
* the active context. this manual commit
|
||||||
|
* is required because this premable handling
|
||||||
|
* skips activation of a new method context
|
||||||
|
* that would commit these fields.
|
||||||
|
*/
|
||||||
|
STORE_ACTIVE_IP (stix);
|
||||||
|
STORE_ACTIVE_SP (stix);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this accesses the instance variable of the receiver */
|
||||||
|
ACTIVE_STACK_SET (stix, stix->sp, rcv->slot[STIX_METHOD_GET_PREAMBLE_INDEX(preamble)]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
case STIX_METHOD_PREAMBLE_PRIMITIVE:
|
||||||
|
{
|
||||||
|
stix_ooi_t prim_no;
|
||||||
|
|
||||||
|
prim_no = STIX_METHOD_GET_PREAMBLE_INDEX(preamble);
|
||||||
|
DBGOUT_EXEC_1 ("METHOD_PREAMBLE_PRIMITIVE %d", (int)prim_no);
|
||||||
|
|
||||||
|
if (prim_no >= 0 && prim_no < STIX_COUNTOF(primitives) &&
|
||||||
|
(primitives[prim_no].nargs < 0 || primitives[prim_no].nargs == nargs))
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
stix_pushtmp (stix, (stix_oop_t*)&method);
|
||||||
|
n = primitives[prim_no].handler (stix, nargs);
|
||||||
|
stix_poptmp (stix);
|
||||||
|
if (n <= -1) return -1; /* hard primitive failure */
|
||||||
|
if (n >= 1) break; /* primitive ok */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* soft primitive failure */
|
||||||
|
if (activate_new_method (stix, method) <= -1) return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case STIX_METHOD_PREAMBLE_NAMED_PRIMITIVE:
|
||||||
|
{
|
||||||
|
stix_ooi_t prim_name_index;
|
||||||
|
stix_oop_t name;
|
||||||
|
stix_prim_impl_t handler;
|
||||||
|
register stix_oow_t w;
|
||||||
|
|
||||||
|
prim_name_index = STIX_METHOD_GET_PREAMBLE_INDEX(preamble);
|
||||||
|
DBGOUT_EXEC_1 ("METHOD_PREAMBLE_NAMED_PRIMITIVE %d", (int)prim_name_index);
|
||||||
|
|
||||||
|
name = method->slot[prim_name_index];
|
||||||
|
|
||||||
|
STIX_ASSERT (STIX_ISTYPEOF(stix,name,STIX_OBJ_TYPE_CHAR));
|
||||||
|
STIX_ASSERT (STIX_OBJ_GET_FLAGS_EXTRA(name));
|
||||||
|
STIX_ASSERT (STIX_CLASSOF(stix,name) == stix->_symbol);
|
||||||
|
|
||||||
|
/* merge two SmallIntegers to get a full pointer */
|
||||||
|
w = (stix_oow_t)STIX_OOP_TO_SMOOI(method->preamble_data[0]) << (STIX_OOW_BITS / 2) |
|
||||||
|
(stix_oow_t)STIX_OOP_TO_SMOOI(method->preamble_data[1]);
|
||||||
|
handler = (stix_prim_impl_t)w;
|
||||||
|
if (!handler) handler = query_prim_module (stix, ((stix_oop_char_t)name)->slot, STIX_OBJ_GET_SIZE(name));
|
||||||
|
|
||||||
|
if (handler)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
/* split a pointer to two OOP fields as SmallIntegers for storing. */
|
||||||
|
method->preamble_data[0] = STIX_SMOOI_TO_OOP((stix_oow_t)handler >> (STIX_OOW_BITS / 2));
|
||||||
|
method->preamble_data[1] = STIX_SMOOI_TO_OOP((stix_oow_t)handler & STIX_LBMASK(stix_oow_t, STIX_OOW_BITS / 2));
|
||||||
|
|
||||||
|
stix_pushtmp (stix, (stix_oop_t*)&method);
|
||||||
|
n = handler (stix, nargs);
|
||||||
|
stix_poptmp (stix);
|
||||||
|
if (n <= -1) return -1; /* hard primitive failure */
|
||||||
|
if (n >= 1) break; /* primitive ok*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/* soft primitive failure or handler not found*/
|
||||||
|
if (activate_new_method (stix, method) <= -1) return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
STIX_ASSERT (preamble_code == STIX_METHOD_PREAMBLE_NONE);
|
||||||
|
if (activate_new_method (stix, method) <= -1) return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
int stix_execute (stix_t* stix)
|
int stix_execute (stix_t* stix)
|
||||||
@ -2501,6 +2690,8 @@ printf ("\n");
|
|||||||
/* -------------------------------------------------------- */
|
/* -------------------------------------------------------- */
|
||||||
case BCODE_SEND_MESSAGE_X:
|
case BCODE_SEND_MESSAGE_X:
|
||||||
case BCODE_SEND_MESSAGE_TO_SUPER_X:
|
case BCODE_SEND_MESSAGE_TO_SUPER_X:
|
||||||
|
/* b1 -> number of arguments
|
||||||
|
* b2 -> selector index stored in the literal frame */
|
||||||
FETCH_PARAM_CODE_TO (stix, b1);
|
FETCH_PARAM_CODE_TO (stix, b1);
|
||||||
FETCH_PARAM_CODE_TO (stix, b2);
|
FETCH_PARAM_CODE_TO (stix, b2);
|
||||||
goto handle_send_message;
|
goto handle_send_message;
|
||||||
@ -2514,205 +2705,21 @@ printf ("\n");
|
|||||||
case BCODE_SEND_MESSAGE_TO_SUPER_2:
|
case BCODE_SEND_MESSAGE_TO_SUPER_2:
|
||||||
case BCODE_SEND_MESSAGE_TO_SUPER_3:
|
case BCODE_SEND_MESSAGE_TO_SUPER_3:
|
||||||
{
|
{
|
||||||
/* b1 -> number of arguments
|
|
||||||
* b2 -> index to the selector stored in the literal frame
|
|
||||||
*/
|
|
||||||
stix_oocs_t mthname;
|
|
||||||
stix_oop_t newrcv;
|
|
||||||
stix_oop_method_t newmth;
|
|
||||||
stix_oop_char_t selector;
|
stix_oop_char_t selector;
|
||||||
stix_ooi_t preamble, preamble_code;
|
|
||||||
|
|
||||||
|
|
||||||
handle_send_message:
|
|
||||||
b1 = bcode & 0x3; /* low 2 bits */
|
b1 = bcode & 0x3; /* low 2 bits */
|
||||||
FETCH_BYTE_CODE_TO (stix, b2);
|
FETCH_BYTE_CODE_TO (stix, b2);
|
||||||
|
|
||||||
|
handle_send_message:
|
||||||
/* get the selector from the literal frame */
|
/* get the selector from the literal frame */
|
||||||
selector = (stix_oop_char_t)stix->active_method->slot[b2];
|
selector = (stix_oop_char_t)stix->active_method->slot[b2];
|
||||||
|
|
||||||
|
|
||||||
#if defined(STIX_DEBUG_EXEC)
|
#if defined(STIX_DEBUG_EXEC)
|
||||||
printf ("SEND_MESSAGE%s TO RECEIVER AT STACKPOS=%d NARGS=%d SELECTOR=", (((bcode >> 2) & 1)? "_TO_SUPER": ""), (int)(stix->sp - b1), (int)b1);
|
printf ("SEND_MESSAGE%s TO RECEIVER AT STACKPOS=%d NARGS=%d SELECTOR=", (((bcode >> 2) & 1)? "_TO_SUPER": ""), (int)(stix->sp - b1), (int)b1);
|
||||||
print_object (stix, (stix_oop_t)selector);
|
print_object (stix, (stix_oop_t)selector);
|
||||||
fflush (stdout);
|
fflush (stdout);
|
||||||
#endif
|
#endif
|
||||||
STIX_ASSERT (STIX_CLASSOF(stix, selector) == stix->_symbol);
|
if (send_message (stix, selector, ((bcode >> 2) & 1), b1) <= -1) goto oops;
|
||||||
newrcv = ACTIVE_STACK_GET(stix, stix->sp - b1);
|
|
||||||
|
|
||||||
#if defined(STIX_DEBUG_EXEC)
|
|
||||||
printf (" RECEIVER = ");
|
|
||||||
print_object(stix, newrcv);
|
|
||||||
printf ("\n");
|
|
||||||
#endif
|
|
||||||
mthname.ptr = selector->slot;
|
|
||||||
mthname.len = STIX_OBJ_GET_SIZE(selector);
|
|
||||||
newmth = find_method (stix, newrcv, &mthname, ((bcode >> 2) & 1));
|
|
||||||
if (!newmth)
|
|
||||||
{
|
|
||||||
/* TODO: implement doesNotUnderstand: XXXXX instead of returning -1. */
|
|
||||||
stix_oop_t c;
|
|
||||||
|
|
||||||
c = STIX_CLASSOF(stix,newrcv);
|
|
||||||
|
|
||||||
printf ("ERROR [NOT IMPLEMENTED YET] - receiver [");
|
|
||||||
print_object (stix, newrcv);
|
|
||||||
printf ("] class ");
|
|
||||||
print_object (stix, c);
|
|
||||||
printf (" doesNotUnderstand: [");
|
|
||||||
print_oocs (&mthname);
|
|
||||||
printf ("]\n");
|
|
||||||
goto oops;
|
|
||||||
}
|
|
||||||
|
|
||||||
STIX_ASSERT (STIX_OOP_TO_SMOOI(newmth->tmpr_nargs) == b1);
|
|
||||||
|
|
||||||
preamble = STIX_OOP_TO_SMOOI(newmth->preamble);
|
|
||||||
preamble_code = STIX_METHOD_GET_PREAMBLE_CODE(preamble);
|
|
||||||
switch (preamble_code)
|
|
||||||
{
|
|
||||||
case STIX_METHOD_PREAMBLE_RETURN_RECEIVER:
|
|
||||||
DBGOUT_EXEC_0 ("METHOD_PREAMBLE_RETURN_RECEIVER");
|
|
||||||
ACTIVE_STACK_POPS (stix, b1); /* pop arguments only*/
|
|
||||||
break;
|
|
||||||
|
|
||||||
case STIX_METHOD_PREAMBLE_RETURN_NIL:
|
|
||||||
DBGOUT_EXEC_0 ("METHOD_PREAMBLE_RETURN_NIL");
|
|
||||||
ACTIVE_STACK_POPS (stix, b1);
|
|
||||||
ACTIVE_STACK_SETTOP (stix, stix->_nil);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case STIX_METHOD_PREAMBLE_RETURN_TRUE:
|
|
||||||
DBGOUT_EXEC_0 ("METHOD_PREAMBLE_RETURN_TRUE");
|
|
||||||
ACTIVE_STACK_POPS (stix, b1);
|
|
||||||
ACTIVE_STACK_SETTOP (stix, stix->_true);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case STIX_METHOD_PREAMBLE_RETURN_FALSE:
|
|
||||||
DBGOUT_EXEC_0 ("METHOD_PREAMBLE_RETURN_FALSE");
|
|
||||||
ACTIVE_STACK_POPS (stix, b1);
|
|
||||||
ACTIVE_STACK_SETTOP (stix, stix->_false);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case STIX_METHOD_PREAMBLE_RETURN_INDEX:
|
|
||||||
DBGOUT_EXEC_1 ("METHOD_PREAMBLE_RETURN_INDEX %d", (int)STIX_METHOD_GET_PREAMBLE_INDEX(preamble));
|
|
||||||
ACTIVE_STACK_POPS (stix, b1);
|
|
||||||
ACTIVE_STACK_SETTOP (stix, STIX_SMOOI_TO_OOP(STIX_METHOD_GET_PREAMBLE_INDEX(preamble)));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case STIX_METHOD_PREAMBLE_RETURN_NEGINDEX:
|
|
||||||
DBGOUT_EXEC_1 ("METHOD_PREAMBLE_RETURN_NEGINDEX %d", (int)STIX_METHOD_GET_PREAMBLE_INDEX(preamble));
|
|
||||||
ACTIVE_STACK_POPS (stix, b1);
|
|
||||||
ACTIVE_STACK_SETTOP (stix, STIX_SMOOI_TO_OOP(-STIX_METHOD_GET_PREAMBLE_INDEX(preamble)));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case STIX_METHOD_PREAMBLE_RETURN_INSTVAR:
|
|
||||||
{
|
|
||||||
stix_oop_oop_t rcv;
|
|
||||||
|
|
||||||
ACTIVE_STACK_POPS (stix, b1); /* pop arguments only */
|
|
||||||
|
|
||||||
DBGOUT_EXEC_1 ("METHOD_PREAMBLE_RETURN_INSTVAR %d", (int)STIX_METHOD_GET_PREAMBLE_INDEX(preamble));
|
|
||||||
|
|
||||||
/* replace the receiver by an instance variable of the receiver */
|
|
||||||
rcv = (stix_oop_oop_t)ACTIVE_STACK_GETTOP(stix);
|
|
||||||
STIX_ASSERT (STIX_OBJ_GET_FLAGS_TYPE(rcv) == STIX_OBJ_TYPE_OOP);
|
|
||||||
STIX_ASSERT (STIX_OBJ_GET_SIZE(rcv) > STIX_METHOD_GET_PREAMBLE_INDEX(preamble));
|
|
||||||
|
|
||||||
if (rcv == (stix_oop_oop_t)stix->active_context)
|
|
||||||
{
|
|
||||||
/* the active context object doesn't keep
|
|
||||||
* the most up-to-date information in the
|
|
||||||
* 'ip' and 'sp' field. commit these fields
|
|
||||||
* when the object to be accessed is
|
|
||||||
* the active context. this manual commit
|
|
||||||
* is required because this premable handling
|
|
||||||
* skips activation of a new method context
|
|
||||||
* that would commit these fields.
|
|
||||||
*/
|
|
||||||
STORE_ACTIVE_IP (stix);
|
|
||||||
STORE_ACTIVE_SP (stix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this accesses the instance variable of the receiver */
|
|
||||||
ACTIVE_STACK_SET (stix, stix->sp, rcv->slot[STIX_METHOD_GET_PREAMBLE_INDEX(preamble)]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
case STIX_METHOD_PREAMBLE_PRIMITIVE:
|
|
||||||
{
|
|
||||||
stix_ooi_t prim_no;
|
|
||||||
|
|
||||||
prim_no = STIX_METHOD_GET_PREAMBLE_INDEX(preamble);
|
|
||||||
DBGOUT_EXEC_1 ("METHOD_PREAMBLE_PRIMITIVE %d", (int)prim_no);
|
|
||||||
|
|
||||||
if (prim_no >= 0 && prim_no < STIX_COUNTOF(primitives) &&
|
|
||||||
(primitives[prim_no].nargs < 0 || primitives[prim_no].nargs == b1))
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
|
|
||||||
stix_pushtmp (stix, (stix_oop_t*)&newmth);
|
|
||||||
n = primitives[prim_no].handler (stix, b1);
|
|
||||||
stix_poptmp (stix);
|
|
||||||
if (n <= -1) goto oops;
|
|
||||||
if (n >= 1) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* primitive handler failed */
|
|
||||||
if (activate_new_method (stix, newmth) <= -1) goto oops;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case STIX_METHOD_PREAMBLE_NAMED_PRIMITIVE:
|
|
||||||
{
|
|
||||||
stix_ooi_t prim_name_index;
|
|
||||||
stix_oop_t name;
|
|
||||||
stix_prim_impl_t handler;
|
|
||||||
register stix_oow_t w;
|
|
||||||
|
|
||||||
prim_name_index = STIX_METHOD_GET_PREAMBLE_INDEX(preamble);
|
|
||||||
DBGOUT_EXEC_1 ("METHOD_PREAMBLE_NAMED_PRIMITIVE %d", (int)prim_name_index);
|
|
||||||
|
|
||||||
name = newmth->slot[prim_name_index];
|
|
||||||
|
|
||||||
STIX_ASSERT (STIX_ISTYPEOF(stix,name,STIX_OBJ_TYPE_CHAR));
|
|
||||||
STIX_ASSERT (STIX_OBJ_GET_FLAGS_EXTRA(name));
|
|
||||||
STIX_ASSERT (STIX_CLASSOF(stix,name) == stix->_symbol);
|
|
||||||
|
|
||||||
/* merge two SmallIntegers to get a full pointer */
|
|
||||||
w = (stix_oow_t)STIX_OOP_TO_SMOOI(newmth->preamble_data[0]) << (STIX_OOW_BITS / 2) |
|
|
||||||
(stix_oow_t)STIX_OOP_TO_SMOOI(newmth->preamble_data[1]);
|
|
||||||
handler = (stix_prim_impl_t)w;
|
|
||||||
if (!handler) handler = query_prim_module (stix, ((stix_oop_char_t)name)->slot, STIX_OBJ_GET_SIZE(name));
|
|
||||||
|
|
||||||
if (handler)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
|
|
||||||
/* split a pointer to two OOP fields as SmallIntegers for storing. */
|
|
||||||
newmth->preamble_data[0] = STIX_SMOOI_TO_OOP((stix_oow_t)handler >> (STIX_OOW_BITS / 2));
|
|
||||||
newmth->preamble_data[1] = STIX_SMOOI_TO_OOP((stix_oow_t)handler & STIX_LBMASK(stix_oow_t, STIX_OOW_BITS / 2));
|
|
||||||
|
|
||||||
stix_pushtmp (stix, (stix_oop_t*)&newmth);
|
|
||||||
n = handler (stix, b1);
|
|
||||||
stix_poptmp (stix);
|
|
||||||
if (n <= -1) goto oops;
|
|
||||||
if (n >= 1) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* primitive handler failed or not found*/
|
|
||||||
if (activate_new_method (stix, newmth) <= -1) goto oops;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
STIX_ASSERT (preamble_code == STIX_METHOD_PREAMBLE_NONE);
|
|
||||||
if (activate_new_method (stix, newmth) <= -1) goto oops;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
break; /* CMD_SEND_MESSAGE */
|
break; /* CMD_SEND_MESSAGE */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user