Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion jerry-core/include/jerryscript-snapshot.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ extern "C"
/**
* Jerry snapshot format version.
*/
#define JERRY_SNAPSHOT_VERSION (42u)
#define JERRY_SNAPSHOT_VERSION (43u)

/**
* Flags for jerry_generate_snapshot and jerry_generate_function_snapshot.
Expand Down
12 changes: 10 additions & 2 deletions jerry-core/parser/js/byte-code.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,14 @@
VM_OC_CREATE_BINDING) \
CBC_OPCODE (CBC_CREATE_LOCAL, CBC_HAS_LITERAL_ARG, 0, \
VM_OC_CREATE_BINDING) \
CBC_OPCODE (CBC_INIT_LOCAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
VM_OC_INIT_LOCAL) \
CBC_OPCODE (CBC_INIT_ARG_OR_CATCH, CBC_HAS_LITERAL_ARG, -1, \
VM_OC_INIT_BINDING) \
CBC_OPCODE (CBC_INIT_LET, CBC_HAS_LITERAL_ARG, -1, \
VM_OC_INIT_BINDING) \
CBC_OPCODE (CBC_INIT_CONST, CBC_HAS_LITERAL_ARG, -1, \
VM_OC_INIT_BINDING) \
CBC_OPCODE (CBC_INIT_ARG_OR_FUNC, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
VM_OC_INIT_ARG_OR_FUNC) \
CBC_OPCODE (CBC_CREATE_VAR_EVAL, CBC_HAS_LITERAL_ARG, 0, \
VM_OC_VAR_EVAL) \
CBC_OPCODE (CBC_CREATE_VAR_FUNC_EVAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
Expand Down Expand Up @@ -498,6 +504,8 @@
VM_OC_MOV_IDENT | VM_OC_GET_STACK | VM_OC_PUT_IDENT) \
CBC_OPCODE (CBC_ASSIGN_LET_CONST, CBC_HAS_LITERAL_ARG, -1, \
VM_OC_ASSIGN_LET_CONST | VM_OC_GET_STACK) \
CBC_OPCODE (CBC_ASSIGN_LET_CONST_LITERAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
VM_OC_ASSIGN_LET_CONST | VM_OC_GET_LITERAL) \
CBC_OPCODE (CBC_ASSIGN_SUPER, CBC_NO_FLAG, -3, \
VM_OC_ASSIGN_SUPER) \
CBC_OPCODE (CBC_ASSIGN_SUPER_PUSH_RESULT, CBC_NO_FLAG, -2, \
Expand Down
52 changes: 37 additions & 15 deletions jerry-core/parser/js/js-parser-expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -813,9 +813,15 @@ parser_parse_class (parser_context_t *context_p, /**< context */

if (is_statement)
{
parser_emit_cbc_literal (context_p,
class_ident_index >= PARSER_REGISTER_START ? CBC_MOV_IDENT : CBC_ASSIGN_LET_CONST,
class_ident_index);
cbc_opcode_t opcode = CBC_MOV_IDENT;

if (class_ident_index < PARSER_REGISTER_START)
{
opcode = (scanner_literal_is_created (context_p, class_ident_index) ? CBC_ASSIGN_LET_CONST
: CBC_INIT_LET);
}

parser_emit_cbc_literal (context_p, (uint16_t) opcode, class_ident_index);
}

