Skip to content

Commit e9a68ba

Browse files
committed
Implement proper creation of function arguments.
After the rework it is possible to detect use before init errors. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
1 parent 8d08cec commit e9a68ba

File tree

15 files changed

+601
-174
lines changed

15 files changed

+601
-174
lines changed

jerry-core/include/jerryscript-snapshot.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ extern "C"
3030
/**
3131
* Jerry snapshot format version.
3232
*/
33-
#define JERRY_SNAPSHOT_VERSION (42u)
33+
#define JERRY_SNAPSHOT_VERSION (43u)
3434

3535
/**
3636
* Flags for jerry_generate_snapshot and jerry_generate_function_snapshot.

jerry-core/parser/js/byte-code.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,8 +312,14 @@
312312
VM_OC_CREATE_BINDING) \
313313
CBC_OPCODE (CBC_CREATE_LOCAL, CBC_HAS_LITERAL_ARG, 0, \
314314
VM_OC_CREATE_BINDING) \
315-
CBC_OPCODE (CBC_INIT_LOCAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
316-
VM_OC_INIT_LOCAL) \
315+
CBC_OPCODE (CBC_INIT_ARG_OR_CATCH, CBC_HAS_LITERAL_ARG, -1, \
316+
VM_OC_INIT_BINDING) \
317+
CBC_OPCODE (CBC_INIT_LET, CBC_HAS_LITERAL_ARG, -1, \
318+
VM_OC_INIT_BINDING) \
319+
CBC_OPCODE (CBC_INIT_CONST, CBC_HAS_LITERAL_ARG, -1, \
320+
VM_OC_INIT_BINDING) \
321+
CBC_OPCODE (CBC_INIT_ARG_OR_FUNC, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
322+
VM_OC_INIT_ARG_OR_FUNC) \
317323
CBC_OPCODE (CBC_CREATE_VAR_EVAL, CBC_HAS_LITERAL_ARG, 0, \
318324
VM_OC_VAR_EVAL) \
319325
CBC_OPCODE (CBC_CREATE_VAR_FUNC_EVAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
@@ -498,6 +504,8 @@
498504
VM_OC_MOV_IDENT | VM_OC_GET_STACK | VM_OC_PUT_IDENT) \
499505
CBC_OPCODE (CBC_ASSIGN_LET_CONST, CBC_HAS_LITERAL_ARG, -1, \
500506
VM_OC_ASSIGN_LET_CONST | VM_OC_GET_STACK) \
507+
CBC_OPCODE (CBC_ASSIGN_LET_CONST_LITERAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
508+
VM_OC_ASSIGN_LET_CONST | VM_OC_GET_LITERAL) \
501509
CBC_OPCODE (CBC_ASSIGN_SUPER, CBC_NO_FLAG, -3, \
502510
VM_OC_ASSIGN_SUPER) \
503511
CBC_OPCODE (CBC_ASSIGN_SUPER_PUSH_RESULT, CBC_NO_FLAG, -2, \

jerry-core/parser/js/js-parser-expr.c

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2251,9 +2251,9 @@ parser_process_unary_expression (parser_context_t *context_p, /**< context */
22512251
*/
22522252
static uint8_t
22532253
parser_append_binary_single_assignment_token (parser_context_t *context_p, /**< context */
2254-
bool is_lexical) /**< assign lexical declaration */
2254+
uint32_t pattern_flags) /**< pattern flags */
22552255
{
2256-
JERRY_UNUSED (is_lexical);
2256+
JERRY_UNUSED (pattern_flags);
22572257

22582258
/* Unlike other tokens, the whole byte code is saved for binary
22592259
* assignment, since it has multiple forms depending on the
@@ -2301,7 +2301,7 @@ parser_append_binary_single_assignment_token (parser_context_t *context_p, /**<
23012301
assign_opcode = CBC_ASSIGN_SET_IDENT;
23022302

23032303
#if ENABLED (JERRY_ES2015)
2304-
if (!is_lexical)
2304+
if (!(pattern_flags & (PARSER_PATTERN_LET | PARSER_PATTERN_CONST | PARSER_PATTERN_LOCAL)))
23052305
{
23062306
if (scanner_literal_is_const_reg (context_p, literal_index))
23072307
{
@@ -2310,7 +2310,20 @@ parser_append_binary_single_assignment_token (parser_context_t *context_p, /**<
23102310
}
23112311
else if (literal_index < PARSER_REGISTER_START)
23122312
{
2313-
assign_opcode = CBC_ASSIGN_LET_CONST;
2313+
assign_opcode = CBC_INIT_LET;
2314+
2315+
if (scanner_literal_is_created (context_p, literal_index))
2316+
{
2317+
assign_opcode = CBC_ASSIGN_LET_CONST;
2318+
}
2319+
else if (pattern_flags & PARSER_PATTERN_CONST)
2320+
{
2321+
assign_opcode = CBC_INIT_CONST;
2322+
}
2323+
else if (pattern_flags & PARSER_PATTERN_LOCAL)
2324+
{
2325+
assign_opcode = CBC_INIT_ARG_OR_CATCH;
2326+
}
23142327
}
23152328
#endif /* ENABLED (JERRY_ES2015) */
23162329

@@ -2395,7 +2408,7 @@ parser_append_binary_token (parser_context_t *context_p) /**< context */
23952408

23962409
if (context_p->token.type == LEXER_ASSIGN)
23972410
{
2398-
parser_append_binary_single_assignment_token (context_p, false);
2411+
parser_append_binary_single_assignment_token (context_p, 0);
23992412
return;
24002413
}
24012414

@@ -2486,7 +2499,10 @@ parser_process_binary_opcodes (parser_context_t *context_p, /**< context */
24862499
JERRY_ASSERT (opcode == CBC_ASSIGN_SET_IDENT
24872500
|| opcode == CBC_ASSIGN_PROP_LITERAL
24882501
|| opcode == CBC_ASSIGN_PROP_THIS_LITERAL
2489-
|| opcode == CBC_ASSIGN_LET_CONST);
2502+
|| opcode == CBC_ASSIGN_LET_CONST
2503+
|| opcode == CBC_INIT_ARG_OR_CATCH
2504+
|| opcode == CBC_INIT_LET
2505+
|| opcode == CBC_INIT_CONST);
24902506

24912507
index = parser_stack_pop_uint16 (context_p);
24922508
}
@@ -2601,7 +2617,7 @@ parser_pattern_get_target (parser_context_t *context_p, /**< context */
26012617
{
26022618
JERRY_ASSERT (flags & PARSER_PATTERN_TARGET_ON_STACK);
26032619

2604-
parser_emit_cbc_forward_branch (context_p, PARSER_TO_EXT_OPCODE (CBC_EXT_DEFAULT_INITIALIZER), &skip_init);
2620+
parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_DEFAULT_INITIALIZER, &skip_init);
26052621
}
26062622

