From 132477f7d5d3628817424e64a22a0777a352517a Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Tue, 22 Nov 2016 13:29:53 +0100 Subject: [PATCH] Change array length into a virtual property. (#1439) This change allows easier access to array length which improves the performance of inserting new items into an array and there is no need to allocate length strings anymore. The trade-of is that array length cannot be cached anymore. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com --- jerry-core/ecma/base/ecma-gc.c | 9 + jerry-core/ecma/base/ecma-globals.h | 9 + .../ecma/builtin-objects/ecma-builtins.c | 30 ++- .../ecma/operations/ecma-array-object.c | 115 +++++----- .../ecma/operations/ecma-array-object.h | 4 + jerry-core/ecma/operations/ecma-objects.c | 208 +++++++++++------- .../ecma/operations/ecma-string-object.c | 3 +- jerry-core/vm/vm.c | 10 +- 8 files changed, 236 insertions(+), 152 deletions(-) diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index 1a6676ead..95290fe26 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -467,6 +467,15 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */ return; } + if (object_type == ECMA_OBJECT_TYPE_ARRAY) + { + size_t size = (ecma_get_object_is_builtin (object_p) ? sizeof (ecma_extended_built_in_object_t) + : sizeof (ecma_extended_object_t)); + + ecma_dealloc_extended_object ((ecma_extended_object_t *) object_p, size); + return; + } + if (ecma_get_object_is_builtin (object_p) || object_type == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION) { diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index b3f3971a0..0a1f3b2ae 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -616,6 +616,15 @@ typedef struct ecma_value_t bytecode_cp; /**< function byte code */ } function; + /* + * Description of array objects. + */ + struct + { + uint32_t length; /**< length property value */ + ecma_property_t length_prop; /**< length property */ + } array; + /* * Description of arguments objects. */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.c b/jerry-core/ecma/builtin-objects/ecma-builtins.c index ff44eabcf..fc964888a 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.c @@ -104,8 +104,11 @@ ecma_builtin_init_object (ecma_builtin_id_t obj_builtin_id, /**< built-in ID */ ecma_object_type_t obj_type, /**< object's type */ bool is_extensible) /**< value of object's [[Extensible]] property */ { - size_t ext_object_size = (obj_type == ECMA_OBJECT_TYPE_CLASS ? sizeof (ecma_extended_built_in_object_t) - : sizeof (ecma_extended_object_t)); + bool is_extended_built_in = (obj_type == ECMA_OBJECT_TYPE_CLASS + || obj_type == ECMA_OBJECT_TYPE_ARRAY); + + size_t ext_object_size = (is_extended_built_in ? sizeof (ecma_extended_built_in_object_t) + : sizeof (ecma_extended_object_t)); ecma_object_t *obj_p = ecma_create_object (prototype_obj_p, ext_object_size, obj_type); @@ -123,7 +126,7 @@ ecma_builtin_init_object (ecma_builtin_id_t obj_builtin_id, /**< built-in ID */ ecma_set_object_is_builtin (obj_p); ecma_built_in_props_t *built_in_props_p; - if (obj_type == ECMA_OBJECT_TYPE_CLASS) + if (is_extended_built_in) { built_in_props_p = &((ecma_extended_built_in_object_t *) obj_p)->built_in; } @@ -142,18 +145,11 @@ ecma_builtin_init_object (ecma_builtin_id_t obj_builtin_id, /**< built-in ID */ #ifndef CONFIG_DISABLE_ARRAY_BUILTIN case ECMA_BUILTIN_ID_ARRAY_PROTOTYPE: { - JERRY_ASSERT (obj_type != ECMA_OBJECT_TYPE_CLASS); - ecma_string_t *length_str_p = ecma_new_ecma_length_string (); + JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_ARRAY); + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; - ecma_property_value_t *length_prop_value_p; - length_prop_value_p = ecma_create_named_data_property (obj_p, - length_str_p, - ECMA_PROPERTY_FLAG_WRITABLE, - NULL); - - length_prop_value_p->value = ecma_make_integer_value (0); - - ecma_deref_ecma_string (length_str_p); + ext_object_p->u.array.length = 0; + ext_object_p->u.array.length_prop = ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_TYPE_VIRTUAL; break; } #endif /* !CONFIG_DISABLE_ARRAY_BUILTIN */ @@ -399,8 +395,9 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * } ecma_built_in_props_t *built_in_props_p; + ecma_object_type_t object_type = ecma_get_object_type (object_p); - if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_CLASS) + if (object_type == ECMA_OBJECT_TYPE_CLASS || object_type == ECMA_OBJECT_TYPE_ARRAY) { built_in_props_p = &((ecma_extended_built_in_object_t *) object_p)->built_in; } @@ -614,8 +611,9 @@ ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in else { ecma_built_in_props_t *built_in_props_p; + ecma_object_type_t object_type = ecma_get_object_type (object_p); - if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_CLASS) + if (object_type == ECMA_OBJECT_TYPE_CLASS || object_type == ECMA_OBJECT_TYPE_ARRAY) { built_in_props_p = &((ecma_extended_built_in_object_t *) object_p)->built_in; } diff --git a/jerry-core/ecma/operations/ecma-array-object.c b/jerry-core/ecma/operations/ecma-array-object.c index 6e58fffd6..0d495753b 100644 --- a/jerry-core/ecma/operations/ecma-array-object.c +++ b/jerry-core/ecma/operations/ecma-array-object.c @@ -86,16 +86,16 @@ ecma_op_create_array_object (const ecma_value_t *arguments_list_p, /**< list of } #ifndef CONFIG_DISABLE_ARRAY_BUILTIN - ecma_object_t *array_prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAY_PROTOTYPE); + ecma_object_t *array_prototype_object_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAY_PROTOTYPE); #else /* CONFIG_DISABLE_ARRAY_BUILTIN */ - ecma_object_t *array_prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + ecma_object_t *array_prototype_object_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); #endif /* !CONFIG_DISABLE_ARRAY_BUILTIN */ - ecma_object_t *obj_p = ecma_create_object (array_prototype_obj_p, - 0, - ECMA_OBJECT_TYPE_ARRAY); + ecma_object_t *object_p = ecma_create_object (array_prototype_object_p, + sizeof (ecma_extended_object_t), + ECMA_OBJECT_TYPE_ARRAY); - ecma_deref_object (array_prototype_obj_p); + ecma_deref_object (array_prototype_object_p); /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_ARRAY type. @@ -103,17 +103,9 @@ ecma_op_create_array_object (const ecma_value_t *arguments_list_p, /**< list of * See also: ecma_object_get_class_name */ - ecma_string_t *length_magic_string_p = ecma_new_ecma_length_string (); - - ecma_property_value_t *length_prop_value_p; - length_prop_value_p = ecma_create_named_data_property (obj_p, - length_magic_string_p, - ECMA_PROPERTY_FLAG_WRITABLE, - NULL); - - length_prop_value_p->value = ecma_make_number_value ((ecma_number_t) length); - - ecma_deref_ecma_string (length_magic_string_p); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + ext_obj_p->u.array.length = length; + ext_obj_p->u.array.length_prop = ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_TYPE_VIRTUAL; for (uint32_t index = 0; index < array_items_count; @@ -126,7 +118,7 @@ ecma_op_create_array_object (const ecma_value_t *arguments_list_p, /**< list of ecma_string_t *item_name_string_p = ecma_new_ecma_string_from_uint32 (index); - ecma_builtin_helper_def_prop (obj_p, + ecma_builtin_helper_def_prop (object_p, item_name_string_p, array_items_p[index], true, /* Writable */ @@ -137,7 +129,7 @@ ecma_op_create_array_object (const ecma_value_t *arguments_list_p, /**< list of ecma_deref_ecma_string (item_name_string_p); } - return ecma_make_object_value (obj_p); + return ecma_make_object_value (object_p); } /* ecma_op_create_array_object */ /** @@ -192,15 +184,9 @@ ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object return ecma_reject (is_throw); } - ecma_string_t magic_string_length; - ecma_init_ecma_length_string (&magic_string_length); + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - ecma_property_t *len_prop_p = ecma_find_named_property (object_p, &magic_string_length); - JERRY_ASSERT (len_prop_p != NULL - && ECMA_PROPERTY_GET_TYPE (*len_prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); - - ecma_property_value_t *len_prop_value_p = ECMA_PROPERTY_VALUE_PTR (len_prop_p); - uint32_t old_len_uint32 = ecma_get_uint32_from_value (len_prop_value_p->value); + uint32_t old_len_uint32 = ext_object_p->u.array.length; if (new_len_num == old_len_uint32) { @@ -209,16 +195,17 @@ ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object { if (!(flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE)) { - ecma_set_property_writable_attr (len_prop_p, false); + uint8_t new_prop_value = (uint8_t) (ext_object_p->u.array.length_prop & ~ECMA_PROPERTY_FLAG_WRITABLE); + ext_object_p->u.array.length_prop = new_prop_value; } - else if (!ecma_is_property_writable (*len_prop_p)) + else if (!ecma_is_property_writable (ext_object_p->u.array.length_prop)) { return ecma_reject (is_throw); } } return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } - else if (!ecma_is_property_writable (*len_prop_p)) + else if (!ecma_is_property_writable (ext_object_p->u.array.length_prop)) { return ecma_reject (is_throw); } @@ -230,12 +217,13 @@ ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object current_len_uint32 = ecma_delete_array_properties (object_p, new_len_uint32, old_len_uint32); } - ecma_value_assign_uint32 (&len_prop_value_p->value, current_len_uint32); + ext_object_p->u.array.length = current_len_uint32; if ((flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE_DEFINED) && !(flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE)) { - ecma_set_property_writable_attr (len_prop_p, false); + uint8_t new_prop_value = (uint8_t) (ext_object_p->u.array.length_prop & ~ECMA_PROPERTY_FLAG_WRITABLE); + ext_object_p->u.array.length_prop = new_prop_value; } if (current_len_uint32 == new_len_uint32) @@ -263,11 +251,6 @@ ecma_op_array_object_define_own_property (ecma_object_t *object_p, /**< the arra { if (ecma_string_is_length (property_name_p)) { - if (!property_desc_p->is_value_defined) - { - return ecma_op_general_object_define_own_property (object_p, property_name_p, property_desc_p, is_throw); - } - JERRY_ASSERT (property_desc_p->is_configurable_defined || !property_desc_p->is_configurable); JERRY_ASSERT (property_desc_p->is_enumerable_defined || !property_desc_p->is_enumerable); JERRY_ASSERT (property_desc_p->is_writable_defined || !property_desc_p->is_writable); @@ -298,7 +281,18 @@ ecma_op_array_object_define_own_property (ecma_object_t *object_p, /**< the arra flags |= ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE; } - return ecma_op_array_object_set_length (object_p, property_desc_p->value, flags); + if (property_desc_p->is_value_defined) + { + return ecma_op_array_object_set_length (object_p, property_desc_p->value, flags); + } + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ecma_value_t length_value = ecma_make_uint32_value (ext_object_p->u.array.length); + + ecma_value_t result = ecma_op_array_object_set_length (object_p, length_value, flags); + + ecma_fast_free_value (length_value); + return result; } uint32_t index = ecma_string_get_array_index (property_name_p); @@ -308,18 +302,11 @@ ecma_op_array_object_define_own_property (ecma_object_t *object_p, /**< the arra return ecma_op_general_object_define_own_property (object_p, property_name_p, property_desc_p, is_throw); } - ecma_string_t magic_string_length; - ecma_init_ecma_length_string (&magic_string_length); + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - ecma_property_t *len_prop_p = ecma_find_named_property (object_p, &magic_string_length); - JERRY_ASSERT (len_prop_p != NULL - && ECMA_PROPERTY_GET_TYPE (*len_prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); + bool update_length = (index >= ext_object_p->u.array.length); - ecma_property_value_t *len_prop_value_p = ECMA_PROPERTY_VALUE_PTR (len_prop_p); - - bool update_length = (index >= ecma_get_uint32_from_value (len_prop_value_p->value)); - - if (update_length && !ecma_is_property_writable (*len_prop_p)) + if (update_length && !ecma_is_property_writable (ext_object_p->u.array.length_prop)) { return ecma_reject (is_throw); } @@ -337,11 +324,41 @@ ecma_op_array_object_define_own_property (ecma_object_t *object_p, /**< the arra if (update_length) { - ecma_value_assign_uint32 (&len_prop_value_p->value, index + 1); + ext_object_p->u.array.length = index + 1; } + return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } /* ecma_op_array_object_define_own_property */ +/** + * List names of a String object's lazy instantiated properties + * + * @return string values collection + */ +void +ecma_op_array_list_lazy_property_names (ecma_object_t *obj_p, /**< a String object */ + bool separate_enumerable, /**< true - list enumerable properties + * into main collection, + * and non-enumerable to collection of + * 'skipped non-enumerable' properties, + * false - list all properties into main + * collection. + */ + ecma_collection_header_t *main_collection_p, /**< 'main' + * collection */ + ecma_collection_header_t *non_enum_collection_p) /**< skipped + * 'non-enumerable' + * collection */ +{ + JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY); + + ecma_collection_header_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p; + + ecma_string_t *length_str_p = ecma_new_ecma_length_string (); + ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (length_str_p), true); + ecma_deref_ecma_string (length_str_p); +} /* ecma_op_array_list_lazy_property_names */ + /** * @} * @} diff --git a/jerry-core/ecma/operations/ecma-array-object.h b/jerry-core/ecma/operations/ecma-array-object.h index 2b80fb495..f32b1b750 100644 --- a/jerry-core/ecma/operations/ecma-array-object.h +++ b/jerry-core/ecma/operations/ecma-array-object.h @@ -48,6 +48,10 @@ ecma_op_array_object_set_length (ecma_object_t *, ecma_value_t, uint32_t); extern ecma_value_t ecma_op_array_object_define_own_property (ecma_object_t *, ecma_string_t *, const ecma_property_descriptor_t *, bool); +extern void +ecma_op_array_list_lazy_property_names (ecma_object_t *, bool, + ecma_collection_header_t *, ecma_collection_header_t *); + /** * @} * @} diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c index 1a069c062..b6e5bab79 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -80,11 +80,9 @@ ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */ ecma_object_type_t type = ecma_get_object_type (object_p); - ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); - - if (property_p == NULL) + switch (type) { - if (type == ECMA_OBJECT_TYPE_CLASS) + case ECMA_OBJECT_TYPE_CLASS: { ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; @@ -124,8 +122,33 @@ ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */ } } } + break; } + case ECMA_OBJECT_TYPE_ARRAY: + { + if (ecma_string_is_length (property_name_p)) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + if (options & ECMA_PROPERTY_GET_VALUE) + { + property_ref_p->virtual_value = ecma_make_uint32_value (ext_object_p->u.array.length); + } + + return ext_object_p->u.array.length_prop; + } + break; + } + default: + { + break; + } + } + + ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); + + if (property_p == NULL) + { if (ecma_get_object_is_builtin (object_p)) { property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p); @@ -314,40 +337,9 @@ ecma_op_object_find_own (ecma_value_t base_value, /**< base value */ ecma_object_type_t type = ecma_get_object_type (object_p); - if (unlikely (type == ECMA_OBJECT_TYPE_ARGUMENTS)) + switch (type) { - uint32_t index = ecma_string_get_array_index (property_name_p); - - if (index != ECMA_STRING_NOT_ARRAY_INDEX) - { - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - - if (index < ext_object_p->u.arguments.length) - { - jmem_cpointer_t *arg_Literal_p = (jmem_cpointer_t *) (ext_object_p + 1); - - if (arg_Literal_p[index] != JMEM_CP_NULL) - { - ecma_string_t *arg_name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, - arg_Literal_p[index]); - - ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, - ext_object_p->u.arguments.lex_env_cp); - - JERRY_ASSERT (lex_env_p != NULL - && ecma_is_lexical_environment (lex_env_p)); - - return ecma_op_get_binding_value (lex_env_p, arg_name_p, true); - } - } - } - } - - ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); - - if (property_p == NULL) - { - if (type == ECMA_OBJECT_TYPE_CLASS) + case ECMA_OBJECT_TYPE_CLASS: { ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; @@ -378,8 +370,57 @@ ecma_op_object_find_own (ecma_value_t base_value, /**< base value */ } } } + break; } + case ECMA_OBJECT_TYPE_ARRAY: + { + if (ecma_string_is_length (property_name_p)) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + return ecma_make_uint32_value (ext_object_p->u.array.length); + } + break; + } + case ECMA_OBJECT_TYPE_ARGUMENTS: + { + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index != ECMA_STRING_NOT_ARRAY_INDEX) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (index < ext_object_p->u.arguments.length) + { + jmem_cpointer_t *arg_Literal_p = (jmem_cpointer_t *) (ext_object_p + 1); + + if (arg_Literal_p[index] != JMEM_CP_NULL) + { + ecma_string_t *arg_name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, + arg_Literal_p[index]); + + ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, + ext_object_p->u.arguments.lex_env_cp); + + JERRY_ASSERT (lex_env_p != NULL + && ecma_is_lexical_environment (lex_env_p)); + + return ecma_op_get_binding_value (lex_env_p, arg_name_p, true); + } + } + } + break; + } + default: + { + break; + } + } + + ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); + + if (property_p == NULL) + { if (ecma_get_object_is_builtin (object_p)) { property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p); @@ -576,33 +617,56 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */ ecma_object_t *setter_p = NULL; ecma_object_type_t type = ecma_get_object_type (object_p); - if (type == ECMA_OBJECT_TYPE_ARGUMENTS) + switch (type) { - uint32_t index = ecma_string_get_array_index (property_name_p); - - if (index != ECMA_STRING_NOT_ARRAY_INDEX) + case ECMA_OBJECT_TYPE_ARRAY: { - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - - if (index < ext_object_p->u.arguments.length) + if (ecma_string_is_length (property_name_p)) { - jmem_cpointer_t *arg_Literal_p = (jmem_cpointer_t *) (ext_object_p + 1); + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - if (arg_Literal_p[index] != JMEM_CP_NULL) + if (ecma_is_property_writable (ext_object_p->u.array.length_prop)) { - ecma_string_t *arg_name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, - arg_Literal_p[index]); + return ecma_op_array_object_set_length (object_p, value, 0); + } - ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, - ext_object_p->u.arguments.lex_env_cp); + return ecma_reject (is_throw); + } + break; + } + case ECMA_OBJECT_TYPE_ARGUMENTS: + { + uint32_t index = ecma_string_get_array_index (property_name_p); - JERRY_ASSERT (lex_env_p != NULL - && ecma_is_lexical_environment (lex_env_p)); + if (index != ECMA_STRING_NOT_ARRAY_INDEX) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - ecma_op_set_mutable_binding (lex_env_p, arg_name_p, value, true); - return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); + if (index < ext_object_p->u.arguments.length) + { + jmem_cpointer_t *arg_Literal_p = (jmem_cpointer_t *) (ext_object_p + 1); + + if (arg_Literal_p[index] != JMEM_CP_NULL) + { + ecma_string_t *arg_name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, + arg_Literal_p[index]); + + ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, + ext_object_p->u.arguments.lex_env_cp); + + JERRY_ASSERT (lex_env_p != NULL + && ecma_is_lexical_environment (lex_env_p)); + + ecma_op_set_mutable_binding (lex_env_p, arg_name_p, value, true); + return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); + } } } + break; + } + default: + { + break; } } @@ -653,11 +717,6 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */ { if (ecma_is_property_writable (*property_p)) { - if (type == ECMA_OBJECT_TYPE_ARRAY && ecma_string_is_length (property_name_p)) - { - return ecma_op_array_object_set_length (object_p, value, 0); - } - /* There is no need for special casing arrays here because changing the * value of an existing property never changes the length of an array. */ ecma_named_data_property_assign_value (object_p, @@ -722,31 +781,17 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */ if (type == ECMA_OBJECT_TYPE_ARRAY && index != ECMA_STRING_NOT_ARRAY_INDEX) { - /* Since the length of an array is a non-configurable named data - * property, the property_p must be a non-NULL pointer for all arrays. */ - - JERRY_ASSERT (!ecma_string_is_length (property_name_p)); - - ecma_string_t magic_string_length; - ecma_init_ecma_length_string (&magic_string_length); - - ecma_property_t *len_prop_p = ecma_find_named_property (object_p, &magic_string_length); - - JERRY_ASSERT (len_prop_p != NULL - && ECMA_PROPERTY_GET_TYPE (*len_prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); - - ecma_property_value_t *len_prop_value_p = ECMA_PROPERTY_VALUE_PTR (len_prop_p); - uint32_t old_len = ecma_get_uint32_from_value (len_prop_value_p->value); + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; if (index < UINT32_MAX - && index >= old_len) + && index >= ext_object_p->u.array.length) { - if (!ecma_is_property_writable (*len_prop_p)) + if (!ecma_is_property_writable (ext_object_p->u.array.length_prop)) { return ecma_reject (is_throw); } - ecma_value_assign_uint32 (&len_prop_value_p->value, index + 1); + ext_object_p->u.array.length = index + 1; } } @@ -1133,7 +1178,6 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ { case ECMA_OBJECT_TYPE_GENERAL: case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION: - case ECMA_OBJECT_TYPE_ARRAY: case ECMA_OBJECT_TYPE_BOUND_FUNCTION: case ECMA_OBJECT_TYPE_ARGUMENTS: { @@ -1159,6 +1203,14 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ } break; } + case ECMA_OBJECT_TYPE_ARRAY: + { + ecma_op_array_list_lazy_property_names (obj_p, + is_enumerable_only, + prop_names_p, + skipped_non_enumerable_p); + break; + } default: { JERRY_UNREACHABLE (); diff --git a/jerry-core/ecma/operations/ecma-string-object.c b/jerry-core/ecma/operations/ecma-string-object.c index 81221ea46..b3af3d38a 100644 --- a/jerry-core/ecma/operations/ecma-string-object.c +++ b/jerry-core/ecma/operations/ecma-string-object.c @@ -107,8 +107,7 @@ ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, /**< a String obj * collection */ ecma_collection_header_t *non_enum_collection_p) /**< skipped * 'non-enumerable' - * collection - */ + * collection */ { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_CLASS); diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index 7b15cfcf9..ca1a5f2cd 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -1000,19 +1000,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ case VM_OC_APPEND_ARRAY: { ecma_object_t *array_obj_p; - ecma_string_t length_str; - ecma_property_value_t *length_prop_value_p; uint32_t length_num; uint32_t values_length = *byte_code_p++; stack_top_p -= values_length; array_obj_p = ecma_get_object_from_value (stack_top_p[-1]); - ecma_init_ecma_length_string (&length_str); - length_prop_value_p = ecma_get_named_data_property (array_obj_p, &length_str); + ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_obj_p; - left_value = length_prop_value_p->value; - length_num = ecma_get_uint32_from_value (left_value); + length_num = ext_array_obj_p->u.array.length; for (uint32_t i = 0; i < values_length; i++) { @@ -1041,7 +1037,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ length_num++; } - ecma_value_assign_uint32 (&length_prop_value_p->value, length_num); + ext_array_obj_p->u.array.length = length_num; continue; } case VM_OC_PUSH_UNDEFINED_BASE: