diff --git a/jerry-core/api/jerry.c b/jerry-core/api/jerry.c index 1f0541cac..f13cd5112 100644 --- a/jerry-core/api/jerry.c +++ b/jerry-core/api/jerry.c @@ -4055,7 +4055,7 @@ jerry_get_resource_name (const jerry_value_t value) /**< jerry api value */ { if (JERRY_CONTEXT (vm_top_context_p) != NULL) { - return ecma_copy_value (ecma_get_resource_name (JERRY_CONTEXT (vm_top_context_p)->bytecode_header_p)); + return ecma_copy_value (ecma_get_resource_name (JERRY_CONTEXT (vm_top_context_p)->shared_p->bytecode_header_p)); } } else if (ecma_is_value_object (value)) diff --git a/jerry-core/debugger/debugger.c b/jerry-core/debugger/debugger.c index d3a88b699..adb644f97 100644 --- a/jerry-core/debugger/debugger.c +++ b/jerry-core/debugger/debugger.c @@ -131,7 +131,7 @@ jerry_debugger_send_backtrace (const uint8_t *recv_buffer_p) /**< pointer to the uint32_t frame_count = 0; while (iter_frame_ctx_p != NULL) { - if (!(iter_frame_ctx_p->bytecode_header_p->status_flags & (CBC_CODE_FLAGS_STATIC_FUNCTION))) + if (!(iter_frame_ctx_p->shared_p->bytecode_header_p->status_flags & (CBC_CODE_FLAGS_STATIC_FUNCTION))) { frame_count++; } @@ -164,7 +164,7 @@ jerry_debugger_send_backtrace (const uint8_t *recv_buffer_p) /**< pointer to the while (frame_ctx_p != NULL && min_depth_offset++ < max_depth) { - if (frame_ctx_p->bytecode_header_p->status_flags + if (frame_ctx_p->shared_p->bytecode_header_p->status_flags & (CBC_CODE_FLAGS_DEBUGGER_IGNORE | CBC_CODE_FLAGS_STATIC_FUNCTION)) { frame_ctx_p = frame_ctx_p->prev_context_p; @@ -183,10 +183,10 @@ jerry_debugger_send_backtrace (const uint8_t *recv_buffer_p) /**< pointer to the jerry_debugger_frame_t *frame_p = backtrace_p->frames + current_frame; jmem_cpointer_t byte_code_cp; - JMEM_CP_SET_NON_NULL_POINTER (byte_code_cp, frame_ctx_p->bytecode_header_p); + JMEM_CP_SET_NON_NULL_POINTER (byte_code_cp, frame_ctx_p->shared_p->bytecode_header_p); memcpy (frame_p->byte_code_cp, &byte_code_cp, sizeof (jmem_cpointer_t)); - uint32_t offset = (uint32_t) (frame_ctx_p->byte_code_p - (uint8_t *) frame_ctx_p->bytecode_header_p); + uint32_t offset = (uint32_t) (frame_ctx_p->byte_code_p - (uint8_t *) frame_ctx_p->shared_p->bytecode_header_p); memcpy (frame_p->offset, &offset, sizeof (uint32_t)); frame_ctx_p = frame_ctx_p->prev_context_p; @@ -1167,10 +1167,10 @@ jerry_debugger_breakpoint_hit (uint8_t message_type) /**< message type */ vm_frame_ctx_t *frame_ctx_p = JERRY_CONTEXT (vm_top_context_p); jmem_cpointer_t byte_code_header_cp; - JMEM_CP_SET_NON_NULL_POINTER (byte_code_header_cp, frame_ctx_p->bytecode_header_p); + JMEM_CP_SET_NON_NULL_POINTER (byte_code_header_cp, frame_ctx_p->shared_p->bytecode_header_p); memcpy (breakpoint_hit_p->byte_code_cp, &byte_code_header_cp, sizeof (jmem_cpointer_t)); - uint32_t offset = (uint32_t) (frame_ctx_p->byte_code_p - (uint8_t *) frame_ctx_p->bytecode_header_p); + uint32_t offset = (uint32_t) (frame_ctx_p->byte_code_p - (uint8_t *) frame_ctx_p->shared_p->bytecode_header_p); memcpy (breakpoint_hit_p->offset, &offset, sizeof (uint32_t)); if (!jerry_debugger_send (sizeof (jerry_debugger_send_breakpoint_hit_t))) diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index 63b14ac4e..82c2111d7 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -450,7 +450,7 @@ ecma_gc_mark_executable_object (ecma_object_t *object_p) /**< object */ ecma_gc_set_object_visited (ecma_get_object_from_value (executable_object_p->frame_ctx.this_binding)); } - const ecma_compiled_code_t *bytecode_header_p = executable_object_p->frame_ctx.bytecode_header_p; + const ecma_compiled_code_t *bytecode_header_p = executable_object_p->shared.bytecode_header_p; size_t register_end; if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) @@ -953,7 +953,7 @@ ecma_gc_free_executable_object (ecma_object_t *object_p) /**< object */ { vm_executable_object_t *executable_object_p = (vm_executable_object_t *) object_p; - const ecma_compiled_code_t *bytecode_header_p = executable_object_p->frame_ctx.bytecode_header_p; + const ecma_compiled_code_t *bytecode_header_p = executable_object_p->shared.bytecode_header_p; size_t size, register_end; if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) diff --git a/jerry-core/ecma/base/ecma-init-finalize.c b/jerry-core/ecma/base/ecma-init-finalize.c index f5e6e3781..e875cbc2c 100644 --- a/jerry-core/ecma/base/ecma-init-finalize.c +++ b/jerry-core/ecma/base/ecma-init-finalize.c @@ -62,7 +62,6 @@ ecma_init (void) #if ENABLED (JERRY_ESNEXT) JERRY_CONTEXT (current_new_target) = NULL; - JERRY_CONTEXT (current_function_obj_p) = NULL; #endif /* ENABLED (JERRY_ESNEXT) */ } /* ecma_init */ @@ -74,7 +73,6 @@ ecma_finalize (void) { #if ENABLED (JERRY_ESNEXT) JERRY_ASSERT (JERRY_CONTEXT (current_new_target) == NULL); - JERRY_ASSERT (JERRY_CONTEXT (current_function_obj_p) == NULL); #endif /* ENABLED (JERRY_ESNEXT) */ ecma_finalize_global_environment (); diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index 950aef403..8e22d03d7 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -878,6 +878,14 @@ ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */ return ecma_builtin_dispatch_call (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); } + vm_frame_ctx_shared_args_t shared_args; + shared_args.header.status_flags = VM_FRAME_CTX_SHARED_HAS_ARG_LIST; + shared_args.arg_list_p = arguments_list_p; + shared_args.arg_list_len = arguments_list_len; +#if ENABLED (JERRY_ESNEXT) + shared_args.function_object_p = func_obj_p; +#endif /* ENABLED (JERRY_ESNEXT) */ + /* Entering Function Code (ECMA-262 v5, 10.4.3) */ ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_p; @@ -886,25 +894,14 @@ ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */ /* 8. */ ecma_value_t this_binding = this_arg_value; - bool free_this_binding = false; const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p); uint16_t status_flags = bytecode_data_p->status_flags; -#if ENABLED (JERRY_ESNEXT) - uint16_t function_type = CBC_FUNCTION_GET_TYPE (status_flags); - - if (JERRY_UNLIKELY (function_type == CBC_FUNCTION_CONSTRUCTOR) - && JERRY_CONTEXT (current_new_target) == NULL) - { - return ecma_raise_type_error (ECMA_ERR_MSG ("Class constructor cannot be invoked without 'new'.")); - } -#endif /* ENABLED (JERRY_ESNEXT) */ + shared_args.header.bytecode_header_p = bytecode_data_p; /* 1. */ #if ENABLED (JERRY_ESNEXT) - ecma_object_t *old_function_object_p = JERRY_CONTEXT (current_function_obj_p); - if (JERRY_UNLIKELY (CBC_FUNCTION_IS_ARROW (status_flags))) { ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) func_obj_p; @@ -921,8 +918,9 @@ ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */ } else { - JERRY_CONTEXT (current_function_obj_p) = func_obj_p; + shared_args.header.status_flags |= VM_FRAME_CTX_SHARED_NON_ARROW_FUNC; #endif /* ENABLED (JERRY_ESNEXT) */ + if (!(status_flags & CBC_CODE_FLAGS_STRICT_MODE)) { if (ecma_is_value_undefined (this_binding) @@ -935,7 +933,7 @@ ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */ { /* 3., 4. */ this_binding = ecma_op_to_object (this_binding); - free_this_binding = true; + shared_args.header.status_flags |= VM_FRAME_CTX_SHARED_FREE_THIS; JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (this_binding)); } @@ -945,45 +943,45 @@ ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */ #endif /* ENABLED (JERRY_ESNEXT) */ /* 5. */ - ecma_object_t *local_env_p; - if (status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED) + if (!(status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED)) { - local_env_p = scope_p; + shared_args.header.status_flags |= VM_FRAME_CTX_SHARED_FREE_LOCAL_ENV; + scope_p = ecma_create_decl_lex_env (scope_p); + + if (JERRY_UNLIKELY (status_flags & CBC_CODE_FLAGS_IS_ARGUMENTS_NEEDED)) + { + ecma_op_create_arguments_object (func_obj_p, scope_p, &shared_args); + } } - else - { - local_env_p = ecma_create_decl_lex_env (scope_p); - if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_IS_ARGUMENTS_NEEDED) - { - ecma_op_create_arguments_object (func_obj_p, - local_env_p, - arguments_list_p, - arguments_list_len, - bytecode_data_p); - } + + ecma_value_t ret_value; + #if ENABLED (JERRY_ESNEXT) - // ECMAScript v6, 9.2.2.8 - if (JERRY_UNLIKELY (function_type == CBC_FUNCTION_CONSTRUCTOR)) + if (JERRY_UNLIKELY (CBC_FUNCTION_GET_TYPE (status_flags) == CBC_FUNCTION_CONSTRUCTOR)) + { + if (JERRY_CONTEXT (current_new_target) == NULL) { - ecma_value_t lexical_this; - lexical_this = (ECMA_GET_THIRD_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp) ? ECMA_VALUE_UNINITIALIZED - : this_binding); - ecma_op_init_this_binding (local_env_p, lexical_this); + ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Class constructor cannot be invoked without 'new'.")); + goto exit; } + + ecma_value_t lexical_this = this_binding; + + if (ECMA_GET_THIRD_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)) + { + shared_args.header.status_flags |= VM_FRAME_CTX_SHARED_HERITAGE_PRESENT; + lexical_this = ECMA_VALUE_UNINITIALIZED; + } + + ecma_op_init_this_binding (scope_p, lexical_this); + } #endif /* ENABLED (JERRY_ESNEXT) */ - } - ecma_value_t ret_value = vm_run (bytecode_data_p, - this_binding, - local_env_p, - arguments_list_p, - arguments_list_len); + ret_value = vm_run (&shared_args.header, this_binding, scope_p); #if ENABLED (JERRY_ESNEXT) - JERRY_CONTEXT (current_function_obj_p) = old_function_object_p; - /* ECMAScript v6, 9.2.2.13 */ - if (ECMA_GET_THIRD_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)) + if (JERRY_UNLIKELY (shared_args.header.status_flags & VM_FRAME_CTX_SHARED_HERITAGE_PRESENT)) { if (!ECMA_IS_VALUE_ERROR (ret_value) && !ecma_is_value_object (ret_value)) { @@ -994,19 +992,20 @@ ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */ } else { - ret_value = ecma_op_get_this_binding (local_env_p); + ret_value = ecma_op_get_this_binding (scope_p); } } } +exit: #endif /* ENABLED (JERRY_ESNEXT) */ - if (!(status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED)) + if (JERRY_UNLIKELY (shared_args.header.status_flags & VM_FRAME_CTX_SHARED_FREE_LOCAL_ENV)) { - ecma_deref_object (local_env_p); + ecma_deref_object (scope_p); } - if (JERRY_UNLIKELY (free_this_binding)) + if (JERRY_UNLIKELY (shared_args.header.status_flags & VM_FRAME_CTX_SHARED_FREE_THIS)) { ecma_free_value (this_binding); } diff --git a/jerry-core/ecma/operations/ecma-objects-arguments.c b/jerry-core/ecma/operations/ecma-objects-arguments.c index 6cfbe2cc7..37ac9e8d1 100644 --- a/jerry-core/ecma/operations/ecma-objects-arguments.c +++ b/jerry-core/ecma/operations/ecma-objects-arguments.c @@ -43,10 +43,9 @@ void ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function */ ecma_object_t *lex_env_p, /**< lexical environment the Arguments object is created for */ - const ecma_value_t *arguments_list_p, /**< arguments list */ - uint32_t arguments_number, /**< length of arguments list */ - const ecma_compiled_code_t *bytecode_data_p) /**< byte code */ + vm_frame_ctx_shared_args_t *shared_p) /**< shared context dta */ { + const ecma_compiled_code_t *bytecode_data_p = shared_p->header.bytecode_header_p; bool is_strict = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0; uint32_t formal_params_number; @@ -65,8 +64,8 @@ ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function } ecma_object_t *prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); - ecma_object_t *obj_p; + uint32_t arguments_number = shared_p->arg_list_len; if ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) && arguments_number > 0 @@ -125,6 +124,7 @@ ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, NULL); + const ecma_value_t *arguments_list_p = shared_p->arg_list_p; prop_value_p->value = ecma_copy_value_if_not_object (arguments_list_p[index]); ecma_deref_ecma_string (index_string_p); diff --git a/jerry-core/ecma/operations/ecma-objects-arguments.h b/jerry-core/ecma/operations/ecma-objects-arguments.h index a0264f257..e08f2bb78 100644 --- a/jerry-core/ecma/operations/ecma-objects-arguments.h +++ b/jerry-core/ecma/operations/ecma-objects-arguments.h @@ -18,11 +18,11 @@ #include "ecma-globals.h" #include "ecma-helpers.h" +#include "vm-defines.h" void ecma_op_create_arguments_object (ecma_object_t *func_obj_p, ecma_object_t *lex_env_p, - const ecma_value_t *arguments_list_p, uint32_t arguments_number, - const ecma_compiled_code_t *bytecode_data_p); + vm_frame_ctx_shared_args_t *shared_p); ecma_value_t ecma_op_arguments_object_delete (ecma_object_t *object_p, ecma_string_t *property_name_p, bool is_throw); diff --git a/jerry-core/include/jerryscript-snapshot.h b/jerry-core/include/jerryscript-snapshot.h index 3c958aa2d..253733b71 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 (57u) +#define JERRY_SNAPSHOT_VERSION (58u) /** * 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 ddebbd73d..11f1a33a0 100644 --- a/jerry-core/jcontext/jcontext.h +++ b/jerry-core/jcontext/jcontext.h @@ -137,9 +137,6 @@ struct jerry_context_t #endif /* ENABLED (JERRY_CPOINTER_32_BIT) */ const lit_utf8_byte_t * const *lit_magic_string_ex_array; /**< array of external magic strings */ const lit_utf8_size_t *lit_magic_string_ex_sizes; /**< external magic string lengths */ -#if ENABLED (JERRY_ESNEXT) - ecma_value_t *computed_class_fields_p; /**< names of the computed class fields */ -#endif /* ENABLED (JERRY_ESNEXT) */ jmem_cpointer_t string_list_first_cp; /**< first item of the literal string list */ #if ENABLED (JERRY_ESNEXT) jmem_cpointer_t symbol_list_first_cp; /**< first item of the global symbol list */ @@ -233,8 +230,6 @@ struct jerry_context_t * * Any other valid function object pointer: the current "new.target" is valid and it is constructor call. */ ecma_object_t *current_new_target; - ecma_object_t *current_function_obj_p; /** currently invoked function object - (Note: currently used only in generator functions) */ #endif /* ENABLED (JERRY_ESNEXT) */ }; diff --git a/jerry-core/parser/js/byte-code.c b/jerry-core/parser/js/byte-code.c index 36158a88f..20bbabdb3 100644 --- a/jerry-core/parser/js/byte-code.c +++ b/jerry-core/parser/js/byte-code.c @@ -27,7 +27,7 @@ JERRY_STATIC_ASSERT ((sizeof (cbc_uint16_arguments_t) % sizeof (jmem_cpointer_t) */ JERRY_STATIC_ASSERT (CBC_END == 238, number_of_cbc_opcodes_changed); -JERRY_STATIC_ASSERT (CBC_EXT_END == 140, +JERRY_STATIC_ASSERT (CBC_EXT_END == 141, number_of_cbc_ext_opcodes_changed); #if ENABLED (JERRY_PARSER) diff --git a/jerry-core/parser/js/byte-code.h b/jerry-core/parser/js/byte-code.h index 9f76efe48..e99e20699 100644 --- a/jerry-core/parser/js/byte-code.h +++ b/jerry-core/parser/js/byte-code.h @@ -594,6 +594,8 @@ VM_OC_EXT_VAR_EVAL) \ CBC_OPCODE (CBC_EXT_COPY_FROM_ARG, CBC_HAS_LITERAL_ARG, 0, \ VM_OC_COPY_FROM_ARG) \ + CBC_OPCODE (CBC_EXT_PUSH_REST_OBJECT, CBC_NO_FLAG, 1, \ + VM_OC_PUSH_REST_OBJECT) \ CBC_OPCODE (CBC_EXT_STRING_CONCAT, CBC_NO_FLAG, -1, \ VM_OC_STRING_CONCAT | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \ CBC_OPCODE (CBC_EXT_STRING_CONCAT_RIGHT_LITERAL, CBC_HAS_LITERAL_ARG, 0, \ @@ -862,9 +864,8 @@ typedef enum CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED = (1u << 5), /**< no need to create a lexical environment */ CBC_CODE_FLAGS_STATIC_FUNCTION = (1u << 6), /**< this function is a static snapshot function */ CBC_CODE_FLAGS_DEBUGGER_IGNORE = (1u << 7), /**< this function should be ignored by debugger */ - CBC_CODE_FLAGS_REST_PARAMETER = (1u << 8), /**< this function has rest parameter */ - CBC_CODE_FLAGS_HAS_TAGGED_LITERALS = (1u << 9), /**< this function has tagged template literal list */ - CBC_CODE_FLAGS_LEXICAL_BLOCK_NEEDED = (1u << 10), /**< compiled code needs a lexical block */ + CBC_CODE_FLAGS_HAS_TAGGED_LITERALS = (1u << 8), /**< this function has tagged template literal list */ + CBC_CODE_FLAGS_LEXICAL_BLOCK_NEEDED = (1u << 9), /**< compiled code needs a lexical block */ /* Bits from bit 12 is reserved for function types (see CBC_FUNCTION_TYPE_SHIFT). * Note: the last bits are used for type flags because < and >= operators can be used to diff --git a/jerry-core/parser/js/js-parser.c b/jerry-core/parser/js/js-parser.c index 66a19b082..dc89d228e 100644 --- a/jerry-core/parser/js/js-parser.c +++ b/jerry-core/parser/js/js-parser.c @@ -555,13 +555,6 @@ parse_print_literal (ecma_compiled_code_t *compiled_code_p, /**< compiled code * ident_end = args_p->ident_end; } -#if ENABLED (JERRY_ESNEXT) - if (compiled_code_p->status_flags & CBC_CODE_FLAGS_REST_PARAMETER) - { - argument_end++; - } -#endif /* ENABLED (JERRY_ESNEXT) */ - if (literal_index < argument_end) { JERRY_DEBUG_MSG (" arg:%d", literal_index); @@ -1437,11 +1430,6 @@ parser_post_processing (parser_context_t *context_p) /**< context */ function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_NORMAL); } - if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM) - { - compiled_code_p->status_flags |= CBC_CODE_FLAGS_REST_PARAMETER; - } - if (context_p->tagged_template_literal_cp != JMEM_CP_NULL) { compiled_code_p->status_flags |= CBC_CODE_FLAGS_HAS_TAGGED_LITERALS; @@ -1870,9 +1858,16 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */ context_p->status_flags |= PARSER_FUNCTION_HAS_COMPLEX_ARGUMENT; - parser_emit_cbc_literal (context_p, - CBC_PUSH_LITERAL, - (uint16_t) (PARSER_REGISTER_START + context_p->argument_count)); + if (!(context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM)) + { + parser_emit_cbc_literal (context_p, + CBC_PUSH_LITERAL, + (uint16_t) (PARSER_REGISTER_START + context_p->argument_count)); + } + else + { + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_REST_OBJECT); + } uint32_t flags = (PARSER_PATTERN_BINDING | PARSER_PATTERN_TARGET_ON_STACK @@ -1990,7 +1985,7 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */ if (literal_index >= PARSER_REGISTER_START) { - opcode = CBC_ASSIGN_SET_IDENT; + opcode = CBC_MOV_IDENT; } else if (!scanner_literal_is_created (context_p, literal_index)) { @@ -1999,6 +1994,24 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */ parser_emit_cbc_literal (context_p, opcode, literal_index); } + else if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM) + { + parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_REST_OBJECT); + + uint16_t opcode = CBC_MOV_IDENT; + + if (literal_index < PARSER_REGISTER_START) + { + opcode = CBC_INIT_ARG_OR_CATCH; + + if (scanner_literal_is_created (context_p, literal_index)) + { + opcode = CBC_ASSIGN_LET_CONST; + } + } + + parser_emit_cbc_literal (context_p, opcode, literal_index); + } else if (has_complex_argument && literal_index < PARSER_REGISTER_START) { uint16_t opcode = CBC_INIT_ARG_OR_FUNC; diff --git a/jerry-core/vm/opcodes.c b/jerry-core/vm/opcodes.c index 7bc3bb367..edf83623a 100644 --- a/jerry-core/vm/opcodes.c +++ b/jerry-core/vm/opcodes.c @@ -652,7 +652,7 @@ vm_executable_object_t * opfunc_create_executable_object (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ vm_create_executable_object_type_t type) /**< executable object type */ { - const ecma_compiled_code_t *bytecode_header_p = frame_ctx_p->bytecode_header_p; + const ecma_compiled_code_t *bytecode_header_p = frame_ctx_p->shared_p->bytecode_header_p; size_t size, register_end; ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_header_p); @@ -680,13 +680,15 @@ opfunc_create_executable_object (vm_frame_ctx_t *frame_ctx_p, /**< frame context { ecma_builtin_id_t default_proto_id = ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE; - if (CBC_FUNCTION_GET_TYPE (frame_ctx_p->bytecode_header_p->status_flags) == CBC_FUNCTION_ASYNC_GENERATOR) + if (CBC_FUNCTION_GET_TYPE (bytecode_header_p->status_flags) == CBC_FUNCTION_ASYNC_GENERATOR) { default_proto_id = ECMA_BUILTIN_ID_ASYNC_GENERATOR_PROTOTYPE; class_id = LIT_MAGIC_STRING_ASYNC_GENERATOR_UL; } - proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_function_obj_p), default_proto_id); + JERRY_ASSERT (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_NON_ARROW_FUNC); + proto_p = ecma_op_get_prototype_from_constructor (VM_FRAME_CTX_GET_FUNCTION_OBJECT (frame_ctx_p), + default_proto_id); } ecma_object_t *object_p = ecma_create_object (proto_p, @@ -704,10 +706,15 @@ opfunc_create_executable_object (vm_frame_ctx_t *frame_ctx_p, /**< frame context executable_object_p->extended_object.u.class_prop.extra_info = 0; ECMA_SET_INTERNAL_VALUE_ANY_POINTER (executable_object_p->extended_object.u.class_prop.u.head, NULL); - JERRY_ASSERT (!frame_ctx_p->is_eval_code); + JERRY_ASSERT (!(frame_ctx_p->status_flags & VM_FRAME_CTX_DIRECT_EVAL)); + + /* Copy shared data and frame context. */ + vm_frame_ctx_shared_t *new_shared_p = &(executable_object_p->shared); + *new_shared_p = *(frame_ctx_p->shared_p); vm_frame_ctx_t *new_frame_ctx_p = &(executable_object_p->frame_ctx); *new_frame_ctx_p = *frame_ctx_p; + new_frame_ctx_p->shared_p = new_shared_p; /* The old register values are discarded. */ ecma_value_t *new_registers_p = VM_GET_REGISTERS (new_frame_ctx_p); @@ -782,7 +789,7 @@ ecma_value_t opfunc_resume_executable_object (vm_executable_object_t *executable_object_p, /**< executable object */ ecma_value_t value) /**< value pushed onto the stack (takes the reference) */ { - const ecma_compiled_code_t *bytecode_header_p = executable_object_p->frame_ctx.bytecode_header_p; + const ecma_compiled_code_t *bytecode_header_p = executable_object_p->shared.bytecode_header_p; ecma_value_t *register_p = VM_GET_REGISTERS (&executable_object_p->frame_ctx); ecma_value_t *register_end_p; @@ -926,8 +933,9 @@ opfunc_async_create_and_await (vm_frame_ctx_t *frame_ctx_p, /**< frame context * uint16_t extra_flags) /**< extra flags */ { JERRY_ASSERT (frame_ctx_p->block_result == ECMA_VALUE_UNDEFINED); - JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (frame_ctx_p->bytecode_header_p->status_flags) == CBC_FUNCTION_ASYNC - || CBC_FUNCTION_GET_TYPE (frame_ctx_p->bytecode_header_p->status_flags) == CBC_FUNCTION_ASYNC_ARROW); + JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (frame_ctx_p->shared_p->bytecode_header_p->status_flags) == CBC_FUNCTION_ASYNC + || (CBC_FUNCTION_GET_TYPE (frame_ctx_p->shared_p->bytecode_header_p->status_flags) + == CBC_FUNCTION_ASYNC_ARROW)); ecma_object_t *promise_p = ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE); ecma_value_t result = ecma_promise_reject_or_resolve (ecma_make_object_value (promise_p), value, true); @@ -982,33 +990,30 @@ ecma_op_init_class_fields (ecma_value_t function_object, /**< the function itsel return ECMA_VALUE_UNDEFINED; } - ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); - ecma_value_t *computed_class_fields_p = NULL; + vm_frame_ctx_shared_class_fields_t shared_class_fields; + shared_class_fields.header.status_flags = VM_FRAME_CTX_SHARED_HAS_CLASS_FIELDS; + shared_class_fields.computed_class_fields_p = NULL; name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED); ecma_property_t *class_field_property_p = ecma_find_named_property (function_object_p, name_p); if (class_field_property_p != NULL) { - ecma_property_value_t *class_field_property_value_p = ECMA_PROPERTY_VALUE_PTR (class_field_property_p); - computed_class_fields_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, class_field_property_value_p->value); + ecma_value_t value = ECMA_PROPERTY_VALUE_PTR (class_field_property_p)->value; + shared_class_fields.computed_class_fields_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, value); } + ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); JERRY_ASSERT (ecma_op_is_callable (property_value_p->value)); ecma_extended_object_t *ext_function_p; ext_function_p = (ecma_extended_object_t *) ecma_get_object_from_value (property_value_p->value); + shared_class_fields.header.bytecode_header_p = ecma_op_function_get_compiled_code (ext_function_p); ecma_object_t *scope_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_function_p->u.function.scope_cp); - const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_function_p); - ecma_value_t *old_computed_class_fields_p = JERRY_CONTEXT (computed_class_fields_p); - JERRY_CONTEXT (computed_class_fields_p) = computed_class_fields_p; - - ecma_value_t result = vm_run (bytecode_data_p, this_val, scope_p, NULL, 0); - - JERRY_CONTEXT (computed_class_fields_p) = old_computed_class_fields_p; + ecma_value_t result = vm_run (&shared_class_fields.header, this_val, scope_p); JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result) || result == ECMA_VALUE_UNDEFINED); return result; @@ -1578,7 +1583,7 @@ opfunc_assign_super_reference (ecma_value_t **vm_stack_top_p, /**< vm stack top return ECMA_VALUE_ERROR; } - bool is_strict = (frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0; + bool is_strict = (frame_ctx_p->status_flags & VM_FRAME_CTX_IS_STRICT) != 0; ecma_value_t result = ecma_op_object_put_with_receiver (base_obj_p, prop_name_p, diff --git a/jerry-core/vm/vm-defines.h b/jerry-core/vm/vm-defines.h index 4cc1ede2c..5e7f514bd 100644 --- a/jerry-core/vm/vm-defines.h +++ b/jerry-core/vm/vm-defines.h @@ -35,12 +35,81 @@ */ #define VM_MINUS_EQUAL_U16(base, value) (base) = (uint16_t) ((base) - (value)) +/** + * Flag bits of vm_frame_ctx_shared_t + */ +typedef enum +{ + VM_FRAME_CTX_SHARED_HAS_ARG_LIST = (1 << 0), /**< has argument list */ + VM_FRAME_CTX_SHARED_DIRECT_EVAL = (1 << 1), /**< direct eval call */ + VM_FRAME_CTX_SHARED_FREE_THIS = (1 << 2), /**< free this binding */ + VM_FRAME_CTX_SHARED_FREE_LOCAL_ENV = (1 << 3), /**< free local environment */ +#if ENABLED (JERRY_ESNEXT) + VM_FRAME_CTX_SHARED_NON_ARROW_FUNC = (1 << 4), /**< non-arrow function */ + VM_FRAME_CTX_SHARED_HERITAGE_PRESENT = (1 << 5), /**< class heritage present */ + VM_FRAME_CTX_SHARED_HAS_CLASS_FIELDS = (1 << 6), /**< has class fields */ +#endif /* ENABLED (JERRY_ESNEXT) */ +} vm_frame_ctx_shared_flags_t; + +/** + * Shared data between the interpreter and the caller + */ +typedef struct +{ + const ecma_compiled_code_t *bytecode_header_p; /**< currently executed byte-code data */ + uint32_t status_flags; /**< combination of vm_frame_ctx_shared_flags_t bits */ +} vm_frame_ctx_shared_t; + +/** + * Shared data extended with arguments + */ +typedef struct +{ + vm_frame_ctx_shared_t header; /**< shared data header */ +#if ENABLED (JERRY_ESNEXT) + ecma_object_t *function_object_p; /**< function obj */ +#endif /* ENABLED (JERRY_ESNEXT) */ + const ecma_value_t *arg_list_p; /**< arguments list */ + uint32_t arg_list_len; /**< arguments list length */ +} vm_frame_ctx_shared_args_t; + +#if ENABLED (JERRY_ESNEXT) + +#define VM_FRAME_CTX_GET_FUNCTION_OBJECT(frame_ctx_p) \ + (((vm_frame_ctx_shared_args_t *) (frame_ctx_p)->shared_p)->function_object_p) + +/** + * Shared data extended with computed class fields + */ +typedef struct +{ + vm_frame_ctx_shared_t header; /**< shared data header */ + ecma_value_t *computed_class_fields_p; /**< names of the computed class fields */ +} vm_frame_ctx_shared_class_fields_t; + +/** + * Get the computed class field + */ +#define VM_GET_COMPUTED_CLASS_FIELDS(frame_ctx_p) \ + (((vm_frame_ctx_shared_class_fields_t *) ((frame_ctx_p)->shared_p))->computed_class_fields_p) + +#endif /* ENABLED (JERRY_ESNEXT) */ + +/** + * Flag bits of vm_frame_ctx_t + */ +typedef enum +{ + VM_FRAME_CTX_DIRECT_EVAL = (1 << 1), /**< direct eval call */ + VM_FRAME_CTX_IS_STRICT = (1 << 2), /**< strict mode */ +} vm_frame_ctx_flags_t; + /** * Context of interpreter, related to a JS stack frame */ typedef struct vm_frame_ctx_t { - const ecma_compiled_code_t *bytecode_header_p; /**< currently executed byte-code data */ + vm_frame_ctx_shared_t *shared_p; /**< shared information */ const uint8_t *byte_code_p; /**< current byte code pointer */ const uint8_t *byte_code_start_p; /**< byte code start pointer */ ecma_value_t *stack_top_p; /**< stack top pointer */ @@ -53,7 +122,7 @@ typedef struct vm_frame_ctx_t uint32_t current_line; /**< currently executed line */ #endif /* ENABLED (JERRY_LINE_INFO) */ uint16_t context_depth; /**< current context depth */ - uint8_t is_eval_code; /**< eval mode flag */ + uint8_t status_flags; /**< combination of vm_frame_ctx_flags_t bits */ uint8_t call_operation; /**< perform a call or construct operation */ /* Registers start immediately after the frame context. */ } vm_frame_ctx_t; @@ -80,6 +149,7 @@ typedef struct vm_frame_ctx_t typedef struct { ecma_extended_object_t extended_object; /**< extended object part */ + vm_frame_ctx_shared_t shared; /**< shared part */ vm_frame_ctx_t frame_ctx; /**< frame context part */ } vm_executable_object_t; diff --git a/jerry-core/vm/vm-utils.c b/jerry-core/vm/vm-utils.c index 574a611eb..c93aecfab 100644 --- a/jerry-core/vm/vm-utils.c +++ b/jerry-core/vm/vm-utils.c @@ -30,7 +30,7 @@ vm_is_strict_mode (void) { JERRY_ASSERT (JERRY_CONTEXT (vm_top_context_p) != NULL); - return JERRY_CONTEXT (vm_top_context_p)->bytecode_header_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE; + return JERRY_CONTEXT (vm_top_context_p)->status_flags & VM_FRAME_CTX_IS_STRICT; } /* vm_is_strict_mode */ /** @@ -76,7 +76,7 @@ vm_get_backtrace (uint32_t max_depth) /**< maximum backtrace depth, 0 = unlimite while (context_p != NULL) { - ecma_value_t resource_name = ecma_get_resource_name (context_p->bytecode_header_p); + ecma_value_t resource_name = ecma_get_resource_name (context_p->shared_p->bytecode_header_p); ecma_string_t *str_p = ecma_get_string_from_value (resource_name); ecma_stringbuilder_t builder = ecma_stringbuilder_create (); diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index c15c95538..0e7ae6dc7 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -46,11 +46,6 @@ * @{ */ -/** - * Special constant to represent direct eval code. - */ -#define VM_DIRECT_EVAL ((void *) 0x1) - /** * Get the value of object[property]. * @@ -281,16 +276,17 @@ vm_run_module (const ecma_compiled_code_t *bytecode_p, /**< pointer to bytecode ecma_object_t *lex_env_p) /**< pointer to the specified lexenv to run in */ { const ecma_value_t module_init_result = ecma_module_initialize_current (); + if (ECMA_IS_VALUE_ERROR (module_init_result)) { return module_init_result; } - return vm_run (bytecode_p, - ECMA_VALUE_UNDEFINED, - lex_env_p, - NULL, - 0); + vm_frame_ctx_shared_t shared; + shared.bytecode_header_p = bytecode_p; + shared.status_flags = 0; + + return vm_run (&shared, ECMA_VALUE_UNDEFINED, lex_env_p); } /* vm_run_module */ #endif /* ENABLED (JERRY_MODULE_SYSTEM) */ @@ -337,11 +333,11 @@ vm_run_global (const ecma_compiled_code_t *bytecode_p) /**< pointer to bytecode } #endif /* ENABLED (JERRY_MODULE_SYSTEM) */ - return vm_run (bytecode_p, - ecma_make_object_value (glob_obj_p), - global_scope_p, - NULL, - 0); + vm_frame_ctx_shared_t shared; + shared.bytecode_header_p = bytecode_p; + shared.status_flags = 0; + + return vm_run (&shared, ecma_make_object_value (glob_obj_p), global_scope_p); } /* vm_run_global */ /** @@ -410,11 +406,11 @@ vm_run_eval (ecma_compiled_code_t *bytecode_data_p, /**< byte-code data */ lex_env_p = lex_block_p; } - ecma_value_t completion_value = vm_run (bytecode_data_p, - this_binding, - lex_env_p, - (parse_opts & ECMA_PARSE_DIRECT_EVAL) ? VM_DIRECT_EVAL : NULL, - 0); + vm_frame_ctx_shared_t shared; + shared.bytecode_header_p = bytecode_data_p; + shared.status_flags = (parse_opts & ECMA_PARSE_DIRECT_EVAL) ? VM_FRAME_CTX_SHARED_DIRECT_EVAL : 0; + + ecma_value_t completion_value = vm_run (&shared, this_binding, lex_env_p); ecma_deref_object (lex_env_p); ecma_free_value (this_binding); @@ -443,7 +439,7 @@ vm_construct_literal_object (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ ecma_compiled_code_t *bytecode_p; #if ENABLED (JERRY_SNAPSHOT_EXEC) - if (JERRY_LIKELY (!(frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))) + if (JERRY_LIKELY (!(frame_ctx_p->shared_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))) { #endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */ bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, @@ -452,7 +448,7 @@ vm_construct_literal_object (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ } else { - uint8_t *byte_p = ((uint8_t *) frame_ctx_p->bytecode_header_p) + lit_value; + uint8_t *byte_p = ((uint8_t *) frame_ctx_p->shared_p->bytecode_header_p) + lit_value; bytecode_p = (ecma_compiled_code_t *) byte_p; } #endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */ @@ -529,6 +525,23 @@ static const uint8_t vm_error_byte_code_p[] = }; #if ENABLED (JERRY_ESNEXT) + +static ecma_object_t * +vm_get_class_function (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ + while (true) + { + JERRY_ASSERT (frame_ctx_p != NULL); + + if (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_NON_ARROW_FUNC) + { + return VM_FRAME_CTX_GET_FUNCTION_OBJECT (frame_ctx_p); + } + + frame_ctx_p = frame_ctx_p->prev_context_p; + } +} /* vm_get_class_function */ + /** * 'super(...)' function call handler. */ @@ -612,7 +625,7 @@ vm_super_call (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ if (ecma_is_value_object (completion_value)) { - ecma_value_t current_function = ecma_make_object_value (JERRY_CONTEXT (current_function_obj_p)); + ecma_value_t current_function = ecma_make_object_value (vm_get_class_function (frame_ctx_p)); ecma_value_t fields_value = ecma_op_init_class_fields (current_function, completion_value); if (ECMA_IS_VALUE_ERROR (fields_value)) @@ -1008,7 +1021,7 @@ opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ static ecma_value_t JERRY_ATTR_NOINLINE 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; + const ecma_compiled_code_t *bytecode_header_p = frame_ctx_p->shared_p->bytecode_header_p; const uint8_t *byte_code_p = frame_ctx_p->byte_code_p; ecma_value_t *literal_start_p = frame_ctx_p->literal_start_p; @@ -1023,7 +1036,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_value_t left_value; ecma_value_t right_value; ecma_value_t result = ECMA_VALUE_EMPTY; - bool is_strict = ((frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0); + bool is_strict = ((bytecode_header_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0); /* Prepare for byte code execution. */ if (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_FULL_LITERAL_ENCODING)) @@ -1403,7 +1416,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } #endif /* ENABLED (JERRY_ESNEXT) && !JERRY_NDEBUG */ - result = vm_var_decl (lex_env_p, name_p, frame_ctx_p->is_eval_code); + result = vm_var_decl (lex_env_p, name_p, (frame_ctx_p->status_flags & VM_FRAME_CTX_DIRECT_EVAL) != 0); if (ECMA_IS_VALUE_ERROR (result)) { @@ -2040,7 +2053,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } case VM_OC_RUN_CLASS_FIELD_INIT: { - result = ecma_op_init_class_fields (ecma_make_object_value (JERRY_CONTEXT (current_function_obj_p)), + JERRY_ASSERT (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_NON_ARROW_FUNC); + result = ecma_op_init_class_fields (ecma_make_object_value (VM_FRAME_CTX_GET_FUNCTION_OBJECT (frame_ctx_p)), frame_ctx_p->this_binding); if (ECMA_IS_VALUE_ERROR (result)) @@ -2055,7 +2069,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ stack_top_p[-2] = ecma_make_integer_value (next_index); stack_top_p++; - ecma_value_t *computed_class_fields_p = JERRY_CONTEXT (computed_class_fields_p); + JERRY_ASSERT (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_HAS_CLASS_FIELDS); + + ecma_value_t *computed_class_fields_p = VM_GET_COMPUTED_CLASS_FIELDS (frame_ctx_p); JERRY_ASSERT ((ecma_value_t) next_index < ECMA_COMPACT_COLLECTION_GET_SIZE (computed_class_fields_p)); result = stack_top_p[-2]; @@ -2065,7 +2081,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } case VM_OC_PUSH_SUPER_CONSTRUCTOR: { - result = ecma_op_function_get_super_constructor (JERRY_CONTEXT (current_function_obj_p)); + result = ecma_op_function_get_super_constructor (vm_get_class_function (frame_ctx_p)); if (ECMA_IS_VALUE_ERROR (result)) { @@ -2200,6 +2216,38 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ *stack_top_p++ = ECMA_VALUE_SPREAD_ELEMENT; continue; } + case VM_OC_PUSH_REST_OBJECT: + { + vm_frame_ctx_shared_t *shared_p = frame_ctx_p->shared_p; + + JERRY_ASSERT (shared_p->status_flags & VM_FRAME_CTX_SHARED_HAS_ARG_LIST); + + const ecma_value_t *arg_list_p = ((vm_frame_ctx_shared_args_t *) shared_p)->arg_list_p; + uint32_t arg_list_len = ((vm_frame_ctx_shared_args_t *) shared_p)->arg_list_len; + uint16_t argument_end; + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + argument_end = ((cbc_uint16_arguments_t *) bytecode_header_p)->argument_end; + } + else + { + argument_end = ((cbc_uint8_arguments_t *) bytecode_header_p)->argument_end; + } + + if (arg_list_len < argument_end) + { + arg_list_len = argument_end; + } + + result = ecma_op_create_array_object (arg_list_p + argument_end, + arg_list_len - argument_end, + false); + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (result)); + *stack_top_p++ = result; + continue; + } case VM_OC_GET_ITERATOR: { result = ecma_op_get_iterator (stack_top_p[-1], ECMA_VALUE_SYNC_ITERATOR, NULL); @@ -4068,7 +4116,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ uint16_t extra_flags = (ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD | (ECMA_AWAIT_FOR_NEXT << ECMA_AWAIT_STATE_SHIFT)); - if (CBC_FUNCTION_GET_TYPE (frame_ctx_p->bytecode_header_p->status_flags) == CBC_FUNCTION_ASYNC_GENERATOR + if (CBC_FUNCTION_GET_TYPE (bytecode_header_p->status_flags) == CBC_FUNCTION_ASYNC_GENERATOR || frame_ctx_p->block_result != ECMA_VALUE_UNDEFINED) { ecma_extended_object_t *executable_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p); @@ -4314,7 +4362,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED); - JERRY_ASSERT (!(frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_DEBUGGER_IGNORE)); + JERRY_ASSERT (!(frame_ctx_p->shared_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_DEBUGGER_IGNORE)); frame_ctx_p->byte_code_p = byte_code_start_p; @@ -4335,7 +4383,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED); - JERRY_ASSERT (!(frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_DEBUGGER_IGNORE)); + JERRY_ASSERT (!(frame_ctx_p->shared_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_DEBUGGER_IGNORE)); frame_ctx_p->byte_code_p = byte_code_start_p; @@ -4528,7 +4576,7 @@ error: | JERRY_DEBUGGER_VM_EXCEPTION_THROWN); if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) - && !(frame_ctx_p->bytecode_header_p->status_flags + && !(frame_ctx_p->shared_p->bytecode_header_p->status_flags & (CBC_CODE_FLAGS_DEBUGGER_IGNORE | CBC_CODE_FLAGS_STATIC_FUNCTION)) && !(JERRY_CONTEXT (debugger_flags) & dont_stop)) { @@ -4676,6 +4724,12 @@ finish: #undef READ_LITERAL #undef READ_LITERAL_INDEX +JERRY_STATIC_ASSERT ((int) VM_FRAME_CTX_SHARED_DIRECT_EVAL == (int) VM_FRAME_CTX_DIRECT_EVAL, + vm_frame_ctx_shared_direct_eval_must_be_equal_to_frame_ctx_direct_eval); + +JERRY_STATIC_ASSERT ((int) CBC_CODE_FLAGS_STRICT_MODE == (int) VM_FRAME_CTX_IS_STRICT, + cbc_code_flags_strict_mode_must_be_equal_to_vm_frame_ctx_is_strict); + /** * Initialize code block execution * @@ -4683,19 +4737,20 @@ finish: * ECMA_VALUE_EMPTY - otherwise */ static void JERRY_ATTR_NOINLINE -vm_init_exec (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ - const ecma_value_t *arg_p, /**< arguments list */ - uint32_t arg_list_len) /**< length of arguments list */ +vm_init_exec (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { + vm_frame_ctx_shared_t *shared_p = frame_ctx_p->shared_p; + const ecma_compiled_code_t *bytecode_header_p = shared_p->bytecode_header_p; + 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) frame_ctx_p->current_line = 0; #endif /* ENABLED (JERRY_LINE_INFO) */ frame_ctx_p->context_depth = 0; - frame_ctx_p->is_eval_code = (arg_p == VM_DIRECT_EVAL); + frame_ctx_p->status_flags = (uint8_t) ((shared_p->status_flags & VM_FRAME_CTX_DIRECT_EVAL) + | (bytecode_header_p->status_flags & VM_FRAME_CTX_IS_STRICT)); - const ecma_compiled_code_t *bytecode_header_p = frame_ctx_p->bytecode_header_p; uint16_t argument_end, register_end; ecma_value_t *literal_p; @@ -4728,18 +4783,24 @@ vm_init_exec (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ frame_ctx_p->byte_code_start_p = (uint8_t *) literal_p; frame_ctx_p->stack_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end; -#if ENABLED (JERRY_ESNEXT) - uint32_t function_call_argument_count = arg_list_len; -#endif /* ENABLED (JERRY_ESNEXT) */ + uint32_t arg_list_len = 0; - if (arg_list_len > argument_end) + if (argument_end > 0) { - arg_list_len = argument_end; - } + JERRY_ASSERT (shared_p->status_flags & VM_FRAME_CTX_SHARED_HAS_ARG_LIST); - for (uint32_t i = 0; i < arg_list_len; i++) - { - VM_GET_REGISTER (frame_ctx_p, i) = ecma_fast_copy_value (arg_p[i]); + const ecma_value_t *arg_list_p = ((vm_frame_ctx_shared_args_t *) shared_p)->arg_list_p; + arg_list_len = ((vm_frame_ctx_shared_args_t *) shared_p)->arg_list_len; + + if (arg_list_len > argument_end) + { + arg_list_len = argument_end; + } + + for (uint32_t i = 0; i < arg_list_len; i++) + { + VM_GET_REGISTER (frame_ctx_p, i) = ecma_fast_copy_value (arg_list_p[i]); + } } /* The arg_list_len contains the end of the copied arguments. @@ -4754,18 +4815,6 @@ vm_init_exec (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ } } -#if ENABLED (JERRY_ESNEXT) - if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_REST_PARAMETER) - { - JERRY_ASSERT (function_call_argument_count >= arg_list_len); - ecma_value_t new_array = ecma_op_create_array_object (arg_p + arg_list_len, - function_call_argument_count - arg_list_len, - false); - JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array)); - VM_GET_REGISTER (frame_ctx_p, argument_end) = new_array; - } -#endif /* ENABLED (JERRY_ESNEXT) */ - JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_DIRECT_EVAL; JERRY_CONTEXT (vm_top_context_p) = frame_ctx_p; } /* vm_init_exec */ @@ -4814,7 +4863,7 @@ vm_execute (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { JERRY_ASSERT (frame_ctx_p->call_operation == VM_NO_EXEC_OP); - const ecma_compiled_code_t *bytecode_header_p = frame_ctx_p->bytecode_header_p; + const ecma_compiled_code_t *bytecode_header_p = frame_ctx_p->shared_p->bytecode_header_p; uint32_t register_end; if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) @@ -4855,12 +4904,11 @@ vm_execute (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ * @return ecma value */ ecma_value_t -vm_run (const ecma_compiled_code_t *bytecode_header_p, /**< byte-code data header */ +vm_run (vm_frame_ctx_shared_t *shared_p, /**< shared data */ ecma_value_t this_binding_value, /**< value of 'ThisBinding' */ - ecma_object_t *lex_env_p, /**< lexical environment to use */ - const ecma_value_t *arg_list_p, /**< arguments list */ - uint32_t arg_list_len) /**< length of arguments list */ + ecma_object_t *lex_env_p) /**< lexical environment to use */ { + const ecma_compiled_code_t *bytecode_header_p = shared_p->bytecode_header_p; vm_frame_ctx_t *frame_ctx_p; size_t frame_size; @@ -4883,11 +4931,11 @@ vm_run (const ecma_compiled_code_t *bytecode_header_p, /**< byte-code data heade frame_ctx_p = (vm_frame_ctx_t *) stack; - frame_ctx_p->bytecode_header_p = bytecode_header_p; + frame_ctx_p->shared_p = shared_p; frame_ctx_p->lex_env_p = lex_env_p; frame_ctx_p->this_binding = this_binding_value; - vm_init_exec (frame_ctx_p, arg_list_p, arg_list_len); + vm_init_exec (frame_ctx_p); return vm_execute (frame_ctx_p); } /* vm_run */ diff --git a/jerry-core/vm/vm.h b/jerry-core/vm/vm.h index 998dbafe8..012e9fc5e 100644 --- a/jerry-core/vm/vm.h +++ b/jerry-core/vm/vm.h @@ -271,6 +271,7 @@ typedef enum VM_OC_SET_FUNCTION_NAME, /**< set function name property */ VM_OC_PUSH_SPREAD_ELEMENT, /**< push spread element */ + VM_OC_PUSH_REST_OBJECT, /**< push rest object */ VM_OC_GET_ITERATOR, /**< GetIterator abstract operation */ VM_OC_ITERATOR_STEP, /**< IteratorStep abstract operation */ VM_OC_ITERATOR_CLOSE, /**< IteratorClose abstract operation */ @@ -352,6 +353,7 @@ typedef enum 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_PUSH_REST_OBJECT = VM_OC_NONE, /**< push rest object */ VM_OC_GET_ITERATOR = VM_OC_NONE, /**< GetIterator abstract operation */ VM_OC_ITERATOR_STEP = VM_OC_NONE, /**< IteratorStep abstract operation */ VM_OC_ITERATOR_CLOSE = VM_OC_NONE, /**< IteratorClose abstract operation */ @@ -469,8 +471,7 @@ ecma_value_t vm_run_eval (ecma_compiled_code_t *bytecode_data_p, uint32_t parse_ ecma_value_t vm_run_module (const ecma_compiled_code_t *bytecode_p, ecma_object_t *lex_env_p); #endif /* ENABLED (JERRY_MODULE_SYSTEM) */ -ecma_value_t vm_run (const ecma_compiled_code_t *bytecode_header_p, ecma_value_t this_binding_value, - ecma_object_t *lex_env_p, const ecma_value_t *arg_list_p, uint32_t arg_list_len); +ecma_value_t vm_run (vm_frame_ctx_shared_t *shared_p, ecma_value_t this_binding_value, ecma_object_t *lex_env_p); ecma_value_t vm_execute (vm_frame_ctx_t *frame_ctx_p); bool vm_is_strict_mode (void);