aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Fancsik <frobert@inf.u-szeged.hu>2019-03-21 09:45:56 +0100
committerZoltan Herczeg <zherczeg.u-szeged@partner.samsung.com>2019-03-21 09:45:56 +0100
commit7b23ecc27240c4b8bff74164a97314c9a8335c3f (patch)
tree9120c64c8f6b95fa97639600b3bcb7909f75eafc
parent4123f35a3baa715c3183d7d515ad1fa88731b001 (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.c182
-rw-r--r--jerry-core/ecma/operations/ecma-lex-env.h6
-rw-r--r--jerry-core/vm/vm.c35
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);