26072623
if ((flags & (PARSER_PATTERN_TARGET_ON_STACK | PARSER_PATTERN_TARGET_DEFAULT)) != PARSER_PATTERN_TARGET_ON_STACK)
@@ -2707,8 +2723,7 @@ parser_pattern_form_assignment (parser_context_t *context_p, /**< context */
27072723
JERRY_UNUSED (ident_line_counter);
27082724

27092725
parser_stack_push_uint8 (context_p, LEXER_EXPRESSION_START);
2710-
bool is_lexical = (flags & (PARSER_PATTERN_LEXICAL | PARSER_PATTERN_LOCAL)) != 0;
2711-
uint8_t assign_opcode = parser_append_binary_single_assignment_token (context_p, is_lexical);
2726+
uint8_t assign_opcode = parser_append_binary_single_assignment_token (context_p, flags);
27122727

27132728
if (flags & PARSER_PATTERN_ARRAY)
27142729
{
@@ -2724,7 +2739,7 @@ parser_pattern_form_assignment (parser_context_t *context_p, /**< context */
27242739
{
27252740
parser_branch_t skip_init;
27262741
lexer_next_token (context_p);
2727-
parser_emit_cbc_forward_branch (context_p, PARSER_TO_EXT_OPCODE (CBC_EXT_DEFAULT_INITIALIZER), &skip_init);
2742+
parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_DEFAULT_INITIALIZER, &skip_init);
27282743

27292744
parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
27302745
parser_set_branch_to_current_position (context_p, &skip_init);
@@ -2770,7 +2785,8 @@ parser_pattern_process_nested_pattern (parser_context_t *context_p, /**< context
27702785
parser_pattern_flags_t options = (PARSER_PATTERN_NESTED_PATTERN
27712786
| PARSER_PATTERN_TARGET_ON_STACK
27722787
| (flags & (PARSER_PATTERN_BINDING
2773-
| PARSER_PATTERN_LEXICAL
2788+
| PARSER_PATTERN_LET
2789+
| PARSER_PATTERN_CONST
27742790
| PARSER_PATTERN_LOCAL
27752791
| PARSER_PATTERN_REST_ELEMENT
27762792
| PARSER_PATTERN_ARGUMENTS)));
@@ -2821,7 +2837,7 @@ parser_pattern_process_assignment (parser_context_t *context_p, /**< context */
28212837

28222838
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL);
28232839

2824-
if (flags & PARSER_PATTERN_LEXICAL
2840+
if (flags & (PARSER_PATTERN_LET | PARSER_PATTERN_CONST)
28252841
&& context_p->token.keyword_type == LEXER_KEYW_LET)
28262842
{
28272843
parser_raise_error (context_p, PARSER_ERR_LEXICAL_LET_BINDING);

jerry-core/parser/js/js-parser-internal.h

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,12 @@ typedef enum
110110
PARSER_PATTERN_TARGET_ON_STACK = (1u << 1), /**< assignment target is the topmost element on the stack */
111111
PARSER_PATTERN_TARGET_DEFAULT = (1u << 2), /**< perform default value comparison for assignment target */
112112
PARSER_PATTERN_NESTED_PATTERN = (1u << 3), /**< parse patter inside a pattern */
113-
PARSER_PATTERN_LEXICAL = (1u << 4), /**< pattern is a lexical (let/const) declaration */
114-
PARSER_PATTERN_LOCAL = (1u << 5), /**< pattern is a local (catch parameter) declaration */
115-
PARSER_PATTERN_REST_ELEMENT = (1u << 6), /**< parse rest array initializer */
116-
PARSER_PATTERN_ARGUMENTS = (1u << 7), /**< parse arguments binding */
117-
PARSER_PATTERN_ARRAY = (1u << 8), /**< array pattern is being parsed */
113+
PARSER_PATTERN_LET = (1u << 4), /**< pattern is a let declaration */
114+
PARSER_PATTERN_CONST = (1u << 5), /**< pattern is a const declaration */
115+
PARSER_PATTERN_LOCAL = (1u << 6), /**< pattern is a local (catch parameter) declaration */
116+
PARSER_PATTERN_REST_ELEMENT = (1u << 7), /**< parse rest array initializer */
117+
PARSER_PATTERN_ARGUMENTS = (1u << 8), /**< parse arguments binding */
118+
PARSER_PATTERN_ARRAY = (1u << 9), /**< array pattern is being parsed */
118119
} parser_pattern_flags_t;
119120

120121
/**
@@ -395,12 +396,17 @@ typedef struct
395396
* Function statements with the name specified
396397
* in map_from should not be copied to global scope.
397398
*/
398-
#define PARSER_SCOPE_STACK_NO_FUNCTION_COPY 0x4000
399+
#define PARSER_SCOPE_STACK_NO_FUNCTION_COPY 0x8000
399400

400401
/**
401-
* The scope stack item represents a const declaration
402+
* The scope stack item represents a const binding stored in register
402403
*/
403-
#define PARSER_SCOPE_STACK_IS_CONST 0x8000
404+
#define PARSER_SCOPE_STACK_IS_CONST_REG 0x4000
405+
406+
/**
407+
* The scope stack item represents a binding which has already created with ECMA_VALUE_UNINITIALIZED
408+
*/
409+
#define PARSER_SCOPE_STACK_IS_LOCAL_CREATED (PARSER_SCOPE_STACK_IS_CONST_REG)
404410

405411
#endif /* ENABLED (JERRY_ES2015) */
406412

@@ -753,6 +759,7 @@ void scanner_set_location (parser_context_t *context_p, scanner_location_t *loca
753759
uint16_t scanner_decode_map_to (parser_scope_stack_t *stack_item_p);
754760
#if ENABLED (JERRY_ES2015)
755761
bool scanner_literal_is_const_reg (parser_context_t *context_p, uint16_t literal_index);
762+
bool scanner_literal_is_created (parser_context_t *context_p, uint16_t literal_index);
756763
#endif /* ENABLED (JERRY_ES2015) */
757764

758765
void scanner_scan_all (parser_context_t *context_p, const uint8_t *arg_list_p, const uint8_t *arg_list_end_p,

jerry-core/parser/js/js-parser-statm.c

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -499,10 +499,15 @@ parser_parse_var_statement (parser_context_t *context_p) /**< context */
499499
{
500500
parser_pattern_flags_t flags = PARSER_PATTERN_BINDING;
501501

502-
if (declaration_type != LEXER_KEYW_VAR)
502+
if (declaration_type == LEXER_KEYW_LET)
503503
{
504-
flags |= PARSER_PATTERN_LEXICAL;
504+
flags |= PARSER_PATTERN_LET;
505505
}
506+
else if (declaration_type == LEXER_KEYW_CONST)
507+
{
508+
flags |= PARSER_PATTERN_CONST;
509+
}
510+
506511
parser_parse_initializer_by_next_char (context_p, flags);
507512
}
508513
else
@@ -569,7 +574,16 @@ parser_parse_var_statement (parser_context_t *context_p) /**< context */
569574
if (declaration_type != LEXER_KEYW_VAR
570575
&& (index < PARSER_REGISTER_START))
571576
{
572-
opcode = CBC_ASSIGN_LET_CONST;
577+
opcode = CBC_INIT_LET;
578+
579+
if (scanner_literal_is_created (context_p, index))
580+
{
581+
opcode = CBC_ASSIGN_LET_CONST;
582+
}
583+
else if (declaration_type == LEXER_KEYW_CONST)
584+
{
585+
opcode = CBC_INIT_CONST;
586+
}
573587
}
574588
#endif /* ENABLED (JERRY_ES2015) */
575589

@@ -1289,8 +1303,6 @@ parser_parse_for_statement_start (parser_context_t *context_p) /**< context */
12891303
#if ENABLED (JERRY_ES2015)
12901304
if (lexer_check_next_characters (context_p, LIT_CHAR_LEFT_SQUARE, LIT_CHAR_LEFT_BRACE))
12911305
{
1292-
bool is_var = (token_type == LEXER_KEYW_VAR);
1293-
12941306
parser_emit_cbc_ext (context_p, is_for_in ? CBC_EXT_FOR_IN_GET_NEXT
12951307
: CBC_EXT_FOR_OF_GET_NEXT);
12961308

@@ -1303,9 +1315,13 @@ parser_parse_for_statement_start (parser_context_t *context_p) /**< context */
13031315

13041316
parser_pattern_flags_t flags = (PARSER_PATTERN_BINDING | PARSER_PATTERN_TARGET_ON_STACK);
13051317

1306-
if (!is_var)
1318+
if (token_type == LEXER_KEYW_LET)
1319+
{
1320+
flags |= PARSER_PATTERN_LET;
1321+
}
1322+
else if (token_type == LEXER_KEYW_CONST)
13071323
{
1308-
flags |= PARSER_PATTERN_LEXICAL;
1324+
flags |= PARSER_PATTERN_CONST;
13091325
}
13101326

13111327
parser_parse_initializer_by_next_char (context_p, flags);
@@ -1347,9 +1363,25 @@ parser_parse_for_statement_start (parser_context_t *context_p) /**< context */
13471363
}
13481364
#endif /* !JERRY_NDEBUG */
13491365

1350-
parser_emit_cbc_literal (context_p,
1351-
has_context ? CBC_ASSIGN_LET_CONST : CBC_ASSIGN_SET_IDENT,
1352-
literal_index);
1366+
uint16_t opcode = CBC_ASSIGN_SET_IDENT;
1367+
1368+
if (has_context && literal_index < PARSER_REGISTER_START)
1369+
{
1370+
JERRY_ASSERT (token_type == LEXER_KEYW_LET || token_type == LEXER_KEYW_CONST);
1371+
1372+
opcode = CBC_INIT_LET;
1373+
1374+
if (scanner_literal_is_created (context_p, literal_index))
1375+
{
1376+
opcode = CBC_ASSIGN_LET_CONST;
1377+
}
1378+
else if (token_type == LEXER_KEYW_CONST)
1379+
{
1380+
opcode = CBC_INIT_CONST;
1381+
}
1382+
}
1383+
1384+
parser_emit_cbc_literal (context_p, opcode, literal_index);
13531385
#else /* !ENABLED (JERRY_ES2015) */
13541386
parser_emit_cbc_literal (context_p, CBC_ASSIGN_SET_IDENT, literal_index);
13551387
#endif /* ENABLED (JERRY_ES2015) */

0 commit comments

Comments
 (0)