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