mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Non-recursive vm_loop to reduce stack usage.
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
parent
2c72bb1139
commit
1200be42b4
@ -295,9 +295,9 @@
|
||||
CBC_OPCODE (CBC_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0, \
|
||||
VM_OC_NEW | VM_OC_GET_BYTE | VM_OC_PUT_STACK) \
|
||||
CBC_OPCODE (CBC_NEW0, CBC_NO_FLAG, 0, \
|
||||
VM_OC_NEW_N | VM_OC_PUT_STACK) \
|
||||
VM_OC_NEW | VM_OC_PUT_STACK) \
|
||||
CBC_OPCODE (CBC_NEW1, CBC_NO_FLAG, -1, \
|
||||
VM_OC_NEW_N | VM_OC_PUT_STACK) \
|
||||
VM_OC_NEW | VM_OC_PUT_STACK) \
|
||||
CBC_OPCODE (CBC_EVAL, CBC_NO_FLAG, 0, \
|
||||
VM_OC_EVAL) \
|
||||
CBC_OPCODE (CBC_DEFINE_VARS, CBC_HAS_LITERAL_ARG, 0, \
|
||||
@ -405,47 +405,47 @@
|
||||
CBC_OPCODE (CBC_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, \
|
||||
VM_OC_CALL | VM_OC_GET_BYTE | VM_OC_PUT_BLOCK) \
|
||||
CBC_OPCODE (CBC_CALL_PROP, CBC_HAS_POP_STACK_BYTE_ARG, -3, \
|
||||
VM_OC_CALL_PROP | VM_OC_GET_BYTE) \
|
||||
VM_OC_CALL | VM_OC_GET_BYTE) \
|
||||
CBC_OPCODE (CBC_CALL_PROP_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, -2, \
|
||||
VM_OC_CALL_PROP | VM_OC_GET_BYTE | VM_OC_PUT_STACK) \
|
||||
VM_OC_CALL | VM_OC_GET_BYTE | VM_OC_PUT_STACK) \
|
||||
CBC_OPCODE (CBC_CALL_PROP_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -3, \
|
||||
VM_OC_CALL_PROP | VM_OC_GET_BYTE | VM_OC_PUT_BLOCK) \
|
||||
VM_OC_CALL | VM_OC_GET_BYTE | VM_OC_PUT_BLOCK) \
|
||||
CBC_OPCODE (CBC_CALL0, CBC_NO_FLAG, -1, \
|
||||
VM_OC_CALL_N) \
|
||||
VM_OC_CALL) \
|
||||
CBC_OPCODE (CBC_CALL0_PUSH_RESULT, CBC_NO_FLAG, 0, \
|
||||
VM_OC_CALL_N | VM_OC_PUT_STACK) \
|
||||
VM_OC_CALL | VM_OC_PUT_STACK) \
|
||||
CBC_OPCODE (CBC_CALL0_BLOCK, CBC_NO_FLAG, -1, \
|
||||
VM_OC_CALL_N | VM_OC_PUT_BLOCK) \
|
||||
VM_OC_CALL | VM_OC_PUT_BLOCK) \
|
||||
CBC_OPCODE (CBC_CALL0_PROP, CBC_NO_FLAG, -3, \
|
||||
VM_OC_CALL_PROP_N) \
|
||||
VM_OC_CALL) \
|
||||
CBC_OPCODE (CBC_CALL0_PROP_PUSH_RESULT, CBC_NO_FLAG, -2, \
|
||||
VM_OC_CALL_PROP_N | VM_OC_PUT_STACK) \
|
||||
VM_OC_CALL | VM_OC_PUT_STACK) \
|
||||
CBC_OPCODE (CBC_CALL0_PROP_BLOCK, CBC_NO_FLAG, -3, \
|
||||
VM_OC_CALL_PROP_N | VM_OC_PUT_BLOCK) \
|
||||
VM_OC_CALL | VM_OC_PUT_BLOCK) \
|
||||
CBC_OPCODE (CBC_CALL1, CBC_NO_FLAG, -2, \
|
||||
VM_OC_CALL_N) \
|
||||
VM_OC_CALL) \
|
||||
CBC_OPCODE (CBC_CALL1_PUSH_RESULT, CBC_NO_FLAG, -1, \
|
||||
VM_OC_CALL_N | VM_OC_PUT_STACK) \
|
||||
VM_OC_CALL | VM_OC_PUT_STACK) \
|
||||
CBC_OPCODE (CBC_CALL1_BLOCK, CBC_NO_FLAG, -2, \
|
||||
VM_OC_CALL_N | VM_OC_PUT_BLOCK) \
|
||||
VM_OC_CALL | VM_OC_PUT_BLOCK) \
|
||||
CBC_OPCODE (CBC_CALL1_PROP, CBC_NO_FLAG, -4, \
|
||||
VM_OC_CALL_PROP_N) \
|
||||
VM_OC_CALL) \
|
||||
CBC_OPCODE (CBC_CALL1_PROP_PUSH_RESULT, CBC_NO_FLAG, -3, \
|
||||
VM_OC_CALL_PROP_N | VM_OC_PUT_STACK) \
|
||||
VM_OC_CALL | VM_OC_PUT_STACK) \
|
||||
CBC_OPCODE (CBC_CALL1_PROP_BLOCK, CBC_NO_FLAG, -4, \
|
||||
VM_OC_CALL_PROP_N | VM_OC_PUT_BLOCK) \
|
||||
VM_OC_CALL | VM_OC_PUT_BLOCK) \
|
||||
CBC_OPCODE (CBC_CALL2, CBC_NO_FLAG, -3, \
|
||||
VM_OC_CALL_N) \
|
||||
VM_OC_CALL) \
|
||||
CBC_OPCODE (CBC_CALL2_PUSH_RESULT, CBC_NO_FLAG, -2, \
|
||||
VM_OC_CALL_N | VM_OC_PUT_STACK) \
|
||||
VM_OC_CALL | VM_OC_PUT_STACK) \
|
||||
CBC_OPCODE (CBC_CALL2_BLOCK, CBC_NO_FLAG, -3, \
|
||||
VM_OC_CALL_N | VM_OC_PUT_BLOCK) \
|
||||
VM_OC_CALL | VM_OC_PUT_BLOCK) \
|
||||
CBC_OPCODE (CBC_CALL2_PROP, CBC_NO_FLAG, -4, \
|
||||
VM_OC_CALL_PROP_N) \
|
||||
VM_OC_CALL) \
|
||||
CBC_OPCODE (CBC_CALL2_PROP_PUSH_RESULT, CBC_NO_FLAG, -3, \
|
||||
VM_OC_CALL_PROP_N | VM_OC_PUT_STACK) \
|
||||
VM_OC_CALL | VM_OC_PUT_STACK) \
|
||||
CBC_OPCODE (CBC_CALL2_PROP_BLOCK, CBC_NO_FLAG, -4, \
|
||||
VM_OC_CALL_PROP_N | VM_OC_PUT_BLOCK) \
|
||||
VM_OC_CALL | VM_OC_PUT_BLOCK) \
|
||||
\
|
||||
/* Binary assignment opcodes. */ \
|
||||
CBC_OPCODE (CBC_ASSIGN, CBC_NO_FLAG, -3, \
|
||||
|
||||
@ -35,74 +35,6 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* 'Function call' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.2.3
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
ecma_value_t
|
||||
opfunc_call_n (ecma_value_t this_value, /**< this object value */
|
||||
ecma_value_t func_value, /**< function object value */
|
||||
const ecma_value_t *arguments_list_p, /**< stack pointer */
|
||||
ecma_length_t arguments_list_len) /**< number of arguments */
|
||||
{
|
||||
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||
|
||||
if (!ecma_op_is_callable (func_value))
|
||||
{
|
||||
return ecma_raise_type_error ("");
|
||||
}
|
||||
|
||||
ecma_object_t *func_obj_p = ecma_get_object_from_value (func_value);
|
||||
|
||||
ret_value = ecma_op_function_call (func_obj_p,
|
||||
this_value,
|
||||
arguments_list_p,
|
||||
arguments_list_len);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_call_n */
|
||||
|
||||
/**
|
||||
* 'Constructor call' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.2.2
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
ecma_value_t
|
||||
opfunc_construct_n (ecma_value_t constructor_value, /**< constructor object value */
|
||||
const ecma_value_t *arguments_list_p, /**< stack pointer */
|
||||
ecma_length_t arguments_list_len) /**< number of arguments */
|
||||
{
|
||||
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||
|
||||
if (!ecma_is_constructor (constructor_value))
|
||||
{
|
||||
ret_value = ecma_raise_type_error ("");
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor_value);
|
||||
|
||||
ECMA_TRY_CATCH (construction_ret_value,
|
||||
ecma_op_function_construct (constructor_obj_p,
|
||||
arguments_list_p,
|
||||
arguments_list_len),
|
||||
ret_value);
|
||||
|
||||
ret_value = ecma_copy_value (construction_ret_value, true);
|
||||
|
||||
ECMA_FINALIZE (construction_ret_value);
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_construct_n */
|
||||
|
||||
/**
|
||||
* 'Variable declaration' opcode handler.
|
||||
*
|
||||
|
||||
@ -56,14 +56,6 @@ typedef enum
|
||||
ecma_value_t
|
||||
vm_var_decl (vm_frame_ctx_t *, ecma_string_t *);
|
||||
|
||||
ecma_value_t
|
||||
opfunc_call_n (ecma_value_t, ecma_value_t,
|
||||
const ecma_value_t *, ecma_length_t);
|
||||
|
||||
ecma_value_t
|
||||
opfunc_construct_n (ecma_value_t,
|
||||
const ecma_value_t *, ecma_length_t);
|
||||
|
||||
ecma_value_t
|
||||
opfunc_equal_value (ecma_value_t, ecma_value_t);
|
||||
|
||||
|
||||
@ -46,11 +46,14 @@ typedef struct
|
||||
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 */
|
||||
lit_cpointer_t *literal_start_p; /**< literal list start pointer */
|
||||
ecma_object_t *lex_env_p; /**< current lexical environment */
|
||||
ecma_value_t this_binding; /**< this binding */
|
||||
ecma_value_t call_block_result; /**< preserve block result during a call */
|
||||
uint16_t context_depth; /**< current context depth */
|
||||
bool is_eval_code; /**< eval mode flag */
|
||||
uint8_t is_eval_code; /**< eval mode flag */
|
||||
uint8_t call_operation; /**< perform a call or construct operation */
|
||||
} vm_frame_ctx_t;
|
||||
|
||||
/**
|
||||
|
||||
@ -327,6 +327,128 @@ vm_get_implicit_this_value (ecma_value_t *this_value_p) /**< [in,out] this value
|
||||
return false;
|
||||
} /* vm_get_implicit_this_value */
|
||||
|
||||
/**
|
||||
* 'Function call' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.2.3
|
||||
*/
|
||||
static void
|
||||
opfunc_call (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
{
|
||||
uint8_t opcode = frame_ctx_p->byte_code_p[0];
|
||||
uint32_t arguments_list_len;
|
||||
|
||||
if (opcode >= CBC_CALL0)
|
||||
{
|
||||
arguments_list_len = (unsigned int) ((opcode - CBC_CALL0) / 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
arguments_list_len = frame_ctx_p->byte_code_p[1];
|
||||
}
|
||||
|
||||
bool is_call_prop = ((opcode - CBC_CALL) % 6) >= 3;
|
||||
|
||||
ecma_value_t this_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
||||
ecma_value_t *stack_top_p = frame_ctx_p->stack_top_p - arguments_list_len;
|
||||
|
||||
if (is_call_prop)
|
||||
{
|
||||
this_value = stack_top_p[-3];
|
||||
|
||||
if (vm_get_implicit_this_value (&this_value))
|
||||
{
|
||||
ecma_free_value (stack_top_p[-3]);
|
||||
stack_top_p[-3] = this_value;
|
||||
}
|
||||
}
|
||||
|
||||
ecma_value_t func_value = stack_top_p[-1];
|
||||
ecma_value_t completion_value;
|
||||
|
||||
if (!ecma_op_is_callable (func_value))
|
||||
{
|
||||
completion_value = ecma_raise_type_error ("");
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_object_t *func_obj_p = ecma_get_object_from_value (func_value);
|
||||
|
||||
completion_value = ecma_op_function_call (func_obj_p,
|
||||
this_value,
|
||||
stack_top_p,
|
||||
arguments_list_len);
|
||||
}
|
||||
|
||||
is_direct_eval_form_call = false;
|
||||
|
||||
/* Free registers. */
|
||||
for (uint32_t i = 0; i < arguments_list_len; i++)
|
||||
{
|
||||
ecma_free_value (stack_top_p[i]);
|
||||
}
|
||||
|
||||
if (is_call_prop)
|
||||
{
|
||||
ecma_free_value (*(--stack_top_p));
|
||||
ecma_free_value (*(--stack_top_p));
|
||||
}
|
||||
|
||||
ecma_free_value (stack_top_p[-1]);
|
||||
stack_top_p[-1] = completion_value;
|
||||
|
||||
frame_ctx_p->stack_top_p = stack_top_p;
|
||||
} /* opfunc_call */
|
||||
|
||||
/**
|
||||
* 'Constructor call' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.2.2
|
||||
*/
|
||||
static void
|
||||
opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
{
|
||||
uint8_t opcode = frame_ctx_p->byte_code_p[0];
|
||||
unsigned int arguments_list_len;
|
||||
|
||||
if (opcode >= CBC_NEW0)
|
||||
{
|
||||
arguments_list_len = (unsigned int) (opcode - CBC_NEW0);
|
||||
}
|
||||
else
|
||||
{
|
||||
arguments_list_len = frame_ctx_p->byte_code_p[1];
|
||||
}
|
||||
|
||||
ecma_value_t *stack_top_p = frame_ctx_p->stack_top_p - arguments_list_len;
|
||||
ecma_value_t constructor_value = stack_top_p[-1];
|
||||
ecma_value_t completion_value;
|
||||
|
||||
if (!ecma_is_constructor (constructor_value))
|
||||
{
|
||||
completion_value = ecma_raise_type_error ("");
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor_value);
|
||||
|
||||
completion_value = ecma_op_function_construct (constructor_obj_p,
|
||||
stack_top_p,
|
||||
arguments_list_len);
|
||||
}
|
||||
|
||||
/* Free registers. */
|
||||
for (uint32_t i = 0; i < arguments_list_len; i++)
|
||||
{
|
||||
ecma_free_value (stack_top_p[i]);
|
||||
}
|
||||
|
||||
ecma_free_value (stack_top_p[-1]);
|
||||
stack_top_p[-1] = completion_value;
|
||||
|
||||
frame_ctx_p->stack_top_p = stack_top_p;
|
||||
} /* opfunc_construct */
|
||||
|
||||
/**
|
||||
* Indicate which value should be freed.
|
||||
*/
|
||||
@ -572,7 +694,7 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
*
|
||||
* @return ecma value
|
||||
*/
|
||||
ecma_value_t
|
||||
static ecma_value_t __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;
|
||||
@ -621,7 +743,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
const_literal_end = args_p->const_literal_end;
|
||||
}
|
||||
|
||||
stack_top_p = frame_ctx_p->registers_p + register_end;
|
||||
stack_top_p = frame_ctx_p->stack_top_p;
|
||||
|
||||
/* Outer loop for exception handling. */
|
||||
while (true)
|
||||
@ -1216,50 +1338,22 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
JERRY_ASSERT (*byte_code_p >= CBC_CALL && *byte_code_p <= CBC_CALL2_PROP_BLOCK);
|
||||
continue;
|
||||
}
|
||||
case VM_OC_CALL_N:
|
||||
case VM_OC_CALL_PROP_N:
|
||||
{
|
||||
right_value = (unsigned int) ((opcode - CBC_CALL0) / 6);
|
||||
/* FALLTHRU */
|
||||
}
|
||||
case VM_OC_CALL:
|
||||
case VM_OC_CALL_PROP:
|
||||
{
|
||||
ecma_value_t this_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
||||
JERRY_ASSERT (free_flags == 0);
|
||||
|
||||
stack_top_p -= right_value;
|
||||
|
||||
if (VM_OC_GROUP_GET_INDEX (opcode_data) >= VM_OC_CALL_PROP_N)
|
||||
if (frame_ctx_p->call_operation == VM_NO_EXEC_OP)
|
||||
{
|
||||
this_value = stack_top_p[-3];
|
||||
|
||||
if (vm_get_implicit_this_value (&this_value))
|
||||
{
|
||||
ecma_free_value (stack_top_p[-3]);
|
||||
stack_top_p[-3] = this_value;
|
||||
}
|
||||
frame_ctx_p->call_operation = VM_EXEC_CALL;
|
||||
frame_ctx_p->byte_code_p = byte_code_start_p;
|
||||
frame_ctx_p->stack_top_p = stack_top_p;
|
||||
frame_ctx_p->call_block_result = block_result;
|
||||
return;
|
||||
}
|
||||
frame_ctx_p->call_operation = VM_NO_EXEC_OP;
|
||||
|
||||
last_completion_value = opfunc_call_n (this_value,
|
||||
stack_top_p[-1],
|
||||
stack_top_p,
|
||||
right_value);
|
||||
|
||||
is_direct_eval_form_call = false;
|
||||
|
||||
/* Free registers. */
|
||||
for (uint32_t i = 0; i < right_value; i++)
|
||||
{
|
||||
ecma_free_value (stack_top_p[i]);
|
||||
}
|
||||
|
||||
ecma_free_value (*(--stack_top_p));
|
||||
|
||||
if (VM_OC_GROUP_GET_INDEX (opcode_data) >= VM_OC_CALL_PROP_N)
|
||||
{
|
||||
ecma_free_value (*(--stack_top_p));
|
||||
ecma_free_value (*(--stack_top_p));
|
||||
}
|
||||
last_completion_value = *(--stack_top_p);
|
||||
block_result = frame_ctx_p->call_block_result;
|
||||
|
||||
if (ecma_is_value_error (last_completion_value))
|
||||
{
|
||||
@ -1274,29 +1368,24 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
{
|
||||
ecma_free_value (last_completion_value);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case VM_OC_NEW_N:
|
||||
{
|
||||
right_value = opcode - (uint32_t) CBC_NEW0;
|
||||
/* FALLTHRU */
|
||||
}
|
||||
case VM_OC_NEW:
|
||||
{
|
||||
stack_top_p -= right_value;
|
||||
JERRY_ASSERT (free_flags == 0);
|
||||
|
||||
last_completion_value = opfunc_construct_n (stack_top_p[-1],
|
||||
stack_top_p,
|
||||
right_value);
|
||||
|
||||
/* Free registers. */
|
||||
for (uint32_t i = 0; i < right_value; i++)
|
||||
if (frame_ctx_p->call_operation == VM_NO_EXEC_OP)
|
||||
{
|
||||
ecma_free_value (stack_top_p[i]);
|
||||
frame_ctx_p->call_operation = VM_EXEC_CONSTRUCT;
|
||||
frame_ctx_p->byte_code_p = byte_code_start_p;
|
||||
frame_ctx_p->stack_top_p = stack_top_p;
|
||||
frame_ctx_p->call_block_result = block_result;
|
||||
return;
|
||||
}
|
||||
frame_ctx_p->call_operation = VM_NO_EXEC_OP;
|
||||
|
||||
ecma_free_value (*(--stack_top_p));
|
||||
last_completion_value = *(--stack_top_p);
|
||||
block_result = frame_ctx_p->call_block_result;
|
||||
|
||||
if (ecma_is_value_error (last_completion_value))
|
||||
{
|
||||
@ -2265,6 +2354,8 @@ vm_execute (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||
register_end = args_p->register_end;
|
||||
}
|
||||
|
||||
frame_ctx_p->stack_top_p = frame_ctx_p->registers_p + register_end;
|
||||
|
||||
if (arg_list_len == 0)
|
||||
{
|
||||
ecma_collection_header_t *arg_collection_p = (ecma_collection_header_t *) arg_p;
|
||||
@ -2320,9 +2411,30 @@ vm_execute (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||
prev_context_p = vm_top_context_p;
|
||||
vm_top_context_p = frame_ctx_p;
|
||||
|
||||
vm_init_loop (frame_ctx_p);
|
||||
completion_value = vm_init_loop (frame_ctx_p);
|
||||
|
||||
completion_value = vm_loop (frame_ctx_p);
|
||||
if (!ecma_is_value_error (completion_value))
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
completion_value = vm_loop (frame_ctx_p);
|
||||
|
||||
if (frame_ctx_p->call_operation == VM_NO_EXEC_OP)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (frame_ctx_p->call_operation == VM_EXEC_CALL)
|
||||
{
|
||||
opfunc_call (frame_ctx_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (frame_ctx_p->call_operation == VM_EXEC_CONSTRUCT);
|
||||
opfunc_construct (frame_ctx_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Free arguments and registers */
|
||||
for (uint32_t i = 0; i < register_end; i++)
|
||||
@ -2418,6 +2530,7 @@ vm_run (const ecma_compiled_code_t *bytecode_header_p, /**< byte-code data heade
|
||||
frame_ctx.this_binding = this_binding_value;
|
||||
frame_ctx.context_depth = 0;
|
||||
frame_ctx.is_eval_code = is_eval_code;
|
||||
frame_ctx.call_operation = VM_NO_EXEC_OP;
|
||||
|
||||
arg_list_len++;
|
||||
|
||||
|
||||
@ -107,14 +107,8 @@ typedef enum
|
||||
VM_OC_THROW, /**< throw */
|
||||
VM_OC_THROW_REFERENCE_ERROR, /**< throw reference error */
|
||||
|
||||
/* The PROP forms must get the highest opcodes. */
|
||||
VM_OC_EVAL, /**< eval */
|
||||
VM_OC_CALL_N, /**< call n */
|
||||
VM_OC_CALL, /**< call */
|
||||
VM_OC_CALL_PROP_N, /**< call property n */
|
||||
VM_OC_CALL_PROP, /**< call property */
|
||||
|
||||
VM_OC_NEW_N, /**< new n */
|
||||
VM_OC_NEW, /**< new */
|
||||
|
||||
VM_OC_JUMP, /**< jump */
|
||||
@ -185,13 +179,24 @@ typedef enum
|
||||
VM_OC_PUT_BLOCK = VM_OC_PUT_DATA_CREATE_FLAG (0x8),
|
||||
} vm_oc_put_types;
|
||||
|
||||
/**
|
||||
* Non-recursive vm_loop: the vm_loop can be suspended
|
||||
* to execute a call /construct operation. These return
|
||||
* types of the vm_loop tells whether a call operation
|
||||
* is in progress or the vm_loop is finished.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
VM_NO_EXEC_OP, /**< do nothing */
|
||||
VM_EXEC_CALL, /**< invoke a function */
|
||||
VM_EXEC_CONSTRUCT, /**< construct a new object */
|
||||
} vm_call_operation;
|
||||
|
||||
extern void vm_init (ecma_compiled_code_t *, bool);
|
||||
extern void vm_finalize (void);
|
||||
extern jerry_completion_code_t vm_run_global (void);
|
||||
extern ecma_value_t vm_run_eval (ecma_compiled_code_t *, bool);
|
||||
|
||||
extern ecma_value_t vm_loop (vm_frame_ctx_t *);
|
||||
|
||||
extern ecma_value_t vm_run (const ecma_compiled_code_t *, ecma_value_t,
|
||||
ecma_object_t *, bool, const ecma_value_t *,
|
||||
ecma_length_t);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user