added JUMP2_FORWARD and JUMP2_BACKWARD

This commit is contained in:
hyunghwan.chung 2015-07-01 07:21:54 +00:00
parent 2d2039f4a5
commit d6a9ca91fa
4 changed files with 209 additions and 504 deletions

View File

@ -1499,7 +1499,6 @@ static int emit_single_param_instruction (stix_t* stix, int cmd, stix_oow_t para
case BCODE_JUMP_BACKWARD_0:
case BCODE_JUMP_IF_TRUE_0:
case BCODE_JUMP_IF_FALSE_0:
case BCODE_JUMP_BY_OFFSET_0:
if (param_1 < 4)
{
bc = (stix_byte_t)(cmd & 0xFC) | (stix_byte_t)param_1;
@ -1511,6 +1510,11 @@ static int emit_single_param_instruction (stix_t* stix, int cmd, stix_oow_t para
bc = cmd | 0x80;
goto write_long;
}
case BCODE_JUMP2_FORWARD:
case BCODE_JUMP2_BACKWARD:
bc = cmd;
goto write_long;
}
stix->errnum = STIX_EINVAL;
@ -2503,21 +2507,35 @@ printf ("\treturn_from_block\n");
}
block_code_size = stix->c->mth.code.len - jump_inst_pos - (STIX_BCODE_LONG_PARAM_SIZE + 1);
if (block_code_size > MAX_CODE_BLKCODE)
if (block_code_size > MAX_CODE_JUMP * 2)
{
/* TOOD: increate the max block code size and
* if it exceedes the limit for BCODE_JUMP_FORWARD_X, switch to BECODE_JUMP_BY_OFFSET */
set_syntax_error (stix, STIX_SYNERR_BLKFLOOD, &block_loc, STIX_NULL);
return -1;
}
else
{
stix_size_t jump_offset;
if (block_code_size > MAX_CODE_JUMP)
{
printf ("\tfixed jump to jump2\n");
stix->c->mth.code.ptr[jump_inst_pos] = BCODE_JUMP2_FORWARD;
jump_offset = block_code_size - MAX_CODE_JUMP;
}
else
{
jump_offset = block_code_size;
}
printf ("\tfixed jump offset to %u\n", (unsigned int)jump_offset);
/* note that the jump offset is a signed number */
#if (STIX_BCODE_LONG_PARAM_SIZE == 2)
stix->c->mth.code.ptr[jump_inst_pos + 1] = block_code_size >> 8;
stix->c->mth.code.ptr[jump_inst_pos + 2] = ((stix_int16_t)block_code_size & 0xFF);
stix->c->mth.code.ptr[jump_inst_pos + 1] = jump_offset >> 8;
stix->c->mth.code.ptr[jump_inst_pos + 2] = jump_offset & 0xFF;
#else
stix->c->mth.code.ptr[jump_inst_pos + 1] = block_code_size ;
stix->c->mth.code.ptr[jump_inst_pos + 1] = jump_offset;
#endif
}
/* restore the temporary count */
stix->c->mth.tmprs.len = saved_tmprs_len;

View File