parser_flush_cbc (context_p);
Expand Down Expand Up @@ -2251,9 +2257,9 @@ parser_process_unary_expression (parser_context_t *context_p, /**< context */
*/
static uint8_t
parser_append_binary_single_assignment_token (parser_context_t *context_p, /**< context */
bool is_lexical) /**< assign lexical declaration */
uint32_t pattern_flags) /**< pattern flags */
{
JERRY_UNUSED (is_lexical);
JERRY_UNUSED (pattern_flags);

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

#if ENABLED (JERRY_ES2015)
if (!is_lexical)
if (!(pattern_flags & (PARSER_PATTERN_LET | PARSER_PATTERN_CONST | PARSER_PATTERN_LOCAL)))
{
if (scanner_literal_is_const_reg (context_p, literal_index))
{
Expand All @@ -2310,7 +2316,20 @@ parser_append_binary_single_assignment_token (parser_context_t *context_p, /**<
}
else if (literal_index < PARSER_REGISTER_START)
{
assign_opcode = CBC_ASSIGN_LET_CONST;
assign_opcode = CBC_INIT_LET;

if (scanner_literal_is_created (context_p, literal_index))
{
assign_opcode = CBC_ASSIGN_LET_CONST;
}
else if (pattern_flags & PARSER_PATTERN_CONST)
{
assign_opcode = CBC_INIT_CONST;
}
else if (pattern_flags & PARSER_PATTERN_LOCAL)
{
assign_opcode = CBC_INIT_ARG_OR_CATCH;
}
}
#endif /* ENABLED (JERRY_ES2015) */

Expand Down Expand Up @@ -2395,7 +2414,7 @@ parser_append_binary_token (parser_context_t *context_p) /**< context */

if (context_p->token.type == LEXER_ASSIGN)
{
parser_append_binary_single_assignment_token (context_p, false);
parser_append_binary_single_assignment_token (context_p, 0);
return;
}

Expand Down Expand Up @@ -2486,7 +2505,10 @@ parser_process_binary_opcodes (parser_context_t *context_p, /**< context */
JERRY_ASSERT (opcode == CBC_ASSIGN_SET_IDENT
|| opcode == CBC_ASSIGN_PROP_LITERAL
|| opcode == CBC_ASSIGN_PROP_THIS_LITERAL
|| opcode == CBC_ASSIGN_LET_CONST);
|| opcode == CBC_ASSIGN_LET_CONST
|| opcode == CBC_INIT_ARG_OR_CATCH
|| opcode == CBC_INIT_LET
|| opcode == CBC_INIT_CONST);

index = parser_stack_pop_uint16 (context_p);
}
Expand Down Expand Up @@ -2601,7 +2623,7 @@ parser_pattern_get_target (parser_context_t *context_p, /**< context */
{
JERRY_ASSERT (flags & PARSER_PATTERN_TARGET_ON_STACK);

parser_emit_cbc_forward_branch (context_p, PARSER_TO_EXT_OPCODE (CBC_EXT_DEFAULT_INITIALIZER), &skip_init);
parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_DEFAULT_INITIALIZER, &skip_init);
}

if ((flags & (PARSER_PATTERN_TARGET_ON_STACK | PARSER_PATTERN_TARGET_DEFAULT)) != PARSER_PATTERN_TARGET_ON_STACK)
Expand Down Expand Up @@ -2707,8 +2729,7 @@ parser_pattern_form_assignment (parser_context_t *context_p, /**< context */
JERRY_UNUSED (ident_line_counter);

parser_stack_push_uint8 (context_p, LEXER_EXPRESSION_START);
bool is_lexical = (flags & (PARSER_PATTERN_LEXICAL | PARSER_PATTERN_LOCAL)) != 0;
uint8_t assign_opcode = parser_append_binary_single_assignment_token (context_p, is_lexical);
uint8_t assign_opcode = parser_append_binary_single_assignment_token (context_p, flags);

if (flags & PARSER_PATTERN_ARRAY)
{
Expand All @@ -2724,7 +2745,7 @@ parser_pattern_form_assignment (parser_context_t *context_p, /**< context */
{
parser_branch_t skip_init;
lexer_next_token (context_p);
parser_emit_cbc_forward_branch (context_p, PARSER_TO_EXT_OPCODE (CBC_EXT_DEFAULT_INITIALIZER), &skip_init);
parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_DEFAULT_INITIALIZER, &skip_init);

parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
parser_set_branch_to_current_position (context_p, &skip_init);
Expand Down Expand Up @@ -2770,7 +2791,8 @@ parser_pattern_process_nested_pattern (parser_context_t *context_p, /**< context
parser_pattern_flags_t options = (PARSER_PATTERN_NESTED_PATTERN
| PARSER_PATTERN_TARGET_ON_STACK
| (flags & (PARSER_PATTERN_BINDING
| PARSER_PATTERN_LEXICAL
| PARSER_PATTERN_LET
| PARSER_PATTERN_CONST
| PARSER_PATTERN_LOCAL
| PARSER_PATTERN_REST_ELEMENT
| PARSER_PATTERN_ARGUMENTS)));
Expand Down Expand Up @@ -2821,7 +2843,7 @@ parser_pattern_process_assignment (parser_context_t *context_p, /**< context */

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

if (flags & PARSER_PATTERN_LEXICAL
if (flags & (PARSER_PATTERN_LET | PARSER_PATTERN_CONST)
&& context_p->token.keyword_type == LEXER_KEYW_LET)
{
parser_raise_error (context_p, PARSER_ERR_LEXICAL_LET_BINDING);
Expand Down
23 changes: 15 additions & 8 deletions jerry-core/parser/js/js-parser-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,12 @@ typedef enum
PARSER_PATTERN_TARGET_ON_STACK = (1u << 1), /**< assignment target is the topmost element on the stack */
PARSER_PATTERN_TARGET_DEFAULT = (1u << 2), /**< perform default value comparison for assignment target */
PARSER_PATTERN_NESTED_PATTERN = (1u << 3), /**< parse patter inside a pattern */
PARSER_PATTERN_LEXICAL = (1u << 4), /**< pattern is a lexical (let/const) declaration */
PARSER_PATTERN_LOCAL = (1u << 5), /**< pattern is a local (catch parameter) declaration */
PARSER_PATTERN_REST_ELEMENT = (1u << 6), /**< parse rest array initializer */
PARSER_PATTERN_ARGUMENTS = (1u << 7), /**< parse arguments binding */
PARSER_PATTERN_ARRAY = (1u << 8), /**< array pattern is being parsed */
PARSER_PATTERN_LET = (1u << 4), /**< pattern is a let declaration */
PARSER_PATTERN_CONST = (1u << 5), /**< pattern is a const declaration */
PARSER_PATTERN_LOCAL = (1u << 6), /**< pattern is a local (catch parameter) declaration */
PARSER_PATTERN_REST_ELEMENT = (1u << 7), /**< parse rest array initializer */
PARSER_PATTERN_ARGUMENTS = (1u << 8), /**< parse arguments binding */
PARSER_PATTERN_ARRAY = (1u << 9), /**< array pattern is being parsed */
} parser_pattern_flags_t;

/**
Expand Down Expand Up @@ -395,12 +396,17 @@ typedef struct
* Function statements with the name specified
* in map_from should not be copied to global scope.
*/
#define PARSER_SCOPE_STACK_NO_FUNCTION_COPY 0x4000
#define PARSER_SCOPE_STACK_NO_FUNCTION_COPY 0x8000

/**
* The scope stack item represents a const declaration
* The scope stack item represents a const binding stored in register
*/
#define PARSER_SCOPE_STACK_IS_CONST 0x8000
#define PARSER_SCOPE_STACK_IS_CONST_REG 0x4000

/**
* The scope stack item represents a binding which has already created with ECMA_VALUE_UNINITIALIZED
*/
#define PARSER_SCOPE_STACK_IS_LOCAL_CREATED (PARSER_SCOPE_STACK_IS_CONST_REG)

#endif /* ENABLED (JERRY_ES2015) */

Expand Down Expand Up @@ -753,6 +759,7 @@ void scanner_set_location (parser_context_t *context_p, scanner_location_t *loca
uint16_t scanner_decode_map_to (parser_scope_stack_t *stack_item_p);
#if ENABLED (JERRY_ES2015)
bool scanner_literal_is_const_reg (parser_context_t *context_p, uint16_t literal_index);
bool scanner_literal_is_created (parser_context_t *context_p, uint16_t literal_index);
#endif /* ENABLED (JERRY_ES2015) */

void scanner_scan_all (parser_context_t *context_p, const uint8_t *arg_list_p, const uint8_t *arg_list_end_p,
Expand Down
53 changes: 39 additions & 14 deletions jerry-core/parser/js/js-parser-statm.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,10 +499,15 @@ parser_parse_var_statement (parser_context_t *context_p) /**< context */
{
parser_pattern_flags_t flags = PARSER_PATTERN_BINDING;

if (declaration_type != LEXER_KEYW_VAR)
if (declaration_type == LEXER_KEYW_LET)
{
flags |= PARSER_PATTERN_LEXICAL;
flags |= PARSER_PATTERN_LET;
}
else if (declaration_type == LEXER_KEYW_CONST)
{
flags |= PARSER_PATTERN_CONST;
}

parser_parse_initializer_by_next_char (context_p, flags);
}
else
Expand Down Expand Up @@ -569,7 +574,16 @@ parser_parse_var_statement (parser_context_t *context_p) /**< context */
if (declaration_type != LEXER_KEYW_VAR
&& (index < PARSER_REGISTER_START))
{
opcode = CBC_ASSIGN_LET_CONST;
opcode = CBC_INIT_LET;

if (scanner_literal_is_created (context_p, index))
{
opcode = CBC_ASSIGN_LET_CONST;
}
else if (declaration_type == LEXER_KEYW_CONST)
{
opcode = CBC_INIT_CONST;
}
}
#endif /* ENABLED (JERRY_ES2015) */

Expand All @@ -581,9 +595,15 @@ parser_parse_var_statement (parser_context_t *context_p) /**< context */
parser_emit_cbc (context_p, CBC_PUSH_UNDEFINED);

uint16_t index = context_p->lit_object.index;
parser_emit_cbc_literal (context_p,
index >= PARSER_REGISTER_START ? CBC_MOV_IDENT : CBC_ASSIGN_LET_CONST,
index);
cbc_opcode_t opcode = CBC_MOV_IDENT;

if (index < PARSER_REGISTER_START)
{
opcode = (scanner_literal_is_created (context_p, index) ? CBC_ASSIGN_LET_CONST
: CBC_INIT_LET);
}

parser_emit_cbc_literal (context_p, (uint16_t) opcode, index);
}
else if (declaration_type == LEXER_KEYW_CONST)
{
Expand Down Expand Up @@ -1289,8 +1309,6 @@ parser_parse_for_statement_start (parser_context_t *context_p) /**< context */
#if ENABLED (JERRY_ES2015)
if (lexer_check_next_characters (context_p, LIT_CHAR_LEFT_SQUARE, LIT_CHAR_LEFT_BRACE))
{
bool is_var = (token_type == LEXER_KEYW_VAR);

parser_emit_cbc_ext (context_p, is_for_in ? CBC_EXT_FOR_IN_GET_NEXT
: CBC_EXT_FOR_OF_GET_NEXT);

Expand All @@ -1303,9 +1321,13 @@ parser_parse_for_statement_start (parser_context_t *context_p) /**< context */

parser_pattern_flags_t flags = (PARSER_PATTERN_BINDING | PARSER_PATTERN_TARGET_ON_STACK);

if (!is_var)
if (token_type == LEXER_KEYW_LET)
{
flags |= PARSER_PATTERN_LET;
}
else if (token_type == LEXER_KEYW_CONST)
{
flags |= PARSER_PATTERN_LEXICAL;
flags |= PARSER_PATTERN_CONST;
}

parser_parse_initializer_by_next_char (context_p, flags);
Expand Down Expand Up @@ -1347,9 +1369,12 @@ parser_parse_for_statement_start (parser_context_t *context_p) /**< context */
}
#endif /* !JERRY_NDEBUG */

parser_emit_cbc_literal (context_p,
has_context ? CBC_ASSIGN_LET_CONST : CBC_ASSIGN_SET_IDENT,
literal_index);
JERRY_ASSERT (literal_index >= PARSER_REGISTER_START
|| !has_context
|| scanner_literal_is_created (context_p, literal_index));

uint16_t opcode = (has_context ? CBC_ASSIGN_LET_CONST : CBC_ASSIGN_SET_IDENT);
parser_emit_cbc_literal (context_p, opcode, literal_index);
#else /* !ENABLED (JERRY_ES2015) */
parser_emit_cbc_literal (context_p, CBC_ASSIGN_SET_IDENT, literal_index);
#endif /* ENABLED (JERRY_ES2015) */
Expand Down Expand Up @@ -1928,7 +1953,7 @@ parser_parse_try_statement_end (parser_context_t *context_p) /**< context */
{
parser_pattern_flags_t flags = (PARSER_PATTERN_BINDING
| PARSER_PATTERN_TARGET_ON_STACK
| PARSER_PATTERN_LOCAL);
| PARSER_PATTERN_LET);

parser_parse_initializer_by_next_char (context_p, flags);
}
Expand Down
Loading