in progress of fixing a bug in instruction elimination

This commit is contained in:
hyunghwan.chung 2017-02-06 17:53:33 +00:00
parent 60c38a1ecb
commit 62eb6db83d
4 changed files with 126 additions and 46 deletions

View File

@ -110,7 +110,8 @@ class MyObject(Object)
} }
method(#class) main
method(#class) main_xx
{ {
|a k| |a k|
@ -214,6 +215,17 @@ class MyObject(Object)
nil. nil.
## end of elimination. ## end of elimination.
## PROBLEM: the following double loop will exhaust the stack
while (true)
{
while (true)
{
##[:j :q | (j + q) dump] value: (if (true) { 20 }) value: (if (true) { break }).
(1 + (if (false) {} else { break })) dump.
}.
}.
a :=999. a :=999.
a := #{ a := #{
1, 1,
@ -228,19 +240,20 @@ class MyObject(Object)
(* Dictionary ??? (* Dictionary ???
a := #{ a := #{
"a": 20, :( key, value ),
b : 30 :( key, value ),
}. :( key, value ),
a := #{ :( key, value )
{ key, value }, }
{ key, value },
{ key, value }, a := :{
{ key, value } :( key, value ),
} }
*) *)
abc := { key, value }.
{ key, value } dump. (* abc := { key, value }.
{ key, value } dump. *)
a do: [ :v | v dump]. a do: [ :v | v dump].
@ -254,4 +267,22 @@ class MyObject(Object)
'---------- END ------------' dump. '---------- END ------------' dump.
##Processor sleepFor: 20. ##Processor sleepFor: 20.
} }
method(#class) main
{
## PROBLEM: the following double loop will exhaust the stack
while (true)
{
##111 dump.
while (true)
{
##[:j :q | (j + q) dump] value: (if (true) { 20 }) value: (if (true) { break }).
(1 + (if (false) {} else { break })) dump.
##break.
##[:j :q | (j + q) dump] value: 10 value: 20.
##if (false) {} else { break }.
}.
}.
}
##
} }

View File

