Delay the variable construction in the function body. (#3289)

Local variables inside the function body should be constructed after the
parameters are initialized. Furthermore arguments should be available
during parameter initialization.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2019-11-08 12:18:23 +01:00
committed by Dániel Bátyai
parent 923fd128b5
commit e1fc90db0e
7 changed files with 223 additions and 92 deletions
@@ -320,6 +320,14 @@ typedef struct
/** /**
* This item represents a function literal in the scope stack. * This item represents a function literal in the scope stack.
*
* When map_from == PARSER_SCOPE_STACK_FUNC:
* map_to represents the literal reserved for a function literal
* Note: the name of the function is the previous value in the scope stack
*
* When map_to == PARSER_SCOPE_STACK_FUNC:
* map_from represents the name of the function literal following this literal
* Note: only the name, the real mapping is somewhere else in the scope stack
*/ */
#define PARSER_SCOPE_STACK_FUNC 0xffff #define PARSER_SCOPE_STACK_FUNC 0xffff
@@ -626,6 +634,7 @@ void parser_parse_super_class_context_end (parser_context_t *context_p);
void scanner_release_next (parser_context_t *context_p, size_t size); void scanner_release_next (parser_context_t *context_p, size_t size);
void scanner_set_active (parser_context_t *context_p); void scanner_set_active (parser_context_t *context_p);
void scanner_revert_active (parser_context_t *context_p);
void scanner_release_active (parser_context_t *context_p, size_t size); void scanner_release_active (parser_context_t *context_p, size_t size);
void scanner_release_switch_cases (scanner_case_info_t *case_p); void scanner_release_switch_cases (scanner_case_info_t *case_p);
void scanner_seek (parser_context_t *context_p); void scanner_seek (parser_context_t *context_p);
+7 -1
View File
@@ -1617,13 +1617,16 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */
#endif /* ENABLED (JERRY_ES2015) */ #endif /* ENABLED (JERRY_ES2015) */
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION); JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS);
if (context_p->token.type == end_type) if (context_p->token.type == end_type)
{ {
scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS);
return; return;
} }
scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_ARGS);
scanner_set_active (context_p);
while (true) while (true)
{ {
#if ENABLED (JERRY_ES2015) #if ENABLED (JERRY_ES2015)
@@ -1730,6 +1733,9 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */
parser_raise_error (context_p, error); parser_raise_error (context_p, error);
} }
scanner_revert_active (context_p);
scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_BODY);
} /* parser_parse_function_arguments */ } /* parser_parse_function_arguments */
/** /**
+137 -75
View File
@@ -258,6 +258,19 @@ scanner_set_active (parser_context_t *context_p) /**< context */
context_p->active_scanner_info_p = scanner_info_p; context_p->active_scanner_info_p = scanner_info_p;
} /* scanner_set_active */ } /* scanner_set_active */
/**
* Set the next scanner info to the active scanner info.
*/
inline void JERRY_ATTR_ALWAYS_INLINE
scanner_revert_active (parser_context_t *context_p) /**< context */
{
scanner_info_t *scanner_info_p = context_p->active_scanner_info_p;
context_p->active_scanner_info_p = scanner_info_p->next_p;
scanner_info_p->next_p = context_p->next_scanner_info_p;
context_p->next_scanner_info_p = scanner_info_p;
} /* scanner_revert_active */
/** /**
* Release the active scanner info. * Release the active scanner info.
*/ */
@@ -394,7 +407,7 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
lexer_lit_location_t *literal_p; lexer_lit_location_t *literal_p;
bool is_function = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION) != 0; bool is_function = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION) != 0;
bool no_reg = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_REG) != 0; bool no_reg = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_REG) != 0;
bool search_arguments = is_function && (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) == 0; bool search_arguments = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) == 0;
bool arguments_required = (no_reg && search_arguments); bool arguments_required = (no_reg && search_arguments);
#if ENABLED (JERRY_ES2015) #if ENABLED (JERRY_ES2015)
bool no_var_reg = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_VAR_REG) != 0; bool no_var_reg = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_VAR_REG) != 0;
@@ -545,7 +558,7 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
if (is_function || (compressed_size > 1)) if (is_function || (compressed_size > 1))
{ {
compressed_size += is_function ? sizeof (scanner_function_info_t) : sizeof (scanner_info_t); compressed_size += sizeof (scanner_info_t);
scanner_info_t *info_p; scanner_info_t *info_p;
@@ -564,14 +577,12 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
no_declarations = PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK; no_declarations = PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK;
} }
uint8_t *data_p = (uint8_t *) info_p; uint8_t *data_p = (uint8_t *) (info_p + 1);
if (is_function) if (is_function)
{ {
info_p->type = SCANNER_TYPE_FUNCTION; info_p->type = SCANNER_TYPE_FUNCTION;
data_p += sizeof (scanner_function_info_t);
scanner_function_info_t *function_info_p = (scanner_function_info_t *) info_p;
uint8_t status_flags = 0; uint8_t status_flags = 0;
if (arguments_required) if (arguments_required)
@@ -584,13 +595,12 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
} }
} }
function_info_p->info.u8_arg = status_flags; info_p->u8_arg = status_flags;
function_info_p->info.u16_arg = (uint16_t) no_declarations; info_p->u16_arg = (uint16_t) no_declarations;
} }
else else
{ {
info_p->type = SCANNER_TYPE_BLOCK; info_p->type = SCANNER_TYPE_BLOCK;
data_p += sizeof (scanner_info_t);
JERRY_ASSERT (prev_literal_pool_p != NULL); JERRY_ASSERT (prev_literal_pool_p != NULL);
} }
@@ -730,6 +740,7 @@ scanner_filter_arguments (parser_context_t *context_p, /**< context */
parser_list_iterator_t literal_iterator; parser_list_iterator_t literal_iterator;
lexer_lit_location_t *literal_p; lexer_lit_location_t *literal_p;
bool no_reg = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_REG) != 0; bool no_reg = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_REG) != 0;
bool has_arguments = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) == 0;
if (no_reg && prev_literal_pool_p != NULL) if (no_reg && prev_literal_pool_p != NULL)
{ {
@@ -774,7 +785,10 @@ scanner_filter_arguments (parser_context_t *context_p, /**< context */
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
{ {
if (literal_p->type & SCANNER_LITERAL_IS_ARG) if ((literal_p->type & SCANNER_LITERAL_IS_ARG)
|| (has_arguments
&& literal_p->length == 9
&& lexer_compare_identifiers (literal_p->char_p, (const uint8_t *) "arguments", 9)))
{ {
lexer_lit_location_t *new_literal_p; lexer_lit_location_t *new_literal_p;
new_literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &new_literal_pool_p->literal_pool); new_literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &new_literal_pool_p->literal_pool);
@@ -1189,10 +1203,6 @@ scanner_cleanup (parser_context_t *context_p) /**< context */
continue; continue;
} }
case SCANNER_TYPE_FUNCTION: case SCANNER_TYPE_FUNCTION:
{
size = scanner_get_stream_size (scanner_info_p, sizeof (scanner_function_info_t));
break;
}
case SCANNER_TYPE_BLOCK: case SCANNER_TYPE_BLOCK:
{ {
size = scanner_get_stream_size (scanner_info_p, sizeof (scanner_info_t)); size = scanner_get_stream_size (scanner_info_p, sizeof (scanner_info_t));
@@ -1396,7 +1406,7 @@ bool
scanner_is_global_context_needed (parser_context_t *context_p) /**< context */ scanner_is_global_context_needed (parser_context_t *context_p) /**< context */
{ {
scanner_info_t *info_p = context_p->next_scanner_info_p; scanner_info_t *info_p = context_p->next_scanner_info_p;
const uint8_t *data_p = ((const uint8_t *) info_p) + sizeof (scanner_function_info_t); const uint8_t *data_p = (const uint8_t *) (info_p + 1);
uint32_t scope_stack_reg_top = 0; uint32_t scope_stack_reg_top = 0;
JERRY_ASSERT (info_p->type == SCANNER_TYPE_FUNCTION); JERRY_ASSERT (info_p->type == SCANNER_TYPE_FUNCTION);
@@ -1467,6 +1477,26 @@ const lexer_lit_location_t lexer_arguments_literal =
(const uint8_t *) "arguments", 9, LEXER_IDENT_LITERAL, false (const uint8_t *) "arguments", 9, LEXER_IDENT_LITERAL, false
}; };
/**
* Create an unused literal.
*/
static void
scanner_create_unused_literal (parser_context_t *context_p, /**< context */
uint8_t status_flags) /**< initial status flags */
{
if (JERRY_UNLIKELY (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS))
{
parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
}
lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool);
literal_p->type = LEXER_UNUSED_LITERAL;
literal_p->status_flags = status_flags;
context_p->literal_count++;
} /* scanner_create_unused_literal */
/** /**
* Create and/or initialize var/let/const/function/etc. variables. * Create and/or initialize var/let/const/function/etc. variables.
*/ */
@@ -1475,15 +1505,19 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
uint32_t option_flags) /**< combination of scanner_create_variables_flags_t bits */ uint32_t option_flags) /**< combination of scanner_create_variables_flags_t bits */
{ {
scanner_info_t *info_p = context_p->next_scanner_info_p; scanner_info_t *info_p = context_p->next_scanner_info_p;
const uint8_t *data_p; const uint8_t *next_data_p = (const uint8_t *) (info_p + 1);
uint8_t info_type = info_p->type; uint8_t info_type = info_p->type;
lexer_lit_location_t literal; lexer_lit_location_t literal;
parser_scope_stack *scope_stack_p; parser_scope_stack *scope_stack_p;
parser_scope_stack *scope_stack_end_p; parser_scope_stack *scope_stack_end_p;
JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION || info_type == SCANNER_TYPE_BLOCK); JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION || info_type == SCANNER_TYPE_BLOCK);
JERRY_ASSERT (!(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS)
|| !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY));
JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION
|| !(option_flags & (SCANNER_CREATE_VARS_IS_FUNCTION_ARGS | SCANNER_CREATE_VARS_IS_FUNCTION_BODY)));
if (info_type == SCANNER_TYPE_FUNCTION) if (info_type == SCANNER_TYPE_FUNCTION && !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY))
{ {
JERRY_ASSERT (context_p->scope_stack_p == NULL); JERRY_ASSERT (context_p->scope_stack_p == NULL);
@@ -1492,59 +1526,55 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
if (stack_size == 0) if (stack_size == 0)
{ {
scanner_release_next (context_p, sizeof (scanner_function_info_t) + 1); if (!(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS))
{
scanner_release_next (context_p, sizeof (scanner_info_t) + 1);
}
return; return;
} }
scope_stack_p = (parser_scope_stack *) parser_malloc (context_p, stack_size); scope_stack_p = (parser_scope_stack *) parser_malloc (context_p, stack_size);
context_p->scope_stack_p = scope_stack_p; context_p->scope_stack_p = scope_stack_p;
scope_stack_end_p = scope_stack_p + context_p->scope_stack_size; scope_stack_end_p = scope_stack_p + context_p->scope_stack_size;
data_p = ((const uint8_t *) info_p) + sizeof (scanner_function_info_t);
} }
else else
{ {
JERRY_ASSERT (context_p->scope_stack_p != NULL); JERRY_ASSERT (context_p->scope_stack_p != NULL);
scope_stack_p = context_p->scope_stack_p; scope_stack_p = context_p->scope_stack_p;
scope_stack_end_p = scope_stack_p + context_p->scope_stack_size; scope_stack_end_p = scope_stack_p + context_p->scope_stack_size;
scope_stack_p += context_p->scope_stack_top; scope_stack_p += context_p->scope_stack_top;
data_p = ((const uint8_t *) info_p) + sizeof (scanner_info_t);
} }
uint32_t scope_stack_reg_top = context_p->scope_stack_reg_top; uint32_t scope_stack_reg_top = context_p->scope_stack_reg_top;
literal.char_p = info_p->source_p - 1; literal.char_p = info_p->source_p - 1;
while (data_p[0] != SCANNER_STREAM_TYPE_END) while (next_data_p[0] != SCANNER_STREAM_TYPE_END)
{ {
uint32_t type = data_p[0] & SCANNER_STREAM_TYPE_MASK; uint32_t type = next_data_p[0] & SCANNER_STREAM_TYPE_MASK;
const uint8_t *data_p = next_data_p;
if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p)) JERRY_ASSERT ((option_flags & (SCANNER_CREATE_VARS_IS_FUNCTION_BODY | SCANNER_CREATE_VARS_IS_FUNCTION_ARGS))
{ || (type != SCANNER_STREAM_TYPE_HOLE
JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK); && type != SCANNER_STREAM_TYPE_ARG
parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED); && type != SCANNER_STREAM_TYPE_ARG_FUNC));
} #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
JERRY_ASSERT (type != SCANNER_STREAM_TYPE_IMPORT || (data_p[0] & SCANNER_STREAM_NO_REG));
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
if (type == SCANNER_STREAM_TYPE_HOLE) if (type == SCANNER_STREAM_TYPE_HOLE)
{ {
data_p++; next_data_p++;
JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION); if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)
{
continue;
}
if (info_p->u8_arg & SCANNER_FUNCTION_ARGUMENTS_NEEDED) if (info_p->u8_arg & SCANNER_FUNCTION_ARGUMENTS_NEEDED)
{ {
if (JERRY_UNLIKELY (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS)) scanner_create_unused_literal (context_p, LEXER_FLAG_FUNCTION_ARGUMENT);
{
parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
}
lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool);
literal_p->type = LEXER_UNUSED_LITERAL;
literal_p->status_flags = LEXER_FLAG_FUNCTION_ARGUMENT;
context_p->literal_count++;
} }
if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS) if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
@@ -1554,19 +1584,17 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
continue; continue;
} }
size_t length;
if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF)) if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF))
{ {
if (data_p[2] != 0) if (data_p[2] != 0)
{ {
literal.char_p += data_p[2]; literal.char_p += data_p[2];
length = 2 + 1; next_data_p += 2 + 1;
} }
else else
{ {
memcpy (&literal.char_p, data_p + 2 + 1, sizeof (const uint8_t *)); memcpy (&literal.char_p, data_p + 2 + 1, sizeof (const uint8_t *));
length = 2 + 1 + sizeof (const uint8_t *); next_data_p += 2 + 1 + sizeof (const uint8_t *);
} }
} }
else else
@@ -1579,7 +1607,22 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
} }
literal.char_p += diff; literal.char_p += diff;
length = 2 + 2; next_data_p += 2 + 2;
}
if (type == SCANNER_STREAM_TYPE_ARG)
{
if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)
{
literal.char_p += data_p[1];
continue;
}
}
else if ((option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS)
&& type != SCANNER_STREAM_TYPE_ARG_FUNC)
{
/* Function arguments must come first. */
break;
} }
literal.length = data_p[1]; literal.length = data_p[1];
@@ -1587,16 +1630,39 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
literal.has_escape = (data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? 1 : 0; literal.has_escape = (data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? 1 : 0;
lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL); lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL);
literal.char_p += data_p[1];
if (type == SCANNER_STREAM_TYPE_ARG_FUNC && (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY))
{
JERRY_ASSERT (scope_stack_p >= context_p->scope_stack_p + 2);
parser_scope_stack *function_map_p = scope_stack_p - 2;
uint16_t literal_index = context_p->lit_object.index;
while (literal_index != function_map_p->map_from)
{
function_map_p--;
JERRY_ASSERT (function_map_p >= context_p->scope_stack_p);
}
JERRY_ASSERT (function_map_p[1].map_from == PARSER_SCOPE_STACK_FUNC);
parser_emit_cbc_literal_value (context_p, CBC_SET_VAR_FUNC, function_map_p[1].map_to, function_map_p[0].map_to);
continue;
}
if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p))
{
JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK);
parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED);
}
scope_stack_p->map_from = context_p->lit_object.index; scope_stack_p->map_from = context_p->lit_object.index;
uint16_t map_to; uint16_t map_to;
uint16_t func_init_opcode = CBC_INIT_LOCAL; uint16_t func_init_opcode = CBC_INIT_LOCAL;
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
JERRY_ASSERT (type != SCANNER_STREAM_TYPE_IMPORT || (data_p[0] & SCANNER_STREAM_NO_REG));
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
#if ENABLED (JERRY_ES2015) #if ENABLED (JERRY_ES2015)
if (info_type == SCANNER_TYPE_FUNCTION) if (info_type == SCANNER_TYPE_FUNCTION)
{ {
@@ -1682,6 +1748,7 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
break; break;
} }
case SCANNER_STREAM_TYPE_ARG: case SCANNER_STREAM_TYPE_ARG:
case SCANNER_STREAM_TYPE_ARG_FUNC:
{ {
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p); context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
@@ -1691,14 +1758,12 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
CBC_INIT_LOCAL, CBC_INIT_LOCAL,
(uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top), (uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top),
map_to); map_to);
/* FALLTHRU */
}
case SCANNER_STREAM_TYPE_ARG_FUNC:
{
if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS) if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
{ {
scope_stack_reg_top++; scope_stack_reg_top++;
} }
break;
} }
} }
} }
@@ -1706,9 +1771,6 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
scope_stack_p++; scope_stack_p++;
literal.char_p += data_p[1];
data_p += length;
if (!SCANNER_STREAM_TYPE_IS_FUNCTION (type)) if (!SCANNER_STREAM_TYPE_IS_FUNCTION (type))
{ {
continue; continue;
@@ -1720,37 +1782,34 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED); parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED);
} }
if (JERRY_UNLIKELY (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS))
{
parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
}
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p); context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */ #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
if (func_init_opcode == CBC_INIT_LOCAL if (type != SCANNER_STREAM_TYPE_ARG_FUNC)
&& (option_flags & SCANNER_CREATE_VARS_IS_EVAL))
{ {
func_init_opcode = CBC_CREATE_VAR_FUNC_EVAL; if (func_init_opcode == CBC_INIT_LOCAL
} && (option_flags & SCANNER_CREATE_VARS_IS_EVAL))
{
func_init_opcode = CBC_CREATE_VAR_FUNC_EVAL;
}
parser_emit_cbc_literal_value (context_p, func_init_opcode, context_p->literal_count, map_to); parser_emit_cbc_literal_value (context_p, func_init_opcode, context_p->literal_count, map_to);
}
scope_stack_p->map_from = PARSER_SCOPE_STACK_FUNC; scope_stack_p->map_from = PARSER_SCOPE_STACK_FUNC;
scope_stack_p->map_to = context_p->literal_count; scope_stack_p->map_to = context_p->literal_count;
scope_stack_p++; scope_stack_p++;
lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool); scanner_create_unused_literal (context_p, 0);
literal_p->type = LEXER_UNUSED_LITERAL;
literal_p->status_flags = 0;
context_p->literal_count++;
} }
if (info_type == SCANNER_TYPE_FUNCTION && (info_p->u8_arg & SCANNER_FUNCTION_ARGUMENTS_NEEDED)) if (info_type == SCANNER_TYPE_FUNCTION
&& !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)
&& (info_p->u8_arg & SCANNER_FUNCTION_ARGUMENTS_NEEDED))
{ {
JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION);
if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p)) if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p))
{ {
JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK); JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK);
@@ -1781,7 +1840,10 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
context_p->register_count = (uint16_t) scope_stack_reg_top; context_p->register_count = (uint16_t) scope_stack_reg_top;
} }
scanner_release_next (context_p, (size_t) (data_p + 1 - ((const uint8_t *) info_p))); if (!(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS))
{
scanner_release_next (context_p, (size_t) (next_data_p + 1 - ((const uint8_t *) info_p)));
}
parser_flush_cbc (context_p); parser_flush_cbc (context_p);
} /* scanner_create_variables */ } /* scanner_create_variables */
+3 -4
View File
@@ -2632,12 +2632,11 @@ scan_completed:
if (info_p->type == SCANNER_TYPE_FUNCTION) if (info_p->type == SCANNER_TYPE_FUNCTION)
{ {
scanner_function_info_t *function_info_p = (scanner_function_info_t *) info_p; data_p = (const uint8_t *) (info_p + 1);
data_p = (const uint8_t *) (function_info_p + 1);
JERRY_DEBUG_MSG (" FUNCTION: flags: 0x%x declarations: %d", JERRY_DEBUG_MSG (" FUNCTION: flags: 0x%x declarations: %d",
(int) function_info_p->info.u8_arg, (int) info_p->u8_arg,
(int) function_info_p->info.u16_arg); (int) info_p->u16_arg);
} }
else else
{ {
+2 -8
View File
@@ -175,14 +175,6 @@ typedef enum
SCANNER_FUNCTION_ARGUMENTS_NEEDED = (1 << 0), /**< arguments object needs to be created */ SCANNER_FUNCTION_ARGUMENTS_NEEDED = (1 << 0), /**< arguments object needs to be created */
} scanner_function_flags_t; } scanner_function_flags_t;
/**
* Scanner info for function statements.
*/
typedef struct
{
scanner_info_t info; /**< header */
} scanner_function_info_t;
/** /**
* Option bits for scanner_create_variables function. * Option bits for scanner_create_variables function.
*/ */
@@ -190,6 +182,8 @@ typedef enum
{ {
SCANNER_CREATE_VARS_NO_OPTS = 0, /**< no options */ SCANNER_CREATE_VARS_NO_OPTS = 0, /**< no options */
SCANNER_CREATE_VARS_IS_EVAL = (1 << 0), /**< create variables for script / direct eval */ SCANNER_CREATE_VARS_IS_EVAL = (1 << 0), /**< create variables for script / direct eval */
SCANNER_CREATE_VARS_IS_FUNCTION_ARGS = (1 << 1), /**< create variables for function arguments */
SCANNER_CREATE_VARS_IS_FUNCTION_BODY = (1 << 2), /**< create variables for function body */
} scanner_create_variables_flags_t; } scanner_create_variables_flags_t;
/** /**
-4
View File
@@ -949,7 +949,6 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
break; break;
} }
#if ENABLED (JERRY_ES2015)
case CBC_SET_VAR_FUNC: case CBC_SET_VAR_FUNC:
{ {
uint32_t literal_index, value_index; uint32_t literal_index, value_index;
@@ -966,8 +965,6 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
if (literal_index < register_end) if (literal_index < register_end)
{ {
JERRY_ASSERT (type == CBC_SET_VAR_FUNC);
ecma_fast_free_value (frame_ctx_p->registers_p[literal_index]); ecma_fast_free_value (frame_ctx_p->registers_p[literal_index]);
frame_ctx_p->registers_p[literal_index] = lit_value; frame_ctx_p->registers_p[literal_index] = lit_value;
break; break;
@@ -978,7 +975,6 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
vm_set_var (frame_ctx_p->lex_env_p, name_p, is_strict, lit_value); vm_set_var (frame_ctx_p->lex_env_p, name_p, is_strict, lit_value);
break; break;
} }
#endif /* ENABLED (JERRY_ES2015) */
#if ENABLED (JERRY_SNAPSHOT_EXEC) #if ENABLED (JERRY_SNAPSHOT_EXEC)
case CBC_SET_BYTECODE_PTR: case CBC_SET_BYTECODE_PTR:
@@ -0,0 +1,65 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
function f(a, b = a)
{
function a() { return 2; }
assert(a() === 2);
assert(b === 1)
}
f(1);
function g(a, b = a)
{
function a() { return 2; }
eval("assert(a() === 2)");
eval("assert(b === 1)");
}
g(1);
var x = 1;
function h(a = x) {
assert(x === undefined);
var x = 2;
assert(a === 1);
assert(x === 2);
}
h();
x = function() { return 4; }
let y = 6;
function i(a = x() / 2, b = (y) + 2, c = typeof z) {
let y = 10;
let z = 11;
function x() { return 5; }
assert(a === 2);
assert(x() === 5);
assert(b === 8);
assert(c === "undefined");
assert(y === 10);
assert(z === 11);
}
i();
var arguments = 10;
function j(a = arguments[1])
{
assert(a === 2);
}
j(undefined,2);