diff --git a/jerry-core/parser/js/opcodes-dumper.cpp b/jerry-core/parser/js/opcodes-dumper.cpp index e2ea1b0cb..7faef75d6 100644 --- a/jerry-core/parser/js/opcodes-dumper.cpp +++ b/jerry-core/parser/js/opcodes-dumper.cpp @@ -2383,11 +2383,27 @@ dump_variable_declaration (literal_index_t lit_id) serializer_dump_op_meta (create_op_meta_100 (opcode, lit_id)); } -void -dump_strict_mode_header (void) +opcode_counter_t +dump_scope_code_flags_for_rewrite (void) { - const opcode_t opcode = getop_meta (OPCODE_META_TYPE_STRICT_CODE, INVALID_VALUE, INVALID_VALUE); + opcode_counter_t oc = serializer_get_current_opcode_counter (); + + const opcode_t opcode = getop_meta (OPCODE_META_TYPE_SCOPE_CODE_FLAGS, INVALID_VALUE, INVALID_VALUE); serializer_dump_op_meta (create_op_meta_000 (opcode)); + + return oc; +} + +void +rewrite_scope_code_flags (opcode_counter_t scope_code_flags_oc, + opcode_scope_code_flags_t scope_flags) +{ + JERRY_ASSERT ((idx_t) scope_flags == scope_flags); + + op_meta opm = serializer_get_op_meta (scope_code_flags_oc); + JERRY_ASSERT (opm.op.op_idx == OPCODE (meta)); + opm.op.data.meta.data_1 = (idx_t) scope_flags; + serializer_rewrite_op_meta (scope_code_flags_oc, opm); } void diff --git a/jerry-core/parser/js/opcodes-dumper.h b/jerry-core/parser/js/opcodes-dumper.h index ef6165ebf..0da07c27e 100644 --- a/jerry-core/parser/js/opcodes-dumper.h +++ b/jerry-core/parser/js/opcodes-dumper.h @@ -217,7 +217,9 @@ void dump_throw (operand); bool dumper_variable_declaration_exists (literal_index_t); void dump_variable_declaration (literal_index_t); -void dump_strict_mode_header (void); +opcode_counter_t dump_scope_code_flags_for_rewrite (void); +void rewrite_scope_code_flags (opcode_counter_t scope_code_flags_oc, + opcode_scope_code_flags_t scope_flags); void dump_reg_var_decl_for_rewrite (void); void rewrite_reg_var_decl (void); diff --git a/jerry-core/parser/js/parser.cpp b/jerry-core/parser/js/parser.cpp index ab14fb37a..08645eec5 100644 --- a/jerry-core/parser/js/parser.cpp +++ b/jerry-core/parser/js/parser.cpp @@ -2648,10 +2648,14 @@ preparse_scope (bool is_global) const locus start_loc = tok.loc; const token_type end_tt = is_global ? TOK_EOF : TOK_CLOSE_BRACE; + opcode_counter_t scope_code_flags_oc = dump_scope_code_flags_for_rewrite (); + + opcode_scope_code_flags_t scope_flags = OPCODE_SCOPE_CODE_FLAGS__NO_FLAGS; + if (token_is (TOK_STRING) && literal_equal_s (lexer_get_literal_by_id (token_data ()), "use strict")) { scopes_tree_set_strict_mode (STACK_TOP (scopes), true); - dump_strict_mode_header (); + scope_flags = (opcode_scope_code_flags_t) (scope_flags | OPCODE_SCOPE_CODE_FLAGS_STRICT); } lexer_set_strict_mode (scopes_tree_strict_mode (STACK_TOP (scopes))); @@ -2688,6 +2692,8 @@ preparse_scope (bool is_global) skip_newlines (); } + rewrite_scope_code_flags (scope_code_flags_oc, scope_flags); + if (start_loc != tok.loc) { lexer_seek (start_loc); diff --git a/jerry-core/parser/js/scopes-tree.cpp b/jerry-core/parser/js/scopes-tree.cpp index 11637894c..5d33a1ec3 100644 --- a/jerry-core/parser/js/scopes-tree.cpp +++ b/jerry-core/parser/js/scopes-tree.cpp @@ -354,7 +354,7 @@ generate_opcode (scopes_tree tree, opcode_counter_t opc_index, lit_id_hash_table case OPCODE_META_TYPE_CATCH: case OPCODE_META_TYPE_FINALLY: case OPCODE_META_TYPE_END_TRY_CATCH_FINALLY: - case OPCODE_META_TYPE_STRICT_CODE: + case OPCODE_META_TYPE_SCOPE_CODE_FLAGS: { change_uid (om, lit_ids, 0x000); break; @@ -493,7 +493,7 @@ count_new_literals_in_opcode (scopes_tree tree, opcode_counter_t opc_index) case OPCODE_META_TYPE_CATCH: case OPCODE_META_TYPE_FINALLY: case OPCODE_META_TYPE_END_TRY_CATCH_FINALLY: - case OPCODE_META_TYPE_STRICT_CODE: + case OPCODE_META_TYPE_SCOPE_CODE_FLAGS: { insert_uids_to_lit_id_map (om, 0x000); break; diff --git a/jerry-core/vm/opcodes.cpp b/jerry-core/vm/opcodes.cpp index be0f44903..05bb69060 100644 --- a/jerry-core/vm/opcodes.cpp +++ b/jerry-core/vm/opcodes.cpp @@ -449,13 +449,11 @@ function_declaration (int_data_t *int_data, /**< interpreter context */ read_meta_opcode_counter (OPCODE_META_TYPE_FUNCTION_END, int_data) + int_data->pos); int_data->pos++; - opcode_t next_opcode = vm_get_opcode (int_data->pos); - if (next_opcode.op_idx == __op__idx_meta - && next_opcode.data.meta.type == OPCODE_META_TYPE_STRICT_CODE) + opcode_scope_code_flags_t scope_flags = vm_get_scope_flags (int_data->pos++); + + if (scope_flags & OPCODE_SCOPE_CODE_FLAGS_STRICT) { is_strict = true; - - int_data->pos++; } ecma_string_t *function_name_string_p = ecma_new_ecma_string_from_lit_index (function_name_lit_id); @@ -548,13 +546,11 @@ opfunc_func_expr_n (opcode_t opdata, /**< operation data */ int_data) + int_data->pos); int_data->pos++; - opcode_t next_opcode = vm_get_opcode (int_data->pos); - if (next_opcode.op_idx == __op__idx_meta - && next_opcode.data.meta.type == OPCODE_META_TYPE_STRICT_CODE) + opcode_scope_code_flags_t scope_flags = vm_get_scope_flags (int_data->pos++); + + if (scope_flags & OPCODE_SCOPE_CODE_FLAGS_STRICT) { is_strict = true; - - int_data->pos++; } ecma_object_t *scope_p; @@ -1651,7 +1647,7 @@ opfunc_meta (opcode_t opdata, /**< operation data */ return ecma_make_meta_completion_value (); } - case OPCODE_META_TYPE_STRICT_CODE: + case OPCODE_META_TYPE_SCOPE_CODE_FLAGS: case OPCODE_META_TYPE_UNDEFINED: case OPCODE_META_TYPE_THIS_ARG: case OPCODE_META_TYPE_FUNCTION_END: diff --git a/jerry-core/vm/opcodes.h b/jerry-core/vm/opcodes.h index d29ed832a..dab0543cb 100644 --- a/jerry-core/vm/opcodes.h +++ b/jerry-core/vm/opcodes.h @@ -70,9 +70,19 @@ typedef enum OPCODE_META_TYPE_CATCH_EXCEPTION_IDENTIFIER, /**< literal index containing name of variable with exception object */ OPCODE_META_TYPE_FINALLY, /**< mark of beginning of finally block containing pointer to end of finally block */ OPCODE_META_TYPE_END_TRY_CATCH_FINALLY, /**< mark of end of try-catch, try-finally, try-catch-finally blocks */ - OPCODE_META_TYPE_STRICT_CODE /**< mark of beginning of strict code */ + OPCODE_META_TYPE_SCOPE_CODE_FLAGS /**< set of flags indicating various properties of the scope's code + * (See also: opcode_scope_code_flags_t) */ } opcode_meta_type; +/** + * Flags indicating various properties of a scope's code + */ +typedef enum : idx_t +{ + OPCODE_SCOPE_CODE_FLAGS__NO_FLAGS = (0u), /**< initializer for empty flag set */ + OPCODE_SCOPE_CODE_FLAGS_STRICT = (1u << 0), /**< code is strict mode code */ +} opcode_scope_code_flags_t; + /** * Interpreter context */ diff --git a/jerry-core/vm/pretty-printer.cpp b/jerry-core/vm/pretty-printer.cpp index 229afbb09..6bf6eb3f4 100644 --- a/jerry-core/vm/pretty-printer.cpp +++ b/jerry-core/vm/pretty-printer.cpp @@ -625,9 +625,18 @@ pp_op_meta (opcode_counter_t oc, op_meta opm, bool rewrite) printf ("end try"); break; } - case OPCODE_META_TYPE_STRICT_CODE: + case OPCODE_META_TYPE_SCOPE_CODE_FLAGS: { - printf ("use strict;"); + idx_t scope_flags = opm.op.data.meta.data_1; + + if (scope_flags & OPCODE_SCOPE_CODE_FLAGS_STRICT) + { + printf ("[use strict] "); + scope_flags &= (idx_t) ~(OPCODE_SCOPE_CODE_FLAGS_STRICT); + } + + JERRY_ASSERT (scope_flags == 0); + break; } default: diff --git a/jerry-core/vm/vm.cpp b/jerry-core/vm/vm.cpp index 5b010b526..834b178b7 100644 --- a/jerry-core/vm/vm.cpp +++ b/jerry-core/vm/vm.cpp @@ -366,12 +366,11 @@ vm_run_global (void) bool is_strict = false; opcode_counter_t start_pos = 0; - opcode_t first_opcode = vm_get_opcode (start_pos); - if (first_opcode.op_idx == __op__idx_meta - && first_opcode.data.meta.type == OPCODE_META_TYPE_STRICT_CODE) + opcode_scope_code_flags_t scope_flags = vm_get_scope_flags (start_pos++); + + if (scope_flags & OPCODE_SCOPE_CODE_FLAGS_STRICT) { is_strict = true; - start_pos++; } ecma_object_t *glob_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_GLOBAL); @@ -557,6 +556,20 @@ vm_get_opcode (opcode_counter_t counter) /**< opcode counter */ return __program[ counter ]; } /* vm_get_opcode */ +/** + * Get scope code flags from opcode specified by opcode counter + * + * @return mask of scope code flags + */ +opcode_scope_code_flags_t +vm_get_scope_flags (opcode_counter_t counter) /**< opcode counter */ +{ + opcode_t flags_opcode = vm_get_opcode (counter); + JERRY_ASSERT (flags_opcode.op_idx == __op__idx_meta + && flags_opcode.data.meta.type == OPCODE_META_TYPE_SCOPE_CODE_FLAGS); + return (opcode_scope_code_flags_t) flags_opcode.data.meta.data_1; +} /* vm_get_scope_flags */ + /** * Get this binding of current execution context * diff --git a/jerry-core/vm/vm.h b/jerry-core/vm/vm.h index 5aa66ea1d..d584c7f2a 100644 --- a/jerry-core/vm/vm.h +++ b/jerry-core/vm/vm.h @@ -30,6 +30,7 @@ extern ecma_completion_value_t vm_run_from_pos (opcode_counter_t start_pos, bool is_eval_code); extern opcode_t vm_get_opcode (opcode_counter_t counter); +extern opcode_scope_code_flags_t vm_get_scope_flags (opcode_counter_t counter); extern ecma_value_t vm_get_this_binding (void); extern ecma_object_t* vm_get_lex_env (void); diff --git a/tests/unit/test_preparser.cpp b/tests/unit/test_preparser.cpp index 6e5eb0eb2..c6e569050 100644 --- a/tests/unit/test_preparser.cpp +++ b/tests/unit/test_preparser.cpp @@ -40,6 +40,9 @@ main (int __attr_unused___ argc, opcode_t opcodes[] = { + getop_meta (OPCODE_META_TYPE_SCOPE_CODE_FLAGS, // [ ] + OPCODE_SCOPE_CODE_FLAGS__NO_FLAGS, + INVALID_VALUE), getop_reg_var_decl (128, 129), // var tmp128 .. tmp129; getop_var_decl (0), // var a; getop_assignment (129, 1, 1), // tmp129 = 1: SMALLINT;