updated the compiler to fix the jump instruction positions for break and continue upon instruction eliminations

This commit is contained in:
hyunghwan.chung 2017-02-09 10:22:44 +00:00
parent c6cf64a586
commit 2a40be7742
2 changed files with 139 additions and 88 deletions

View File

@ -316,6 +316,15 @@ class MyObject(Object)
]. ].
(a associationAt: :(#aaa)) dump. (a associationAt: :(#aaa)) dump.
while (true)
{
while (true)
{
[:j :q | (j + q) dump] value: (if (true) { 20 }) value: (if (true) { break }).
(1 + (if (false) {} else { break })) dump.
}
}
} }
} }

View File

@ -1912,7 +1912,7 @@ static int end_include (moo_t* moo)
} }
/* --------------------------------------------------------------------- /* ---------------------------------------------------------------------
* Byte-Code Generator * Byte-Code Manipulation Functions
* --------------------------------------------------------------------- */ * --------------------------------------------------------------------- */
static MOO_INLINE int emit_byte_instruction (moo_t* moo, moo_oob_t code) static MOO_INLINE int emit_byte_instruction (moo_t* moo, moo_oob_t code)
@ -2223,28 +2223,154 @@ static int patch_long_forward_jump_instruction (moo_t* moo, moo_oow_t jip, moo_o
return 0; return 0;
} }
static int push_loop (moo_t* moo, moo_loop_type_t type, moo_oow_t startpos)
{
moo_loop_t* loop;
loop = moo_callocmem (moo, MOO_SIZEOF(*loop));
if (!loop) return -1;
init_oow_pool (moo, &loop->break_ip_pool);
init_oow_pool (moo, &loop->continue_ip_pool);
loop->type = type;
loop->startpos = startpos;
loop->next = moo->c->mth.loop;
moo->c->mth.loop = loop;
return 0;
}
static int update_loop_jumps (moo_t* moo, moo_oow_pool_t* pool, moo_oow_t jt)
{
/* patch the jump instructions emitted for 'break' or 'continue' */
moo_oow_pool_chunk_t* chunk;
moo_oow_t i, j;
for (chunk = pool->head, i = 0; chunk; chunk = chunk->next)
{
for (j = 0; j < MOO_COUNTOF(pool->static_chunk.buf) && i < pool->count; j++)
{
if (chunk->buf[j] != INVALID_IP &&
patch_long_forward_jump_instruction (moo, chunk->buf[j], jt, BCODE_JUMP2_FORWARD, MOO_NULL) <= -1) return -1;
i++;
}
}
return 0;
}
static void adjust_loop_jumps_for_elimination (moo_t* moo, moo_oow_pool_t* pool, moo_oow_t start, moo_oow_t end)
{
/* update the jump instruction positions emitted for 'break' or 'continue' */
moo_oow_pool_chunk_t* chunk;
moo_oow_t i, j;
for (chunk = pool->head, i = 0; chunk; chunk = chunk->next)
{
for (j = 0; j < MOO_COUNTOF(pool->static_chunk.buf) && i < pool->count; j++)
{
if (chunk->buf[j] != INVALID_IP)
{
if (chunk->buf[j] >= start && chunk->buf[j] <= end)
{
/* invalidate the instruction position */
chunk->buf[j] = INVALID_IP;
}
else if (chunk->buf[j] > end && chunk->buf[j] < moo->c->mth.code.len)
{
/* decrement the instruction position */
chunk->buf[j] -= end - start + 1;
}
}
i++;
}
}
}
static MOO_INLINE int update_loop_breaks (moo_t* moo, moo_oow_t jt)
{
return update_loop_jumps (moo, &moo->c->mth.loop->break_ip_pool, jt);
}
static MOO_INLINE int update_loop_continues (moo_t* moo, moo_oow_t jt)
{
return update_loop_jumps (moo, &moo->c->mth.loop->continue_ip_pool, jt);
}
static MOO_INLINE void adjust_all_loop_jumps_for_elimination (moo_t* moo, moo_oow_t start, moo_oow_t end)
{
moo_loop_t* loop;
loop = moo->c->mth.loop;
while (loop)
{
adjust_loop_jumps_for_elimination (moo, &loop->break_ip_pool, start, end);
adjust_loop_jumps_for_elimination (moo, &loop->continue_ip_pool, start, end);
loop = loop->next;
}
}
static MOO_INLINE moo_loop_t* unlink_loop (moo_t* moo)
{
moo_loop_t* loop;
MOO_ASSERT (moo, moo->c->mth.loop != MOO_NULL);
loop = moo->c->mth.loop;
moo->c->mth.loop = loop->next;
return loop;
}
static MOO_INLINE void free_loop (moo_t* moo, moo_loop_t* loop)
{
fini_oow_pool (moo, &loop->continue_ip_pool);
fini_oow_pool (moo, &loop->break_ip_pool);
moo_freemem (moo, loop);
}
static MOO_INLINE void pop_loop (moo_t* moo)
{
free_loop (moo, unlink_loop (moo));
}
static MOO_INLINE int inject_break_to_loop (moo_t* moo)
{
if (add_to_oow_pool (moo, &moo->c->mth.loop->break_ip_pool, moo->c->mth.code.len) <= -1 ||
emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_0, MAX_CODE_JUMP) <= -1) return -1;
return 0;
}
static MOO_INLINE int inject_continue_to_loop (moo_t* moo)
{
if (add_to_oow_pool (moo, &moo->c->mth.loop->continue_ip_pool, moo->c->mth.code.len) <= -1 ||
emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_0, MAX_CODE_JUMP) <= -1) return -1;
return 0;
}
static void eliminate_instructions (moo_t* moo, moo_oow_t start, moo_oow_t end) static void eliminate_instructions (moo_t* moo, moo_oow_t start, moo_oow_t end)
{ {
moo_oow_t last; moo_oow_t last;
MOO_ASSERT (moo, moo->c->mth.code.len >= 1); 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; last = moo->c->mth.code.len - 1;
if (end >= last) if (end >= last)
{ {
/* eliminate all instructions starting from the start index. /* eliminate all instructions starting from the start index.
* setting the length to the start length will achieve this */ * setting the length to the start length will achieve this */
adjust_all_loop_jumps_for_elimination (moo, start, last);
moo->c->mth.code.len = start; moo->c->mth.code.len = start;
} }
else else
{ {
/* eliminate a chunk in the middle of the instruction buffer. /* eliminate a chunk in the middle of the instruction buffer.
* some copying is required */ * some copying is required */
if (end > last) end = last; adjust_all_loop_jumps_for_elimination (moo, start, end);
MOO_MEMMOVE (&moo->c->mth.code.ptr[start], &moo->c->mth.code.ptr[end + 1], moo->c->mth.code.len - end - 1); 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--; moo->c->mth.code.len -= end - start + 1;
} }
} }
@ -2252,7 +2378,6 @@ MOO_DEBUG2 (moo, "ELIMINATE INSTRUCTION FROM %zu TO %zu\n", start, end);
* Compiler * Compiler
* --------------------------------------------------------------------- */ * --------------------------------------------------------------------- */
static int add_literal (moo_t* moo, moo_oop_t lit, moo_oow_t* index) static int add_literal (moo_t* moo, moo_oop_t lit, moo_oow_t* index)
{ {
moo_oow_t i; moo_oow_t i;
@ -3480,89 +3605,6 @@ static int store_tmpr_count_for_block (moo_t* moo, moo_oow_t tmpr_count)
return 0; return 0;
} }
static int push_loop (moo_t* moo, moo_loop_type_t type, moo_oow_t startpos)
{
moo_loop_t* loop;
loop = moo_callocmem (moo, MOO_SIZEOF(*loop));
if (!loop) return -1;
init_oow_pool (moo, &loop->break_ip_pool);
init_oow_pool (moo, &loop->continue_ip_pool);
loop->type = type;
loop->startpos = startpos;
loop->next = moo->c->mth.loop;
moo->c->mth.loop = loop;
return 0;
}
static int update_loop_jumps (moo_t* moo, moo_oow_pool_t* pool, moo_oow_t jt)
{
/* patch the jump instructions emitted for 'break' */
moo_oow_pool_chunk_t* chunk;
moo_oow_t i, j;
for (chunk = pool->head, i = 0; chunk; chunk = chunk->next)
{
for (j = 0; j < MOO_COUNTOF(pool->static_chunk.buf) && i < pool->count; j++)
{
if (patch_long_forward_jump_instruction (moo, chunk->buf[j], jt, BCODE_JUMP2_FORWARD, MOO_NULL) <= -1) return -1;
i++;
}
}
return 0;
}
static MOO_INLINE int update_loop_breaks (moo_t* moo, moo_oow_t jt)
{
return update_loop_jumps (moo, &moo->c->mth.loop->break_ip_pool, jt);
}
static MOO_INLINE int update_loop_continues (moo_t* moo, moo_oow_t jt)
{
return update_loop_jumps (moo, &moo->c->mth.loop->continue_ip_pool, jt);
}
static MOO_INLINE moo_loop_t* unlink_loop (moo_t* moo)
{
moo_loop_t* loop;
MOO_ASSERT (moo, moo->c->mth.loop != MOO_NULL);
loop = moo->c->mth.loop;
moo->c->mth.loop = loop->next;
return loop;
}
static MOO_INLINE void free_loop (moo_t* moo, moo_loop_t* loop)
{
fini_oow_pool (moo, &loop->continue_ip_pool);
fini_oow_pool (moo, &loop->break_ip_pool);
moo_freemem (moo, loop);
}
static MOO_INLINE void pop_loop (moo_t* moo)
{
free_loop (moo, unlink_loop (moo));
}
static MOO_INLINE int inject_break_to_loop (moo_t* moo)
{
if (add_to_oow_pool (moo, &moo->c->mth.loop->break_ip_pool, moo->c->mth.code.len) <= -1 ||
emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_0, MAX_CODE_JUMP) <= -1) return -1;
return 0;
}
static MOO_INLINE int inject_continue_to_loop (moo_t* moo)
{
if (add_to_oow_pool (moo, &moo->c->mth.loop->continue_ip_pool, moo->c->mth.code.len) <= -1 ||
emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_0, MAX_CODE_JUMP) <= -1) return -1;
return 0;
}
static int compile_block_expression (moo_t* moo) static int compile_block_expression (moo_t* moo)
{ {
moo_oow_t jump_inst_pos; moo_oow_t jump_inst_pos;