@ -1508,6 +1508,16 @@ retry:
SET_TOKEN_TYPE (moo, MOO_IOTOK_ASSIGN); SET_TOKEN_TYPE (moo, MOO_IOTOK_ASSIGN);
ADD_TOKEN_CHAR (moo, c); ADD_TOKEN_CHAR (moo, c);
} }
else if (c == '{')
{
SET_TOKEN_TYPE (moo, MOO_IOTOK_DICBRACE);
ADD_TOKEN_CHAR (moo, c);
}
else if (c == '(')
{
SET_TOKEN_TYPE (moo, MOO_IOTOK_ASSPAREN);
ADD_TOKEN_CHAR (moo, c);
}
else else
{ {
unget_char (moo, &moo->c->lxc); unget_char (moo, &moo->c->lxc);
@ -1577,7 +1587,7 @@ retry:
case '[': case '[':
/* #[ - byte array literal */ /* #[ - byte array literal */
ADD_TOKEN_CHAR(moo, c); ADD_TOKEN_CHAR(moo, c);
SET_TOKEN_TYPE (moo, MOO_IOTOK_BAPAREN); SET_TOKEN_TYPE (moo, MOO_IOTOK_BABRACK);
break; break;
case '{': case '{':
@ -2185,7 +2195,7 @@ static int patch_long_forward_jump_instruction (moo_t* moo, moo_oow_t jip, moo_o
code_size = jt - jip - (MOO_BCODE_LONG_PARAM_SIZE + 1); code_size = jt - jip - (MOO_BCODE_LONG_PARAM_SIZE + 1);
if (code_size > MAX_CODE_JUMP * 2) if (code_size > MAX_CODE_JUMP * 2)
{ {
/* TODO: change error code or get it as a parameter */ /* TODO: change error code or get it as a parameter */
set_syntax_error (moo, MOO_SYNERR_BLKFLOOD, errloc, MOO_NULL); set_syntax_error (moo, MOO_SYNERR_BLKFLOOD, errloc, MOO_NULL);
return -1; return -1;
} }
@ -2211,6 +2221,32 @@ static int patch_long_forward_jump_instruction (moo_t* moo, moo_oow_t jip, moo_o
return 0; return 0;
} }
static void eliminate_instructions (moo_t* moo, moo_oow_t start, moo_oow_t end)
{
moo_oow_t last;
MOO_ASSERT (moo, moo->c->mth.code.len >= 1);
MOO_DEBUG2 (moo, "ELIMINATE INSTRUCTION FROM %zu TO %zu\n", start, end);
last = moo->c->mth.code.len - 1;
if (end >= last)
{
/* eliminate all instructions starting from the start index.
* setting the length to the start length will achieve this */
moo->c->mth.code.len = start;
}
else
{
/* eliminate a chunk in the middle of the instruction buffer.
* some copying is required */
if (end > last) end = last;
MOO_MEMMOVE (&moo->c->mth.code.ptr[start], &moo->c->mth.code.ptr[end + 1], moo->c->mth.code.len - end - 1);
moo->c->mth.code.len--;
}
}
/* --------------------------------------------------------------------- /* ---------------------------------------------------------------------
* Compiler * Compiler
* --------------------------------------------------------------------- */ * --------------------------------------------------------------------- */
@ -3884,7 +3920,7 @@ if index is too large, switch to at:put? (or don't care as it's too large???).
moo->c->mth.arlit_count = saved_arlit_count; moo->c->mth.arlit_count = saved_arlit_count;
break; break;
case MOO_IOTOK_BAPAREN: /* #[ */ case MOO_IOTOK_BABRACK: /* #[ */
/*case MOO_IOTOK_LBRACK:*/ /* [ */ /*case MOO_IOTOK_LBRACK:*/ /* [ */
GET_TOKEN (moo); GET_TOKEN (moo);
if (__read_byte_array_literal (moo, &lit) <= -1) return -1; if (__read_byte_array_literal (moo, &lit) <= -1) return -1;
@ -4218,7 +4254,7 @@ static int compile_expression_primary (moo_t* moo, const moo_oocs_t* ident, cons
break; break;
} }
case MOO_IOTOK_BAPAREN: /* #[ */ case MOO_IOTOK_BABRACK: /* #[ */
/*GET_TOKEN (moo);*/ /*GET_TOKEN (moo);*/
if (compile_byte_array_literal(moo) <= -1) return -1; if (compile_byte_array_literal(moo) <= -1) return -1;
break; break;
@ -4464,8 +4500,10 @@ static int compile_message_expression (moo_t* moo, int to_super)
if (TOKEN_TYPE(moo) == MOO_IOTOK_BINSEL) if (TOKEN_TYPE(moo) == MOO_IOTOK_BINSEL)
{ {
MOO_ASSERT (moo, moo->c->mth.code.len > noop_pos); MOO_ASSERT (moo, moo->c->mth.code.len > noop_pos);
MOO_MEMMOVE (&moo->c->mth.code.ptr[noop_pos], &moo->c->mth.code.ptr[noop_pos + 1], moo->c->mth.code.len - noop_pos - 1); /*MOO_MEMMOVE (&moo->c->mth.code.ptr[noop_pos], &moo->c->mth.code.ptr[noop_pos + 1], moo->c->mth.code.len - noop_pos - 1);
moo->c->mth.code.len--; moo->c->mth.code.len--;*/
/* eliminate the NOOP instruction */
eliminate_instructions (moo, noop_pos, noop_pos);
noop_pos = moo->c->mth.code.len; noop_pos = moo->c->mth.code.len;
if (emit_byte_instruction(moo, BCODE_NOOP) <= -1) return -1; if (emit_byte_instruction(moo, BCODE_NOOP) <= -1) return -1;
@ -4475,8 +4513,10 @@ static int compile_message_expression (moo_t* moo, int to_super)
if (TOKEN_TYPE(moo) == MOO_IOTOK_KEYWORD) if (TOKEN_TYPE(moo) == MOO_IOTOK_KEYWORD)
{ {
MOO_ASSERT (moo, moo->c->mth.code.len > noop_pos); MOO_ASSERT (moo, moo->c->mth.code.len > noop_pos);
MOO_MEMMOVE (&moo->c->mth.code.ptr[noop_pos], &moo->c->mth.code.ptr[noop_pos + 1], moo->c->mth.code.len - noop_pos - 1); /*MOO_MEMMOVE (&moo->c->mth.code.ptr[noop_pos], &moo->c->mth.code.ptr[noop_pos + 1], moo->c->mth.code.len - noop_pos - 1);
moo->c->mth.code.len--; moo->c->mth.code.len--;*/
/* eliminate the NOOP instruction */
eliminate_instructions (moo, noop_pos, noop_pos);
noop_pos = moo->c->mth.code.len; noop_pos = moo->c->mth.code.len;
if (emit_byte_instruction(moo, BCODE_NOOP) <= -1) return -1; if (emit_byte_instruction(moo, BCODE_NOOP) <= -1) return -1;
@ -4492,8 +4532,10 @@ static int compile_message_expression (moo_t* moo, int to_super)
if (TOKEN_TYPE(moo) == MOO_IOTOK_KEYWORD) if (TOKEN_TYPE(moo) == MOO_IOTOK_KEYWORD)
{ {
MOO_ASSERT (moo, moo->c->mth.code.len > noop_pos); MOO_ASSERT (moo, moo->c->mth.code.len > noop_pos);
MOO_MEMMOVE (&moo->c->mth.code.ptr[noop_pos], &moo->c->mth.code.ptr[noop_pos + 1], moo->c->mth.code.len - noop_pos - 1); /*MOO_MEMMOVE (&moo->c->mth.code.ptr[noop_pos], &moo->c->mth.code.ptr[noop_pos + 1], moo->c->mth.code.len - noop_pos - 1);
moo->c->mth.code.len--; moo->c->mth.code.len--;*/
/* eliminate the NOOP instruction */
eliminate_instructions (moo, noop_pos, noop_pos);
noop_pos = moo->c->mth.code.len; noop_pos = moo->c->mth.code.len;
if (emit_byte_instruction(moo, BCODE_NOOP) <= -1) return -1; if (emit_byte_instruction(moo, BCODE_NOOP) <= -1) return -1;
@ -4521,10 +4563,11 @@ static int compile_message_expression (moo_t* moo, int to_super)
} }
else else
{ {
/* delete the NOOP instruction inserted */
MOO_ASSERT (moo, moo->c->mth.code.len > noop_pos); MOO_ASSERT (moo, moo->c->mth.code.len > noop_pos);
MOO_MEMMOVE (&moo->c->mth.code.ptr[noop_pos], &moo->c->mth.code.ptr[noop_pos + 1], moo->c->mth.code.len - noop_pos - 1); /*MOO_MEMMOVE (&moo->c->mth.code.ptr[noop_pos], &moo->c->mth.code.ptr[noop_pos + 1], moo->c->mth.code.len - noop_pos - 1);
moo->c->mth.code.len--; moo->c->mth.code.len--;*/
/* eliminate the NOOP instruction */
eliminate_instructions (moo, noop_pos, noop_pos);
goto done; goto done;
} }
} }
@ -4673,7 +4716,7 @@ static int compile_if_expression (moo_t* moo)
falseblock = 0; falseblock = 0;
/* eliminate PUSH_TRUE as well */ /* eliminate PUSH_TRUE as well */
moo->c->mth.code.len = precondpos; eliminate_instructions (moo, precondpos, moo->c->mth.code.len - 1);
postcondpos = precondpos; postcondpos = precondpos;
} }
else if (precondpos + 1 == postcondpos && moo->c->mth.code.ptr[precondpos] == BCODE_PUSH_FALSE) else if (precondpos + 1 == postcondpos && moo->c->mth.code.ptr[precondpos] == BCODE_PUSH_FALSE)
@ -4699,7 +4742,9 @@ static int compile_if_expression (moo_t* moo)
{ {
if (falseblock) if (falseblock)
{ {
moo->c->mth.code.len = precondpos; /* the conditional was false. elimiate instructions emitted
* for the block attached to the conditional */
eliminate_instructions (moo, precondpos, moo->c->mth.code.len - 1);
postcondpos = precondpos; postcondpos = precondpos;
} }
else if (endoftrueblock == INVALID_IP) else if (endoftrueblock == INVALID_IP)
@ -4713,8 +4758,8 @@ static int compile_if_expression (moo_t* moo)
if (endoftrueblock == INVALID_IP) if (endoftrueblock == INVALID_IP)
{ {
/* emit an instruction to jump to the end */ /* emit an instruction to jump to the end */
if (add_to_oow_pool(moo, &jumptoend, moo->c->mth.code.len) <= -1) goto oops; if (add_to_oow_pool(moo, &jumptoend, moo->c->mth.code.len) <= -1 ||
if (emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_0, MAX_CODE_JUMP) <= -1) goto oops; emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_0, MAX_CODE_JUMP) <= -1) goto oops;
} }
} }
@ -4739,7 +4784,7 @@ static int compile_if_expression (moo_t* moo)
if (endoftrueblock != INVALID_IP) if (endoftrueblock != INVALID_IP)
{ {
/* eliminate all instructions after the end of the first true block found */ /* eliminate all instructions after the end of the first true block found */
moo->c->mth.code.len = endoftrueblock; eliminate_instructions (moo, endoftrueblock, moo->c->mth.code.len - 1);
} }
/* patch instructions that jumps to the end of if expression */ /* patch instructions that jumps to the end of if expression */
@ -4777,6 +4822,7 @@ static int compile_while_expression (moo_t* moo)
if (compile_conditional (moo) <= -1) goto oops; if (compile_conditional (moo) <= -1) goto oops;
postcondpos = moo->c->mth.code.len; postcondpos = moo->c->mth.code.len;
#if 0
if (precondpos + 1 == postcondpos) if (precondpos + 1 == postcondpos)
{ {
/* simple optimization - /* simple optimization -
@ -4786,7 +4832,7 @@ static int compile_while_expression (moo_t* moo)
{ {
/* the conditional is always true */ /* the conditional is always true */
cond_style = 1; cond_style = 1;
moo->c->mth.code.len = precondpos; eliminate_instructions (moo, precondpos, moo->c->mth.code.len - 1);
postcondpos = precondpos; postcondpos = precondpos;
} }
else if (moo->c->mth.code.ptr[precondpos] == BCODE_PUSH_FALSE) else if (moo->c->mth.code.ptr[precondpos] == BCODE_PUSH_FALSE)
@ -4795,6 +4841,7 @@ static int compile_while_expression (moo_t* moo)
cond_style = -1; cond_style = -1;
} }
} }
#endif
if (cond_style != 1) if (cond_style != 1)
{ {
@ -4819,7 +4866,7 @@ static int compile_while_expression (moo_t* moo)
/* optimization - /* optimization -
* the braced block is kind of empty as it only pushes nil. * the braced block is kind of empty as it only pushes nil.
* get rid of this push instruction and don't generate the POP_STACKTOP */ * get rid of this push instruction and don't generate the POP_STACKTOP */
moo->c->mth.code.len = prebbpos; eliminate_instructions (moo, prebbpos, moo->c->mth.code.len - 1);
} }
else if (prebbpos < postbbpos) else if (prebbpos < postbbpos)
{ {
@ -4841,15 +4888,15 @@ static int compile_while_expression (moo_t* moo)
if (cond_style != 1) if (cond_style != 1)
{ {
/* patch the jump instruction. */ /* patch the jump instruction */
if (patch_long_forward_jump_instruction (moo, postcondpos, moo->c->mth.code.len, BCODE_JUMP2_FORWARD_IF_FALSE, &brace_loc) <= -1) goto oops; if (patch_long_forward_jump_instruction (moo, postcondpos, moo->c->mth.code.len, BCODE_JUMP2_FORWARD_IF_FALSE, &brace_loc) <= -1) goto oops;
} }
if (cond_style == -1) if (cond_style == -1)
{ {
/* optimization - get rid of code generated for the while /* optimization - get rid of instructions generated for the while
* loop including the conditional */ * loop including the conditional as the condition was false */
moo->c->mth.code.len = precondpos; eliminate_instructions (moo, precondpos, moo->c->mth.code.len - 1);
} }
/* patch the jump instructions for break */ /* patch the jump instructions for break */
@ -4903,7 +4950,7 @@ static int compile_do_while_expression (moo_t* moo)
/* optimization - /* optimization -
* the braced block is kind of empty as it only pushes nil. * the braced block is kind of empty as it only pushes nil.
* get rid of this push instruction and don't generate the POP_STACKTOP */ * get rid of this push instruction and don't generate the POP_STACKTOP */
moo->c->mth.code.len = prebbpos; eliminate_instructions (moo, prebbpos, moo->c->mth.code.len - 1);
precondpos = prebbpos; precondpos = prebbpos;
} }
else if (prebbpos < postbbpos) else if (prebbpos < postbbpos)
@ -4932,14 +4979,14 @@ static int compile_do_while_expression (moo_t* moo)
if (moo->c->mth.code.ptr[precondpos] == BCODE_PUSH_TRUE) if (moo->c->mth.code.ptr[precondpos] == BCODE_PUSH_TRUE)
{ {
/* the conditional is always true. eliminate PUSH_TRUE and emit an absolute jump */ /* the conditional is always true. eliminate PUSH_TRUE and emit an absolute jump */
moo->c->mth.code.len = precondpos; eliminate_instructions (moo, precondpos, moo->c->mth.code.len - 1);
postcondpos = precondpos; postcondpos = precondpos;
jbinst = BCODE_JUMP_BACKWARD_0; jbinst = BCODE_JUMP_BACKWARD_0;
} }
else if (moo->c->mth.code.ptr[precondpos] == BCODE_PUSH_FALSE) else if (moo->c->mth.code.ptr[precondpos] == BCODE_PUSH_FALSE)
{ {
/* the conditional is always false. eliminate PUSH_FALSE and don't emit jump */ /* the conditional is always false. eliminate PUSH_FALSE and don't emit jump */
moo->c->mth.code.len = precondpos; eliminate_instructions (moo, precondpos, moo->c->mth.code.len - 1);
postcondpos = precondpos; postcondpos = precondpos;
goto skip_emitting_jump_backward; goto skip_emitting_jump_backward;
} }
@ -5237,7 +5284,7 @@ static int compile_method_statement (moo_t* moo)
case BCODE_PUSH_TWO: case BCODE_PUSH_TWO:
/* eliminate the unneeded push instruction */ /* eliminate the unneeded push instruction */
n = 0; n = 0;
moo->c->mth.code.len = preexprpos; eliminate_instructions (moo, preexprpos, moo->c->mth.code.len - 1);
break; break;
default: default:
goto pop_stacktop; goto pop_stacktop;
@ -6252,7 +6299,7 @@ static int __compile_pooldic_definition (moo_t* moo)
if (!lit) return -1; if (!lit) return -1;
goto add_literal; goto add_literal;
case MOO_IOTOK_BAPAREN: /* #[ - byte array literal parenthesis */ case MOO_IOTOK_BABRACK: /* #[ - byte array literal parenthesis */
if (read_byte_array_literal(moo, &lit) <= -1) return -1; if (read_byte_array_literal(moo, &lit) <= -1) return -1;
goto add_literal; goto add_literal;

