Skip to content

Commit 98e8737

Browse files
Introducing interpreter run scopes.
JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan [email protected]
1 parent 48d012f commit 98e8737

File tree

9 files changed

+109
-27
lines changed

9 files changed

+109
-27
lines changed

jerry-core/parser/js/opcodes-dumper.cpp

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2262,18 +2262,61 @@ finish_dumping_case_clauses (void)
22622262
STACK_DROP (U8, 1);
22632263
}
22642264

2265+
/**
2266+
* Dump template of 'with' instruction.
2267+
*
2268+
* Note:
2269+
* the instruction's flags field is written later (see also: rewrite_with).
2270+
*
2271+
* @return position of dumped instruction
2272+
*/
2273+
opcode_counter_t
2274+
dump_with_for_rewrite (operand op) /**< operand - result of evaluating Expression
2275+
* in WithStatement */
2276+
{
2277+
opcode_counter_t oc = serializer_get_current_opcode_counter ();
2278+
2279+
if (op.type == OPERAND_LITERAL)
2280+
{
2281+
const opcode_t opcode = getop_with (LITERAL_TO_REWRITE, INVALID_VALUE, INVALID_VALUE);
2282+
serializer_dump_op_meta (create_op_meta_100 (opcode, op.data.lit_id));
2283+
}
2284+
else
2285+
{
2286+
JERRY_ASSERT (op.type == OPERAND_TMP);
2287+
2288+
const opcode_t opcode = getop_with (op.data.uid, INVALID_VALUE, INVALID_VALUE);
2289+
serializer_dump_op_meta (create_op_meta_000 (opcode));
2290+
}
2291+
2292+
return oc;
2293+
} /* dump_with_for_rewrite */
2294+
2295+
/**
2296+
* Write position of 'with' block's end to specified 'with' instruction template,
2297+
* dumped earlier (see also: dump_with_for_rewrite).
2298+
*/
22652299
void
2266-
dump_with (operand op)
2300+
rewrite_with (opcode_counter_t oc) /**< opcode counter of the instruction template */
22672301
{
2268-
dump_single_address (getop_with, op);
2269-
}
2302+
op_meta with_op_meta = serializer_get_op_meta (oc);
22702303

2304+
idx_t id1, id2;
2305+
split_opcode_counter (get_diff_from (oc), &id1, &id2);
2306+
with_op_meta.op.data.with.oc_idx_1 = id1;
2307+
with_op_meta.op.data.with.oc_idx_2 = id2;
2308+
serializer_rewrite_op_meta (oc, with_op_meta);
2309+
} /* rewrite_with */
2310+
2311+
/**
2312+
* Dump 'meta' instruction of 'end with' type
2313+
*/
22712314
void
22722315
dump_with_end (void)
22732316
{
22742317
const opcode_t opcode = getop_meta (OPCODE_META_TYPE_END_WITH, INVALID_VALUE, INVALID_VALUE);
22752318
serializer_dump_op_meta (create_op_meta_000 (opcode));
2276-
}
2319+
} /* dump_with_end */
22772320

22782321
void
22792322
dump_try_for_rewrite (void)

jerry-core/parser/js/opcodes-dumper.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,8 @@ operand dump_delete_res (operand, bool, locus);
202202
void dump_typeof (operand, operand);
203203
operand dump_typeof_res (operand);
204204

205-
void dump_with (operand);
205+
opcode_counter_t dump_with_for_rewrite (operand);
206+
void rewrite_with (opcode_counter_t);
206207
void dump_with_end (void);
207208

208209
void dump_try_for_rewrite (void);

jerry-core/parser/js/parser.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2022,9 +2022,10 @@ parse_with_statement (void)
20222022

20232023
push_nesting (NESTING_WITH);
20242024

2025-
dump_with (expr);
2025+
opcode_counter_t with_begin_oc = dump_with_for_rewrite (expr);
20262026
skip_newlines ();
20272027
parse_statement ();
2028+
rewrite_with (with_begin_oc);
20282029
dump_with_end ();
20292030

20302031
pop_nesting (NESTING_WITH);

