Skip to content

Commit 50ef3eb

Browse files
Replacing 'this_arg' meta opcode with more general 'call site additional information' meta opcode with flags describing the call site features, and, optionally, 'this' argument.
Introducing opcode_call_flags_t for argument of the new meta opcode, currently with two flags: 'have this argument' and '"direct call to eval" form'. JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan [email protected]
1 parent d80063b commit 50ef3eb

File tree

7 files changed

+149
-49
lines changed

7 files changed

+149
-49
lines changed

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

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,27 @@ dump_intrinsic (operand obj, operand arg)
764764
return dump_undefined_assignment_res ();
765765
}
766766

767+
/**
768+
* Check that byte-code operand refers to 'eval' string
769+
*
770+
* @return true - if specified byte-code operand's type is literal, and value of corresponding
771+
* literal is equal to ECMA_MAGIC_STRING_EVAL string,
772+
* false - otherwise.
773+
*/
774+
bool
775+
dumper_is_eval_literal (operand obj) /**< byte-code operand */
776+
{
777+
/*
778+
* FIXME: Switch to corresponding magic string
779+
*/
780+
const ecma_char_t *eval_string_p = (const ecma_char_t *) "eval";
781+
bool is_eval_lit = (obj.type == OPERAND_LITERAL
782+
&& lit_literal_equal_type_zt (lit_get_literal_by_cp (obj.data.lit_id),
783+
eval_string_p));
784+
785+
return is_eval_lit;
786+
} /* dumper_is_eval_literal */
787+
767788
void
768789
dump_boolean_assignment (operand op, bool is_true)
769790
{
@@ -1077,14 +1098,30 @@ rewrite_varg_header_set_args_count (uint8_t args_count)
10771098
}
10781099
}
10791100

1101+
/**
1102+
* Dump 'meta' instruction of 'call additional information' type,
1103+
* containing call flags and, optionally, 'this' argument
1104+
*/
10801105
void
1081-
dump_this_arg (operand this_arg)
1106+
dump_call_additional_info (opcode_call_flags_t flags, /**< call flags */
1107+
operand this_arg) /**< 'this' argument - if flags include OPCODE_CALL_FLAGS_HAVE_THIS_ARG,
1108+
* or empty operand - otherwise */
10821109
{
1083-
JERRY_ASSERT (this_arg.type == OPERAND_TMP);
1084-
const opcode_t opcode = getop_meta (OPCODE_META_TYPE_THIS_ARG, this_arg.data.uid, INVALID_VALUE);
1110+
if (flags & OPCODE_CALL_FLAGS_HAVE_THIS_ARG)
1111+
{
1112+
JERRY_ASSERT (this_arg.type == OPERAND_TMP);
1113+
JERRY_ASSERT (!operand_is_empty (this_arg));
1114+
}
1115+
else
1116+
{
1117+
JERRY_ASSERT (operand_is_empty (this_arg));
1118+
}
1119+
1120+
const opcode_t opcode = getop_meta (OPCODE_META_TYPE_CALL_SITE_INFO,
1121+
flags,
1122+
(flags & OPCODE_CALL_FLAGS_HAVE_THIS_ARG) ? this_arg.data.uid : INVALID_VALUE);
10851123
serializer_dump_op_meta (create_op_meta_000 (opcode));
1086-
return;
1087-
}
1124+
} /* dump_call_additional_info */
10881125

10891126
void
10901127
dump_varg (operand op)

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ void dumper_finish_scope (void);
6161
bool dumper_is_intrinsic (operand);
6262
operand dump_intrinsic (operand, operand);
6363

64+
extern bool dumper_is_eval_literal (operand);
65+
6466
void dump_boolean_assignment (operand, bool);
6567
operand dump_boolean_assignment_res (bool);
6668
void dump_string_assignment (operand, lit_cpointer_t);
@@ -78,7 +80,7 @@ operand dump_variable_assignment_res (operand);
7880

7981
void dump_varg_header_for_rewrite (varg_list_type, operand);
8082
operand rewrite_varg_header_set_args_count (uint8_t);
81-
void dump_this_arg (operand);
83+
void dump_call_additional_info (opcode_call_flags_t, operand);
8284
void dump_varg (operand);
8385

8486
void dump_prop_name_and_value (operand, operand);

