diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index 95290fe26a..7adb41f401 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -384,14 +384,7 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */ { if (prop_iter_p->types[i] != ECMA_PROPERTY_TYPE_DELETED) { - ecma_string_t *name_p = ECMA_GET_POINTER (ecma_string_t, prop_pair_p->names_cp[i]); - - ecma_free_property (object_p, name_p, prop_iter_p->types + i); - - if (name_p != NULL) - { - ecma_deref_ecma_string (name_p); - } + ecma_free_property (object_p, prop_pair_p->names_cp[i], prop_iter_p->types + i); } } diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 0a1f3b2aed..a34649ba51 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -329,6 +329,16 @@ typedef enum */ #define ECMA_PROPERTY_FIXED 0 +/** + * Shift for property name part. + */ +#define ECMA_PROPERTY_NAME_TYPE_SHIFT (ECMA_PROPERTY_FLAG_SHIFT + 4) + +/** + * Property name is a generic string. + */ +#define ECMA_PROPERTY_NAME_TYPE_STRING 3 + /** * Abstract property representation. * @@ -411,6 +421,12 @@ typedef struct #define ECMA_PROPERTY_GET_TYPE(property) \ ((ecma_property_types_t) ((property) & ECMA_PROPERTY_TYPE_MASK)) +/** + * Get property name type. + */ +#define ECMA_PROPERTY_GET_NAME_TYPE(property) \ + ((property) >> ECMA_PROPERTY_NAME_TYPE_SHIFT) + /** * Returns true if the property pointer is a property pair. */ @@ -418,6 +434,12 @@ typedef struct (ECMA_PROPERTY_GET_TYPE ((property_header_p)->types[0]) != ECMA_PROPERTY_TYPE_VIRTUAL \ && (property_header_p)->types[0] != ECMA_PROPERTY_TYPE_HASHMAP) +/** + * Returns true if the property is named property. + */ +#define ECMA_PROPERTY_IS_NAMED_PROPERTY(property) \ + (ECMA_PROPERTY_GET_TYPE (property) != ECMA_PROPERTY_TYPE_SPECIAL) + /** * Returns the internal property type */ @@ -909,14 +931,14 @@ typedef struct */ typedef enum { - ECMA_STRING_CONTAINER_HEAP_UTF8_STRING, /**< actual data is on the heap as an utf-8 (cesu8) string - * maximum size is 2^16. */ - ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING, /**< actual data is on the heap as an utf-8 (cesu8) string - * maximum size is 2^32. */ ECMA_STRING_CONTAINER_UINT32_IN_DESC, /**< actual data is UInt32-represeneted Number stored locally in the string's descriptor */ ECMA_STRING_CONTAINER_MAGIC_STRING, /**< the ecma-string is equal to one of ECMA magic strings */ ECMA_STRING_CONTAINER_MAGIC_STRING_EX, /**< the ecma-string is equal to one of external magic strings */ + ECMA_STRING_CONTAINER_HEAP_UTF8_STRING, /**< actual data is on the heap as an utf-8 (cesu8) string + * maximum size is 2^16. */ + ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING, /**< actual data is on the heap as an utf-8 (cesu8) string + * maximum size is 2^32. */ ECMA_STRING_LITERAL_NUMBER, /**< a literal number which is used solely by the literal storage * so no string processing function supports this type except @@ -985,10 +1007,10 @@ typedef struct lit_utf8_size_t long_utf8_string_size; /**< size of this long utf-8 string in bytes */ uint32_t uint32_number; /**< uint32-represented number placed locally in the descriptor */ - lit_magic_string_id_t magic_string_id; /**< identifier of a magic string */ - lit_magic_string_ex_id_t magic_string_ex_id; /**< identifier of an external magic string */ + uint32_t magic_string_id; /**< identifier of a magic string (lit_magic_string_id_t) */ + uint32_t magic_string_ex_id; /**< identifier of an external magic string (lit_magic_string_ex_id_t) */ ecma_value_t lit_number; /**< literal number (note: not a regular string type) */ - uint32_t common_field; /**< for zeroing and comparison in some cases */ + uint32_t common_uint32_field; /**< for zeroing and comparison in some cases */ } u; } ecma_string_t; diff --git a/jerry-core/ecma/base/ecma-helpers-string.c b/jerry-core/ecma/base/ecma-helpers-string.c index 8b340ab75c..a89354f5ee 100644 --- a/jerry-core/ecma/base/ecma-helpers-string.c +++ b/jerry-core/ecma/base/ecma-helpers-string.c @@ -60,10 +60,8 @@ ecma_init_ecma_string_from_magic_string_id (ecma_string_t *string_p, /**< descri the magic string */ { string_p->refs_and_container = ECMA_STRING_CONTAINER_MAGIC_STRING | ECMA_STRING_REF_ONE; - string_p->hash = lit_utf8_string_calc_hash (lit_get_magic_string_utf8 (magic_string_id), - lit_get_magic_string_size (magic_string_id)); + string_p->hash = (lit_string_hash_t) magic_string_id; - string_p->u.common_field = 0; string_p->u.magic_string_id = magic_string_id; } /* ecma_init_ecma_string_from_magic_string_id */ @@ -76,10 +74,8 @@ ecma_init_ecma_string_from_magic_string_ex_id (ecma_string_t *string_p, /**< des the external magic string */ { string_p->refs_and_container = ECMA_STRING_CONTAINER_MAGIC_STRING_EX | ECMA_STRING_REF_ONE; - string_p->hash = lit_utf8_string_calc_hash (lit_get_magic_string_ex_utf8 (magic_string_ex_id), - lit_get_magic_string_ex_size (magic_string_ex_id)); + string_p->hash = (lit_string_hash_t) (LIT_MAGIC_STRING__COUNT + magic_string_ex_id); - string_p->u.common_field = 0; string_p->u.magic_string_ex_id = magic_string_ex_id; } /* ecma_init_ecma_string_from_magic_string_ex_id */ @@ -158,8 +154,9 @@ ecma_new_ecma_string_from_utf8 (const lit_utf8_byte_t *string_p, /**< utf-8 stri JERRY_ASSERT (string_p != NULL || string_size == 0); JERRY_ASSERT (lit_is_cesu8_string_valid (string_p, string_size)); - lit_magic_string_id_t magic_string_id; - if (lit_is_utf8_string_magic (string_p, string_size, &magic_string_id)) + lit_magic_string_id_t magic_string_id = lit_is_utf8_string_magic (string_p, string_size); + + if (magic_string_id != LIT_MAGIC_STRING__COUNT) { return ecma_get_magic_string (magic_string_id); } @@ -176,10 +173,14 @@ ecma_new_ecma_string_from_utf8 (const lit_utf8_byte_t *string_p, /**< utf-8 stri } } - lit_magic_string_ex_id_t magic_string_ex_id; - if (lit_is_ex_utf8_string_magic (string_p, string_size, &magic_string_ex_id)) + if (lit_get_magic_string_ex_count () > 0) { - return ecma_get_magic_string_ex (magic_string_ex_id); + lit_magic_string_ex_id_t magic_string_ex_id = lit_is_ex_utf8_string_magic (string_p, string_size); + + if (magic_string_ex_id < lit_get_magic_string_ex_count ()) + { + return ecma_get_magic_string_ex (magic_string_ex_id); + } } ecma_string_t *string_desc_p; @@ -190,7 +191,7 @@ ecma_new_ecma_string_from_utf8 (const lit_utf8_byte_t *string_p, /**< utf-8 stri string_desc_p = jmem_heap_alloc_block (sizeof (ecma_string_t) + string_size); string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_UTF8_STRING | ECMA_STRING_REF_ONE; - string_desc_p->u.common_field = 0; + string_desc_p->u.common_uint32_field = 0; string_desc_p->u.utf8_string.size = (uint16_t) string_size; string_desc_p->u.utf8_string.length = (uint16_t) lit_utf8_string_length (string_p, string_size); @@ -201,7 +202,7 @@ ecma_new_ecma_string_from_utf8 (const lit_utf8_byte_t *string_p, /**< utf-8 stri string_desc_p = jmem_heap_alloc_block (sizeof (ecma_long_string_t) + string_size); string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING | ECMA_STRING_REF_ONE; - string_desc_p->u.common_field = 0; + string_desc_p->u.common_uint32_field = 0; string_desc_p->u.long_utf8_string_size = string_size; ecma_long_string_t *long_string_desc_p = (ecma_long_string_t *) string_desc_p; @@ -278,7 +279,7 @@ ecma_new_ecma_string_from_utf8_converted_to_cesu8 (const lit_utf8_byte_t *string string_desc_p = jmem_heap_alloc_block (sizeof (ecma_string_t) + converted_string_size); string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_UTF8_STRING | ECMA_STRING_REF_ONE; - string_desc_p->u.common_field = 0; + string_desc_p->u.common_uint32_field = 0; string_desc_p->u.utf8_string.size = (uint16_t) converted_string_size; string_desc_p->u.utf8_string.length = (uint16_t) converted_string_length; @@ -289,7 +290,7 @@ ecma_new_ecma_string_from_utf8_converted_to_cesu8 (const lit_utf8_byte_t *string string_desc_p = jmem_heap_alloc_block (sizeof (ecma_long_string_t) + converted_string_size); string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING | ECMA_STRING_REF_ONE; - string_desc_p->u.common_field = 0; + string_desc_p->u.common_uint32_field = 0; string_desc_p->u.long_utf8_string_size = converted_string_size; ecma_long_string_t *long_string_desc_p = (ecma_long_string_t *) string_desc_p; @@ -354,7 +355,6 @@ ecma_init_ecma_string_from_uint32 (ecma_string_t *string_desc_p, /**< ecma-strin string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_UINT32_IN_DESC | ECMA_STRING_REF_ONE; string_desc_p->hash = (lit_string_hash_t) uint32_number; - string_desc_p->u.common_field = 0; string_desc_p->u.uint32_number = uint32_number; } /* ecma_init_ecma_string_from_uint32 */ @@ -364,12 +364,9 @@ ecma_init_ecma_string_from_uint32 (ecma_string_t *string_desc_p, /**< ecma-strin inline void __attr_always_inline___ ecma_init_ecma_length_string (ecma_string_t *string_desc_p) /**< ecma-string */ { - JERRY_ASSERT (lit_utf8_string_calc_hash ((const lit_utf8_byte_t *) "length", 6) == LIT_STRING_LENGTH_HASH); - string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_MAGIC_STRING | ECMA_STRING_REF_ONE; - string_desc_p->hash = LIT_STRING_LENGTH_HASH; + string_desc_p->hash = LIT_MAGIC_STRING_LENGTH; - string_desc_p->u.common_field = 0; string_desc_p->u.magic_string_id = LIT_MAGIC_STRING_LENGTH; } /* ecma_init_ecma_length_string */ @@ -418,18 +415,15 @@ ecma_new_ecma_string_from_number (ecma_number_t num) /**< ecma-number */ JERRY_ASSERT (str_size > 0); #ifndef JERRY_NDEBUG - lit_magic_string_id_t magic_string_id; - lit_magic_string_ex_id_t magic_string_ex_id; - - JERRY_ASSERT (!lit_is_utf8_string_magic (str_buf, str_size, &magic_string_id) - && !lit_is_ex_utf8_string_magic (str_buf, str_size, &magic_string_ex_id)); + JERRY_ASSERT (lit_is_utf8_string_magic (str_buf, str_size) == LIT_MAGIC_STRING__COUNT + && lit_is_ex_utf8_string_magic (str_buf, str_size) == lit_get_magic_string_ex_count ()); #endif /* !JERRY_NDEBUG */ ecma_string_t *string_desc_p = jmem_heap_alloc_block (sizeof (ecma_string_t) + str_size); string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_UTF8_STRING | ECMA_STRING_REF_ONE; string_desc_p->hash = lit_utf8_string_calc_hash (str_buf, str_size); - string_desc_p->u.common_field = 0; + string_desc_p->u.common_uint32_field = 0; string_desc_p->u.utf8_string.size = (uint16_t) str_size; string_desc_p->u.utf8_string.length = (uint16_t) str_size; @@ -515,6 +509,7 @@ ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */ lit_utf8_byte_t uint32_to_string_buffer2[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; bool string1_is_uint32 = false; + bool string1_rehash_needed = false; switch (ECMA_STRING_GET_CONTAINER (string1_p)) { @@ -542,6 +537,7 @@ ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */ utf8_string1_p = uint32_to_string_buffer1; utf8_string1_length = utf8_string1_size; string1_is_uint32 = true; + string1_rehash_needed = true; break; } case ECMA_STRING_CONTAINER_MAGIC_STRING: @@ -549,6 +545,7 @@ ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */ utf8_string1_p = lit_get_magic_string_utf8 (string1_p->u.magic_string_id); utf8_string1_size = lit_get_magic_string_size (string1_p->u.magic_string_id); utf8_string1_length = utf8_string1_size; + string1_rehash_needed = true; break; } default: @@ -558,6 +555,7 @@ ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */ utf8_string1_p = lit_get_magic_string_ex_utf8 (string1_p->u.magic_string_id); utf8_string1_size = lit_get_magic_string_ex_size (string1_p->u.magic_string_id); utf8_string1_length = utf8_string1_size; + string1_rehash_needed = true; break; } } @@ -620,6 +618,17 @@ ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */ jerry_fatal (ERR_OUT_OF_MEMORY); } + lit_magic_string_id_t magic_string_id; + magic_string_id = lit_is_utf8_string_pair_magic (utf8_string1_p, + utf8_string1_size, + utf8_string2_p, + utf8_string2_size); + + if (magic_string_id != LIT_MAGIC_STRING__COUNT) + { + return ecma_get_magic_string (magic_string_id); + } + if (string1_is_uint32 && new_size <= ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32) { memcpy (uint32_to_string_buffer1 + utf8_string1_size, @@ -634,6 +643,20 @@ ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */ } } + if (lit_get_magic_string_ex_count () > 0) + { + lit_magic_string_ex_id_t magic_string_ex_id; + magic_string_ex_id = lit_is_ex_utf8_string_pair_magic (utf8_string1_p, + utf8_string1_size, + utf8_string2_p, + utf8_string2_size); + + if (magic_string_ex_id < lit_get_magic_string_ex_count ()) + { + return ecma_get_magic_string_ex (magic_string_ex_id); + } + } + ecma_string_t *string_desc_p; lit_utf8_byte_t *data_p; @@ -642,7 +665,7 @@ ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */ string_desc_p = jmem_heap_alloc_block (sizeof (ecma_string_t) + new_size); string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_UTF8_STRING | ECMA_STRING_REF_ONE; - string_desc_p->u.common_field = 0; + string_desc_p->u.common_uint32_field = 0; string_desc_p->u.utf8_string.size = (uint16_t) new_size; string_desc_p->u.utf8_string.length = (uint16_t) (utf8_string1_length + utf8_string2_length); @@ -653,7 +676,7 @@ ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */ string_desc_p = jmem_heap_alloc_block (sizeof (ecma_long_string_t) + new_size); string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING | ECMA_STRING_REF_ONE; - string_desc_p->u.common_field = 0; + string_desc_p->u.common_uint32_field = 0; string_desc_p->u.long_utf8_string_size = new_size; ecma_long_string_t *long_string_desc_p = (ecma_long_string_t *) string_desc_p; @@ -664,9 +687,9 @@ ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */ lit_string_hash_t hash_start = string1_p->hash; - if (string1_is_uint32) + if (string1_rehash_needed) { - hash_start = lit_utf8_string_calc_hash (uint32_to_string_buffer1, utf8_string1_size); + hash_start = lit_utf8_string_calc_hash (utf8_string1_p, utf8_string1_size); } string_desc_p->hash = lit_utf8_string_hash_combine (hash_start, utf8_string2_p, utf8_string2_size); @@ -1049,119 +1072,226 @@ ecma_string_is_empty (const ecma_string_t *str_p) /**< ecma-string */ inline bool __attr_always_inline___ ecma_string_is_length (const ecma_string_t *string_p) /**< property name */ { - static const char length_str_p[] = "length"; - - ecma_string_container_t container = ECMA_STRING_GET_CONTAINER (string_p); - - if (container == ECMA_STRING_CONTAINER_MAGIC_STRING) - { - return string_p->u.magic_string_id == LIT_MAGIC_STRING_LENGTH; - } - - if (container != ECMA_STRING_CONTAINER_HEAP_UTF8_STRING - || string_p->u.utf8_string.size != (sizeof (length_str_p) - 1) - || string_p->hash != LIT_STRING_LENGTH_HASH) - { - return false; - } - - return !strncmp ((char *) (string_p + 1), length_str_p, (sizeof (length_str_p) - 1)); + return (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING + && string_p->u.magic_string_id == LIT_MAGIC_STRING_LENGTH); } /* ecma_string_is_length */ /** - * Long path part of ecma-string to ecma-string comparison routine + * Converts a string into a property name * - * See also: - * ecma_compare_ecma_strings - * - * @return true - if strings are equal; - * false - otherwise. + * @return the compressed pointer part of the name */ -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 */ +inline jmem_cpointer_t __attr_always_inline___ +ecma_string_to_property_name (ecma_string_t *prop_name_p, /**< property name */ + ecma_property_t *name_type_p) /**< [out] property name type */ { - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string1_p) != ECMA_STRING_GET_CONTAINER (string2_p) - || ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_HEAP_UTF8_STRING - || ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING); - - const lit_utf8_byte_t *utf8_string1_p, *utf8_string2_p; - lit_utf8_size_t utf8_string1_size, utf8_string2_size; + ecma_string_container_t container = ECMA_STRING_GET_CONTAINER (prop_name_p); - switch (ECMA_STRING_GET_CONTAINER (string1_p)) + switch (container) { - case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + case ECMA_STRING_CONTAINER_UINT32_IN_DESC: + case ECMA_STRING_CONTAINER_MAGIC_STRING: + case ECMA_STRING_CONTAINER_MAGIC_STRING_EX: { - utf8_string1_p = (lit_utf8_byte_t *) (string1_p + 1); - utf8_string1_size = string1_p->u.utf8_string.size; +#ifdef JERRY_CPOINTER_32_BIT + + *name_type_p = (ecma_property_t) (container << ECMA_PROPERTY_NAME_TYPE_SHIFT); + return (jmem_cpointer_t) prop_name_p->u.common_uint32_field; + +#else /* !JERRY_CPOINTER_32_BIT */ + + if (prop_name_p->u.common_uint32_field < (UINT16_MAX + 1)) + { + *name_type_p = (ecma_property_t) (container << ECMA_PROPERTY_NAME_TYPE_SHIFT); + return (jmem_cpointer_t) prop_name_p->u.common_uint32_field; + } + +#endif /* JERRY_CPOINTER_32_BIT */ + break; } - case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: + default: { - utf8_string1_p = (lit_utf8_byte_t *) (((ecma_long_string_t *) string1_p) + 1); - utf8_string1_size = string1_p->u.long_utf8_string_size; break; } + } + + *name_type_p = ECMA_PROPERTY_NAME_TYPE_STRING << ECMA_PROPERTY_NAME_TYPE_SHIFT; + + ecma_ref_ecma_string (prop_name_p); + + jmem_cpointer_t prop_name_cp; + ECMA_SET_NON_NULL_POINTER (prop_name_cp, prop_name_p); + return prop_name_cp; +} /* ecma_string_to_property_name */ + +/** + * Converts a property name into a string + * + * @return the string pointer + */ +ecma_string_t * +ecma_string_from_property_name (ecma_property_t property, /**< property name type */ + jmem_cpointer_t prop_name_cp) /**< property name compressed pointer */ +{ + /* If string_buf_p is NULL this function returns with a new string + * instance which needs to be released with ecma_deref_ecma_string. */ + + switch (ECMA_PROPERTY_GET_NAME_TYPE (property)) + { case ECMA_STRING_CONTAINER_UINT32_IN_DESC: { - return false; + return ecma_new_ecma_string_from_uint32 ((uint32_t) prop_name_cp); } case ECMA_STRING_CONTAINER_MAGIC_STRING: { - utf8_string1_p = lit_get_magic_string_utf8 (string1_p->u.magic_string_id); - utf8_string1_size = lit_get_magic_string_size (string1_p->u.magic_string_id); - break; + return ecma_new_ecma_string_from_magic_string_id ((lit_magic_string_id_t) prop_name_cp); + } + case ECMA_STRING_CONTAINER_MAGIC_STRING_EX: + { + return ecma_new_ecma_string_from_magic_string_ex_id ((lit_magic_string_ex_id_t) prop_name_cp); } default: { - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + JERRY_ASSERT (ECMA_PROPERTY_GET_NAME_TYPE (property) == ECMA_PROPERTY_NAME_TYPE_STRING); - utf8_string1_p = lit_get_magic_string_ex_utf8 (string1_p->u.magic_string_id); - utf8_string1_size = lit_get_magic_string_ex_size (string1_p->u.magic_string_id); - break; + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); + ecma_ref_ecma_string (prop_name_p); + return prop_name_p; } } +} /* ecma_string_from_property_name */ - switch (ECMA_STRING_GET_CONTAINER (string2_p)) +/** + * Get hash code of property name + * + * @return hash code of property name + */ +inline lit_string_hash_t __attr_always_inline___ +ecma_string_get_property_name_hash (ecma_property_t property, /**< property name type */ + jmem_cpointer_t prop_name_cp) /**< property name compressed pointer */ +{ + switch (ECMA_PROPERTY_GET_NAME_TYPE (property)) { - case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + case ECMA_STRING_CONTAINER_MAGIC_STRING_EX: { - utf8_string2_p = (lit_utf8_byte_t *) (string2_p + 1); - utf8_string2_size = string2_p->u.utf8_string.size; - break; + return (lit_string_hash_t) (LIT_MAGIC_STRING__COUNT + prop_name_cp); } - case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: + case ECMA_PROPERTY_NAME_TYPE_STRING: { - utf8_string2_p = (lit_utf8_byte_t *) (((ecma_long_string_t *) string2_p) + 1); - utf8_string2_size = string2_p->u.long_utf8_string_size; - break; + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); + return ecma_string_hash (prop_name_p); + } + default: + { + return (lit_string_hash_t) prop_name_cp; } + } +} /* ecma_string_get_property_name_hash */ + +/** + * Check if property name is array index. + * + * @return ECMA_STRING_NOT_ARRAY_INDEX if string is not array index + * the array index otherwise + */ +uint32_t +ecma_string_get_property_index (ecma_property_t property, /**< property name type */ + jmem_cpointer_t prop_name_cp) /**< property name compressed pointer */ +{ + switch (ECMA_PROPERTY_GET_NAME_TYPE (property)) + { case ECMA_STRING_CONTAINER_UINT32_IN_DESC: { - return false; + return (uint32_t) prop_name_cp; + } +#ifndef JERRY_CPOINTER_32_BIT + case ECMA_PROPERTY_NAME_TYPE_STRING: + { + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); + return ecma_string_get_array_index (prop_name_p); + } +#endif /* !JERRY_CPOINTER_32_BIT */ + default: + { + return ECMA_STRING_NOT_ARRAY_INDEX; } + } +} /* ecma_string_get_property_index */ + +/** + * Compare a property name to a string + * + * @return true if they are equals + * false otherwise + */ +inline bool __attr_always_inline___ +ecma_string_compare_to_property_name (ecma_property_t property, /**< property name type */ + jmem_cpointer_t prop_name_cp, /**< property name compressed pointer */ + const ecma_string_t *string_p) /**< other string */ +{ + uint32_t property_name_type = ECMA_PROPERTY_GET_NAME_TYPE (property); + + switch (property_name_type) + { + case ECMA_STRING_CONTAINER_UINT32_IN_DESC: case ECMA_STRING_CONTAINER_MAGIC_STRING: + case ECMA_STRING_CONTAINER_MAGIC_STRING_EX: { - utf8_string2_p = lit_get_magic_string_utf8 (string2_p->u.magic_string_id); - utf8_string2_size = lit_get_magic_string_size (string2_p->u.magic_string_id); - break; + return (ECMA_STRING_GET_CONTAINER (string_p) == property_name_type + && string_p->u.common_uint32_field == (uint32_t) prop_name_cp); } default: { - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string2_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + JERRY_ASSERT (property_name_type == ECMA_PROPERTY_NAME_TYPE_STRING); - utf8_string2_p = lit_get_magic_string_ex_utf8 (string2_p->u.magic_string_id); - utf8_string2_size = lit_get_magic_string_ex_size (string2_p->u.magic_string_id); - break; + 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); } } +} /* ecma_string_compare_to_property_name */ + +/** + * Long path part of ecma-string to ecma-string comparison routine + * + * See also: + * ecma_compare_ecma_strings + * + * @return true - if strings are equal; + * 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 */ +{ + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_GET_CONTAINER (string2_p)); + + const lit_utf8_byte_t *utf8_string1_p, *utf8_string2_p; + lit_utf8_size_t utf8_string1_size, utf8_string2_size; + + if (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_HEAP_UTF8_STRING) + { + utf8_string1_p = (lit_utf8_byte_t *) (string1_p + 1); + utf8_string1_size = string1_p->u.utf8_string.size; + utf8_string2_p = (lit_utf8_byte_t *) (string2_p + 1); + utf8_string2_size = string2_p->u.utf8_string.size; + } + else + { + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING); + + utf8_string1_p = (lit_utf8_byte_t *) (((ecma_long_string_t *) string1_p) + 1); + utf8_string1_size = string1_p->u.long_utf8_string_size; + utf8_string2_p = (lit_utf8_byte_t *) (((ecma_long_string_t *) string2_p) + 1); + utf8_string2_size = string2_p->u.long_utf8_string_size; + } if (utf8_string1_size != utf8_string2_size) { return false; } - return !strncmp ((char *) utf8_string1_p, (char *) utf8_string2_p, utf8_string1_size); + return !memcmp ((char *) utf8_string1_p, (char *) utf8_string2_p, utf8_string1_size); } /* ecma_compare_ecma_strings_longpath */ /** @@ -1189,10 +1319,14 @@ ecma_compare_ecma_strings (const ecma_string_t *string1_p, /* ecma-string */ ecma_string_container_t string1_container = ECMA_STRING_GET_CONTAINER (string1_p); - if (string1_container > ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING - && string1_container == ECMA_STRING_GET_CONTAINER (string2_p)) + if (string1_container != ECMA_STRING_GET_CONTAINER (string2_p)) + { + return false; + } + + if (string1_container < ECMA_STRING_CONTAINER_HEAP_UTF8_STRING) { - return string1_p->u.common_field == string2_p->u.common_field; + return string1_p->u.common_uint32_field == string2_p->u.common_uint32_field; } return ecma_compare_ecma_strings_longpath (string1_p, string2_p); @@ -1443,67 +1577,23 @@ ecma_get_magic_string_ex (lit_magic_string_ex_id_t id) /**< external magic strin return ecma_new_ecma_string_from_magic_string_ex_id (id); } /* ecma_get_magic_string_ex */ -#ifndef JERRY_NDEBUG -/** - * Long path part of ecma_is_string_magic - * - * Converts passed ecma-string to zt-string and - * checks if it is equal to one of magic string - * - * @return true - if magic string equal to passed string was found, - * false - otherwise. - */ -static bool -ecma_is_string_magic_longpath (const ecma_string_t *string_p, /**< ecma-string */ - lit_magic_string_id_t *out_id_p) /**< [out] magic string's id */ -{ - lit_utf8_size_t utf8_str_size; - bool is_ascii; - const lit_utf8_byte_t *utf8_str_p = ecma_string_raw_chars (string_p, &utf8_str_size, &is_ascii); - - if (utf8_str_p == NULL || !is_ascii) - { - return false; - } - - return lit_is_utf8_string_magic (utf8_str_p, utf8_str_size, out_id_p); -} /* ecma_is_string_magic_longpath */ -#endif /* !JERRY_NDEBUG */ - /** * Check if passed string equals to one of magic strings * and if equal magic string was found, return it's id in 'out_id_p' argument. * - * @return true - if magic string equal to passed string was found, - * false - otherwise. + * @return id - if magic string equal to passed string was found, + * LIT_MAGIC_STRING__COUNT - otherwise. */ -bool -ecma_is_string_magic (const ecma_string_t *string_p, /**< ecma-string */ - lit_magic_string_id_t *out_id_p) /**< [out] magic string's id */ +lit_magic_string_id_t +ecma_get_string_magic (const ecma_string_t *string_p) /**< ecma-string */ { if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING) { - JERRY_ASSERT (string_p->u.magic_string_id < LIT_MAGIC_STRING__COUNT); - - *out_id_p = (lit_magic_string_id_t) string_p->u.magic_string_id; - - return true; + return (lit_magic_string_id_t) string_p->u.magic_string_id; } - else - { - /* - * Any ecma-string constructor except ecma_concat_ecma_strings - * should return ecma-string with ECMA_STRING_CONTAINER_MAGIC_STRING - * container type if new ecma-string's content is equal to one of magic strings. - */ -#ifndef JERRY_NDEBUG - JERRY_ASSERT (ecma_string_get_length (string_p) > LIT_MAGIC_STRING_LENGTH_LIMIT - || !ecma_is_string_magic_longpath (string_p, out_id_p)); -#endif /* !JERRY_NDEBUG */ - return false; - } -} /* ecma_is_string_magic */ + return LIT_MAGIC_STRING__COUNT; +} /* ecma_get_string_magic */ /** * Try to calculate hash of the ecma-string diff --git a/jerry-core/ecma/base/ecma-helpers.c b/jerry-core/ecma/base/ecma-helpers.c index 04ca1282cf..cba5bbecab 100644 --- a/jerry-core/ecma/base/ecma-helpers.c +++ b/jerry-core/ecma/base/ecma-helpers.c @@ -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: + default: { - JERRY_ASSERT (name_p == NULL); + 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); - break; - } - default: - { - JERRY_UNREACHABLE (); - break; + *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); } } } diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index fa2829c943..81bee4ce8d 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -186,7 +186,12 @@ extern void ecma_init_ecma_length_string (ecma_string_t *); extern bool ecma_string_is_empty (const ecma_string_t *); extern bool ecma_string_is_length (const ecma_string_t *); -extern bool ecma_compare_ecma_strings_equal_hashes (const ecma_string_t *, const ecma_string_t *); +extern jmem_cpointer_t ecma_string_to_property_name (ecma_string_t *, ecma_property_t *); +extern ecma_string_t *ecma_string_from_property_name (ecma_property_t, jmem_cpointer_t); +extern lit_string_hash_t ecma_string_get_property_name_hash (ecma_property_t, jmem_cpointer_t); +extern uint32_t ecma_string_get_property_index (ecma_property_t, jmem_cpointer_t); +extern bool ecma_string_compare_to_property_name (ecma_property_t, jmem_cpointer_t, const ecma_string_t *); + extern bool ecma_compare_ecma_strings (const ecma_string_t *, const ecma_string_t *); extern bool ecma_compare_ecma_strings_relational (const ecma_string_t *, const ecma_string_t *); extern ecma_length_t ecma_string_get_length (const ecma_string_t *); @@ -195,7 +200,7 @@ extern ecma_char_t ecma_string_get_char_at_pos (const ecma_string_t *, ecma_leng extern ecma_string_t *ecma_get_magic_string (lit_magic_string_id_t); extern ecma_string_t *ecma_get_magic_string_ex (lit_magic_string_ex_id_t); -extern bool ecma_is_string_magic (const ecma_string_t *, lit_magic_string_id_t *); +extern lit_magic_string_id_t ecma_get_string_magic (const ecma_string_t *); extern lit_string_hash_t ecma_string_hash (const ecma_string_t *); extern ecma_string_t *ecma_string_substr (const ecma_string_t *, ecma_length_t, ecma_length_t); @@ -281,7 +286,7 @@ ecma_find_named_property (ecma_object_t *, ecma_string_t *); extern ecma_property_value_t * ecma_get_named_data_property (ecma_object_t *, ecma_string_t *); -extern void ecma_free_property (ecma_object_t *, ecma_string_t *, ecma_property_t *); +extern void ecma_free_property (ecma_object_t *, jmem_cpointer_t, ecma_property_t *); extern void ecma_delete_property (ecma_object_t *, ecma_property_value_t *); extern uint32_t ecma_delete_array_properties (ecma_object_t *, uint32_t, uint32_t); diff --git a/jerry-core/ecma/base/ecma-lcache.c b/jerry-core/ecma/base/ecma-lcache.c index 0387f15168..29431c7970 100644 --- a/jerry-core/ecma/base/ecma-lcache.c +++ b/jerry-core/ecma/base/ecma-lcache.c @@ -56,7 +56,6 @@ ecma_lcache_invalidate_entry (ecma_lcache_hash_entry_t *entry_p) /**< entry to i { JERRY_ASSERT (entry_p != NULL); JERRY_ASSERT (entry_p->object_cp != ECMA_NULL_POINTER); - JERRY_ASSERT (entry_p->prop_name_cp != ECMA_NULL_POINTER); JERRY_ASSERT (entry_p->prop_p != NULL); entry_p->object_cp = ECMA_NULL_POINTER; @@ -70,11 +69,11 @@ ecma_lcache_invalidate_entry (ecma_lcache_hash_entry_t *entry_p) /**< entry to i */ static inline size_t __attr_always_inline___ ecma_lcache_row_index (jmem_cpointer_t object_cp, /**< compressed pointer to object */ - const ecma_string_t *prop_name_p) /**< proeprty name */ + lit_string_hash_t name_hash) /**< property name hash */ { /* 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_MASK); + return (size_t) ((name_hash ^ object_cp) & ECMA_LCACHE_HASH_MASK); } /* ecma_lcache_row_index */ #endif /* !CONFIG_ECMA_LCACHE_DISABLE */ @@ -83,11 +82,10 @@ ecma_lcache_row_index (jmem_cpointer_t object_cp, /**< compressed pointer to obj */ void ecma_lcache_insert (ecma_object_t *object_p, /**< object */ - ecma_string_t *prop_name_p, /**< property name */ + jmem_cpointer_t name_cp, /**< 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); @@ -97,7 +95,8 @@ ecma_lcache_insert (ecma_object_t *object_p, /**< object */ ECMA_SET_NON_NULL_POINTER (object_cp, object_p); - size_t row_index = ecma_lcache_row_index (object_cp, prop_name_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); ecma_lcache_hash_entry_t *entries_p = JERRY_HASH_TABLE_CONTEXT (table)[row_index]; int32_t entry_index; @@ -125,13 +124,64 @@ ecma_lcache_insert (ecma_object_t *object_p, /**< object */ 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_name_cp = name_cp; entry_p->prop_p = prop_p; ecma_set_property_lcached (entry_p->prop_p, true); #endif /* !CONFIG_ECMA_LCACHE_DISABLE */ } /* ecma_lcache_insert */ +#ifndef CONFIG_ECMA_LCACHE_DISABLE + +/** + * Converts a string into a property name + * + * @return the compressed pointer part of the name + */ +static inline jmem_cpointer_t __attr_always_inline___ +ecma_string_to_lcache_property_name (const ecma_string_t *prop_name_p, /**< property name */ + ecma_property_t *name_type_p) /**< [out] property name type */ +{ + ecma_string_container_t container = ECMA_STRING_GET_CONTAINER (prop_name_p); + + switch (container) + { + case ECMA_STRING_CONTAINER_UINT32_IN_DESC: + case ECMA_STRING_CONTAINER_MAGIC_STRING: + case ECMA_STRING_CONTAINER_MAGIC_STRING_EX: + { +#ifdef JERRY_CPOINTER_32_BIT + + *name_type_p = (ecma_property_t) container; + return (jmem_cpointer_t) prop_name_p->u.uint32_number; + +#else /* !JERRY_CPOINTER_32_BIT */ + + if (prop_name_p->u.uint32_number < (UINT16_MAX + 1)) + { + *name_type_p = (ecma_property_t) container; + return (jmem_cpointer_t) prop_name_p->u.uint32_number; + } + +#endif /* JERRY_CPOINTER_32_BIT */ + + break; + } + default: + { + break; + } + } + + *name_type_p = ECMA_PROPERTY_NAME_TYPE_STRING; + + jmem_cpointer_t prop_name_cp; + ECMA_SET_NON_NULL_POINTER (prop_name_cp, prop_name_p); + return prop_name_cp; +} /* ecma_string_to_lcache_property_name */ + +#endif /* !CONFIG_ECMA_LCACHE_DISABLE */ + /** * Lookup property in the LCache * @@ -149,35 +199,32 @@ 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, prop_name_p); + size_t row_index = ecma_lcache_row_index (object_cp, ecma_string_hash (prop_name_p)); 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_string_container_t prop_container = ECMA_STRING_GET_CONTAINER (prop_name_p); + + 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) + if (entry_p->object_cp == object_cp + && entry_p->prop_name_cp == prop_name_cp) { - ecma_string_t *entry_prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, - entry_p->prop_name_cp); + ecma_property_t *prop_p = entry_p->prop_p; - JERRY_ASSERT ((prop_name_p->hash & ECMA_LCACHE_HASH_MASK) == (entry_prop_name_p->hash & ECMA_LCACHE_HASH_MASK)); + JERRY_ASSERT (prop_p != NULL && ecma_is_property_lcached (prop_p)); - if (prop_name_p == entry_prop_name_p - || (prop_container > ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING - && prop_container == ECMA_STRING_GET_CONTAINER (entry_prop_name_p) - && prop_name_p->u.common_field == entry_prop_name_p->u.common_field)) + if (ECMA_PROPERTY_GET_NAME_TYPE (*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)); - return prop_p; } - else - { - /* They can be equal, but generic string comparison is too costly. */ - } } + else + { + /* They can be equal, but generic string comparison is too costly. */ + } + entry_p++; } #endif /* !CONFIG_ECMA_LCACHE_DISABLE */ @@ -190,11 +237,10 @@ ecma_lcache_lookup (ecma_object_t *object_p, /**< object */ */ void ecma_lcache_invalidate (ecma_object_t *object_p, /**< object */ - ecma_string_t *prop_name_p, /**< property's name */ + jmem_cpointer_t name_cp, /**< 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); @@ -203,7 +249,8 @@ ecma_lcache_invalidate (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, prop_name_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); ecma_lcache_hash_entry_t *entry_p = JERRY_HASH_TABLE_CONTEXT (table) [row_index]; for (uint32_t entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++) diff --git a/jerry-core/ecma/base/ecma-lcache.h b/jerry-core/ecma/base/ecma-lcache.h index 4cf1f6e37c..190ab06920 100644 --- a/jerry-core/ecma/base/ecma-lcache.h +++ b/jerry-core/ecma/base/ecma-lcache.h @@ -24,9 +24,9 @@ */ extern void ecma_lcache_init (void); -extern void ecma_lcache_insert (ecma_object_t *, ecma_string_t *, ecma_property_t *); +extern void ecma_lcache_insert (ecma_object_t *, jmem_cpointer_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 *); +extern void ecma_lcache_invalidate (ecma_object_t *, jmem_cpointer_t, ecma_property_t *); /** * @} diff --git a/jerry-core/ecma/base/ecma-property-hashmap.c b/jerry-core/ecma/base/ecma-property-hashmap.c index 4c201f217c..d0279cc0eb 100644 --- a/jerry-core/ecma/base/ecma-property-hashmap.c +++ b/jerry-core/ecma/base/ecma-property-hashmap.c @@ -161,18 +161,15 @@ ecma_property_hashmap_create (ecma_object_t *object_p) /**< object */ for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) { - ecma_property_types_t type = ECMA_PROPERTY_GET_TYPE (prop_iter_p->types[i]); - - if (!(type == ECMA_PROPERTY_TYPE_NAMEDDATA || type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR)) + if (!ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[i])) { continue; } ecma_property_pair_t *property_pair_p = (ecma_property_pair_t *) prop_iter_p; - ecma_string_t *name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, - property_pair_p->names_cp[i]); - uint32_t entry_index = name_p->hash; + uint32_t entry_index = ecma_string_get_property_name_hash (prop_iter_p->types[i], + property_pair_p->names_cp[i]); uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)]; if (mask < LIT_STRING_HASH_LIMIT) @@ -333,7 +330,7 @@ ecma_property_hashmap_insert (ecma_object_t *object_p, /**< object */ */ void ecma_property_hashmap_delete (ecma_object_t *object_p, /**< object */ - ecma_string_t *name_p, /**< name of the property */ + jmem_cpointer_t name_cp, /**< property name */ ecma_property_t *property_p) /**< property */ { #ifndef CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE @@ -342,7 +339,7 @@ ecma_property_hashmap_delete (ecma_object_t *object_p, /**< object */ JERRY_ASSERT (hashmap_p->header.types[0] == ECMA_PROPERTY_TYPE_HASHMAP); - uint32_t entry_index = name_p->hash; + uint32_t entry_index = ecma_string_get_property_name_hash (*property_p, name_cp); uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)]; uint32_t mask = hashmap_p->max_property_count - 1; jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1); @@ -368,6 +365,7 @@ ecma_property_hashmap_delete (ecma_object_t *object_p, /**< object */ 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; @@ -378,9 +376,7 @@ ecma_property_hashmap_delete (ecma_object_t *object_p, /**< object */ if ((property_pair_p->header.types + offset) == property_p) { - JERRY_ASSERT (ecma_compare_ecma_strings (ECMA_GET_NON_NULL_POINTER (ecma_string_t, - property_pair_p->names_cp[offset]), - name_p)); + JERRY_ASSERT (property_pair_p->names_cp[offset] == name_cp); pair_list_p[entry_index] = ECMA_NULL_POINTER; ECMA_PROPERTY_HASHMAP_SET_BIT (bits_p, entry_index); @@ -415,7 +411,7 @@ 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 **property_real_name_p) /**< [out] property real name */ + jmem_cpointer_t *property_real_name_cp) /**< [out] property real name */ { #ifndef JERRY_NDEBUG /* A sanity check in debug mode: a named property must be present @@ -434,12 +430,11 @@ ecma_property_hashmap_find (ecma_property_hashmap_t *hashmap_p, /**< hashmap */ 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 (prop_iter_p->types[i])) { - ecma_string_t *property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, - prop_pair_p->names_cp[i]); - - if (ecma_compare_ecma_strings (name_p, property_name_p)) + if (ecma_string_compare_to_property_name (prop_iter_p->types[i], + prop_pair_p->names_cp[i], + name_p)) { property_found = true; break; @@ -486,16 +481,19 @@ ecma_property_hashmap_find (ecma_property_hashmap_t *hashmap_p, /**< hashmap */ ecma_property_pair_t *property_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_property_pair_t, pair_list_p[entry_index]); - ecma_string_t *property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, - property_pair_p->names_cp[offset]); + ecma_property_t *property_p = property_pair_p->header.types + offset; + + JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (*property_p)); - if (ecma_compare_ecma_strings (name_p, property_name_p)) + if (ecma_string_compare_to_property_name (*property_p, + property_pair_p->names_cp[offset], + name_p)) { #ifndef JERRY_NDEBUG JERRY_ASSERT (property_found); #endif /* !JERRY_NDEBUG */ - *property_real_name_p = property_name_p; - return property_pair_p->header.types + offset; + *property_real_name_cp = property_pair_p->names_cp[offset]; + return property_p; } } else diff --git a/jerry-core/ecma/base/ecma-property-hashmap.h b/jerry-core/ecma/base/ecma-property-hashmap.h index 3aa4333145..c2f2e49b0c 100644 --- a/jerry-core/ecma/base/ecma-property-hashmap.h +++ b/jerry-core/ecma/base/ecma-property-hashmap.h @@ -56,10 +56,10 @@ typedef struct extern void ecma_property_hashmap_create (ecma_object_t *); extern void ecma_property_hashmap_free (ecma_object_t *); extern void ecma_property_hashmap_insert (ecma_object_t *, ecma_string_t *, ecma_property_pair_t *, int); -extern void ecma_property_hashmap_delete (ecma_object_t *, ecma_string_t *, ecma_property_t *); +extern void ecma_property_hashmap_delete (ecma_object_t *, jmem_cpointer_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 *, ecma_string_t **); +extern ecma_property_t *ecma_property_hashmap_find (ecma_property_hashmap_t *, ecma_string_t *, jmem_cpointer_t *); #endif /* !CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */ /** diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.c b/jerry-core/ecma/builtin-objects/ecma-builtins.c index fc964888a5..bf8732b29f 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.c @@ -387,9 +387,9 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * return NULL; } - lit_magic_string_id_t magic_string_id; + lit_magic_string_id_t magic_string_id = ecma_get_string_magic (string_p); - if (!ecma_is_string_magic (string_p, &magic_string_id)) + if (magic_string_id == LIT_MAGIC_STRING__COUNT) { return NULL; } diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c index b6e5bab795..be2c2cbbb3 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -1259,7 +1259,8 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ || ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR) { ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; - ecma_string_t *name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_pair_p->names_cp[i]); + ecma_string_t *name_p = ecma_string_from_property_name (*property_p, + prop_pair_p->names_cp[i]); if (!(is_enumerable_only && !ecma_is_property_enumerable (*property_p))) { @@ -1311,6 +1312,8 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ names_hashes_bitmap[bitmap_row] |= (1u << bitmap_column); } } + + ecma_deref_ecma_string (name_p); } } diff --git a/jerry-core/lit/lit-globals.h b/jerry-core/lit/lit-globals.h index b5b6071399..8081571595 100644 --- a/jerry-core/lit/lit-globals.h +++ b/jerry-core/lit/lit-globals.h @@ -139,9 +139,4 @@ typedef uint16_t lit_string_hash_t; */ #define LIT_STRING_HASH_LIMIT 0x10000u -/** - * Hash of the frequently used "length" string. - */ -#define LIT_STRING_LENGTH_HASH 0x3615u - #endif /* !LIT_GLOBALS_H */ diff --git a/jerry-core/lit/lit-magic-strings.c b/jerry-core/lit/lit-magic-strings.c index f17e604282..9b7c6f3621 100644 --- a/jerry-core/lit/lit-magic-strings.c +++ b/jerry-core/lit/lit-magic-strings.c @@ -23,7 +23,7 @@ * @return number of the strings, if there were registered, * zero - otherwise. */ -uint32_t +inline uint32_t __attr_always_inline___ lit_get_magic_string_ex_count (void) { return JERRY_CONTEXT (lit_magic_string_ex_count); @@ -161,28 +161,24 @@ lit_magic_strings_ex_set (const lit_utf8_byte_t **ex_str_items, /**< character a #endif /* !JERRY_NDEBUG */ } /* lit_magic_strings_ex_set */ - /** - * Check if passed cesu-8 string equals to one of magic strings - * and if equal magic string was found, return it's id in 'out_id_p' argument. + * Returns the magic string id of the argument string if it is available. * - * @return true - if magic string equal to passed string was found, - * false - otherwise. + * @return id - if magic string id is found, + * LIT_MAGIC_STRING__COUNT - otherwise. */ -bool +lit_magic_string_id_t lit_is_utf8_string_magic (const lit_utf8_byte_t *string_p, /**< utf-8 string */ - lit_utf8_size_t string_size, /**< string size in bytes */ - lit_magic_string_id_t *out_id_p) /**< [out] magic string's id */ + lit_utf8_size_t string_size) /**< string size in bytes */ { - *out_id_p = LIT_MAGIC_STRING__COUNT; - if (string_size > lit_get_magic_string_size (LIT_MAGIC_STRING__COUNT - 1)) { - return false; + return LIT_MAGIC_STRING__COUNT; } - int first = (int) lit_get_magic_string_size_block_start (string_size); /**< First magic string element */ - int last = (int) (lit_get_magic_string_size_block_start (string_size + 1) - 1); /**< Last magic string element */ + /**< The string must be in this id range. */ + int first = (int) lit_get_magic_string_size_block_start (string_size); + int last = (int) (lit_get_magic_string_size_block_start (string_size + 1) - 1); while (first <= last) { @@ -191,8 +187,7 @@ lit_is_utf8_string_magic (const lit_utf8_byte_t *string_p, /**< utf-8 string */ if (compare == 0) { - *out_id_p = (lit_magic_string_id_t) middle; - return true; + return (lit_magic_string_id_t) middle; } else if (compare > 0) { @@ -204,19 +199,70 @@ lit_is_utf8_string_magic (const lit_utf8_byte_t *string_p, /**< utf-8 string */ } } - return false; + return LIT_MAGIC_STRING__COUNT; } /* lit_is_utf8_string_magic */ /** - * Check if passed utf-8 string equals to one of external magic strings - * and if equal magic string was found, return it's id in 'out_id_p' argument. + * Returns the magic string id of the argument string pair if it is available. * - * @return true - if external magic string equal to passed string was found, - * false - otherwise. + * @return id - if magic string id is found, + * LIT_MAGIC_STRING__COUNT - otherwise. */ -bool lit_is_ex_utf8_string_magic (const lit_utf8_byte_t *string_p, /**< utf-8 string */ - lit_utf8_size_t string_size, /**< string size in bytes */ - lit_magic_string_ex_id_t *out_id_p) /**< [out] magic string's id */ +lit_magic_string_id_t +lit_is_utf8_string_pair_magic (const lit_utf8_byte_t *string1_p, /**< first utf-8 string */ + lit_utf8_size_t string1_size, /**< first string size in bytes */ + const lit_utf8_byte_t *string2_p, /**< second utf-8 string */ + lit_utf8_size_t string2_size) /**< second string size in bytes */ +{ + lit_utf8_size_t total_string_size = string1_size + string2_size; + + if (total_string_size > lit_get_magic_string_size (LIT_MAGIC_STRING__COUNT - 1)) + { + return LIT_MAGIC_STRING__COUNT; + } + + /**< The string must be in this id range. */ + int first = (int) lit_get_magic_string_size_block_start (total_string_size); + int last = (int) (lit_get_magic_string_size_block_start (total_string_size + 1) - 1); + + while (first <= last) + { + int middle = ((first + last) / 2); /**< mid point of search */ + const lit_utf8_byte_t *middle_string_p = lit_get_magic_string_utf8 (middle); + + int compare = memcmp (middle_string_p, string1_p, string1_size); + + if (compare == 0) + { + compare = memcmp (middle_string_p + string1_size, string2_p, string2_size); + } + + if (compare == 0) + { + return (lit_magic_string_id_t) middle; + } + else if (compare > 0) + { + last = middle - 1; + } + else + { + first = middle + 1; + } + } + + return LIT_MAGIC_STRING__COUNT; +} /* lit_is_utf8_string_pair_magic */ + +/** + * Returns the ex magic string id of the argument string if it is available. + * + * @return id - if magic string id is found, + * lit_get_magic_string_ex_count () - otherwise. + */ +lit_magic_string_ex_id_t +lit_is_ex_utf8_string_magic (const lit_utf8_byte_t *string_p, /**< utf-8 string */ + lit_utf8_size_t string_size) /**< string size in bytes */ { /* TODO: Improve performance of search */ @@ -224,36 +270,51 @@ bool lit_is_ex_utf8_string_magic (const lit_utf8_byte_t *string_p, /**< utf-8 st id < JERRY_CONTEXT (lit_magic_string_ex_count); id = (lit_magic_string_ex_id_t) (id + 1)) { - if (lit_compare_utf8_string_and_magic_string_ex (string_p, string_size, id)) + if (string_size == lit_get_magic_string_ex_size (id)) { - *out_id_p = id; - - return true; + if (memcmp (string_p, lit_get_magic_string_ex_utf8 (id), string_size) == 0) + { + return id; + } } } - *out_id_p = JERRY_CONTEXT (lit_magic_string_ex_count); - - return false; + return JERRY_CONTEXT (lit_magic_string_ex_count); } /* lit_is_ex_utf8_string_magic */ /** - * Compare utf-8 string and external magic string for equality + * Returns the ex magic string id of the argument string pair if it is available. * - * @return true if strings are equal - * false otherwise + * @return id - if magic string id is found, + * lit_get_magic_string_ex_count () - otherwise. */ -bool -lit_compare_utf8_string_and_magic_string_ex (const lit_utf8_byte_t *string_p, /**< utf-8 string */ - lit_utf8_size_t string_size, /**< string size in bytes */ - lit_magic_string_ex_id_t magic_string_ex_id) /**< external magic string's - * id */ +lit_magic_string_ex_id_t +lit_is_ex_utf8_string_pair_magic (const lit_utf8_byte_t *string1_p, /**< first utf-8 string */ + lit_utf8_size_t string1_size, /**< first string size in bytes */ + const lit_utf8_byte_t *string2_p, /**< second utf-8 string */ + lit_utf8_size_t string2_size) /**< second string size in bytes */ { - return lit_compare_utf8_strings (string_p, - string_size, - lit_get_magic_string_ex_utf8 (magic_string_ex_id), - lit_get_magic_string_ex_size (magic_string_ex_id)); -} /* lit_compare_utf8_string_and_magic_string_ex */ + /* TODO: Improve performance of search */ + lit_utf8_size_t total_string_size = string1_size + string2_size; + + for (lit_magic_string_ex_id_t id = (lit_magic_string_ex_id_t) 0; + id < JERRY_CONTEXT (lit_magic_string_ex_count); + id = (lit_magic_string_ex_id_t) (id + 1)) + { + if (total_string_size == lit_get_magic_string_ex_size (id)) + { + const lit_utf8_byte_t *ex_magic_string_p = lit_get_magic_string_ex_utf8 (id); + + if (memcmp (string1_p, ex_magic_string_p, string1_size) == 0 + && memcmp (string2_p, ex_magic_string_p + string1_size, string2_size) == 0) + { + return id; + } + } + } + + return JERRY_CONTEXT (lit_magic_string_ex_count); +} /* lit_is_ex_utf8_string_pair_magic */ /** * Copy magic string to buffer diff --git a/jerry-core/lit/lit-magic-strings.h b/jerry-core/lit/lit-magic-strings.h index 02adeb7abd..d8dff47996 100644 --- a/jerry-core/lit/lit-magic-strings.h +++ b/jerry-core/lit/lit-magic-strings.h @@ -53,12 +53,13 @@ extern lit_utf8_size_t lit_get_magic_string_ex_size (lit_magic_string_ex_id_t); extern void lit_magic_strings_ex_set (const lit_utf8_byte_t **, uint32_t, const lit_utf8_size_t *); -extern bool lit_is_utf8_string_magic (const lit_utf8_byte_t *, lit_utf8_size_t, lit_magic_string_id_t *); +extern lit_magic_string_id_t lit_is_utf8_string_magic (const lit_utf8_byte_t *, lit_utf8_size_t); +extern lit_magic_string_id_t lit_is_utf8_string_pair_magic (const lit_utf8_byte_t *, lit_utf8_size_t, + const lit_utf8_byte_t *, lit_utf8_size_t); -extern bool lit_is_ex_utf8_string_magic (const lit_utf8_byte_t *, lit_utf8_size_t, lit_magic_string_ex_id_t *); - -extern bool lit_compare_utf8_string_and_magic_string_ex (const lit_utf8_byte_t *, lit_utf8_size_t, - lit_magic_string_ex_id_t); +extern lit_magic_string_ex_id_t lit_is_ex_utf8_string_magic (const lit_utf8_byte_t *, lit_utf8_size_t); +extern lit_magic_string_ex_id_t lit_is_ex_utf8_string_pair_magic (const lit_utf8_byte_t *, lit_utf8_size_t, + const lit_utf8_byte_t *, lit_utf8_size_t); extern lit_utf8_byte_t *lit_copy_magic_string_to_buffer (lit_magic_string_id_t, lit_utf8_byte_t *, lit_utf8_size_t); diff --git a/jerry-core/lit/lit-magic-strings.inc.h b/jerry-core/lit/lit-magic-strings.inc.h index 2770932d2c..9c13243260 100644 --- a/jerry-core/lit/lit-magic-strings.inc.h +++ b/jerry-core/lit/lit-magic-strings.inc.h @@ -63,8 +63,8 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MIN, "min") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NOW, "now") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_POP, "pop") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_POW, "pow") -LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SIN, "sin") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET, "set") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SIN, "sin") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TAN, "tan") LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (4, LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP, "(?:)") diff --git a/jerry-core/lit/lit-strings.c b/jerry-core/lit/lit-strings.c index ee26c62d83..26c2073d63 100644 --- a/jerry-core/lit/lit-strings.c +++ b/jerry-core/lit/lit-strings.c @@ -739,26 +739,6 @@ lit_convert_surrogate_pair_to_code_point (ecma_char_t high_surrogate, /**< high return code_point; } /* lit_convert_surrogate_pair_to_code_point */ -/** - * Compare cesu-8 string to cesu-8 string - * - * @return true - if strings are equal; - * false - otherwise. - */ -bool -lit_compare_utf8_strings (const lit_utf8_byte_t *string1_p, /**< utf-8 string */ - lit_utf8_size_t string1_size, /**< string size */ - const lit_utf8_byte_t *string2_p, /**< utf-8 string */ - lit_utf8_size_t string2_size) /**< string size */ -{ - if (string1_size != string2_size) - { - return false; - } - - return memcmp (string1_p, string2_p, string1_size) == 0; -} /* lit_compare_utf8_strings */ - /** * Relational compare of cesu-8 strings * diff --git a/jerry-core/lit/lit-strings.h b/jerry-core/lit/lit-strings.h index c49f96bb7c..3bd49b4b7e 100644 --- a/jerry-core/lit/lit-strings.h +++ b/jerry-core/lit/lit-strings.h @@ -113,9 +113,6 @@ lit_utf8_size_t lit_code_point_to_utf8 (lit_code_point_t, lit_utf8_byte_t *); lit_utf8_size_t lit_code_point_to_cesu8 (lit_code_point_t, lit_utf8_byte_t *); lit_code_point_t lit_convert_surrogate_pair_to_code_point (ecma_char_t, ecma_char_t); -bool lit_compare_utf8_strings (const lit_utf8_byte_t *, lit_utf8_size_t, - const lit_utf8_byte_t *, lit_utf8_size_t); - bool lit_compare_utf8_strings_relational (const lit_utf8_byte_t *string1_p, lit_utf8_size_t, const lit_utf8_byte_t *string2_p, lit_utf8_size_t); diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index ca1a5f2cdf..bbf038d8b5 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -62,7 +62,13 @@ vm_op_get_value (ecma_value_t object, /**< base object */ { ecma_integer_value_t int_value = ecma_get_integer_from_value (property); - if (int_value >= 0) +#ifdef JERRY_CPOINTER_32_BIT + bool limit_check = (int_value >= 0); +#else /* !JERRY_CPOINTER_32_BIT */ + bool limit_check = (int_value >= 0 && int_value < (UINT16_MAX + 1)); +#endif + + if (limit_check) { /* Statically allocated string for searching. */ ecma_init_ecma_string_from_uint32 (&uint32_string, (uint32_t) int_value);