Create function variables using the data produced by the pre-scanner. (#3199)

The pre-scanner now is able to track all variable declarations and produces a compressed
stream which store this data for each function and catch block. When a function or
catch block is parsed, this information is decoded and the appropriate variables are
created. Furthermore a stack scope is created which contains the currently available
local variables and their register or literal index.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2019-10-17 15:20:04 +02:00
committed by GitHub
parent fd1f7eab9f
commit 7df87b7778
20 changed files with 2098 additions and 1219 deletions
+54 -61
View File
@@ -181,6 +181,8 @@ typedef enum
typedef struct
{
parser_try_block_type_t type; /**< current block type */
uint16_t scope_stack_top; /**< current top of scope stack */
uint16_t scope_stack_reg_top; /**< current top register of scope stack */
parser_branch_t branch; /**< branch to the end of the current block */
} parser_try_statement_t;
@@ -310,8 +312,6 @@ parser_parse_var_statement (parser_context_t *context_p) /**< context */
parser_line_counter_t ident_line_counter = context_p->token.line;
#endif /* ENABLED (JERRY_DEBUGGER) || ENABLED (JERRY_LINE_INFO) */
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_VAR;
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
if (context_p->status_flags & PARSER_MODULE_STORE_IDENT)
{
@@ -362,9 +362,7 @@ static void
parser_parse_function_statement (parser_context_t *context_p) /**< context */
{
uint32_t status_flags;
lexer_literal_t *name_p;
lexer_literal_t *literal_p;
uint8_t no_reg_store;
JERRY_ASSERT (context_p->token.type == LEXER_KEYW_FUNCTION);
@@ -373,7 +371,7 @@ parser_parse_function_statement (parser_context_t *context_p) /**< context */
parser_line_counter_t debugger_column = context_p->token.column;
#endif /* ENABLED (JERRY_DEBUGGER) */
lexer_expect_identifier (context_p, LEXER_IDENT_LITERAL);
lexer_expect_identifier (context_p, LEXER_NEW_IDENT_LITERAL);
JERRY_ASSERT (context_p->token.type == LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL);
@@ -382,8 +380,6 @@ parser_parse_function_statement (parser_context_t *context_p) /**< context */
context_p->status_flags |= PARSER_ARGUMENTS_NOT_NEEDED;
}
name_p = context_p->lit_object.literal_p;
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
if (context_p->status_flags & PARSER_MODULE_STORE_IDENT)
{
@@ -403,6 +399,7 @@ parser_parse_function_statement (parser_context_t *context_p) /**< context */
#if ENABLED (JERRY_DEBUGGER)
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
{
lexer_literal_t *name_p = context_p->lit_object.literal_p;
jerry_debugger_send_string (JERRY_DEBUGGER_FUNCTION_NAME,
JERRY_DEBUGGER_NO_SUBTYPE,
name_p->u.char_p,
@@ -414,55 +411,35 @@ parser_parse_function_statement (parser_context_t *context_p) /**< context */
}
#endif /* ENABLED (JERRY_DEBUGGER) */
if (name_p->status_flags & LEXER_FLAG_INITIALIZED)
JERRY_ASSERT (context_p->scope_stack_top >= 2);
parser_scope_stack *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top - 2;
uint16_t literal_index = context_p->lit_object.index;
while (literal_index != scope_stack_p->map_from)
{
if (!(name_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT))
{
/* Overwrite the previous initialization. */
ecma_compiled_code_t *compiled_code_p;
scope_stack_p--;
literal_p = PARSER_GET_LITERAL ((size_t) (context_p->lit_object.index + 1));
JERRY_ASSERT (literal_p->type == LEXER_FUNCTION_LITERAL
&& literal_p->status_flags == 0);
compiled_code_p = parser_parse_function (context_p, status_flags);
util_free_literal (literal_p);
literal_p->u.bytecode_p = compiled_code_p;
lexer_next_token (context_p);
return;
}
}
else if (context_p->lit_object.index + 1 == context_p->literal_count)
{
/* The most common case: the literal is the last literal. */
name_p->status_flags |= LEXER_FLAG_VAR | LEXER_FLAG_INITIALIZED;
lexer_construct_function_object (context_p, status_flags);
lexer_next_token (context_p);
return;
JERRY_ASSERT (scope_stack_p >= context_p->scope_stack_p);
}
/* Clone the literal at the end. */
if (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS)
JERRY_ASSERT (scope_stack_p[1].map_from == PARSER_SCOPE_STACK_FUNC);
literal_p = PARSER_GET_LITERAL ((size_t) scope_stack_p[1].map_to);
JERRY_ASSERT ((literal_p->type == LEXER_UNUSED_LITERAL || literal_p->type == LEXER_FUNCTION_LITERAL)
&& literal_p->status_flags == 0);
ecma_compiled_code_t *compiled_code_p = parser_parse_function (context_p, status_flags);
if (literal_p->type == LEXER_FUNCTION_LITERAL)
{
parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
ecma_bytecode_deref (literal_p->u.bytecode_p);
}
literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool);
*literal_p = *name_p;
no_reg_store = name_p->status_flags & (LEXER_FLAG_NO_REG_STORE | LEXER_FLAG_SOURCE_PTR);
literal_p->status_flags = LEXER_FLAG_VAR | LEXER_FLAG_INITIALIZED | no_reg_store;
literal_p->u.bytecode_p = compiled_code_p;
literal_p->type = LEXER_FUNCTION_LITERAL;
name_p->type = LEXER_UNUSED_LITERAL;
name_p->status_flags &= LEXER_FLAG_FUNCTION_ARGUMENT | LEXER_FLAG_SOURCE_PTR;
/* Byte code references to this literal are
* redirected to the newly allocated literal. */
name_p->prop.index = context_p->literal_count;
context_p->literal_count++;
lexer_construct_function_object (context_p, status_flags);
lexer_next_token (context_p);
} /* parser_parse_function_statement */
@@ -967,8 +944,6 @@ parser_parse_for_statement_start (parser_context_t *context_p) /**< context */
JERRY_ASSERT (context_p->token.type == LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL);
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_VAR;
literal_index = context_p->lit_object.index;
lexer_next_token (context_p);
@@ -1400,6 +1375,9 @@ parser_parse_try_statement_end (parser_context_t *context_p) /**< context */
if (try_statement.type == parser_catch_block)
{
context_p->scope_stack_top = try_statement.scope_stack_top;
context_p->scope_stack_reg_top = try_statement.scope_stack_reg_top;
if (context_p->token.type != LEXER_KEYW_FINALLY)
{
parser_flush_cbc (context_p);
@@ -1410,6 +1388,7 @@ parser_parse_try_statement_end (parser_context_t *context_p) /**< context */
parser_emit_cbc (context_p, CBC_CONTEXT_END);
parser_flush_cbc (context_p);
try_statement.type = parser_finally_block;
}
}
@@ -1439,12 +1418,34 @@ parser_parse_try_statement_end (parser_context_t *context_p) /**< context */
parser_raise_error (context_p, PARSER_ERR_LEFT_PAREN_EXPECTED);
}
try_statement.type = parser_catch_block;
parser_emit_cbc_ext_forward_branch (context_p,
CBC_EXT_CATCH,
&try_statement.branch);
try_statement.scope_stack_top = context_p->scope_stack_top;
try_statement.scope_stack_reg_top = context_p->scope_stack_reg_top;
#ifndef JERRY_NDEBUG
bool block_found = false;
#endif /* !JERRY_NDEBUG */
if (context_p->next_scanner_info_p->source_p == context_p->source_p
&& context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK)
{
#ifndef JERRY_NDEBUG
block_found = true;
#endif /* !JERRY_NDEBUG */
scanner_create_variables (context_p, sizeof (scanner_info_t));
}
lexer_expect_identifier (context_p, LEXER_IDENT_LITERAL);
JERRY_ASSERT (context_p->token.type == LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL);
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_NO_REG_STORE;
context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED;
#ifndef JERRY_NDEBUG
JERRY_ASSERT (block_found);
#endif /* !JERRY_NDEBUG */
literal_index = context_p->lit_object.index;
@@ -1462,11 +1463,6 @@ parser_parse_try_statement_end (parser_context_t *context_p) /**< context */
parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED);
}
try_statement.type = parser_catch_block;
parser_emit_cbc_ext_forward_branch (context_p,
CBC_EXT_CATCH,
&try_statement.branch);
parser_emit_cbc_literal (context_p, CBC_ASSIGN_SET_IDENT, literal_index);
parser_flush_cbc (context_p);
}
@@ -1960,10 +1956,7 @@ parser_parse_export_statement (parser_context_t *context_p) /**< context */
scanner_set_location (context_p, &location);
/* 15.2.3.5 Use the synthetic name '*default*' as the identifier. */
lexer_construct_literal_object (context_p,
(lexer_lit_location_t *) &lexer_default_literal,
lexer_default_literal.type);
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_VAR;
lexer_construct_literal_object (context_p, &lexer_default_literal, lexer_default_literal.type);
context_p->token.lit_location.type = LEXER_IDENT_LITERAL;
parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL);