From 07d8d0ea838b662e3187468b6927825082dbd1c7 Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Tue, 31 Jan 2017 16:14:11 +0000 Subject: [PATCH] implemented simple optimization in compiling an if expression --- moo/kernel/Mill.moo | 10 +++-- moo/lib/comp.c | 107 +++++++++++++++++++++++++++++--------------- moo/lib/exec.c | 9 ++-- moo/lib/moo.c | 2 +- 4 files changed, 86 insertions(+), 42 deletions(-) diff --git a/moo/kernel/Mill.moo b/moo/kernel/Mill.moo index 95c2793..e1af1e5 100644 --- a/moo/kernel/Mill.moo +++ b/moo/kernel/Mill.moo @@ -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). diff --git a/moo/lib/comp.c b/moo/lib/comp.c index 7fe6d09..d18074a 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -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; diff --git a/moo/lib/exec.c b/moo/lib/exec.c index 84e5ded..6ad36e6 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -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; /* -------------------------------------------------------- */ diff --git a/moo/lib/moo.c b/moo/lib/moo.c index 752e8a5..e8f515d 100644 --- a/moo/lib/moo.c +++ b/moo/lib/moo.c @@ -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);