From 3ce48be152b450737f0ceaff1233c7619cd46f98 Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Wed, 19 Oct 2016 09:45:17 +0200 Subject: [PATCH] Improve array length setting. (#1393) The new set does not allocate memory when the size of the array is reduced. Furthermore the [[PutObject]] method directly calls the new length setter. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com --- jerry-core/ecma/base/ecma-helpers.c | 140 +++++- jerry-core/ecma/base/ecma-helpers.h | 1 + .../ecma/operations/ecma-array-object.c | 458 +++++++----------- .../ecma/operations/ecma-array-object.h | 17 + jerry-core/ecma/operations/ecma-objects.c | 11 +- 5 files changed, 332 insertions(+), 295 deletions(-) diff --git a/jerry-core/ecma/base/ecma-helpers.c b/jerry-core/ecma/base/ecma-helpers.c index 0b7f97e08..dd3e86de1 100644 --- a/jerry-core/ecma/base/ecma-helpers.c +++ b/jerry-core/ecma/base/ecma-helpers.c @@ -945,10 +945,9 @@ ecma_delete_property (ecma_object_t *object_p, /**< object */ } ecma_deref_ecma_string (name_p); + prop_pair_p->names_cp[i] = ECMA_NULL_POINTER; } - prop_pair_p->names_cp[i] = ECMA_NULL_POINTER; - JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2); if (cur_prop_p->types[1 - i] != ECMA_PROPERTY_TYPE_DELETED) @@ -979,6 +978,143 @@ ecma_delete_property (ecma_object_t *object_p, /**< object */ } } /* ecma_delete_property */ +/** + * Low level delete of array items from new_length to old_length + * + * Note: new_length must be less than old_length + * + * @return the updated value of new_length + */ +uint32_t +ecma_delete_array_properties (ecma_object_t *object_p, /**< object */ + uint32_t new_length, /**< new length */ + uint32_t old_length) /**< old length */ +{ + JERRY_ASSERT (new_length < old_length); + + /* First the minimum value of new_length is updated. */ + ecma_property_header_t *current_prop_p = ecma_get_property_list (object_p); + + if (current_prop_p == NULL) + { + return new_length; + } + + if (ECMA_PROPERTY_GET_TYPE (current_prop_p->types[0]) == ECMA_PROPERTY_TYPE_HASHMAP) + { + current_prop_p = ECMA_GET_POINTER (ecma_property_header_t, + current_prop_p->next_property_cp); + } + + while (current_prop_p != NULL) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (current_prop_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) current_prop_p; + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if (prop_pair_p->names_cp[i] != ECMA_NULL_POINTER + && !ecma_is_property_configurable (current_prop_p->types[i])) + { + ecma_string_t *property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, + prop_pair_p->names_cp[i]); + + uint32_t index; + if (ecma_string_get_array_index (property_name_p, &index)) + { + if (index < old_length && index >= new_length) + { + new_length = index + 1; + + if (new_length == old_length) + { + /* Early return. */ + return new_length; + } + } + } + } + } + + current_prop_p = ECMA_GET_POINTER (ecma_property_header_t, + current_prop_p->next_property_cp); + } + + /* Second all properties between new_length and old_length are deleted. */ + current_prop_p = ecma_get_property_list (object_p); + ecma_property_header_t *prev_prop_p = NULL; + bool has_hashmap = false; + + if (ECMA_PROPERTY_GET_TYPE (current_prop_p->types[0]) == ECMA_PROPERTY_TYPE_HASHMAP) + { + prev_prop_p = current_prop_p; + current_prop_p = ECMA_GET_POINTER (ecma_property_header_t, + current_prop_p->next_property_cp); + has_hashmap = true; + } + + while (current_prop_p != NULL) + { + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) current_prop_p; + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + if (prop_pair_p->names_cp[i] != ECMA_NULL_POINTER + && ecma_is_property_configurable (current_prop_p->types[i])) + { + ecma_string_t *property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, + prop_pair_p->names_cp[i]); + + uint32_t index; + if (ecma_string_get_array_index (property_name_p, &index)) + { + if (index < old_length && index >= new_length) + { + ecma_free_property (object_p, property_name_p, current_prop_p->types + i); + + if (has_hashmap) + { + ecma_property_hashmap_delete (object_p, property_name_p, current_prop_p->types + i); + } + + JERRY_ASSERT (current_prop_p->types[i] == ECMA_PROPERTY_TYPE_DELETED); + + ecma_deref_ecma_string (property_name_p); + prop_pair_p->names_cp[i] = ECMA_NULL_POINTER; + } + } + } + } + + if (current_prop_p->types[0] == ECMA_PROPERTY_TYPE_DELETED + && current_prop_p->types[1] == ECMA_PROPERTY_TYPE_DELETED) + { + if (prev_prop_p == NULL) + { + object_p->property_list_or_bound_object_cp = current_prop_p->next_property_cp; + } + else + { + prev_prop_p->next_property_cp = current_prop_p->next_property_cp; + } + + ecma_property_header_t *next_prop_p = ECMA_GET_POINTER (ecma_property_header_t, + current_prop_p->next_property_cp); + ecma_dealloc_property_pair ((ecma_property_pair_t *) current_prop_p); + current_prop_p = next_prop_p; + } + else + { + prev_prop_p = current_prop_p; + current_prop_p = ECMA_GET_POINTER (ecma_property_header_t, + current_prop_p->next_property_cp); + } + } + + return new_length; +} /* ecma_delete_array_properties */ + /** * Check whether the object contains a property */ diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 43461540d..c3d836baa 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -283,6 +283,7 @@ ecma_get_named_data_property (ecma_object_t *, ecma_string_t *); extern void ecma_free_property (ecma_object_t *, ecma_string_t *, ecma_property_t *); extern void ecma_delete_property (ecma_object_t *, ecma_property_value_t *); +extern uint32_t ecma_delete_array_properties (ecma_object_t *, uint32_t, uint32_t); extern void ecma_named_data_property_assign_value (ecma_object_t *, ecma_property_value_t *, ecma_value_t); diff --git a/jerry-core/ecma/operations/ecma-array-object.c b/jerry-core/ecma/operations/ecma-array-object.c index b3a17879e..05264e63d 100644 --- a/jerry-core/ecma/operations/ecma-array-object.c +++ b/jerry-core/ecma/operations/ecma-array-object.c @@ -141,6 +141,111 @@ ecma_op_create_array_object (const ecma_value_t *arguments_list_p, /**< list of return ecma_make_object_value (obj_p); } /* ecma_op_create_array_object */ +/** + * Update the length of an array to a new length + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +extern ecma_value_t +ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object */ + ecma_value_t new_value, /**< new length value */ + uint32_t flags) /**< configuration options */ +{ + bool is_throw = (flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_IS_THROW); + + ecma_value_t completion = ecma_op_to_number (new_value); + + if (ECMA_IS_VALUE_ERROR (completion)) + { + return completion; + } + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (completion) + && ecma_is_value_number (completion)); + + ecma_number_t new_len_num = ecma_get_number_from_value (completion); + + ecma_free_value (completion); + + if (ecma_is_value_object (new_value)) + { + ecma_value_t compared_num_val = ecma_op_to_number (new_value); + + if (ECMA_IS_VALUE_ERROR (completion)) + { + return compared_num_val; + } + + new_len_num = ecma_get_number_from_value (compared_num_val); + ecma_free_value (compared_num_val); + } + + uint32_t new_len_uint32 = ecma_number_to_uint32 (new_len_num); + + if (((ecma_number_t) new_len_uint32) != new_len_num) + { + return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid array length.")); + } + + if (flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_REJECT) + { + return ecma_reject (is_throw); + } + + 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_uint32 = ecma_get_uint32_from_value (len_prop_value_p->value); + + if (new_len_num == old_len_uint32) + { + /* Only the writable flag must be updated. */ + if (flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE_DEFINED) + { + if (!(flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE)) + { + ecma_set_property_writable_attr (len_prop_p, false); + } + else if (!ecma_is_property_writable (*len_prop_p)) + { + return ecma_reject (is_throw); + } + } + return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); + } + else if (!ecma_is_property_writable (*len_prop_p)) + { + return ecma_reject (is_throw); + } + + uint32_t current_len_uint32 = new_len_uint32; + + if (new_len_uint32 < old_len_uint32) + { + 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); + + 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); + } + + if (current_len_uint32 == new_len_uint32) + { + return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); + } + return ecma_reject (is_throw); +} /* ecma_op_array_object_set_length */ + /** * [[DefineOwnProperty]] ecma array object's operation * @@ -152,303 +257,90 @@ ecma_op_create_array_object (const ecma_value_t *arguments_list_p, /**< list of * Returned value must be freed with ecma_free_value */ ecma_value_t -ecma_op_array_object_define_own_property (ecma_object_t *obj_p, /**< the array object */ +ecma_op_array_object_define_own_property (ecma_object_t *object_p, /**< the array object */ ecma_string_t *property_name_p, /**< property name */ const ecma_property_descriptor_t *property_desc_p, /**< property descriptor */ bool is_throw) /**< flag that controls failure handling */ { - JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY); + 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); + } - // 1. - ecma_string_t *magic_string_length_p = ecma_new_ecma_length_string (); - ecma_property_t *len_prop_p = ecma_find_named_property (obj_p, magic_string_length_p); + 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); + uint32_t flags = 0; + + if (is_throw) + { + flags |= ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_IS_THROW; + } + + /* Only the writable and data properties can be modified. */ + if (property_desc_p->is_configurable + || property_desc_p->is_enumerable + || property_desc_p->is_get_defined + || property_desc_p->is_set_defined) + { + flags |= ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_REJECT; + } + + if (property_desc_p->is_writable_defined) + { + flags |= ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE_DEFINED; + } + + if (property_desc_p->is_writable) + { + flags |= ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE; + } + + return ecma_op_array_object_set_length (object_p, property_desc_p->value, flags); + } + + uint32_t index; + + if (!ecma_string_get_array_index (property_name_p, &index)) + { + 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_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); - // 2. - ecma_value_t old_len_value = ECMA_PROPERTY_VALUE_PTR (len_prop_p)->value; + 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 (old_len_value); + bool update_length = (index >= ecma_get_uint32_from_value (len_prop_value_p->value)); - // 3. - bool is_property_name_equal_length = ecma_compare_ecma_strings (property_name_p, - magic_string_length_p); - - ecma_deref_ecma_string (magic_string_length_p); - - if (is_property_name_equal_length) + if (update_length && !ecma_is_property_writable (*len_prop_p)) { - // a. - if (!property_desc_p->is_value_defined) - { - // i. - return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, is_throw); - } - - // c. - ecma_value_t completion = ecma_op_to_number (property_desc_p->value); - if (ECMA_IS_VALUE_ERROR (completion)) - { - return completion; - } - - JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (completion) - && ecma_is_value_number (completion)); - - ecma_number_t new_len_num = ecma_get_number_from_value (completion); - - ecma_free_value (completion); - - uint32_t new_len_uint32 = ecma_number_to_uint32 (new_len_num); - - // d. - if (ecma_is_value_object (property_desc_p->value)) - { - ecma_value_t compared_num_val = ecma_op_to_number (property_desc_p->value); - new_len_num = ecma_get_number_from_value (compared_num_val); - ecma_free_value (compared_num_val); - } - - if (((ecma_number_t) new_len_uint32) != new_len_num) - { - return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid array length.")); - } - else - { - // b., e. - ecma_property_descriptor_t new_len_property_desc = *property_desc_p; - new_len_property_desc.value = ecma_make_number_value (new_len_num); - - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); - - // f. - if (new_len_uint32 >= old_len_uint32) - { - // i. - magic_string_length_p = ecma_new_ecma_length_string (); - ret_value = ecma_op_general_object_define_own_property (obj_p, - magic_string_length_p, - &new_len_property_desc, - is_throw); - ecma_deref_ecma_string (magic_string_length_p); - } - else - { - // g. - if (!ecma_is_property_writable (*len_prop_p)) - { - ret_value = ecma_reject (is_throw); - } - else - { - // h. - bool new_writable; - if (!new_len_property_desc.is_writable_defined - || new_len_property_desc.is_writable) - { - new_writable = true; - } - else - { - // ii. - new_writable = false; - - // iii. - new_len_property_desc.is_writable_defined = true; - new_len_property_desc.is_writable = true; - } - - // j. - magic_string_length_p = ecma_new_ecma_length_string (); - ecma_value_t succeeded = ecma_op_general_object_define_own_property (obj_p, - magic_string_length_p, - &new_len_property_desc, - is_throw); - ecma_deref_ecma_string (magic_string_length_p); - - /* Handling normal false and throw values */ - if (!ecma_is_value_true (succeeded)) - { - JERRY_ASSERT (ecma_is_value_false (succeeded) - || ECMA_IS_VALUE_ERROR (succeeded)); - - // k. - ret_value = succeeded; - } - else - { - // l - JERRY_ASSERT (new_len_uint32 < old_len_uint32); - - /* - * Item i. is replaced with faster iteration: only indices that actually exist in the array, are iterated - */ - bool is_reduce_succeeded = true; - - ecma_collection_header_t *array_index_props_p = ecma_op_object_get_property_names (obj_p, - true, - false, - false); - - ecma_length_t array_index_props_num = array_index_props_p->unit_number; - - JMEM_DEFINE_LOCAL_ARRAY (array_index_values_p, array_index_props_num, uint32_t); - - ecma_collection_iterator_t iter; - ecma_collection_iterator_init (&iter, array_index_props_p); - - uint32_t array_index_values_pos = 0; - - while (ecma_collection_iterator_next (&iter)) - { - ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p); - - uint32_t index; - bool is_index = ecma_string_get_array_index (property_name_p, &index); - JERRY_ASSERT (is_index); - JERRY_ASSERT (index < old_len_uint32); - - array_index_values_p[array_index_values_pos++] = index; - } - - JERRY_ASSERT (array_index_values_pos == array_index_props_num); - - while (array_index_values_pos != 0 - && array_index_values_p[--array_index_values_pos] >= new_len_uint32) - { - uint32_t index = array_index_values_p[array_index_values_pos]; - - // ii. - ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); - ecma_value_t delete_succeeded = ecma_op_object_delete (obj_p, index_string_p, false); - ecma_deref_ecma_string (index_string_p); - - if (ecma_is_value_false (delete_succeeded)) - { - // iii. - new_len_uint32 = (index + 1u); - - // 1. - ecma_number_t new_len_num = ((ecma_number_t) index + 1u); - ecma_value_assign_number (&new_len_property_desc.value, new_len_num); - - // 2. - if (!new_writable) - { - new_len_property_desc.is_writable_defined = true; - new_len_property_desc.is_writable = false; - } - - // 3. - ecma_string_t *magic_string_length_p = ecma_new_ecma_length_string (); - ecma_value_t completion = ecma_op_general_object_define_own_property (obj_p, - magic_string_length_p, - &new_len_property_desc, - false); - ecma_deref_ecma_string (magic_string_length_p); - - JERRY_ASSERT (ecma_is_value_boolean (completion)); - - is_reduce_succeeded = false; - - break; - } - } - - JMEM_FINALIZE_LOCAL_ARRAY (array_index_values_p); - - ecma_free_values_collection (array_index_props_p, true); - - if (!is_reduce_succeeded) - { - ret_value = ecma_reject (is_throw); - } - else - { - // m. - if (!new_writable) - { - ecma_property_descriptor_t prop_desc_not_writable = ecma_make_empty_property_descriptor (); - - prop_desc_not_writable.is_writable_defined = true; - prop_desc_not_writable.is_writable = false; - - ecma_value_t completion_set_not_writable; - magic_string_length_p = ecma_new_ecma_length_string (); - completion_set_not_writable = ecma_op_general_object_define_own_property (obj_p, - magic_string_length_p, - &prop_desc_not_writable, - false); - ecma_deref_ecma_string (magic_string_length_p); - JERRY_ASSERT (ecma_is_value_true (completion_set_not_writable)); - } - - ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); - } - } - } - } - - ecma_free_value (new_len_property_desc.value); - - return ret_value; - } - - JERRY_UNREACHABLE (); - } - else - { - // 4.a. - uint32_t index; - - if (!ecma_string_get_array_index (property_name_p, &index)) - { - // 5. - return ecma_op_general_object_define_own_property (obj_p, - property_name_p, - property_desc_p, - is_throw); - } - - // 4. - - // b. - if (index >= old_len_uint32 - && !ecma_is_property_writable (*len_prop_p)) - { - return ecma_reject (is_throw); - } - - // c. - ecma_value_t succeeded = ecma_op_general_object_define_own_property (obj_p, - property_name_p, - property_desc_p, - false); - // d. - JERRY_ASSERT (ecma_is_value_boolean (succeeded)); - - if (ecma_is_value_false (succeeded)) - { - return ecma_reject (is_throw); - } - - // e. - if (index < UINT32_MAX - && index >= old_len_uint32) - { - ecma_property_value_t *len_prop_value_p = ECMA_PROPERTY_VALUE_PTR (len_prop_p); - - // i., ii. - /* Setting the length property is always successful. */ - ecma_value_assign_uint32 (&len_prop_value_p->value, index + 1); - } - - // f. - return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); + return ecma_reject (is_throw); } - JERRY_UNREACHABLE (); + ecma_value_t completition = ecma_op_general_object_define_own_property (object_p, + property_name_p, + property_desc_p, + false); + JERRY_ASSERT (ecma_is_value_boolean (completition)); + + if (ecma_is_value_false (completition)) + { + return ecma_reject (is_throw); + } + + if (update_length) + { + ecma_value_assign_uint32 (&len_prop_value_p->value, index + 1); + } + return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } /* ecma_op_array_object_define_own_property */ /** diff --git a/jerry-core/ecma/operations/ecma-array-object.h b/jerry-core/ecma/operations/ecma-array-object.h index e7e19b9f5..2b80fb495 100644 --- a/jerry-core/ecma/operations/ecma-array-object.h +++ b/jerry-core/ecma/operations/ecma-array-object.h @@ -25,9 +25,26 @@ * @{ */ +/** + * Flags for ecma_op_array_object_set_length + */ +typedef enum +{ + ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_IS_THROW = 1u << 0, /**< is_throw flag is set */ + ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_REJECT = 1u << 1, /**< reject later because the descriptor flags + * contains an unallowed combination */ + ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE_DEFINED = 1u << 2, /**< writable flag defined + * in the property descriptor */ + ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE = 1u << 3, /**< writable flag enabled + * in the property descriptor */ +} ecma_array_object_set_length_flags_t; + extern ecma_value_t ecma_op_create_array_object (const ecma_value_t *, ecma_length_t, bool); +extern ecma_value_t +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); diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c index b94021afe..adae5e198 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -624,16 +624,7 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */ { if (type == ECMA_OBJECT_TYPE_ARRAY && ecma_string_is_length (property_name_p)) { - /* These cases cannot be optimized. */ - ecma_property_descriptor_t value_desc = ecma_make_empty_property_descriptor (); - - value_desc.is_value_defined = true; - value_desc.value = value; - - return ecma_op_object_define_own_property (object_p, - property_name_p, - &value_desc, - is_throw); + return ecma_op_array_object_set_length (object_p, value, 0); } /* There is no need for special casing arrays here because changing the