Introducing interpreter run scopes.

JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan r.ayrapetyan@samsung.com
This commit is contained in:
Ruben Ayrapetyan
2015-06-02 17:04:18 +03:00
parent 712f8b0c9a
commit 8433df3097
9 changed files with 110 additions and 28 deletions
+48 -5
View File
@@ -2262,18 +2262,61 @@ finish_dumping_case_clauses (void)
STACK_DROP (U8, 1);
}
void
dump_with (operand op)
/**
* Dump template of 'with' instruction.
*
* Note:
* the instruction's flags field is written later (see also: rewrite_with).
*
* @return position of dumped instruction
*/
opcode_counter_t
dump_with_for_rewrite (operand op) /**< operand - result of evaluating Expression
* in WithStatement */
{
dump_single_address (getop_with, op);
}
opcode_counter_t oc = serializer_get_current_opcode_counter ();
if (op.type == OPERAND_LITERAL)
{
const opcode_t opcode = getop_with (LITERAL_TO_REWRITE, INVALID_VALUE, INVALID_VALUE);
serializer_dump_op_meta (create_op_meta_100 (opcode, op.data.lit_id));
}
else
{
JERRY_ASSERT (op.type == OPERAND_TMP);
const opcode_t opcode = getop_with (op.data.uid, INVALID_VALUE, INVALID_VALUE);
serializer_dump_op_meta (create_op_meta_000 (opcode));
}
return oc;
} /* dump_with_for_rewrite */
/**
* Write position of 'with' block's end to specified 'with' instruction template,
* dumped earlier (see also: dump_with_for_rewrite).
*/
void
rewrite_with (opcode_counter_t oc) /**< opcode counter of the instruction template */
{
op_meta with_op_meta = serializer_get_op_meta (oc);
idx_t id1, id2;
split_opcode_counter (get_diff_from (oc), &id1, &id2);
with_op_meta.op.data.with.oc_idx_1 = id1;
with_op_meta.op.data.with.oc_idx_2 = id2;
serializer_rewrite_op_meta (oc, with_op_meta);
} /* rewrite_with */
/**
* Dump 'meta' instruction of 'end with' type
*/
void
dump_with_end (void)
{
const opcode_t opcode = getop_meta (OPCODE_META_TYPE_END_WITH, INVALID_VALUE, INVALID_VALUE);
serializer_dump_op_meta (create_op_meta_000 (opcode));
}
} /* dump_with_end */
void
dump_try_for_rewrite (void)
+2 -1
View File
@@ -202,7 +202,8 @@ operand dump_delete_res (operand, bool, locus);
void dump_typeof (operand, operand);
operand dump_typeof_res (operand);
void dump_with (operand);
opcode_counter_t dump_with_for_rewrite (operand);
void rewrite_with (opcode_counter_t);
void dump_with_end (void);
void dump_try_for_rewrite (void);
+2 -1
View File
@@ -2022,9 +2022,10 @@ parse_with_statement (void)
push_nesting (NESTING_WITH);
dump_with (expr);
opcode_counter_t with_begin_oc = dump_with_for_rewrite (expr);
skip_newlines ();
parse_statement ();
rewrite_with (with_begin_oc);
dump_with_end ();
pop_nesting (NESTING_WITH);
@@ -37,7 +37,8 @@ opfunc_try_block (opcode_t opdata, /**< operation data */
int_data->pos++;
ecma_completion_value_t try_completion = vm_loop (int_data);
vm_run_scope_t run_scope_try = { int_data->pos, try_end_oc };
ecma_completion_value_t try_completion = vm_loop (int_data, &run_scope_try);
JERRY_ASSERT ((!ecma_is_completion_value_empty (try_completion) && int_data->pos <= try_end_oc)
|| (ecma_is_completion_value_empty (try_completion) && int_data->pos == try_end_oc));
int_data->pos = try_end_oc;
@@ -87,7 +88,9 @@ opfunc_try_block (opcode_t opdata, /**< operation data */
int_data->lex_env_p = catch_env_p;
ecma_free_completion_value (try_completion);
try_completion = vm_loop (int_data);
vm_run_scope_t run_scope_catch = { int_data->pos, catch_end_oc };
try_completion = vm_loop (int_data, &run_scope_catch);
int_data->lex_env_p = old_env_p;
@@ -114,7 +117,9 @@ opfunc_try_block (opcode_t opdata, /**< operation data */
read_meta_opcode_counter (OPCODE_META_TYPE_FINALLY, int_data) + int_data->pos);
int_data->pos++;
ecma_completion_value_t finally_completion = vm_loop (int_data);
vm_run_scope_t run_scope_finally = { int_data->pos, finally_end_oc };
ecma_completion_value_t finally_completion = vm_loop (int_data, &run_scope_finally);
JERRY_ASSERT ((!ecma_is_completion_value_empty (finally_completion) && int_data->pos <= finally_end_oc)
|| (ecma_is_completion_value_empty (finally_completion) && int_data->pos == finally_end_oc));
int_data->pos = finally_end_oc;
+1 -1
View File
@@ -40,7 +40,7 @@ fill_varg_list (int_data_t *int_data, /**< interpreter context */
arg_index < args_number;
arg_index++)
{
ecma_completion_value_t evaluate_arg_completion = vm_loop (int_data);
ecma_completion_value_t evaluate_arg_completion = vm_loop (int_data, NULL);
if (ecma_is_completion_value_normal (evaluate_arg_completion))
{
+19 -9
View File
@@ -912,7 +912,7 @@ opfunc_obj_decl (opcode_t opdata, /**< operation data */
prop_index < args_number;
prop_index++)
{
ecma_completion_value_t evaluate_prop_completion = vm_loop (int_data);
ecma_completion_value_t evaluate_prop_completion = vm_loop (int_data, NULL);
if (ecma_is_completion_value_normal (evaluate_prop_completion))
{
@@ -1299,6 +1299,10 @@ opfunc_with (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t expr_var_idx = opdata.data.with.expr;
const idx_t block_end_oc_idx_1 = opdata.data.with.oc_idx_1;
const idx_t block_end_oc_idx_2 = opdata.data.with.oc_idx_2;
const opcode_counter_t with_end_oc = (opcode_counter_t) (
calc_opcode_counter_from_idx_idx (block_end_oc_idx_1, block_end_oc_idx_2) + int_data->pos);
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
@@ -1321,15 +1325,19 @@ opfunc_with (opcode_t opdata, /**< operation data */
true);
int_data->lex_env_p = new_env_p;
ecma_completion_value_t evaluation_completion = vm_loop (int_data);
#ifndef JERRY_NDEBUG
opcode_t meta_opcode = vm_get_opcode (with_end_oc);
JERRY_ASSERT (meta_opcode.op_idx == __op__idx_meta);
JERRY_ASSERT (meta_opcode.data.meta.type == OPCODE_META_TYPE_END_WITH);
#endif /* !JERRY_NDEBUG */
if (ecma_is_completion_value_normal (evaluation_completion))
vm_run_scope_t run_scope_with = { int_data->pos, with_end_oc };
ecma_completion_value_t with_completion = vm_loop (int_data, &run_scope_with);
if (ecma_is_completion_value_normal (with_completion))
{
JERRY_ASSERT (ecma_is_completion_value_empty (evaluation_completion));
opcode_t meta_opcode = vm_get_opcode (int_data->pos);
JERRY_ASSERT (meta_opcode.op_idx == __op__idx_meta);
JERRY_ASSERT (meta_opcode.data.meta.type == OPCODE_META_TYPE_END_WITH);
JERRY_ASSERT (ecma_is_completion_value_empty (with_completion));
JERRY_ASSERT (int_data->pos == with_end_oc);
int_data->pos++;
@@ -1337,7 +1345,9 @@ opfunc_with (opcode_t opdata, /**< operation data */
}
else
{
ret_value = evaluation_completion;
JERRY_ASSERT (int_data->pos <= with_end_oc);
ret_value = with_completion;
}
int_data->lex_env_p = old_env_p;
+17 -1
View File
@@ -113,6 +113,22 @@ typedef struct
#endif /* MEM_STATS */
} int_data_t;
/**
* Description of a run scope
*
* Note:
* Run scope represents boundaries of byte-code block to run.
*
* Jumps within of the current run scope are performed by just changing opcode counter,
* and outside of the run scope - by returning corresponding ECMA_COMPLETION_TYPE_BREAK_CONTINUE
* completion value.
*/
typedef struct
{
const opcode_counter_t start_oc; /**< opcode counter of the first instruction of the scope */
const opcode_counter_t end_oc; /**< opcode counter of the last instruction of the scope */
} vm_run_scope_t;
opcode_counter_t calc_opcode_counter_from_idx_idx (const idx_t oc_idx_1, const idx_t oc_idx_2);
opcode_counter_t read_meta_opcode_counter (opcode_meta_type expected_type, int_data_t *int_data);
@@ -135,7 +151,7 @@ opcode_counter_t read_meta_opcode_counter (opcode_meta_type expected_type, int_d
p##_2 (a, delete_var, lhs, name) \
p##_3 (a, delete_prop, lhs, base, name) \
p##_2 (a, typeof, lhs, obj) \
p##_1 (a, with, expr) \
p##_3 (a, with, expr, oc_idx_1, oc_idx_2) \
p##_2 (a, try_block, oc_idx_1, oc_idx_2) \
p##_1 (a, throw_value, var)
+12 -6
View File
@@ -423,7 +423,9 @@ vm_run_global (void)
* Otherwise - the completion value is discarded and normal empty completion value is returned.
*/
ecma_completion_value_t
vm_loop (int_data_t *int_data) /**< interpreter context */
vm_loop (int_data_t *int_data_p, /**< interpreter context */
vm_run_scope_t *run_scope_p) /**< current run scope,
* or NULL - if there is no active run scope */
{
ecma_completion_value_t completion;
@@ -439,24 +441,28 @@ vm_loop (int_data_t *int_data) /**< interpreter context */
{
do
{
const opcode_t *curr = &__program[int_data->pos];
JERRY_ASSERT (run_scope_p == NULL
|| (run_scope_p->start_oc <= int_data_p->pos
&& int_data_p->pos <= run_scope_p->end_oc));
const opcode_t *curr = &__program[int_data_p->pos];
#ifdef MEM_STATS
const opcode_counter_t opcode_pos = int_data->pos;
const opcode_counter_t opcode_pos = int_data_p->pos;
interp_mem_stats_opcode_enter (opcode_pos,
&heap_stats_before,
&pools_stats_before);
#endif /* MEM_STATS */
completion = __opfuncs[curr->op_idx] (*curr, int_data);
completion = __opfuncs[curr->op_idx] (*curr, int_data_p);
#ifdef CONFIG_VM_RUN_GC_AFTER_EACH_OPCODE
ecma_gc_run ();
#endif /* CONFIG_VM_RUN_GC_AFTER_EACH_OPCODE */
#ifdef MEM_STATS
interp_mem_stats_opcode_exit (int_data,
interp_mem_stats_opcode_exit (int_data_p,
opcode_pos,
&heap_stats_before,
&pools_stats_before);
@@ -525,7 +531,7 @@ vm_run_from_pos (opcode_counter_t start_pos, /**< identifier of starting opcode
interp_mem_stats_context_enter (&int_data, start_pos);
#endif /* MEM_STATS */
completion = vm_loop (&int_data);
completion = vm_loop (&int_data, NULL);
JERRY_ASSERT (ecma_is_completion_value_normal (completion)
|| ecma_is_completion_value_throw (completion)
+1 -1
View File
@@ -22,7 +22,7 @@
extern void vm_init (const opcode_t* program_p, bool dump_mem_stats);
extern jerry_completion_code_t vm_run_global (void);
extern ecma_completion_value_t vm_loop (int_data_t *int_data);
extern ecma_completion_value_t vm_loop (int_data_t *int_data, vm_run_scope_t *run_scope_p);
extern ecma_completion_value_t vm_run_from_pos (opcode_counter_t start_pos,
ecma_value_t this_binding_value,
ecma_object_t *lex_env_p,