diff --git a/src/libcoreint/opcodes-helpers-variables.c b/src/libcoreint/opcodes-helpers-variables.c index 085374293..df6465d70 100644 --- a/src/libcoreint/opcodes-helpers-variables.c +++ b/src/libcoreint/opcodes-helpers-variables.c @@ -15,46 +15,42 @@ #include "opcodes-ecma-support.h" +#ifndef JERRY_NDEBUG /** * Perform so-called 'strict eval or arguments reference' check * that is used in definition of several statement handling algorithms, * but has no ECMA-defined name. - * - * @return true - if ref is strict reference - * and it's base is lexical environment - * and it's referenced name is 'eval' or 'arguments'; - * false - otherwise. */ -static bool -do_strict_eval_arguments_check (ecma_reference_t ref) /**< ECMA-reference */ +static void +do_strict_eval_arguments_check (ecma_object_t *ref_base_lex_env_p, /**< base of ECMA-reference + (lexical environment) */ + ecma_string_t *var_name_string_p, /**< variable name */ + bool is_strict) /**< flag indicating strict mode */ { - bool ret = false; + bool is_check_failed = false; - if (ref.is_strict) + if (is_strict) { - if (ecma_is_value_object (ref.base)) + if (ref_base_lex_env_p != NULL) { - ecma_object_t *obj_p = ECMA_GET_POINTER (ref.base.value); + JERRY_ASSERT (ecma_is_lexical_environment (ref_base_lex_env_p)); - if (obj_p != NULL - && ecma_is_lexical_environment (obj_p)) - { - ecma_string_t* magic_string_eval = ecma_get_magic_string (ECMA_MAGIC_STRING_EVAL); - ecma_string_t* magic_string_arguments = ecma_get_magic_string (ECMA_MAGIC_STRING_ARGUMENTS); + ecma_string_t* magic_string_eval = ecma_get_magic_string (ECMA_MAGIC_STRING_EVAL); + ecma_string_t* magic_string_arguments = ecma_get_magic_string (ECMA_MAGIC_STRING_ARGUMENTS); - ret = (ecma_compare_ecma_strings (ECMA_GET_NON_NULL_POINTER (ref.referenced_name_cp), - magic_string_eval) - || ecma_compare_ecma_strings (ECMA_GET_NON_NULL_POINTER (ref.referenced_name_cp), - magic_string_arguments)); + is_check_failed = (ecma_compare_ecma_strings (var_name_string_p, + magic_string_eval) + || ecma_compare_ecma_strings (var_name_string_p, + magic_string_arguments)); - ecma_deref_ecma_string (magic_string_eval); - ecma_deref_ecma_string (magic_string_arguments); - } + ecma_deref_ecma_string (magic_string_eval); + ecma_deref_ecma_string (magic_string_arguments); } } - return ret; + JERRY_ASSERT (!is_check_failed); } /* do_strict_eval_arguments_check */ +#endif /* !JERRY_NDEBUG */ /** * Check if the variable is register variable. @@ -93,22 +89,25 @@ get_variable_value (int_data_t *int_data, /**< interpreter context */ } else { - ecma_reference_t ref; - ecma_string_t *var_name_string_p = ecma_new_ecma_string_from_lit_index (var_idx); - ref = ecma_op_get_identifier_reference (int_data->lex_env_p, - var_name_string_p, - int_data->is_strict); + ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (int_data->lex_env_p, + var_name_string_p); - /* SyntaxError should be treated as an early error */ - JERRY_ASSERT (!do_eval_or_arguments_check - || !do_strict_eval_arguments_check (ref)); + if (do_eval_or_arguments_check) + { +#ifndef JERRY_NDEBUG + do_strict_eval_arguments_check (ref_base_lex_env_p, + var_name_string_p, + int_data->is_strict); +#endif /* !JERRY_NDEBUG */ + } - ret_value = ecma_op_get_value_lex_env_base (ref); + ret_value = ecma_op_get_value_lex_env_base (ref_base_lex_env_p, + var_name_string_p, + int_data->is_strict); ecma_deref_ecma_string (var_name_string_p); - ecma_free_reference (ref); } return ret_value; @@ -142,21 +141,23 @@ set_variable_value (int_data_t *int_data, /**< interpreter context */ } else { - ecma_reference_t ref; - ecma_string_t *var_name_string_p = ecma_new_ecma_string_from_lit_index (var_idx); - ref = ecma_op_get_identifier_reference (int_data->lex_env_p, - var_name_string_p, - int_data->is_strict); + ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (int_data->lex_env_p, + var_name_string_p); - /* SyntaxError should be treated as an early error */ - JERRY_ASSERT (!do_strict_eval_arguments_check (ref)); +#ifndef JERRY_NDEBUG + do_strict_eval_arguments_check (ref_base_lex_env_p, + var_name_string_p, + int_data->is_strict); +#endif /* !JERRY_NDEBUG */ - ret_value = ecma_op_put_value_lex_env_base (ref, value); + ret_value = ecma_op_put_value_lex_env_base (ref_base_lex_env_p, + var_name_string_p, + int_data->is_strict, + value); ecma_deref_ecma_string (var_name_string_p); - ecma_free_reference (ref); } return ret_value; diff --git a/src/libcoreint/opcodes.c b/src/libcoreint/opcodes.c index 9add69421..53267936f 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -1309,24 +1309,20 @@ evaluate_arg_for_typeof (int_data_t *int_data, /**< interpreter context */ { ecma_string_t *var_name_string_p = ecma_new_ecma_string_from_lit_index (var_idx); - ecma_reference_t ref = ecma_op_get_identifier_reference (int_data->lex_env_p, - var_name_string_p, - int_data->is_strict); - - ecma_deref_ecma_string (var_name_string_p); - - const bool is_unresolvable_reference = ecma_is_value_undefined (ref.base); - - if (is_unresolvable_reference) + ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (int_data->lex_env_p, + var_name_string_p); + if (ref_base_lex_env_p == NULL) { ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_UNDEFINED); } else { - ret_value = ecma_op_get_value_lex_env_base (ref); + ret_value = ecma_op_get_value_lex_env_base (ref_base_lex_env_p, + var_name_string_p, + int_data->is_strict); } - ecma_free_reference (ref); + ecma_deref_ecma_string (var_name_string_p); } return ret_value; diff --git a/src/libecmaoperations/ecma-get-put-value.c b/src/libecmaoperations/ecma-get-put-value.c index ef9a016a5..0e35d7567 100644 --- a/src/libecmaoperations/ecma-get-put-value.c +++ b/src/libecmaoperations/ecma-get-put-value.c @@ -44,10 +44,11 @@ * Returned value must be freed with ecma_free_completion_value. */ ecma_completion_value_t -ecma_op_get_value_lex_env_base (ecma_reference_t ref) /**< ECMA-reference */ +ecma_op_get_value_lex_env_base (ecma_object_t *ref_base_lex_env_p, /**< reference's base (lexical environment) */ + ecma_string_t *var_name_string_p, /**< variable name */ + bool is_strict) /**< flag indicating strict mode */ { - const ecma_value_t base = ref.base; - const bool is_unresolvable_reference = ecma_is_value_undefined (base); + const bool is_unresolvable_reference = (ref_base_lex_env_p == NULL); // 3. if (unlikely (is_unresolvable_reference)) @@ -56,14 +57,13 @@ ecma_op_get_value_lex_env_base (ecma_reference_t ref) /**< ECMA-reference */ } // 5. - ecma_object_t *lex_env_p = ECMA_GET_NON_NULL_POINTER(base.value); - JERRY_ASSERT(lex_env_p != NULL - && ecma_is_lexical_environment (lex_env_p)); + JERRY_ASSERT(ref_base_lex_env_p != NULL + && ecma_is_lexical_environment (ref_base_lex_env_p)); // 5.a - return ecma_op_get_binding_value (lex_env_p, - ECMA_GET_NON_NULL_POINTER (ref.referenced_name_cp), - ref.is_strict); + return ecma_op_get_binding_value (ref_base_lex_env_p, + var_name_string_p, + is_strict); } /* ecma_op_get_value_lex_env_base */ /** @@ -128,17 +128,18 @@ ecma_op_get_value_object_base (ecma_reference_t ref) /**< ECMA-reference */ * Returned value must be freed with ecma_free_completion_value. */ ecma_completion_value_t -ecma_op_put_value_lex_env_base (ecma_reference_t ref, /**< ECMA-reference */ +ecma_op_put_value_lex_env_base (ecma_object_t *ref_base_lex_env_p, /**< reference's base (lexical environment) */ + ecma_string_t *var_name_string_p, /**< variable name */ + bool is_strict, /**< flag indicating strict mode */ ecma_value_t value) /**< ECMA-value */ { - const ecma_value_t base = ref.base; - const bool is_unresolvable_reference = ecma_is_value_undefined (base); + const bool is_unresolvable_reference = (ref_base_lex_env_p == NULL); // 3. if (unlikely (is_unresolvable_reference)) { // 3.a. - if (ref.is_strict) + if (is_strict) { return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_REFERENCE)); } @@ -148,7 +149,7 @@ ecma_op_put_value_lex_env_base (ecma_reference_t ref, /**< ECMA-reference */ ecma_object_t *global_object_p = ecma_builtin_get (ECMA_BUILTIN_ID_GLOBAL); ecma_completion_value_t completion = ecma_op_object_put (global_object_p, - ECMA_GET_NON_NULL_POINTER (ref.referenced_name_cp), + var_name_string_p, value, false); @@ -162,15 +163,14 @@ ecma_op_put_value_lex_env_base (ecma_reference_t ref, /**< ECMA-reference */ } // 5. - ecma_object_t *lex_env_p = ECMA_GET_NON_NULL_POINTER(base.value); - JERRY_ASSERT(lex_env_p != NULL - && ecma_is_lexical_environment (lex_env_p)); + JERRY_ASSERT(ref_base_lex_env_p != NULL + && ecma_is_lexical_environment (ref_base_lex_env_p)); // 5.a - return ecma_op_set_mutable_binding (lex_env_p, - ECMA_GET_NON_NULL_POINTER (ref.referenced_name_cp), + return ecma_op_set_mutable_binding (ref_base_lex_env_p, + var_name_string_p, value, - ref.is_strict); + is_strict); } /* ecma_op_put_value_lex_env_base */ /** diff --git a/src/libecmaoperations/ecma-lex-env.h b/src/libecmaoperations/ecma-lex-env.h index 76aa75206..9aa06f944 100644 --- a/src/libecmaoperations/ecma-lex-env.h +++ b/src/libecmaoperations/ecma-lex-env.h @@ -29,9 +29,13 @@ */ /* ECMA-262 v5, 8.7.1 and 8.7.2 */ -extern ecma_completion_value_t ecma_op_get_value_lex_env_base (ecma_reference_t ref); +extern ecma_completion_value_t ecma_op_get_value_lex_env_base (ecma_object_t *ref_base_lex_env_p, + ecma_string_t *var_name_string_p, + bool is_strict); extern ecma_completion_value_t ecma_op_get_value_object_base (ecma_reference_t ref); -extern ecma_completion_value_t ecma_op_put_value_lex_env_base (ecma_reference_t ref, +extern ecma_completion_value_t ecma_op_put_value_lex_env_base (ecma_object_t *ref_base_lex_env_p, + ecma_string_t *var_name_string_p, + bool is_strict, ecma_value_t value); extern ecma_completion_value_t ecma_op_put_value_object_base (ecma_reference_t ref, ecma_value_t value); diff --git a/src/libecmaoperations/ecma-reference.c b/src/libecmaoperations/ecma-reference.c index 5013a5faf..c885e9638 100644 --- a/src/libecmaoperations/ecma-reference.c +++ b/src/libecmaoperations/ecma-reference.c @@ -29,6 +29,34 @@ * @{ */ +/** + * Resolve syntactic reference. + * + * @return if reference was resolved successfully, + * pointer to lexical environment - reference's base, + * else - NULL. + */ +ecma_object_t* +ecma_op_resolve_reference_base (ecma_object_t *lex_env_p, /**< starting lexical environment */ + ecma_string_t *name_p) /**< identifier's name */ +{ + JERRY_ASSERT(lex_env_p != NULL); + + ecma_object_t *lex_env_iter_p = lex_env_p; + + while (lex_env_iter_p != NULL) + { + if (ecma_op_has_binding (lex_env_iter_p, name_p)) + { + return lex_env_iter_p; + } + + lex_env_iter_p = ecma_get_lex_env_outer_reference (lex_env_iter_p); + } + + return NULL; +} /* ecma_op_resolve_reference_base */ + /** * Resolve syntactic reference to ECMA-reference. * @@ -42,23 +70,20 @@ ecma_op_get_identifier_reference (ecma_object_t *lex_env_p, /**< lexical environ { JERRY_ASSERT(lex_env_p != NULL); - ecma_object_t *lex_env_iter_p = lex_env_p; + ecma_object_t *base_lex_env_p = ecma_op_resolve_reference_base (lex_env_p, name_p); - while (lex_env_iter_p != NULL) + if (base_lex_env_p != NULL) { - if (ecma_op_has_binding (lex_env_iter_p, name_p)) - { - return ecma_make_reference (ecma_make_object_value (lex_env_iter_p), - name_p, - is_strict); - } - - lex_env_iter_p = ecma_get_lex_env_outer_reference (lex_env_iter_p); + return ecma_make_reference (ecma_make_object_value (base_lex_env_p), + name_p, + is_strict); + } + else + { + return ecma_make_reference (ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), + name_p, + is_strict); } - - return ecma_make_reference (ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), - name_p, - is_strict); } /* ecma_op_get_identifier_reference */ /** diff --git a/src/libecmaoperations/ecma-reference.h b/src/libecmaoperations/ecma-reference.h index 3fe2cea76..8654fc85d 100644 --- a/src/libecmaoperations/ecma-reference.h +++ b/src/libecmaoperations/ecma-reference.h @@ -28,6 +28,9 @@ * @{ */ +extern ecma_object_t* ecma_op_resolve_reference_base (ecma_object_t *lex_env_p, + ecma_string_t *name_p); + extern ecma_reference_t ecma_op_get_identifier_reference (ecma_object_t *lex_env_p, ecma_string_t *name_p, bool is_strict);