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: