/** * Create a property in an object and link it into * the object's properties' linked-list (at start of the list). * * @return pointer to newly created property */ static ecma_property_t * ecma_create_property (ecma_object_t *object_p, /**< the object */ ecma_string_t *name_p, /**< property name */ uint8_t type_and_flags) /**< type and flags, see ecma_property_info_t */ { JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2); if (object_p->property_list_or_bound_object_cp != ECMA_NULL_POINTER) { /* If the first entry is free (deleted), we simply use its value. */ ecma_property_header_t *first_property_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, object_p->property_list_or_bound_object_cp); JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (first_property_p)); if (first_property_p->types[0].type_and_flags == ECMA_PROPERTY_TYPE_DELETED) { first_property_p->types[0].type_and_flags = type_and_flags; ecma_property_pair_t *first_property_pair_p = (ecma_property_pair_t *) first_property_p; ECMA_SET_POINTER (first_property_pair_p->names_cp[0], name_p); ecma_property_t *property_p = first_property_p->types + 0; JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p) == first_property_pair_p->values + 0); return property_p; } } /* Otherwise we create a new property pair and use its second value. */ ecma_property_pair_t *first_property_pair_p = ecma_alloc_property_pair (); /* Just copy the previous value (no need to decompress, compress). */ first_property_pair_p->header.next_property_cp = object_p->property_list_or_bound_object_cp; first_property_pair_p->header.types[0].type_and_flags = ECMA_PROPERTY_TYPE_DELETED; first_property_pair_p->header.types[1].type_and_flags = type_and_flags; first_property_pair_p->names_cp[0] = ECMA_NULL_POINTER; ECMA_SET_POINTER (first_property_pair_p->names_cp[1], name_p); ecma_set_property_list (object_p, &first_property_pair_p->header); ecma_property_t *property_p = first_property_pair_p->header.types + 1; JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p) == first_property_pair_p->values + 1); return property_p; } /* ecma_create_property */
/** * Create a property in an object and link it into * the object's properties' linked-list (at start of the list). * * @return pointer to newly created property */ static ecma_property_t * ecma_create_property (ecma_object_t *object_p, /**< the object */ ecma_string_t *name_p, /**< property name */ uint8_t type_and_flags, /**< type and flags, see ecma_property_info_t */ ecma_property_value_t value) /**< property value */ { JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2); jmem_cpointer_t *property_list_head_p = &object_p->property_list_or_bound_object_cp; bool has_hashmap = false; if (*property_list_head_p != ECMA_NULL_POINTER) { /* If the first entry is a hashmap, it is skipped. */ ecma_property_header_t *first_property_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, *property_list_head_p); if (ECMA_PROPERTY_GET_TYPE (first_property_p->types + 0) == ECMA_PROPERTY_TYPE_HASHMAP) { property_list_head_p = &first_property_p->next_property_cp; has_hashmap = true; } } if (*property_list_head_p != ECMA_NULL_POINTER) { /* If the first entry is free (deleted), it is reused. */ ecma_property_header_t *first_property_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, *property_list_head_p); JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (first_property_p)); if (first_property_p->types[0].type_and_flags == ECMA_PROPERTY_TYPE_DELETED) { first_property_p->types[0].type_and_flags = type_and_flags; ecma_property_pair_t *first_property_pair_p = (ecma_property_pair_t *) first_property_p; ECMA_SET_POINTER (first_property_pair_p->names_cp[0], name_p); ecma_property_t *property_p = first_property_p->types + 0; JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p) == first_property_pair_p->values + 0); first_property_pair_p->values[0] = value; /* The property must be fully initialized before ecma_property_hashmap_insert * is called, because the insert operation may reallocate the hashmap, and * that triggers garbage collection which scans all properties of all objects. * A not fully initialized but queued property may cause a crash. */ if (has_hashmap && name_p != NULL) { ecma_property_hashmap_insert (object_p, name_p, first_property_pair_p, 0); } return property_p; } } /* Otherwise we create a new property pair and use its second value. */ ecma_property_pair_t *first_property_pair_p = ecma_alloc_property_pair (); /* Just copy the previous value (no need to decompress, compress). */ first_property_pair_p->header.next_property_cp = *property_list_head_p; first_property_pair_p->header.types[0].type_and_flags = ECMA_PROPERTY_TYPE_DELETED; first_property_pair_p->header.types[1].type_and_flags = type_and_flags; first_property_pair_p->names_cp[0] = ECMA_NULL_POINTER; ECMA_SET_POINTER (first_property_pair_p->names_cp[1], name_p); ECMA_SET_NON_NULL_POINTER (*property_list_head_p, &first_property_pair_p->header); ecma_property_t *property_p = first_property_pair_p->header.types + 1; JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p) == first_property_pair_p->values + 1); first_property_pair_p->values[1] = value; /* See the comment before the other ecma_property_hashmap_insert above. */ if (has_hashmap && name_p != NULL) { ecma_property_hashmap_insert (object_p, name_p, first_property_pair_p, 1); } return property_p; } /* ecma_create_property */