Introducing interpreter run scopes.
JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan r.ayrapetyan@samsung.com
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user