diff --git a/jerry-core/api/jerry-snapshot.c b/jerry-core/api/jerry-snapshot.c index e3f77f1222..45cb45ec0e 100644 --- a/jerry-core/api/jerry-snapshot.c +++ b/jerry-core/api/jerry-snapshot.c @@ -367,7 +367,6 @@ static_snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< c /* Sub-functions and regular expressions are stored recursively. */ uint8_t *buffer_p = (uint8_t *) copied_code_p; ecma_value_t *literal_start_p; - uint32_t argument_end; uint32_t const_literal_end; uint32_t literal_end; @@ -378,7 +377,6 @@ static_snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< c 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; - argument_end = args_p->argument_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); } @@ -387,7 +385,6 @@ static_snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< c 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; - argument_end = args_p->argument_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); } @@ -424,19 +421,19 @@ static_snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< c } } - if (compiled_code_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) - { - buffer_p += ((size_t) compiled_code_p->size) << JMEM_ALIGNMENT_LOG; - literal_start_p = ((ecma_value_t *) buffer_p) - argument_end; + buffer_p += ((size_t) compiled_code_p->size) << JMEM_ALIGNMENT_LOG; + literal_start_p = ecma_snapshot_resolve_serializable_values (compiled_code_p, buffer_p); - for (uint32_t i = 0; i < argument_end; i++) + while (literal_start_p < (ecma_value_t *) buffer_p) + { + if (!ecma_is_value_direct_string (*literal_start_p) + && !ecma_is_value_empty (*literal_start_p)) { - if (!ecma_is_value_direct_string (literal_start_p[i])) - { - static_snapshot_error_unsupported_literal (globals_p, literal_start_p[i]); - return 0; - } + static_snapshot_error_unsupported_literal (globals_p, *literal_start_p); + return 0; } + + literal_start_p++; } return start_offset; @@ -460,7 +457,6 @@ jerry_snapshot_set_offsets (uint32_t *buffer_p, /**< buffer */ if (bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION) { 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) @@ -468,7 +464,6 @@ jerry_snapshot_set_offsets (uint32_t *buffer_p, /**< buffer */ 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; const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); } else @@ -476,7 +471,6 @@ jerry_snapshot_set_offsets (uint32_t *buffer_p, /**< buffer */ 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; const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); } @@ -496,28 +490,26 @@ jerry_snapshot_set_offsets (uint32_t *buffer_p, /**< buffer */ } } - if (bytecode_p->status_flags & CBC_CODE_FLAGS_MAPPED_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; + uint8_t *byte_p = (uint8_t *) bytecode_p + (((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG); + literal_start_p = ecma_snapshot_resolve_serializable_values (bytecode_p, byte_p); - for (uint32_t i = 0; i < argument_end; i++) + while (literal_start_p < (ecma_value_t *) byte_p) + { + if (*literal_start_p != ECMA_VALUE_EMPTY) { - 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; + JERRY_ASSERT (ecma_is_value_string (*literal_start_p)); - while (current_p->literal_id != literal_start_p[i]) - { - current_p++; - } + lit_mem_to_snapshot_id_map_entry_t *current_p = lit_map_p; - literal_start_p[i] = current_p->literal_offset; + while (current_p->literal_id != *literal_start_p) + { + current_p++; } + + *literal_start_p = current_p->literal_offset; } + + literal_start_p++; } /* Set reference counter to 1. */ @@ -577,7 +569,7 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th JERRY_ASSERT (bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION); size_t header_size; - uint32_t argument_end = 0; + uint32_t argument_end; uint32_t const_literal_end; uint32_t literal_end; @@ -586,11 +578,7 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th uint8_t *byte_p = (uint8_t *) bytecode_p; cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) byte_p; - if (bytecode_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) - { - argument_end = args_p->argument_end; - } - + 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); @@ -600,11 +588,7 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th uint8_t *byte_p = (uint8_t *) bytecode_p; cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) byte_p; - if (bytecode_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) - { - argument_end = args_p->argument_end; - } - + 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); @@ -627,13 +611,33 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th uint8_t *real_bytecode_p = ((uint8_t *) bytecode_p) + start_offset; uint32_t new_code_size = (uint32_t) (start_offset + 1 + sizeof (uint8_t *)); + uint32_t extra_bytes = 0; - if (argument_end != 0) + if (bytecode_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) { - new_code_size += (uint32_t) (argument_end * sizeof (ecma_value_t)); + extra_bytes += (uint32_t) (argument_end * sizeof (ecma_value_t)); } - new_code_size = JERRY_ALIGNUP (new_code_size, JMEM_ALIGNMENT); +#if ENABLED (JERRY_ES2015) + /* function name */ + if (!(bytecode_p->status_flags & CBC_CODE_FLAGS_CLASS_CONSTRUCTOR)) + { + extra_bytes += (uint32_t) sizeof (ecma_value_t); + } + + /* tagged template literals */ + if (bytecode_p->status_flags & CBC_CODE_FLAG_HAS_TAGGED_LITERALS) + { + extra_bytes += (uint32_t) sizeof (ecma_value_t); + } +#endif /* ENABLED (JERRY_ES2015) */ + +#if ENABLED (JERRY_RESOURCE_NAME) + /* resource name */ + extra_bytes += (uint32_t) sizeof (ecma_value_t); +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ + + new_code_size = JERRY_ALIGNUP (new_code_size + extra_bytes, JMEM_ALIGNMENT); bytecode_p = (ecma_compiled_code_t *) jmem_heap_alloc_block (new_code_size); @@ -647,12 +651,12 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th uint8_t *byte_p = (uint8_t *) bytecode_p; - if (argument_end != 0) + uint8_t *new_base_p = byte_p + new_code_size - extra_bytes; + const uint8_t *base_p = base_addr_p + code_size - extra_bytes; + + if (extra_bytes != 0) { - uint32_t argument_size = (uint32_t) (argument_end * sizeof (ecma_value_t)); - memcpy (byte_p + new_code_size - argument_size, - base_addr_p + code_size - argument_size, - argument_size); + memcpy (new_base_p, base_p, extra_bytes); } byte_p[start_offset] = CBC_SET_BYTECODE_PTR; @@ -699,18 +703,17 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th } } - if (argument_end != 0) - { - literal_start_p = (ecma_value_t *) (((uint8_t *) bytecode_p) + code_size); - literal_start_p -= argument_end; + uint8_t *byte_p = ((uint8_t *) bytecode_p) + code_size; + literal_start_p = ecma_snapshot_resolve_serializable_values (bytecode_p, byte_p); - for (uint32_t i = 0; i < argument_end; i++) + while (literal_start_p < (ecma_value_t *) byte_p) + { + if ((*literal_start_p & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_SNAPSHOT_OFFSET) { - 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]); - } + *literal_start_p = ecma_snapshot_get_literal (literal_base_p, *literal_start_p); } + + literal_start_p++; } return bytecode_p; @@ -743,9 +746,17 @@ jerry_generate_snapshot_with_args (const jerry_char_t *resource_name_p, /**< scr JERRY_UNUSED (resource_name_p); JERRY_UNUSED (resource_name_length); -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) - JERRY_CONTEXT (resource_name) = ECMA_VALUE_UNDEFINED; -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ +#if ENABLED (JERRY_RESOURCE_NAME) + if (resource_name_length == 0) + { + JERRY_CONTEXT (resource_name) = ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON); + } + else + { + JERRY_CONTEXT (resource_name) = ecma_find_or_create_literal_string (resource_name_p, + (lit_utf8_size_t) resource_name_length); + } +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ snapshot_globals_t globals; ecma_value_t parse_status; @@ -758,11 +769,14 @@ jerry_generate_snapshot_with_args (const jerry_char_t *resource_name_p, /**< scr globals.regex_found = false; globals.class_found = false; + uint32_t status_flags = ((generate_snapshot_opts & JERRY_SNAPSHOT_SAVE_STRICT) ? ECMA_PARSE_STRICT_MODE + : ECMA_PARSE_NO_OPTS); + parse_status = parser_parse_script (args_p, args_size, source_p, source_size, - (generate_snapshot_opts & JERRY_SNAPSHOT_SAVE_STRICT) != 0, + status_flags, &bytecode_data_p); if (ECMA_IS_VALUE_ERROR (parse_status)) @@ -1073,7 +1087,6 @@ scan_snapshot_functions (const uint8_t *buffer_p, /**< snapshot buffer start */ && !(bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)) { const 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) @@ -1081,7 +1094,6 @@ scan_snapshot_functions (const uint8_t *buffer_p, /**< snapshot buffer start */ 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; - argument_end = args_p->argument_end; const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); } else @@ -1089,7 +1101,6 @@ scan_snapshot_functions (const uint8_t *buffer_p, /**< snapshot buffer start */ 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; - argument_end = args_p->argument_end; const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); } @@ -1102,20 +1113,18 @@ scan_snapshot_functions (const uint8_t *buffer_p, /**< snapshot buffer start */ } } - if (bytecode_p->status_flags & CBC_CODE_FLAGS_MAPPED_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; + uint8_t *byte_p = (uint8_t *) bytecode_p + (((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG); + literal_start_p = ecma_snapshot_resolve_serializable_values ((ecma_compiled_code_t *) bytecode_p, byte_p); - for (uint32_t i = 0; i < argument_end; i++) + while (literal_start_p < (ecma_value_t *) byte_p) + { + if ((*literal_start_p & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_SNAPSHOT_OFFSET) { - 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]); - ecma_save_literals_append_value (lit_value, lit_pool_p); - } + ecma_value_t lit_value = ecma_snapshot_get_literal (literal_base_p, *literal_start_p); + ecma_save_literals_append_value (lit_value, lit_pool_p); } + + literal_start_p++; } } @@ -1144,7 +1153,6 @@ update_literal_offsets (uint8_t *buffer_p, /**< [in,out] snapshot buffer start * && !(bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)) { 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) @@ -1152,7 +1160,6 @@ update_literal_offsets (uint8_t *buffer_p, /**< [in,out] snapshot buffer start * 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; - argument_end = args_p->argument_end; const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); } else @@ -1160,7 +1167,6 @@ update_literal_offsets (uint8_t *buffer_p, /**< [in,out] snapshot buffer start * 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; - argument_end = args_p->argument_end; const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); } @@ -1180,27 +1186,25 @@ update_literal_offsets (uint8_t *buffer_p, /**< [in,out] snapshot buffer start * } } - if (bytecode_p->status_flags & CBC_CODE_FLAGS_MAPPED_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; + uint8_t *byte_p = (uint8_t *) bytecode_p + (((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG); + literal_start_p = ecma_snapshot_resolve_serializable_values ((ecma_compiled_code_t *) bytecode_p, byte_p); - for (uint32_t i = 0; i < argument_end; i++) + while (literal_start_p < (ecma_value_t *) byte_p) + { + if ((*literal_start_p & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_SNAPSHOT_OFFSET) { - 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]); - const lit_mem_to_snapshot_id_map_entry_t *current_p = lit_map_p; - - while (current_p->literal_id != lit_value) - { - current_p++; - } + ecma_value_t lit_value = ecma_snapshot_get_literal (literal_base_p, *literal_start_p); + const lit_mem_to_snapshot_id_map_entry_t *current_p = lit_map_p; - literal_start_p[i] = current_p->literal_offset; + while (current_p->literal_id != lit_value) + { + current_p++; } + + *literal_start_p = current_p->literal_offset; } + + literal_start_p++; } } diff --git a/jerry-core/api/jerry.c b/jerry-core/api/jerry.c index ae904bd3bb..ba879dcbbc 100644 --- a/jerry-core/api/jerry.c +++ b/jerry-core/api/jerry.c @@ -429,7 +429,7 @@ jerry_parse (const jerry_char_t *resource_name_p, /**< resource name (usually a #if ENABLED (JERRY_PARSER) jerry_assert_api_available (); -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) +#if ENABLED (JERRY_RESOURCE_NAME) if (resource_name_length == 0) { JERRY_CONTEXT (resource_name) = ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON); @@ -439,7 +439,7 @@ jerry_parse (const jerry_char_t *resource_name_p, /**< resource name (usually a JERRY_CONTEXT (resource_name) = ecma_find_or_create_literal_string (resource_name_p, (lit_utf8_size_t) resource_name_length); } -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ ecma_compiled_code_t *bytecode_data_p; ecma_value_t parse_status; @@ -507,7 +507,7 @@ jerry_parse_function (const jerry_char_t *resource_name_p, /**< resource name (u ecma_compiled_code_t *bytecode_data_p; ecma_value_t parse_status; -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) +#if ENABLED (JERRY_RESOURCE_NAME) if (resource_name_length == 0) { JERRY_CONTEXT (resource_name) = ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON); @@ -517,7 +517,7 @@ jerry_parse_function (const jerry_char_t *resource_name_p, /**< resource name (u JERRY_CONTEXT (resource_name) = ecma_find_or_create_literal_string (resource_name_p, (lit_utf8_size_t) resource_name_length); } -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ if (arg_list_p == NULL) { @@ -3546,7 +3546,7 @@ jerry_get_backtrace (uint32_t max_depth) /**< depth limit of the backtrace */ jerry_value_t jerry_get_resource_name (const jerry_value_t value) /**< jerry api value */ { -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) +#if ENABLED (JERRY_RESOURCE_NAME) if (ecma_is_value_undefined (value)) { if (JERRY_CONTEXT (vm_top_context_p) != NULL) @@ -3554,7 +3554,7 @@ jerry_get_resource_name (const jerry_value_t value) /**< jerry api value */ return ecma_copy_value (JERRY_CONTEXT (vm_top_context_p)->resource_name); } } -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ #if ENABLED (JERRY_LINE_INFO) else if (ecma_is_value_object (value)) { diff --git a/jerry-core/config.h b/jerry-core/config.h index 0e5e8b97af..2e806f78dc 100644 --- a/jerry-core/config.h +++ b/jerry-core/config.h @@ -684,4 +684,13 @@ # define JERRY_ES2015_BUILTIN_CONTAINER 0 #endif +/** + * Resource name relatey types into a single guard + */ +#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) +# define JERRY_RESOURCE_NAME 1 +#else +# define JERRY_RESOURCE_NAME 0 +#endif + #endif /* !JERRYSCRIPT_CONFIG_H */ diff --git a/jerry-core/ecma/base/ecma-helpers.c b/jerry-core/ecma/base/ecma-helpers.c index fd079aefc6..7a56b3a145 100644 --- a/jerry-core/ecma/base/ecma-helpers.c +++ b/jerry-core/ecma/base/ecma-helpers.c @@ -1441,17 +1441,7 @@ ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */ #if ENABLED (JERRY_ES2015) if (bytecode_p->status_flags & CBC_CODE_FLAG_HAS_TAGGED_LITERALS) { - ecma_length_t formal_params_number = ecma_compiled_code_get_formal_params (bytecode_p); - - uint8_t *byte_p = (uint8_t *) bytecode_p; - byte_p += ((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG; - - ecma_value_t *tagged_base_p = (ecma_value_t *) byte_p; - tagged_base_p -= formal_params_number; - - ecma_collection_t *coll_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, tagged_base_p[-1]); - - ecma_collection_destroy (coll_p); + ecma_collection_destroy (ecma_compiled_code_get_tagged_template_collection (bytecode_p)); } #endif /* ENABLED (JERRY_ES2015) */ @@ -1484,17 +1474,17 @@ ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *b JERRY_ASSERT (bytecode_header_p != NULL); JERRY_ASSERT (bytecode_header_p->status_flags & CBC_CODE_FLAG_HAS_TAGGED_LITERALS); - uint8_t *byte_p = (uint8_t *) bytecode_header_p; - byte_p += ((size_t) bytecode_header_p->size) << JMEM_ALIGNMENT_LOG; + ecma_value_t *base_p = ecma_compiled_code_resolve_function_name (bytecode_header_p); - ecma_value_t *tagged_base_p = (ecma_value_t *) byte_p; - tagged_base_p -= ecma_compiled_code_get_formal_params (bytecode_header_p); +#if ENABLED (JERRY_RESOURCE_NAME) + base_p--; +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ - return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, tagged_base_p[-1]); + return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, base_p[-1]); } /* ecma_compiled_code_get_tagged_template_collection */ #endif /* ENABLED (JERRY_ES2015) */ -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) || ENABLED (JERRY_ES2015) +#if ENABLED (JERRY_RESOURCE_NAME) || ENABLED (JERRY_ES2015) /** * Get the number of formal parameters of the compiled code * @@ -1515,7 +1505,44 @@ ecma_compiled_code_get_formal_params (const ecma_compiled_code_t *bytecode_heade return ((cbc_uint8_arguments_t *) bytecode_header_p)->argument_end; } /* ecma_compiled_code_get_formal_params */ -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) || ENABLED (JERRY_ES2015) */ + +/** + * Resolve the position of the arguments list start of the compiled code + * + * @return start position of the arguments list start of the compiled code + */ +ecma_value_t * +ecma_compiled_code_resolve_arguments_start (const ecma_compiled_code_t *bytecode_header_p) +{ + JERRY_ASSERT (bytecode_header_p != NULL); + + uint8_t *byte_p = (uint8_t *) bytecode_header_p; + byte_p += ((size_t) bytecode_header_p->size) << JMEM_ALIGNMENT_LOG; + + return ((ecma_value_t *) byte_p) - ecma_compiled_code_get_formal_params (bytecode_header_p); +} /* ecma_compiled_code_resolve_arguments_start */ + +/** + * Resolve the position of the function name of the compiled code + * + * @return position of the function name of the compiled code + */ +inline ecma_value_t * JERRY_ATTR_ALWAYS_INLINE +ecma_compiled_code_resolve_function_name (const ecma_compiled_code_t *bytecode_header_p) +{ + JERRY_ASSERT (bytecode_header_p != NULL); + ecma_value_t *base_p = ecma_compiled_code_resolve_arguments_start (bytecode_header_p); + +#if ENABLED (JERRY_ES2015) + if (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_CLASS_CONSTRUCTOR)) + { + base_p--; + } +#endif /* ENABLED (JERRY_ES2015) */ + + return base_p; +} /* ecma_compiled_code_resolve_function_name */ +#endif /* ENABLED (JERRY_RESOURCE_NAME) || ENABLED (JERRY_ES2015) */ #if (JERRY_STACK_LIMIT != 0) /** diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 83acd6fbc6..7de5451862 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -488,9 +488,11 @@ void ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p); #if ENABLED (JERRY_ES2015) ecma_collection_t *ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p); #endif /* ENABLED (JERRY_ES2015) */ -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) || ENABLED (JERRY_ES2015) +#if ENABLED (JERRY_RESOURCE_NAME) || ENABLED (JERRY_ES2015) ecma_length_t ecma_compiled_code_get_formal_params (const ecma_compiled_code_t *bytecode_p); -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) || ENABLED (JERRY_ES2015) */ +ecma_value_t *ecma_compiled_code_resolve_arguments_start (const ecma_compiled_code_t *bytecode_header_p); +ecma_value_t *ecma_compiled_code_resolve_function_name (const ecma_compiled_code_t *bytecode_header_p); +#endif /* ENABLED (JERRY_RESOURCE_NAME) || ENABLED (JERRY_ES2015) */ #if (JERRY_STACK_LIMIT != 0) uintptr_t ecma_get_current_stack_usage (void); #endif /* (JERRY_STACK_LIMIT != 0) */ diff --git a/jerry-core/ecma/base/ecma-literal-storage.c b/jerry-core/ecma/base/ecma-literal-storage.c index e4dc58ce3d..33888959cf 100644 --- a/jerry-core/ecma/base/ecma-literal-storage.c +++ b/jerry-core/ecma/base/ecma-literal-storage.c @@ -329,7 +329,7 @@ ecma_save_literals_add_compiled_code (const ecma_compiled_code_t *compiled_code_ ecma_collection_t *lit_pool_p) /**< list of known values */ { ecma_value_t *literal_p; - uint32_t argument_end = 0; + uint32_t argument_end; uint32_t register_end; uint32_t const_literal_end; uint32_t literal_end; @@ -345,11 +345,7 @@ ecma_save_literals_add_compiled_code (const ecma_compiled_code_t *compiled_code_ 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_MAPPED_ARGUMENTS_NEEDED) - { - argument_end = args_p->argument_end; - } + argument_end = args_p->argument_end; } else { @@ -360,16 +356,15 @@ ecma_save_literals_add_compiled_code (const ecma_compiled_code_t *compiled_code_ 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_MAPPED_ARGUMENTS_NEEDED) - { - argument_end = args_p->argument_end; - } + argument_end = args_p->argument_end; } - for (uint32_t i = 0; i < argument_end; i++) + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) { - ecma_save_literals_append_value (literal_p[i], lit_pool_p); + 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++) @@ -389,16 +384,13 @@ ecma_save_literals_add_compiled_code (const ecma_compiled_code_t *compiled_code_ } } - 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; + uint8_t *byte_p = ((uint8_t *) compiled_code_p) + (((size_t) compiled_code_p->size) << JMEM_ALIGNMENT_LOG); + literal_p = ecma_snapshot_resolve_serializable_values ((ecma_compiled_code_t *) compiled_code_p, byte_p); - for (uint32_t i = 0; i < argument_end; i++) - { - ecma_save_literals_append_value (literal_p[i], lit_pool_p); - } + while (literal_p < (ecma_value_t *) byte_p) + { + ecma_save_literals_append_value (*literal_p, lit_pool_p); + literal_p++; } } /* ecma_save_literals_add_compiled_code */ @@ -546,6 +538,51 @@ ecma_snapshot_get_literal (const uint8_t *literal_base_p, /**< literal start */ return ecma_find_or_create_literal_string (literal_p + sizeof (uint16_t), length); } /* ecma_snapshot_get_literal */ +/** + * Compute the start of the serializable ecma-values of the bytecode + * Related values: + * - function argument names, if CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED is present + * - function name, if CBC_CODE_FLAGS_CLASS_CONSTRUCTOR is not present and ES2015 profile is enabled + * - resource name, if JERRY_RESOURCE_NAME is enabled + * + * @return pointer to the beginning of the serializable ecma-values + */ +ecma_value_t * +ecma_snapshot_resolve_serializable_values (ecma_compiled_code_t *compiled_code_p, /**< compiled code */ + uint8_t *bytecode_end_p) /**< end of the bytecode */ +{ + ecma_value_t *base_p = (ecma_value_t *) bytecode_end_p; + + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) + { + uint32_t argument_end; + if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + argument_end = ((cbc_uint16_arguments_t *) compiled_code_p)->argument_end; + } + else + { + argument_end = ((cbc_uint8_arguments_t *) compiled_code_p)->argument_end; + } + + base_p -= argument_end; + } + +#if ENABLED (JERRY_ES2015) + /* function name */ + if (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_CLASS_CONSTRUCTOR)) + { + base_p--; + } +#endif /* ENABLED (JERRY_ES2015) */ + +#if ENABLED (JERRY_RESOURCE_NAME) + /* resource name */ + base_p--; +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ + + return base_p; +} /* ecma_snapshot_resolve_serializable_values */ #endif /* ENABLED (JERRY_SNAPSHOT_EXEC) || ENABLED (JERRY_SNAPSHOT_SAVE) */ /** diff --git a/jerry-core/ecma/base/ecma-literal-storage.h b/jerry-core/ecma/base/ecma-literal-storage.h index debbcc50a8..bac05b7b15 100644 --- a/jerry-core/ecma/base/ecma-literal-storage.h +++ b/jerry-core/ecma/base/ecma-literal-storage.h @@ -55,6 +55,8 @@ bool ecma_save_literals_for_snapshot (ecma_collection_t *lit_pool_p, uint32_t *b #if ENABLED (JERRY_SNAPSHOT_EXEC) || ENABLED (JERRY_SNAPSHOT_SAVE) ecma_value_t ecma_snapshot_get_literal (const uint8_t *literal_base_p, ecma_value_t literal_value); +ecma_value_t * +ecma_snapshot_resolve_serializable_values (ecma_compiled_code_t *compiled_code_p, uint8_t *byte_code_end_p); #endif /* ENABLED (JERRY_SNAPSHOT_EXEC) || ENABLED (JERRY_SNAPSHOT_SAVE) */ /** diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c index c8ea48cd9c..1dc7d06204 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c @@ -297,6 +297,11 @@ ecma_builtin_function_prototype_object_bind (ecma_object_t *this_arg_obj_p , /** } #if ENABLED (JERRY_ES2015) + if (prototype_obj_p != NULL) + { + ecma_deref_object (prototype_obj_p); + } + ecma_integer_value_t len = 0; ecma_string_t *len_string = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_property_descriptor_t prop_desc; @@ -307,6 +312,7 @@ ecma_builtin_function_prototype_object_bind (ecma_object_t *this_arg_obj_p , /** #if ENABLED (JERRY_ES2015_BUILTIN_PROXY) if (ECMA_IS_VALUE_ERROR (status)) { + ecma_deref_object (function_p); return status; } #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */ @@ -319,6 +325,7 @@ ecma_builtin_function_prototype_object_bind (ecma_object_t *this_arg_obj_p , /** if (ECMA_IS_VALUE_ERROR (len_value)) { + ecma_deref_object (function_p); return len_value; } @@ -328,14 +335,36 @@ ecma_builtin_function_prototype_object_bind (ecma_object_t *this_arg_obj_p , /** ecma_op_to_integer (len_value, &len_num); len = (ecma_integer_value_t) len_num; } + ecma_free_value (len_value); } bound_func_p->target_length = len; - if (prototype_obj_p != NULL) + /* 12. */ + ecma_value_t name_value = ecma_op_object_get_by_magic_id (this_arg_obj_p, LIT_MAGIC_STRING_NAME); + if (ECMA_IS_VALUE_ERROR (name_value)) { - ecma_deref_object (prototype_obj_p); + ecma_deref_object (function_p); + return name_value; } + + if (!ecma_is_value_string (name_value)) + { + ecma_free_value (name_value); + name_value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + ecma_value_t bound_function_name = ecma_op_function_form_name (name_value, "bound ", 6); + + ecma_free_value (name_value); + + ecma_property_value_t *name_prop_value_p; + name_prop_value_p = ecma_create_named_data_property (function_p, + ecma_get_magic_string (LIT_MAGIC_STRING_NAME), + ECMA_PROPERTY_FLAG_CONFIGURABLE, + NULL); + + name_prop_value_p->value = bound_function_name; #endif /* ENABLED (JERRY_ES2015) */ /* diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-function.c b/jerry-core/ecma/builtin-objects/ecma-builtin-function.c index e9499168ad..db46f54426 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-function.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-function.c @@ -24,9 +24,9 @@ #include "js-parser.h" #include "lit-magic-strings.h" -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) +#if ENABLED (JERRY_RESOURCE_NAME) #include "jcontext.h" -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ #define ECMA_BUILTINS_INTERNAL #include "ecma-builtins-internal.h" diff --git a/jerry-core/ecma/operations/ecma-eval.c b/jerry-core/ecma/operations/ecma-eval.c index 69cc4546e8..f499af87c2 100644 --- a/jerry-core/ecma/operations/ecma-eval.c +++ b/jerry-core/ecma/operations/ecma-eval.c @@ -93,9 +93,9 @@ ecma_op_eval_chars_buffer (const lit_utf8_byte_t *code_p, /**< code characters b parse_opts |= ECMA_PARSE_EVAL; -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) +#if ENABLED (JERRY_RESOURCE_NAME) JERRY_CONTEXT (resource_name) = ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_EVAL); -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) */ +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ #if ENABLED (JERRY_ES2015) ECMA_CLEAR_LOCAL_PARSE_OPTS (); diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index 5a4431220d..6f5e3884bd 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -25,6 +25,7 @@ #include "ecma-objects-general.h" #include "ecma-objects-arguments.h" #include "ecma-proxy-object.h" +#include "ecma-symbol-object.h" #include "ecma-try-catch-macro.h" #include "jcontext.h" @@ -35,7 +36,7 @@ * @{ */ -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) +#if ENABLED (JERRY_RESOURCE_NAME) /** * Get the resource name from the compiled code header * @@ -46,22 +47,62 @@ ecma_op_resource_name (const ecma_compiled_code_t *bytecode_header_p) { JERRY_ASSERT (bytecode_header_p != NULL); - uint8_t *byte_p = (uint8_t *) bytecode_header_p; - byte_p += ((size_t) bytecode_header_p->size) << JMEM_ALIGNMENT_LOG; - - ecma_value_t *resource_name_p = (ecma_value_t *) byte_p; - resource_name_p -= ecma_compiled_code_get_formal_params (bytecode_header_p); + return ecma_compiled_code_resolve_function_name (bytecode_header_p)[-1]; +} /* ecma_op_resource_name */ +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ #if ENABLED (JERRY_ES2015) - if (bytecode_header_p->status_flags & CBC_CODE_FLAG_HAS_TAGGED_LITERALS) +/** + * SetFunctionName operation + * + * See also: ECMAScript v6, 9.2.1.1 + * + * @return resource name as ecma-string + */ +ecma_value_t +ecma_op_function_form_name (ecma_value_t prop_name, /**< property name */ + char *prefix_p, /**< prefix */ + lit_utf8_size_t prefix_size) /**< prefix length */ +{ + ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (prop_name); + + /* 4. */ + if (ecma_prop_name_is_symbol (prop_name_p)) { - resource_name_p--; + /* .a */ + ecma_string_t *string_desc_p = ecma_get_symbol_description (prop_name_p); + + /* .b */ + if (ecma_string_is_empty (string_desc_p)) + { + prop_name_p = string_desc_p; + } + /* .c */ + else + { + ecma_stringbuilder_t builder = ecma_stringbuilder_create_raw ((lit_utf8_byte_t *) "[", 1); + ecma_stringbuilder_append (&builder, string_desc_p); + ecma_stringbuilder_append_byte (&builder, (lit_utf8_byte_t) LIT_CHAR_RIGHT_SQUARE); + prop_name_p = ecma_stringbuilder_finalize (&builder); + } + } + else + { + ecma_ref_ecma_string (prop_name_p); } -#endif /* ENABLED (JERRY_ES2015) */ - return resource_name_p[-1]; -} /* ecma_op_resource_name */ -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ + /* 5. */ + if (JERRY_UNLIKELY (prefix_p != NULL)) + { + ecma_stringbuilder_t builder = ecma_stringbuilder_create_raw ((lit_utf8_byte_t *) prefix_p, prefix_size); + ecma_stringbuilder_append (&builder, prop_name_p); + ecma_deref_ecma_string (prop_name_p); + prop_name_p = ecma_stringbuilder_finalize (&builder); + } + + return ecma_make_string_value (prop_name_p); +} /* ecma_op_function_form_name */ +#endif /* ENABLED (JERRY_ES2015) */ /** * IsCallable operation. @@ -328,9 +369,9 @@ ecma_op_create_dynamic_function (const ecma_value_t *arguments_list_p, /**< argu ECMA_STRING_TO_UTF8_STRING (arguments_str_p, arguments_buffer_p, arguments_buffer_size); ECMA_STRING_TO_UTF8_STRING (function_body_str_p, function_body_buffer_p, function_body_buffer_size); -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) +#if ENABLED (JERRY_RESOURCE_NAME) JERRY_CONTEXT (resource_name) = ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON); -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ ecma_compiled_code_t *bytecode_data_p = NULL; @@ -345,6 +386,12 @@ ecma_op_create_dynamic_function (const ecma_value_t *arguments_list_p, /**< argu { JERRY_ASSERT (ecma_is_value_true (ret_value)); +#if ENABLED (JERRY_ES2015) + ecma_value_t *func_name_p; + func_name_p = ecma_compiled_code_resolve_function_name ((const ecma_compiled_code_t *) bytecode_data_p); + *func_name_p = ecma_make_magic_string_value (LIT_MAGIC_STRING_ANONYMOUS); +#endif /* ENABLED (JERRY_ES2015) */ + ecma_object_t *global_env_p = ecma_get_global_environment (); ecma_builtin_id_t fallback_proto = ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE; @@ -1417,6 +1464,34 @@ ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< return NULL; } + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)) + { + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + if (!ECMA_GET_SECOND_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)) + { + /* Set tag bit to represent initialized 'name' property */ + ECMA_SET_SECOND_BIT_TO_POINTER_TAG (ext_func_p->u.function.scope_cp); + const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p); + + ecma_value_t value = *ecma_compiled_code_resolve_function_name (bytecode_data_p); + if (value != ECMA_VALUE_EMPTY) + { + JERRY_ASSERT (ecma_is_value_string (value)); + + /* Initialize 'name' property */ + ecma_property_t *value_prop_p; + ecma_property_value_t *value_p = ecma_create_named_data_property (object_p, + property_name_p, + ECMA_PROPERTY_FLAG_CONFIGURABLE, + &value_prop_p); + value_p->value = ecma_copy_value (value); + return value_prop_p; + } + } + + return NULL; + } #endif /* ENABLED (JERRY_ES2015) */ if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_PROTOTYPE) diff --git a/jerry-core/ecma/operations/ecma-function-object.h b/jerry-core/ecma/operations/ecma-function-object.h index 25e47461f4..262fabf9bd 100644 --- a/jerry-core/ecma/operations/ecma-function-object.h +++ b/jerry-core/ecma/operations/ecma-function-object.h @@ -27,9 +27,13 @@ * @{ */ -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) +#if ENABLED (JERRY_RESOURCE_NAME) ecma_value_t ecma_op_resource_name (const ecma_compiled_code_t *bytecode_header_p); -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ + +#if ENABLED (JERRY_ES2015) +ecma_value_t ecma_op_function_form_name (ecma_value_t prop_name, char *prefix_p, lit_utf8_size_t prefix_size); +#endif /* ENABLED (JERRY_ES2015) */ bool ecma_op_is_callable (ecma_value_t value); bool ecma_op_object_is_callable (ecma_object_t *obj_p); diff --git a/jerry-core/include/jerryscript-snapshot.h b/jerry-core/include/jerryscript-snapshot.h index 291dd5755a..071b0033a1 100644 --- a/jerry-core/include/jerryscript-snapshot.h +++ b/jerry-core/include/jerryscript-snapshot.h @@ -30,7 +30,7 @@ extern "C" /** * Jerry snapshot format version. */ -#define JERRY_SNAPSHOT_VERSION (44u) +#define JERRY_SNAPSHOT_VERSION (45u) /** * Flags for jerry_generate_snapshot and jerry_generate_function_snapshot. diff --git a/jerry-core/jcontext/jcontext.h b/jerry-core/jcontext/jcontext.h index fd655651cc..e609fcac58 100644 --- a/jerry-core/jcontext/jcontext.h +++ b/jerry-core/jcontext/jcontext.h @@ -210,9 +210,9 @@ struct jerry_context_t uint8_t debugger_max_receive_size; /**< maximum amount of data that can be received */ #endif /* ENABLED (JERRY_DEBUGGER) */ -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) +#if ENABLED (JERRY_RESOURCE_NAME) ecma_value_t resource_name; /**< resource name (usually a file name) */ -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ #if ENABLED (JERRY_MEM_STATS) jmem_heap_stats_t jmem_heap_stats; /**< heap's memory usage statistics */ diff --git a/jerry-core/lit/lit-magic-strings.inc.h b/jerry-core/lit/lit-magic-strings.inc.h index 5c8b6c4fc4..c33c6cf18c 100644 --- a/jerry-core/lit/lit-magic-strings.inc.h +++ b/jerry-core/lit/lit-magic-strings.inc.h @@ -301,7 +301,7 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_THROW, "throw") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TRUNC, "trunc") #endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_VALUE, "value") -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) && ENABLED (JERRY_PARSER) +#if ENABLED (JERRY_PARSER) && ENABLED (JERRY_RESOURCE_NAME) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RESOURCE_EVAL, "") #endif #if ENABLED (JERRY_BUILTIN_MATH) @@ -589,6 +589,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TYPE_ERROR_UL, "TypeError") #endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UNDEFINED_UL, "Undefined") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING__PROTO__, "__proto__") +#if ENABLED (JERRY_ES2015) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ANONYMOUS, "anonymous") +#endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ARGUMENTS, "arguments") #if ENABLED (JERRY_ES2015_BUILTIN_PROXY) \ || ENABLED (JERRY_ES2015_BUILTIN_REFLECT) @@ -911,7 +914,7 @@ LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (4, LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_G LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (4, LIT_MAGIC_STRING_DATE_UL) #endif LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (5, LIT_MAGIC_STRING_ARRAY_UL) -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) && ENABLED (JERRY_PARSER) +#if ENABLED (JERRY_PARSER) && ENABLED (JERRY_RESOURCE_NAME) LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (6, LIT_MAGIC_STRING_RESOURCE_EVAL) #elif ENABLED (JERRY_BUILTIN_MATH) LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (6, LIT_MAGIC_STRING_LOG10E_U) diff --git a/jerry-core/lit/lit-magic-strings.ini b/jerry-core/lit/lit-magic-strings.ini index 75180dba16..7ff86da52c 100644 --- a/jerry-core/lit/lit-magic-strings.ini +++ b/jerry-core/lit/lit-magic-strings.ini @@ -232,6 +232,7 @@ LIT_MAGIC_STRING_UNESCAPE = "unescape" LIT_MAGIC_STRING_WRITABLE = "writable" LIT_MAGIC_STRING_NEGATIVE_INFINITY_UL = "-Infinity" LIT_MAGIC_STRING_ARGUMENTS_UL = "Arguments" +LIT_MAGIC_STRING_ANONYMOUS = "anonymous" LIT_MAGIC_STRING_CONSTRUCT = "construct" LIT_MAGIC_STRING_EVAL_ERROR_UL = "EvalError" LIT_MAGIC_STRING_INT8_ARRAY_UL = "Int8Array" diff --git a/jerry-core/parser/js/byte-code.c b/jerry-core/parser/js/byte-code.c index 374a99b2c0..b275a25090 100644 --- a/jerry-core/parser/js/byte-code.c +++ b/jerry-core/parser/js/byte-code.c @@ -21,6 +21,15 @@ JERRY_STATIC_ASSERT ((sizeof (cbc_uint8_arguments_t) % sizeof (jmem_cpointer_t)) JERRY_STATIC_ASSERT ((sizeof (cbc_uint16_arguments_t) % sizeof (jmem_cpointer_t)) == 0, sizeof_cbc_uint16_arguments_t_must_be_divisible_by_sizeof_jmem_cpointer_t); +/** + * The reason of these two static asserts to notify the developer to increase the JERRY_SNAPSHOT_VERSION + * whenever new bytecodes are introduced or existing ones have been deleted. + */ +JERRY_STATIC_ASSERT (CBC_END == 238, + number_of_cbc_opcodes_changed); +JERRY_STATIC_ASSERT (CBC_EXT_END == 115, + number_of_cbc_ext_opcodes_changed); + #if ENABLED (JERRY_PARSER) /** \addtogroup parser Parser diff --git a/jerry-core/parser/js/byte-code.h b/jerry-core/parser/js/byte-code.h index 194d90d093..0bb5d3838d 100644 --- a/jerry-core/parser/js/byte-code.h +++ b/jerry-core/parser/js/byte-code.h @@ -590,28 +590,38 @@ VM_OC_THROW_CONST_ERROR) \ CBC_OPCODE (CBC_EXT_REQUIRE_OBJECT_COERCIBLE, CBC_NO_FLAG, 0, \ VM_OC_REQUIRE_OBJECT_COERCIBLE) \ + CBC_OPCODE (CBC_EXT_SET_FUNCTION_NAME, CBC_HAS_LITERAL_ARG, 0, \ + VM_OC_SET_FUNCTION_NAME | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_SET_CLASS_NAME, CBC_HAS_LITERAL_ARG, 0, \ + VM_OC_SET_FUNCTION_NAME) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_FUNCTION_NAME, CBC_NO_FLAG, 0, \ + VM_OC_SET_FUNCTION_NAME) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_GETTER_NAME, CBC_NO_FLAG, 0, \ + VM_OC_SET_FUNCTION_NAME) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_SETTER_NAME, CBC_NO_FLAG, 0, \ + VM_OC_SET_FUNCTION_NAME) \ \ /* Computed / class property related opcodes. */ \ CBC_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY, CBC_NO_FLAG, -2, \ VM_OC_SET_COMPUTED_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_STACK) \ CBC_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL, CBC_HAS_LITERAL_ARG, -1, \ VM_OC_SET_COMPUTED_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_LITERAL) \ - CBC_OPCODE (CBC_EXT_SET_COMPUTED_GETTER, CBC_HAS_LITERAL_ARG, -1, \ - VM_OC_SET_GETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_LITERAL) \ - CBC_OPCODE (CBC_EXT_SET_COMPUTED_SETTER, CBC_HAS_LITERAL_ARG, -1, \ - VM_OC_SET_SETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_LITERAL) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_GETTER, CBC_NO_FLAG, -2, \ + VM_OC_SET_GETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_STACK) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_SETTER, CBC_NO_FLAG, -2, \ + VM_OC_SET_SETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_STACK) \ CBC_OPCODE (CBC_EXT_SET_STATIC_PROPERTY_LITERAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \ VM_OC_SET_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ - CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_PROPERTY_LITERAL, CBC_HAS_LITERAL_ARG, -1, \ - VM_OC_SET_COMPUTED_PROPERTY | VM_OC_GET_STACK_LITERAL) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_PROPERTY, CBC_NO_FLAG, -2, \ + VM_OC_SET_COMPUTED_PROPERTY | VM_OC_GET_STACK_STACK) \ CBC_OPCODE (CBC_EXT_SET_STATIC_GETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \ VM_OC_SET_GETTER | VM_OC_GET_LITERAL_LITERAL) \ CBC_OPCODE (CBC_EXT_SET_STATIC_SETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \ VM_OC_SET_SETTER | VM_OC_GET_LITERAL_LITERAL) \ - CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_GETTER, CBC_HAS_LITERAL_ARG, -1, \ - VM_OC_SET_GETTER | VM_OC_GET_STACK_LITERAL) \ - CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_SETTER, CBC_HAS_LITERAL_ARG, -1, \ - VM_OC_SET_SETTER | VM_OC_GET_STACK_LITERAL) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_GETTER, CBC_NO_FLAG, -2, \ + VM_OC_SET_GETTER | VM_OC_GET_STACK_STACK) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_SETTER, CBC_NO_FLAG, -2, \ + VM_OC_SET_SETTER | VM_OC_GET_STACK_STACK) \ CBC_OPCODE (CBC_EXT_SET__PROTO__, CBC_NO_FLAG, -1, \ VM_OC_SET__PROTO__ | VM_OC_GET_STACK) \ \ diff --git a/jerry-core/parser/js/js-lexer.h b/jerry-core/parser/js/js-lexer.h index ac1f5ad050..6fe14c3cb4 100644 --- a/jerry-core/parser/js/js-lexer.h +++ b/jerry-core/parser/js/js-lexer.h @@ -174,6 +174,7 @@ typedef enum LEXER_PROPERTY_SETTER, /**< property setter function */ LEXER_COMMA_SEP_LIST, /**< comma separated bracketed expression list */ #if ENABLED (JERRY_ES2015) + LEXER_ASSIGN_GROUP_EXPR, /**< indetifier for the assignment is located in a group expression */ LEXER_ASSIGN_CONST, /**< a const binding is reassigned */ LEXER_CLASS_CONSTRUCTOR, /**< special value for class constructor method */ LEXER_INVALID_PATTERN, /**< special value for invalid destructuring pattern */ diff --git a/jerry-core/parser/js/js-parser-expr.c b/jerry-core/parser/js/js-parser-expr.c index 4059087a74..cc775db548 100644 --- a/jerry-core/parser/js/js-parser-expr.c +++ b/jerry-core/parser/js/js-parser-expr.c @@ -603,7 +603,18 @@ parser_parse_class_literal (parser_context_t *context_p, /**< context */ } } - context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (opcode); + if (is_computed) + { + parser_emit_cbc_ext (context_p, is_getter ? CBC_EXT_SET_COMPUTED_GETTER_NAME + : CBC_EXT_SET_COMPUTED_SETTER_NAME); + parser_emit_cbc_ext (context_p, opcode); + } + else + { + parser_set_function_name (context_p, function_literal_index, literal_index, accessor_status_flags); + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (opcode); + } + is_static = false; continue; } @@ -693,20 +704,29 @@ parser_parse_class_literal (parser_context_t *context_p, /**< context */ CBC_PUSH_LITERAL, function_literal_index); + if (is_computed) + { + parser_emit_cbc_ext (context_p, CBC_EXT_SET_COMPUTED_FUNCTION_NAME); + parser_emit_cbc_ext (context_p, is_static ? CBC_EXT_SET_STATIC_COMPUTED_PROPERTY + : CBC_EXT_SET_COMPUTED_PROPERTY); + is_static = false; + continue; + } + + parser_set_function_name (context_p, function_literal_index, literal_index, 0); + JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL); context_p->last_cbc.value = literal_index; if (is_static) { - context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (is_computed ? CBC_EXT_SET_STATIC_COMPUTED_PROPERTY_LITERAL - : CBC_EXT_SET_STATIC_PROPERTY_LITERAL); + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SET_STATIC_PROPERTY_LITERAL); is_static = false; } else { - context_p->last_cbc_opcode = (is_computed ? PARSER_TO_EXT_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL) - : CBC_SET_LITERAL_PROPERTY); + context_p->last_cbc_opcode = CBC_SET_LITERAL_PROPERTY; } } } /* parser_parse_class_literal */ @@ -721,8 +741,8 @@ parser_parse_class (parser_context_t *context_p, /**< context */ { JERRY_ASSERT (context_p->token.type == LEXER_KEYW_CLASS); - uint16_t class_ident_index = PARSER_MAXIMUM_NUMBER_OF_LITERALS; - uint16_t class_name_index = PARSER_MAXIMUM_NUMBER_OF_LITERALS; + uint16_t class_ident_index = UINT16_MAX; + uint16_t class_name_index = UINT16_MAX; parser_class_literal_opts_t opts = PARSER_CLASS_LITERAL_NO_OPTS; if (context_p->next_scanner_info_p->source_p == context_p->source_p) @@ -763,14 +783,13 @@ parser_parse_class (parser_context_t *context_p, /**< context */ /* Class expression may contain an identifier. */ if (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) { - /* NOTE: If 'Function.name' will be supported, the current literal object must be set to 'name' property. */ lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL); class_name_index = context_p->lit_object.index; lexer_next_token (context_p); } } - if (class_name_index != PARSER_MAXIMUM_NUMBER_OF_LITERALS) + if (class_name_index != UINT16_MAX) { parser_emit_cbc_ext_literal (context_p, CBC_EXT_PUSH_NAMED_CLASS_ENV, class_name_index); } @@ -804,9 +823,10 @@ parser_parse_class (parser_context_t *context_p, /**< context */ /* ClassDeclaration is parsed. Continue with class body. */ parser_parse_class_literal (context_p, opts); - if (class_name_index != PARSER_MAXIMUM_NUMBER_OF_LITERALS) + if (class_name_index != UINT16_MAX) { parser_emit_cbc_ext_literal (context_p, CBC_EXT_FINALIZE_NAMED_CLASS, class_name_index); + parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_FUNCTION_NAME, class_name_index); } else { @@ -824,10 +844,9 @@ parser_parse_class (parser_context_t *context_p, /**< context */ } parser_emit_cbc_literal (context_p, (uint16_t) opcode, class_ident_index); + parser_flush_cbc (context_p); } - parser_flush_cbc (context_p); - if (!is_strict) { /* Restore flag */ @@ -856,6 +875,8 @@ parser_parse_object_method (parser_context_t *context_p) /**< context */ CBC_PUSH_LITERAL, function_literal_index); + context_p->last_cbc.literal_type = LEXER_FUNCTION_LITERAL; + lexer_next_token (context_p); } /* parser_parse_object_method */ @@ -922,8 +943,9 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */ #if !ENABLED (JERRY_ES2015) parser_object_literal_item_types_t item_type; #endif /* !ENABLED (JERRY_ES2015) */ + bool is_getter = context_p->token.type == LEXER_PROPERTY_GETTER; - if (context_p->token.type == LEXER_PROPERTY_GETTER) + if (is_getter) { status_flags = PARSER_FUNCTION_CLOSURE | PARSER_IS_PROPERTY_GETTER; opcode = CBC_EXT_SET_GETTER; @@ -946,7 +968,9 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */ uint16_t literal_index = context_p->lit_object.index; #if ENABLED (JERRY_ES2015) - if (context_p->token.type == LEXER_RIGHT_SQUARE) + bool is_computed = context_p->token.type == LEXER_RIGHT_SQUARE; + + if (is_computed) { opcode = ((opcode == CBC_EXT_SET_GETTER) ? CBC_EXT_SET_COMPUTED_GETTER : CBC_EXT_SET_COMPUTED_SETTER); @@ -969,6 +993,20 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */ literal_index); JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL); + +#if ENABLED (JERRY_ES2015) + if (is_computed) + { + parser_emit_cbc_ext (context_p, is_getter ? CBC_EXT_SET_COMPUTED_GETTER_NAME + : CBC_EXT_SET_COMPUTED_SETTER_NAME); + parser_emit_cbc_ext (context_p, opcode); + lexer_next_token (context_p); + break; + } + + parser_set_function_name (context_p, function_literal_index, literal_index, status_flags); +#endif /* ENABLED (JERRY_ES2015) */ + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (opcode); context_p->last_cbc.value = function_literal_index; @@ -983,9 +1021,18 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */ if (context_p->token.type == LEXER_LEFT_PAREN) { parser_parse_object_method (context_p); - JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL); - context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL); + + if (parser_check_anonymous_function_declaration (context_p) < PARSER_NAMED_FUNCTION) + { + parser_emit_cbc_ext (context_p, CBC_EXT_SET_COMPUTED_FUNCTION_NAME); + parser_emit_cbc_ext (context_p, CBC_EXT_SET_COMPUTED_PROPERTY); + } + else + { + context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL); + } + break; } @@ -997,6 +1044,11 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */ lexer_next_token (context_p); parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + if (parser_check_anonymous_function_declaration (context_p) < PARSER_NAMED_FUNCTION) + { + parser_emit_cbc_ext (context_p, CBC_EXT_SET_COMPUTED_FUNCTION_NAME); + } + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) { context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL); @@ -1028,10 +1080,11 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */ uint16_t opcode = CBC_SET_LITERAL_PROPERTY; /* This assignment is a nop for CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL. */ uint16_t literal_index = context_p->lit_object.index; + bool is_computed = context_p->token.type == LEXER_RIGHT_SQUARE; - if (context_p->token.type == LEXER_RIGHT_SQUARE) + if (is_computed) { - opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL); + opcode = CBC_EXT_SET_COMPUTED_PROPERTY; } uint16_t function_literal_index = lexer_construct_function_object (context_p, status_flags); @@ -1041,6 +1094,17 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */ function_literal_index); JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL); + + if (is_computed) + { + parser_emit_cbc_ext (context_p, CBC_EXT_SET_COMPUTED_FUNCTION_NAME); + parser_emit_cbc_ext (context_p, opcode); + lexer_next_token (context_p); + break; + } + + parser_set_function_name (context_p, function_literal_index, literal_index, status_flags); + context_p->last_cbc_opcode = opcode; context_p->last_cbc.value = literal_index; @@ -1086,6 +1150,7 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */ parser_parse_object_method (context_p); JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL); + parser_set_function_name (context_p, context_p->last_cbc.literal_index, literal_index, 0); context_p->last_cbc_opcode = CBC_SET_LITERAL_PROPERTY; context_p->last_cbc.value = literal_index; break; @@ -1123,11 +1188,24 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */ if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) { +#if ENABLED (JERRY_ES2015) + if (context_p->last_cbc.literal_type == LEXER_FUNCTION_LITERAL) + { + parser_set_function_name (context_p, context_p->last_cbc.literal_index, literal_index, 0); + } +#endif /* ENABLED (JERRY_ES2015) */ context_p->last_cbc_opcode = CBC_SET_LITERAL_PROPERTY; context_p->last_cbc.value = literal_index; } else { +#if ENABLED (JERRY_ES2015) + if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_FINALIZE_ANONYMOUS_CLASS)) + { + uint16_t name_index = scanner_save_literal (context_p, literal_index); + parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_CLASS_NAME, name_index); + } +#endif /* ENABLED (JERRY_ES2015) */ parser_emit_cbc_literal (context_p, CBC_SET_PROPERTY, literal_index); } @@ -1262,6 +1340,13 @@ parser_parse_function_expression (parser_context_t *context_p, /**< context */ JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE); +#if ENABLED (JERRY_ES2015) + if (function_name_index != -1) + { + parser_set_function_name (context_p, function_literal_index, (uint16_t) function_name_index, 0); + } +#endif /* ENABLED (JERRY_ES2015) */ + if (literals == 1) { context_p->last_cbc_opcode = CBC_PUSH_TWO_LITERALS; @@ -2382,6 +2467,11 @@ parser_append_binary_single_assignment_token (parser_context_t *context_p, /**< assign_opcode = CBC_ASSIGN_SET_IDENT; #if ENABLED (JERRY_ES2015) + if (pattern_flags & PARSER_PATTERN_GROUP_EXPR) + { + parser_stack_push_uint8 (context_p, LEXER_ASSIGN_GROUP_EXPR); + } + if (!(pattern_flags & (PARSER_PATTERN_LET | PARSER_PATTERN_CONST | PARSER_PATTERN_LOCAL))) { if (scanner_literal_is_const_reg (context_p, literal_index)) @@ -2574,7 +2664,8 @@ parser_process_binary_opcodes (parser_context_t *context_p, /**< context */ opcode = (cbc_opcode_t) context_p->stack_top_uint8; parser_stack_pop_uint8 (context_p); - int32_t index = -1; + uint16_t index = UINT16_MAX; + if (cbc_flags[opcode] & CBC_HAS_LITERAL_ARG) { JERRY_ASSERT (opcode == CBC_ASSIGN_SET_IDENT @@ -2589,6 +2680,14 @@ parser_process_binary_opcodes (parser_context_t *context_p, /**< context */ } #if ENABLED (JERRY_ES2015) + bool group_expr_assingment = false; + + if (JERRY_UNLIKELY (context_p->stack_top_uint8 == LEXER_ASSIGN_GROUP_EXPR)) + { + group_expr_assingment = true; + parser_stack_pop_uint8 (context_p); + } + if (JERRY_UNLIKELY (context_p->stack_top_uint8 == LEXER_ASSIGN_CONST)) { parser_stack_pop_uint8 (context_p); @@ -2596,20 +2695,37 @@ parser_process_binary_opcodes (parser_context_t *context_p, /**< context */ } #endif /* ENABLED (JERRY_ES2015) */ - if (index >= 0) + if (index != UINT16_MAX) { +#if ENABLED (JERRY_ES2015) + if (!group_expr_assingment) + { + uint16_t function_literal_index = parser_check_anonymous_function_declaration (context_p); + + if (function_literal_index == PARSER_ANONYMOUS_CLASS) + { + uint16_t name_index = scanner_save_literal (context_p, index); + parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_CLASS_NAME, name_index); + } + else if (function_literal_index < PARSER_NAMED_FUNCTION) + { + parser_set_function_name (context_p, function_literal_index, (uint16_t) index, 0); + } + } +#endif /* ENABLED (JERRY_ES2015) */ + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL && opcode == CBC_ASSIGN_SET_IDENT) { JERRY_ASSERT (CBC_ARGS_EQ (CBC_ASSIGN_LITERAL_SET_IDENT, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2)); - context_p->last_cbc.value = (uint16_t) index; + context_p->last_cbc.value = index; context_p->last_cbc_opcode = CBC_ASSIGN_LITERAL_SET_IDENT; continue; } - parser_emit_cbc_literal (context_p, (uint16_t) opcode, (uint16_t) index); + parser_emit_cbc_literal (context_p, (uint16_t) opcode, index); if (opcode == CBC_ASSIGN_PROP_THIS_LITERAL && (context_p->stack_depth >= context_p->stack_limit)) @@ -2803,6 +2919,15 @@ parser_pattern_form_assignment (parser_context_t *context_p, /**< context */ { JERRY_UNUSED (ident_line_counter); + uint16_t name_index = UINT16_MAX; + + if ((flags & PARSER_PATTERN_BINDING) + || (context_p->last_cbc_opcode == CBC_PUSH_LITERAL + && context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL)) + { + name_index = context_p->lit_object.index; + } + parser_stack_push_uint8 (context_p, LEXER_EXPRESSION_START); uint8_t assign_opcode = parser_append_binary_single_assignment_token (context_p, flags); @@ -2823,6 +2948,21 @@ parser_pattern_form_assignment (parser_context_t *context_p, /**< context */ parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_DEFAULT_INITIALIZER, &skip_init); parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA); + + if (name_index != UINT16_MAX) + { + uint16_t function_literal_index = parser_check_anonymous_function_declaration (context_p); + + if (function_literal_index == PARSER_ANONYMOUS_CLASS) + { + name_index = scanner_save_literal (context_p, name_index); + parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_CLASS_NAME, name_index); + } + else if (function_literal_index < PARSER_NAMED_FUNCTION) + { + parser_set_function_name (context_p, function_literal_index, name_index, 0); + } + } parser_set_branch_to_current_position (context_p, &skip_init); } @@ -3240,14 +3380,16 @@ parser_process_expression_sequence (parser_context_t *context_p) /**< context */ /** * Process group expression. */ -static void +static bool parser_process_group_expression (parser_context_t *context_p, /**< context */ size_t *grouping_level_p) /**< grouping level */ { JERRY_ASSERT (*grouping_level_p >= PARSER_GROUPING_LEVEL_INCREASE); (*grouping_level_p) -= PARSER_GROUPING_LEVEL_INCREASE; - if (context_p->stack_top_uint8 == LEXER_COMMA_SEP_LIST) + uint8_t token = context_p->stack_top_uint8; + + if (token == LEXER_COMMA_SEP_LIST) { parser_push_result (context_p); parser_flush_cbc (context_p); @@ -3255,6 +3397,22 @@ parser_process_group_expression (parser_context_t *context_p, /**< context */ parser_stack_pop_uint8 (context_p); lexer_next_token (context_p); + + if (context_p->token.type == LEXER_ASSIGN) + { + uint32_t flags = 0; +#if ENABLED (JERRY_ES2015) + if (JERRY_UNLIKELY (token == LEXER_LEFT_PAREN)) + { + flags = PARSER_PATTERN_GROUP_EXPR; + } +#endif /* ENABLED (JERRY_ES2015) */ + parser_append_binary_single_assignment_token (context_p, flags); + lexer_next_token (context_p); + return true; + } + + return false; } /* parser_process_group_expression */ /** @@ -3315,6 +3473,7 @@ parser_parse_expression (parser_context_t *context_p, /**< context */ while (true) { +parse_unary_expression: if (parser_parse_unary_expression (context_p, &grouping_level)) { parser_process_binary_opcodes (context_p, 0); @@ -3361,7 +3520,10 @@ parser_parse_expression (parser_context_t *context_p, /**< context */ && (context_p->stack_top_uint8 == LEXER_LEFT_PAREN || context_p->stack_top_uint8 == LEXER_COMMA_SEP_LIST)) { - parser_process_group_expression (context_p, &grouping_level); + if (parser_process_group_expression (context_p, &grouping_level)) + { + goto parse_unary_expression; + } continue; } diff --git a/jerry-core/parser/js/js-parser-internal.h b/jerry-core/parser/js/js-parser-internal.h index 5f8cd9f832..a9facea6ce 100644 --- a/jerry-core/parser/js/js-parser-internal.h +++ b/jerry-core/parser/js/js-parser-internal.h @@ -116,6 +116,7 @@ typedef enum PARSER_PATTERN_REST_ELEMENT = (1u << 7), /**< parse rest array initializer */ PARSER_PATTERN_ARGUMENTS = (1u << 8), /**< parse arguments binding */ PARSER_PATTERN_ARRAY = (1u << 9), /**< array pattern is being parsed */ + PARSER_PATTERN_GROUP_EXPR = (1u << 10), /**< group expression is being assigned */ } parser_pattern_flags_t; /** @@ -415,6 +416,21 @@ typedef struct */ #define PARSER_REGISTER_START 0x8000 +/** + * Lastly emitted opcode is not a function literal + */ +#define PARSER_NOT_FUNCTION_LITERAL UINT16_MAX + +/** + * Lastly emitted opcode is not a named function literal + */ +#define PARSER_NAMED_FUNCTION (uint16_t) (PARSER_NOT_FUNCTION_LITERAL - 1) + +/** + * Lastly emitted opcode is not an anonymous class literal + */ +#define PARSER_ANONYMOUS_CLASS (uint16_t) (PARSER_NAMED_FUNCTION - 1) + /* Forward definitions for js-scanner-internal.h. */ struct scanner_context_t; typedef struct scanner_context_t scanner_context_t; @@ -692,6 +708,7 @@ void lexer_convert_ident_to_cesu8 (uint8_t *destination_p, const uint8_t *source const uint8_t *lexer_convert_literal_to_chars (parser_context_t *context_p, const lexer_lit_location_t *literal_p, uint8_t *local_byte_array_p, lexer_string_options_t opts); void lexer_expect_object_literal_id (parser_context_t *context_p, uint32_t ident_opts); +uint16_t scanner_save_literal (parser_context_t *context_p, uint16_t ident_index); void lexer_construct_literal_object (parser_context_t *context_p, const lexer_lit_location_t *lit_location_p, uint8_t literal_type); bool lexer_construct_number_object (parser_context_t *context_p, bool is_expr, bool is_negative_number); @@ -814,6 +831,11 @@ void parser_module_add_names_to_node (parser_context_t *context_p, ecma_compiled_code_t *parser_parse_function (parser_context_t *context_p, uint32_t status_flags); #if ENABLED (JERRY_ES2015) ecma_compiled_code_t *parser_parse_arrow_function (parser_context_t *context_p, uint32_t status_flags); +void parser_set_function_name (parser_context_t *context_p, uint16_t function_literal_index, uint16_t name_index, + uint32_t status_flags); +void parser_compiled_code_set_function_name (parser_context_t *context_p, ecma_compiled_code_t *bytecode_p, + uint16_t name_index, uint32_t status_flags); +uint16_t parser_check_anonymous_function_declaration (parser_context_t *context_p); #endif /* ENABLED (JERRY_ES2015) */ /* Error management. */ diff --git a/jerry-core/parser/js/js-parser-statm.c b/jerry-core/parser/js/js-parser-statm.c index 828ba54d75..00d8bdce08 100644 --- a/jerry-core/parser/js/js-parser-statm.c +++ b/jerry-core/parser/js/js-parser-statm.c @@ -571,6 +571,18 @@ parser_parse_var_statement (parser_context_t *context_p) /**< context */ cbc_opcode_t opcode = CBC_ASSIGN_SET_IDENT; #if ENABLED (JERRY_ES2015) + uint16_t function_literal_index = parser_check_anonymous_function_declaration (context_p); + + if (function_literal_index == PARSER_ANONYMOUS_CLASS) + { + uint16_t name_index = scanner_save_literal (context_p, index); + parser_emit_cbc_ext_literal (context_p, CBC_EXT_SET_CLASS_NAME, name_index); + } + else if (function_literal_index < PARSER_NAMED_FUNCTION) + { + parser_set_function_name (context_p, function_literal_index, index, 0); + } + if (declaration_type != LEXER_KEYW_VAR && (index < PARSER_REGISTER_START)) { @@ -706,6 +718,7 @@ parser_parse_function_statement (parser_context_t *context_p) /**< context */ #endif /* ENABLED (JERRY_ES2015) */ #if ENABLED (JERRY_ES2015_MODULE_SYSTEM) + uint16_t function_name_index = context_p->lit_object.index; parser_module_append_export_name (context_p); context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_STORE_IDENT); #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ @@ -828,6 +841,10 @@ parser_parse_function_statement (parser_context_t *context_p) /**< context */ literal_p->u.bytecode_p = compiled_code_p; literal_p->type = LEXER_FUNCTION_LITERAL; +#if ENABLED (JERRY_ES2015) + parser_compiled_code_set_function_name (context_p, compiled_code_p, function_name_index, 0); +#endif /* ENABLED (JERRY_ES2015) */ + lexer_next_token (context_p); } /* parser_parse_function_statement */ @@ -2623,13 +2640,13 @@ parser_parse_statements (parser_context_t *context_p) /**< context */ } #endif /* ENABLED (JERRY_DEBUGGER) */ -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) +#if ENABLED (JERRY_RESOURCE_NAME) if (JERRY_CONTEXT (resource_name) != ECMA_VALUE_UNDEFINED) { parser_emit_cbc_ext (context_p, CBC_EXT_RESOURCE_NAME); parser_flush_cbc (context_p); } -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ #if ENABLED (JERRY_LINE_INFO) context_p->last_line_info_line = 0; #endif /* ENABLED (JERRY_LINE_INFO) */ diff --git a/jerry-core/parser/js/js-parser.c b/jerry-core/parser/js/js-parser.c index 519440b56c..9298d728ee 100644 --- a/jerry-core/parser/js/js-parser.c +++ b/jerry-core/parser/js/js-parser.c @@ -1191,18 +1191,24 @@ parser_post_processing (parser_context_t *context_p) /**< context */ } #if ENABLED (JERRY_ES2015) + /* function.name */ + if (!(context_p->status_flags & PARSER_CLASS_CONSTRUCTOR)) + { + total_size += sizeof (ecma_value_t); + } + if (context_p->tagged_template_literal_cp != JMEM_CP_NULL) { total_size += sizeof (ecma_value_t); } #endif /* ENABLED (JERRY_ES2015) */ -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) +#if ENABLED (JERRY_RESOURCE_NAME) if (JERRY_CONTEXT (resource_name) != ECMA_VALUE_UNDEFINED) { total_size += sizeof (ecma_value_t); } -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ #if ENABLED (JERRY_SNAPSHOT_SAVE) total_size_used = total_size; @@ -1590,13 +1596,14 @@ parser_post_processing (parser_context_t *context_p) /**< context */ } #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */ + ecma_value_t *base_p = (ecma_value_t *) (((uint8_t *) compiled_code_p) + total_size); + if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags)) { 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; + base_p -= context_p->argument_count; parser_list_iterator_init (&context_p->literal_pool, &literal_iterator); while (argument_count < context_p->argument_count) @@ -1614,7 +1621,7 @@ parser_post_processing (parser_context_t *context_p) /**< context */ /* All arguments must be moved to initialized registers. */ if (literal_p->type == LEXER_UNUSED_LITERAL) { - argument_base_p[argument_count] = ECMA_VALUE_EMPTY; + base_p[argument_count] = ECMA_VALUE_EMPTY; argument_count++; continue; } @@ -1623,22 +1630,29 @@ parser_post_processing (parser_context_t *context_p) /**< context */ JERRY_ASSERT (literal_p->prop.index >= register_count); - argument_base_p[argument_count] = literal_pool_p[literal_p->prop.index]; + base_p[argument_count] = literal_pool_p[literal_p->prop.index]; argument_count++; } } #if ENABLED (JERRY_ES2015) - if (context_p->tagged_template_literal_cp != JMEM_CP_NULL) + if (!(context_p->status_flags & PARSER_CLASS_CONSTRUCTOR)) { - ecma_value_t *tagged_base_p = (ecma_value_t *) (((uint8_t *) compiled_code_p) + total_size); + *(--base_p) = ECMA_VALUE_EMPTY; + } +#endif /* ENABLED (JERRY_ES2015) */ - if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags)) - { - tagged_base_p -= context_p->argument_count; - } +#if ENABLED (JERRY_RESOURCE_NAME) + if (JERRY_CONTEXT (resource_name) != ECMA_VALUE_UNDEFINED) + { + *(--base_p) = JERRY_CONTEXT (resource_name); + } +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ - tagged_base_p[-1] = (ecma_value_t) context_p->tagged_template_literal_cp; +#if ENABLED (JERRY_ES2015) + if (context_p->tagged_template_literal_cp != JMEM_CP_NULL) + { + base_p[-1] = (ecma_value_t) context_p->tagged_template_literal_cp; ecma_collection_t *collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, context_p->tagged_template_literal_cp); @@ -1650,27 +1664,6 @@ parser_post_processing (parser_context_t *context_p) /**< context */ } #endif /* ENABLED (JERRY_ES2015) */ -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) - if (JERRY_CONTEXT (resource_name) != ECMA_VALUE_UNDEFINED) - { - ecma_value_t *resource_name_p = (ecma_value_t *) (((uint8_t *) compiled_code_p) + total_size); - - if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags)) - { - resource_name_p -= context_p->argument_count; - } - -#if ENABLED (JERRY_ES2015) - if (context_p->tagged_template_literal_cp != JMEM_CP_NULL) - { - resource_name_p--; - } -#endif /* ENABLED (JERRY_ES2015) */ - - resource_name_p[-1] = JERRY_CONTEXT (resource_name); - } -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ - #if ENABLED (JERRY_DEBUGGER) if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) { @@ -2599,6 +2592,124 @@ parser_parse_arrow_function (parser_context_t *context_p, /**< context */ return compiled_code_p; } /* parser_parse_arrow_function */ +/** + * Check whether the last emitted cbc opcode was an anonymous function declaration + * + * @return PARSER_NOT_FUNCTION_LITERAL - if the last opcode is not a function literal + * PARSER_NAMED_FUNCTION - if the last opcode is not a named function declataion + * PARSER_ANONYMOUS_CLASS - if the last opcode is an anonymous class declaration + * literal index of the anonymous function literal - otherwise + */ +uint16_t +parser_check_anonymous_function_declaration (parser_context_t *context_p) /**< context */ +{ + if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_FINALIZE_ANONYMOUS_CLASS)) + { + return PARSER_ANONYMOUS_CLASS; + } + + if (context_p->last_cbc.literal_type != LEXER_FUNCTION_LITERAL) + { + return PARSER_NOT_FUNCTION_LITERAL; + } + + uint16_t literal_index = PARSER_NOT_FUNCTION_LITERAL; + + if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL) + { + literal_index = context_p->last_cbc.literal_index; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_TWO_LITERALS) + { + literal_index = context_p->last_cbc.value; + } + else if (context_p->last_cbc_opcode == CBC_PUSH_THREE_LITERALS) + { + literal_index = context_p->last_cbc.third_literal_index; + } + else + { + return PARSER_NOT_FUNCTION_LITERAL; + } + + const ecma_compiled_code_t *bytecode_p; + bytecode_p = (const ecma_compiled_code_t *) (PARSER_GET_LITERAL (literal_index)->u.bytecode_p); + ecma_value_t *func_name_start_p = ecma_compiled_code_resolve_function_name (bytecode_p); + + return (*func_name_start_p == ECMA_VALUE_EMPTY ? literal_index : PARSER_NAMED_FUNCTION); +} /* parser_check_anonymous_function_declaration */ + +/** + * Set the function name of the function literal corresponds to the given function literal index + * to the given character buffer of literal corresponds to the given name index. + */ +void +parser_set_function_name (parser_context_t *context_p, /**< context */ + uint16_t function_literal_index, /**< function literal index */ + uint16_t name_index, /**< function name literal index */ + uint32_t status_flags) /**< status flags */ +{ + ecma_compiled_code_t *bytecode_p; + bytecode_p = (ecma_compiled_code_t *) (PARSER_GET_LITERAL (function_literal_index)->u.bytecode_p); + + parser_compiled_code_set_function_name (context_p, bytecode_p, name_index, status_flags); +} /* parser_set_function_name */ + +/** + * Set the function name of the given compiled code + * to the given character buffer of literal corresponds to the given name index. + */ +void +parser_compiled_code_set_function_name (parser_context_t *context_p, /**< context */ + ecma_compiled_code_t *bytecode_p, /**< function literal index */ + uint16_t name_index, /**< function name literal index */ + uint32_t status_flags) /**< status flags */ +{ + ecma_value_t *func_name_start_p; + func_name_start_p = ecma_compiled_code_resolve_function_name ((const ecma_compiled_code_t *) bytecode_p); + + if (JERRY_UNLIKELY (*func_name_start_p != ECMA_VALUE_EMPTY)) + { + return; + } + + parser_scope_stack_t *scope_stack_start_p = context_p->scope_stack_p; + parser_scope_stack_t *scope_stack_p = scope_stack_start_p + context_p->scope_stack_top; + + while (scope_stack_p > scope_stack_start_p) + { + scope_stack_p--; + + if (scope_stack_p->map_from != PARSER_SCOPE_STACK_FUNC + && scanner_decode_map_to (scope_stack_p) == name_index) + { + name_index = scope_stack_p->map_from; + break; + } + } + + lexer_literal_t *name_lit_p = (lexer_literal_t *) PARSER_GET_LITERAL (name_index); + + uint8_t *name_buffer_p = (uint8_t *) name_lit_p->u.char_p; + uint32_t name_length = name_lit_p->prop.length; + + if (status_flags & (PARSER_IS_PROPERTY_GETTER | PARSER_IS_PROPERTY_SETTER)) + { + name_length += 4; + name_buffer_p = (uint8_t *) parser_malloc (context_p, name_length * sizeof (uint8_t)); + char *prefix_p = (status_flags & PARSER_IS_PROPERTY_GETTER) ? "get " : "set "; + memcpy (name_buffer_p, prefix_p, 4); + memcpy (name_buffer_p + 4, name_lit_p->u.char_p, name_lit_p->prop.length); + } + + *func_name_start_p = ecma_find_or_create_literal_string (name_buffer_p, name_length); + + if (name_buffer_p != name_lit_p->u.char_p) + { + parser_free (name_buffer_p, name_length); + } +} /* parser_compiled_code_set_function_name */ + #endif /* ENABLED (JERRY_ES2015) */ /** diff --git a/jerry-core/parser/js/js-scanner-util.c b/jerry-core/parser/js/js-scanner-util.c index f2d6235638..bc2ccde2a5 100644 --- a/jerry-core/parser/js/js-scanner-util.c +++ b/jerry-core/parser/js/js-scanner-util.c @@ -2429,6 +2429,38 @@ scanner_decode_map_to (parser_scope_stack_t *stack_item_p) /**< scope stack item #if ENABLED (JERRY_ES2015) +/** + * Find the given literal index in the scope stack + * and save it the constant literal pool if the literal is register stored + * + * @return given literal index - if literal corresponds to this index is not register stored + * literal index on which literal index has been mapped - otherwise + */ +uint16_t +scanner_save_literal (parser_context_t *context_p, /**< context */ + uint16_t literal_index) /**< literal index */ +{ + if (literal_index >= PARSER_REGISTER_START) + { + literal_index = (uint16_t) (literal_index - (PARSER_REGISTER_START - 1)); + + parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top; + + do + { + /* Registers must be found in the scope stack. */ + JERRY_ASSERT (scope_stack_p > context_p->scope_stack_p); + scope_stack_p--; + } + while (literal_index != (scope_stack_p->map_to & PARSER_SCOPE_STACK_REGISTER_MASK)); + + literal_index = scope_stack_p->map_from; + PARSER_GET_LITERAL (literal_index)->status_flags |= LEXER_FLAG_USED; + } + + return literal_index; +} /* scanner_save_literal */ + /** * Checks whether the literal is a const in the current scope. * diff --git a/jerry-core/vm/vm-defines.h b/jerry-core/vm/vm-defines.h index f328fcff85..d20fe348f8 100644 --- a/jerry-core/vm/vm-defines.h +++ b/jerry-core/vm/vm-defines.h @@ -49,9 +49,9 @@ typedef struct vm_frame_ctx_t struct vm_frame_ctx_t *prev_context_p; /**< previous context */ ecma_value_t this_binding; /**< this binding */ ecma_value_t block_result; /**< block result */ -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) +#if ENABLED (JERRY_RESOURCE_NAME) ecma_value_t resource_name; /**< current resource name (usually a file name) */ -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ #if ENABLED (JERRY_LINE_INFO) uint32_t current_line; /**< currently executed line */ #endif /* ENABLED (JERRY_LINE_INFO) */ diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index 10a5dc9a5f..ea57a7f62e 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -1829,6 +1829,64 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ goto free_left_value; } + case VM_OC_SET_FUNCTION_NAME: + { + char *prefix_p = NULL; + lit_utf8_size_t prefix_size = 0; + + if (opcode == CBC_EXT_SET_CLASS_NAME) + { + uint16_t literal_index; + READ_LITERAL_INDEX (literal_index); + left_value = ecma_copy_value (literal_start_p[literal_index]); + } + else if (opcode != CBC_EXT_SET_FUNCTION_NAME) + { + ecma_string_t *prop_name_p = ecma_op_to_prop_name (stack_top_p[-2]); + + if (JERRY_UNLIKELY (prop_name_p == NULL)) + { + result = ECMA_VALUE_ERROR; + goto error; + } + + ecma_free_value (stack_top_p[-2]); + ecma_ref_ecma_string (prop_name_p); + left_value = ecma_make_prop_name_value (prop_name_p); + stack_top_p[-2] = left_value; + + if (opcode != CBC_EXT_SET_COMPUTED_FUNCTION_NAME) + { + JERRY_ASSERT (opcode == CBC_EXT_SET_COMPUTED_GETTER_NAME + || opcode == CBC_EXT_SET_COMPUTED_SETTER_NAME); + prefix_p = (opcode == CBC_EXT_SET_COMPUTED_GETTER_NAME) ? "get " : "set "; + prefix_size = 4; + } + } + + ecma_object_t *func_obj_p = ecma_get_object_from_value (stack_top_p[-1]); + + if (ecma_find_named_property (func_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_NAME)) != NULL) + { + ecma_free_value (left_value); + continue; + } + + ecma_property_value_t *value_p; + value_p = ecma_create_named_data_property (func_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_NAME), + ECMA_PROPERTY_FLAG_CONFIGURABLE, + NULL); + + if (ecma_get_object_type (func_obj_p) != ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION) + { + ECMA_SET_SECOND_BIT_TO_POINTER_TAG (((ecma_extended_object_t *) func_obj_p)->u.function.scope_cp); + } + + value_p->value = ecma_op_function_form_name (left_value, prefix_p, prefix_size); + ecma_free_value (left_value); + continue; + } case VM_OC_PUSH_SPREAD_ELEMENT: { *stack_top_p++ = ECMA_VALUE_SPREAD_ELEMENT; @@ -3737,13 +3795,13 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ continue; } #endif /* ENABLED (JERRY_DEBUGGER) */ -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) +#if ENABLED (JERRY_RESOURCE_NAME) case VM_OC_RESOURCE_NAME: { frame_ctx_p->resource_name = ecma_op_resource_name (bytecode_header_p); continue; } -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ #if ENABLED (JERRY_LINE_INFO) case VM_OC_LINE: { @@ -4027,9 +4085,9 @@ vm_init_exec (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ { frame_ctx_p->prev_context_p = JERRY_CONTEXT (vm_top_context_p); frame_ctx_p->block_result = ECMA_VALUE_UNDEFINED; -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) +#if ENABLED (JERRY_RESOURCE_NAME) frame_ctx_p->resource_name = ECMA_VALUE_UNDEFINED; -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ #if ENABLED (JERRY_LINE_INFO) frame_ctx_p->current_line = 0; #endif /* ENABLED (JERRY_LINE_INFO) */ diff --git a/jerry-core/vm/vm.h b/jerry-core/vm/vm.h index a47ade919e..627ec8bdb5 100644 --- a/jerry-core/vm/vm.h +++ b/jerry-core/vm/vm.h @@ -225,9 +225,9 @@ typedef enum VM_OC_BREAKPOINT_ENABLED, /**< enabled breakpoint for debugger */ VM_OC_BREAKPOINT_DISABLED, /**< disabled breakpoint for debugger */ #endif /* ENABLED (JERRY_DEBUGGER) */ -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) +#if ENABLED (JERRY_RESOURCE_NAME) VM_OC_RESOURCE_NAME, /**< resource name of the current function */ -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ +#endif /* ENABLED (JERRY_RESOURCE_NAME) */ #if ENABLED (JERRY_LINE_INFO) VM_OC_LINE, /**< line number of the next statement */ #endif /* ENABLED (JERRY_LINE_INFO) */ @@ -254,6 +254,7 @@ typedef enum VM_OC_PUSH_SUPER_CONSTRUCTOR, /**< getSuperConstructor operation */ VM_OC_RESOLVE_LEXICAL_THIS, /**< resolve this_binding from from the lexical environment */ VM_OC_SUPER_REFERENCE, /**< push super reference */ + VM_OC_SET_FUNCTION_NAME, /**< set function name property */ VM_OC_PUSH_SPREAD_ELEMENT, /**< push spread element */ VM_OC_GET_ITERATOR, /**< GetIterator abstract operation */ @@ -290,9 +291,9 @@ typedef enum VM_OC_BREAKPOINT_ENABLED = VM_OC_NONE, /**< enabled breakpoint for debugger is unused */ VM_OC_BREAKPOINT_DISABLED = VM_OC_NONE, /**< disabled breakpoint for debugger is unused */ #endif /* !ENABLED (JERRY_DEBUGGER) */ -#if !ENABLED (JERRY_LINE_INFO) && !ENABLED (JERRY_ES2015_MODULE_SYSTEM) +#if !ENABLED (JERRY_RESOURCE_NAME) VM_OC_RESOURCE_NAME = VM_OC_NONE, /**< resource name of the current function is unused */ -#endif /* !ENABLED (JERRY_LINE_INFO) && !ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ +#endif /* !ENABLED (JERRY_RESOURCE_NAME) */ #if !ENABLED (JERRY_LINE_INFO) VM_OC_LINE = VM_OC_NONE, /**< line number of the next statement is unused */ #endif /* !ENABLED (JERRY_LINE_INFO) */ @@ -319,6 +320,7 @@ typedef enum VM_OC_PUSH_SUPER_CONSTRUCTOR = VM_OC_NONE, /**< getSuperConstructor operation */ VM_OC_RESOLVE_LEXICAL_THIS = VM_OC_NONE, /**< resolve this_binding from from the lexical environment */ VM_OC_SUPER_REFERENCE = VM_OC_NONE, /**< push super reference */ + VM_OC_SET_FUNCTION_NAME = VM_OC_NONE, /**< set function name property */ VM_OC_PUSH_SPREAD_ELEMENT = VM_OC_NONE, /**< push spread element */ VM_OC_GET_ITERATOR = VM_OC_NONE, /**< GetIterator abstract operation */ diff --git a/tests/test262-es6-excludelist.xml b/tests/test262-es6-excludelist.xml index 0ab5852cad..ead4a8ce93 100644 --- a/tests/test262-es6-excludelist.xml +++ b/tests/test262-es6-excludelist.xml @@ -57,17 +57,11 @@ - - - - - - @@ -444,40 +438,17 @@ - - - - - - - - - - - - - - - - - - - - - - - @@ -489,7 +460,6 @@ - @@ -502,29 +472,13 @@ - - - - - - - - - - - - - - - - @@ -579,11 +533,6 @@ - - - - - @@ -592,15 +541,9 @@ - - - - - - @@ -613,20 +556,8 @@ - - - - - - - - - - - - diff --git a/tests/unit-core/test-snapshot.c b/tests/unit-core/test-snapshot.c index 8c1a39ed02..8e33d436f8 100644 --- a/tests/unit-core/test-snapshot.c +++ b/tests/unit-core/test-snapshot.c @@ -195,79 +195,13 @@ static void test_exec_snapshot (uint32_t *snapshot_p, size_t snapshot_size, uint int main (void) { - static uint32_t snapshot_buffer[SNAPSHOT_BUFFER_SIZE]; - TEST_INIT (); - /* Dump / execute snapshot */ - if (jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_SAVE) - && jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_EXEC)) - { - const jerry_char_t code_to_snapshot[] = "(function () { return 'string from snapshot'; }) ();"; - - jerry_init (JERRY_INIT_EMPTY); - jerry_value_t generate_result; - generate_result = jerry_generate_snapshot (NULL, - 0, - code_to_snapshot, - sizeof (code_to_snapshot) - 1, - 0, - snapshot_buffer, - SNAPSHOT_BUFFER_SIZE); - TEST_ASSERT (!jerry_value_is_error (generate_result) - && jerry_value_is_number (generate_result)); - - size_t snapshot_size = (size_t) jerry_get_number_value (generate_result); - jerry_release_value (generate_result); - - /* Check the snapshot data. Unused bytes should be filled with zeroes */ - const uint8_t expected_data[] = - { - 0x4A, 0x52, 0x52, 0x59, 0x2C, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x01, 0x00, 0x41, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00, - 0x2C, 0x00, 0xC9, 0x53, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x01, 0x00, 0x41, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x01, 0x07, 0x00, 0x00, 0x00, - 0x54, 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, - }; - - if (sizeof (expected_data) != snapshot_size || memcmp (expected_data, snapshot_buffer, sizeof (expected_data))) - { - printf ("Snapshot data has been changed, please update tests/unit-core/test-snapshot.c.\n"); - printf ("-------------------------------------------------------------------------------\n"); - printf (" const uint8_t expected_data[] =\n"); - printf (" {"); - for (unsigned int i = 0; i < snapshot_size; i++) - { - if ((i % 8) == 0) - { - printf ("\n "); - } - printf (" 0x%02X,", ((uint8_t *) snapshot_buffer)[i]); - } - printf ("\n };\n"); - printf ("-------------------------------------------------------------------------------\n"); - } - - TEST_ASSERT (sizeof (expected_data) == snapshot_size); - TEST_ASSERT (0 == memcmp (expected_data, snapshot_buffer, sizeof (expected_data))); - - jerry_cleanup (); - - test_exec_snapshot (snapshot_buffer, snapshot_size, 0); - test_exec_snapshot (snapshot_buffer, snapshot_size, JERRY_SNAPSHOT_EXEC_COPY_DATA); - } - /* Static snapshot */ if (jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_SAVE) && jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_EXEC)) { + static uint32_t snapshot_buffer[SNAPSHOT_BUFFER_SIZE]; const jerry_char_t code_to_snapshot[] = TEST_STRING_LITERAL ( "function func(a, b, c) {" " c = 'snapshot';" @@ -417,10 +351,6 @@ main (void) size_t snapshot_size = (size_t) jerry_get_number_value (generate_result); jerry_release_value (generate_result); - /* In ES2015 we emit extra bytecode instructions to check global variable redeclaration. */ - const size_t expected_size = (jerry_is_feature_enabled (JERRY_FEATURE_SYMBOL)) ? 132 : 124; - TEST_ASSERT (snapshot_size == expected_size); - const size_t lit_c_buf_sz = jerry_get_literals_from_snapshot (literal_snapshot_buffer, snapshot_size, literal_buffer_c,