From 51e3c4455a7de73f1b46f7c433deb6652930b3e6 Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Fri, 23 Feb 2018 00:21:46 +0100 Subject: [PATCH] Implement direct strings. (#2196) Direct strings are a new type of direct ecma-values (no memory allocation is needed for encoding them) in JerryScript. Currently magic strings, external magic strings and uint values are encoded as direct strings. The constant pool of JerryScript byte-code is changed to hold ecma-values rather than cpointers to support direct strings. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com --- jerry-core/api/jerry-snapshot.c | 367 ++++-- jerry-core/api/jerry-snapshot.h | 2 +- jerry-core/api/jerry.c | 13 +- jerry-core/debugger/debugger.c | 5 +- jerry-core/ecma/base/ecma-gc.c | 12 +- jerry-core/ecma/base/ecma-globals.h | 100 +- .../base/ecma-helpers-external-pointers.c | 17 +- jerry-core/ecma/base/ecma-helpers-string.c | 1158 ++++++++++------- jerry-core/ecma/base/ecma-helpers-value.c | 21 +- .../base/ecma-helpers-values-collection.c | 10 +- jerry-core/ecma/base/ecma-helpers.c | 25 +- jerry-core/ecma/base/ecma-helpers.h | 2 - jerry-core/ecma/base/ecma-lcache.c | 33 +- jerry-core/ecma/base/ecma-literal-storage.c | 373 +++--- jerry-core/ecma/base/ecma-literal-storage.h | 26 +- jerry-core/ecma/base/ecma-property-hashmap.c | 4 +- .../ecma/builtin-objects/ecma-builtins.c | 4 +- .../ecma-builtin-typedarray-prototype.c | 7 +- .../ecma/operations/ecma-function-object.c | 5 +- jerry-core/ecma/operations/ecma-jobqueue.c | 11 +- .../ecma/operations/ecma-objects-arguments.c | 37 +- jerry-core/ecma/operations/ecma-objects.c | 82 +- .../ecma/operations/ecma-promise-object.c | 47 +- .../ecma/operations/ecma-regexp-object.c | 2 +- jerry-core/parser/js/byte-code.h | 7 +- jerry-core/parser/js/common.c | 6 +- jerry-core/parser/js/common.h | 2 +- jerry-core/parser/js/js-lexer.c | 6 +- jerry-core/parser/js/js-parser.c | 108 +- jerry-core/parser/regexp/re-bytecode.h | 2 +- jerry-core/parser/regexp/re-compiler.c | 5 +- jerry-core/vm/opcodes.c | 4 +- jerry-core/vm/opcodes.h | 2 +- jerry-core/vm/vm-defines.h | 2 +- jerry-core/vm/vm.c | 103 +- tests/unit-core/test-literal-storage.c | 11 +- tests/unit-core/test-snapshot.c | 20 +- 37 files changed, 1493 insertions(+), 1148 deletions(-) diff --git a/jerry-core/api/jerry-snapshot.c b/jerry-core/api/jerry-snapshot.c index 03243e539..90852f45a 100644 --- a/jerry-core/api/jerry-snapshot.c +++ b/jerry-core/api/jerry-snapshot.c @@ -154,9 +154,8 @@ snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< compiled globals_p->snapshot_buffer_write_offset += sizeof (ecma_compiled_code_t); - jmem_cpointer_t pattern_cp = ((re_compiled_code_t *) compiled_code_p)->pattern_cp; - ecma_string_t *pattern_string_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, - pattern_cp); + ecma_value_t pattern = ((re_compiled_code_t *) compiled_code_p)->pattern; + ecma_string_t *pattern_string_p = ecma_get_string_from_value (pattern); ecma_length_t pattern_size = 0; @@ -206,34 +205,34 @@ snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< compiled /* Sub-functions and regular expressions are stored recursively. */ uint8_t *src_buffer_p = (uint8_t *) compiled_code_p; uint8_t *dst_buffer_p = (uint8_t *) copied_code_p; - jmem_cpointer_t *src_literal_start_p; - jmem_cpointer_t *dst_literal_start_p; + ecma_value_t *src_literal_start_p; + ecma_value_t *dst_literal_start_p; uint32_t const_literal_end; uint32_t literal_end; if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) { - src_literal_start_p = (jmem_cpointer_t *) (src_buffer_p + sizeof (cbc_uint16_arguments_t)); - dst_literal_start_p = (jmem_cpointer_t *) (dst_buffer_p + sizeof (cbc_uint16_arguments_t)); + src_literal_start_p = (ecma_value_t *) (src_buffer_p + sizeof (cbc_uint16_arguments_t)); + dst_literal_start_p = (ecma_value_t *) (dst_buffer_p + sizeof (cbc_uint16_arguments_t)); cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) src_buffer_p; - literal_end = args_p->literal_end; - const_literal_end = args_p->const_literal_end; + literal_end = (uint32_t) (args_p->literal_end - args_p->register_end); + const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); } else { - src_literal_start_p = (jmem_cpointer_t *) (src_buffer_p + sizeof (cbc_uint8_arguments_t)); - dst_literal_start_p = (jmem_cpointer_t *) (dst_buffer_p + sizeof (cbc_uint8_arguments_t)); + src_literal_start_p = (ecma_value_t *) (src_buffer_p + sizeof (cbc_uint8_arguments_t)); + dst_literal_start_p = (ecma_value_t *) (dst_buffer_p + sizeof (cbc_uint8_arguments_t)); cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) src_buffer_p; - literal_end = args_p->literal_end; - const_literal_end = args_p->const_literal_end; + literal_end = (uint32_t) (args_p->literal_end - args_p->register_end); + const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); } for (uint32_t i = const_literal_end; i < literal_end; i++) { - ecma_compiled_code_t *bytecode_p = ECMA_GET_NON_NULL_POINTER (ecma_compiled_code_t, - src_literal_start_p[i]); + ecma_compiled_code_t *bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, + src_literal_start_p[i]); if (bytecode_p == compiled_code_p) { @@ -268,39 +267,55 @@ jerry_snapshot_set_offsets (uint32_t *buffer_p, /**< buffer */ if (bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION) { - jmem_cpointer_t *literal_start_p; + ecma_value_t *literal_start_p; uint32_t argument_end; - uint32_t register_end; uint32_t const_literal_end; if (bytecode_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) { - literal_start_p = (jmem_cpointer_t *) (((uint8_t *) buffer_p) + sizeof (cbc_uint16_arguments_t)); + literal_start_p = (ecma_value_t *) (((uint8_t *) buffer_p) + sizeof (cbc_uint16_arguments_t)); cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) buffer_p; argument_end = args_p->argument_end; - register_end = args_p->register_end; - const_literal_end = args_p->const_literal_end; + const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); } else { - literal_start_p = (jmem_cpointer_t *) (((uint8_t *) buffer_p) + sizeof (cbc_uint8_arguments_t)); + literal_start_p = (ecma_value_t *) (((uint8_t *) buffer_p) + sizeof (cbc_uint8_arguments_t)); cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) buffer_p; argument_end = args_p->argument_end; - register_end = args_p->register_end; - const_literal_end = args_p->const_literal_end; + const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); } - uint32_t register_clear_start = 0; - - if ((bytecode_p->status_flags & CBC_CODE_FLAGS_ARGUMENTS_NEEDED) - && !(bytecode_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE)) + for (uint32_t i = 0; i < const_literal_end; i++) { + if (ecma_is_value_string (literal_start_p[i]) + || ecma_is_value_float_number (literal_start_p[i])) + { + lit_mem_to_snapshot_id_map_entry_t *current_p = lit_map_p; + + while (current_p->literal_id != literal_start_p[i]) + { + current_p++; + } + + literal_start_p[i] = current_p->literal_offset; + } + } + + if (bytecode_p->status_flags & CBC_CODE_FLAGS_NON_STRICT_ARGUMENTS_NEEDED) + { + uint8_t *byte_p = (uint8_t *) bytecode_p; + byte_p += ((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG; + literal_start_p = ((ecma_value_t *) byte_p) - argument_end; + for (uint32_t i = 0; i < argument_end; i++) { - if (literal_start_p[i] != JMEM_CP_NULL) + if (literal_start_p[i] != ECMA_VALUE_EMPTY) { + JERRY_ASSERT (ecma_is_value_string (literal_start_p[i])); + lit_mem_to_snapshot_id_map_entry_t *current_p = lit_map_p; while (current_p->literal_id != literal_start_p[i]) @@ -311,28 +326,6 @@ jerry_snapshot_set_offsets (uint32_t *buffer_p, /**< buffer */ literal_start_p[i] = current_p->literal_offset; } } - - register_clear_start = argument_end; - } - - for (uint32_t i = register_clear_start; i < register_end; i++) - { - literal_start_p[i] = JMEM_CP_NULL; - } - - for (uint32_t i = register_end; i < const_literal_end; i++) - { - lit_mem_to_snapshot_id_map_entry_t *current_p = lit_map_p; - - if (literal_start_p[i] != JMEM_CP_NULL) - { - while (current_p->literal_id != literal_start_p[i]) - { - current_p++; - } - - literal_start_p[i] = current_p->literal_offset; - } } /* Set reference counter to 1. */ @@ -367,7 +360,6 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th * current primary function */ size_t offset, /**< byte code offset */ const uint8_t *literal_base_p, /**< literal start */ - const uint8_t *number_base_p, /**< literal number start */ bool copy_bytecode) /**< byte code should be copied to memory */ { ecma_compiled_code_t *bytecode_p = (ecma_compiled_code_t *) (base_addr_p + offset); @@ -397,23 +389,36 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th } size_t header_size; - uint32_t literal_end; + uint32_t argument_end = 0; uint32_t const_literal_end; + uint32_t literal_end; if (bytecode_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) { uint8_t *byte_p = (uint8_t *) bytecode_p; cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) byte_p; - literal_end = args_p->literal_end; - const_literal_end = args_p->const_literal_end; + + if (bytecode_p->status_flags & CBC_CODE_FLAGS_NON_STRICT_ARGUMENTS_NEEDED) + { + argument_end = args_p->argument_end; + } + + const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); + literal_end = (uint32_t) (args_p->literal_end - args_p->register_end); header_size = sizeof (cbc_uint16_arguments_t); } else { uint8_t *byte_p = (uint8_t *) bytecode_p; cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) byte_p; - literal_end = args_p->literal_end; - const_literal_end = args_p->const_literal_end; + + if (bytecode_p->status_flags & CBC_CODE_FLAGS_NON_STRICT_ARGUMENTS_NEEDED) + { + argument_end = args_p->argument_end; + } + + const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); + literal_end = (uint32_t) (args_p->literal_end - args_p->register_end); header_size = sizeof (cbc_uint8_arguments_t); } @@ -430,25 +435,42 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th } else { - code_size = (uint32_t) (header_size + literal_end * sizeof (jmem_cpointer_t)); + uint32_t start_offset = (uint32_t) (header_size + literal_end * sizeof (ecma_value_t)); - uint8_t *real_bytecode_p = ((uint8_t *) bytecode_p) + code_size; - uint32_t total_size = JERRY_ALIGNUP (code_size + 1 + sizeof (uint8_t *), JMEM_ALIGNMENT); + uint8_t *real_bytecode_p = ((uint8_t *) bytecode_p) + start_offset; + uint32_t new_code_size = (uint32_t) (start_offset + 1 + sizeof (uint8_t *)); - bytecode_p = (ecma_compiled_code_t *) jmem_heap_alloc_block (total_size); + if (argument_end != 0) + { + new_code_size += (uint32_t) (argument_end * sizeof (ecma_value_t)); + } + + new_code_size = JERRY_ALIGNUP (new_code_size, JMEM_ALIGNMENT); + + bytecode_p = (ecma_compiled_code_t *) jmem_heap_alloc_block (new_code_size); #ifdef JMEM_STATS - jmem_stats_allocate_byte_code_bytes (total_size); + jmem_stats_allocate_byte_code_bytes (new_code_size); #endif /* JMEM_STATS */ - memcpy (bytecode_p, base_addr_p + offset, code_size); + memcpy (bytecode_p, base_addr_p + offset, start_offset); - bytecode_p->size = (uint16_t) (total_size >> JMEM_ALIGNMENT_LOG); + bytecode_p->size = (uint16_t) (new_code_size >> JMEM_ALIGNMENT_LOG); - uint8_t *instructions_p = ((uint8_t *) bytecode_p); + uint8_t *byte_p = (uint8_t *) bytecode_p; - instructions_p[code_size] = CBC_SET_BYTECODE_PTR; - memcpy (instructions_p + code_size + 1, &real_bytecode_p, sizeof (uint8_t *)); + if (argument_end != 0) + { + uint32_t argument_size = (uint32_t) (argument_end * sizeof (ecma_value_t)); + memcpy (byte_p + new_code_size - argument_size, + base_addr_p + offset + code_size - argument_size, + argument_size); + } + + byte_p[start_offset] = CBC_SET_BYTECODE_PTR; + memcpy (byte_p + start_offset + 1, &real_bytecode_p, sizeof (uint8_t *)); + + code_size = new_code_size; } JERRY_ASSERT (bytecode_p->refs == 1); @@ -457,13 +479,14 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th bytecode_p->status_flags = (uint16_t) (bytecode_p->status_flags | CBC_CODE_FLAGS_DEBUGGER_IGNORE); #endif /* JERRY_DEBUGGER */ - jmem_cpointer_t *literal_start_p = (jmem_cpointer_t *) (((uint8_t *) bytecode_p) + header_size); + ecma_value_t *literal_start_p = (ecma_value_t *) (((uint8_t *) bytecode_p) + header_size); for (uint32_t i = 0; i < const_literal_end; i++) { - literal_start_p[i] = ecma_snapshot_get_literal (literal_base_p, - number_base_p, - literal_start_p[i]); + if ((literal_start_p[i] & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_SNAPSHOT_OFFSET) + { + literal_start_p[i] = ecma_snapshot_get_literal (literal_base_p, literal_start_p[i]); + } } for (uint32_t i = const_literal_end; i < literal_end; i++) @@ -473,8 +496,8 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th if (literal_offset == offset) { /* Self reference */ - ECMA_SET_NON_NULL_POINTER (literal_start_p[i], - bytecode_p); + ECMA_SET_INTERNAL_VALUE_POINTER (literal_start_p[i], + bytecode_p); } else { @@ -482,11 +505,24 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th literal_bytecode_p = snapshot_load_compiled_code (base_addr_p, literal_offset, literal_base_p, - number_base_p, copy_bytecode); - ECMA_SET_NON_NULL_POINTER (literal_start_p[i], - literal_bytecode_p); + ECMA_SET_INTERNAL_VALUE_POINTER (literal_start_p[i], + literal_bytecode_p); + } + } + + if (argument_end != 0) + { + literal_start_p = (ecma_value_t *) (((uint8_t *) bytecode_p) + code_size); + literal_start_p -= argument_end; + + for (uint32_t i = 0; i < argument_end; i++) + { + if ((literal_start_p[i] & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_SNAPSHOT_OFFSET) + { + literal_start_p[i] = ecma_snapshot_get_literal (literal_base_p, literal_start_p[i]); + } } } @@ -561,7 +597,12 @@ jerry_parse_and_save_snapshot_with_args (const jerry_char_t *source_p, /**< scri lit_mem_to_snapshot_id_map_entry_t *lit_map_p = NULL; uint32_t literals_num; - if (!ecma_save_literals_for_snapshot (buffer_p, + ecma_collection_header_t *lit_pool_p = ecma_new_values_collection (); + + ecma_save_literals_add_compiled_code (bytecode_data_p, lit_pool_p); + + if (!ecma_save_literals_for_snapshot (lit_pool_p, + buffer_p, buffer_size, &globals.snapshot_buffer_write_offset, &lit_map_p, @@ -672,34 +713,31 @@ jerry_snapshot_result_at (const uint32_t *snapshot_p, /**< snapshot */ || header_p->version != JERRY_SNAPSHOT_VERSION || !snapshot_check_global_flags (header_p->global_flags)) { - return ecma_raise_type_error (invalid_version_error_p); + ecma_raise_type_error (invalid_version_error_p); + return ecma_create_error_reference_from_context (); } - if (header_p->lit_table_offset >= snapshot_size) + if (header_p->lit_table_offset > snapshot_size) { - return ecma_raise_type_error (invalid_version_error_p); + ecma_raise_type_error (invalid_version_error_p); + return ecma_create_error_reference_from_context (); } if (func_index >= header_p->number_of_funcs) { - return ecma_raise_range_error (ECMA_ERR_MSG ("Function index is higher than maximum")); + ecma_raise_range_error (ECMA_ERR_MSG ("Function index is higher than maximum")); + return ecma_create_error_reference_from_context (); } JERRY_ASSERT ((header_p->lit_table_offset % sizeof (uint32_t)) == 0); - const uint8_t *literal_base_p; - const uint8_t *number_base_p; - - literal_base_p = ecma_snapshot_get_literals_base ((uint32_t *) (snapshot_data_p + header_p->lit_table_offset), - &number_base_p); - + const uint8_t *literal_base_p = (uint8_t *) (snapshot_data_p + header_p->lit_table_offset); ecma_compiled_code_t *bytecode_p; uint32_t func_offset = header_p->func_offsets[func_index] & ~JERRY_SNAPSHOT_EVAL_CONTEXT; bytecode_p = snapshot_load_compiled_code (snapshot_data_p + func_offset, 0, literal_base_p, - number_base_p, copy_bytecode); if (bytecode_p == NULL) @@ -813,8 +851,8 @@ jerry_exec_snapshot (const uint32_t *snapshot_p, /**< snapshot */ static void scan_snapshot_functions (const uint8_t *buffer_p, /**< snapshot buffer start */ const uint8_t *buffer_end_p, /**< snapshot buffer end */ - const uint8_t *literal_base_p, /**< start of literal data */ - const uint8_t *number_base_p) /**< start of number data */ + ecma_collection_header_t *lit_pool_p, /**< list of known values */ + const uint8_t *literal_base_p) /**< start of literal data */ { JERRY_ASSERT (buffer_end_p > buffer_p); @@ -825,29 +863,51 @@ scan_snapshot_functions (const uint8_t *buffer_p, /**< snapshot buffer start */ if (bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION) { - jmem_cpointer_t *literal_start_p; + ecma_value_t *literal_start_p; + uint32_t argument_end; uint32_t const_literal_end; if (bytecode_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) { - literal_start_p = (jmem_cpointer_t *) (buffer_p + sizeof (cbc_uint16_arguments_t)); + literal_start_p = (ecma_value_t *) (buffer_p + sizeof (cbc_uint16_arguments_t)); cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) buffer_p; - const_literal_end = args_p->const_literal_end; + argument_end = args_p->argument_end; + const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); } else { - literal_start_p = (jmem_cpointer_t *) (buffer_p + sizeof (cbc_uint8_arguments_t)); + literal_start_p = (ecma_value_t *) (buffer_p + sizeof (cbc_uint8_arguments_t)); cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) buffer_p; - const_literal_end = args_p->const_literal_end; + argument_end = args_p->argument_end; + const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); } for (uint32_t i = 0; i < const_literal_end; i++) { - if (literal_start_p[i] != JMEM_CP_NULL) + if ((literal_start_p[i] & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_SNAPSHOT_OFFSET) { - literal_start_p[i] = ecma_snapshot_get_literal (literal_base_p, number_base_p, literal_start_p[i]); + ecma_value_t lit_value = ecma_snapshot_get_literal (literal_base_p, literal_start_p[i]); + literal_start_p[i] = lit_value; + ecma_save_literals_append_value (lit_value, lit_pool_p); + } + } + + if (bytecode_p->status_flags & CBC_CODE_FLAGS_NON_STRICT_ARGUMENTS_NEEDED) + { + uint8_t *byte_p = (uint8_t *) bytecode_p; + byte_p += ((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG; + literal_start_p = ((ecma_value_t *) byte_p) - argument_end; + + for (uint32_t i = 0; i < argument_end; i++) + { + if ((literal_start_p[i] & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_SNAPSHOT_OFFSET) + { + ecma_value_t lit_value = ecma_snapshot_get_literal (literal_base_p, literal_start_p[i]); + literal_start_p[i] = lit_value; + ecma_save_literals_append_value (lit_value, lit_pool_p); + } } } } @@ -862,7 +922,7 @@ scan_snapshot_functions (const uint8_t *buffer_p, /**< snapshot buffer start */ */ static void update_literal_offsets (uint8_t *buffer_p, /**< snapshot buffer start */ - const uint8_t *buffer_end_p, /**< snapshot buffer start */ + const uint8_t *buffer_end_p, /**< snapshot buffer end */ lit_mem_to_snapshot_id_map_entry_t *lit_map_p) /**< literal map */ { JERRY_ASSERT (buffer_end_p > buffer_p); @@ -874,27 +934,31 @@ update_literal_offsets (uint8_t *buffer_p, /**< snapshot buffer start */ if (bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION) { - jmem_cpointer_t *literal_start_p; + ecma_value_t *literal_start_p; + uint32_t argument_end; uint32_t const_literal_end; if (bytecode_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) { - literal_start_p = (jmem_cpointer_t *) (buffer_p + sizeof (cbc_uint16_arguments_t)); + literal_start_p = (ecma_value_t *) (buffer_p + sizeof (cbc_uint16_arguments_t)); cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) buffer_p; - const_literal_end = args_p->const_literal_end; + argument_end = args_p->argument_end; + const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); } else { - literal_start_p = (jmem_cpointer_t *) (buffer_p + sizeof (cbc_uint8_arguments_t)); + literal_start_p = (ecma_value_t *) (buffer_p + sizeof (cbc_uint8_arguments_t)); cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) buffer_p; - const_literal_end = args_p->const_literal_end; + argument_end = args_p->argument_end; + const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); } for (uint32_t i = 0; i < const_literal_end; i++) { - if (literal_start_p[i] != JMEM_CP_NULL) + if (ecma_is_value_string (literal_start_p[i]) + || ecma_is_value_float_number (literal_start_p[i])) { lit_mem_to_snapshot_id_map_entry_t *current_p = lit_map_p; @@ -906,6 +970,28 @@ update_literal_offsets (uint8_t *buffer_p, /**< snapshot buffer start */ literal_start_p[i] = current_p->literal_offset; } } + + if (bytecode_p->status_flags & CBC_CODE_FLAGS_NON_STRICT_ARGUMENTS_NEEDED) + { + uint8_t *byte_p = (uint8_t *) bytecode_p; + byte_p += ((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG; + literal_start_p = ((ecma_value_t *) byte_p) - argument_end; + + for (uint32_t i = 0; i < argument_end; i++) + { + if (literal_start_p[i] != ECMA_VALUE_EMPTY) + { + lit_mem_to_snapshot_id_map_entry_t *current_p = lit_map_p; + + while (current_p->literal_id != literal_start_p[i]) + { + current_p++; + } + + literal_start_p[i] = current_p->literal_offset; + } + } + } } buffer_p += code_size; @@ -940,11 +1026,14 @@ jerry_merge_snapshots (const uint32_t **inp_buffers_p, /**< array of (pointers t return 0; } + ecma_collection_header_t *lit_pool_p = ecma_new_values_collection (); + for (uint32_t i = 0; i < number_of_snapshots; i++) { if (inp_buffer_sizes_p[i] < sizeof (jerry_snapshot_header_t)) { *error_p = "invalid snapshot file"; + ecma_free_values_collection (lit_pool_p, ECMA_COLLECTION_NO_COPY); return 0; } @@ -955,6 +1044,7 @@ jerry_merge_snapshots (const uint32_t **inp_buffers_p, /**< array of (pointers t || !snapshot_check_global_flags (header_p->global_flags)) { *error_p = "invalid snapshot version or unsupported features present"; + ecma_free_values_collection (lit_pool_p, ECMA_COLLECTION_NO_COPY); return 0; } @@ -962,11 +1052,7 @@ jerry_merge_snapshots (const uint32_t **inp_buffers_p, /**< array of (pointers t uint32_t start_offset = header_p->func_offsets[0] & ~JERRY_SNAPSHOT_EVAL_CONTEXT; const uint8_t *data_p = (const uint8_t *) inp_buffers_p[i]; - const uint8_t *literal_base_p; - const uint8_t *number_base_p; - - literal_base_p = ecma_snapshot_get_literals_base ((uint32_t *) (data_p + header_p->lit_table_offset), - &number_base_p); + const uint8_t *literal_base_p = (uint8_t *) (data_p + header_p->lit_table_offset); JERRY_ASSERT (header_p->number_of_funcs > 0); @@ -975,8 +1061,8 @@ jerry_merge_snapshots (const uint32_t **inp_buffers_p, /**< array of (pointers t scan_snapshot_functions (data_p + start_offset, data_p + header_p->lit_table_offset, - literal_base_p, - number_base_p); + lit_pool_p, + literal_base_p); } JERRY_ASSERT (number_of_funcs > 0); @@ -986,6 +1072,7 @@ jerry_merge_snapshots (const uint32_t **inp_buffers_p, /**< array of (pointers t if (functions_size >= out_buffer_size) { *error_p = "output buffer is too small"; + ecma_free_values_collection (lit_pool_p, ECMA_COLLECTION_NO_COPY); return 0; } @@ -1000,7 +1087,8 @@ jerry_merge_snapshots (const uint32_t **inp_buffers_p, /**< array of (pointers t lit_mem_to_snapshot_id_map_entry_t *lit_map_p; uint32_t literals_num; - if (!ecma_save_literals_for_snapshot (out_buffer_p, + if (!ecma_save_literals_for_snapshot (lit_pool_p, + out_buffer_p, out_buffer_size, &functions_size, &lit_map_p, @@ -1041,7 +1129,10 @@ jerry_merge_snapshots (const uint32_t **inp_buffers_p, /**< array of (pointers t JERRY_ASSERT ((uint32_t) (dst_p - (uint8_t *) out_buffer_p) == header_p->lit_table_offset); - jmem_heap_free_block (lit_map_p, literals_num * sizeof (lit_mem_to_snapshot_id_map_entry_t)); + if (lit_map_p != NULL) + { + jmem_heap_free_block (lit_map_p, literals_num * sizeof (lit_mem_to_snapshot_id_map_entry_t)); + } *error_p = NULL; return functions_size; @@ -1325,35 +1416,35 @@ jerry_parse_and_save_literals (const jerry_char_t *source_p, /**< script source ecma_free_value (parse_status); + ecma_collection_header_t *lit_pool_p = ecma_new_values_collection (); + ecma_save_literals_add_compiled_code (bytecode_data_p, lit_pool_p); + ecma_bytecode_deref (bytecode_data_p); - ecma_lit_storage_item_t *string_list_p = JERRY_CONTEXT (string_list_first_p); lit_utf8_size_t literal_count = 0; + ecma_value_t *iterator_p = ecma_collection_iterator_init (lit_pool_p); /* Count the valid and non-magic identifiers in the list. */ - while (string_list_p != NULL) + while (iterator_p != NULL) { - for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + if (ecma_is_value_string (*iterator_p)) { - if (string_list_p->values[i] != JMEM_CP_NULL) + ecma_string_t *literal_p = ecma_get_string_from_value (*iterator_p); + + /* We don't save a literal which isn't a valid identifier or it's a magic string. */ + if (ecma_get_string_magic (literal_p) == LIT_MAGIC_STRING__COUNT + && ecma_string_is_valid_identifier (literal_p)) { - ecma_string_t *literal_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, - string_list_p->values[i]); - /* We don't save a literal which isn't a valid identifier - or it's a magic string. */ - if (ecma_get_string_magic (literal_p) == LIT_MAGIC_STRING__COUNT - && ecma_string_is_valid_identifier (literal_p)) - { - literal_count++; - } + literal_count++; } } - string_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, string_list_p->next_cp); + iterator_p = ecma_collection_iterator_next (iterator_p); } if (literal_count == 0) { + ecma_free_values_collection (lit_pool_p, ECMA_COLLECTION_NO_COPY); return 0; } @@ -1365,28 +1456,26 @@ jerry_parse_and_save_literals (const jerry_char_t *source_p, /**< script source JMEM_DEFINE_LOCAL_ARRAY (literal_array, literal_count, ecma_string_t *); lit_utf8_size_t literal_idx = 0; - string_list_p = JERRY_CONTEXT (string_list_first_p); + iterator_p = ecma_collection_iterator_init (lit_pool_p); - while (string_list_p != NULL) + while (iterator_p != NULL) { - for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + if (ecma_is_value_string (*iterator_p)) { - if (string_list_p->values[i] != JMEM_CP_NULL) - { - ecma_string_t *literal_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, - string_list_p->values[i]); + ecma_string_t *literal_p = ecma_get_string_from_value (*iterator_p); - if (ecma_get_string_magic (literal_p) == LIT_MAGIC_STRING__COUNT - && ecma_string_is_valid_identifier (literal_p)) - { - literal_array[literal_idx++] = literal_p; - } + if (ecma_get_string_magic (literal_p) == LIT_MAGIC_STRING__COUNT + && ecma_string_is_valid_identifier (literal_p)) + { + literal_array[literal_idx++] = literal_p; } } - string_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, string_list_p->next_cp); + iterator_p = ecma_collection_iterator_next (iterator_p); } + ecma_free_values_collection (lit_pool_p, ECMA_COLLECTION_NO_COPY); + /* Sort the strings by size at first, then lexicographically. */ jerry_save_literals_sort (literal_array, literal_count); diff --git a/jerry-core/api/jerry-snapshot.h b/jerry-core/api/jerry-snapshot.h index 8a91a43a9..76038dda9 100644 --- a/jerry-core/api/jerry-snapshot.h +++ b/jerry-core/api/jerry-snapshot.h @@ -46,7 +46,7 @@ typedef struct /** * Jerry snapshot format version. */ -#define JERRY_SNAPSHOT_VERSION (8u) +#define JERRY_SNAPSHOT_VERSION (9u) /** * Snapshot configuration flags. diff --git a/jerry-core/api/jerry.c b/jerry-core/api/jerry.c index cb5790d91..137061f8f 100644 --- a/jerry-core/api/jerry.c +++ b/jerry-core/api/jerry.c @@ -1846,11 +1846,12 @@ jerry_delete_property_by_index (const jerry_value_t obj_val, /**< object value * return false; } - ecma_string_t str_idx; - ecma_init_ecma_string_from_uint32 (&str_idx, index); + ecma_string_t *str_idx_p = ecma_new_ecma_string_from_uint32 (index); ecma_value_t ret_value = ecma_op_object_delete (ecma_get_object_from_value (obj_value), - &str_idx, + str_idx_p, false); + ecma_deref_ecma_string (str_idx_p); + return ecma_is_value_true (ret_value); } /* jerry_delete_property_by_index */ @@ -1905,9 +1906,9 @@ jerry_get_property_by_index (const jerry_value_t obj_val, /**< object value */ return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } - ecma_string_t str_idx; - ecma_init_ecma_string_from_uint32 (&str_idx, index); - ecma_value_t ret_value = ecma_op_object_get (ecma_get_object_from_value (obj_value), &str_idx); + ecma_string_t *str_idx_p = ecma_new_ecma_string_from_uint32 (index); + ecma_value_t ret_value = ecma_op_object_get (ecma_get_object_from_value (obj_value), str_idx_p); + ecma_deref_ecma_string (str_idx_p); return jerry_return (ret_value); } /* jerry_get_property_by_index */ diff --git a/jerry-core/debugger/debugger.c b/jerry-core/debugger/debugger.c index f58957411..eabd614a9 100644 --- a/jerry-core/debugger/debugger.c +++ b/jerry-core/debugger/debugger.c @@ -978,12 +978,11 @@ jerry_debugger_exception_object_to_string (ecma_value_t exception_obj_value) /** lit_utf8_byte_t data[16]; memcpy (data, lit_get_magic_string_utf8 (string_id), size); - ecma_string_t message_string; - ecma_init_ecma_magic_string (&message_string, LIT_MAGIC_STRING_MESSAGE); + ecma_string_t *message_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE); ecma_property_t *property_p; property_p = ecma_find_named_property (ecma_get_object_from_value (exception_obj_value), - &message_string); + message_string_p); if (property_p == NULL || ECMA_PROPERTY_GET_TYPE (*property_p) != ECMA_PROPERTY_TYPE_NAMEDDATA) diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index 6f328bd25..fb6f6be40 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -157,7 +157,7 @@ ecma_gc_mark_property (ecma_property_pair_t *property_pair_p, /**< property pair { case ECMA_PROPERTY_TYPE_NAMEDDATA: { - if (ECMA_PROPERTY_GET_NAME_TYPE (property) == ECMA_STRING_CONTAINER_MAGIC_STRING + if (ECMA_PROPERTY_GET_NAME_TYPE (property) == ECMA_DIRECT_STRING_MAGIC && property_pair_p->names_cp[index] >= LIT_NEED_MARK_MAGIC_STRING__COUNT) { break; @@ -478,7 +478,7 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */ jmem_cpointer_t name_cp = prop_pair_p->names_cp[i]; /* Call the native's free callback. */ - if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_STRING_CONTAINER_MAGIC_STRING + if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC && (name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE || name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER)) { @@ -666,18 +666,18 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */ case ECMA_PSEUDO_ARRAY_ARGUMENTS: { ecma_length_t formal_params_number = ext_object_p->u.pseudo_array.u1.length; - jmem_cpointer_t *arg_Literal_p = (jmem_cpointer_t *) (ext_object_p + 1); + ecma_value_t *arg_Literal_p = (ecma_value_t *) (ext_object_p + 1); for (ecma_length_t i = 0; i < formal_params_number; i++) { - if (arg_Literal_p[i] != JMEM_CP_NULL) + if (arg_Literal_p[i] != ECMA_VALUE_EMPTY) { - ecma_string_t *name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, arg_Literal_p[i]); + ecma_string_t *name_p = ecma_get_string_from_value (arg_Literal_p[i]); ecma_deref_ecma_string (name_p); } } - size_t formal_params_size = formal_params_number * sizeof (jmem_cpointer_t); + size_t formal_params_size = formal_params_number * sizeof (ecma_value_t); ecma_dealloc_extended_object (object_p, sizeof (ecma_extended_object_t) + formal_params_size); return; } diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index cff16160a..5ae7a0532 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -83,18 +83,20 @@ typedef enum typedef enum { ECMA_TYPE_DIRECT = 0, /**< directly encoded value, a 28 bit signed integer or a simple value */ - ECMA_TYPE_FLOAT = 1, /**< pointer to a 64 or 32 bit floating point number */ - ECMA_TYPE_STRING = 2, /**< pointer to description of a string */ + ECMA_TYPE_STRING = 1, /**< pointer to description of a string */ + ECMA_TYPE_FLOAT = 2, /**< pointer to a 64 or 32 bit floating point number */ ECMA_TYPE_OBJECT = 3, /**< pointer to description of an object */ + ECMA_TYPE_DIRECT_STRING = 5, /**< directly encoded string values */ ECMA_TYPE_ERROR = 7, /**< pointer to description of an error reference */ ECMA_TYPE_COLLECTION_CHUNK = ECMA_TYPE_ERROR, /**< pointer to description of a collection chunk */ + ECMA_TYPE_SNAPSHOT_OFFSET = ECMA_TYPE_ERROR, /**< offset to a snapshot number/string */ ECMA_TYPE___MAX = ECMA_TYPE_ERROR /** highest value for ecma types */ } ecma_type_t; /** * Description of an ecma value * - * Bit-field structure: type (2) | error (1) | value (29) + * Bit-field structure: type (3) | value (29) */ typedef uint32_t ecma_value_t; @@ -113,12 +115,12 @@ typedef int32_t ecma_integer_value_t; #endif /* UINTPTR_MAX <= UINT32_MAX */ /** - * Mask for ecma types in ecma_type_t + * Mask for ecma types in ecma_value_t */ #define ECMA_VALUE_TYPE_MASK 0x7u /** - * Shift for value part in ecma_type_t + * Shift for value part in ecma_value_t */ #define ECMA_VALUE_SHIFT 3 @@ -420,11 +422,6 @@ typedef enum */ #define ECMA_PROPERTY_NAME_TYPE_SHIFT (ECMA_PROPERTY_FLAG_SHIFT + 4) -/** - * Property name is a generic string. - */ -#define ECMA_PROPERTY_NAME_TYPE_STRING 3 - /** * Abstract property representation. * @@ -1058,6 +1055,7 @@ typedef double ecma_number_t; typedef enum { ECMA_COLLECTION_NO_REF_OBJECTS = (1u << 0), /**< do not increase the refcount of objects */ + ECMA_COLLECTION_NO_COPY = (1u << 1), /**< do not copy values */ } ecma_collection_flag_t; /** @@ -1085,19 +1083,90 @@ typedef struct * so the chunk area is enlarged by one for this value */ } ecma_collection_chunk_t; +/** + * Direct string types (2 bit). + */ +typedef enum +{ + ECMA_DIRECT_STRING_PTR = 0, /**< string is a string pointer, only used by property names */ + ECMA_DIRECT_STRING_MAGIC = 1, /**< string is a magic string */ + ECMA_DIRECT_STRING_UINT = 2, /**< string is an unsigned int */ + ECMA_DIRECT_STRING_MAGIC_EX = 3, /**< string is an extended magic string */ +} ecma_direct_string_type_t; + +/** + * Maximum value of the immediate part of a direct magic string. + * Must be compatible with the immediate property name. + */ +#ifdef JERRY_CPOINTER_32_BIT +#define ECMA_DIRECT_STRING_MAX_IMM 0x07ffffff +#else /* !JERRY_CPOINTER_32_BIT */ +#define ECMA_DIRECT_STRING_MAX_IMM 0x0000ffff +#endif /* JERRY_CPOINTER_32_BIT */ + +/** + * Shift for direct string value part in ecma_value_t. + */ +#define ECMA_DIRECT_STRING_SHIFT (ECMA_VALUE_SHIFT + 2) + +/** + * Full mask for direct strings. + */ +#define ECMA_DIRECT_STRING_MASK ((uintptr_t) (ECMA_DIRECT_TYPE_MASK | (0x3u << ECMA_VALUE_SHIFT))) + +/** + * Create an ecma direct string. + */ +#define ECMA_CREATE_DIRECT_STRING(type, value) \ + ((uintptr_t) (ECMA_TYPE_DIRECT_STRING | ((type) << ECMA_VALUE_SHIFT) | (value) << ECMA_DIRECT_STRING_SHIFT)) + +/** + * Checks whether the string is direct. + */ +#define ECMA_IS_DIRECT_STRING(string_p) \ + ((((uintptr_t) (string_p)) & 0x1) != 0) + +/** + * Checks whether the string is direct. + */ +#define ECMA_IS_DIRECT_STRING_WITH_TYPE(string_p, type) \ + ((((uintptr_t) (string_p)) & ECMA_DIRECT_STRING_MASK) == ECMA_CREATE_DIRECT_STRING (type, 0)) + +/** + * Returns the type of a direct string. + */ +#define ECMA_GET_DIRECT_STRING_TYPE(string_p) \ + ((((uintptr_t) (string_p)) >> ECMA_VALUE_SHIFT) & 0x3) + +/** + * Shift applied to type conversions. + */ +#define ECMA_STRING_TYPE_CONVERSION_SHIFT (ECMA_PROPERTY_NAME_TYPE_SHIFT - ECMA_VALUE_SHIFT) + +/** + * Converts direct string type to property name type. + */ +#define ECMA_DIRECT_STRING_TYPE_TO_PROP_NAME_TYPE(string_p) \ + ((((uintptr_t) (string_p)) & (0x3 << ECMA_VALUE_SHIFT)) << ECMA_STRING_TYPE_CONVERSION_SHIFT) + +/** + * Returns the value of a direct string. + */ +#define ECMA_GET_DIRECT_STRING_VALUE(string_p) \ + (((uintptr_t) (string_p)) >> ECMA_DIRECT_STRING_SHIFT) + /** * Identifier for ecma-string's actual data container */ typedef enum { - ECMA_STRING_CONTAINER_UINT32_IN_DESC, /**< actual data is UInt32-represeneted Number - stored locally in the string's descriptor */ - ECMA_STRING_CONTAINER_MAGIC_STRING, /**< the ecma-string is equal to one of ECMA magic strings */ - ECMA_STRING_CONTAINER_MAGIC_STRING_EX, /**< the ecma-string is equal to one of external magic strings */ ECMA_STRING_CONTAINER_HEAP_UTF8_STRING, /**< actual data is on the heap as an utf-8 (cesu8) string * maximum size is 2^16. */ ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING, /**< actual data is on the heap as an utf-8 (cesu8) string * maximum size is 2^32. */ + ECMA_STRING_CONTAINER_UINT32_IN_DESC, /**< actual data is UInt32-represeneted Number + stored locally in the string's descriptor */ + ECMA_STRING_CONTAINER_MAGIC_STRING_EX, /**< the ecma-string is equal to one of external magic strings */ ECMA_STRING_LITERAL_NUMBER, /**< a literal number which is used solely by the literal storage * so no string processing function supports this type except @@ -1166,9 +1235,8 @@ typedef struct lit_utf8_size_t long_utf8_string_size; /**< size of this long utf-8 string in bytes */ uint32_t uint32_number; /**< uint32-represented number placed locally in the descriptor */ - uint32_t magic_string_id; /**< identifier of a magic string (lit_magic_string_id_t) */ uint32_t magic_string_ex_id; /**< identifier of an external magic string (lit_magic_string_ex_id_t) */ - ecma_value_t lit_number; /**< literal number (note: not a regular string type) */ + ecma_value_t lit_number; /**< number (see ECMA_STRING_LITERAL_NUMBER) */ uint32_t common_uint32_field; /**< for zeroing and comparison in some cases */ } u; } ecma_string_t; diff --git a/jerry-core/ecma/base/ecma-helpers-external-pointers.c b/jerry-core/ecma/base/ecma-helpers-external-pointers.c index 6a5ad2b56..a09a26116 100644 --- a/jerry-core/ecma/base/ecma-helpers-external-pointers.c +++ b/jerry-core/ecma/base/ecma-helpers-external-pointers.c @@ -45,10 +45,9 @@ ecma_create_native_property (ecma_object_t *obj_p, /**< object to create propert JERRY_ASSERT (id == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE || id == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER); - ecma_string_t name; - ecma_init_ecma_magic_string (&name, id); + ecma_string_t *name_p = ecma_get_magic_string (id); + ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p); - ecma_property_t *property_p = ecma_find_named_property (obj_p, &name); bool is_new = (property_p == NULL); ecma_native_pointer_t *native_pointer_p; @@ -56,7 +55,7 @@ ecma_create_native_property (ecma_object_t *obj_p, /**< object to create propert if (is_new) { ecma_property_value_t *value_p; - value_p = ecma_create_named_data_property (obj_p, &name, ECMA_PROPERTY_FLAG_WRITABLE, NULL); + value_p = ecma_create_named_data_property (obj_p, name_p, ECMA_PROPERTY_FLAG_WRITABLE, NULL); native_pointer_p = jmem_heap_alloc_block (sizeof (ecma_native_pointer_t)); @@ -69,8 +68,6 @@ ecma_create_native_property (ecma_object_t *obj_p, /**< object to create propert native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value_p->value); } - JERRY_ASSERT (ECMA_STRING_IS_REF_EQUALS_TO_ONE (&name)); - native_pointer_p->data_p = data_p; native_pointer_p->u.info_p = info_p; @@ -130,12 +127,8 @@ ecma_get_native_pointer_value (ecma_object_t *obj_p, /**< object to get property JERRY_ASSERT (id == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE || id == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER); - ecma_string_t name; - ecma_init_ecma_magic_string (&name, id); - - ecma_property_t *property_p = ecma_find_named_property (obj_p, &name); - - JERRY_ASSERT (ECMA_STRING_IS_REF_EQUALS_TO_ONE (&name)); + ecma_string_t *name_p = ecma_get_magic_string (id); + ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p); if (property_p == NULL) { diff --git a/jerry-core/ecma/base/ecma-helpers-string.c b/jerry-core/ecma/base/ecma-helpers-string.c index b6b6c893a..77f499b4d 100644 --- a/jerry-core/ecma/base/ecma-helpers-string.c +++ b/jerry-core/ecma/base/ecma-helpers-string.c @@ -42,41 +42,27 @@ JERRY_STATIC_ASSERT ((ECMA_STRING_MAX_REF | ECMA_STRING_CONTAINER_MASK) == UINT1 JERRY_STATIC_ASSERT (ECMA_STRING_NOT_ARRAY_INDEX == UINT32_MAX, ecma_string_not_array_index_must_be_equal_to_uint32_max); -static void -ecma_init_ecma_string_from_magic_string_id (ecma_string_t *string_p, - lit_magic_string_id_t magic_string_id); +JERRY_STATIC_ASSERT ((ECMA_TYPE_DIRECT_STRING & 0x1) != 0, + ecma_type_direct_string_must_be_odd_number); -static void -ecma_init_ecma_string_from_magic_string_ex_id (ecma_string_t *string_p, - lit_magic_string_ex_id_t magic_string_ex_id); +JERRY_STATIC_ASSERT (LIT_MAGIC_STRING__COUNT <= ECMA_DIRECT_STRING_MAX_IMM, + all_magic_strings_must_be_encoded_as_direct_string); + +JERRY_STATIC_ASSERT ((int) ECMA_DIRECT_STRING_UINT == (int) ECMA_STRING_CONTAINER_UINT32_IN_DESC + && (int) ECMA_DIRECT_STRING_MAGIC_EX == (int) ECMA_STRING_CONTAINER_MAGIC_STRING_EX, + ecma_direct_and_container_types_must_match); + +JERRY_STATIC_ASSERT (ECMA_PROPERTY_NAME_TYPE_SHIFT > ECMA_VALUE_SHIFT, + ecma_property_name_type_shift_must_be_greater_than_ecma_value_shift); /** - * Initialize ecma-string descriptor with specified magic string + * Checks whether the string is direct */ -static void -ecma_init_ecma_string_from_magic_string_id (ecma_string_t *string_p, /**< descriptor to initialize */ - lit_magic_string_id_t magic_string_id) /**< identifier of - the magic string */ +static inline bool __attr_always_inline___ +ecma_is_string_direct (ecma_string_t *string_p) { - string_p->refs_and_container = ECMA_STRING_CONTAINER_MAGIC_STRING | ECMA_STRING_REF_ONE; - string_p->hash = (lit_string_hash_t) magic_string_id; - - 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 */ - lit_magic_string_ex_id_t magic_string_ex_id) /**< identifier of - the external magic string */ -{ - string_p->refs_and_container = ECMA_STRING_CONTAINER_MAGIC_STRING_EX | ECMA_STRING_REF_ONE; - string_p->hash = (lit_string_hash_t) (LIT_MAGIC_STRING__COUNT + magic_string_ex_id); - - string_p->u.magic_string_ex_id = magic_string_ex_id; -} /* ecma_init_ecma_string_from_magic_string_ex_id */ + return (((uintptr_t) string_p) & 0x1) != 0; +} /* ecma_is_string_direct */ /** * Convert a string to an unsigned 32 bit value if possible @@ -141,6 +127,62 @@ ecma_string_to_array_index (const lit_utf8_byte_t *string_p, /**< utf-8 string * return true; } /* ecma_string_to_array_index */ +/** + * Returns the characters and size of a string. + * + * Note: + * UINT type is not supported + * + * @return byte array start - if the byte array of a string is available + * NULL - otherwise + */ +static const lit_utf8_byte_t * +ecma_string_get_chars_fast (const ecma_string_t *string_p, /**< ecma-string */ + lit_utf8_size_t *size_p) /**< [out] size of the ecma string */ +{ + if (ECMA_IS_DIRECT_STRING (string_p)) + { + if (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_MAGIC) + { + lit_magic_string_id_t id = (lit_magic_string_id_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + + *size_p = lit_get_magic_string_size (id); + return lit_get_magic_string_utf8 (id); + } + + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_MAGIC_EX); + + lit_magic_string_ex_id_t id = (lit_magic_string_ex_id_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + + *size_p = lit_get_magic_string_ex_size (id); + return lit_get_magic_string_ex_utf8 (id); + } + + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); + + switch (ECMA_STRING_GET_CONTAINER (string_p)) + { + case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + { + *size_p = string_p->u.utf8_string.size; + return (const lit_utf8_byte_t *) (string_p + 1); + } + case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: + { + *size_p = string_p->u.long_utf8_string_size; + ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; + return (const lit_utf8_byte_t *) (long_string_p + 1); + } + default: + { + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + *size_p = lit_get_magic_string_ex_size (string_p->u.magic_string_ex_id); + return lit_get_magic_string_ex_utf8 (string_p->u.magic_string_ex_id); + } + } +} /* ecma_string_get_chars_fast */ + /** * Allocate new ecma-string and fill it with characters from the utf8 string * @@ -345,32 +387,6 @@ ecma_new_ecma_string_from_code_unit (ecma_char_t code_unit) /**< code unit */ return ecma_new_ecma_string_from_utf8 (lit_utf8_bytes, bytes_size); } /* ecma_new_ecma_string_from_code_unit */ -/** - * Initialize an ecma-string with an ecma-number - */ -inline void __attr_always_inline___ -ecma_init_ecma_string_from_uint32 (ecma_string_t *string_desc_p, /**< ecma-string */ - uint32_t uint32_number) /**< uint32 value of the string */ -{ - string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_UINT32_IN_DESC | ECMA_STRING_REF_ONE; - string_desc_p->hash = (lit_string_hash_t) uint32_number; - - string_desc_p->u.uint32_number = uint32_number; -} /* ecma_init_ecma_string_from_uint32 */ - -/** - * Initialize a magic ecma-string - */ -void -ecma_init_ecma_magic_string (ecma_string_t *string_desc_p, /**< ecma-string */ - lit_magic_string_id_t id) /**< literal id */ -{ - string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_MAGIC_STRING | ECMA_STRING_REF_ONE; - string_desc_p->hash = (lit_string_hash_t) id; - - string_desc_p->u.magic_string_id = (uint32_t) id; -} /* ecma_init_ecma_magic_string */ - /** * Allocate new ecma-string and fill it with ecma-number * @@ -379,10 +395,18 @@ ecma_init_ecma_magic_string (ecma_string_t *string_desc_p, /**< ecma-string */ ecma_string_t * ecma_new_ecma_string_from_uint32 (uint32_t uint32_number) /**< uint32 value of the string */ { - ecma_string_t *string_desc_p = ecma_alloc_string (); + if (likely (uint32_number <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return (ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_UINT, (uintptr_t) uint32_number); + } - ecma_init_ecma_string_from_uint32 (string_desc_p, uint32_number); - return string_desc_p; + ecma_string_t *string_p = ecma_alloc_string (); + + string_p->refs_and_container = ECMA_STRING_CONTAINER_UINT32_IN_DESC | ECMA_STRING_REF_ONE; + string_p->hash = (lit_string_hash_t) uint32_number; + string_p->u.uint32_number = uint32_number; + + return string_p; } /* ecma_new_ecma_string_from_uint32 */ /** @@ -438,15 +462,11 @@ ecma_new_ecma_string_from_number (ecma_number_t num) /**< ecma-number */ * * @return pointer to ecma-string descriptor */ -ecma_string_t * +inline ecma_string_t * __attr_always_inline___ ecma_new_ecma_string_from_magic_string_id (lit_magic_string_id_t id) /**< identifier of magic string */ { JERRY_ASSERT (id < LIT_MAGIC_STRING__COUNT); - - ecma_string_t *string_desc_p = ecma_alloc_string (); - ecma_init_ecma_string_from_magic_string_id (string_desc_p, id); - - return string_desc_p; + return (ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_MAGIC, (uintptr_t) id); } /* ecma_new_ecma_string_from_magic_string_id */ /** @@ -459,8 +479,16 @@ ecma_new_ecma_string_from_magic_string_ex_id (lit_magic_string_ex_id_t id) /**< { JERRY_ASSERT (id < lit_get_magic_string_ex_count ()); + if (likely (id <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return (ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_MAGIC_EX, (uintptr_t) id); + } + ecma_string_t *string_desc_p = ecma_alloc_string (); - ecma_init_ecma_string_from_magic_string_ex_id (string_desc_p, id); + + string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_MAGIC_STRING_EX | ECMA_STRING_REF_ONE; + string_desc_p->hash = (lit_string_hash_t) (LIT_MAGIC_STRING__COUNT + id); + string_desc_p->u.magic_string_ex_id = id; return string_desc_p; } /* ecma_new_ecma_string_from_magic_string_ex_id */ @@ -473,10 +501,7 @@ ecma_new_ecma_string_from_magic_string_ex_id (lit_magic_string_ex_id_t id) /**< ecma_string_t * ecma_new_ecma_length_string (void) { - ecma_string_t *string_desc_p = ecma_alloc_string (); - ecma_init_ecma_magic_string (string_desc_p, LIT_MAGIC_STRING_LENGTH); - - return string_desc_p; + return ecma_new_ecma_string_from_magic_string_id (LIT_MAGIC_STRING_LENGTH); } /* ecma_new_ecma_length_string */ /** @@ -498,7 +523,6 @@ ecma_append_chars_to_string (ecma_string_t *string1_p, /**< base ecma-string */ if (unlikely (ecma_string_is_empty (string1_p))) { - ecma_deref_ecma_string (string1_p); return ecma_new_ecma_string_from_utf8 (cesu8_string2_p, cesu8_string2_size); } @@ -511,52 +535,85 @@ ecma_append_chars_to_string (ecma_string_t *string1_p, /**< base ecma-string */ bool string1_is_uint32 = false; bool string1_rehash_needed = false; - switch (ECMA_STRING_GET_CONTAINER (string1_p)) + if (ECMA_IS_DIRECT_STRING (string1_p)) { - case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: - { - cesu8_string1_p = (lit_utf8_byte_t *) (string1_p + 1); - cesu8_string1_size = string1_p->u.utf8_string.size; - cesu8_string1_length = string1_p->u.utf8_string.length; - break; - } - case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: - { - ecma_long_string_t *long_string_desc_p = (ecma_long_string_t *) string1_p; + string1_rehash_needed = true; - cesu8_string1_p = (lit_utf8_byte_t *) (long_string_desc_p + 1); - cesu8_string1_size = string1_p->u.long_utf8_string_size; - cesu8_string1_length = long_string_desc_p->long_utf8_string_length; - break; - } - case ECMA_STRING_CONTAINER_UINT32_IN_DESC: + switch (ECMA_GET_DIRECT_STRING_TYPE (string1_p)) { - cesu8_string1_size = ecma_uint32_to_utf8_string (string1_p->u.uint32_number, - uint32_to_string_buffer, - ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); - cesu8_string1_p = uint32_to_string_buffer; - cesu8_string1_length = cesu8_string1_size; - string1_is_uint32 = true; - string1_rehash_needed = true; - break; - } - case ECMA_STRING_CONTAINER_MAGIC_STRING: - { - cesu8_string1_p = lit_get_magic_string_utf8 (string1_p->u.magic_string_id); - cesu8_string1_size = lit_get_magic_string_size (string1_p->u.magic_string_id); - cesu8_string1_length = cesu8_string1_size; - string1_rehash_needed = true; - break; - } - default: - { - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + case ECMA_DIRECT_STRING_MAGIC: + { + lit_magic_string_id_t id = (lit_magic_string_id_t) ECMA_GET_DIRECT_STRING_VALUE (string1_p); + cesu8_string1_p = lit_get_magic_string_utf8 (id); + cesu8_string1_size = lit_get_magic_string_size (id); + cesu8_string1_length = cesu8_string1_size; + break; + } + case ECMA_DIRECT_STRING_UINT: + { + cesu8_string1_size = ecma_uint32_to_utf8_string ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string1_p), + uint32_to_string_buffer, + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + cesu8_string1_p = uint32_to_string_buffer; + cesu8_string1_length = cesu8_string1_size; + string1_is_uint32 = true; + break; + } + default: + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string1_p) == ECMA_DIRECT_STRING_MAGIC_EX); - cesu8_string1_p = lit_get_magic_string_ex_utf8 (string1_p->u.magic_string_id); - cesu8_string1_size = lit_get_magic_string_ex_size (string1_p->u.magic_string_id); - cesu8_string1_length = lit_utf8_string_length (cesu8_string1_p, cesu8_string1_size); - string1_rehash_needed = true; - break; + lit_magic_string_ex_id_t id = (lit_magic_string_ex_id_t) ECMA_GET_DIRECT_STRING_VALUE (string1_p); + cesu8_string1_p = lit_get_magic_string_ex_utf8 (id); + cesu8_string1_size = lit_get_magic_string_ex_size (id); + cesu8_string1_length = lit_utf8_string_length (cesu8_string1_p, cesu8_string1_size); + break; + } + } + } + else + { + JERRY_ASSERT (string1_p->refs_and_container >= ECMA_STRING_REF_ONE); + + switch (ECMA_STRING_GET_CONTAINER (string1_p)) + { + case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + { + cesu8_string1_p = (lit_utf8_byte_t *) (string1_p + 1); + cesu8_string1_size = string1_p->u.utf8_string.size; + cesu8_string1_length = string1_p->u.utf8_string.length; + break; + } + case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: + { + ecma_long_string_t *long_string_desc_p = (ecma_long_string_t *) string1_p; + + cesu8_string1_p = (lit_utf8_byte_t *) (long_string_desc_p + 1); + cesu8_string1_size = string1_p->u.long_utf8_string_size; + cesu8_string1_length = long_string_desc_p->long_utf8_string_length; + break; + } + case ECMA_STRING_CONTAINER_UINT32_IN_DESC: + { + cesu8_string1_size = ecma_uint32_to_utf8_string (string1_p->u.uint32_number, + uint32_to_string_buffer, + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + cesu8_string1_p = uint32_to_string_buffer; + cesu8_string1_length = cesu8_string1_size; + string1_is_uint32 = true; + string1_rehash_needed = true; + break; + } + default: + { + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + cesu8_string1_p = lit_get_magic_string_ex_utf8 (string1_p->u.magic_string_ex_id); + cesu8_string1_size = lit_get_magic_string_ex_size (string1_p->u.magic_string_ex_id); + cesu8_string1_length = lit_utf8_string_length (cesu8_string1_p, cesu8_string1_size); + string1_rehash_needed = true; + break; + } } } @@ -641,12 +698,17 @@ ecma_append_chars_to_string (ecma_string_t *string1_p, /**< base ecma-string */ data_p = (lit_utf8_byte_t *) (long_string_desc_p + 1); } - lit_string_hash_t hash_start = string1_p->hash; + lit_string_hash_t hash_start; if (string1_rehash_needed) { hash_start = lit_utf8_string_calc_hash (cesu8_string1_p, cesu8_string1_size); } + else + { + JERRY_ASSERT (!ECMA_IS_DIRECT_STRING (string1_p)); + hash_start = string1_p->hash; + } string_desc_p->hash = lit_utf8_string_hash_combine (hash_start, cesu8_string2_p, cesu8_string2_size); @@ -670,12 +732,10 @@ ecma_string_t * ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */ ecma_string_t *string2_p) /**< second ecma-string */ { - JERRY_ASSERT (string1_p != NULL - && string2_p != NULL); + JERRY_ASSERT (string1_p != NULL && string2_p != NULL); if (unlikely (ecma_string_is_empty (string1_p))) { - ecma_deref_ecma_string (string1_p); ecma_ref_ecma_string (string2_p); return string2_p; } @@ -690,48 +750,79 @@ ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */ lit_utf8_byte_t uint32_to_string_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; - switch (ECMA_STRING_GET_CONTAINER (string2_p)) + if (ECMA_IS_DIRECT_STRING (string2_p)) { - case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + switch (ECMA_GET_DIRECT_STRING_TYPE (string2_p)) { - cesu8_string2_p = (lit_utf8_byte_t *) (string2_p + 1); - cesu8_string2_size = string2_p->u.utf8_string.size; - cesu8_string2_length = string2_p->u.utf8_string.length; - break; - } - case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: - { - ecma_long_string_t *long_string_desc_p = (ecma_long_string_t *) string2_p; + case ECMA_DIRECT_STRING_MAGIC: + { + lit_magic_string_id_t id = (lit_magic_string_id_t) ECMA_GET_DIRECT_STRING_VALUE (string2_p); + cesu8_string2_p = lit_get_magic_string_utf8 (id); + cesu8_string2_size = lit_get_magic_string_size (id); + cesu8_string2_length = cesu8_string2_size; + break; + } + case ECMA_DIRECT_STRING_UINT: + { + cesu8_string2_size = ecma_uint32_to_utf8_string ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string2_p), + uint32_to_string_buffer, + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + cesu8_string2_p = uint32_to_string_buffer; + cesu8_string2_length = cesu8_string2_size; + break; + } + default: + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string2_p) == ECMA_DIRECT_STRING_MAGIC_EX); - cesu8_string2_p = (lit_utf8_byte_t *) (long_string_desc_p + 1); - cesu8_string2_size = string2_p->u.long_utf8_string_size; - cesu8_string2_length = long_string_desc_p->long_utf8_string_length; - break; + lit_magic_string_ex_id_t id = (lit_magic_string_ex_id_t) ECMA_GET_DIRECT_STRING_VALUE (string2_p); + cesu8_string2_p = lit_get_magic_string_ex_utf8 (id); + cesu8_string2_size = lit_get_magic_string_ex_size (id); + cesu8_string2_length = lit_utf8_string_length (cesu8_string2_p, cesu8_string2_size); + break; + } } - case ECMA_STRING_CONTAINER_UINT32_IN_DESC: - { - cesu8_string2_size = ecma_uint32_to_utf8_string (string2_p->u.uint32_number, - uint32_to_string_buffer, - ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); - cesu8_string2_p = uint32_to_string_buffer; - cesu8_string2_length = cesu8_string2_size; - break; - } - case ECMA_STRING_CONTAINER_MAGIC_STRING: - { - cesu8_string2_p = lit_get_magic_string_utf8 (string2_p->u.magic_string_id); - cesu8_string2_size = lit_get_magic_string_size (string2_p->u.magic_string_id); - cesu8_string2_length = cesu8_string2_size; - break; - } - default: - { - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string2_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + } + else + { + JERRY_ASSERT (string2_p->refs_and_container >= ECMA_STRING_REF_ONE); - cesu8_string2_p = lit_get_magic_string_ex_utf8 (string2_p->u.magic_string_id); - cesu8_string2_size = lit_get_magic_string_ex_size (string2_p->u.magic_string_id); - cesu8_string2_length = lit_utf8_string_length (cesu8_string2_p, cesu8_string2_size); - break; + switch (ECMA_STRING_GET_CONTAINER (string2_p)) + { + case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + { + cesu8_string2_p = (lit_utf8_byte_t *) (string2_p + 1); + cesu8_string2_size = string2_p->u.utf8_string.size; + cesu8_string2_length = string2_p->u.utf8_string.length; + break; + } + case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: + { + ecma_long_string_t *long_string_desc_p = (ecma_long_string_t *) string2_p; + + cesu8_string2_p = (lit_utf8_byte_t *) (long_string_desc_p + 1); + cesu8_string2_size = string2_p->u.long_utf8_string_size; + cesu8_string2_length = long_string_desc_p->long_utf8_string_length; + break; + } + case ECMA_STRING_CONTAINER_UINT32_IN_DESC: + { + cesu8_string2_size = ecma_uint32_to_utf8_string (string2_p->u.uint32_number, + uint32_to_string_buffer, + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + cesu8_string2_p = uint32_to_string_buffer; + cesu8_string2_length = cesu8_string2_size; + break; + } + default: + { + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string2_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + cesu8_string2_p = lit_get_magic_string_ex_utf8 (string2_p->u.magic_string_ex_id); + cesu8_string2_size = lit_get_magic_string_ex_size (string2_p->u.magic_string_ex_id); + cesu8_string2_length = lit_utf8_string_length (cesu8_string2_p, cesu8_string2_size); + break; + } } } @@ -753,7 +844,6 @@ ecma_append_magic_string_to_string (ecma_string_t *string1_p, { if (unlikely (ecma_string_is_empty (string1_p))) { - ecma_deref_ecma_string (string1_p); return ecma_new_ecma_string_from_magic_string_id (string2_id); } @@ -770,6 +860,12 @@ void ecma_ref_ecma_string (ecma_string_t *string_p) /**< string descriptor */ { JERRY_ASSERT (string_p != NULL); + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + return; + } + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); if (likely (string_p->refs_and_container < ECMA_STRING_MAX_REF)) @@ -791,6 +887,12 @@ void ecma_deref_ecma_string (ecma_string_t *string_p) /**< ecma-string */ { JERRY_ASSERT (string_p != NULL); + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + return; + } + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); /* Decrease reference counter. */ @@ -829,7 +931,6 @@ ecma_deref_ecma_string (ecma_string_t *string_p) /**< ecma-string */ return; } 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 */ @@ -837,7 +938,7 @@ ecma_deref_ecma_string (ecma_string_t *string_p) /**< ecma-string */ } case ECMA_STRING_LITERAL_NUMBER: { - ecma_fast_free_value (string_p->u.lit_number); + ecma_free_value (string_p->u.lit_number); break; } default: @@ -854,43 +955,33 @@ ecma_deref_ecma_string (ecma_string_t *string_p) /**< ecma-string */ * Convert ecma-string to number */ ecma_number_t -ecma_string_to_number (const ecma_string_t *str_p) /**< ecma-string */ +ecma_string_to_number (const ecma_string_t *string_p) /**< ecma-string */ { - JERRY_ASSERT (str_p != NULL); + JERRY_ASSERT (string_p != NULL); - switch (ECMA_STRING_GET_CONTAINER (str_p)) + if (ECMA_IS_DIRECT_STRING (string_p)) { - case ECMA_STRING_CONTAINER_UINT32_IN_DESC: + if (ECMA_IS_DIRECT_STRING_WITH_TYPE (string_p, ECMA_DIRECT_STRING_UINT)) { - return ((ecma_number_t) str_p->u.uint32_number); - } - - case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: - case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: - case ECMA_STRING_CONTAINER_MAGIC_STRING: - case ECMA_STRING_CONTAINER_MAGIC_STRING_EX: - { - ecma_number_t num; - - ECMA_STRING_TO_UTF8_STRING (str_p, str_buffer_p, str_buffer_size); - - if (str_buffer_size == 0) - { - return ECMA_NUMBER_ZERO; - } - - num = ecma_utf8_string_to_number (str_buffer_p, str_buffer_size); - - ECMA_FINALIZE_UTF8_STRING (str_buffer_p, str_buffer_size); - - return num; - } - - default: - { - JERRY_UNREACHABLE (); + return (ecma_number_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); } } + else if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + return ((ecma_number_t) string_p->u.uint32_number); + } + + lit_utf8_size_t size; + const lit_utf8_byte_t *chars_p = ecma_string_get_chars_fast (string_p, &size); + + JERRY_ASSERT (chars_p != NULL); + + if (size == 0) + { + return ECMA_NUMBER_ZERO; + } + + return ecma_utf8_string_to_number (chars_p, size); } /* ecma_string_to_number */ /** @@ -902,14 +993,22 @@ ecma_string_to_number (const ecma_string_t *str_p) /**< ecma-string */ inline uint32_t __attr_always_inline___ ecma_string_get_array_index (const ecma_string_t *str_p) /**< ecma-string */ { - const ecma_string_container_t type = ECMA_STRING_GET_CONTAINER (str_p); - - if (type == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + if (ECMA_IS_DIRECT_STRING (str_p)) { - /* When the uint32_number is equal to the maximum value of 32 bit - * unsigned integer number, it is also an invalid array index. - * The comparison to ECMA_STRING_NOT_ARRAY_INDEX will be true - * in this case. */ + if (ECMA_IS_DIRECT_STRING_WITH_TYPE (str_p, ECMA_DIRECT_STRING_UINT)) + { + /* Value cannot be equal to the maximum value of a 32 bit unsigned number. */ + return (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (str_p); + } + + return ECMA_STRING_NOT_ARRAY_INDEX; + } + + if (ECMA_STRING_GET_CONTAINER (str_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + /* When the uint32_number is equal to the maximum value of 32 bit unsigned integer number, + * it is also an invalid array index. The comparison to ECMA_STRING_NOT_ARRAY_INDEX will + * be true in this case. */ return str_p->u.uint32_number; } @@ -923,57 +1022,46 @@ ecma_string_get_array_index (const ecma_string_t *str_p) /**< ecma-string */ * @return number of bytes, actually copied to the buffer. */ lit_utf8_size_t __attr_return_value_should_be_checked___ -ecma_string_copy_to_cesu8_buffer (const ecma_string_t *string_desc_p, /**< ecma-string descriptor */ +ecma_string_copy_to_cesu8_buffer (const ecma_string_t *string_p, /**< ecma-string descriptor */ lit_utf8_byte_t *buffer_p, /**< destination buffer pointer * (can be NULL if buffer_size == 0) */ lit_utf8_size_t buffer_size) /**< size of buffer */ { - JERRY_ASSERT (string_desc_p != NULL); - JERRY_ASSERT (string_desc_p->refs_and_container >= ECMA_STRING_REF_ONE); + JERRY_ASSERT (string_p != NULL); JERRY_ASSERT (buffer_p != NULL || buffer_size == 0); - JERRY_ASSERT (ecma_string_get_size (string_desc_p) <= buffer_size); + JERRY_ASSERT (ecma_string_get_size (string_p) <= buffer_size); lit_utf8_size_t size; - switch (ECMA_STRING_GET_CONTAINER (string_desc_p)) + if (ECMA_IS_DIRECT_STRING (string_p)) { - case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + if (ECMA_IS_DIRECT_STRING_WITH_TYPE (string_p, ECMA_DIRECT_STRING_UINT)) { - size = string_desc_p->u.utf8_string.size; - memcpy (buffer_p, string_desc_p + 1, size); - break; - } - case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: - { - size = string_desc_p->u.long_utf8_string_size; - memcpy (buffer_p, ((ecma_long_string_t *) string_desc_p) + 1, size); - break; - } - case ECMA_STRING_CONTAINER_UINT32_IN_DESC: - { - const uint32_t uint32_number = string_desc_p->u.uint32_number; + uint32_t uint32_number = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); size = ecma_uint32_to_utf8_string (uint32_number, buffer_p, buffer_size); - break; + JERRY_ASSERT (size <= buffer_size); + return size; } - case ECMA_STRING_CONTAINER_MAGIC_STRING: - { - const lit_magic_string_id_t id = string_desc_p->u.magic_string_id; - size = lit_get_magic_string_size (id); - memcpy (buffer_p, lit_get_magic_string_utf8 (id), size); - break; - } - default: - { - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_desc_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + } + else + { + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); - const lit_magic_string_ex_id_t id = string_desc_p->u.magic_string_ex_id; - size = lit_get_magic_string_ex_size (id); - memcpy (buffer_p, lit_get_magic_string_ex_utf8 (id), size); - break; + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + uint32_t uint32_number = string_p->u.uint32_number; + size = ecma_uint32_to_utf8_string (uint32_number, buffer_p, buffer_size); + JERRY_ASSERT (size <= buffer_size); + return size; } } + const lit_utf8_byte_t *chars_p = ecma_string_get_chars_fast (string_p, &size); + + JERRY_ASSERT (chars_p != NULL); JERRY_ASSERT (size <= buffer_size); + + memcpy (buffer_p, chars_p, size); return size; } /* ecma_string_copy_to_cesu8_buffer */ @@ -984,61 +1072,56 @@ ecma_string_copy_to_cesu8_buffer (const ecma_string_t *string_desc_p, /**< ecma- * @return number of bytes, actually copied to the buffer. */ lit_utf8_size_t __attr_return_value_should_be_checked___ -ecma_string_copy_to_utf8_buffer (const ecma_string_t *string_desc_p, /**< ecma-string descriptor */ +ecma_string_copy_to_utf8_buffer (const ecma_string_t *string_p, /**< ecma-string descriptor */ lit_utf8_byte_t *buffer_p, /**< destination buffer pointer * (can be NULL if buffer_size == 0) */ lit_utf8_size_t buffer_size) /**< size of buffer */ { - JERRY_ASSERT (string_desc_p != NULL); - JERRY_ASSERT (string_desc_p->refs_and_container >= ECMA_STRING_REF_ONE); + JERRY_ASSERT (string_p != NULL); JERRY_ASSERT (buffer_p != NULL || buffer_size == 0); - JERRY_ASSERT (ecma_string_get_utf8_size (string_desc_p) <= buffer_size); + JERRY_ASSERT (ecma_string_get_utf8_size (string_p) <= buffer_size); lit_utf8_size_t size; - switch (ECMA_STRING_GET_CONTAINER (string_desc_p)) + if (ECMA_IS_DIRECT_STRING (string_p)) { - case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + if (ECMA_IS_DIRECT_STRING_WITH_TYPE (string_p, ECMA_DIRECT_STRING_UINT)) { - size = lit_convert_cesu8_string_to_utf8_string ((lit_utf8_byte_t *) (string_desc_p + 1), - string_desc_p->u.utf8_string.size, - buffer_p, - buffer_size); - break; - } - case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: - { - size = lit_convert_cesu8_string_to_utf8_string ((lit_utf8_byte_t *) (((ecma_long_string_t *) string_desc_p) + 1), - string_desc_p->u.long_utf8_string_size, - buffer_p, - buffer_size); - break; - } - case ECMA_STRING_CONTAINER_UINT32_IN_DESC: - { - const uint32_t uint32_number = string_desc_p->u.uint32_number; + uint32_t uint32_number = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); size = ecma_uint32_to_utf8_string (uint32_number, buffer_p, buffer_size); - break; - } - case ECMA_STRING_CONTAINER_MAGIC_STRING: - { - const lit_magic_string_id_t id = string_desc_p->u.magic_string_id; - size = lit_get_magic_string_size (id); - memcpy (buffer_p, lit_get_magic_string_utf8 (id), size); - break; - } - default: - { - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_desc_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); - - const lit_magic_string_ex_id_t id = string_desc_p->u.magic_string_ex_id; - size = lit_convert_cesu8_string_to_utf8_string (lit_get_magic_string_ex_utf8 (id), - lit_get_magic_string_ex_size (id), - buffer_p, - buffer_size); - break; + JERRY_ASSERT (size <= buffer_size); + return size; } } + else + { + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + uint32_t uint32_number = string_p->u.uint32_number; + size = ecma_uint32_to_utf8_string (uint32_number, buffer_p, buffer_size); + JERRY_ASSERT (size <= buffer_size); + return size; + } + } + + bool is_ascii; + const lit_utf8_byte_t *chars_p = ecma_string_get_chars (string_p, &size, &is_ascii); + + JERRY_ASSERT (chars_p != NULL); + + if (is_ascii) + { + JERRY_ASSERT (size <= buffer_size); + memcpy (buffer_p, chars_p, size); + return size; + } + + size = lit_convert_cesu8_string_to_utf8_string (chars_p, + size, + buffer_p, + buffer_size); JERRY_ASSERT (size <= buffer_size); return size; @@ -1060,7 +1143,6 @@ ecma_substring_copy_to_cesu8_buffer (const ecma_string_t *string_desc_p, /**< ec lit_utf8_size_t buffer_size) /**< size of buffer */ { JERRY_ASSERT (string_desc_p != NULL); - JERRY_ASSERT (string_desc_p->refs_and_container >= ECMA_STRING_REF_ONE); JERRY_ASSERT (buffer_p != NULL || buffer_size == 0); ecma_length_t string_length = ecma_string_get_length (string_desc_p); @@ -1271,14 +1353,14 @@ ecma_string_to_utf8_bytes (const ecma_string_t *string_desc_p, /**< ecma-string } /* ecma_string_to_utf8_bytes */ /** - * Get size of the number stored locally in the string's descriptor + * Get size of the uint32 number stored locally in the string's descriptor * * Note: the represented number size and length are equal * * @return size in bytes */ static inline ecma_length_t __attr_always_inline___ -ecma_string_get_number_in_desc_size (const uint32_t uint32_number) /**< number in the string-descriptor */ +ecma_string_get_uint32_size (const uint32_t uint32_number) /**< number in the string-descriptor */ { uint32_t prev_number = 1; uint32_t next_number = 100; @@ -1299,7 +1381,7 @@ ecma_string_get_number_in_desc_size (const uint32_t uint32_number) /**< number i } return size; -} /* ecma_string_get_number_in_desc_size */ +} /* ecma_string_get_uint32_size */ /** * Checks whether the given string is a sequence of ascii characters. @@ -1327,60 +1409,103 @@ ecma_string_get_chars (const ecma_string_t *string_p, /**< ecma-string */ lit_utf8_size_t size; const lit_utf8_byte_t *result_p; - switch (ECMA_STRING_GET_CONTAINER (string_p)) + if (ECMA_IS_DIRECT_STRING (string_p)) { - case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + switch (ECMA_GET_DIRECT_STRING_TYPE (string_p)) { - size = string_p->u.utf8_string.size; - length = string_p->u.utf8_string.length; - result_p = (const lit_utf8_byte_t *) (string_p + 1); - break; - } - case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: - { - size = string_p->u.long_utf8_string_size; - ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; - length = long_string_p->long_utf8_string_length; - result_p = (const lit_utf8_byte_t *) (long_string_p + 1); - break; - } - case ECMA_STRING_CONTAINER_UINT32_IN_DESC: - { - size = (lit_utf8_size_t) ecma_string_get_number_in_desc_size (string_p->u.uint32_number); - - /* All numbers must be ascii strings. */ - JERRY_ASSERT (ecma_string_get_length (string_p) == size); - - length = size; - result_p = NULL; - break; - } - case ECMA_STRING_CONTAINER_MAGIC_STRING: - { - size = lit_get_magic_string_size (string_p->u.magic_string_id); - - length = size; - result_p = lit_get_magic_string_utf8 (string_p->u.magic_string_id); - - /* All magic strings must be ascii strings. */ - JERRY_ASSERT (ECMA_STRING_IS_ASCII (result_p, size)); - break; - } - default: - { - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); - - size = lit_get_magic_string_ex_size (string_p->u.magic_string_ex_id); - length = 0; - - if (is_ascii_p != NULL) + case ECMA_DIRECT_STRING_MAGIC: { - length = lit_utf8_string_length (lit_get_magic_string_ex_utf8 (string_p->u.magic_string_ex_id), - lit_get_magic_string_ex_size (string_p->u.magic_string_ex_id)); - } + lit_magic_string_id_t id = (lit_magic_string_id_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); - result_p = lit_get_magic_string_ex_utf8 (string_p->u.magic_string_ex_id); - break; + size = lit_get_magic_string_size (id); + length = size; + + result_p = lit_get_magic_string_utf8 (id); + + /* All magic strings must be ascii strings. */ + JERRY_ASSERT (ECMA_STRING_IS_ASCII (result_p, size)); + break; + } + case ECMA_DIRECT_STRING_UINT: + { + uint32_t uint32_number = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + size = (lit_utf8_size_t) ecma_string_get_uint32_size (uint32_number); + + /* All numbers must be ascii strings. */ + JERRY_ASSERT (ecma_string_get_length (string_p) == size); + + length = size; + result_p = NULL; + break; + } + default: + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_MAGIC_EX); + + lit_magic_string_ex_id_t id = (lit_magic_string_ex_id_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + + size = lit_get_magic_string_ex_size (id); + length = 0; + + if (unlikely (is_ascii_p != NULL)) + { + length = lit_utf8_string_length (lit_get_magic_string_ex_utf8 (string_p->u.magic_string_ex_id), + lit_get_magic_string_ex_size (string_p->u.magic_string_ex_id)); + } + + result_p = lit_get_magic_string_ex_utf8 (id); + break; + } + } + } + else + { + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); + + switch (ECMA_STRING_GET_CONTAINER (string_p)) + { + case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + { + size = string_p->u.utf8_string.size; + length = string_p->u.utf8_string.length; + result_p = (const lit_utf8_byte_t *) (string_p + 1); + break; + } + case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: + { + size = string_p->u.long_utf8_string_size; + ecma_long_string_t *long_string_p = (ecma_long_string_t *) string_p; + length = long_string_p->long_utf8_string_length; + result_p = (const lit_utf8_byte_t *) (long_string_p + 1); + break; + } + case ECMA_STRING_CONTAINER_UINT32_IN_DESC: + { + size = (lit_utf8_size_t) ecma_string_get_uint32_size (string_p->u.uint32_number); + + /* All numbers must be ascii strings. */ + JERRY_ASSERT (ecma_string_get_length (string_p) == size); + + length = size; + result_p = NULL; + break; + } + default: + { + JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); + + size = lit_get_magic_string_ex_size (string_p->u.magic_string_ex_id); + length = 0; + + if (unlikely (is_ascii_p != NULL)) + { + length = lit_utf8_string_length (lit_get_magic_string_ex_utf8 (string_p->u.magic_string_ex_id), + lit_get_magic_string_ex_size (string_p->u.magic_string_ex_id)); + } + + result_p = lit_get_magic_string_ex_utf8 (string_p->u.magic_string_ex_id); + break; + } } } @@ -1403,8 +1528,7 @@ inline bool __attr_always_inline___ ecma_compare_ecma_string_to_magic_id (const ecma_string_t *string_p, /**< property name */ lit_magic_string_id_t id) /**< magic string id */ { - return (string_p->u.magic_string_id == id - && ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING); + return (string_p == ecma_get_magic_string (id)); } /* ecma_compare_ecma_string_to_magic_id */ /** @@ -1431,6 +1555,16 @@ ecma_string_is_length (const ecma_string_t *string_p) /**< property name */ return ecma_compare_ecma_string_to_magic_id (string_p, LIT_MAGIC_STRING_LENGTH); } /* ecma_string_is_length */ + +static inline ecma_string_t * __attr_always_inline___ +ecma_property_to_string (ecma_property_t property, /**< property name type */ + jmem_cpointer_t prop_name_cp) /**< property name compressed pointer */ +{ + uintptr_t property_string = ((uintptr_t) (property)) & (0x3 << ECMA_PROPERTY_NAME_TYPE_SHIFT); + property_string = (property_string >> ECMA_STRING_TYPE_CONVERSION_SHIFT) | ECMA_TYPE_DIRECT_STRING; + return (ecma_string_t *) (property_string | (((uintptr_t) prop_name_cp) << ECMA_DIRECT_STRING_SHIFT)); +} /* ecma_property_to_string */ + /** * Converts a string into a property name * @@ -1440,38 +1574,13 @@ inline jmem_cpointer_t __attr_always_inline___ ecma_string_to_property_name (ecma_string_t *prop_name_p, /**< property name */ ecma_property_t *name_type_p) /**< [out] property name type */ { - ecma_string_container_t container = ECMA_STRING_GET_CONTAINER (prop_name_p); - - switch (container) + if (ECMA_IS_DIRECT_STRING (prop_name_p)) { - case ECMA_STRING_CONTAINER_UINT32_IN_DESC: - case ECMA_STRING_CONTAINER_MAGIC_STRING: - case ECMA_STRING_CONTAINER_MAGIC_STRING_EX: - { -#ifdef JERRY_CPOINTER_32_BIT - - *name_type_p = (ecma_property_t) (container << ECMA_PROPERTY_NAME_TYPE_SHIFT); - return (jmem_cpointer_t) prop_name_p->u.common_uint32_field; - -#else /* !JERRY_CPOINTER_32_BIT */ - - if (prop_name_p->u.common_uint32_field < (UINT16_MAX + 1)) - { - *name_type_p = (ecma_property_t) (container << ECMA_PROPERTY_NAME_TYPE_SHIFT); - return (jmem_cpointer_t) prop_name_p->u.common_uint32_field; - } - -#endif /* JERRY_CPOINTER_32_BIT */ - - break; - } - default: - { - break; - } + *name_type_p = (ecma_property_t) ECMA_DIRECT_STRING_TYPE_TO_PROP_NAME_TYPE (prop_name_p); + return (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (prop_name_p); } - *name_type_p = ECMA_PROPERTY_NAME_TYPE_STRING << ECMA_PROPERTY_NAME_TYPE_SHIFT; + *name_type_p = ECMA_DIRECT_STRING_PTR << ECMA_PROPERTY_NAME_TYPE_SHIFT; ecma_ref_ecma_string (prop_name_p); @@ -1484,37 +1593,20 @@ ecma_string_to_property_name (ecma_string_t *prop_name_p, /**< property name */ * Converts a property name into a string * * @return the string pointer + * string must be released with ecma_deref_ecma_string */ ecma_string_t * ecma_string_from_property_name (ecma_property_t property, /**< property name type */ jmem_cpointer_t prop_name_cp) /**< property name compressed pointer */ { - /* If string_buf_p is NULL this function returns with a new string - * instance which needs to be released with ecma_deref_ecma_string. */ - - switch (ECMA_PROPERTY_GET_NAME_TYPE (property)) + if (ECMA_PROPERTY_GET_NAME_TYPE (property) != ECMA_DIRECT_STRING_PTR) { - case ECMA_STRING_CONTAINER_UINT32_IN_DESC: - { - return ecma_new_ecma_string_from_uint32 ((uint32_t) prop_name_cp); - } - case ECMA_STRING_CONTAINER_MAGIC_STRING: - { - return ecma_new_ecma_string_from_magic_string_id ((lit_magic_string_id_t) prop_name_cp); - } - case ECMA_STRING_CONTAINER_MAGIC_STRING_EX: - { - return ecma_new_ecma_string_from_magic_string_ex_id ((lit_magic_string_ex_id_t) prop_name_cp); - } - default: - { - JERRY_ASSERT (ECMA_PROPERTY_GET_NAME_TYPE (property) == ECMA_PROPERTY_NAME_TYPE_STRING); - - ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); - ecma_ref_ecma_string (prop_name_p); - return prop_name_p; - } + return ecma_property_to_string (property, prop_name_cp); } + + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); + ecma_ref_ecma_string (prop_name_p); + return prop_name_p; } /* ecma_string_from_property_name */ /** @@ -1528,14 +1620,14 @@ ecma_string_get_property_name_hash (ecma_property_t property, /**< property name { switch (ECMA_PROPERTY_GET_NAME_TYPE (property)) { - case ECMA_STRING_CONTAINER_MAGIC_STRING_EX: - { - return (lit_string_hash_t) (LIT_MAGIC_STRING__COUNT + prop_name_cp); - } - case ECMA_PROPERTY_NAME_TYPE_STRING: + case ECMA_DIRECT_STRING_PTR: { ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); - return ecma_string_hash (prop_name_p); + return prop_name_p->hash; + } + case ECMA_DIRECT_STRING_MAGIC_EX: + { + return (lit_string_hash_t) (LIT_MAGIC_STRING__COUNT + prop_name_cp); } default: { @@ -1556,17 +1648,15 @@ ecma_string_get_property_index (ecma_property_t property, /**< property name typ { switch (ECMA_PROPERTY_GET_NAME_TYPE (property)) { - case ECMA_STRING_CONTAINER_UINT32_IN_DESC: + case ECMA_DIRECT_STRING_UINT: { return (uint32_t) prop_name_cp; } -#ifndef JERRY_CPOINTER_32_BIT - case ECMA_PROPERTY_NAME_TYPE_STRING: + case ECMA_DIRECT_STRING_PTR: { ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); return ecma_string_get_array_index (prop_name_p); } -#endif /* !JERRY_CPOINTER_32_BIT */ default: { return ECMA_STRING_NOT_ARRAY_INDEX; @@ -1585,25 +1675,13 @@ ecma_string_compare_to_property_name (ecma_property_t property, /**< property na jmem_cpointer_t prop_name_cp, /**< property name compressed pointer */ const ecma_string_t *string_p) /**< other string */ { - uint32_t property_name_type = ECMA_PROPERTY_GET_NAME_TYPE (property); - - switch (property_name_type) + if (ECMA_PROPERTY_GET_NAME_TYPE (property) != ECMA_DIRECT_STRING_PTR) { - case ECMA_STRING_CONTAINER_UINT32_IN_DESC: - case ECMA_STRING_CONTAINER_MAGIC_STRING: - case ECMA_STRING_CONTAINER_MAGIC_STRING_EX: - { - return (ECMA_STRING_GET_CONTAINER (string_p) == property_name_type - && string_p->u.common_uint32_field == (uint32_t) prop_name_cp); - } - default: - { - JERRY_ASSERT (property_name_type == ECMA_PROPERTY_NAME_TYPE_STRING); - - ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); - return ecma_compare_ecma_strings (prop_name_p, string_p); - } + return ecma_property_to_string (property, prop_name_cp) == string_p; } + + ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_name_cp); + return ecma_compare_ecma_strings (prop_name_p, string_p); } /* ecma_string_compare_to_property_name */ /** @@ -1667,6 +1745,12 @@ ecma_compare_ecma_strings (const ecma_string_t *string1_p, /* ecma-string */ return true; } + /* Either string is direct, return with false. */ + if (ECMA_IS_DIRECT_STRING (((uintptr_t) string1_p) | ((uintptr_t) string2_p))) + { + return false; + } + if (string1_p->hash != string2_p->hash) { return false; @@ -1679,7 +1763,7 @@ ecma_compare_ecma_strings (const ecma_string_t *string1_p, /* ecma-string */ return false; } - if (string1_container < ECMA_STRING_CONTAINER_HEAP_UTF8_STRING) + if (string1_container >= ECMA_STRING_CONTAINER_UINT32_IN_DESC) { return string1_p->u.common_uint32_field == string2_p->u.common_uint32_field; } @@ -1713,79 +1797,65 @@ ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p, /**< ecma- lit_utf8_byte_t uint32_to_string_buffer1[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; lit_utf8_byte_t uint32_to_string_buffer2[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; - switch (ECMA_STRING_GET_CONTAINER (string1_p)) + if (ECMA_IS_DIRECT_STRING (string1_p)) { - case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + if (ECMA_GET_DIRECT_STRING_TYPE (string1_p) != ECMA_DIRECT_STRING_UINT) { - utf8_string1_p = (lit_utf8_byte_t *) (string1_p + 1); - utf8_string1_size = string1_p->u.utf8_string.size; - break; + utf8_string1_p = ecma_string_get_chars_fast (string1_p, &utf8_string1_size); } - case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: + else { - utf8_string1_p = (lit_utf8_byte_t *) (((ecma_long_string_t *) string1_p) + 1); - utf8_string1_size = string1_p->u.long_utf8_string_size; - break; + utf8_string1_size = ecma_uint32_to_utf8_string ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string1_p), + uint32_to_string_buffer1, + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + utf8_string1_p = uint32_to_string_buffer1; } - case ECMA_STRING_CONTAINER_UINT32_IN_DESC: + } + else + { + JERRY_ASSERT (string1_p->refs_and_container >= ECMA_STRING_REF_ONE); + + if (ECMA_STRING_GET_CONTAINER (string1_p) != ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + utf8_string1_p = ecma_string_get_chars_fast (string1_p, &utf8_string1_size); + } + else { utf8_string1_size = ecma_uint32_to_utf8_string (string1_p->u.uint32_number, uint32_to_string_buffer1, ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); utf8_string1_p = uint32_to_string_buffer1; - break; - } - case ECMA_STRING_CONTAINER_MAGIC_STRING: - { - utf8_string1_p = lit_get_magic_string_utf8 (string1_p->u.magic_string_id); - utf8_string1_size = lit_get_magic_string_size (string1_p->u.magic_string_id); - break; - } - default: - { - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); - - utf8_string1_p = lit_get_magic_string_ex_utf8 (string1_p->u.magic_string_id); - utf8_string1_size = lit_get_magic_string_ex_size (string1_p->u.magic_string_id); - break; } } - switch (ECMA_STRING_GET_CONTAINER (string2_p)) + if (ECMA_IS_DIRECT_STRING (string2_p)) { - case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: + if (ECMA_GET_DIRECT_STRING_TYPE (string2_p) != ECMA_DIRECT_STRING_UINT) { - utf8_string2_p = (lit_utf8_byte_t *) (string2_p + 1); - utf8_string2_size = string2_p->u.utf8_string.size; - break; + utf8_string2_p = ecma_string_get_chars_fast (string2_p, &utf8_string2_size); } - case ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING: + else { - utf8_string2_p = (lit_utf8_byte_t *) (((ecma_long_string_t *) string2_p) + 1); - utf8_string2_size = string2_p->u.long_utf8_string_size; - break; + utf8_string2_size = ecma_uint32_to_utf8_string ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string2_p), + uint32_to_string_buffer2, + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + utf8_string2_p = uint32_to_string_buffer2; } - case ECMA_STRING_CONTAINER_UINT32_IN_DESC: + } + else + { + JERRY_ASSERT (string2_p->refs_and_container >= ECMA_STRING_REF_ONE); + + if (ECMA_STRING_GET_CONTAINER (string2_p) != ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + utf8_string2_p = ecma_string_get_chars_fast (string2_p, &utf8_string2_size); + } + else { utf8_string2_size = ecma_uint32_to_utf8_string (string2_p->u.uint32_number, uint32_to_string_buffer2, ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); utf8_string2_p = uint32_to_string_buffer2; - break; - } - case ECMA_STRING_CONTAINER_MAGIC_STRING: - { - utf8_string2_p = lit_get_magic_string_utf8 (string2_p->u.magic_string_id); - utf8_string2_size = lit_get_magic_string_size (string2_p->u.magic_string_id); - break; - } - default: - { - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string2_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); - - utf8_string2_p = lit_get_magic_string_ex_utf8 (string2_p->u.magic_string_id); - utf8_string2_size = lit_get_magic_string_ex_size (string2_p->u.magic_string_id); - break; } } @@ -1795,6 +1865,56 @@ ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p, /**< ecma- utf8_string2_size); } /* ecma_compare_ecma_strings_relational */ +/* + * Special value to represent that no size is available. + */ +#define ECMA_STRING_NO_ASCII_SIZE 0xffff + +/** + * Return the size of uint32 and magic strings. + * The length of these strings are equal to thier size. + * + * @return number of characters in the string + */ +static ecma_length_t +ecma_string_get_ascii_size (const ecma_string_t *string_p) /**< ecma-string */ +{ + if (ECMA_IS_DIRECT_STRING (string_p)) + { + switch (ECMA_GET_DIRECT_STRING_TYPE (string_p)) + { + case ECMA_DIRECT_STRING_MAGIC: + { + lit_magic_string_id_t id = (lit_magic_string_id_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + + JERRY_ASSERT (ECMA_STRING_IS_ASCII (lit_get_magic_string_utf8 (id), + lit_get_magic_string_size (id))); + return lit_get_magic_string_size (id); + } + case ECMA_DIRECT_STRING_UINT: + { + uint32_t uint32_number = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + return ecma_string_get_uint32_size (uint32_number); + } + default: + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_MAGIC_EX); + + return ECMA_STRING_NO_ASCII_SIZE; + } + } + } + + JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE); + + if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + { + return ecma_string_get_uint32_size (string_p->u.uint32_number); + } + + return ECMA_STRING_NO_ASCII_SIZE; +} /* ecma_string_get_ascii_size */ + /** * Get length of ecma-string * @@ -1803,6 +1923,22 @@ ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p, /**< ecma- ecma_length_t ecma_string_get_length (const ecma_string_t *string_p) /**< ecma-string */ { + ecma_length_t length = ecma_string_get_ascii_size (string_p); + + if (length != ECMA_STRING_NO_ASCII_SIZE) + { + return length; + } + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_MAGIC_EX); + + lit_magic_string_ex_id_t id = (lit_magic_string_ex_id_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + return lit_utf8_string_length (lit_get_magic_string_ex_utf8 (id), + lit_get_magic_string_ex_size (id)); + } + switch (ECMA_STRING_GET_CONTAINER (string_p)) { case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: @@ -1813,16 +1949,6 @@ ecma_string_get_length (const ecma_string_t *string_p) /**< ecma-string */ { return (ecma_length_t) (((ecma_long_string_t *) string_p)->long_utf8_string_length); } - case ECMA_STRING_CONTAINER_UINT32_IN_DESC: - { - return ecma_string_get_number_in_desc_size (string_p->u.uint32_number); - } - case ECMA_STRING_CONTAINER_MAGIC_STRING: - { - JERRY_ASSERT (ECMA_STRING_IS_ASCII (lit_get_magic_string_utf8 (string_p->u.magic_string_id), - lit_get_magic_string_size (string_p->u.magic_string_id))); - return lit_get_magic_string_size (string_p->u.magic_string_id); - } default: { JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); @@ -1841,6 +1967,22 @@ ecma_string_get_length (const ecma_string_t *string_p) /**< ecma-string */ ecma_length_t ecma_string_get_utf8_length (const ecma_string_t *string_p) /**< ecma-string */ { + ecma_length_t length = ecma_string_get_ascii_size (string_p); + + if (length != ECMA_STRING_NO_ASCII_SIZE) + { + return length; + } + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_MAGIC_EX); + + lit_magic_string_ex_id_t id = (lit_magic_string_ex_id_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + return lit_get_utf8_length_of_cesu8_string (lit_get_magic_string_ex_utf8 (id), + lit_get_magic_string_ex_size (id)); + } + switch (ECMA_STRING_GET_CONTAINER (string_p)) { case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: @@ -1864,16 +2006,6 @@ ecma_string_get_utf8_length (const ecma_string_t *string_p) /**< ecma-string */ return lit_get_utf8_length_of_cesu8_string ((const lit_utf8_byte_t *) (string_p + 1), (lit_utf8_size_t) string_p->u.long_utf8_string_size); } - case ECMA_STRING_CONTAINER_UINT32_IN_DESC: - { - return ecma_string_get_number_in_desc_size (string_p->u.uint32_number); - } - case ECMA_STRING_CONTAINER_MAGIC_STRING: - { - JERRY_ASSERT (ECMA_STRING_IS_ASCII (lit_get_magic_string_utf8 (string_p->u.magic_string_id), - lit_get_magic_string_size (string_p->u.magic_string_id))); - return lit_get_magic_string_size (string_p->u.magic_string_id); - } default: { JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); @@ -1892,6 +2024,21 @@ ecma_string_get_utf8_length (const ecma_string_t *string_p) /**< ecma-string */ lit_utf8_size_t ecma_string_get_size (const ecma_string_t *string_p) /**< ecma-string */ { + ecma_length_t length = ecma_string_get_ascii_size (string_p); + + if (length != ECMA_STRING_NO_ASCII_SIZE) + { + return length; + } + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_MAGIC_EX); + + lit_magic_string_ex_id_t id = (lit_magic_string_ex_id_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + return lit_get_magic_string_ex_size (id); + } + switch (ECMA_STRING_GET_CONTAINER (string_p)) { case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: @@ -1902,14 +2049,6 @@ ecma_string_get_size (const ecma_string_t *string_p) /**< ecma-string */ { return (lit_utf8_size_t) string_p->u.long_utf8_string_size; } - case ECMA_STRING_CONTAINER_UINT32_IN_DESC: - { - return (lit_utf8_size_t) ecma_string_get_number_in_desc_size (string_p->u.uint32_number); - } - case ECMA_STRING_CONTAINER_MAGIC_STRING: - { - return lit_get_magic_string_size (string_p->u.magic_string_id); - } default: { JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); @@ -1926,6 +2065,22 @@ ecma_string_get_size (const ecma_string_t *string_p) /**< ecma-string */ lit_utf8_size_t ecma_string_get_utf8_size (const ecma_string_t *string_p) /**< ecma-string */ { + ecma_length_t length = ecma_string_get_ascii_size (string_p); + + if (length != ECMA_STRING_NO_ASCII_SIZE) + { + return length; + } + + if (ECMA_IS_DIRECT_STRING (string_p)) + { + JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_MAGIC_EX); + + lit_magic_string_ex_id_t id = (lit_magic_string_ex_id_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + return lit_get_utf8_size_of_cesu8_string (lit_get_magic_string_ex_utf8 (id), + lit_get_magic_string_ex_size (id)); + } + switch (ECMA_STRING_GET_CONTAINER (string_p)) { case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING: @@ -1949,14 +2104,6 @@ ecma_string_get_utf8_size (const ecma_string_t *string_p) /**< ecma-string */ return lit_get_utf8_size_of_cesu8_string ((const lit_utf8_byte_t *) (string_p + 1), (lit_utf8_size_t) string_p->u.long_utf8_string_size); } - case ECMA_STRING_CONTAINER_UINT32_IN_DESC: - { - return (lit_utf8_size_t) ecma_string_get_number_in_desc_size (string_p->u.uint32_number); - } - case ECMA_STRING_CONTAINER_MAGIC_STRING: - { - return lit_get_magic_string_size (string_p->u.magic_string_id); - } default: { JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX); @@ -1998,7 +2145,6 @@ ecma_string_get_char_at_pos (const ecma_string_t *string_p, /**< ecma-string */ ecma_string_to_utf8_bytes (string_p, utf8_str_p, buffer_size); - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC); /* Uint32 must be an ascii string. */ JERRY_ASSERT (is_ascii); @@ -2014,7 +2160,7 @@ ecma_string_get_char_at_pos (const ecma_string_t *string_p, /**< ecma-string */ * * @return ecma-string containing specified magic string */ -ecma_string_t * +inline ecma_string_t * __attr_always_inline___ ecma_get_magic_string (lit_magic_string_id_t id) /**< magic string id */ { return ecma_new_ecma_string_from_magic_string_id (id); @@ -2025,7 +2171,7 @@ ecma_get_magic_string (lit_magic_string_id_t id) /**< magic string id */ * * @return ecma-string containing specified external magic string */ -ecma_string_t * +inline ecma_string_t * __attr_always_inline___ ecma_get_magic_string_ex (lit_magic_string_ex_id_t id) /**< external magic string id */ { return ecma_new_ecma_string_from_magic_string_ex_id (id); @@ -2041,9 +2187,9 @@ ecma_get_magic_string_ex (lit_magic_string_ex_id_t id) /**< external magic strin lit_magic_string_id_t ecma_get_string_magic (const ecma_string_t *string_p) /**< ecma-string */ { - if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING) + if (ECMA_IS_DIRECT_STRING_WITH_TYPE (string_p, ECMA_DIRECT_STRING_MAGIC)) { - return (lit_magic_string_id_t) string_p->u.magic_string_id; + return (lit_magic_string_id_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); } return LIT_MAGIC_STRING__COUNT; @@ -2057,7 +2203,19 @@ ecma_get_string_magic (const ecma_string_t *string_p) /**< ecma-string */ inline lit_string_hash_t __attr_always_inline___ ecma_string_hash (const ecma_string_t *string_p) /**< ecma-string to calculate hash for */ { - return (string_p->hash); + if (!ECMA_IS_DIRECT_STRING (string_p)) + { + return (string_p->hash); + } + + lit_string_hash_t hash = (lit_string_hash_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); + + if (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_MAGIC_EX) + { + hash = (lit_string_hash_t) (hash + LIT_MAGIC_STRING__COUNT); + } + + return hash; } /* ecma_string_hash */ /** diff --git a/jerry-core/ecma/base/ecma-helpers-value.c b/jerry-core/ecma/base/ecma-helpers-value.c index 5318333ec..5d6a43eba 100644 --- a/jerry-core/ecma/base/ecma-helpers-value.c +++ b/jerry-core/ecma/base/ecma-helpers-value.c @@ -296,6 +296,9 @@ ecma_is_value_number (ecma_value_t value) /**< ecma value */ || ecma_is_value_float_number (value)); } /* ecma_is_value_number */ +JERRY_STATIC_ASSERT ((ECMA_TYPE_STRING | 0x4) == ECMA_TYPE_DIRECT_STRING, + ecma_type_string_and_direct_string_must_have_one_bit_difference); + /** * Check if the value is ecma-string. * @@ -305,7 +308,7 @@ ecma_is_value_number (ecma_value_t value) /**< ecma value */ inline bool __attr_const___ __attr_always_inline___ ecma_is_value_string (ecma_value_t value) /**< ecma value */ { - return (ecma_get_value_type_field (value) == ECMA_TYPE_STRING); + return ((value & (ECMA_VALUE_TYPE_MASK - 0x4)) == ECMA_TYPE_STRING); } /* ecma_is_value_string */ /** @@ -503,6 +506,11 @@ ecma_make_string_value (const ecma_string_t *ecma_string_p) /**< string to refer { JERRY_ASSERT (ecma_string_p != NULL); + if ((((uintptr_t) ecma_string_p) & ECMA_VALUE_TYPE_MASK) != 0) + { + return (ecma_value_t) (uintptr_t) ecma_string_p; + } + return ecma_pointer_to_ecma_value (ecma_string_p) | ECMA_TYPE_STRING; } /* ecma_make_string_value */ @@ -594,7 +602,12 @@ ecma_get_number_from_value (ecma_value_t value) /**< ecma value */ inline ecma_string_t *__attr_pure___ __attr_always_inline___ ecma_get_string_from_value (ecma_value_t value) /**< ecma value */ { - JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_STRING); + JERRY_ASSERT (ecma_is_value_string (value)); + + if ((value & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_DIRECT_STRING) + { + return (ecma_string_t *) (uintptr_t) value; + } return (ecma_string_t *) ecma_get_pointer_from_ecma_value (value); } /* ecma_get_string_from_value */ @@ -607,7 +620,7 @@ ecma_get_string_from_value (ecma_value_t value) /**< ecma value */ inline ecma_object_t *__attr_pure___ __attr_always_inline___ ecma_get_object_from_value (ecma_value_t value) /**< ecma value */ { - JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_OBJECT); + JERRY_ASSERT (ecma_is_value_object (value)); return (ecma_object_t *) ecma_get_pointer_from_ecma_value (value); } /* ecma_get_object_from_value */ @@ -666,6 +679,7 @@ ecma_copy_value (ecma_value_t value) /**< value description */ switch (ecma_get_value_type_field (value)) { case ECMA_TYPE_DIRECT: + case ECMA_TYPE_DIRECT_STRING: { return value; } @@ -856,6 +870,7 @@ ecma_free_value (ecma_value_t value) /**< value description */ switch (ecma_get_value_type_field (value)) { case ECMA_TYPE_DIRECT: + case ECMA_TYPE_DIRECT_STRING: { /* no memory is allocated */ break; diff --git a/jerry-core/ecma/base/ecma-helpers-values-collection.c b/jerry-core/ecma/base/ecma-helpers-values-collection.c index 69705d10f..c4739911a 100644 --- a/jerry-core/ecma/base/ecma-helpers-values-collection.c +++ b/jerry-core/ecma/base/ecma-helpers-values-collection.c @@ -74,8 +74,9 @@ ecma_free_values_collection (ecma_collection_header_t *header_p, /**< collection do { - if (!ecma_is_value_object (*item_p) - || !(flags & ECMA_COLLECTION_NO_REF_OBJECTS)) + if (!(flags & ECMA_COLLECTION_NO_COPY) + && (!ecma_is_value_object (*item_p) + || !(flags & ECMA_COLLECTION_NO_REF_OBJECTS))) { ecma_free_value (*item_p); } @@ -139,8 +140,9 @@ ecma_append_to_values_collection (ecma_collection_header_t *header_p, /**< colle } } - if (!ecma_is_value_object (value) - || !(flags & ECMA_COLLECTION_NO_REF_OBJECTS)) + if (!(flags & ECMA_COLLECTION_NO_COPY) + && (!ecma_is_value_object (value) + || !(flags & ECMA_COLLECTION_NO_REF_OBJECTS))) { value = ecma_copy_value (value); } diff --git a/jerry-core/ecma/base/ecma-helpers.c b/jerry-core/ecma/base/ecma-helpers.c index 0e1148c7a..12a5870c2 100644 --- a/jerry-core/ecma/base/ecma-helpers.c +++ b/jerry-core/ecma/base/ecma-helpers.c @@ -723,7 +723,7 @@ ecma_free_property (ecma_object_t *object_p, /**< object the property belongs to { case ECMA_PROPERTY_TYPE_NAMEDDATA: { - if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_STRING_CONTAINER_MAGIC_STRING) + if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC) { if (name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE || name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER) @@ -758,7 +758,7 @@ ecma_free_property (ecma_object_t *object_p, /**< object the property belongs to ecma_lcache_invalidate (object_p, name_cp, property_p); } - if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_PROPERTY_NAME_TYPE_STRING) + if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_PTR) { ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, name_cp); ecma_deref_ecma_string (prop_name_p); @@ -1475,34 +1475,33 @@ ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */ if (bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION) { - jmem_cpointer_t *literal_start_p = NULL; + ecma_value_t *literal_start_p = NULL; uint32_t literal_end; uint32_t const_literal_end; if (bytecode_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) { - uint8_t *byte_p = (uint8_t *) bytecode_p; - literal_start_p = (jmem_cpointer_t *) (byte_p + sizeof (cbc_uint16_arguments_t)); - cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_p; literal_end = args_p->literal_end; const_literal_end = args_p->const_literal_end; + + literal_start_p = (ecma_value_t *) ((uint8_t *) bytecode_p + sizeof (cbc_uint16_arguments_t)); + literal_start_p -= args_p->register_end; } else { - uint8_t *byte_p = (uint8_t *) bytecode_p; - literal_start_p = (jmem_cpointer_t *) (byte_p + sizeof (cbc_uint8_arguments_t)); - cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_p; literal_end = args_p->literal_end; const_literal_end = args_p->const_literal_end; + + literal_start_p = (ecma_value_t *) ((uint8_t *) bytecode_p + sizeof (cbc_uint8_arguments_t)); + literal_start_p -= args_p->register_end; } for (uint32_t i = const_literal_end; i < literal_end; i++) { - jmem_cpointer_t bytecode_cpointer = literal_start_p[i]; - ecma_compiled_code_t *bytecode_literal_p = ECMA_GET_NON_NULL_POINTER (ecma_compiled_code_t, - bytecode_cpointer); + ecma_compiled_code_t *bytecode_literal_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, + literal_start_p[i]); /* Self references are ignored. */ if (bytecode_literal_p != bytecode_p) @@ -1554,7 +1553,7 @@ ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */ #ifndef CONFIG_DISABLE_REGEXP_BUILTIN re_compiled_code_t *re_bytecode_p = (re_compiled_code_t *) bytecode_p; - ecma_deref_ecma_string (ECMA_GET_NON_NULL_POINTER (ecma_string_t, re_bytecode_p->pattern_cp)); + ecma_deref_ecma_string (ecma_get_string_from_value (re_bytecode_p->pattern)); #endif /* !CONFIG_DISABLE_REGEXP_BUILTIN */ } diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 77b0d0f8f..d60c578bd 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -233,8 +233,6 @@ ecma_substring_copy_to_utf8_buffer (const ecma_string_t *string_desc_p, void ecma_string_to_utf8_bytes (const ecma_string_t *string_desc_p, lit_utf8_byte_t *buffer_p, lit_utf8_size_t buffer_size); const lit_utf8_byte_t *ecma_string_get_chars (const ecma_string_t *string_p, lit_utf8_size_t *size_p, bool *is_ascii_p); -void ecma_init_ecma_string_from_uint32 (ecma_string_t *string_desc_p, uint32_t uint32_number); -void ecma_init_ecma_magic_string (ecma_string_t *string_desc_p, lit_magic_string_id_t id); bool ecma_compare_ecma_string_to_magic_id (const ecma_string_t *string_p, lit_magic_string_id_t id); bool ecma_string_is_empty (const ecma_string_t *string_p); bool ecma_string_is_length (const ecma_string_t *string_p); diff --git a/jerry-core/ecma/base/ecma-lcache.c b/jerry-core/ecma/base/ecma-lcache.c index 6982883c4..81cb7618a 100644 --- a/jerry-core/ecma/base/ecma-lcache.c +++ b/jerry-core/ecma/base/ecma-lcache.c @@ -143,38 +143,13 @@ static inline jmem_cpointer_t __attr_always_inline___ ecma_string_to_lcache_property_name (const ecma_string_t *prop_name_p, /**< property name */ ecma_property_t *name_type_p) /**< [out] property name type */ { - ecma_string_container_t container = ECMA_STRING_GET_CONTAINER (prop_name_p); - - switch (container) + if (ECMA_IS_DIRECT_STRING (prop_name_p)) { - case ECMA_STRING_CONTAINER_UINT32_IN_DESC: - case ECMA_STRING_CONTAINER_MAGIC_STRING: - case ECMA_STRING_CONTAINER_MAGIC_STRING_EX: - { -#ifdef JERRY_CPOINTER_32_BIT - - *name_type_p = (ecma_property_t) container; - return (jmem_cpointer_t) prop_name_p->u.uint32_number; - -#else /* !JERRY_CPOINTER_32_BIT */ - - if (prop_name_p->u.uint32_number < (UINT16_MAX + 1)) - { - *name_type_p = (ecma_property_t) container; - return (jmem_cpointer_t) prop_name_p->u.uint32_number; - } - -#endif /* JERRY_CPOINTER_32_BIT */ - - break; - } - default: - { - break; - } + *name_type_p = (ecma_property_t) ECMA_GET_DIRECT_STRING_TYPE (prop_name_p); + return (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (prop_name_p); } - *name_type_p = ECMA_PROPERTY_NAME_TYPE_STRING; + *name_type_p = ECMA_DIRECT_STRING_PTR; jmem_cpointer_t prop_name_cp; ECMA_SET_NON_NULL_POINTER (prop_name_cp, prop_name_p); diff --git a/jerry-core/ecma/base/ecma-literal-storage.c b/jerry-core/ecma/base/ecma-literal-storage.c index e1627f0ae..b93bd77b2 100644 --- a/jerry-core/ecma/base/ecma-literal-storage.c +++ b/jerry-core/ecma/base/ecma-literal-storage.c @@ -66,12 +66,17 @@ ecma_finalize_lit_storage (void) * * @return ecma_string_t compressed pointer */ -jmem_cpointer_t +ecma_value_t ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p, /**< string to be searched */ lit_utf8_size_t size) /**< size of the string */ { ecma_string_t *string_p = ecma_new_ecma_string_from_utf8 (chars_p, size); + if (ECMA_IS_DIRECT_STRING (string_p)) + { + return ecma_make_string_value (string_p); + } + ecma_lit_storage_item_t *string_list_p = JERRY_CONTEXT (string_list_first_p); jmem_cpointer_t *empty_cpointer_p = NULL; @@ -95,7 +100,7 @@ ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p, /**< string { /* Return with string if found in the list. */ ecma_deref_ecma_string (string_p); - return string_list_p->values[i]; + return ecma_make_string_value (value_p); } } } @@ -109,7 +114,7 @@ ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p, /**< string if (empty_cpointer_p != NULL) { *empty_cpointer_p = result; - return result; + return ecma_make_string_value (string_p); } ecma_lit_storage_item_t *new_item_p; @@ -124,7 +129,7 @@ ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p, /**< string JMEM_CP_SET_POINTER (new_item_p->next_cp, JERRY_CONTEXT (string_list_first_p)); JERRY_CONTEXT (string_list_first_p) = new_item_p; - return result; + return ecma_make_string_value (string_p); } /* ecma_find_or_create_literal_string */ /** @@ -132,11 +137,18 @@ ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p, /**< string * * @return ecma_string_t compressed pointer */ -jmem_cpointer_t +ecma_value_t ecma_find_or_create_literal_number (ecma_number_t number_arg) /**< number to be searched */ { ecma_value_t num = ecma_make_number_value (number_arg); + if (ecma_is_value_integer_number (num)) + { + return num; + } + + JERRY_ASSERT (ecma_is_value_float_number (num)); + ecma_lit_storage_item_t *number_list_p = JERRY_CONTEXT (number_list_first_p); jmem_cpointer_t *empty_cpointer_p = NULL; @@ -157,22 +169,12 @@ ecma_find_or_create_literal_number (ecma_number_t number_arg) /**< number to be number_list_p->values[i]); JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (value_p) == ECMA_STRING_LITERAL_NUMBER); + JERRY_ASSERT (ecma_is_value_float_number (value_p->u.lit_number)); - if (ecma_is_value_integer_number (num)) + if (ecma_get_float_from_value (value_p->u.lit_number) == number_arg) { - if (value_p->u.lit_number == num) - { - return number_list_p->values[i]; - } - } - else - { - if (ecma_is_value_float_number (value_p->u.lit_number) - && ecma_get_float_from_value (value_p->u.lit_number) == ecma_get_float_from_value (num)) - { - ecma_free_value (num); - return number_list_p->values[i]; - } + ecma_free_value (num); + return value_p->u.lit_number; } } } @@ -190,7 +192,7 @@ ecma_find_or_create_literal_number (ecma_number_t number_arg) /**< number to be if (empty_cpointer_p != NULL) { *empty_cpointer_p = result; - return result; + return num; } ecma_lit_storage_item_t *new_item_p; @@ -205,29 +207,153 @@ ecma_find_or_create_literal_number (ecma_number_t number_arg) /**< number to be JMEM_CP_SET_POINTER (new_item_p->next_cp, JERRY_CONTEXT (number_list_first_p)); JERRY_CONTEXT (number_list_first_p) = new_item_p; - return result; + return num; } /* ecma_find_or_create_literal_number */ /** * Log2 of snapshot literal alignment. */ -#define JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG 2 +#define JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG 1 /** * Snapshot literal alignment. */ #define JERRY_SNAPSHOT_LITERAL_ALIGNMENT (1u << JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG) +/** + * Literal offset shift. + */ +#define JERRY_SNAPSHOT_LITERAL_SHIFT (ECMA_VALUE_SHIFT + 1) + +/** + * Literal value is number. + */ +#define JERRY_SNAPSHOT_LITERAL_IS_NUMBER (1u << ECMA_VALUE_SHIFT) + #ifdef JERRY_ENABLE_SNAPSHOT_SAVE +/** + * Append the value at the end of the appropriate list if it is not present there. + */ +void ecma_save_literals_append_value (ecma_value_t value, /**< value to be appended */ + ecma_collection_header_t *lit_pool_p) /**< list of known values */ +{ + /* Unlike direct numbers, direct strings are converted to character literals. */ + if (!ecma_is_value_string (value) && !ecma_is_value_float_number (value)) + { + return; + } + + ecma_value_t *iterator_p = ecma_collection_iterator_init (lit_pool_p); + + while (iterator_p != NULL) + { + /* Strings / numbers are direct strings or stored in the literal storage. + * Therefore direct comparison is enough to find the same strings / numbers. */ + if (*iterator_p == value) + { + return; + } + + iterator_p = ecma_collection_iterator_next (iterator_p); + } + + ecma_append_to_values_collection (lit_pool_p, value, ECMA_COLLECTION_NO_COPY); +} /* ecma_save_literals_append_value */ + +/** + * Add names from a byte-code data to a list. + */ +void +ecma_save_literals_add_compiled_code (const ecma_compiled_code_t *compiled_code_p, /**< byte-code data */ + ecma_collection_header_t *lit_pool_p) /**< list of known values */ +{ + ecma_value_t *literal_p; + uint32_t argument_end = 0; + uint32_t register_end; + uint32_t const_literal_end; + uint32_t literal_end; + + JERRY_ASSERT (compiled_code_p->status_flags & CBC_CODE_FLAGS_FUNCTION); + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) compiled_code_p; + uint8_t *byte_p = (uint8_t *) compiled_code_p; + + literal_p = (ecma_value_t *) (byte_p + sizeof (cbc_uint16_arguments_t)); + register_end = args_p->register_end; + const_literal_end = args_p->const_literal_end - register_end; + literal_end = args_p->literal_end - register_end; + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_NON_STRICT_ARGUMENTS_NEEDED) + { + argument_end = args_p->argument_end; + } + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) compiled_code_p; + uint8_t *byte_p = (uint8_t *) compiled_code_p; + + literal_p = (ecma_value_t *) (byte_p + sizeof (cbc_uint8_arguments_t)); + register_end = args_p->register_end; + const_literal_end = args_p->const_literal_end - register_end; + literal_end = args_p->literal_end - register_end; + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_NON_STRICT_ARGUMENTS_NEEDED) + { + argument_end = args_p->argument_end; + } + } + + for (uint32_t i = 0; i < argument_end; i++) + { + ecma_save_literals_append_value (literal_p[i], lit_pool_p); + } + + for (uint32_t i = 0; i < const_literal_end; i++) + { + ecma_save_literals_append_value (literal_p[i], lit_pool_p); + } + + for (uint32_t i = const_literal_end; i < literal_end; i++) + { + ecma_compiled_code_t *bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, + literal_p[i]); + + if ((bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION) + && bytecode_p != compiled_code_p) + { + ecma_save_literals_add_compiled_code (bytecode_p, lit_pool_p); + } + } + + if (argument_end != 0) + { + uint8_t *byte_p = (uint8_t *) compiled_code_p; + byte_p += ((size_t) compiled_code_p->size) << JMEM_ALIGNMENT_LOG; + literal_p = ((ecma_value_t *) byte_p) - argument_end; + + for (uint32_t i = 0; i < argument_end; i++) + { + ecma_save_literals_append_value (literal_p[i], lit_pool_p); + } + } +} /* ecma_save_literals_add_compiled_code */ + /** * Save literals to specified snapshot buffer. * + * Note: + * Frees lit_pool_p regardless of success. + * * @return true - if save was performed successfully (i.e. buffer size is sufficient), * false - otherwise */ bool -ecma_save_literals_for_snapshot (uint32_t *buffer_p, /**< [out] output snapshot buffer */ +ecma_save_literals_for_snapshot (ecma_collection_header_t *lit_pool_p, /**< list of known values */ + uint32_t *buffer_p, /**< [out] output snapshot buffer */ size_t buffer_size, /**< size of the buffer */ size_t *in_out_buffer_offset_p, /**< [in,out] write position in the buffer */ lit_mem_to_snapshot_id_map_entry_t **out_map_p, /**< [out] map from literal identifiers @@ -235,145 +361,102 @@ ecma_save_literals_for_snapshot (uint32_t *buffer_p, /**< [out] output snapshot * in snapshot */ uint32_t *out_map_len_p) /**< [out] number of literals */ { - /* Count literals and literal space. */ - uint32_t lit_table_size = sizeof (uint32_t); - uint32_t total_count = 0; - - ecma_lit_storage_item_t *string_list_p = JERRY_CONTEXT (string_list_first_p); - - while (string_list_p != NULL) + if (lit_pool_p->item_count == 0) { - for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) - { - if (string_list_p->values[i] != JMEM_CP_NULL) - { - ecma_string_t *string_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, - string_list_p->values[i]); + *out_map_p = NULL; + *out_map_len_p = 0; + } - lit_table_size += (uint32_t) JERRY_ALIGNUP (sizeof (uint16_t) + ecma_string_get_size (string_p), - JERRY_SNAPSHOT_LITERAL_ALIGNMENT); - total_count++; - } + uint32_t lit_table_size = 0; + size_t max_lit_table_size = buffer_size - *in_out_buffer_offset_p; + + if (max_lit_table_size > (UINT32_MAX >> JERRY_SNAPSHOT_LITERAL_SHIFT)) + { + max_lit_table_size = (UINT32_MAX >> JERRY_SNAPSHOT_LITERAL_SHIFT); + } + + ecma_value_t *iterator_p = ecma_collection_iterator_init (lit_pool_p); + + /* Compute the size of the literal pool. */ + while (iterator_p != NULL) + { + if (ecma_is_value_float_number (*iterator_p)) + { + lit_table_size += (uint32_t) sizeof (ecma_number_t); + } + else + { + ecma_string_t *string_p = ecma_get_string_from_value (*iterator_p); + + lit_table_size += (uint32_t) JERRY_ALIGNUP (sizeof (uint16_t) + ecma_string_get_size (string_p), + JERRY_SNAPSHOT_LITERAL_ALIGNMENT); } - string_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, string_list_p->next_cp); - } - - uint32_t number_offset = lit_table_size; - - ecma_lit_storage_item_t *number_list_p = JERRY_CONTEXT (number_list_first_p); - - while (number_list_p != NULL) - { - for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + /* Check whether enough space is available and the maximum size is not reached. */ + if (lit_table_size > max_lit_table_size) { - if (number_list_p->values[i] != JMEM_CP_NULL) - { - lit_table_size += (uint32_t) sizeof (ecma_number_t); - total_count++; - } + ecma_free_values_collection (lit_pool_p, ECMA_COLLECTION_NO_COPY); + return false; } - number_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, number_list_p->next_cp); - } - - /* Check whether enough space is available. */ - if (*in_out_buffer_offset_p + lit_table_size > buffer_size) - { - return false; - } - - /* Check whether the maximum literal table size is reached. */ - if ((lit_table_size >> JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG) > UINT16_MAX) - { - return false; + iterator_p = ecma_collection_iterator_next (iterator_p); } lit_mem_to_snapshot_id_map_entry_t *map_p; + ecma_length_t total_count = lit_pool_p->item_count; map_p = jmem_heap_alloc_block (total_count * sizeof (lit_mem_to_snapshot_id_map_entry_t)); /* Set return values (no error is possible from here). */ JERRY_ASSERT ((*in_out_buffer_offset_p % sizeof (uint32_t)) == 0); - buffer_p += *in_out_buffer_offset_p / sizeof (uint32_t); + + uint8_t *destination_p = (uint8_t *) (buffer_p + (*in_out_buffer_offset_p / sizeof (uint32_t))); + uint32_t literal_offset = 0; + *in_out_buffer_offset_p += lit_table_size; *out_map_p = map_p; *out_map_len_p = total_count; - /* Write data into the buffer. */ + iterator_p = ecma_collection_iterator_init (lit_pool_p); - /* The zero value is reserved for NULL (no literal) - * constant so the first literal must have offset one. */ - uint32_t literal_offset = JERRY_SNAPSHOT_LITERAL_ALIGNMENT; - - *buffer_p++ = number_offset; - - string_list_p = JERRY_CONTEXT (string_list_first_p); - - uint16_t *destination_p = (uint16_t *) buffer_p; - - while (string_list_p != NULL) + /* Generate literal pool data. */ + while (iterator_p != NULL) { - for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + map_p->literal_id = *iterator_p; + map_p->literal_offset = (literal_offset << JERRY_SNAPSHOT_LITERAL_SHIFT) | ECMA_TYPE_SNAPSHOT_OFFSET; + + ecma_length_t length; + + if (ecma_is_value_float_number (*iterator_p)) { - if (string_list_p->values[i] != JMEM_CP_NULL) - { - map_p->literal_id = string_list_p->values[i]; - map_p->literal_offset = (jmem_cpointer_t) (literal_offset >> JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG); - map_p++; + map_p->literal_offset |= JERRY_SNAPSHOT_LITERAL_IS_NUMBER; - ecma_string_t *string_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, - string_list_p->values[i]); + ecma_number_t num = ecma_get_float_from_value (*iterator_p); + memcpy (destination_p, &num, sizeof (ecma_number_t)); - ecma_length_t length = ecma_string_get_size (string_p); + length = JERRY_ALIGNUP (sizeof (ecma_number_t), JERRY_SNAPSHOT_LITERAL_ALIGNMENT); + } + else + { + ecma_string_t *string_p = ecma_get_string_from_value (*iterator_p); + length = ecma_string_get_size (string_p); - *destination_p = (uint16_t) length; - ecma_string_to_utf8_bytes (string_p, ((lit_utf8_byte_t *) destination_p) + sizeof (uint16_t), length); + *(uint16_t *) destination_p = (uint16_t) length; - length = JERRY_ALIGNUP (sizeof (uint16_t) + length, - JERRY_SNAPSHOT_LITERAL_ALIGNMENT); + ecma_string_to_utf8_bytes (string_p, destination_p + sizeof (uint16_t), length); - JERRY_ASSERT ((length % sizeof (uint16_t)) == 0); - destination_p += length / sizeof (uint16_t); - literal_offset += length; - } + length = JERRY_ALIGNUP (sizeof (uint16_t) + length, JERRY_SNAPSHOT_LITERAL_ALIGNMENT); } - string_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, string_list_p->next_cp); - } - - number_list_p = JERRY_CONTEXT (number_list_first_p); - - while (number_list_p != NULL) - { - for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) - { - if (number_list_p->values[i] != JMEM_CP_NULL) - { - map_p->literal_id = number_list_p->values[i]; - map_p->literal_offset = (jmem_cpointer_t) (literal_offset >> JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG); - map_p++; - - ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, - number_list_p->values[i]); - - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (value_p) == ECMA_STRING_LITERAL_NUMBER); - - ecma_number_t num = ecma_get_number_from_value (value_p->u.lit_number); - memcpy (destination_p, &num, sizeof (ecma_number_t)); - - ecma_length_t length = JERRY_ALIGNUP (sizeof (ecma_number_t), - JERRY_SNAPSHOT_LITERAL_ALIGNMENT); - - JERRY_ASSERT ((length % sizeof (uint16_t)) == 0); - destination_p += length / sizeof (uint16_t); - literal_offset += length; - } - } - - number_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, number_list_p->next_cp); + JERRY_ASSERT ((length % sizeof (uint16_t)) == 0); + destination_p += length; + literal_offset += length; + + iterator_p = ecma_collection_iterator_next (iterator_p); + map_p++; } + ecma_free_values_collection (lit_pool_p, ECMA_COLLECTION_NO_COPY); return true; } /* ecma_save_literals_for_snapshot */ @@ -381,38 +464,20 @@ ecma_save_literals_for_snapshot (uint32_t *buffer_p, /**< [out] output snapshot #if defined JERRY_ENABLE_SNAPSHOT_EXEC || defined JERRY_ENABLE_SNAPSHOT_SAVE -/** - * Computes the base pointer of the literals and starting offset of numbers. - * - * @return the base pointer of the literals - */ -const uint8_t * -ecma_snapshot_get_literals_base (uint32_t *buffer_p, /**< literal buffer start */ - const uint8_t **number_base_p) /**< [out] literal number start */ -{ - *number_base_p = ((uint8_t *) buffer_p) + buffer_p[0]; - - return ((uint8_t *) (buffer_p + 1)) - JERRY_SNAPSHOT_LITERAL_ALIGNMENT; -} /* ecma_snapshot_get_literals_base */ - /** * Get the compressed pointer of a given literal. * * @return literal compressed pointer */ -jmem_cpointer_t +ecma_value_t ecma_snapshot_get_literal (const uint8_t *literal_base_p, /**< literal start */ - const uint8_t *number_base_p, /**< literal number start */ - jmem_cpointer_t offset) + ecma_value_t literal_value) /**< string / number offset */ { - if (offset == 0) - { - return ECMA_NULL_POINTER; - } + JERRY_ASSERT ((literal_value & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_SNAPSHOT_OFFSET); - const uint8_t *literal_p = literal_base_p + (((size_t) offset) << JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG); + const uint8_t *literal_p = literal_base_p + (literal_value >> JERRY_SNAPSHOT_LITERAL_SHIFT); - if (literal_p >= number_base_p) + if (literal_value & JERRY_SNAPSHOT_LITERAL_IS_NUMBER) { ecma_number_t num; memcpy (&num, literal_p, sizeof (ecma_number_t)); diff --git a/jerry-core/ecma/base/ecma-literal-storage.h b/jerry-core/ecma/base/ecma-literal-storage.h index ec6469101..814da6049 100644 --- a/jerry-core/ecma/base/ecma-literal-storage.h +++ b/jerry-core/ecma/base/ecma-literal-storage.h @@ -27,32 +27,34 @@ * @{ */ +#ifdef JERRY_ENABLE_SNAPSHOT_SAVE /** * Snapshot literal - offset map */ typedef struct { - jmem_cpointer_t literal_id; /**< literal id */ - jmem_cpointer_t literal_offset; /**< literal offset */ + ecma_value_t literal_id; /**< literal id */ + ecma_value_t literal_offset; /**< literal offset */ } lit_mem_to_snapshot_id_map_entry_t; +#endif /* JERRY_ENABLE_SNAPSHOT_SAVE */ void ecma_finalize_lit_storage (void); -jmem_cpointer_t ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p, lit_utf8_size_t size); -jmem_cpointer_t ecma_find_or_create_literal_number (ecma_number_t number_arg); +ecma_value_t ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p, lit_utf8_size_t size); +ecma_value_t ecma_find_or_create_literal_number (ecma_number_t number_arg); #ifdef JERRY_ENABLE_SNAPSHOT_SAVE -bool -ecma_save_literals_for_snapshot (uint32_t *buffer_p, size_t buffer_size, size_t *in_out_buffer_offset_p, - lit_mem_to_snapshot_id_map_entry_t **out_map_p, uint32_t *out_map_len_p); +void ecma_save_literals_append_value (ecma_value_t value, ecma_collection_header_t *lit_pool_p); +void ecma_save_literals_add_compiled_code (const ecma_compiled_code_t *compiled_code_p, + ecma_collection_header_t *lit_pool_p); +bool ecma_save_literals_for_snapshot (ecma_collection_header_t *lit_pool_p, uint32_t *buffer_p, size_t buffer_size, + size_t *in_out_buffer_offset_p, lit_mem_to_snapshot_id_map_entry_t **out_map_p, + uint32_t *out_map_len_p); #endif /* JERRY_ENABLE_SNAPSHOT_SAVE */ #if defined JERRY_ENABLE_SNAPSHOT_EXEC || defined JERRY_ENABLE_SNAPSHOT_SAVE -const uint8_t * -ecma_snapshot_get_literals_base (uint32_t *buffer_p, const uint8_t **number_base_p); -jmem_cpointer_t -ecma_snapshot_get_literal (const uint8_t *literal_base_p, const uint8_t *number_base_p, - jmem_cpointer_t offset); +ecma_value_t +ecma_snapshot_get_literal (const uint8_t *literal_base_p, ecma_value_t literal_value); #endif /* JERRY_ENABLE_SNAPSHOT_EXEC || JERRY_ENABLE_SNAPSHOT_SAVE */ /** diff --git a/jerry-core/ecma/base/ecma-property-hashmap.c b/jerry-core/ecma/base/ecma-property-hashmap.c index d9c0047d1..716825968 100644 --- a/jerry-core/ecma/base/ecma-property-hashmap.c +++ b/jerry-core/ecma/base/ecma-property-hashmap.c @@ -275,7 +275,7 @@ ecma_property_hashmap_insert (ecma_object_t *object_p, /**< object */ JERRY_ASSERT (property_index < ECMA_PROPERTY_PAIR_ITEM_COUNT); - uint32_t entry_index = name_p->hash; + uint32_t entry_index = ecma_string_hash (name_p); uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)]; uint32_t mask = hashmap_p->max_property_count - 1; @@ -471,7 +471,7 @@ ecma_property_hashmap_find (ecma_property_hashmap_t *hashmap_p, /**< hashmap */ } #endif /* !JERRY_NDEBUG */ - uint32_t entry_index = name_p->hash; + uint32_t entry_index = ecma_string_hash (name_p); uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)]; uint32_t mask = hashmap_p->max_property_count - 1; jmem_cpointer_t *pair_list_p = (jmem_cpointer_t *) (hashmap_p + 1); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.c b/jerry-core/ecma/builtin-objects/ecma-builtins.c index b116b6cd1..33014d1ab 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.c @@ -761,9 +761,7 @@ ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in if (!(*bitset_p & bit_for_index) || ecma_op_object_has_own_property (object_p, name_p)) { - ecma_append_to_values_collection (for_non_enumerable_p, - ecma_make_string_value (name_p), - 0); + ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p), 0); } ecma_deref_ecma_string (name_p); diff --git a/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.c b/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.c index b633503e7..6b09a71e5 100644 --- a/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.c +++ b/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.c @@ -736,11 +736,10 @@ ecma_builtin_typedarray_prototype_set (ecma_value_t this_arg, /**< this argument while (k < source_length_uint32 && ecma_is_value_empty (ret_val)) { - ecma_string_t k_str; - ecma_init_ecma_string_from_uint32 (&k_str, k); + ecma_string_t *k_str_p = ecma_new_ecma_string_from_uint32 (k); ECMA_TRY_CATCH (elem, - ecma_op_object_get (source_obj_p, &k_str), + ecma_op_object_get (source_obj_p, k_str_p), ret_val); ECMA_OP_TO_NUMBER_TRY_CATCH (elem_num, elem, ret_val); @@ -750,6 +749,8 @@ ecma_builtin_typedarray_prototype_set (ecma_value_t this_arg, /**< this argument ECMA_OP_TO_NUMBER_FINALIZE (elem_num); ECMA_FINALIZE (elem); + ecma_deref_ecma_string (k_str_p); + k++; target_byte_index += element_size; } diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index 72f5aa83b..8ae4401cf 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -749,12 +749,11 @@ ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< ecma_object_t *proto_object_p = ecma_op_create_object_object_noarg (); /* 17. */ - ecma_string_t magic_string_constructor; - ecma_init_ecma_magic_string (&magic_string_constructor, LIT_MAGIC_STRING_CONSTRUCTOR); + ecma_string_t *magic_string_constructor_p = ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR); ecma_property_value_t *constructor_prop_value_p; constructor_prop_value_p = ecma_create_named_data_property (proto_object_p, - &magic_string_constructor, + magic_string_constructor_p, ECMA_PROPERTY_CONFIGURABLE_WRITABLE, NULL); diff --git a/jerry-core/ecma/operations/ecma-jobqueue.c b/jerry-core/ecma/operations/ecma-jobqueue.c index f6c20be99..8e33369cb 100644 --- a/jerry-core/ecma/operations/ecma-jobqueue.c +++ b/jerry-core/ecma/operations/ecma-jobqueue.c @@ -233,15 +233,16 @@ ecma_process_promise_resolve_thenable_job (void *obj_p) /**< the job to be opera ecma_job_promise_resolve_thenable_t *job_p = (ecma_job_promise_resolve_thenable_t *) obj_p; ecma_object_t *promise_p = ecma_get_object_from_value (job_p->promise); ecma_promise_resolving_functions_t *funcs = ecma_promise_create_resolving_functions (promise_p); - ecma_string_t str_resolve, str_reject; - ecma_init_ecma_magic_string (&str_resolve, LIT_INTERNAL_MAGIC_STRING_RESOLVE_FUNCTION); - ecma_init_ecma_magic_string (&str_reject, LIT_INTERNAL_MAGIC_STRING_REJECT_FUNCTION); + + ecma_string_t *str_resolve_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_RESOLVE_FUNCTION); + ecma_string_t *str_reject_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_REJECT_FUNCTION); + ecma_op_object_put (promise_p, - &str_resolve, + str_resolve_p, funcs->resolve, false); ecma_op_object_put (promise_p, - &str_reject, + str_reject_p, funcs->reject, false); diff --git a/jerry-core/ecma/operations/ecma-objects-arguments.c b/jerry-core/ecma/operations/ecma-objects-arguments.c index d55fbf5c3..3fd35219a 100644 --- a/jerry-core/ecma/operations/ecma-objects-arguments.c +++ b/jerry-core/ecma/operations/ecma-objects-arguments.c @@ -51,23 +51,18 @@ ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function bool is_strict = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0; ecma_length_t formal_params_number; - jmem_cpointer_t *literal_p; if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) { cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p; - uint8_t *byte_p = (uint8_t *) bytecode_data_p; formal_params_number = args_p->argument_end; - literal_p = (jmem_cpointer_t *) (byte_p + sizeof (cbc_uint16_arguments_t)); } else { cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p; - uint8_t *byte_p = (uint8_t *) bytecode_data_p; formal_params_number = args_p->argument_end; - literal_p = (jmem_cpointer_t *) (byte_p + sizeof (cbc_uint8_arguments_t)); } ecma_object_t *prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); @@ -76,7 +71,7 @@ ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function if (!is_strict && arguments_number > 0 && formal_params_number > 0) { - size_t formal_params_size = formal_params_number * sizeof (jmem_cpointer_t); + size_t formal_params_size = formal_params_number * sizeof (ecma_value_t); obj_p = ecma_create_object (prototype_p, sizeof (ecma_extended_object_t) + formal_params_size, @@ -90,15 +85,19 @@ ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function ext_object_p->u.pseudo_array.u1.length = (uint16_t) formal_params_number; - jmem_cpointer_t *arg_Literal_p = (jmem_cpointer_t *) (ext_object_p + 1); + ecma_value_t *arg_Literal_p = (ecma_value_t *) (ext_object_p + 1); - memcpy (arg_Literal_p, literal_p, formal_params_size); + uint8_t *byte_p = (uint8_t *) bytecode_data_p; + byte_p += ((size_t) bytecode_data_p->size) << JMEM_ALIGNMENT_LOG; + byte_p -= formal_params_size; + + memcpy (arg_Literal_p, byte_p, formal_params_size); for (ecma_length_t i = 0; i < formal_params_number; i++) { - if (arg_Literal_p[i] != JMEM_CP_NULL) + if (arg_Literal_p[i] != ECMA_VALUE_EMPTY) { - ecma_string_t *name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, arg_Literal_p[i]); + ecma_string_t *name_p = ecma_get_string_from_value (arg_Literal_p[i]); ecma_ref_ecma_string (name_p); } } @@ -270,20 +269,20 @@ ecma_op_arguments_object_define_own_property (ecma_object_t *object_p, /**< the return ret_value; } - jmem_cpointer_t *arg_Literal_p = (jmem_cpointer_t *) (ext_object_p + 1); + ecma_value_t *arg_Literal_p = (ecma_value_t *) (ext_object_p + 1); - if (arg_Literal_p[index] == JMEM_CP_NULL) + if (arg_Literal_p[index] == ECMA_VALUE_EMPTY) { return ret_value; } - ecma_string_t *name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, arg_Literal_p[index]); + ecma_string_t *name_p = ecma_get_string_from_value (arg_Literal_p[index]); if (property_desc_p->is_get_defined || property_desc_p->is_set_defined) { ecma_deref_ecma_string (name_p); - arg_Literal_p[index] = JMEM_CP_NULL; + arg_Literal_p[index] = ECMA_VALUE_EMPTY; } else { @@ -305,7 +304,7 @@ ecma_op_arguments_object_define_own_property (ecma_object_t *object_p, /**< the && !property_desc_p->is_writable) { ecma_deref_ecma_string (name_p); - arg_Literal_p[index] = JMEM_CP_NULL; + arg_Literal_p[index] = ECMA_VALUE_EMPTY; } } @@ -347,13 +346,13 @@ ecma_op_arguments_object_delete (ecma_object_t *object_p, /**< the object */ if (index < ext_object_p->u.pseudo_array.u1.length) { - jmem_cpointer_t *arg_Literal_p = (jmem_cpointer_t *) (ext_object_p + 1); + ecma_value_t *arg_Literal_p = (ecma_value_t *) (ext_object_p + 1); - if (arg_Literal_p[index] != JMEM_CP_NULL) + if (arg_Literal_p[index] != ECMA_VALUE_EMPTY) { - ecma_string_t *name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, arg_Literal_p[index]); + ecma_string_t *name_p = ecma_get_string_from_value (arg_Literal_p[index]); ecma_deref_ecma_string (name_p); - arg_Literal_p[index] = JMEM_CP_NULL; + arg_Literal_p[index] = ECMA_VALUE_EMPTY; } } } diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c index cd296f8d6..5c80a0f86 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -142,9 +142,11 @@ ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */ /* ES2015 9.4.5.1 */ if (ecma_is_typedarray (ecma_make_object_value (object_p))) { - if (ECMA_STRING_GET_CONTAINER (property_name_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + uint32_t array_index = ecma_string_get_array_index (property_name_p); + + if (array_index != ECMA_STRING_NOT_ARRAY_INDEX) { - ecma_value_t value = ecma_op_typedarray_get_index_prop (object_p, property_name_p->u.uint32_number); + ecma_value_t value = ecma_op_typedarray_get_index_prop (object_p, array_index); if (!ecma_is_value_undefined (value)) { @@ -269,12 +271,11 @@ ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */ { if (index < ext_object_p->u.pseudo_array.u1.length) { - jmem_cpointer_t *arg_Literal_p = (jmem_cpointer_t *) (ext_object_p + 1); + ecma_value_t *arg_Literal_p = (ecma_value_t *) (ext_object_p + 1); - if (arg_Literal_p[index] != JMEM_CP_NULL) + if (arg_Literal_p[index] != ECMA_VALUE_EMPTY) { - ecma_string_t *arg_name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, - arg_Literal_p[index]); + ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_Literal_p[index]); ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, ext_object_p->u.pseudo_array.u2.lex_env_cp); @@ -462,12 +463,11 @@ ecma_op_object_find_own (ecma_value_t base_value, /**< base value */ { if (index < ext_object_p->u.pseudo_array.u1.length) { - jmem_cpointer_t *arg_Literal_p = (jmem_cpointer_t *) (ext_object_p + 1); + ecma_value_t *arg_Literal_p = (ecma_value_t *) (ext_object_p + 1); - if (arg_Literal_p[index] != JMEM_CP_NULL) + if (arg_Literal_p[index] != ECMA_VALUE_EMPTY) { - ecma_string_t *arg_name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, - arg_Literal_p[index]); + ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_Literal_p[index]); ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, ext_object_p->u.pseudo_array.u2.lex_env_cp); @@ -484,9 +484,11 @@ ecma_op_object_find_own (ecma_value_t base_value, /**< base value */ /* ES2015 9.4.5.4 */ if (ecma_is_typedarray (ecma_make_object_value (object_p))) { - if (ECMA_STRING_GET_CONTAINER (property_name_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + uint32_t array_index = ecma_string_get_array_index (property_name_p); + + if (array_index != ECMA_STRING_NOT_ARRAY_INDEX) { - return ecma_op_typedarray_get_index_prop (object_p, property_name_p->u.uint32_number); + return ecma_op_typedarray_get_index_prop (object_p, array_index); } ecma_number_t num = ecma_string_to_number (property_name_p); @@ -722,36 +724,11 @@ ecma_op_object_get (ecma_object_t *object_p, /**< the object */ * @return ecma value * Returned value must be freed with ecma_free_value */ -ecma_value_t +inline ecma_value_t __attr_always_inline___ ecma_op_object_get_by_magic_id (ecma_object_t *object_p, /**< the object */ lit_magic_string_id_t property_id) /**< property magic string id */ { - /* Circular reference is possible in JavaScript and testing it is complicated. */ - int max_depth = ECMA_PROPERTY_SEARCH_DEPTH_LIMIT; - - ecma_string_t property_name; - ecma_init_ecma_magic_string (&property_name, property_id); - - ecma_value_t base_value = ecma_make_object_value (object_p); - do - { - ecma_value_t value = ecma_op_object_find_own (base_value, object_p, &property_name); - - if (ecma_is_value_found (value)) - { - return value; - } - - if (--max_depth == 0) - { - break; - } - - object_p = ecma_get_object_prototype (object_p); - } - while (object_p != NULL); - - return ECMA_VALUE_UNDEFINED; + return ecma_op_object_get (object_p, ecma_get_magic_string (property_id)); } /* ecma_op_object_get_by_magic_id */ /** @@ -814,12 +791,11 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */ { if (index < ext_object_p->u.pseudo_array.u1.length) { - jmem_cpointer_t *arg_Literal_p = (jmem_cpointer_t *) (ext_object_p + 1); + ecma_value_t *arg_Literal_p = (ecma_value_t *) (ext_object_p + 1); - if (arg_Literal_p[index] != JMEM_CP_NULL) + if (arg_Literal_p[index] != ECMA_VALUE_EMPTY) { - ecma_string_t *arg_name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, - arg_Literal_p[index]); + ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_Literal_p[index]); ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, ext_object_p->u.pseudo_array.u2.lex_env_cp); @@ -837,9 +813,11 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */ /* ES2015 9.4.5.5 */ if (ecma_is_typedarray (ecma_make_object_value (object_p))) { - if (ECMA_STRING_GET_CONTAINER (property_name_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + uint32_t array_index = ecma_string_get_array_index (property_name_p); + + if (array_index != ECMA_STRING_NOT_ARRAY_INDEX) { - bool set_status = ecma_op_typedarray_set_index_prop (object_p, property_name_p->u.uint32_number, value); + bool set_status = ecma_op_typedarray_set_index_prop (object_p, array_index, value); if (set_status) { @@ -1179,10 +1157,12 @@ ecma_op_object_define_own_property (ecma_object_t *obj_p, /**< the object */ /* ES2015 9.4.5.3 */ if (ecma_is_typedarray (ecma_make_object_value (obj_p))) { - if (ECMA_STRING_GET_CONTAINER (property_name_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) + uint32_t array_index = ecma_string_get_array_index (property_name_p); + + if (array_index != ECMA_STRING_NOT_ARRAY_INDEX) { bool define_status = ecma_op_typedarray_define_index_prop (obj_p, - property_name_p->u.uint32_number, + array_index, property_desc_p); if (define_status) @@ -1492,7 +1472,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ ecma_string_t *name_p = ecma_get_string_from_value (*ecma_value_p); ecma_value_p = ecma_collection_iterator_next (ecma_value_p); - uint8_t hash = (uint8_t) name_p->hash; + uint8_t hash = (uint8_t) ecma_string_hash (name_p); uint32_t bitmap_row = (uint32_t) (hash / bitmap_row_size); uint32_t bitmap_column = (uint32_t) (hash % bitmap_row_size); @@ -1523,7 +1503,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ { ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; - if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_STRING_CONTAINER_MAGIC_STRING + if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC && prop_pair_p->names_cp[i] >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT) { /* Internal properties are never enumerated. */ @@ -1535,7 +1515,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ if (!(is_enumerable_only && !ecma_is_property_enumerable (*property_p))) { - uint8_t hash = (uint8_t) name_p->hash; + uint8_t hash = (uint8_t) ecma_string_hash (name_p); uint32_t bitmap_row = (uint32_t) (hash / bitmap_row_size); uint32_t bitmap_column = (uint32_t) (hash % bitmap_row_size); @@ -1691,7 +1671,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ ecma_string_t *name_p = names_p[i]; - uint8_t hash = (uint8_t) name_p->hash; + uint8_t hash = (uint8_t) ecma_string_hash (name_p); uint32_t bitmap_row = (uint32_t) (hash / bitmap_row_size); uint32_t bitmap_column = (uint32_t) (hash % bitmap_row_size); diff --git a/jerry-core/ecma/operations/ecma-promise-object.c b/jerry-core/ecma/operations/ecma-promise-object.c index 161e7403c..e84d9e85f 100644 --- a/jerry-core/ecma/operations/ecma-promise-object.c +++ b/jerry-core/ecma/operations/ecma-promise-object.c @@ -232,17 +232,16 @@ ecma_promise_reject_handler (const ecma_value_t function, /**< the function itse { JERRY_UNUSED (this); - ecma_string_t str_promise; - ecma_string_t str_already_resolved; - ecma_init_ecma_magic_string (&str_promise, LIT_INTERNAL_MAGIC_STRING_PROMISE); - ecma_init_ecma_magic_string (&str_already_resolved, LIT_INTERNAL_MAGIC_STRING_ALREADY_RESOLVED); + ecma_string_t *str_promise_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE); + ecma_string_t *str_already_resolved_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ALREADY_RESOLVED); + ecma_object_t *function_p = ecma_get_object_from_value (function); /* 2. */ - ecma_value_t promise = ecma_op_object_get (function_p, &str_promise); + ecma_value_t promise = ecma_op_object_get (function_p, str_promise_p); /* 1. */ JERRY_ASSERT (ecma_is_promise (ecma_get_object_from_value (promise))); /* 3. */ - ecma_value_t already_resolved = ecma_op_object_get (function_p, &str_already_resolved); + ecma_value_t already_resolved = ecma_op_object_get (function_p, str_already_resolved_p); /* 4. */ if (ecma_get_already_resolved_bool_value (already_resolved)) @@ -278,17 +277,16 @@ ecma_promise_resolve_handler (const ecma_value_t function, /**< the function its { JERRY_UNUSED (this); - ecma_string_t str_promise; - ecma_string_t str_already_resolved; - ecma_init_ecma_magic_string (&str_promise, LIT_INTERNAL_MAGIC_STRING_PROMISE); - ecma_init_ecma_magic_string (&str_already_resolved, LIT_INTERNAL_MAGIC_STRING_ALREADY_RESOLVED); + ecma_string_t *str_promise_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE); + ecma_string_t *str_already_resolved_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ALREADY_RESOLVED); + ecma_object_t *function_p = ecma_get_object_from_value (function); /* 2. */ - ecma_value_t promise = ecma_op_object_get (function_p, &str_promise); + ecma_value_t promise = ecma_op_object_get (function_p, str_promise_p); /* 1. */ JERRY_ASSERT (ecma_is_promise (ecma_get_object_from_value (promise))); /* 3. */ - ecma_value_t already_resolved = ecma_op_object_get (function_p, &str_already_resolved); + ecma_value_t already_resolved = ecma_op_object_get (function_p, str_already_resolved_p); /* 4. */ if (ecma_get_already_resolved_bool_value (already_resolved)) @@ -430,22 +428,21 @@ ecma_promise_create_resolving_functions (ecma_object_t *object_p) /**< the promi /* 1. */ ecma_value_t already_resolved = ecma_op_create_boolean_object (ecma_make_boolean_value (false)); - ecma_string_t str_promise; - ecma_string_t str_already_resolved; - ecma_init_ecma_magic_string (&str_promise, LIT_INTERNAL_MAGIC_STRING_PROMISE); - ecma_init_ecma_magic_string (&str_already_resolved, LIT_INTERNAL_MAGIC_STRING_ALREADY_RESOLVED); + ecma_string_t *str_promise_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_PROMISE); + ecma_string_t *str_already_resolved_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ALREADY_RESOLVED); + /* 2. */ ecma_object_t *resolve_p; resolve_p = ecma_op_create_external_function_object (ecma_promise_resolve_handler); /* 3. */ ecma_op_object_put (resolve_p, - &str_promise, + str_promise_p, ecma_make_object_value (object_p), false); /* 4. */ ecma_op_object_put (resolve_p, - &str_already_resolved, + str_already_resolved_p, already_resolved, false); /* 5. */ @@ -453,12 +450,12 @@ ecma_promise_create_resolving_functions (ecma_object_t *object_p) /**< the promi reject_p = ecma_op_create_external_function_object (ecma_promise_reject_handler); /* 6. */ ecma_op_object_put (reject_p, - &str_promise, + str_promise_p, ecma_make_object_value (object_p), false); /* 7. */ ecma_op_object_put (reject_p, - &str_already_resolved, + str_already_resolved_p, already_resolved, false); @@ -516,15 +513,15 @@ ecma_op_create_promise_object (ecma_value_t executor, /**< the executor function /* 8. */ ecma_promise_resolving_functions_t *funcs = ecma_promise_create_resolving_functions (object_p); - ecma_string_t str_resolve, str_reject; - ecma_init_ecma_magic_string (&str_resolve, LIT_INTERNAL_MAGIC_STRING_RESOLVE_FUNCTION); - ecma_init_ecma_magic_string (&str_reject, LIT_INTERNAL_MAGIC_STRING_REJECT_FUNCTION); + ecma_string_t *str_resolve_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_RESOLVE_FUNCTION); + ecma_string_t *str_reject_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_REJECT_FUNCTION); + ecma_op_object_put (object_p, - &str_resolve, + str_resolve_p, funcs->resolve, false); ecma_op_object_put (object_p, - &str_reject, + str_reject_p, funcs->reject, false); diff --git a/jerry-core/ecma/operations/ecma-regexp-object.c b/jerry-core/ecma/operations/ecma-regexp-object.c index 172b8019e..d37f63e8c 100644 --- a/jerry-core/ecma/operations/ecma-regexp-object.c +++ b/jerry-core/ecma/operations/ecma-regexp-object.c @@ -239,7 +239,7 @@ ecma_op_create_regexp_object_from_bytecode (re_compiled_code_t *bytecode_p) /**< /* Initialize RegExp object properties */ re_initialize_props (object_p, - ECMA_GET_NON_NULL_POINTER (ecma_string_t, bytecode_p->pattern_cp), + ecma_get_string_from_value (bytecode_p->pattern), bytecode_p->header.status_flags); return ecma_make_object_value (object_p); diff --git a/jerry-core/parser/js/byte-code.h b/jerry-core/parser/js/byte-code.h index 99ab5f9f8..58531f057 100644 --- a/jerry-core/parser/js/byte-code.h +++ b/jerry-core/parser/js/byte-code.h @@ -637,9 +637,7 @@ typedef struct uint16_t ident_end; /**< end position of the identifier group */ uint16_t const_literal_end; /**< end position of the const literal group */ uint16_t literal_end; /**< end position of the literal group */ -#ifdef JERRY_CPOINTER_32_BIT uint16_t padding; /**< an unused value */ -#endif } cbc_uint16_arguments_t; /** @@ -652,9 +650,10 @@ typedef enum CBC_CODE_FLAGS_UINT16_ARGUMENTS = (1u << 2), /**< compiled code data is cbc_uint16_arguments_t */ CBC_CODE_FLAGS_STRICT_MODE = (1u << 3), /**< strict mode is enabled */ CBC_CODE_FLAGS_ARGUMENTS_NEEDED = (1u << 4), /**< arguments object must be constructed */ - CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED = (1u << 5), /**< no need to create a lexical environment */ - CBC_CODE_FLAGS_DEBUGGER_IGNORE = (1u << 6), /**< this function should be ignored by debugger */ + CBC_CODE_FLAGS_NON_STRICT_ARGUMENTS_NEEDED = (1u << 5), /**< non-strict arguments object must be constructed */ + CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED = (1u << 6), /**< no need to create a lexical environment */ CBC_CODE_FLAGS_ARROW_FUNCTION = (1u << 7), /**< this function is an arrow function */ + CBC_CODE_FLAGS_DEBUGGER_IGNORE = (1u << 8), /**< this function should be ignored by debugger */ } cbc_code_flags; #define CBC_OPCODE(arg1, arg2, arg3, arg4) arg1, diff --git a/jerry-core/parser/js/common.c b/jerry-core/parser/js/common.c index 9c31333f4..52e68a47d 100644 --- a/jerry-core/parser/js/common.c +++ b/jerry-core/parser/js/common.c @@ -107,12 +107,8 @@ util_print_literal (lexer_literal_t *literal_p) /**< literal */ } else if (literal_p->type == LEXER_NUMBER_LITERAL) { - ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, literal_p->u.value); - - JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (value_p) == ECMA_STRING_LITERAL_NUMBER); - JERRY_DEBUG_MSG ("number("); - util_print_number (ecma_get_number_from_value (value_p->u.lit_number)); + util_print_number (ecma_get_number_from_value (literal_p->u.value)); } else if (literal_p->type == LEXER_REGEXP_LITERAL) { diff --git a/jerry-core/parser/js/common.h b/jerry-core/parser/js/common.h index 6829d0a3f..d22841d7c 100644 --- a/jerry-core/parser/js/common.h +++ b/jerry-core/parser/js/common.h @@ -81,7 +81,7 @@ typedef struct { union { - jmem_cpointer_t value; /**< literal value (not processed by the parser) */ + ecma_value_t value; /**< literal value (not processed by the parser) */ const uint8_t *char_p; /**< character value */ ecma_compiled_code_t *bytecode_p; /**< compiled function or regexp pointer */ uint32_t source_data; /**< encoded source literal */ diff --git a/jerry-core/parser/js/js-lexer.c b/jerry-core/parser/js/js-lexer.c index e271fd3da..c7a95b4c5 100644 --- a/jerry-core/parser/js/js-lexer.c +++ b/jerry-core/parser/js/js-lexer.c @@ -1759,13 +1759,13 @@ lexer_construct_number_object (parser_context_t *context_p, /**< context */ num = -num; } - jmem_cpointer_t lit_cp = ecma_find_or_create_literal_number (num); + ecma_value_t lit_value = ecma_find_or_create_literal_number (num); parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)) != NULL) { if (literal_p->type == LEXER_NUMBER_LITERAL - && literal_p->u.value == lit_cp) + && literal_p->u.value == lit_value) { context_p->lit_object.literal_p = literal_p; context_p->lit_object.index = (uint16_t) literal_index; @@ -1790,7 +1790,7 @@ lexer_construct_number_object (parser_context_t *context_p, /**< context */ context_p->literal_count++; - literal_p->u.value = lit_cp; + literal_p->u.value = lit_value; literal_p->type = LEXER_NUMBER_LITERAL; context_p->lit_object.literal_p = literal_p; diff --git a/jerry-core/parser/js/js-parser.c b/jerry-core/parser/js/js-parser.c index d8e48897b..b459556ba 100644 --- a/jerry-core/parser/js/js-parser.c +++ b/jerry-core/parser/js/js-parser.c @@ -534,7 +534,7 @@ parser_encode_literal (uint8_t *dst_p, /**< destination buffer */ static uint8_t * parser_generate_initializers (parser_context_t *context_p, /**< context */ uint8_t *dst_p, /**< destination buffer */ - jmem_cpointer_t *literal_pool_p, /**< start of literal pool */ + ecma_value_t *literal_pool_p, /**< start of literal pool */ uint16_t uninitialized_var_end, /**< end of the uninitialized var group */ uint16_t initialized_var_end, /**< end of the initialized var group */ uint16_t const_literal_end, /**< end of the const literal group */ @@ -543,7 +543,7 @@ parser_generate_initializers (parser_context_t *context_p, /**< context */ { parser_list_iterator_t literal_iterator; lexer_literal_t *literal_p; - uint16_t argument_count; + uint16_t argument_count, register_count; if (uninitialized_var_end > context_p->register_count) { @@ -618,6 +618,7 @@ parser_generate_initializers (parser_context_t *context_p, /**< context */ parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); argument_count = 0; + register_count = context_p->register_count; while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator))) { @@ -628,35 +629,42 @@ parser_generate_initializers (parser_context_t *context_p, /**< context */ if (literal_p->type == LEXER_IDENT_LITERAL || literal_p->type == LEXER_STRING_LITERAL) { + if (literal_p->prop.index >= register_count) + { #ifdef PARSER_DUMP_BYTE_CODE - if (!(literal_p->status_flags & LEXER_FLAG_UNUSED_IDENT)) - { - jmem_cpointer_t lit_cp = ecma_find_or_create_literal_string (literal_p->u.char_p, - literal_p->prop.length); - literal_pool_p[literal_p->prop.index] = lit_cp; - } + if (!(literal_p->status_flags & LEXER_FLAG_UNUSED_IDENT)) + { + ecma_value_t lit_value = ecma_find_or_create_literal_string (literal_p->u.char_p, + literal_p->prop.length); + literal_pool_p[literal_p->prop.index] = lit_value; + } - if (!context_p->is_show_opcodes - && !(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR)) - { - jmem_heap_free_block ((void *) literal_p->u.char_p, literal_p->prop.length); - } + if (!context_p->is_show_opcodes + && !(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR)) + { + jmem_heap_free_block ((void *) literal_p->u.char_p, literal_p->prop.length); + } #else /* !PARSER_DUMP_BYTE_CODE */ - if (!(literal_p->status_flags & LEXER_FLAG_UNUSED_IDENT)) - { - literal_pool_p[literal_p->prop.index] = literal_p->u.value; - } + if (!(literal_p->status_flags & LEXER_FLAG_UNUSED_IDENT)) + { + literal_pool_p[literal_p->prop.index] = literal_p->u.value; + } #endif /* PARSER_DUMP_BYTE_CODE */ + } } else if ((literal_p->type == LEXER_FUNCTION_LITERAL) || (literal_p->type == LEXER_REGEXP_LITERAL)) { - ECMA_SET_NON_NULL_POINTER (literal_pool_p[literal_p->prop.index], - literal_p->u.bytecode_p); + JERRY_ASSERT (literal_p->prop.index >= register_count); + + ECMA_SET_INTERNAL_VALUE_POINTER (literal_pool_p[literal_p->prop.index], + literal_p->u.bytecode_p); } else { - JERRY_ASSERT (literal_p->type == LEXER_NUMBER_LITERAL); + JERRY_ASSERT (literal_p->type == LEXER_NUMBER_LITERAL + && literal_p->prop.index >= register_count); + literal_pool_p[literal_p->prop.index] = literal_p->u.value; } } @@ -692,9 +700,12 @@ parser_generate_initializers (parser_context_t *context_p, /**< context */ JERRY_ASSERT (literal_p != NULL && literal_p->type == LEXER_FUNCTION_LITERAL); + init_index = literal_p->prop.index; - ECMA_SET_NON_NULL_POINTER (literal_pool_p[literal_p->prop.index], - literal_p->u.bytecode_p); + JERRY_ASSERT (init_index >= register_count); + + ECMA_SET_INTERNAL_VALUE_POINTER (literal_pool_p[init_index], + literal_p->u.bytecode_p); } *dst_p++ = CBC_INITIALIZE_VAR; @@ -1216,7 +1227,12 @@ parse_print_final_cbc (ecma_compiled_code_t *compiled_code_p, /**< compiled code byte_code_start_p += sizeof (cbc_uint8_arguments_t); } - byte_code_start_p += literal_end * sizeof (jmem_cpointer_t); + byte_code_start_p += (unsigned int) (literal_end - register_end) * sizeof (ecma_value_t); + if (unlikely (compiled_code_p->status_flags & CBC_CODE_FLAGS_NON_STRICT_ARGUMENTS_NEEDED)) + { + byte_code_start_p += argument_end * sizeof (ecma_value_t); + } + byte_code_end_p = byte_code_start_p + length; byte_code_p = byte_code_start_p; @@ -1378,6 +1394,7 @@ parser_post_processing (parser_context_t *context_p) /**< context */ size_t last_position; size_t offset; size_t length; + size_t literal_length; size_t total_size; #ifdef JERRY_ENABLE_SNAPSHOT_SAVE size_t total_size_used; @@ -1388,7 +1405,7 @@ parser_post_processing (parser_context_t *context_p) /**< context */ bool needs_uint16_arguments; cbc_opcode_t last_opcode = CBC_EXT_OPCODE; ecma_compiled_code_t *compiled_code_p; - jmem_cpointer_t *literal_pool_p; + ecma_value_t *literal_pool_p; uint8_t *dst_p; if ((size_t) context_p->stack_limit + (size_t) context_p->register_count > PARSER_MAXIMUM_STACK_LIMIT) @@ -1612,7 +1629,16 @@ parser_post_processing (parser_context_t *context_p) /**< context */ total_size = sizeof (cbc_uint16_arguments_t); } - total_size += length + context_p->literal_count * sizeof (jmem_cpointer_t); + literal_length = (size_t) (context_p->literal_count - context_p->register_count) * sizeof (ecma_value_t); + + total_size += literal_length + length; + + if ((context_p->status_flags & PARSER_ARGUMENTS_NEEDED) + && !(context_p->status_flags & PARSER_IS_STRICT)) + { + total_size += context_p->argument_count * sizeof (ecma_value_t); + } + #ifdef JERRY_ENABLE_SNAPSHOT_SAVE total_size_used = total_size; #endif @@ -1678,6 +1704,12 @@ parser_post_processing (parser_context_t *context_p) /**< context */ if (context_p->status_flags & PARSER_ARGUMENTS_NEEDED) { compiled_code_p->status_flags |= CBC_CODE_FLAGS_ARGUMENTS_NEEDED; + + if (!(context_p->status_flags & PARSER_IS_STRICT)) + { + compiled_code_p->status_flags |= CBC_CODE_FLAGS_NON_STRICT_ARGUMENTS_NEEDED; + } + /* Arguments is stored in the lexical environment. */ context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED; } @@ -1694,8 +1726,9 @@ parser_post_processing (parser_context_t *context_p) /**< context */ } #endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ - literal_pool_p = (jmem_cpointer_t *) byte_code_p; - byte_code_p += context_p->literal_count * sizeof (jmem_cpointer_t); + literal_pool_p = (ecma_value_t *) byte_code_p; + literal_pool_p -= context_p->register_count; + byte_code_p += literal_length; dst_p = parser_generate_initializers (context_p, byte_code_p, @@ -1896,17 +1929,19 @@ parser_post_processing (parser_context_t *context_p) /**< context */ { parser_list_iterator_t literal_iterator; lexer_literal_t *literal_p; + uint16_t register_count = context_p->register_count; parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator))) { - if (literal_p->status_flags & LEXER_FLAG_LATE_INIT) + if ((literal_p->status_flags & LEXER_FLAG_LATE_INIT) + && literal_p->prop.index >= register_count) { uint32_t source_data = literal_p->u.source_data; const uint8_t *char_p = context_p->source_end_p - (source_data & 0xfffff); - jmem_cpointer_t lit_cp = ecma_find_or_create_literal_string (char_p, + ecma_value_t lit_value = ecma_find_or_create_literal_string (char_p, source_data >> 20); - literal_pool_p[literal_p->prop.index] = lit_cp; + literal_pool_p[literal_p->prop.index] = lit_value; } } } @@ -1917,6 +1952,9 @@ parser_post_processing (parser_context_t *context_p) /**< context */ { parser_list_iterator_t literal_iterator; uint16_t argument_count = 0; + uint16_t register_count = context_p->register_count; + ecma_value_t *argument_base_p = (ecma_value_t *) (((uint8_t *) compiled_code_p) + total_size); + argument_base_p -= context_p->argument_count; parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); while (argument_count < context_p->argument_count) @@ -1936,7 +1974,7 @@ parser_post_processing (parser_context_t *context_p) /**< context */ { if (literal_p->u.char_p == NULL) { - literal_pool_p[argument_count] = JMEM_CP_NULL; + argument_base_p[argument_count] = ECMA_VALUE_EMPTY; argument_count++; continue; } @@ -1949,17 +1987,17 @@ parser_post_processing (parser_context_t *context_p) /**< context */ JERRY_ASSERT (literal_p->type == LEXER_IDENT_LITERAL && (literal_p->status_flags & LEXER_FLAG_VAR)); - JERRY_ASSERT (argument_count < literal_p->prop.index); + JERRY_ASSERT (literal_p->prop.index >= register_count); - literal_pool_p[argument_count] = literal_pool_p[literal_p->prop.index]; + argument_base_p[argument_count] = literal_pool_p[literal_p->prop.index]; argument_count++; } } if (context_p->status_flags & PARSER_NAMED_FUNCTION_EXP) { - ECMA_SET_NON_NULL_POINTER (literal_pool_p[const_literal_end], - compiled_code_p); + ECMA_SET_INTERNAL_VALUE_POINTER (literal_pool_p[const_literal_end], + compiled_code_p); } #ifdef JERRY_DEBUGGER diff --git a/jerry-core/parser/regexp/re-bytecode.h b/jerry-core/parser/regexp/re-bytecode.h index c1661515b..45846e01c 100644 --- a/jerry-core/parser/regexp/re-bytecode.h +++ b/jerry-core/parser/regexp/re-bytecode.h @@ -85,7 +85,7 @@ typedef enum typedef struct { ecma_compiled_code_t header; /**< compiled code header */ - jmem_cpointer_t pattern_cp; /**< original RegExp pattern */ + ecma_value_t pattern; /**< original RegExp pattern */ uint32_t num_of_captures; /**< number of capturing brackets */ uint32_t num_of_non_captures; /**< number of non capturing brackets */ } re_compiled_code_t; diff --git a/jerry-core/parser/regexp/re-compiler.c b/jerry-core/parser/regexp/re-compiler.c index c4fa8916e..a82c7e599 100644 --- a/jerry-core/parser/regexp/re-compiler.c +++ b/jerry-core/parser/regexp/re-compiler.c @@ -468,8 +468,7 @@ re_find_bytecode_in_cache (ecma_string_t *pattern_str_p, /**< pattern string */ if (cached_bytecode_p != NULL) { - ecma_string_t *cached_pattern_str_p; - cached_pattern_str_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, cached_bytecode_p->pattern_cp); + ecma_string_t *cached_pattern_str_p = ecma_get_string_from_value (cached_bytecode_p->pattern); if ((cached_bytecode_p->header.status_flags & RE_FLAGS_MASK) == flags && ecma_compare_ecma_strings (cached_pattern_str_p, pattern_str_p)) @@ -580,7 +579,7 @@ re_compile_bytecode (const re_compiled_code_t **out_bytecode_p, /**< [out] point re_compiled_code.header.refs = 1; re_compiled_code.header.status_flags = re_ctx.flags; ecma_ref_ecma_string (pattern_str_p); - ECMA_SET_NON_NULL_POINTER (re_compiled_code.pattern_cp, pattern_str_p); + re_compiled_code.pattern = ecma_make_string_value (pattern_str_p); re_compiled_code.num_of_captures = re_ctx.num_of_captures * 2; re_compiled_code.num_of_non_captures = re_ctx.num_of_non_captures; diff --git a/jerry-core/vm/opcodes.c b/jerry-core/vm/opcodes.c index e0596fae7..d5a2b261a 100644 --- a/jerry-core/vm/opcodes.c +++ b/jerry-core/vm/opcodes.c @@ -217,12 +217,12 @@ vm_op_delete_prop (ecma_value_t object, /**< base object */ * Returned value must be freed with ecma_free_value */ ecma_value_t -vm_op_delete_var (jmem_cpointer_t name_literal, /**< name literal */ +vm_op_delete_var (ecma_value_t name_literal, /**< name literal */ ecma_object_t *lex_env_p) /**< lexical environment */ { ecma_value_t completion_value = ECMA_VALUE_EMPTY; - ecma_string_t *var_name_str_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, name_literal); + ecma_string_t *var_name_str_p = ecma_get_string_from_value (name_literal); ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (lex_env_p, var_name_str_p); diff --git a/jerry-core/vm/opcodes.h b/jerry-core/vm/opcodes.h index 56128e494..5114578fa 100644 --- a/jerry-core/vm/opcodes.h +++ b/jerry-core/vm/opcodes.h @@ -91,7 +91,7 @@ ecma_value_t vm_op_delete_prop (ecma_value_t object, ecma_value_t property, bool is_strict); ecma_value_t -vm_op_delete_var (jmem_cpointer_t name_literal, ecma_object_t *lex_env_p); +vm_op_delete_var (ecma_value_t name_literal, ecma_object_t *lex_env_p); ecma_collection_chunk_t * opfunc_for_in (ecma_value_t left_value, ecma_value_t *result_obj_p); diff --git a/jerry-core/vm/vm-defines.h b/jerry-core/vm/vm-defines.h index 7ae91ee17..b0fd1fe34 100644 --- a/jerry-core/vm/vm-defines.h +++ b/jerry-core/vm/vm-defines.h @@ -46,7 +46,7 @@ typedef struct vm_frame_ctx_t uint8_t *byte_code_start_p; /**< byte code start pointer */ ecma_value_t *registers_p; /**< register start pointer */ ecma_value_t *stack_top_p; /**< stack top pointer */ - jmem_cpointer_t *literal_start_p; /**< literal list start pointer */ + ecma_value_t *literal_start_p; /**< literal list start pointer */ ecma_object_t *lex_env_p; /**< current lexical environment */ struct vm_frame_ctx_t *prev_context_p; /**< previous context */ ecma_value_t this_binding; /**< this binding */ diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index b9dfc8012..d10b6ffae 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -55,23 +55,15 @@ vm_op_get_value (ecma_value_t object, /**< base object */ { ecma_object_t *object_p = ecma_get_object_from_value (object); ecma_string_t *property_name_p = NULL; - ecma_string_t uint32_string; if (ecma_is_value_integer_number (property)) { ecma_integer_value_t int_value = ecma_get_integer_from_value (property); -#ifdef JERRY_CPOINTER_32_BIT - bool limit_check = (int_value >= 0); -#else /* !JERRY_CPOINTER_32_BIT */ - bool limit_check = (int_value >= 0 && int_value < (ecma_integer_value_t) (UINT16_MAX + 1)); -#endif - - if (limit_check) + if (int_value >= 0 && int_value <= ECMA_DIRECT_STRING_MAX_IMM) { - /* Statically allocated string for searching. */ - ecma_init_ecma_string_from_uint32 (&uint32_string, (uint32_t) int_value); - property_name_p = &uint32_string; + property_name_p = (ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_UINT, + (uintptr_t) int_value); } } else if (ecma_is_value_string (property)) @@ -295,10 +287,10 @@ vm_run_eval (ecma_compiled_code_t *bytecode_data_p, /**< byte-code data */ */ static ecma_value_t vm_construct_literal_object (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ - jmem_cpointer_t lit_cp) /**< literal */ + ecma_value_t lit_value) /**< literal */ { - ecma_compiled_code_t *bytecode_p = ECMA_GET_NON_NULL_POINTER (ecma_compiled_code_t, - lit_cp); + ecma_compiled_code_t *bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, + lit_value); bool is_function = ((bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION) != 0); if (is_function) @@ -523,8 +515,8 @@ opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } \ else \ { \ - ecma_string_t *name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, \ - literal_start_p[literal_index]); \ + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); \ + \ result = ecma_op_resolve_reference_value (frame_ctx_p->lex_env_p, \ name_p); \ \ @@ -537,23 +529,13 @@ opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } \ else if (literal_index < const_literal_end) \ { \ - ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, \ - literal_start_p[literal_index]); \ - \ - if (unlikely (ECMA_STRING_GET_CONTAINER (value_p) == ECMA_STRING_LITERAL_NUMBER)) \ - { \ - (target_value) = ecma_fast_copy_value (value_p->u.lit_number); \ - } \ - else \ - { \ - ecma_ref_ecma_string (value_p); \ - (target_value) = ecma_make_string_value (value_p); \ - } \ + (target_value) = ecma_fast_copy_value (literal_start_p[literal_index]); \ } \ else \ { \ /* Object construction. */ \ - (target_value) = vm_construct_literal_object (frame_ctx_p, literal_start_p[literal_index]); \ + (target_value) = vm_construct_literal_object (frame_ctx_p, \ + literal_start_p[literal_index]); \ } \ } \ while (0) @@ -571,10 +553,10 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ uint16_t encoding_limit; uint16_t encoding_delta; uint16_t register_end; - jmem_cpointer_t *literal_start_p = frame_ctx_p->literal_start_p; + ecma_value_t *literal_start_p = frame_ctx_p->literal_start_p; bool is_strict = ((frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0); - jmem_cpointer_t self_reference; - ECMA_SET_NON_NULL_POINTER (self_reference, bytecode_header_p); + ecma_value_t self_reference; + ECMA_SET_INTERNAL_VALUE_POINTER (self_reference, bytecode_header_p); /* Prepare. */ if (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_FULL_LITERAL_ENCODING)) @@ -613,8 +595,7 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ while (literal_index <= literal_index_end) { - ecma_string_t *name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, - literal_start_p[literal_index]); + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); vm_var_decl (frame_ctx_p, name_p); literal_index++; } @@ -663,14 +644,9 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } else { - ecma_string_t *name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, - literal_start_p[literal_index]); + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); - if (self_reference == literal_start_p[value_index]) - { - ecma_op_create_immutable_binding (frame_ctx_p->lex_env_p, name_p, lit_value); - } - else + if (likely (value_index < register_end || self_reference != literal_start_p[value_index])) { vm_var_decl (frame_ctx_p, name_p); @@ -690,6 +666,10 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_free_value (JERRY_CONTEXT (error_value)); } } + else + { + ecma_op_create_immutable_binding (frame_ctx_p->lex_env_p, name_p, lit_value); + } if (value_index >= register_end) { @@ -730,7 +710,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { const ecma_compiled_code_t *bytecode_header_p = frame_ctx_p->bytecode_header_p; uint8_t *byte_code_p = frame_ctx_p->byte_code_p; - jmem_cpointer_t *literal_start_p = frame_ctx_p->literal_start_p; + ecma_value_t *literal_start_p = frame_ctx_p->literal_start_p; ecma_value_t *stack_top_p; uint16_t encoding_limit; @@ -1146,10 +1126,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } else { - ecma_string_t *name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, - literal_start_p[literal_index]); - ecma_object_t *ref_base_lex_env_p; + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + ecma_object_t *ref_base_lex_env_p; ref_base_lex_env_p = ecma_op_resolve_reference_base (frame_ctx_p->lex_env_p, name_p); @@ -1648,8 +1627,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } else { - ecma_string_t *name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, - literal_start_p[literal_index]); + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (frame_ctx_p->lex_env_p, name_p); @@ -2592,8 +2570,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } else { - ecma_string_t *var_name_str_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, - literal_start_p[literal_index]); + ecma_string_t *var_name_str_p = ecma_get_string_from_value (literal_start_p[literal_index]); + ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (frame_ctx_p->lex_env_p, var_name_str_p); @@ -2745,25 +2723,20 @@ error: if (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_CATCH) { - uint32_t literal_index; - ecma_object_t *catch_env_p; - ecma_string_t *catch_name_p; - *stack_top_p++ = JERRY_CONTEXT (error_value); JERRY_ASSERT (byte_code_p[0] == CBC_ASSIGN_SET_IDENT); - literal_index = byte_code_p[1]; + uint32_t literal_index = byte_code_p[1]; + if (literal_index >= encoding_limit) { literal_index = ((literal_index << 8) | byte_code_p[2]) - encoding_delta; } - catch_env_p = ecma_create_decl_lex_env (frame_ctx_p->lex_env_p); - - catch_name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, - literal_start_p[literal_index]); + ecma_object_t *catch_env_p = ecma_create_decl_lex_env (frame_ctx_p->lex_env_p); + ecma_string_t *catch_name_p = ecma_get_string_from_value (literal_start_p[literal_index]); ecma_op_create_mutable_binding (catch_env_p, catch_name_p, false); stack_top_p[-2 - 1] = ecma_make_object_value (frame_ctx_p->lex_env_p); @@ -2909,29 +2882,29 @@ vm_run (const ecma_compiled_code_t *bytecode_header_p, /**< byte-code data heade const ecma_value_t *arg_list_p, /**< arguments list */ ecma_length_t arg_list_len) /**< length of arguments list */ { - jmem_cpointer_t *literal_p; + ecma_value_t *literal_p; vm_frame_ctx_t frame_ctx; uint32_t call_stack_size; if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) { cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p; - uint8_t *byte_p = (uint8_t *) bytecode_header_p; + call_stack_size = (uint32_t) (args_p->register_end + args_p->stack_limit); - literal_p = (jmem_cpointer_t *) (byte_p + sizeof (cbc_uint16_arguments_t)); + literal_p = (ecma_value_t *) ((uint8_t *) bytecode_header_p + sizeof (cbc_uint16_arguments_t)); + literal_p -= args_p->register_end; frame_ctx.literal_start_p = literal_p; literal_p += args_p->literal_end; - call_stack_size = (uint32_t) (args_p->register_end + args_p->stack_limit); } else { cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p; - uint8_t *byte_p = (uint8_t *) bytecode_header_p; + call_stack_size = (uint32_t) (args_p->register_end + args_p->stack_limit); - literal_p = (jmem_cpointer_t *) (byte_p + sizeof (cbc_uint8_arguments_t)); + literal_p = (ecma_value_t *) ((uint8_t *) bytecode_header_p + sizeof (cbc_uint8_arguments_t)); + literal_p -= args_p->register_end; frame_ctx.literal_start_p = literal_p; literal_p += args_p->literal_end; - call_stack_size = (uint32_t) (args_p->register_end + args_p->stack_limit); } frame_ctx.bytecode_header_p = bytecode_header_p; diff --git a/tests/unit-core/test-literal-storage.c b/tests/unit-core/test-literal-storage.c index ceae4a764..c471c03f6 100644 --- a/tests/unit-core/test-literal-storage.c +++ b/tests/unit-core/test-literal-storage.c @@ -104,23 +104,24 @@ main (void) for (uint32_t j = 0; j < test_sub_iters; j++) { - jmem_cpointer_t lit1; - jmem_cpointer_t lit2; + ecma_value_t lit1; + ecma_value_t lit2; if (ptrs[j]) { lit1 = ecma_find_or_create_literal_string (ptrs[j], lengths[j]); lit2 = ecma_find_or_create_literal_string (ptrs[j], lengths[j]); + TEST_ASSERT (ecma_is_value_string (lit1)); + TEST_ASSERT (ecma_is_value_string (lit2)); TEST_ASSERT (lit1 == lit2); } else { lit1 = ecma_find_or_create_literal_number (numbers[j]); lit2 = ecma_find_or_create_literal_number (numbers[j]); + TEST_ASSERT (ecma_is_value_number (lit1)); + TEST_ASSERT (ecma_is_value_number (lit2)); TEST_ASSERT (lit1 == lit2); } - TEST_ASSERT (lit1); - TEST_ASSERT (lit2); - TEST_ASSERT (lit1 == lit2); } /* Check empty string exists. */ diff --git a/tests/unit-core/test-snapshot.c b/tests/unit-core/test-snapshot.c index 228a11873..4cd718a9f 100644 --- a/tests/unit-core/test-snapshot.c +++ b/tests/unit-core/test-snapshot.c @@ -127,18 +127,18 @@ main (void) /* Check the snapshot data. Unused bytes should be filled with zeroes */ const uint8_t expected_data[] = { - 0x4A, 0x52, 0x52, 0x59, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x4A, 0x52, 0x52, 0x59, 0x09, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x28, 0x00, - 0xB7, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x01, 0x00, 0x21, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x47, 0x00, - 0x1C, 0x00, 0x00, 0x00, 0x14, 0x00, 0x73, 0x74, - 0x72, 0x69, 0x6E, 0x67, 0x20, 0x66, 0x72, 0x6F, - 0x6D, 0x20, 0x73, 0x6E, 0x61, 0x70, 0x73, 0x68, - 0x6F, 0x74, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, + 0x28, 0x00, 0xB7, 0x46, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x41, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x01, 0x07, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, + 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x73, 0x6E, + 0x61, 0x70, 0x73, 0x68, 0x6F, 0x74 }; TEST_ASSERT (sizeof (expected_data) == global_mode_snapshot_size); TEST_ASSERT (0 == memcmp (expected_data, global_mode_snapshot_buffer, sizeof (expected_data)));