@ -728,6 +728,58 @@ static int primitive_integer_sub (stix_t* stix, stix_ooi_t nargs)
return 0;
}
static int primitive_integer_mul (stix_t* stix, stix_ooi_t nargs)
{
stix_ooi_t tmp;
stix_oop_t rcv, arg;
STIX_ASSERT (nargs == 1);
rcv = ACTIVE_STACK_GET(stix, stix->sp - 1);
arg = ACTIVE_STACK_GET(stix, stix->sp);
if (STIX_OOP_IS_SMINT(rcv) && STIX_OOP_IS_SMINT(arg))
{
tmp = STIX_OOP_TO_SMINT(rcv) * STIX_OOP_TO_SMINT(arg);
/* TODO: check overflow. if so convert it to LargeInteger */
ACTIVE_STACK_POP (stix);
ACTIVE_STACK_SETTOP (stix, STIX_OOP_FROM_SMINT(tmp));
return 1;
}
/* TODO: handle LargeInteger */
return 0;
}
static int primitive_integer_eq (stix_t* stix, stix_ooi_t nargs)
{
stix_oop_t rcv, arg;
STIX_ASSERT (nargs == 1);
rcv = ACTIVE_STACK_GET(stix, stix->sp - 1);
arg = ACTIVE_STACK_GET(stix, stix->sp);
if (STIX_OOP_IS_SMINT(rcv) && STIX_OOP_IS_SMINT(arg))
{
ACTIVE_STACK_POP (stix);
if (STIX_OOP_TO_SMINT(rcv) < STIX_OOP_TO_SMINT(arg))
{
ACTIVE_STACK_SETTOP (stix, stix->_true);
}
else
{
ACTIVE_STACK_SETTOP (stix, stix->_false);
}
return 1;
}
/* TODO: handle LargeInteger */
return 0;
}
static int primitive_integer_lt (stix_t* stix, stix_ooi_t nargs)
{
stix_oop_t rcv, arg;
@ -796,17 +848,19 @@ typedef struct primitive_t primitive_t;
static primitive_t primitives[] =
{
{ -1, primitive_dump },
{ 0, primitive_new },
{ 1, primitive_new_with_size },
{ 0, primitive_basic_size },
{ 1, primitive_basic_at },
{ 2, primitive_basic_at_put },
{ -1, primitive_block_context_value },
{ 1, primitive_integer_add },
{ 1, primitive_integer_sub },
{ 1, primitive_integer_lt },
{ 1, primitive_integer_gt }
{ -1, primitive_dump }, /* 0 */
{ 0, primitive_new }, /* 1 */
{ 1, primitive_new_with_size }, /* 2 */
{ 0, primitive_basic_size }, /* 3 */
{ 1, primitive_basic_at }, /* 4 */
{ 2, primitive_basic_at_put }, /* 5 */
{ -1, primitive_block_context_value }, /* 6 */
{ 1, primitive_integer_add }, /* 7 */
{ 1, primitive_integer_sub }, /* 8 */
{ 1, primitive_integer_mul }, /* 9 */
{ 1, primitive_integer_eq }, /* 10 */
{ 1, primitive_integer_lt }, /* 11 */
{ 1, primitive_integer_gt } /* 12 */
};
@ -1127,7 +1181,6 @@ printf ("JUMP_BACKWARD %d\n", (int)(bcode & 0x3));
case BCODE_JUMP_IF_TRUE_X:
case BCODE_JUMP_IF_FALSE_X:
case BCODE_JUMP_BY_OFFSET_X:
case BCODE_JUMP_IF_TRUE_0:
case BCODE_JUMP_IF_TRUE_1:
case BCODE_JUMP_IF_TRUE_2:
@ -1136,13 +1189,21 @@ printf ("JUMP_BACKWARD %d\n", (int)(bcode & 0x3));
case BCODE_JUMP_IF_FALSE_1:
case BCODE_JUMP_IF_FALSE_2:
case BCODE_JUMP_IF_FALSE_3:
case BCODE_JUMP_BY_OFFSET_0:
case BCODE_JUMP_BY_OFFSET_1:
case BCODE_JUMP_BY_OFFSET_2:
case BCODE_JUMP_BY_OFFSET_3:
printf ("<<<<<<<<<<<<<< JUMP NOT IMPLEMENTED YET >>>>>>>>>>>> \n");
stix->errnum = STIX_ENOIMPL;
return -1;
case BCODE_JUMP2_FORWARD:
FETCH_PARAM_CODE_TO (stix, b1);
printf ("JUMP2_FORWARD %d\n", (int)b1);
stix->ip += MAX_CODE_JUMP + b1;
break;
break;
case BCODE_JUMP2_BACKWARD:
FETCH_PARAM_CODE_TO (stix, b1);
printf ("JUMP2_BACKWARD %d\n", (int)b1);
stix->ip -= MAX_CODE_JUMP + b1;
break;
/* -------------------------------------------------------- */

View File

@ -43,7 +43,6 @@
#define STIX_DEBUG_GC_001
#include <stdio.h> /* TODO: delete these header inclusion lines */
#include <string.h>
#include <assert.h>
@ -477,7 +476,7 @@ struct stix_compiler_t
# define MAX_CODE_NBLKARGS (0xFFu)
# define MAX_CODE_NBLKTMPRS (0xFFu)
# define MAX_CODE_PRIMNO (0xFFFFu)
# define MAX_CODE_JUMP (0xFF)
# define MAX_CODE_JUMP (0xFFu)
#elif defined(STIX_BCODE_LONG_PARAM_SIZE) && (STIX_BCODE_LONG_PARAM_SIZE == 2)
# define MAX_CODE_INDEX (0xFFFFu)
# define MAX_CODE_NTMPRS (0xFFFFu)
@ -485,14 +484,11 @@ struct stix_compiler_t
# define MAX_CODE_NBLKARGS (0xFFFFu)
# define MAX_CODE_NBLKTMPRS (0xFFFFu)
# define MAX_CODE_PRIMNO (0xFFFFu)
# define MAX_CODE_JUMP (0xFFFF)
# define MAX_CODE_JUMP (0xFFFFu)
#else
# error Unsupported STIX_BCODE_LONG_PARAM_SIZE
#endif
#define MAX_CODE_BLKCODE MAX_CODE_JUMP
/*
----------------------------------------------------------------------------------------------------------------
@ -527,8 +523,8 @@ SHORT INSTRUCTION CODE LONG INSTRUCTION C
72-75 0100 10XX JUMP_BACKWARD 200 1100 1000 XXXXXXXX JUMP_BACKWARD_X
76-79 0100 11XX JUMP_IF_TRUE 204 1100 1100 XXXXXXXX JUMP_IF_TRUE_X
80-83 0101 00XX JUMP_IF_FALSE 208 1101 0000 XXXXXXXX JUMP_IF_FALSE_X
84-87 0101 01XX JUMP_BY_OFFSET 212 1101 0100 XXXXXXXX JUMP_BY_OFFSET_X
# for JUMP_BY_OFFSET, XX is an index to literal frame pointing to a small integer.
84-87 0101 01XX UNUSED
vv
88-91 0101 10XX YYYYYYYY STORE_INTO_CTXTEMPVAR 216 1101 1000 XXXXXXXX YYYYYYYY STORE_INTO_CTXTEMPVAR_X (bit 3 on, bit 2 off)
@ -659,15 +655,12 @@ enum stix_bcode_t
BCODE_JUMP_IF_TRUE_2 = 0x4E,
BCODE_JUMP_IF_TRUE_3 = 0x4F,
BCODE_JUMP_IF_FALSE_0 = 0x50,
BCODE_JUMP_IF_FALSE_1 = 0x51,
BCODE_JUMP_IF_FALSE_2 = 0x52,
BCODE_JUMP_IF_FALSE_3 = 0x53,
BCODE_JUMP_IF_FALSE_0 = 0x50, /* 80 */
BCODE_JUMP_IF_FALSE_1 = 0x51, /* 81 */
BCODE_JUMP_IF_FALSE_2 = 0x52, /* 82 */
BCODE_JUMP_IF_FALSE_3 = 0x53, /* 83 */
BCODE_JUMP_BY_OFFSET_0 = 0x54,
BCODE_JUMP_BY_OFFSET_1 = 0x55,
BCODE_JUMP_BY_OFFSET_2 = 0x56,
BCODE_JUMP_BY_OFFSET_3 = 0x57,
BCODE_STORE_INTO_CTXTEMPVAR_0 = 0x58, /* 88 */
BCODE_STORE_INTO_CTXTEMPVAR_1 = 0x59, /* 89 */
@ -729,7 +722,7 @@ enum stix_bcode_t
BCODE_JUMP_BACKWARD_X = 0xC8, /* 200 */
BCODE_JUMP_IF_TRUE_X = 0xCC, /* 204 */
BCODE_JUMP_IF_FALSE_X = 0xD0, /* 208 */
BCODE_JUMP_BY_OFFSET_X = 0xD4, /* 212 */
BCODE_STORE_INTO_CTXTEMPVAR_X = 0xD8, /* 216 */
BCODE_POP_INTO_CTXTEMPVAR_X = 0xDC, /* 220 */
@ -743,15 +736,18 @@ enum stix_bcode_t
BCODE_SEND_MESSAGE_TO_SUPER_X = 0xF4, /* 244 */
BCODE_PUSH_RECEIVER = 0x81,
BCODE_PUSH_NIL = 0x82,
BCODE_PUSH_TRUE = 0x83,
BCODE_PUSH_FALSE = 0x84,
BCODE_PUSH_CONTEXT = 0x85,
BCODE_PUSH_NEGONE = 0x86,
BCODE_PUSH_ZERO = 0x87,
BCODE_PUSH_ONE = 0x89,
BCODE_PUSH_TWO = 0x91,
BCODE_JUMP2_FORWARD = 0xC5, /* 197 */
BCODE_JUMP2_BACKWARD = 0xC9, /* 201 */
BCODE_PUSH_RECEIVER = 0x81, /* 129 */
BCODE_PUSH_NIL = 0x82, /* 130 */
BCODE_PUSH_TRUE = 0x83, /* 131 */
BCODE_PUSH_FALSE = 0x84, /* 132 */
BCODE_PUSH_CONTEXT = 0x85, /* 133 */
BCODE_PUSH_NEGONE = 0x86, /* 134 */
BCODE_PUSH_ZERO = 0x87, /* 135 */
BCODE_PUSH_ONE = 0x89, /* 137 */
BCODE_PUSH_TWO = 0x8A, /* 138 */
/* UNUSED 0xE8 - 0xF8 */

View File

@ -1,375 +1,5 @@
#class Stix(nil)
{
#dcl(#class) sysdic.
#method(#class) yourself
{
^self.
}
#method yourself
{
^self.
}
#method(#class) dump
{
<primitive: 0>
}
#method dump
{
<primitive: 0>
}
#method(#class) new
{
<primitive: 1>
}
#method(#class) new: anInteger
{
<primitive: 2>
}
#method basicSize
{
<primitive: 3>
^0
}
#method basicAt: anInteger
{
<primitive: 4>
## self error: 'out of range'.
}
#method basicAt: anInteger put: anObject
{
<primitive: 5>
## self error: 'out of range'.
}
#method badReturnError
{
## TODO: implement this
}
#method mustBeBoolean
{
## TODO: implement this
}
#method doesNotUnderstand: aMessageSymbol
{
## TODO: implement this
}
#method error: anErrorString
{
anErrorString dump.
}
}
#class Object(Stix)
{
}
#class NilObject(Stix)
{
}
#class(#pointer) Class(Stix)
{
#dcl spec selfspec superclass subclasses name instvars classvars classinstvars instmthdic classmthdic.
}
#class Magnitude(Object)
{
}
#class Association(Magnitude)
{
#dcl key value.
}
#class Character(Magnitude)
{
}
#class Number(Magnitude)
{
#method add: aNumber
{
<primitive: 7>
}
#method + aNumber
{
<primitive: 7>
}
#method - aNumber
{
<primitive: 8>
}
#method < aNumber
{
<primitive: 9>
}
}
#class SmallInteger(Number)
{
}
#class Boolean(Object)
{
}
#class True(Boolean)
{
#method ifTrue: trueBlock ifFalse: falseBlock
{
^trueBlock value.
}
#method ifTrue: trueBlock
{
^trueBlock value.
}
#method ifFalse: falseBlock
{
^nil.
}
}
#class False(Boolean)
{
#method ifTrue: trueBlock ifFalse: falseBlock
{
^falseBlock value.
}
#method ifTrue: trueBlock
{
^nil.
}
#method ifFalse: falseBlock
{
^falseBlock value.
}
}
#class Collection(Object)
{
}
#class(#byte) ByteArray(Collection)
{
#method at: anInteger
{
^self basicAt: anInteger.
}
#method at: anInteger put: aValue
{
^self basicAt: anInteger put: aValue.
}
}
#class(#pointer) Array(Collection)
{
#method at: anInteger
{
^self basicAt: anInteger.
}
#method at: anInteger put: aValue
{
^self basicAt: anInteger put: aValue.
}
}
#class(#character) String(Array)
{
}
#class(#character) Symbol(Array)
{
}
#class Set(Collection)
{
#dcl tally bucket.
}
#class SymbolSet(Set)
{
}
#class Dictionary(Set)
{
}
#class SystemDictionary(Dictionary)
{
}
#class MethodDictionary(Dictionary)
{
}
#class(#pointer) Context(Stix)
{
}
#class(#pointer) MethodContext(Context)
{
#dcl sender ip sp ntmprs method receiver home origin.
#method pc
{
^ip
}
#method pc: anInteger
{
ip := anInteger.
"sp := sp - 1." "whould this always work??? "
}
#method sp
{
^sp.
}
#method sp: anInteger
{
sp := anInteger.
}
#method pc: aPC sp: aSP
{
ip := aPC.
sp := aSP.
##sp := sp - 1.
}
}
#class(#pointer) BlockContext(Context)
{
#dcl caller ip sp ntmprs nargs source home origin.
#method value
{
<primitive: 6>
}
#method value: a
{
<primitive: 6>
}
#method value: a value: b
{
<primitive: 6>
}
#method value: a value: b value: c
{
<primitive: 6>
}
#method whileTrue: aBlock
{
## http://stackoverflow.com/questions/2500483/is-there-a-way-in-a-message-only-language-to-define-a-whiletrue-message-without
## ----------------------------------------------------------------------------
## ^(self value) ifTrue: [aBlock value. self whileTrue: aBlock].
## ----------------------------------------------------------------------------
## less block context before whileTrue: is recursively sent.
## whileTrue: is sent in a method context.
## (self value) ifFalse: [^nil].
## aBlock value.
## self whileTrue: aBlock.
## ----------------------------------------------------------------------------
## ----------------------------------------------------------------------------
| pc sp xsp |
sp := thisContext sp.
sp := sp - 1. "decrement sp by 1 becuase thisContext pushed above affects the sp method"
pc := thisContext pc.
self value ifFalse: [ ^nil "^self" ].
aBlock value.
##thisContext pc: pc - 3 sp: sp.
##thisContext pc: pc + 2 sp: sp.
thisContext pc: pc + 1 sp: sp.
## this +2 or - 3 above is dependent on the byte code instruction size used for 'store'
## +2 to skip STORE_INTO_TEMP(pc) and POP_STACKTOP.
## TODO: make it independent of the byte code size
## ----------------------------------------------------------------------------
## #<label>:
## thisContext pc: #<label> sp: sp.
##
## | pc |
## pc := thisContext pc.
## ^self value ifTrue: [aBlock value. thisContext pc: pc]
## ----------------------------------------------------------------------------
## self value ifTrue: [ aBlock value. thisContext restart. ].
}
#method pc
{
^ip
}
#method pc: anInteger
{
ip := anInteger.
}
#method sp
{
^sp
}
#method sp: anInteger
{
sp := anInteger.
}
#method restart
{
ip := source pc.
}
}
#class(#pointer) CompiledMethod(Object)
{
#dcl owner preamble ntmprs nargs code source.
}
#include 'Stix.st'
#################################################################
## MAIN