Introducing cache for property by name lookup (LCache).
This commit is contained in:
@@ -13,10 +13,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "globals.h"
|
||||
#include "ecma-alloc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-lcache.h"
|
||||
#include "globals.h"
|
||||
#include "mem-poolman.h"
|
||||
|
||||
JERRY_STATIC_ASSERT (sizeof (ecma_value_t) <= sizeof (uint16_t));
|
||||
@@ -64,6 +65,8 @@ JERRY_STATIC_ASSERT (sizeof (ecma_label_descriptor_t) == sizeof (uint64_t));
|
||||
return p ## ecma_type; \
|
||||
} \
|
||||
\
|
||||
ecma_lcache_invalidate_all (); \
|
||||
\
|
||||
for (ecma_gc_gen_t gen_id = ECMA_GC_GEN_0; \
|
||||
gen_id < ECMA_GC_GEN_COUNT; \
|
||||
gen_id++) \
|
||||
|
||||
@@ -274,6 +274,9 @@ typedef struct ecma_property_t
|
||||
/** Attribute 'Configurable' (ecma_property_configurable_value_t) */
|
||||
unsigned int configurable : 1;
|
||||
|
||||
/** Flag indicating whether the property is registered in LCache */
|
||||
unsigned int is_lcached : 1;
|
||||
|
||||
/** Value */
|
||||
ecma_value_t value;
|
||||
} named_data_property;
|
||||
@@ -290,6 +293,9 @@ typedef struct ecma_property_t
|
||||
/** Attribute 'Configurable' (ecma_property_configurable_value_t) */
|
||||
unsigned int configurable : 1;
|
||||
|
||||
/** Flag indicating whether the property is registered in LCache */
|
||||
unsigned int is_lcached : 1;
|
||||
|
||||
/** Compressed pointer to property's getter */
|
||||
unsigned int get_p : ECMA_POINTER_FIELD_WIDTH;
|
||||
|
||||
|
||||
@@ -1510,6 +1510,44 @@ ecma_is_string_magic (const ecma_string_t *string_p, /**< ecma-string */
|
||||
}
|
||||
} /* ecma_is_string_magic */
|
||||
|
||||
/**
|
||||
* Try to calculate hash of the ecma-string
|
||||
*
|
||||
* Note:
|
||||
* Not all ecma-string containers provide ability to calculate hash.
|
||||
* For now, only strings stored in literal table support calculating of hash.
|
||||
*
|
||||
* Warning:
|
||||
* Anyway, if ecma-string is hashable, for given length of hash,
|
||||
* the hash values should always be equal for equal strings
|
||||
* irrespective of the strings' container type.
|
||||
*
|
||||
* If a ecma-string stored in a container of some type is hashable,
|
||||
* then the ecma-string should always be hashable if stored in container
|
||||
* of the same type.
|
||||
*
|
||||
* @return true - if hash was calculated,
|
||||
* false - otherwise (the string is not hashable).
|
||||
*/
|
||||
bool
|
||||
ecma_string_try_hash (const ecma_string_t *string_p, /**< ecma-string to calculate hash for */
|
||||
uint32_t hash_length_bits, /**< length of hash value, in bits */
|
||||
uint32_t *out_hash_p) /**< out: hash value, if calculated */
|
||||
|
||||
{
|
||||
JERRY_ASSERT (hash_length_bits < sizeof (uint32_t) * JERRY_BITSINBYTE);
|
||||
uint32_t hash_mask = (1u << hash_length_bits);
|
||||
|
||||
if (string_p->container == ECMA_STRING_CONTAINER_LIT_TABLE)
|
||||
{
|
||||
*out_hash_p = (string_p->u.lit_index) & hash_mask;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} /* ecma_string_try_hash */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-lcache.h"
|
||||
#include "jrt-bit-fields.h"
|
||||
|
||||
/**
|
||||
@@ -461,10 +462,13 @@ ecma_create_named_data_property (ecma_object_t *obj_p, /**< object */
|
||||
prop_p->u.named_data_property.enumerable = enumerable;
|
||||
prop_p->u.named_data_property.configurable = configurable;
|
||||
|
||||
prop_p->u.named_data_property.is_lcached = false;
|
||||
|
||||
prop_p->u.named_data_property.value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
||||
|
||||
ecma_property_t *list_head_p = ecma_get_property_list (obj_p);
|
||||
ecma_lcache_invalidate (obj_p, name_p, NULL);
|
||||
|
||||
ecma_property_t *list_head_p = ecma_get_property_list (obj_p);
|
||||
ECMA_SET_POINTER(prop_p->next_property_p, list_head_p);
|
||||
ecma_set_property_list (obj_p, prop_p);
|
||||
|
||||
@@ -502,6 +506,10 @@ ecma_create_named_accessor_property (ecma_object_t *obj_p, /**< object */
|
||||
prop_p->u.named_accessor_property.enumerable = enumerable;
|
||||
prop_p->u.named_accessor_property.configurable = configurable;
|
||||
|
||||
prop_p->u.named_accessor_property.is_lcached = false;
|
||||
|
||||
ecma_lcache_invalidate (obj_p, name_p, NULL);
|
||||
|
||||
ecma_property_t *list_head_p = ecma_get_property_list (obj_p);
|
||||
ECMA_SET_POINTER(prop_p->next_property_p, list_head_p);
|
||||
ecma_set_property_list (obj_p, prop_p);
|
||||
@@ -602,12 +610,14 @@ ecma_get_named_data_property (ecma_object_t *obj_p, /**< object to find property
|
||||
* Free the named data property and values it references.
|
||||
*/
|
||||
static void
|
||||
ecma_free_named_data_property (ecma_object_t *object_p __unused, /**< object the property belongs to */
|
||||
ecma_free_named_data_property (ecma_object_t *object_p, /**< object the property belongs to */
|
||||
ecma_property_t *property_p) /**< the property */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
JERRY_ASSERT (property_p != NULL && property_p->type == ECMA_PROPERTY_NAMEDDATA);
|
||||
|
||||
ecma_lcache_invalidate (object_p, NULL, property_p);
|
||||
|
||||
ecma_deref_ecma_string (ECMA_GET_NON_NULL_POINTER (property_p->u.named_data_property.name_p));
|
||||
ecma_free_value (property_p->u.named_data_property.value, false);
|
||||
|
||||
@@ -618,12 +628,14 @@ ecma_free_named_data_property (ecma_object_t *object_p __unused, /**< object the
|
||||
* Free the named accessor property and values it references.
|
||||
*/
|
||||
static void
|
||||
ecma_free_named_accessor_property (ecma_object_t *object_p __unused, /**< object the property belongs to */
|
||||
ecma_free_named_accessor_property (ecma_object_t *object_p, /**< object the property belongs to */
|
||||
ecma_property_t *property_p) /**< the property */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
JERRY_ASSERT (property_p != NULL && property_p->type == ECMA_PROPERTY_NAMEDACCESSOR);
|
||||
|
||||
ecma_lcache_invalidate (object_p, NULL, property_p);
|
||||
|
||||
ecma_deref_ecma_string (ECMA_GET_NON_NULL_POINTER (property_p->u.named_accessor_property.name_p));
|
||||
|
||||
ecma_dealloc_property (property_p);
|
||||
@@ -805,6 +817,47 @@ ecma_is_property_configurable (ecma_property_t* prop_p) /**< property */
|
||||
}
|
||||
} /* ecma_is_property_configurable */
|
||||
|
||||
/**
|
||||
* Check whether the property is registered in LCache
|
||||
*
|
||||
* @return true / false
|
||||
*/
|
||||
bool
|
||||
ecma_is_property_lcached (ecma_property_t *prop_p) /**< property */
|
||||
{
|
||||
JERRY_ASSERT (prop_p->type == ECMA_PROPERTY_NAMEDDATA
|
||||
|| prop_p->type == ECMA_PROPERTY_NAMEDACCESSOR);
|
||||
|
||||
if (prop_p->type == ECMA_PROPERTY_NAMEDDATA)
|
||||
{
|
||||
return prop_p->u.named_data_property.is_lcached;
|
||||
}
|
||||
else
|
||||
{
|
||||
return prop_p->u.named_accessor_property.is_lcached;
|
||||
}
|
||||
} /* ecma_is_property_lcached */
|
||||
|
||||
/**
|
||||
* Set value of flag indicating whether the property is registered in LCache
|
||||
*/
|
||||
void
|
||||
ecma_set_property_lcached (ecma_property_t *prop_p, /**< property */
|
||||
bool is_lcached) /**< contained (true) or not (false) */
|
||||
{
|
||||
JERRY_ASSERT (prop_p->type == ECMA_PROPERTY_NAMEDDATA
|
||||
|| prop_p->type == ECMA_PROPERTY_NAMEDACCESSOR);
|
||||
|
||||
if (prop_p->type == ECMA_PROPERTY_NAMEDDATA)
|
||||
{
|
||||
prop_p->u.named_data_property.is_lcached = is_lcached;
|
||||
}
|
||||
else
|
||||
{
|
||||
prop_p->u.named_accessor_property.is_lcached = is_lcached;
|
||||
}
|
||||
} /* ecma_set_property_lcached */
|
||||
|
||||
/**
|
||||
* Construct empty property descriptor, i.e.:
|
||||
* property descriptor with all is_defined flags set to false and the rest - to default value.
|
||||
|
||||
@@ -133,6 +133,7 @@ extern const ecma_char_t* ecma_get_magic_string_zt (ecma_magic_string_id_t id);
|
||||
extern ecma_string_t* ecma_get_magic_string (ecma_magic_string_id_t id);
|
||||
extern bool ecma_is_string_magic (const ecma_string_t *string_p, ecma_magic_string_id_t *out_id_p);
|
||||
extern bool ecma_is_zt_string_magic (const ecma_char_t *zt_string_p, ecma_magic_string_id_t *out_id_p);
|
||||
extern bool ecma_string_try_hash (const ecma_string_t *string_p, uint32_t hash_length_bits, uint32_t *out_hash_p);
|
||||
|
||||
/* ecma-helpers-number.c */
|
||||
extern const ecma_number_t ecma_number_relative_eps;
|
||||
@@ -248,6 +249,10 @@ extern void ecma_delete_property (ecma_object_t *obj_p, ecma_property_t *prop_p)
|
||||
extern bool ecma_is_property_enumerable (ecma_property_t* prop_p);
|
||||
extern bool ecma_is_property_configurable (ecma_property_t* prop_p);
|
||||
|
||||
extern bool ecma_is_property_lcached (ecma_property_t *prop_p);
|
||||
extern void ecma_set_property_lcached (ecma_property_t *prop_p,
|
||||
bool is_lcached);
|
||||
|
||||
extern ecma_property_descriptor_t ecma_make_empty_property_descriptor (void);
|
||||
extern void ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p);
|
||||
|
||||
|
||||
@@ -0,0 +1,302 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-lcache.h"
|
||||
#include "jerry-libc.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmalcache Property lookup cache
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Entry of LCache hash table
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/** Compressed pointer to object (ECMA_NULL_POINTER marks record empty) */
|
||||
uint16_t object_cp;
|
||||
|
||||
/** Compressed pointer to property's name */
|
||||
uint16_t prop_name_cp;
|
||||
|
||||
/** Compressed pointer to a property of the object */
|
||||
uint16_t prop_cp;
|
||||
} ecma_lcache_hash_entry_t;
|
||||
|
||||
/**
|
||||
* LCache hash value length, in bits
|
||||
*/
|
||||
#define ECMA_LCACHE_HASH_BITS (8)
|
||||
|
||||
/**
|
||||
* Number of rows in LCache's hash table
|
||||
*/
|
||||
#define ECMA_LCACHE_HASH_ROWS_COUNT (1ull << ECMA_LCACHE_HASH_BITS)
|
||||
|
||||
/**
|
||||
* Number of entries in a row of LCache's hash table
|
||||
*/
|
||||
#define ECMA_LCACHE_HASH_ROW_LENGTH (2)
|
||||
|
||||
/**
|
||||
* LCache's hash table
|
||||
*/
|
||||
static ecma_lcache_hash_entry_t ecma_lcache_hash_table[ ECMA_LCACHE_HASH_ROWS_COUNT ][ ECMA_LCACHE_HASH_ROW_LENGTH ];
|
||||
|
||||
/**
|
||||
* Initialize LCache
|
||||
*/
|
||||
void
|
||||
ecma_lcache_init (void)
|
||||
{
|
||||
__memset (ecma_lcache_hash_table, 0, sizeof (ecma_lcache_hash_entry_t));
|
||||
} /* ecma_lcache_init */
|
||||
|
||||
/**
|
||||
* Invalidate specified LCache entry
|
||||
*/
|
||||
static void
|
||||
ecma_lcache_invalidate_entry (ecma_lcache_hash_entry_t *entry_p) /**< entry to invalidate */
|
||||
{
|
||||
JERRY_ASSERT (entry_p != NULL);
|
||||
JERRY_ASSERT (entry_p->object_cp != ECMA_NULL_POINTER);
|
||||
|
||||
ecma_deref_object (ECMA_GET_NON_NULL_POINTER (entry_p->object_cp));
|
||||
|
||||
entry_p->object_cp = ECMA_NULL_POINTER;
|
||||
ecma_deref_ecma_string (ECMA_GET_NON_NULL_POINTER (entry_p->prop_name_cp));
|
||||
|
||||
if (entry_p->prop_cp != ECMA_NULL_POINTER)
|
||||
{
|
||||
ecma_set_property_lcached (ECMA_GET_NON_NULL_POINTER (entry_p->prop_cp), false);
|
||||
}
|
||||
} /* ecma_lcache_invalidate_entry */
|
||||
|
||||
/**
|
||||
* Invalidate all entries in LCache
|
||||
*/
|
||||
void
|
||||
ecma_lcache_invalidate_all (void)
|
||||
{
|
||||
for (uint32_t row_index = 0; row_index < ECMA_LCACHE_HASH_ROWS_COUNT; row_index++)
|
||||
{
|
||||
for (uint32_t entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++)
|
||||
{
|
||||
if (ecma_lcache_hash_table[ row_index ][ entry_index ].object_cp != ECMA_NULL_POINTER)
|
||||
{
|
||||
ecma_lcache_invalidate_entry (&ecma_lcache_hash_table[ row_index ][ entry_index ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* ecma_lcache_invalidate_all */
|
||||
|
||||
/**
|
||||
* Invalidate entries of LCache's row that correspond to given (object, property) pair
|
||||
*/
|
||||
static void
|
||||
ecma_lcache_invalidate_row_for_object_property_pair (uint32_t row_index, /**< index of the row */
|
||||
unsigned int object_cp, /**< compressed pointer
|
||||
* to an object */
|
||||
unsigned property_cp) /**< compressed pointer
|
||||
* to the object's
|
||||
* property */
|
||||
{
|
||||
for (uint32_t entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++)
|
||||
{
|
||||
if (ecma_lcache_hash_table[ row_index ][ entry_index ].object_cp == object_cp
|
||||
&& ecma_lcache_hash_table[ row_index ][ entry_index ].prop_cp == property_cp)
|
||||
{
|
||||
ecma_lcache_invalidate_entry (&ecma_lcache_hash_table[ row_index ][ entry_index ]);
|
||||
}
|
||||
}
|
||||
} /* ecma_lcache_invalidate_row_for_object_property_pair */
|
||||
|
||||
/**
|
||||
* Insert an entry into LCache
|
||||
*/
|
||||
void
|
||||
ecma_lcache_insert (ecma_object_t *object_p, /**< object */
|
||||
ecma_string_t *prop_name_p, /**< property's name */
|
||||
ecma_property_t *prop_p) /**< pointer to associated property or NULL
|
||||
* (NULL indicates that the object doesn't have property
|
||||
* with the name specified) */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
JERRY_ASSERT (prop_name_p != NULL);
|
||||
|
||||
uint32_t hash_key;
|
||||
|
||||
if (!ecma_string_try_hash (prop_name_p, ECMA_LCACHE_HASH_BITS, &hash_key))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (prop_p != NULL)
|
||||
{
|
||||
JERRY_ASSERT (!ecma_is_property_lcached (prop_p));
|
||||
ecma_set_property_lcached (prop_p, true);
|
||||
}
|
||||
|
||||
int32_t entry_index;
|
||||
for (entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++)
|
||||
{
|
||||
if (ecma_lcache_hash_table[hash_key][entry_index].object_cp == ECMA_NULL_POINTER)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry_index == ECMA_LCACHE_HASH_ROW_LENGTH)
|
||||
{
|
||||
/* No empty entry was found, invalidating the whole row */
|
||||
for (uint32_t i = 0; i < ECMA_LCACHE_HASH_ROW_LENGTH; i++)
|
||||
{
|
||||
ecma_lcache_invalidate_entry (&ecma_lcache_hash_table[hash_key][i]);
|
||||
}
|
||||
|
||||
entry_index = 0;
|
||||
}
|
||||
|
||||
ecma_ref_object (object_p);
|
||||
ECMA_SET_NON_NULL_POINTER (ecma_lcache_hash_table[ hash_key ][ entry_index ].object_cp, object_p);
|
||||
ECMA_SET_NON_NULL_POINTER (ecma_lcache_hash_table[ hash_key ][ entry_index ].prop_name_cp,
|
||||
ecma_copy_or_ref_ecma_string (prop_name_p));
|
||||
ECMA_SET_POINTER (ecma_lcache_hash_table[ hash_key ][ entry_index ].prop_cp, prop_p);
|
||||
} /* ecma_lcache_insert */
|
||||
|
||||
/**
|
||||
* Lookup property in the LCache
|
||||
*
|
||||
* @return true - if (object, property name) pair is registered in LCache,
|
||||
* false - otherwise.
|
||||
*/
|
||||
bool
|
||||
ecma_lcache_lookup (ecma_object_t *object_p, /**< object */
|
||||
const ecma_string_t *prop_name_p, /**< property's name */
|
||||
ecma_property_t **prop_p_p) /**< out: if return value is true,
|
||||
* then here will be pointer to property,
|
||||
* if the object contains property with specified name,
|
||||
* or, otherwise - NULL;
|
||||
* if return value is false,
|
||||
* then the output parameter is not set */
|
||||
{
|
||||
uint32_t hash_key;
|
||||
|
||||
if (!ecma_string_try_hash (prop_name_p, ECMA_LCACHE_HASH_BITS, &hash_key))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int object_cp;
|
||||
ECMA_SET_NON_NULL_POINTER (object_cp, object_p);
|
||||
|
||||
for (uint32_t i = 0; i < ECMA_LCACHE_HASH_ROW_LENGTH; i++)
|
||||
{
|
||||
if (ecma_lcache_hash_table[hash_key][i].object_cp == object_cp
|
||||
&& ecma_compare_ecma_strings (prop_name_p,
|
||||
ECMA_GET_NON_NULL_POINTER (ecma_lcache_hash_table[hash_key][i].prop_name_cp)))
|
||||
{
|
||||
ecma_property_t *prop_p = ECMA_GET_POINTER (ecma_lcache_hash_table[hash_key][i].prop_cp);
|
||||
JERRY_ASSERT (prop_p == NULL || ecma_is_property_lcached (prop_p));
|
||||
|
||||
*prop_p_p = prop_p;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} /* ecma_lcache_lookup */
|
||||
|
||||
/**
|
||||
* Invalidate LCache entries associated with given object and property name / property
|
||||
*
|
||||
* Note:
|
||||
* Either property name argument or property argument should be NULL,
|
||||
* and another should be non-NULL.
|
||||
* In case property name argument is NULL, property's name is taken
|
||||
* from property's description.
|
||||
*/
|
||||
void
|
||||
ecma_lcache_invalidate (ecma_object_t *object_p, /**< object */
|
||||
ecma_string_t *prop_name_arg_p, /**< property's name (See also: Note) */
|
||||
ecma_property_t *prop_p) /**< property (See also: Note) */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
JERRY_ASSERT (prop_p != NULL || prop_name_arg_p != NULL);
|
||||
|
||||
ecma_string_t *prop_name_p = NULL;
|
||||
|
||||
if (prop_p != NULL)
|
||||
{
|
||||
JERRY_ASSERT (prop_p->type == ECMA_PROPERTY_NAMEDDATA
|
||||
|| prop_p->type == ECMA_PROPERTY_NAMEDACCESSOR);
|
||||
|
||||
bool is_cached = ecma_is_property_lcached (prop_p);
|
||||
|
||||
if (!is_cached)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ecma_set_property_lcached (prop_p, false);
|
||||
|
||||
if (prop_p->type == ECMA_PROPERTY_NAMEDDATA)
|
||||
{
|
||||
prop_name_p = ECMA_GET_NON_NULL_POINTER (prop_p->u.named_data_property.name_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
prop_name_p = ECMA_GET_NON_NULL_POINTER (prop_p->u.named_accessor_property.name_p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
prop_name_p = prop_name_arg_p;
|
||||
}
|
||||
|
||||
unsigned int object_cp, prop_cp;
|
||||
ECMA_SET_NON_NULL_POINTER (object_cp, object_p);
|
||||
ECMA_SET_POINTER (prop_cp, prop_p);
|
||||
|
||||
uint32_t hash_key;
|
||||
|
||||
if (!ecma_string_try_hash (prop_name_p, ECMA_LCACHE_HASH_BITS, &hash_key))
|
||||
{
|
||||
/* Property's name hash was not computed, so iterating the whole hash table */
|
||||
for (uint32_t row_index = 0; row_index < ECMA_LCACHE_HASH_ROWS_COUNT; row_index++)
|
||||
{
|
||||
ecma_lcache_invalidate_row_for_object_property_pair (row_index, object_cp, prop_cp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Property's name has was computed.
|
||||
* Given (object, property name) pair should be in the row corresponding to computed hash.
|
||||
*/
|
||||
ecma_lcache_invalidate_row_for_object_property_pair (hash_key, object_cp, prop_cp);
|
||||
}
|
||||
} /* ecma_lcache_invalidate */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,37 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ECMA_LCACHE_H
|
||||
#define ECMA_LCACHE_H
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmalcache Property lookup cache
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern void ecma_lcache_init (void);
|
||||
extern void ecma_lcache_invalidate_all (void);
|
||||
extern void ecma_lcache_insert (ecma_object_t *object_p, ecma_string_t *prop_name_p, ecma_property_t *prop_p);
|
||||
extern bool ecma_lcache_lookup (ecma_object_t *object_p, const ecma_string_t *prop_name_p, ecma_property_t **prop_p_p);
|
||||
extern void ecma_lcache_invalidate (ecma_object_t *object_p, ecma_string_t *prop_name_arg_p, ecma_property_t *prop_p);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ECMA_LCACHE_H */
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "ecma-builtins.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-lcache.h"
|
||||
#include "ecma-operations.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
@@ -32,6 +33,7 @@ ecma_init (void)
|
||||
{
|
||||
ecma_strings_init ();
|
||||
ecma_init_builtins ();
|
||||
ecma_lcache_init ();
|
||||
} /* ecma_init */
|
||||
|
||||
/**
|
||||
@@ -40,6 +42,7 @@ ecma_init (void)
|
||||
void
|
||||
ecma_finalize (void)
|
||||
{
|
||||
ecma_lcache_invalidate_all ();
|
||||
ecma_finalize_builtins ();
|
||||
} /* ecma_finalize */
|
||||
|
||||
|
||||
@@ -13,11 +13,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecma-array-object.h"
|
||||
#include "ecma-builtins.h"
|
||||
#include "ecma-exceptions.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-array-object.h"
|
||||
#include "ecma-function-object.h"
|
||||
#include "ecma-lcache.h"
|
||||
#include "ecma-string-object.h"
|
||||
#include "ecma-objects-arguments.h"
|
||||
#include "ecma-objects-general.h"
|
||||
@@ -82,12 +83,18 @@ ecma_op_object_get_own_property (ecma_object_t *obj_p, /**< the object */
|
||||
&& !ecma_is_lexical_environment (obj_p));
|
||||
JERRY_ASSERT(property_name_p != NULL);
|
||||
|
||||
ecma_property_t *prop_p = NULL;
|
||||
|
||||
if (likely (ecma_lcache_lookup (obj_p, property_name_p, &prop_p)))
|
||||
{
|
||||
return prop_p;
|
||||
}
|
||||
|
||||
const ecma_object_type_t type = ecma_get_object_type (obj_p);
|
||||
JERRY_ASSERT (type < ECMA_OBJECT_TYPE__COUNT);
|
||||
|
||||
const bool is_builtin = ecma_get_object_is_builtin (obj_p);
|
||||
|
||||
ecma_property_t *prop_p = NULL;
|
||||
typedef ecma_property_t* (*get_own_property_ptr_t) (ecma_object_t *, ecma_string_t *);
|
||||
static const get_own_property_ptr_t get_own_property [ECMA_OBJECT_TYPE__COUNT] =
|
||||
{
|
||||
@@ -111,6 +118,12 @@ ecma_op_object_get_own_property (ecma_object_t *obj_p, /**< the object */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Property name should be the same as the value passed to ecma_lcache_lookup above,
|
||||
* or at least hash for the two strings should be either non-computable or the same (see also: ecma_string_try_hash).
|
||||
*/
|
||||
ecma_lcache_insert (obj_p, property_name_p, prop_p);
|
||||
|
||||
return prop_p;
|
||||
} /* ecma_op_object_get_own_property */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user