diff --git a/jerry-core/CMakeLists.txt b/jerry-core/CMakeLists.txt index 20de934fbc..b20965dda2 100644 --- a/jerry-core/CMakeLists.txt +++ b/jerry-core/CMakeLists.txt @@ -93,6 +93,7 @@ project (JerryCore CXX C ASM) # Include directories set(INCLUDE_CORE ${CMAKE_SOURCE_DIR}/jerry-core + ${CMAKE_SOURCE_DIR}/jerry-core/lit ${CMAKE_SOURCE_DIR}/jerry-core/rcs ${CMAKE_SOURCE_DIR}/jerry-core/mem ${CMAKE_SOURCE_DIR}/jerry-core/vm @@ -110,6 +111,7 @@ project (JerryCore CXX C ASM) # Sources # Jerry core file(GLOB SOURCE_CORE_API *.cpp) + file(GLOB SOURCE_CORE_LIT lit/*.cpp) file(GLOB SOURCE_CORE_RCS rcs/*.cpp) file(GLOB SOURCE_CORE_MEM mem/*.cpp) file(GLOB SOURCE_CORE_VM vm/*.cpp) @@ -123,6 +125,7 @@ project (JerryCore CXX C ASM) set(SOURCE_CORE jerry.cpp ${SOURCE_CORE_API} + ${SOURCE_CORE_LIT} ${SOURCE_CORE_RCS} ${SOURCE_CORE_MEM} ${SOURCE_CORE_VM} diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 2823f1f6dc..8aebcdf4dd 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -26,6 +26,7 @@ #include "config.h" #include "jrt.h" #include "mem-allocator.h" +#include "rcs-recordset.h" /** \addtogroup compressedpointer Compressed pointer * @{ @@ -757,10 +758,12 @@ typedef enum } ecma_string_container_t; FIXME (Move to library that should define the type (literal.h /* ? */)) + /** - * Index in literal table + * Literal and compressed pointer to literal */ -typedef uint32_t literal_index_t; +typedef rcs_record_t *literal_t; +typedef rcs_cpointer_t lit_cpointer_t; /** * Identifiers of ECMA and implementation-defined magic string constants @@ -814,7 +817,7 @@ typedef struct ecma_string_t union { /** Index of string in literal table */ - literal_index_t lit_index; + lit_cpointer_t lit_cp; /** Compressed pointer to an ecma_collection_header_t */ mem_cpointer_t collection_cp : ECMA_POINTER_FIELD_WIDTH; diff --git a/jerry-core/ecma/base/ecma-helpers-string.cpp b/jerry-core/ecma/base/ecma-helpers-string.cpp index e8d0cbbce5..c3590f716e 100644 --- a/jerry-core/ecma/base/ecma-helpers-string.cpp +++ b/jerry-core/ecma/base/ecma-helpers-string.cpp @@ -66,9 +66,9 @@ static ecma_length_t ecma_magic_string_max_length; #endif /* !JERRY_NDEBUG */ static void -ecma_init_ecma_string_from_lit_index (ecma_string_t *string_p, - literal_index_t lit_index, - bool is_stack_var); +ecma_init_ecma_string_from_lit_cp (ecma_string_t *string_p, + lit_cpointer_t lit_index, + bool is_stack_var); static void ecma_init_ecma_string_from_magic_string_id (ecma_string_t *string_p, ecma_magic_string_id_t magic_string_id, @@ -370,42 +370,42 @@ ecma_get_magic_string_ex_count (void) * Initialize ecma-string descriptor with string described by index in literal table */ static void -ecma_init_ecma_string_from_lit_index (ecma_string_t *string_p, /**< descriptor to initialize */ - literal_index_t lit_index, /**< index in the literal table */ - bool is_stack_var) /**< flag indicating whether the string descriptor +ecma_init_ecma_string_from_lit_cp (ecma_string_t *string_p, /**< descriptor to initialize */ + lit_cpointer_t lit_cp, /**< compressed pointer to literal */ + bool is_stack_var) /**< flag indicating whether the string descriptor is placed on stack (true) or in the heap (false) */ { #ifndef JERRY_NDEBUG JERRY_ASSERT (is_stack_var == (!mem_is_heap_pointer (string_p))); #endif /* !JERRY_NDEBUG */ - const literal lit = serializer_get_literal_by_id (lit_index); - if (lit.type == LIT_MAGIC_STR) + literal_t lit = lit_get_literal_by_cp (lit_cp); + if (lit->get_type () == LIT_MAGIC_STR_T) { ecma_init_ecma_string_from_magic_string_id (string_p, - lit.data.magic_str_id, + lit_magic_record_get_magic_str_id (lit), is_stack_var); return; } - else if (lit.type == LIT_MAGIC_STR_EX) + else if (lit->get_type () == LIT_MAGIC_STR_EX_T) { ecma_init_ecma_string_from_magic_string_ex_id (string_p, - lit.data.magic_str_ex_id, + lit_magic_record_ex_get_magic_str_id (lit), is_stack_var); - return; } - JERRY_ASSERT (lit.type == LIT_STR); + + JERRY_ASSERT (lit->get_type () == LIT_STR_T); string_p->refs = 1; string_p->is_stack_var = (is_stack_var != 0); string_p->container = ECMA_STRING_CONTAINER_LIT_TABLE; - string_p->hash = lit.data.lp.hash; + string_p->hash = lit_charset_literal_get_hash (lit); string_p->u.common_field = 0; - string_p->u.lit_index = lit_index; -} /* ecma_init_ecma_string_from_lit_index */ + string_p->u.lit_cp = lit_cp; +} /* ecma_init_ecma_string_from_lit_cp */ /** * Initialize ecma-string descriptor with specified magic string @@ -591,12 +591,12 @@ ecma_new_ecma_string_from_number (ecma_number_t num) /**< ecma-number */ * with string described by index in literal table */ void -ecma_new_ecma_string_on_stack_from_lit_index (ecma_string_t *string_p, /**< pointer to the ecma-string +ecma_new_ecma_string_on_stack_from_lit_cp (ecma_string_t *string_p, /**< pointer to the ecma-string descriptor to initialize */ - literal_index_t lit_index) /**< index in the literal table */ + lit_cpointer_t lit_cp) /**< compressed pointer to literal */ { - ecma_init_ecma_string_from_lit_index (string_p, lit_index, true); -} /* ecma_new_ecma_string_on_stack_from_lit_index */ + ecma_init_ecma_string_from_lit_cp (string_p, lit_cp, true); +} /* ecma_new_ecma_string_on_stack_from_lit_cp */ /** * Allocate new ecma-string and fill it with reference to string literal @@ -604,14 +604,14 @@ ecma_new_ecma_string_on_stack_from_lit_index (ecma_string_t *string_p, /**< poin * @return pointer to ecma-string descriptor */ ecma_string_t* -ecma_new_ecma_string_from_lit_index (literal_index_t lit_index) /**< index in the literal table */ +ecma_new_ecma_string_from_lit_cp (lit_cpointer_t lit_cp) /**< index in the literal table */ { ecma_string_t* string_desc_p = ecma_alloc_string (); - ecma_init_ecma_string_from_lit_index (string_desc_p, lit_index, false); + ecma_init_ecma_string_from_lit_cp (string_desc_p, lit_cp, false); return string_desc_p; -} /* ecma_new_ecma_string_from_lit_index */ +} /* ecma_new_ecma_string_from_lit_cp */ /** * Initialize ecma-string descriptor placed on stack with specified magic string @@ -1037,13 +1037,9 @@ ecma_string_to_zt_string (const ecma_string_t *string_desc_p, /**< ecma-string d } case ECMA_STRING_CONTAINER_LIT_TABLE: { - const literal lit = serializer_get_literal_by_id (string_desc_p->u.lit_index); - JERRY_ASSERT (lit.type == LIT_STR); - const ecma_char_t *str_p = literal_to_zt (lit); - JERRY_ASSERT (str_p != NULL); - - ecma_copy_zt_string_to_buffer (str_p, buffer_p, required_buffer_size); - + literal_t lit = lit_get_literal_by_cp (string_desc_p->u.lit_cp); + JERRY_ASSERT (lit->get_type () == LIT_STR_T); + lit_literal_to_charset (lit, buffer_p, (size_t) required_buffer_size); break; } case ECMA_STRING_CONTAINER_UINT32_IN_DESC: @@ -1141,7 +1137,7 @@ ecma_compare_ecma_strings_longpath (const ecma_string_t *string1_p, /* ecma-stri { if (string1_p->container == ECMA_STRING_CONTAINER_LIT_TABLE) { - JERRY_ASSERT (string1_p->u.lit_index != string2_p->u.lit_index); + JERRY_ASSERT (string1_p->u.lit_cp.packed_value != string2_p->u.lit_cp.packed_value); return false; } @@ -1214,7 +1210,7 @@ ecma_compare_ecma_strings_longpath (const ecma_string_t *string1_p, /* ecma-stri } case ECMA_STRING_CONTAINER_LIT_TABLE: { - JERRY_ASSERT (string1_p->u.lit_index != string2_p->u.lit_index); + JERRY_ASSERT (string1_p->u.lit_cp.packed_value != string2_p->u.lit_cp.packed_value); return false; } @@ -1346,74 +1342,56 @@ ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p, /**< ecma- ecma_char_t zt_string1_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER + 1]; ecma_char_t zt_string2_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER + 1]; - if (string1_p->container == ECMA_STRING_CONTAINER_LIT_TABLE) - { - const literal lit = serializer_get_literal_by_id (string1_p->u.lit_index); - JERRY_ASSERT (lit.type == LIT_STR); - zt_string1_p = literal_to_zt (lit); - } - else - { - ssize_t req_size = ecma_string_to_zt_string (string1_p, - zt_string1_buffer, - sizeof (zt_string1_buffer)); + ssize_t req_size = ecma_string_to_zt_string (string1_p, + zt_string1_buffer, + sizeof (zt_string1_buffer)); - if (req_size < 0) + if (req_size < 0) + { + ecma_char_t *heap_buffer_p = (ecma_char_t*) mem_heap_alloc_block ((size_t) -req_size, MEM_HEAP_ALLOC_SHORT_TERM); + if (heap_buffer_p == NULL) { - ecma_char_t *heap_buffer_p = (ecma_char_t*) mem_heap_alloc_block ((size_t) -req_size, MEM_HEAP_ALLOC_SHORT_TERM); - if (heap_buffer_p == NULL) - { - jerry_fatal (ERR_OUT_OF_MEMORY); - } + jerry_fatal (ERR_OUT_OF_MEMORY); + } - ssize_t bytes_copied = ecma_string_to_zt_string (string1_p, - heap_buffer_p, - -req_size); + ssize_t bytes_copied = ecma_string_to_zt_string (string1_p, + heap_buffer_p, + -req_size); - JERRY_ASSERT (bytes_copied > 0); + JERRY_ASSERT (bytes_copied > 0); - zt_string1_p = heap_buffer_p; - is_zt_string1_on_heap = true; - } - else - { - zt_string1_p = zt_string1_buffer; - } - } - - if (string2_p->container == ECMA_STRING_CONTAINER_LIT_TABLE) - { - const literal lit = serializer_get_literal_by_id (string2_p->u.lit_index); - JERRY_ASSERT (lit.type == LIT_STR); - zt_string2_p = literal_to_zt (lit); + zt_string1_p = heap_buffer_p; + is_zt_string1_on_heap = true; } else { - ssize_t req_size = ecma_string_to_zt_string (string2_p, - zt_string2_buffer, - sizeof (zt_string2_buffer)); + zt_string1_p = zt_string1_buffer; + } - if (req_size < 0) + req_size = ecma_string_to_zt_string (string2_p, + zt_string2_buffer, + sizeof (zt_string2_buffer)); + + if (req_size < 0) + { + ecma_char_t *heap_buffer_p = (ecma_char_t*) mem_heap_alloc_block ((size_t) -req_size, MEM_HEAP_ALLOC_SHORT_TERM); + if (heap_buffer_p == NULL) { - ecma_char_t *heap_buffer_p = (ecma_char_t*) mem_heap_alloc_block ((size_t) -req_size, MEM_HEAP_ALLOC_SHORT_TERM); - if (heap_buffer_p == NULL) - { - jerry_fatal (ERR_OUT_OF_MEMORY); - } + jerry_fatal (ERR_OUT_OF_MEMORY); + } - ssize_t bytes_copied = ecma_string_to_zt_string (string2_p, - heap_buffer_p, - -req_size); + ssize_t bytes_copied = ecma_string_to_zt_string (string2_p, + heap_buffer_p, + -req_size); - JERRY_ASSERT (bytes_copied > 0); + JERRY_ASSERT (bytes_copied > 0); - zt_string2_p = heap_buffer_p; - is_zt_string2_on_heap = true; - } - else - { - zt_string2_p = zt_string2_buffer; - } + zt_string2_p = heap_buffer_p; + is_zt_string2_on_heap = true; + } + else + { + zt_string2_p = zt_string2_buffer; } bool is_first_less_than_second = ecma_compare_zt_strings_relational (zt_string1_p, @@ -1445,9 +1423,9 @@ ecma_string_get_length (const ecma_string_t *string_p) /**< ecma-string */ if (container == ECMA_STRING_CONTAINER_LIT_TABLE) { - const literal lit = serializer_get_literal_by_id (string_p->u.lit_index); - - return lit.data.lp.length; + literal_t lit = lit_get_literal_by_cp (string_p->u.lit_cp); + JERRY_ASSERT (lit->get_type () == LIT_STR_T); + return lit_charset_record_get_length (lit); } else if (container == ECMA_STRING_CONTAINER_MAGIC_STRING) { diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 2df2bfd2ca..33f4d82e6e 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -112,9 +112,9 @@ extern bool ecma_is_completion_value_empty (ecma_completion_value_t value); extern ecma_string_t* ecma_new_ecma_string (const ecma_char_t *string_p); extern ecma_string_t* ecma_new_ecma_string_from_uint32 (uint32_t uint_number); extern ecma_string_t* ecma_new_ecma_string_from_number (ecma_number_t number); -extern void ecma_new_ecma_string_on_stack_from_lit_index (ecma_string_t *string_p, - literal_index_t lit_index); -extern ecma_string_t* ecma_new_ecma_string_from_lit_index (literal_index_t lit_index); +extern void ecma_new_ecma_string_on_stack_from_lit_cp (ecma_string_t *string_p, + lit_cpointer_t lit_index); +extern ecma_string_t *ecma_new_ecma_string_from_lit_cp (lit_cpointer_t lit_cp); extern void ecma_new_ecma_string_on_stack_from_magic_string_id (ecma_string_t *string_p, ecma_magic_string_id_t id); extern ecma_string_t* ecma_new_ecma_string_from_magic_string_id (ecma_magic_string_id_t id); diff --git a/jerry-core/ecma/operations/ecma-function-object.cpp b/jerry-core/ecma/operations/ecma-function-object.cpp index 250ee86c22..b6f46424d5 100644 --- a/jerry-core/ecma/operations/ecma-function-object.cpp +++ b/jerry-core/ecma/operations/ecma-function-object.cpp @@ -18,14 +18,12 @@ #include "ecma-exceptions.h" #include "ecma-function-object.h" #include "ecma-gc.h" -#include "ecma-globals.h" #include "ecma-helpers.h" #include "ecma-lex-env.h" #include "ecma-objects.h" #include "ecma-objects-general.h" #include "ecma-objects-arguments.h" #include "ecma-try-catch-macro.h" -#include "jrt.h" #define JERRY_INTERNAL #include "jerry-internal.h" diff --git a/jerry-core/jerry.cpp b/jerry-core/jerry.cpp index 50754731e2..f7a96deef6 100644 --- a/jerry-core/jerry.cpp +++ b/jerry-core/jerry.cpp @@ -26,13 +26,8 @@ #include "ecma-init-finalize.h" #include "ecma-objects.h" #include "ecma-objects-general.h" -#include "jerry.h" -#include "jrt.h" -#include "mem-heap.h" -#include "mem-poolman.h" #include "parser.h" #include "serializer.h" -#include "vm.h" #define JERRY_INTERNAL #include "jerry-internal.h" diff --git a/jerry-core/jrt/jrt.h b/jerry-core/jrt/jrt.h index 5cc7a8e208..45fa13affb 100644 --- a/jerry-core/jrt/jrt.h +++ b/jerry-core/jrt/jrt.h @@ -214,4 +214,16 @@ extern void __noreturn jerry_fatal (jerry_fatal_code_t code); #define JERRY_MIN(v1, v2) ((v1 < v2) ? v1 : v2) #define JERRY_MAX(v1, v2) ((v1 < v2) ? v2 : v1) +/** + * Placement new operator (constructs an object on a pre-allocated buffer) + * + * Our version of the libc library doesn't support calling the constructors and destructors of the static variables. + * It is proposed to use placement new operator. Generally it is available via #include , + * To fix the unavailability of the header in some configurations placement new operator is implemented here. + */ +inline void* operator new (size_t, void* where) +{ + return where; +} /* operator new */ + #endif /* !JERRY_GLOBALS_H */ diff --git a/jerry-core/lit/lit-literal-storage.cpp b/jerry-core/lit/lit-literal-storage.cpp new file mode 100644 index 0000000000..d94a09805d --- /dev/null +++ b/jerry-core/lit/lit-literal-storage.cpp @@ -0,0 +1,490 @@ +/* Copyright 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lit-literal-storage.h" +#include "ecma-helpers.h" +#include "lit-literal.h" + +/** + * Literal storage + * As our libc library doesn't call constructors of static variables, lit_storage is initialized + * in lit_init function by placement new operator. + */ +lit_literal_storage_t lit_storage; + +/** + * Get pointer to the previous record inside the literal storage + * + * @return pointer to the previous record of NULL if this is the first record ('prev' field in the header) + */ +rcs_record_t * +lit_charset_record_t::get_prev () const +{ + rcs_record_iterator_t it ((rcs_recordset_t *)&lit_storage, (rcs_record_t *)this); + it.skip (RCS_DYN_STORAGE_LENGTH_UNIT); + + cpointer_t cpointer; + cpointer.packed_value = it.read (); + + return cpointer_t::decompress (cpointer); +} /* lit_charset_record_t::get_prev */ + +/** + * Set the pointer to the previous record inside the literal storage (sets 'prev' field in the header) + */ +void +lit_charset_record_t::set_prev (rcs_record_t *prev_rec_p) /**< pointer to the record to set as previous */ +{ + rcs_record_iterator_t it ((rcs_recordset_t *)&lit_storage, (rcs_record_t *)this); + it.skip (RCS_DYN_STORAGE_LENGTH_UNIT); + + it.write (cpointer_t::compress (prev_rec_p).packed_value); +} /* lit_charset_record_t::set_prev */ + +/** + * Set the charset of the record + */ +void +lit_charset_record_t::set_charset (const ecma_char_t *str, /**< buffer containing characters to set */ + size_t size) /**< size of the buffer in bytes */ +{ + JERRY_ASSERT (header_size () + size == get_size () - get_alignment_bytes_count ()); + + rcs_record_iterator_t it ((rcs_recordset_t *)&lit_storage, (rcs_record_t *)this); + it.skip (header_size ()); + + for (size_t i = 0; i < get_length (); ++i) + { + it.write (str[i]); + it.skip (); + } +} /* lit_charset_record_t::set_charset */ + +/** + * Get the characters which are stored to the record + * + * @return number of code units written to the buffer + */ +ecma_length_t +lit_charset_record_t::get_charset (ecma_char_t *buff, /**< output buffer */ + size_t size) /**< size of the output buffer in bytes */ +{ + JERRY_ASSERT (buff && size >= sizeof (ecma_char_t)); + + rcs_record_iterator_t it ((rcs_recordset_t *)&lit_storage, (rcs_record_t *)this); + it.skip (header_size ()); + ecma_length_t len = get_length (); + size_t i; + + for (i = 0; i < len && size > sizeof (ecma_char_t); ++i) + { + buff[i] = it.read (); + it.skip (); + size -= sizeof (ecma_char_t); + } + + return (ecma_length_t) i; +} /* lit_charset_record_t::get_charset */ + +/** + * Compares characters from the record to the string + * + * @return 0 if strings are equal + * -1 if str2 is greater + * 1 if str2 is less + */ +int +lit_charset_record_t::compare_zt (const ecma_char_t *str_to_compare_with, /**< buffer with string to compare */ + size_t length) /**< length of the string in buffer str2 */ +{ + size_t i; + + if (get_length () == 0) + { + if (str_to_compare_with != NULL) + { + return -1; + } + else + { + return 0; + } + } + + if (str_to_compare_with == NULL) + { + return 1; + } + + rcs_record_iterator_t it_this (&lit_storage, this); + + it_this.skip (header_size ()); + + for (i = 0; i < get_length () && i < length; i++) + { + ecma_char_t chr = it_this.read (); + + if (chr > str_to_compare_with[i]) + { + return 1; + } + else if (chr < str_to_compare_with[i]) + { + return -1; + } + + it_this.skip (); + } + + if (i < length) + { + return -1; + } + + return 0; +} /* lit_charset_record_t::compare_zt */ + +/** + * Compares two lit_charset_record_t records for equality + * + * @return true if strings inside records are equal + * false otherwise + */ +bool +lit_charset_record_t::equal (lit_charset_record_t *rec) /**< charset record to compare with */ +{ + if (get_length () != rec->get_length ()) + { + return false; + } + + rcs_record_iterator_t it_this (&lit_storage, this); + rcs_record_iterator_t it_record (&lit_storage, rec); + + it_this.skip (header_size ()); + it_record.skip (rec->header_size ()); + + for (ecma_length_t i = 0; i < get_length (); i++) + { + if (it_this.read () != it_record.read ()) + { + return false; + } + + it_this.skip (); + it_record.skip (); + } + + return true; +} /* lit_charset_record_t::equal */ + +/** + * Compares this lit_charset_record_t records with zero-terminated string for equality + * + * @return true if compared instances are equal + * false otherwise + */ +bool +lit_charset_record_t::equal_zt (const ecma_char_t *str) /**< zero-terminated string */ +{ + return equal_non_zt (str, ecma_zt_string_length (str)); +} /* lit_charset_record_t::equal_zt */ + +/** + * Compare this lit_charset_record_t record with string (which could contain '\0' characters) for equality + * + * @return true if compared instances are equal + * false otherwise + */ +bool +lit_charset_record_t::equal_non_zt (const ecma_char_t *str, /**< string to compare with */ + ecma_length_t len) /**< length of the string */ +{ + rcs_record_iterator_t it_this (&lit_storage, this); + + it_this.skip (header_size ()); + + for (ecma_length_t i = 0; i < get_length () && i < len; i++) + { + if (it_this.read () != str[i]) + { + return false; + } + + it_this.skip (); + } + + return get_length () == len; +} /* lit_charset_record_t::equal_non_zt */ + +/** + * Create charset record in the literal storage + * + * @return pointer to the created record + */ +lit_charset_record_t * +lit_literal_storage_t::create_charset_record (const ecma_char_t *str, /**< string to be placed in the record */ + size_t buf_size) /**< size in bytes of the buffer which holds the + * string */ +{ + const size_t alignment = lit_charset_record_t::size (buf_size) - (lit_charset_record_t::header_size () + buf_size); + + lit_charset_record_t *ret = alloc_record (LIT_STR, buf_size); + + ret->set_alignment_bytes_count (alignment); + ret->set_charset (str, buf_size); + ret->set_hash (ecma_chars_buffer_calc_hash_last_chars (str, ret->get_length ())); + + return ret; +} /* lit_literal_storage_t::create_charset_record */ + +/** + * Create magic string record in the literal storage + * + * @return pointer to the created record + */ +lit_magic_record_t * +lit_literal_storage_t::create_magic_record (ecma_magic_string_id_t id) /**< id of a magic string */ +{ + lit_magic_record_t *ret = alloc_record (LIT_MAGIC_STR); + ret->set_magic_str_id (id); + + return ret; +} /* lit_literal_storage_t::create_magic_record */ + +/** + * Create external magic string record in the literal storage + * + * @return pointer to the created record + */ +lit_magic_record_t * +lit_literal_storage_t::create_magic_record_ex (ecma_magic_string_ex_id_t id) /**< id of a magic string */ +{ + lit_magic_record_t *ret = alloc_record (LIT_MAGIC_STR_EX); + ret->set_magic_str_id (id); + + return ret; +} /* lit_literal_storage_t::create_magic_record_ex */ + +/** + * Create number record in the literal storage + * + * @return pointer to the created record + */ +lit_number_record_t * +lit_literal_storage_t::create_number_record (ecma_number_t num) /**< number */ +{ + lit_number_record_t *ret = alloc_record (LIT_NUMBER); + rcs_record_iterator_t it_this (this, ret); + + it_this.skip (ret->header_size ()); + it_this.write (num); + + return ret; +} /* lit_literal_storage_t::create_number_record */ + +/** + * Dump the contents of the literal storage + */ +void +lit_literal_storage_t::dump () +{ + printf ("LITERALS:\n"); + + for (rcs_record_t *rec_p = lit_storage.get_first (); rec_p != NULL; rec_p = lit_storage.get_next (rec_p)) + { + printf ("%p ", rec_p); + printf ("[%3zu] ", get_record_size (rec_p)); + + switch (rec_p->get_type ()) + { + case LIT_STR: + { + lit_charset_record_t *lit_p = static_cast (rec_p); + rcs_record_iterator_t it_this (this, rec_p); + + it_this.skip (lit_charset_record_t::header_size ()); + + for (size_t i = 0; i < lit_p->get_length (); ++i) + { + printf ("%c", it_this.read ()); + it_this.skip (); + } + + printf (" : STRING"); + + break; + } + case LIT_MAGIC_STR: + { + ecma_magic_string_id_t id = lit_magic_record_get_magic_str_id (rec_p); + printf ("%s : MAGIC STRING", ecma_get_magic_string_zt (id)); + printf (" [id=%d] ", id); + + break; + } + case LIT_MAGIC_STR_EX: + { + ecma_magic_string_ex_id_t id = lit_magic_record_ex_get_magic_str_id (rec_p); + printf ("%s : EXT MAGIC STRING", ecma_get_magic_string_ex_zt (id)); + printf (" [id=%d] ", id); + + break; + } + case LIT_NUMBER: + { + lit_number_record_t *lit_p = static_cast (rec_p); + + if (ecma_number_is_nan (lit_p->get_number ())) + { + printf ("%s : NUMBER", "NaN"); + } + else + { + ecma_char_t buff[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; + ecma_number_to_zt_string (lit_p->get_number (), buff, ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER); + printf ("%s : NUMBER", buff); + } + + break; + } + default: + { + printf (" : EMPTY RECORD"); + } + } + + printf ("\n"); + } +} /* lit_literal_storage_t::dump */ + +/** + * Get previous record in the literal storage + * + * @return pointer to the previous record relative to rec_p, or NULL if rec_p is the first record in the storage + */ +rcs_record_t * +lit_literal_storage_t::get_prev (rcs_record_t *rec_p) /**< record, relative to which previous should be found */ +{ + switch (rec_p->get_type ()) + { + case LIT_STR: + { + return (static_cast (rec_p))->get_prev (); + } + case LIT_MAGIC_STR: + case LIT_MAGIC_STR_EX: + { + return (static_cast (rec_p))->get_prev (); + } + case LIT_NUMBER: + { + return (static_cast (rec_p))->get_prev (); + } + default: + { + JERRY_ASSERT (rec_p->get_type () < _first_type_id); + + return rcs_recordset_t::get_prev (rec_p); + } + } +} /* lit_literal_storage_t::get_prev */ + +/** + * Set pointer to the previous record + */ +void +lit_literal_storage_t::set_prev (rcs_record_t *rec_p, /**< record to modify */ + rcs_record_t *prev_rec_p) /**< record which should be set as previous */ +{ + switch (rec_p->get_type ()) + { + case LIT_STR: + { + return (static_cast (rec_p))->set_prev (prev_rec_p); + } + case LIT_MAGIC_STR: + case LIT_MAGIC_STR_EX: + { + return (static_cast (rec_p))->set_prev (prev_rec_p); + } + case LIT_NUMBER: + { + return (static_cast (rec_p))->set_prev (prev_rec_p); + } + default: + { + JERRY_ASSERT (rec_p->get_type () < _first_type_id); + + return rcs_recordset_t::set_prev (rec_p, prev_rec_p); + } + } +} /* lit_literal_storage_t::set_prev */ + +/** + * Get size of a record + * + * @return size of a record in bytes + */ +size_t +lit_literal_storage_t::get_record_size (rcs_record_t* rec_p) /**< pointer to a record */ +{ + switch (rec_p->get_type ()) + { + case LIT_STR: + { + return (static_cast (rec_p))->get_size (); + } + case LIT_MAGIC_STR: + case LIT_MAGIC_STR_EX: + { + return lit_magic_record_t::size (); + } + case LIT_NUMBER: + { + return lit_number_record_t::size (); + } + default: + { + JERRY_ASSERT (rec_p->get_type () < _first_type_id); + + return rcs_recordset_t::get_record_size (rec_p); + } + } +} /* lit_literal_storage_t::get_record_size */ + +template void rcs_record_iterator_t::skip (); +template void rcs_record_iterator_t::skip (); +template void rcs_record_iterator_t::skip (); + +template void rcs_record_iterator_t::write (ecma_char_t); +template ecma_char_t rcs_record_iterator_t::read (); + +template void rcs_record_iterator_t::write (ecma_number_t); +template ecma_number_t rcs_record_iterator_t::read (); + +template void rcs_record_iterator_t::write (uint16_t); +template uint16_t rcs_record_iterator_t::read (); + +template ecma_magic_string_id_t lit_magic_record_t::get_magic_str_id() const; +template ecma_magic_string_ex_id_t lit_magic_record_t::get_magic_str_id() const; +template void lit_magic_record_t::set_magic_str_id(ecma_magic_string_id_t); +template void lit_magic_record_t::set_magic_str_id(ecma_magic_string_ex_id_t); + +template lit_charset_record_t *rcs_recordset_t::alloc_record (rcs_record_t::type_t type, + size_t size); +template lit_magic_record_t *rcs_recordset_t::alloc_record (rcs_record_t::type_t type); +template lit_number_record_t *rcs_recordset_t::alloc_record (rcs_record_t::type_t type); + diff --git a/jerry-core/lit/lit-literal-storage.h b/jerry-core/lit/lit-literal-storage.h new file mode 100644 index 0000000000..e6949c2d5f --- /dev/null +++ b/jerry-core/lit/lit-literal-storage.h @@ -0,0 +1,438 @@ +/* Copyright 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIT_LITERAL_STORAGE_H +#define LIT_LITERAL_STORAGE_H + +#include "ecma-globals.h" +#include "rcs-recordset.h" + +class lit_literal_storage_t; +extern lit_literal_storage_t lit_storage; + +/** + * Charset record + * + * layout: + * ------- header ----------------------- + * type (4 bits) + * alignment (2 bits) + * unused (2 bits) + * hash (8 bits) + * length (16 bits) + * pointer to prev (16 bits) + * ------- characters ------------------- + * ... + * chars + * .... + * ------- alignment bytes -------------- + * unused bytes (their count is specified + * by 'alignment' field in header) + * -------------------------------------- + */ +class lit_charset_record_t : public rcs_record_t +{ + friend class rcs_recordset_t; + friend class lit_literal_storage_t; + +public: + /** + * Calculate the size that record will occupy inside the storage + * + * @return size of the record in bytes + */ + static size_t + size (size_t size) /**< size of the charset buffer */ + { + return JERRY_ALIGNUP (size + header_size (), RCS_DYN_STORAGE_LENGTH_UNIT); + } /* size */ + + /** + * Get the size of the header part of the record + * + * @return size of the header in bytes + */ + static size_t + header_size () + { + return _header_size; + } /* header_size */ + + /** + * Get the count of the alignment bytes at the end of record. + * These bytes are needed to align the record to RCS_DYN_STORAGE_ALIGNMENT. + * + * @return alignment bytes count (the value of the 'alignment' field in the header) + */ + size_t + get_alignment_bytes_count () const + { + return get_field (_alignment_field_pos, _alignment_field_width); + } /* get_alignment_bytes_count */ + + /** + * Set the count of the alignment bytes at the end of record (the value of the 'alignment' field in the header) + */ + void + set_alignment_bytes_count (size_t count) /**< count of the alignment bytes */ + { + JERRY_ASSERT (count <= RCS_DYN_STORAGE_ALIGNMENT); + set_field (_alignment_field_pos, _alignment_field_width, count); + } /* set_alignment_bytes_count */ + + /** + * Get hash value of the record's charset. + * + * @return hash value of the string (the value of the 'hash' field in the header) + */ + ecma_string_hash_t + get_hash () const + { + return (ecma_string_hash_t) get_field (_hash_field_pos, _hash_field_width); + } /* get_hash */ + + /** + * Get the length of the string, which is contained inside the record + * + * @return length of the string (count of the ecma_char_t characters inside the charset) + */ + ecma_length_t + get_length () const + { + return (ecma_length_t) ((get_size () - header_size () - get_alignment_bytes_count ()) / sizeof (ecma_char_t)); + } /* get_length */ + + /** + * Get the size of the record + * + * @return size of the record in bytes + */ + size_t + get_size () const + { + return get_field (_length_field_pos, _length_field_width) * RCS_DYN_STORAGE_LENGTH_UNIT; + } /* get_size */ + + rcs_record_t *get_prev () const; + + ecma_length_t get_charset (ecma_char_t *buff, size_t size); + + int compare_zt (const ecma_char_t *, size_t); + bool equal (lit_charset_record_t *); + bool equal_zt (const ecma_char_t *); + bool equal_non_zt (const ecma_char_t *, ecma_length_t); + +private: + /** + * Set record's size (the value of the 'length' field in the header) + */ + void + set_size (size_t size) /**< size in bytes */ + { + JERRY_ASSERT (JERRY_ALIGNUP (size, RCS_DYN_STORAGE_ALIGNMENT) == size); + + set_field (_length_field_pos, _length_field_width, size >> RCS_DYN_STORAGE_ALIGNMENT_LOG); + } /* set_size */ + + /** + * Set record's hash (the value of the 'hash' field in the header) + */ + void + set_hash (ecma_string_hash_t hash) /**< hash value */ + { + set_field (_hash_field_pos, _hash_field_width, hash); + } /* set_hash */ + + void set_prev (rcs_record_t *); + + void set_charset (const ecma_char_t *, size_t); + + /** + * Offset and length of 'alignment' field, in bits + */ + static const uint32_t _alignment_field_pos = _fields_offset_begin; + static const uint32_t _alignment_field_width = 2u; + + /** + * Offset and length of 'hash' field, in bits + */ + static const uint32_t _hash_field_pos = _alignment_field_pos + _alignment_field_width + 2u; + static const uint32_t _hash_field_width = 8u; + + /** + * Offset and length of 'alignment' field, in bits + */ + static const uint32_t _length_field_pos = _hash_field_pos + _hash_field_width; + static const uint32_t _length_field_width = 16u; + + /** + * Offset and length of 'prev' field, in bits + */ + static const uint32_t _prev_field_pos = _length_field_pos + _length_field_width; + static const uint32_t _prev_field_width = rcs_cpointer_t::bit_field_width; + + static const size_t _header_size = RCS_DYN_STORAGE_LENGTH_UNIT + RCS_DYN_STORAGE_LENGTH_UNIT / 2; +}; /* lit_charset_record_t */ + +/** + * Magic string record + * Doesn't hold any characters. Corresponding string is identified by its id. + * + * Layout: + * ------- header ----------------------- + * type (4 bits) + * magic string id (12 bits) + * pointer to prev (16 bits) + * -------------------------------------- + */ +class lit_magic_record_t : public rcs_record_t +{ + friend class rcs_recordset_t; + friend class lit_literal_storage_t; + +public: + /** + * Calculate the size that record will occupy inside the storage + * + * @return size of the record in bytes + */ + static size_t size () + { + return _size; + } /* size */ + + /** + * Get the size of the header part of the record + * + * @return size of the header in bytes + */ + static size_t header_size () + { + return _size; + } /* header_size */ + + /** + * Get the size of the record + * + * @return size of the record in bytes + */ + size_t get_size () const + { + return _size; + } /* get_size */ + + /** + * Get magic string id which is held by the record + * + * @return magic string id + */ + template + magic_string_id_t get_magic_str_id () const + { + uint32_t id = get_field (magic_field_pos, magic_field_width); + // JERRY_ASSERT (id < ECMA_MAGIC_STRING__COUNT); + return (magic_string_id_t) id; + } /* get_magic_str_id */ + +private: + /** + * Set record's size (the value of the 'length' field in the header) + */ + void set_size (size_t size) /**< size in bytes */ + { + JERRY_ASSERT (size == get_size ()); + } /* set_size */ + + template + void set_magic_str_id (magic_string_id_t id) + { + set_field (magic_field_pos, magic_field_width, id); + } /* set_magic_str_id */ + + /** + * Get previous record in the literal storage + * + * @return pointer to the previous record relative to this record, or NULL if this is the first record in the + * storage + */ + rcs_record_t *get_prev () const + { + return get_pointer (prev_field_pos, prev_field_width); + } /* get_prev */ + + /** + * Set the pointer to the previous record inside the literal storage (sets 'prev' field in the header) + */ + void set_prev (rcs_record_t *prev_rec_p) + { + set_pointer (prev_field_pos, prev_field_width, prev_rec_p); + } /* set_prev */ + + + /** + * Offset and length of 'magic string id' field, in bits + */ + static const uint32_t magic_field_pos = _fields_offset_begin; + static const uint32_t magic_field_width = 12u; + + /** + * Offset and length of 'prev' field, in bits + */ + static const uint32_t prev_field_pos = magic_field_pos + magic_field_width; + static const uint32_t prev_field_width = rcs_cpointer_t::bit_field_width; + + static const size_t _size = RCS_DYN_STORAGE_LENGTH_UNIT; +}; /* lit_magic_record_t */ + +/** + * Number record + * Doesn't hold any characters, holds a number. Numbers from source code are represented as number literals. + * + * Layout: + * ------- header ----------------------- + * type (4 bits) + * magic string id (12 bits) + * pointer to prev (16 bits) + * -------------------------------------- + */ +class lit_number_record_t : public rcs_record_t +{ + friend class rcs_recordset_t; + friend class lit_literal_storage_t; + +public: + + static size_t + size () + { + return _size; + } /* size */ + + /** + * Get the size of the header part of the record + * + * @return size of the header in bytes + */ + static size_t + header_size () + { + return _header_size; + } /* header_size */ + + /** + * Get the size of the record + * + * @return size of the record in bytes + */ + size_t + get_size () const + { + return _size; + } /* get_size */ + + /** + * Get previous record in the literal storage + * + * @return pointer to the previous record relative to this record, or NULL if this is the first record in the + * storage + */ + rcs_record_t * + get_prev () const + { + return get_pointer (prev_field_pos, prev_field_width); + } /* get_prev */ + + /** + * Set the pointer to the previous record inside the literal storage (sets 'prev' field in the header) + */ + void + set_prev (rcs_record_t *prev_rec_p) + { + set_pointer (prev_field_pos, prev_field_width, prev_rec_p); + } /* set_prev */ + + /** + * Get the number which is held by the record + * + * @return number + */ + ecma_number_t + get_number () const + { + rcs_record_iterator_t it ((rcs_recordset_t *)&lit_storage, + (rcs_record_t *)this); + it.skip (header_size ()); + + return it.read (); + } /* get_number */ + +private: + /** + * Set record's size (the value of the 'length' field in the header) + */ + void + set_size (size_t size) /**< size in bytes */ + { + JERRY_ASSERT (size == get_size ()); + } /* set_size */ + + /** + * Offset and length of 'prev' field, in bits + */ + static const uint32_t prev_field_pos = _fields_offset_begin + 12u; + static const uint32_t prev_field_width = rcs_cpointer_t::bit_field_width; + + static const size_t _header_size = RCS_DYN_STORAGE_LENGTH_UNIT; + static const size_t _size = _header_size + sizeof (ecma_number_t); +}; /* lit_number_record_t */ + +/** + * Literal storage + * + * Represents flexible storage for the literals. The following records could be created inside the storage: + * - charset literal (lit_charset_record_t) + * - magic string literal (lit_magic_record_t) + * - number literal (lit_number_record_t) + */ +class lit_literal_storage_t : public rcs_recordset_t +{ +public: + enum + { + LIT_STR = _first_type_id, + LIT_MAGIC_STR, + LIT_MAGIC_STR_EX, + LIT_NUMBER + }; + + lit_charset_record_t *create_charset_record (const ecma_char_t *, size_t); + lit_magic_record_t *create_magic_record (ecma_magic_string_id_t); + lit_magic_record_t *create_magic_record_ex (ecma_magic_string_ex_id_t); + lit_number_record_t *create_number_record (ecma_number_t); + + void dump (); + +private: + virtual rcs_record_t *get_prev (rcs_record_t *); + virtual void set_prev (rcs_record_t *, rcs_record_t *); + virtual size_t get_record_size (rcs_record_t *); +}; /* lit_literal_storage_t */ + +#define LIT_STR_T (lit_literal_storage_t::LIT_STR) +#define LIT_MAGIC_STR_T (lit_literal_storage_t::LIT_MAGIC_STR) +#define LIT_MAGIC_STR_EX_T (lit_literal_storage_t::LIT_MAGIC_STR_EX) +#define LIT_NUMBER_T (lit_literal_storage_t::LIT_NUMBER) + +#endif /* LIT_LITERAL_STORAGE_H */ diff --git a/jerry-core/lit/lit-literal.cpp b/jerry-core/lit/lit-literal.cpp new file mode 100644 index 0000000000..2b57509ef3 --- /dev/null +++ b/jerry-core/lit/lit-literal.cpp @@ -0,0 +1,555 @@ +/* Copyright 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lit-literal.h" +#include "ecma-helpers.h" + +/** + * Initialize literal storage + */ +void +lit_init () +{ + new (&lit_storage) lit_literal_storage_t (); + lit_storage.init (); +} /* lit_init */ + +/** + * Finalize literal storage + */ +void +lit_finalize () +{ + lit_storage.cleanup (); + lit_storage.finalize (); +} /* lit_finalize */ + +/** + * Dump records from the literal storage + */ +void +lit_dump_literals () +{ + lit_storage.dump (); +} /* lit_dump_literals */ + +/** + * Create new literal in literal storage from characters buffer. + * Don't check if the same literal already exists. + * + * @return pointer to created record + */ +literal_t +lit_create_literal_from_charset (const ecma_char_t *str, /**< string to initialize the record, + * could be non-zero-terminated */ + ecma_length_t len) /**< length of the string */ +{ + JERRY_ASSERT (str || !len); + for (ecma_magic_string_id_t msi = (ecma_magic_string_id_t) 0; + msi < ECMA_MAGIC_STRING__COUNT; + msi = (ecma_magic_string_id_t) (msi + 1)) + { + if (ecma_zt_string_length (ecma_get_magic_string_zt (msi)) != len) + { + continue; + } + + if (!strncmp ((const char *) str, (const char *) ecma_get_magic_string_zt (msi), len)) + { + return lit_storage.create_magic_record (msi); + } + } + + for (ecma_magic_string_ex_id_t msi = (ecma_magic_string_ex_id_t) 0; + msi < ecma_get_magic_string_ex_count (); + msi = (ecma_magic_string_ex_id_t) (msi + 1)) + { + if (ecma_zt_string_length (ecma_get_magic_string_ex_zt (msi)) != len) + { + continue; + } + + if (!strncmp ((const char *) str, (const char *) ecma_get_magic_string_ex_zt (msi), len)) + { + return lit_storage.create_magic_record_ex (msi); + } + } + + return lit_storage.create_charset_record (str, len * sizeof (ecma_char_t)); +} /* lit_create_literal_from_charset */ + +/** + * Find a literal in literal storage. + * Only charset and magic string records are checked during search. + * + * @return pointer to a literal or NULL if no corresponding literal exists + */ +literal_t +lit_find_literal_by_charset (const ecma_char_t *str, /**< a string to search for */ + ecma_length_t len) /**< length of the string */ +{ + JERRY_ASSERT (str || !len); + for (literal_t lit = lit_storage.get_first (); lit != NULL; lit = lit_storage.get_next (lit)) + { + rcs_record_t::type_t type = lit->get_type (); + + if (type == LIT_STR_T) + { + if (static_cast(lit)->get_length () != len) + { + continue; + } + + if (!static_cast(lit)->compare_zt (str, len)) + { + return lit; + } + } + else if (type == LIT_MAGIC_STR_T) + { + ecma_magic_string_id_t magic_id = lit_magic_record_get_magic_str_id (lit); + const char *magic_str = (const char *) ecma_get_magic_string_zt (magic_id); + + if (strlen (magic_str) != len) + { + continue; + } + + if (!strncmp (magic_str, (const char *) str, strlen (magic_str))) + { + return lit; + } + } + else if (type == LIT_MAGIC_STR_EX_T) + { + ecma_magic_string_ex_id_t magic_id = lit_magic_record_ex_get_magic_str_id (lit); + const char *magic_str = (const char *) ecma_get_magic_string_ex_zt (magic_id); + + if (strlen (magic_str) != len) + { + continue; + } + + if (!strncmp (magic_str, (const char *) str, strlen (magic_str))) + { + return lit; + } + } + } + + return NULL; +} /* lit_find_literal_by_charset */ + +/** + * Check if a literal which holds the passed string exists. + * If it doesn't exist, create a new one. + * + * @return pointer to existing or newly created record + */ +literal_t +lit_find_or_create_literal_from_charset (const ecma_char_t *str, /**< string, could be non-zero-terminated */ + ecma_length_t len) /**< length of the string */ +{ + literal_t lit = lit_find_literal_by_charset (str, len); + + if (lit == NULL) + { + lit = lit_create_literal_from_charset (str, len); + } + + return lit; +} /* lit_find_or_create_literal_from_s */ + + +/** + * Create new literal in literal storage from number. + * + * @return pointer to a newly created record + */ +literal_t +lit_create_literal_from_num (ecma_number_t num) /**< number to initialize a new number literal */ +{ + return lit_storage.create_number_record (num); +} /* lit_create_literal_from_num */ + +/** + * Find existing or create new number literal in literal storage. + * + * @return pointer to existing or a newly created record + */ +literal_t +lit_find_or_create_literal_from_num (ecma_number_t num) /**< number which a literal should contain */ +{ + literal_t lit = lit_find_literal_by_num (num); + + if (lit == NULL) + { + lit = lit_create_literal_from_num (num); + } + + return lit; +} /* lit_find_or_create_literal_from_num */ + +/** + * Find an existing number literal which contains the passed number + * + * @return pointer to existing or null + */ +literal_t +lit_find_literal_by_num (ecma_number_t num) /**< a number to search for */ +{ + for (literal_t lit = lit_storage.get_first (); lit != NULL; lit = lit_storage.get_next (lit)) + { + rcs_record_t::type_t type = lit->get_type (); + + if (type != LIT_NUMBER_T) + { + continue; + } + + ecma_number_t lit_num = static_cast(lit)->get_number (); + + if (lit_num == num) + { + return lit; + } + } + + return NULL; +} /* lit_find_literal_by_num */ + +/** + * Check if literal equals to charset record + * + * @return true if equal + * false otherwise + */ +static bool +lit_literal_equal_charset_rec (literal_t lit, /**< literal to compare */ + lit_charset_record_t *record) /**< charset record to compare */ +{ + switch (lit->get_type ()) + { + case LIT_STR_T: + { + return static_cast(lit)->equal (record); + } + case LIT_MAGIC_STR_T: + { + return record->equal_zt (ecma_get_magic_string_zt (lit_magic_record_get_magic_str_id (lit))); + } + case LIT_MAGIC_STR_EX_T: + { + return record->equal_zt (ecma_get_magic_string_ex_zt (lit_magic_record_ex_get_magic_str_id (lit))); + } + case LIT_NUMBER_T: + { + ecma_char_t buff[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; + ecma_number_to_zt_string (static_cast(lit)->get_number (), + buff, + ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER); + + return record->equal_zt (buff); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* lit_literal_equal_charset_rec */ + +/** + * Check if literal equals to zero-terminated string + * + * @return true if equal + * false otherwise + */ +bool +lit_literal_equal_zt (literal_t lit, /**< literal to compare */ + const ecma_char_t *str) /**< zero-terminated string to compare */ +{ + switch (lit->get_type ()) + { + case LIT_STR_T: + { + return static_cast(lit)->equal_zt (str); + } + case LIT_MAGIC_STR_T: + { + ecma_magic_string_id_t magic_id = lit_magic_record_get_magic_str_id (lit); + return ecma_compare_zt_strings (str, ecma_get_magic_string_zt (magic_id)); + } + case LIT_MAGIC_STR_EX_T: + { + ecma_magic_string_ex_id_t magic_id = lit_magic_record_ex_get_magic_str_id (lit); + return ecma_compare_zt_strings (str, ecma_get_magic_string_ex_zt (magic_id)); + } + case LIT_NUMBER_T: + { + ecma_char_t buff[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; + ecma_number_to_zt_string (static_cast(lit)->get_number (), + buff, + ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER); + + return ecma_compare_zt_strings (str, buff); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* lit_literal_equal_zt */ + +/** + * Check if literal contains the string equal to the passed number + * + * @return true if equal + * false otherwise + */ +bool +lit_literal_equal_num (literal_t lit, /**< literal to check */ + ecma_number_t num) /**< number to compare with */ +{ + ecma_char_t buff[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; + ecma_number_to_zt_string (num, buff, ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER); + + return lit_literal_equal_zt (lit, buff); +} /* lit_literal_equal_num */ + +/** + * Check if two literals are equal + * + * @return true if equal + * false otherwise + */ +bool +lit_literal_equal (literal_t lit1, /**< first literal */ + literal_t lit2) /**< second literal */ +{ + switch (lit2->get_type ()) + { + case lit_literal_storage_t::LIT_STR: + { + return lit_literal_equal_charset_rec (lit1, static_cast(lit2)); + } + case lit_literal_storage_t::LIT_MAGIC_STR: + { + return lit_literal_equal_zt (lit1, ecma_get_magic_string_zt (lit_magic_record_get_magic_str_id (lit2))); + } + case lit_literal_storage_t::LIT_MAGIC_STR_EX: + { + return lit_literal_equal_zt (lit1, ecma_get_magic_string_ex_zt (lit_magic_record_ex_get_magic_str_id (lit2))); + } + case lit_literal_storage_t::LIT_NUMBER: + { + return lit_literal_equal_num (lit1, static_cast(lit2)->get_number ()); + } + default: + { + JERRY_UNREACHABLE (); + } + } +} /* lit_literal_equal */ + +/** + * Check if literal equals to zero-terminated string. + * Check that literal is a string literal before performing detailed comparison. + * + * @return true if equal + * false otherwise + */ +bool +lit_literal_equal_type_zt (literal_t lit, /**< literal to compare */ + const ecma_char_t *str) /**< zero-terminated string */ +{ + if (lit->get_type () != LIT_STR_T + && lit->get_type () != LIT_MAGIC_STR_T + && lit->get_type () != LIT_MAGIC_STR_EX_T) + { + return false; + } + + return lit_literal_equal_zt (lit, str); +} /* lit_literal_equal_type_zt */ + +/** + * Check if literal contains the string equal to the passed number. + * Check that literal is a number literal before performing detailed comparison. + * + * @return true if equal + * false otherwise + */ +bool +lit_literal_equal_type_num (literal_t lit, /**< literal to check */ + ecma_number_t num) /**< number to compare with */ +{ + if (lit->get_type () != lit_literal_storage_t::LIT_NUMBER) + { + return false; + } + + return lit_literal_equal_num (lit, num); +} /* lit_literal_equal_type_num */ + +/** + * Check if two literals are equal + * Compare types of literals before performing detailed comparison. + * + * @return true if equal + * false otherwise + */ +bool +lit_literal_equal_type (literal_t lit1, /**< first literal */ + literal_t lit2) /**< second literal */ +{ + if (lit1->get_type () != lit2->get_type ()) + { + return false; + } + + return lit_literal_equal (lit1, lit2); +} /* lit_literal_equal_type */ + + +/** + * Get the contents of the literal as a zero-terminated string. + * If literal is a magic string record, the corresponding string is not copied to the buffer, + * but is returned directly. + * + * @return pointer to the zero-terminated string. + */ +const ecma_char_t * +lit_literal_to_charset (literal_t lit, /**< literal to be processed */ + ecma_char_t *buff, /**< buffer to use as a string storage */ + size_t size) /**< size of the buffer */ +{ + JERRY_ASSERT (buff != NULL && size > sizeof (ecma_char_t)); + rcs_record_t::type_t type = lit->get_type (); + + switch (type) + { + case LIT_STR_T: + { + lit_charset_record_t *ch_rec_p = static_cast (lit); + ecma_length_t index = ch_rec_p->get_charset (buff, size); + + if (index != 0 && ((size_t)index + 1) * sizeof (ecma_char_t) > size) + { + index--; + } + buff[index] = '\0'; + + return buff; + } + case LIT_MAGIC_STR_T: + { + return ecma_get_magic_string_zt (lit_magic_record_get_magic_str_id (lit)); + } + case LIT_MAGIC_STR_EX_T: + { + return ecma_get_magic_string_ex_zt (lit_magic_record_ex_get_magic_str_id (lit)); + } + case LIT_NUMBER_T: + { + ecma_number_to_zt_string (static_cast (lit)->get_number (), buff, (ssize_t)size); + + return buff; + } + default: JERRY_UNREACHABLE (); + } + + JERRY_UNREACHABLE (); +} /* lit_literal_to_charset */ + +/** + * Get the contents of the literal as a C string. + * If literal holds a very long string, it would be trimmed to ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER characters. + * + * @return pointer to the C string. + */ +const char * +lit_literal_to_str_internal_buf (literal_t lit) /**< literal */ +{ + const ecma_length_t buff_size = ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER; + static ecma_char_t buff[buff_size]; + + return (const char *)lit_literal_to_charset (lit, buff, buff_size); +} /* lit_literal_to_str_internal_buf */ + + +/** + * Check if literal really exists in the storage + * + * @return true if literal exists in the storage + * false otherwise + */ +static bool +lit_literal_exists (literal_t lit) /**< literal to check for existence */ +{ + for (literal_t l = lit_storage.get_first (); l != NULL; l = lit_storage.get_next (l)) + { + if (l == lit) + { + return true; + } + } + + return false; +} /* lit_literal_exists */ + +/** + * Convert compressed pointer to literal + * + * @return literal + */ +literal_t +lit_get_literal_by_cp (lit_cpointer_t lit_cp) /**< compressed pointer to literal */ +{ + JERRY_ASSERT (lit_cp.packed_value != MEM_CP_NULL); + literal_t lit = lit_cpointer_t::decompress (lit_cp); + JERRY_ASSERT (lit_literal_exists (lit)); + + return lit; +} /* lit_get_literal_by_cp */ + +ecma_string_hash_t +lit_charset_literal_get_hash (literal_t lit) /**< literal */ +{ + return static_cast (lit)->get_hash (); +} /* lit_charset_literal_get_hash */ + +ecma_magic_string_id_t +lit_magic_record_get_magic_str_id (literal_t lit) /**< literal */ +{ + return static_cast (lit)->get_magic_str_id (); +} /* lit_magic_record_get_magic_str_id */ + +ecma_magic_string_ex_id_t +lit_magic_record_ex_get_magic_str_id (literal_t lit) /**< literal */ +{ + return static_cast (lit)->get_magic_str_id (); +} /* lit_magic_record_ex_get_magic_str_id */ + +int32_t +lit_charset_record_get_length (literal_t lit) /**< literal */ +{ + return static_cast (lit)->get_length ();; +} /* lit_charset_record_get_length */ + +ecma_number_t +lit_charset_literal_get_number (literal_t lit) /**< literal */ +{ + return static_cast (lit)->get_number ();; +} /* lit_charset_literal_get_number */ diff --git a/jerry-core/lit/lit-literal.h b/jerry-core/lit/lit-literal.h new file mode 100644 index 0000000000..e3da1c9273 --- /dev/null +++ b/jerry-core/lit/lit-literal.h @@ -0,0 +1,56 @@ +/* Copyright 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIT_LITERAL_H +#define LIT_LITERAL_H + +#include "ecma-globals.h" +#include "lit-literal-storage.h" + +#define LITERAL_TO_REWRITE (INVALID_VALUE - 1) + +void lit_init (); +void lit_finalize (); +void lit_dump_literals (); + +literal_t lit_create_literal_from_charset (const ecma_char_t *, ecma_length_t); +literal_t lit_find_literal_by_charset (const ecma_char_t *, ecma_length_t); +literal_t lit_find_or_create_literal_from_charset (const ecma_char_t *, ecma_length_t); + +literal_t lit_create_literal_from_num (ecma_number_t); +literal_t lit_find_literal_by_num (ecma_number_t); +literal_t lit_find_or_create_literal_from_num (ecma_number_t); + +bool lit_literal_equal_zt (literal_t, const ecma_char_t *); +bool lit_literal_equal_num (literal_t, ecma_number_t); +bool lit_literal_equal (literal_t, literal_t); + +bool lit_literal_equal_type_zt (literal_t, const ecma_char_t *); +bool lit_literal_equal_type_num (literal_t, ecma_number_t); +bool lit_literal_equal_type (literal_t, literal_t); + +const ecma_char_t *lit_literal_to_charset (literal_t, ecma_char_t *, size_t); +const char *lit_literal_to_str_internal_buf (literal_t); + +literal_t lit_get_literal_by_cp (lit_cpointer_t); + +ecma_string_hash_t lit_charset_literal_get_hash (literal_t); +ecma_number_t lit_charset_literal_get_number (literal_t); +int32_t lit_charset_record_get_length (literal_t); + +ecma_magic_string_id_t lit_magic_record_get_magic_str_id (literal_t); +ecma_magic_string_ex_id_t lit_magic_record_ex_get_magic_str_id (literal_t); + +#endif /* LIT_LITERAL_H */ diff --git a/jerry-core/parser/collections/linked-list.cpp b/jerry-core/parser/collections/linked-list.cpp index 58193c1f4d..f9b6c2cfdc 100644 --- a/jerry-core/parser/collections/linked-list.cpp +++ b/jerry-core/parser/collections/linked-list.cpp @@ -15,9 +15,7 @@ #include "linked-list.h" #include "jrt-libc-includes.h" -#include "jrt.h" #include "mem-heap.h" -#include "lp-string.h" typedef struct linked_list_header { diff --git a/jerry-core/parser/collections/lit-id-hash-table.cpp b/jerry-core/parser/collections/lit-id-hash-table.cpp index c61aa4e5a6..924299c6ce 100644 --- a/jerry-core/parser/collections/lit-id-hash-table.cpp +++ b/jerry-core/parser/collections/lit-id-hash-table.cpp @@ -15,8 +15,6 @@ #include "lit-id-hash-table.h" #include "bytecode-data.h" -#include "mem-heap.h" -#include "jrt-libc-includes.h" lit_id_hash_table * lit_id_hash_table_init (size_t buckets_count, size_t blocks_count) @@ -24,11 +22,11 @@ lit_id_hash_table_init (size_t buckets_count, size_t blocks_count) size_t size = mem_heap_recommend_allocation_size (sizeof (lit_id_hash_table)); lit_id_hash_table *table = (lit_id_hash_table *) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_LONG_TERM); memset (table, 0, size); - size = mem_heap_recommend_allocation_size (sizeof (literal_index_t) * buckets_count); - table->raw_buckets = (literal_index_t *) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_LONG_TERM); + size = mem_heap_recommend_allocation_size (sizeof (lit_cpointer_t) * buckets_count); + table->raw_buckets = (lit_cpointer_t *) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_LONG_TERM); memset (table->raw_buckets, 0, size); - size = mem_heap_recommend_allocation_size (sizeof (literal_index_t *) * blocks_count); - table->buckets = (literal_index_t **) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_LONG_TERM); + size = mem_heap_recommend_allocation_size (sizeof (lit_cpointer_t *) * blocks_count); + table->buckets = (lit_cpointer_t **) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_LONG_TERM); memset (table->buckets, 0, size); table->current_bucket_pos = 0; return table; @@ -44,7 +42,7 @@ lit_id_hash_table_free (lit_id_hash_table *table) } void -lit_id_hash_table_insert (lit_id_hash_table *table, idx_t uid, opcode_counter_t oc, literal_index_t lit_id) +lit_id_hash_table_insert (lit_id_hash_table *table, idx_t uid, opcode_counter_t oc, lit_cpointer_t lit_cp) { JERRY_ASSERT (table); size_t block_id = oc / BLOCK_SIZE; @@ -52,11 +50,11 @@ lit_id_hash_table_insert (lit_id_hash_table *table, idx_t uid, opcode_counter_t { table->buckets[block_id] = table->raw_buckets + table->current_bucket_pos; } - table->buckets[block_id][uid] = lit_id; + table->buckets[block_id][uid] = lit_cp; table->current_bucket_pos++; } -literal_index_t +lit_cpointer_t lit_id_hash_table_lookup (lit_id_hash_table *table, idx_t uid, opcode_counter_t oc) { JERRY_ASSERT (table); diff --git a/jerry-core/parser/collections/lit-id-hash-table.h b/jerry-core/parser/collections/lit-id-hash-table.h index 2aa48569ad..94ef734690 100644 --- a/jerry-core/parser/collections/lit-id-hash-table.h +++ b/jerry-core/parser/collections/lit-id-hash-table.h @@ -19,17 +19,18 @@ #include "jrt.h" #include "ecma-globals.h" #include "opcodes.h" +#include "lit-literal.h" typedef struct { size_t current_bucket_pos; - literal_index_t *raw_buckets; - literal_index_t **buckets; + lit_cpointer_t *raw_buckets; + lit_cpointer_t **buckets; } lit_id_hash_table; lit_id_hash_table *lit_id_hash_table_init (size_t, size_t); void lit_id_hash_table_free (lit_id_hash_table *); -void lit_id_hash_table_insert (lit_id_hash_table *, idx_t, opcode_counter_t, literal_index_t); -literal_index_t lit_id_hash_table_lookup (lit_id_hash_table *, idx_t, opcode_counter_t); +void lit_id_hash_table_insert (lit_id_hash_table *, idx_t, opcode_counter_t, lit_cpointer_t); +lit_cpointer_t lit_id_hash_table_lookup (lit_id_hash_table *, idx_t, opcode_counter_t); #endif /* LIT_ID_HASH_TABLE */ diff --git a/jerry-core/parser/collections/lp-string.cpp b/jerry-core/parser/collections/lp-string.cpp deleted file mode 100644 index 2b98448dbb..0000000000 --- a/jerry-core/parser/collections/lp-string.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright 2014-2015 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "lp-string.h" -#include "jrt-libc-includes.h" - -bool -lp_string_equal (lp_string s1, lp_string s2) -{ - if (s1.length != s2.length) - { - return false; - } - - for (ecma_length_t i = 0; i < s1.length; i++) - { - JERRY_ASSERT (s1.str[i] != '\0' && s1.str[i] != '\0'); - if (s1.str[i] != s2.str[i]) - { - return false; - } - } - - return true; -} - -bool -lp_string_equal_s (lp_string lp, const char *s) -{ - return lp_string_equal_zt (lp, (const ecma_char_t *) s); -} - -bool -lp_string_equal_zt (lp_string lp, const ecma_char_t *s) -{ - for (ecma_length_t i = 0; i < lp.length; i++) - { - JERRY_ASSERT (lp.str[i] != '\0'); - if (lp.str[i] != s[i]) - { - return false; - } - } - - if (s[lp.length] != '\0') - { - return false; - } - - return true; -} diff --git a/jerry-core/parser/collections/lp-string.h b/jerry-core/parser/collections/lp-string.h deleted file mode 100644 index b5958d5ff1..0000000000 --- a/jerry-core/parser/collections/lp-string.h +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright 2014 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LP_STRING -#define LP_STRING - -#include "ecma-globals.h" - -/* Length-prefixed or "pascal" string. */ -typedef struct -{ - const ecma_char_t *str; - ecma_length_t length; - ecma_string_hash_t hash; -} lp_string; - -bool lp_string_equal (lp_string, lp_string); -bool lp_string_equal_s (lp_string, const char *); -bool lp_string_equal_zt (lp_string, const ecma_char_t *); - -#endif /* LP_STRING */ diff --git a/jerry-core/parser/js/bytecode-data.h b/jerry-core/parser/js/bytecode-data.h index 978d226e2e..7e2f881791 100644 --- a/jerry-core/parser/js/bytecode-data.h +++ b/jerry-core/parser/js/bytecode-data.h @@ -17,7 +17,6 @@ #define BYTECODE_DATA_H #include "opcodes.h" -#include "literal.h" #include "lit-id-hash-table.h" /* @@ -38,10 +37,8 @@ typedef struct { const ecma_char_t *strings_buffer; - const literal *literals; const opcode_t *opcodes; lit_id_hash_table *lit_id_hash; - literal_index_t literals_count; opcode_counter_t opcodes_count; } bytecode_data_t; diff --git a/jerry-core/parser/js/lexer.cpp b/jerry-core/parser/js/lexer.cpp index 54d5bed2d9..e5b110b532 100644 --- a/jerry-core/parser/js/lexer.cpp +++ b/jerry-core/parser/js/lexer.cpp @@ -16,11 +16,7 @@ #include "mem-allocator.h" #include "jrt-libc-includes.h" #include "lexer.h" -#include "parser.h" -#include "stack.h" -#include "opcodes.h" #include "syntax-errors.h" -#include "parser.h" #include "ecma-helpers.h" static token saved_token, prev_token, sent_token, empty_token; @@ -32,18 +28,9 @@ static size_t buffer_size = 0; static const char *buffer_start = NULL; static const char *buffer = NULL; static const char *token_start; -static ecma_char_t *strings_cache; -static size_t strings_cache_size; -static size_t strings_cache_used_size; #define LA(I) (get_char (I)) -enum -{ - literals_global_size -}; -STATIC_STACK (literals, literal) - static bool is_empty (token tok) { @@ -93,101 +80,34 @@ dump_current_line (void) } static token -create_token (token_type type, literal_index_t uid) +create_token_from_lit (token_type type, literal_t lit) { token ret; ret.type = type; ret.loc = current_locus () - (type == TOK_STRING ? 1 : 0); - ret.uid = uid; + ret.uid = lit_cpointer_t::compress (lit).packed_value; return ret; } /** - * Compare specified string to literal + * Create token of specified type * - * @return true - if the literal contains exactly the specified string, - * false - otherwise. + * @return token descriptor */ -static bool -string_equals_to_literal (const ecma_char_t *str_p, /**< characters buffer */ - ecma_length_t length, /**< string's length */ - literal lit) /**< literal */ -{ - if (lit.type == LIT_STR) - { - if (lit.data.lp.length == length - && strncmp ((const char *) lit.data.lp.str, (const char*) str_p, length) == 0) - { - return true; - } - } - else if (lit.type == LIT_MAGIC_STR) - { - const char *magic_str_p = (const char *) ecma_get_magic_string_zt (lit.data.magic_str_id); - - if (strlen (magic_str_p) == length - && strncmp (magic_str_p, (const char*) str_p, length) == 0) - { - return true; - } - } - else if (lit.type == LIT_MAGIC_STR_EX) - { - const char *magic_str_p = (const char *) ecma_get_magic_string_ex_zt (lit.data.magic_str_ex_id); - - if (strlen (magic_str_p) == length - && strncmp (magic_str_p, (const char*) str_p, length) == 0) - { - return true; - } - } - - return false; -} /* string_equals_to_literal */ - -static literal -adjust_string_ptrs (literal lit, size_t diff) +static token +create_token (token_type type, /**< type of token */ + uint16_t uid) /**< uid of token */ { - if (lit.type != LIT_STR) - { - return lit; - } - - literal ret; + token ret; - ret.type = LIT_STR; - ret.data.lp.length = lit.data.lp.length; - ret.data.lp.hash = lit.data.lp.hash; - ret.data.lp.str = lit.data.lp.str + diff; + ret.type = type; + ret.loc = current_locus () - (type == TOK_STRING ? 1 : 0); + ret.uid = uid; return ret; -} - -static literal -add_string_to_string_cache (const ecma_char_t* str, ecma_length_t length) -{ - if (strings_cache_used_size + length * sizeof (ecma_char_t) >= strings_cache_size) - { - strings_cache_size = mem_heap_recommend_allocation_size (strings_cache_used_size - + ((size_t) length + 1) * sizeof (ecma_char_t)); - ecma_char_t *temp = (ecma_char_t *) mem_heap_alloc_block (strings_cache_size, - MEM_HEAP_ALLOC_SHORT_TERM); - if (strings_cache) - { - memcpy (temp, strings_cache, strings_cache_used_size); - STACK_ITERATE_VARG_SET (literals, adjust_string_ptrs, 0, (size_t) (temp - strings_cache)); - mem_heap_free_block ((uint8_t *) strings_cache); - } - strings_cache = temp; - } - strncpy ((char *) (strings_cache + strings_cache_used_size), (const char*) str, length); - (strings_cache + strings_cache_used_size)[length] = '\0'; - const literal res = create_literal_from_zt (strings_cache + strings_cache_used_size, length); - strings_cache_used_size = (size_t) (((size_t) length + 1) * sizeof (ecma_char_t) + strings_cache_used_size); - return res; -} +} /* create_token */ /** * Convert string to token of specified type @@ -201,30 +121,22 @@ convert_string_to_token (token_type tt, /**< token type */ { JERRY_ASSERT (str_p != NULL); - for (literal_index_t i = 0; i < STACK_SIZE (literals); i++) + literal_t lit = lit_find_literal_by_charset (str_p, length); + if (lit != NULL) { - const literal lit = STACK_ELEMENT (literals, i); - if ((lit.type == LIT_STR || lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX) - && string_equals_to_literal (str_p, length, lit)) - { - return create_token (tt, i); - } + return create_token_from_lit (tt, lit); } - literal lit = create_literal_from_str (str_p, length); - JERRY_ASSERT (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX); - if (lit.type == LIT_STR) - { - lit = add_string_to_string_cache (str_p, length); - } + lit = lit_create_literal_from_charset (str_p, length); + JERRY_ASSERT (lit->get_type () == LIT_STR_T + || lit->get_type () == LIT_MAGIC_STR_T + || lit->get_type () == LIT_MAGIC_STR_EX_T); - STACK_PUSH (literals, lit); - - return create_token (tt, (literal_index_t) (STACK_SIZE (literals) - 1)); + return create_token_from_lit (tt, lit); } /** - * Try to decore specified string as keyword + * Try to decode specified string as keyword * * @return if specified string represents a keyword, return corresponding keyword token, * else if it is 'null' - return TOK_NULL token, @@ -360,85 +272,13 @@ decode_keyword (const ecma_char_t *str_p, /**< characters buffer */ static token convert_seen_num_to_token (ecma_number_t num) { - for (literal_index_t i = 0; i < STACK_SIZE (literals); i++) - { - const literal lit = STACK_ELEMENT (literals, i); - if (lit.type != LIT_NUMBER) - { - continue; - } - if (lit.data.num == num) - { - return create_token (TOK_NUMBER, i); - } - } - - STACK_PUSH (literals, create_literal_from_num (num)); - - return create_token (TOK_NUMBER, (literal_index_t) (STACK_SIZE (literals) - 1)); -} - -const literal * -lexer_get_literals (void) -{ - literal *data = NULL; - if (STACK_SIZE (literals) > 0) - { - STACK_CONVERT_TO_RAW_DATA (literals, data); - } - return data; -} - -literal_index_t -lexer_get_literals_count (void) -{ - return (literal_index_t) STACK_SIZE (literals); -} - -literal_index_t -lexer_lookup_literal_uid (literal lit) -{ - for (literal_index_t i = 0; i < STACK_SIZE (literals); i++) + literal_t lit = lit_find_literal_by_num (num); + if (lit != NULL) { - if (literal_equal_type (STACK_ELEMENT (literals, i), lit)) - { - return i; - } + return create_token_from_lit (TOK_NUMBER, lit); } - return INVALID_VALUE; -} -literal -lexer_get_literal_by_id (literal_index_t id) -{ - JERRY_ASSERT (id != INVALID_LITERAL); - JERRY_ASSERT (id < STACK_SIZE (literals)); - return STACK_ELEMENT (literals, id); -} - -const ecma_char_t * -lexer_get_strings_cache (void) -{ - return strings_cache; -} - -void -lexer_add_keyword_or_numeric_literal_if_not_present (literal lit) -{ - for (literal_index_t i = 0; i < STACK_SIZE (literals); i++) - { - if (literal_equal_type (STACK_ELEMENT (literals, i), lit)) - { - return; - } - } - - if (lit.type == LIT_STR) - { - lit = add_string_to_string_cache (lit.data.lp.str, lit.data.lp.length); - } - - STACK_PUSH (literals, lit); + return create_token_from_lit (TOK_NUMBER, lit_create_literal_from_num (num)); } static void @@ -1644,15 +1484,10 @@ lexer_init (const char *source, size_t source_size, bool show_opcodes) buffer_size = source_size; lexer_set_source (source); - strings_cache = NULL; - strings_cache_used_size = strings_cache_size = 0; lexer_set_strict_mode (false); - - STACK_INIT (literals); } void lexer_free (void) { - STACK_FREE (literals); } diff --git a/jerry-core/parser/js/lexer.h b/jerry-core/parser/js/lexer.h index edc7b9762d..4f1caba8be 100644 --- a/jerry-core/parser/js/lexer.h +++ b/jerry-core/parser/js/lexer.h @@ -16,10 +16,10 @@ #ifndef LEXER_H #define LEXER_H -#include "literal.h" +#include "lit-literal.h" #define INVALID_VALUE 255 -#define INVALID_LITERAL ((uint32_t) -1) +#define INVALID_LITERAL (rcs_cpointer_t::null_cp ()) /* Keywords. */ typedef enum __attr_packed___ @@ -160,7 +160,7 @@ typedef struct { locus loc; token_type type; - literal_index_t uid; + uint16_t uid; } token; /** @@ -175,13 +175,6 @@ token lexer_next_token (void); void lexer_save_token (token); token lexer_prev_token (void); -const literal *lexer_get_literals (void); -const ecma_char_t *lexer_get_strings_cache (void); -void lexer_add_keyword_or_numeric_literal_if_not_present (literal); -literal_index_t lexer_get_literals_count (void); -literal lexer_get_literal_by_id (literal_index_t); -literal_index_t lexer_lookup_literal_uid (literal lit); - void lexer_seek (locus); void lexer_locus_to_line_and_column (locus, size_t *, size_t *); void lexer_dump_line (size_t); diff --git a/jerry-core/parser/js/literal.cpp b/jerry-core/parser/js/literal.cpp deleted file mode 100644 index ca143850ff..0000000000 --- a/jerry-core/parser/js/literal.cpp +++ /dev/null @@ -1,275 +0,0 @@ -/* Copyright 2014-2015 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "literal.h" -#include "ecma-helpers.h" -#include "jrt-libc-includes.h" - -literal -create_empty_literal (void) -{ - literal ret; - - ret.type = LIT_UNKNOWN; - ret.data.none = NULL; - - return ret; -} - -literal -create_literal_from_num (ecma_number_t num) -{ - literal ret; - - ret.type = LIT_NUMBER; - ret.data.num = num; - - return ret; -} - -/** - * Create literal from string - * - * @return literal descriptor - */ -literal -create_literal_from_str (const ecma_char_t *s, /**< characters buffer */ - ecma_length_t len) /**< string's length */ -{ - return create_literal_from_zt (s, len); -} /* create_literal_from_str */ - -literal -create_literal_from_str_compute_len (const char *s) -{ - return create_literal_from_zt ((const ecma_char_t *) s, (ecma_length_t) strlen (s)); -} - -literal -create_literal_from_zt (const ecma_char_t *s, ecma_length_t len) -{ - for (ecma_magic_string_id_t msi = (ecma_magic_string_id_t) 0; - msi < ECMA_MAGIC_STRING__COUNT; - msi = (ecma_magic_string_id_t) (msi + 1)) - { - if (ecma_zt_string_length (ecma_get_magic_string_zt (msi)) != len) - { - continue; - } - if (!strncmp ((const char *) s, (const char *) ecma_get_magic_string_zt (msi), len)) - { - literal ret; - - ret.type = LIT_MAGIC_STR; - ret.data.magic_str_id = msi; - - return ret; - } - } - - uint32_t ex_count = ecma_get_magic_string_ex_count (); - for (ecma_magic_string_ex_id_t msi = (ecma_magic_string_ex_id_t) 0; - msi < ex_count; - msi = (ecma_magic_string_id_t) (msi + 1)) - { - const ecma_char_t* ex_string = ecma_get_magic_string_ex_zt (msi); - if (ecma_zt_string_length (ex_string) != len) - { - continue; - } - if (!strncmp ((const char *) s, (const char *) ex_string, len)) - { - literal ret; - - ret.type = LIT_MAGIC_STR_EX; - ret.data.magic_str_ex_id = msi; - - return ret; - } - } - - literal ret; - - ret.type = LIT_STR; - ret.data.lp.length = len; - ret.data.lp.str = s; - ret.data.lp.hash = ecma_chars_buffer_calc_hash_last_chars (s, len); - - return ret; -} - -bool -literal_equal_type (literal lit1, literal lit2) -{ - if (lit1.type != lit2.type) - { - return false; - } - return literal_equal (lit1, lit2); -} - -bool -literal_equal_type_s (literal lit, const char *s) -{ - return literal_equal_type_zt (lit, (const ecma_char_t *) s); -} - -bool -literal_equal_type_zt (literal lit, const ecma_char_t *s) -{ - if (lit.type != LIT_STR && lit.type != LIT_MAGIC_STR && lit.type != LIT_MAGIC_STR_EX) - { - return false; - } - return literal_equal_zt (lit, s); -} - -bool -literal_equal_type_num (literal lit, ecma_number_t num) -{ - if (lit.type != LIT_NUMBER) - { - return false; - } - return literal_equal_num (lit, num); -} - -static bool -literal_equal_lp (literal lit, lp_string lp) -{ - switch (lit.type) - { - case LIT_UNKNOWN: - { - return false; - } - case LIT_STR: - { - return lp_string_equal (lit.data.lp, lp); - } - case LIT_MAGIC_STR: - { - return lp_string_equal_zt (lp, ecma_get_magic_string_zt (lit.data.magic_str_id)); - } - case LIT_MAGIC_STR_EX: - { - return lp_string_equal_zt (lp, ecma_get_magic_string_ex_zt (lit.data.magic_str_ex_id)); - } - case LIT_NUMBER: - { - ecma_char_t buff[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; - ecma_number_to_zt_string (lit.data.num, buff, ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER); - return lp_string_equal_zt (lp, buff); - } - default: - { - JERRY_UNREACHABLE (); - } - } -} - -bool -literal_equal (literal lit1, literal lit2) -{ - switch (lit2.type) - { - case LIT_UNKNOWN: - { - return lit2.type == LIT_UNKNOWN; - } - case LIT_STR: - { - return literal_equal_lp (lit1, lit2.data.lp); - } - case LIT_MAGIC_STR: - { - return literal_equal_zt (lit1, ecma_get_magic_string_zt (lit2.data.magic_str_id)); - } - case LIT_MAGIC_STR_EX: - { - return literal_equal_zt (lit1, ecma_get_magic_string_ex_zt (lit2.data.magic_str_ex_id)); - } - case LIT_NUMBER: - { - return literal_equal_num (lit1, lit2.data.num); - } - default: - { - JERRY_UNREACHABLE (); - } - } -} - -bool -literal_equal_s (literal lit, const char *s) -{ - return literal_equal_zt (lit, (const ecma_char_t *) s); -} - -bool -literal_equal_zt (literal lit, const ecma_char_t *s) -{ - switch (lit.type) - { - case LIT_UNKNOWN: - { - return false; - } - case LIT_STR: - { - return lp_string_equal_zt (lit.data.lp, s); - } - case LIT_MAGIC_STR: - { - return ecma_compare_zt_strings (s, ecma_get_magic_string_zt (lit.data.magic_str_id)); - } - case LIT_MAGIC_STR_EX: - { - return ecma_compare_zt_strings (s, ecma_get_magic_string_ex_zt (lit.data.magic_str_ex_id)); - } - case LIT_NUMBER: - { - ecma_char_t buff[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; - ecma_number_to_zt_string (lit.data.num, buff, ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER); - return ecma_compare_zt_strings (s, buff); - } - default: - { - JERRY_UNREACHABLE (); - } - } -} - -bool -literal_equal_num (literal lit, ecma_number_t num) -{ - ecma_char_t buff[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; - ecma_number_to_zt_string (num, buff, ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER); - return literal_equal_zt (lit, buff); -} - -const ecma_char_t * -literal_to_zt (literal lit) -{ - JERRY_ASSERT (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX); - - switch (lit.type) - { - case LIT_STR: return lit.data.lp.str; - case LIT_MAGIC_STR: return ecma_get_magic_string_zt (lit.data.magic_str_id); - case LIT_MAGIC_STR_EX: return ecma_get_magic_string_ex_zt (lit.data.magic_str_ex_id); - default: JERRY_UNREACHABLE (); - } -} diff --git a/jerry-core/parser/js/literal.h b/jerry-core/parser/js/literal.h deleted file mode 100644 index b2dfd3c98e..0000000000 --- a/jerry-core/parser/js/literal.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright 2015 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LITERAL_H -#define LITERAL_H - -#include "ecma-globals.h" -#include "lp-string.h" - -typedef enum __attr_packed___ -{ - LIT_UNKNOWN, - LIT_STR, - LIT_MAGIC_STR, - LIT_MAGIC_STR_EX, - LIT_NUMBER -} literal_type; - -typedef struct -{ - union - { - ecma_magic_string_id_t magic_str_id; - ecma_magic_string_ex_id_t magic_str_ex_id; - ecma_number_t num; - lp_string lp; - void *none; - } data; - literal_type type; -} literal; - -#define LITERAL_TO_REWRITE (INVALID_VALUE - 1) - -literal create_empty_literal (void); -literal create_literal_from_num (ecma_number_t); -literal create_literal_from_str (const ecma_char_t*, ecma_length_t); -literal create_literal_from_str_compute_len (const char *); -literal create_literal_from_zt (const ecma_char_t *, ecma_length_t); -bool literal_equal (literal, literal); -bool literal_equal_s (literal, const char *); -bool literal_equal_zt (literal, const ecma_char_t *); -bool literal_equal_num (literal, ecma_number_t); -bool literal_equal_type (literal, literal); -bool literal_equal_type_s (literal, const char *); -bool literal_equal_type_zt (literal, const ecma_char_t *); -bool literal_equal_type_num (literal, ecma_number_t); -const ecma_char_t *literal_to_zt (literal); - -#endif /* LITERAL_H */ diff --git a/jerry-core/parser/js/opcodes-dumper.cpp b/jerry-core/parser/js/opcodes-dumper.cpp index 51eaf476bf..5abb95d824 100644 --- a/jerry-core/parser/js/opcodes-dumper.cpp +++ b/jerry-core/parser/js/opcodes-dumper.cpp @@ -14,14 +14,11 @@ */ #include "opcodes-dumper.h" + #include "serializer.h" -#include "jrt.h" -#include "lexer.h" #include "stack.h" #include "syntax-errors.h" -#include "jrt-libc-includes.h" #include "opcodes-native-call.h" -#include "serializer.h" #define MIN_TEMP_NAME 128 static idx_t temp_name, max_temp_name; @@ -136,7 +133,7 @@ next_temp_name (void) } static op_meta -create_op_meta (opcode_t op, literal_index_t lit_id1, literal_index_t lit_id2, literal_index_t lit_id3) +create_op_meta (opcode_t op, lit_cpointer_t lit_id1, lit_cpointer_t lit_id2, lit_cpointer_t lit_id3) { op_meta ret; @@ -155,43 +152,43 @@ create_op_meta_000 (opcode_t op) } static op_meta -create_op_meta_001 (opcode_t op, literal_index_t lit_id) +create_op_meta_001 (opcode_t op, lit_cpointer_t lit_id) { return create_op_meta (op, NOT_A_LITERAL, NOT_A_LITERAL, lit_id); } static op_meta -create_op_meta_010 (opcode_t op, literal_index_t lit_id) +create_op_meta_010 (opcode_t op, lit_cpointer_t lit_id) { return create_op_meta (op, NOT_A_LITERAL, lit_id, NOT_A_LITERAL); } static op_meta -create_op_meta_011 (opcode_t op, literal_index_t lit_id2, literal_index_t lit_id3) +create_op_meta_011 (opcode_t op, lit_cpointer_t lit_id2, lit_cpointer_t lit_id3) { return create_op_meta (op, NOT_A_LITERAL, lit_id2, lit_id3); } static op_meta -create_op_meta_100 (opcode_t op, literal_index_t lit_id) +create_op_meta_100 (opcode_t op, lit_cpointer_t lit_id) { return create_op_meta (op, lit_id, NOT_A_LITERAL, NOT_A_LITERAL); } static op_meta -create_op_meta_101 (opcode_t op, literal_index_t lit_id1, literal_index_t lit_id3) +create_op_meta_101 (opcode_t op, lit_cpointer_t lit_id1, lit_cpointer_t lit_id3) { return create_op_meta (op, lit_id1, NOT_A_LITERAL, lit_id3); } static op_meta -create_op_meta_110 (opcode_t op, literal_index_t lit_id1, literal_index_t lit_id2) +create_op_meta_110 (opcode_t op, lit_cpointer_t lit_id1, lit_cpointer_t lit_id2) { return create_op_meta (op, lit_id1, lit_id2, NOT_A_LITERAL); } static op_meta -create_op_meta_111 (opcode_t op, literal_index_t lit_id1, literal_index_t lit_id2, literal_index_t lit_id3) +create_op_meta_111 (opcode_t op, lit_cpointer_t lit_id1, lit_cpointer_t lit_id2, lit_cpointer_t lit_id3) { return create_op_meta (op, lit_id1, lit_id2, lit_id3); } @@ -214,27 +211,27 @@ name_to_native_call_id (operand obj) { return OPCODE_NATIVE_CALL__COUNT; } - if (literal_equal_type_s (lexer_get_literal_by_id (obj.data.lit_id), "LEDToggle")) + if (lit_literal_equal_type_zt (lit_get_literal_by_cp (obj.data.lit_id), (const ecma_char_t *) "LEDToggle")) { return OPCODE_NATIVE_CALL_LED_TOGGLE; } - else if (literal_equal_type_s (lexer_get_literal_by_id (obj.data.lit_id), "LEDOn")) + else if (lit_literal_equal_type_zt (lit_get_literal_by_cp (obj.data.lit_id), (const ecma_char_t *) "LEDOn")) { return OPCODE_NATIVE_CALL_LED_ON; } - else if (literal_equal_type_s (lexer_get_literal_by_id (obj.data.lit_id), "LEDOff")) + else if (lit_literal_equal_type_zt (lit_get_literal_by_cp (obj.data.lit_id), (const ecma_char_t *) "LEDOff")) { return OPCODE_NATIVE_CALL_LED_OFF; } - else if (literal_equal_type_s (lexer_get_literal_by_id (obj.data.lit_id), "LEDOnce")) + else if (lit_literal_equal_type_zt (lit_get_literal_by_cp (obj.data.lit_id), (const ecma_char_t *) "LEDOnce")) { return OPCODE_NATIVE_CALL_LED_ONCE; } - else if (literal_equal_type_s (lexer_get_literal_by_id (obj.data.lit_id), "wait")) + else if (lit_literal_equal_type_zt (lit_get_literal_by_cp (obj.data.lit_id), (const ecma_char_t *) "wait")) { return OPCODE_NATIVE_CALL_WAIT; } - else if (literal_equal_type_s (lexer_get_literal_by_id (obj.data.lit_id), "print")) + else if (lit_literal_equal_type_zt (lit_get_literal_by_cp (obj.data.lit_id), (const ecma_char_t *) "print")) { return OPCODE_NATIVE_CALL_PRINT; } @@ -614,11 +611,11 @@ dump_prop_setter_op_meta (op_meta last, operand op) } static operand -create_operand_from_tmp_and_lit (idx_t tmp, literal_index_t lit_id) +create_operand_from_tmp_and_lit (idx_t tmp, lit_cpointer_t lit_id) { if (tmp != LITERAL_TO_REWRITE) { - JERRY_ASSERT (lit_id == NOT_A_LITERAL); + JERRY_ASSERT (lit_id.packed_value == MEM_CP_NULL); operand ret; @@ -629,7 +626,7 @@ create_operand_from_tmp_and_lit (idx_t tmp, literal_index_t lit_id) } else { - JERRY_ASSERT (lit_id != NOT_A_LITERAL); + JERRY_ASSERT (lit_id.packed_value != MEM_CP_NULL); operand ret; @@ -688,12 +685,12 @@ empty_operand (void) } operand -literal_operand (literal_index_t lit_id) +literal_operand (lit_cpointer_t lit_cp) { operand ret; ret.type = OPERAND_LITERAL; - ret.data.lit_id = lit_id; + ret.data.lit_id = lit_cp; return ret; } @@ -733,7 +730,7 @@ dumper_is_intrinsic (operand obj) { if (obj.type == OPERAND_LITERAL) { - if (literal_equal_type_s (lexer_get_literal_by_id (obj.data.lit_id), "assert")) + if (lit_literal_equal_type_zt (lit_get_literal_by_cp (obj.data.lit_id), (const ecma_char_t *) "assert")) { return true; } @@ -746,7 +743,7 @@ dump_intrinsic (operand obj, operand arg) { JERRY_ASSERT (obj.type == OPERAND_LITERAL); TODO (/* Rewrite when there will be more intrinsics. */) - JERRY_ASSERT (literal_equal_type_s (lexer_get_literal_by_id (obj.data.lit_id), "assert")); + JERRY_ASSERT (lit_literal_equal_type_zt (lit_get_literal_by_cp (obj.data.lit_id), (const ecma_char_t *) "assert")); dump_assert (arg); return dump_undefined_assignment_res (); } @@ -786,7 +783,7 @@ dump_boolean_assignment_res (bool is_true) } void -dump_string_assignment (operand op, literal_index_t lit_id) +dump_string_assignment (operand op, lit_cpointer_t lit_id) { switch (op.type) { @@ -806,7 +803,7 @@ dump_string_assignment (operand op, literal_index_t lit_id) } operand -dump_string_assignment_res (literal_index_t lit_id) +dump_string_assignment_res (lit_cpointer_t lit_id) { operand op = tmp_operand (); dump_string_assignment (op, lit_id); @@ -814,7 +811,7 @@ dump_string_assignment_res (literal_index_t lit_id) } void -dump_number_assignment (operand op, literal_index_t lit_id) +dump_number_assignment (operand op, lit_cpointer_t lit_id) { switch (op.type) { @@ -834,7 +831,7 @@ dump_number_assignment (operand op, literal_index_t lit_id) } operand -dump_number_assignment_res (literal_index_t lit_id) +dump_number_assignment_res (lit_cpointer_t lit_id) { operand op = tmp_operand (); dump_number_assignment (op, lit_id); @@ -1097,15 +1094,17 @@ void dump_prop_name_and_value (operand name, operand value) { JERRY_ASSERT (name.type == OPERAND_LITERAL); - const literal lit = lexer_get_literal_by_id (name.data.lit_id); + literal_t lit = lit_get_literal_by_cp (name.data.lit_id); operand tmp; - if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX) + if (lit->get_type () == LIT_STR_T + || lit->get_type () == LIT_MAGIC_STR_T + || lit->get_type () == LIT_MAGIC_STR_EX_T) { tmp = dump_string_assignment_res (name.data.lit_id); } else { - JERRY_ASSERT (lit.type == LIT_NUMBER); + JERRY_ASSERT (lit->get_type () == LIT_NUMBER_T); tmp = dump_number_assignment_res (name.data.lit_id); } switch (value.type) @@ -1130,15 +1129,17 @@ dump_prop_getter_decl (operand name, operand func) { JERRY_ASSERT (name.type == OPERAND_LITERAL); JERRY_ASSERT (func.type == OPERAND_TMP); - const literal lit = lexer_get_literal_by_id (name.data.lit_id); + literal_t lit = lit_get_literal_by_cp (name.data.lit_id); operand tmp; - if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX) + if (lit->get_type () == LIT_STR_T + || lit->get_type () == LIT_MAGIC_STR_T + || lit->get_type () == LIT_MAGIC_STR_EX_T) { tmp = dump_string_assignment_res (name.data.lit_id); } else { - JERRY_ASSERT (lit.type == LIT_NUMBER); + JERRY_ASSERT (lit->get_type () == LIT_NUMBER_T); tmp = dump_number_assignment_res (name.data.lit_id); } const opcode_t opcode = getop_meta (OPCODE_META_TYPE_VARG_PROP_GETTER, tmp.data.uid, func.data.uid); @@ -1150,15 +1151,17 @@ dump_prop_setter_decl (operand name, operand func) { JERRY_ASSERT (name.type == OPERAND_LITERAL); JERRY_ASSERT (func.type == OPERAND_TMP); - const literal lit = lexer_get_literal_by_id (name.data.lit_id); + literal_t lit = lit_get_literal_by_cp (name.data.lit_id); operand tmp; - if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX) + if (lit->get_type () == LIT_STR_T + || lit->get_type () == LIT_MAGIC_STR_T + || lit->get_type () == LIT_MAGIC_STR_EX_T) { tmp = dump_string_assignment_res (name.data.lit_id); } else { - JERRY_ASSERT (lit.type == LIT_NUMBER); + JERRY_ASSERT (lit->get_type () == LIT_NUMBER_T); tmp = dump_number_assignment_res (name.data.lit_id); } const opcode_t opcode = getop_meta (OPCODE_META_TYPE_VARG_PROP_SETTER, tmp.data.uid, func.data.uid); @@ -1347,8 +1350,10 @@ dump_delete (operand res, operand op, bool is_strict, locus loc) { case OPERAND_LITERAL: { - const literal lit = lexer_get_literal_by_id (op.data.lit_id); - if (lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX || lit.type == LIT_STR) + literal_t lit = lit_get_literal_by_cp (op.data.lit_id); + if (lit->get_type () == LIT_STR_T + || lit->get_type () == LIT_MAGIC_STR_T + || lit->get_type () == LIT_MAGIC_STR_EX_T) { syntax_check_delete (is_strict, loc); switch (res.type) @@ -1368,7 +1373,7 @@ dump_delete (operand res, operand op, bool is_strict, locus loc) } break; } - else if (lit.type == LIT_NUMBER) + else if (lit->get_type () == LIT_NUMBER_T) { dump_boolean_assignment (res, true); } @@ -2372,7 +2377,7 @@ dump_throw (operand op) } bool -dumper_variable_declaration_exists (literal_index_t lit_id) +dumper_variable_declaration_exists (lit_cpointer_t lit_id) { for (opcode_counter_t oc = (opcode_counter_t) (serializer_get_current_opcode_counter () - 1); oc > 0; oc--) @@ -2382,7 +2387,7 @@ dumper_variable_declaration_exists (literal_index_t lit_id) { break; } - if (var_decl_op_meta.lit_id[0] == lit_id) + if (var_decl_op_meta.lit_id[0].packed_value == lit_id.packed_value) { return true; } @@ -2391,7 +2396,7 @@ dumper_variable_declaration_exists (literal_index_t lit_id) } void -dump_variable_declaration (literal_index_t lit_id) +dump_variable_declaration (lit_cpointer_t lit_id) { const opcode_t opcode = getop_var_decl (LITERAL_TO_REWRITE); serializer_dump_op_meta (create_op_meta_100 (opcode, lit_id)); diff --git a/jerry-core/parser/js/opcodes-dumper.h b/jerry-core/parser/js/opcodes-dumper.h index 0f96b91b85..bb483c90be 100644 --- a/jerry-core/parser/js/opcodes-dumper.h +++ b/jerry-core/parser/js/opcodes-dumper.h @@ -32,7 +32,7 @@ typedef struct union { idx_t uid; - literal_index_t lit_id; + lit_cpointer_t lit_id; } data; } operand; @@ -47,7 +47,7 @@ typedef enum __attr_packed___ } varg_list_type; operand empty_operand (void); -operand literal_operand (literal_index_t); +operand literal_operand (lit_cpointer_t); bool operand_is_empty (operand); void dumper_init (void); @@ -62,10 +62,10 @@ operand dump_intrinsic (operand, operand); void dump_boolean_assignment (operand, bool); operand dump_boolean_assignment_res (bool); -void dump_string_assignment (operand, literal_index_t); -operand dump_string_assignment_res (literal_index_t); -void dump_number_assignment (operand, literal_index_t); -operand dump_number_assignment_res (literal_index_t); +void dump_string_assignment (operand, lit_cpointer_t); +operand dump_string_assignment_res (lit_cpointer_t); +void dump_number_assignment (operand, lit_cpointer_t); +operand dump_number_assignment_res (lit_cpointer_t); void dump_smallint_assignment (operand, idx_t); operand dump_smallint_assignment_res (idx_t); void dump_undefined_assignment (operand); @@ -215,8 +215,8 @@ void rewrite_finally (void); void dump_end_try_catch_finally (void); void dump_throw (operand); -bool dumper_variable_declaration_exists (literal_index_t); -void dump_variable_declaration (literal_index_t); +bool dumper_variable_declaration_exists (lit_cpointer_t); +void dump_variable_declaration (lit_cpointer_t); opcode_counter_t dump_scope_code_flags_for_rewrite (void); void rewrite_scope_code_flags (opcode_counter_t scope_code_flags_oc, diff --git a/jerry-core/parser/js/parser.cpp b/jerry-core/parser/js/parser.cpp index 77742ff7cd..2e40fc6f66 100644 --- a/jerry-core/parser/js/parser.cpp +++ b/jerry-core/parser/js/parser.cpp @@ -59,12 +59,26 @@ token_is (token_type tt) return tok.type == tt; } -static literal_index_t +static uint16_t token_data (void) { return tok.uid; } +/** + * Get token data as `lit_cpointer_t` + * + * @return compressed pointer to token data + */ +static lit_cpointer_t +token_data_as_lit_cp (void) +{ + lit_cpointer_t cp; + cp.packed_value = tok.uid; + + return cp; +} /* token_data_as_lit_cp */ + static void skip_token (void) { @@ -158,21 +172,18 @@ parse_property_name (void) case TOK_STRING: case TOK_NUMBER: { - return literal_operand (token_data ()); + return literal_operand (token_data_as_lit_cp ()); } case TOK_SMALL_INT: { - const literal lit = create_literal_from_num ((ecma_number_t) token_data ()); - lexer_add_keyword_or_numeric_literal_if_not_present (lit); - const literal_index_t lit_id = lexer_lookup_literal_uid (lit); - return literal_operand (lit_id); + literal_t lit = lit_find_or_create_literal_from_num ((ecma_number_t) token_data ()); + return literal_operand (lit_cpointer_t::compress (lit)); } case TOK_KEYWORD: { - const literal lit = create_literal_from_str_compute_len (lexer_keyword_to_string ((keyword) token_data ())); - lexer_add_keyword_or_numeric_literal_if_not_present (lit); - const literal_index_t lit_id = lexer_lookup_literal_uid (lit); - return literal_operand (lit_id); + const char *s = lexer_keyword_to_string ((keyword) token_data ()); + literal_t lit = lit_find_or_create_literal_from_charset ((const ecma_char_t *) s, (ecma_length_t) strlen (s)); + return literal_operand (lit_cpointer_t::compress (lit)); } default: { @@ -207,11 +218,11 @@ parse_property_assignment (void) { bool is_setter; - if (literal_equal_type_s (lexer_get_literal_by_id (token_data ()), "get")) + if (lit_literal_equal_type_zt (lit_get_literal_by_cp (token_data_as_lit_cp ()), (const ecma_char_t *) "get")) { is_setter = false; } - else if (literal_equal_type_s (lexer_get_literal_by_id (token_data ()), "set")) + else if (lit_literal_equal_type_zt (lit_get_literal_by_cp (token_data_as_lit_cp ()), (const ecma_char_t *) "set")) { is_setter = true; } @@ -344,7 +355,7 @@ parse_argument_list (varg_list_type vlt, operand obj, uint8_t *args_count, opera case VARG_FUNC_EXPR: { current_token_must_be (TOK_NAME); - op = literal_operand (token_data ()); + op = literal_operand (token_data_as_lit_cp ()); syntax_add_varg (op); syntax_check_for_eval_and_arguments_in_strict_mode (op, is_strict_mode (), tok.loc); break; @@ -451,7 +462,7 @@ parse_function_declaration (void) jsp_label_t *masked_label_set_p = jsp_label_mask_set (); token_after_newlines_must_be (TOK_NAME); - const operand name = literal_operand (token_data ()); + const operand name = literal_operand (token_data_as_lit_cp ()); skip_newlines (); STACK_PUSH (scopes, scopes_tree_init (STACK_TOP (scopes))); @@ -495,7 +506,7 @@ parse_function_expression (void) skip_newlines (); if (token_is (TOK_NAME)) { - const operand name = literal_operand (token_data ()); + const operand name = literal_operand (token_data_as_lit_cp ()); skip_newlines (); res = parse_argument_list (VARG_FUNC_EXPR, name, NULL, NULL); } @@ -556,8 +567,8 @@ parse_literal (void) { switch (tok.type) { - case TOK_NUMBER: return dump_number_assignment_res (token_data ()); - case TOK_STRING: return dump_string_assignment_res (token_data ()); + case TOK_NUMBER: return dump_number_assignment_res (token_data_as_lit_cp ()); + case TOK_STRING: return dump_string_assignment_res (token_data_as_lit_cp ()); case TOK_NULL: return dump_null_assignment_res (); case TOK_BOOL: return dump_boolean_assignment_res ((bool) token_data ()); case TOK_SMALL_INT: return dump_smallint_assignment_res ((idx_t) token_data ()); @@ -592,7 +603,7 @@ parse_primary_expression (void) case TOK_SMALL_INT: case TOK_NUMBER: case TOK_STRING: return parse_literal (); - case TOK_NAME: return literal_operand (token_data ()); + case TOK_NAME: return literal_operand (token_data_as_lit_cp ()); case TOK_OPEN_SQUARE: return parse_array_literal (); case TOK_OPEN_BRACE: return parse_object_literal (); case TOK_OPEN_PAREN: @@ -680,17 +691,17 @@ parse_member_expression (operand *this_arg, operand *prop_gl) skip_newlines (); if (token_is (TOK_NAME)) { - prop = dump_string_assignment_res (token_data ()); + prop = dump_string_assignment_res (token_data_as_lit_cp ()); } else if (token_is (TOK_KEYWORD)) { - const literal lit = create_literal_from_str_compute_len (lexer_keyword_to_string ((keyword) token_data ())); - const literal_index_t lit_id = lexer_lookup_literal_uid (lit); - if (lit_id == INVALID_LITERAL) + const char *s = lexer_keyword_to_string ((keyword) token_data ()); + literal_t lit = lit_find_literal_by_charset ((const ecma_char_t *) s, (ecma_length_t) strlen (s)); + if (lit == NULL) { EMIT_ERROR ("Expected identifier"); } - prop = dump_string_assignment_res (lit_id); + prop = dump_string_assignment_res (lit_cpointer_t::compress (lit)); } else { @@ -769,7 +780,7 @@ parse_call_expression (operand *this_arg_gl, operand *prop_gl) else if (tok.type == TOK_DOT) { token_after_newlines_must_be (TOK_NAME); - prop = dump_string_assignment_res (token_data ()); + prop = dump_string_assignment_res (token_data_as_lit_cp ()); } expr = dump_prop_getter_res (expr, prop); skip_newlines (); @@ -1557,7 +1568,7 @@ static void parse_variable_declaration (void) { current_token_must_be (TOK_NAME); - const operand name = literal_operand (token_data ()); + const operand name = literal_operand (token_data_as_lit_cp ()); skip_newlines (); if (token_is (TOK_EQ)) @@ -2036,7 +2047,7 @@ parse_catch_clause (void) token_after_newlines_must_be (TOK_OPEN_PAREN); token_after_newlines_must_be (TOK_NAME); - const operand exception = literal_operand (token_data ()); + const operand exception = literal_operand (token_data_as_lit_cp ()); syntax_check_for_eval_and_arguments_in_strict_mode (exception, is_strict_mode (), tok.loc); token_after_newlines_must_be (TOK_CLOSE_PAREN); @@ -2471,8 +2482,8 @@ static void process_keyword_names () skip_newlines (); if (token_is (TOK_COLON)) { - lexer_add_keyword_or_numeric_literal_if_not_present ( - create_literal_from_str_compute_len (lexer_keyword_to_string (kw))); + const char *s = lexer_keyword_to_string (kw); + lit_find_or_create_literal_from_charset ((const ecma_char_t *) s, (ecma_length_t) strlen (s)); } else { @@ -2481,8 +2492,8 @@ static void process_keyword_names () } else if (token_is (TOK_NAME)) { - if (literal_equal_type_s (lexer_get_literal_by_id (token_data ()), "get") - || literal_equal_type_s (lexer_get_literal_by_id (token_data ()), "set")) + if (lit_literal_equal_type_zt (lit_get_literal_by_cp (token_data_as_lit_cp ()), (const ecma_char_t *) "get") + || lit_literal_equal_type_zt (lit_get_literal_by_cp (token_data_as_lit_cp ()), (const ecma_char_t *) "set")) { skip_newlines (); if (token_is (TOK_KEYWORD)) @@ -2491,8 +2502,8 @@ static void process_keyword_names () skip_newlines (); if (token_is (TOK_OPEN_PAREN)) { - lexer_add_keyword_or_numeric_literal_if_not_present ( - create_literal_from_str_compute_len (lexer_keyword_to_string (kw))); + const char *s = lexer_keyword_to_string (kw); + lit_find_or_create_literal_from_charset ((const ecma_char_t *) s, (ecma_length_t) strlen (s)); } else { @@ -2581,9 +2592,9 @@ skip_parens (void) } static bool -var_declared (literal_index_t var_id) +var_declared (lit_cpointer_t var_cp) { - return dumper_variable_declaration_exists (var_id); + return dumper_variable_declaration_exists (var_cp); } static void @@ -2596,12 +2607,12 @@ preparse_var_decls (void) { if (token_is (TOK_NAME)) { - if (!var_declared (token_data ())) + if (!var_declared (token_data_as_lit_cp ())) { - syntax_check_for_eval_and_arguments_in_strict_mode (literal_operand (token_data ()), + syntax_check_for_eval_and_arguments_in_strict_mode (literal_operand (token_data_as_lit_cp ()), is_strict_mode (), tok.loc); - dump_variable_declaration (token_data ()); + dump_variable_declaration (token_data_as_lit_cp ()); } skip_token (); continue; @@ -2653,7 +2664,8 @@ preparse_scope (bool is_global) bool is_ref_eval_identifier = false; bool is_use_strict = false; - if (token_is (TOK_STRING) && literal_equal_s (lexer_get_literal_by_id (token_data ()), "use strict")) + if (token_is (TOK_STRING) && lit_literal_equal_zt (lit_get_literal_by_cp (token_data_as_lit_cp ()), + (const ecma_char_t *) "use strict")) { scopes_tree_set_strict_mode (STACK_TOP (scopes), true); is_use_strict = true; @@ -2690,14 +2702,13 @@ preparse_scope (bool is_global) { if (token_is (TOK_NAME)) { - if (literal_equal_type_s (lexer_get_literal_by_id (token_data ()), - "arguments")) + if (lit_literal_equal_type_zt (lit_get_literal_by_cp (token_data_as_lit_cp ()), + (const ecma_char_t *) "arguments")) { is_ref_arguments_identifier = true; } - - if (literal_equal_type_s (lexer_get_literal_by_id (token_data ()), - "eval")) + else if (lit_literal_equal_type_zt (lit_get_literal_by_cp (token_data_as_lit_cp ()), + (const ecma_char_t *) "eval")) { is_ref_eval_identifier = true; } @@ -2774,10 +2785,9 @@ parser_parse_program (void) JERRY_ASSERT (token_is (TOK_EOF)); dump_exit (); - serializer_dump_literals (lexer_get_literals (), lexer_get_literals_count ()); + serializer_dump_literals (); serializer_merge_scopes_into_bytecode (); serializer_set_scope (NULL); - serializer_set_strings_buffer (lexer_get_strings_cache ()); scopes_tree_free (STACK_TOP (scopes)); STACK_DROP (scopes, 1); diff --git a/jerry-core/parser/js/scopes-tree.cpp b/jerry-core/parser/js/scopes-tree.cpp index 5d33a1ec3a..ba0cfbee28 100644 --- a/jerry-core/parser/js/scopes-tree.cpp +++ b/jerry-core/parser/js/scopes-tree.cpp @@ -15,9 +15,6 @@ #include "scopes-tree.h" #include "bytecode-data.h" -#include "mem-heap.h" -#include "jrt-libc-includes.h" -#include "lexer.h" #define OPCODE(op) (__op__idx_##op) #define HASH_SIZE 128 @@ -103,7 +100,7 @@ scopes_tree_count_opcodes (scopes_tree t) static uint16_t lit_id_hash (void * lit_id) { - return *(literal_index_t *) lit_id % HASH_SIZE; + return ((lit_cpointer_t *) lit_id)->packed_value % HASH_SIZE; } static void @@ -117,7 +114,7 @@ start_new_block_if_necessary (void) hash_table_free (lit_id_to_uid); lit_id_to_uid = null_hash; } - lit_id_to_uid = hash_table_init (sizeof (literal_index_t), sizeof (idx_t), HASH_SIZE, lit_id_hash, + lit_id_to_uid = hash_table_init (sizeof (lit_cpointer_t), sizeof (idx_t), HASH_SIZE, lit_id_hash, MEM_HEAP_ALLOC_SHORT_TERM); } } @@ -157,8 +154,8 @@ change_uid (op_meta *om, lit_id_hash_table *lit_ids, uint16_t mask) { if (get_uid (om, i) == LITERAL_TO_REWRITE) { - JERRY_ASSERT (om->lit_id[i] != NOT_A_LITERAL); - literal_index_t lit_id = om->lit_id[i]; + JERRY_ASSERT (om->lit_id[i].packed_value != MEM_CP_NULL); + lit_cpointer_t lit_id = om->lit_id[i]; idx_t *uid = (idx_t *) hash_table_lookup (lit_id_to_uid, &lit_id); if (uid == NULL) { @@ -173,12 +170,12 @@ change_uid (op_meta *om, lit_id_hash_table *lit_ids, uint16_t mask) } else { - JERRY_ASSERT (om->lit_id[i] == NOT_A_LITERAL); + JERRY_ASSERT (om->lit_id[i].packed_value == MEM_CP_NULL); } } else { - JERRY_ASSERT (om->lit_id[i] == NOT_A_LITERAL); + JERRY_ASSERT (om->lit_id[i].packed_value == MEM_CP_NULL); } } } @@ -192,8 +189,8 @@ insert_uids_to_lit_id_map (op_meta *om, uint16_t mask) { if (get_uid (om, i) == LITERAL_TO_REWRITE) { - JERRY_ASSERT (om->lit_id[i] != NOT_A_LITERAL); - literal_index_t lit_id = om->lit_id[i]; + JERRY_ASSERT (om->lit_id[i].packed_value != MEM_CP_NULL); + lit_cpointer_t lit_id = om->lit_id[i]; idx_t *uid = (idx_t *) hash_table_lookup (lit_id_to_uid, &lit_id); if (uid == NULL) { @@ -206,12 +203,12 @@ insert_uids_to_lit_id_map (op_meta *om, uint16_t mask) } else { - JERRY_ASSERT (om->lit_id[i] == NOT_A_LITERAL); + JERRY_ASSERT (om->lit_id[i].packed_value == MEM_CP_NULL); } } else { - JERRY_ASSERT (om->lit_id[i] == NOT_A_LITERAL); + JERRY_ASSERT (om->lit_id[i].packed_value == MEM_CP_NULL); } } } diff --git a/jerry-core/parser/js/scopes-tree.h b/jerry-core/parser/js/scopes-tree.h index 48b44720c6..a18e42b28c 100644 --- a/jerry-core/parser/js/scopes-tree.h +++ b/jerry-core/parser/js/scopes-tree.h @@ -22,12 +22,13 @@ #include "hash-table.h" #include "opcodes.h" #include "lit-id-hash-table.h" +#include "lit-literal.h" -#define NOT_A_LITERAL (INVALID_LITERAL - 1) +#define NOT_A_LITERAL (lit_cpointer_t::null_cp ()) typedef struct { - literal_index_t lit_id[3]; + lit_cpointer_t lit_id[3]; opcode_t op; } op_meta; diff --git a/jerry-core/parser/js/serializer.cpp b/jerry-core/parser/js/serializer.cpp index e6d47d2a66..06bb853593 100644 --- a/jerry-core/parser/js/serializer.cpp +++ b/jerry-core/parser/js/serializer.cpp @@ -15,9 +15,6 @@ #include "serializer.h" #include "bytecode-data.h" -#include "jrt.h" -#include "parser.h" -#include "jrt-libc-includes.h" #include "pretty-printer.h" static bytecode_data_t bytecode_data; @@ -43,16 +40,8 @@ serializer_get_opcode (opcode_counter_t oc) return bytecode_data.opcodes[oc]; } -literal -serializer_get_literal_by_id (literal_index_t id) -{ - JERRY_ASSERT (id != INVALID_LITERAL); - JERRY_ASSERT (id < bytecode_data.literals_count); - return bytecode_data.literals[id]; -} - -literal_index_t -serializer_get_literal_id_by_uid (uint8_t id, opcode_counter_t oc) +lit_cpointer_t +serializer_get_literal_cp_by_uid (uint8_t id, opcode_counter_t oc) { if (bytecode_data.lit_id_hash == null_hash) { @@ -91,17 +80,14 @@ serializer_merge_scopes_into_bytecode (void) } void -serializer_dump_literals (const literal *literals, literal_index_t literals_count) +serializer_dump_literals (void) { #ifdef JERRY_ENABLE_PRETTY_PRINTER if (print_opcodes) { - pp_literals (literals, literals_count); + lit_dump_literals (); } #endif - - bytecode_data.literals_count = literals_count; - bytecode_data.literals = literals; } void @@ -185,9 +171,10 @@ serializer_init () print_opcodes = false; bytecode_data.strings_buffer = NULL; - bytecode_data.literals = NULL; bytecode_data.opcodes = NULL; bytecode_data.lit_id_hash = null_hash; + + lit_init (); } void serializer_set_show_opcodes (bool show_opcodes) @@ -206,9 +193,8 @@ serializer_free (void) { lit_id_hash_table_free (bytecode_data.lit_id_hash); } - if (bytecode_data.literals != NULL) - { - mem_heap_free_block ((uint8_t *) bytecode_data.literals); - } + mem_heap_free_block ((uint8_t *) bytecode_data.opcodes); + + lit_finalize (); } diff --git a/jerry-core/parser/js/serializer.h b/jerry-core/parser/js/serializer.h index dd06aa4e9e..d12774a7f4 100644 --- a/jerry-core/parser/js/serializer.h +++ b/jerry-core/parser/js/serializer.h @@ -20,18 +20,16 @@ #include "ecma-globals.h" #include "opcodes.h" #include "vm.h" -#include "literal.h" #include "scopes-tree.h" void serializer_init (); void serializer_set_show_opcodes (bool show_opcodes); op_meta serializer_get_op_meta (opcode_counter_t); opcode_t serializer_get_opcode (opcode_counter_t); -literal serializer_get_literal_by_id (literal_index_t); -literal_index_t serializer_get_literal_id_by_uid (uint8_t, opcode_counter_t); +lit_cpointer_t serializer_get_literal_cp_by_uid (uint8_t, opcode_counter_t); const void *serializer_get_bytecode (void); void serializer_set_strings_buffer (const ecma_char_t *); -void serializer_dump_literals (const literal *, literal_index_t); +void serializer_dump_literals (); void serializer_set_scope (scopes_tree); void serializer_merge_scopes_into_bytecode (void); void serializer_dump_op_meta (op_meta); diff --git a/jerry-core/parser/js/syntax-errors.cpp b/jerry-core/parser/js/syntax-errors.cpp index c328508612..481aef3508 100644 --- a/jerry-core/parser/js/syntax-errors.cpp +++ b/jerry-core/parser/js/syntax-errors.cpp @@ -23,7 +23,7 @@ typedef struct { prop_type type; - literal lit; + literal_t lit; } prop_literal; enum @@ -39,7 +39,7 @@ enum STATIC_STACK (U8, uint8_t) static prop_literal -create_prop_literal (literal lit, prop_type type) +create_prop_literal (literal_t lit, prop_type type) { prop_literal ret; @@ -59,7 +59,7 @@ void syntax_add_prop_name (operand op, prop_type pt) { JERRY_ASSERT (op.type == OPERAND_LITERAL); - STACK_PUSH (props, create_prop_literal (lexer_get_literal_by_id (op.data.lit_id), pt)); + STACK_PUSH (props, create_prop_literal (lit_get_literal_by_cp (op.data.lit_id), pt)); } void @@ -94,34 +94,34 @@ syntax_check_for_duplication_of_prop_names (bool is_strict, locus loc __attr_unu JERRY_ASSERT (current.type == PROP_DATA || current.type == PROP_GET || current.type == PROP_SET); - if (literal_equal (previous.lit, current.lit)) + if (lit_literal_equal (previous.lit, current.lit)) { /*a*/ if (is_strict && previous.type == PROP_DATA && current.type == PROP_DATA) { PARSE_ERROR_VARG ("Duplication of parameter name '%s' in ObjectDeclaration is not allowed in strict mode", - loc, (const char *) literal_to_zt (current.lit)); + loc, lit_literal_to_str_internal_buf (current.lit)); } /*b*/ if (previous.type == PROP_DATA && (current.type == PROP_SET || current.type == PROP_GET)) { PARSE_ERROR_VARG ("Parameter name '%s' in ObjectDeclaration may not be both data and accessor", - loc, (const char *) literal_to_zt (current.lit)); + loc, lit_literal_to_str_internal_buf (current.lit)); } /*c*/ if (current.type == PROP_DATA && (previous.type == PROP_SET || previous.type == PROP_GET)) { PARSE_ERROR_VARG ("Parameter name '%s' in ObjectDeclaration may not be both data and accessor", - loc, (const char *) literal_to_zt (current.lit)); + loc, lit_literal_to_str_internal_buf (current.lit)); } /*d*/ if ((previous.type == PROP_SET && current.type == PROP_SET) || (previous.type == PROP_GET && current.type == PROP_GET)) { PARSE_ERROR_VARG ("Parameter name '%s' in ObjectDeclaration may not be accessor of same type", - loc, (const char *) literal_to_zt (current.lit)); + loc, lit_literal_to_str_internal_buf (current.lit)); } } } @@ -140,7 +140,7 @@ syntax_start_checking_of_vargs (void) void syntax_add_varg (operand op) { JERRY_ASSERT (op.type == OPERAND_LITERAL); - STACK_PUSH (props, create_prop_literal (lexer_get_literal_by_id (op.data.lit_id), VARG)); + STACK_PUSH (props, create_prop_literal (lit_get_literal_by_cp (op.data.lit_id), VARG)); } static void @@ -148,10 +148,10 @@ emit_error_on_eval_and_arguments (operand op, locus loc __attr_unused___) { if (op.type == OPERAND_LITERAL) { - if (literal_equal_type_zt (lexer_get_literal_by_id (op.data.lit_id), - ecma_get_magic_string_zt (ECMA_MAGIC_STRING_ARGUMENTS)) - || literal_equal_type_zt (lexer_get_literal_by_id (op.data.lit_id), - ecma_get_magic_string_zt (ECMA_MAGIC_STRING_EVAL))) + if (lit_literal_equal_type_zt (lit_get_literal_by_cp (op.data.lit_id), + ecma_get_magic_string_zt (ECMA_MAGIC_STRING_ARGUMENTS)) + || lit_literal_equal_type_zt (lit_get_literal_by_cp (op.data.lit_id), + ecma_get_magic_string_zt (ECMA_MAGIC_STRING_EVAL))) { PARSE_ERROR ("'eval' and 'arguments' are not allowed here in strict mode", loc); } @@ -179,17 +179,21 @@ syntax_check_for_syntax_errors_in_formal_param_list (bool is_strict, locus loc _ for (uint8_t i = (uint8_t) (STACK_TOP (U8) + 1); i < STACK_SIZE (props); i = (uint8_t) (i + 1)) { JERRY_ASSERT (STACK_ELEMENT (props, i).type == VARG); - const literal previous = STACK_ELEMENT (props, i).lit; - JERRY_ASSERT (previous.type == LIT_STR || previous.type == LIT_MAGIC_STR || previous.type == LIT_MAGIC_STR_EX); + literal_t previous = STACK_ELEMENT (props, i).lit; + JERRY_ASSERT (previous->get_type () == LIT_STR_T + || previous->get_type () == LIT_MAGIC_STR_T + || previous->get_type () == LIT_MAGIC_STR_EX_T); for (uint8_t j = STACK_TOP (U8); j < i; j = (uint8_t) (j + 1)) { JERRY_ASSERT (STACK_ELEMENT (props, j).type == VARG); - const literal current = STACK_ELEMENT (props, j).lit; - JERRY_ASSERT (current.type == LIT_STR || current.type == LIT_MAGIC_STR || current.type == LIT_MAGIC_STR_EX); - if (literal_equal_type (previous, current)) + literal_t current = STACK_ELEMENT (props, j).lit; + JERRY_ASSERT (current->get_type () == LIT_STR_T + || current->get_type () == LIT_MAGIC_STR_T + || current->get_type () == LIT_MAGIC_STR_EX_T); + if (lit_literal_equal_type (previous, current)) { PARSE_ERROR_VARG ("Duplication of literal '%s' in FormalParameterList is not allowed in strict mode", - loc, (const char *) literal_to_zt (previous)); + loc, lit_literal_to_str_internal_buf (previous)); } } } diff --git a/jerry-core/parser/js/syntax-errors.h b/jerry-core/parser/js/syntax-errors.h index 5259931d6a..62dc228ccc 100644 --- a/jerry-core/parser/js/syntax-errors.h +++ b/jerry-core/parser/js/syntax-errors.h @@ -16,7 +16,6 @@ #ifndef SYNTAX_ERRORS_H #define SYNTAX_ERRORS_H -#include "literal.h" #include "opcodes-dumper.h" #include "lexer.h" diff --git a/jerry-core/rcs/rcs-chunked-list.cpp b/jerry-core/rcs/rcs-chunked-list.cpp index 29a28bee25..def0ada18c 100644 --- a/jerry-core/rcs/rcs-chunked-list.cpp +++ b/jerry-core/rcs/rcs-chunked-list.cpp @@ -35,6 +35,15 @@ rcs_chunked_list_t::free (void) JERRY_ASSERT (tail_p == NULL); } /* rcs_chunked_list_t::free */ +void +rcs_chunked_list_t::cleanup (void) +{ + while (head_p) + { + remove (head_p); + } +} /* rcs_chunked_list_t::cleanup */ + /** * Get first node of the list * diff --git a/jerry-core/rcs/rcs-chunked-list.h b/jerry-core/rcs/rcs-chunked-list.h index 18f4a0d883..ff54e464f6 100644 --- a/jerry-core/rcs/rcs-chunked-list.h +++ b/jerry-core/rcs/rcs-chunked-list.h @@ -37,6 +37,14 @@ class rcs_chunked_list_t { public: + /** + * Constructor of chunked list + */ + rcs_chunked_list_t () + { + head_p = tail_p = NULL; + } /* rcs_chunked_list_t */ + /** * List node */ @@ -47,32 +55,33 @@ class rcs_chunked_list_t } node_t; void init (void); + void cleanup (void); void free (void); node_t *get_first (void) const; node_t *get_last (void) const; - node_t *get_prev (node_t *node_p) const; + node_t *get_prev (node_t *) const; node_t *get_next (node_t *node_p) const; node_t *append_new (void); - node_t *insert_new (node_t *after_p); + node_t *insert_new (node_t *); - void remove (node_t *node_p); + void remove (node_t *); - node_t *get_node_from_pointer (void *ptr) const; - uint8_t* get_data_space (node_t *node_p) const; + node_t *get_node_from_pointer (void *) const; + uint8_t* get_data_space (node_t *) const; static size_t get_data_space_size (void); private: - void set_prev (node_t *node_p, node_t *prev_node_p); - void set_next (node_t *node_p, node_t *next_node_p); + void set_prev (node_t *, node_t *); + void set_next (node_t *, node_t *); static size_t get_node_size (void); void assert_list_is_correct (void) const; - void assert_node_is_correct (const node_t *node_p) const; + void assert_node_is_correct (const node_t *) const; node_t* head_p; /**< head node of list */ node_t* tail_p; /**< tail node of list */ diff --git a/jerry-core/rcs/rcs-recordset.cpp b/jerry-core/rcs/rcs-recordset.cpp index 2b9fbae608..4bab26b1bc 100644 --- a/jerry-core/rcs/rcs-recordset.cpp +++ b/jerry-core/rcs/rcs-recordset.cpp @@ -15,7 +15,6 @@ #include "rcs-chunked-list.h" #include "rcs-recordset.h" -#include "jrt-bit-fields.h" /** \addtogroup recordset Recordset * @{ @@ -91,7 +90,6 @@ rcs_recordset_t::record_t::cpointer_t::decompress (rcs_cpointer_t compressed_poi * compressed pointer */ { uint8_t* base_pointer; - if (compressed_pointer.value.base_cp == MEM_CP_NULL) { base_pointer = NULL; @@ -106,6 +104,19 @@ rcs_recordset_t::record_t::cpointer_t::decompress (rcs_cpointer_t compressed_poi return (rcs_recordset_t::record_t*) (base_pointer + diff); } /* rcs_recordset_t::record_t::cpointer_t::decompress */ +/** + * Create NULL compressed pointer + * + * @return NULL compressed pointer + */ +rcs_cpointer_t +rcs_recordset_t::record_t::cpointer_t::null_cp () +{ + rcs_cpointer_t cp; + cp.packed_value = MEM_CP_NULL; + return cp; +} /* rcs_recordset_t::record_t::cpointer_t::null_cp */ + /** * Assert that 'this' value points to correct record */ @@ -612,6 +623,7 @@ rcs_recordset_t::assert_state_is_correct (void) rec_p != NULL; last_record_p = rec_p, rec_p = next_rec_p) { + JERRY_ASSERT (get_record_size (rec_p) > 0); record_size_sum += get_record_size (rec_p); rcs_chunked_list_t::node_t *node_p = _chunk_list.get_node_from_pointer (rec_p); @@ -649,6 +661,110 @@ rcs_recordset_t::assert_state_is_correct (void) #endif /* !JERRY_NDEBUG */ } /* rcs_recordset_t::assert_state_is_correct */ +/** + * Perform general access to the record + * + * Warning: This function is implemented in assumption that `size` is not more than `2 * node_data_space_size`. + */ +void +rcs_record_iterator_t::access (access_t access_type, /**< type of access: read, write or skip */ + void *data, /**< in/out data to read or write */ + size_t size) /**< size of the data in bytes */ +{ + const size_t node_data_space_size = _recordset_p->_chunk_list.get_data_space_size (); + JERRY_ASSERT (2 * node_data_space_size >= size); + const size_t record_size = _recordset_p->get_record_size (_record_start_p); + + JERRY_ASSERT (!finished ()); + + rcs_chunked_list_t::node_t *current_node_p = _recordset_p->_chunk_list.get_node_from_pointer (_current_pos_p); + uint8_t *current_node_data_space_p = _recordset_p->_chunk_list.get_data_space (current_node_p); + size_t left_in_node = node_data_space_size - (size_t)(_current_pos_p - current_node_data_space_p); + + JERRY_ASSERT (_current_offset + size <= record_size); + + /* + * Read the data and increase the current position pointer. + */ + if (left_in_node >= size) + { + /* all data is placed inside single node */ + if (access_type == ACCESS_READ) + { + memcpy (data, _current_pos_p, size); + } + else if (access_type == ACCESS_WRITE) + { + memcpy (_current_pos_p, data, size); + } + else + { + JERRY_ASSERT (access_type == ACCESS_SKIP); + + if (left_in_node > size) + { + _current_pos_p += size; + } + else if (_current_offset + size < record_size) + { + current_node_p = _recordset_p->_chunk_list.get_next (current_node_p); + JERRY_ASSERT (current_node_p); + _current_pos_p = _recordset_p->_chunk_list.get_data_space (current_node_p); + } + else + { + JERRY_ASSERT (_current_offset + size == record_size); + } + } + } + else + { + /* data is distributed between two nodes */ + size_t first_chunk_size = node_data_space_size - (size_t) (_current_pos_p - current_node_data_space_p); + + if (access_type == ACCESS_READ) + { + memcpy (data, _current_pos_p, first_chunk_size); + } + else if (access_type == ACCESS_WRITE) + { + memcpy (_current_pos_p, data, first_chunk_size); + } + + rcs_chunked_list_t::node_t *next_node_p = _recordset_p->_chunk_list.get_next (current_node_p); + JERRY_ASSERT (next_node_p != NULL); + uint8_t *next_node_data_space_p = _recordset_p->_chunk_list.get_data_space (next_node_p); + + if (access_type == ACCESS_READ) + { + memcpy ((uint8_t *)data + first_chunk_size, next_node_data_space_p, size - first_chunk_size); + } + else if (access_type == ACCESS_WRITE) + { + memcpy (next_node_data_space_p, (uint8_t *)data + first_chunk_size, size - first_chunk_size); + } + else + { + JERRY_ASSERT (access_type == ACCESS_SKIP); + + _current_pos_p = next_node_data_space_p + size - first_chunk_size; + } + } + + /* check if we reached the end */ + if (access_type == ACCESS_SKIP) + { + _current_offset += size; + JERRY_ASSERT (_current_offset <= record_size); + + if (_current_offset == record_size) + { + _current_pos_p = NULL; + _current_offset = 0; + } + } +} /* rcs_record_iterator_t::access */ + /** * Get size of the free record */ diff --git a/jerry-core/rcs/rcs-recordset.h b/jerry-core/rcs/rcs-recordset.h index 2e60358cbb..fab08382a4 100644 --- a/jerry-core/rcs/rcs-recordset.h +++ b/jerry-core/rcs/rcs-recordset.h @@ -16,6 +16,8 @@ #ifndef RCS_RECORDSET_H #define RCS_RECORDSET_H +#include + #include "jrt.h" #include "jrt-bit-fields.h" #include "mem-allocator.h" @@ -72,6 +74,12 @@ class rcs_recordset_t _chunk_list.free (); } /* finalize */ + /* Free memory occupied by the dynamic storage */ + void cleanup (void) + { + _chunk_list.cleanup (); + } /* cleanup */ + /** * Record type */ @@ -109,8 +117,12 @@ class rcs_recordset_t uint16_t packed_value; }; - static cpointer_t compress (record_t* pointer_p); - static record_t* decompress (cpointer_t pointer_cp); + static cpointer_t compress (record_t *pointer_p); + static record_t *decompress (cpointer_t pointer_cp); + + static cpointer_t null_cp (); + + static const int conval = 3; }; private: @@ -130,7 +142,7 @@ class rcs_recordset_t uint32_t get_field (uint32_t field_pos, uint32_t field_width) const; void set_field (uint32_t field_pos, uint32_t field_width, size_t value); - record_t* get_pointer (uint32_t field_pos, uint32_t field_width) const; + record_t *get_pointer (uint32_t field_pos, uint32_t field_width) const; void set_pointer (uint32_t field_pos, uint32_t field_width, record_t* pointer_p); /** @@ -139,6 +151,9 @@ class rcs_recordset_t static const uint32_t _fields_offset_begin = _type_field_pos + _type_field_width; }; + record_t *get_first (void); + record_t *get_next (record_t *rec_p); + private: friend class rcs_record_iterator_t; @@ -158,6 +173,7 @@ class rcs_recordset_t void init_free_record (record_t *free_rec_p, size_t size, record_t *prev_rec_p); bool is_record_free (record_t *record_p); + protected: /** * First type identifier that can be used for storage-specific record types @@ -172,7 +188,7 @@ class rcs_recordset_t template< typename T, /**< type of record structure */ typename ... SizeArgs> /**< type of arguments of T::size */ - T* alloc_record (record_t::type_t type, /**< record's type identifier */ + T *alloc_record (record_t::type_t type, /**< record's type identifier */ SizeArgs ... size_args) /**< arguments of T::size */ { JERRY_ASSERT (type >= _first_type_id); @@ -180,7 +196,7 @@ class rcs_recordset_t size_t size = T::size (size_args...); record_t *prev_rec_p; - T* rec_p = static_cast (alloc_space_for_record (size, &prev_rec_p)); + T *rec_p = static_cast (alloc_space_for_record (size, &prev_rec_p)); rec_p->set_type (type); rec_p->set_size (size); @@ -191,16 +207,14 @@ class rcs_recordset_t return rec_p; } /* alloc_record */ - record_t* alloc_space_for_record (size_t bytes, record_t** out_prev_rec_p); - void free_record (record_t* record_p); + record_t *alloc_space_for_record (size_t bytes, record_t **out_prev_rec_p); + void free_record (record_t *record_p); - record_t* get_first (void); + virtual record_t *get_prev (record_t *rec_p); - virtual record_t* get_prev (record_t* rec_p); - record_t* get_next (record_t* rec_p); - virtual void set_prev (record_t* rec_p, record_t *prev_rec_p); + virtual void set_prev (record_t *rec_p, record_t *prev_rec_p); - virtual size_t get_record_size (record_t* rec_p); + virtual size_t get_record_size (record_t *rec_p); void assert_state_is_correct (void); }; /* rcs_recordset_t */ @@ -221,17 +235,109 @@ typedef rcs_record_t::cpointer_t rcs_cpointer_t; class rcs_record_iterator_t { public: - rcs_record_iterator_t (rcs_record_t* rec_p); - rcs_record_iterator_t (rcs_cpointer_t rec_ext_cp); + /** + * Constructor + */ + rcs_record_iterator_t (rcs_recordset_t *rcs_p, /**< recordset */ + rcs_record_t *rec_p) /**< record which should belong to the recordset */ + { + _record_start_p = rec_p; + _recordset_p = rcs_p; + + reset (); + } /* rcs_record_iterator_t */ + + /** + * Constructor + */ + rcs_record_iterator_t (rcs_recordset_t *rcs_p, /**< recordset */ + rcs_cpointer_t rec_ext_cp) /**< compressed pointer to the record */ + { + _record_start_p = rcs_cpointer_t::decompress (rec_ext_cp); + _recordset_p = rcs_p; + + reset (); + } /* rcs_record_iterator_t */ protected: - template T read (void); - template void write (T value); + /** + * Types of access + */ + typedef enum + { + ACCESS_WRITE, /**< If access_type == ACCESS_WRITE, + * write 'size' bytes from 'data' buffer to the record. */ + ACCESS_READ, /**< If access_type == ACCESS_READ, + * read 'size' bytes from the record and write to the 'data' buffer. */ + ACCESS_SKIP /**< If access_type == ACCESS_SKIP, + * increment current position so that 'size' bytes would be skipped. */ + } access_t; + + void access (access_t access_type, void *data, size_t size); + +public: + /** + * Read value of type T from the record. + * After reading iterator doesn't change its position. + * + * @return read value + */ + template T read (void) + { + T data; + access (ACCESS_READ, &data, sizeof (T)); + return data; + } /* read */ + + /** + * Write value of type T to the record. + * After writing iterator doesn't change its position. + */ + template void write (T value) /**< value to write */ + { + access (ACCESS_WRITE, &value, sizeof (T)); + } /* write */ + + /** + * Increment current position to skip T value in the record. + */ + template void skip () + { + access (ACCESS_SKIP, NULL, sizeof (T)); + } /* skip */ + + /** + * Increment current position to skip 'size' bytes. + */ + void skip (size_t size) /**< number of bytes to skip */ + { + access (ACCESS_SKIP, NULL, size); + } /* skip */ + + /** + * Check if the end of the record was reached. + * + * @return true if the whole record was iterated + * false otherwise + */ + bool finished () + { + return _current_pos_p == NULL; + } /* finished */ + + /** + * Reset the iterator, so that it points to the beginning of the record + */ + void reset () + { + _current_pos_p = (uint8_t *)_record_start_p; + _current_offset = 0; + } /* reset */ private: rcs_record_t* _record_start_p; /**< start of current record */ uint8_t* _current_pos_p; /**< pointer to current offset in current record */ - + size_t _current_offset; /**< current offset */ rcs_recordset_t *_recordset_p; /**< recordset containing the record */ }; /* rcs_record_iterator_t */ diff --git a/jerry-core/vm/opcodes-ecma-try-catch-finally.cpp b/jerry-core/vm/opcodes-ecma-try-catch-finally.cpp index 75caf7186c..1d8d008fa5 100644 --- a/jerry-core/vm/opcodes-ecma-try-catch-finally.cpp +++ b/jerry-core/vm/opcodes-ecma-try-catch-finally.cpp @@ -63,12 +63,12 @@ opfunc_try_block (opcode_t opdata, /**< operation data */ JERRY_ASSERT (next_opcode.op_idx == __op__idx_meta); JERRY_ASSERT (next_opcode.data.meta.type == OPCODE_META_TYPE_CATCH_EXCEPTION_IDENTIFIER); - const literal_index_t catch_exc_val_var_name_lit_idx = serializer_get_literal_id_by_uid ( - next_opcode.data.meta.data_1, - int_data->pos); + lit_cpointer_t catch_exc_val_var_name_lit_cp = serializer_get_literal_cp_by_uid ( + next_opcode.data.meta.data_1, + int_data->pos); int_data->pos++; - ecma_string_t *catch_exc_var_name_str_p = ecma_new_ecma_string_from_lit_index (catch_exc_val_var_name_lit_idx); + ecma_string_t *catch_exc_var_name_str_p = ecma_new_ecma_string_from_lit_cp (catch_exc_val_var_name_lit_cp); ecma_object_t *old_env_p = int_data->lex_env_p; ecma_object_t *catch_env_p = ecma_create_decl_lex_env (old_env_p); diff --git a/jerry-core/vm/opcodes-helpers-variables.cpp b/jerry-core/vm/opcodes-helpers-variables.cpp index db8b673915..91462de166 100644 --- a/jerry-core/vm/opcodes-helpers-variables.cpp +++ b/jerry-core/vm/opcodes-helpers-variables.cpp @@ -91,9 +91,9 @@ get_variable_value (int_data_t *int_data, /**< interpreter context */ else { ecma_string_t var_name_string; - const literal_index_t lit_id = serializer_get_literal_id_by_uid (var_idx, int_data->pos); - JERRY_ASSERT (lit_id != INVALID_LITERAL); - ecma_new_ecma_string_on_stack_from_lit_index (&var_name_string, lit_id); + lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (var_idx, int_data->pos); + JERRY_ASSERT (lit_cp.packed_value != MEM_CP_NULL); + ecma_new_ecma_string_on_stack_from_lit_cp (&var_name_string, lit_cp); ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (int_data->lex_env_p, &var_name_string); @@ -158,9 +158,9 @@ set_variable_value (int_data_t *int_data, /**< interpreter context */ else { ecma_string_t var_name_string; - const literal_index_t lit_id = serializer_get_literal_id_by_uid (var_idx, lit_oc); - JERRY_ASSERT (lit_id != INVALID_LITERAL); - ecma_new_ecma_string_on_stack_from_lit_index (&var_name_string, lit_id); + lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (var_idx, lit_oc); + JERRY_ASSERT (lit_cp.packed_value != MEM_CP_NULL); + ecma_new_ecma_string_on_stack_from_lit_cp (&var_name_string, lit_cp); ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (int_data->lex_env_p, &var_name_string); diff --git a/jerry-core/vm/opcodes-varg.cpp b/jerry-core/vm/opcodes-varg.cpp index 85c209f645..00447ae3af 100644 --- a/jerry-core/vm/opcodes-varg.cpp +++ b/jerry-core/vm/opcodes-varg.cpp @@ -96,10 +96,10 @@ fill_params_list (int_data_t *int_data, /**< interpreter context */ JERRY_ASSERT (next_opcode.op_idx == __op__idx_meta); JERRY_ASSERT (next_opcode.data.meta.type == OPCODE_META_TYPE_VARG); - const literal_index_t param_name_lit_idx = serializer_get_literal_id_by_uid (next_opcode.data.meta.data_1, - int_data->pos); + const lit_cpointer_t param_name_lit_idx = serializer_get_literal_cp_by_uid (next_opcode.data.meta.data_1, + int_data->pos); - params_names[param_index] = ecma_new_ecma_string_from_lit_index (param_name_lit_idx); + params_names[param_index] = ecma_new_ecma_string_from_lit_cp (param_name_lit_idx); int_data->pos++; } diff --git a/jerry-core/vm/opcodes.cpp b/jerry-core/vm/opcodes.cpp index 33b1e1f62b..150cb6cec9 100644 --- a/jerry-core/vm/opcodes.cpp +++ b/jerry-core/vm/opcodes.cpp @@ -16,8 +16,6 @@ #include "jrt.h" #include "opcodes.h" #include "opcodes-ecma-support.h" -#include "serializer.h" -#include "vm.h" /** * Note: @@ -98,8 +96,8 @@ opfunc_assignment (opcode_t opdata, /**< operation data */ } else if (type_value_right == OPCODE_ARG_TYPE_STRING) { - const literal_index_t lit_id = serializer_get_literal_id_by_uid (src_val_descr, int_data->pos); - ecma_string_t *string_p = ecma_new_ecma_string_from_lit_index (lit_id); + lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (src_val_descr, int_data->pos); + ecma_string_t *string_p = ecma_new_ecma_string_from_lit_cp (lit_cp); ret_value = set_variable_value (int_data, int_data->pos, @@ -127,11 +125,11 @@ opfunc_assignment (opcode_t opdata, /**< operation data */ { ecma_number_t *num_p = int_data->tmp_num_p; - const literal_index_t lit_id = serializer_get_literal_id_by_uid (src_val_descr, int_data->pos); - const literal lit = serializer_get_literal_by_id (lit_id); - JERRY_ASSERT (lit.type == LIT_NUMBER); + lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (src_val_descr, int_data->pos); + literal_t lit = lit_get_literal_by_cp (lit_cp); + JERRY_ASSERT (lit->get_type () == LIT_NUMBER_T); - *num_p = lit.data.num; + *num_p = lit_charset_literal_get_number (lit); ret_value = set_variable_value (int_data, int_data->pos, @@ -142,11 +140,11 @@ opfunc_assignment (opcode_t opdata, /**< operation data */ { ecma_number_t *num_p = int_data->tmp_num_p; - const literal_index_t lit_id = serializer_get_literal_id_by_uid (src_val_descr, int_data->pos); - const literal lit = serializer_get_literal_by_id (lit_id); - JERRY_ASSERT (lit.type == LIT_NUMBER); + lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (src_val_descr, int_data->pos); + literal_t lit = lit_get_literal_by_cp (lit_cp); + JERRY_ASSERT (lit->get_type () == LIT_NUMBER_T); - *num_p = ecma_number_negate (lit.data.num); + *num_p = lit_charset_literal_get_number (lit); ret_value = set_variable_value (int_data, int_data->pos, @@ -397,11 +395,10 @@ ecma_completion_value_t opfunc_var_decl (opcode_t opdata, /**< operation data */ int_data_t *int_data) /**< interpreter context */ { - const literal_index_t lit_id = serializer_get_literal_id_by_uid (opdata.data.var_decl.variable_name, - int_data->pos); - JERRY_ASSERT (lit_id != INVALID_LITERAL); + lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (opdata.data.var_decl.variable_name, int_data->pos); + JERRY_ASSERT (lit_cp.packed_value != MEM_CP_NULL); - ecma_string_t *var_name_string_p = ecma_new_ecma_string_from_lit_index (lit_id); + ecma_string_t *var_name_string_p = ecma_new_ecma_string_from_lit_cp (lit_cp); if (!ecma_op_has_binding (int_data->lex_env_p, var_name_string_p)) { @@ -437,8 +434,7 @@ opfunc_var_decl (opcode_t opdata, /**< operation data */ */ static ecma_completion_value_t function_declaration (int_data_t *int_data, /**< interpreter context */ - literal_index_t function_name_lit_id, /**< index of literal - with function name */ + lit_cpointer_t function_name_lit_cp, /**< compressed pointer to literal with function name */ ecma_string_t* args_names[], /**< names of arguments */ ecma_length_t args_number) /**< number of arguments */ { @@ -465,7 +461,7 @@ function_declaration (int_data_t *int_data, /**< interpreter context */ do_instantiate_arguments_object = false; } - ecma_string_t *function_name_string_p = ecma_new_ecma_string_from_lit_index (function_name_lit_id); + ecma_string_t *function_name_string_p = ecma_new_ecma_string_from_lit_cp (function_name_lit_cp); ecma_completion_value_t ret_value = ecma_op_function_declaration (int_data->lex_env_p, function_name_string_p, @@ -495,8 +491,7 @@ opfunc_func_decl_n (opcode_t opdata, /**< operation data */ const idx_t function_name_idx = opdata.data.func_decl_n.name_lit_idx; const ecma_length_t params_number = opdata.data.func_decl_n.arg_list; - literal_index_t function_name_lit_id = serializer_get_literal_id_by_uid (function_name_idx, - int_data->pos); + lit_cpointer_t function_name_lit_cp = serializer_get_literal_cp_by_uid (function_name_idx, int_data->pos); int_data->pos++; @@ -507,7 +502,7 @@ opfunc_func_decl_n (opcode_t opdata, /**< operation data */ fill_params_list (int_data, params_number, params_names); ret_value = function_declaration (int_data, - function_name_lit_id, + function_name_lit_cp, params_names, params_number); @@ -578,12 +573,11 @@ opfunc_func_expr_n (opcode_t opdata, /**< operation data */ { scope_p = ecma_create_decl_lex_env (int_data->lex_env_p); - const literal_index_t lit_id = serializer_get_literal_id_by_uid (function_name_lit_idx, lit_oc); - JERRY_ASSERT (lit_id != INVALID_LITERAL); + lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (function_name_lit_idx, lit_oc); + JERRY_ASSERT (lit_cp.packed_value != MEM_CP_NULL); - function_name_string_p = ecma_new_ecma_string_from_lit_index (lit_id); - ecma_op_create_immutable_binding (scope_p, - function_name_string_p); + function_name_string_p = ecma_new_ecma_string_from_lit_cp (lit_cp); + ecma_op_create_immutable_binding (scope_p, function_name_string_p); } else { @@ -1413,10 +1407,10 @@ evaluate_arg_for_typeof (int_data_t *int_data, /**< interpreter context */ } else { - const literal_index_t lit_id = serializer_get_literal_id_by_uid (var_idx, int_data->pos); - JERRY_ASSERT (lit_id != INVALID_LITERAL); + lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (var_idx, int_data->pos); + JERRY_ASSERT (lit_cp.packed_value != MEM_CP_NULL); - ecma_string_t *var_name_string_p = ecma_new_ecma_string_from_lit_index (lit_id); + ecma_string_t *var_name_string_p = ecma_new_ecma_string_from_lit_cp (lit_cp); ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (int_data->lex_env_p, var_name_string_p); @@ -1529,10 +1523,10 @@ opfunc_delete_var (opcode_t opdata, /**< operation data */ ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); - const literal_index_t lit_id = serializer_get_literal_id_by_uid (name_lit_idx, lit_oc); - JERRY_ASSERT (lit_id != INVALID_LITERAL); + lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (name_lit_idx, lit_oc); + JERRY_ASSERT (lit_cp.packed_value != MEM_CP_NULL); - ecma_string_t *name_string_p = ecma_new_ecma_string_from_lit_index (lit_id); + ecma_string_t *name_string_p = ecma_new_ecma_string_from_lit_cp (lit_cp); ecma_reference_t ref = ecma_op_get_identifier_reference (int_data->lex_env_p, name_string_p, diff --git a/jerry-core/vm/pretty-printer.cpp b/jerry-core/vm/pretty-printer.cpp index e38c0a5b50..c8a1320b57 100644 --- a/jerry-core/vm/pretty-printer.cpp +++ b/jerry-core/vm/pretty-printer.cpp @@ -23,6 +23,7 @@ #include "ecma-helpers.h" #include "ecma-globals.h" #include "serializer.h" +#include "lit-literal.h" #define NAME_TO_ID(op) (__op__idx_##op) @@ -44,57 +45,6 @@ static uint8_t opcode_sizes[] = 0 }; -static void -dump_literal (literal lit) -{ - switch (lit.type) - { - case LIT_NUMBER: - { - if (ecma_number_is_nan (lit.data.num)) - { - printf ("%s : NUMBER", "NaN"); - } - else - { - printf ("%d : Truncated NUMBER", (int) lit.data.num); - } - break; - } - case LIT_MAGIC_STR: - { - printf ("%s : MAGIC STRING", (const char *) ecma_get_magic_string_zt (lit.data.magic_str_id)); - break; - } - case LIT_MAGIC_STR_EX: - { - printf ("%s : EXT MAGIC STRING", (const char *) ecma_get_magic_string_ex_zt (lit.data.magic_str_ex_id)); - break; - } - case LIT_STR: - { - printf ("%s : STRING", (const char *) (lit.data.lp.str)); - break; - } - default: - { - JERRY_UNREACHABLE (); - } - } -} - -void -pp_literals (const literal *lits, literal_index_t size) -{ - printf ("LITERALS %lu:\n", (unsigned long) size); - for (literal_index_t i = 0; i < size; i++) - { - printf ("%3lu ", (unsigned long) i); - dump_literal (lits[i]); - putchar ('\n'); - } -} - static char buff[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; static void @@ -104,20 +54,10 @@ clear_temp_buffer (void) } static const char * -lit_id_to_str (literal_index_t id) +lit_cp_to_str (lit_cpointer_t cp) { - literal lit = lexer_get_literal_by_id (id); - if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX) - { - return (char *) literal_to_zt (lit); - } - else - { - JERRY_ASSERT (lit.type == LIT_NUMBER); - clear_temp_buffer (); - ecma_number_to_zt_string (lit.data.num, (ecma_char_t *) buff, ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER); - return buff; - } + literal_t lit = lit_get_literal_by_cp (cp); + return lit_literal_to_str_internal_buf (lit); } static const char * @@ -146,7 +86,7 @@ tmp_id_to_str (idx_t id) } static const char * -var_to_str (opcode_t opcode, literal_index_t lit_ids[], opcode_counter_t oc, uint8_t current_arg) +var_to_str (opcode_t opcode, lit_cpointer_t lit_ids[], opcode_counter_t oc, uint8_t current_arg) { raw_opcode raw = *(raw_opcode*) &opcode; if (raw.uids[current_arg] == LITERAL_TO_REWRITE) @@ -155,9 +95,8 @@ var_to_str (opcode_t opcode, literal_index_t lit_ids[], opcode_counter_t oc, uin { return "hz"; } - JERRY_ASSERT (lit_ids[current_arg - 1] != NOT_A_LITERAL - && lit_ids[current_arg - 1] != INVALID_LITERAL); - return lit_id_to_str (lit_ids[current_arg - 1]); + JERRY_ASSERT (lit_ids[current_arg - 1].packed_value != MEM_CP_NULL); + return lit_cp_to_str (lit_ids[current_arg - 1]); } else if (raw.uids[current_arg] >= 128) { @@ -165,14 +104,15 @@ var_to_str (opcode_t opcode, literal_index_t lit_ids[], opcode_counter_t oc, uin } else { - return lit_id_to_str (serializer_get_literal_id_by_uid (raw.uids[current_arg], oc)); + return lit_cp_to_str (serializer_get_literal_cp_by_uid (raw.uids[current_arg], oc)); } } static void -pp_printf (const char *format, opcode_t opcode, literal_index_t lit_ids[], opcode_counter_t oc) +pp_printf (const char *format, opcode_t opcode, lit_cpointer_t lit_ids[], opcode_counter_t oc, uint8_t start_arg) { - uint8_t current_arg = 1; + uint8_t current_arg = start_arg; + JERRY_ASSERT (current_arg <= 3); while (*format) { if (*format != '%') @@ -187,12 +127,14 @@ pp_printf (const char *format, opcode_t opcode, literal_index_t lit_ids[], opcod { case 'd': { + JERRY_ASSERT (current_arg <= 3); raw_opcode raw = *(raw_opcode*) &opcode; printf ("%d", raw.uids[current_arg]); break; } case 's': { + JERRY_ASSERT (current_arg <= 3); printf ("%s", var_to_str (opcode, lit_ids, oc, current_arg)); break; } @@ -208,7 +150,7 @@ pp_printf (const char *format, opcode_t opcode, literal_index_t lit_ids[], opcod } #define PP_OP(op_name, format) \ - case NAME_TO_ID (op_name): pp_printf (format, opm.op, opm.lit_id, oc); break; + case NAME_TO_ID (op_name): pp_printf (format, opm.op, opm.lit_id, oc, 1); break; #define VAR(i) var_to_str (opm.op, opm.lit_id, oc, i) #define OC(i, j) __extension__({ raw_opcode* raw = (raw_opcode *) &opm.op; \ calc_opcode_counter_from_idx_idx (raw->uids[i], raw->uids[j]); }) @@ -326,7 +268,7 @@ pp_op_meta (opcode_counter_t oc, op_meta opm, bool rewrite) { if (opm.op.data.call_n.arg_list == 0) { - printf ("%s = %s ();", VAR (1), VAR (2)); + pp_printf ("%s = %s ();", opm.op, opm.lit_id, oc, 1); } else { @@ -362,7 +304,7 @@ pp_op_meta (opcode_counter_t oc, op_meta opm, bool rewrite) { if (opm.op.data.construct_n.arg_list == 0) { - printf ("%s = new %s;", VAR (1), VAR (2)); + pp_printf ("%s = new %s;", opm.op, opm.lit_id, oc, 1); } else { @@ -394,7 +336,7 @@ pp_op_meta (opcode_counter_t oc, op_meta opm, bool rewrite) } else { - printf ("%s = function %s ();", VAR (1), VAR (2)); + pp_printf ("%s = function %s ();", opm.op, opm.lit_id, oc, 1); } } else @@ -473,13 +415,12 @@ pp_op_meta (opcode_counter_t oc, op_meta opm, bool rewrite) { case NAME_TO_ID (call_n): { - printf ("%s = %s (", var_to_str (start_op, NULL, start, 1), - var_to_str (start_op, NULL, start, 2)); + pp_printf ("%s = %s (", start_op, NULL, start, 1); break; } case NAME_TO_ID (native_call): { - printf ("%s = ", var_to_str (start_op, NULL, start, 1)); + pp_printf ("%s = ", start_op, NULL, start, 1); switch (start_op.data.native_call.name) { case OPCODE_NATIVE_CALL_LED_TOGGLE: printf ("LEDToggle ("); break; @@ -494,36 +435,34 @@ pp_op_meta (opcode_counter_t oc, op_meta opm, bool rewrite) } case NAME_TO_ID (construct_n): { - printf ("%s = new %s (", var_to_str (start_op, NULL, start, 1), - var_to_str (start_op, NULL, start, 2)); + pp_printf ("%s = new %s (", start_op, NULL, start, 1); break; } case NAME_TO_ID (func_decl_n): { - printf ("function %s (", var_to_str (start_op, NULL, start, 1)); + pp_printf ("function %s (", start_op, NULL, start, 1); break; } case NAME_TO_ID (func_expr_n): { if (start_op.data.func_expr_n.name_lit_idx == INVALID_VALUE) { - printf ("%s = function (", var_to_str (start_op, NULL, start, 1)); + pp_printf ("%s = function (", start_op, NULL, start, 1); } else { - printf ("%s = function %s (", var_to_str (start_op, NULL, start, 1), - var_to_str (start_op, NULL, start, 2)); + pp_printf ("%s = function %s (", start_op, NULL, start, 1); } break; } case NAME_TO_ID (array_decl): { - printf ("%s = [", var_to_str (start_op, NULL, start, 1)); + pp_printf ("%s = [", start_op, NULL, start, 1); break; } case NAME_TO_ID (obj_decl): { - printf ("%s = {", var_to_str (start_op, NULL, start, 1)); + pp_printf ("%s = {", start_op, NULL, start, 1); break; } default: @@ -542,30 +481,27 @@ pp_op_meta (opcode_counter_t oc, op_meta opm, bool rewrite) { case OPCODE_META_TYPE_THIS_ARG: { - printf ("this_arg = %s", var_to_str (meta_op, NULL, counter, 2)); + pp_printf ("this_arg = %s", meta_op, NULL, counter, 2); break; } case OPCODE_META_TYPE_VARG: { - printf ("%s", var_to_str (meta_op, NULL, counter, 2)); + pp_printf ("%s", meta_op, NULL, counter, 2); break; } case OPCODE_META_TYPE_VARG_PROP_DATA: { - printf ("%s:%s", var_to_str (meta_op, NULL, counter, 2), - var_to_str (meta_op, NULL, counter, 3)); + pp_printf ("%s:%s", meta_op, NULL, counter, 2); break; } case OPCODE_META_TYPE_VARG_PROP_GETTER: { - printf ("%s = get %s ();", var_to_str (meta_op, NULL, counter, 2), - var_to_str (meta_op, NULL, counter, 3)); + pp_printf ("%s = get %s ();", meta_op, NULL, counter, 2); break; } case OPCODE_META_TYPE_VARG_PROP_SETTER: { - printf ("%s = set (%s);", var_to_str (meta_op, NULL, counter, 2), - var_to_str (meta_op, NULL, counter, 3)); + pp_printf ("%s = set (%s);", meta_op, NULL, counter, 2); break; } default: diff --git a/jerry-core/vm/pretty-printer.h b/jerry-core/vm/pretty-printer.h index 09b27d19e3..8dcfb3d9aa 100644 --- a/jerry-core/vm/pretty-printer.h +++ b/jerry-core/vm/pretty-printer.h @@ -19,12 +19,10 @@ #include "jrt.h" #ifdef JERRY_ENABLE_PRETTY_PRINTER #include "vm.h" -#include "literal.h" #include "scopes-tree.h" void pp_opcode (opcode_counter_t, opcode_t, bool); void pp_op_meta (opcode_counter_t, op_meta, bool); -void pp_literals (const literal *, literal_index_t); #endif // JERRY_ENABLE_PRETTY_PRINTER #endif // PRETTY_PRINTER diff --git a/jerry-libc/jerry-libc.c b/jerry-libc/jerry-libc.c index 78681580a0..79cd500aff 100644 --- a/jerry-libc/jerry-libc.c +++ b/jerry-libc/jerry-libc.c @@ -96,7 +96,7 @@ memcmp (const void *s1, /**< first area */ /** * memcpy */ -void * +void * __attr_used___ // FIXME memcpy (void *s1, /**< destination */ const void *s2, /**< source */ size_t n) /**< bytes number */ diff --git a/tests/unit/common.h b/tests/unit/common.h index 4931976e9b..c3800e0c7b 100644 --- a/tests/unit/common.h +++ b/tests/unit/common.h @@ -16,16 +16,11 @@ #ifndef COMMON_H #define COMMON_H -#include "literal.h" - #define NAME_TO_ID(op) (__op__idx_##op) #define __OPCODE_SIZE(name, arg1, arg2, arg3) \ (uint8_t) (sizeof (__op_##name) + 1), -#define LP(s) create_literal_from_str_compute_len (s) -#define NUM(s) create_literal_from_num (s) - static uint8_t opcode_sizes[] = { OP_LIST (OPCODE_SIZE) diff --git a/tests/unit/test_literal_storage.cpp b/tests/unit/test_literal_storage.cpp new file mode 100644 index 0000000000..d052d08cfc --- /dev/null +++ b/tests/unit/test_literal_storage.cpp @@ -0,0 +1,155 @@ +/* Copyright 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-helpers.h" +#include "lit-literal.h" + +extern "C" +{ + extern void srand (unsigned int __seed); + extern int rand (void); + extern long int time (long int *__timer); + extern int printf (__const char *__restrict __format, ...); + extern void *memset (void *__s, int __c, size_t __n); +} + +// Heap size is 32K +#define test_heap_size (32 * 1024) + +// Iterations count +#define test_iters 64 + +// Subiterations count +#define test_sub_iters 64 + +// Max characters in a string +#define max_characters_in_string 256 + +static void +generate_string (ecma_char_t *str, ecma_length_t len) +{ + static const ecma_char_t characters[] = "!@#$%^&*()_+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"; + static const ecma_length_t length = (ecma_length_t) (sizeof (characters) / sizeof (ecma_char_t) - 1); + for (ecma_length_t i = 0; i < len; ++i) + { + str[i] = characters[(unsigned long) rand () % length]; + } +} + +static ecma_number_t +generate_number () +{ + ecma_number_t num = ((ecma_number_t) rand () / 32767.0); + if (rand () % 2) + { + num = -num; + } + int power = rand () % 30; + while (power-- > 0) + { + num *= 10; + } + return num; +} + +int +main (int __attr_unused___ argc, + char __attr_unused___ **argv) +{ + const ecma_char_t *ptrs[test_sub_iters]; + ecma_number_t numbers[test_sub_iters]; + ecma_char_t strings[test_sub_iters][max_characters_in_string + 1]; + ecma_length_t lengths[test_sub_iters]; + + mem_init (); + lit_init (); + + srand ((unsigned int) time (NULL)); + int k = rand (); + printf ("seed=%d\n", k); + srand ((unsigned int) k); + + for (uint32_t i = 0; i < test_iters; i++) + { + memset (numbers, 0, sizeof (ecma_number_t) * test_sub_iters); + memset (lengths, 0, sizeof (ecma_length_t) * test_sub_iters); + memset (ptrs, 0, sizeof (ecma_char_t *) * test_sub_iters); + + for (uint32_t j = 0; j < test_sub_iters; j++) + { + int type = rand () % 3; + if (type == 0) + { + lengths[j] = (ecma_length_t) (rand () % max_characters_in_string + 1); + generate_string (strings[j], lengths[j]); + lit_create_literal_from_charset (strings[j], lengths[j]); + strings[j][lengths[j]] = '\0'; + ptrs[j] = strings[j]; + JERRY_ASSERT (ptrs[j]); + } + else if (type == 1) + { + ecma_magic_string_id_t msi = (ecma_magic_string_id_t) (rand () % ECMA_MAGIC_STRING__COUNT); + ptrs[j] = ecma_get_magic_string_zt (msi); + JERRY_ASSERT (ptrs[j]); + lengths[j] = (ecma_length_t) ecma_zt_string_length (ptrs[j]); + lit_create_literal_from_charset (ptrs[j], lengths[j]); + } + else + { + ecma_number_t num = generate_number (); + lengths[j] = ecma_number_to_zt_string (num, strings[j], max_characters_in_string); + lit_create_literal_from_num (num); + } + } + + // Add empty string + lit_create_literal_from_charset (NULL, 0); + + for (uint32_t j = 0; j < test_sub_iters; j++) + { + literal_t lit1; + literal_t lit2; + if (ptrs[j]) + { + lit1 = lit_find_or_create_literal_from_charset (ptrs[j], lengths[j]); + lit2 = lit_find_literal_by_charset (ptrs[j], lengths[j]); + JERRY_ASSERT (lit_literal_equal_zt (lit1, ptrs[j])); + JERRY_ASSERT (lit_literal_equal_type_zt (lit2, ptrs[j])); + } + else + { + lit1 = lit_find_or_create_literal_from_num (numbers[j]); + lit2 = lit_find_literal_by_num (numbers[j]); + JERRY_ASSERT (lit_literal_equal_num (lit1, numbers[j])); + JERRY_ASSERT (lit_literal_equal_type_num (lit2, numbers[j])); + } + JERRY_ASSERT (lit1); + JERRY_ASSERT (lit2); + JERRY_ASSERT (lit1 == lit2); + JERRY_ASSERT (lit_literal_equal (lit1, lit2)); + } + + // Check empty string exists + JERRY_ASSERT (lit_find_literal_by_charset (NULL, 0)); + + lit_storage.cleanup (); + JERRY_ASSERT (lit_storage.get_first () == NULL); + } + + lit_finalize (); + mem_finalize (true); + return 0; +} diff --git a/tests/unit/test_recordset.cpp b/tests/unit/test_recordset.cpp index a3dcbf3676..7089e9b549 100644 --- a/tests/unit/test_recordset.cpp +++ b/tests/unit/test_recordset.cpp @@ -41,6 +41,9 @@ extern "C" // Maximum number of elements in a type-one record #define test_max_type_one_record_elements 64 +// Element size in a type-one record +#define test_element_size_type_one_record (sizeof (uint16_t)) + class test_rcs_record_type_one_t : public rcs_record_t { public: @@ -80,7 +83,7 @@ class test_rcs_record_type_one_t : public rcs_record_t static const uint32_t prev_field_width = rcs_cpointer_t::bit_field_width; static const size_t header_size = 2 * RCS_DYN_STORAGE_LENGTH_UNIT; - static const size_t element_size = sizeof (uint16_t); + static const size_t element_size = test_element_size_type_one_record; }; class test_rcs_record_type_two_t : public rcs_record_t @@ -232,6 +235,7 @@ main (int __attr_unused___ argc, { test_rcs_record_type_one_t *type_one_records[test_sub_iters]; uint32_t type_one_record_element_counts[test_sub_iters]; + uint16_t type_one_record_elements[test_sub_iters][test_max_type_one_record_elements]; int type_one_records_number = 0; test_rcs_record_type_two_t *type_two_records[test_sub_iters]; @@ -249,6 +253,27 @@ main (int __attr_unused___ argc, JERRY_ASSERT (type_one_records[type_one_records_number] != NULL); + rcs_record_iterator_t it (&storage, type_one_records[type_one_records_number]); + it.skip (); // skip header + it.skip (); // skip header + for (uint32_t i = 0; i < type_one_record_element_counts[type_one_records_number]; it.skip(), i++) + { + uint16_t val = (uint16_t)rand (); + type_one_record_elements[type_one_records_number][i] = val; + it.write (val); + } + + JERRY_ASSERT (type_one_records[type_one_records_number] != NULL); + + it.reset (); + it.skip (); // skip header + it.skip (); // skip header + for (uint32_t i = 0; i < type_one_record_element_counts[type_one_records_number]; it.skip(), i++) + { + uint16_t val = type_one_record_elements[type_one_records_number][i]; + JERRY_ASSERT (val == it.read ()); + } + type_one_records_number++; } else @@ -265,6 +290,26 @@ main (int __attr_unused___ argc, while (type_one_records_number + type_two_records_number != 0) { + // Read test + for (int index_to_free = 0; index_to_free < type_one_records_number; index_to_free++) + { + JERRY_ASSERT (type_one_records_number > 0); + + JERRY_ASSERT (index_to_free >= 0 && index_to_free < type_one_records_number); + + rcs_record_iterator_t it (&storage, type_one_records[index_to_free]); + it.skip (); // skip header + it.skip (); // skip header + for (uint32_t i = 0; i < type_one_record_element_counts[index_to_free]; it.skip(), i++) + { + uint16_t val = type_one_record_elements[index_to_free][i]; + JERRY_ASSERT (it.read () == val); + } + + JERRY_ASSERT (JERRY_ALIGNUP (type_one_record_element_counts[index_to_free]*2 + 8, RCS_DYN_STORAGE_ALIGNMENT) == + type_one_records[index_to_free]->get_size ()); + } + bool free_type_one; if (type_one_records_number == 0) @@ -291,6 +336,16 @@ main (int __attr_unused___ argc, JERRY_ASSERT (index_to_free >= 0 && index_to_free < type_one_records_number); + rcs_record_iterator_t it (&storage, type_one_records[index_to_free]); + it.skip (); // skip header + it.skip (); // skip header + for (uint32_t i = 0; i < type_one_record_element_counts[index_to_free]; it.skip(), i++) + { + uint16_t val = type_one_record_elements[index_to_free][i]; + JERRY_ASSERT (it.read () == val); + } + + // free the record storage.free_record_type_one (type_one_records[index_to_free]); type_one_records_number--; @@ -298,6 +353,8 @@ main (int __attr_unused___ argc, { type_one_records[index_to_free] = type_one_records[index_to_free + 1]; type_one_record_element_counts[index_to_free] = type_one_record_element_counts[index_to_free + 1]; + memcpy (type_one_record_elements[index_to_free], type_one_record_elements[index_to_free + 1], + test_max_type_one_record_elements * test_element_size_type_one_record); index_to_free++; } @@ -328,3 +385,9 @@ main (int __attr_unused___ argc, return 0; } /* main */ + +template test_rcs_record_type_one_t * +rcs_recordset_t::alloc_record (rcs_record_t::type_t, uint32_t); + +template test_rcs_record_type_two_t * +rcs_recordset_t::alloc_record (rcs_record_t::type_t);