From c831912ae5c4999a8afafe6b9e2d3c775534b212 Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Wed, 13 Aug 2014 19:21:21 +0400 Subject: [PATCH] Replacing ecma_array_first_chunk_t with ecma_string_t for ecma-strings. --- src/libcoreint/opcodes.c | 2 +- src/libecmaobjects/ecma-alloc.c | 47 ++- src/libecmaobjects/ecma-alloc.h | 14 +- src/libecmaobjects/ecma-globals.h | 4 +- src/libecmaobjects/ecma-helpers-string.c | 369 +++++++++++++++-------- src/libecmaobjects/ecma-helpers-value.c | 12 +- src/libecmaobjects/ecma-helpers.c | 10 +- src/libecmaobjects/ecma-helpers.h | 25 +- src/libecmaoperations/ecma-comparison.c | 6 +- src/libecmaoperations/ecma-conversion.c | 8 +- 10 files changed, 318 insertions(+), 179 deletions(-) diff --git a/src/libcoreint/opcodes.c b/src/libcoreint/opcodes.c index 05f1f55b0..681c5700e 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -662,7 +662,7 @@ opfunc_assignment (OPCODE opdata, /**< operation data */ case OPCODE_ARG_TYPE_STRING: { string_literal_copy str_value; - ecma_array_first_chunk_t *ecma_string_p; + ecma_string_t *ecma_string_p; init_string_literal_copy (src_val_descr, &str_value); ecma_string_p = ecma_new_ecma_string (str_value.str_p); diff --git a/src/libecmaobjects/ecma-alloc.c b/src/libecmaobjects/ecma-alloc.c index 86fbb135e..614eff018 100644 --- a/src/libecmaobjects/ecma-alloc.c +++ b/src/libecmaobjects/ecma-alloc.c @@ -13,25 +13,6 @@ * limitations under the License. */ -/** \addtogroup ecma ---TODO--- - * @{ - * - * \addtogroup ecmaalloc Routines for allocation/freeing memory for ECMA data types - * @{ - */ - -/** - * Implementation of routins for allocation/freeing memory for ECMA data types. - * - * All allocation routines from this module have the same structure: - * 1. Try to allocate memory. - * 2. If allocation was successful, return pointer to the allocated block. - * 3. Run garbage collection. - * 4. Try to allocate memory. - * 5. If allocation was successful, return pointer to the allocated block; - * else - shutdown engine. - */ - #include "globals.h" #include "ecma-alloc.h" #include "ecma-globals.h" @@ -50,16 +31,32 @@ JERRY_STATIC_ASSERT(sizeof (ecma_array_non_first_chunk_t) == sizeof (uint64_t)); JERRY_STATIC_ASSERT(sizeof (ecma_string_t) == sizeof (uint64_t)); JERRY_STATIC_ASSERT(sizeof (ecma_completion_value_t) == sizeof (uint32_t)); +/** \addtogroup ecma ---TODO--- + * @{ + * + * \addtogroup ecmaalloc Routines for allocation/freeing memory for ECMA data types + * @{ + */ + +/** + * Implementation of routines for allocation/freeing memory for ECMA data types. + * + * All allocation routines from this module have the same structure: + * 1. Try to allocate memory. + * 2. If allocation was successful, return pointer to the allocated block. + * 3. Run garbage collection. + * 4. Try to allocate memory. + * 5. If allocation was successful, return pointer to the allocated block; + * else - shutdown engine. + */ + /** * Template of an allocation routine. - * - * FIXME: Run GC only if allocation failed. */ #define ALLOC(ecma_type) ecma_ ## ecma_type ## _t * \ ecma_alloc_ ## ecma_type (void) \ { \ - ecma_ ## ecma_type ## _t *p ## ecma_type = (ecma_ ## ecma_type ## _t *) \ - mem_pools_alloc (); \ + ecma_ ## ecma_type ## _t *p ## ecma_type = (ecma_ ## ecma_type ## _t *) mem_pools_alloc (); \ \ if (likely (p ## ecma_type != NULL)) \ { \ @@ -72,8 +69,7 @@ JERRY_STATIC_ASSERT(sizeof (ecma_completion_value_t) == sizeof (uint32_t)); { \ ecma_gc_run (gen_id); \ \ - p ## ecma_type = (ecma_ ## ecma_type ## _t *) \ - mem_pools_alloc (); \ + p ## ecma_type = (ecma_ ## ecma_type ## _t *) mem_pools_alloc (); \ \ if (likely (p ## ecma_type != NULL)) \ { \ @@ -104,6 +100,7 @@ DECLARE_ROUTINES_FOR (property) DECLARE_ROUTINES_FOR (number) DECLARE_ROUTINES_FOR (array_first_chunk) DECLARE_ROUTINES_FOR (array_non_first_chunk) +DECLARE_ROUTINES_FOR (string) /** * @} diff --git a/src/libecmaobjects/ecma-alloc.h b/src/libecmaobjects/ecma-alloc.h index 1c23af9b4..9aa23fc8a 100644 --- a/src/libecmaobjects/ecma-alloc.h +++ b/src/libecmaobjects/ecma-alloc.h @@ -83,7 +83,19 @@ extern ecma_array_non_first_chunk_t *ecma_alloc_array_non_first_chunk (void); /** * Dealloc memory from non-first chunk of an ecma-array */ -extern void ecma_dealloc_array_non_first_chunk (ecma_array_non_first_chunk_t *number_p); +extern void ecma_dealloc_array_non_first_chunk (ecma_array_non_first_chunk_t *non_first_chunk_p); + +/** + * Allocate memory for ecma-string descriptor + * + * @return pointer to allocated memory + */ +extern ecma_string_t *ecma_alloc_string (void); + +/** + * Dealloc memory from ecma-string descriptor + */ +extern void ecma_dealloc_string (ecma_string_t *string_p); #endif /* JERRY_ECMA_ALLOC_H */ diff --git a/src/libecmaobjects/ecma-globals.h b/src/libecmaobjects/ecma-globals.h index b651c399f..cf40921a7 100644 --- a/src/libecmaobjects/ecma-globals.h +++ b/src/libecmaobjects/ecma-globals.h @@ -491,7 +491,7 @@ typedef uint16_t ecma_length_t; typedef struct { /** Compressed pointer to next chunk */ - uint16_t next_chunk_p; + uint16_t next_chunk_cp; /** Number of elements in the Array */ ecma_length_t unit_number; @@ -515,7 +515,7 @@ typedef struct typedef struct { /** Compressed pointer to next chunk */ - uint16_t next_chunk_p; + uint16_t next_chunk_cp; /** Characters */ uint8_t data[ sizeof (uint64_t) - sizeof (uint16_t) ]; diff --git a/src/libecmaobjects/ecma-helpers-string.c b/src/libecmaobjects/ecma-helpers-string.c index cb8ead728..14b01a2ad 100644 --- a/src/libecmaobjects/ecma-helpers-string.c +++ b/src/libecmaobjects/ecma-helpers-string.c @@ -29,140 +29,196 @@ /** * Allocate new ecma-string and fill it with characters from specified buffer * - * @return Pointer to first chunk of an array, containing allocated string + * @return pointer to ecma-string descriptor */ -ecma_array_first_chunk_t* -ecma_new_ecma_string (const ecma_char_t *string_p) /**< zero-terminated string of ecma-characters */ +ecma_string_t* +ecma_new_ecma_string (const ecma_char_t *string_p) /**< zero-terminated string */ { - ecma_length_t length = 0; + JERRY_ASSERT (string_p != NULL); - /* - * TODO: Do not precalculate length. - */ - if (string_p != NULL) + ecma_length_t length = 0; + const ecma_char_t *iter_p = string_p; + + while (*iter_p++) { - const ecma_char_t *iter_p = string_p; - while (*iter_p++) - { - length++; - } + length++; } - ecma_array_first_chunk_t *string_first_chunk_p = ecma_alloc_array_first_chunk (); + const size_t bytes_needed_for_current_string = sizeof (ecma_char_t) * length; + const size_t bytes_for_chars_in_string_descriptor = JERRY_SIZE_OF_STRUCT_MEMBER (ecma_string_t, u.chars); + JERRY_STATIC_ASSERT (bytes_for_chars_in_string_descriptor % sizeof (ecma_char_t) == 0); - string_first_chunk_p->header.unit_number = length; - uint8_t *copy_pointer = (uint8_t*) string_p; - size_t chars_left = length; - size_t chars_to_copy = JERRY_MIN(length, sizeof (string_first_chunk_p->data) / sizeof (ecma_char_t)); - __memcpy (string_first_chunk_p->data, copy_pointer, chars_to_copy * sizeof (ecma_char_t)); - chars_left -= chars_to_copy; - copy_pointer += chars_to_copy * sizeof (ecma_char_t); + ecma_string_t* string_desc_p = ecma_alloc_string (); + string_desc_p->refs = 1; + string_desc_p->length = length; - ecma_array_non_first_chunk_t *string_non_first_chunk_p; + if (bytes_needed_for_current_string <= bytes_for_chars_in_string_descriptor) + { + string_desc_p->container = ECMA_STRING_CONTAINER_IN_DESCRIPTOR; + __memcpy (string_desc_p->u.chars, string_p, bytes_needed_for_current_string); - JERRY_STATIC_ASSERT(ECMA_POINTER_FIELD_WIDTH <= sizeof (uint16_t) * JERRY_BITSINBYTE); - uint16_t *next_chunk_compressed_pointer_p = &string_first_chunk_p->header.next_chunk_p; + return string_desc_p; + } + string_desc_p->container = ECMA_STRING_CONTAINER_HEAP; + + const ecma_char_t* src_p = string_p; + + ecma_length_t chars_left = length; + JERRY_ASSERT (chars_left > 0); + + ecma_array_non_first_chunk_t *string_chunk_p = ecma_alloc_array_non_first_chunk (); + + ECMA_SET_NON_NULL_POINTER (string_desc_p->u.chunk_cp, string_chunk_p); + + const ecma_length_t max_chars_in_chunk = sizeof (string_chunk_p->data) / sizeof (ecma_char_t); while (chars_left > 0) { - string_non_first_chunk_p = ecma_alloc_array_non_first_chunk (); + ecma_length_t chars_to_copy = JERRY_MIN(chars_left, max_chars_in_chunk); - size_t chars_to_copy = JERRY_MIN(chars_left, sizeof (string_non_first_chunk_p->data) / sizeof (ecma_char_t)); - __memcpy (string_non_first_chunk_p->data, copy_pointer, chars_to_copy * sizeof (ecma_char_t)); - chars_left -= chars_to_copy; - copy_pointer += chars_to_copy * sizeof (ecma_char_t); + __memcpy (string_chunk_p->data, src_p, chars_to_copy * sizeof (ecma_char_t)); + chars_left = (ecma_length_t) (chars_left - chars_to_copy); + src_p += chars_to_copy; - ECMA_SET_NON_NULL_POINTER(*next_chunk_compressed_pointer_p, string_non_first_chunk_p); - next_chunk_compressed_pointer_p = &string_non_first_chunk_p->next_chunk_p; + ecma_array_non_first_chunk_t* next_string_chunk_p = ecma_alloc_array_non_first_chunk (); + ECMA_SET_NON_NULL_POINTER (string_chunk_p->next_chunk_cp, next_string_chunk_p); + string_chunk_p = next_string_chunk_p; } - *next_chunk_compressed_pointer_p = ECMA_NULL_POINTER; + string_chunk_p->next_chunk_cp = ECMA_NULL_POINTER; - return string_first_chunk_p; + return string_desc_p; } /* ecma_new_ecma_string */ +/** + * Decrease reference counter and deallocate ecma-string if + * after that the counter the counter becomes zero. + */ +void +ecma_free_string (ecma_string_t *string_p) /**< ecma-string */ +{ + JERRY_ASSERT (string_p != NULL); + JERRY_ASSERT (string_p->refs != 0); + + string_p->refs--; + + if (string_p->refs != 0) + { + return; + } + + if (string_p->container == ECMA_STRING_CONTAINER_HEAP) + { + ecma_array_non_first_chunk_t *chunk_p = ECMA_GET_POINTER (string_p->u.chunk_cp); + + JERRY_ASSERT (chunk_p != NULL); + + while (chunk_p != NULL) + { + ecma_array_non_first_chunk_t *next_chunk_p = ECMA_GET_POINTER (chunk_p->next_chunk_cp); + + ecma_dealloc_array_non_first_chunk (chunk_p); + + chunk_p = next_chunk_p; + } + } + else + { + JERRY_ASSERT (string_p->container == ECMA_STRING_CONTAINER_IN_DESCRIPTOR + || string_p->container == ECMA_STRING_CONTAINER_LIT_TABLE); + + /* only the string descriptor itself should be freed */ + } + + ecma_dealloc_string (string_p); +} /* ecma_free_string */ + /** * Copy ecma-string's contents to a buffer. * * Buffer will contain length of string, in characters, followed by string's characters. * - * @return number of bytes, actually copied to the buffer, if string's content was copied successfully; - * negative number, which is calculated as negation of buffer size, that is required - * to hold the string's content (in case size of buffer is insuficcient). + * @return number of bytes, actually copied to the buffer - if string's content was copied successfully; + * otherwise (in case size of buffer is insuficcient) - negative number, which is calculated + * as negation of buffer size, that is required to hold the string's content. */ ssize_t -ecma_copy_ecma_string_chars_to_buffer (ecma_array_first_chunk_t *first_chunk_p, /**< first chunk of ecma-string */ - uint8_t *buffer_p, /**< destination buffer */ - size_t buffer_size) /**< size of buffer */ +ecma_string_to_zt_string (ecma_string_t *string_desc_p, /**< ecma-string descriptor */ + ecma_char_t *buffer_p, /**< destination buffer */ + size_t buffer_size) /**< size of buffer */ { - ecma_length_t string_length = first_chunk_p->header.unit_number; - size_t required_buffer_size = sizeof (ecma_length_t) + sizeof (ecma_char_t) * string_length; + JERRY_ASSERT (string_desc_p != NULL); + JERRY_ASSERT (string_desc_p->refs > 0); + JERRY_ASSERT (buffer_p != NULL); + JERRY_ASSERT (buffer_size > 0); + + const ecma_length_t string_length = string_desc_p->length; + size_t required_buffer_size = sizeof (ecma_char_t) * string_length + 1 /* for zero char */; if (required_buffer_size > buffer_size) { return - (ssize_t) required_buffer_size; } - *(ecma_length_t*) buffer_p = string_length; + ecma_char_t *dest_p = buffer_p; - size_t chars_left = string_length; - uint8_t *dest_pointer = buffer_p + sizeof (ecma_length_t); - size_t copy_chunk_chars = JERRY_MIN(sizeof (first_chunk_p->data) / sizeof (ecma_char_t), - chars_left); - __memcpy (dest_pointer, first_chunk_p->data, copy_chunk_chars * sizeof (ecma_char_t)); - dest_pointer += copy_chunk_chars * sizeof (ecma_char_t); - chars_left -= copy_chunk_chars; - - ecma_array_non_first_chunk_t *non_first_chunk_p = ECMA_GET_POINTER(first_chunk_p->header.next_chunk_p); - - while (chars_left > 0) + switch ((ecma_string_container_t)string_desc_p->container) { - JERRY_ASSERT(chars_left < string_length); + case ECMA_STRING_CONTAINER_IN_DESCRIPTOR: + { + __memcpy (dest_p, string_desc_p->u.chars, string_length * sizeof (ecma_char_t)); + dest_p += string_length; - copy_chunk_chars = JERRY_MIN(sizeof (non_first_chunk_p->data) / sizeof (ecma_char_t), - chars_left); - __memcpy (dest_pointer, non_first_chunk_p->data, copy_chunk_chars * sizeof (ecma_char_t)); - dest_pointer += copy_chunk_chars * sizeof (ecma_char_t); - chars_left -= copy_chunk_chars; + break; + } + case ECMA_STRING_CONTAINER_HEAP: + { + ecma_array_non_first_chunk_t *string_chunk_p = ECMA_GET_POINTER(string_desc_p->u.chunk_cp); - non_first_chunk_p = ECMA_GET_POINTER(non_first_chunk_p->next_chunk_p); + const ecma_length_t max_chars_in_chunk = sizeof (string_chunk_p->data) / sizeof (ecma_char_t); + + ecma_length_t chars_left = string_length; + while (chars_left > 0) + { + JERRY_ASSERT(chars_left < string_length); + + ecma_length_t chars_to_copy = JERRY_MIN(max_chars_in_chunk, chars_left); + + __memcpy (dest_p, string_chunk_p->data, chars_to_copy * sizeof (ecma_char_t)); + dest_p += chars_to_copy; + chars_left = (ecma_length_t) (chars_left - chars_to_copy); + + string_chunk_p = ECMA_GET_POINTER(string_chunk_p->next_chunk_cp); + } + break; + } + case ECMA_STRING_CONTAINER_LIT_TABLE: + { + JERRY_UNIMPLEMENTED(); + } } + *dest_p = '\0'; + return (ssize_t) required_buffer_size; -} /* ecma_copy_ecma_string_chars_to_buffer */ +} /* ecma_string_to_zt_string */ /** - * Duplicate an ecma-string. + * Increase reference counter of ecma-string. * - * @return pointer to new ecma-string's first chunk + * @return pointer to same ecma-string descriptor with increased reference counter */ -ecma_array_first_chunk_t* -ecma_duplicate_ecma_string (ecma_array_first_chunk_t *first_chunk_p) /**< first chunk of string to duplicate */ +void +ecma_ref_ecma_string (ecma_string_t *string_desc_p) /**< string descriptor */ { - JERRY_ASSERT(first_chunk_p != NULL); + JERRY_ASSERT (string_desc_p != NULL); + JERRY_ASSERT (string_desc_p->refs > 0); - ecma_array_first_chunk_t *first_chunk_copy_p = ecma_alloc_array_first_chunk (); - __memcpy (first_chunk_copy_p, first_chunk_p, sizeof (ecma_array_first_chunk_t)); + string_desc_p->refs++; - ecma_array_non_first_chunk_t *non_first_chunk_p, *non_first_chunk_copy_p; - non_first_chunk_p = ECMA_GET_POINTER(first_chunk_p->header.next_chunk_p); - uint16_t *next_pointer_p = &first_chunk_copy_p->header.next_chunk_p; - - while (non_first_chunk_p != NULL) - { - non_first_chunk_copy_p = ecma_alloc_array_non_first_chunk (); - ECMA_SET_POINTER(*next_pointer_p, non_first_chunk_copy_p); - next_pointer_p = &non_first_chunk_copy_p->next_chunk_p; - - __memcpy (non_first_chunk_copy_p, non_first_chunk_p, sizeof (ecma_array_non_first_chunk_t)); - - non_first_chunk_p = ECMA_GET_POINTER(non_first_chunk_p->next_chunk_p); - } - - *next_pointer_p = ECMA_NULL_POINTER; - - return first_chunk_copy_p; -} /* ecma_duplicate_ecma_string */ + /* Check for overflow */ + JERRY_ASSERT (string_desc_p->refs > 0); +} /* ecma_ref_ecma_string */ /** * Compare ecma-string to ecma-string @@ -171,29 +227,78 @@ ecma_duplicate_ecma_string (ecma_array_first_chunk_t *first_chunk_p) /**< first * false - otherwise. */ bool -ecma_compare_ecma_string_to_ecma_string (const ecma_array_first_chunk_t *string1_p, /* ecma-string */ - const ecma_array_first_chunk_t *string2_p) /* ecma-string */ +ecma_compare_ecma_string_to_ecma_string (const ecma_string_t *string1_p, /* ecma-string */ + const ecma_string_t *string2_p) /* ecma-string */ { JERRY_ASSERT (string1_p != NULL && string2_p != NULL); - if (string1_p->header.unit_number != string2_p->header.unit_number) + if (string1_p == string2_p) + { + return true; + } + + if (string1_p->length != string2_p->length) { return false; } - ecma_length_t chars_left = string1_p->header.unit_number; + ecma_length_t chars_left = string1_p->length; - JERRY_STATIC_ASSERT (ECMA_POINTER_FIELD_WIDTH <= sizeof (uint16_t) * JERRY_BITSINBYTE); - const uint16_t *next_chunk_compressed_pointer_1_p = &string1_p->header.next_chunk_p; - const uint16_t *next_chunk_compressed_pointer_2_p = &string2_p->header.next_chunk_p; - const ecma_char_t *cur_char_array_1_p = string1_p->data; - const ecma_char_t *cur_char_array_1_end_p = string1_p->data + sizeof (string1_p->data); - const ecma_char_t *cur_char_array_2_p = string2_p->data; - const ecma_char_t *cur_char_array_2_end_p = string2_p->data + sizeof (string2_p->data); + if (string1_p->container == ECMA_STRING_CONTAINER_IN_DESCRIPTOR + && string2_p->container == ECMA_STRING_CONTAINER_IN_DESCRIPTOR) + { + return __memcmp (string1_p->u.chars, string2_p->u.chars, chars_left * sizeof (ecma_char_t)); + } + + if (string1_p->container == ECMA_STRING_CONTAINER_LIT_TABLE + || string2_p->container == ECMA_STRING_CONTAINER_LIT_TABLE) + { + JERRY_UNIMPLEMENTED(); + } + + if (string1_p->container == ECMA_STRING_CONTAINER_HEAP + && string2_p->container == ECMA_STRING_CONTAINER_IN_DESCRIPTOR) + { + const ecma_string_t *tmp_string_p = string1_p; + string1_p = string2_p; + string2_p = tmp_string_p; + } + JERRY_ASSERT (string2_p->container == ECMA_STRING_CONTAINER_HEAP); + + ecma_array_non_first_chunk_t *string1_chunk_p, *string2_chunk_p; + const ecma_char_t *cur_char_array_1_p, *cur_char_array_2_p; + const ecma_char_t *cur_char_array_1_end_p, *cur_char_array_2_end_p; + if (string1_p->container == ECMA_STRING_CONTAINER_IN_DESCRIPTOR) + { + string1_chunk_p = NULL; + cur_char_array_1_p = string1_p->u.chars; + cur_char_array_1_end_p = cur_char_array_1_p + sizeof (string1_p->u.chars) / sizeof (ecma_char_t); + } + else + { + string1_chunk_p = ECMA_GET_POINTER (string1_p->u.chunk_cp); + cur_char_array_1_p = string1_chunk_p->data; + cur_char_array_1_end_p = cur_char_array_1_p + sizeof (string1_chunk_p->data) / sizeof (ecma_char_t); + } + + string2_chunk_p = ECMA_GET_POINTER (string2_p->u.chunk_cp); + cur_char_array_2_p = string2_chunk_p->data; + cur_char_array_2_end_p = cur_char_array_2_p + sizeof (string2_chunk_p->data) / sizeof (ecma_char_t); + + /* + * The assertion check allows to combine update of cur_char_array_1_p and cur_char_array_2_p pointers, + * because: + * - if we reached end of string in descriptor then we reached end of string => chars_left is zero; + * - if we reached end of string chunk in heap then we reached end of other string's chunk too + * (they're lengths are equal) => both pointer should be updated. + */ + JERRY_STATIC_ASSERT (sizeof (string1_p->u.chars) / sizeof (ecma_char_t) + < sizeof (string1_chunk_p->data) / sizeof (ecma_char_t)); while (chars_left > 0) { - if (cur_char_array_1_p != cur_char_array_1_end_p) + if (cur_char_array_1_p != cur_char_array_1_end_p + && cur_char_array_2_p != cur_char_array_2_end_p) { JERRY_ASSERT (cur_char_array_2_p < cur_char_array_2_end_p); @@ -203,18 +308,25 @@ ecma_compare_ecma_string_to_ecma_string (const ecma_array_first_chunk_t *string1 } chars_left--; + + continue; } - else + + if (cur_char_array_1_p == cur_char_array_1_end_p) { - ecma_array_non_first_chunk_t *non_first_chunk_1_p = ECMA_GET_POINTER (*next_chunk_compressed_pointer_1_p); - ecma_array_non_first_chunk_t *non_first_chunk_2_p = ECMA_GET_POINTER (*next_chunk_compressed_pointer_2_p); + JERRY_ASSERT (string1_p->container == ECMA_STRING_CONTAINER_HEAP + && string2_p->container == ECMA_STRING_CONTAINER_HEAP); + JERRY_ASSERT (cur_char_array_2_p == cur_char_array_2_end_p); - JERRY_ASSERT (non_first_chunk_1_p != NULL && non_first_chunk_2_p != NULL); + string1_chunk_p = ECMA_GET_POINTER (string1_chunk_p->next_chunk_cp); + JERRY_ASSERT (string1_chunk_p != NULL); + cur_char_array_1_p = string1_chunk_p->data; + cur_char_array_1_end_p = cur_char_array_1_p + sizeof (string1_chunk_p->data) / sizeof (ecma_char_t); - cur_char_array_1_p = non_first_chunk_1_p->data; - cur_char_array_1_end_p = non_first_chunk_1_p->data + sizeof (non_first_chunk_1_p->data); - cur_char_array_2_p = non_first_chunk_2_p->data; - cur_char_array_2_end_p = non_first_chunk_2_p->data + sizeof (non_first_chunk_2_p->data); + string2_chunk_p = ECMA_GET_POINTER (string2_chunk_p->next_chunk_cp); + JERRY_ASSERT (string2_chunk_p != NULL); + cur_char_array_2_p = string2_chunk_p->data; + cur_char_array_2_end_p = cur_char_array_2_p + sizeof (string2_chunk_p->data) / sizeof (ecma_char_t); } } @@ -245,19 +357,34 @@ ecma_compare_zt_string_to_zt_string (const ecma_char_t *string1_p, /**< zero-ter */ bool ecma_compare_zt_string_to_ecma_string (const ecma_char_t *string_p, /**< zero-terminated string */ - const ecma_array_first_chunk_t *ecma_string_p) /* ecma-string */ + const ecma_string_t *ecma_string_p) /* ecma-string */ { JERRY_ASSERT(string_p != NULL); JERRY_ASSERT(ecma_string_p != NULL); const ecma_char_t *str_iter_p = string_p; - ecma_length_t ecma_str_len = ecma_string_p->header.unit_number; - const ecma_char_t *current_chunk_chars_cur = (const ecma_char_t*) ecma_string_p->data; - const ecma_char_t *current_chunk_chars_end = (const ecma_char_t*) (ecma_string_p->data + - sizeof (ecma_string_p->data)); + ecma_length_t ecma_str_len = ecma_string_p->length; + const ecma_char_t *current_chunk_chars_cur; + const ecma_char_t *current_chunk_chars_end; + ecma_array_non_first_chunk_t *string_chunk_p = NULL; - JERRY_STATIC_ASSERT(ECMA_POINTER_FIELD_WIDTH <= sizeof (uint16_t) * JERRY_BITSINBYTE); - const uint16_t *next_chunk_compressed_pointer_p = &ecma_string_p->header.next_chunk_p; + if (ecma_string_p->container == ECMA_STRING_CONTAINER_IN_DESCRIPTOR) + { + current_chunk_chars_cur = ecma_string_p->u.chars; + current_chunk_chars_end = current_chunk_chars_cur + sizeof (ecma_string_p->u.chars) / sizeof (ecma_char_t); + } + else if (ecma_string_p->container == ECMA_STRING_CONTAINER_HEAP) + { + string_chunk_p = ECMA_GET_POINTER (ecma_string_p->u.chunk_cp); + current_chunk_chars_cur = string_chunk_p->data; + current_chunk_chars_end = current_chunk_chars_cur + sizeof (string_chunk_p->data) / sizeof (ecma_char_t); + } + else + { + JERRY_ASSERT (ecma_string_p->container == ECMA_STRING_CONTAINER_LIT_TABLE); + + JERRY_UNIMPLEMENTED(); + } for (ecma_length_t str_index = 0; str_index < ecma_str_len; @@ -267,15 +394,15 @@ ecma_compare_zt_string_to_ecma_string (const ecma_char_t *string_p, /**< zero-te if (current_chunk_chars_cur == current_chunk_chars_end) { + JERRY_ASSERT (ecma_string_p->container == ECMA_STRING_CONTAINER_HEAP); + /* switching to next chunk */ - ecma_array_non_first_chunk_t *next_chunk_p = ECMA_GET_POINTER(*next_chunk_compressed_pointer_p); + string_chunk_p = ECMA_GET_POINTER (string_chunk_p->next_chunk_cp); - JERRY_ASSERT(next_chunk_p != NULL); + JERRY_ASSERT(string_chunk_p != NULL); - current_chunk_chars_cur = (const ecma_char_t*) next_chunk_p->data; - current_chunk_chars_end = (const ecma_char_t*) (next_chunk_p->data + sizeof (next_chunk_p->data)); - - next_chunk_compressed_pointer_p = &next_chunk_p->next_chunk_p; + current_chunk_chars_cur = string_chunk_p->data; + current_chunk_chars_end = current_chunk_chars_cur + sizeof (string_chunk_p->data) / sizeof (ecma_char_t); } if (*str_iter_p != *current_chunk_chars_cur) @@ -296,7 +423,7 @@ ecma_compare_zt_string_to_ecma_string (const ecma_char_t *string_p, /**< zero-te * If we have also reached end of zero-terminated string, than strings are equal. * Otherwise zero-terminated string is longer. */ - return (*str_iter_p == 0); + return (*str_iter_p == '\0'); } /* ecma_compare_zt_string_to_ecma_string */ /** diff --git a/src/libecmaobjects/ecma-helpers-value.c b/src/libecmaobjects/ecma-helpers-value.c index 329d639c6..d954f0792 100644 --- a/src/libecmaobjects/ecma-helpers-value.c +++ b/src/libecmaobjects/ecma-helpers-value.c @@ -127,7 +127,7 @@ ecma_make_number_value (ecma_number_t* num_p) /**< number to reference in value * String value constructor */ ecma_value_t -ecma_make_string_value (ecma_array_first_chunk_t* ecma_string_p) /**< string to reference in value */ +ecma_make_string_value (ecma_string_t* ecma_string_p) /**< string to reference in value */ { JERRY_ASSERT(ecma_string_p != NULL); @@ -209,16 +209,16 @@ ecma_copy_value (const ecma_value_t value, /**< ecma-value */ } case ECMA_TYPE_STRING: { - ecma_array_first_chunk_t *string_p = ECMA_GET_POINTER(value.value); + ecma_string_t *string_p = ECMA_GET_POINTER(value.value); JERRY_ASSERT(string_p != NULL); - ecma_array_first_chunk_t *string_copy_p = ecma_duplicate_ecma_string (string_p); + ecma_ref_ecma_string (string_p); value_copy = (ecma_value_t) { .value_type = ECMA_TYPE_STRING }; - ECMA_SET_POINTER(value_copy.value, string_copy_p); + ECMA_SET_POINTER(value_copy.value, string_p); break; } @@ -270,8 +270,8 @@ ecma_free_value (ecma_value_t value, /**< value description */ case ECMA_TYPE_STRING: { - ecma_array_first_chunk_t *string_p = ECMA_GET_POINTER(value.value); - ecma_free_array (string_p); + ecma_string_t *string_p = ECMA_GET_POINTER(value.value); + ecma_free_string (string_p); break; } diff --git a/src/libecmaobjects/ecma-helpers.c b/src/libecmaobjects/ecma-helpers.c index a9b5c8796..2e1b61294 100644 --- a/src/libecmaobjects/ecma-helpers.c +++ b/src/libecmaobjects/ecma-helpers.c @@ -281,7 +281,7 @@ ecma_find_named_property (ecma_object_t *obj_p, /**< object to find property in property_p != NULL; property_p = ECMA_GET_POINTER(property_p->next_property_p)) { - ecma_array_first_chunk_t *property_name_p; + ecma_string_t *property_name_p; if (property_p->type == ECMA_PROPERTY_NAMEDDATA) { @@ -361,7 +361,7 @@ ecma_free_named_data_property (ecma_property_t *property_p) /**< the property */ { JERRY_ASSERT(property_p->type == ECMA_PROPERTY_NAMEDDATA); - ecma_free_array (ECMA_GET_POINTER(property_p->u.named_data_property.name_p)); + ecma_free_string (ECMA_GET_POINTER (property_p->u.named_data_property.name_p)); ecma_free_value (property_p->u.named_data_property.value, false); ecma_dealloc_property (property_p); @@ -375,7 +375,7 @@ ecma_free_named_accessor_property (ecma_property_t *property_p) /**< the propert { JERRY_ASSERT(property_p->type == ECMA_PROPERTY_NAMEDACCESSOR); - ecma_free_array (ECMA_GET_POINTER(property_p->u.named_accessor_property.name_p)); + ecma_free_string (ECMA_GET_POINTER (property_p->u.named_accessor_property.name_p)); ecma_dealloc_property (property_p); } /* ecma_free_named_accessor_property */ @@ -490,13 +490,13 @@ ecma_free_array (ecma_array_first_chunk_t *first_chunk_p) /**< first chunk of th { JERRY_ASSERT(first_chunk_p != NULL); - ecma_array_non_first_chunk_t *non_first_chunk_p = ECMA_GET_POINTER(first_chunk_p->header.next_chunk_p); + ecma_array_non_first_chunk_t *non_first_chunk_p = ECMA_GET_POINTER (first_chunk_p->header.next_chunk_cp); ecma_dealloc_array_first_chunk (first_chunk_p); while (non_first_chunk_p != NULL) { - ecma_array_non_first_chunk_t *next_chunk_p = ECMA_GET_POINTER(non_first_chunk_p->next_chunk_p); + ecma_array_non_first_chunk_t *next_chunk_p = ECMA_GET_POINTER (non_first_chunk_p->next_chunk_cp); ecma_dealloc_array_non_first_chunk (non_first_chunk_p); diff --git a/src/libecmaobjects/ecma-helpers.h b/src/libecmaobjects/ecma-helpers.h index d368b023e..e38c7b7e7 100644 --- a/src/libecmaobjects/ecma-helpers.h +++ b/src/libecmaobjects/ecma-helpers.h @@ -63,7 +63,7 @@ extern bool ecma_is_value_true (ecma_value_t value); extern ecma_value_t ecma_make_simple_value (ecma_simple_value_t value); extern ecma_value_t ecma_make_number_value (ecma_number_t* num_p); -extern ecma_value_t ecma_make_string_value (ecma_array_first_chunk_t* ecma_string_p); +extern ecma_value_t ecma_make_string_value (ecma_string_t* ecma_string_p); extern ecma_value_t ecma_make_object_value (ecma_object_t* object_p); extern ecma_value_t ecma_copy_value (const ecma_value_t value, bool do_ref_if_object); extern void ecma_free_value (const ecma_value_t value, bool do_deref_if_object); @@ -85,6 +85,19 @@ extern bool ecma_is_completion_value_normal_true (ecma_completion_value_t value) extern bool ecma_is_completion_value_normal_false (ecma_completion_value_t value); extern bool ecma_is_empty_completion_value (ecma_completion_value_t value); +/* ecma-helpers-string.c */ +extern ecma_string_t* ecma_new_ecma_string (const ecma_char_t *string_p); +extern void ecma_free_string (ecma_string_t *string_p); +extern ssize_t ecma_string_to_zt_string (ecma_string_t *string_desc_p, + ecma_char_t *buffer_p, + size_t buffer_size); +extern void ecma_ref_ecma_string (ecma_string_t *string_desc_p); +extern int32_t ecma_compare_zt_string_to_zt_string (const ecma_char_t *string1_p, const ecma_char_t *string2_p); +extern bool ecma_compare_zt_string_to_ecma_string (const ecma_char_t *string_p, + const ecma_string_t *ecma_string_p); +extern bool ecma_compare_ecma_string_to_ecma_string (const ecma_string_t *string1_p, + const ecma_string_t *string2_p); + /* ecma-helpers.c */ extern ecma_object_t* ecma_create_object (ecma_object_t *prototype_object_p, bool is_extensible, @@ -126,16 +139,6 @@ extern void ecma_free_property (ecma_property_t *prop_p); extern void ecma_delete_property (ecma_object_t *obj_p, ecma_property_t *prop_p); -extern ecma_array_first_chunk_t* ecma_new_ecma_string (const ecma_char_t *string_p); -extern ssize_t ecma_copy_ecma_string_chars_to_buffer (ecma_array_first_chunk_t *first_chunk_p, - uint8_t *buffer_p, - size_t buffer_size); -extern ecma_array_first_chunk_t* ecma_duplicate_ecma_string (ecma_array_first_chunk_t *first_chunk_p); -extern int32_t ecma_compare_zt_string_to_zt_string (const ecma_char_t *string1_p, const ecma_char_t *string2_p); -extern bool ecma_compare_zt_string_to_ecma_string (const ecma_char_t *string_p, - const ecma_array_first_chunk_t *ecma_string_p); -extern bool ecma_compare_ecma_string_to_ecma_string (const ecma_array_first_chunk_t *string1_p, - const ecma_array_first_chunk_t *string2_p); extern void ecma_free_array (ecma_array_first_chunk_t *first_chunk_p); extern ecma_property_descriptor_t ecma_make_empty_property_descriptor (void); diff --git a/src/libecmaoperations/ecma-comparison.c b/src/libecmaoperations/ecma-comparison.c index 007725058..642f3c313 100644 --- a/src/libecmaoperations/ecma-comparison.c +++ b/src/libecmaoperations/ecma-comparison.c @@ -80,10 +80,10 @@ ecma_op_abstract_equality_compare (ecma_value_t x, /**< first operand */ } else if (is_x_string) { // d. - ecma_array_first_chunk_t* x_str = (ecma_array_first_chunk_t*)(ECMA_GET_POINTER(x.value)); - ecma_array_first_chunk_t* y_str = (ecma_array_first_chunk_t*)(ECMA_GET_POINTER(y.value)); + ecma_string_t* x_str_p = ECMA_GET_POINTER(x.value); + ecma_string_t* y_str_p = ECMA_GET_POINTER(y.value); - return ecma_compare_ecma_string_to_ecma_string (x_str, y_str); + return ecma_compare_ecma_string_to_ecma_string (x_str_p, y_str_p); } else if (is_x_boolean) { // e. diff --git a/src/libecmaoperations/ecma-conversion.c b/src/libecmaoperations/ecma-conversion.c index 62072577b..577a19e6e 100644 --- a/src/libecmaoperations/ecma-conversion.c +++ b/src/libecmaoperations/ecma-conversion.c @@ -134,8 +134,8 @@ ecma_op_same_value (ecma_value_t x, /**< ecma-value */ if (is_x_string) { - ecma_array_first_chunk_t* x_str_p = (ecma_array_first_chunk_t*)(ECMA_GET_POINTER(x.value)); - ecma_array_first_chunk_t* y_str_p = (ecma_array_first_chunk_t*)(ECMA_GET_POINTER(y.value)); + ecma_string_t* x_str_p = ECMA_GET_POINTER(x.value); + ecma_string_t* y_str_p = ECMA_GET_POINTER(y.value); return ecma_compare_ecma_string_to_ecma_string (x_str_p, y_str_p); } @@ -234,9 +234,9 @@ ecma_op_to_boolean (ecma_value_t value) /**< ecma-value */ } case ECMA_TYPE_STRING: { - ecma_array_first_chunk_t *str_p = ECMA_GET_POINTER(value.value); + ecma_string_t *str_p = ECMA_GET_POINTER(value.value); - return ecma_make_simple_completion_value ((str_p->header.unit_number == 0) ? ECMA_SIMPLE_VALUE_FALSE + return ecma_make_simple_completion_value ((str_p->length == 0) ? ECMA_SIMPLE_VALUE_FALSE : ECMA_SIMPLE_VALUE_TRUE); break;