Reduce memory consumption of property names.

Property names were always required a string reference which consumed
a large amount of memory for arrays. This patch reduces this consumption
by directly storing the value part of certain strings.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2016-11-25 05:44:57 -08:00
parent abaf4c8af8
commit 6d67b8dff9
18 changed files with 595 additions and 393 deletions
+77 -73
View File
@@ -406,10 +406,21 @@ ecma_create_property (ecma_object_t *object_p, /**< the object */
if (first_property_p->types[0] == ECMA_PROPERTY_TYPE_DELETED)
{
first_property_p->types[0] = 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);
if (name_p == NULL)
{
first_property_pair_p->names_cp[0] = ECMA_NULL_POINTER;
}
else
{
ecma_property_t name_type;
first_property_pair_p->names_cp[0] = ecma_string_to_property_name (name_p,
&name_type);
type_and_flags = (ecma_property_t) (type_and_flags | name_type);
}
first_property_p->types[0] = type_and_flags;
ecma_property_t *property_p = first_property_p->types + 0;
@@ -462,9 +473,21 @@ ecma_create_property (ecma_object_t *object_p, /**< the object */
/* 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] = ECMA_PROPERTY_TYPE_DELETED;
first_property_pair_p->header.types[1] = 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);
if (name_p == NULL)
{
first_property_pair_p->names_cp[1] = ECMA_NULL_POINTER;
}
else
{
ecma_property_t name_type;
first_property_pair_p->names_cp[1] = ecma_string_to_property_name (name_p,
&name_type);
type_and_flags = (ecma_property_t) (type_and_flags | name_type);
}
first_property_pair_p->header.types[1] = type_and_flags;
ECMA_SET_NON_NULL_POINTER (*property_list_head_p, &first_property_pair_p->header);
@@ -591,8 +614,6 @@ ecma_create_named_data_property (ecma_object_t *object_p, /**< object */
uint8_t type_and_flags = ECMA_PROPERTY_TYPE_NAMEDDATA | prop_attributes;
ecma_ref_ecma_string (name_p);
ecma_property_value_t value;
value.value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
@@ -617,8 +638,6 @@ ecma_create_named_accessor_property (ecma_object_t *object_p, /**< object */
uint8_t type_and_flags = ECMA_PROPERTY_TYPE_NAMEDACCESSOR | prop_attributes;
ecma_ref_ecma_string (name_p);
ecma_property_value_t value;
#ifdef JERRY_CPOINTER_32_BIT
ecma_getter_setter_pointers_t *getter_setter_pair_p;
@@ -659,15 +678,15 @@ ecma_find_named_property (ecma_object_t *obj_p, /**< object to find property in
#ifndef CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE
if (prop_iter_p != NULL && prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP)
{
ecma_string_t *property_real_name_p;
jmem_cpointer_t property_real_name_cp;
property_p = ecma_property_hashmap_find ((ecma_property_hashmap_t *) prop_iter_p,
name_p,
&property_real_name_p);
&property_real_name_cp);
if (property_p != NULL
&& !ecma_is_property_lcached (property_p))
{
ecma_lcache_insert (obj_p, property_real_name_p, property_p);
ecma_lcache_insert (obj_p, property_real_name_cp, property_p);
}
return property_p;
@@ -675,7 +694,7 @@ ecma_find_named_property (ecma_object_t *obj_p, /**< object to find property in
#endif /* !CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */
property_p = NULL;
ecma_string_t *property_name_p = NULL;
jmem_cpointer_t property_name_cp = ECMA_NULL_POINTER;
uint32_t steps = 0;
@@ -687,25 +706,25 @@ ecma_find_named_property (ecma_object_t *obj_p, /**< object to find property in
JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2);
if (prop_pair_p->names_cp[0] != ECMA_NULL_POINTER)
if (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[0]))
{
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))
if (ecma_string_compare_to_property_name (prop_iter_p->types[0],
prop_pair_p->names_cp[0],
name_p))
{
property_name_cp = prop_pair_p->names_cp[0];
property_p = prop_iter_p->types + 0;
break;
}
}
if (prop_pair_p->names_cp[1] != ECMA_NULL_POINTER)
if (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[1]))
{
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))
if (ecma_string_compare_to_property_name (prop_iter_p->types[1],
prop_pair_p->names_cp[1],
name_p))
{
property_name_cp = prop_pair_p->names_cp[1];
property_p = prop_iter_p->types + 1;
break;
}
@@ -725,7 +744,7 @@ ecma_find_named_property (ecma_object_t *obj_p, /**< object to find property in
if (property_p != NULL
&& !ecma_is_property_lcached (property_p))
{
ecma_lcache_insert (obj_p, property_name_p, property_p);
ecma_lcache_insert (obj_p, property_name_cp, property_p);
}
return property_p;
@@ -791,7 +810,7 @@ ecma_free_internal_property (ecma_property_t *property_p) /**< the property */
*/
void
ecma_free_property (ecma_object_t *object_p, /**< object the property belongs to */
ecma_string_t *name_p, /**< name of the property or NULL */
jmem_cpointer_t name_cp, /**< name of the property or ECMA_NULL_POINTER */
ecma_property_t *property_p) /**< property */
{
JERRY_ASSERT (object_p != NULL && property_p != NULL);
@@ -801,11 +820,6 @@ ecma_free_property (ecma_object_t *object_p, /**< object the property belongs to
case ECMA_PROPERTY_TYPE_NAMEDDATA:
{
ecma_free_value_if_not_object (ECMA_PROPERTY_VALUE_PTR (property_p)->value);
if (ecma_is_property_lcached (property_p))
{
ecma_lcache_invalidate (object_p, name_p, property_p);
}
break;
}
case ECMA_PROPERTY_TYPE_NAMEDACCESSOR:
@@ -816,27 +830,30 @@ ecma_free_property (ecma_object_t *object_p, /**< object the property belongs to
ECMA_PROPERTY_VALUE_PTR (property_p)->getter_setter_pair_cp);
jmem_pools_free (getter_setter_pair_p, sizeof (ecma_getter_setter_pointers_t));
#endif /* JERRY_CPOINTER_32_BIT */
if (ecma_is_property_lcached (property_p))
{
ecma_lcache_invalidate (object_p, name_p, property_p);
}
break;
}
case ECMA_PROPERTY_TYPE_SPECIAL:
{
JERRY_ASSERT (name_p == NULL);
ecma_free_internal_property (property_p);
break;
}
default:
{
JERRY_UNREACHABLE ();
break;
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_SPECIAL);
JERRY_ASSERT (name_cp == ECMA_NULL_POINTER);
ecma_free_internal_property (property_p);
*property_p = ECMA_PROPERTY_TYPE_DELETED;
return;
}
}
if (ecma_is_property_lcached (property_p))
{
ecma_lcache_invalidate (object_p, name_cp, property_p);
}
if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_PROPERTY_NAME_TYPE_STRING)
{
ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, name_cp);
ecma_deref_ecma_string (prop_name_p);
}
*property_p = ECMA_PROPERTY_TYPE_DELETED;
} /* ecma_free_property */
@@ -872,23 +889,17 @@ ecma_delete_property (ecma_object_t *object_p, /**< object */
{
if ((prop_pair_p->values + i) == prop_value_p)
{
ecma_string_t *name_p = ECMA_GET_POINTER (ecma_string_t, prop_pair_p->names_cp[i]);
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (cur_prop_p->types[i]) != ECMA_PROPERTY_TYPE_SPECIAL);
ecma_free_property (object_p, name_p, cur_prop_p->types + i);
if (name_p != NULL)
if (has_hashmap)
{
if (has_hashmap)
{
ecma_property_hashmap_delete (object_p,
name_p,
cur_prop_p->types + i);
}
ecma_deref_ecma_string (name_p);
prop_pair_p->names_cp[i] = ECMA_NULL_POINTER;
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)
@@ -955,13 +966,11 @@ ecma_delete_array_properties (ecma_object_t *object_p, /**< object */
for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
{
if (prop_pair_p->names_cp[i] != ECMA_NULL_POINTER
if (ECMA_PROPERTY_IS_NAMED_PROPERTY (current_prop_p->types[i])
&& !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 = ecma_string_get_array_index (property_name_p);
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)
{
@@ -1001,29 +1010,24 @@ ecma_delete_array_properties (ecma_object_t *object_p, /**< object */
for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
{
if (prop_pair_p->names_cp[i] != ECMA_NULL_POINTER
if (ECMA_PROPERTY_IS_NAMED_PROPERTY (current_prop_p->types[i])
&& 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 = ecma_string_get_array_index (property_name_p);
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);
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);
ecma_property_hashmap_delete (object_p, prop_pair_p->names_cp[i], current_prop_p->types + i);
}
JERRY_ASSERT (current_prop_p->types[i] == ECMA_PROPERTY_TYPE_DELETED);
ecma_free_property (object_p, prop_pair_p->names_cp[i], current_prop_p->types + i);
ecma_deref_ecma_string (property_name_p);
prop_pair_p->names_cp[i] = ECMA_NULL_POINTER;
JERRY_ASSERT (current_prop_p->types[i] == ECMA_PROPERTY_TYPE_DELETED);
}
}
}