From 90f37a557384dc8bd21336724c59505fe2ae00a6 Mon Sep 17 00:00:00 2001 From: Robert Fancsik Date: Fri, 8 Mar 2019 18:46:12 +0100 Subject: [PATCH] Optimize LCache entrys keys (#2767) JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu --- jerry-core/ecma/base/ecma-globals.h | 15 ++++-- jerry-core/ecma/base/ecma-lcache.c | 72 ++++++++++++----------------- 2 files changed, 39 insertions(+), 48 deletions(-) diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 9def75cda..4e7c06976 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -1489,6 +1489,14 @@ typedef struct } ecma_lit_storage_item_t; #ifndef CONFIG_ECMA_LCACHE_DISABLE +/** + * Container of an LCache entry identifier + */ +#ifdef JERRY_CPOINTER_32_BIT +typedef uint64_t ecma_lcache_hash_entry_id_t; +#else /* !JERRY_CPOINTER_32_BIT */ +typedef uint32_t ecma_lcache_hash_entry_id_t; +#endif /* JERRY_CPOINTER_32_BIT */ /** * Entry of LCache hash table @@ -1498,11 +1506,8 @@ typedef struct /** Pointer to a property of the object */ ecma_property_t *prop_p; - /** Compressed pointer to object (ECMA_NULL_POINTER marks record empty) */ - jmem_cpointer_t object_cp; - - /** Compressed pointer to property's name */ - jmem_cpointer_t prop_name_cp; + /** Entry identifier in LCache */ + ecma_lcache_hash_entry_id_t id; } ecma_lcache_hash_entry_t; /** diff --git a/jerry-core/ecma/base/ecma-lcache.c b/jerry-core/ecma/base/ecma-lcache.c index b4465d1f8..d702bb2b5 100644 --- a/jerry-core/ecma/base/ecma-lcache.c +++ b/jerry-core/ecma/base/ecma-lcache.c @@ -33,6 +33,17 @@ */ #define ECMA_LCACHE_HASH_MASK (ECMA_LCACHE_HASH_ROWS_COUNT - 1) +/** + * Bitshift index for creating property identifier + */ +#define ECMA_LCACHE_HASH_ENTRY_ID_SHIFT (8 * sizeof (jmem_cpointer_t)) + +/** + * Create property identifier + */ +#define ECMA_LCACHE_CREATE_ID(object_cp, name_cp) \ + (((ecma_lcache_hash_entry_id_t) (object_cp) << ECMA_LCACHE_HASH_ENTRY_ID_SHIFT) | (name_cp)) + /** * Invalidate specified LCache entry */ @@ -40,10 +51,10 @@ static inline void JERRY_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); + JERRY_ASSERT (entry_p->id != 0); JERRY_ASSERT (entry_p->prop_p != NULL); - entry_p->object_cp = ECMA_NULL_POINTER; + entry_p->id = 0; ecma_set_property_lcached (entry_p->prop_p, false); } /* ecma_lcache_invalidate_entry */ @@ -54,11 +65,11 @@ ecma_lcache_invalidate_entry (ecma_lcache_hash_entry_t *entry_p) /**< entry to i */ static inline size_t JERRY_ATTR_ALWAYS_INLINE ecma_lcache_row_index (jmem_cpointer_t object_cp, /**< compressed pointer to object */ - lit_string_hash_t name_hash) /**< property name hash */ + jmem_cpointer_t name_cp) /**< compressed pointer to property name */ { - /* Randomize the hash of the property name with the object pointer using a xor operation, + /* Randomize 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) ((name_hash ^ object_cp) & ECMA_LCACHE_HASH_MASK); + return (size_t) ((name_cp ^ object_cp) & ECMA_LCACHE_HASH_MASK); } /* ecma_lcache_row_index */ /** @@ -79,14 +90,13 @@ ecma_lcache_insert (ecma_object_t *object_p, /**< object */ ECMA_SET_NON_NULL_POINTER (object_cp, object_p); - lit_string_hash_t name_hash = ecma_string_get_property_name_hash (*prop_p, name_cp); - size_t row_index = ecma_lcache_row_index (object_cp, name_hash); + size_t row_index = ecma_lcache_row_index (object_cp, name_cp); ecma_lcache_hash_entry_t *entries_p = JERRY_CONTEXT (lcache) [row_index]; uint32_t entry_index; for (entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++) { - if (entries_p[entry_index].object_cp == ECMA_NULL_POINTER) + if (entries_p[entry_index].id == 0) { break; } @@ -102,14 +112,12 @@ ecma_lcache_insert (ecma_object_t *object_p, /**< object */ { entries_p[i] = entries_p[i - 1]; } - entry_index = 0; } ecma_lcache_hash_entry_t *entry_p = entries_p + entry_index; - ECMA_SET_NON_NULL_POINTER (entry_p->object_cp, object_p); - entry_p->prop_name_cp = name_cp; entry_p->prop_p = prop_p; + entry_p->id = ECMA_LCACHE_CREATE_ID (object_cp, name_cp); ecma_set_property_lcached (entry_p->prop_p, true); } /* ecma_lcache_insert */ @@ -132,53 +140,32 @@ ecma_lcache_lookup (ecma_object_t *object_p, /**< object */ 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); - } + prop_name_cp = (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (prop_name_p); } 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); + size_t row_index = ecma_lcache_row_index (object_cp, prop_name_cp); ecma_lcache_hash_entry_t *entry_p = JERRY_CONTEXT (lcache) [row_index]; ecma_lcache_hash_entry_t *entry_end_p = entry_p + ECMA_LCACHE_HASH_ROW_LENGTH; + ecma_lcache_hash_entry_id_t id = ECMA_LCACHE_CREATE_ID (object_cp, prop_name_cp); + while (entry_p < entry_end_p) { - if (entry_p->object_cp == object_cp - && entry_p->prop_name_cp == prop_name_cp) + if (entry_p->id == id && ECMA_PROPERTY_GET_NAME_TYPE (*entry_p->prop_p) == prop_name_type) { - ecma_property_t *prop_p = entry_p->prop_p; - - JERRY_ASSERT (prop_p != NULL && ecma_is_property_lcached (prop_p)); - - if (ECMA_PROPERTY_GET_NAME_TYPE (*prop_p) == prop_name_type) - { - return prop_p; - } + JERRY_ASSERT (entry_p->prop_p != NULL && ecma_is_property_lcached (entry_p->prop_p)); + return entry_p->prop_p; } - else - { - /* They can be equal, but generic string comparison is too costly. */ - } - entry_p++; } @@ -202,8 +189,7 @@ ecma_lcache_invalidate (ecma_object_t *object_p, /**< object */ jmem_cpointer_t object_cp; ECMA_SET_NON_NULL_POINTER (object_cp, object_p); - lit_string_hash_t name_hash = ecma_string_get_property_name_hash (*prop_p, name_cp); - size_t row_index = ecma_lcache_row_index (object_cp, name_hash); + size_t row_index = ecma_lcache_row_index (object_cp, name_cp); ecma_lcache_hash_entry_t *entry_p = JERRY_CONTEXT (lcache) [row_index]; while (true) @@ -211,9 +197,9 @@ ecma_lcache_invalidate (ecma_object_t *object_p, /**< object */ /* The property must be present. */ JERRY_ASSERT (entry_p - JERRY_CONTEXT (lcache) [row_index] < ECMA_LCACHE_HASH_ROW_LENGTH); - if (entry_p->object_cp != ECMA_NULL_POINTER && entry_p->prop_p == prop_p) + if (entry_p->id != 0 && entry_p->prop_p == prop_p) { - JERRY_ASSERT (entry_p->object_cp == object_cp); + JERRY_ASSERT (entry_p->id == ECMA_LCACHE_CREATE_ID (object_cp, name_cp)); ecma_lcache_invalidate_entry (entry_p); return;