Optimize LCache operation.

The cache stores only real properties now, because storing NULLs has
little benefit according to tests. Since only real properties are
stored now, there is no need to create real references to objects
and property names, which reduces the keeping of dead objects after
garbage collection.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2016-06-02 03:56:36 -07:00
parent d7f95434e2
commit 5c852ab6fb
12 changed files with 185 additions and 253 deletions
-2
View File
@@ -583,8 +583,6 @@ ecma_try_to_give_back_some_memory (jmem_try_give_memory_back_severity_t severity
JERRY_ASSERT (severity == JMEM_TRY_GIVE_MEMORY_BACK_SEVERITY_HIGH);
/* Freeing as much memory as we currently can */
ecma_lcache_invalidate_all ();
ecma_gc_run ();
}
} /* ecma_try_to_give_back_some_memory */
@@ -527,7 +527,6 @@ ecma_copy_or_ref_ecma_string (ecma_string_t *string_p) /**< string descriptor */
if (unlikely (string_p->refs_and_container >= ECMA_STRING_MAX_REF))
{
/* First trying to free unreachable objects that maybe refer to the string */
ecma_lcache_invalidate_all ();
ecma_gc_run ();
if (string_p->refs_and_container >= ECMA_STRING_MAX_REF)
+31 -16
View File
@@ -586,8 +586,6 @@ ecma_create_named_data_property (ecma_object_t *object_p, /**< object */
name_p = ecma_copy_or_ref_ecma_string (name_p);
ecma_lcache_invalidate (object_p, name_p, NULL);
ecma_property_value_t value;
value.value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
@@ -614,8 +612,6 @@ ecma_create_named_accessor_property (ecma_object_t *object_p, /**< object */
name_p = ecma_copy_or_ref_ecma_string (name_p);
ecma_lcache_invalidate (object_p, name_p, NULL);
ecma_property_value_t value;
ECMA_SET_POINTER (value.getter_setter_pair.getter_p, get_p);
ECMA_SET_POINTER (value.getter_setter_pair.setter_p, set_p);
@@ -636,9 +632,9 @@ ecma_find_named_property (ecma_object_t *obj_p, /**< object to find property in
JERRY_ASSERT (obj_p != NULL);
JERRY_ASSERT (name_p != NULL);
ecma_property_t *property_p;
ecma_property_t *property_p = ecma_lcache_lookup (obj_p, name_p);
if (ecma_lcache_lookup (obj_p, name_p, &property_p))
if (property_p != NULL)
{
return property_p;
}
@@ -649,14 +645,23 @@ ecma_find_named_property (ecma_object_t *obj_p, /**< object to find property in
if (prop_iter_p != NULL
&& ECMA_PROPERTY_GET_TYPE (prop_iter_p->types + 0) == ECMA_PROPERTY_TYPE_HASHMAP)
{
property_p = ecma_property_hashmap_find ((ecma_property_hashmap_t *) prop_iter_p, name_p);
ecma_lcache_insert (obj_p, name_p, property_p);
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;
@@ -670,8 +675,8 @@ ecma_find_named_property (ecma_object_t *obj_p, /**< object to find property in
if (prop_pair_p->names_cp[0] != ECMA_NULL_POINTER)
{
ecma_string_t *property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
prop_pair_p->names_cp[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))
{
@@ -682,8 +687,8 @@ ecma_find_named_property (ecma_object_t *obj_p, /**< object to find property in
if (prop_pair_p->names_cp[1] != ECMA_NULL_POINTER)
{
ecma_string_t *property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
prop_pair_p->names_cp[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))
{
@@ -703,7 +708,11 @@ ecma_find_named_property (ecma_object_t *obj_p, /**< object to find property in
ecma_property_hashmap_create (obj_p);
}
ecma_lcache_insert (obj_p, name_p, property_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 */
@@ -875,12 +884,18 @@ ecma_free_property (ecma_object_t *object_p, /**< object the property belongs to
case ECMA_PROPERTY_TYPE_NAMEDDATA:
{
ecma_free_named_data_property (object_p, property_p);
ecma_lcache_invalidate (object_p, name_p, property_p);
if (ecma_is_property_lcached (property_p))
{
ecma_lcache_invalidate (object_p, name_p, property_p);
}
break;
}
case ECMA_PROPERTY_TYPE_NAMEDACCESSOR:
{
ecma_lcache_invalidate (object_p, name_p, property_p);
if (ecma_is_property_lcached (property_p))
{
ecma_lcache_invalidate (object_p, name_p, property_p);
}
break;
}
case ECMA_PROPERTY_TYPE_INTERNAL:
@@ -1270,7 +1285,7 @@ ecma_is_property_lcached (ecma_property_t *prop_p) /**< property */
/**
* Set value of flag indicating whether the property is registered in LCache
*/
void
inline void __attr_always_inline___
ecma_set_property_lcached (ecma_property_t *prop_p, /**< property */
bool is_lcached) /**< contained (true) or not (false) */
{
@@ -51,7 +51,6 @@ ecma_finalize (void)
jmem_unregister_a_try_give_memory_back_callback (ecma_try_to_give_back_some_memory);
ecma_finalize_environment ();
ecma_lcache_invalidate_all ();
ecma_finalize_builtins ();
ecma_gc_run ();
} /* ecma_finalize */
+80 -155
View File
@@ -43,20 +43,15 @@ typedef struct
jmem_cpointer_t prop_name_cp;
} ecma_lcache_hash_entry_t;
/**
* LCache hash value length, in bits
*/
#define ECMA_LCACHE_HASH_BITS (sizeof (lit_string_hash_t) * JERRY_BITSINBYTE)
/**
* Number of rows in LCache's hash table
*/
#define ECMA_LCACHE_HASH_ROWS_COUNT (1ull << ECMA_LCACHE_HASH_BITS)
#define ECMA_LCACHE_HASH_ROWS_COUNT 256
/**
* Number of entries in a row of LCache's hash table
*/
#define ECMA_LCACHE_HASH_ROW_LENGTH (2)
#define ECMA_LCACHE_HASH_ROW_LENGTH 2
/**
* LCache's hash table
@@ -79,66 +74,31 @@ ecma_lcache_init (void)
/**
* Invalidate specified LCache entry
*/
static void
static inline void __attr_always_inline___
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 (ecma_object_t,
entry_p->object_cp));
JERRY_ASSERT (entry_p->prop_name_cp != ECMA_NULL_POINTER);
JERRY_ASSERT (entry_p->prop_p != NULL);
entry_p->object_cp = ECMA_NULL_POINTER;
ecma_deref_ecma_string (ECMA_GET_NON_NULL_POINTER (ecma_string_t,
entry_p->prop_name_cp));
if (entry_p->prop_p != NULL)
{
ecma_set_property_lcached (entry_p->prop_p, false);
}
ecma_set_property_lcached (entry_p->prop_p, false);
} /* ecma_lcache_invalidate_entry */
#endif /* !CONFIG_ECMA_LCACHE_DISABLE */
/**
* Invalidate all entries in LCache
* Compute the row index of object / property name pair
*
* @return row index
*/
void
ecma_lcache_invalidate_all (void)
static inline size_t __attr_always_inline___
ecma_lcache_row_idx (jmem_cpointer_t object_cp, /**< compressed pointer to object */
const ecma_string_t *prop_name_p) /**< proeprty name */
{
#ifndef CONFIG_ECMA_LCACHE_DISABLE
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 ]);
}
}
}
#endif /* !CONFIG_ECMA_LCACHE_DISABLE */
} /* ecma_lcache_invalidate_all */
#ifndef CONFIG_ECMA_LCACHE_DISABLE
/**
* 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 */
ecma_property_t *property_p) /**< 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_p == property_p)
{
ecma_lcache_invalidate_entry (&ecma_lcache_hash_table[ row_index ][ entry_index ]);
}
}
} /* ecma_lcache_invalidate_row_for_object_property_pair */
/* Randomize the hash of the property name with the object pointer using a xor operation,
* so properties of different objects with the same name can be cached effectively. */
return (size_t) ((ecma_string_hash (prop_name_p) ^ object_cp) & (ECMA_LCACHE_HASH_ROWS_COUNT - 1));
} /* ecma_lcache_row_idx */
#endif /* !CONFIG_ECMA_LCACHE_DISABLE */
/**
@@ -146,51 +106,26 @@ ecma_lcache_invalidate_row_for_object_property_pair (uint32_t row_index, /**< in
*/
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) */
ecma_string_t *prop_name_p, /**< property name */
ecma_property_t *prop_p) /**< property */
{
JERRY_ASSERT (object_p != NULL);
JERRY_ASSERT (prop_name_p != NULL);
JERRY_ASSERT (prop_p != NULL && !ecma_is_property_lcached (prop_p));
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA
|| ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
#ifndef CONFIG_ECMA_LCACHE_DISABLE
prop_name_p = ecma_copy_or_ref_ecma_string (prop_name_p);
jmem_cpointer_t object_cp;
lit_string_hash_t hash_key = ecma_string_hash (prop_name_p);
ECMA_SET_NON_NULL_POINTER (object_cp, object_p);
if (prop_p != NULL)
{
if (unlikely (ecma_is_property_lcached (prop_p)))
{
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
&& ecma_lcache_hash_table[hash_key][entry_index].prop_p == prop_p)
{
#ifndef JERRY_NDEBUG
ecma_object_t *obj_in_entry_p;
obj_in_entry_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t,
ecma_lcache_hash_table[hash_key][entry_index].object_cp);
JERRY_ASSERT (obj_in_entry_p == object_p);
#endif /* !JERRY_NDEBUG */
break;
}
}
JERRY_ASSERT (entry_index != ECMA_LCACHE_HASH_ROW_LENGTH);
ecma_lcache_invalidate_entry (&ecma_lcache_hash_table[hash_key][entry_index]);
}
JERRY_ASSERT (!ecma_is_property_lcached (prop_p));
ecma_set_property_lcached (prop_p, true);
}
ecma_lcache_hash_entry_t *entries_p = ecma_lcache_hash_table[ecma_lcache_row_idx (object_cp, prop_name_p)];
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)
if (entries_p[entry_index].object_cp == ECMA_NULL_POINTER)
{
break;
}
@@ -198,122 +133,112 @@ ecma_lcache_insert (ecma_object_t *object_p, /**< object */
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++)
/* Invalidate the last entry. */
ecma_lcache_invalidate_entry (entries_p + ECMA_LCACHE_HASH_ROW_LENGTH - 1);
/* Shift other entries towards the end. */
for (uint32_t i = ECMA_LCACHE_HASH_ROW_LENGTH - 1; i > 0; i--)
{
ecma_lcache_invalidate_entry (&ecma_lcache_hash_table[hash_key][i]);
entries_p[i] = entries_p[i - 1];
}
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, prop_name_p);
ecma_lcache_hash_table[ hash_key ][ entry_index ].prop_p = prop_p;
#else /* CONFIG_ECMA_LCACHE_DISABLE */
(void) prop_p;
ecma_lcache_hash_entry_t *entry_p = entries_p + entry_index;
ECMA_SET_NON_NULL_POINTER (entry_p->object_cp, object_p);
ECMA_SET_NON_NULL_POINTER (entry_p->prop_name_cp, prop_name_p);
entry_p->prop_p = prop_p;
ecma_set_property_lcached (entry_p->prop_p, true);
#endif /* !CONFIG_ECMA_LCACHE_DISABLE */
} /* ecma_lcache_insert */
/**
* Lookup property in the LCache
*
* @return true - if (object, property name) pair is registered in LCache,
* false - probably, not registered.
* @return a pointer to an ecma_property_t if the lookup is successful
* NULL otherwise
*/
inline bool __attr_always_inline___
inline ecma_property_t * __attr_always_inline___
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 */
const ecma_string_t *prop_name_p) /**< property's name */
{
#ifndef CONFIG_ECMA_LCACHE_DISABLE
lit_string_hash_t hash_key = ecma_string_hash (prop_name_p);
JERRY_ASSERT (object_p != NULL);
JERRY_ASSERT (prop_name_p != NULL);
unsigned int object_cp;
#ifndef CONFIG_ECMA_LCACHE_DISABLE
jmem_cpointer_t object_cp;
ECMA_SET_NON_NULL_POINTER (object_cp, object_p);
for (uint32_t i = 0; i < ECMA_LCACHE_HASH_ROW_LENGTH; i++)
ecma_lcache_hash_entry_t *entry_p = ecma_lcache_hash_table[ecma_lcache_row_idx (object_cp, prop_name_p)];
ecma_lcache_hash_entry_t *entry_end_p = entry_p + ECMA_LCACHE_HASH_ROW_LENGTH;
while (entry_p < entry_end_p)
{
if (ecma_lcache_hash_table[hash_key][i].object_cp == object_cp)
if (entry_p->object_cp == object_cp)
{
ecma_string_t *entry_prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
ecma_lcache_hash_table[hash_key][i].prop_name_cp);
entry_p->prop_name_cp);
JERRY_ASSERT (prop_name_p->hash == entry_prop_name_p->hash);
if (ECMA_STRING_GET_CONTAINER (prop_name_p) == ECMA_STRING_GET_CONTAINER (entry_prop_name_p)
&& prop_name_p->u.common_field == entry_prop_name_p->u.common_field)
{
ecma_property_t *prop_p = ecma_lcache_hash_table[hash_key][i].prop_p;
JERRY_ASSERT (prop_p == NULL || ecma_is_property_lcached (prop_p));
ecma_property_t *prop_p = entry_p->prop_p;
JERRY_ASSERT (prop_p != NULL && ecma_is_property_lcached (prop_p));
*prop_p_p = prop_p;
return true;
return prop_p;
}
else
{
/* may be equal but it is long to compare it here */
/* They can be equal, but generic string comparison is too costly. */
}
}
entry_p++;
}
#else /* CONFIG_ECMA_LCACHE_DISABLE */
(void) object_p;
(void) prop_name_p;
(void) prop_p_p;
#endif /* !CONFIG_ECMA_LCACHE_DISABLE */
return false;
return NULL;
} /* 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_p, /**< property's name (See also: Note) */
ecma_property_t *prop_p) /**< property (See also: Note) */
ecma_string_t *prop_name_p, /**< property's name */
ecma_property_t *prop_p) /**< property */
{
JERRY_ASSERT (object_p != NULL);
JERRY_ASSERT (prop_name_p != NULL);
JERRY_ASSERT (prop_p != NULL && ecma_is_property_lcached (prop_p));
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA
|| ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
#ifndef CONFIG_ECMA_LCACHE_DISABLE
if (prop_p != NULL)
{
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA
|| ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
bool is_cached = ecma_is_property_lcached (prop_p);
if (!is_cached)
{
return;
}
ecma_set_property_lcached (prop_p, false);
}
unsigned int object_cp;
jmem_cpointer_t object_cp;
ECMA_SET_NON_NULL_POINTER (object_cp, object_p);
lit_string_hash_t hash_key = ecma_string_hash (prop_name_p);
ecma_lcache_hash_entry_t *entry_p = ecma_lcache_hash_table[ecma_lcache_row_idx (object_cp, prop_name_p)];
/* 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_p);
for (uint32_t entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++)
{
if (entry_p->object_cp != ECMA_NULL_POINTER && entry_p->prop_p == prop_p)
{
JERRY_ASSERT (ECMA_GET_NON_NULL_POINTER (ecma_string_t,
entry_p->prop_name_cp) == prop_name_p);
JERRY_ASSERT (entry_p->object_cp == object_cp);
ecma_lcache_invalidate_entry (entry_p);
return;
}
entry_p++;
}
/* The property must be present. */
JERRY_UNREACHABLE ();
#endif /* !CONFIG_ECMA_LCACHE_DISABLE */
} /* ecma_lcache_invalidate */
+1 -2
View File
@@ -24,9 +24,8 @@
*/
extern void ecma_lcache_init (void);
extern void ecma_lcache_invalidate_all (void);
extern void ecma_lcache_insert (ecma_object_t *, ecma_string_t *, ecma_property_t *);
extern bool ecma_lcache_lookup (ecma_object_t *, const ecma_string_t *, ecma_property_t **);
extern ecma_property_t *ecma_lcache_lookup (ecma_object_t *, const ecma_string_t *);
extern void ecma_lcache_invalidate (ecma_object_t *, ecma_string_t *, ecma_property_t *);
/**
+3 -1
View File
@@ -402,7 +402,8 @@ ecma_property_hashmap_delete (ecma_object_t *object_p, /**< object */
*/
ecma_property_t *
ecma_property_hashmap_find (ecma_property_hashmap_t *hashmap_p, /**< hashmap */
ecma_string_t *name_p) /**< property name */
ecma_string_t *name_p, /**< property name */
ecma_string_t **property_real_name_p) /**< [out] property real name */
{
#ifndef JERRY_NDEBUG
/* A sanity check in debug mode: a named property must be present
@@ -481,6 +482,7 @@ ecma_property_hashmap_find (ecma_property_hashmap_t *hashmap_p, /**< hashmap */
#ifndef JERRY_NDEBUG
JERRY_ASSERT (property_found);
#endif /* !JERRY_NDEBUG */
*property_real_name_p = property_name_p;
return property_pair_p->header.types + offset;
}
}
+1 -1
View File
@@ -59,7 +59,7 @@ extern void ecma_property_hashmap_insert (ecma_object_t *, ecma_string_t *, ecma
extern void ecma_property_hashmap_delete (ecma_object_t *, ecma_string_t *, ecma_property_t *);
#ifndef CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE
extern ecma_property_t *ecma_property_hashmap_find (ecma_property_hashmap_t *, ecma_string_t *);
extern ecma_property_t *ecma_property_hashmap_find (ecma_property_hashmap_t *, ecma_string_t *, ecma_string_t **);
#endif /* !CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */
/**
+43 -57
View File
@@ -75,83 +75,69 @@ ecma_op_get_value_lex_env_base (ecma_object_t *ref_base_lex_env_p, /**< referenc
* Returned value must be freed with ecma_free_value.
*/
ecma_value_t
ecma_op_get_value_object_base (ecma_reference_t ref) /**< ECMA-reference */
ecma_op_get_value_object_base (ecma_value_t base, /**< base value */
ecma_string_t *property_name_p) /**< property name */
{
const ecma_value_t base = ref.base;
const bool is_unresolvable_reference = ecma_is_value_undefined (base);
const bool has_primitive_base = (ecma_is_value_boolean (base)
|| ecma_is_value_number (base)
|| ecma_is_value_string (base));
const bool has_object_base = (ecma_is_value_object (base)
&& !(ecma_is_lexical_environment (ecma_get_object_from_value (base))));
const bool is_property_reference = has_primitive_base || has_object_base;
JERRY_ASSERT (!is_unresolvable_reference);
JERRY_ASSERT (is_property_reference);
ecma_string_t *referenced_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
ref.referenced_name_cp);
// 4.a
if (!has_primitive_base)
if (ecma_is_value_object (base))
{
// 4.b case 1
ecma_object_t *obj_p = ecma_get_object_from_value (base);
JERRY_ASSERT (obj_p != NULL
&& !ecma_is_lexical_environment (obj_p));
return ecma_op_object_get (obj_p, referenced_name_p);
return ecma_op_object_get (obj_p, property_name_p);
}
JERRY_ASSERT (ecma_is_value_boolean (base)
|| ecma_is_value_number (base)
|| ecma_is_value_string (base));
// 4.b case 2
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
// 1.
ECMA_TRY_CATCH (obj_base, ecma_op_to_object (base), ret_value);
ecma_object_t *obj_p = ecma_get_object_from_value (obj_base);
JERRY_ASSERT (obj_p != NULL
&& !ecma_is_lexical_environment (obj_p));
// 2.
ecma_property_t *prop_p = ecma_op_object_get_property (obj_p, property_name_p);
if (prop_p == NULL)
{
// 3.
ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
}
else if (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA)
{
// 4.
ret_value = ecma_copy_value (ecma_get_named_data_property_value (prop_p));
}
else
{
// 4.b case 2
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
// 5.
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
// 1.
ECMA_TRY_CATCH (obj_base, ecma_op_to_object (base), ret_value);
ecma_object_t *obj_p = ecma_get_named_accessor_property_getter (prop_p);
ecma_object_t *obj_p = ecma_get_object_from_value (obj_base);
JERRY_ASSERT (obj_p != NULL
&& !ecma_is_lexical_environment (obj_p));
// 2.
ecma_property_t *prop_p = ecma_op_object_get_property (obj_p, referenced_name_p);
if (prop_p == NULL)
// 6.
if (obj_p == NULL)
{
// 3.
ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
}
else if (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA)
{
// 4.
ret_value = ecma_copy_value (ecma_get_named_data_property_value (prop_p));
}
else
{
// 5.
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
ecma_object_t *obj_p = ecma_get_named_accessor_property_getter (prop_p);
// 6.
if (obj_p == NULL)
{
ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
}
else
{
// 7.
ret_value = ecma_op_function_call (obj_p, base, NULL, 0);
}
// 7.
ret_value = ecma_op_function_call (obj_p, base, NULL, 0);
}
ECMA_FINALIZE (obj_base);
return ret_value;
}
ECMA_FINALIZE (obj_base);
return ret_value;
} /* ecma_op_get_value_object_base */
/**
+1 -1
View File
@@ -40,7 +40,7 @@ extern ecma_object_t *ecma_get_global_environment (void);
/* ECMA-262 v5, 8.7.1 and 8.7.2 */
extern ecma_value_t ecma_op_get_value_lex_env_base (ecma_object_t *, ecma_string_t *, bool);
extern ecma_value_t ecma_op_get_value_object_base (ecma_reference_t);
extern ecma_value_t ecma_op_get_value_object_base (ecma_value_t, ecma_string_t *);
extern ecma_value_t ecma_op_put_value_lex_env_base (ecma_object_t *, ecma_string_t *, bool, ecma_value_t);
/* ECMA-262 v5, Table 17. Abstract methods of Environment Records */
+2 -2
View File
@@ -177,9 +177,9 @@ 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;
ecma_property_t *prop_p = ecma_lcache_lookup (obj_p, property_name_p);
if (likely (ecma_lcache_lookup (obj_p, property_name_p, &prop_p)))
if (likely (prop_p != NULL))
{
return prop_p;
}
+23 -14
View File
@@ -24,6 +24,7 @@
#include "ecma-function-object.h"
#include "ecma-gc.h"
#include "ecma-helpers.h"
#include "ecma-lcache.h"
#include "ecma-lex-env.h"
#include "ecma-objects.h"
#include "ecma-objects-general.h"
@@ -65,31 +66,40 @@ static ecma_compiled_code_t *__program = NULL;
*/
static ecma_value_t
vm_op_get_value (ecma_value_t object, /**< base object */
ecma_value_t property, /**< property name */
bool is_strict) /**< strict mode */
ecma_value_t property) /**< property name */
{
if (unlikely (ecma_is_value_undefined (object) || ecma_is_value_null (object)))
{
return ecma_raise_type_error (ECMA_ERR_MSG (""));
}
ecma_value_t completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
ecma_value_t prop_to_string_result = ecma_op_to_string (property);
ECMA_TRY_CATCH (property_val,
ecma_op_to_string (property),
completion_value);
if (ecma_is_value_error (prop_to_string_result))
{
return prop_to_string_result;
}
ecma_string_t *property_p = ecma_get_string_from_value (property_val);
ecma_string_t *property_name_p = ecma_get_string_from_value (prop_to_string_result);
ecma_reference_t reference = ecma_make_reference (object, property_p, is_strict);
if (ecma_is_value_object (object))
{
ecma_object_t *object_p = ecma_get_object_from_value (object);
completion_value = ecma_op_get_value_object_base (reference);
ecma_property_t *property_p = ecma_lcache_lookup (object_p, property_name_p);
ecma_free_reference (reference);
if (property_p != NULL &&
ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA)
{
ecma_deref_ecma_string (property_name_p);
return ecma_fast_copy_value (ecma_get_named_data_property_value (property_p));
}
}
ECMA_FINALIZE (property_val);
ecma_value_t get_value_result = ecma_op_get_value_object_base (object, property_name_p);
return completion_value;
ecma_deref_ecma_string (property_name_p);
return get_value_result;
} /* vm_op_get_value */
/**
@@ -1145,8 +1155,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
case VM_OC_PROP_POST_DECR:
{
last_completion_value = vm_op_get_value (left_value,
right_value,
is_strict);
right_value);
if (ecma_is_value_error (last_completion_value))
{