diff --git a/jerry-core/vm/opcodes.cpp b/jerry-core/vm/opcodes.cpp index b0b2ddef9..04e04948f 100644 --- a/jerry-core/vm/opcodes.cpp +++ b/jerry-core/vm/opcodes.cpp @@ -657,6 +657,8 @@ opfunc_call_n (opcode_t opdata, /**< operation data */ opcode_call_flags_t call_flags = OPCODE_CALL_FLAGS__EMPTY; + JERRY_ASSERT (!int_data->is_call_in_direct_eval_form); + opcode_t next_opcode = vm_get_opcode (int_data->opcodes_p, int_data->pos); if (next_opcode.op_idx == __op__idx_meta && next_opcode.data.meta.type == OPCODE_META_TYPE_CALL_SITE_INFO) @@ -667,6 +669,8 @@ opfunc_call_n (opcode_t opdata, /**< operation data */ { this_arg_var_idx = next_opcode.data.meta.data_2; JERRY_ASSERT (is_reg_variable (int_data, this_arg_var_idx)); + + JERRY_ASSERT ((call_flags & OPCODE_CALL_FLAGS_DIRECT_CALL_TO_EVAL_FORM) == 0); } int_data->pos++; @@ -704,6 +708,11 @@ opfunc_call_n (opcode_t opdata, /**< operation data */ } else { + if (call_flags & OPCODE_CALL_FLAGS_DIRECT_CALL_TO_EVAL_FORM) + { + int_data->is_call_in_direct_eval_form = true; + } + ecma_object_t *func_obj_p = ecma_get_object_from_value (func_value); ECMA_TRY_CATCH (call_ret_value, @@ -719,6 +728,15 @@ opfunc_call_n (opcode_t opdata, /**< operation data */ ECMA_FINALIZE (call_ret_value); + if (call_flags & OPCODE_CALL_FLAGS_DIRECT_CALL_TO_EVAL_FORM) + { + JERRY_ASSERT (int_data->is_call_in_direct_eval_form); + int_data->is_call_in_direct_eval_form = false; + } + else + { + JERRY_ASSERT (!int_data->is_call_in_direct_eval_form); + } } ecma_free_completion_value (get_this_completion_value); diff --git a/jerry-core/vm/opcodes.h b/jerry-core/vm/opcodes.h index 26874e1a7..1afea172c 100644 --- a/jerry-core/vm/opcodes.h +++ b/jerry-core/vm/opcodes.h @@ -83,7 +83,9 @@ typedef enum : idx_t OPCODE_CALL_FLAGS_DIRECT_CALL_TO_EVAL_FORM = (1u << 1) /**< flag, indicating that call is performed * in form 'eval (...)', i.e. through 'eval' string * without object base (i.e. with lexical environment - * as base), so it can be a direct call to eval */ + * as base), so it can be a direct call to eval + * See also: ECMA-262 v5, 15.1.2.1.1 + */ } opcode_call_flags_t; /** @@ -115,6 +117,8 @@ typedef struct ecma_object_t *lex_env_p; /**< current lexical environment */ bool is_strict; /**< is current code execution mode strict? */ bool is_eval_code; /**< is current code executed with eval */ + bool is_call_in_direct_eval_form; /** flag, indicating if there is call of 'Direct call to eval' form in + * process (see also: OPCODE_CALL_FLAGS_DIRECT_CALL_TO_EVAL_FORM) */ idx_t min_reg_num; /**< minimum idx used for register identification */ idx_t max_reg_num; /**< maximum idx used for register identification */ ecma_number_t* tmp_num_p; /**< an allocated number (to reduce temporary allocations) */ diff --git a/jerry-core/vm/vm.cpp b/jerry-core/vm/vm.cpp index 1bbb5ccbc..1ad36b3f4 100644 --- a/jerry-core/vm/vm.cpp +++ b/jerry-core/vm/vm.cpp @@ -545,6 +545,7 @@ vm_run_from_pos (const opcode_t *opcodes_p, /**< byte-code array */ int_data.lex_env_p = lex_env_p; int_data.is_strict = is_strict; int_data.is_eval_code = is_eval_code; + int_data.is_call_in_direct_eval_form = false; int_data.min_reg_num = min_reg_num; int_data.max_reg_num = max_reg_num; int_data.tmp_num_p = ecma_alloc_number (); @@ -604,6 +605,49 @@ vm_get_scope_flags (const opcode_t *opcodes_p, /**< byte-code array */ return (opcode_scope_code_flags_t) flags_opcode.data.meta.data_1; } /* vm_get_scope_flags */ +/** + * Check whether currently executed code is strict mode code + * + * @return true - current code is executed in strict mode, + * false - otherwise. + */ +bool +vm_is_strict_mode (void) +{ + JERRY_ASSERT (vm_top_context_p != NULL); + + return vm_top_context_p->is_strict; +} /* vm_is_strict_mode */ + +/** + * Check whether currently performed call (on top of call-stack) is performed in form, + * meeting conditions of 'Direct Call to Eval' (see also: ECMA-262 v5, 15.1.2.1.1) + * + * Warning: + * the function should only be called from implementation + * of built-in 'eval' routine of Global object + * + * @return true - currently performed call is performed through 'eval' identifier, + * without 'this' argument, + * false - otherwise. + */ +bool +vm_is_direct_eval_form_call (void) +{ + if (vm_top_context_p != NULL) + { + return vm_top_context_p->is_call_in_direct_eval_form; + } + else + { + /* + * There is no any interpreter context, so call is performed not from a script. + * This implies that the call is indirect. + */ + return false; + } +} /* vm_is_direct_eval_form_call */ + /** * Get this binding of current execution context * diff --git a/jerry-core/vm/vm.h b/jerry-core/vm/vm.h index b4bab7221..9934d2e4e 100644 --- a/jerry-core/vm/vm.h +++ b/jerry-core/vm/vm.h @@ -34,6 +34,9 @@ extern ecma_completion_value_t vm_run_from_pos (const opcode_t *opcodes_p, extern opcode_t vm_get_opcode (const opcode_t*, opcode_counter_t counter); extern opcode_scope_code_flags_t vm_get_scope_flags (const opcode_t*, opcode_counter_t counter); +extern bool vm_is_strict_mode (void); +extern bool vm_is_direct_eval_form_call (void); + extern ecma_value_t vm_get_this_binding (void); extern ecma_object_t* vm_get_lex_env (void);