diff --git a/jerry-core/ecma/base/ecma-alloc.c b/jerry-core/ecma/base/ecma-alloc.c index fd2f9684c..9e72b9971 100644 --- a/jerry-core/ecma/base/ecma-alloc.c +++ b/jerry-core/ecma/base/ecma-alloc.c @@ -24,9 +24,6 @@ JERRY_STATIC_ASSERT (sizeof (ecma_property_value_t) == sizeof (ecma_value_t), JERRY_STATIC_ASSERT (((sizeof (ecma_property_value_t) - 1) & sizeof (ecma_property_value_t)) == 0, size_of_ecma_property_value_t_must_be_power_of_2); -JERRY_STATIC_ASSERT (sizeof (ecma_string_t) == sizeof (uint64_t), - size_of_ecma_string_t_must_be_less_than_or_equal_to_8_bytes); - JERRY_STATIC_ASSERT (sizeof (ecma_extended_object_t) - sizeof (ecma_object_t) <= sizeof (uint64_t), size_of_ecma_extended_object_part_must_be_less_than_or_equal_to_8_bytes); @@ -155,7 +152,35 @@ ecma_dealloc_string (ecma_string_t *string_p) /**< string to be freed */ } /* ecma_dealloc_string */ /** - * Allocate memory for string with character data + * Allocate memory for extended ecma-string descriptor + * + * @return pointer to allocated memory + */ +inline ecma_extended_string_t * JERRY_ATTR_ALWAYS_INLINE +ecma_alloc_extended_string (void) +{ +#if ENABLED (JERRY_MEM_STATS) + jmem_stats_allocate_string_bytes (sizeof (ecma_extended_string_t)); +#endif /* ENABLED (JERRY_MEM_STATS) */ + + return (ecma_extended_string_t *) jmem_heap_alloc_block (sizeof (ecma_extended_string_t)); +} /* ecma_alloc_extended_string */ + +/** + * Dealloc memory from extended ecma-string descriptor + */ +inline void JERRY_ATTR_ALWAYS_INLINE +ecma_dealloc_extended_string (ecma_extended_string_t *ext_string_p) /**< extended string to be freed */ +{ +#if ENABLED (JERRY_MEM_STATS) + jmem_stats_free_string_bytes (sizeof (ecma_extended_string_t)); +#endif /* ENABLED (JERRY_MEM_STATS) */ + + jmem_heap_free_block (ext_string_p, sizeof (ecma_extended_string_t)); +} /* ecma_dealloc_extended_string */ + +/** + * Allocate memory for an string with character data * * @return pointer to allocated memory */ diff --git a/jerry-core/ecma/base/ecma-alloc.h b/jerry-core/ecma/base/ecma-alloc.h index da75f690f..437931781 100644 --- a/jerry-core/ecma/base/ecma-alloc.h +++ b/jerry-core/ecma/base/ecma-alloc.h @@ -73,6 +73,18 @@ ecma_string_t *ecma_alloc_string (void); */ void ecma_dealloc_string (ecma_string_t *string_p); +/** + * Allocate memory for extended ecma-string descriptor + * + * @return pointer to allocated memory + */ +ecma_extended_string_t *ecma_alloc_extended_string (void); + +/** + * Dealloc memory from extended ecma-string descriptor + */ +void ecma_dealloc_extended_string (ecma_extended_string_t *string_p); + /** * Allocate memory for string with character data * diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index d40c3c3f6..fe64f2ef0 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -266,7 +266,7 @@ ecma_gc_mark_container_object (ecma_object_t *object_p) /**< object */ if (ECMA_STRING_GET_CONTAINER (prop_name_p) == ECMA_STRING_CONTAINER_MAP_KEY) { - ecma_value_t key_arg = prop_name_p->u.value; + ecma_value_t key_arg = ((ecma_extended_string_t *) prop_name_p)->u.value; if (ecma_is_value_object (key_arg)) { diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 953bee465..542ea3cd4 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -1330,9 +1330,6 @@ typedef enum #define ECMA_GET_DIRECT_STRING_VALUE(string_p) \ (((uintptr_t) (string_p)) >> ECMA_DIRECT_STRING_SHIFT) -/** - * Identifier for ecma-string's actual data container - */ typedef enum { ECMA_STRING_CONTAINER_HEAP_UTF8_STRING, /**< actual data is on the heap as an utf-8 (cesu8) string @@ -1341,17 +1338,15 @@ typedef enum * 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_HEAP_ASCII_STRING, /**< actual data is on the heap as an ASCII string + * maximum size is 2^16. */ ECMA_STRING_CONTAINER_MAGIC_STRING_EX, /**< the ecma-string is equal to one of external magic strings */ ECMA_STRING_CONTAINER_SYMBOL, /**< the ecma-string is a symbol */ ECMA_STRING_CONTAINER_MAP_KEY, /**< the ecma-string is a map key string */ - ECMA_STRING_LITERAL_NUMBER, /**< a literal number which is used solely by the literal storage - * so no string processing function supports this type except - * the ecma_deref_ecma_string function. */ - - ECMA_STRING_CONTAINER__MAX = ECMA_STRING_LITERAL_NUMBER /**< maximum value */ + ECMA_STRING_CONTAINER__MAX = ECMA_STRING_CONTAINER_MAP_KEY /**< maximum value */ } ecma_string_container_t; /** @@ -1362,12 +1357,29 @@ typedef enum /** * Value for increasing or decreasing the reference counter. */ -#define ECMA_STRING_REF_ONE (1u << 3) +#define ECMA_STRING_REF_ONE (1u << 4) /** - * Maximum value of the reference counter (8191). + * Maximum value of the reference counter (4294967280). */ -#define ECMA_STRING_MAX_REF (0x1fffu << 3) +#define ECMA_STRING_MAX_REF (0xFFFFFFF0) + +/** + * Flag that identifies that the string is static which means it is stored in JERRY_CONTEXT (string_list_cp) + */ +#define ECMA_STATIC_STRING_FLAG (1 << 3) + +/** + * Set an ecma-string as static string + */ +#define ECMA_SET_STRING_AS_STATIC(string_p) \ + (string_p)->refs_and_container |= ECMA_STATIC_STRING_FLAG + +/** + * Checks whether the ecma-string is static string + */ +#define ECMA_STRING_IS_STATIC(string_p) \ + ((string_p)->refs_and_container & ECMA_STATIC_STRING_FLAG) /** * Returns with the container type of a string. @@ -1379,7 +1391,7 @@ typedef enum * Checks whether the reference counter is 1. */ #define ECMA_STRING_IS_REF_EQUALS_TO_ONE(string_desc_p) \ - (((string_desc_p)->refs_and_container >> 3) == 1) + (((string_desc_p)->refs_and_container >> 4) == 1) /** * ECMA string-value descriptor @@ -1387,43 +1399,79 @@ typedef enum typedef struct { /** Reference counter for the string */ - uint16_t refs_and_container; - - /** Hash of the string (calculated from two last characters of the string) */ - lit_string_hash_t hash; + uint32_t refs_and_container; /** * Actual data or identifier of it's place in container (depending on 'container' field) */ union { - /** - * Actual data of an utf-8 string type - */ - struct - { - uint16_t size; /**< size of this utf-8 string in bytes */ - uint16_t length; /**< length of this utf-8 string in characters */ - } utf8_string; - - 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_string_hash_t hash; /**< hash of the ASCII/UTF8 string */ uint32_t magic_string_ex_id; /**< identifier of an external magic string (lit_magic_string_ex_id_t) */ - ecma_value_t lit_number; /**< number (see ECMA_STRING_LITERAL_NUMBER) */ - uint32_t common_uint32_field; /**< for zeroing and comparison in some cases */ - ecma_value_t symbol_descriptor; /**< symbol descriptor string-value */ - ecma_value_t value; /**< original key value corresponds to the map key string */ + uint32_t uint32_number; /**< uint32-represented number placed locally in the descriptor */ } u; } ecma_string_t; /** - * Long ECMA string-value descriptor + * ECMA ASCII string-value descriptor */ typedef struct { ecma_string_t header; /**< string header */ - lit_utf8_size_t long_utf8_string_length; /**< length of this long utf-8 string in bytes */ -} ecma_long_string_t; + uint16_t size; /**< size of this ASCII string in bytes */ +} ecma_ascii_string_t; + +/** + * ECMA long UTF8 string-value descriptor + */ +typedef struct +{ + ecma_string_t header; /**< string header */ + uint16_t size; /**< size of this utf-8 string in bytes */ + uint16_t length; /**< length of this utf-8 string in bytes */ +} ecma_utf8_string_t; + +/** + * ECMA UTF8 string-value descriptor + */ +typedef struct +{ + ecma_string_t header; /**< string header */ + lit_utf8_size_t size; /**< size of this long utf-8 string in bytes */ + lit_utf8_size_t length; /**< length of this long utf-8 string in bytes */ +} ecma_long_utf8_string_t; + +/** + * Get the start position of the string buffer of an ecma ASCII string + */ +#define ECMA_ASCII_STRING_GET_BUFFER(string_p) \ + ((lit_utf8_byte_t *) ((lit_utf8_byte_t *) (string_p) + sizeof (ecma_ascii_string_t))) + +/** + * Get the start position of the string buffer of an ecma UTF8 string + */ +#define ECMA_UTF8_STRING_GET_BUFFER(string_p) \ + ((lit_utf8_byte_t *) ((lit_utf8_byte_t *) (string_p) + sizeof (ecma_utf8_string_t))) + +/** + * Get the start position of the string buffer of an ecma long UTF8 string + */ +#define ECMA_LONG_UTF8_STRING_GET_BUFFER(string_p) \ + ((lit_utf8_byte_t *) ((lit_utf8_byte_t *) (string_p) + sizeof (ecma_long_utf8_string_t))) + +/** + * ECMA extended string-value descriptor + */ +typedef struct +{ + ecma_string_t header; /**< string header */ + + union + { + ecma_value_t symbol_descriptor; /**< symbol descriptor string-value */ + ecma_value_t value; /**< original key value corresponds to the map key string */ + } u; +} ecma_extended_string_t; /** * String builder header @@ -1437,13 +1485,13 @@ typedef struct * Get pointer to the beginning of the stored string in the string builder */ #define ECMA_STRINGBUILDER_STRING_PTR(header_p) \ - ((lit_utf8_byte_t *) (((ecma_string_t *) header_p) + 1)) + ((lit_utf8_byte_t *) (((lit_utf8_byte_t *) header_p) + sizeof (ecma_ascii_string_t))) /** * Get the size of the stored string in the string builder */ #define ECMA_STRINGBUILDER_STRING_SIZE(header_p) \ - ((lit_utf8_size_t) (header_p->current_size - sizeof (ecma_string_t))) + ((lit_utf8_size_t) (header_p->current_size - sizeof (ecma_ascii_string_t))) /** * String builder handle @@ -1507,6 +1555,15 @@ typedef struct jmem_cpointer_t values[ECMA_LIT_STORAGE_VALUE_COUNT]; /**< list of values */ } ecma_lit_storage_item_t; +/** + * Number storage item + */ +typedef struct +{ + jmem_cpointer_t next_cp; /**< cpointer ot next item */ + jmem_cpointer_t values[ECMA_LIT_STORAGE_VALUE_COUNT]; /**< list of values */ +} ecma_number_storage_item_t; + #if ENABLED (JERRY_LCACHE) /** * Container of an LCache entry identifier diff --git a/jerry-core/ecma/base/ecma-helpers-string.c b/jerry-core/ecma/base/ecma-helpers-string.c index 7810dc4b3..4236e3770 100644 --- a/jerry-core/ecma/base/ecma-helpers-string.c +++ b/jerry-core/ecma/base/ecma-helpers-string.c @@ -30,14 +30,11 @@ * @{ */ -JERRY_STATIC_ASSERT (ECMA_STRING_CONTAINER_MASK + 1 == ECMA_STRING_REF_ONE, - ecma_string_ref_counter_should_start_after_the_container_field); - JERRY_STATIC_ASSERT (ECMA_STRING_CONTAINER_MASK >= ECMA_STRING_CONTAINER__MAX, ecma_string_container_types_must_be_lower_than_the_container_mask); -JERRY_STATIC_ASSERT ((ECMA_STRING_MAX_REF | ECMA_STRING_CONTAINER_MASK) == UINT16_MAX, - ecma_string_ref_and_container_fields_should_fill_the_16_bit_field); +JERRY_STATIC_ASSERT ((ECMA_STRING_MAX_REF | ECMA_STRING_CONTAINER_MASK | ECMA_STATIC_STRING_FLAG) == UINT32_MAX, + ecma_string_ref_and_container_fields_should_fill_the_32_bit_field); JERRY_STATIC_ASSERT (ECMA_STRING_NOT_ARRAY_INDEX == UINT32_MAX, ecma_string_not_array_index_must_be_equal_to_uint32_max); @@ -54,8 +51,8 @@ JERRY_STATIC_ASSERT ((int) ECMA_DIRECT_STRING_UINT == (int) ECMA_STRING_CONTAINE JERRY_STATIC_ASSERT (ECMA_PROPERTY_NAME_TYPE_SHIFT > ECMA_VALUE_SHIFT, ecma_property_name_type_shift_must_be_greater_than_ecma_value_shift); -JERRY_STATIC_ASSERT (sizeof (ecma_stringbuilder_header_t) <= sizeof (ecma_string_t), - ecma_stringbuilder_header_must_not_be_larger_than_ecma_string); +JERRY_STATIC_ASSERT (sizeof (ecma_stringbuilder_header_t) <= sizeof (ecma_ascii_string_t), + ecma_stringbuilder_header_must_not_be_larger_than_ecma_ascii_string); /** * Convert a string to an unsigned 32 bit value if possible @@ -158,21 +155,26 @@ ecma_string_get_chars_fast (const ecma_string_t *string_p, /**< ecma-string */ { case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: { - *size_p = string_p->u.utf8_string.size; - return (const lit_utf8_byte_t *) (string_p + 1); + *size_p = ((ecma_utf8_string_t *) string_p)->size; + return ECMA_UTF8_STRING_GET_BUFFER (string_p); } case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: { - *size_p = string_p->u.long_utf8_string_size; - ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; - return (const lit_utf8_byte_t *) (long_string_p + 1); + *size_p = ((ecma_long_utf8_string_t *) string_p)->size; + return ECMA_LONG_UTF8_STRING_GET_BUFFER (string_p); + } + case ECMA_STRING_CONTAINER_HEAP_ASCII_STRING: + { + *size_p = ((ecma_ascii_string_t *) string_p)->size; + return ECMA_ASCII_STRING_GET_BUFFER (string_p); } default: { JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); - *size_p = lit_get_magic_string_ex_size (string_p->u.magic_string_ex_id); - return lit_get_magic_string_ex_utf8 (string_p->u.magic_string_ex_id); + lit_magic_string_ex_id_t id = LIT_MAGIC_STRING__COUNT - string_p->u.magic_string_ex_id; + *size_p = lit_get_magic_string_ex_size (id); + return lit_get_magic_string_ex_utf8 (id); } } } /* ecma_string_get_chars_fast */ @@ -197,8 +199,7 @@ ecma_new_ecma_string_from_magic_string_ex_id (lit_magic_string_ex_id_t id) /**< ecma_string_t *string_desc_p = ecma_alloc_string (); string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_MAGIC_STRING_EX | ECMA_STRING_REF_ONE; - string_desc_p->hash = (lit_string_hash_t) (LIT_MAGIC_STRING__COUNT + id); - string_desc_p->u.magic_string_ex_id = id; + string_desc_p->u.magic_string_ex_id = id + LIT_MAGIC_STRING__COUNT; return string_desc_p; } /* ecma_new_ecma_string_from_magic_string_ex_id */ @@ -214,13 +215,13 @@ ecma_new_symbol_from_descriptor_string (ecma_value_t string_desc) /**< ecma-stri { JERRY_ASSERT (!ecma_is_value_symbol (string_desc)); - ecma_string_t *symbol_p = ecma_alloc_string (); - symbol_p->refs_and_container = ECMA_STRING_REF_ONE | ECMA_STRING_CONTAINER_SYMBOL; + ecma_extended_string_t *symbol_p = ecma_alloc_extended_string (); + symbol_p->header.refs_and_container = ECMA_STRING_REF_ONE | ECMA_STRING_CONTAINER_SYMBOL; symbol_p->u.symbol_descriptor = string_desc; - symbol_p->hash = (uint16_t) (((uintptr_t) symbol_p) >> ECMA_SYMBOL_HASH_SHIFT); - JERRY_ASSERT ((symbol_p->hash & ECMA_GLOBAL_SYMBOL_FLAG) == 0); + symbol_p->header.u.hash = (lit_string_hash_t) (((uintptr_t) symbol_p) >> ECMA_SYMBOL_HASH_SHIFT); + JERRY_ASSERT ((symbol_p->header.u.hash & ECMA_GLOBAL_SYMBOL_FLAG) == 0); - return symbol_p; + return (ecma_string_t *) symbol_p; } /* ecma_new_symbol_from_descriptor_string */ /** @@ -250,12 +251,12 @@ ecma_new_map_key_string (ecma_value_t value) /**< non prop-name ecma-value */ { JERRY_ASSERT (!ecma_is_value_prop_name (value)); - ecma_string_t *string_p = ecma_alloc_string (); - string_p->refs_and_container = ECMA_STRING_REF_ONE | ECMA_STRING_CONTAINER_MAP_KEY; + ecma_extended_string_t *string_p = ecma_alloc_extended_string (); + string_p->header.refs_and_container = ECMA_STRING_REF_ONE | ECMA_STRING_CONTAINER_MAP_KEY; string_p->u.value = ecma_copy_value_if_not_object (value); - string_p->hash = (lit_string_hash_t) (ecma_is_value_simple (value) ? value : 0); + string_p->header.u.hash = (lit_string_hash_t) (ecma_is_value_simple (value) ? value : 0); - return string_p; + return (ecma_string_t *) string_p; } /* ecma_new_map_key_string */ /** @@ -274,6 +275,51 @@ ecma_prop_name_is_map_key (ecma_string_t *string_p) /**< ecma-string */ } /* ecma_prop_name_is_map_key */ #endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) || ENABLED (JERRY_ES2015_BUILTIN_SET) */ +/** + * Allocate new UTF8 ecma-string and fill it with characters from the given utf8 buffer + * + * @return pointer to ecma-string descriptor + */ +static inline ecma_string_t * JERRY_ATTR_ALWAYS_INLINE +ecma_new_ecma_string_from_utf8_buffer (lit_utf8_size_t length, /**< length of the buffer */ + lit_utf8_size_t size, /**< size of the buffer */ + lit_utf8_byte_t **data_p) /**< [out] pointer to the start of the string buffer */ +{ + if (JERRY_LIKELY (size <= UINT16_MAX)) + { + if (JERRY_LIKELY (length == size)) + { + ecma_ascii_string_t *string_desc_p; + string_desc_p = (ecma_ascii_string_t *) ecma_alloc_string_buffer (size + sizeof (ecma_ascii_string_t)); + string_desc_p->header.refs_and_container = ECMA_STRING_CONTAINER_HEAP_ASCII_STRING | ECMA_STRING_REF_ONE; + string_desc_p->size = (uint16_t) size; + + *data_p = ECMA_ASCII_STRING_GET_BUFFER (string_desc_p); + return (ecma_string_t *) string_desc_p; + } + + JERRY_ASSERT (length < size); + + ecma_utf8_string_t *string_desc_p; + string_desc_p = (ecma_utf8_string_t *) ecma_alloc_string_buffer (size + sizeof (ecma_utf8_string_t)); + string_desc_p->header.refs_and_container = ECMA_STRING_CONTAINER_HEAP_UTF8_STRING | ECMA_STRING_REF_ONE; + string_desc_p->size = (uint16_t) size; + string_desc_p->length = (uint16_t) length; + + *data_p = ECMA_UTF8_STRING_GET_BUFFER (string_desc_p); + return (ecma_string_t *) string_desc_p; + } + + ecma_long_utf8_string_t *string_desc_p; + string_desc_p = (ecma_long_utf8_string_t *) ecma_alloc_string_buffer (size + sizeof (ecma_long_utf8_string_t)); + string_desc_p->header.refs_and_container = ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING | ECMA_STRING_REF_ONE; + string_desc_p->size = size; + string_desc_p->length = length; + + *data_p = ECMA_LONG_UTF8_STRING_GET_BUFFER (string_desc_p); + return (ecma_string_t *) string_desc_p; +} /* ecma_new_ecma_string_from_utf8_buffer */ + /** * Checks whether a string has a special representation, that is, the string is either a magic string, * an external magic string, or an uint32 number, and creates an ecma string using the special representation, @@ -332,40 +378,20 @@ ecma_new_ecma_string_from_utf8 (const lit_utf8_byte_t *string_p, /**< utf-8 stri JERRY_ASSERT (lit_is_valid_cesu8_string (string_p, string_size)); ecma_string_t *string_desc_p = ecma_find_special_string (string_p, string_size); + if (string_desc_p != NULL) { return string_desc_p; } lit_utf8_byte_t *data_p; + string_desc_p = ecma_new_ecma_string_from_utf8_buffer (lit_utf8_string_length (string_p, string_size), + string_size, + &data_p); - if (JERRY_LIKELY (string_size <= UINT16_MAX)) - { - string_desc_p = ecma_alloc_string_buffer (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_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); - - data_p = (lit_utf8_byte_t *) (string_desc_p + 1); - } - else - { - string_desc_p = ecma_alloc_string_buffer (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_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; - long_string_desc_p->long_utf8_string_length = lit_utf8_string_length (string_p, string_size); - - data_p = (lit_utf8_byte_t *) (long_string_desc_p + 1); - } - - string_desc_p->hash = lit_utf8_string_calc_hash (string_p, string_size); + string_desc_p->u.hash = lit_utf8_string_calc_hash (string_p, string_size); memcpy (data_p, string_p, string_size); + return string_desc_p; } /* ecma_new_ecma_string_from_utf8 */ @@ -381,8 +407,6 @@ ecma_new_ecma_string_from_utf8_converted_to_cesu8 (const lit_utf8_byte_t *string { JERRY_ASSERT (string_p != NULL || string_size == 0); - ecma_string_t *string_desc_p = NULL; - ecma_length_t converted_string_length = 0; lit_utf8_size_t converted_string_size = 0; lit_utf8_size_t pos = 0; @@ -419,70 +443,46 @@ ecma_new_ecma_string_from_utf8_converted_to_cesu8 (const lit_utf8_byte_t *string { return ecma_new_ecma_string_from_utf8 (string_p, string_size); } - else + + converted_string_size += string_size; + + JERRY_ASSERT (lit_is_valid_utf8_string (string_p, string_size)); + + lit_utf8_byte_t *data_p; + ecma_string_t *string_desc_p = ecma_new_ecma_string_from_utf8_buffer (converted_string_length, + converted_string_size, + &data_p); + + const lit_utf8_byte_t *const begin_data_p = data_p; + pos = 0; + + while (pos < string_size) { - converted_string_size += string_size; - - JERRY_ASSERT (lit_is_valid_utf8_string (string_p, string_size)); - - lit_utf8_byte_t *data_p; - - if (JERRY_LIKELY (converted_string_size <= UINT16_MAX)) + if ((string_p[pos] & LIT_UTF8_4_BYTE_MASK) == LIT_UTF8_4_BYTE_MARKER) { - string_desc_p = ecma_alloc_string_buffer (sizeof (ecma_string_t) + converted_string_size); + /* Processing 4 byte unicode sequence. Always converted to two 3 byte long sequence. */ + uint32_t character = ((((uint32_t) string_p[pos++]) & 0x7) << 18); + character |= ((((uint32_t) string_p[pos++]) & LIT_UTF8_LAST_6_BITS_MASK) << 12); + character |= ((((uint32_t) string_p[pos++]) & LIT_UTF8_LAST_6_BITS_MASK) << 6); + character |= (((uint32_t) string_p[pos++]) & LIT_UTF8_LAST_6_BITS_MASK); - string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_UTF8_STRING | ECMA_STRING_REF_ONE; - 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; + JERRY_ASSERT (character >= 0x10000); + character -= 0x10000; - data_p = (lit_utf8_byte_t *) (string_desc_p + 1); + data_p += lit_char_to_utf8_bytes (data_p, (ecma_char_t) (0xd800 | (character >> 10))); + data_p += lit_char_to_utf8_bytes (data_p, (ecma_char_t) (0xdc00 | (character & LIT_UTF16_LAST_10_BITS_MASK))); } else { - string_desc_p = ecma_alloc_string_buffer (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_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; - long_string_desc_p->long_utf8_string_length = converted_string_length; - - data_p = (lit_utf8_byte_t *) (long_string_desc_p + 1); + *data_p++ = string_p[pos++]; } - - const lit_utf8_byte_t *const begin_data_p = data_p; - pos = 0; - - while (pos < string_size) - { - if ((string_p[pos] & LIT_UTF8_4_BYTE_MASK) == LIT_UTF8_4_BYTE_MARKER) - { - /* Processing 4 byte unicode sequence. Always converted to two 3 byte long sequence. */ - uint32_t character = ((((uint32_t) string_p[pos++]) & 0x7) << 18); - character |= ((((uint32_t) string_p[pos++]) & LIT_UTF8_LAST_6_BITS_MASK) << 12); - character |= ((((uint32_t) string_p[pos++]) & LIT_UTF8_LAST_6_BITS_MASK) << 6); - character |= (((uint32_t) string_p[pos++]) & LIT_UTF8_LAST_6_BITS_MASK); - - JERRY_ASSERT (character >= 0x10000); - character -= 0x10000; - - data_p += lit_char_to_utf8_bytes (data_p, (ecma_char_t) (0xd800 | (character >> 10))); - data_p += lit_char_to_utf8_bytes (data_p, (ecma_char_t) (0xdc00 | (character & LIT_UTF16_LAST_10_BITS_MASK))); - } - else - { - *data_p++ = string_p[pos++]; - } - } - - JERRY_ASSERT (pos == string_size); - - string_desc_p->hash = lit_utf8_string_calc_hash (begin_data_p, converted_string_size); } - return string_desc_p; + JERRY_ASSERT (pos == string_size); + + string_desc_p->u.hash = lit_utf8_string_calc_hash (begin_data_p, converted_string_size); + + return (ecma_string_t *) string_desc_p; } /* ecma_new_ecma_string_from_utf8_converted_to_cesu8 */ /** @@ -532,7 +532,6 @@ ecma_new_non_direct_string_from_uint32 (uint32_t uint32_number) /**< uint32 valu ecma_string_t *string_p = ecma_alloc_string (); string_p->refs_and_container = ECMA_STRING_CONTAINER_UINT32_IN_DESC | ECMA_STRING_REF_ONE; - string_p->hash = (lit_string_hash_t) uint32_number; string_p->u.uint32_number = uint32_number; return string_p; @@ -605,16 +604,14 @@ ecma_new_ecma_string_from_number (ecma_number_t num) /**< ecma-number */ && 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 = ecma_alloc_string_buffer (sizeof (ecma_string_t) + str_size); + lit_utf8_byte_t *data_p; + ecma_string_t *string_desc_p = ecma_new_ecma_string_from_utf8_buffer (lit_utf8_string_length (str_buf, str_size), + str_size, + &data_p); - 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_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; - - lit_utf8_byte_t *data_p = (lit_utf8_byte_t *) (string_desc_p + 1); + string_desc_p->u.hash = lit_utf8_string_calc_hash (str_buf, str_size); memcpy (data_p, str_buf, str_size); + return string_desc_p; } /* ecma_new_ecma_string_from_number */ @@ -655,100 +652,18 @@ ecma_append_chars_to_string (ecma_string_t *string1_p, /**< base ecma-string */ return ecma_new_ecma_string_from_utf8 (cesu8_string2_p, cesu8_string2_size); } - const lit_utf8_byte_t *cesu8_string1_p; lit_utf8_size_t cesu8_string1_size; lit_utf8_size_t cesu8_string1_length; - + uint8_t flags = ECMA_STRING_FLAG_IS_ASCII; lit_utf8_byte_t uint32_to_string_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; - bool string1_is_uint32 = false; - bool string1_rehash_needed = false; - - if (ECMA_IS_DIRECT_STRING (string1_p)) - { - string1_rehash_needed = true; - - switch (ECMA_GET_DIRECT_STRING_TYPE (string1_p)) - { - case ECMA_DIRECT_STRING_MAGIC: - { - uint32_t id = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string1_p); - - if (id >= LIT_MAGIC_STRING__COUNT) - { - id -= LIT_MAGIC_STRING__COUNT; - cesu8_string1_p = lit_get_magic_string_ex_utf8 (id); - cesu8_string1_size = lit_get_magic_string_ex_size (id); - cesu8_string1_length = lit_utf8_string_length (cesu8_string1_p, cesu8_string1_size); - } - else - { - cesu8_string1_p = lit_get_magic_string_utf8 (id); - cesu8_string1_size = lit_get_magic_string_size (id); - cesu8_string1_length = cesu8_string1_size; - } - - break; - } - default: - { - JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string1_p) == ECMA_DIRECT_STRING_UINT); - cesu8_string1_size = ecma_uint32_to_utf8_string ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string1_p), - uint32_to_string_buffer, - ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); - cesu8_string1_p = uint32_to_string_buffer; - cesu8_string1_length = cesu8_string1_size; - string1_is_uint32 = true; - break; - } - } - } - else - { - JERRY_ASSERT (string1_p->refs_and_container >= ECMA_STRING_REF_ONE); - - switch (ECMA_STRING_GET_CONTAINER (string1_p)) - { - case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: - { - cesu8_string1_p = (lit_utf8_byte_t *) (string1_p + 1); - cesu8_string1_size = string1_p->u.utf8_string.size; - cesu8_string1_length = string1_p->u.utf8_string.length; - break; - } - case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: - { - ecma_long_string_t *long_string_desc_p = (ecma_long_string_t *) string1_p; - - cesu8_string1_p = (lit_utf8_byte_t *) (long_string_desc_p + 1); - cesu8_string1_size = string1_p->u.long_utf8_string_size; - cesu8_string1_length = long_string_desc_p->long_utf8_string_length; - break; - } - case ECMA_STRING_CONTAINER_UINT32_IN_DESC: - { - cesu8_string1_size = ecma_uint32_to_utf8_string (string1_p->u.uint32_number, - uint32_to_string_buffer, - ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); - cesu8_string1_p = uint32_to_string_buffer; - cesu8_string1_length = cesu8_string1_size; - string1_is_uint32 = true; - string1_rehash_needed = true; - break; - } - default: - { - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); - - cesu8_string1_p = lit_get_magic_string_ex_utf8 (string1_p->u.magic_string_ex_id); - cesu8_string1_size = lit_get_magic_string_ex_size (string1_p->u.magic_string_ex_id); - cesu8_string1_length = lit_utf8_string_length (cesu8_string1_p, cesu8_string1_size); - string1_rehash_needed = true; - break; - } - } - } + const lit_utf8_byte_t *cesu8_string1_p = ecma_string_get_chars (string1_p, + &cesu8_string1_size, + &cesu8_string1_length, + uint32_to_string_buffer, + &flags); + JERRY_ASSERT (!(flags & ECMA_STRING_FLAG_MUST_BE_FREED)); JERRY_ASSERT (cesu8_string1_length > 0); JERRY_ASSERT (cesu8_string1_length <= cesu8_string1_size); @@ -766,17 +681,16 @@ ecma_append_chars_to_string (ecma_string_t *string1_p, /**< base ecma-string */ cesu8_string2_p, cesu8_string2_size); + if (magic_string_id != LIT_MAGIC_STRING__COUNT) { ecma_deref_ecma_string (string1_p); return ecma_get_magic_string (magic_string_id); } - if (string1_is_uint32 && new_size <= ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32) + if ((flags & ECMA_STRING_FLAG_IS_UINT32) && new_size <= ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32) { - memcpy (uint32_to_string_buffer + cesu8_string1_size, - cesu8_string2_p, - cesu8_string2_size); + memcpy (uint32_to_string_buffer + cesu8_string1_size, cesu8_string2_p, cesu8_string2_size); uint32_t array_index; @@ -802,53 +716,30 @@ ecma_append_chars_to_string (ecma_string_t *string1_p, /**< base ecma-string */ } } - ecma_string_t *string_desc_p; lit_utf8_byte_t *data_p; - - if (JERRY_LIKELY (new_size <= UINT16_MAX)) - { - string_desc_p = ecma_alloc_string_buffer (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_uint32_field = 0; - string_desc_p->u.utf8_string.size = (uint16_t) new_size; - string_desc_p->u.utf8_string.length = (uint16_t) (cesu8_string1_length + cesu8_string2_length); - - data_p = (lit_utf8_byte_t *) (string_desc_p + 1); - } - else - { - string_desc_p = ecma_alloc_string_buffer (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_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; - long_string_desc_p->long_utf8_string_length = cesu8_string1_length + cesu8_string2_length; - - data_p = (lit_utf8_byte_t *) (long_string_desc_p + 1); - } + ecma_string_t *string_desc_p = ecma_new_ecma_string_from_utf8_buffer (cesu8_string1_length + cesu8_string2_length, + new_size, + &data_p); lit_string_hash_t hash_start; - if (string1_rehash_needed) + if (JERRY_UNLIKELY (flags & ECMA_STRING_FLAG_REHASH_NEEDED)) { hash_start = lit_utf8_string_calc_hash (cesu8_string1_p, cesu8_string1_size); } else { JERRY_ASSERT (!ECMA_IS_DIRECT_STRING (string1_p)); - hash_start = string1_p->hash; + hash_start = string1_p->u.hash; } - string_desc_p->hash = lit_utf8_string_hash_combine (hash_start, cesu8_string2_p, cesu8_string2_size); + string_desc_p->u.hash = lit_utf8_string_hash_combine (hash_start, cesu8_string2_p, cesu8_string2_size); memcpy (data_p, cesu8_string1_p, cesu8_string1_size); memcpy (data_p + cesu8_string1_size, cesu8_string2_p, cesu8_string2_size); ecma_deref_ecma_string (string1_p); - return string_desc_p; + return (ecma_string_t *) string_desc_p; } /* ecma_append_chars_to_string */ /** @@ -876,91 +767,27 @@ ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */ return string1_p; } - const lit_utf8_byte_t *cesu8_string2_p; lit_utf8_size_t cesu8_string2_size; lit_utf8_size_t cesu8_string2_length; - lit_utf8_byte_t uint32_to_string_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; + uint8_t flags = ECMA_STRING_FLAG_IS_ASCII; - if (ECMA_IS_DIRECT_STRING (string2_p)) - { - switch (ECMA_GET_DIRECT_STRING_TYPE (string2_p)) - { - case ECMA_DIRECT_STRING_MAGIC: - { - uint32_t id = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string2_p); + const lit_utf8_byte_t *cesu8_string2_p = ecma_string_get_chars (string2_p, + &cesu8_string2_size, + &cesu8_string2_length, + uint32_to_string_buffer, + &flags); - if (id >= LIT_MAGIC_STRING__COUNT) - { - id -= LIT_MAGIC_STRING__COUNT; - cesu8_string2_p = lit_get_magic_string_ex_utf8 (id); - cesu8_string2_size = lit_get_magic_string_ex_size (id); - cesu8_string2_length = lit_utf8_string_length (cesu8_string2_p, cesu8_string2_size); - } - else - { - cesu8_string2_p = lit_get_magic_string_utf8 (id); - cesu8_string2_size = lit_get_magic_string_size (id); - cesu8_string2_length = cesu8_string2_size; - } - break; - } - default: - { - JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string2_p) == ECMA_DIRECT_STRING_UINT); - cesu8_string2_size = ecma_uint32_to_utf8_string ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string2_p), - uint32_to_string_buffer, - ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); - cesu8_string2_p = uint32_to_string_buffer; - cesu8_string2_length = cesu8_string2_size; - break; - } - } - } - else - { - JERRY_ASSERT (string2_p->refs_and_container >= ECMA_STRING_REF_ONE); + JERRY_ASSERT (cesu8_string2_p != NULL); - switch (ECMA_STRING_GET_CONTAINER (string2_p)) - { - case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: - { - cesu8_string2_p = (lit_utf8_byte_t *) (string2_p + 1); - cesu8_string2_size = string2_p->u.utf8_string.size; - cesu8_string2_length = string2_p->u.utf8_string.length; - break; - } - case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: - { - ecma_long_string_t *long_string_desc_p = (ecma_long_string_t *) string2_p; + ecma_string_t *result_p = ecma_append_chars_to_string (string1_p, + cesu8_string2_p, + cesu8_string2_size, + cesu8_string2_length); - cesu8_string2_p = (lit_utf8_byte_t *) (long_string_desc_p + 1); - cesu8_string2_size = string2_p->u.long_utf8_string_size; - cesu8_string2_length = long_string_desc_p->long_utf8_string_length; - break; - } - case ECMA_STRING_CONTAINER_UINT32_IN_DESC: - { - cesu8_string2_size = ecma_uint32_to_utf8_string (string2_p->u.uint32_number, - uint32_to_string_buffer, - ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); - cesu8_string2_p = uint32_to_string_buffer; - cesu8_string2_length = cesu8_string2_size; - break; - } - default: - { - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string2_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + JERRY_ASSERT (!(flags & ECMA_STRING_FLAG_MUST_BE_FREED)); - cesu8_string2_p = lit_get_magic_string_ex_utf8 (string2_p->u.magic_string_ex_id); - cesu8_string2_size = lit_get_magic_string_ex_size (string2_p->u.magic_string_ex_id); - cesu8_string2_length = lit_utf8_string_length (cesu8_string2_p, cesu8_string2_size); - break; - } - } - } - - return ecma_append_chars_to_string (string1_p, cesu8_string2_p, cesu8_string2_size, cesu8_string2_length); + return result_p; } /* ecma_concat_ecma_strings */ /** @@ -995,7 +822,7 @@ ecma_ref_ecma_string (ecma_string_t *string_p) /**< string descriptor */ { JERRY_ASSERT (string_p != NULL); - if (ECMA_IS_DIRECT_STRING (string_p)) + if (ECMA_IS_DIRECT_STRING (string_p) || ECMA_STRING_IS_STATIC (string_p)) { return; } @@ -1005,7 +832,7 @@ ecma_ref_ecma_string (ecma_string_t *string_p) /**< string descriptor */ if (JERRY_LIKELY (string_p->refs_and_container < ECMA_STRING_MAX_REF)) { /* Increase reference counter. */ - string_p->refs_and_container = (uint16_t) (string_p->refs_and_container + ECMA_STRING_REF_ONE); + string_p->refs_and_container += ECMA_STRING_REF_ONE; } else { @@ -1022,7 +849,7 @@ ecma_deref_ecma_string (ecma_string_t *string_p) /**< ecma-string */ { JERRY_ASSERT (string_p != NULL); - if (ECMA_IS_DIRECT_STRING (string_p)) + if (ECMA_IS_DIRECT_STRING (string_p) || ECMA_STRING_IS_STATIC (string_p)) { return; } @@ -1030,57 +857,61 @@ ecma_deref_ecma_string (ecma_string_t *string_p) /**< ecma-string */ JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); /* Decrease reference counter. */ - string_p->refs_and_container = (uint16_t) (string_p->refs_and_container - ECMA_STRING_REF_ONE); + string_p->refs_and_container -= ECMA_STRING_REF_ONE; if (string_p->refs_and_container >= ECMA_STRING_REF_ONE) { return; } + ecma_destroy_ecma_string (string_p); +} /* ecma_deref_ecma_string */ + +/** + * Deallocate an ecma-string + */ +void +ecma_destroy_ecma_string (ecma_string_t *string_p) /**< ecma-string */ +{ + JERRY_ASSERT (string_p != NULL); + JERRY_ASSERT (!ECMA_IS_DIRECT_STRING (string_p)); + JERRY_ASSERT ((string_p->refs_and_container < ECMA_STRING_REF_ONE) || ECMA_STRING_IS_STATIC (string_p)); + switch (ECMA_STRING_GET_CONTAINER (string_p)) { case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: { -#ifndef JERRY_NDEBUG - const lit_utf8_byte_t *chars_p = (const lit_utf8_byte_t *) (string_p + 1); - - if (*chars_p >= LIT_CHAR_0 && *chars_p <= LIT_CHAR_9) - { - uint32_t array_index; - - JERRY_ASSERT (!ecma_string_to_array_index (chars_p, - string_p->u.utf8_string.size, - &array_index)); - } -#endif /* !JERRY_NDEBUG */ - - ecma_dealloc_string_buffer (string_p, string_p->u.utf8_string.size + sizeof (ecma_string_t)); + ecma_dealloc_string_buffer (string_p, ((ecma_utf8_string_t *) string_p)->size + sizeof (ecma_utf8_string_t)); return; } case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: { - JERRY_ASSERT (string_p->u.long_utf8_string_size > UINT16_MAX); - - ecma_dealloc_string_buffer (string_p, string_p->u.long_utf8_string_size + sizeof (ecma_long_string_t)); + ecma_dealloc_string_buffer (string_p, + ((ecma_long_utf8_string_t *) string_p)->size + sizeof (ecma_long_utf8_string_t)); return; } - case ECMA_STRING_LITERAL_NUMBER: + case ECMA_STRING_CONTAINER_HEAP_ASCII_STRING: { - ecma_free_value (string_p->u.lit_number); - break; + ecma_dealloc_string_buffer (string_p, + ((ecma_ascii_string_t *) string_p)->size + sizeof (ecma_ascii_string_t)); + return; } #if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) case ECMA_STRING_CONTAINER_SYMBOL: { - ecma_free_value (string_p->u.symbol_descriptor); - break; + ecma_extended_string_t * symbol_p = (ecma_extended_string_t *) string_p; + ecma_free_value (symbol_p->u.symbol_descriptor); + ecma_dealloc_extended_string (symbol_p); + return; } #endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */ #if ENABLED (JERRY_ES2015_BUILTIN_MAP) || ENABLED (JERRY_ES2015_BUILTIN_SET) case ECMA_STRING_CONTAINER_MAP_KEY: { - ecma_free_value_if_not_object (string_p->u.value); - break; + ecma_extended_string_t *key_p = (ecma_extended_string_t *) string_p; + ecma_free_value_if_not_object (key_p->u.value); + ecma_dealloc_extended_string (key_p); + return; } #endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) || ENABLED (JERRY_ES2015_BUILTIN_SET) */ default: @@ -1089,12 +920,10 @@ ecma_deref_ecma_string (ecma_string_t *string_p) /**< ecma-string */ || ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); /* only the string descriptor itself should be freed */ - break; + ecma_dealloc_string (string_p); } } - - ecma_dealloc_string (string_p); -} /* ecma_deref_ecma_string */ +} /* ecma_destroy_ecma_string */ /** * Convert ecma-string to number @@ -1254,7 +1083,7 @@ ecma_string_copy_to_utf8_buffer (const ecma_string_t *string_p, /**< ecma-string } uint8_t flags = ECMA_STRING_FLAG_IS_ASCII; - const lit_utf8_byte_t *chars_p = ecma_string_get_chars (string_p, &size, &flags); + const lit_utf8_byte_t *chars_p = ecma_string_get_chars (string_p, &size, NULL, NULL, &flags); JERRY_ASSERT (chars_p != NULL); @@ -1545,7 +1374,7 @@ ecma_string_get_uint32_size (const uint32_t uint32_number) /**< number in the st * * Note: * - This function returns with a newly allocated buffer for uint32 strings, - * which must be freed. + * which must be freed if the optional uint32_buff_p parameter is NULL. * - The ASCII check only happens if the flags parameter gets * 'ECMA_STRING_FLAG_IS_ASCII' as an input. * @@ -1554,9 +1383,12 @@ ecma_string_get_uint32_size (const uint32_t uint32_number) /**< number in the st const lit_utf8_byte_t * ecma_string_get_chars (const ecma_string_t *string_p, /**< ecma-string */ lit_utf8_size_t *size_p, /**< [out] size of the ecma string */ - uint8_t *flags_p) /**< [in,out] flags: ECMA_STRING_FLAG_EMPTY, - ECMA_STRING_FLAG_IS_ASCII, - ECMA_STRING_FLAG_MUST_BE_FREED */ + lit_utf8_size_t *length_p, /**< [out] optional argument. If the pointer is not NULL the pointed + * memory area is filled with the length of the ecma string */ + lit_utf8_byte_t *uint32_buff_p, /**< [out] optional argument. If the pointer is not NULL the + * pointed memory area is filled with the string converted + * uint32 string descriptor */ + uint8_t *flags_p) /**< [in,out] any combination of ecma_string_flag_t bits */ { ecma_length_t length; lit_utf8_size_t size; @@ -1564,6 +1396,8 @@ ecma_string_get_chars (const ecma_string_t *string_p, /**< ecma-string */ if (ECMA_IS_DIRECT_STRING (string_p)) { + *flags_p |= ECMA_STRING_FLAG_REHASH_NEEDED; + switch (ECMA_GET_DIRECT_STRING_TYPE (string_p)) { case ECMA_DIRECT_STRING_MAGIC: @@ -1600,10 +1434,20 @@ ecma_string_get_chars (const ecma_string_t *string_p, /**< ecma-string */ uint32_t uint32_number = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); size = (lit_utf8_size_t) ecma_string_get_uint32_size (uint32_number); - result_p = (const lit_utf8_byte_t *) jmem_heap_alloc_block (size); + if (uint32_buff_p != NULL) + { + result_p = uint32_buff_p; + } + else + { + result_p = (const lit_utf8_byte_t *) jmem_heap_alloc_block (size); + *flags_p |= ECMA_STRING_FLAG_MUST_BE_FREED; + } + length = ecma_uint32_to_utf8_string (uint32_number, (lit_utf8_byte_t *) result_p, size); + JERRY_ASSERT (length == size); - *flags_p |= ECMA_STRING_FLAG_MUST_BE_FREED; + *flags_p |= ECMA_STRING_FLAG_IS_UINT32; break; } } @@ -1616,27 +1460,46 @@ ecma_string_get_chars (const ecma_string_t *string_p, /**< ecma-string */ { case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: { - size = string_p->u.utf8_string.size; - length = string_p->u.utf8_string.length; - result_p = (const lit_utf8_byte_t *) (string_p + 1); + ecma_utf8_string_t *utf8_string_desc_p = (ecma_utf8_string_t *) string_p; + size = utf8_string_desc_p->size; + length = utf8_string_desc_p->length; + result_p = ECMA_UTF8_STRING_GET_BUFFER (utf8_string_desc_p); break; } case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: { - size = string_p->u.long_utf8_string_size; - ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; - length = long_string_p->long_utf8_string_length; - result_p = (const lit_utf8_byte_t *) (long_string_p + 1); + ecma_long_utf8_string_t *long_utf8_string_desc_p = (ecma_long_utf8_string_t *) string_p; + size = long_utf8_string_desc_p->size; + length = long_utf8_string_desc_p->length; + result_p = ECMA_LONG_UTF8_STRING_GET_BUFFER (long_utf8_string_desc_p); + break; + } + case ECMA_STRING_CONTAINER_HEAP_ASCII_STRING: + { + ecma_ascii_string_t *ascii_string_desc_p = (ecma_ascii_string_t *) string_p; + size = ascii_string_desc_p->size; + length = ascii_string_desc_p->size; + result_p = ECMA_ASCII_STRING_GET_BUFFER (ascii_string_desc_p); break; } case ECMA_STRING_CONTAINER_UINT32_IN_DESC: { size = (lit_utf8_size_t) ecma_string_get_uint32_size (string_p->u.uint32_number); - result_p = (const lit_utf8_byte_t *) jmem_heap_alloc_block (size); + if (uint32_buff_p != NULL) + { + result_p = uint32_buff_p; + } + else + { + result_p = (const lit_utf8_byte_t *) jmem_heap_alloc_block (size); + *flags_p |= ECMA_STRING_FLAG_MUST_BE_FREED; + } + length = ecma_uint32_to_utf8_string (string_p->u.uint32_number, (lit_utf8_byte_t *) result_p, size); + JERRY_ASSERT (length == size); - *flags_p |= ECMA_STRING_FLAG_MUST_BE_FREED; + *flags_p |= ECMA_STRING_FLAG_IS_UINT32 | ECMA_STRING_FLAG_REHASH_NEEDED; break; } @@ -1644,25 +1507,32 @@ ecma_string_get_chars (const ecma_string_t *string_p, /**< ecma-string */ { JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); - size = lit_get_magic_string_ex_size (string_p->u.magic_string_ex_id); + lit_magic_string_ex_id_t id = LIT_MAGIC_STRING__COUNT - string_p->u.magic_string_ex_id; + size = lit_get_magic_string_ex_size (id); length = 0; if (JERRY_UNLIKELY (*flags_p & ECMA_STRING_FLAG_IS_ASCII)) { - length = lit_utf8_string_length (lit_get_magic_string_ex_utf8 (string_p->u.magic_string_ex_id), size); + length = lit_utf8_string_length (lit_get_magic_string_ex_utf8 (id), size); } - result_p = lit_get_magic_string_ex_utf8 (string_p->u.magic_string_ex_id); + result_p = lit_get_magic_string_ex_utf8 (id); + *flags_p |= ECMA_STRING_FLAG_REHASH_NEEDED; break; } } } *size_p = size; + if (length_p != NULL) + { + *length_p = length; + } + if ((*flags_p & ECMA_STRING_FLAG_IS_ASCII) && length != size) { - *flags_p = (uint8_t) (*flags_p & ~ECMA_STRING_FLAG_IS_ASCII); + *flags_p = (uint8_t) (*flags_p & (uint8_t) ~ECMA_STRING_FLAG_IS_ASCII); } return result_p; @@ -1772,18 +1642,13 @@ inline lit_string_hash_t JERRY_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)) + if (ECMA_PROPERTY_GET_NAME_TYPE (property) == ECMA_DIRECT_STRING_PTR) { - case ECMA_DIRECT_STRING_PTR: - { - ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); - return prop_name_p->hash; - } - default: - { - return (lit_string_hash_t) prop_name_cp; - } + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); + return prop_name_p->u.hash; } + + return (lit_string_hash_t) prop_name_cp; } /* ecma_string_get_property_name_hash */ /** @@ -1857,21 +1722,28 @@ ecma_compare_ecma_strings_longpath (const ecma_string_t *string1_p, /**< ecma-st 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) + if (JERRY_LIKELY (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_HEAP_ASCII_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; + utf8_string1_p = ECMA_ASCII_STRING_GET_BUFFER (string1_p); + utf8_string1_size = ((ecma_ascii_string_t *) string1_p)->size; + utf8_string2_p = ECMA_ASCII_STRING_GET_BUFFER (string2_p); + utf8_string2_size = ((ecma_ascii_string_t *) string2_p)->size; + } + else if (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_HEAP_UTF8_STRING) + { + utf8_string1_p = ECMA_UTF8_STRING_GET_BUFFER (string1_p); + utf8_string1_size = ((ecma_utf8_string_t *) string1_p)->size; + utf8_string2_p = ECMA_UTF8_STRING_GET_BUFFER (string2_p); + utf8_string2_size = ((ecma_utf8_string_t *) string2_p)->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; + utf8_string1_p = ECMA_LONG_UTF8_STRING_GET_BUFFER (string1_p); + utf8_string1_size = ((ecma_long_utf8_string_t *) string1_p)->size; + utf8_string2_p = ECMA_LONG_UTF8_STRING_GET_BUFFER (string2_p); + utf8_string2_size = ((ecma_long_utf8_string_t *) string2_p)->size; } if (utf8_string1_size != utf8_string2_size) @@ -1906,7 +1778,7 @@ ecma_compare_ecma_strings (const ecma_string_t *string1_p, /**< ecma-string */ return false; } - if (string1_p->hash != string2_p->hash) + if (string1_p->u.hash != string2_p->u.hash) { return false; } @@ -1918,6 +1790,11 @@ ecma_compare_ecma_strings (const ecma_string_t *string1_p, /**< ecma-string */ return false; } + if (string1_container == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + return true; + } + #if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) if (string1_container == ECMA_STRING_CONTAINER_SYMBOL) { @@ -1925,10 +1802,13 @@ ecma_compare_ecma_strings (const ecma_string_t *string1_p, /**< ecma-string */ } #endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */ - if (string1_container >= ECMA_STRING_CONTAINER_UINT32_IN_DESC) +#if ENABLED (JERRY_ES2015_BUILTIN_MAP) + if (string1_container == ECMA_STRING_CONTAINER_MAP_KEY) { - return string1_p->u.common_uint32_field == string2_p->u.common_uint32_field; + return ecma_op_same_value_zero (((ecma_extended_string_t *) string1_p)->u.value, + ((ecma_extended_string_t *) string2_p)->u.value); } +#endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */ return ecma_compare_ecma_strings_longpath (string1_p, string2_p); } /* ecma_compare_ecma_strings */ @@ -1952,7 +1832,7 @@ ecma_compare_ecma_non_direct_strings (const ecma_string_t *string1_p, /**< ecma- return true; } - if (string1_p->hash != string2_p->hash) + if (string1_p->u.hash != string2_p->u.hash) { return false; } @@ -1964,18 +1844,26 @@ ecma_compare_ecma_non_direct_strings (const ecma_string_t *string1_p, /**< ecma- return false; } + if (string1_container == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + return true; + } + +#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) + if (string1_container == ECMA_STRING_CONTAINER_SYMBOL) + { + return false; + } +#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */ + #if ENABLED (JERRY_ES2015_BUILTIN_MAP) if (string1_container == ECMA_STRING_CONTAINER_MAP_KEY) { - return ecma_op_same_value_zero (string1_p->u.value, string2_p->u.value); + return ecma_op_same_value_zero (((ecma_extended_string_t *) string1_p)->u.value, + ((ecma_extended_string_t *) string2_p)->u.value); } #endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */ - 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 */ @@ -2076,11 +1964,11 @@ ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p, /**< ecma- /** * Special value to represent that no size is available. */ -#define ECMA_STRING_NO_ASCII_SIZE 0xffff +#define ECMA_STRING_NO_ASCII_SIZE 0xffffffff /** * Return the size of uint32 and magic strings. - * The length of these strings are equal to thier size. + * The length of these strings are equal to their size. * * @return number of characters in the string */ @@ -2120,6 +2008,10 @@ ecma_string_get_ascii_size (const ecma_string_t *string_p) /**< ecma-string */ { return ecma_string_get_uint32_size (string_p->u.uint32_number); } + else if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_HEAP_ASCII_STRING) + { + return ((ecma_ascii_string_t *) string_p)->size; + } return ECMA_STRING_NO_ASCII_SIZE; } /* ecma_string_get_ascii_size */ @@ -2149,24 +2041,21 @@ ecma_string_get_length (const ecma_string_t *string_p) /**< ecma-string */ lit_get_magic_string_ex_size (id)); } - switch (ECMA_STRING_GET_CONTAINER (string_p)) + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_HEAP_UTF8_STRING) { - case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: - { - return (ecma_length_t) (string_p->u.utf8_string.length); - } - case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: - { - return (ecma_length_t) (((ecma_long_string_t *) string_p)->long_utf8_string_length); - } - default: - { - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); - - return lit_utf8_string_length (lit_get_magic_string_ex_utf8 (string_p->u.magic_string_ex_id), - lit_get_magic_string_ex_size (string_p->u.magic_string_ex_id)); - } + return (ecma_length_t) (((ecma_utf8_string_t *) string_p)->length); } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING) + { + return (ecma_length_t) (((ecma_long_utf8_string_t *) string_p)->length); + } + + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + lit_magic_string_ex_id_t id = LIT_MAGIC_STRING__COUNT - string_p->u.magic_string_ex_id; + return lit_utf8_string_length (lit_get_magic_string_ex_utf8 (id), + lit_get_magic_string_ex_size (id)); } /* ecma_string_get_length */ /** @@ -2194,37 +2083,37 @@ ecma_string_get_utf8_length (const ecma_string_t *string_p) /**< ecma-string */ lit_get_magic_string_ex_size (id)); } - switch (ECMA_STRING_GET_CONTAINER (string_p)) + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_HEAP_UTF8_STRING) { - case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: - { - if (string_p->u.utf8_string.size == (lit_utf8_size_t) string_p->u.utf8_string.length) - { - return (ecma_length_t) (string_p->u.utf8_string.length); - } + ecma_utf8_string_t *utf8_string_p = (ecma_utf8_string_t *) string_p; - return lit_get_utf8_length_of_cesu8_string ((const lit_utf8_byte_t *) (string_p + 1), - (lit_utf8_size_t) string_p->u.utf8_string.size); - } - case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: + if (utf8_string_p->size == utf8_string_p->length) { - ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; - if (string_p->u.long_utf8_string_size == (lit_utf8_size_t) long_string_p->long_utf8_string_length) - { - return (ecma_length_t) (long_string_p->long_utf8_string_length); - } - - return lit_get_utf8_length_of_cesu8_string ((const lit_utf8_byte_t *) (long_string_p + 1), - (lit_utf8_size_t) string_p->u.long_utf8_string_size); + return (ecma_length_t) (utf8_string_p->length); } - default: - { - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); - return lit_get_utf8_length_of_cesu8_string (lit_get_magic_string_ex_utf8 (string_p->u.magic_string_ex_id), - lit_get_magic_string_ex_size (string_p->u.magic_string_ex_id)); - } + return lit_get_utf8_length_of_cesu8_string (ECMA_UTF8_STRING_GET_BUFFER (string_p), utf8_string_p->size); } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING) + { + ecma_long_utf8_string_t *long_utf8_string_p = (ecma_long_utf8_string_t *) string_p; + + if (long_utf8_string_p->size == long_utf8_string_p->length) + { + return (ecma_length_t) (long_utf8_string_p->length); + } + + return lit_get_utf8_length_of_cesu8_string (ECMA_LONG_UTF8_STRING_GET_BUFFER (string_p), + long_utf8_string_p->size); + } + + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + lit_magic_string_ex_id_t id = LIT_MAGIC_STRING__COUNT - string_p->u.magic_string_ex_id; + + return lit_get_utf8_length_of_cesu8_string (lit_get_magic_string_ex_utf8 (id), + lit_get_magic_string_ex_size (id)); } /* ecma_string_get_utf8_length */ /** @@ -2250,23 +2139,19 @@ ecma_string_get_size (const ecma_string_t *string_p) /**< ecma-string */ return lit_get_magic_string_ex_size ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p) - LIT_MAGIC_STRING__COUNT); } - switch (ECMA_STRING_GET_CONTAINER (string_p)) + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_HEAP_UTF8_STRING) { - case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: - { - return (lit_utf8_size_t) string_p->u.utf8_string.size; - } - case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: - { - return (lit_utf8_size_t) string_p->u.long_utf8_string_size; - } - default: - { - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); - - return lit_get_magic_string_ex_size (string_p->u.magic_string_ex_id); - } + return (lit_utf8_size_t) (((ecma_utf8_string_t *) string_p)->size); } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING) + { + return (lit_utf8_size_t) (((ecma_long_utf8_string_t *) string_p)->size); + } + + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + return lit_get_magic_string_ex_size (LIT_MAGIC_STRING__COUNT - string_p->u.magic_string_ex_id); } /* ecma_string_get_size */ /** @@ -2294,39 +2179,60 @@ ecma_string_get_utf8_size (const ecma_string_t *string_p) /**< ecma-string */ lit_get_magic_string_ex_size (id)); } - switch (ECMA_STRING_GET_CONTAINER (string_p)) + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_HEAP_UTF8_STRING) { - case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: - { - if (string_p->u.utf8_string.size == (lit_utf8_size_t) string_p->u.utf8_string.length) - { - return (lit_utf8_size_t) string_p->u.utf8_string.size; - } + ecma_utf8_string_t *utf8_string_p = (ecma_utf8_string_t *) string_p; - return lit_get_utf8_size_of_cesu8_string ((const lit_utf8_byte_t *) (string_p + 1), - (lit_utf8_size_t) string_p->u.utf8_string.size); - } - case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: + if (utf8_string_p->size == utf8_string_p->length) { - ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; - if (string_p->u.long_utf8_string_size == (lit_utf8_size_t) long_string_p->long_utf8_string_length) - { - return (lit_utf8_size_t) string_p->u.long_utf8_string_size; - } - - return lit_get_utf8_size_of_cesu8_string ((const lit_utf8_byte_t *) (string_p + 1), - (lit_utf8_size_t) string_p->u.long_utf8_string_size); + return utf8_string_p->size; } - default: - { - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); - return lit_get_utf8_size_of_cesu8_string (lit_get_magic_string_ex_utf8 (string_p->u.magic_string_ex_id), - lit_get_magic_string_ex_size (string_p->u.magic_string_ex_id)); - } + return lit_get_utf8_size_of_cesu8_string (ECMA_UTF8_STRING_GET_BUFFER (string_p), utf8_string_p->size); } + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING) + { + ecma_long_utf8_string_t *long_utf8_string_p = (ecma_long_utf8_string_t *) string_p; + + if (long_utf8_string_p->size == long_utf8_string_p->length) + { + return long_utf8_string_p->size; + } + + return lit_get_utf8_size_of_cesu8_string (ECMA_LONG_UTF8_STRING_GET_BUFFER (string_p), + long_utf8_string_p->size); + } + + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + lit_magic_string_ex_id_t id = LIT_MAGIC_STRING__COUNT - string_p->u.magic_string_ex_id; + return lit_get_utf8_size_of_cesu8_string (lit_get_magic_string_ex_utf8 (id), + lit_get_magic_string_ex_size (id)); } /* ecma_string_get_utf8_size */ +/** + * Get character from specified position in an external ecma-string. + * + * @return character value + */ +static ecma_char_t JERRY_ATTR_NOINLINE +ecma_external_string_get_char_at_pos (lit_utf8_size_t id, /**< id of the external magic string */ + ecma_length_t index) /**< index of character */ +{ + id -= LIT_MAGIC_STRING__COUNT; + const lit_utf8_byte_t *data_p = lit_get_magic_string_ex_utf8 (id); + lit_utf8_size_t size = lit_get_magic_string_ex_size (id); + lit_utf8_size_t length = lit_utf8_string_length (data_p, size); + + if (JERRY_LIKELY (size == length)) + { + return (ecma_char_t) data_p[index]; + } + + return lit_utf8_string_code_unit_at (data_p, size, index); +} /* ecma_external_string_get_char_at_pos */ + /** * Get character from specified position in the ecma-string. * @@ -2338,26 +2244,87 @@ ecma_string_get_char_at_pos (const ecma_string_t *string_p, /**< ecma-string */ { JERRY_ASSERT (index < ecma_string_get_length (string_p)); - lit_utf8_size_t buffer_size; - uint8_t flags = ECMA_STRING_FLAG_IS_ASCII; - const lit_utf8_byte_t *chars_p = ecma_string_get_chars (string_p, &buffer_size, &flags); + lit_utf8_byte_t uint32_to_string_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; - ecma_char_t ch; - if (flags & ECMA_STRING_FLAG_IS_ASCII) + if (ECMA_IS_DIRECT_STRING (string_p)) { - ch = chars_p[index]; - } - else - { - ch = lit_utf8_string_code_unit_at (chars_p, buffer_size, index); + switch (ECMA_GET_DIRECT_STRING_TYPE (string_p)) + { + case ECMA_DIRECT_STRING_MAGIC: + { + uint32_t id = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + + if (JERRY_LIKELY (id < LIT_MAGIC_STRING__COUNT)) + { + /* All magic strings must be ascii strings. */ + const lit_utf8_byte_t *data_p = lit_get_magic_string_utf8 (id); + + return (ecma_char_t) data_p[index]; + } + + return ecma_external_string_get_char_at_pos (id, index); + } + default: + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_UINT); + uint32_t uint32_number = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + + ecma_uint32_to_utf8_string (uint32_number, uint32_to_string_buffer, ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + + return (ecma_char_t) uint32_to_string_buffer[index]; + } + } } - if (flags & ECMA_STRING_FLAG_MUST_BE_FREED) - { - jmem_heap_free_block ((void *) chars_p, buffer_size); - } + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); - return ch; + switch (ECMA_STRING_GET_CONTAINER (string_p)) + { + case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + { + ecma_utf8_string_t *utf8_string_desc_p = (ecma_utf8_string_t *) string_p; + lit_utf8_size_t size = utf8_string_desc_p->size; + const lit_utf8_byte_t *data_p = ECMA_UTF8_STRING_GET_BUFFER (string_p); + + if (JERRY_LIKELY (size == utf8_string_desc_p->length)) + { + return (ecma_char_t) data_p[index]; + } + + return lit_utf8_string_code_unit_at (data_p, size, index); + } + case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: + { + ecma_long_utf8_string_t *long_utf8_string_desc_p = (ecma_long_utf8_string_t *) string_p; + lit_utf8_size_t size = long_utf8_string_desc_p->size; + const lit_utf8_byte_t *data_p = ECMA_LONG_UTF8_STRING_GET_BUFFER (string_p); + + if (JERRY_LIKELY (size == long_utf8_string_desc_p->length)) + { + return (ecma_char_t) data_p[index]; + } + + return lit_utf8_string_code_unit_at (data_p, size, index); + } + case ECMA_STRING_CONTAINER_HEAP_ASCII_STRING: + { + const lit_utf8_byte_t *data_p = ECMA_ASCII_STRING_GET_BUFFER (string_p); + return (ecma_char_t) data_p[index]; + } + case ECMA_STRING_CONTAINER_UINT32_IN_DESC: + { + ecma_uint32_to_utf8_string (string_p->u.uint32_number, + uint32_to_string_buffer, + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + + return (ecma_char_t) uint32_to_string_buffer[index]; + } + default: + { + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + return ecma_external_string_get_char_at_pos (string_p->u.magic_string_ex_id, index); + } + } } /* ecma_string_get_char_at_pos */ /** @@ -2391,12 +2358,12 @@ ecma_get_string_magic (const ecma_string_t *string_p) /**< ecma-string */ inline lit_string_hash_t JERRY_ATTR_ALWAYS_INLINE ecma_string_hash (const ecma_string_t *string_p) /**< ecma-string to calculate hash for */ { - if (!ECMA_IS_DIRECT_STRING (string_p)) + if (ECMA_IS_DIRECT_STRING (string_p)) { - return (string_p->hash); + return (lit_string_hash_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); } - return (lit_string_hash_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + return (lit_string_hash_t) string_p->u.hash; } /* ecma_string_hash */ /** @@ -2512,7 +2479,7 @@ ecma_string_trim (const ecma_string_t *string_p) /**< pointer to an ecma string lit_utf8_size_t utf8_str_size; uint8_t flags = ECMA_STRING_FLAG_IS_ASCII; - const lit_utf8_byte_t *utf8_str_p = ecma_string_get_chars (string_p, &utf8_str_size, &flags); + const lit_utf8_byte_t *utf8_str_p = ecma_string_get_chars (string_p, &utf8_str_size, NULL, NULL, &flags); if (utf8_str_size > 0) { @@ -2540,7 +2507,7 @@ ecma_string_trim (const ecma_string_t *string_p) /**< pointer to an ecma string ecma_stringbuilder_t ecma_stringbuilder_create (void) { - const lit_utf8_size_t initial_size = sizeof (ecma_string_t); + const lit_utf8_size_t initial_size = sizeof (ecma_ascii_string_t); ecma_stringbuilder_header_t *header_p = (ecma_stringbuilder_header_t *) jmem_heap_alloc_block (initial_size); header_p->current_size = initial_size; #if ENABLED (JERRY_MEM_STATS) @@ -2560,7 +2527,7 @@ ecma_stringbuilder_t ecma_stringbuilder_create_from (ecma_string_t *string_p) /**< ecma string */ { const lit_utf8_size_t string_size = ecma_string_get_size (string_p); - const lit_utf8_size_t initial_size = string_size + (lit_utf8_size_t) sizeof (ecma_string_t); + const lit_utf8_size_t initial_size = string_size + (lit_utf8_size_t) sizeof (ecma_ascii_string_t); ecma_stringbuilder_header_t *header_p = (ecma_stringbuilder_header_t *) jmem_heap_alloc_block (initial_size); header_p->current_size = initial_size; @@ -2674,6 +2641,7 @@ ecma_stringbuilder_finalize (ecma_stringbuilder_t *builder_p) /**< string builde lit_utf8_byte_t *string_begin_p = ECMA_STRINGBUILDER_STRING_PTR (header_p); ecma_string_t *string_p = ecma_find_special_string (string_begin_p, string_size); + if (JERRY_UNLIKELY (string_p != NULL)) { ecma_stringbuilder_destroy (builder_p); @@ -2684,36 +2652,55 @@ ecma_stringbuilder_finalize (ecma_stringbuilder_t *builder_p) /**< string builde builder_p->header_p = NULL; #endif - string_p = (ecma_string_t *) header_p; + size_t container_size = sizeof (ecma_utf8_string_t); const lit_string_hash_t hash = lit_utf8_string_calc_hash (string_begin_p, string_size); const lit_utf8_size_t length = lit_utf8_string_length (string_begin_p, string_size); - if (JERRY_LIKELY (string_size < UINT16_MAX)) + if (JERRY_LIKELY (string_size <= UINT16_MAX)) { - string_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_UTF8_STRING | ECMA_STRING_REF_ONE; - string_p->u.utf8_string.size = (uint16_t) string_size; - string_p->u.utf8_string.length = (uint16_t) length; - string_p->hash = hash; + if (JERRY_LIKELY (length == string_size)) + { + ecma_ascii_string_t *ascii_string_p = (ecma_ascii_string_t *) header_p; + ascii_string_p->header.refs_and_container = ECMA_STRING_CONTAINER_HEAP_ASCII_STRING | ECMA_STRING_REF_ONE; + ascii_string_p->header.u.hash = hash; + ascii_string_p->size = (uint16_t) string_size; - return string_p; + return (ecma_string_t *) ascii_string_p; + } + } + else + { + container_size = sizeof (ecma_long_utf8_string_t); } - const size_t long_string_size = string_size + sizeof (ecma_long_string_t); - header_p = jmem_heap_realloc_block (header_p, header_p->current_size, long_string_size); - memmove (((ecma_long_string_t *) header_p) + 1, string_begin_p, string_size); + const size_t utf8_string_size = string_size + container_size; + header_p = jmem_heap_realloc_block (header_p, header_p->current_size, utf8_string_size); + memmove (((lit_utf8_byte_t *) header_p + container_size), string_begin_p, string_size); #if ENABLED (JERRY_MEM_STATS) - jmem_stats_allocate_string_bytes (sizeof (ecma_long_string_t) - sizeof (ecma_string_t)); + jmem_stats_allocate_string_bytes (container_size - sizeof (ecma_ascii_string_t)); #endif /* ENABLED (JERRY_MEM_STATS) */ - string_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING | ECMA_STRING_REF_ONE; - string_p->u.long_utf8_string_size = string_size; - string_p->hash = hash; + if (JERRY_LIKELY (string_size <= UINT16_MAX)) + { + ecma_utf8_string_t *utf8_string_p = (ecma_utf8_string_t *) header_p; - ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; - long_string_p->long_utf8_string_length = length; + utf8_string_p->header.refs_and_container = ECMA_STRING_CONTAINER_HEAP_UTF8_STRING | ECMA_STRING_REF_ONE; + utf8_string_p->header.u.hash = hash; + utf8_string_p->size = (uint16_t) string_size; + utf8_string_p->length = (uint16_t) length; - return string_p; + return (ecma_string_t *) utf8_string_p; + } + + ecma_long_utf8_string_t *long_utf8_string_p = (ecma_long_utf8_string_t *) header_p; + + long_utf8_string_p->header.refs_and_container = ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING | ECMA_STRING_REF_ONE; + long_utf8_string_p->header.u.hash = hash; + long_utf8_string_p->size = string_size; + long_utf8_string_p->length = length; + + return (ecma_string_t *) long_utf8_string_p; } /* ecma_stringbuilder_finalize */ /** diff --git a/jerry-core/ecma/base/ecma-helpers-value.c b/jerry-core/ecma/base/ecma-helpers-value.c index 9c91e5408..679b55c37 100644 --- a/jerry-core/ecma/base/ecma-helpers-value.c +++ b/jerry-core/ecma/base/ecma-helpers-value.c @@ -459,6 +459,17 @@ ecma_create_float_number (ecma_number_t ecma_number) /**< value of the float num return ecma_pointer_to_ecma_value (ecma_num_p) | ECMA_TYPE_FLOAT; } /* ecma_create_float_number */ +/** + * Encode float number without checks. + * + * @return ecma-value + */ +ecma_value_t +ecma_make_float_value (ecma_number_t *ecma_num_p) /**< pointer to the float number */ +{ + return ecma_pointer_to_ecma_value (ecma_num_p) | ECMA_TYPE_FLOAT; +} /* ecma_make_float_value */ + /** * Create a new NaN value. * @@ -696,6 +707,19 @@ ecma_get_float_from_value (ecma_value_t value) /**< ecma value */ return *(ecma_number_t *) ecma_get_pointer_from_ecma_value (value); } /* ecma_get_float_from_value */ +/** + * Get floating point value pointer from an ecma value + * + * @return floating point value + */ +inline ecma_number_t * JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE +ecma_get_pointer_from_float_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_FLOAT); + + return (ecma_number_t *) ecma_get_pointer_from_ecma_value (value); +} /* ecma_get_pointer_from_float_value */ + /** * Get floating point value from an ecma value * diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 40d7dd35d..039fe92b4 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -50,11 +50,17 @@ */ #define ECMA_SET_POINTER(field, non_compressed_pointer) JMEM_CP_SET_POINTER (field, non_compressed_pointer) +/** + * Status flags for ecma_string_get_chars function + */ typedef enum { - ECMA_STRING_FLAG_EMPTY = 0, - ECMA_STRING_FLAG_IS_ASCII, - ECMA_STRING_FLAG_MUST_BE_FREED + ECMA_STRING_FLAG_EMPTY = 0, /**< No options are provided. */ + ECMA_STRING_FLAG_IS_ASCII = (1 << 0), /**< The string contains only ASCII characters. */ + ECMA_STRING_FLAG_REHASH_NEEDED = (1 << 1), /**< The hash of the string must be recalculated. + * For more details see ecma_append_chars_to_string */ + ECMA_STRING_FLAG_IS_UINT32 = (1 << 2), /**< The string repesents an UINT32 number */ + ECMA_STRING_FLAG_MUST_BE_FREED = (1 << 3), /**< The returned buffer must be freed */ } ecma_string_flag_t; /** @@ -65,7 +71,11 @@ typedef enum utf8_str_size) /**< [out] output buffer size */ \ lit_utf8_size_t utf8_str_size; \ uint8_t utf8_ptr ## flags = ECMA_STRING_FLAG_EMPTY; \ - const lit_utf8_byte_t *utf8_ptr = ecma_string_get_chars (ecma_str_ptr, &utf8_str_size, &utf8_ptr ## flags); + const lit_utf8_byte_t *utf8_ptr = ecma_string_get_chars (ecma_str_ptr, \ + &utf8_str_size, \ + NULL, \ + NULL, \ + &utf8_ptr ## flags); /** * Free the cesu-8 string buffer allocated by 'ECMA_STRING_TO_UTF8_STRING' @@ -181,6 +191,7 @@ void ecma_check_value_type_is_spec_defined (ecma_value_t value); ecma_value_t JERRY_ATTR_CONST ecma_make_boolean_value (bool boolean_value); ecma_value_t JERRY_ATTR_CONST ecma_make_integer_value (ecma_integer_value_t integer_value); ecma_value_t ecma_make_nan_value (void); +ecma_value_t ecma_make_float_value (ecma_number_t *ecma_num_p); ecma_value_t ecma_make_number_value (ecma_number_t ecma_number); ecma_value_t ecma_make_int32_value (int32_t int32_number); ecma_value_t ecma_make_uint32_value (uint32_t uint32_number); @@ -195,6 +206,7 @@ ecma_value_t JERRY_ATTR_PURE ecma_make_error_reference_value (const ecma_error_r ecma_value_t JERRY_ATTR_PURE ecma_make_pointer_value (const void *any_p); ecma_integer_value_t JERRY_ATTR_CONST ecma_get_integer_from_value (ecma_value_t value); ecma_number_t JERRY_ATTR_PURE ecma_get_float_from_value (ecma_value_t value); +ecma_number_t * ecma_get_pointer_from_float_value (ecma_value_t value); ecma_number_t JERRY_ATTR_PURE ecma_get_number_from_value (ecma_value_t value); ecma_string_t JERRY_ATTR_PURE *ecma_get_string_from_value (ecma_value_t value); #if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) @@ -246,6 +258,7 @@ ecma_string_t *ecma_concat_ecma_strings (ecma_string_t *string1_p, ecma_string_t ecma_string_t *ecma_append_magic_string_to_string (ecma_string_t *string1_p, lit_magic_string_id_t string2_id); void ecma_ref_ecma_string (ecma_string_t *string_p); void ecma_deref_ecma_string (ecma_string_t *string_p); +void ecma_destroy_ecma_string (ecma_string_t *string_p); ecma_number_t ecma_string_to_number (const ecma_string_t *str_p); uint32_t ecma_string_get_array_index (const ecma_string_t *str_p); @@ -271,7 +284,11 @@ ecma_substring_copy_to_utf8_buffer (const ecma_string_t *string_desc_p, lit_utf8_size_t buffer_size); void ecma_string_to_utf8_bytes (const ecma_string_t *string_desc_p, lit_utf8_byte_t *buffer_p, lit_utf8_size_t buffer_size); -const lit_utf8_byte_t *ecma_string_get_chars (const ecma_string_t *string_p, lit_utf8_size_t *size_p, uint8_t *flags_p); +const lit_utf8_byte_t *ecma_string_get_chars (const ecma_string_t *string_p, + lit_utf8_size_t *size_p, + lit_utf8_size_t *length_p, + lit_utf8_byte_t *uint32_buff_p, + uint8_t *flags_p); bool ecma_compare_ecma_string_to_magic_id (const ecma_string_t *string_p, lit_magic_string_id_t id); bool ecma_string_is_empty (const ecma_string_t *string_p); bool ecma_string_is_length (const ecma_string_t *string_p); diff --git a/jerry-core/ecma/base/ecma-literal-storage.c b/jerry-core/ecma/base/ecma-literal-storage.c index d0bae5cb7..bb34b7816 100644 --- a/jerry-core/ecma/base/ecma-literal-storage.c +++ b/jerry-core/ecma/base/ecma-literal-storage.c @@ -25,14 +25,46 @@ * @{ */ +#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) +/** + * Free symbol list + */ +static void +ecma_free_symbol_list (jmem_cpointer_t symbol_list_cp) /**< symbol list */ +{ + while (symbol_list_cp != JMEM_CP_NULL) + { + ecma_lit_storage_item_t *symbol_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, symbol_list_cp); + + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + if (symbol_list_p->values[i] != JMEM_CP_NULL) + { + ecma_string_t *string_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, + symbol_list_p->values[i]); + + JERRY_ASSERT (ECMA_STRING_IS_REF_EQUALS_TO_ONE (string_p)); + ecma_deref_ecma_string (string_p); + } + } + + jmem_cpointer_t next_item_cp = symbol_list_p->next_cp; + jmem_pools_free (symbol_list_p, sizeof (ecma_lit_storage_item_t)); + symbol_list_cp = next_item_cp; + } +} /* ecma_free_symbol_list */ +#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */ + /** * Free string list */ static void -ecma_free_string_list (ecma_lit_storage_item_t *string_list_p) /**< string list */ +ecma_free_string_list (jmem_cpointer_t string_list_cp) /**< string list */ { - while (string_list_p != NULL) + while (string_list_cp != JMEM_CP_NULL) { + ecma_lit_storage_item_t *string_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, string_list_cp); + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) { if (string_list_p->values[i] != JMEM_CP_NULL) @@ -41,16 +73,42 @@ ecma_free_string_list (ecma_lit_storage_item_t *string_list_p) /**< string list string_list_p->values[i]); JERRY_ASSERT (ECMA_STRING_IS_REF_EQUALS_TO_ONE (string_p)); - ecma_deref_ecma_string (string_p); + ecma_destroy_ecma_string (string_p); } } - ecma_lit_storage_item_t *prev_item = string_list_p; - string_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, string_list_p->next_cp); - jmem_pools_free (prev_item, sizeof (ecma_lit_storage_item_t)); + jmem_cpointer_t next_item_cp = string_list_p->next_cp; + jmem_pools_free (string_list_p, sizeof (ecma_lit_storage_item_t)); + string_list_cp = next_item_cp; } } /* ecma_free_string_list */ +/** + * Free number list + */ +static void +ecma_free_number_list (jmem_cpointer_t number_list_cp) /**< string list */ +{ + while (number_list_cp != JMEM_CP_NULL) + { + ecma_number_storage_item_t *number_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_number_storage_item_t, + number_list_cp); + + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + if (number_list_p->values[i] != JMEM_CP_NULL) + { + ecma_number_t *num_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_number_t, number_list_p->values[i]); + ecma_dealloc_number (num_p); + } + } + + jmem_cpointer_t next_item_cp = number_list_p->next_cp; + jmem_pools_free (number_list_p, sizeof (ecma_number_storage_item_t)); + number_list_cp = next_item_cp; + } +} /* ecma_free_number_list */ + /** * Finalize literal storage */ @@ -58,10 +116,10 @@ void ecma_finalize_lit_storage (void) { #if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) - ecma_free_string_list (JERRY_CONTEXT (symbol_list_first_p)); + ecma_free_symbol_list (JERRY_CONTEXT (symbol_list_first_cp)); #endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */ - ecma_free_string_list (JERRY_CONTEXT (string_list_first_p)); - ecma_free_string_list (JERRY_CONTEXT (number_list_first_p)); + ecma_free_string_list (JERRY_CONTEXT (string_list_first_cp)); + ecma_free_number_list (JERRY_CONTEXT (number_list_first_cp)); } /* ecma_finalize_lit_storage */ /** @@ -80,11 +138,13 @@ ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p, /**< string return ecma_make_string_value (string_p); } - ecma_lit_storage_item_t *string_list_p = JERRY_CONTEXT (string_list_first_p); + jmem_cpointer_t string_list_cp = JERRY_CONTEXT (string_list_first_cp); jmem_cpointer_t *empty_cpointer_p = NULL; - while (string_list_p != NULL) + while (string_list_cp != JMEM_CP_NULL) { + ecma_lit_storage_item_t *string_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, string_list_cp); + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) { if (string_list_p->values[i] == JMEM_CP_NULL) @@ -108,9 +168,10 @@ ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p, /**< string } } - string_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, string_list_p->next_cp); + string_list_cp = string_list_p->next_cp; } + ECMA_SET_STRING_AS_STATIC (string_p); jmem_cpointer_t result; JMEM_CP_SET_NON_NULL_POINTER (result, string_p); @@ -129,8 +190,8 @@ ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p, /**< string new_item_p->values[i] = JMEM_CP_NULL; } - JMEM_CP_SET_POINTER (new_item_p->next_cp, JERRY_CONTEXT (string_list_first_p)); - JERRY_CONTEXT (string_list_first_p) = new_item_p; + new_item_p->next_cp = JERRY_CONTEXT (string_list_first_cp); + JMEM_CP_SET_NON_NULL_POINTER (JERRY_CONTEXT (string_list_first_cp), new_item_p); return ecma_make_string_value (string_p); } /* ecma_find_or_create_literal_string */ @@ -152,11 +213,14 @@ ecma_find_or_create_literal_number (ecma_number_t number_arg) /**< number to be JERRY_ASSERT (ecma_is_value_float_number (num)); - ecma_lit_storage_item_t *number_list_p = JERRY_CONTEXT (number_list_first_p); + jmem_cpointer_t number_list_cp = JERRY_CONTEXT (number_list_first_cp); jmem_cpointer_t *empty_cpointer_p = NULL; - while (number_list_p != NULL) + while (number_list_cp != JMEM_CP_NULL) { + ecma_number_storage_item_t *number_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_number_storage_item_t, + number_list_cp); + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) { if (number_list_p->values[i] == JMEM_CP_NULL) @@ -168,29 +232,24 @@ ecma_find_or_create_literal_number (ecma_number_t number_arg) /**< number to be } else { - ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, - number_list_p->values[i]); + ecma_number_t *number_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_number_t, + number_list_p->values[i]); - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (value_p) == ECMA_STRING_LITERAL_NUMBER); - JERRY_ASSERT (ecma_is_value_float_number (value_p->u.lit_number)); - - if (ecma_get_float_from_value (value_p->u.lit_number) == number_arg) + if (*number_p == number_arg) { ecma_free_value (num); - return value_p->u.lit_number; + return ecma_make_float_value (number_p); } } } - number_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, number_list_p->next_cp); + number_list_cp = number_list_p->next_cp; } - ecma_string_t *string_p = ecma_alloc_string (); - string_p->refs_and_container = ECMA_STRING_REF_ONE | ECMA_STRING_LITERAL_NUMBER; - string_p->u.lit_number = num; + ecma_number_t *num_p = ecma_get_pointer_from_float_value (num); jmem_cpointer_t result; - JMEM_CP_SET_NON_NULL_POINTER (result, string_p); + JMEM_CP_SET_NON_NULL_POINTER (result, num_p); if (empty_cpointer_p != NULL) { @@ -198,8 +257,8 @@ ecma_find_or_create_literal_number (ecma_number_t number_arg) /**< number to be return num; } - ecma_lit_storage_item_t *new_item_p; - new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t)); + ecma_number_storage_item_t *new_item_p; + new_item_p = (ecma_number_storage_item_t *) jmem_pools_alloc (sizeof (ecma_number_storage_item_t)); new_item_p->values[0] = result; for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) @@ -207,8 +266,8 @@ ecma_find_or_create_literal_number (ecma_number_t number_arg) /**< number to be new_item_p->values[i] = JMEM_CP_NULL; } - JMEM_CP_SET_POINTER (new_item_p->next_cp, JERRY_CONTEXT (number_list_first_p)); - JERRY_CONTEXT (number_list_first_p) = new_item_p; + new_item_p->next_cp = JERRY_CONTEXT (number_list_first_cp); + JMEM_CP_SET_NON_NULL_POINTER (JERRY_CONTEXT (number_list_first_cp), new_item_p); return num; } /* ecma_find_or_create_literal_number */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.c b/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.c index c4fc01e53..68c28cf81 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.c @@ -102,11 +102,14 @@ ecma_builtin_symbol_for_helper (ecma_value_t value_to_find) /**< symbol or ecma- string_p = ecma_get_symbol_from_value (value_to_find); } - ecma_lit_storage_item_t *symbol_list_p = JERRY_CONTEXT (symbol_list_first_p); + jmem_cpointer_t symbol_list_cp = JERRY_CONTEXT (symbol_list_first_cp); jmem_cpointer_t *empty_cpointer_p = NULL; - while (symbol_list_p != NULL) + while (symbol_list_cp != JMEM_CP_NULL) { + ecma_lit_storage_item_t *symbol_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t, + symbol_list_cp); + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) { if (symbol_list_p->values[i] != JMEM_CP_NULL) @@ -145,7 +148,7 @@ ecma_builtin_symbol_for_helper (ecma_value_t value_to_find) /**< symbol or ecma- } } - symbol_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, symbol_list_p->next_cp); + symbol_list_cp = symbol_list_p->next_cp; } if (!is_for) @@ -175,8 +178,8 @@ ecma_builtin_symbol_for_helper (ecma_value_t value_to_find) /**< symbol or ecma- new_item_p->values[i] = JMEM_CP_NULL; } - JMEM_CP_SET_POINTER (new_item_p->next_cp, JERRY_CONTEXT (symbol_list_first_p)); - JERRY_CONTEXT (symbol_list_first_p) = new_item_p; + new_item_p->next_cp = JERRY_CONTEXT (symbol_list_first_cp); + JMEM_CP_SET_NON_NULL_POINTER (JERRY_CONTEXT (symbol_list_first_cp), new_item_p); return ecma_copy_value (ecma_make_symbol_value (new_symbol_p)); } /* ecma_builtin_symbol_for_helper */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.c b/jerry-core/ecma/builtin-objects/ecma-builtins.c index b0af8931f..ce76638d0 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.c @@ -659,9 +659,9 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * #if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (string_p))) { - if (string_p->hash & ECMA_GLOBAL_SYMBOL_FLAG) + if (string_p->u.hash & ECMA_GLOBAL_SYMBOL_FLAG) { - magic_string_id = (string_p->hash >> ECMA_GLOBAL_SYMBOL_SHIFT); + magic_string_id = (string_p->u.hash >> ECMA_GLOBAL_SYMBOL_SHIFT); } } #endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */ @@ -802,7 +802,7 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * ecma_string_t *symbol_p = ecma_new_symbol_from_descriptor_string (symbol_desc_value); lit_magic_string_id_t symbol_id = (lit_magic_string_id_t) curr_property_p->value; - symbol_p->hash = (uint16_t) ((symbol_id << ECMA_GLOBAL_SYMBOL_SHIFT) | ECMA_GLOBAL_SYMBOL_FLAG); + symbol_p->u.hash = (uint16_t) ((symbol_id << ECMA_GLOBAL_SYMBOL_SHIFT) | ECMA_GLOBAL_SYMBOL_FLAG); value = ecma_make_symbol_value (symbol_p); break; diff --git a/jerry-core/ecma/operations/ecma-container-object.c b/jerry-core/ecma/operations/ecma-container-object.c index 83681b099..6c8b4a270 100644 --- a/jerry-core/ecma/operations/ecma-container-object.c +++ b/jerry-core/ecma/operations/ecma-container-object.c @@ -476,7 +476,7 @@ ecma_op_container_foreach (ecma_value_t this_arg, /**< this argument */ } else if (ecma_prop_name_is_map_key (prop_name_p)) { - key_arg = prop_name_p->u.value; + key_arg = ((ecma_extended_string_t *) prop_name_p)->u.value; } else { @@ -730,7 +730,7 @@ ecma_op_container_iterator_next (ecma_value_t this_val, /**< this argument */ } else if (ecma_prop_name_is_map_key (prop_name_p)) { - key_arg = prop_name_p->u.value; + key_arg = ((ecma_extended_string_t *) prop_name_p)->u.value; } else { diff --git a/jerry-core/ecma/operations/ecma-symbol-object.c b/jerry-core/ecma/operations/ecma-symbol-object.c index 2e1d57a30..818cdf951 100644 --- a/jerry-core/ecma/operations/ecma-symbol-object.c +++ b/jerry-core/ecma/operations/ecma-symbol-object.c @@ -111,7 +111,7 @@ ecma_get_symbol_description (ecma_string_t *symbol_p) /**< ecma-symbol */ JERRY_ASSERT (symbol_p != NULL); JERRY_ASSERT (ecma_prop_name_is_symbol (symbol_p)); - return ecma_get_string_from_value (symbol_p->u.symbol_descriptor); + return ecma_get_string_from_value (((ecma_extended_string_t *) symbol_p)->u.symbol_descriptor); } /* ecma_get_symbol_description */ /** diff --git a/jerry-core/jcontext/jcontext.h b/jerry-core/jcontext/jcontext.h index dbbc03885..4d5feb6c5 100644 --- a/jerry-core/jcontext/jcontext.h +++ b/jerry-core/jcontext/jcontext.h @@ -136,11 +136,11 @@ struct jerry_context_t #endif /* ENABLED (JERRY_CPOINTER_32_BIT) */ const lit_utf8_byte_t * const *lit_magic_string_ex_array; /**< array of external magic strings */ const lit_utf8_size_t *lit_magic_string_ex_sizes; /**< external magic string lengths */ - ecma_lit_storage_item_t *string_list_first_p; /**< first item of the literal string list */ + jmem_cpointer_t string_list_first_cp; /**< first item of the literal string list */ #if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) - ecma_lit_storage_item_t *symbol_list_first_p; /**< first item of the global symbol list */ + jmem_cpointer_t symbol_list_first_cp; /**< first item of the global symbol list */ #endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */ - ecma_lit_storage_item_t *number_list_first_p; /**< first item of the literal number list */ + jmem_cpointer_t number_list_first_cp; /**< first item of the literal number list */ jmem_cpointer_t ecma_global_lex_env_cp; /**< global lexical environment */ #if ENABLED (JERRY_ES2015_MODULE_SYSTEM) diff --git a/jerry-core/lit/lit-globals.h b/jerry-core/lit/lit-globals.h index 8cfe6aeb1..9edefb224 100644 --- a/jerry-core/lit/lit-globals.h +++ b/jerry-core/lit/lit-globals.h @@ -121,16 +121,11 @@ typedef uint32_t lit_code_point_t; /** * ECMA string hash */ -typedef uint16_t lit_string_hash_t; +typedef uint32_t lit_string_hash_t; /** - * Maximum value of ECMA string hash + 1 - * - * Note: - * On ARM, this constant can be encoded as an immediate value - * while 0xffffu cannot be. Hence using this constant reduces - * binary size and improves performance. + * Maximum value of ECMA string hash */ -#define LIT_STRING_HASH_LIMIT 0x10000u +#define LIT_STRING_HASH_LIMIT UINT32_MAX #endif /* !LIT_GLOBALS_H */ diff --git a/jerry-core/parser/js/js-parser-module.c b/jerry-core/parser/js/js-parser-module.c index 026906f72..a616ee63f 100644 --- a/jerry-core/parser/js/js-parser-module.c +++ b/jerry-core/parser/js/js-parser-module.c @@ -275,6 +275,8 @@ parser_module_context_init (void) const lit_utf8_byte_t *path_str_chars_p = ecma_string_get_chars (path_str_p, &path_str_size, + NULL, + NULL, &flags); ecma_string_t *path_p = ecma_module_create_normalized_path (path_str_chars_p,