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)));