jerry-core/vm/opcodes-ecma-try-catch-finally.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ opfunc_try_block (opcode_t opdata, /**< operation data */
3737

3838
int_data->pos++;
3939

40-
ecma_completion_value_t try_completion = vm_loop (int_data);
40+
vm_run_scope_t run_scope_try = { int_data->pos, try_end_oc };
41+
ecma_completion_value_t try_completion = vm_loop (int_data, &run_scope_try);
4142
JERRY_ASSERT ((!ecma_is_completion_value_empty (try_completion) && int_data->pos <= try_end_oc)
4243
|| (ecma_is_completion_value_empty (try_completion) && int_data->pos == try_end_oc));
4344
int_data->pos = try_end_oc;
@@ -87,7 +88,9 @@ opfunc_try_block (opcode_t opdata, /**< operation data */
8788
int_data->lex_env_p = catch_env_p;
8889

8990
ecma_free_completion_value (try_completion);
90-
try_completion = vm_loop (int_data);
91+
92+
vm_run_scope_t run_scope_catch = { int_data->pos, catch_end_oc };
93+
try_completion = vm_loop (int_data, &run_scope_catch);
9194

9295
int_data->lex_env_p = old_env_p;
9396

@@ -114,7 +117,9 @@ opfunc_try_block (opcode_t opdata, /**< operation data */
114117
read_meta_opcode_counter (OPCODE_META_TYPE_FINALLY, int_data) + int_data->pos);
115118
int_data->pos++;
116119

117-
ecma_completion_value_t finally_completion = vm_loop (int_data);
120+
vm_run_scope_t run_scope_finally = { int_data->pos, finally_end_oc };
121+
ecma_completion_value_t finally_completion = vm_loop (int_data, &run_scope_finally);
122+
118123
JERRY_ASSERT ((!ecma_is_completion_value_empty (finally_completion) && int_data->pos <= finally_end_oc)
119124
|| (ecma_is_completion_value_empty (finally_completion) && int_data->pos == finally_end_oc));
120125
int_data->pos = finally_end_oc;

jerry-core/vm/opcodes-varg.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ fill_varg_list (int_data_t *int_data, /**< interpreter context */
4040
arg_index < args_number;
4141
arg_index++)
4242
{
43-
ecma_completion_value_t evaluate_arg_completion = vm_loop (int_data);
43+
ecma_completion_value_t evaluate_arg_completion = vm_loop (int_data, NULL);
4444

4545
if (ecma_is_completion_value_normal (evaluate_arg_completion))
4646
{

jerry-core/vm/opcodes.cpp

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -912,7 +912,7 @@ opfunc_obj_decl (opcode_t opdata, /**< operation data */
912912
prop_index < args_number;
913913
prop_index++)
914914
{
915-
ecma_completion_value_t evaluate_prop_completion = vm_loop (int_data);
915+
ecma_completion_value_t evaluate_prop_completion = vm_loop (int_data, NULL);
916916

917917
if (ecma_is_completion_value_normal (evaluate_prop_completion))
918918
{
@@ -1299,6 +1299,10 @@ opfunc_with (opcode_t opdata, /**< operation data */
12991299
int_data_t *int_data) /**< interpreter context */
13001300
{
13011301
const idx_t expr_var_idx = opdata.data.with.expr;
1302+
const idx_t block_end_oc_idx_1 = opdata.data.with.oc_idx_1;
1303+
const idx_t block_end_oc_idx_2 = opdata.data.with.oc_idx_2;
1304+
const opcode_counter_t with_end_oc = (opcode_counter_t) (
1305+
calc_opcode_counter_from_idx_idx (block_end_oc_idx_1, block_end_oc_idx_2) + int_data->pos);
13021306

13031307
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
13041308

@@ -1321,23 +1325,29 @@ opfunc_with (opcode_t opdata, /**< operation data */
13211325
true);
13221326
int_data->lex_env_p = new_env_p;
13231327

1324-
ecma_completion_value_t evaluation_completion = vm_loop (int_data);
1328+
#ifndef JERRY_NDEBUG
1329+
opcode_t meta_opcode = vm_get_opcode (with_end_oc);
1330+
JERRY_ASSERT (meta_opcode.op_idx == __op__idx_meta);
1331+
JERRY_ASSERT (meta_opcode.data.meta.type == OPCODE_META_TYPE_END_WITH);
1332+
#endif /* !JERRY_NDEBUG */
13251333

1326-
if (ecma_is_completion_value_normal (evaluation_completion))
1327-
{
1328-
JERRY_ASSERT (ecma_is_completion_value_empty (evaluation_completion));
1334+
vm_run_scope_t run_scope_with = { int_data->pos, with_end_oc };
1335+
ecma_completion_value_t with_completion = vm_loop (int_data, &run_scope_with);
13291336

1330-
opcode_t meta_opcode = vm_get_opcode (int_data->pos);
1331-
JERRY_ASSERT (meta_opcode.op_idx == __op__idx_meta);
1332-
JERRY_ASSERT (meta_opcode.data.meta.type == OPCODE_META_TYPE_END_WITH);
1337+
if (ecma_is_completion_value_normal (with_completion))
1338+
{
1339+
JERRY_ASSERT (ecma_is_completion_value_empty (with_completion));
1340+
JERRY_ASSERT (int_data->pos == with_end_oc);
13331341

13341342
int_data->pos++;
13351343

13361344
ret_value = ecma_make_empty_completion_value ();
13371345
}
13381346
else
13391347
{
1340-
ret_value = evaluation_completion;
1348+
JERRY_ASSERT (int_data->pos <= with_end_oc);
1349+
1350+
ret_value = with_completion;
13411351
}
13421352

13431353
int_data->lex_env_p = old_env_p;

jerry-core/vm/opcodes.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,22 @@ typedef struct
113113
#endif /* MEM_STATS */
114114
} int_data_t;
115115

116+
/**
117+
* Description of a run scope
118+
*
119+
* Note:
120+
* Run scope represents boundaries of byte-code block to run.
121+
*
122+
* Jumps within of the current run scope are performed by just changing opcode counter,
123+
* and outside of the run scope - by returning corresponding ECMA_COMPLETION_TYPE_BREAK_CONTINUE
124+
* completion value.
125+
*/
126+
typedef struct
127+
{
128+
const opcode_counter_t start_oc; /**< opcode counter of the first instruction of the scope */
129+
const opcode_counter_t end_oc; /**< opcode counter of the last instruction of the scope */
130+
} vm_run_scope_t;
131+
116132
opcode_counter_t calc_opcode_counter_from_idx_idx (const idx_t oc_idx_1, const idx_t oc_idx_2);
117133
opcode_counter_t read_meta_opcode_counter (opcode_meta_type expected_type, int_data_t *int_data);
118134

@@ -135,7 +151,7 @@ opcode_counter_t read_meta_opcode_counter (opcode_meta_type expected_type, int_d
135151
p##_2 (a, delete_var, lhs, name) \
136152
p##_3 (a, delete_prop, lhs, base, name) \
137153
p##_2 (a, typeof, lhs, obj) \
138-
p##_1 (a, with, expr) \
154+
p##_3 (a, with, expr, oc_idx_1, oc_idx_2) \
139155
p##_2 (a, try_block, oc_idx_1, oc_idx_2) \
140156
p##_1 (a, throw_value, var)
141157

jerry-core/vm/vm.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,9 @@ vm_run_global (void)
423423
* Otherwise - the completion value is discarded and normal empty completion value is returned.
424424
*/
425425
ecma_completion_value_t
426-
vm_loop (int_data_t *int_data) /**< interpreter context */
426+
vm_loop (int_data_t *int_data_p, /**< interpreter context */
427+
vm_run_scope_t *run_scope_p) /**< current run scope,
428+
* or NULL - if there is no active run scope */
427429
{
428430
ecma_completion_value_t completion;
429431

@@ -439,24 +441,28 @@ vm_loop (int_data_t *int_data) /**< interpreter context */
439441
{
440442
do
441443
{
442-
const opcode_t *curr = &__program[int_data->pos];
444+
JERRY_ASSERT (run_scope_p == NULL
445+
|| (run_scope_p->start_oc <= int_data_p->pos
446+
&& int_data_p->pos <= run_scope_p->end_oc));
447+
448+
const opcode_t *curr = &__program[int_data_p->pos];
443449

444450
#ifdef MEM_STATS
445-
const opcode_counter_t opcode_pos = int_data->pos;
451+
const opcode_counter_t opcode_pos = int_data_p->pos;
446452

447453
interp_mem_stats_opcode_enter (opcode_pos,
448454
&heap_stats_before,
449455
&pools_stats_before);
450456
#endif /* MEM_STATS */
451457

452-
completion = __opfuncs[curr->op_idx] (*curr, int_data);
458+
completion = __opfuncs[curr->op_idx] (*curr, int_data_p);
453459

454460
#ifdef CONFIG_VM_RUN_GC_AFTER_EACH_OPCODE
455461
ecma_gc_run ();
456462
#endif /* CONFIG_VM_RUN_GC_AFTER_EACH_OPCODE */
457463

458464
#ifdef MEM_STATS
459-
interp_mem_stats_opcode_exit (int_data,
465+
interp_mem_stats_opcode_exit (int_data_p,
460466
opcode_pos,
461467
&heap_stats_before,
462468
&pools_stats_before);
@@ -525,7 +531,7 @@ vm_run_from_pos (opcode_counter_t start_pos, /**< identifier of starting opcode
525531
interp_mem_stats_context_enter (&int_data, start_pos);
526532
#endif /* MEM_STATS */
527533

528-
completion = vm_loop (&int_data);
534+
completion = vm_loop (&int_data, NULL);
529535

530536
JERRY_ASSERT (ecma_is_completion_value_normal (completion)
531537
|| ecma_is_completion_value_throw (completion)

jerry-core/vm/vm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
extern void vm_init (const opcode_t* program_p, bool dump_mem_stats);
2424
extern jerry_completion_code_t vm_run_global (void);
25-
extern ecma_completion_value_t vm_loop (int_data_t *int_data);
25+
extern ecma_completion_value_t vm_loop (int_data_t *int_data, vm_run_scope_t *run_scope_p);
2626
extern ecma_completion_value_t vm_run_from_pos (opcode_counter_t start_pos,
2727
ecma_value_t this_binding_value,
2828
ecma_object_t *lex_env_p,

0 commit comments

Comments
 (0)