From 603fa56acfc7988e7bf39aacbe73d016aed2fc20 Mon Sep 17 00:00:00 2001 From: SaeHie Park Date: Mon, 8 Jun 2015 08:34:11 +0900 Subject: [PATCH 1/3] Add vm_finalize() to clean program pointer for embed systems JerryScript-DCO-1.0-Signed-off-by: SaeHie Park saehie.park@samsung.com --- jerry-core/jerry.cpp | 1 + jerry-core/vm/vm.cpp | 9 +++++++++ jerry-core/vm/vm.h | 1 + 3 files changed, 11 insertions(+) diff --git a/jerry-core/jerry.cpp b/jerry-core/jerry.cpp index 411fac2aa8..24d91cb0af 100644 --- a/jerry-core/jerry.cpp +++ b/jerry-core/jerry.cpp @@ -1171,6 +1171,7 @@ jerry_cleanup (void) ecma_finalize (); serializer_free (); mem_finalize (is_show_mem_stats); + vm_finalize (); } /* jerry_cleanup */ /** diff --git a/jerry-core/vm/vm.cpp b/jerry-core/vm/vm.cpp index b21f94264a..203c709da4 100644 --- a/jerry-core/vm/vm.cpp +++ b/jerry-core/vm/vm.cpp @@ -350,6 +350,15 @@ vm_init (const opcode_t *program_p, /**< pointer to byte-code program */ __program = program_p; } /* vm_init */ +/** + * Cleanup interpreter + */ +void +vm_finalize (void) +{ + __program = NULL; +} /* vm_finalize */ + /** * Run global code */ diff --git a/jerry-core/vm/vm.h b/jerry-core/vm/vm.h index 37b7e90b71..7ed8acc5cd 100644 --- a/jerry-core/vm/vm.h +++ b/jerry-core/vm/vm.h @@ -21,6 +21,7 @@ #include "opcodes.h" extern void vm_init (const opcode_t* program_p, bool dump_mem_stats); +extern void vm_finalize (void); extern jerry_completion_code_t vm_run_global (void); extern ecma_completion_value_t vm_loop (int_data_t *int_data, vm_run_scope_t *run_scope_p); extern ecma_completion_value_t vm_run_from_pos (opcode_counter_t start_pos, From 723924f36fd625a62ff7e806d1c4fdfd093147fe Mon Sep 17 00:00:00 2001 From: SaeHie Park Date: Mon, 8 Jun 2015 09:03:25 +0900 Subject: [PATCH 2/3] New External Magic String API to save heap memory JerryScript-DCO-1.0-Signed-off-by: SaeHie Park saehie.park@samsung.com --- jerry-core/ecma/base/ecma-globals.h | 17 +- jerry-core/ecma/base/ecma-helpers-string.cpp | 276 +++++++++++++++++++ jerry-core/ecma/base/ecma-helpers.h | 10 + jerry-core/ecma/base/ecma-init-finalize.cpp | 1 + jerry-core/jerry-api.h | 24 ++ jerry-core/jerry.cpp | 13 + jerry-core/parser/js/lexer.cpp | 14 +- jerry-core/parser/js/literal.cpp | 38 ++- jerry-core/parser/js/literal.h | 2 + jerry-core/parser/js/opcodes-dumper.cpp | 8 +- jerry-core/parser/js/syntax-errors.cpp | 4 +- jerry-core/vm/pretty-printer.cpp | 7 +- tests/unit/test_api.cpp | 55 ++++ 13 files changed, 457 insertions(+), 12 deletions(-) diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index c45d743a34..2823f1f6dc 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -574,6 +574,12 @@ typedef uint8_t ecma_char_t; typedef uint16_t ecma_char_t; #endif /* CONFIG_ECMA_CHAR_ENCODING == CONFIG_ECMA_CHAR_UTF16 */ +/** + * Description of an ecma-character pointer + */ +typedef ecma_char_t* ecma_char_ptr_t; + + #if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32 /** * Description of an ecma-number @@ -746,7 +752,8 @@ typedef enum ECMA_STRING_CONTAINER_UINT32_IN_DESC, /**< actual data is UInt32-represeneted Number stored locally in the string's descriptor */ ECMA_STRING_CONTAINER_CONCATENATION, /**< the ecma-string is concatenation of two specified ecma-strings */ - ECMA_STRING_CONTAINER_MAGIC_STRING /**< the ecma-string is equal to one of ECMA magic strings */ + ECMA_STRING_CONTAINER_MAGIC_STRING, /**< the ecma-string is equal to one of ECMA magic strings */ + ECMA_STRING_CONTAINER_MAGIC_STRING_EX /**< the ecma-string is equal to one of external magic strings */ } ecma_string_container_t; FIXME (Move to library that should define the type (literal.h /* ? */)) @@ -768,6 +775,11 @@ typedef enum ECMA_MAGIC_STRING__COUNT /**< number of magic strings */ } ecma_magic_string_id_t; +/** + * Identifiers of implementation-defined external magic string constants + */ +typedef uint32_t ecma_magic_string_ex_id_t; + /** * ECMA string hash */ @@ -823,6 +835,9 @@ typedef struct ecma_string_t /** Identifier of magic string */ ecma_magic_string_id_t magic_string_id; + /** Identifier of external magic string */ + ecma_magic_string_ex_id_t magic_string_ex_id; + /** For zeroing and comparison in some cases */ uint32_t common_field; } u; diff --git a/jerry-core/ecma/base/ecma-helpers-string.cpp b/jerry-core/ecma/base/ecma-helpers-string.cpp index 7e5ca78ff7..e8d0cbbce5 100644 --- a/jerry-core/ecma/base/ecma-helpers-string.cpp +++ b/jerry-core/ecma/base/ecma-helpers-string.cpp @@ -51,6 +51,13 @@ JERRY_STATIC_ASSERT ((uint32_t) ((int32_t) ECMA_STRING_MAX_CONCATENATION_LENGTH) */ static ecma_length_t ecma_magic_string_lengths[ECMA_MAGIC_STRING__COUNT]; +/** + * External magic strings data array, count and lengths + */ +static const ecma_char_ptr_t* ecma_magic_string_ex_array = NULL; +static uint32_t ecma_magic_string_ex_count = 0; +static const ecma_length_t* ecma_magic_string_ex_lengths = NULL; + #ifndef JERRY_NDEBUG /** * Maximum length among lengths of magic strings @@ -67,6 +74,10 @@ ecma_init_ecma_string_from_magic_string_id (ecma_string_t *string_p, ecma_magic_string_id_t magic_string_id, bool is_stack_var); +static void +ecma_init_ecma_string_from_magic_string_ex_id (ecma_string_t *string_p, + ecma_magic_string_ex_id_t magic_string_ex_id, + bool is_stack_var); /** * Allocate a collection of ecma-chars. * @@ -296,6 +307,65 @@ ecma_strings_init (void) } } /* ecma_strings_init */ +/** + * Initialize external magic strings + */ +void +ecma_strings_ex_init (void) +{ + ecma_magic_string_ex_array = NULL; + ecma_magic_string_ex_count = 0; + ecma_magic_string_ex_lengths = NULL; +} /* ecma_strings_ex_init */ + +/** + * Register external magic strings + */ +void +ecma_strings_ex_set (const ecma_char_ptr_t* ex_str_items, /**< character arrays, representing + * external magic strings' contents */ + uint32_t count, /**< number of the strings */ + const ecma_length_t* ex_str_lengths) /**< lengths of the strings */ +{ + JERRY_ASSERT (ex_str_items != NULL); + JERRY_ASSERT (count > 0); + JERRY_ASSERT (ex_str_lengths != NULL); + + JERRY_ASSERT (ecma_magic_string_ex_array == NULL); + JERRY_ASSERT (ecma_magic_string_ex_count == 0); + JERRY_ASSERT (ecma_magic_string_ex_lengths == NULL); + + /* Set external magic strings information */ + ecma_magic_string_ex_array = ex_str_items; + ecma_magic_string_ex_count = count; + ecma_magic_string_ex_lengths = ex_str_lengths; + +#ifndef JERRY_NDEBUG + for (ecma_magic_string_ex_id_t id = (ecma_magic_string_ex_id_t) 0; + id < ecma_magic_string_ex_count; + id = (ecma_magic_string_ex_id_t) (id + 1)) + { + JERRY_ASSERT (ecma_magic_string_ex_lengths[id] == ecma_zt_string_length (ecma_get_magic_string_ex_zt (id))); + + ecma_magic_string_max_length = JERRY_MAX (ecma_magic_string_max_length, ecma_magic_string_ex_lengths[id]); + + JERRY_ASSERT (ecma_magic_string_max_length <= ECMA_STRING_MAGIC_STRING_LENGTH_LIMIT); + } +#endif /* !JERRY_NDEBUG */ +} /* ecma_strings_ex_init */ + +/** + * Get number of external magic strings + * + * @return number of the strings, if there were registered, + * zero - otherwise. + */ +uint32_t +ecma_get_magic_string_ex_count (void) +{ + return ecma_magic_string_ex_count; +} /* ecma_get_magic_string_ex_count */ + /** * Initialize ecma-string descriptor with string described by index in literal table */ @@ -318,7 +388,14 @@ ecma_init_ecma_string_from_lit_index (ecma_string_t *string_p, /**< descriptor t return; } + else if (lit.type == LIT_MAGIC_STR_EX) + { + ecma_init_ecma_string_from_magic_string_ex_id (string_p, + lit.data.magic_str_ex_id, + is_stack_var); + return; + } JERRY_ASSERT (lit.type == LIT_STR); string_p->refs = 1; @@ -354,6 +431,30 @@ ecma_init_ecma_string_from_magic_string_id (ecma_string_t *string_p, /**< descri string_p->u.magic_string_id = magic_string_id; } /* ecma_init_ecma_string_from_magic_string_id */ +/** + * Initialize external ecma-string descriptor with specified magic string + */ +static void +ecma_init_ecma_string_from_magic_string_ex_id (ecma_string_t *string_p, /**< descriptor to initialize */ + ecma_magic_string_ex_id_t magic_string_ex_id, /**< identifier of + the external magic string */ + 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 */ + + string_p->refs = 1; + string_p->is_stack_var = (is_stack_var != 0); + string_p->container = ECMA_STRING_CONTAINER_MAGIC_STRING_EX; + string_p->hash = ecma_chars_buffer_calc_hash_last_chars (ecma_get_magic_string_ex_zt (magic_string_ex_id), + ecma_magic_string_ex_lengths[magic_string_ex_id]); + + string_p->u.common_field = 0; + string_p->u.magic_string_ex_id = magic_string_ex_id; +} /* ecma_init_ecma_string_from_magic_string_ex_id */ + /** * Allocate new ecma-string and fill it with characters from specified buffer * @@ -370,6 +471,12 @@ ecma_new_ecma_string (const ecma_char_t *string_p) /**< zero-terminated string * return ecma_get_magic_string (magic_string_id); } + ecma_magic_string_ex_id_t magic_string_ex_id; + if (ecma_is_zt_ex_string_magic (string_p, &magic_string_ex_id)) + { + return ecma_get_magic_string_ex (magic_string_ex_id); + } + ecma_length_t length = 0; const ecma_char_t *iter_p = string_p; @@ -533,6 +640,23 @@ ecma_new_ecma_string_from_magic_string_id (ecma_magic_string_id_t id) /**< ident return string_desc_p; } /* ecma_new_ecma_string_from_magic_string_id */ +/** + * Allocate new ecma-string and fill it with reference to ECMA magic string + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t* +ecma_new_ecma_string_from_magic_string_ex_id (ecma_magic_string_ex_id_t id) /**< identifier of externl magic string */ +{ + JERRY_ASSERT (id < ecma_magic_string_ex_count); + + ecma_string_t* string_desc_p = ecma_alloc_string (); + ecma_init_ecma_string_from_magic_string_ex_id (string_desc_p, id, false); + + return string_desc_p; +} /* ecma_new_ecma_string_from_magic_string_ex_id */ + + /** * Concatenate ecma-strings * @@ -616,6 +740,7 @@ ecma_copy_ecma_string (ecma_string_t *string_desc_p) /**< string descriptor */ case ECMA_STRING_CONTAINER_LIT_TABLE: case ECMA_STRING_CONTAINER_UINT32_IN_DESC: case ECMA_STRING_CONTAINER_MAGIC_STRING: + case ECMA_STRING_CONTAINER_MAGIC_STRING_EX: { new_str_p = ecma_alloc_string (); @@ -778,6 +903,7 @@ ecma_deref_ecma_string (ecma_string_t *string_p) /**< ecma-string */ case ECMA_STRING_CONTAINER_LIT_TABLE: case ECMA_STRING_CONTAINER_UINT32_IN_DESC: case ECMA_STRING_CONTAINER_MAGIC_STRING: + case ECMA_STRING_CONTAINER_MAGIC_STRING_EX: { /* only the string descriptor itself should be freed */ } @@ -812,6 +938,7 @@ ecma_check_that_ecma_string_need_not_be_freed (const ecma_string_t *string_p) /* JERRY_ASSERT (container_type == ECMA_STRING_CONTAINER_LIT_TABLE || container_type == ECMA_STRING_CONTAINER_MAGIC_STRING || + container_type == ECMA_STRING_CONTAINER_MAGIC_STRING_EX || container_type == ECMA_STRING_CONTAINER_UINT32_IN_DESC); #endif /* !JERRY_NDEBUG */ } /* ecma_check_that_ecma_string_need_not_be_freed */ @@ -845,6 +972,7 @@ ecma_string_to_number (const ecma_string_t *str_p) /**< ecma-string */ case ECMA_STRING_CONTAINER_HEAP_CHUNKS: case ECMA_STRING_CONTAINER_CONCATENATION: case ECMA_STRING_CONTAINER_MAGIC_STRING: + case ECMA_STRING_CONTAINER_MAGIC_STRING_EX: { const int32_t string_len = ecma_string_get_length (str_p); const size_t string_buf_size = (size_t) (string_len + 1) * sizeof (ecma_char_t); @@ -976,6 +1104,19 @@ ecma_string_to_zt_string (const ecma_string_t *string_desc_p, /**< ecma-string d JERRY_ASSERT (required_buffer_size == (ssize_t) bytes_to_copy); + break; + } + case ECMA_STRING_CONTAINER_MAGIC_STRING_EX: + { + const ecma_magic_string_ex_id_t id = string_desc_p->u.magic_string_ex_id; + const size_t length = ecma_magic_string_ex_lengths[id]; + + size_t bytes_to_copy = (length + 1) * sizeof (ecma_char_t); + + memcpy (buffer_p, ecma_get_magic_string_ex_zt (id), bytes_to_copy); + + JERRY_ASSERT (required_buffer_size == (ssize_t) bytes_to_copy); + break; } } @@ -1010,6 +1151,12 @@ ecma_compare_ecma_strings_longpath (const ecma_string_t *string1_p, /* ecma-stri return false; } + else if (string1_p->container == ECMA_STRING_CONTAINER_MAGIC_STRING_EX) + { + JERRY_ASSERT (string1_p->u.magic_string_ex_id != string2_p->u.magic_string_ex_id); + + return false; + } else if (string1_p->container == ECMA_STRING_CONTAINER_UINT32_IN_DESC) { JERRY_ASSERT (string1_p->u.uint32_number != string2_p->u.uint32_number); @@ -1077,6 +1224,12 @@ ecma_compare_ecma_strings_longpath (const ecma_string_t *string1_p, /* ecma-stri return false; } + case ECMA_STRING_CONTAINER_MAGIC_STRING_EX: + { + JERRY_ASSERT (string1_p->u.magic_string_ex_id != string2_p->u.magic_string_ex_id); + + return false; + } case ECMA_STRING_CONTAINER_UINT32_IN_DESC: { JERRY_ASSERT (string1_p->u.uint32_number != string2_p->u.uint32_number); @@ -1300,6 +1453,10 @@ ecma_string_get_length (const ecma_string_t *string_p) /**< ecma-string */ { return ecma_magic_string_lengths[string_p->u.magic_string_id]; } + else if (container == ECMA_STRING_CONTAINER_MAGIC_STRING_EX) + { + return ecma_magic_string_ex_lengths[string_p->u.magic_string_ex_id]; + } else if (container == ECMA_STRING_CONTAINER_UINT32_IN_DESC) { const uint32_t uint32_number = string_p->u.uint32_number; @@ -1607,6 +1764,25 @@ ecma_get_magic_string_zt (ecma_magic_string_id_t id) /**< magic string id */ JERRY_UNREACHABLE (); } /* ecma_get_magic_string_zt */ +/** + * Get specified magic string as zero-terminated string from external table + * + * @return pointer to zero-terminated magic string + */ +const ecma_char_t* +ecma_get_magic_string_ex_zt (ecma_magic_string_ex_id_t id) /**< extern magic string id */ +{ + TODO (Support UTF-16); + + if (ecma_magic_string_ex_array && id < ecma_magic_string_ex_count) + { + return ecma_magic_string_ex_array[id]; + } + + JERRY_UNREACHABLE (); +} /* ecma_get_magic_string_ex_zt */ + + /** * Get specified magic string * @@ -1618,6 +1794,17 @@ ecma_get_magic_string (ecma_magic_string_id_t id) /**< magic string id */ return ecma_new_ecma_string_from_magic_string_id (id); } /* ecma_get_magic_string */ +/** + * Get specified external magic string + * + * @return ecma-string containing specified external magic string + */ +ecma_string_t* +ecma_get_magic_string_ex (ecma_magic_string_ex_id_t id) /**< external magic string id */ +{ + return ecma_new_ecma_string_from_magic_string_ex_id (id); +} /* ecma_get_magic_string_ex */ + /** * Check if passed zt-string equals to one of magic strings * and if equal magic string was found, return it's id in 'out_id_p' argument. @@ -1648,6 +1835,36 @@ ecma_is_zt_string_magic (const ecma_char_t *zt_string_p, /**< zero-terminated st return false; } /* ecma_is_zt_string_magic */ +/** + * Check if passed zt-string equals to one of external magic strings + * and if equal magic string was found, return it's id in 'out_id_p' argument. + * + * @return true - if external magic string equal to passed string was found, + * false - otherwise. + */ +bool +ecma_is_zt_ex_string_magic (const ecma_char_t *zt_string_p, /**< zero-terminated string */ + ecma_magic_string_ex_id_t *out_id_p) /**< out: external magic string's id */ +{ + TODO (Improve performance of search); + + for (ecma_magic_string_ex_id_t id = (ecma_magic_string_ex_id_t) 0; + id < ecma_magic_string_ex_count; + id = (ecma_magic_string_ex_id_t) (id + 1)) + { + if (ecma_compare_zt_strings (zt_string_p, ecma_get_magic_string_ex_zt (id))) + { + *out_id_p = id; + + return true; + } + } + + *out_id_p = ecma_magic_string_ex_count; + + return false; +} /* ecma_is_zt_ex_string_magic */ + /** * Long path part of ecma_is_string_magic * @@ -1669,6 +1886,27 @@ ecma_is_string_magic_longpath (const ecma_string_t *string_p, /**< ecma-string * return ecma_is_zt_string_magic (zt_string_buffer, out_id_p); } /* ecma_is_string_magic_longpath */ +/** + * Long path part of ecma_is_ex_string_magic + * + * Converts passed ecma-string to zt-string and + * checks if it is equal to one of magic string + * + * @return true - if magic string equal to passed string was found, + * false - otherwise. + */ +static bool +ecma_is_ex_string_magic_longpath (const ecma_string_t *string_p, /**< ecma-string */ + ecma_magic_string_ex_id_t *out_id_p) /**< out: external magic string's id */ +{ + ecma_char_t zt_string_buffer[ECMA_STRING_MAGIC_STRING_LENGTH_LIMIT + 1]; + + ssize_t copied = ecma_string_to_zt_string (string_p, zt_string_buffer, (ssize_t) sizeof (zt_string_buffer)); + JERRY_ASSERT (copied > 0); + + return ecma_is_zt_ex_string_magic (zt_string_buffer, out_id_p); +} /* ecma_is_ex_string_magic_longpath */ + /** * Check if passed string equals to one of magic strings * and if equal magic string was found, return it's id in 'out_id_p' argument. @@ -1707,6 +1945,44 @@ ecma_is_string_magic (const ecma_string_t *string_p, /**< ecma-string */ } } /* ecma_is_string_magic */ +/** + * Check if passed string equals to one of external magic strings + * and if equal external magic string was found, return it's id in 'out_id_p' argument. + * + * @return true - if external magic string equal to passed string was found, + * false - otherwise. + */ +bool +ecma_is_ex_string_magic (const ecma_string_t *string_p, /**< ecma-string */ + ecma_magic_string_ex_id_t *out_id_p) /**< out: external magic string's id */ +{ + if (string_p->container == ECMA_STRING_CONTAINER_MAGIC_STRING_EX) + { + JERRY_ASSERT (string_p->u.magic_string_ex_id < ecma_magic_string_ex_count); + + *out_id_p = (ecma_magic_string_ex_id_t) string_p->u.magic_string_ex_id; + + return true; + } + else if (string_p->container == ECMA_STRING_CONTAINER_CONCATENATION + && ecma_string_get_length (string_p) <= ECMA_STRING_MAGIC_STRING_LENGTH_LIMIT) + { + return ecma_is_ex_string_magic_longpath (string_p, out_id_p); + } + else + { + /* + * Any ecma-string constructor except ecma_concat_ecma_strings + * should return ecma-string with ECMA_STRING_CONTAINER_MAGIC_STRING_EX + * container type if new ecma-string's content is equal to one of external magic strings. + */ + JERRY_ASSERT (ecma_string_get_length (string_p) > ECMA_STRING_MAGIC_STRING_LENGTH_LIMIT + || !ecma_is_ex_string_magic_longpath (string_p, out_id_p)); + + return false; + } +} /* ecma_is_ex_string_magic */ + /** * Try to calculate hash of the ecma-string * diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 618bc517c4..2df2bfd2ca 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -118,6 +118,7 @@ extern ecma_string_t* ecma_new_ecma_string_from_lit_index (literal_index_t lit_i 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); +extern ecma_string_t* ecma_new_ecma_string_from_magic_string_ex_id (ecma_magic_string_ex_id_t id); extern ecma_string_t* ecma_concat_ecma_strings (ecma_string_t *string1_p, ecma_string_t *string2_p); extern ecma_string_t* ecma_copy_or_ref_ecma_string (ecma_string_t *string_desc_p); extern void ecma_deref_ecma_string (ecma_string_t *string_p); @@ -143,10 +144,19 @@ ecma_copy_zt_string_to_buffer (const ecma_char_t *string_p, extern ecma_length_t ecma_zt_string_length (const ecma_char_t *string_p); extern void ecma_strings_init (void); +extern void ecma_strings_ex_init (void); +extern void ecma_strings_ex_set (const ecma_char_ptr_t* ex_str_items, + uint32_t count, + const ecma_length_t* ex_str_lengths); +extern uint32_t ecma_get_magic_string_ex_count (void); extern const ecma_char_t* ecma_get_magic_string_zt (ecma_magic_string_id_t id); +extern const ecma_char_t* ecma_get_magic_string_ex_zt (ecma_magic_string_ex_id_t id); extern ecma_string_t* ecma_get_magic_string (ecma_magic_string_id_t id); +extern ecma_string_t* ecma_get_magic_string_ex (ecma_magic_string_ex_id_t id); extern bool ecma_is_string_magic (const ecma_string_t *string_p, ecma_magic_string_id_t *out_id_p); +extern bool ecma_is_ex_string_magic (const ecma_string_t *string_p, ecma_magic_string_ex_id_t *out_id_p); extern bool ecma_is_zt_string_magic (const ecma_char_t *zt_string_p, ecma_magic_string_id_t *out_id_p); +extern bool ecma_is_zt_ex_string_magic (const ecma_char_t *zt_string_p, ecma_magic_string_ex_id_t *out_id_p); extern ecma_string_hash_t ecma_string_hash (const ecma_string_t *string_p); extern ecma_string_hash_t ecma_chars_buffer_calc_hash_last_chars (const ecma_char_t *chars, ecma_length_t length); diff --git a/jerry-core/ecma/base/ecma-init-finalize.cpp b/jerry-core/ecma/base/ecma-init-finalize.cpp index de69bdf169..68c29c503d 100644 --- a/jerry-core/ecma/base/ecma-init-finalize.cpp +++ b/jerry-core/ecma/base/ecma-init-finalize.cpp @@ -36,6 +36,7 @@ void ecma_init (void) { ecma_strings_init (); + ecma_strings_ex_init (); ecma_init_builtins (); ecma_lcache_init (); ecma_stack_init (); diff --git a/jerry-core/jerry-api.h b/jerry-core/jerry-api.h index 5641d9023b..4165a0dfec 100644 --- a/jerry-core/jerry-api.h +++ b/jerry-core/jerry-api.h @@ -71,6 +71,25 @@ typedef enum JERRY_API_ERROR_URI /**< URIError */ } jerry_api_error_t; +/** + * Jerry's char value +*/ +#if CONFIG_ECMA_CHAR_ENCODING == CONFIG_ECMA_CHAR_ASCII +typedef uint8_t jerry_api_char_t; +#elif CONFIG_ECMA_CHAR_ENCODING == CONFIG_ECMA_CHAR_UTF16 +typedef uint16_t jerry_api_char_t; +#endif /* CONFIG_ECMA_CHAR_ENCODING == CONFIG_ECMA_CHAR_UTF16 */ + +/** + * Pointer to an array of character values + */ +typedef jerry_api_char_t* jerry_api_char_ptr_t; + +/** + * Jerry's length +*/ +typedef uint16_t jerry_api_length_t; + /** * Jerry's string value */ @@ -198,6 +217,11 @@ jerry_completion_code_t jerry_api_eval (const char *source_p, extern EXTERN_C jerry_api_object_t* jerry_api_get_global (void); +extern EXTERN_C +void jerry_register_external_magic_strings (const jerry_api_char_ptr_t* ex_str_items, + uint32_t count, + const jerry_api_length_t* str_lengths); + /** * @} */ diff --git a/jerry-core/jerry.cpp b/jerry-core/jerry.cpp index 24d91cb0af..50754731e2 100644 --- a/jerry-core/jerry.cpp +++ b/jerry-core/jerry.cpp @@ -1337,3 +1337,16 @@ jerry_pop_ctx (void) JERRY_UNIMPLEMENTED ("Run contexts are not implemented"); } /* jerry_pop_ctx */ #endif /* CONFIG_JERRY_ENABLE_CONTEXTS */ + + +/** + * Register external magic string array + */ +void +jerry_register_external_magic_strings (const jerry_api_char_ptr_t* ex_str_items, /**< character arrays, representing + * external magic strings' contents */ + uint32_t count, /**< number of the strings */ + const jerry_api_length_t* str_lengths) /**< lengths of the strings */ +{ + ecma_strings_ex_set ((const ecma_char_ptr_t*)ex_str_items, count, (const ecma_length_t*)str_lengths); +} /* jerry_register_external_magic_strings */ diff --git a/jerry-core/parser/js/lexer.cpp b/jerry-core/parser/js/lexer.cpp index ad10b9c0ac..54d5bed2d9 100644 --- a/jerry-core/parser/js/lexer.cpp +++ b/jerry-core/parser/js/lexer.cpp @@ -133,6 +133,16 @@ string_equals_to_literal (const ecma_char_t *str_p, /**< characters buffer */ 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 */ @@ -194,7 +204,7 @@ convert_string_to_token (token_type tt, /**< token type */ for (literal_index_t i = 0; i < STACK_SIZE (literals); i++) { const literal lit = STACK_ELEMENT (literals, i); - if ((lit.type == LIT_STR || lit.type == LIT_MAGIC_STR) + 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); @@ -202,7 +212,7 @@ convert_string_to_token (token_type tt, /**< token type */ } literal lit = create_literal_from_str (str_p, length); - JERRY_ASSERT (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR); + 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); diff --git a/jerry-core/parser/js/literal.cpp b/jerry-core/parser/js/literal.cpp index 2fc010285c..ca143850ff 100644 --- a/jerry-core/parser/js/literal.cpp +++ b/jerry-core/parser/js/literal.cpp @@ -79,6 +79,27 @@ create_literal_from_zt (const ecma_char_t *s, ecma_length_t len) } } + 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; @@ -108,7 +129,7 @@ literal_equal_type_s (literal lit, const char *s) bool literal_equal_type_zt (literal lit, const ecma_char_t *s) { - if (lit.type != LIT_STR && lit.type != LIT_MAGIC_STR) + if (lit.type != LIT_STR && lit.type != LIT_MAGIC_STR && lit.type != LIT_MAGIC_STR_EX) { return false; } @@ -142,6 +163,10 @@ literal_equal_lp (literal lit, lp_string lp) { 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]; @@ -172,6 +197,10 @@ literal_equal (literal lit1, literal lit2) { 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); @@ -206,6 +235,10 @@ literal_equal_zt (literal lit, const ecma_char_t *s) { 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]; @@ -230,12 +263,13 @@ literal_equal_num (literal lit, ecma_number_t num) const ecma_char_t * literal_to_zt (literal lit) { - JERRY_ASSERT (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR); + 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 index c089cb70f1..b2dfd3c98e 100644 --- a/jerry-core/parser/js/literal.h +++ b/jerry-core/parser/js/literal.h @@ -24,6 +24,7 @@ typedef enum __attr_packed___ LIT_UNKNOWN, LIT_STR, LIT_MAGIC_STR, + LIT_MAGIC_STR_EX, LIT_NUMBER } literal_type; @@ -32,6 +33,7 @@ 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; diff --git a/jerry-core/parser/js/opcodes-dumper.cpp b/jerry-core/parser/js/opcodes-dumper.cpp index fb9a5edc11..51eaf476bf 100644 --- a/jerry-core/parser/js/opcodes-dumper.cpp +++ b/jerry-core/parser/js/opcodes-dumper.cpp @@ -1099,7 +1099,7 @@ 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); operand tmp; - if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR) + if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX) { tmp = dump_string_assignment_res (name.data.lit_id); } @@ -1132,7 +1132,7 @@ dump_prop_getter_decl (operand name, operand func) JERRY_ASSERT (func.type == OPERAND_TMP); const literal lit = lexer_get_literal_by_id (name.data.lit_id); operand tmp; - if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR) + if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX) { tmp = dump_string_assignment_res (name.data.lit_id); } @@ -1152,7 +1152,7 @@ dump_prop_setter_decl (operand name, operand func) JERRY_ASSERT (func.type == OPERAND_TMP); const literal lit = lexer_get_literal_by_id (name.data.lit_id); operand tmp; - if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR) + if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX) { tmp = dump_string_assignment_res (name.data.lit_id); } @@ -1348,7 +1348,7 @@ 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_STR) + if (lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX || lit.type == LIT_STR) { syntax_check_delete (is_strict, loc); switch (res.type) diff --git a/jerry-core/parser/js/syntax-errors.cpp b/jerry-core/parser/js/syntax-errors.cpp index e469af9be1..c328508612 100644 --- a/jerry-core/parser/js/syntax-errors.cpp +++ b/jerry-core/parser/js/syntax-errors.cpp @@ -180,12 +180,12 @@ syntax_check_for_syntax_errors_in_formal_param_list (bool is_strict, locus loc _ { 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); + JERRY_ASSERT (previous.type == LIT_STR || previous.type == LIT_MAGIC_STR || previous.type == LIT_MAGIC_STR_EX); 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); + JERRY_ASSERT (current.type == LIT_STR || current.type == LIT_MAGIC_STR || current.type == LIT_MAGIC_STR_EX); if (literal_equal_type (previous, current)) { PARSE_ERROR_VARG ("Duplication of literal '%s' in FormalParameterList is not allowed in strict mode", diff --git a/jerry-core/vm/pretty-printer.cpp b/jerry-core/vm/pretty-printer.cpp index 8bbe5a4336..e38c0a5b50 100644 --- a/jerry-core/vm/pretty-printer.cpp +++ b/jerry-core/vm/pretty-printer.cpp @@ -66,6 +66,11 @@ dump_literal (literal lit) 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)); @@ -102,7 +107,7 @@ static const char * lit_id_to_str (literal_index_t id) { literal lit = lexer_get_literal_by_id (id); - if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR) + if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX) { return (char *) literal_to_zt (lit); } diff --git a/tests/unit/test_api.cpp b/tests/unit/test_api.cpp index 84f2d2e28f..f002f35bde 100644 --- a/tests/unit/test_api.cpp +++ b/tests/unit/test_api.cpp @@ -180,6 +180,44 @@ handler_construct (const jerry_api_object_t *function_obj_p, return true; } /* handler_construct */ + +/** + * Extended Magic Strings + */ +#define JERRY_MAGIC_STRING_ITEMS \ + JERRY_MAGIC_STRING_DEF (GLOBAL, global) \ + JERRY_MAGIC_STRING_DEF (CONSOLE, console) + + +#define JERRY_MAGIC_STRING_DEF(NAME, STRING) \ + static const char jerry_magic_string_ex_ ## NAME[] = # STRING; + +JERRY_MAGIC_STRING_ITEMS + +#undef JERRY_MAGIC_STRING_DEF + +const jerry_api_length_t magic_string_lengths[] = +{ +#define JERRY_MAGIC_STRING_DEF(NAME, STRING) \ + (jerry_api_length_t)(sizeof(jerry_magic_string_ex_ ## NAME) - 1u), + + JERRY_MAGIC_STRING_ITEMS + +#undef JERRY_MAGIC_STRING_DEF +}; + +const jerry_api_char_ptr_t magic_string_items[] = +{ +#define JERRY_MAGIC_STRING_DEF(NAME, STRING) \ + (const jerry_api_char_ptr_t)jerry_magic_string_ex_ ## NAME, + + JERRY_MAGIC_STRING_ITEMS + +#undef JERRY_MAGIC_STRING_DEF +}; + + + int main (void) { @@ -408,5 +446,22 @@ main (void) assert (test_api_is_free_callback_was_called); + // External Magic String + jerry_init (JERRY_FLAG_SHOW_OPCODES); + + uint32_t num_magic_string_items = sizeof (magic_string_items) / sizeof (jerry_api_char_ptr_t); + jerry_register_external_magic_strings (magic_string_items, + num_magic_string_items, + magic_string_lengths); + + const char *ms_code_src_p = "var global = {}; var console = [1]; var process = 1;"; + is_ok = jerry_parse (ms_code_src_p, strlen (ms_code_src_p)); + assert (is_ok); + + is_ok = (jerry_run () == JERRY_COMPLETION_CODE_OK); + assert (is_ok); + + jerry_cleanup (); + return 0; } From 43ec3a33cfcb9d0fd039e0213e3e4b1fd658edbb Mon Sep 17 00:00:00 2001 From: SaeHie Park Date: Mon, 8 Jun 2015 09:25:44 +0900 Subject: [PATCH 3/3] Enable pretty-printer for unittests also * dump string literals with test_api to see jerry_register_external_magic_strings is working ok JerryScript-DCO-1.0-Signed-off-by: SaeHie Park saehie.park@samsung.com --- jerry-core/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jerry-core/CMakeLists.txt b/jerry-core/CMakeLists.txt index 6828d9ebf7..20de934fbc 100644 --- a/jerry-core/CMakeLists.txt +++ b/jerry-core/CMakeLists.txt @@ -43,7 +43,7 @@ project (JerryCore CXX C ASM) set(DEFINES_JERRY_RELEASE JERRY_NDEBUG) # Unit tests - set(DEFINES_JERRY_UNITTESTS ) + set(DEFINES_JERRY_UNITTESTS JERRY_ENABLE_PRETTY_PRINTER) # Modifiers # Full profile