diff options
author | Robert Fancsik <frobert@inf.u-szeged.hu> | 2019-03-21 09:45:56 +0100 |
---|---|---|
committer | Zoltan Herczeg <zherczeg.u-szeged@partner.samsung.com> | 2019-03-21 09:45:56 +0100 |
commit | 7b23ecc27240c4b8bff74164a97314c9a8335c3f (patch) | |
tree | 9120c64c8f6b95fa97639600b3bcb7909f75eafc | |
parent | 4123f35a3baa715c3183d7d515ad1fa88731b001 (diff) |
Merge base resolve + get/put operations for lexical environments to increase performance (#2798)
JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
-rw-r--r-- | jerry-core/ecma/operations/ecma-get-put-value.c | 182 | ||||
-rw-r--r-- | jerry-core/ecma/operations/ecma-lex-env.h | 6 | ||||
-rw-r--r-- | jerry-core/vm/vm.c | 35 |
3 files changed, 139 insertions, 84 deletions
diff --git a/jerry-core/ecma/operations/ecma-get-put-value.c b/jerry-core/ecma/operations/ecma-get-put-value.c index cb8a0819..1e6b5259 100644 --- a/jerry-core/ecma/operations/ecma-get-put-value.c +++ b/jerry-core/ecma/operations/ecma-get-put-value.c @@ -35,7 +35,7 @@ */ /** - * GetValue operation part (lexical environment base or unresolvable reference). + * GetValue operation part * * See also: ECMA-262 v5, 8.7.1, sections 3 and 5 * @@ -43,34 +43,64 @@ * Returned value must be freed with ecma_free_value. */ ecma_value_t -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 */ +ecma_op_get_value_lex_env_base (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_object_t **ref_base_lex_env_p, /**< [out] reference's base (lexical environment) */ + ecma_string_t *name_p) /**< variable name */ { - const bool is_unresolvable_reference = (ref_base_lex_env_p == NULL); + JERRY_ASSERT (lex_env_p != NULL + && ecma_is_lexical_environment (lex_env_p)); - /* 3. */ - if (JERRY_UNLIKELY (is_unresolvable_reference)) + while (lex_env_p != NULL) { + switch (ecma_get_lex_env_type (lex_env_p)) + { + case ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE: + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + if (property_p != NULL) + { + *ref_base_lex_env_p = lex_env_p; + return ecma_copy_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value); + } + break; + } +#ifndef CONFIG_DISABLE_ES2015_CLASS + case ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND: + { + break; + } +#endif /* !CONFIG_DISABLE_ES2015_CLASS */ + default: + { + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); + + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); + + ecma_value_t result = ecma_op_object_find (binding_obj_p, name_p); + + if (ecma_is_value_found (result)) + { + *ref_base_lex_env_p = lex_env_p; + return result; + } + + break; + } + } + + lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p); + } + + *ref_base_lex_env_p = NULL; #ifdef JERRY_ENABLE_ERROR_MESSAGES - ecma_value_t var_name_val = ecma_make_string_value (var_name_string_p); - ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_REFERENCE, - "% is not defined", - var_name_val); + return ecma_raise_standard_error_with_format (ECMA_ERROR_REFERENCE, + "% is not defined", + ecma_make_string_value (name_p)); #else /* !JERRY_ENABLE_ERROR_MESSAGES */ - ecma_value_t error_value = ecma_raise_reference_error (NULL); + return ecma_raise_reference_error (NULL); #endif /* JERRY_ENABLE_ERROR_MESSAGES */ - return error_value; - } - /* 5. */ - 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 (ref_base_lex_env_p, - var_name_string_p, - is_strict); } /* ecma_op_get_value_lex_env_base */ /** @@ -145,7 +175,7 @@ ecma_op_get_value_object_base (ecma_value_t base_value, /**< base value */ } /* ecma_op_get_value_object_base */ /** - * PutValue operation part (lexical environment base or unresolvable reference). + * PutValue operation part * * See also: ECMA-262 v5, 8.7.2, sections 3 and 5 * @@ -153,54 +183,90 @@ ecma_op_get_value_object_base (ecma_value_t base_value, /**< base value */ * Returned value must be freed with ecma_free_value. */ ecma_value_t -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 */ +ecma_op_put_value_lex_env_base (ecma_object_t *lex_env_p, /**< lexical environment */ + ecma_string_t *name_p, /**< variable name */ bool is_strict, /**< flag indicating strict mode */ ecma_value_t value) /**< ECMA-value */ { - const bool is_unresolvable_reference = (ref_base_lex_env_p == NULL); + JERRY_ASSERT (lex_env_p != NULL + && ecma_is_lexical_environment (lex_env_p)); - /* 3. */ - if (JERRY_UNLIKELY (is_unresolvable_reference)) + while (lex_env_p != NULL) { - /* 3.a. */ - if (is_strict) - { -#ifdef JERRY_ENABLE_ERROR_MESSAGES - ecma_value_t var_name_val = ecma_make_string_value (var_name_string_p); - ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_REFERENCE, - "% is not defined", - var_name_val); -#else /* !JERRY_ENABLE_ERROR_MESSAGES */ - ecma_value_t error_value = ecma_raise_reference_error (NULL); -#endif /* JERRY_ENABLE_ERROR_MESSAGES */ - return error_value; - } - else + switch (ecma_get_lex_env_type (lex_env_p)) { - /* 3.b. */ - ecma_object_t *global_object_p = ecma_builtin_get_global (); + case ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE: + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + if (property_p != NULL) + { + if (ecma_is_property_writable (*property_p)) + { + ecma_named_data_property_assign_value (lex_env_p, ECMA_PROPERTY_VALUE_PTR (property_p), value); + } + else if (is_strict) + { + return ecma_raise_type_error (ECMA_ERR_MSG ("Binding cannot be set.")); + } + return ECMA_VALUE_EMPTY; + } + break; + } +#ifndef CONFIG_DISABLE_ES2015_CLASS + case ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND: + { + break; + } +#endif /* !CONFIG_DISABLE_ES2015_CLASS */ + default: + { + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND); - ecma_value_t completion = ecma_op_object_put (global_object_p, - var_name_string_p, - value, - false); + ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); - JERRY_ASSERT (ecma_is_value_boolean (completion)); + if (ecma_op_object_has_property (binding_obj_p, name_p)) + { + ecma_value_t completion = ecma_op_object_put (binding_obj_p, + name_p, + value, + is_strict); - return ECMA_VALUE_EMPTY; + if (ECMA_IS_VALUE_ERROR (completion)) + { + return completion; + } + + JERRY_ASSERT (ecma_is_value_boolean (completion)); + return ECMA_VALUE_EMPTY; + } + + break; + } } + + lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p); } - /* 5. */ - JERRY_ASSERT (ref_base_lex_env_p != NULL - && ecma_is_lexical_environment (ref_base_lex_env_p)); + if (is_strict) + { +#ifdef JERRY_ENABLE_ERROR_MESSAGES + return ecma_raise_standard_error_with_format (ECMA_ERROR_REFERENCE, + "% is not defined", + ecma_make_string_value (name_p)); +#else /* !JERRY_ENABLE_ERROR_MESSAGES */ + return ecma_raise_reference_error (NULL); +#endif /* JERRY_ENABLE_ERROR_MESSAGES */ + } + + ecma_value_t completion = ecma_op_object_put (ecma_builtin_get_global (), + name_p, + value, + false); + + JERRY_ASSERT (ecma_is_value_boolean (completion)); - /* 5.a */ - return ecma_op_set_mutable_binding (ref_base_lex_env_p, - var_name_string_p, - value, - is_strict); + return ECMA_VALUE_EMPTY; } /* ecma_op_put_value_lex_env_base */ /** diff --git a/jerry-core/ecma/operations/ecma-lex-env.h b/jerry-core/ecma/operations/ecma-lex-env.h index 5d9afd9c..a3041737 100644 --- a/jerry-core/ecma/operations/ecma-lex-env.h +++ b/jerry-core/ecma/operations/ecma-lex-env.h @@ -44,10 +44,10 @@ void ecma_module_finalize_lex_envs (void); */ /* ECMA-262 v5, 8.7.1 and 8.7.2 */ -ecma_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); +ecma_value_t ecma_op_get_value_lex_env_base (ecma_object_t *lex_env_p, ecma_object_t **ref_base_lex_env_p, + ecma_string_t *name_p); ecma_value_t ecma_op_get_value_object_base (ecma_value_t base_value, ecma_string_t *property_name_p); -ecma_value_t ecma_op_put_value_lex_env_base (ecma_object_t *ref_base_lex_env_p, ecma_string_t *var_name_string_p, +ecma_value_t ecma_op_put_value_lex_env_base (ecma_object_t *lex_env_p, ecma_string_t *var_name_string_p, bool is_strict, ecma_value_t value); /* ECMA-262 v5, Table 17. Abstract methods of Environment Records */ diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index 602029e7..4a9105f6 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -851,9 +851,7 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ vm_var_decl (frame_ctx_p, name_p); - ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (frame_ctx_p->lex_env_p, name_p); - - ecma_value_t put_value_result = ecma_op_put_value_lex_env_base (ref_base_lex_env_p, + ecma_value_t put_value_result = ecma_op_put_value_lex_env_base (frame_ctx_p->lex_env_p, name_p, is_strict, lit_value); @@ -1679,12 +1677,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); ecma_object_t *ref_base_lex_env_p; - ref_base_lex_env_p = ecma_op_resolve_reference_base (frame_ctx_p->lex_env_p, - name_p); - result = ecma_op_get_value_lex_env_base (ref_base_lex_env_p, - name_p, - is_strict); + result = ecma_op_get_value_lex_env_base (frame_ctx_p->lex_env_p, + &ref_base_lex_env_p, + name_p); if (ECMA_IS_VALUE_ERROR (result)) { @@ -2152,22 +2148,18 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); - ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (frame_ctx_p->lex_env_p, - name_p); + ecma_object_t *ref_base_lex_env_p; + + result = ecma_op_get_value_lex_env_base (frame_ctx_p->lex_env_p, + &ref_base_lex_env_p, + name_p); if (ref_base_lex_env_p == NULL) { + ecma_free_value (JERRY_CONTEXT (error_value)); result = ECMA_VALUE_UNDEFINED; } - else - { - result = ecma_op_get_value_lex_env_base (ref_base_lex_env_p, - name_p, - is_strict); - - } - - if (ECMA_IS_VALUE_ERROR (result)) + else if (ECMA_IS_VALUE_ERROR (result)) { goto error; } @@ -3179,10 +3171,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { ecma_string_t *var_name_str_p = ecma_get_string_from_value (literal_start_p[literal_index]); - ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (frame_ctx_p->lex_env_p, - var_name_str_p); - - ecma_value_t put_value_result = ecma_op_put_value_lex_env_base (ref_base_lex_env_p, + ecma_value_t put_value_result = ecma_op_put_value_lex_env_base (frame_ctx_p->lex_env_p, var_name_str_p, is_strict, result); |