Parser optimizations.
- parser is now non-recursive (i.e. parse function is not called recursively in any case);
- byte-code is now more compact:
- constants are now not immediately dumped upon occurence, but later - where necessary;
- assignments are combined with unary / binary operations;
- binary operations are encoded more compactly in many cases;
- byte-code arrays are now allocated separately for each scope (so, GC of the scopes now becomes possible);
- byte-code is dumped directly into corresponding byte-code arrays:
- linked lists of op_meta are not now used for main code of a scope.
JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan r.ayrapetyan@samsung.com
JerryScript-DCO-1.0-Signed-off-by: Andrey Shitov a.shitov@samsung.com
This commit is contained in:
committed by
Ruben Ayrapetyan
parent
b1de93abd6
commit
50d124bfc3
@@ -32,11 +32,17 @@
|
||||
#include "ecma-reference.h"
|
||||
#include "ecma-regexp-object.h"
|
||||
#include "ecma-try-catch-macro.h"
|
||||
#include "serializer.h"
|
||||
|
||||
bool vm_is_reg_variable (vm_idx_t);
|
||||
ecma_completion_value_t get_variable_value (vm_frame_ctx_t *, vm_idx_t, bool);
|
||||
ecma_completion_value_t set_variable_value (vm_frame_ctx_t *, vm_instr_counter_t, vm_idx_t, ecma_value_t);
|
||||
ecma_completion_value_t vm_fill_varg_list (vm_frame_ctx_t *, ecma_length_t, ecma_collection_header_t *);
|
||||
extern void vm_fill_params_list (vm_frame_ctx_t *, ecma_length_t, ecma_collection_header_t *);
|
||||
extern vm_instr_counter_t vm_fill_params_list (const bytecode_data_header_t *,
|
||||
vm_instr_counter_t,
|
||||
ecma_length_t,
|
||||
ecma_collection_header_t *);
|
||||
extern ecma_completion_value_t vm_function_declaration (const bytecode_data_header_t *bytecode_header_p,
|
||||
bool is_strict,
|
||||
bool is_eval_code,
|
||||
ecma_object_t *lex_env_p);
|
||||
#endif /* OPCODES_ECMA_SUPPORT_H */
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "bytecode-data.h"
|
||||
#include "jrt.h"
|
||||
#include "vm.h"
|
||||
#include "opcodes.h"
|
||||
@@ -49,7 +50,9 @@ opfunc_try_block (vm_instr_t instr, /**< instruction */
|
||||
if (next_instr.data.meta.type == OPCODE_META_TYPE_CATCH)
|
||||
{
|
||||
const vm_instr_counter_t catch_end_oc = (vm_instr_counter_t) (
|
||||
vm_read_instr_counter_from_meta (OPCODE_META_TYPE_CATCH, frame_ctx_p) + frame_ctx_p->pos);
|
||||
vm_read_instr_counter_from_meta (OPCODE_META_TYPE_CATCH,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos) + frame_ctx_p->pos);
|
||||
frame_ctx_p->pos++;
|
||||
|
||||
if (ecma_is_completion_value_throw (try_completion))
|
||||
@@ -58,9 +61,9 @@ opfunc_try_block (vm_instr_t instr, /**< instruction */
|
||||
JERRY_ASSERT (next_instr.op_idx == VM_OP_META);
|
||||
JERRY_ASSERT (next_instr.data.meta.type == OPCODE_META_TYPE_CATCH_EXCEPTION_IDENTIFIER);
|
||||
|
||||
lit_cpointer_t catch_exc_val_var_name_lit_cp = serializer_get_literal_cp_by_uid (next_instr.data.meta.data_1,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos);
|
||||
lit_cpointer_t catch_exc_val_var_name_lit_cp = bc_get_literal_cp_by_uid (next_instr.data.meta.data_1,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos);
|
||||
frame_ctx_p->pos++;
|
||||
|
||||
ecma_string_t *catch_exc_var_name_str_p = ecma_new_ecma_string_from_lit_cp (catch_exc_val_var_name_lit_cp);
|
||||
@@ -104,7 +107,9 @@ opfunc_try_block (vm_instr_t instr, /**< instruction */
|
||||
if (next_instr.data.meta.type == OPCODE_META_TYPE_FINALLY)
|
||||
{
|
||||
const vm_instr_counter_t finally_end_oc = (vm_instr_counter_t) (
|
||||
vm_read_instr_counter_from_meta (OPCODE_META_TYPE_FINALLY, frame_ctx_p) + frame_ctx_p->pos);
|
||||
vm_read_instr_counter_from_meta (OPCODE_META_TYPE_FINALLY,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos) + frame_ctx_p->pos);
|
||||
frame_ctx_p->pos++;
|
||||
|
||||
vm_run_scope_t run_scope_finally = { frame_ctx_p->pos, finally_end_oc };
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "bytecode-data.h"
|
||||
#include "jrt.h"
|
||||
#include "opcodes.h"
|
||||
#include "opcodes-ecma-support.h"
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "bytecode-data.h"
|
||||
#include "opcodes-ecma-support.h"
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
@@ -89,9 +90,9 @@ get_variable_value (vm_frame_ctx_t *frame_ctx_p, /**< interpreter context */
|
||||
else
|
||||
{
|
||||
ecma_string_t var_name_string;
|
||||
lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (var_idx,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos);
|
||||
lit_cpointer_t lit_cp = bc_get_literal_cp_by_uid (var_idx,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos);
|
||||
JERRY_ASSERT (lit_cp.packed_value != MEM_CP_NULL);
|
||||
ecma_new_ecma_string_on_stack_from_lit_cp (&var_name_string, lit_cp);
|
||||
|
||||
@@ -155,7 +156,7 @@ set_variable_value (vm_frame_ctx_t *frame_ctx_p, /**< interpreter context */
|
||||
else
|
||||
{
|
||||
ecma_string_t var_name_string;
|
||||
lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (var_idx, frame_ctx_p->bytecode_header_p, lit_oc);
|
||||
lit_cpointer_t lit_cp = bc_get_literal_cp_by_uid (var_idx, frame_ctx_p->bytecode_header_p, lit_oc);
|
||||
JERRY_ASSERT (lit_cp.packed_value != MEM_CP_NULL);
|
||||
ecma_new_ecma_string_on_stack_from_lit_cp (&var_name_string, lit_cp);
|
||||
|
||||
|
||||
@@ -13,11 +13,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "opcodes-ecma-support.h"
|
||||
|
||||
#include "bytecode-data.h"
|
||||
#include "jrt.h"
|
||||
#include "vm.h"
|
||||
#include "opcodes.h"
|
||||
#include "opcodes-ecma-support.h"
|
||||
#include "vm.h"
|
||||
|
||||
/**
|
||||
* Fill arguments' list
|
||||
@@ -69,25 +70,28 @@ vm_fill_varg_list (vm_frame_ctx_t *frame_ctx_p, /**< interpreter context */
|
||||
/**
|
||||
* Fill parameters' list
|
||||
*/
|
||||
void
|
||||
vm_fill_params_list (vm_frame_ctx_t *frame_ctx_p, /**< interpreter context */
|
||||
vm_instr_counter_t
|
||||
vm_fill_params_list (const bytecode_data_header_t *bytecode_header_p, /**< header of byte-code */
|
||||
vm_instr_counter_t first_instr_pos, /**< position of the first instruction
|
||||
* with a formal parameter's name */
|
||||
ecma_length_t params_number, /**< number of parameters */
|
||||
ecma_collection_header_t *formal_params_collection_p) /**< collection to fill with
|
||||
* parameters' names */
|
||||
{
|
||||
vm_instr_counter_t instr_pos = first_instr_pos;
|
||||
|
||||
uint32_t param_index;
|
||||
for (param_index = 0;
|
||||
param_index < params_number;
|
||||
param_index++)
|
||||
{
|
||||
vm_instr_t next_instr = vm_get_instr (frame_ctx_p->bytecode_header_p->instrs_p, frame_ctx_p->pos);
|
||||
vm_instr_t next_instr = vm_get_instr (bytecode_header_p->instrs_p, instr_pos);
|
||||
JERRY_ASSERT (next_instr.op_idx == VM_OP_META);
|
||||
JERRY_ASSERT (next_instr.data.meta.type == OPCODE_META_TYPE_VARG);
|
||||
|
||||
const lit_cpointer_t param_name_lit_idx = serializer_get_literal_cp_by_uid (next_instr.data.meta.data_1,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos);
|
||||
|
||||
const lit_cpointer_t param_name_lit_idx = bc_get_literal_cp_by_uid (next_instr.data.meta.data_1,
|
||||
bytecode_header_p,
|
||||
instr_pos);
|
||||
|
||||
ecma_string_t *param_name_str_p = ecma_new_ecma_string_from_lit_cp (param_name_lit_idx);
|
||||
ecma_value_t param_name_value = ecma_make_string_value (param_name_str_p);
|
||||
@@ -96,8 +100,10 @@ vm_fill_params_list (vm_frame_ctx_t *frame_ctx_p, /**< interpreter context */
|
||||
|
||||
ecma_deref_ecma_string (param_name_str_p);
|
||||
|
||||
frame_ctx_p->pos++;
|
||||
instr_pos++;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (param_index == params_number);
|
||||
|
||||
return instr_pos;
|
||||
} /* vm_fill_params_list */
|
||||
|
||||
+188
-173
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "bytecode-data.h"
|
||||
#include "jrt.h"
|
||||
#include "opcodes.h"
|
||||
#include "opcodes-ecma-support.h"
|
||||
@@ -77,9 +78,9 @@ opfunc_assignment (vm_instr_t instr, /**< instruction */
|
||||
}
|
||||
else if (type_value_right == OPCODE_ARG_TYPE_STRING)
|
||||
{
|
||||
lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (src_val_descr,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos);
|
||||
lit_cpointer_t lit_cp = bc_get_literal_cp_by_uid (src_val_descr,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos);
|
||||
ecma_string_t *string_p = ecma_new_ecma_string_from_lit_cp (lit_cp);
|
||||
|
||||
ret_value = set_variable_value (frame_ctx_p,
|
||||
@@ -108,9 +109,9 @@ opfunc_assignment (vm_instr_t instr, /**< instruction */
|
||||
{
|
||||
ecma_number_t *num_p = frame_ctx_p->tmp_num_p;
|
||||
|
||||
lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (src_val_descr,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos);
|
||||
lit_cpointer_t lit_cp = bc_get_literal_cp_by_uid (src_val_descr,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos);
|
||||
literal_t lit = lit_get_literal_by_cp (lit_cp);
|
||||
JERRY_ASSERT (lit->get_type () == LIT_NUMBER_T);
|
||||
|
||||
@@ -125,9 +126,9 @@ opfunc_assignment (vm_instr_t instr, /**< instruction */
|
||||
{
|
||||
ecma_number_t *num_p = frame_ctx_p->tmp_num_p;
|
||||
|
||||
lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (src_val_descr,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos);
|
||||
lit_cpointer_t lit_cp = bc_get_literal_cp_by_uid (src_val_descr,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos);
|
||||
literal_t lit = lit_get_literal_by_cp (lit_cp);
|
||||
JERRY_ASSERT (lit->get_type () == LIT_NUMBER_T);
|
||||
|
||||
@@ -152,7 +153,7 @@ opfunc_assignment (vm_instr_t instr, /**< instruction */
|
||||
else if (type_value_right == OPCODE_ARG_TYPE_REGEXP)
|
||||
{
|
||||
#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_REGEXP_BUILTIN
|
||||
lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (src_val_descr,
|
||||
lit_cpointer_t lit_cp = bc_get_literal_cp_by_uid (src_val_descr,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos);
|
||||
ecma_string_t *string_p = ecma_new_ecma_string_from_lit_cp (lit_cp);
|
||||
@@ -440,40 +441,10 @@ opfunc_reg_var_decl (vm_instr_t instr __attr_unused___, /**< instruction */
|
||||
* However, ecma_free_completion_value may be called for it, but it is a no-op.
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_var_decl (vm_instr_t instr, /**< instruction */
|
||||
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
|
||||
opfunc_var_decl (vm_instr_t instr __attr_unused___, /**< instruction */
|
||||
vm_frame_ctx_t *frame_ctx_p __attr_unused___) /**< interpreter context */
|
||||
{
|
||||
lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (instr.data.var_decl.variable_name,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos);
|
||||
JERRY_ASSERT (lit_cp.packed_value != MEM_CP_NULL);
|
||||
|
||||
ecma_string_t *var_name_string_p = ecma_new_ecma_string_from_lit_cp (lit_cp);
|
||||
|
||||
if (!ecma_op_has_binding (frame_ctx_p->lex_env_p, var_name_string_p))
|
||||
{
|
||||
const bool is_configurable_bindings = frame_ctx_p->is_eval_code;
|
||||
|
||||
ecma_completion_value_t completion = ecma_op_create_mutable_binding (frame_ctx_p->lex_env_p,
|
||||
var_name_string_p,
|
||||
is_configurable_bindings);
|
||||
|
||||
JERRY_ASSERT (ecma_is_completion_value_empty (completion));
|
||||
|
||||
/* Skipping SetMutableBinding as we have already checked that there were not
|
||||
* any binding with specified name in current lexical environment
|
||||
* and CreateMutableBinding sets the created binding's value to undefined */
|
||||
JERRY_ASSERT (ecma_is_completion_value_normal_simple_value (ecma_op_get_binding_value (frame_ctx_p->lex_env_p,
|
||||
var_name_string_p,
|
||||
true),
|
||||
ECMA_SIMPLE_VALUE_UNDEFINED));
|
||||
}
|
||||
|
||||
ecma_deref_ecma_string (var_name_string_p);
|
||||
|
||||
frame_ctx_p->pos++;
|
||||
|
||||
return ecma_make_empty_completion_value ();
|
||||
JERRY_UNREACHABLE ();
|
||||
} /* opfunc_var_decl */
|
||||
|
||||
/**
|
||||
@@ -482,74 +453,156 @@ opfunc_var_decl (vm_instr_t instr, /**< instruction */
|
||||
* @return completion value
|
||||
* returned value must be freed with ecma_free_completion_value.
|
||||
*/
|
||||
static ecma_completion_value_t
|
||||
function_declaration (vm_frame_ctx_t *frame_ctx_p, /**< interpreter context */
|
||||
lit_cpointer_t function_name_lit_cp, /**< compressed pointer to literal with function name */
|
||||
ecma_collection_header_t *formal_params_collection_p) /** formal parameters collection */
|
||||
ecma_completion_value_t
|
||||
vm_function_declaration (const bytecode_data_header_t *bytecode_header_p, /**< byte-code header */
|
||||
bool is_strict, /**< is function declared in strict mode code? */
|
||||
bool is_eval_code, /**< is function declared in eval code? */
|
||||
ecma_object_t *lex_env_p) /**< lexical environment to use */
|
||||
{
|
||||
const bool is_configurable_bindings = frame_ctx_p->is_eval_code;
|
||||
vm_instr_t *function_instrs_p = bytecode_header_p->instrs_p;
|
||||
|
||||
const vm_instr_counter_t function_code_end_oc = (vm_instr_counter_t) (
|
||||
vm_read_instr_counter_from_meta (OPCODE_META_TYPE_FUNCTION_END, frame_ctx_p) + frame_ctx_p->pos);
|
||||
frame_ctx_p->pos++;
|
||||
vm_instr_counter_t instr_pos = 0;
|
||||
|
||||
ecma_string_t *function_name_string_p = ecma_new_ecma_string_from_lit_cp (function_name_lit_cp);
|
||||
vm_instr_t func_header_instr = function_instrs_p[instr_pos];
|
||||
|
||||
ecma_completion_value_t ret_value = ecma_op_function_declaration (frame_ctx_p->lex_env_p,
|
||||
function_name_string_p,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos,
|
||||
formal_params_collection_p,
|
||||
frame_ctx_p->is_strict,
|
||||
is_configurable_bindings);
|
||||
ecma_deref_ecma_string (function_name_string_p);
|
||||
bool is_func_decl;
|
||||
vm_idx_t function_name_idx;
|
||||
ecma_length_t params_number;
|
||||
|
||||
frame_ctx_p->pos = function_code_end_oc;
|
||||
if (func_header_instr.op_idx == VM_OP_FUNC_DECL_N)
|
||||
{
|
||||
is_func_decl = true;
|
||||
|
||||
function_name_idx = func_header_instr.data.func_decl_n.name_lit_idx;
|
||||
params_number = func_header_instr.data.func_decl_n.arg_list;
|
||||
}
|
||||
else
|
||||
{
|
||||
is_func_decl = false;
|
||||
|
||||
function_name_idx = func_header_instr.data.func_expr_n.name_lit_idx;
|
||||
params_number = func_header_instr.data.func_expr_n.arg_list;
|
||||
}
|
||||
|
||||
lit_cpointer_t function_name_lit_cp = NOT_A_LITERAL;
|
||||
|
||||
if (function_name_idx != VM_IDX_EMPTY)
|
||||
{
|
||||
function_name_lit_cp = bc_get_literal_cp_by_uid (function_name_idx,
|
||||
bytecode_header_p,
|
||||
instr_pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (!is_func_decl);
|
||||
}
|
||||
|
||||
instr_pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ecma_collection_header_t *formal_params_collection_p = NULL;
|
||||
|
||||
if (bytecode_header_p->is_args_moved_to_regs)
|
||||
{
|
||||
instr_pos = (vm_instr_counter_t) (instr_pos + params_number);
|
||||
}
|
||||
else if (params_number != 0)
|
||||
{
|
||||
formal_params_collection_p = ecma_new_strings_collection (NULL, 0);
|
||||
|
||||
instr_pos = vm_fill_params_list (bytecode_header_p,
|
||||
instr_pos,
|
||||
params_number,
|
||||
formal_params_collection_p);
|
||||
}
|
||||
|
||||
if (is_func_decl)
|
||||
{
|
||||
const bool is_configurable_bindings = is_eval_code;
|
||||
|
||||
ecma_string_t *function_name_string_p = ecma_new_ecma_string_from_lit_cp (function_name_lit_cp);
|
||||
|
||||
ret_value = ecma_op_function_declaration (lex_env_p,
|
||||
function_name_string_p,
|
||||
bytecode_header_p,
|
||||
instr_pos,
|
||||
formal_params_collection_p,
|
||||
is_strict,
|
||||
is_configurable_bindings);
|
||||
|
||||
ecma_deref_ecma_string (function_name_string_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_object_t *scope_p;
|
||||
ecma_string_t *function_name_string_p = NULL;
|
||||
|
||||
bool is_named_func_expr = (function_name_idx != VM_IDX_EMPTY);
|
||||
|
||||
if (is_named_func_expr)
|
||||
{
|
||||
scope_p = ecma_create_decl_lex_env (lex_env_p);
|
||||
|
||||
JERRY_ASSERT (function_name_lit_cp.packed_value != MEM_CP_NULL);
|
||||
|
||||
function_name_string_p = ecma_new_ecma_string_from_lit_cp (function_name_lit_cp);
|
||||
ecma_op_create_immutable_binding (scope_p, function_name_string_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
scope_p = lex_env_p;
|
||||
ecma_ref_object (scope_p);
|
||||
}
|
||||
|
||||
ecma_object_t *func_obj_p = ecma_op_create_function_object (formal_params_collection_p,
|
||||
scope_p,
|
||||
is_strict,
|
||||
bytecode_header_p,
|
||||
instr_pos);
|
||||
|
||||
ret_value = ecma_make_normal_completion_value (ecma_make_object_value (func_obj_p));
|
||||
|
||||
if (is_named_func_expr)
|
||||
{
|
||||
ecma_op_initialize_immutable_binding (scope_p,
|
||||
function_name_string_p,
|
||||
ecma_make_object_value (func_obj_p));
|
||||
ecma_deref_ecma_string (function_name_string_p);
|
||||
}
|
||||
|
||||
ecma_deref_object (scope_p);
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
} /* function_declaration */
|
||||
} /* vm_function_declaration */
|
||||
|
||||
/**
|
||||
* 'Function declaration' opcode handler.
|
||||
* 'Function declaration header' opcode handler.
|
||||
*
|
||||
* @return completion value
|
||||
* returned value must be freed with ecma_free_completion_value.
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_func_decl_n (vm_instr_t instr, /**< instruction */
|
||||
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
|
||||
opfunc_func_decl_n (vm_instr_t instr __attr_unused___, /**< instruction */
|
||||
vm_frame_ctx_t *frame_ctx_p __attr_unused___) /**< interpreter context */
|
||||
{
|
||||
const vm_idx_t function_name_idx = instr.data.func_decl_n.name_lit_idx;
|
||||
const ecma_length_t params_number = instr.data.func_decl_n.arg_list;
|
||||
|
||||
lit_cpointer_t function_name_lit_cp = serializer_get_literal_cp_by_uid (function_name_idx,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos);
|
||||
|
||||
frame_ctx_p->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ecma_collection_header_t *formal_params_collection_p;
|
||||
|
||||
if (params_number != 0)
|
||||
{
|
||||
formal_params_collection_p = ecma_new_strings_collection (NULL, 0);
|
||||
|
||||
vm_fill_params_list (frame_ctx_p, params_number, formal_params_collection_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
formal_params_collection_p = NULL;
|
||||
}
|
||||
|
||||
ret_value = function_declaration (frame_ctx_p,
|
||||
function_name_lit_cp,
|
||||
formal_params_collection_p);
|
||||
|
||||
return ret_value;
|
||||
JERRY_UNREACHABLE ();
|
||||
} /* opfunc_func_decl_n */
|
||||
|
||||
/**
|
||||
* 'Function expression header' opcode handler.
|
||||
*
|
||||
* @return completion value
|
||||
* returned value must be freed with ecma_free_completion_value.
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_func_expr_n (vm_instr_t instr __attr_unused___, /**< instruction */
|
||||
vm_frame_ctx_t *frame_ctx_p __attr_unused___) /**< interpreter context */
|
||||
{
|
||||
JERRY_UNREACHABLE ();
|
||||
} /* opfunc_func_expr_n */
|
||||
|
||||
/**
|
||||
* 'Function expression' opcode handler.
|
||||
*
|
||||
@@ -557,84 +610,46 @@ opfunc_func_decl_n (vm_instr_t instr, /**< instruction */
|
||||
* returned value must be freed with ecma_free_completion_value.
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_func_expr_n (vm_instr_t instr, /**< instruction */
|
||||
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
|
||||
opfunc_func_expr_ref (vm_instr_t instr, /**< instruction */
|
||||
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
|
||||
{
|
||||
const vm_instr_counter_t lit_oc = frame_ctx_p->pos;
|
||||
|
||||
frame_ctx_p->pos++;
|
||||
|
||||
const vm_idx_t dst_var_idx = instr.data.func_expr_n.lhs;
|
||||
const vm_idx_t function_name_lit_idx = instr.data.func_expr_n.name_lit_idx;
|
||||
const ecma_length_t params_number = instr.data.func_expr_n.arg_list;
|
||||
const bool is_named_func_expr = (function_name_lit_idx != VM_IDX_EMPTY);
|
||||
const vm_idx_t dst_var_idx = instr.data.func_expr_ref.lhs;
|
||||
const vm_idx_t idx1 = instr.data.func_expr_ref.idx1;
|
||||
const vm_idx_t idx2 = instr.data.func_expr_ref.idx2;
|
||||
|
||||
uint16_t index = (uint16_t) jrt_set_bit_field_value (jrt_set_bit_field_value (0, idx1, 0, JERRY_BITSINBYTE),
|
||||
idx2, JERRY_BITSINBYTE, JERRY_BITSINBYTE);
|
||||
|
||||
const bytecode_data_header_t *header_p = frame_ctx_p->bytecode_header_p;
|
||||
mem_cpointer_t *declarations_p = MEM_CP_GET_POINTER (mem_cpointer_t, header_p->declarations_cp);
|
||||
JERRY_ASSERT (index < header_p->func_scopes_count);
|
||||
|
||||
const bytecode_data_header_t *func_expr_bc_header_p = MEM_CP_GET_NON_NULL_POINTER (const bytecode_data_header_t,
|
||||
declarations_p[index]);
|
||||
|
||||
JERRY_ASSERT (func_expr_bc_header_p->instrs_p[0].op_idx == VM_OP_FUNC_EXPR_N);
|
||||
|
||||
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
|
||||
|
||||
vm_instr_counter_t function_code_end_oc;
|
||||
ECMA_TRY_CATCH (func_obj_value,
|
||||
vm_function_declaration (func_expr_bc_header_p,
|
||||
frame_ctx_p->is_strict,
|
||||
frame_ctx_p->is_eval_code,
|
||||
frame_ctx_p->lex_env_p),
|
||||
ret_value);
|
||||
|
||||
ecma_collection_header_t *formal_params_collection_p;
|
||||
JERRY_ASSERT (ecma_is_constructor (func_obj_value));
|
||||
|
||||
if (params_number != 0)
|
||||
{
|
||||
formal_params_collection_p = ecma_new_strings_collection (NULL, 0);
|
||||
ret_value = set_variable_value (frame_ctx_p, lit_oc, dst_var_idx, func_obj_value);
|
||||
|
||||
vm_fill_params_list (frame_ctx_p, params_number, formal_params_collection_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
formal_params_collection_p = NULL;
|
||||
}
|
||||
|
||||
function_code_end_oc = (vm_instr_counter_t) (vm_read_instr_counter_from_meta (OPCODE_META_TYPE_FUNCTION_END,
|
||||
frame_ctx_p) + frame_ctx_p->pos);
|
||||
frame_ctx_p->pos++;
|
||||
|
||||
ecma_object_t *scope_p;
|
||||
ecma_string_t *function_name_string_p = NULL;
|
||||
if (is_named_func_expr)
|
||||
{
|
||||
scope_p = ecma_create_decl_lex_env (frame_ctx_p->lex_env_p);
|
||||
|
||||
lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (function_name_lit_idx,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
lit_oc);
|
||||
JERRY_ASSERT (lit_cp.packed_value != MEM_CP_NULL);
|
||||
|
||||
function_name_string_p = ecma_new_ecma_string_from_lit_cp (lit_cp);
|
||||
ecma_op_create_immutable_binding (scope_p, function_name_string_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
scope_p = frame_ctx_p->lex_env_p;
|
||||
ecma_ref_object (scope_p);
|
||||
}
|
||||
|
||||
ecma_object_t *func_obj_p = ecma_op_create_function_object (formal_params_collection_p,
|
||||
scope_p,
|
||||
frame_ctx_p->is_strict,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos);
|
||||
|
||||
ret_value = set_variable_value (frame_ctx_p, lit_oc,
|
||||
dst_var_idx,
|
||||
ecma_make_object_value (func_obj_p));
|
||||
|
||||
if (is_named_func_expr)
|
||||
{
|
||||
ecma_op_initialize_immutable_binding (scope_p,
|
||||
function_name_string_p,
|
||||
ecma_make_object_value (func_obj_p));
|
||||
ecma_deref_ecma_string (function_name_string_p);
|
||||
}
|
||||
|
||||
ecma_deref_object (func_obj_p);
|
||||
ecma_deref_object (scope_p);
|
||||
|
||||
frame_ctx_p->pos = function_code_end_oc;
|
||||
ECMA_FINALIZE (func_obj_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_func_expr_n */
|
||||
} /* opfunc_func_expr_ref */
|
||||
|
||||
/**
|
||||
* Get 'this' argument value and call flags mask for function call
|
||||
@@ -718,9 +733,9 @@ vm_helper_call_get_call_flags_and_this_arg (vm_frame_ctx_t *int_data_p, /**< int
|
||||
|
||||
/* 6.b.i */
|
||||
ecma_string_t var_name_string;
|
||||
lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (var_idx,
|
||||
int_data_p->bytecode_header_p,
|
||||
var_idx_lit_oc);
|
||||
lit_cpointer_t lit_cp = bc_get_literal_cp_by_uid (var_idx,
|
||||
int_data_p->bytecode_header_p,
|
||||
var_idx_lit_oc);
|
||||
ecma_new_ecma_string_on_stack_from_lit_cp (&var_name_string, lit_cp);
|
||||
|
||||
ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (int_data_p->lex_env_p,
|
||||
@@ -1038,9 +1053,9 @@ opfunc_obj_decl (vm_instr_t instr, /**< instruction */
|
||||
false),
|
||||
ret_value);
|
||||
|
||||
lit_cpointer_t prop_name_lit_cp = serializer_get_literal_cp_by_uid (prop_name_idx,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos);
|
||||
lit_cpointer_t prop_name_lit_cp = bc_get_literal_cp_by_uid (prop_name_idx,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos);
|
||||
JERRY_ASSERT (prop_name_lit_cp.packed_value != MEM_CP_NULL);
|
||||
ecma_string_t *prop_name_string_p = ecma_new_ecma_string_from_lit_cp (prop_name_lit_cp);
|
||||
|
||||
@@ -1453,9 +1468,9 @@ evaluate_arg_for_typeof (vm_frame_ctx_t *frame_ctx_p, /**< interpreter context *
|
||||
}
|
||||
else
|
||||
{
|
||||
lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (var_idx,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos);
|
||||
lit_cpointer_t lit_cp = bc_get_literal_cp_by_uid (var_idx,
|
||||
frame_ctx_p->bytecode_header_p,
|
||||
frame_ctx_p->pos);
|
||||
JERRY_ASSERT (lit_cp.packed_value != MEM_CP_NULL);
|
||||
|
||||
ecma_string_t *var_name_string_p = ecma_new_ecma_string_from_lit_cp (lit_cp);
|
||||
@@ -1571,7 +1586,7 @@ opfunc_delete_var (vm_instr_t instr, /**< instruction */
|
||||
|
||||
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
|
||||
|
||||
lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (name_lit_idx, frame_ctx_p->bytecode_header_p, lit_oc);
|
||||
lit_cpointer_t lit_cp = bc_get_literal_cp_by_uid (name_lit_idx, frame_ctx_p->bytecode_header_p, lit_oc);
|
||||
JERRY_ASSERT (lit_cp.packed_value != MEM_CP_NULL);
|
||||
|
||||
ecma_string_t *name_string_p = ecma_new_ecma_string_from_lit_cp (lit_cp);
|
||||
@@ -1718,7 +1733,6 @@ opfunc_meta (vm_instr_t instr, /**< instruction */
|
||||
return ecma_make_meta_completion_value ();
|
||||
}
|
||||
|
||||
case OPCODE_META_TYPE_SCOPE_CODE_FLAGS:
|
||||
case OPCODE_META_TYPE_UNDEFINED:
|
||||
case OPCODE_META_TYPE_CALL_SITE_INFO:
|
||||
case OPCODE_META_TYPE_FUNCTION_END:
|
||||
@@ -1750,14 +1764,15 @@ vm_calc_instr_counter_from_idx_idx (const vm_idx_t oc_idx_1, /**< first idx */
|
||||
} /* vm_calc_instr_counter_from_idx_idx */
|
||||
|
||||
/**
|
||||
* Read instruction counter from current instruction,
|
||||
* Read instruction counter from specified instruction,
|
||||
* that should be 'meta' instruction of specified type.
|
||||
*/
|
||||
vm_instr_counter_t
|
||||
vm_read_instr_counter_from_meta (opcode_meta_type expected_type, /**< expected type of meta instruction */
|
||||
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
|
||||
const bytecode_data_header_t *bytecode_header_p, /**< byte-code header */
|
||||
vm_instr_counter_t instr_pos) /**< position of the instruction */
|
||||
{
|
||||
vm_instr_t meta_opcode = vm_get_instr (frame_ctx_p->bytecode_header_p->instrs_p, frame_ctx_p->pos);
|
||||
vm_instr_t meta_opcode = vm_get_instr (bytecode_header_p->instrs_p, instr_pos);
|
||||
JERRY_ASSERT (meta_opcode.data.meta.type == expected_type);
|
||||
|
||||
const vm_idx_t data_1 = meta_opcode.data.meta.data_1;
|
||||
|
||||
+3
-20
@@ -137,8 +137,6 @@ typedef enum
|
||||
OPCODE_META_TYPE_CATCH_EXCEPTION_IDENTIFIER, /**< literal index containing name of variable with exception object */
|
||||
OPCODE_META_TYPE_FINALLY, /**< mark of beginning of finally block containing pointer to end of finally block */
|
||||
OPCODE_META_TYPE_END_TRY_CATCH_FINALLY, /**< mark of end of try-catch, try-finally, try-catch-finally blocks */
|
||||
OPCODE_META_TYPE_SCOPE_CODE_FLAGS, /**< set of flags indicating various properties of the scope's code
|
||||
* (See also: opcode_scope_code_flags_t) */
|
||||
OPCODE_META_TYPE_END_FOR_IN /**< end of for-in statement */
|
||||
} opcode_meta_type;
|
||||
|
||||
@@ -155,23 +153,6 @@ typedef enum : vm_idx_t
|
||||
*/
|
||||
} opcode_call_flags_t;
|
||||
|
||||
/**
|
||||
* Flags indicating various properties of a scope's code
|
||||
*/
|
||||
typedef enum : vm_idx_t
|
||||
{
|
||||
OPCODE_SCOPE_CODE_FLAGS__EMPTY = (0u), /**< initializer for empty flag set */
|
||||
OPCODE_SCOPE_CODE_FLAGS_STRICT = (1u << 0), /**< code is strict mode code */
|
||||
OPCODE_SCOPE_CODE_FLAGS_NOT_REF_ARGUMENTS_IDENTIFIER = (1u << 1), /**< code doesn't reference
|
||||
* 'arguments' identifier */
|
||||
OPCODE_SCOPE_CODE_FLAGS_NOT_REF_EVAL_IDENTIFIER = (1u << 2), /**< code doesn't reference
|
||||
* 'eval' identifier */
|
||||
OPCODE_SCOPE_CODE_FLAGS_ARGUMENTS_ON_REGISTERS = (1u << 3), /**< function's arguments are moved to registers,
|
||||
* so should be initialized in vm registers,
|
||||
* and not in lexical environment */
|
||||
OPCODE_SCOPE_CODE_FLAGS_NO_LEX_ENV = (1u << 4) /**< no lex. env. is necessary for the function */
|
||||
} opcode_scope_code_flags_t;
|
||||
|
||||
/**
|
||||
* Types of byte-code instruction arguments, used for instruction description
|
||||
*
|
||||
@@ -246,7 +227,9 @@ typedef struct
|
||||
} vm_run_scope_t;
|
||||
|
||||
vm_instr_counter_t vm_calc_instr_counter_from_idx_idx (const vm_idx_t, const vm_idx_t);
|
||||
vm_instr_counter_t vm_read_instr_counter_from_meta (opcode_meta_type, vm_frame_ctx_t *);
|
||||
vm_instr_counter_t vm_read_instr_counter_from_meta (opcode_meta_type,
|
||||
const bytecode_data_header_t *,
|
||||
vm_instr_counter_t);
|
||||
|
||||
typedef struct vm_instr_t
|
||||
{
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "lexer.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "serializer.h"
|
||||
#include "lit-literal.h"
|
||||
|
||||
static const char* opcode_names[] =
|
||||
@@ -52,6 +51,8 @@ static uint8_t opcode_sizes[] =
|
||||
#include "vm-opcodes.inc.h"
|
||||
};
|
||||
|
||||
const bytecode_data_header_t *bc_to_print_header_p = NULL;
|
||||
|
||||
static char buff[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER];
|
||||
|
||||
static void
|
||||
@@ -110,7 +111,9 @@ var_to_str (vm_instr_t instr, lit_cpointer_t lit_ids[], vm_instr_counter_t oc, u
|
||||
}
|
||||
else
|
||||
{
|
||||
return lit_cp_to_str (serializer_get_literal_cp_by_uid (instr.data.raw_args[current_arg - 1], NULL, oc));
|
||||
return lit_cp_to_str (bc_get_literal_cp_by_uid (instr.data.raw_args[current_arg - 1],
|
||||
bc_to_print_header_p,
|
||||
oc));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,6 +189,8 @@ pp_op_meta (const bytecode_data_header_t *bytecode_data_p,
|
||||
op_meta opm,
|
||||
bool rewrite)
|
||||
{
|
||||
bc_to_print_header_p = bytecode_data_p;
|
||||
|
||||
dump_asm (oc, opm.op);
|
||||
printf (" // ");
|
||||
|
||||
@@ -301,6 +306,11 @@ pp_op_meta (const bytecode_data_header_t *bytecode_data_p,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VM_OP_FUNC_EXPR_REF:
|
||||
{
|
||||
printf ("%s = function ();", VAR (1));
|
||||
break;
|
||||
}
|
||||
case VM_OP_FUNC_EXPR_N:
|
||||
{
|
||||
if (opm.op.data.func_expr_n.arg_list == 0)
|
||||
@@ -378,7 +388,7 @@ pp_op_meta (const bytecode_data_header_t *bytecode_data_p,
|
||||
while ((int16_t) start >= 0 && !found)
|
||||
{
|
||||
start--;
|
||||
switch (serializer_get_instr (bytecode_data_p, start).op_idx)
|
||||
switch (bc_get_instr (bytecode_data_p, start).op_idx)
|
||||
{
|
||||
case VM_OP_CALL_N:
|
||||
case VM_OP_CONSTRUCT_N:
|
||||
@@ -392,7 +402,7 @@ pp_op_meta (const bytecode_data_header_t *bytecode_data_p,
|
||||
}
|
||||
}
|
||||
}
|
||||
vm_instr_t start_op = serializer_get_instr (bytecode_data_p, start);
|
||||
vm_instr_t start_op = bc_get_instr (bytecode_data_p, start);
|
||||
switch (start_op.op_idx)
|
||||
{
|
||||
case VM_OP_CALL_N:
|
||||
@@ -439,7 +449,7 @@ pp_op_meta (const bytecode_data_header_t *bytecode_data_p,
|
||||
}
|
||||
for (vm_instr_counter_t counter = start; counter <= oc; counter++)
|
||||
{
|
||||
vm_instr_t meta_op = serializer_get_instr (bytecode_data_p, counter);
|
||||
vm_instr_t meta_op = bc_get_instr (bytecode_data_p, counter);
|
||||
|
||||
switch (meta_op.op_idx)
|
||||
{
|
||||
@@ -550,48 +560,6 @@ pp_op_meta (const bytecode_data_header_t *bytecode_data_p,
|
||||
printf ("end try");
|
||||
break;
|
||||
}
|
||||
case OPCODE_META_TYPE_SCOPE_CODE_FLAGS:
|
||||
{
|
||||
if (opm.op.data.meta.data_1 != VM_IDX_REWRITE_GENERAL_CASE
|
||||
&& opm.op.data.meta.data_1 != VM_IDX_EMPTY)
|
||||
{
|
||||
vm_idx_t scope_flags = opm.op.data.meta.data_1;
|
||||
|
||||
if (scope_flags & OPCODE_SCOPE_CODE_FLAGS_STRICT)
|
||||
{
|
||||
printf ("[use strict] ");
|
||||
scope_flags &= (vm_idx_t) ~(OPCODE_SCOPE_CODE_FLAGS_STRICT);
|
||||
}
|
||||
if (scope_flags & OPCODE_SCOPE_CODE_FLAGS_NOT_REF_ARGUMENTS_IDENTIFIER)
|
||||
{
|
||||
printf ("[no 'arguments'] ");
|
||||
scope_flags &= (vm_idx_t) ~(OPCODE_SCOPE_CODE_FLAGS_NOT_REF_ARGUMENTS_IDENTIFIER);
|
||||
}
|
||||
if (scope_flags & OPCODE_SCOPE_CODE_FLAGS_NOT_REF_EVAL_IDENTIFIER)
|
||||
{
|
||||
printf ("[no 'eval'] ");
|
||||
scope_flags &= (vm_idx_t) ~(OPCODE_SCOPE_CODE_FLAGS_NOT_REF_EVAL_IDENTIFIER);
|
||||
}
|
||||
if (scope_flags & OPCODE_SCOPE_CODE_FLAGS_ARGUMENTS_ON_REGISTERS)
|
||||
{
|
||||
printf ("[arguments are placed on registers] ");
|
||||
scope_flags &= (vm_idx_t) ~(OPCODE_SCOPE_CODE_FLAGS_ARGUMENTS_ON_REGISTERS);
|
||||
}
|
||||
if (scope_flags & OPCODE_SCOPE_CODE_FLAGS_NO_LEX_ENV)
|
||||
{
|
||||
printf ("[no lexical environment should be created for the scope] ");
|
||||
scope_flags &= (vm_idx_t) ~(OPCODE_SCOPE_CODE_FLAGS_NO_LEX_ENV);
|
||||
}
|
||||
|
||||
JERRY_ASSERT (scope_flags == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("[to be rewritten]");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
JERRY_UNREACHABLE ();
|
||||
|
||||
@@ -53,6 +53,11 @@ VM_OP_3 (func_expr_n, FUNC_EXPR_N,
|
||||
VM_OP_ARG_TYPE_EMPTY,
|
||||
arg_list, VM_OP_ARG_TYPE_INTEGER_CONST)
|
||||
|
||||
VM_OP_3 (func_expr_ref, FUNC_EXPR_REF,
|
||||
lhs, VM_OP_ARG_TYPE_VARIABLE,
|
||||
idx1, VM_OP_ARG_TYPE_INTEGER_CONST,
|
||||
idx2, VM_OP_ARG_TYPE_INTEGER_CONST)
|
||||
|
||||
VM_OP_1 (retval, RETVAL,
|
||||
ret_value, VM_OP_ARG_TYPE_VARIABLE)
|
||||
|
||||
|
||||
+92
-54
@@ -26,6 +26,7 @@
|
||||
#include "vm.h"
|
||||
#include "vm-stack.h"
|
||||
#include "opcodes.h"
|
||||
#include "opcodes-ecma-support.h"
|
||||
|
||||
/**
|
||||
* Top (current) interpreter context
|
||||
@@ -393,16 +394,9 @@ vm_run_global (void)
|
||||
interp_mem_stats_print_legend ();
|
||||
#endif /* MEM_STATS */
|
||||
|
||||
bool is_strict = false;
|
||||
bool is_strict = __program->is_strict;
|
||||
vm_instr_counter_t start_pos = 0;
|
||||
|
||||
opcode_scope_code_flags_t scope_flags = vm_get_scope_flags (__program, start_pos++);
|
||||
|
||||
if (scope_flags & OPCODE_SCOPE_CODE_FLAGS_STRICT)
|
||||
{
|
||||
is_strict = true;
|
||||
}
|
||||
|
||||
ecma_object_t *glob_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_GLOBAL);
|
||||
ecma_object_t *lex_env_p = ecma_get_global_environment ();
|
||||
|
||||
@@ -449,8 +443,8 @@ vm_run_eval (const bytecode_data_header_t *bytecode_data_p, /**< byte-code data
|
||||
bool is_direct) /**< is eval called in direct mode? */
|
||||
{
|
||||
vm_instr_counter_t first_instr_index = 0u;
|
||||
opcode_scope_code_flags_t scope_flags = vm_get_scope_flags (bytecode_data_p, first_instr_index++);
|
||||
bool is_strict = ((scope_flags & OPCODE_SCOPE_CODE_FLAGS_STRICT) != 0);
|
||||
|
||||
bool is_strict = bytecode_data_p->is_strict;
|
||||
|
||||
ecma_value_t this_binding;
|
||||
ecma_object_t *lex_env_p;
|
||||
@@ -605,57 +599,116 @@ vm_run_from_pos (const bytecode_data_header_t *header_p, /**< byte-code data hea
|
||||
* - NULL - otherwise.
|
||||
*/
|
||||
{
|
||||
ecma_completion_value_t completion;
|
||||
ecma_completion_value_t completion = ecma_make_empty_completion_value ();
|
||||
|
||||
const vm_instr_t *instrs_p = header_p->instrs_p;
|
||||
const vm_instr_t *curr = &instrs_p[start_pos];
|
||||
JERRY_ASSERT (curr->op_idx == VM_OP_REG_VAR_DECL);
|
||||
|
||||
const uint32_t tmp_regs_num = curr->data.reg_var_decl.tmp_regs_num;
|
||||
const uint32_t local_var_regs_num = curr->data.reg_var_decl.local_var_regs_num;
|
||||
const uint32_t arg_regs_num = curr->data.reg_var_decl.arg_regs_num;
|
||||
mem_cpointer_t *declarations_p = MEM_CP_GET_POINTER (mem_cpointer_t, header_p->declarations_cp);
|
||||
for (uint16_t func_scope_index = 0;
|
||||
func_scope_index < header_p->func_scopes_count && ecma_is_completion_value_empty (completion);
|
||||
func_scope_index++)
|
||||
{
|
||||
bytecode_data_header_t *func_bc_header_p = MEM_CP_GET_NON_NULL_POINTER (bytecode_data_header_t,
|
||||
declarations_p[func_scope_index]);
|
||||
|
||||
uint32_t regs_num = VM_SPECIAL_REGS_NUMBER + tmp_regs_num + local_var_regs_num + arg_regs_num;
|
||||
if (func_bc_header_p->instrs_p[0].op_idx == VM_OP_FUNC_DECL_N)
|
||||
{
|
||||
completion = vm_function_declaration (func_bc_header_p,
|
||||
is_strict,
|
||||
is_eval_code,
|
||||
lex_env_p);
|
||||
|
||||
MEM_DEFINE_LOCAL_ARRAY (regs, regs_num, ecma_value_t);
|
||||
}
|
||||
}
|
||||
|
||||
vm_frame_ctx_t frame_ctx;
|
||||
frame_ctx.bytecode_header_p = header_p;
|
||||
frame_ctx.pos = (vm_instr_counter_t) (start_pos + 1);
|
||||
frame_ctx.lex_env_p = lex_env_p;
|
||||
frame_ctx.is_strict = is_strict;
|
||||
frame_ctx.is_eval_code = is_eval_code;
|
||||
frame_ctx.is_call_in_direct_eval_form = false;
|
||||
frame_ctx.tmp_num_p = ecma_alloc_number ();
|
||||
lit_cpointer_t *lit_ids_p = (lit_cpointer_t *) (declarations_p + header_p->func_scopes_count);
|
||||
for (uint16_t var_decl_index = 0;
|
||||
var_decl_index < header_p->var_decls_count && ecma_is_completion_value_empty (completion);
|
||||
var_decl_index++)
|
||||
{
|
||||
lit_cpointer_t lit_cp = lit_ids_p[var_decl_index];
|
||||
|
||||
vm_stack_add_frame (&frame_ctx.stack_frame, regs, regs_num, local_var_regs_num, arg_regs_num, arg_collection_p);
|
||||
vm_stack_frame_set_reg_value (&frame_ctx.stack_frame,
|
||||
VM_REG_SPECIAL_THIS_BINDING,
|
||||
ecma_copy_value (this_binding_value, false));
|
||||
if (lit_cp.packed_value != NOT_A_LITERAL.packed_value)
|
||||
{
|
||||
ecma_string_t *var_name_string_p = ecma_new_ecma_string_from_lit_cp (lit_cp);
|
||||
|
||||
vm_frame_ctx_t *prev_context_p = vm_top_context_p;
|
||||
vm_top_context_p = &frame_ctx;
|
||||
if (!ecma_op_has_binding (lex_env_p, var_name_string_p))
|
||||
{
|
||||
const bool is_configurable_bindings = is_eval_code;
|
||||
|
||||
completion = ecma_op_create_mutable_binding (lex_env_p,
|
||||
var_name_string_p,
|
||||
is_configurable_bindings);
|
||||
|
||||
JERRY_ASSERT (ecma_is_completion_value_empty (completion));
|
||||
|
||||
/* Skipping SetMutableBinding as we have already checked that there were not
|
||||
* any binding with specified name in current lexical environment
|
||||
* and CreateMutableBinding sets the created binding's value to undefined */
|
||||
JERRY_ASSERT (ecma_is_completion_value_normal_simple_value (ecma_op_get_binding_value (lex_env_p,
|
||||
var_name_string_p,
|
||||
true),
|
||||
ECMA_SIMPLE_VALUE_UNDEFINED));
|
||||
}
|
||||
|
||||
ecma_deref_ecma_string (var_name_string_p);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ecma_is_completion_value_empty (completion))
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_completion_value_throw (completion));
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint32_t tmp_regs_num = curr->data.reg_var_decl.tmp_regs_num;
|
||||
const uint32_t local_var_regs_num = curr->data.reg_var_decl.local_var_regs_num;
|
||||
const uint32_t arg_regs_num = curr->data.reg_var_decl.arg_regs_num;
|
||||
|
||||
uint32_t regs_num = VM_SPECIAL_REGS_NUMBER + tmp_regs_num + local_var_regs_num + arg_regs_num;
|
||||
|
||||
MEM_DEFINE_LOCAL_ARRAY (regs, regs_num, ecma_value_t);
|
||||
|
||||
vm_frame_ctx_t frame_ctx;
|
||||
frame_ctx.bytecode_header_p = header_p;
|
||||
frame_ctx.pos = (vm_instr_counter_t) (start_pos + 1);
|
||||
frame_ctx.lex_env_p = lex_env_p;
|
||||
frame_ctx.is_strict = is_strict;
|
||||
frame_ctx.is_eval_code = is_eval_code;
|
||||
frame_ctx.is_call_in_direct_eval_form = false;
|
||||
frame_ctx.tmp_num_p = ecma_alloc_number ();
|
||||
|
||||
vm_stack_add_frame (&frame_ctx.stack_frame, regs, regs_num, local_var_regs_num, arg_regs_num, arg_collection_p);
|
||||
vm_stack_frame_set_reg_value (&frame_ctx.stack_frame,
|
||||
VM_REG_SPECIAL_THIS_BINDING,
|
||||
ecma_copy_value (this_binding_value, false));
|
||||
|
||||
vm_frame_ctx_t *prev_context_p = vm_top_context_p;
|
||||
vm_top_context_p = &frame_ctx;
|
||||
|
||||
#ifdef MEM_STATS
|
||||
interp_mem_stats_context_enter (&frame_ctx, start_pos);
|
||||
interp_mem_stats_context_enter (&frame_ctx, start_pos);
|
||||
#endif /* MEM_STATS */
|
||||
|
||||
completion = vm_loop (&frame_ctx, NULL);
|
||||
completion = vm_loop (&frame_ctx, NULL);
|
||||
|
||||
JERRY_ASSERT (ecma_is_completion_value_throw (completion)
|
||||
|| ecma_is_completion_value_return (completion));
|
||||
JERRY_ASSERT (ecma_is_completion_value_throw (completion)
|
||||
|| ecma_is_completion_value_return (completion));
|
||||
|
||||
vm_top_context_p = prev_context_p;
|
||||
vm_top_context_p = prev_context_p;
|
||||
|
||||
vm_stack_free_frame (&frame_ctx.stack_frame);
|
||||
vm_stack_free_frame (&frame_ctx.stack_frame);
|
||||
|
||||
ecma_dealloc_number (frame_ctx.tmp_num_p);
|
||||
ecma_dealloc_number (frame_ctx.tmp_num_p);
|
||||
|
||||
#ifdef MEM_STATS
|
||||
interp_mem_stats_context_exit (&frame_ctx, start_pos);
|
||||
interp_mem_stats_context_exit (&frame_ctx, start_pos);
|
||||
#endif /* MEM_STATS */
|
||||
|
||||
MEM_FINALIZE_LOCAL_ARRAY (regs);
|
||||
MEM_FINALIZE_LOCAL_ARRAY (regs);
|
||||
}
|
||||
|
||||
return completion;
|
||||
} /* vm_run_from_pos */
|
||||
@@ -670,21 +723,6 @@ vm_get_instr (const vm_instr_t *instrs_p, /**< byte-code array */
|
||||
return instrs_p[ counter ];
|
||||
} /* vm_get_instr */
|
||||
|
||||
/**
|
||||
* Get scope code flags from instruction at specified position
|
||||
*
|
||||
* @return mask of scope code flags
|
||||
*/
|
||||
opcode_scope_code_flags_t
|
||||
vm_get_scope_flags (const bytecode_data_header_t *bytecode_header_p, /**< byte-code data */
|
||||
vm_instr_counter_t counter) /**< instruction counter */
|
||||
{
|
||||
vm_instr_t flags_instr = vm_get_instr (bytecode_header_p->instrs_p, counter);
|
||||
JERRY_ASSERT (flags_instr.op_idx == VM_OP_META
|
||||
&& flags_instr.data.meta.type == OPCODE_META_TYPE_SCOPE_CODE_FLAGS);
|
||||
return (opcode_scope_code_flags_t) flags_instr.data.meta.data_1;
|
||||
} /* vm_get_scope_flags */
|
||||
|
||||
/**
|
||||
* Get arguments number, encoded in specified reg_var_decl instruction
|
||||
*
|
||||
|
||||
@@ -30,7 +30,6 @@ extern ecma_completion_value_t vm_run_from_pos (const bytecode_data_header_t *,
|
||||
ecma_value_t, ecma_object_t *, bool, bool, ecma_collection_header_t *);
|
||||
|
||||
extern vm_instr_t vm_get_instr (const vm_instr_t *, vm_instr_counter_t);
|
||||
extern opcode_scope_code_flags_t vm_get_scope_flags (const bytecode_data_header_t *, vm_instr_counter_t);
|
||||
extern uint8_t vm_get_scope_args_num (const bytecode_data_header_t *, vm_instr_counter_t);
|
||||
|
||||
extern bool vm_is_strict_mode (void);
|
||||
|
||||
Reference in New Issue
Block a user