From d006f068f4bf86a544e6c6e003f16549679f59a3 Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Fri, 22 Nov 2019 12:47:11 +0100 Subject: [PATCH] Improve the performance of the interpreter. (#3344) Registers are stored immediately after the frame pointer and an argument is dropped from vm_run. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com --- .../ecma/operations/ecma-function-object.c | 2 - jerry-core/vm/vm-defines.h | 14 +- jerry-core/vm/vm.c | 251 ++++++++++-------- jerry-core/vm/vm.h | 3 +- 4 files changed, 148 insertions(+), 122 deletions(-) diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index 4072f1872..f37c364a5 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -851,7 +851,6 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */ ecma_value_t ret_value = vm_run (bytecode_data_p, this_binding, local_env_p, - ECMA_PARSE_NO_OPTS, arguments_list_p, arguments_list_len); @@ -914,7 +913,6 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */ ecma_value_t ret_value = vm_run (bytecode_data_p, arrow_func_p->this_binding, local_env_p, - ECMA_PARSE_NO_OPTS, arguments_list_p, arguments_list_len); diff --git a/jerry-core/vm/vm-defines.h b/jerry-core/vm/vm-defines.h index 54a8843aa..fb1d2b1c8 100644 --- a/jerry-core/vm/vm-defines.h +++ b/jerry-core/vm/vm-defines.h @@ -43,13 +43,10 @@ typedef struct vm_frame_ctx_t const ecma_compiled_code_t *bytecode_header_p; /**< currently executed byte-code data */ uint8_t *byte_code_p; /**< current byte code pointer */ uint8_t *byte_code_start_p; /**< byte code start pointer */ - ecma_value_t *registers_p; /**< register start pointer */ ecma_value_t *stack_top_p; /**< stack top pointer */ ecma_value_t *literal_start_p; /**< literal list start pointer */ ecma_object_t *lex_env_p; /**< current lexical environment */ -#if defined (JERRY_DEBUGGER) || ENABLED (JERRY_LINE_INFO) struct vm_frame_ctx_t *prev_context_p; /**< previous context */ -#endif /* defined (JERRY_DEBUGGER) || ENABLED (JERRY_LINE_INFO) */ ecma_value_t this_binding; /**< this binding */ ecma_value_t block_result; /**< block result */ #if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) @@ -61,8 +58,19 @@ typedef struct vm_frame_ctx_t uint16_t context_depth; /**< current context depth */ uint8_t is_eval_code; /**< eval mode flag */ uint8_t call_operation; /**< perform a call or construct operation */ + /* Registers start immediately after the frame context. */ } vm_frame_ctx_t; +/** + * Get register list corresponding to the frame context. + */ +#define VM_GET_REGISTERS(frame_ctx_p) ((ecma_value_t *) (frame_ctx_p + 1)) + +/** + * Read or write a specific register. + */ +#define VM_GET_REGISTER(frame_ctx_p, i) (((ecma_value_t *) (frame_ctx_p + 1))[i]) + /** * @} * @} diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index 9a65ea950..63b3b4e25 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -43,6 +43,11 @@ * @{ */ +/** + * Special constant to represent direct eval code. + */ +#define VM_DIRECT_EVAL ((void *) 0x1) + /** * Get the value of object[property]. * @@ -260,7 +265,6 @@ vm_run_module (const ecma_compiled_code_t *bytecode_p, /**< pointer to bytecode return vm_run (bytecode_p, ecma_make_object_value (glob_obj_p), lex_env_p, - false, NULL, 0); } /* vm_run_module */ @@ -282,7 +286,6 @@ vm_run_global (const ecma_compiled_code_t *bytecode_p) /**< pointer to bytecode return vm_run (bytecode_p, ecma_make_object_value (glob_obj_p), ecma_get_global_environment (), - false, NULL, 0); } /* vm_run_global */ @@ -346,8 +349,7 @@ vm_run_eval (ecma_compiled_code_t *bytecode_data_p, /**< byte-code data */ ecma_value_t completion_value = vm_run (bytecode_data_p, this_binding, lex_env_p, - parse_opts, - NULL, + (parse_opts & ECMA_PARSE_DIRECT_EVAL) ? VM_DIRECT_EVAL : NULL, 0); ecma_deref_object (lex_env_p); @@ -842,7 +844,7 @@ opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ if ((literal_index) < register_end) \ { \ /* Note: There should be no specialization for arguments. */ \ - (target_value) = ecma_fast_copy_value (frame_ctx_p->registers_p[literal_index]); \ + (target_value) = ecma_fast_copy_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); \ } \ else \ { \ @@ -973,7 +975,7 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ if (value_index < register_end) { /* Take (not copy) the reference. */ - lit_value = ecma_copy_value_if_not_object (frame_ctx_p->registers_p[value_index]); + lit_value = ecma_copy_value_if_not_object (VM_GET_REGISTER (frame_ctx_p, value_index)); } else { @@ -983,8 +985,8 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ if (literal_index < register_end) { - ecma_fast_free_value (frame_ctx_p->registers_p[literal_index]); - frame_ctx_p->registers_p[literal_index] = lit_value; + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); + VM_GET_REGISTER (frame_ctx_p, literal_index) = lit_value; break; } @@ -1080,8 +1082,8 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ if (literal_index < register_end) { - ecma_fast_free_value (frame_ctx_p->registers_p[literal_index]); - frame_ctx_p->registers_p[literal_index] = lit_value; + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); + VM_GET_REGISTER (frame_ctx_p, literal_index) = lit_value; break; } @@ -1205,7 +1207,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } case VM_OC_GET_STACK_LITERAL: { - JERRY_ASSERT (stack_top_p > frame_ctx_p->registers_p + register_end); + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); right_value = left_value; left_value = *(--stack_top_p); break; @@ -1226,12 +1228,12 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ JERRY_ASSERT (operands == VM_OC_GET_STACK || operands == VM_OC_GET_STACK_STACK); - JERRY_ASSERT (stack_top_p > frame_ctx_p->registers_p + register_end); + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); left_value = *(--stack_top_p); if (operands == VM_OC_GET_STACK_STACK) { - JERRY_ASSERT (stack_top_p > frame_ctx_p->registers_p + register_end); + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); right_value = left_value; left_value = *(--stack_top_p); } @@ -1295,7 +1297,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { case VM_OC_POP: { - JERRY_ASSERT (stack_top_p > frame_ctx_p->registers_p + register_end); + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); ecma_free_value (*(--stack_top_p)); continue; } @@ -1651,7 +1653,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ stack_top_p[-1] = VM_CREATE_CONTEXT_WITH_ENV (VM_CONTEXT_SUPER_CLASS, branch_offset); frame_ctx_p->lex_env_p = super_env_p; - continue; } case VM_OC_CLASS_INHERITANCE: @@ -1978,7 +1979,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } case VM_OC_DEFAULT_INITIALIZER: { - JERRY_ASSERT (stack_top_p > frame_ctx_p->registers_p + register_end); + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); if (stack_top_p[-1] != ECMA_VALUE_UNDEFINED) { @@ -2100,7 +2101,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { *stack_top_p++ = ECMA_VALUE_REGISTER_REF; *stack_top_p++ = literal_index; - *stack_top_p++ = ecma_fast_copy_value (frame_ctx_p->registers_p[literal_index]); + *stack_top_p++ = ecma_fast_copy_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); } else { @@ -2344,8 +2345,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ JERRY_ASSERT (literal_index < register_end); JERRY_ASSERT (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))); - ecma_fast_free_value (frame_ctx_p->registers_p[literal_index]); - frame_ctx_p->registers_p[literal_index] = left_value; + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); + VM_GET_REGISTER (frame_ctx_p, literal_index) = left_value; continue; } case VM_OC_ASSIGN_PROP: @@ -2489,7 +2490,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { ecma_value_t value = *(--stack_top_p); - JERRY_ASSERT (stack_top_p > frame_ctx_p->registers_p + register_end); + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); if (ecma_op_strict_equality_compare (value, stack_top_p[-1])) { @@ -2585,7 +2586,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ if (literal_index < register_end) { - left_value = ecma_copy_value (frame_ctx_p->registers_p[literal_index]); + left_value = ecma_copy_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); } else { @@ -3194,7 +3195,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ case VM_OC_BLOCK_CREATE_CONTEXT: { #if ENABLED (JERRY_ES2015) - ecma_value_t *stack_context_top_p = frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth; + ecma_value_t *stack_context_top_p; + stack_context_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth; + JERRY_ASSERT (stack_context_top_p == stack_top_p || stack_context_top_p == stack_top_p - 1); if (byte_code_start_p[0] != CBC_EXT_OPCODE) @@ -3249,7 +3252,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); - JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); result = ecma_op_to_object (value); ecma_free_value (value); @@ -3279,7 +3282,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { ecma_value_t value = *(--stack_top_p); - JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); ecma_value_t expr_obj_value = ECMA_VALUE_UNDEFINED; ecma_collection_t *prop_names_p = opfunc_for_in (value, &expr_obj_value); @@ -3312,7 +3315,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } case VM_OC_FOR_IN_GET_NEXT: { - ecma_value_t *context_top_p = frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth; + ecma_value_t *context_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth; ecma_collection_t *collection_p; collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, context_top_p[-2]); @@ -3328,7 +3331,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } case VM_OC_FOR_IN_HAS_NEXT: { - JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); ecma_collection_t *collection_p; collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, stack_top_p[-2]); @@ -3371,7 +3374,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { ecma_value_t value = *(--stack_top_p); - JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); ecma_value_t iterator = ecma_op_get_iterator (value, ECMA_VALUE_EMPTY); @@ -3416,7 +3419,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } case VM_OC_FOR_OF_GET_NEXT: { - ecma_value_t *context_top_p = frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth; + ecma_value_t *context_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth; JERRY_ASSERT (VM_GET_CONTEXT_TYPE (context_top_p[-1]) == VM_CONTEXT_FOR_OF); ecma_value_t next_value = ecma_op_iterator_value (context_top_p[-2]); @@ -3432,7 +3435,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } case VM_OC_FOR_OF_HAS_NEXT: { - JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); ecma_value_t iterator_step = ecma_op_iterator_step (stack_top_p[-3]); @@ -3463,7 +3466,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ /* Try opcode simply creates the try context. */ branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); - JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION); stack_top_p += PARSER_TRY_CONTEXT_STACK_ALLOCATION; @@ -3474,7 +3477,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ case VM_OC_CATCH: { /* Catches are ignored and turned to jumps. */ - JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_TRY); byte_code_p = byte_code_start_p + branch_offset; @@ -3484,7 +3487,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); - JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_TRY || VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_CATCH); @@ -3505,7 +3508,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } case VM_OC_CONTEXT_END: { - JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); ecma_value_t context_type = VM_GET_CONTEXT_TYPE (stack_top_p[-1]); @@ -3513,7 +3516,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { stack_top_p = vm_stack_context_abort (frame_ctx_p, stack_top_p); - JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); continue; } @@ -3567,12 +3570,12 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ byte_code_p = frame_ctx_p->byte_code_start_p + jump_target; } - JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); continue; } case VM_OC_JUMP_AND_EXIT_CONTEXT: { - JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); @@ -3590,7 +3593,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ byte_code_p = frame_ctx_p->byte_code_start_p + branch_offset; } - JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); continue; } #if ENABLED (JERRY_DEBUGGER) @@ -3711,9 +3714,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ if (literal_index < register_end) { - ecma_fast_free_value (frame_ctx_p->registers_p[literal_index]); - - frame_ctx_p->registers_p[literal_index] = result; + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); + VM_GET_REGISTER (frame_ctx_p, literal_index) = result; if (opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)) { @@ -3749,9 +3751,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ if (object == ECMA_VALUE_REGISTER_REF) { - ecma_fast_free_value (frame_ctx_p->registers_p[property]); - - frame_ctx_p->registers_p[property] = result; + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, property)); + VM_GET_REGISTER (frame_ctx_p, property) = result; if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) { @@ -3805,7 +3806,7 @@ error: { ecma_value_t *vm_stack_p = stack_top_p; - for (vm_stack_p = frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth; + for (vm_stack_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth; vm_stack_p < stack_top_p; vm_stack_p++) { @@ -3820,7 +3821,7 @@ error: } } - stack_top_p = frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth; + stack_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth; #if ENABLED (JERRY_DEBUGGER) const uint32_t dont_stop = (JERRY_DEBUGGER_VM_IGNORE_EXCEPTION | JERRY_DEBUGGER_VM_IGNORE @@ -3854,7 +3855,7 @@ error: #endif /* ENABLED (JERRY_DEBUGGER) */ } - JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); if (frame_ctx_p->context_depth == 0) { @@ -3873,7 +3874,7 @@ error: 0)) { JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_RETURN); - JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); byte_code_p = frame_ctx_p->byte_code_p; stack_top_p[-2] = result; @@ -3887,7 +3888,7 @@ error: VM_CONTEXT_FINALLY_THROW, 0)) { - JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); JERRY_ASSERT (!(stack_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV)); #if ENABLED (JERRY_DEBUGGER) @@ -3914,7 +3915,7 @@ error: { do { - JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); stack_top_p = vm_stack_context_abort (frame_ctx_p, stack_top_p); } @@ -3932,19 +3933,29 @@ error: #undef READ_LITERAL_INDEX /** - * Execute code block. + * Initialize code block execution * * @return ecma value */ -static ecma_value_t JERRY_ATTR_NOINLINE -vm_execute (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ - const ecma_value_t *arg_p, /**< arguments list */ - ecma_length_t arg_list_len) /**< length of arguments list */ +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 */ + ecma_length_t arg_list_len) /**< length of arguments list */ { + 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) + frame_ctx_p->resource_name = ECMA_VALUE_UNDEFINED; +#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ +#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); + const ecma_compiled_code_t *bytecode_header_p = frame_ctx_p->bytecode_header_p; - ecma_value_t completion_value; - uint16_t argument_end; - uint16_t register_end; + uint16_t argument_end, register_end; + ecma_value_t *literal_p; if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) { @@ -3952,6 +3963,11 @@ vm_execute (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ argument_end = args_p->argument_end; register_end = args_p->register_end; + + literal_p = (ecma_value_t *) ((uint8_t *) bytecode_header_p + sizeof (cbc_uint16_arguments_t)); + literal_p -= register_end; + frame_ctx_p->literal_start_p = literal_p; + literal_p += args_p->literal_end; } else { @@ -3959,9 +3975,16 @@ vm_execute (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ argument_end = args_p->argument_end; register_end = args_p->register_end; + + literal_p = (ecma_value_t *) ((uint8_t *) bytecode_header_p + sizeof (cbc_uint8_arguments_t)); + literal_p -= register_end; + frame_ctx_p->literal_start_p = literal_p; + literal_p += args_p->literal_end; } - frame_ctx_p->stack_top_p = frame_ctx_p->registers_p + register_end; + frame_ctx_p->byte_code_p = (uint8_t *) literal_p; + 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_ES2015) uint32_t function_call_argument_count = arg_list_len; @@ -3974,14 +3997,14 @@ vm_execute (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ for (uint32_t i = 0; i < arg_list_len; i++) { - frame_ctx_p->registers_p[i] = ecma_fast_copy_value (arg_p[i]); + VM_GET_REGISTER (frame_ctx_p, i) = ecma_fast_copy_value (arg_p[i]); } /* The arg_list_len contains the end of the copied arguments. * Fill everything else with undefined. */ if (register_end > arg_list_len) { - ecma_value_t *stack_p = frame_ctx_p->registers_p + arg_list_len; + ecma_value_t *stack_p = VM_GET_REGISTERS (frame_ctx_p) + arg_list_len; for (uint32_t i = arg_list_len; i < register_end; i++) { @@ -3997,21 +4020,27 @@ vm_execute (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ function_call_argument_count - arg_list_len, false); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array)); - frame_ctx_p->registers_p[argument_end] = new_array; - arg_list_len++; + VM_GET_REGISTER (frame_ctx_p, argument_end) = new_array; } #endif /* ENABLED (JERRY_ES2015) */ JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_DIRECT_EVAL; - - vm_frame_ctx_t *prev_context_p = JERRY_CONTEXT (vm_top_context_p); JERRY_CONTEXT (vm_top_context_p) = frame_ctx_p; vm_init_loop (frame_ctx_p); +} /* vm_init_exec */ +/** + * Resume execution of a code block. + * + * @return ecma value + */ +static ecma_value_t JERRY_ATTR_NOINLINE +vm_execute (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ +{ while (true) { - completion_value = vm_loop (frame_ctx_p); + ecma_value_t completion_value = vm_loop (frame_ctx_p); switch (frame_ctx_p->call_operation) { @@ -4041,10 +4070,23 @@ 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; + uint32_t register_end; + + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + register_end = ((cbc_uint16_arguments_t *) bytecode_header_p)->register_end; + } + else + { + register_end = ((cbc_uint8_arguments_t *) bytecode_header_p)->register_end; + } + /* Free arguments and registers */ + ecma_value_t *registers_p = VM_GET_REGISTERS (frame_ctx_p); for (uint32_t i = 0; i < register_end; i++) { - ecma_fast_free_value (frame_ctx_p->registers_p[i]); + ecma_fast_free_value (registers_p[i]); } #if ENABLED (JERRY_DEBUGGER) @@ -4056,7 +4098,7 @@ vm_execute (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ } #endif /* ENABLED (JERRY_DEBUGGER) */ - JERRY_CONTEXT (vm_top_context_p) = prev_context_p; + JERRY_CONTEXT (vm_top_context_p) = frame_ctx_p->prev_context_p; return completion_value; } } @@ -4072,56 +4114,11 @@ ecma_value_t vm_run (const ecma_compiled_code_t *bytecode_header_p, /**< byte-code data header */ ecma_value_t this_binding_value, /**< value of 'ThisBinding' */ ecma_object_t *lex_env_p, /**< lexical environment to use */ - uint32_t parse_opts, /**< ecma_parse_opts_t option bits */ const ecma_value_t *arg_list_p, /**< arguments list */ ecma_length_t arg_list_len) /**< length of arguments list */ { - ecma_value_t *literal_p; - vm_frame_ctx_t frame_ctx; - uint32_t call_stack_size; - - if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) - { - cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p; - call_stack_size = (uint32_t) (args_p->register_end + args_p->stack_limit); - - literal_p = (ecma_value_t *) ((uint8_t *) bytecode_header_p + sizeof (cbc_uint16_arguments_t)); - literal_p -= args_p->register_end; - frame_ctx.literal_start_p = literal_p; - literal_p += args_p->literal_end; - } - else - { - cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p; - call_stack_size = (uint32_t) (args_p->register_end + args_p->stack_limit); - - literal_p = (ecma_value_t *) ((uint8_t *) bytecode_header_p + sizeof (cbc_uint8_arguments_t)); - literal_p -= args_p->register_end; - frame_ctx.literal_start_p = literal_p; - literal_p += args_p->literal_end; - } - - frame_ctx.bytecode_header_p = bytecode_header_p; - frame_ctx.byte_code_p = (uint8_t *) literal_p; - frame_ctx.byte_code_start_p = (uint8_t *) literal_p; - frame_ctx.lex_env_p = lex_env_p; -#if defined (JERRY_DEBUGGER) || ENABLED (JERRY_LINE_INFO) - frame_ctx.prev_context_p = JERRY_CONTEXT (vm_top_context_p); -#endif /* defined (JERRY_DEBUGGER) || ENABLED (JERRY_LINE_INFO) */ - frame_ctx.this_binding = this_binding_value; - frame_ctx.block_result = ECMA_VALUE_UNDEFINED; -#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) - frame_ctx.resource_name = ECMA_VALUE_UNDEFINED; -#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ -#if ENABLED (JERRY_LINE_INFO) - frame_ctx.current_line = 0; -#endif /* ENABLED (JERRY_LINE_INFO) */ - frame_ctx.context_depth = 0; - frame_ctx.is_eval_code = parse_opts & ECMA_PARSE_DIRECT_EVAL; - - /* Use JERRY_MAX() to avoid array declaration with size 0. */ - JERRY_VLA (ecma_value_t, stack, JERRY_MAX (call_stack_size, 1)); - frame_ctx.registers_p = stack; + vm_frame_ctx_t *frame_ctx_p; + size_t frame_size; #if ENABLED (JERRY_ES2015_MODULE_SYSTEM) if (JERRY_CONTEXT (module_top_context_p) != NULL) @@ -4144,7 +4141,31 @@ vm_run (const ecma_compiled_code_t *bytecode_header_p, /**< byte-code data heade } #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ - return vm_execute (&frame_ctx, arg_list_p, arg_list_len); + if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p; + frame_size = (size_t) (args_p->register_end + args_p->stack_limit); + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p; + frame_size = (size_t) (args_p->register_end + args_p->stack_limit); + } + + frame_size = frame_size * sizeof (ecma_value_t) + sizeof (vm_frame_ctx_t); + frame_size = (frame_size + sizeof (uintptr_t) - 1) / sizeof (uintptr_t); + + /* Use JERRY_MAX() to avoid array declaration with size 0. */ + JERRY_VLA (uintptr_t, stack, frame_size); + + frame_ctx_p = (vm_frame_ctx_t *) stack; + + frame_ctx_p->bytecode_header_p = bytecode_header_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); + return vm_execute (frame_ctx_p); } /* vm_run */ /** diff --git a/jerry-core/vm/vm.h b/jerry-core/vm/vm.h index cffbf6c2d..e9976d301 100644 --- a/jerry-core/vm/vm.h +++ b/jerry-core/vm/vm.h @@ -399,8 +399,7 @@ ecma_value_t vm_run_module (const ecma_compiled_code_t *bytecode_p, ecma_object_ #endif /* ENABLED (JERRY_ES2015_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, uint32_t parse_opts, const ecma_value_t *arg_list_p, - ecma_length_t arg_list_len); + ecma_object_t *lex_env_p, const ecma_value_t *arg_list_p, ecma_length_t arg_list_len); bool vm_is_strict_mode (void); bool vm_is_direct_eval_form_call (void);