/** * 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 (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 (ECMA_PROPERTY_IS_NAMED_PROPERTY (current_prop_p->types[i]) && !ecma_is_property_configurable (current_prop_p->types[i])) { uint32_t index = ecma_string_get_property_index (current_prop_p->types[i], prop_pair_p->names_cp[i]); if (index < old_length && index >= new_length) { JERRY_ASSERT (index != ECMA_STRING_NOT_ARRAY_INDEX); 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; ecma_property_hashmap_delete_status hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_NO_HASHMAP; if (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); hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP; } 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 (ECMA_PROPERTY_IS_NAMED_PROPERTY (current_prop_p->types[i]) && ecma_is_property_configurable (current_prop_p->types[i])) { uint32_t index = ecma_string_get_property_index (current_prop_p->types[i], prop_pair_p->names_cp[i]); if (index < old_length && index >= new_length) { JERRY_ASSERT (index != ECMA_STRING_NOT_ARRAY_INDEX); if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP) { hashmap_status = ecma_property_hashmap_delete (object_p, prop_pair_p->names_cp[i], current_prop_p->types + i); } ecma_free_property (object_p, prop_pair_p->names_cp[i], current_prop_p->types + i); JERRY_ASSERT (current_prop_p->types[i] == ECMA_PROPERTY_TYPE_DELETED); } } } 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); } } if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP) { ecma_property_hashmap_free (object_p); ecma_property_hashmap_create (object_p); } return new_length; } /* ecma_delete_array_properties */
/** * Find named data property or named access property in specified object. * * @return pointer to the property, if it is found, * NULL - otherwise. */ ecma_property_t * ecma_find_named_property (ecma_object_t *obj_p, /**< object to find property in */ ecma_string_t *name_p) /**< property's name */ { JERRY_ASSERT (obj_p != NULL); JERRY_ASSERT (name_p != NULL); ecma_property_t *property_p = ecma_lcache_lookup (obj_p, name_p); if (property_p != NULL) { return property_p; } ecma_property_header_t *prop_iter_p = ecma_get_property_list (obj_p); #ifndef CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE if (prop_iter_p != NULL && ECMA_PROPERTY_GET_TYPE (prop_iter_p->types + 0) == ECMA_PROPERTY_TYPE_HASHMAP) { ecma_string_t *property_real_name_p; property_p = ecma_property_hashmap_find ((ecma_property_hashmap_t *) prop_iter_p, name_p, &property_real_name_p); if (property_p != NULL && !ecma_is_property_lcached (property_p)) { ecma_lcache_insert (obj_p, property_real_name_p, property_p); } return property_p; } #endif /* !CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */ property_p = NULL; ecma_string_t *property_name_p = NULL; uint32_t steps = 0; while (prop_iter_p != NULL) { JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2); if (prop_pair_p->names_cp[0] != ECMA_NULL_POINTER) { property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_pair_p->names_cp[0]); if (ecma_compare_ecma_strings (name_p, property_name_p)) { property_p = prop_iter_p->types + 0; break; } } if (prop_pair_p->names_cp[1] != ECMA_NULL_POINTER) { property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_pair_p->names_cp[1]); if (ecma_compare_ecma_strings (name_p, property_name_p)) { property_p = prop_iter_p->types + 1; break; } } steps++; prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t, prop_iter_p->next_property_cp); } if (steps > (ECMA_PROPERTY_HASMAP_MINIMUM_SIZE / 4)) { ecma_property_hashmap_create (obj_p); } if (property_p != NULL && !ecma_is_property_lcached (property_p)) { ecma_lcache_insert (obj_p, property_name_p, property_p); } return property_p; } /* ecma_find_named_property */
/** * Delete the object's property referenced by its value pointer. * * Note: specified property must be owned by specified object. */ void ecma_delete_property (ecma_object_t *object_p, /**< object */ ecma_property_value_t *prop_value_p) /**< property value reference */ { ecma_property_header_t *cur_prop_p = ecma_get_property_list (object_p); ecma_property_header_t *prev_prop_p = NULL; ecma_property_hashmap_delete_status hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_NO_HASHMAP; if (cur_prop_p != NULL && cur_prop_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) { prev_prop_p = cur_prop_p; cur_prop_p = ECMA_GET_POINTER (ecma_property_header_t, cur_prop_p->next_property_cp); hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP; } while (true) { JERRY_ASSERT (cur_prop_p != NULL); JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (cur_prop_p)); ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) cur_prop_p; for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) { if ((prop_pair_p->values + i) == prop_value_p) { JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (cur_prop_p->types[i]) != ECMA_PROPERTY_TYPE_SPECIAL); if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP) { hashmap_status = ecma_property_hashmap_delete (object_p, prop_pair_p->names_cp[i], cur_prop_p->types + i); } ecma_free_property (object_p, prop_pair_p->names_cp[i], cur_prop_p->types + i); JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2); if (cur_prop_p->types[1 - i] != ECMA_PROPERTY_TYPE_DELETED) { /* The other property is still valid. */ if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP) { ecma_property_hashmap_free (object_p); ecma_property_hashmap_create (object_p); } return; } JERRY_ASSERT (cur_prop_p->types[i] == ECMA_PROPERTY_TYPE_DELETED); if (prev_prop_p == NULL) { object_p->property_list_or_bound_object_cp = cur_prop_p->next_property_cp; } else { prev_prop_p->next_property_cp = cur_prop_p->next_property_cp; } ecma_dealloc_property_pair ((ecma_property_pair_t *) cur_prop_p); if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP) { ecma_property_hashmap_free (object_p); ecma_property_hashmap_create (object_p); } return; } } prev_prop_p = cur_prop_p; cur_prop_p = ECMA_GET_POINTER (ecma_property_header_t, cur_prop_p->next_property_cp); } } /* ecma_delete_property */