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
This commit is contained in:
Zoltan Herczeg
2019-11-22 12:47:11 +01:00
committed by Robert Fancsik
parent 996bf76f59
commit d006f068f4
4 changed files with 148 additions and 122 deletions
@@ -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, ecma_value_t ret_value = vm_run (bytecode_data_p,
this_binding, this_binding,
local_env_p, local_env_p,
ECMA_PARSE_NO_OPTS,
arguments_list_p, arguments_list_p,
arguments_list_len); 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, ecma_value_t ret_value = vm_run (bytecode_data_p,
arrow_func_p->this_binding, arrow_func_p->this_binding,
local_env_p, local_env_p,
ECMA_PARSE_NO_OPTS,
arguments_list_p, arguments_list_p,
arguments_list_len); arguments_list_len);
+11 -3
View File
@@ -43,13 +43,10 @@ typedef struct vm_frame_ctx_t
const ecma_compiled_code_t *bytecode_header_p; /**< currently executed byte-code data */ 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_p; /**< current byte code pointer */
uint8_t *byte_code_start_p; /**< byte code start 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 *stack_top_p; /**< stack top pointer */
ecma_value_t *literal_start_p; /**< literal list start pointer */ ecma_value_t *literal_start_p; /**< literal list start pointer */
ecma_object_t *lex_env_p; /**< current lexical environment */ 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 */ 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 this_binding; /**< this binding */
ecma_value_t block_result; /**< block result */ ecma_value_t block_result; /**< block result */
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) #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 */ uint16_t context_depth; /**< current context depth */
uint8_t is_eval_code; /**< eval mode flag */ uint8_t is_eval_code; /**< eval mode flag */
uint8_t call_operation; /**< perform a call or construct operation */ uint8_t call_operation; /**< perform a call or construct operation */
/* Registers start immediately after the frame context. */
} vm_frame_ctx_t; } 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])
/** /**
* @} * @}
* @} * @}
+136 -115
View File
@@ -43,6 +43,11 @@
* @{ * @{
*/ */
/**
* Special constant to represent direct eval code.
*/
#define VM_DIRECT_EVAL ((void *) 0x1)
/** /**
* Get the value of object[property]. * 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, return vm_run (bytecode_p,
ecma_make_object_value (glob_obj_p), ecma_make_object_value (glob_obj_p),
lex_env_p, lex_env_p,
false,
NULL, NULL,
0); 0);
} /* vm_run_module */ } /* 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, return vm_run (bytecode_p,
ecma_make_object_value (glob_obj_p), ecma_make_object_value (glob_obj_p),
ecma_get_global_environment (), ecma_get_global_environment (),
false,
NULL, NULL,
0); 0);
} /* vm_run_global */ } /* 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, ecma_value_t completion_value = vm_run (bytecode_data_p,
this_binding, this_binding,
lex_env_p, lex_env_p,
parse_opts, (parse_opts & ECMA_PARSE_DIRECT_EVAL) ? VM_DIRECT_EVAL : NULL,
NULL,
0); 0);
ecma_deref_object (lex_env_p); 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) \ if ((literal_index) < register_end) \
{ \ { \
/* Note: There should be no specialization for arguments. */ \ /* 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 \ else \
{ \ { \
@@ -973,7 +975,7 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
if (value_index < register_end) if (value_index < register_end)
{ {
/* Take (not copy) the reference. */ /* 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 else
{ {
@@ -983,8 +985,8 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
if (literal_index < register_end) if (literal_index < register_end)
{ {
ecma_fast_free_value (frame_ctx_p->registers_p[literal_index]); ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index));
frame_ctx_p->registers_p[literal_index] = lit_value; VM_GET_REGISTER (frame_ctx_p, literal_index) = lit_value;
break; break;
} }
@@ -1080,8 +1082,8 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
if (literal_index < register_end) if (literal_index < register_end)
{ {
ecma_fast_free_value (frame_ctx_p->registers_p[literal_index]); ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index));
frame_ctx_p->registers_p[literal_index] = lit_value; VM_GET_REGISTER (frame_ctx_p, literal_index) = lit_value;
break; break;
} }
@@ -1205,7 +1207,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
} }
case VM_OC_GET_STACK_LITERAL: 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; right_value = left_value;
left_value = *(--stack_top_p); left_value = *(--stack_top_p);
break; break;
@@ -1226,12 +1228,12 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
JERRY_ASSERT (operands == VM_OC_GET_STACK JERRY_ASSERT (operands == VM_OC_GET_STACK
|| operands == VM_OC_GET_STACK_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); left_value = *(--stack_top_p);
if (operands == VM_OC_GET_STACK_STACK) 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; right_value = left_value;
left_value = *(--stack_top_p); left_value = *(--stack_top_p);
} }
@@ -1295,7 +1297,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{ {
case VM_OC_POP: 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)); ecma_free_value (*(--stack_top_p));
continue; 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); stack_top_p[-1] = VM_CREATE_CONTEXT_WITH_ENV (VM_CONTEXT_SUPER_CLASS, branch_offset);
frame_ctx_p->lex_env_p = super_env_p; frame_ctx_p->lex_env_p = super_env_p;
continue; continue;
} }
case VM_OC_CLASS_INHERITANCE: 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: 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) 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++ = ECMA_VALUE_REGISTER_REF;
*stack_top_p++ = literal_index; *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 else
{ {
@@ -2344,8 +2345,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
JERRY_ASSERT (literal_index < register_end); JERRY_ASSERT (literal_index < register_end);
JERRY_ASSERT (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))); JERRY_ASSERT (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)));
ecma_fast_free_value (frame_ctx_p->registers_p[literal_index]); ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index));
frame_ctx_p->registers_p[literal_index] = left_value; VM_GET_REGISTER (frame_ctx_p, literal_index) = left_value;
continue; continue;
} }
case VM_OC_ASSIGN_PROP: 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); 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])) 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) 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 else
{ {
@@ -3194,7 +3195,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
case VM_OC_BLOCK_CREATE_CONTEXT: case VM_OC_BLOCK_CREATE_CONTEXT:
{ {
#if ENABLED (JERRY_ES2015) #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); 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) 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); 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); result = ecma_op_to_object (value);
ecma_free_value (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); 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_value_t expr_obj_value = ECMA_VALUE_UNDEFINED;
ecma_collection_t *prop_names_p = opfunc_for_in (value, &expr_obj_value); 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: 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; ecma_collection_t *collection_p;
collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, context_top_p[-2]); 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: 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; ecma_collection_t *collection_p;
collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, stack_top_p[-2]); 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); 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); 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: 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); 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]); 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: 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]); 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. */ /* Try opcode simply creates the try context. */
branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); 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); VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION);
stack_top_p += 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: case VM_OC_CATCH:
{ {
/* Catches are ignored and turned to jumps. */ /* 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); JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_TRY);
byte_code_p = byte_code_start_p + branch_offset; 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); 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 JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_TRY
|| VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_CATCH); || 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: 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]); 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); 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; 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; 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; continue;
} }
case VM_OC_JUMP_AND_EXIT_CONTEXT: 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); 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; 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; continue;
} }
#if ENABLED (JERRY_DEBUGGER) #if ENABLED (JERRY_DEBUGGER)
@@ -3711,9 +3714,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
if (literal_index < register_end) if (literal_index < register_end)
{ {
ecma_fast_free_value (frame_ctx_p->registers_p[literal_index]); ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index));
VM_GET_REGISTER (frame_ctx_p, literal_index) = result;
frame_ctx_p->registers_p[literal_index] = result;
if (opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)) 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) if (object == ECMA_VALUE_REGISTER_REF)
{ {
ecma_fast_free_value (frame_ctx_p->registers_p[property]); ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, property));
VM_GET_REGISTER (frame_ctx_p, property) = result;
frame_ctx_p->registers_p[property] = result;
if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) 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; 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 < stack_top_p;
vm_stack_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) #if ENABLED (JERRY_DEBUGGER)
const uint32_t dont_stop = (JERRY_DEBUGGER_VM_IGNORE_EXCEPTION const uint32_t dont_stop = (JERRY_DEBUGGER_VM_IGNORE_EXCEPTION
| JERRY_DEBUGGER_VM_IGNORE | JERRY_DEBUGGER_VM_IGNORE
@@ -3854,7 +3855,7 @@ error:
#endif /* ENABLED (JERRY_DEBUGGER) */ #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) if (frame_ctx_p->context_depth == 0)
{ {
@@ -3873,7 +3874,7 @@ error:
0)) 0))
{ {
JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FINALLY_RETURN); 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; byte_code_p = frame_ctx_p->byte_code_p;
stack_top_p[-2] = result; stack_top_p[-2] = result;
@@ -3887,7 +3888,7 @@ error:
VM_CONTEXT_FINALLY_THROW, VM_CONTEXT_FINALLY_THROW,
0)) 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)); JERRY_ASSERT (!(stack_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV));
#if ENABLED (JERRY_DEBUGGER) #if ENABLED (JERRY_DEBUGGER)
@@ -3914,7 +3915,7 @@ error:
{ {
do 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); stack_top_p = vm_stack_context_abort (frame_ctx_p, stack_top_p);
} }
@@ -3932,19 +3933,29 @@ error:
#undef READ_LITERAL_INDEX #undef READ_LITERAL_INDEX
/** /**
* Execute code block. * Initialize code block execution
* *
* @return ecma value * @return ecma value
*/ */
static ecma_value_t JERRY_ATTR_NOINLINE static void JERRY_ATTR_NOINLINE
vm_execute (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ vm_init_exec (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
const ecma_value_t *arg_p, /**< arguments list */ const ecma_value_t *arg_p, /**< arguments list */
ecma_length_t arg_list_len) /**< length of 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; const ecma_compiled_code_t *bytecode_header_p = frame_ctx_p->bytecode_header_p;
ecma_value_t completion_value; uint16_t argument_end, register_end;
uint16_t argument_end; ecma_value_t *literal_p;
uint16_t register_end;
if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) 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; argument_end = args_p->argument_end;
register_end = args_p->register_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 else
{ {
@@ -3959,9 +3975,16 @@ vm_execute (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
argument_end = args_p->argument_end; argument_end = args_p->argument_end;
register_end = args_p->register_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) #if ENABLED (JERRY_ES2015)
uint32_t function_call_argument_count = arg_list_len; 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++) 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. /* The arg_list_len contains the end of the copied arguments.
* Fill everything else with undefined. */ * Fill everything else with undefined. */
if (register_end > arg_list_len) 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++) 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, function_call_argument_count - arg_list_len,
false); false);
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array)); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array));
frame_ctx_p->registers_p[argument_end] = new_array; VM_GET_REGISTER (frame_ctx_p, argument_end) = new_array;
arg_list_len++;
} }
#endif /* ENABLED (JERRY_ES2015) */ #endif /* ENABLED (JERRY_ES2015) */
JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_DIRECT_EVAL; 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; JERRY_CONTEXT (vm_top_context_p) = frame_ctx_p;
vm_init_loop (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) 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) 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); 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 */ /* Free arguments and registers */
ecma_value_t *registers_p = VM_GET_REGISTERS (frame_ctx_p);
for (uint32_t i = 0; i < register_end; i++) 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) #if ENABLED (JERRY_DEBUGGER)
@@ -4056,7 +4098,7 @@ vm_execute (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
} }
#endif /* ENABLED (JERRY_DEBUGGER) */ #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; return completion_value;
} }
} }
@@ -4072,56 +4114,11 @@ ecma_value_t
vm_run (const ecma_compiled_code_t *bytecode_header_p, /**< byte-code data header */ vm_run (const ecma_compiled_code_t *bytecode_header_p, /**< byte-code data header */
ecma_value_t this_binding_value, /**< value of 'ThisBinding' */ ecma_value_t this_binding_value, /**< value of 'ThisBinding' */
ecma_object_t *lex_env_p, /**< lexical environment to use */ 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 */ const ecma_value_t *arg_list_p, /**< arguments list */
ecma_length_t arg_list_len) /**< length of arguments list */ ecma_length_t arg_list_len) /**< length of arguments list */
{ {
ecma_value_t *literal_p; vm_frame_ctx_t *frame_ctx_p;
vm_frame_ctx_t frame_ctx; size_t frame_size;
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;
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM) #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
if (JERRY_CONTEXT (module_top_context_p) != NULL) 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) */ #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 */ } /* vm_run */
/** /**
+1 -2
View File
@@ -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) */ #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_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_object_t *lex_env_p, const ecma_value_t *arg_list_p, ecma_length_t arg_list_len);
ecma_length_t arg_list_len);
bool vm_is_strict_mode (void); bool vm_is_strict_mode (void);
bool vm_is_direct_eval_form_call (void); bool vm_is_direct_eval_form_call (void);