jerry-core/parser/js/parser.cpp

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -299,11 +299,13 @@ parse_property_assignment (void)
299299
For each ALT dumps appropriate bytecode. Uses OBJ during dump if neccesary.
300300
Result tmp. */
301301
static operand
302-
parse_argument_list (varg_list_type vlt, operand obj, uint8_t *args_count, operand *this_arg)
302+
parse_argument_list (varg_list_type vlt, operand obj, uint8_t *args_count, operand *this_arg_p)
303303
{
304304
token_type close_tt = TOK_CLOSE_PAREN;
305305
uint8_t args_num = 0;
306306

307+
JERRY_ASSERT (!(vlt != VARG_CALL_EXPR && this_arg_p != NULL));
308+
307309
switch (vlt)
308310
{
309311
case VARG_FUNC_DECL:
@@ -325,11 +327,58 @@ parse_argument_list (varg_list_type vlt, operand obj, uint8_t *args_count, opera
325327
{
326328
break;
327329
}
328-
if (this_arg != NULL && this_arg->type == OPERAND_LITERAL)
330+
331+
opcode_call_flags_t call_flags = OPCODE_CALL_FLAGS__EMPTY;
332+
333+
operand this_arg = empty_operand ();
334+
if (this_arg_p != NULL
335+
&& !operand_is_empty (*this_arg_p))
329336
{
330-
*this_arg = dump_variable_assignment_res (*this_arg);
337+
call_flags = (opcode_call_flags_t) (call_flags | OPCODE_CALL_FLAGS_HAVE_THIS_ARG);
338+
339+
if (this_arg_p->type == OPERAND_LITERAL)
340+
{
341+
/*
342+
* FIXME:
343+
* Base of CallExpression should be evaluated only once during evaluation of CallExpression
344+
*
345+
* See also:
346+
* Evaluation of MemberExpression (ECMA-262 v5, 11.2.1)
347+
*/
348+
this_arg = dump_variable_assignment_res (*this_arg_p);
349+
}
350+
else
351+
{
352+
this_arg = *this_arg_p;
353+
}
354+
355+
/*
356+
* Presence of explicit 'this' argument implies that it is not Direct call to Eval
357+
*
358+
* See also:
359+
* ECMA-262 v5, 15.2.2.1
360+
*/
331361
}
362+
else if (dumper_is_eval_literal (obj))
363+
{
364+
call_flags = (opcode_call_flags_t) (call_flags | OPCODE_CALL_FLAGS_DIRECT_CALL_TO_EVAL_FORM);
365+
}
366+
332367
dump_varg_header_for_rewrite (vlt, obj);
368+
369+
if (call_flags != OPCODE_CALL_FLAGS__EMPTY)
370+
{
371+
if (call_flags & OPCODE_CALL_FLAGS_HAVE_THIS_ARG)
372+
{
373+
JERRY_ASSERT (!operand_is_empty (this_arg));
374+
dump_call_additional_info (call_flags, this_arg);
375+
}
376+
else
377+
{
378+
dump_call_additional_info (call_flags, empty_operand ());
379+
}
380+
}
381+
333382
break;
334383
}
335384
case VARG_ARRAY_DECL:
@@ -348,11 +397,6 @@ parse_argument_list (varg_list_type vlt, operand obj, uint8_t *args_count, opera
348397
break;
349398
}
350399
}
351-
if (vlt == VARG_CALL_EXPR && this_arg != NULL && !operand_is_empty (*this_arg))
352-
{
353-
dump_this_arg (*this_arg);
354-
args_num++;
355-
}
356400

357401
skip_newlines ();
358402
while (!token_is (close_tt))

jerry-core/parser/js/scopes-tree.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,6 @@ generate_opcode (scopes_tree tree, opcode_counter_t opc_index, lit_id_hash_table
338338
change_uid (om, lit_ids, 0x011);
339339
break;
340340
}
341-
case OPCODE_META_TYPE_THIS_ARG:
342341
case OPCODE_META_TYPE_VARG:
343342
case OPCODE_META_TYPE_CATCH_EXCEPTION_IDENTIFIER:
344343
{
@@ -351,6 +350,7 @@ generate_opcode (scopes_tree tree, opcode_counter_t opc_index, lit_id_hash_table
351350
case OPCODE_META_TYPE_CATCH:
352351
case OPCODE_META_TYPE_FINALLY:
353352
case OPCODE_META_TYPE_END_TRY_CATCH_FINALLY:
353+
case OPCODE_META_TYPE_CALL_SITE_INFO:
354354
case OPCODE_META_TYPE_SCOPE_CODE_FLAGS:
355355
{
356356
change_uid (om, lit_ids, 0x000);
@@ -477,7 +477,6 @@ count_new_literals_in_opcode (scopes_tree tree, opcode_counter_t opc_index)
477477
insert_uids_to_lit_id_map (om, 0x011);
478478
break;
479479
}
480-
case OPCODE_META_TYPE_THIS_ARG:
481480
case OPCODE_META_TYPE_VARG:
482481
case OPCODE_META_TYPE_CATCH_EXCEPTION_IDENTIFIER:
483482
{
@@ -490,6 +489,7 @@ count_new_literals_in_opcode (scopes_tree tree, opcode_counter_t opc_index)
490489
case OPCODE_META_TYPE_CATCH:
491490
case OPCODE_META_TYPE_FINALLY:
492491
case OPCODE_META_TYPE_END_TRY_CATCH_FINALLY:
492+
case OPCODE_META_TYPE_CALL_SITE_INFO:
493493
case OPCODE_META_TYPE_SCOPE_CODE_FLAGS:
494494
{
495495
insert_uids_to_lit_id_map (om, 0x000);

jerry-core/vm/opcodes.cpp

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -652,44 +652,40 @@ opfunc_call_n (opcode_t opdata, /**< operation data */
652652

653653
int_data->pos++;
654654

655-
bool this_arg_var_idx_set = false;
656655
idx_t this_arg_var_idx = INVALID_VALUE;
657-
idx_t args_number;
656+
657+
opcode_call_flags_t call_flags = OPCODE_CALL_FLAGS__EMPTY;
658658

659659
opcode_t next_opcode = vm_get_opcode (int_data->opcodes_p, int_data->pos);
660660
if (next_opcode.op_idx == __op__idx_meta
661-
&& next_opcode.data.meta.type == OPCODE_META_TYPE_THIS_ARG)
661+
&& next_opcode.data.meta.type == OPCODE_META_TYPE_CALL_SITE_INFO)
662662
{
663-
this_arg_var_idx = next_opcode.data.meta.data_1;
664-
JERRY_ASSERT (is_reg_variable (int_data, this_arg_var_idx));
665-
666-
this_arg_var_idx_set = true;
663+
call_flags = (opcode_call_flags_t) next_opcode.data.meta.data_1;
667664

668-
JERRY_ASSERT (args_number_idx > 0);
669-
args_number = (idx_t) (args_number_idx - 1);
665+
if (call_flags & OPCODE_CALL_FLAGS_HAVE_THIS_ARG)
666+
{
667+
this_arg_var_idx = next_opcode.data.meta.data_2;
668+
JERRY_ASSERT (is_reg_variable (int_data, this_arg_var_idx));
669+
}
670670

671671
int_data->pos++;
672672
}
673-
else
674-
{
675-
args_number = args_number_idx;
676-
}
677673

678-
MEM_DEFINE_LOCAL_ARRAY (arg_values, args_number, ecma_value_t);
674+
MEM_DEFINE_LOCAL_ARRAY (arg_values, args_number_idx, ecma_value_t);
679675

680676
ecma_length_t args_read;
681677
ecma_completion_value_t get_arg_completion = fill_varg_list (int_data,
682-
args_number,
678+
args_number_idx,
683679
arg_values,
684680
&args_read);
685681

686682
if (ecma_is_completion_value_empty (get_arg_completion))
687683
{
688-
JERRY_ASSERT (args_read == args_number);
684+
JERRY_ASSERT (args_read == args_number_idx);
689685

690686
ecma_completion_value_t get_this_completion_value;
691687

692-
if (this_arg_var_idx_set)
688+
if (call_flags & OPCODE_CALL_FLAGS_HAVE_THIS_ARG)
693689
{
694690
get_this_completion_value = get_variable_value (int_data, this_arg_var_idx, false);
695691
}
@@ -713,7 +709,7 @@ opfunc_call_n (opcode_t opdata, /**< operation data */
713709
ecma_op_function_call (func_obj_p,
714710
this_value,
715711
arg_values,
716-
args_number),
712+
args_number_idx),
717713
ret_value);
718714

719715
ret_value = set_variable_value (int_data, lit_oc,
@@ -1679,7 +1675,7 @@ opfunc_meta (opcode_t opdata, /**< operation data */
16791675

16801676
case OPCODE_META_TYPE_SCOPE_CODE_FLAGS:
16811677
case OPCODE_META_TYPE_UNDEFINED:
1682-
case OPCODE_META_TYPE_THIS_ARG:
1678+
case OPCODE_META_TYPE_CALL_SITE_INFO:
16831679
case OPCODE_META_TYPE_FUNCTION_END:
16841680
case OPCODE_META_TYPE_CATCH_EXCEPTION_IDENTIFIER:
16851681
{

jerry-core/vm/opcodes.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ typedef enum
5959
typedef enum
6060
{
6161
OPCODE_META_TYPE_UNDEFINED, /**< undefined meta (should be rewritten) */
62-
OPCODE_META_TYPE_THIS_ARG, /**< value (var_idx) of this used during call */
62+
OPCODE_META_TYPE_CALL_SITE_INFO, /**< optional additional information about call site
63+
* (includes opcode_call_flags_t and can include 'this' argument) */
6364
OPCODE_META_TYPE_VARG, /**< element (var_idx) of arguments' list */
6465
OPCODE_META_TYPE_VARG_PROP_DATA, /**< name (lit_idx) and value (var_idx) for a data property descriptor */
6566
OPCODE_META_TYPE_VARG_PROP_GETTER, /**< name (lit_idx) and getter (var_idx) for an accessor property descriptor */
@@ -74,6 +75,17 @@ typedef enum
7475
* (See also: opcode_scope_code_flags_t) */
7576
} opcode_meta_type;
7677

78+
typedef enum : idx_t
79+
{
80+
OPCODE_CALL_FLAGS__EMPTY = (0u), /**< initializer for empty flag set */
81+
OPCODE_CALL_FLAGS_HAVE_THIS_ARG = (1u << 0), /**< flag, indicating that call is performed
82+
* with 'this' argument specified */
83+
OPCODE_CALL_FLAGS_DIRECT_CALL_TO_EVAL_FORM = (1u << 1) /**< flag, indicating that call is performed
84+
* in form 'eval (...)', i.e. through 'eval' string
85+
* without object base (i.e. with lexical environment
86+
* as base), so it can be a direct call to eval */
87+
} opcode_call_flags_t;
88+
7789
/**
7890
* Flags indicating various properties of a scope's code
7991
*/

jerry-core/vm/pretty-printer.cpp

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -266,15 +266,9 @@ pp_op_meta (opcode_counter_t oc, op_meta opm, bool rewrite)
266266
}
267267
case NAME_TO_ID (call_n):
268268
{
269-
if (opm.op.data.call_n.arg_list == 0)
270-
{
271-
pp_printf ("%s = %s ();", opm.op, opm.lit_id, oc, 1);
272-
}
273-
else
274-
{
275-
vargs_num = opm.op.data.call_n.arg_list;
276-
seen_vargs = 0;
277-
}
269+
vargs_num = opm.op.data.call_n.arg_list;
270+
seen_vargs = 0;
271+
278272
break;
279273
}
280274
case NAME_TO_ID (native_call):
@@ -381,13 +375,17 @@ pp_op_meta (opcode_counter_t oc, op_meta opm, bool rewrite)
381375
printf ("unknown meta;");
382376
break;
383377
}
384-
case OPCODE_META_TYPE_THIS_ARG:
378+
case OPCODE_META_TYPE_CALL_SITE_INFO:
385379
case OPCODE_META_TYPE_VARG:
386380
case OPCODE_META_TYPE_VARG_PROP_DATA:
387381
case OPCODE_META_TYPE_VARG_PROP_GETTER:
388382
case OPCODE_META_TYPE_VARG_PROP_SETTER:
389383
{
390-
seen_vargs++;
384+
if (opm.op.data.meta.type != OPCODE_META_TYPE_CALL_SITE_INFO)
385+
{
386+
seen_vargs++;
387+
}
388+
391389
if (seen_vargs == vargs_num)
392390
{
393391
bool found = false;
@@ -473,15 +471,26 @@ pp_op_meta (opcode_counter_t oc, op_meta opm, bool rewrite)
473471
for (opcode_counter_t counter = start; counter <= oc; counter++)
474472
{
475473
opcode_t meta_op = serializer_get_opcode (counter);
474+
476475
switch (meta_op.op_idx)
477476
{
478477
case NAME_TO_ID (meta):
479478
{
480479
switch (meta_op.data.meta.type)
481480
{
482-
case OPCODE_META_TYPE_THIS_ARG:
481+
case OPCODE_META_TYPE_CALL_SITE_INFO:
483482
{
484-
pp_printf ("this_arg = %s", meta_op, NULL, counter, 2);
483+
opcode_call_flags_t call_flags = (opcode_call_flags_t) meta_op.data.meta.data_1;
484+
485+
if (call_flags & OPCODE_CALL_FLAGS_HAVE_THIS_ARG)
486+
{
487+
pp_printf ("this_arg = %s", meta_op, NULL, counter, 3);
488+
}
489+
if (call_flags & OPCODE_CALL_FLAGS_DIRECT_CALL_TO_EVAL_FORM)
490+
{
491+
printf ("['direct call to eval' form]");
492+
}
493+
485494
break;
486495
}
487496
case OPCODE_META_TYPE_VARG:

0 commit comments

Comments
 (0)