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
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+3
-7
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user