From 322265bfb9f6fade377453efd7b968ac0b81672c Mon Sep 17 00:00:00 2001 From: Robert Fancsik Date: Tue, 23 Feb 2021 10:00:00 +0100 Subject: [PATCH] Move push literal number opcodes to basic opcodes (#4609) `obj[number]` is a widely used structure especially for array element indexing, however super property assignment is not. This patch moves super-assignment opcodes to ext opcodes and fills the freed 3 basic opcodes with push-literal-number ones. JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik robert.fancsik@h-lab.eu --- jerry-core/include/jerryscript-snapshot.h | 2 +- jerry-core/parser/js/byte-code.h | 26 ++++++------ jerry-core/parser/js/common.c | 4 +- jerry-core/parser/js/js-lexer.c | 8 ++-- jerry-core/parser/js/js-lexer.h | 2 +- jerry-core/parser/js/js-parser-expr.c | 50 +++++++++++++++-------- jerry-core/parser/js/js-parser-internal.h | 8 +--- jerry-core/parser/js/js-parser-util.c | 14 +++---- 8 files changed, 62 insertions(+), 52 deletions(-) diff --git a/jerry-core/include/jerryscript-snapshot.h b/jerry-core/include/jerryscript-snapshot.h index e70144c80..d71a93f8a 100644 --- a/jerry-core/include/jerryscript-snapshot.h +++ b/jerry-core/include/jerryscript-snapshot.h @@ -30,7 +30,7 @@ extern "C" /** * Jerry snapshot format version. */ -#define JERRY_SNAPSHOT_VERSION (64u) +#define JERRY_SNAPSHOT_VERSION (65u) /** * Flags for jerry_generate_snapshot and jerry_generate_function_snapshot. diff --git a/jerry-core/parser/js/byte-code.h b/jerry-core/parser/js/byte-code.h index 5277b959a..918242dec 100644 --- a/jerry-core/parser/js/byte-code.h +++ b/jerry-core/parser/js/byte-code.h @@ -69,7 +69,7 @@ * CBC_NO_RESULT_OPERATION for ext opcodes */ #define CBC_EXT_NO_RESULT_OPERATION(opcode) \ - ((opcode) >= PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_CALL) \ + ((opcode) >= PARSER_TO_EXT_OPCODE (CBC_EXT_ASSIGN_SUPER) \ && (opcode) <= PARSER_TO_EXT_OPCODE (CBC_EXT_SPREAD_CALL_PROP_BLOCK)) #else /* !JERRY_ESNEXT */ /** @@ -288,6 +288,12 @@ VM_OC_PUSH_POS_BYTE | VM_OC_PUT_STACK) \ CBC_OPCODE (CBC_PUSH_NUMBER_NEG_BYTE, CBC_HAS_BYTE_ARG, 1, \ VM_OC_PUSH_NEG_BYTE | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_PUSH_LITERAL_PUSH_NUMBER_0, CBC_HAS_LITERAL_ARG, 2, \ + VM_OC_PUSH_LIT_0 | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE, CBC_HAS_LITERAL_ARG | CBC_HAS_BYTE_ARG, 2, \ + VM_OC_PUSH_LIT_POS_BYTE | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE, CBC_HAS_LITERAL_ARG | CBC_HAS_BYTE_ARG, 2, \ + VM_OC_PUSH_LIT_NEG_BYTE | VM_OC_GET_LITERAL) \ /* Note: These 4 opcodes must me in this order */ \ CBC_OPCODE (CBC_PUSH_PROP, CBC_NO_FLAG, -1, \ VM_OC_PROP_GET | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \ @@ -522,12 +528,6 @@ 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, \ - VM_OC_ASSIGN_SUPER | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_ASSIGN_SUPER_BLOCK, CBC_NO_FLAG, -3, \ - VM_OC_ASSIGN_SUPER | VM_OC_PUT_BLOCK) \ \ /* Last opcode (not a real opcode). */ \ CBC_OPCODE (CBC_END, CBC_NO_FLAG, 0, \ @@ -590,12 +590,6 @@ /* Basic opcodes. */ \ CBC_OPCODE (CBC_EXT_CREATE_ARGUMENTS, CBC_HAS_LITERAL_ARG, 0, \ VM_OC_CREATE_ARGUMENTS) \ - CBC_OPCODE (CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_0, CBC_HAS_LITERAL_ARG, 2, \ - VM_OC_PUSH_LIT_0 | VM_OC_GET_LITERAL) \ - CBC_OPCODE (CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE, CBC_HAS_LITERAL_ARG | CBC_HAS_BYTE_ARG, 2, \ - VM_OC_PUSH_LIT_POS_BYTE | VM_OC_GET_LITERAL) \ - CBC_OPCODE (CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE, CBC_HAS_LITERAL_ARG | CBC_HAS_BYTE_ARG, 2, \ - VM_OC_PUSH_LIT_NEG_BYTE | VM_OC_GET_LITERAL) \ CBC_OPCODE (CBC_EXT_CREATE_VAR_EVAL, CBC_HAS_LITERAL_ARG, 0, \ VM_OC_EXT_VAR_EVAL) \ CBC_OPCODE (CBC_EXT_CREATE_VAR_FUNC_EVAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \ @@ -716,6 +710,12 @@ VM_OC_RESOLVE_LEXICAL_THIS | VM_OC_PUT_STACK) \ CBC_OPCODE (CBC_EXT_LOCAL_EVAL, CBC_HAS_BYTE_ARG, 0, \ VM_OC_LOCAL_EVAL) \ + CBC_OPCODE (CBC_EXT_ASSIGN_SUPER, CBC_NO_FLAG, -3, \ + VM_OC_ASSIGN_SUPER) \ + CBC_OPCODE (CBC_EXT_ASSIGN_SUPER_PUSH_RESULT, CBC_NO_FLAG, -2, \ + VM_OC_ASSIGN_SUPER | VM_OC_PUT_STACK) \ + CBC_OPCODE (CBC_EXT_ASSIGN_SUPER_BLOCK, CBC_NO_FLAG, -3, \ + VM_OC_ASSIGN_SUPER | VM_OC_PUT_BLOCK) \ CBC_OPCODE (CBC_EXT_SUPER_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, \ VM_OC_SUPER_CALL) \ CBC_OPCODE (CBC_EXT_SUPER_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0, \ diff --git a/jerry-core/parser/js/common.c b/jerry-core/parser/js/common.c index 8e1d47845..9a20f92aa 100644 --- a/jerry-core/parser/js/common.c +++ b/jerry-core/parser/js/common.c @@ -507,12 +507,12 @@ util_print_cbc (ecma_compiled_code_t *compiled_code_p) /**< compiled code */ if (flags & CBC_HAS_BYTE_ARG) { if (opcode == CBC_PUSH_NUMBER_POS_BYTE - || ext_opcode == CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE) + || opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE) { JERRY_DEBUG_MSG (" number:%d", (int) *byte_code_p + 1); } else if (opcode == CBC_PUSH_NUMBER_NEG_BYTE - || ext_opcode == CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE) + || opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE) { JERRY_DEBUG_MSG (" number:%d", -((int) *byte_code_p + 1)); } diff --git a/jerry-core/parser/js/js-lexer.c b/jerry-core/parser/js/js-lexer.c index 9ba9f688a..e1d083409 100644 --- a/jerry-core/parser/js/js-lexer.c +++ b/jerry-core/parser/js/js-lexer.c @@ -2764,22 +2764,22 @@ void lexer_convert_push_number_to_push_literal (parser_context_t *context_p) /**< context */ { ecma_integer_value_t value; - bool two_literals = !PARSER_IS_BASIC_OPCODE (context_p->last_cbc_opcode); + bool two_literals = context_p->last_cbc_opcode >= CBC_PUSH_LITERAL_PUSH_NUMBER_0; if (context_p->last_cbc_opcode == CBC_PUSH_NUMBER_0 - || context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_0)) + || context_p->last_cbc_opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_0) { value = 0; } else if (context_p->last_cbc_opcode == CBC_PUSH_NUMBER_POS_BYTE - || context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE)) + || context_p->last_cbc_opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE) { value = ((ecma_integer_value_t) context_p->last_cbc.value) + 1; } else { JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_NUMBER_NEG_BYTE - || context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE)); + || context_p->last_cbc_opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE); value = -((ecma_integer_value_t) context_p->last_cbc.value) - 1; } diff --git a/jerry-core/parser/js/js-lexer.h b/jerry-core/parser/js/js-lexer.h index 0f298f6db..85c87f28e 100644 --- a/jerry-core/parser/js/js-lexer.h +++ b/jerry-core/parser/js/js-lexer.h @@ -251,7 +251,7 @@ typedef enum ((((token_type) - LEXER_INCREASE) * 6) + CBC_PRE_INCR) #define LEXER_BINARY_OP_TOKEN_TO_OPCODE(token_type) \ - ((cbc_opcode_t) ((((token_type) - LEXER_BIT_OR) * 3) + CBC_BIT_OR)) + ((uint16_t) ((((token_type) - LEXER_BIT_OR) * 3) + CBC_BIT_OR)) #define LEXER_BINARY_LVALUE_OP_TOKEN_TO_OPCODE(token_type) \ ((cbc_opcode_t) ((((token_type) - LEXER_ASSIGN_ADD) * 2) + CBC_ASSIGN_ADD)) diff --git a/jerry-core/parser/js/js-parser-expr.c b/jerry-core/parser/js/js-parser-expr.c index bd87d677c..19d4a6e27 100644 --- a/jerry-core/parser/js/js-parser-expr.c +++ b/jerry-core/parser/js/js-parser-expr.c @@ -2885,12 +2885,14 @@ parser_append_binary_single_assignment_token (parser_context_t *context_p, /**< else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL)) { context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE); - assign_opcode = CBC_ASSIGN_SUPER; + parser_stack_push_uint8 (context_p, CBC_EXT_ASSIGN_SUPER); + assign_opcode = CBC_EXT_OPCODE; } else if (context_p->last_cbc_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_SUPER_PROP)) { context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE); - assign_opcode = CBC_ASSIGN_SUPER; + parser_stack_push_uint8 (context_p, CBC_EXT_ASSIGN_SUPER); + assign_opcode = CBC_EXT_OPCODE; } #endif /* JERRY_ESNEXT */ else @@ -2982,9 +2984,9 @@ parser_append_binary_token (parser_context_t *context_p) /**< context */ #if JERRY_ESNEXT parser_check_invalid_new_target (context_p, CBC_ASSIGN); parser_raise_error (context_p, PARSER_ERR_INVALID_LHS_ASSIGNMENT); -#else /* !JERRY_ES2015 */ +#else /* !JERRY_ESNEXT */ parser_emit_cbc_ext (context_p, CBC_EXT_THROW_REFERENCE_ERROR); -#endif /* JERRY_ES2015 */ +#endif /* JERRY_ESNEXT */ parser_emit_cbc (context_p, CBC_PUSH_PROP_REFERENCE); } @@ -3035,7 +3037,7 @@ parser_process_binary_opcodes (parser_context_t *context_p, /**< context */ while (true) { uint8_t token = context_p->stack_top_uint8; - cbc_opcode_t opcode; + uint16_t opcode; /* For left-to-right operators (all binary operators except assignment * and logical operators), the byte code is flushed if the precedence @@ -3054,22 +3056,34 @@ parser_process_binary_opcodes (parser_context_t *context_p, /**< context */ if (token == LEXER_ASSIGN) { - opcode = (cbc_opcode_t) context_p->stack_top_uint8; - parser_stack_pop_uint8 (context_p); - uint16_t index = PARSER_INVALID_LITERAL_INDEX; + opcode = context_p->stack_top_uint8; - if (cbc_flags[opcode] & CBC_HAS_LITERAL_ARG) +#if JERRY_ESNEXT + if (JERRY_UNLIKELY (opcode == CBC_EXT_OPCODE)) { - 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_INIT_ARG_OR_CATCH - || opcode == CBC_INIT_LET - || opcode == CBC_INIT_CONST); + parser_stack_pop_uint8 (context_p); + JERRY_ASSERT (context_p->stack_top_uint8 == CBC_EXT_ASSIGN_SUPER); + opcode = PARSER_TO_EXT_OPCODE (context_p->stack_top_uint8); + parser_stack_pop_uint8 (context_p); + } + else +#endif /* JERRY_ESNEXT */ + { + parser_stack_pop_uint8 (context_p); - index = parser_stack_pop_uint16 (context_p); + if (cbc_flags[opcode] & CBC_HAS_LITERAL_ARG) + { + 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_INIT_ARG_OR_CATCH + || opcode == CBC_INIT_LET + || opcode == CBC_INIT_CONST); + + index = parser_stack_pop_uint16 (context_p); + } } #if JERRY_ESNEXT @@ -3182,7 +3196,7 @@ parser_process_binary_opcodes (parser_context_t *context_p, /**< context */ continue; } } - parser_emit_cbc (context_p, (uint16_t) opcode); + parser_emit_cbc (context_p, opcode); } } /* parser_process_binary_opcodes */ diff --git a/jerry-core/parser/js/js-parser-internal.h b/jerry-core/parser/js/js-parser-internal.h index 3ab998deb..bda679dc6 100644 --- a/jerry-core/parser/js/js-parser-internal.h +++ b/jerry-core/parser/js/js-parser-internal.h @@ -274,12 +274,8 @@ typedef struct || (opcode) == CBC_PUSH_TWO_LITERALS \ || (opcode) == CBC_PUSH_THREE_LITERALS) #define PARSER_IS_PUSH_NUMBER(opcode) \ - ((opcode) == CBC_PUSH_NUMBER_0 \ - || (opcode) == CBC_PUSH_NUMBER_POS_BYTE \ - || (opcode) == CBC_PUSH_NUMBER_NEG_BYTE \ - || (opcode) == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_0) \ - || (opcode) == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE) \ - || (opcode) == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE)) + ((opcode) >= CBC_PUSH_NUMBER_0 \ + && (opcode) <= CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE) #define PARSER_IS_MUTABLE_PUSH_LITERAL(opcode) \ ((opcode) >= CBC_PUSH_LITERAL && (opcode) <= CBC_PUSH_THIS_LITERAL) diff --git a/jerry-core/parser/js/js-parser-util.c b/jerry-core/parser/js/js-parser-util.c index d7beaba43..492f42bad 100644 --- a/jerry-core/parser/js/js-parser-util.c +++ b/jerry-core/parser/js/js-parser-util.c @@ -250,13 +250,13 @@ parser_flush_cbc (parser_context_t *context_p) /**< context */ if (flags & CBC_HAS_BYTE_ARG) { - if ((last_opcode == CBC_PUSH_NUMBER_POS_BYTE) - || (last_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE))) + if (last_opcode == CBC_PUSH_NUMBER_POS_BYTE + || last_opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE) { JERRY_DEBUG_MSG (" number:%d", (int) context_p->last_cbc.value + 1); } - else if ((last_opcode == CBC_PUSH_NUMBER_NEG_BYTE) - || (last_opcode == PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE))) + else if (last_opcode == CBC_PUSH_NUMBER_NEG_BYTE + || last_opcode == CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE) { JERRY_DEBUG_MSG (" number:%d", -((int) context_p->last_cbc.value + 1)); } @@ -424,7 +424,7 @@ parser_emit_cbc_push_number (parser_context_t *context_p, /**< context */ return; } - context_p->last_cbc_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_0); + context_p->last_cbc_opcode = CBC_PUSH_LITERAL_PUSH_NUMBER_0; context_p->last_cbc.literal_index = lit_value; return; } @@ -440,8 +440,8 @@ parser_emit_cbc_push_number (parser_context_t *context_p, /**< context */ } else { - opcode = PARSER_TO_EXT_OPCODE (is_negative_number ? CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE - : CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE); + opcode = (is_negative_number ? CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE + : CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE); JERRY_ASSERT (CBC_STACK_ADJUST_VALUE (PARSER_GET_FLAGS (opcode)) == 2); context_p->last_cbc.literal_index = lit_value;