Remove preparser lexer pass and pass for searching of "eval" and "arguments" literals.
JerryScript-DCO-1.0-Signed-off-by: Andrey Shitov a.shitov@samsung.com
This commit is contained in:
@@ -2507,31 +2507,36 @@ dump_throw (operand op)
|
||||
dump_single_address (getop_throw_value, op);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if variable is already declared
|
||||
*
|
||||
* @return true if variable declaration already exists
|
||||
* false otherwise
|
||||
*/
|
||||
bool
|
||||
dumper_variable_declaration_exists (lit_cpointer_t lit_id)
|
||||
dumper_variable_declaration_exists (lit_cpointer_t lit_id) /**< literal which holds variable's name */
|
||||
{
|
||||
for (vm_instr_counter_t oc = (vm_instr_counter_t) (serializer_get_current_instr_counter () - 1);
|
||||
oc > 0; oc--)
|
||||
vm_instr_counter_t var_decls_count = (vm_instr_counter_t) serializer_get_current_var_decls_counter ();
|
||||
for (vm_instr_counter_t oc = (vm_instr_counter_t) (0); oc < var_decls_count; oc++)
|
||||
{
|
||||
const op_meta var_decl_op_meta = serializer_get_op_meta (oc);
|
||||
if (var_decl_op_meta.op.op_idx != VM_OP_VAR_DECL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
const op_meta var_decl_op_meta = serializer_get_var_decl (oc);
|
||||
if (var_decl_op_meta.lit_id[0].packed_value == lit_id.packed_value)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} /* dumper_variable_declaration_exists */
|
||||
|
||||
/**
|
||||
* Dump instruction designating variable declaration
|
||||
*/
|
||||
void
|
||||
dump_variable_declaration (lit_cpointer_t lit_id)
|
||||
dump_variable_declaration (lit_cpointer_t lit_id) /**< literal which holds variable's name */
|
||||
{
|
||||
const vm_instr_t instr = getop_var_decl (LITERAL_TO_REWRITE);
|
||||
serializer_dump_op_meta (create_op_meta_100 (instr, lit_id));
|
||||
}
|
||||
serializer_dump_var_decl (create_op_meta_100 (instr, lit_id));
|
||||
} /* dump_variable_declaration */
|
||||
|
||||
/**
|
||||
* Dump template of 'meta' instruction for scope's code flags.
|
||||
|
||||
+62
-232
@@ -829,7 +829,18 @@ parse_primary_expression (void)
|
||||
case TOK_NUMBER:
|
||||
case TOK_REGEXP:
|
||||
case TOK_STRING: return parse_literal ();
|
||||
case TOK_NAME: return literal_operand (token_data_as_lit_cp ());
|
||||
case TOK_NAME:
|
||||
{
|
||||
if (lit_literal_equal_type_cstr (lit_get_literal_by_cp (token_data_as_lit_cp ()), "arguments"))
|
||||
{
|
||||
scopes_tree_set_arguments_used (STACK_TOP (scopes));
|
||||
}
|
||||
if (lit_literal_equal_type_cstr (lit_get_literal_by_cp (token_data_as_lit_cp ()), "eval"))
|
||||
{
|
||||
scopes_tree_set_eval_used (STACK_TOP (scopes));
|
||||
}
|
||||
return literal_operand (token_data_as_lit_cp ());
|
||||
}
|
||||
case TOK_OPEN_SQUARE: return parse_array_literal ();
|
||||
case TOK_OPEN_BRACE: return parse_object_literal ();
|
||||
case TOK_OPEN_PAREN:
|
||||
@@ -1812,6 +1823,15 @@ parse_variable_declaration (void)
|
||||
current_token_must_be (TOK_NAME);
|
||||
const operand name = literal_operand (token_data_as_lit_cp ());
|
||||
|
||||
if (!dumper_variable_declaration_exists (token_data_as_lit_cp ()))
|
||||
{
|
||||
jsp_early_error_check_for_eval_and_arguments_in_strict_mode (literal_operand (token_data_as_lit_cp ()),
|
||||
is_strict_mode (),
|
||||
tok.loc);
|
||||
|
||||
dump_variable_declaration (token_data_as_lit_cp ());
|
||||
}
|
||||
|
||||
skip_newlines ();
|
||||
if (token_is (TOK_EQ))
|
||||
{
|
||||
@@ -1825,7 +1845,7 @@ parse_variable_declaration (void)
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
} /* parse_variable_declaration */
|
||||
|
||||
/* variable_declaration_list
|
||||
: variable_declaration
|
||||
@@ -2886,65 +2906,12 @@ parse_source_element (void)
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip function's optional name and parentheses
|
||||
*
|
||||
* @return: true, if skipped successfully
|
||||
* false, if open parentheses wasn't found (this means that keyword 'function' is used as
|
||||
* a property name)
|
||||
* Check for "use strict" in directive prologue
|
||||
*/
|
||||
static bool
|
||||
skip_optional_name_and_parens (void)
|
||||
{
|
||||
if (token_is (TOK_NAME))
|
||||
{
|
||||
token_after_newlines_must_be (TOK_OPEN_PAREN);
|
||||
}
|
||||
|
||||
if (token_is (TOK_OPEN_PAREN))
|
||||
{
|
||||
skip_newlines ();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
while (!token_is (TOK_CLOSE_PAREN))
|
||||
{
|
||||
skip_newlines ();
|
||||
}
|
||||
|
||||
return true;
|
||||
} /* skip_optional_name_and_parens */
|
||||
|
||||
static void
|
||||
skip_function (void)
|
||||
{
|
||||
skip_newlines ();
|
||||
if (skip_optional_name_and_parens ())
|
||||
{
|
||||
skip_newlines ();
|
||||
jsp_skip_braces (TOK_OPEN_BRACE);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
var_declared (lit_cpointer_t var_cp)
|
||||
{
|
||||
return dumper_variable_declaration_exists (var_cp);
|
||||
}
|
||||
|
||||
static void
|
||||
preparse_scope (bool is_global)
|
||||
check_directive_prologue_for_use_strict ()
|
||||
{
|
||||
const locus start_loc = tok.loc;
|
||||
const token_type end_tt = is_global ? TOK_EOF : TOK_CLOSE_BRACE;
|
||||
|
||||
vm_instr_counter_t scope_code_flags_oc = dump_scope_code_flags_for_rewrite ();
|
||||
|
||||
bool is_use_strict = false;
|
||||
bool is_ref_arguments_identifier = false;
|
||||
bool is_ref_eval_identifier = false;
|
||||
|
||||
/*
|
||||
* Check Directive Prologue for Use Strict directive (see ECMA-262 5.1 section 14.1)
|
||||
@@ -2954,7 +2921,8 @@ preparse_scope (bool is_global)
|
||||
if (lit_literal_equal_type_cstr (lit_get_literal_by_cp (token_data_as_lit_cp ()), "use strict")
|
||||
&& lexer_is_no_escape_sequences_in_token_string (tok))
|
||||
{
|
||||
is_use_strict = true;
|
||||
scopes_tree_set_strict_mode (STACK_TOP (scopes), true);
|
||||
lexer_set_strict_mode (scopes_tree_strict_mode (STACK_TOP (scopes)));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2966,186 +2934,15 @@ preparse_scope (bool is_global)
|
||||
}
|
||||
}
|
||||
|
||||
size_t nesting_level = 0;
|
||||
while (nesting_level > 0 || !token_is (end_tt))
|
||||
{
|
||||
if (token_is (TOK_OPEN_BRACE))
|
||||
{
|
||||
nesting_level++;
|
||||
}
|
||||
else if (token_is (TOK_CLOSE_BRACE))
|
||||
{
|
||||
nesting_level--;
|
||||
}
|
||||
else if (token_is (TOK_NAME))
|
||||
{
|
||||
if (lit_literal_equal_type_cstr (lit_get_literal_by_cp (token_data_as_lit_cp ()), "arguments"))
|
||||
{
|
||||
is_ref_arguments_identifier = true;
|
||||
}
|
||||
else if (lit_literal_equal_type_cstr (lit_get_literal_by_cp (token_data_as_lit_cp ()), "eval"))
|
||||
{
|
||||
is_ref_eval_identifier = true;
|
||||
}
|
||||
}
|
||||
|
||||
skip_newlines ();
|
||||
}
|
||||
|
||||
opcode_scope_code_flags_t scope_flags = OPCODE_SCOPE_CODE_FLAGS__EMPTY;
|
||||
|
||||
if (is_use_strict)
|
||||
{
|
||||
scopes_tree_set_strict_mode (STACK_TOP (scopes), true);
|
||||
|
||||
scope_flags = (opcode_scope_code_flags_t) (scope_flags | OPCODE_SCOPE_CODE_FLAGS_STRICT);
|
||||
}
|
||||
|
||||
if (!is_ref_arguments_identifier)
|
||||
{
|
||||
scope_flags = (opcode_scope_code_flags_t) (scope_flags | OPCODE_SCOPE_CODE_FLAGS_NOT_REF_ARGUMENTS_IDENTIFIER);
|
||||
}
|
||||
|
||||
if (!is_ref_eval_identifier)
|
||||
{
|
||||
scope_flags = (opcode_scope_code_flags_t) (scope_flags | OPCODE_SCOPE_CODE_FLAGS_NOT_REF_EVAL_IDENTIFIER);
|
||||
}
|
||||
|
||||
rewrite_scope_code_flags (scope_code_flags_oc, scope_flags);
|
||||
|
||||
lexer_set_strict_mode (scopes_tree_strict_mode (STACK_TOP (scopes)));
|
||||
|
||||
dump_reg_var_decl_for_rewrite ();
|
||||
|
||||
if (lit_utf8_iterator_pos_cmp (start_loc, tok.loc) != 0)
|
||||
{
|
||||
lexer_seek (start_loc);
|
||||
skip_newlines ();
|
||||
|
||||
bool is_in_var_declaration_list = false;
|
||||
|
||||
size_t nesting_level = 0;
|
||||
while (nesting_level > 0 || !token_is (end_tt))
|
||||
{
|
||||
/*
|
||||
* FIXME:
|
||||
* Remove preparse_scope; move variable declaration search to main pass of parser.
|
||||
* When byte-code and scope storages would be introduced, move variable declarations
|
||||
* from byte-code to scope descriptor.
|
||||
*/
|
||||
if (token_is (TOK_NAME))
|
||||
{
|
||||
if (is_in_var_declaration_list)
|
||||
{
|
||||
if (!var_declared (token_data_as_lit_cp ()))
|
||||
{
|
||||
jsp_early_error_check_for_eval_and_arguments_in_strict_mode (literal_operand (token_data_as_lit_cp ()),
|
||||
is_strict_mode (),
|
||||
tok.loc);
|
||||
dump_variable_declaration (token_data_as_lit_cp ());
|
||||
}
|
||||
}
|
||||
|
||||
skip_newlines ();
|
||||
|
||||
if (!token_is (TOK_COMMA)
|
||||
&& !token_is (TOK_EQ))
|
||||
{
|
||||
is_in_var_declaration_list = false;
|
||||
}
|
||||
}
|
||||
else if (is_in_var_declaration_list)
|
||||
{
|
||||
if (token_is (TOK_EQ))
|
||||
{
|
||||
skip_newlines ();
|
||||
|
||||
while (!token_is (end_tt)
|
||||
&& !token_is (TOK_COMMA)
|
||||
&& !token_is (TOK_SEMICOLON))
|
||||
{
|
||||
if (is_keyword (KW_FUNCTION))
|
||||
{
|
||||
skip_function ();
|
||||
}
|
||||
else if (token_is (TOK_OPEN_BRACE))
|
||||
{
|
||||
jsp_skip_braces (TOK_OPEN_BRACE);
|
||||
}
|
||||
else if (token_is (TOK_OPEN_SQUARE))
|
||||
{
|
||||
jsp_skip_braces (TOK_OPEN_SQUARE);
|
||||
}
|
||||
else if (token_is (TOK_OPEN_PAREN))
|
||||
{
|
||||
jsp_skip_braces (TOK_OPEN_PAREN);
|
||||
}
|
||||
else if (token_is (TOK_KEYWORD))
|
||||
{
|
||||
if (is_keyword (KW_VAR))
|
||||
{
|
||||
is_in_var_declaration_list = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (token_is (TOK_CLOSE_BRACE))
|
||||
{
|
||||
/* the '}' would be handled during next iteration, reducing nesting level counter */
|
||||
is_in_var_declaration_list = false;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
skip_token ();
|
||||
}
|
||||
}
|
||||
else if (token_is (TOK_COMMA))
|
||||
{
|
||||
skip_newlines ();
|
||||
}
|
||||
else
|
||||
{
|
||||
is_in_var_declaration_list = false;
|
||||
|
||||
skip_newlines ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (token_is (TOK_OPEN_BRACE))
|
||||
{
|
||||
nesting_level++;
|
||||
}
|
||||
else if (token_is (TOK_CLOSE_BRACE))
|
||||
{
|
||||
nesting_level--;
|
||||
}
|
||||
else if (token_is (TOK_OPEN_SQUARE))
|
||||
{
|
||||
jsp_skip_braces (TOK_OPEN_SQUARE);
|
||||
}
|
||||
else if (is_keyword (KW_VAR))
|
||||
{
|
||||
is_in_var_declaration_list = true;
|
||||
}
|
||||
else if (is_keyword (KW_FUNCTION))
|
||||
{
|
||||
skip_function ();
|
||||
}
|
||||
|
||||
skip_newlines ();
|
||||
}
|
||||
}
|
||||
|
||||
lexer_seek (start_loc);
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (token_is (end_tt));
|
||||
|
||||
lexer_save_token (tok);
|
||||
}
|
||||
}
|
||||
} /* check_directive_prologue_for_use_strict */
|
||||
|
||||
/**
|
||||
* Parse source element list
|
||||
@@ -3155,10 +2952,17 @@ preparse_scope (bool is_global)
|
||||
* ;
|
||||
*/
|
||||
static void
|
||||
parse_source_element_list (bool is_global) /**< flag indicating if we are parsing the global scope */
|
||||
parse_source_element_list (bool is_global) /**< flag, indicating that we parsing global context */
|
||||
{
|
||||
const token_type end_tt = is_global ? TOK_EOF : TOK_CLOSE_BRACE;
|
||||
|
||||
dumper_new_scope ();
|
||||
preparse_scope (is_global);
|
||||
|
||||
vm_instr_counter_t scope_code_flags_oc = dump_scope_code_flags_for_rewrite ();
|
||||
|
||||
check_directive_prologue_for_use_strict ();
|
||||
|
||||
dump_reg_var_decl_for_rewrite ();
|
||||
|
||||
if (inside_eval
|
||||
&& !inside_function)
|
||||
@@ -3172,7 +2976,33 @@ parse_source_element_list (bool is_global) /**< flag indicating if we are parsin
|
||||
parse_source_element ();
|
||||
skip_newlines ();
|
||||
}
|
||||
|
||||
if (!token_is (end_tt))
|
||||
{
|
||||
PARSE_ERROR (JSP_EARLY_ERROR_SYNTAX, "Unexpected token", tok.loc);
|
||||
}
|
||||
|
||||
lexer_save_token (tok);
|
||||
|
||||
opcode_scope_code_flags_t scope_flags = OPCODE_SCOPE_CODE_FLAGS__EMPTY;
|
||||
|
||||
scopes_tree fe_scope_tree = STACK_TOP (scopes);
|
||||
if (fe_scope_tree->strict_mode)
|
||||
{
|
||||
scope_flags = (opcode_scope_code_flags_t) (scope_flags | OPCODE_SCOPE_CODE_FLAGS_STRICT);
|
||||
}
|
||||
|
||||
if (!fe_scope_tree->ref_arguments)
|
||||
{
|
||||
scope_flags = (opcode_scope_code_flags_t) (scope_flags | OPCODE_SCOPE_CODE_FLAGS_NOT_REF_ARGUMENTS_IDENTIFIER);
|
||||
}
|
||||
|
||||
if (!fe_scope_tree->ref_eval)
|
||||
{
|
||||
scope_flags = (opcode_scope_code_flags_t) (scope_flags | OPCODE_SCOPE_CODE_FLAGS_NOT_REF_EVAL_IDENTIFIER);
|
||||
}
|
||||
rewrite_scope_code_flags (scope_code_flags_oc, scope_flags);
|
||||
|
||||
rewrite_reg_var_decl ();
|
||||
dumper_finish_scope ();
|
||||
} /* parse_source_element_list */
|
||||
|
||||
@@ -49,21 +49,44 @@ vm_instr_counter_t
|
||||
scopes_tree_instrs_num (scopes_tree t)
|
||||
{
|
||||
assert_tree (t);
|
||||
return t->instrs_num;
|
||||
return t->instrs_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of variable declarations in the scope
|
||||
*
|
||||
* @return number of variable declarations
|
||||
*/
|
||||
vm_instr_counter_t
|
||||
scopes_tree_var_decls_num (scopes_tree t) /**< scope */
|
||||
{
|
||||
assert_tree (t);
|
||||
return t->var_decls_cout;
|
||||
} /* scopes_tree_var_decls_num */
|
||||
|
||||
void
|
||||
scopes_tree_add_op_meta (scopes_tree tree, op_meta op)
|
||||
{
|
||||
assert_tree (tree);
|
||||
linked_list_set_element (tree->instrs, tree->instrs_num++, &op);
|
||||
linked_list_set_element (tree->instrs, tree->instrs_count++, &op);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add variable declaration to a scope
|
||||
*/
|
||||
void
|
||||
scopes_tree_add_var_decl (scopes_tree tree, /**< scope, to which variable declaration is added */
|
||||
op_meta op) /**< variable declaration instruction */
|
||||
{
|
||||
assert_tree (tree);
|
||||
linked_list_set_element (tree->var_decls, tree->var_decls_cout++, &op);
|
||||
} /* scopes_tree_add_var_decl */
|
||||
|
||||
void
|
||||
scopes_tree_set_op_meta (scopes_tree tree, vm_instr_counter_t oc, op_meta op)
|
||||
{
|
||||
assert_tree (tree);
|
||||
JERRY_ASSERT (oc < tree->instrs_num);
|
||||
JERRY_ASSERT (oc < tree->instrs_count);
|
||||
linked_list_set_element (tree->instrs, oc, &op);
|
||||
}
|
||||
|
||||
@@ -71,23 +94,37 @@ void
|
||||
scopes_tree_set_instrs_num (scopes_tree tree, vm_instr_counter_t oc)
|
||||
{
|
||||
assert_tree (tree);
|
||||
JERRY_ASSERT (oc < tree->instrs_num);
|
||||
tree->instrs_num = oc;
|
||||
JERRY_ASSERT (oc < tree->instrs_count);
|
||||
tree->instrs_count = oc;
|
||||
}
|
||||
|
||||
op_meta
|
||||
scopes_tree_op_meta (scopes_tree tree, vm_instr_counter_t oc)
|
||||
{
|
||||
assert_tree (tree);
|
||||
JERRY_ASSERT (oc < tree->instrs_num);
|
||||
JERRY_ASSERT (oc < tree->instrs_count);
|
||||
return *(op_meta *) linked_list_element (tree->instrs, oc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get variable declaration for the specified scope
|
||||
*
|
||||
* @return instruction, declaring a variable
|
||||
*/
|
||||
op_meta
|
||||
scopes_tree_var_decl (scopes_tree tree, /**< scope, from which variable declaration is retrieved */
|
||||
vm_instr_counter_t oc) /**< number of variable declaration in the scope */
|
||||
{
|
||||
assert_tree (tree);
|
||||
JERRY_ASSERT (oc < tree->var_decls_cout);
|
||||
return *(op_meta *) linked_list_element (tree->var_decls, oc);
|
||||
} /* scopes_tree_var_decl */
|
||||
|
||||
vm_instr_counter_t
|
||||
scopes_tree_count_instructions (scopes_tree t)
|
||||
{
|
||||
assert_tree (t);
|
||||
vm_instr_counter_t res = t->instrs_num;
|
||||
vm_instr_counter_t res = (vm_instr_counter_t) (t->instrs_count + t->var_decls_cout);
|
||||
for (uint8_t i = 0; i < t->t.children_num; i++)
|
||||
{
|
||||
res = (vm_instr_counter_t) (
|
||||
@@ -212,24 +249,37 @@ insert_uids_to_lit_id_map (op_meta *om, uint16_t mask)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get instruction from instruction list
|
||||
*
|
||||
* @return instruction at specified position
|
||||
*/
|
||||
static op_meta *
|
||||
extract_op_meta (scopes_tree tree, vm_instr_counter_t instr_pos)
|
||||
extract_op_meta (linked_list instr_list, /**< instruction list */
|
||||
vm_instr_counter_t instr_pos) /**< position inside the list */
|
||||
{
|
||||
return (op_meta *) linked_list_element (tree->instrs, instr_pos);
|
||||
}
|
||||
return (op_meta *) linked_list_element (instr_list, instr_pos);
|
||||
} /* extract_op_meta */
|
||||
|
||||
/**
|
||||
* Add instruction to an instruction list
|
||||
*
|
||||
* @return generated instruction
|
||||
*/
|
||||
static vm_instr_t
|
||||
generate_instr (scopes_tree tree, vm_instr_counter_t instr_pos, lit_id_hash_table *lit_ids)
|
||||
generate_instr (linked_list instr_list, /**< instruction list */
|
||||
vm_instr_counter_t instr_pos, /**< position where to generate an instruction */
|
||||
lit_id_hash_table *lit_ids) /**< hash table binding operand identifiers and literals */
|
||||
{
|
||||
start_new_block_if_necessary ();
|
||||
op_meta *om = extract_op_meta (tree, instr_pos);
|
||||
op_meta *om_p = extract_op_meta (instr_list, instr_pos);
|
||||
/* Now we should change uids of instructions.
|
||||
Since different instructions has different literals/tmps in different places,
|
||||
we should change only them.
|
||||
For each case possible literal positions are shown as 0xYYY literal,
|
||||
where Y is set to '1' when there is a possible literal in this position,
|
||||
and '0' otherwise. */
|
||||
switch (om->op.op_idx)
|
||||
switch (om_p->op.op_idx)
|
||||
{
|
||||
case VM_OP_PROP_GETTER:
|
||||
case VM_OP_PROP_SETTER:
|
||||
@@ -256,7 +306,7 @@ generate_instr (scopes_tree tree, vm_instr_counter_t instr_pos, lit_id_hash_tabl
|
||||
case VM_OP_MULTIPLICATION:
|
||||
case VM_OP_REMAINDER:
|
||||
{
|
||||
change_uid (om, lit_ids, 0x111);
|
||||
change_uid (om_p, lit_ids, 0x111);
|
||||
break;
|
||||
}
|
||||
case VM_OP_CALL_N:
|
||||
@@ -273,18 +323,18 @@ generate_instr (scopes_tree tree, vm_instr_counter_t instr_pos, lit_id_hash_tabl
|
||||
case VM_OP_UNARY_PLUS:
|
||||
case VM_OP_UNARY_MINUS:
|
||||
{
|
||||
change_uid (om, lit_ids, 0x110);
|
||||
change_uid (om_p, lit_ids, 0x110);
|
||||
break;
|
||||
}
|
||||
case VM_OP_ASSIGNMENT:
|
||||
{
|
||||
switch (om->op.data.assignment.type_value_right)
|
||||
switch (om_p->op.data.assignment.type_value_right)
|
||||
{
|
||||
case OPCODE_ARG_TYPE_SIMPLE:
|
||||
case OPCODE_ARG_TYPE_SMALLINT:
|
||||
case OPCODE_ARG_TYPE_SMALLINT_NEGATE:
|
||||
{
|
||||
change_uid (om, lit_ids, 0x100);
|
||||
change_uid (om_p, lit_ids, 0x100);
|
||||
break;
|
||||
}
|
||||
case OPCODE_ARG_TYPE_NUMBER:
|
||||
@@ -293,7 +343,7 @@ generate_instr (scopes_tree tree, vm_instr_counter_t instr_pos, lit_id_hash_tabl
|
||||
case OPCODE_ARG_TYPE_STRING:
|
||||
case OPCODE_ARG_TYPE_VARIABLE:
|
||||
{
|
||||
change_uid (om, lit_ids, 0x101);
|
||||
change_uid (om_p, lit_ids, 0x101);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -313,7 +363,7 @@ generate_instr (scopes_tree tree, vm_instr_counter_t instr_pos, lit_id_hash_tabl
|
||||
case VM_OP_VAR_DECL:
|
||||
case VM_OP_RETVAL:
|
||||
{
|
||||
change_uid (om, lit_ids, 0x100);
|
||||
change_uid (om_p, lit_ids, 0x100);
|
||||
break;
|
||||
}
|
||||
case VM_OP_RET:
|
||||
@@ -322,24 +372,24 @@ generate_instr (scopes_tree tree, vm_instr_counter_t instr_pos, lit_id_hash_tabl
|
||||
case VM_OP_JMP_DOWN:
|
||||
case VM_OP_REG_VAR_DECL:
|
||||
{
|
||||
change_uid (om, lit_ids, 0x000);
|
||||
change_uid (om_p, lit_ids, 0x000);
|
||||
break;
|
||||
}
|
||||
case VM_OP_META:
|
||||
{
|
||||
switch (om->op.data.meta.type)
|
||||
switch (om_p->op.data.meta.type)
|
||||
{
|
||||
case OPCODE_META_TYPE_VARG_PROP_DATA:
|
||||
case OPCODE_META_TYPE_VARG_PROP_GETTER:
|
||||
case OPCODE_META_TYPE_VARG_PROP_SETTER:
|
||||
{
|
||||
change_uid (om, lit_ids, 0x011);
|
||||
change_uid (om_p, lit_ids, 0x011);
|
||||
break;
|
||||
}
|
||||
case OPCODE_META_TYPE_VARG:
|
||||
case OPCODE_META_TYPE_CATCH_EXCEPTION_IDENTIFIER:
|
||||
{
|
||||
change_uid (om, lit_ids, 0x010);
|
||||
change_uid (om_p, lit_ids, 0x010);
|
||||
break;
|
||||
}
|
||||
case OPCODE_META_TYPE_UNDEFINED:
|
||||
@@ -351,23 +401,27 @@ generate_instr (scopes_tree tree, vm_instr_counter_t instr_pos, lit_id_hash_tabl
|
||||
case OPCODE_META_TYPE_CALL_SITE_INFO:
|
||||
case OPCODE_META_TYPE_SCOPE_CODE_FLAGS:
|
||||
{
|
||||
change_uid (om, lit_ids, 0x000);
|
||||
change_uid (om_p, lit_ids, 0x000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return om->op;
|
||||
}
|
||||
return om_p->op;
|
||||
} /* generate_instr */
|
||||
|
||||
/**
|
||||
* Count number of literals in instruction which were not seen previously
|
||||
*
|
||||
* @return number of new literals
|
||||
*/
|
||||
static idx_t
|
||||
count_new_literals_in_instr (scopes_tree tree, vm_instr_counter_t instr_pos)
|
||||
count_new_literals_in_instr (op_meta *om_p) /**< instruction */
|
||||
{
|
||||
start_new_block_if_necessary ();
|
||||
idx_t current_uid = next_uid;
|
||||
op_meta *om = extract_op_meta (tree, instr_pos);
|
||||
switch (om->op.op_idx)
|
||||
switch (om_p->op.op_idx)
|
||||
{
|
||||
case VM_OP_PROP_GETTER:
|
||||
case VM_OP_PROP_SETTER:
|
||||
@@ -394,7 +448,7 @@ count_new_literals_in_instr (scopes_tree tree, vm_instr_counter_t instr_pos)
|
||||
case VM_OP_MULTIPLICATION:
|
||||
case VM_OP_REMAINDER:
|
||||
{
|
||||
insert_uids_to_lit_id_map (om, 0x111);
|
||||
insert_uids_to_lit_id_map (om_p, 0x111);
|
||||
break;
|
||||
}
|
||||
case VM_OP_CALL_N:
|
||||
@@ -411,18 +465,18 @@ count_new_literals_in_instr (scopes_tree tree, vm_instr_counter_t instr_pos)
|
||||
case VM_OP_UNARY_PLUS:
|
||||
case VM_OP_UNARY_MINUS:
|
||||
{
|
||||
insert_uids_to_lit_id_map (om, 0x110);
|
||||
insert_uids_to_lit_id_map (om_p, 0x110);
|
||||
break;
|
||||
}
|
||||
case VM_OP_ASSIGNMENT:
|
||||
{
|
||||
switch (om->op.data.assignment.type_value_right)
|
||||
switch (om_p->op.data.assignment.type_value_right)
|
||||
{
|
||||
case OPCODE_ARG_TYPE_SIMPLE:
|
||||
case OPCODE_ARG_TYPE_SMALLINT:
|
||||
case OPCODE_ARG_TYPE_SMALLINT_NEGATE:
|
||||
{
|
||||
insert_uids_to_lit_id_map (om, 0x100);
|
||||
insert_uids_to_lit_id_map (om_p, 0x100);
|
||||
break;
|
||||
}
|
||||
case OPCODE_ARG_TYPE_NUMBER:
|
||||
@@ -431,7 +485,7 @@ count_new_literals_in_instr (scopes_tree tree, vm_instr_counter_t instr_pos)
|
||||
case OPCODE_ARG_TYPE_STRING:
|
||||
case OPCODE_ARG_TYPE_VARIABLE:
|
||||
{
|
||||
insert_uids_to_lit_id_map (om, 0x101);
|
||||
insert_uids_to_lit_id_map (om_p, 0x101);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -450,7 +504,7 @@ count_new_literals_in_instr (scopes_tree tree, vm_instr_counter_t instr_pos)
|
||||
case VM_OP_VAR_DECL:
|
||||
case VM_OP_RETVAL:
|
||||
{
|
||||
insert_uids_to_lit_id_map (om, 0x100);
|
||||
insert_uids_to_lit_id_map (om_p, 0x100);
|
||||
break;
|
||||
}
|
||||
case VM_OP_RET:
|
||||
@@ -459,24 +513,24 @@ count_new_literals_in_instr (scopes_tree tree, vm_instr_counter_t instr_pos)
|
||||
case VM_OP_JMP_DOWN:
|
||||
case VM_OP_REG_VAR_DECL:
|
||||
{
|
||||
insert_uids_to_lit_id_map (om, 0x000);
|
||||
insert_uids_to_lit_id_map (om_p, 0x000);
|
||||
break;
|
||||
}
|
||||
case VM_OP_META:
|
||||
{
|
||||
switch (om->op.data.meta.type)
|
||||
switch (om_p->op.data.meta.type)
|
||||
{
|
||||
case OPCODE_META_TYPE_VARG_PROP_DATA:
|
||||
case OPCODE_META_TYPE_VARG_PROP_GETTER:
|
||||
case OPCODE_META_TYPE_VARG_PROP_SETTER:
|
||||
{
|
||||
insert_uids_to_lit_id_map (om, 0x011);
|
||||
insert_uids_to_lit_id_map (om_p, 0x011);
|
||||
break;
|
||||
}
|
||||
case OPCODE_META_TYPE_VARG:
|
||||
case OPCODE_META_TYPE_CATCH_EXCEPTION_IDENTIFIER:
|
||||
{
|
||||
insert_uids_to_lit_id_map (om, 0x010);
|
||||
insert_uids_to_lit_id_map (om_p, 0x010);
|
||||
break;
|
||||
}
|
||||
case OPCODE_META_TYPE_UNDEFINED:
|
||||
@@ -488,7 +542,7 @@ count_new_literals_in_instr (scopes_tree tree, vm_instr_counter_t instr_pos)
|
||||
case OPCODE_META_TYPE_CALL_SITE_INFO:
|
||||
case OPCODE_META_TYPE_SCOPE_CODE_FLAGS:
|
||||
{
|
||||
insert_uids_to_lit_id_map (om, 0x000);
|
||||
insert_uids_to_lit_id_map (om_p, 0x000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -496,16 +550,23 @@ count_new_literals_in_instr (scopes_tree tree, vm_instr_counter_t instr_pos)
|
||||
}
|
||||
}
|
||||
return (idx_t) (next_uid - current_uid);
|
||||
}
|
||||
} /* count_new_literals_in_instr */
|
||||
|
||||
/* Before filling literal indexes 'hash' table we shall initiate it with number of neccesary literal indexes.
|
||||
Since bytecode is divided into blocks and id of the block is a part of hash key, we shall divide bytecode
|
||||
into blocks and count unique literal indexes used in each block. */
|
||||
/**
|
||||
* Count slots needed for a scope's hash table
|
||||
*
|
||||
* Before filling literal indexes 'hash' table we shall initiate it with number of neccesary literal indexes.
|
||||
* Since bytecode is divided into blocks and id of the block is a part of hash key, we shall divide bytecode
|
||||
* into blocks and count unique literal indexes used in each block.
|
||||
*
|
||||
* @return total number of literals in scope
|
||||
*/
|
||||
size_t
|
||||
scopes_tree_count_literals_in_blocks (scopes_tree tree)
|
||||
scopes_tree_count_literals_in_blocks (scopes_tree tree) /**< scope */
|
||||
{
|
||||
assert_tree (tree);
|
||||
size_t result = 0;
|
||||
|
||||
if (lit_id_to_uid != null_hash)
|
||||
{
|
||||
hash_table_free (lit_id_to_uid);
|
||||
@@ -517,79 +578,99 @@ scopes_tree_count_literals_in_blocks (scopes_tree tree)
|
||||
assert_tree (tree);
|
||||
vm_instr_counter_t instr_pos;
|
||||
bool header = true;
|
||||
for (instr_pos = 0; instr_pos < tree->instrs_num; instr_pos++)
|
||||
for (instr_pos = 0; instr_pos < tree->instrs_count; instr_pos++)
|
||||
{
|
||||
op_meta *om = extract_op_meta (tree, instr_pos);
|
||||
if (om->op.op_idx != VM_OP_VAR_DECL
|
||||
&& om->op.op_idx != VM_OP_META && !header)
|
||||
op_meta *om_p = extract_op_meta (tree->instrs, instr_pos);
|
||||
if (om_p->op.op_idx != VM_OP_META && !header)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (om->op.op_idx == VM_OP_REG_VAR_DECL)
|
||||
if (om_p->op.op_idx == VM_OP_REG_VAR_DECL)
|
||||
{
|
||||
header = false;
|
||||
}
|
||||
result += count_new_literals_in_instr (tree, instr_pos);
|
||||
result += count_new_literals_in_instr (om_p);
|
||||
}
|
||||
|
||||
for (vm_instr_counter_t var_decl_pos = 0; var_decl_pos < tree->var_decls_cout; var_decl_pos++)
|
||||
{
|
||||
op_meta *om_p = extract_op_meta (tree->var_decls, var_decl_pos);
|
||||
result += count_new_literals_in_instr (om_p);
|
||||
}
|
||||
|
||||
for (uint8_t child_id = 0; child_id < tree->t.children_num; child_id++)
|
||||
{
|
||||
result += scopes_tree_count_literals_in_blocks (*(scopes_tree *) linked_list_element (tree->t.children, child_id));
|
||||
}
|
||||
for (; instr_pos < tree->instrs_num; instr_pos++)
|
||||
|
||||
for (; instr_pos < tree->instrs_count; instr_pos++)
|
||||
{
|
||||
result += count_new_literals_in_instr (tree, instr_pos);
|
||||
op_meta *om_p = extract_op_meta (tree->instrs, instr_pos);
|
||||
result += count_new_literals_in_instr (om_p);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
} /* scopes_tree_count_literals_in_blocks */
|
||||
|
||||
/* This function performs functions hoisting.
|
||||
|
||||
Each scope consists of four parts:
|
||||
1) Header with 'use strict' marker and reg_var_decl opcode
|
||||
2) Variable declarations, dumped by the preparser
|
||||
3) Function declarations
|
||||
4) Computational code
|
||||
|
||||
Header and var_decls are dumped first,
|
||||
then we shall recursively dump function declaration,
|
||||
and finally, other instructions.
|
||||
|
||||
For each instructions block (size of block is defined in bytecode-data.h)
|
||||
literal indexes 'hash' table is filled. */
|
||||
/*
|
||||
* This function performs functions hoisting.
|
||||
*
|
||||
* Each scope consists of four parts:
|
||||
* 1) Header with 'use strict' marker and reg_var_decl opcode
|
||||
* 2) Variable declarations, dumped by the preparser
|
||||
* 3) Function declarations
|
||||
* 4) Computational code
|
||||
*
|
||||
* Header and var_decls are dumped first,
|
||||
* then we shall recursively dump function declaration,
|
||||
* and finally, other instructions.
|
||||
*
|
||||
* For each instructions block (size of block is defined in bytecode-data.h)
|
||||
* literal indexes 'hash' table is filled.
|
||||
*/
|
||||
static void
|
||||
merge_subscopes (scopes_tree tree, vm_instr_t *data, lit_id_hash_table *lit_ids)
|
||||
merge_subscopes (scopes_tree tree, /**< scopes tree to merge */
|
||||
vm_instr_t *data_p, /**< instruction array, where the scopes are merged to */
|
||||
lit_id_hash_table *lit_ids_p) /**< literal indexes 'hash' table */
|
||||
{
|
||||
assert_tree (tree);
|
||||
JERRY_ASSERT (data);
|
||||
JERRY_ASSERT (data_p);
|
||||
vm_instr_counter_t instr_pos;
|
||||
bool header = true;
|
||||
for (instr_pos = 0; instr_pos < tree->instrs_num; instr_pos++)
|
||||
for (instr_pos = 0; instr_pos < tree->instrs_count; instr_pos++)
|
||||
{
|
||||
op_meta *om = extract_op_meta (tree, instr_pos);
|
||||
if (om->op.op_idx != VM_OP_VAR_DECL
|
||||
&& om->op.op_idx != VM_OP_META && !header)
|
||||
op_meta *om_p = extract_op_meta (tree->instrs, instr_pos);
|
||||
if (om_p->op.op_idx != VM_OP_VAR_DECL
|
||||
&& om_p->op.op_idx != VM_OP_META && !header)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (om->op.op_idx == VM_OP_REG_VAR_DECL)
|
||||
if (om_p->op.op_idx == VM_OP_REG_VAR_DECL)
|
||||
{
|
||||
header = false;
|
||||
}
|
||||
data[global_oc] = generate_instr (tree, instr_pos, lit_ids);
|
||||
data_p[global_oc] = generate_instr (tree->instrs, instr_pos, lit_ids_p);
|
||||
global_oc++;
|
||||
}
|
||||
|
||||
for (vm_instr_counter_t var_decl_pos = 0; var_decl_pos < tree->var_decls_cout; var_decl_pos++)
|
||||
{
|
||||
data_p[global_oc] = generate_instr (tree->var_decls, var_decl_pos, lit_ids_p);
|
||||
global_oc++;
|
||||
}
|
||||
|
||||
for (uint8_t child_id = 0; child_id < tree->t.children_num; child_id++)
|
||||
{
|
||||
merge_subscopes (*(scopes_tree *) linked_list_element (tree->t.children, child_id),
|
||||
data, lit_ids);
|
||||
data_p, lit_ids_p);
|
||||
}
|
||||
for (; instr_pos < tree->instrs_num; instr_pos++)
|
||||
|
||||
for (; instr_pos < tree->instrs_count; instr_pos++)
|
||||
{
|
||||
data[global_oc] = generate_instr (tree, instr_pos, lit_ids);
|
||||
data_p[global_oc] = generate_instr (tree->instrs, instr_pos, lit_ids_p);
|
||||
global_oc++;
|
||||
}
|
||||
}
|
||||
} /* merge_subscopes */
|
||||
|
||||
/* Postparser.
|
||||
Init literal indexes 'hash' table.
|
||||
@@ -631,12 +712,36 @@ scopes_tree_raw_data (scopes_tree tree, /**< scopes tree to convert to byte-code
|
||||
return instrs;
|
||||
} /* scopes_tree_raw_data */
|
||||
|
||||
/**
|
||||
* Set up a flag, indicating that scope should be executed in strict mode
|
||||
*/
|
||||
void
|
||||
scopes_tree_set_strict_mode (scopes_tree tree, bool strict_mode)
|
||||
scopes_tree_set_strict_mode (scopes_tree tree, /**< scope */
|
||||
bool strict_mode) /**< value of the strict mode flag */
|
||||
{
|
||||
assert_tree (tree);
|
||||
tree->strict_mode = strict_mode ? 1 : 0;
|
||||
}
|
||||
tree->strict_mode = strict_mode;
|
||||
} /* scopes_tree_set_strict_mode */
|
||||
|
||||
/**
|
||||
* Set up a flag, indicating that "arguments" is used inside a scope
|
||||
*/
|
||||
void
|
||||
scopes_tree_set_arguments_used (scopes_tree tree) /**< scope */
|
||||
{
|
||||
assert_tree (tree);
|
||||
tree->ref_arguments = true;
|
||||
} /* merge_subscopes */
|
||||
|
||||
/**
|
||||
* Set up a flag, indicating that "eval" is used inside a scope
|
||||
*/
|
||||
void
|
||||
scopes_tree_set_eval_used (scopes_tree tree) /**< scope */
|
||||
{
|
||||
assert_tree (tree);
|
||||
tree->ref_eval = true;
|
||||
} /* scopes_tree_set_eval_used */
|
||||
|
||||
bool
|
||||
scopes_tree_strict_mode (scopes_tree tree)
|
||||
@@ -645,8 +750,13 @@ scopes_tree_strict_mode (scopes_tree tree)
|
||||
return (bool) tree->strict_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a scope
|
||||
*
|
||||
* @return initialized scope
|
||||
*/
|
||||
scopes_tree
|
||||
scopes_tree_init (scopes_tree parent)
|
||||
scopes_tree_init (scopes_tree parent) /**< parent scope */
|
||||
{
|
||||
scopes_tree tree = (scopes_tree) jsp_mm_alloc (sizeof (scopes_tree_int));
|
||||
memset (tree, 0, sizeof (scopes_tree_int));
|
||||
@@ -664,11 +774,15 @@ scopes_tree_init (scopes_tree parent)
|
||||
JERRY_ASSERT (*(scopes_tree *) added == tree);
|
||||
parent->t.children_num++;
|
||||
}
|
||||
tree->instrs_num = 0;
|
||||
tree->strict_mode = 0;
|
||||
tree->instrs_count = 0;
|
||||
tree->strict_mode = false;
|
||||
tree->ref_eval = false;
|
||||
tree->ref_arguments = false;
|
||||
tree->instrs = linked_list_init (sizeof (op_meta));
|
||||
tree->var_decls_cout = 0;
|
||||
tree->var_decls = linked_list_init (sizeof (op_meta));
|
||||
return tree;
|
||||
}
|
||||
} /* scopes_tree_init */
|
||||
|
||||
void
|
||||
scopes_tree_free (scopes_tree tree)
|
||||
@@ -683,5 +797,6 @@ scopes_tree_free (scopes_tree tree)
|
||||
linked_list_free (tree->t.children);
|
||||
}
|
||||
linked_list_free (tree->instrs);
|
||||
linked_list_free (tree->var_decls);
|
||||
jsp_mm_free (tree);
|
||||
}
|
||||
|
||||
@@ -39,12 +39,19 @@ typedef struct tree_header
|
||||
uint8_t children_num;
|
||||
} tree_header;
|
||||
|
||||
/**
|
||||
* Structure for holding scope information during parsing
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
tree_header t;
|
||||
linked_list instrs;
|
||||
vm_instr_counter_t instrs_num;
|
||||
unsigned strict_mode:1;
|
||||
tree_header t; /**< header */
|
||||
linked_list instrs; /**< instructions */
|
||||
vm_instr_counter_t instrs_count; /**< count of instructions */
|
||||
linked_list var_decls; /**< instructions for variable declarations */
|
||||
uint8_t var_decls_cout; /**< number of instructions for variable declarations */
|
||||
bool strict_mode: 1; /**< flag, indicating that scope's code should be executed in strict mode */
|
||||
bool ref_arguments: 1; /**< flag, indicating that "arguments" variable is used inside the scope */
|
||||
bool ref_eval: 1; /**< flag, indicating that "eval" is used inside the scope */
|
||||
} scopes_tree_int;
|
||||
|
||||
typedef scopes_tree_int * scopes_tree;
|
||||
@@ -52,14 +59,19 @@ typedef scopes_tree_int * scopes_tree;
|
||||
scopes_tree scopes_tree_init (scopes_tree);
|
||||
void scopes_tree_free (scopes_tree);
|
||||
vm_instr_counter_t scopes_tree_instrs_num (scopes_tree);
|
||||
vm_instr_counter_t scopes_tree_var_decls_num (scopes_tree);
|
||||
void scopes_tree_add_op_meta (scopes_tree, op_meta);
|
||||
void scopes_tree_add_var_decl (scopes_tree, op_meta);
|
||||
void scopes_tree_set_op_meta (scopes_tree, vm_instr_counter_t, op_meta);
|
||||
void scopes_tree_set_instrs_num (scopes_tree, vm_instr_counter_t);
|
||||
op_meta scopes_tree_op_meta (scopes_tree, vm_instr_counter_t);
|
||||
op_meta scopes_tree_var_decl (scopes_tree, vm_instr_counter_t);
|
||||
size_t scopes_tree_count_literals_in_blocks (scopes_tree);
|
||||
vm_instr_counter_t scopes_tree_count_instructions (scopes_tree);
|
||||
vm_instr_t *scopes_tree_raw_data (scopes_tree, uint8_t *, size_t, lit_id_hash_table *);
|
||||
void scopes_tree_set_strict_mode (scopes_tree, bool);
|
||||
void scopes_tree_set_arguments_used (scopes_tree);
|
||||
void scopes_tree_set_eval_used (scopes_tree);
|
||||
bool scopes_tree_strict_mode (scopes_tree);
|
||||
|
||||
#endif /* SCOPES_TREE_H */
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "bytecode-data.h"
|
||||
#include "pretty-printer.h"
|
||||
#include "array-list.h"
|
||||
#include "scopes-tree.h"
|
||||
|
||||
static bytecode_data_t bytecode_data;
|
||||
static scopes_tree current_scope;
|
||||
@@ -33,6 +34,18 @@ serializer_get_op_meta (vm_instr_counter_t oc)
|
||||
return scopes_tree_op_meta (current_scope, oc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get variable declaration of the current scope
|
||||
*
|
||||
* @return variable declaration instruction
|
||||
*/
|
||||
op_meta
|
||||
serializer_get_var_decl (vm_instr_counter_t oc) /**< index of variable declaration */
|
||||
{
|
||||
JERRY_ASSERT (current_scope);
|
||||
return scopes_tree_var_decl (current_scope, oc);
|
||||
} /* serializer_get_var_decl */
|
||||
|
||||
/**
|
||||
* Get byte-code instruction from current scope, or specified byte-code array
|
||||
*
|
||||
@@ -102,28 +115,33 @@ serializer_dump_subscope (scopes_tree tree) /**< scope to dump */
|
||||
JERRY_ASSERT (tree != NULL);
|
||||
vm_instr_counter_t instr_pos;
|
||||
bool header = true;
|
||||
for (instr_pos = 0; instr_pos < tree->instrs_num; instr_pos++)
|
||||
for (instr_pos = 0; instr_pos < tree->instrs_count; instr_pos++)
|
||||
{
|
||||
op_meta *om = (op_meta *) linked_list_element (tree->instrs, instr_pos);
|
||||
if (om->op.op_idx != VM_OP_VAR_DECL
|
||||
&& om->op.op_idx != VM_OP_META && !header)
|
||||
op_meta *om_p = (op_meta *) linked_list_element (tree->instrs, instr_pos);
|
||||
if (om_p->op.op_idx != VM_OP_VAR_DECL
|
||||
&& om_p->op.op_idx != VM_OP_META && !header)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (om->op.op_idx == VM_OP_REG_VAR_DECL)
|
||||
if (om_p->op.op_idx == VM_OP_REG_VAR_DECL)
|
||||
{
|
||||
header = false;
|
||||
}
|
||||
scopes_tree_add_op_meta (current_scope, *om);
|
||||
scopes_tree_add_op_meta (current_scope, *om_p);
|
||||
}
|
||||
for (vm_instr_counter_t var_decl_pos = 0; var_decl_pos < tree->var_decls_cout; var_decl_pos++)
|
||||
{
|
||||
op_meta *om_p = (op_meta *) linked_list_element (tree->var_decls, var_decl_pos);
|
||||
scopes_tree_add_op_meta (current_scope, *om_p);
|
||||
}
|
||||
for (uint8_t child_id = 0; child_id < tree->t.children_num; child_id++)
|
||||
{
|
||||
serializer_dump_subscope (*(scopes_tree *) linked_list_element (tree->t.children, child_id));
|
||||
}
|
||||
for (; instr_pos < tree->instrs_num; instr_pos++)
|
||||
for (; instr_pos < tree->instrs_count; instr_pos++)
|
||||
{
|
||||
op_meta *om = (op_meta *) linked_list_element (tree->instrs, instr_pos);
|
||||
scopes_tree_add_op_meta (current_scope, *om);
|
||||
op_meta *om_p = (op_meta *) linked_list_element (tree->instrs, instr_pos);
|
||||
scopes_tree_add_op_meta (current_scope, *om_p);
|
||||
}
|
||||
} /* serializer_dump_subscope */
|
||||
|
||||
@@ -180,12 +198,34 @@ serializer_dump_op_meta (op_meta op)
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump variable declaration into the current scope
|
||||
*/
|
||||
void
|
||||
serializer_dump_var_decl (op_meta op) /**< variable declaration instruction */
|
||||
{
|
||||
JERRY_ASSERT (scopes_tree_instrs_num (current_scope) + current_scope->var_decls_cout < MAX_OPCODES);
|
||||
|
||||
scopes_tree_add_var_decl (current_scope, op);
|
||||
} /* serializer_dump_var_decl */
|
||||
|
||||
vm_instr_counter_t
|
||||
serializer_get_current_instr_counter (void)
|
||||
{
|
||||
return scopes_tree_instrs_num (current_scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of variable declarations in the current scope
|
||||
*
|
||||
* @return count of variable declarations
|
||||
*/
|
||||
vm_instr_counter_t
|
||||
serializer_get_current_var_decls_counter (void)
|
||||
{
|
||||
return scopes_tree_var_decls_num (current_scope);
|
||||
} /* serializer_get_current_var_decls_counter */
|
||||
|
||||
vm_instr_counter_t
|
||||
serializer_count_instrs_in_subscopes (void)
|
||||
{
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
void serializer_init ();
|
||||
void serializer_set_show_instrs (bool show_instrs);
|
||||
op_meta serializer_get_op_meta (vm_instr_counter_t);
|
||||
op_meta serializer_get_var_decl (vm_instr_counter_t);
|
||||
vm_instr_t serializer_get_instr (const vm_instr_t*, vm_instr_counter_t);
|
||||
lit_cpointer_t serializer_get_literal_cp_by_uid (uint8_t, const vm_instr_t*, vm_instr_counter_t);
|
||||
void serializer_set_strings_buffer (const ecma_char_t *);
|
||||
@@ -32,7 +33,9 @@ void serializer_set_scope (scopes_tree);
|
||||
void serializer_dump_subscope (scopes_tree);
|
||||
const vm_instr_t *serializer_merge_scopes_into_bytecode (void);
|
||||
void serializer_dump_op_meta (op_meta);
|
||||
void serializer_dump_var_decl (op_meta);
|
||||
vm_instr_counter_t serializer_get_current_instr_counter (void);
|
||||
vm_instr_counter_t serializer_get_current_var_decls_counter (void);
|
||||
vm_instr_counter_t serializer_count_instrs_in_subscopes (void);
|
||||
void serializer_set_writing_position (vm_instr_counter_t);
|
||||
void serializer_rewrite_op_meta (vm_instr_counter_t, op_meta);
|
||||
|
||||
@@ -1810,6 +1810,7 @@ vm_read_instr_counter_from_meta (opcode_meta_type expected_type, /**< expected t
|
||||
vm_instr_t getop_##opcode_name (void) \
|
||||
{ \
|
||||
vm_instr_t instr; \
|
||||
memset (&instr, 0, sizeof(instr)); \
|
||||
instr.op_idx = VM_OP_##opcode_name_uppercase; \
|
||||
return instr; \
|
||||
}
|
||||
@@ -1817,6 +1818,7 @@ vm_read_instr_counter_from_meta (opcode_meta_type expected_type, /**< expected t
|
||||
vm_instr_t getop_##opcode_name (idx_t arg1_v) \
|
||||
{ \
|
||||
vm_instr_t instr; \
|
||||
memset (&instr, 0, sizeof(instr)); \
|
||||
instr.op_idx = VM_OP_##opcode_name_uppercase; \
|
||||
instr.data.opcode_name.arg1 = arg1_v; \
|
||||
return instr; \
|
||||
@@ -1825,6 +1827,7 @@ vm_read_instr_counter_from_meta (opcode_meta_type expected_type, /**< expected t
|
||||
vm_instr_t getop_##opcode_name (idx_t arg1_v, idx_t arg2_v) \
|
||||
{ \
|
||||
vm_instr_t instr; \
|
||||
memset (&instr, 0, sizeof(instr)); \
|
||||
instr.op_idx = VM_OP_##opcode_name_uppercase; \
|
||||
instr.data.opcode_name.arg1 = arg1_v; \
|
||||
instr.data.opcode_name.arg2 = arg2_v; \
|
||||
|
||||
Reference in New Issue
Block a user