implemented simple optimization in compiling an if expression

This commit is contained in:
hyunghwan.chung 2017-01-31 16:14:11 +00:00
parent 22013650bb
commit 07d8d0ea83
4 changed files with 86 additions and 42 deletions

View File

@ -176,7 +176,11 @@ class MyObject(Object)
a := a + 100000000000000.
}.*)
(*
a := if(false) { 10 } elsif (false) { 20 } elsif (false) { 30} else { 40}.
##a := if(false) { 999 } else { 888 }.
a dump.
a := 5.
a := while (true)
{
@ -187,12 +191,12 @@ class MyObject(Object)
}.
a dump.
}.
a dump.*)
a dump.
a := 5.
do {
a := do {
('in loop.....' & a asString) dump.
if (a > 5) { break }.
##if (a > 5) { break }.
a := a + 1.
} while(a < 10).
} while (false).

View File

@ -4530,63 +4530,94 @@ static int compile_conditional (moo_t* moo)
return 0;
}
#define INVALID_IP MOO_TYPE_MAX(moo_oow_t)
static int compile_if_expression (moo_t* moo)
{
moo_oow_pool_t jumptoend;
moo_oow_pool_chunk_t* jumptoend_chunk;
moo_oow_t i, j;
moo_oow_t jumptonext;
moo_oow_t jumptonext, precondpos, postcondpos, endoftrueblock;
int falseblock;
moo_ioloc_t if_loc, brace_loc;
MOO_ASSERT (moo, TOKEN_TYPE(moo) == MOO_IOTOK_IF);
if_loc = *TOKEN_LOC(moo);
init_oow_pool (moo, &jumptoend);
jumptonext = INVALID_IP;
endoftrueblock = INVALID_IP;
/* TODO: simple optimization to check if the conditional is true or false */
GET_TOKEN (moo); /* get ( */
if (compile_conditional (moo) <= -1) goto oops;
jumptonext = moo->c->mth.code.len;
/* specifying MAX_CODE_JUMP causes emit_single_param_instruction() to
* produce the long jump instruction (BCODE_JUMP_FORWARD_X) */
if (emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_IF_FALSE_0, MAX_CODE_JUMP) <= -1) goto oops;
GET_TOKEN (moo); /* get { */
brace_loc = *TOKEN_LOC(moo);
if (compile_braced_block (moo) <= -1) goto oops;
/* emit code to jump to the end */
/*jumptoend[jumptoend_count++] = moo->c->mth.code.len;*/
if (add_to_oow_pool(moo, &jumptoend, moo->c->mth.code.len) <= -1) goto oops;
if (emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_0, MAX_CODE_JUMP) <= -1) goto oops;
GET_TOKEN (moo);
while (TOKEN_TYPE(moo) == MOO_IOTOK_ELSIF)
do
{
if (patch_long_forward_jump_instruction (moo, jumptonext, moo->c->mth.code.len, BCODE_JUMP2_FORWARD_IF_FALSE, &brace_loc) <= -1) goto oops;
int falseblock = 0;
GET_TOKEN (moo); /* get ( */
if (compile_conditional(moo) <= -1) goto oops;
precondpos = moo->c->mth.code.len;
/* emit code to jump to the next elsif or else */
jumptonext = moo->c->mth.code.len;
if (emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_IF_FALSE_0, MAX_CODE_JUMP) <= -1) goto oops;
if (jumptonext != INVALID_IP &&
patch_long_forward_jump_instruction (moo, jumptonext, precondpos, BCODE_JUMP2_FORWARD_IF_FALSE, &brace_loc) <= -1) goto oops;
if (compile_conditional(moo) <= -1) goto oops;
postcondpos = moo->c->mth.code.len;
if (precondpos + 1 == postcondpos && moo->c->mth.code.ptr[precondpos] == BCODE_PUSH_TRUE)
{
/* do not generate jump */
jumptonext = INVALID_IP;
falseblock = 0;
/* eliminate PUSH_TRUE as well */
moo->c->mth.code.len = precondpos;
postcondpos = precondpos;
}
else if (precondpos + 1 == postcondpos && moo->c->mth.code.ptr[precondpos] == BCODE_PUSH_FALSE)
{
jumptonext = INVALID_IP;
/* mark that the conditional is false. instructions will get eliminated below */
falseblock = 1;
}
else
{
/* remember position of the jump_forward_if_false instruction to be generated */
jumptonext = moo->c->mth.code.len;
/* specifying MAX_CODE_JUMP causes emit_single_param_instruction() to
* produce the long jump instruction (BCODE_JUMP_FORWARD_X) */
if (emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_IF_FALSE_0, MAX_CODE_JUMP) <= -1) goto oops;
}
GET_TOKEN (moo); /* get { */
brace_loc = *TOKEN_LOC(moo);
if (compile_braced_block(moo) <= -1) goto oops;
/* emit code to jump to the end */
/*jumptoend[jumptoend_count++] = moo->c->mth.code.len;*/
if (add_to_oow_pool(moo, &jumptoend, moo->c->mth.code.len) <= -1) goto oops;
if (emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_0, MAX_CODE_JUMP) <= -1) goto oops;
if (jumptonext == INVALID_IP)
{
if (falseblock)
{
moo->c->mth.code.len = precondpos;
postcondpos = precondpos;
}
else if (endoftrueblock == INVALID_IP)
{
/* update the end position of the first true block */
endoftrueblock = moo->c->mth.code.len;
}
}
else
{
if (endoftrueblock == INVALID_IP)
{
/* emit an instruction to jump to the end */
if (add_to_oow_pool(moo, &jumptoend, moo->c->mth.code.len) <= -1) goto oops;
if (emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_0, MAX_CODE_JUMP) <= -1) goto oops;
}
}
GET_TOKEN (moo); /* get the next token after } */
}
} while (TOKEN_TYPE(moo) == MOO_IOTOK_ELSIF);
if (patch_long_forward_jump_instruction (moo, jumptonext, moo->c->mth.code.len, BCODE_JUMP2_FORWARD_IF_FALSE, &brace_loc) <= -1) goto oops;
if (jumptonext != INVALID_IP &&
patch_long_forward_jump_instruction (moo, jumptonext, moo->c->mth.code.len, BCODE_JUMP2_FORWARD_IF_FALSE, &brace_loc) <= -1) goto oops;
if (TOKEN_TYPE(moo) == MOO_IOTOK_ELSE)
{
@ -4596,10 +4627,16 @@ static int compile_if_expression (moo_t* moo)
}
else
{
/* emit code to push nil if no 'else' part exists */
/* emit an instruction to push nil if no 'else' part exists */
if (emit_byte_instruction (moo, BCODE_PUSH_NIL) <= -1) goto oops;
}
if (endoftrueblock != INVALID_IP)
{
/* eliminate all instructions after the end of the first true block found */
moo->c->mth.code.len = endoftrueblock;
}
/* patch instructions that jumps to the end of if expression */
for (jumptoend_chunk = jumptoend.head, i = 0; jumptoend_chunk; jumptoend_chunk = jumptoend_chunk->next)
{
@ -4819,7 +4856,7 @@ skip_emitting_jump_backward:
/* update jump instructions emitted for break */
if (update_loop_jumps (moo, &loop->break_ip_pool, moo->c->mth.code.len) <= -1) return -1;
free_loop (moo, loop);
free_loop (moo, loop); /* destroy the unlinked loop information */
loop = MOO_NULL;
loop_pushed = 0;

View File

@ -3518,7 +3518,8 @@ int moo_execute (moo_t* moo)
case BCODE_JUMP_BACKWARD_IF_TRUE_X:
FETCH_PARAM_CODE_TO (moo, b1);
LOG_INST_1 (moo, "jump_backward_if_true %zu", b1);
if (MOO_STACK_GETTOP(moo) == moo->_true) moo->ip -= b1;
/*if (MOO_STACK_GETTOP(moo) == moo->_true) moo->ip -= b1;*/
if (MOO_STACK_GETTOP(moo) != moo->_false) moo->ip -= b1;
MOO_STACK_POP (moo);
break;
@ -3527,7 +3528,8 @@ int moo_execute (moo_t* moo)
case BCODE_JUMP_BACKWARD_IF_TRUE_2:
case BCODE_JUMP_BACKWARD_IF_TRUE_3:
LOG_INST_1 (moo, "jump_backward_if_true %zu", (moo_oow_t)(bcode & 0x3));
if (MOO_STACK_GETTOP(moo) == moo->_true) moo->ip -= (bcode & 0x3); /* low 2 bits */
/*if (MOO_STACK_GETTOP(moo) == moo->_true) moo->ip -= (bcode & 0x3);*/ /* low 2 bits */
if (MOO_STACK_GETTOP(moo) != moo->_false) moo->ip -= (bcode & 0x3);
MOO_STACK_POP (moo);
break;
@ -3560,7 +3562,8 @@ int moo_execute (moo_t* moo)
case BCODE_JUMP2_BACKWARD_IF_TRUE:
FETCH_PARAM_CODE_TO (moo, b1);
LOG_INST_1 (moo, "jump2_backward_if_true %zu", b1);
if (MOO_STACK_GETTOP(moo) == moo->_true) moo->ip -= MAX_CODE_JUMP + b1;
/* if (MOO_STACK_GETTOP(moo) == moo->_true) moo->ip -= MAX_CODE_JUMP + b1; */
if (MOO_STACK_GETTOP(moo) != moo->_false) moo->ip -= MAX_CODE_JUMP + b1;
MOO_STACK_POP (moo);
break;
/* -------------------------------------------------------- */

View File

@ -96,7 +96,7 @@ int moo_init (moo_t* moo, moo_mmgr_t* mmgr, moo_oow_t heapsz, const moo_vmprim_t
moo->option.dfl_sysdic_size = MOO_DFL_SYSDIC_SIZE;
moo->option.dfl_procstk_size = MOO_DFL_PROCSTK_SIZE;
/* TODO: intoduct a permanent heap */
/* TODO: introduce a permanent heap */
/*moo->permheap = moo_makeheap (moo, what is the best size???);
if (!moo->permheap) goto oops; */
moo->curheap = moo_makeheap (moo, heapsz);