Remove vm_init_loop (#3551)

For every bytecode in the above function, i created a new VM_OC group code
to be able to execute them in the vm_loop. With this update, the expectation
is a faster runtime.

JerryScript-DCO-1.0-Signed-off-by: Adam Szilagyi aszilagy@inf.u-szeged.hu
This commit is contained in:
Szilagyi Adam
2020-02-19 16:49:35 +01:00
committed by GitHub
parent 98b90ba697
commit f8da3d5e9d
3 changed files with 161 additions and 258 deletions
+8 -8
View File
@@ -303,23 +303,23 @@
CBC_OPCODE (CBC_EVAL, CBC_NO_FLAG, 0, \
VM_OC_EVAL) \
CBC_OPCODE (CBC_CREATE_VAR, CBC_HAS_LITERAL_ARG, 0, \
VM_OC_INIT_LOCALS) \
VM_OC_CREATE_BINDING) \
CBC_OPCODE (CBC_CREATE_LET, CBC_HAS_LITERAL_ARG, 0, \
VM_OC_INIT_LOCALS) \
VM_OC_CREATE_BINDING) \
CBC_OPCODE (CBC_CREATE_CONST, CBC_HAS_LITERAL_ARG, 0, \
VM_OC_INIT_LOCALS) \
VM_OC_CREATE_BINDING) \
CBC_OPCODE (CBC_CREATE_LOCAL, CBC_HAS_LITERAL_ARG, 0, \
VM_OC_NONE) \
VM_OC_CREATE_BINDING) \
CBC_OPCODE (CBC_INIT_LOCAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
VM_OC_INIT_LOCALS) \
VM_OC_INIT_LOCAL) \
CBC_OPCODE (CBC_CREATE_VAR_EVAL, CBC_HAS_LITERAL_ARG, 0, \
VM_OC_NONE) \
VM_OC_VAR_EVAL) \
CBC_OPCODE (CBC_CREATE_VAR_FUNC_EVAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
VM_OC_NONE) \
VM_OC_VAR_EVAL) \
CBC_OPCODE (CBC_SET_VAR_FUNC, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT) \
CBC_OPCODE (CBC_SET_BYTECODE_PTR, CBC_NO_FLAG, 0, \
VM_OC_NONE) \
VM_OC_SET_BYTECODE_PTR) \
CBC_OPCODE (CBC_RETURN, CBC_NO_FLAG, -1, \
VM_OC_RETURN | VM_OC_GET_STACK) \
CBC_OPCODE (CBC_RETURN_WITH_BLOCK, CBC_NO_FLAG, 0, \
+148 -248
View File
@@ -876,244 +876,6 @@ opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
} \
while (0)
/**
* Run initializer byte codes.
*
* @return ecma value
*/
static void
vm_init_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 uint8_t *byte_code_p = frame_ctx_p->byte_code_p;
uint16_t encoding_limit;
uint16_t encoding_delta;
uint16_t register_end;
ecma_value_t *literal_start_p = frame_ctx_p->literal_start_p;
bool is_strict = ((frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0);
/* Prepare. */
if (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_FULL_LITERAL_ENCODING))
{
encoding_limit = CBC_SMALL_LITERAL_ENCODING_LIMIT;
encoding_delta = CBC_SMALL_LITERAL_ENCODING_DELTA;
}
else
{
encoding_limit = CBC_FULL_LITERAL_ENCODING_LIMIT;
encoding_delta = CBC_FULL_LITERAL_ENCODING_DELTA;
}
if (frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
{
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) (frame_ctx_p->bytecode_header_p);
register_end = args_p->register_end;
}
else
{
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) (frame_ctx_p->bytecode_header_p);
register_end = args_p->register_end;
}
while (true)
{
uint8_t type = *byte_code_p;
switch (type)
{
case CBC_CREATE_VAR:
#if ENABLED (JERRY_ES2015)
case CBC_CREATE_LET:
case CBC_CREATE_CONST:
case CBC_CREATE_LOCAL:
#endif /* ENABLED (JERRY_ES2015) */
{
uint32_t literal_index;
byte_code_p++;
READ_LITERAL_INDEX (literal_index);
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
JERRY_ASSERT (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE);
JERRY_ASSERT (ecma_find_named_property (frame_ctx_p->lex_env_p, name_p) == NULL);
uint8_t prop_attributes = ECMA_PROPERTY_FLAG_WRITABLE;
#if ENABLED (JERRY_ES2015)
if (type == CBC_CREATE_LET)
{
prop_attributes = ECMA_PROPERTY_ENUMERABLE_WRITABLE;
}
else if (type == CBC_CREATE_CONST)
{
prop_attributes = ECMA_PROPERTY_FLAG_ENUMERABLE;
}
ecma_property_value_t *property_value_p;
property_value_p = ecma_create_named_data_property (frame_ctx_p->lex_env_p, name_p, prop_attributes, NULL);
if (type != CBC_CREATE_VAR)
{
property_value_p->value = ECMA_VALUE_UNINITIALIZED;
}
#else /* !ENABLED (JERRY_ES2015) */
ecma_create_named_data_property (frame_ctx_p->lex_env_p, name_p, prop_attributes, NULL);
#endif /* ENABLED (JERRY_ES2015) */
break;
}
case CBC_INIT_LOCAL:
{
uint32_t literal_index, value_index;
ecma_value_t lit_value;
byte_code_p++;
READ_LITERAL_INDEX (value_index);
READ_LITERAL_INDEX (literal_index);
JERRY_ASSERT (value_index != literal_index);
JERRY_ASSERT (value_index >= register_end || literal_index >= register_end);
if (value_index < register_end)
{
/* Take (not copy) the reference. */
lit_value = ecma_copy_value_if_not_object (VM_GET_REGISTER (frame_ctx_p, value_index));
}
else
{
lit_value = vm_construct_literal_object (frame_ctx_p,
literal_start_p[value_index]);
}
if (literal_index < register_end)
{
ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index));
VM_GET_REGISTER (frame_ctx_p, literal_index) = lit_value;
break;
}
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
JERRY_ASSERT (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE);
JERRY_ASSERT (ecma_find_named_property (frame_ctx_p->lex_env_p, name_p) == NULL);
ecma_property_value_t *property_value_p;
property_value_p = ecma_create_named_data_property (frame_ctx_p->lex_env_p,
name_p,
ECMA_PROPERTY_FLAG_WRITABLE,
NULL);
JERRY_ASSERT (property_value_p->value == ECMA_VALUE_UNDEFINED);
property_value_p->value = lit_value;
if (value_index >= register_end)
{
ecma_free_value (lit_value);
}
break;
}
case CBC_CREATE_VAR_EVAL:
case CBC_CREATE_VAR_FUNC_EVAL:
{
uint32_t literal_index;
ecma_value_t lit_value = ECMA_VALUE_UNDEFINED;
byte_code_p++;
if (type == CBC_CREATE_VAR_FUNC_EVAL)
{
uint32_t value_index;
READ_LITERAL_INDEX (value_index);
lit_value = vm_construct_literal_object (frame_ctx_p,
literal_start_p[value_index]);
}
READ_LITERAL_INDEX (literal_index);
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p;
while (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK)
{
#if ENABLED (JERRY_ES2015) && !(defined JERRY_NDEBUG)
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
{
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
JERRY_ASSERT (property_p == NULL || !(*property_p & ECMA_PROPERTY_FLAG_ENUMERABLE));
}
#endif /* ENABLED (JERRY_ES2015) && !JERRY_NDEBUG */
JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
}
#if ENABLED (JERRY_ES2015) && !(defined JERRY_NDEBUG)
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
{
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
JERRY_ASSERT (property_p == NULL || !(*property_p & ECMA_PROPERTY_FLAG_ENUMERABLE));
}
#endif /* ENABLED (JERRY_ES2015) && !JERRY_NDEBUG */
vm_var_decl (lex_env_p, name_p, frame_ctx_p->is_eval_code);
if (lit_value != ECMA_VALUE_UNDEFINED)
{
vm_set_var (lex_env_p, name_p, is_strict, lit_value);
}
break;
}
case CBC_SET_VAR_FUNC:
{
uint32_t literal_index, value_index;
ecma_value_t lit_value;
byte_code_p++;
READ_LITERAL_INDEX (value_index);
READ_LITERAL_INDEX (literal_index);
JERRY_ASSERT (value_index != literal_index && value_index >= register_end);
lit_value = vm_construct_literal_object (frame_ctx_p,
literal_start_p[value_index]);
if (literal_index < register_end)
{
ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index));
VM_GET_REGISTER (frame_ctx_p, literal_index) = lit_value;
break;
}
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
vm_set_var (frame_ctx_p->lex_env_p, name_p, is_strict, lit_value);
break;
}
#if ENABLED (JERRY_SNAPSHOT_EXEC)
case CBC_SET_BYTECODE_PTR:
{
memcpy (&byte_code_p, byte_code_p + 1, sizeof (uint8_t *));
frame_ctx_p->byte_code_start_p = byte_code_p;
break;
}
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
default:
{
frame_ctx_p->byte_code_p = byte_code_p;
return;
}
}
}
} /* vm_init_loop */
/**
* Run generic byte code.
*
@@ -1432,14 +1194,149 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
*stack_top_p++ = left_value;
continue;
}
#if ENABLED (JERRY_ES2015)
case VM_OC_INIT_LOCALS:
case VM_OC_CREATE_BINDING:
{
frame_ctx_p->byte_code_p = byte_code_start_p;
vm_init_loop (frame_ctx_p);
byte_code_p = frame_ctx_p->byte_code_p;
#if !ENABLED (JERRY_ES2015)
JERRY_ASSERT (opcode == CBC_CREATE_VAR);
#endif /* !ENABLED (JERRY_ES2015) */
uint32_t literal_index;
READ_LITERAL_INDEX (literal_index);
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
JERRY_ASSERT (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE);
JERRY_ASSERT (ecma_find_named_property (frame_ctx_p->lex_env_p, name_p) == NULL);
uint8_t prop_attributes = ECMA_PROPERTY_FLAG_WRITABLE;
#if ENABLED (JERRY_ES2015)
if (opcode == CBC_CREATE_LET)
{
prop_attributes = ECMA_PROPERTY_ENUMERABLE_WRITABLE;
}
else if (opcode == CBC_CREATE_CONST)
{
prop_attributes = ECMA_PROPERTY_FLAG_ENUMERABLE;
}
ecma_property_value_t *property_value_p;
property_value_p = ecma_create_named_data_property (frame_ctx_p->lex_env_p, name_p, prop_attributes, NULL);
if (opcode != CBC_CREATE_VAR)
{
property_value_p->value = ECMA_VALUE_UNINITIALIZED;
}
#else /* !ENABLED (JERRY_ES2015) */
ecma_create_named_data_property (frame_ctx_p->lex_env_p, name_p, prop_attributes, NULL);
#endif /* ENABLED (JERRY_ES2015) */
continue;
}
case VM_OC_VAR_EVAL:
{
uint32_t literal_index;
ecma_value_t lit_value = ECMA_VALUE_UNDEFINED;
if (opcode == CBC_CREATE_VAR_FUNC_EVAL)
{
uint32_t value_index;
READ_LITERAL_INDEX (value_index);
lit_value = vm_construct_literal_object (frame_ctx_p,
literal_start_p[value_index]);
}
READ_LITERAL_INDEX (literal_index);
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p;
while (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK)
{
#if ENABLED (JERRY_ES2015) && !(defined JERRY_NDEBUG)
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
{
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
JERRY_ASSERT (property_p == NULL || !(*property_p & ECMA_PROPERTY_FLAG_ENUMERABLE));
}
#endif /* ENABLED (JERRY_ES2015) && !JERRY_NDEBUG */
JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
}
#if ENABLED (JERRY_ES2015) && !(defined JERRY_NDEBUG)
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
{
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
JERRY_ASSERT (property_p == NULL || !(*property_p & ECMA_PROPERTY_FLAG_ENUMERABLE));
}
#endif /* ENABLED (JERRY_ES2015) && !JERRY_NDEBUG */
vm_var_decl (lex_env_p, name_p, frame_ctx_p->is_eval_code);
if (lit_value != ECMA_VALUE_UNDEFINED)
{
vm_set_var (lex_env_p, name_p, is_strict, lit_value);
}
continue;
}
case VM_OC_INIT_LOCAL:
{
uint32_t literal_index, value_index;
ecma_value_t lit_value;
READ_LITERAL_INDEX (value_index);
READ_LITERAL_INDEX (literal_index);
JERRY_ASSERT (value_index != literal_index);
JERRY_ASSERT (value_index >= register_end || literal_index >= register_end);
if (value_index < register_end)
{
/* Take (not copy) the reference. */
lit_value = ecma_copy_value_if_not_object (VM_GET_REGISTER (frame_ctx_p, value_index));
}
else
{
lit_value = vm_construct_literal_object (frame_ctx_p,
literal_start_p[value_index]);
}
if (literal_index < register_end)
{
ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index));
VM_GET_REGISTER (frame_ctx_p, literal_index) = lit_value;
continue;
}
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
JERRY_ASSERT (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE);
JERRY_ASSERT (ecma_find_named_property (frame_ctx_p->lex_env_p, name_p) == NULL);
ecma_property_value_t *property_value_p;
property_value_p = ecma_create_named_data_property (frame_ctx_p->lex_env_p,
name_p,
ECMA_PROPERTY_FLAG_WRITABLE,
NULL);
JERRY_ASSERT (property_value_p->value == ECMA_VALUE_UNDEFINED);
property_value_p->value = lit_value;
if (value_index >= register_end)
{
ecma_free_value (lit_value);
}
continue;
}
#if ENABLED (JERRY_ES2015)
case VM_OC_ASSIGN_LET_CONST:
{
uint32_t literal_index;
@@ -1515,6 +1412,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
/* FALLTHRU */
}
#endif /* ENABLED (JERRY_ES2015) */
#if ENABLED (JERRY_SNAPSHOT_EXEC)
case VM_OC_SET_BYTECODE_PTR:
{
memcpy (&byte_code_p, byte_code_p++, sizeof (uint8_t *));
frame_ctx_p->byte_code_start_p = byte_code_p;
continue;
}
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
case VM_OC_SET_PROPERTY:
{
JERRY_STATIC_ASSERT (VM_OC_NON_STATIC_FLAG == VM_OC_BACKWARD_BRANCH,
@@ -3380,9 +3285,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
frame_ctx_p->lex_env_p = ecma_create_decl_lex_env (frame_ctx_p->lex_env_p);
frame_ctx_p->lex_env_p->type_flags_refs |= (uint16_t) ECMA_OBJECT_FLAG_BLOCK;
frame_ctx_p->byte_code_p = byte_code_p;
vm_init_loop (frame_ctx_p);
byte_code_p = frame_ctx_p->byte_code_p;
continue;
}
case VM_OC_WITH:
@@ -4183,8 +4085,6 @@ vm_init_exec (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_DIRECT_EVAL;
JERRY_CONTEXT (vm_top_context_p) = frame_ctx_p;
vm_init_loop (frame_ctx_p);
} /* vm_init_exec */
/**
+5 -2
View File
@@ -213,6 +213,11 @@ typedef enum
VM_OC_CONTEXT_END, /**< context end */
VM_OC_JUMP_AND_EXIT_CONTEXT, /**< jump and exit context */
VM_OC_CREATE_BINDING, /**< create variables */
VM_OC_SET_BYTECODE_PTR, /**< setting bytecode pointer */
VM_OC_VAR_EVAL, /**< variable and function evaluation */
VM_OC_INIT_LOCAL, /**< initialize local variable */
#if ENABLED (JERRY_DEBUGGER)
VM_OC_BREAKPOINT_ENABLED, /**< enabled breakpoint for debugger */
VM_OC_BREAKPOINT_DISABLED, /**< disabled breakpoint for debugger */
@@ -224,7 +229,6 @@ typedef enum
VM_OC_LINE, /**< line number of the next statement */
#endif /* ENABLED (JERRY_LINE_INFO) */
#if ENABLED (JERRY_ES2015)
VM_OC_INIT_LOCALS, /**< call vm_init_loop() */
VM_OC_ASSIGN_LET_CONST, /**< assign values to let/const declarations */
VM_OC_COPY_TO_GLOBAL, /**< copy value to global lex env */
VM_OC_CLONE_CONTEXT, /**< clone lexical environment with let/const declarations */
@@ -282,7 +286,6 @@ typedef enum
VM_OC_LINE = VM_OC_NONE, /**< line number of the next statement is unused */
#endif /* !ENABLED (JERRY_LINE_INFO) */
#if !ENABLED (JERRY_ES2015)
VM_OC_INIT_LOCALS = VM_OC_NONE, /**< call vm_init_loop() */
VM_OC_ASSIGN_LET_CONST = VM_OC_NONE, /**< assign values to let/const declarations */
VM_OC_COPY_TO_GLOBAL = VM_OC_NONE, /**< copy value to global lex env */
VM_OC_CLONE_CONTEXT = VM_OC_NONE, /**< clone lexical environment with let/const declarations */