From 7b0e1672aefdff1497e449addb659a33b625b419 Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Mon, 5 Mar 2018 14:54:33 +0100 Subject: [PATCH] Improve property search. (#2232) JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com --- jerry-core/ecma/base/ecma-gc.c | 8 +- jerry-core/ecma/base/ecma-globals.h | 94 ++++++++------- jerry-core/ecma/base/ecma-helpers-string.c | 56 ++++++++- jerry-core/ecma/base/ecma-helpers.c | 119 +++++++++++-------- jerry-core/ecma/base/ecma-helpers.h | 1 + jerry-core/ecma/base/ecma-lcache.c | 31 ++++- jerry-core/ecma/base/ecma-property-hashmap.c | 90 +++++++++++--- 7 files changed, 272 insertions(+), 127 deletions(-) diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index fb6f6be40..995cf665f 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -192,8 +192,8 @@ ecma_gc_mark_property (ecma_property_pair_t *property_pair_p, /**< property pair } case ECMA_PROPERTY_TYPE_SPECIAL: { - JERRY_ASSERT (ECMA_PROPERTY_GET_SPECIAL_PROPERTY_TYPE (&property) == ECMA_SPECIAL_PROPERTY_DELETED - || ECMA_PROPERTY_GET_SPECIAL_PROPERTY_TYPE (&property) == ECMA_SPECIAL_PROPERTY_HASHMAP); + JERRY_ASSERT (property == ECMA_PROPERTY_TYPE_HASHMAP + || property == ECMA_PROPERTY_TYPE_DELETED); break; } default: @@ -491,10 +491,6 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */ } } - /* Both must be deleted. */ - JERRY_ASSERT (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_DELETED - && prop_iter_p->types[1] == ECMA_PROPERTY_TYPE_DELETED); - prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t, prop_iter_p->next_property_cp); diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 5ae7a0532..8ca734d15 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -274,20 +274,6 @@ typedef struct } u; } ecma_native_pointer_t; -/** - * Special property identifiers. - */ -typedef enum -{ - ECMA_SPECIAL_PROPERTY_DELETED, /**< deleted property */ - - /* Note: when new special types are added - * ECMA_PROPERTY_IS_PROPERTY_PAIR must be updated as well. */ - ECMA_SPECIAL_PROPERTY_HASHMAP, /**< hashmap property */ - - ECMA_SPECIAL_PROPERTY__COUNT /**< Number of special property types */ -} ecma_internal_property_id_t; - /** * Property's 'Writable' attribute's values description. */ @@ -350,32 +336,6 @@ typedef enum */ #define ECMA_PROPERTY_FLAG_SHIFT 2 -/** - * Define special property type. - */ -#define ECMA_SPECIAL_PROPERTY_VALUE(type) \ - ((uint8_t) (ECMA_PROPERTY_TYPE_SPECIAL | ((type) << ECMA_PROPERTY_FLAG_SHIFT))) - -/** - * Type of deleted property. - */ -#define ECMA_PROPERTY_TYPE_DELETED ECMA_SPECIAL_PROPERTY_VALUE (ECMA_SPECIAL_PROPERTY_DELETED) - -/** - * Type of hash-map property. - */ -#define ECMA_PROPERTY_TYPE_HASHMAP ECMA_SPECIAL_PROPERTY_VALUE (ECMA_SPECIAL_PROPERTY_HASHMAP) - -/** - * Type of property not found. - */ -#define ECMA_PROPERTY_TYPE_NOT_FOUND ECMA_PROPERTY_TYPE_DELETED - -/** - * Type of property not found and no more searching in the proto chain. - */ -#define ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP ECMA_PROPERTY_TYPE_HASHMAP - /** * Property flag list (for ECMA_PROPERTY_TYPE_NAMEDDATA * and ECMA_PROPERTY_TYPE_NAMEDACCESSOR). @@ -422,6 +382,54 @@ typedef enum */ #define ECMA_PROPERTY_NAME_TYPE_SHIFT (ECMA_PROPERTY_FLAG_SHIFT + 4) +/** + * Special property identifiers. + */ +typedef enum +{ + /* Note: when new special types are added + * ECMA_PROPERTY_IS_PROPERTY_PAIR must be updated as well. */ + ECMA_SPECIAL_PROPERTY_HASHMAP, /**< hashmap property */ + ECMA_SPECIAL_PROPERTY_DELETED, /**< deleted property */ + + ECMA_SPECIAL_PROPERTY__COUNT /**< Number of special property types */ +} ecma_internal_property_id_t; + +/** + * Define special property type. + */ +#define ECMA_SPECIAL_PROPERTY_VALUE(type) \ + ((uint8_t) (ECMA_PROPERTY_TYPE_SPECIAL | ((type) << ECMA_PROPERTY_NAME_TYPE_SHIFT))) + +/** + * Type of deleted property. + */ +#define ECMA_PROPERTY_TYPE_DELETED ECMA_SPECIAL_PROPERTY_VALUE (ECMA_SPECIAL_PROPERTY_DELETED) + +/** + * Type of hash-map property. + */ +#define ECMA_PROPERTY_TYPE_HASHMAP ECMA_SPECIAL_PROPERTY_VALUE (ECMA_SPECIAL_PROPERTY_HASHMAP) + +/** + * Name constant of a deleted property. + */ +#ifdef JERRY_CPOINTER_32_BIT +#define ECMA_PROPERTY_DELETED_NAME 0xffffffffu +#else /* !JERRY_CPOINTER_32_BIT */ +#define ECMA_PROPERTY_DELETED_NAME 0xffffu +#endif /* JERRY_CPOINTER_32_BIT */ + +/** + * Type of property not found. + */ +#define ECMA_PROPERTY_TYPE_NOT_FOUND ECMA_PROPERTY_TYPE_HASHMAP + +/** + * Type of property not found and no more searching in the proto chain. + */ +#define ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP ECMA_PROPERTY_TYPE_DELETED + /** * Abstract property representation. * @@ -523,12 +531,6 @@ typedef struct #define ECMA_PROPERTY_IS_NAMED_PROPERTY(property) \ (ECMA_PROPERTY_GET_TYPE (property) != ECMA_PROPERTY_TYPE_SPECIAL) -/** - * Returns the internal property type - */ -#define ECMA_PROPERTY_GET_SPECIAL_PROPERTY_TYPE(property_p) \ - ((ecma_internal_property_id_t) (*(property_p) >> ECMA_PROPERTY_FLAG_SHIFT)) - /** * Add the offset part to a property for computing its property data pointer. */ diff --git a/jerry-core/ecma/base/ecma-helpers-string.c b/jerry-core/ecma/base/ecma-helpers-string.c index 2823a16a3..d1888ad50 100644 --- a/jerry-core/ecma/base/ecma-helpers-string.c +++ b/jerry-core/ecma/base/ecma-helpers-string.c @@ -1708,8 +1708,13 @@ ecma_string_compare_to_property_name (ecma_property_t property, /**< property na return ecma_property_to_string (property, prop_name_cp) == string_p; } + if (ECMA_IS_DIRECT_STRING (string_p)) + { + return false; + } + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); - return ecma_compare_ecma_strings (prop_name_p, string_p); + return ecma_compare_ecma_non_direct_strings (prop_name_p, string_p); } /* ecma_string_compare_to_property_name */ /** @@ -1722,8 +1727,8 @@ ecma_string_compare_to_property_name (ecma_property_t property, /**< property na * false - otherwise */ static bool __attr_noinline___ -ecma_compare_ecma_strings_longpath (const ecma_string_t *string1_p, /* ecma-string */ - const ecma_string_t *string2_p) /* ecma-string */ +ecma_compare_ecma_strings_longpath (const ecma_string_t *string1_p, /**< ecma-string */ + const ecma_string_t *string2_p) /**< ecma-string */ { JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_GET_CONTAINER (string2_p)); @@ -1756,14 +1761,14 @@ ecma_compare_ecma_strings_longpath (const ecma_string_t *string1_p, /* ecma-stri } /* ecma_compare_ecma_strings_longpath */ /** - * Compare ecma-string to ecma-string + * Compare two ecma-strings * * @return true - if strings are equal; * false - otherwise */ inline bool __attr_always_inline___ -ecma_compare_ecma_strings (const ecma_string_t *string1_p, /* ecma-string */ - const ecma_string_t *string2_p) /* ecma-string */ +ecma_compare_ecma_strings (const ecma_string_t *string1_p, /**< ecma-string */ + const ecma_string_t *string2_p) /**< ecma-string */ { JERRY_ASSERT (string1_p != NULL && string2_p != NULL); @@ -1799,6 +1804,45 @@ ecma_compare_ecma_strings (const ecma_string_t *string1_p, /* ecma-string */ return ecma_compare_ecma_strings_longpath (string1_p, string2_p); } /* ecma_compare_ecma_strings */ +/** + * Compare two non-direct ecma-strings + * + * @return true - if strings are equal; + * false - otherwise + */ +inline bool __attr_always_inline___ +ecma_compare_ecma_non_direct_strings (const ecma_string_t *string1_p, /**< ecma-string */ + const ecma_string_t *string2_p) /**< ecma-string */ +{ + JERRY_ASSERT (string1_p != NULL && string2_p != NULL); + JERRY_ASSERT (!ECMA_IS_DIRECT_STRING (string1_p) && !ECMA_IS_DIRECT_STRING (string2_p)); + + /* Fast paths first. */ + if (string1_p == string2_p) + { + return true; + } + + if (string1_p->hash != string2_p->hash) + { + return false; + } + + ecma_string_container_t string1_container = ECMA_STRING_GET_CONTAINER (string1_p); + + if (string1_container != ECMA_STRING_GET_CONTAINER (string2_p)) + { + return false; + } + + if (string1_container >= ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + return string1_p->u.common_uint32_field == string2_p->u.common_uint32_field; + } + + return ecma_compare_ecma_strings_longpath (string1_p, string2_p); +} /* ecma_compare_ecma_non_direct_strings */ + /** * Relational compare of ecma-strings. * diff --git a/jerry-core/ecma/base/ecma-helpers.c b/jerry-core/ecma/base/ecma-helpers.c index 12a5870c2..7541b983b 100644 --- a/jerry-core/ecma/base/ecma-helpers.c +++ b/jerry-core/ecma/base/ecma-helpers.c @@ -36,48 +36,33 @@ * @{ */ -/** - * The ecma property types must be lower than the container mask. - */ JERRY_STATIC_ASSERT (ECMA_PROPERTY_TYPE_MASK >= ECMA_PROPERTY_TYPE__MAX, ecma_property_types_must_be_lower_than_the_container_mask); -/** - * The ecma object types must be lower than the container mask. - */ JERRY_STATIC_ASSERT (ECMA_OBJECT_TYPE_MASK >= ECMA_OBJECT_TYPE__MAX - 1, ecma_object_types_must_be_lower_than_the_container_mask); -/** - * The ecma lexical environment types must be lower than the container mask. - */ JERRY_STATIC_ASSERT (ECMA_OBJECT_TYPE_MASK >= ECMA_LEXICAL_ENVIRONMENT_TYPE__MAX, ecma_lexical_environment_types_must_be_lower_than_the_container_mask); -/** - * The ecma built in flag must follow the object type. - */ JERRY_STATIC_ASSERT (ECMA_OBJECT_TYPE_MASK + 1 == ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV, ecma_built_in_flag_must_follow_the_object_type); -/** - * The ecma extensible flag must follow the gc visited flag. - */ JERRY_STATIC_ASSERT (ECMA_OBJECT_FLAG_EXTENSIBLE == (ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV << 1), ecma_extensible_flag_must_follow_the_built_in_flag); -/** - * The ecma object ref one must follow the extensible flag. - */ JERRY_STATIC_ASSERT (ECMA_OBJECT_REF_ONE == (ECMA_OBJECT_FLAG_EXTENSIBLE << 1), ecma_object_ref_one_must_follow_the_extensible_flag); -/** - * The ecma object max ref does not fill the remaining bits. - */ JERRY_STATIC_ASSERT ((ECMA_OBJECT_MAX_REF | (ECMA_OBJECT_REF_ONE - 1)) == UINT16_MAX, ecma_object_max_ref_does_not_fill_the_remaining_bits); +JERRY_STATIC_ASSERT (ECMA_PROPERTY_TYPE_DELETED == (ECMA_DIRECT_STRING_MAGIC << ECMA_PROPERTY_NAME_TYPE_SHIFT), + ecma_property_type_deleted_must_have_magic_string_name_type); + +JERRY_STATIC_ASSERT (ECMA_PROPERTY_DELETED_NAME >= LIT_MAGIC_STRING__COUNT, + ecma_property_deleted_name_must_not_be_valid_maigc_string_id); + /** * Create an object with specified prototype object * (or NULL prototype if there is not prototype for the object) @@ -486,7 +471,7 @@ 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->names_cp[0] = ECMA_NULL_POINTER; + first_property_pair_p->names_cp[0] = ECMA_PROPERTY_DELETED_NAME; if (name_p == NULL) { @@ -628,47 +613,85 @@ ecma_find_named_property (ecma_object_t *obj_p, /**< object to find property in } #endif /* !CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */ - property_p = NULL; - jmem_cpointer_t property_name_cp = ECMA_NULL_POINTER; + JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2); uint32_t steps = 0; + jmem_cpointer_t property_name_cp = ECMA_NULL_POINTER; - while (prop_iter_p != NULL) + if (ECMA_IS_DIRECT_STRING (name_p)) { - JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + ecma_property_t prop_name_type = (ecma_property_t) ECMA_GET_DIRECT_STRING_TYPE (name_p); + property_name_cp = (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (name_p); - ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + JERRY_ASSERT (prop_name_type > 0); - JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2); - - if (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[0])) + while (prop_iter_p != NULL) { - if (ecma_string_compare_to_property_name (prop_iter_p->types[0], - prop_pair_p->names_cp[0], - name_p)) + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + if (prop_pair_p->names_cp[0] == property_name_cp + && ECMA_PROPERTY_GET_NAME_TYPE (prop_iter_p->types[0]) == prop_name_type) { - property_name_cp = prop_pair_p->names_cp[0]; + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[0])); + property_p = prop_iter_p->types + 0; break; } - } - if (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[1])) - { - if (ecma_string_compare_to_property_name (prop_iter_p->types[1], - prop_pair_p->names_cp[1], - name_p)) + if (prop_pair_p->names_cp[1] == property_name_cp + && ECMA_PROPERTY_GET_NAME_TYPE (prop_iter_p->types[1]) == prop_name_type) { - property_name_cp = prop_pair_p->names_cp[1]; + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[1])); + 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); } + } + else + { + while (prop_iter_p != NULL) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); - steps++; + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; - prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t, - prop_iter_p->next_property_cp); + if (ECMA_PROPERTY_GET_NAME_TYPE (prop_iter_p->types[0]) == ECMA_DIRECT_STRING_PTR) + { + property_name_cp = prop_pair_p->names_cp[0]; + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, property_name_cp); + + if (ecma_compare_ecma_non_direct_strings (name_p, prop_name_p)) + { + property_p = prop_iter_p->types + 0; + break; + } + } + + if (ECMA_PROPERTY_GET_NAME_TYPE (prop_iter_p->types[1]) == ECMA_DIRECT_STRING_PTR) + { + property_name_cp = prop_pair_p->names_cp[1]; + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, property_name_cp); + + if (ecma_compare_ecma_non_direct_strings (name_p, prop_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 / 2)) @@ -763,8 +786,6 @@ ecma_free_property (ecma_object_t *object_p, /**< object the property belongs to 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 */ /** @@ -809,6 +830,8 @@ ecma_delete_property (ecma_object_t *object_p, /**< object */ } ecma_free_property (object_p, prop_pair_p->names_cp[i], cur_prop_p->types + i); + cur_prop_p->types[i] = ECMA_PROPERTY_TYPE_DELETED; + prop_pair_p->names_cp[i] = ECMA_PROPERTY_DELETED_NAME; JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2); @@ -949,8 +972,8 @@ ecma_delete_array_properties (ecma_object_t *object_p, /**< object */ } 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); + current_prop_p->types[i] = ECMA_PROPERTY_TYPE_DELETED; + prop_pair_p->names_cp[i] = ECMA_PROPERTY_DELETED_NAME; } } } diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 8ac4555fb..cbc8d8e74 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -247,6 +247,7 @@ bool ecma_string_compare_to_property_name (ecma_property_t property, jmem_cpoint const ecma_string_t *string_p); bool ecma_compare_ecma_strings (const ecma_string_t *string1_p, const ecma_string_t *string2_p); +bool ecma_compare_ecma_non_direct_strings (const ecma_string_t *string1_p, const ecma_string_t *string2_p); bool ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p, const ecma_string_t *string2_p); ecma_length_t ecma_string_get_length (const ecma_string_t *string_p); ecma_length_t ecma_string_get_utf8_length (const ecma_string_t *string_p); diff --git a/jerry-core/ecma/base/ecma-lcache.c b/jerry-core/ecma/base/ecma-lcache.c index 81cb7618a..32b69bc41 100644 --- a/jerry-core/ecma/base/ecma-lcache.c +++ b/jerry-core/ecma/base/ecma-lcache.c @@ -175,13 +175,36 @@ ecma_lcache_lookup (ecma_object_t *object_p, /**< object */ jmem_cpointer_t object_cp; ECMA_SET_NON_NULL_POINTER (object_cp, object_p); - size_t row_index = ecma_lcache_row_index (object_cp, ecma_string_hash (prop_name_p)); + ecma_property_t prop_name_type; + jmem_cpointer_t prop_name_cp; + lit_string_hash_t name_hash; + + if (ECMA_IS_DIRECT_STRING (prop_name_p)) + { + prop_name_type = (ecma_property_t) ECMA_GET_DIRECT_STRING_TYPE (prop_name_p); + + uintptr_t value = ECMA_GET_DIRECT_STRING_VALUE (prop_name_p); + prop_name_cp = (jmem_cpointer_t) value; + name_hash = (lit_string_hash_t) value; + + if (prop_name_type == ECMA_DIRECT_STRING_MAGIC_EX) + { + name_hash = (lit_string_hash_t) (name_hash + LIT_MAGIC_STRING__COUNT); + } + } + else + { + prop_name_type = ECMA_DIRECT_STRING_PTR; + + ECMA_SET_NON_NULL_POINTER (prop_name_cp, prop_name_p); + name_hash = prop_name_p->hash; + } + + size_t row_index = ecma_lcache_row_index (object_cp, name_hash); + ecma_lcache_hash_entry_t *entry_p = JERRY_HASH_TABLE_CONTEXT (table) [row_index]; ecma_lcache_hash_entry_t *entry_end_p = entry_p + ECMA_LCACHE_HASH_ROW_LENGTH; - ecma_property_t prop_name_type; - jmem_cpointer_t prop_name_cp = ecma_string_to_lcache_property_name (prop_name_p, &prop_name_type); - while (entry_p < entry_end_p) { if (entry_p->object_cp == object_cp diff --git a/jerry-core/ecma/base/ecma-property-hashmap.c b/jerry-core/ecma/base/ecma-property-hashmap.c index 716825968..aaff48387 100644 --- a/jerry-core/ecma/base/ecma-property-hashmap.c +++ b/jerry-core/ecma/base/ecma-property-hashmap.c @@ -134,7 +134,7 @@ ecma_property_hashmap_create (ecma_object_t *object_p) /**< object */ memset (hashmap_p, 0, total_size); hashmap_p->header.types[0] = ECMA_PROPERTY_TYPE_HASHMAP; - hashmap_p->header.types[1] = ECMA_PROPERTY_TYPE_DELETED; + hashmap_p->header.types[1] = 0; hashmap_p->header.next_property_cp = object_p->property_list_or_bound_object_cp; hashmap_p->max_property_count = max_property_count; hashmap_p->null_count = max_property_count - named_property_count; @@ -146,17 +146,10 @@ ecma_property_hashmap_create (ecma_object_t *object_p) /**< object */ uint8_t shift_counter = 0; - if (max_property_count <= LIT_STRING_HASH_LIMIT) + while (max_property_count > LIT_STRING_HASH_LIMIT) { - hashmap_p->header.types[1] = 0; - } - else - { - while (max_property_count > LIT_STRING_HASH_LIMIT) - { - shift_counter++; - max_property_count >>= 1; - } + shift_counter++; + max_property_count >>= 1; } hashmap_p->header.types[1] = shift_counter; @@ -492,6 +485,64 @@ ecma_property_hashmap_find (ecma_property_hashmap_t *hashmap_p, /**< hashmap */ uint32_t start_entry_index = entry_index; #endif /* !JERRY_NDEBUG */ + if (ECMA_IS_DIRECT_STRING (name_p)) + { + ecma_property_t prop_name_type = (ecma_property_t) ECMA_GET_DIRECT_STRING_TYPE (name_p); + jmem_cpointer_t property_name_cp = (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (name_p); + + JERRY_ASSERT (prop_name_type > 0); + + while (true) + { + if (pair_list_p[entry_index] != ECMA_NULL_POINTER) + { + size_t offset = 0; + if (ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)) + { + offset = 1; + } + + ecma_property_pair_t *property_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_property_pair_t, + pair_list_p[entry_index]); + + ecma_property_t *property_p = property_pair_p->header.types + offset; + + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*property_p)); + + if (property_pair_p->names_cp[offset] == property_name_cp + && ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == prop_name_type) + { +#ifndef JERRY_NDEBUG + JERRY_ASSERT (property_found); +#endif /* !JERRY_NDEBUG */ + + *property_real_name_cp = property_name_cp; + return property_p; + } + } + else + { + if (!ECMA_PROPERTY_HASHMAP_GET_BIT (bits_p, entry_index)) + { +#ifndef JERRY_NDEBUG + JERRY_ASSERT (!property_found); +#endif /* !JERRY_NDEBUG */ + + return NULL; + } + /* Otherwise it is a deleted entry. */ + } + + entry_index = (entry_index + step) & mask; + +#ifndef JERRY_NDEBUG + JERRY_ASSERT (entry_index != start_entry_index); +#endif /* !JERRY_NDEBUG */ + } + + JERRY_UNREACHABLE (); + } + while (true) { if (pair_list_p[entry_index] != ECMA_NULL_POINTER) @@ -509,15 +560,19 @@ ecma_property_hashmap_find (ecma_property_hashmap_t *hashmap_p, /**< hashmap */ JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*property_p)); - if (ecma_string_compare_to_property_name (*property_p, - property_pair_p->names_cp[offset], - name_p)) + if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_PTR) { + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, property_pair_p->names_cp[offset]); + + if (ecma_compare_ecma_non_direct_strings (prop_name_p, name_p)) + { #ifndef JERRY_NDEBUG - JERRY_ASSERT (property_found); + JERRY_ASSERT (property_found); #endif /* !JERRY_NDEBUG */ - *property_real_name_cp = property_pair_p->names_cp[offset]; - return property_p; + + *property_real_name_cp = property_pair_p->names_cp[offset]; + return property_p; + } } } else @@ -527,6 +582,7 @@ ecma_property_hashmap_find (ecma_property_hashmap_t *hashmap_p, /**< hashmap */ #ifndef JERRY_NDEBUG JERRY_ASSERT (!property_found); #endif /* !JERRY_NDEBUG */ + return NULL; } /* Otherwise it is a deleted entry. */