View File

@ -323,9 +323,11 @@ struct moo_iotok_t
MOO_IOTOK_RBRACK, MOO_IOTOK_RBRACK,
MOO_IOTOK_LPAREN, MOO_IOTOK_LPAREN,
MOO_IOTOK_RPAREN, MOO_IOTOK_RPAREN,
MOO_IOTOK_APAREN, /* #( */ MOO_IOTOK_APAREN, /* #( - array literal */
MOO_IOTOK_BAPAREN, /* #[ */ MOO_IOTOK_BABRACK, /* #[ - byte array literal */
MOO_IOTOK_ABRACE, /* #{ */ MOO_IOTOK_ABRACE, /* #{ - array expression */
MOO_IOTOK_DICBRACE, /* :{ - dictionary expression */
MOO_IOTOK_ASSPAREN, /* :( - association expression */
MOO_IOTOK_PERIOD, MOO_IOTOK_PERIOD,
MOO_IOTOK_COMMA, MOO_IOTOK_COMMA,
MOO_IOTOK_SEMICOLON, MOO_IOTOK_SEMICOLON,

View File

@ -979,11 +979,11 @@ struct moo_t
#endif #endif
}; };
/* TODO: proper stack bound check when pushing */
/* TODO: stack bound check when pushing */
#define MOO_STACK_PUSH(moo,v) \ #define MOO_STACK_PUSH(moo,v) \
do { \ do { \
(moo)->sp = (moo)->sp + 1; \ (moo)->sp = (moo)->sp + 1; \
MOO_ASSERT (moo, (moo)->sp < (unsigned int)(MOO_OBJ_GET_SIZE((moo)->processor->active) - MOO_PROCESS_NAMED_INSTVARS)); \
(moo)->processor->active->slot[(moo)->sp] = v; \ (moo)->processor->active->slot[(moo)->sp] = v; \
} while (0) } while (0)