From 03b8e310c2eb83f29afe13fa297ba4d2ab358cc8 Mon Sep 17 00:00:00 2001 From: Robert Fancsik Date: Wed, 5 Jan 2022 16:44:35 +0100 Subject: [PATCH] Rework VM dispatch JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik robert.fancsik@h-lab.eu --- docs/05.PORT-API.md | 1 - jerry-core/include/jerryscript-port.h | 1 - jerry-core/jrt/jrt-fatals.c | 5 - jerry-core/parser/js/byte-code.c | 4 +- jerry-core/parser/js/byte-code.h | 935 ++++------ jerry-core/parser/js/js-parser-expr.c | 4 +- jerry-core/vm/opcodes.c | 225 +-- jerry-core/vm/opcodes.h | 32 +- jerry-core/vm/vm.c | 2317 +++++++++++++++++-------- jerry-core/vm/vm.h | 458 +---- 10 files changed, 2086 insertions(+), 1896 deletions(-) diff --git a/docs/05.PORT-API.md b/docs/05.PORT-API.md index 10eca0a95c..82c0b4c96c 100644 --- a/docs/05.PORT-API.md +++ b/docs/05.PORT-API.md @@ -26,7 +26,6 @@ typedef enum { ERR_OUT_OF_MEMORY = 10, ERR_REF_COUNT_LIMIT = 12, - ERR_DISABLED_BYTE_CODE = 13, ERR_FAILED_INTERNAL_ASSERTION = 120 } jerry_fatal_code_t; ``` diff --git a/jerry-core/include/jerryscript-port.h b/jerry-core/include/jerryscript-port.h index 91bb3fe398..843b42b50f 100644 --- a/jerry-core/include/jerryscript-port.h +++ b/jerry-core/include/jerryscript-port.h @@ -46,7 +46,6 @@ typedef enum { ERR_OUT_OF_MEMORY = 10, ERR_REF_COUNT_LIMIT = 12, - ERR_DISABLED_BYTE_CODE = 13, ERR_UNTERMINATED_GC_LOOPS = 14, ERR_FAILED_INTERNAL_ASSERTION = 120 } jerry_fatal_code_t; diff --git a/jerry-core/jrt/jrt-fatals.c b/jerry-core/jrt/jrt-fatals.c index 36c0227736..c1864ae90d 100644 --- a/jerry-core/jrt/jrt-fatals.c +++ b/jerry-core/jrt/jrt-fatals.c @@ -47,11 +47,6 @@ jerry_fatal (jerry_fatal_code_t code) /**< status code */ JERRY_ERROR_MSG ("Error: ERR_UNTERMINATED_GC_LOOPS\n"); break; } - case ERR_DISABLED_BYTE_CODE: - { - JERRY_ERROR_MSG ("Error: ERR_DISABLED_BYTE_CODE\n"); - break; - } case ERR_FAILED_INTERNAL_ASSERTION: { JERRY_ERROR_MSG ("Error: ERR_FAILED_INTERNAL_ASSERTION\n"); diff --git a/jerry-core/parser/js/byte-code.c b/jerry-core/parser/js/byte-code.c index 4ba63cd3d1..429ad1cea5 100644 --- a/jerry-core/parser/js/byte-code.c +++ b/jerry-core/parser/js/byte-code.c @@ -45,7 +45,7 @@ JERRY_STATIC_ASSERT (CBC_EXT_END == 167, number_of_cbc_ext_opcodes_changed); /** * Compact bytecode definition */ -#define CBC_OPCODE(arg1, arg2, arg3, arg4) ((arg2) | (((arg3) + CBC_STACK_ADJUST_BASE) << CBC_STACK_ADJUST_SHIFT)), +#define CBC_OPCODE(arg1, arg2, arg3) ((arg2) | (((arg3) + CBC_STACK_ADJUST_BASE) << CBC_STACK_ADJUST_SHIFT)), /** * Flags of the opcodes. @@ -63,7 +63,7 @@ const uint8_t cbc_ext_flags[] = { CBC_EXT_OPCODE_LIST }; #if JERRY_PARSER_DUMP_BYTE_CODE -#define CBC_OPCODE(arg1, arg2, arg3, arg4) #arg1, +#define CBC_OPCODE(arg1, arg2, arg3) #arg1, /** * Names of the opcodes. diff --git a/jerry-core/parser/js/byte-code.h b/jerry-core/parser/js/byte-code.h index 18d5325e9d..e57e5cbe1b 100644 --- a/jerry-core/parser/js/byte-code.h +++ b/jerry-core/parser/js/byte-code.h @@ -86,40 +86,22 @@ == (cbc_ext_flags[PARSER_GET_EXT_OPCODE (op2)] & CBC_ARG_TYPES)) \ : ((cbc_flags[op1] & CBC_ARG_TYPES) == (cbc_flags[op2] & CBC_ARG_TYPES))) -#define CBC_UNARY_OPERATION(name, group) \ - CBC_OPCODE (name, CBC_NO_FLAG, 0, (VM_OC_##group) | VM_OC_GET_STACK | VM_OC_PUT_STACK) \ - CBC_OPCODE (name##_LITERAL, CBC_HAS_LITERAL_ARG, 1, (VM_OC_##group) | VM_OC_GET_LITERAL | VM_OC_PUT_STACK) - -#define CBC_BINARY_OPERATION(name, group) \ - CBC_OPCODE (name, CBC_NO_FLAG, -1, (VM_OC_##group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \ - CBC_OPCODE (name##_RIGHT_LITERAL, \ - CBC_HAS_LITERAL_ARG, \ - 0, \ - (VM_OC_##group) | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK) \ - CBC_OPCODE (name##_TWO_LITERALS, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 1, \ - (VM_OC_##group) | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK) - -#define CBC_UNARY_LVALUE_OPERATION(name, group) \ - CBC_OPCODE (name, CBC_NO_FLAG, -2, (VM_OC_PROP_##group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_REFERENCE) \ - CBC_OPCODE (name##_PUSH_RESULT, \ - CBC_NO_FLAG, \ - -1, \ - (VM_OC_PROP_##group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK) \ - CBC_OPCODE (name##_BLOCK, \ - CBC_NO_FLAG, \ - -2, \ - (VM_OC_PROP_##group) | VM_OC_GET_STACK_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK) \ - CBC_OPCODE (name##_IDENT, CBC_HAS_LITERAL_ARG, 0, (VM_OC_##group) | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT) \ - CBC_OPCODE (name##_IDENT_PUSH_RESULT, \ - CBC_HAS_LITERAL_ARG, \ - 1, \ - (VM_OC_##group) | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_STACK) \ - CBC_OPCODE (name##_IDENT_BLOCK, \ - CBC_HAS_LITERAL_ARG, \ - 0, \ - (VM_OC_##group) | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_BLOCK) +#define CBC_UNARY_OPERATION(name) \ + CBC_OPCODE (name, CBC_NO_FLAG, 0) \ + CBC_OPCODE (name##_LITERAL, CBC_HAS_LITERAL_ARG, 1) + +#define CBC_BINARY_OPERATION(name) \ + CBC_OPCODE (name, CBC_NO_FLAG, -1) \ + CBC_OPCODE (name##_RIGHT_LITERAL, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (name##_TWO_LITERALS, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 1) + +#define CBC_UNARY_LVALUE_OPERATION(name) \ + CBC_OPCODE (name, CBC_NO_FLAG, -2) \ + CBC_OPCODE (name##_PUSH_RESULT, CBC_NO_FLAG, -1) \ + CBC_OPCODE (name##_BLOCK, CBC_NO_FLAG, -2) \ + CBC_OPCODE (name##_IDENT, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (name##_IDENT_PUSH_RESULT, CBC_HAS_LITERAL_ARG, 1) \ + CBC_OPCODE (name##_IDENT_BLOCK, CBC_HAS_LITERAL_ARG, 0) #define CBC_UNARY_LVALUE_WITH_IDENT 3 @@ -166,15 +148,15 @@ * The offset bytes are encoded in higher to lower order. */ -#define CBC_FORWARD_BRANCH(name, stack, vm_oc) \ - CBC_OPCODE (name, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH) \ - CBC_OPCODE (name##_2, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH) \ - CBC_OPCODE (name##_3, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH) +#define CBC_FORWARD_BRANCH(name, stack) \ + CBC_OPCODE (name, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack) \ + CBC_OPCODE (name##_2, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack) \ + CBC_OPCODE (name##_3, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack) -#define CBC_BACKWARD_BRANCH(name, stack, vm_oc) \ - CBC_OPCODE (name, CBC_HAS_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH | VM_OC_BACKWARD_BRANCH) \ - CBC_OPCODE (name##_2, CBC_HAS_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH | VM_OC_BACKWARD_BRANCH) \ - CBC_OPCODE (name##_3, CBC_HAS_BRANCH_ARG, stack, (vm_oc) | VM_OC_GET_BRANCH | VM_OC_BACKWARD_BRANCH) +#define CBC_BACKWARD_BRANCH(name, stack) \ + CBC_OPCODE (name, CBC_HAS_BRANCH_ARG, stack) \ + CBC_OPCODE (name##_2, CBC_HAS_BRANCH_ARG, stack) \ + CBC_OPCODE (name##_3, CBC_HAS_BRANCH_ARG, stack) #define CBC_BRANCH_OFFSET_LENGTH(opcode) ((opcode) &0x3) @@ -216,542 +198,345 @@ /** * Opcode definitions. */ -#define CBC_OPCODE_LIST \ - /* Branch opcodes first. Some other opcodes are mixed. */ \ - CBC_OPCODE (CBC_EXT_OPCODE, CBC_NO_FLAG, 0, VM_OC_NONE) \ - CBC_FORWARD_BRANCH (CBC_JUMP_FORWARD, 0, VM_OC_JUMP) \ - CBC_OPCODE (CBC_POP, CBC_NO_FLAG, -1, VM_OC_POP) \ - CBC_BACKWARD_BRANCH (CBC_JUMP_BACKWARD, 0, VM_OC_JUMP) \ - CBC_OPCODE (CBC_POP_BLOCK, CBC_NO_FLAG, -1, VM_OC_POP_BLOCK | VM_OC_PUT_BLOCK) \ - CBC_FORWARD_BRANCH (CBC_BRANCH_IF_TRUE_FORWARD, -1, VM_OC_BRANCH_IF_TRUE) \ - CBC_OPCODE (CBC_THROW, CBC_NO_FLAG, -1, VM_OC_THROW | VM_OC_GET_STACK) \ - CBC_BACKWARD_BRANCH (CBC_BRANCH_IF_TRUE_BACKWARD, -1, VM_OC_BRANCH_IF_TRUE) \ - CBC_OPCODE (CBC_CONTEXT_END, CBC_NO_FLAG, 0, VM_OC_CONTEXT_END) \ - CBC_FORWARD_BRANCH (CBC_BRANCH_IF_FALSE_FORWARD, -1, VM_OC_BRANCH_IF_FALSE) \ - CBC_OPCODE (CBC_CREATE_OBJECT, CBC_NO_FLAG, 1, VM_OC_PUSH_OBJECT | VM_OC_PUT_STACK) \ - CBC_BACKWARD_BRANCH (CBC_BRANCH_IF_FALSE_BACKWARD, -1, VM_OC_BRANCH_IF_FALSE) \ - CBC_OPCODE (CBC_SET_PROPERTY, \ - CBC_HAS_LITERAL_ARG, \ - -1, \ - VM_OC_SET_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_LITERAL) \ - CBC_FORWARD_BRANCH (CBC_JUMP_FORWARD_EXIT_CONTEXT, 0, VM_OC_JUMP_AND_EXIT_CONTEXT) \ - CBC_OPCODE (CBC_CREATE_ARRAY, CBC_NO_FLAG, 1, VM_OC_PUSH_ARRAY | VM_OC_PUT_STACK) \ - CBC_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_TRUE, -1, VM_OC_BRANCH_IF_LOGICAL_TRUE) \ - CBC_OPCODE (CBC_ARRAY_APPEND, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_APPEND_ARRAY) \ - CBC_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_FALSE, -1, VM_OC_BRANCH_IF_LOGICAL_FALSE) \ - CBC_OPCODE (CBC_PUSH_ELISION, CBC_NO_FLAG, 1, VM_OC_PUSH_ELISON | VM_OC_PUT_STACK) \ - CBC_FORWARD_BRANCH (CBC_BRANCH_IF_STRICT_EQUAL, -1, VM_OC_BRANCH_IF_STRICT_EQUAL) \ - CBC_OPCODE (CBC_PUSH_NULL, CBC_NO_FLAG, 1, VM_OC_PUSH_NULL | VM_OC_PUT_STACK) \ - CBC_FORWARD_BRANCH (CBC_BLOCK_CREATE_CONTEXT, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION, VM_OC_BLOCK_CREATE_CONTEXT) \ - \ - /* Basic opcodes. Note: These 4 opcodes must me in this order */ \ - CBC_OPCODE (CBC_PUSH_LITERAL, CBC_HAS_LITERAL_ARG, 1, VM_OC_PUSH | VM_OC_GET_LITERAL) \ - CBC_OPCODE (CBC_PUSH_TWO_LITERALS, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 2, \ - VM_OC_PUSH_TWO | VM_OC_GET_LITERAL_LITERAL) \ - CBC_OPCODE (CBC_PUSH_THIS_LITERAL, CBC_HAS_LITERAL_ARG, 2, VM_OC_PUSH_TWO | VM_OC_GET_THIS_LITERAL) \ - CBC_OPCODE (CBC_PUSH_THREE_LITERALS, CBC_HAS_LITERAL_ARG2, 3, VM_OC_PUSH_THREE | VM_OC_GET_LITERAL_LITERAL) \ - CBC_OPCODE (CBC_PUSH_UNDEFINED, CBC_NO_FLAG, 1, VM_OC_PUSH_UNDEFINED | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_PUSH_TRUE, CBC_NO_FLAG, 1, VM_OC_PUSH_TRUE | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_PUSH_FALSE, CBC_NO_FLAG, 1, VM_OC_PUSH_FALSE | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_PUSH_THIS, CBC_NO_FLAG, 1, VM_OC_PUSH_THIS | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_PUSH_NUMBER_0, CBC_NO_FLAG, 1, VM_OC_PUSH_0 | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_PUSH_NUMBER_POS_BYTE, CBC_HAS_BYTE_ARG, 1, 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) \ - CBC_OPCODE (CBC_PUSH_PROP_LITERAL, \ - CBC_HAS_LITERAL_ARG, \ - 0, \ - VM_OC_PROP_GET | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_PUSH_PROP_LITERAL_LITERAL, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 1, \ - VM_OC_PROP_GET | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_PUSH_PROP_THIS_LITERAL, \ - CBC_HAS_LITERAL_ARG, \ - 1, \ - VM_OC_PROP_GET | VM_OC_GET_THIS_LITERAL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_PUSH_IDENT_REFERENCE, CBC_HAS_LITERAL_ARG, 3, VM_OC_IDENT_REFERENCE | VM_OC_PUT_STACK) \ - /* Note: These 4 opcodes must me in this order */ \ - CBC_OPCODE (CBC_PUSH_PROP_REFERENCE, CBC_NO_FLAG, 1, VM_OC_PROP_REFERENCE | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_PUSH_PROP_LITERAL_REFERENCE, \ - CBC_HAS_LITERAL_ARG, \ - 2, \ - VM_OC_PROP_REFERENCE | VM_OC_GET_LITERAL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_PUSH_PROP_LITERAL_LITERAL_REFERENCE, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 3, \ - VM_OC_PROP_REFERENCE | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_PUSH_PROP_THIS_LITERAL_REFERENCE, \ - CBC_HAS_LITERAL_ARG, \ - 3, \ - VM_OC_PROP_REFERENCE | VM_OC_GET_THIS_LITERAL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_NEW | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_NEW0, CBC_NO_FLAG, 0, VM_OC_NEW | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_NEW1, CBC_NO_FLAG, -1, VM_OC_NEW | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_EVAL, CBC_NO_FLAG, 0, VM_OC_EVAL) \ - CBC_OPCODE (CBC_CHECK_VAR, CBC_HAS_LITERAL_ARG, 0, VM_OC_CHECK_VAR) \ - CBC_OPCODE (CBC_CHECK_LET, CBC_HAS_LITERAL_ARG, 0, VM_OC_CHECK_LET) \ - CBC_OPCODE (CBC_CREATE_VAR, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_BINDING) \ - CBC_OPCODE (CBC_CREATE_LET, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_BINDING) \ - CBC_OPCODE (CBC_CREATE_CONST, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_BINDING) \ - CBC_OPCODE (CBC_CREATE_LOCAL, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_BINDING) \ - 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, VM_OC_VAR_EVAL) \ - CBC_OPCODE (CBC_SET_VAR_FUNC, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 0, \ - VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT) \ - CBC_OPCODE (CBC_SET_BYTECODE_PTR, CBC_NO_FLAG, 0, VM_OC_SET_BYTECODE_PTR) \ - CBC_OPCODE (CBC_RETURN, CBC_NO_FLAG, -1, VM_OC_RETURN | VM_OC_GET_STACK) \ - CBC_OPCODE (CBC_RETURN_FUNCTION_END, CBC_NO_FLAG, 0, VM_OC_RETURN_FUNCTION_END) \ - CBC_OPCODE (CBC_RETURN_WITH_LITERAL, CBC_HAS_LITERAL_ARG, 0, VM_OC_RETURN | VM_OC_GET_LITERAL) \ - CBC_OPCODE (CBC_SET_LITERAL_PROPERTY, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 0, \ - VM_OC_SET_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_LITERAL_LITERAL) \ - CBC_OPCODE (CBC_COPY_TO_GLOBAL, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 0, \ - VM_OC_COPY_TO_GLOBAL | VM_OC_GET_LITERAL) \ - CBC_OPCODE (CBC_BREAKPOINT_ENABLED, CBC_NO_FLAG, 0, VM_OC_BREAKPOINT_ENABLED) \ - CBC_OPCODE (CBC_BREAKPOINT_DISABLED, CBC_NO_FLAG, 0, VM_OC_BREAKPOINT_DISABLED) \ - \ - /* Unary opcodes. */ \ - CBC_UNARY_OPERATION (CBC_PLUS, PLUS) \ - CBC_UNARY_OPERATION (CBC_NEGATE, MINUS) \ - CBC_UNARY_OPERATION (CBC_LOGICAL_NOT, NOT) \ - CBC_UNARY_OPERATION (CBC_BIT_NOT, BIT_NOT) \ - CBC_UNARY_OPERATION (CBC_VOID, VOID) \ - CBC_OPCODE (CBC_TYPEOF, CBC_NO_FLAG, 0, VM_OC_TYPEOF | VM_OC_GET_STACK | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_TYPEOF_IDENT, CBC_HAS_LITERAL_ARG, 1, VM_OC_TYPEOF_IDENT | VM_OC_PUT_STACK) \ - \ - /* Binary opcodes. */ \ - CBC_BINARY_OPERATION (CBC_BIT_OR, BIT_OR) \ - CBC_BINARY_OPERATION (CBC_BIT_XOR, BIT_XOR) \ - CBC_BINARY_OPERATION (CBC_BIT_AND, BIT_AND) \ - CBC_BINARY_OPERATION (CBC_EQUAL, EQUAL) \ - CBC_BINARY_OPERATION (CBC_NOT_EQUAL, NOT_EQUAL) \ - CBC_BINARY_OPERATION (CBC_STRICT_EQUAL, STRICT_EQUAL) \ - CBC_BINARY_OPERATION (CBC_STRICT_NOT_EQUAL, STRICT_NOT_EQUAL) \ - CBC_BINARY_OPERATION (CBC_LESS, LESS) \ - CBC_BINARY_OPERATION (CBC_GREATER, GREATER) \ - CBC_BINARY_OPERATION (CBC_LESS_EQUAL, LESS_EQUAL) \ - CBC_BINARY_OPERATION (CBC_GREATER_EQUAL, GREATER_EQUAL) \ - CBC_BINARY_OPERATION (CBC_IN, IN) \ - CBC_BINARY_OPERATION (CBC_INSTANCEOF, INSTANCEOF) \ - CBC_BINARY_OPERATION (CBC_LEFT_SHIFT, LEFT_SHIFT) \ - CBC_BINARY_OPERATION (CBC_RIGHT_SHIFT, RIGHT_SHIFT) \ - CBC_BINARY_OPERATION (CBC_UNS_RIGHT_SHIFT, UNS_RIGHT_SHIFT) \ - CBC_BINARY_OPERATION (CBC_ADD, ADD) \ - CBC_BINARY_OPERATION (CBC_SUBTRACT, SUB) \ - CBC_BINARY_OPERATION (CBC_MULTIPLY, MUL) \ - CBC_BINARY_OPERATION (CBC_DIVIDE, DIV) \ - CBC_BINARY_OPERATION (CBC_MODULO, MOD) \ - CBC_BINARY_OPERATION (CBC_EXPONENTIATION, EXP) \ - \ - /* Unary lvalue opcodes. */ \ - CBC_OPCODE (CBC_DELETE_PUSH_RESULT, CBC_NO_FLAG, -1, VM_OC_PROP_DELETE | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_DELETE_IDENT_PUSH_RESULT, CBC_HAS_LITERAL_ARG, 1, VM_OC_DELETE | VM_OC_PUT_STACK) \ - CBC_UNARY_LVALUE_OPERATION (CBC_PRE_INCR, PRE_INCR) \ - CBC_UNARY_LVALUE_OPERATION (CBC_PRE_DECR, PRE_DECR) \ - CBC_UNARY_LVALUE_OPERATION (CBC_POST_INCR, POST_INCR) \ - CBC_UNARY_LVALUE_OPERATION (CBC_POST_DECR, POST_DECR) \ - \ - /* Call opcodes. */ \ - CBC_OPCODE (CBC_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_CALL) \ - CBC_OPCODE (CBC_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_CALL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_CALL | VM_OC_PUT_BLOCK) \ - CBC_OPCODE (CBC_CALL_PROP, CBC_HAS_POP_STACK_BYTE_ARG, -3, VM_OC_CALL) \ - CBC_OPCODE (CBC_CALL_PROP_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, -2, VM_OC_CALL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_CALL_PROP_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -3, VM_OC_CALL | VM_OC_PUT_BLOCK) \ - CBC_OPCODE (CBC_CALL0, CBC_NO_FLAG, -1, VM_OC_CALL) \ - CBC_OPCODE (CBC_CALL0_PUSH_RESULT, CBC_NO_FLAG, 0, VM_OC_CALL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_CALL0_BLOCK, CBC_NO_FLAG, -1, VM_OC_CALL | VM_OC_PUT_BLOCK) \ - CBC_OPCODE (CBC_CALL0_PROP, CBC_NO_FLAG, -3, VM_OC_CALL) \ - CBC_OPCODE (CBC_CALL0_PROP_PUSH_RESULT, CBC_NO_FLAG, -2, VM_OC_CALL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_CALL0_PROP_BLOCK, CBC_NO_FLAG, -3, VM_OC_CALL | VM_OC_PUT_BLOCK) \ - CBC_OPCODE (CBC_CALL1, CBC_NO_FLAG, -2, VM_OC_CALL) \ - CBC_OPCODE (CBC_CALL1_PUSH_RESULT, CBC_NO_FLAG, -1, VM_OC_CALL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_CALL1_BLOCK, CBC_NO_FLAG, -2, VM_OC_CALL | VM_OC_PUT_BLOCK) \ - CBC_OPCODE (CBC_CALL1_PROP, CBC_NO_FLAG, -4, VM_OC_CALL) \ - CBC_OPCODE (CBC_CALL1_PROP_PUSH_RESULT, CBC_NO_FLAG, -3, VM_OC_CALL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_CALL1_PROP_BLOCK, CBC_NO_FLAG, -4, VM_OC_CALL | VM_OC_PUT_BLOCK) \ - CBC_OPCODE (CBC_CALL2, CBC_NO_FLAG, -3, VM_OC_CALL) \ - CBC_OPCODE (CBC_CALL2_PUSH_RESULT, CBC_NO_FLAG, -2, VM_OC_CALL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_CALL2_BLOCK, CBC_NO_FLAG, -3, VM_OC_CALL | VM_OC_PUT_BLOCK) \ - CBC_OPCODE (CBC_CALL2_PROP, CBC_NO_FLAG, -4, VM_OC_CALL) \ - CBC_OPCODE (CBC_CALL2_PROP_PUSH_RESULT, CBC_NO_FLAG, -3, VM_OC_CALL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_CALL2_PROP_BLOCK, CBC_NO_FLAG, -4, VM_OC_CALL | VM_OC_PUT_BLOCK) \ - \ - /* Binary assignment opcodes. */ \ - CBC_OPCODE (CBC_ASSIGN, CBC_NO_FLAG, -3, VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_REFERENCE) \ - CBC_OPCODE (CBC_ASSIGN_PUSH_RESULT, \ - CBC_NO_FLAG, \ - -2, \ - VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_ASSIGN_BLOCK, \ - CBC_NO_FLAG, \ - -3, \ - VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK) \ - CBC_OPCODE (CBC_ASSIGN_SET_IDENT, CBC_HAS_LITERAL_ARG, -1, VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_IDENT) \ - CBC_OPCODE (CBC_ASSIGN_SET_IDENT_PUSH_RESULT, \ - CBC_HAS_LITERAL_ARG, \ - 0, \ - VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_IDENT | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_ASSIGN_SET_IDENT_BLOCK, \ - CBC_HAS_LITERAL_ARG, \ - -1, \ - VM_OC_ASSIGN | VM_OC_GET_STACK | VM_OC_PUT_IDENT | VM_OC_PUT_BLOCK) \ - CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 0, \ - VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT) \ - CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT_PUSH_RESULT, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 1, \ - VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT_BLOCK, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 0, \ - VM_OC_ASSIGN | VM_OC_GET_LITERAL | VM_OC_PUT_IDENT | VM_OC_PUT_BLOCK) \ - CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL, \ - CBC_HAS_LITERAL_ARG, \ - -2, \ - VM_OC_ASSIGN_PROP | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE) \ - CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL_PUSH_RESULT, \ - CBC_HAS_LITERAL_ARG, \ - -1, \ - VM_OC_ASSIGN_PROP | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL_BLOCK, \ - CBC_HAS_LITERAL_ARG, \ - -2, \ - VM_OC_ASSIGN_PROP | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK) \ - CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL, \ - CBC_HAS_LITERAL_ARG, \ - -1, \ - VM_OC_ASSIGN_PROP_THIS | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE) \ - CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL_PUSH_RESULT, \ - CBC_HAS_LITERAL_ARG, \ - 0, \ - VM_OC_ASSIGN_PROP_THIS | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL_BLOCK, \ - CBC_HAS_LITERAL_ARG, \ - -1, \ - VM_OC_ASSIGN_PROP_THIS | VM_OC_GET_LITERAL | VM_OC_PUT_REFERENCE | VM_OC_PUT_BLOCK) \ - CBC_OPCODE (CBC_MOV_IDENT, CBC_HAS_LITERAL_ARG, -1, 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) \ - \ - /* Last opcode (not a real opcode). */ \ - CBC_OPCODE (CBC_END, CBC_NO_FLAG, 0, VM_OC_NONE) +#define CBC_OPCODE_LIST \ + /* Branch opcodes first. Some other opcodes are mixed. */ \ + CBC_OPCODE (CBC_EXT_OPCODE, CBC_NO_FLAG, 0) \ + CBC_FORWARD_BRANCH (CBC_JUMP_FORWARD, 0) \ + CBC_OPCODE (CBC_POP, CBC_NO_FLAG, -1) \ + CBC_BACKWARD_BRANCH (CBC_JUMP_BACKWARD, 0) \ + CBC_OPCODE (CBC_POP_BLOCK, CBC_NO_FLAG, -1) \ + CBC_FORWARD_BRANCH (CBC_BRANCH_IF_TRUE_FORWARD, -1) \ + CBC_OPCODE (CBC_THROW, CBC_NO_FLAG, -1) \ + CBC_BACKWARD_BRANCH (CBC_BRANCH_IF_TRUE_BACKWARD, -1) \ + CBC_OPCODE (CBC_CONTEXT_END, CBC_NO_FLAG, 0) \ + CBC_FORWARD_BRANCH (CBC_BRANCH_IF_FALSE_FORWARD, -1) \ + CBC_OPCODE (CBC_CREATE_OBJECT, CBC_NO_FLAG, 1) \ + CBC_BACKWARD_BRANCH (CBC_BRANCH_IF_FALSE_BACKWARD, -1) \ + CBC_OPCODE (CBC_SET_PROPERTY, CBC_HAS_LITERAL_ARG, -1) \ + CBC_FORWARD_BRANCH (CBC_JUMP_FORWARD_EXIT_CONTEXT, 0) \ + CBC_OPCODE (CBC_CREATE_ARRAY, CBC_NO_FLAG, 1) \ + CBC_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_TRUE, -1) \ + CBC_OPCODE (CBC_ARRAY_APPEND, CBC_HAS_POP_STACK_BYTE_ARG, 0) \ + CBC_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_FALSE, -1) \ + CBC_OPCODE (CBC_PUSH_ELISION, CBC_NO_FLAG, 1) \ + CBC_FORWARD_BRANCH (CBC_BRANCH_IF_STRICT_EQUAL, -1) \ + CBC_OPCODE (CBC_PUSH_NULL, CBC_NO_FLAG, 1) \ + CBC_FORWARD_BRANCH (CBC_BLOCK_CREATE_CONTEXT, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION) \ + \ + /* Basic opcodes. Note: These 4 opcodes must me in this order */ \ + CBC_OPCODE (CBC_PUSH_LITERAL, CBC_HAS_LITERAL_ARG, 1) \ + CBC_OPCODE (CBC_PUSH_TWO_LITERALS, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 2) \ + CBC_OPCODE (CBC_PUSH_THIS_LITERAL, CBC_HAS_LITERAL_ARG, 2) \ + CBC_OPCODE (CBC_PUSH_THREE_LITERALS, CBC_HAS_LITERAL_ARG2, 3) \ + CBC_OPCODE (CBC_PUSH_UNDEFINED, CBC_NO_FLAG, 1) \ + CBC_OPCODE (CBC_PUSH_TRUE, CBC_NO_FLAG, 1) \ + CBC_OPCODE (CBC_PUSH_FALSE, CBC_NO_FLAG, 1) \ + CBC_OPCODE (CBC_PUSH_THIS, CBC_NO_FLAG, 1) \ + CBC_OPCODE (CBC_PUSH_NUMBER_0, CBC_NO_FLAG, 1) \ + CBC_OPCODE (CBC_PUSH_NUMBER_POS_BYTE, CBC_HAS_BYTE_ARG, 1) \ + CBC_OPCODE (CBC_PUSH_NUMBER_NEG_BYTE, CBC_HAS_BYTE_ARG, 1) \ + CBC_OPCODE (CBC_PUSH_LITERAL_PUSH_NUMBER_0, CBC_HAS_LITERAL_ARG, 2) \ + CBC_OPCODE (CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE, CBC_HAS_LITERAL_ARG | CBC_HAS_BYTE_ARG, 2) \ + CBC_OPCODE (CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE, CBC_HAS_LITERAL_ARG | CBC_HAS_BYTE_ARG, 2) \ + /* Note: These 4 opcodes must me in this order */ \ + CBC_OPCODE (CBC_PUSH_PROP, CBC_NO_FLAG, -1) \ + CBC_OPCODE (CBC_PUSH_PROP_LITERAL, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_PUSH_PROP_LITERAL_LITERAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 1) \ + CBC_OPCODE (CBC_PUSH_PROP_THIS_LITERAL, CBC_HAS_LITERAL_ARG, 1) \ + CBC_OPCODE (CBC_PUSH_IDENT_REFERENCE, CBC_HAS_LITERAL_ARG, 3) \ + /* Note: These 4 opcodes must me in this order */ \ + CBC_OPCODE (CBC_PUSH_PROP_REFERENCE, CBC_NO_FLAG, 1) \ + CBC_OPCODE (CBC_PUSH_PROP_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG, 2) \ + CBC_OPCODE (CBC_PUSH_PROP_LITERAL_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 3) \ + CBC_OPCODE (CBC_PUSH_PROP_THIS_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG, 3) \ + CBC_OPCODE (CBC_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0) \ + CBC_OPCODE (CBC_NEW0, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_NEW1, CBC_NO_FLAG, -1) \ + CBC_OPCODE (CBC_EVAL, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_CHECK_VAR, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_CHECK_LET, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_CREATE_VAR, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_CREATE_LET, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_CREATE_CONST, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_CREATE_LOCAL, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_INIT_ARG_OR_CATCH, CBC_HAS_LITERAL_ARG, -1) \ + CBC_OPCODE (CBC_INIT_LET, CBC_HAS_LITERAL_ARG, -1) \ + CBC_OPCODE (CBC_INIT_CONST, CBC_HAS_LITERAL_ARG, -1) \ + CBC_OPCODE (CBC_INIT_ARG_OR_FUNC, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + CBC_OPCODE (CBC_CREATE_VAR_EVAL, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_CREATE_VAR_FUNC_EVAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + CBC_OPCODE (CBC_SET_VAR_FUNC, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + CBC_OPCODE (CBC_SET_BYTECODE_PTR, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_RETURN, CBC_NO_FLAG, -1) \ + CBC_OPCODE (CBC_RETURN_FUNCTION_END, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_RETURN_WITH_LITERAL, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_SET_LITERAL_PROPERTY, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + CBC_OPCODE (CBC_COPY_TO_GLOBAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + CBC_OPCODE (CBC_BREAKPOINT_ENABLED, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_BREAKPOINT_DISABLED, CBC_NO_FLAG, 0) \ + \ + /* Unary opcodes. */ \ + CBC_UNARY_OPERATION (CBC_PLUS) \ + CBC_UNARY_OPERATION (CBC_NEGATE) \ + CBC_UNARY_OPERATION (CBC_LOGICAL_NOT) \ + CBC_UNARY_OPERATION (CBC_BIT_NOT) \ + CBC_UNARY_OPERATION (CBC_VOID) \ + CBC_OPCODE (CBC_TYPEOF, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_TYPEOF_IDENT, CBC_HAS_LITERAL_ARG, 1) \ + \ + /* Binary opcodes. */ \ + CBC_BINARY_OPERATION (CBC_BIT_OR) \ + CBC_BINARY_OPERATION (CBC_BIT_XOR) \ + CBC_BINARY_OPERATION (CBC_BIT_AND) \ + CBC_BINARY_OPERATION (CBC_EQUAL) \ + CBC_BINARY_OPERATION (CBC_NOT_EQUAL) \ + CBC_BINARY_OPERATION (CBC_STRICT_EQUAL) \ + CBC_BINARY_OPERATION (CBC_STRICT_NOT_EQUAL) \ + CBC_BINARY_OPERATION (CBC_LESS) \ + CBC_BINARY_OPERATION (CBC_GREATER) \ + CBC_BINARY_OPERATION (CBC_LESS_EQUAL) \ + CBC_BINARY_OPERATION (CBC_GREATER_EQUAL) \ + CBC_BINARY_OPERATION (CBC_IN) \ + CBC_BINARY_OPERATION (CBC_INSTANCEOF) \ + CBC_BINARY_OPERATION (CBC_LEFT_SHIFT) \ + CBC_BINARY_OPERATION (CBC_RIGHT_SHIFT) \ + CBC_BINARY_OPERATION (CBC_UNS_RIGHT_SHIFT) \ + CBC_BINARY_OPERATION (CBC_ADD) \ + CBC_BINARY_OPERATION (CBC_SUBTRACT) \ + CBC_BINARY_OPERATION (CBC_MULTIPLY) \ + CBC_BINARY_OPERATION (CBC_DIVIDE) \ + CBC_BINARY_OPERATION (CBC_MODULO) \ + CBC_BINARY_OPERATION (CBC_EXPONENTIATION) \ + \ + /* Unary lvalue opcodes. */ \ + CBC_OPCODE (CBC_DELETE_PUSH_RESULT, CBC_NO_FLAG, -1) \ + CBC_OPCODE (CBC_DELETE_IDENT_PUSH_RESULT, CBC_HAS_LITERAL_ARG, 1) \ + CBC_UNARY_LVALUE_OPERATION (CBC_PRE_INCR) \ + CBC_UNARY_LVALUE_OPERATION (CBC_PRE_DECR) \ + CBC_UNARY_LVALUE_OPERATION (CBC_POST_INCR) \ + CBC_UNARY_LVALUE_OPERATION (CBC_POST_DECR) \ + \ + /* Call opcodes. */ \ + CBC_OPCODE (CBC_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1) \ + CBC_OPCODE (CBC_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0) \ + CBC_OPCODE (CBC_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1) \ + CBC_OPCODE (CBC_CALL_PROP, CBC_HAS_POP_STACK_BYTE_ARG, -3) \ + CBC_OPCODE (CBC_CALL_PROP_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, -2) \ + CBC_OPCODE (CBC_CALL_PROP_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -3) \ + CBC_OPCODE (CBC_CALL0, CBC_NO_FLAG, -1) \ + CBC_OPCODE (CBC_CALL0_PUSH_RESULT, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_CALL0_BLOCK, CBC_NO_FLAG, -1) \ + CBC_OPCODE (CBC_CALL0_PROP, CBC_NO_FLAG, -3) \ + CBC_OPCODE (CBC_CALL0_PROP_PUSH_RESULT, CBC_NO_FLAG, -2) \ + CBC_OPCODE (CBC_CALL0_PROP_BLOCK, CBC_NO_FLAG, -3) \ + CBC_OPCODE (CBC_CALL1, CBC_NO_FLAG, -2) \ + CBC_OPCODE (CBC_CALL1_PUSH_RESULT, CBC_NO_FLAG, -1) \ + CBC_OPCODE (CBC_CALL1_BLOCK, CBC_NO_FLAG, -2) \ + CBC_OPCODE (CBC_CALL1_PROP, CBC_NO_FLAG, -4) \ + CBC_OPCODE (CBC_CALL1_PROP_PUSH_RESULT, CBC_NO_FLAG, -3) \ + CBC_OPCODE (CBC_CALL1_PROP_BLOCK, CBC_NO_FLAG, -4) \ + CBC_OPCODE (CBC_CALL2, CBC_NO_FLAG, -3) \ + CBC_OPCODE (CBC_CALL2_PUSH_RESULT, CBC_NO_FLAG, -2) \ + CBC_OPCODE (CBC_CALL2_BLOCK, CBC_NO_FLAG, -3) \ + CBC_OPCODE (CBC_CALL2_PROP, CBC_NO_FLAG, -4) \ + CBC_OPCODE (CBC_CALL2_PROP_PUSH_RESULT, CBC_NO_FLAG, -3) \ + CBC_OPCODE (CBC_CALL2_PROP_BLOCK, CBC_NO_FLAG, -4) \ + \ + /* Binary assignment opcodes. */ \ + CBC_OPCODE (CBC_ASSIGN, CBC_NO_FLAG, -3) \ + CBC_OPCODE (CBC_ASSIGN_PUSH_RESULT, CBC_NO_FLAG, -2) \ + CBC_OPCODE (CBC_ASSIGN_BLOCK, CBC_NO_FLAG, -3) \ + CBC_OPCODE (CBC_ASSIGN_SET_IDENT, CBC_HAS_LITERAL_ARG, -1) \ + CBC_OPCODE (CBC_ASSIGN_SET_IDENT_PUSH_RESULT, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_ASSIGN_SET_IDENT_BLOCK, CBC_HAS_LITERAL_ARG, -1) \ + CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT_PUSH_RESULT, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 1) \ + CBC_OPCODE (CBC_ASSIGN_LITERAL_SET_IDENT_BLOCK, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL, CBC_HAS_LITERAL_ARG, -2) \ + CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL_PUSH_RESULT, CBC_HAS_LITERAL_ARG, -1) \ + CBC_OPCODE (CBC_ASSIGN_PROP_LITERAL_BLOCK, CBC_HAS_LITERAL_ARG, -2) \ + CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL, CBC_HAS_LITERAL_ARG, -1) \ + CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL_PUSH_RESULT, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_ASSIGN_PROP_THIS_LITERAL_BLOCK, CBC_HAS_LITERAL_ARG, -1) \ + CBC_OPCODE (CBC_MOV_IDENT, CBC_HAS_LITERAL_ARG, -1) \ + CBC_OPCODE (CBC_ASSIGN_LET_CONST, CBC_HAS_LITERAL_ARG, -1) \ + CBC_OPCODE (CBC_ASSIGN_LET_CONST_LITERAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + \ + /* Last opcode (not a real opcode). */ \ + CBC_OPCODE (CBC_END, CBC_NO_FLAG, 0) /* All EXT branches are statement block end * marks, so they are always forward branches. */ -#define CBC_EXT_OPCODE_LIST \ - /* Branch opcodes first. Some other opcodes are mixed. */ \ - CBC_OPCODE (CBC_EXT_NOP, CBC_NO_FLAG, 0, VM_OC_NONE) \ - CBC_FORWARD_BRANCH (CBC_EXT_WITH_CREATE_CONTEXT, -1 + PARSER_WITH_CONTEXT_STACK_ALLOCATION, VM_OC_WITH) \ - CBC_OPCODE (CBC_EXT_FOR_IN_GET_NEXT, CBC_NO_FLAG, 1, VM_OC_FOR_IN_GET_NEXT | VM_OC_PUT_STACK) \ - CBC_FORWARD_BRANCH (CBC_EXT_FOR_IN_INIT, -1 + PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION, VM_OC_FOR_IN_INIT) \ - CBC_OPCODE (CBC_EXT_SET_GETTER, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 0, \ - VM_OC_SET_GETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_LITERAL_LITERAL) \ - CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_IN_HAS_NEXT, 0, VM_OC_FOR_IN_HAS_NEXT) \ - CBC_OPCODE (CBC_EXT_FOR_OF_GET_NEXT, CBC_NO_FLAG, 1, VM_OC_FOR_OF_GET_NEXT | VM_OC_PUT_STACK) \ - CBC_FORWARD_BRANCH (CBC_EXT_FOR_OF_INIT, -1 + PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION, VM_OC_FOR_OF_INIT) \ - CBC_OPCODE (CBC_EXT_PUSH_NAMED_FUNC_EXPRESSION, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 1, \ - VM_OC_PUSH_NAMED_FUNC_EXPR | VM_OC_GET_LITERAL_LITERAL) \ - CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_OF_HAS_NEXT, 0, VM_OC_FOR_OF_HAS_NEXT) \ - CBC_OPCODE (CBC_EXT_CLONE_CONTEXT, CBC_NO_FLAG, 0, VM_OC_CLONE_CONTEXT) \ - CBC_FORWARD_BRANCH (CBC_EXT_FOR_AWAIT_OF_INIT, \ - -1 + PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION, \ - VM_OC_FOR_AWAIT_OF_INIT) \ - CBC_OPCODE (CBC_EXT_CLONE_FULL_CONTEXT, CBC_NO_FLAG, 0, VM_OC_CLONE_CONTEXT) \ - CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_AWAIT_OF_HAS_NEXT, 0, VM_OC_FOR_AWAIT_OF_HAS_NEXT) \ - CBC_OPCODE (CBC_EXT_SET_SETTER, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 0, \ - VM_OC_SET_SETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_LITERAL_LITERAL) \ - CBC_FORWARD_BRANCH (CBC_EXT_TRY_CREATE_CONTEXT, PARSER_TRY_CONTEXT_STACK_ALLOCATION, VM_OC_TRY) \ - CBC_OPCODE (CBC_EXT_TRY_CREATE_ENV, CBC_NO_FLAG, 0, VM_OC_BLOCK_CREATE_CONTEXT) \ - CBC_FORWARD_BRANCH (CBC_EXT_CATCH, 1, VM_OC_CATCH) \ - CBC_OPCODE (CBC_EXT_RESOLVE_BASE, CBC_NO_FLAG, 0, VM_OC_RESOLVE_BASE_FOR_CALL) \ - CBC_FORWARD_BRANCH (CBC_EXT_FINALLY, PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION, VM_OC_FINALLY) \ - CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP, CBC_NO_FLAG, 0, VM_OC_INITIALIZER_PUSH_PROP) \ - CBC_FORWARD_BRANCH (CBC_EXT_DEFAULT_INITIALIZER, -1, VM_OC_DEFAULT_INITIALIZER) \ - CBC_OPCODE (CBC_EXT_ERROR, CBC_NO_FLAG, 0, VM_OC_ERROR) \ - CBC_FORWARD_BRANCH (CBC_EXT_BRANCH_IF_NULLISH, -1, VM_OC_BRANCH_IF_NULLISH) \ - \ - /* Basic opcodes. */ \ - CBC_OPCODE (CBC_EXT_POP_REFERENCE, CBC_NO_FLAG, -2, VM_OC_POP_REFERENCE) \ - CBC_OPCODE (CBC_EXT_CREATE_ARGUMENTS, CBC_HAS_LITERAL_ARG, 0, VM_OC_CREATE_ARGUMENTS) \ - 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, VM_OC_EXT_VAR_EVAL) \ - CBC_OPCODE (CBC_EXT_COPY_FROM_ARG, CBC_HAS_LITERAL_ARG, 0, VM_OC_COPY_FROM_ARG) \ - CBC_OPCODE (CBC_EXT_PUSH_REST_OBJECT, CBC_NO_FLAG, 1, VM_OC_PUSH_REST_OBJECT) \ - CBC_OPCODE (CBC_EXT_MODULE_IMPORT, CBC_NO_FLAG, 0, VM_OC_MODULE_IMPORT) \ - CBC_OPCODE (CBC_EXT_MODULE_IMPORT_META, CBC_NO_FLAG, 1, VM_OC_MODULE_IMPORT_META) \ - CBC_OPCODE (CBC_EXT_STRING_CONCAT, CBC_NO_FLAG, -1, VM_OC_STRING_CONCAT | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_EXT_STRING_CONCAT_RIGHT_LITERAL, \ - CBC_HAS_LITERAL_ARG, \ - 0, \ - VM_OC_STRING_CONCAT | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_EXT_STRING_CONCAT_TWO_LITERALS, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 1, \ - VM_OC_STRING_CONCAT | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_EXT_GET_TAGGED_TEMPLATE_LITERAL, CBC_HAS_BYTE_ARG, 1, VM_OC_GET_TEMPLATE_OBJECT | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_EXT_THROW_REFERENCE_ERROR, CBC_NO_FLAG, 1, VM_OC_THROW_REFERENCE_ERROR) \ - CBC_OPCODE (CBC_EXT_THROW_ASSIGN_CONST_ERROR, CBC_NO_FLAG, 0, VM_OC_THROW_CONST_ERROR) \ - CBC_OPCODE (CBC_EXT_REQUIRE_OBJECT_COERCIBLE, CBC_NO_FLAG, 0, VM_OC_REQUIRE_OBJECT_COERCIBLE) \ - CBC_OPCODE (CBC_EXT_COPY_DATA_PROPERTIES, CBC_NO_FLAG, -1, VM_OC_COPY_DATA_PROPERTIES) \ - CBC_OPCODE (CBC_EXT_SET_FUNCTION_NAME, CBC_HAS_LITERAL_ARG, 0, VM_OC_SET_FUNCTION_NAME | VM_OC_GET_LITERAL) \ - CBC_OPCODE (CBC_EXT_SET_CLASS_NAME, CBC_HAS_LITERAL_ARG, 0, VM_OC_SET_FUNCTION_NAME) \ - CBC_OPCODE (CBC_EXT_SET_COMPUTED_FUNCTION_NAME, CBC_NO_FLAG, 0, VM_OC_SET_FUNCTION_NAME) \ - CBC_OPCODE (CBC_EXT_SET_COMPUTED_GETTER_NAME, CBC_NO_FLAG, 0, VM_OC_SET_FUNCTION_NAME) \ - CBC_OPCODE (CBC_EXT_SET_COMPUTED_SETTER_NAME, CBC_NO_FLAG, 0, VM_OC_SET_FUNCTION_NAME) \ - \ - /* Computed / class property related opcodes. */ \ - CBC_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY, \ - CBC_NO_FLAG, \ - -2, \ - VM_OC_SET_COMPUTED_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_STACK) \ - CBC_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL, \ - CBC_HAS_LITERAL_ARG, \ - -1, \ - VM_OC_SET_COMPUTED_PROPERTY | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_LITERAL) \ - CBC_OPCODE (CBC_EXT_SET_COMPUTED_GETTER, \ - CBC_NO_FLAG, \ - -2, \ - VM_OC_SET_GETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_STACK) \ - CBC_OPCODE (CBC_EXT_SET_COMPUTED_SETTER, \ - CBC_NO_FLAG, \ - -2, \ - VM_OC_SET_SETTER | VM_OC_NON_STATIC_FLAG | VM_OC_GET_STACK_STACK) \ - CBC_OPCODE (CBC_EXT_SET_STATIC_PROPERTY, CBC_HAS_LITERAL_ARG, -1, VM_OC_SET_PROPERTY | VM_OC_GET_STACK_LITERAL) \ - CBC_OPCODE (CBC_EXT_SET_STATIC_PROPERTY_LITERAL, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 0, \ - VM_OC_SET_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ - CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_PROPERTY, \ - CBC_NO_FLAG, \ - -2, \ - VM_OC_SET_COMPUTED_PROPERTY | VM_OC_GET_STACK_STACK) \ - CBC_OPCODE (CBC_EXT_SET_STATIC_GETTER, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 0, \ - VM_OC_SET_GETTER | VM_OC_GET_LITERAL_LITERAL) \ - CBC_OPCODE (CBC_EXT_SET_STATIC_SETTER, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 0, \ - VM_OC_SET_SETTER | VM_OC_GET_LITERAL_LITERAL) \ - CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_GETTER, CBC_NO_FLAG, -2, VM_OC_SET_GETTER | VM_OC_GET_STACK_STACK) \ - CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_SETTER, CBC_NO_FLAG, -2, VM_OC_SET_SETTER | VM_OC_GET_STACK_STACK) \ - CBC_OPCODE (CBC_EXT_SET__PROTO__, CBC_NO_FLAG, -1, VM_OC_SET__PROTO__ | VM_OC_GET_STACK) \ - CBC_OPCODE (CBC_EXT_PUSH_STATIC_FIELD_FUNC, \ - CBC_HAS_LITERAL_ARG, \ - 1, \ - VM_OC_PUSH_STATIC_FIELD_FUNC | VM_OC_GET_LITERAL) \ - CBC_OPCODE (CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC, \ - CBC_HAS_LITERAL_ARG, \ - 0, \ - VM_OC_PUSH_STATIC_FIELD_FUNC | VM_OC_GET_LITERAL) \ - CBC_OPCODE (CBC_EXT_ADD_COMPUTED_FIELD, CBC_NO_FLAG, -1, VM_OC_ADD_COMPUTED_FIELD | VM_OC_GET_STACK) \ - CBC_OPCODE (CBC_EXT_ADD_STATIC_COMPUTED_FIELD, CBC_NO_FLAG, -1, VM_OC_ADD_COMPUTED_FIELD | VM_OC_GET_STACK) \ - CBC_OPCODE (CBC_EXT_CLASS_CALL_STATIC_BLOCK, \ - CBC_HAS_LITERAL_ARG, \ - 0, \ - VM_OC_CLASS_CALL_STATIC_BLOCK | VM_OC_GET_LITERAL) \ - /* Class private property related opcodes */ \ - CBC_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_REFERENCE, \ - CBC_HAS_LITERAL_ARG, \ - 2, \ - VM_OC_PRIVATE_PROP_REFERENCE | VM_OC_GET_LITERAL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL, \ - CBC_HAS_LITERAL_ARG, \ - 0, \ - VM_OC_PRIVATE_PROP_GET | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_IN, \ - CBC_HAS_LITERAL_ARG, \ - 0, \ - VM_OC_PRIVATE_IN | VM_OC_GET_STACK_LITERAL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_EXT_PRIVATE_FIELD_ADD, CBC_HAS_LITERAL_ARG, -1, VM_OC_PRIVATE_FIELD_ADD | VM_OC_GET_STACK_LITERAL) \ - /* These 8 opcodes must be in this order */ \ - CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_FIELD, \ - CBC_HAS_LITERAL_ARG, \ - 0, \ - VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL) \ - CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_METHOD, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 0, \ - VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ - CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_GETTER, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 0, \ - VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ - CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_SETTER, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 0, \ - VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ - CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_FIELD, \ - CBC_HAS_LITERAL_ARG, \ - 0, \ - VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL) \ - CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_METHOD, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 0, \ - VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ - CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_GETTER, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 0, \ - VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ - CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_SETTER, \ - CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, \ - 0, \ - VM_OC_COLLECT_PRIVATE_PROPERTY | VM_OC_GET_LITERAL_LITERAL) \ - /* Class related opcodes. */ \ - CBC_OPCODE (CBC_EXT_PUSH_NAMED_CLASS_ENV, CBC_HAS_LITERAL_ARG, 1, VM_OC_PUSH_CLASS_ENVIRONMENT) \ - CBC_OPCODE (CBC_EXT_DEFINE_FIELD, CBC_HAS_LITERAL_ARG, -1, VM_OC_DEFINE_FIELD | VM_OC_GET_STACK_LITERAL) \ - CBC_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR, CBC_NO_FLAG, 1, VM_OC_PUSH_IMPLICIT_CTOR | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE, CBC_NO_FLAG, 1, VM_OC_PUSH_IMPLICIT_CTOR | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_EXT_INIT_CLASS, CBC_NO_FLAG, 0, VM_OC_INIT_CLASS | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_EXT_FINALIZE_NAMED_CLASS, CBC_HAS_LITERAL_ARG, -2, VM_OC_FINALIZE_CLASS) \ - CBC_OPCODE (CBC_EXT_FINALIZE_ANONYMOUS_CLASS, CBC_NO_FLAG, -2, VM_OC_FINALIZE_CLASS) \ - CBC_OPCODE (CBC_EXT_SET_FIELD_INIT, CBC_HAS_LITERAL_ARG, 0, VM_OC_SET_FIELD_INIT | VM_OC_GET_LITERAL) \ - CBC_OPCODE (CBC_EXT_RUN_FIELD_INIT, CBC_NO_FLAG, 0, VM_OC_RUN_FIELD_INIT) \ - CBC_OPCODE (CBC_EXT_RUN_STATIC_FIELD_INIT, CBC_NO_FLAG, -1, VM_OC_RUN_STATIC_FIELD_INIT) \ - CBC_OPCODE (CBC_EXT_SET_NEXT_COMPUTED_FIELD_ANONYMOUS_FUNC, \ - CBC_NO_FLAG, \ - -1, \ - VM_OC_SET_NEXT_COMPUTED_FIELD | VM_OC_PUT_REFERENCE) \ - CBC_OPCODE (CBC_EXT_SET_NEXT_COMPUTED_FIELD, CBC_NO_FLAG, -1, VM_OC_SET_NEXT_COMPUTED_FIELD | VM_OC_PUT_REFERENCE) \ - CBC_OPCODE (CBC_EXT_PUSH_SUPER, CBC_NO_FLAG, 1, VM_OC_NONE) \ - CBC_OPCODE (CBC_EXT_PUSH_SUPER_CONSTRUCTOR, CBC_NO_FLAG, 1, VM_OC_PUSH_SUPER_CONSTRUCTOR) \ - CBC_OPCODE (CBC_EXT_PUSH_SUPER_PROP, CBC_NO_FLAG, 0, VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK) \ - CBC_OPCODE (CBC_EXT_SUPER_PROP_REFERENCE, CBC_NO_FLAG, 2, VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK) \ - CBC_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL, CBC_HAS_LITERAL_ARG, 1, VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL) \ - CBC_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG, 3, VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL) \ - CBC_OPCODE (CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE, CBC_NO_FLAG, 1, VM_OC_SUPER_REFERENCE | VM_OC_GET_STACK) \ - CBC_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE, \ - CBC_HAS_LITERAL_ARG, \ - 2, \ - VM_OC_SUPER_REFERENCE | VM_OC_GET_LITERAL) \ - CBC_OPCODE (CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT, CBC_NO_FLAG, 0, VM_OC_SET_HOME_OBJECT) \ - CBC_OPCODE (CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED, CBC_NO_FLAG, 0, VM_OC_SET_HOME_OBJECT) \ - CBC_OPCODE (CBC_EXT_PUSH_OBJECT_SUPER_ENVIRONMENT, CBC_NO_FLAG, 1, VM_OC_OBJECT_LITERAL_HOME_ENV) \ - CBC_OPCODE (CBC_EXT_POP_OBJECT_SUPER_ENVIRONMENT, CBC_NO_FLAG, -1, VM_OC_OBJECT_LITERAL_HOME_ENV) \ - CBC_OPCODE (CBC_EXT_RESOLVE_LEXICAL_THIS, CBC_NO_FLAG, 1, 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_ASSIGN_PRIVATE, CBC_NO_FLAG, -3, VM_OC_ASSIGN_PRIVATE) \ - CBC_OPCODE (CBC_EXT_ASSIGN_PRIVATE_PUSH_RESULT, CBC_NO_FLAG, -2, VM_OC_ASSIGN_PRIVATE | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_EXT_ASSIGN_PRIVATE_BLOCK, CBC_NO_FLAG, -3, VM_OC_ASSIGN_PRIVATE | 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, VM_OC_SUPER_CALL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_EXT_SUPER_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SUPER_CALL | VM_OC_PUT_BLOCK) \ - CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SUPER_CALL) \ - CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL_PUSH_RESULT, \ - CBC_HAS_POP_STACK_BYTE_ARG, \ - 0, \ - VM_OC_SUPER_CALL | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SUPER_CALL | VM_OC_PUT_BLOCK) \ - \ - /* Spread / rest operation related opcodes. */ \ - CBC_OPCODE (CBC_EXT_SPREAD_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SPREAD_ARGUMENTS) \ - CBC_OPCODE (CBC_EXT_SPREAD_CALL_PUSH_RESULT, \ - CBC_HAS_POP_STACK_BYTE_ARG, \ - 0, \ - VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_EXT_SPREAD_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_BLOCK) \ - CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP, CBC_HAS_POP_STACK_BYTE_ARG, -3, VM_OC_SPREAD_ARGUMENTS) \ - CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP_PUSH_RESULT, \ - CBC_HAS_POP_STACK_BYTE_ARG, \ - -2, \ - VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_STACK) \ - CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP_BLOCK, \ - CBC_HAS_POP_STACK_BYTE_ARG, \ - -3, \ - VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_BLOCK) \ - CBC_OPCODE (CBC_EXT_PUSH_SPREAD_ELEMENT, CBC_NO_FLAG, 1, VM_OC_PUSH_SPREAD_ELEMENT) \ - CBC_OPCODE (CBC_EXT_SPREAD_ARRAY_APPEND, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_APPEND_ARRAY) \ - CBC_OPCODE (CBC_EXT_REST_INITIALIZER, CBC_NO_FLAG, 1, VM_OC_REST_INITIALIZER) \ - CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP_LITERAL, \ - CBC_HAS_LITERAL_ARG, \ - 1, \ - VM_OC_INITIALIZER_PUSH_PROP | VM_OC_GET_LITERAL) \ - CBC_OPCODE (CBC_EXT_SPREAD_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0, VM_OC_SPREAD_ARGUMENTS | VM_OC_PUT_STACK) \ - \ - /* Iterator related opcodes. */ \ - CBC_OPCODE (CBC_EXT_ITERATOR_CONTEXT_CREATE, \ - CBC_NO_FLAG, \ - PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION, \ - VM_OC_ITERATOR_CONTEXT_CREATE) \ - CBC_OPCODE (CBC_EXT_ITERATOR_CONTEXT_END, \ - CBC_NO_FLAG, \ - -PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION, \ - VM_OC_ITERATOR_CONTEXT_END) \ - CBC_OPCODE (CBC_EXT_ITERATOR_STEP, CBC_NO_FLAG, 1, VM_OC_ITERATOR_STEP) \ - \ - /* Object initializer related opcodes. */ \ - CBC_OPCODE (CBC_EXT_OBJ_INIT_CONTEXT_CREATE, \ - CBC_NO_FLAG, \ - PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION, \ - VM_OC_OBJ_INIT_CONTEXT_CREATE) \ - CBC_OPCODE (CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE, \ - CBC_NO_FLAG, \ - PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION, \ - VM_OC_OBJ_INIT_CONTEXT_CREATE) \ - CBC_OPCODE (CBC_EXT_OBJ_INIT_PUSH_REST, CBC_NO_FLAG, 1, VM_OC_OBJ_INIT_PUSH_REST) \ - CBC_OPCODE (CBC_EXT_OBJ_INIT_CONTEXT_END, \ - CBC_NO_FLAG, \ - -PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION, \ - VM_OC_OBJ_INIT_CONTEXT_END) \ - CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_NAME, CBC_NO_FLAG, 0, VM_OC_INITIALIZER_PUSH_NAME | VM_OC_GET_STACK) \ - CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_NAME_LITERAL, \ - CBC_HAS_LITERAL_ARG, \ - 1, \ - VM_OC_INITIALIZER_PUSH_NAME | VM_OC_GET_LITERAL) \ - \ - /* Executable object related opcodes. */ \ - CBC_OPCODE (CBC_EXT_CREATE_GENERATOR, CBC_NO_FLAG, 1, VM_OC_CREATE_GENERATOR) \ - CBC_OPCODE (CBC_EXT_YIELD, CBC_NO_FLAG, 0, VM_OC_YIELD) \ - CBC_OPCODE (CBC_EXT_YIELD_ITERATOR, CBC_NO_FLAG, 0, VM_OC_YIELD) \ - CBC_OPCODE (CBC_EXT_ASYNC_YIELD, CBC_NO_FLAG, 0, VM_OC_ASYNC_YIELD) \ - CBC_OPCODE (CBC_EXT_ASYNC_YIELD_ITERATOR, CBC_NO_FLAG, 0, VM_OC_ASYNC_YIELD_ITERATOR) \ - CBC_OPCODE (CBC_EXT_AWAIT, CBC_NO_FLAG, 0, VM_OC_AWAIT) \ - CBC_OPCODE (CBC_EXT_GENERATOR_AWAIT, CBC_NO_FLAG, 0, VM_OC_GENERATOR_AWAIT) \ - CBC_OPCODE (CBC_EXT_ASYNC_EXIT, CBC_NO_FLAG, 0, VM_OC_ASYNC_EXIT) \ - CBC_OPCODE (CBC_EXT_RETURN, CBC_NO_FLAG, -1, VM_OC_EXT_RETURN | VM_OC_GET_STACK) \ - CBC_OPCODE (CBC_EXT_RETURN_UNDEFINED, CBC_NO_FLAG, 0, VM_OC_EXT_RETURN) \ - CBC_OPCODE (CBC_EXT_PUSH_NEW_TARGET, CBC_NO_FLAG, 1, VM_OC_PUSH_NEW_TARGET | VM_OC_PUT_STACK) \ - \ - /* Last opcode (not a real opcode). */ \ - CBC_OPCODE (CBC_EXT_END, CBC_NO_FLAG, 0, VM_OC_NONE) +#define CBC_EXT_OPCODE_LIST \ + /* Branch opcodes first. Some other opcodes are mixed. */ \ + CBC_OPCODE (CBC_EXT_NOP, CBC_NO_FLAG, 0) \ + CBC_FORWARD_BRANCH (CBC_EXT_WITH_CREATE_CONTEXT, -1 + PARSER_WITH_CONTEXT_STACK_ALLOCATION) \ + CBC_OPCODE (CBC_EXT_FOR_IN_GET_NEXT, CBC_NO_FLAG, 1) \ + CBC_FORWARD_BRANCH (CBC_EXT_FOR_IN_INIT, -1 + PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION) \ + CBC_OPCODE (CBC_EXT_POP_REFERENCE, CBC_NO_FLAG, -2) \ + CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_IN_HAS_NEXT, 0) \ + CBC_OPCODE (CBC_EXT_FOR_OF_GET_NEXT, CBC_NO_FLAG, 1) \ + CBC_FORWARD_BRANCH (CBC_EXT_FOR_OF_INIT, -1 + PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION) \ + CBC_OPCODE (CBC_EXT_PUSH_NAMED_FUNC_EXPRESSION, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 1) \ + CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_OF_HAS_NEXT, 0) \ + CBC_OPCODE (CBC_EXT_CLONE_CONTEXT, CBC_NO_FLAG, 0) \ + CBC_FORWARD_BRANCH (CBC_EXT_FOR_AWAIT_OF_INIT, -1 + PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION) \ + CBC_OPCODE (CBC_EXT_CLONE_FULL_CONTEXT, CBC_NO_FLAG, 0) \ + CBC_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_AWAIT_OF_HAS_NEXT, 0) \ + CBC_OPCODE (CBC_EXT_CREATE_ARGUMENTS, CBC_HAS_LITERAL_ARG, 0) \ + CBC_FORWARD_BRANCH (CBC_EXT_TRY_CREATE_CONTEXT, PARSER_TRY_CONTEXT_STACK_ALLOCATION) \ + CBC_OPCODE (CBC_EXT_TRY_CREATE_ENV, CBC_NO_FLAG, 0) \ + CBC_FORWARD_BRANCH (CBC_EXT_CATCH, 1) \ + CBC_OPCODE (CBC_EXT_RESOLVE_BASE, CBC_NO_FLAG, 0) \ + CBC_FORWARD_BRANCH (CBC_EXT_FINALLY, PARSER_FINALLY_CONTEXT_EXTRA_STACK_ALLOCATION) \ + CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP, CBC_NO_FLAG, 0) \ + CBC_FORWARD_BRANCH (CBC_EXT_DEFAULT_INITIALIZER, -1) \ + CBC_OPCODE (CBC_EXT_ERROR, CBC_NO_FLAG, 0) \ + CBC_FORWARD_BRANCH (CBC_EXT_BRANCH_IF_NULLISH, -1) \ + \ + /* Basic opcodes. */ \ + CBC_OPCODE (CBC_EXT_CREATE_VAR_EVAL, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_EXT_CREATE_VAR_FUNC_EVAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + CBC_OPCODE (CBC_EXT_COPY_FROM_ARG, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_EXT_PUSH_REST_OBJECT, CBC_NO_FLAG, 1) \ + CBC_OPCODE (CBC_EXT_MODULE_IMPORT, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_EXT_MODULE_IMPORT_META, CBC_NO_FLAG, 1) \ + /*Note: These 3 opcodes must be in this order */ \ + CBC_OPCODE (CBC_EXT_STRING_CONCAT, CBC_NO_FLAG, -1) \ + CBC_OPCODE (CBC_EXT_STRING_CONCAT_RIGHT_LITERAL, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_EXT_STRING_CONCAT_TWO_LITERALS, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 1) \ + CBC_OPCODE (CBC_EXT_GET_TAGGED_TEMPLATE_LITERAL, CBC_HAS_BYTE_ARG, 1) \ + CBC_OPCODE (CBC_EXT_THROW_REFERENCE_ERROR, CBC_NO_FLAG, 1) \ + CBC_OPCODE (CBC_EXT_THROW_ASSIGN_CONST_ERROR, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_EXT_REQUIRE_OBJECT_COERCIBLE, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_EXT_COPY_DATA_PROPERTIES, CBC_NO_FLAG, -1) \ + CBC_OPCODE (CBC_EXT_SET_FUNCTION_NAME, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_EXT_SET_CLASS_NAME, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_FUNCTION_NAME, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_GETTER_NAME, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_SETTER_NAME, CBC_NO_FLAG, 0) \ + \ + /* Computed / class property related opcodes. */ \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY, CBC_NO_FLAG, -2) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL, CBC_HAS_LITERAL_ARG, -1) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_PROPERTY, CBC_NO_FLAG, -2) \ + /* Note: These 8 opcodes must be in this order */ \ + CBC_OPCODE (CBC_EXT_SET_GETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_GETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_GETTER, CBC_NO_FLAG, -2) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_GETTER, CBC_NO_FLAG, -2) \ + CBC_OPCODE (CBC_EXT_SET_SETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_SETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + CBC_OPCODE (CBC_EXT_SET_COMPUTED_SETTER, CBC_NO_FLAG, -2) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_SETTER, CBC_NO_FLAG, -2) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_PROPERTY, CBC_HAS_LITERAL_ARG, -1) \ + CBC_OPCODE (CBC_EXT_SET_STATIC_PROPERTY_LITERAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + CBC_OPCODE (CBC_EXT_SET__PROTO__, CBC_NO_FLAG, -1) \ + CBC_OPCODE (CBC_EXT_PUSH_STATIC_FIELD_FUNC, CBC_HAS_LITERAL_ARG, 1) \ + CBC_OPCODE (CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_EXT_ADD_COMPUTED_FIELD, CBC_NO_FLAG, -1) \ + CBC_OPCODE (CBC_EXT_ADD_STATIC_COMPUTED_FIELD, CBC_NO_FLAG, -1) \ + CBC_OPCODE (CBC_EXT_CLASS_CALL_STATIC_BLOCK, CBC_HAS_LITERAL_ARG, 0) \ + /* Class private property related opcodes */ \ + CBC_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG, 2) \ + CBC_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_IN, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_EXT_PRIVATE_FIELD_ADD, CBC_HAS_LITERAL_ARG, -1) \ + /* These 8 opcodes must be in this order */ \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_FIELD, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_METHOD, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_GETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_SETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_FIELD, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_METHOD, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_GETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + CBC_OPCODE (CBC_EXT_COLLECT_PRIVATE_STATIC_SETTER, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0) \ + /* Class related opcodes. */ \ + CBC_OPCODE (CBC_EXT_PUSH_NAMED_CLASS_ENV, CBC_HAS_LITERAL_ARG, 1) \ + CBC_OPCODE (CBC_EXT_DEFINE_FIELD, CBC_HAS_LITERAL_ARG, -1) \ + CBC_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR, CBC_NO_FLAG, 1) \ + CBC_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE, CBC_NO_FLAG, 1) \ + CBC_OPCODE (CBC_EXT_INIT_CLASS, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_EXT_FINALIZE_NAMED_CLASS, CBC_HAS_LITERAL_ARG, -2) \ + CBC_OPCODE (CBC_EXT_FINALIZE_ANONYMOUS_CLASS, CBC_NO_FLAG, -2) \ + CBC_OPCODE (CBC_EXT_SET_FIELD_INIT, CBC_HAS_LITERAL_ARG, 0) \ + CBC_OPCODE (CBC_EXT_RUN_FIELD_INIT, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_EXT_RUN_STATIC_FIELD_INIT, CBC_NO_FLAG, -1) \ + CBC_OPCODE (CBC_EXT_SET_NEXT_COMPUTED_FIELD_ANONYMOUS_FUNC, CBC_NO_FLAG, -1) \ + CBC_OPCODE (CBC_EXT_SET_NEXT_COMPUTED_FIELD, CBC_NO_FLAG, -1) \ + CBC_OPCODE (CBC_EXT_PUSH_SUPER, CBC_NO_FLAG, 1) \ + CBC_OPCODE (CBC_EXT_PUSH_SUPER_CONSTRUCTOR, CBC_NO_FLAG, 1) \ + /* Note: These 4 opcodes must be in this order */ \ + CBC_OPCODE (CBC_EXT_PUSH_SUPER_PROP, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_EXT_PUSH_SUPER_PROP_LITERAL, CBC_HAS_LITERAL_ARG, 1) \ + CBC_OPCODE (CBC_EXT_SUPER_PROP_REFERENCE, CBC_NO_FLAG, 2) \ + CBC_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG, 3) \ + CBC_OPCODE (CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE, CBC_NO_FLAG, 1) \ + CBC_OPCODE (CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE, CBC_HAS_LITERAL_ARG, 2) \ + /* Note: These 2 opcodes must be in this order */ \ + CBC_OPCODE (CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_EXT_PUSH_OBJECT_SUPER_ENVIRONMENT, CBC_NO_FLAG, 1) \ + CBC_OPCODE (CBC_EXT_POP_OBJECT_SUPER_ENVIRONMENT, CBC_NO_FLAG, -1) \ + CBC_OPCODE (CBC_EXT_RESOLVE_LEXICAL_THIS, CBC_NO_FLAG, 1) \ + CBC_OPCODE (CBC_EXT_LOCAL_EVAL, CBC_HAS_BYTE_ARG, 0) \ + CBC_OPCODE (CBC_EXT_ASSIGN_SUPER, CBC_NO_FLAG, -3) \ + CBC_OPCODE (CBC_EXT_ASSIGN_SUPER_PUSH_RESULT, CBC_NO_FLAG, -2) \ + CBC_OPCODE (CBC_EXT_ASSIGN_SUPER_BLOCK, CBC_NO_FLAG, -3) \ + CBC_OPCODE (CBC_EXT_ASSIGN_PRIVATE, CBC_NO_FLAG, -3) \ + CBC_OPCODE (CBC_EXT_ASSIGN_PRIVATE_PUSH_RESULT, CBC_NO_FLAG, -2) \ + CBC_OPCODE (CBC_EXT_ASSIGN_PRIVATE_BLOCK, CBC_NO_FLAG, -3) \ + /* Note: These 6 opcodes must be in this order */ \ + CBC_OPCODE (CBC_EXT_SUPER_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1) \ + CBC_OPCODE (CBC_EXT_SUPER_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0) \ + CBC_OPCODE (CBC_EXT_SUPER_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1) \ + CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1) \ + CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0) \ + CBC_OPCODE (CBC_EXT_SPREAD_SUPER_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1) \ + \ + /* Spread / rest operation related opcodes. */ \ + /* Note: These 9 opcodes must be in this order */ \ + CBC_OPCODE (CBC_EXT_SPREAD_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1) \ + CBC_OPCODE (CBC_EXT_SPREAD_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0) \ + CBC_OPCODE (CBC_EXT_SPREAD_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1) \ + CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP, CBC_HAS_POP_STACK_BYTE_ARG, -3) \ + CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, -2) \ + CBC_OPCODE (CBC_EXT_SPREAD_CALL_PROP_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -3) \ + CBC_OPCODE (CBC_EXT_PUSH_SPREAD_ELEMENT, CBC_NO_FLAG, 1) \ + CBC_OPCODE (CBC_EXT_SPREAD_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0) \ + CBC_OPCODE (CBC_EXT_SPREAD_ARRAY_APPEND, CBC_HAS_POP_STACK_BYTE_ARG, 0) \ + CBC_OPCODE (CBC_EXT_REST_INITIALIZER, CBC_NO_FLAG, 1) \ + CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP_LITERAL, CBC_HAS_LITERAL_ARG, 1) \ + \ + /* Iterator related opcodes. */ \ + CBC_OPCODE (CBC_EXT_ITERATOR_CONTEXT_CREATE, CBC_NO_FLAG, PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION) \ + CBC_OPCODE (CBC_EXT_ITERATOR_CONTEXT_END, CBC_NO_FLAG, -PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION) \ + CBC_OPCODE (CBC_EXT_ITERATOR_STEP, CBC_NO_FLAG, 1) \ + \ + /* Object initializer related opcodes. */ \ + CBC_OPCODE (CBC_EXT_OBJ_INIT_CONTEXT_CREATE, CBC_NO_FLAG, PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION) \ + CBC_OPCODE (CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE, CBC_NO_FLAG, PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION) \ + CBC_OPCODE (CBC_EXT_OBJ_INIT_PUSH_REST, CBC_NO_FLAG, 1) \ + CBC_OPCODE (CBC_EXT_OBJ_INIT_CONTEXT_END, CBC_NO_FLAG, -PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION) \ + CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_NAME, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_NAME_LITERAL, CBC_HAS_LITERAL_ARG, 1) \ + \ + /* Executable object related opcodes. */ \ + CBC_OPCODE (CBC_EXT_CREATE_GENERATOR, CBC_NO_FLAG, 1) \ + CBC_OPCODE (CBC_EXT_YIELD, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_EXT_YIELD_ITERATOR, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_EXT_ASYNC_YIELD, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_EXT_ASYNC_YIELD_ITERATOR, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_EXT_AWAIT, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_EXT_GENERATOR_AWAIT, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_EXT_ASYNC_EXIT, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_EXT_RETURN, CBC_NO_FLAG, -1) \ + CBC_OPCODE (CBC_EXT_RETURN_UNDEFINED, CBC_NO_FLAG, 0) \ + CBC_OPCODE (CBC_EXT_PUSH_NEW_TARGET, CBC_NO_FLAG, 1) \ + \ + /* Last opcode (not a real opcode). */ \ + CBC_OPCODE (CBC_EXT_END, CBC_NO_FLAG, 0) #define CBC_MAXIMUM_BYTE_VALUE 255 #define CBC_MAXIMUM_SMALL_VALUE 510 @@ -1018,7 +803,7 @@ typedef struct #define CBC_SCRIPT_GET_IMPORT_META(script_p, type) \ (CBC_SCRIPT_GET_OPTIONAL_VALUES (script_p)[((type) &CBC_SCRIPT_HAS_USER_VALUE) ? 1 : 0]) -#define CBC_OPCODE(arg1, arg2, arg3, arg4) arg1, +#define CBC_OPCODE(arg1, arg2, arg3) arg1, /** * Opcode list. diff --git a/jerry-core/parser/js/js-parser-expr.c b/jerry-core/parser/js/js-parser-expr.c index 67b69d2c76..dd76f951a0 100644 --- a/jerry-core/parser/js/js-parser-expr.c +++ b/jerry-core/parser/js/js-parser-expr.c @@ -1420,7 +1420,7 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */ uint16_t function_literal_index = lexer_construct_function_object (context_p, status_flags); #if JERRY_ESNEXT - if (opcode >= CBC_EXT_SET_COMPUTED_GETTER) + if (is_computed) { literal_index = function_literal_index; } @@ -3487,7 +3487,7 @@ parser_process_binary_assignment_token (parser_context_t *context_p, /**< contex if (opcode == CBC_ASSIGN_PROP_THIS_LITERAL && (context_p->stack_depth >= context_p->stack_limit)) { - /* Stack limit is increased for VM_OC_ASSIGN_PROP_THIS. Needed by vm.c. */ + /* Needed by vm.c. */ JERRY_ASSERT (context_p->stack_depth == context_p->stack_limit); context_p->stack_limit++; diff --git a/jerry-core/vm/opcodes.c b/jerry-core/vm/opcodes.c index 9819f343b2..4cbeb78025 100644 --- a/jerry-core/vm/opcodes.c +++ b/jerry-core/vm/opcodes.c @@ -59,10 +59,10 @@ opfunc_typeof (ecma_value_t left_value) /**< left value */ /** * Update data property for object literals. */ -void -opfunc_set_data_property (ecma_object_t *object_p, /**< object */ - ecma_string_t *prop_name_p, /**< data property name */ - ecma_value_t value) /**< new value */ +static void +opfunc_assing_data_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *prop_name_p, /**< data property name */ + ecma_value_t value) /**< new value */ { JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p)); @@ -96,7 +96,7 @@ opfunc_set_data_property (ecma_object_t *object_p, /**< object */ } ecma_named_data_property_assign_value (object_p, prop_value_p, value); -} /* opfunc_set_data_property */ +} /* opfunc_assing_data_property */ /** * Update getter or setter for object literals. @@ -320,16 +320,15 @@ opfunc_for_in (ecma_value_t iterable_value, /**< ideally an iterable value */ #if JERRY_ESNEXT /** - * 'VM_OC_APPEND_ARRAY' opcode handler specialized for spread objects + * 'CBC_EXT_SPREAD_ARRAY_APPEND' opcode handler specialized for spread objects * * @return ECMA_VALUE_ERROR - if the operation failed * ECMA_VALUE_EMPTY, otherwise */ -static ecma_value_t JERRY_ATTR_NOINLINE +ecma_value_t JERRY_ATTR_NOINLINE opfunc_append_to_spread_array (ecma_value_t *stack_top_p, /**< current stack top */ uint16_t values_length) /**< number of elements to set */ { - JERRY_ASSERT (!(values_length & OPFUNC_HAS_SPREAD_ELEMENT)); ecma_object_t *array_obj_p = ecma_get_object_from_value (stack_top_p[-1]); JERRY_ASSERT (ecma_get_object_type (array_obj_p) == ECMA_OBJECT_TYPE_ARRAY); @@ -501,23 +500,15 @@ opfunc_spread_arguments (ecma_value_t *stack_top_p, /**< pointer to the current #endif /* JERRY_ESNEXT */ /** - * 'VM_OC_APPEND_ARRAY' opcode handler, for setting array object properties + * 'CBC_ARRAY_APPEND' opcode handler, for setting array object properties * * @return ECMA_VALUE_ERROR - if the operation failed * ECMA_VALUE_EMPTY, otherwise */ ecma_value_t JERRY_ATTR_NOINLINE opfunc_append_array (ecma_value_t *stack_top_p, /**< current stack top */ - uint16_t values_length) /**< number of elements to set - * with potential OPFUNC_HAS_SPREAD_ELEMENT flag */ + uint16_t values_length) /**< number of elements to set */ { -#if JERRY_ESNEXT - if (values_length >= OPFUNC_HAS_SPREAD_ELEMENT) - { - return opfunc_append_to_spread_array (stack_top_p, (uint16_t) (values_length & ~OPFUNC_HAS_SPREAD_ELEMENT)); - } -#endif /* JERRY_ESNEXT */ - ecma_object_t *array_obj_p = ecma_get_object_from_value (stack_top_p[-1]); JERRY_ASSERT (ecma_get_object_type (array_obj_p) == ECMA_OBJECT_TYPE_ARRAY); @@ -1158,8 +1149,8 @@ opfunc_add_computed_field (ecma_value_t class_object, /**< class object */ * @return - new external function ecma-object */ ecma_value_t -opfunc_create_implicit_class_constructor (uint8_t opcode, /**< current cbc opcode */ - const ecma_compiled_code_t *bytecode_p) /**< current byte code */ +opfunc_create_implicit_class_constructor (const ecma_compiled_code_t *bytecode_p, /**< current byte code */ + bool is_herigate) /* true -if class heritage is present */ { /* 8. */ ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_p)->script_value; @@ -1181,7 +1172,7 @@ opfunc_create_implicit_class_constructor (uint8_t opcode, /**< current cbc opcod constructor_object_p->u.constructor_function.flags = 0; /* 10.a.i */ - if (opcode == CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE) + if (is_herigate) { constructor_object_p->u.constructor_function.flags |= ECMA_CONSTRUCTOR_FUNCTION_HAS_HERITAGE; } @@ -1574,9 +1565,6 @@ opfunc_collect_private_properties (ecma_value_t constructor, ecma_value_t prop_n if (opcode == CBC_EXT_COLLECT_PRIVATE_METHOD) { - prop_name ^= value; - value ^= prop_name; - prop_name ^= value; kind = ECMA_PRIVATE_METHOD; } else if (opcode == CBC_EXT_COLLECT_PRIVATE_GETTER) @@ -1977,10 +1965,7 @@ opfunc_finalize_class (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ * ECMA_VALUE_EMPTY - otherwise */ ecma_value_t -opfunc_form_super_reference (ecma_value_t **vm_stack_top_p, /**< current vm stack top */ - vm_frame_ctx_t *frame_ctx_p, /**< frame context */ - ecma_value_t prop_name, /**< property name to resolve */ - uint8_t opcode) /**< current cbc opcode */ +opfunc_resolve_super (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { ecma_environment_record_t *environment_record_p = ecma_op_get_environment_record (frame_ctx_p->lex_env_p); @@ -2001,112 +1986,8 @@ opfunc_form_super_reference (ecma_value_t **vm_stack_top_p, /**< current vm stac return ECMA_VALUE_ERROR; } - ecma_value_t *stack_top_p = *vm_stack_top_p; - - if (opcode >= CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE) - { - JERRY_ASSERT (opcode == CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE - || opcode == CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE); - *stack_top_p++ = parent; - *stack_top_p++ = ecma_copy_value (prop_name); - *vm_stack_top_p = stack_top_p; - - return ECMA_VALUE_EMPTY; - } - - ecma_object_t *parent_p = ecma_get_object_from_value (parent); - ecma_string_t *prop_name_p = ecma_op_to_property_key (prop_name); - - if (prop_name_p == NULL) - { - ecma_deref_object (parent_p); - return ECMA_VALUE_ERROR; - } - - ecma_value_t result = ecma_op_object_get_with_receiver (parent_p, prop_name_p, frame_ctx_p->this_binding); - ecma_deref_ecma_string (prop_name_p); - ecma_deref_object (parent_p); - - if (ECMA_IS_VALUE_ERROR (result)) - { - return result; - } - - if (opcode == CBC_EXT_SUPER_PROP_LITERAL_REFERENCE || opcode == CBC_EXT_SUPER_PROP_REFERENCE) - { - *stack_top_p++ = ecma_copy_value (frame_ctx_p->this_binding); - *stack_top_p++ = ECMA_VALUE_UNDEFINED; - } - - *stack_top_p++ = result; - *vm_stack_top_p = stack_top_p; - - return ECMA_VALUE_EMPTY; -} /* opfunc_form_super_reference */ - -/** - * Assignment operation for SuperRefence base - * - * @return ECMA_VALUE_ERROR - if the operation fails - * ECMA_VALUE_EMPTY - otherwise - */ -ecma_value_t -opfunc_assign_super_reference (ecma_value_t **vm_stack_top_p, /**< vm stack top */ - vm_frame_ctx_t *frame_ctx_p, /**< frame context */ - uint32_t opcode_data) /**< opcode data to store the result */ -{ - ecma_value_t *stack_top_p = *vm_stack_top_p; - - ecma_value_t base_obj = ecma_op_to_object (stack_top_p[-3]); - - if (ECMA_IS_VALUE_ERROR (base_obj)) - { - return base_obj; - } - - ecma_object_t *base_obj_p = ecma_get_object_from_value (base_obj); - ecma_string_t *prop_name_p = ecma_op_to_property_key (stack_top_p[-2]); - - if (prop_name_p == NULL) - { - ecma_deref_object (base_obj_p); - return ECMA_VALUE_ERROR; - } - - bool is_strict = (frame_ctx_p->status_flags & VM_FRAME_CTX_IS_STRICT) != 0; - - ecma_value_t result = - ecma_op_object_put_with_receiver (base_obj_p, prop_name_p, stack_top_p[-1], frame_ctx_p->this_binding, is_strict); - - ecma_deref_ecma_string (prop_name_p); - ecma_deref_object (base_obj_p); - - if (ECMA_IS_VALUE_ERROR (result)) - { - return result; - } - - for (int32_t i = 1; i <= 3; i++) - { - ecma_free_value (stack_top_p[-i]); - } - - stack_top_p -= 3; - - if (opcode_data & VM_OC_PUT_STACK) - { - *stack_top_p++ = result; - } - else if (opcode_data & VM_OC_PUT_BLOCK) - { - ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); - VM_GET_REGISTERS (frame_ctx_p)[0] = result; - } - - *vm_stack_top_p = stack_top_p; - - return result; -} /* opfunc_assign_super_reference */ + return parent; +} /* opfunc_resolve_super */ /** * Copy data properties of an object @@ -2222,7 +2103,7 @@ opfunc_copy_data_properties (ecma_value_t target_object, /**< target object */ } } - opfunc_set_data_property (target_object_p, property_name_p, result); + opfunc_assing_data_property (target_object_p, property_name_p, result); ecma_free_value (result); result = ECMA_VALUE_EMPTY; @@ -2303,8 +2184,82 @@ opfunc_lexical_scope_has_restricted_binding (vm_frame_ctx_t *frame_ctx_p, /**< f && !ecma_is_property_configurable (property)); } /* opfunc_lexical_scope_has_restricted_binding */ +/** + * Create function name property to the given function object + */ +void +opfunc_set_function_name (ecma_value_t function_object, /**< function object */ + ecma_value_t function_name, /**< function name */ + char *prefix_p, /**< function name prefix */ + lit_utf8_size_t prefix_size) /**< function name prefix's length */ +{ + ecma_object_t *func_obj_p = ecma_get_object_from_value (function_object); + + if (ecma_find_named_property (func_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_NAME)) != NULL) + { + return; + } + + ecma_property_value_t *value_p; + value_p = ecma_create_named_data_property (func_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_NAME), + ECMA_PROPERTY_FLAG_CONFIGURABLE, + NULL); + + if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION) + { + ECMA_SET_SECOND_BIT_TO_POINTER_TAG (((ecma_extended_object_t *) func_obj_p)->u.function.scope_cp); + } + + value_p->value = ecma_op_function_form_name (ecma_get_prop_name_from_value (function_name), prefix_p, prefix_size); +} /* opfunc_set_function_name */ + #endif /* JERRY_ESNEXT */ +/** + * Set data property to an object/class + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +opfunc_set_data_property (ecma_value_t *stack_top_p, /**< vm stack */ + ecma_value_t prop_name, /**< property name to set */ + ecma_value_t value, /**< value to set */ + bool is_static) /**< true - if set class property + false - otherwise */ +{ + ecma_string_t *prop_name_p = ecma_op_to_property_key (prop_name); + + if (JERRY_UNLIKELY (prop_name_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + int index = -1; + +#if JERRY_ESNEXT + if (JERRY_UNLIKELY (is_static)) + { + if (ecma_compare_ecma_string_to_magic_id (prop_name_p, LIT_MAGIC_STRING_PROTOTYPE)) + { + return ecma_raise_type_error (ECMA_ERR_CLASS_IS_NON_CONFIGURABLE); + } + + index--; + } +#else /* !JERRY_ESNEXT */ + JERRY_UNUSED (is_static); +#endif /* JERRY_ESNEXT */ + + ecma_object_t *object_p = ecma_get_object_from_value (stack_top_p[index]); + + opfunc_assing_data_property (object_p, prop_name_p, value); + ecma_deref_ecma_string (prop_name_p); + + return ECMA_VALUE_EMPTY; +} /* opfunc_set_data_property */ + /** * @} * @} diff --git a/jerry-core/vm/opcodes.h b/jerry-core/vm/opcodes.h index 1657755d1b..415ec748f2 100644 --- a/jerry-core/vm/opcodes.h +++ b/jerry-core/vm/opcodes.h @@ -67,11 +67,6 @@ typedef enum #endif /* JERRY_ESNEXT */ -/** - * The stack contains spread object during the upcoming APPEND_ARRAY operation - */ -#define OPFUNC_HAS_SPREAD_ELEMENT (1 << 8) - ecma_value_t opfunc_equality (ecma_value_t left_value, ecma_value_t right_value); ecma_value_t do_number_arithmetic (number_arithmetic_op op, ecma_value_t left_value, ecma_value_t right_value); @@ -92,8 +87,6 @@ ecma_value_t opfunc_instanceof (ecma_value_t left_value, ecma_value_t right_valu ecma_value_t opfunc_typeof (ecma_value_t left_value); -void opfunc_set_data_property (ecma_object_t *object_p, ecma_string_t *prop_name_p, ecma_value_t value); - void opfunc_set_accessor (bool is_getter, ecma_value_t object, ecma_string_t *accessor_name_p, ecma_value_t accessor); ecma_value_t vm_op_delete_prop (ecma_value_t object, ecma_value_t property, bool is_strict); @@ -102,13 +95,12 @@ ecma_value_t vm_op_delete_var (ecma_value_t name_literal, ecma_object_t *lex_env ecma_collection_t *opfunc_for_in (ecma_value_t left_value, ecma_value_t *result_obj_p); -#if JERRY_ESNEXT -ecma_collection_t *opfunc_spread_arguments (ecma_value_t *stack_top_p, uint8_t argument_list_len); -#endif /* JERRY_ESNEXT */ - ecma_value_t opfunc_append_array (ecma_value_t *stack_top_p, uint16_t values_length); #if JERRY_ESNEXT +ecma_value_t opfunc_append_to_spread_array (ecma_value_t *stack_top_p, uint16_t values_length); + +ecma_collection_t *opfunc_spread_arguments (ecma_value_t *stack_top_p, uint8_t argument_list_len); vm_executable_object_t *opfunc_create_executable_object (vm_frame_ctx_t *frame_ctx_p, vm_create_executable_object_type_t type); @@ -128,7 +120,7 @@ ecma_value_t opfunc_init_static_class_fields (ecma_value_t function_object, ecma ecma_value_t opfunc_add_computed_field (ecma_value_t class_object, ecma_value_t name); -ecma_value_t opfunc_create_implicit_class_constructor (uint8_t opcode, const ecma_compiled_code_t *bytecode_p); +ecma_value_t opfunc_create_implicit_class_constructor (const ecma_compiled_code_t *bytecode_p, bool is_herigate); void opfunc_set_home_object (ecma_object_t *func_p, ecma_object_t *parent_env_p); @@ -162,20 +154,22 @@ void opfunc_pop_lexical_environment (vm_frame_ctx_t *frame_ctx_p); void opfunc_finalize_class (vm_frame_ctx_t *frame_ctx_p, ecma_value_t **vm_stack_top_p, ecma_value_t class_name); -ecma_value_t opfunc_form_super_reference (ecma_value_t **vm_stack_top_p, - vm_frame_ctx_t *frame_ctx_p, - ecma_value_t prop_name, - uint8_t opcode); - -ecma_value_t -opfunc_assign_super_reference (ecma_value_t **vm_stack_top_p, vm_frame_ctx_t *frame_ctx_p, uint32_t opcode_data); +ecma_value_t opfunc_resolve_super (vm_frame_ctx_t *frame_ctx_p); ecma_value_t opfunc_copy_data_properties (ecma_value_t target_object, ecma_value_t source_object, ecma_value_t filter_array); ecma_value_t opfunc_lexical_scope_has_restricted_binding (vm_frame_ctx_t *vm_frame_ctx_p, ecma_string_t *name_p); + +void opfunc_set_function_name (ecma_value_t function_object, + ecma_value_t function_name, + char *prefix_p, + lit_utf8_size_t prefix_size); #endif /* JERRY_ESNEXT */ +ecma_value_t +opfunc_set_data_property (ecma_value_t *stack_top_p, ecma_value_t prop_name, ecma_value_t value, bool is_static); + /** * @} * @} diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index 95b5840dd2..c58d9a5472 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -236,16 +236,6 @@ vm_op_set_value (ecma_value_t base, /**< base object */ return result; } /* vm_op_set_value */ -/** Compact bytecode define */ -#define CBC_OPCODE(arg1, arg2, arg3, arg4) arg4, - -/** - * Decode table for both opcodes and extended opcodes. - */ -static const uint16_t vm_decode_table[] JERRY_ATTR_CONST_DATA = { CBC_OPCODE_LIST CBC_EXT_OPCODE_LIST }; - -#undef CBC_OPCODE - /** * Run global code * @@ -622,13 +612,13 @@ vm_super_call (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ else { frame_ctx_p->byte_code_p = byte_code_p; - uint32_t opcode_data = vm_decode_table[(CBC_END + 1) + opcode]; + vm_put_result_flags_t put_result_flags = (opcode - CBC_EXT_SUPER_CALL) % 3; - if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) + if (!(put_result_flags & (VM_PUT_RESULT_STACK | VM_PUT_RESULT_BLOCK))) { ecma_fast_free_value (completion_value); } - else if (opcode_data & VM_OC_PUT_STACK) + else if (put_result_flags & VM_PUT_RESULT_STACK) { *frame_ctx_p->stack_top_p++ = completion_value; } @@ -711,13 +701,13 @@ vm_spread_operation (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } else { - uint32_t opcode_data = vm_decode_table[(CBC_END + 1) + opcode]; + vm_put_result_flags_t put_result_flags = (opcode - CBC_EXT_SPREAD_CALL) % 3; - if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) + if (!(put_result_flags & (VM_PUT_RESULT_STACK | VM_PUT_RESULT_BLOCK))) { ecma_fast_free_value (completion_value); } - else if (opcode_data & VM_OC_PUT_STACK) + else if (put_result_flags & VM_PUT_RESULT_STACK) { *frame_ctx_p->stack_top_p++ = completion_value; } @@ -788,13 +778,13 @@ opfunc_call (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { frame_ctx_p->byte_code_p = byte_code_p; ecma_free_value (*(--stack_top_p)); - uint32_t opcode_data = vm_decode_table[opcode]; + vm_put_result_flags_t put_result_flags = (opcode - CBC_CALL) % 3; - if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) + if (!(put_result_flags & (VM_PUT_RESULT_STACK | VM_PUT_RESULT_BLOCK))) { ecma_fast_free_value (completion_value); } - else if (opcode_data & VM_OC_PUT_STACK) + else if (put_result_flags & VM_PUT_RESULT_STACK) { *stack_top_p++ = completion_value; } @@ -894,77 +884,546 @@ opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ * When we are able to construct a function with similar speed, * we can remove this macro. */ -#define READ_LITERAL(literal_index, target_value) \ - do \ - { \ - if ((literal_index) < ident_end) \ - { \ - if ((literal_index) < register_end) \ - { \ - /* Note: There should be no specialization for arguments. */ \ - (target_value) = ecma_fast_copy_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); \ - } \ - else \ - { \ - ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); \ - \ - result = ecma_op_resolve_reference_value (frame_ctx_p->lex_env_p, name_p); \ - \ - if (ECMA_IS_VALUE_ERROR (result)) \ - { \ - goto error; \ - } \ - (target_value) = result; \ - } \ - } \ - else if (literal_index < const_literal_end) \ - { \ - (target_value) = ecma_fast_copy_value (literal_start_p[literal_index]); \ - } \ - else \ - { \ - /* Object construction. */ \ - (target_value) = vm_construct_literal_object (frame_ctx_p, literal_start_p[literal_index]); \ - } \ - } while (0) +#define READ_LITERAL(literal_index, target_value) \ + if ((literal_index) < register_end) \ + { \ + /* Note: There should be no specialization for arguments. */ \ + (target_value) = ecma_fast_copy_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); \ + } \ + else if ((literal_index) < ident_end) \ + { \ + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); \ + \ + result = ecma_op_resolve_reference_value (frame_ctx_p->lex_env_p, name_p); \ + \ + if (ECMA_IS_VALUE_ERROR (result)) \ + { \ + goto error; \ + } \ + (target_value) = result; \ + } \ + else if (literal_index < const_literal_end) \ + { \ + (target_value) = ecma_fast_copy_value (literal_start_p[literal_index]); \ + } \ + else \ + { \ + /* Object construction. */ \ + (target_value) = vm_construct_literal_object (frame_ctx_p, literal_start_p[literal_index]); \ + } + +/** + * Get the end of the existing topmost context + */ +#define VM_LAST_CONTEXT_END() (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth) /** - * Store the original value for post increase/decrease operators + * VM opcode layout: * - * @param value original value + * 0 - 255: CBC opcodes + * 256 - 511: decoded CBC opcodes with one literal or branch argument + * 511 - 767: decoded CBC opcodes with two literal arguments + * + * 768 - 1023: CBC_EXTt opcodes + * 1024 - 1279: decoded CBC_EXT opcodes with one literal or branch argument + * 1280 - 1535: decoded CBC_EXT opcodes with two literal arguments + */ + +/** + * Whenver an opcode's argument is decoded in `VM_DECODE_ARGUMENT_OPCODE` block + * the opcode is incremented by this offset + */ +#define VM_OPCODE_DECODED_ARG 256 + +/** + * Decoded branch CBC opcode + */ +#define VM_OPCODE_BRANCH(opcode) (opcode + VM_OPCODE_DECODED_ARG) + +/** + * Decoded CBC opcode with one literal argument + */ +#define VM_OPCODE_ONE_LITERAL(opcode) (opcode + VM_OPCODE_DECODED_ARG) + +/** + * Decoded CBC opcode with two literal arguments + */ +#define VM_OPCODE_TWO_LITERALS(opcode) (VM_OPCODE_ONE_LITERAL (opcode) + VM_OPCODE_DECODED_ARG) + +/** + * Last VM opcode for CBC opcodes + */ +#define VM_OPCODE_LAST VM_OPCODE_TWO_LITERALS (VM_OPCODE_DECODED_ARG) + +/** + * CBC_EXT opcodes corresponding VM opcode + */ +#define VM_EXT_OPCODE(opcode) (VM_OPCODE_LAST + opcode) + +/** + * Generate VM opcode cases for branch CBC opcodes + */ +#define VM_OPCODE_BRANCH_CASE(op) \ + VM_OPCODE_BRANCH (op) : case VM_OPCODE_BRANCH (op##_2) : case VM_OPCODE_BRANCH (op##_3) + +/** + * Generate VM opcode cases for CBC opcodes with put result + */ +#define VM_OPCODE_PUT_RESULT_CASE(op) \ +op: \ + case op##_PUSH_RESULT: \ + case op##_BLOCK + +/** + * Generate VM opcode cases for CBC opcodes with put result and one literal argument + */ +#define VM_OPCODE_ONE_LITERAL_PUT_RESULT_CASE(op) \ + VM_OPCODE_ONE_LITERAL (op) : case VM_OPCODE_ONE_LITERAL (op##_PUSH_RESULT) : case VM_OPCODE_ONE_LITERAL (op##_BLOCK) + +/** + * Generate VM opcode cases for arithmetic CBC opcodes + */ +#define VM_OPCODE_ARITHMETIC_CASE(op) \ + VM_OPCODE_ONE_LITERAL (op##_RIGHT_LITERAL) : case VM_OPCODE_TWO_LITERALS (op##_TWO_LITERALS) + +/** + * Decoded branch CBC_EXT opcode + */ +#define VM_EXT_OPCODE_BRANCH(ext_opcode) (VM_EXT_OPCODE (ext_opcode) + VM_OPCODE_DECODED_ARG) + +/** + * Decoded CBC_EXT opcode with one literal argument + */ +#define VM_EXT_OPCODE_ONE_LITERAL(ext_opcode) (VM_EXT_OPCODE (ext_opcode) + VM_OPCODE_DECODED_ARG) + +/** + * Decoded CBC_EXT opcode with two literal arguments + */ +#define VM_EXT_OPCODE_TWO_LITERALS(ext_opcode) (VM_EXT_OPCODE_ONE_LITERAL (ext_opcode) + VM_OPCODE_DECODED_ARG) + +/** + * Last VM opcode for CBC_EXT opcodes + */ +#define VM_EXT_OPCODE_LAST VM_EXT_OPCODE_TWO_LITERALS (VM_OPCODE_DECODED_ARG) + +/** + * Generate VM opcode cases for branch CBC_EXT opcodes + */ +#define VM_EXT_OPCODE_BRANCH_CASE(op) \ + VM_EXT_OPCODE_BRANCH (op) : case VM_EXT_OPCODE_BRANCH (op##_2) : case VM_EXT_OPCODE_BRANCH (op##_3) + +/** + * VM opcode case where for argument decoding + */ +#define VM_DECODE_ARGUMENT_OPCODE (VM_EXT_OPCODE_LAST + 1) + +/** + * Open an unreachable block. This can be used to create cases with same ending, however the normal execution never + * reaches this block. You can enter this block via goto or you can place the opcode dispather `case VM_OPCODE...:` + * label into this block. */ -#define POST_INCREASE_DECREASE_PUT_RESULT(value) \ - if (opcode_data & VM_OC_PUT_STACK) \ - { \ - if (opcode_flags & VM_OC_IDENT_INCR_DECR_OPERATOR_FLAG) \ - { \ - JERRY_ASSERT (opcode == CBC_POST_INCR_IDENT_PUSH_RESULT || opcode == CBC_POST_DECR_IDENT_PUSH_RESULT); \ - *stack_top_p++ = (value); \ - } \ - else \ - { \ - /* The parser ensures there is enough space for the \ - * extra value on the stack. See js-parser-expr.c. */ \ - JERRY_ASSERT (opcode == CBC_POST_INCR_PUSH_RESULT || opcode == CBC_POST_DECR_PUSH_RESULT); \ - stack_top_p++; \ - stack_top_p[-1] = stack_top_p[-2]; \ - stack_top_p[-2] = stack_top_p[-3]; \ - stack_top_p[-3] = (value); \ - } \ - opcode_data &= (uint32_t) ~VM_OC_PUT_STACK; \ - } \ - else \ - { \ - JERRY_ASSERT (opcode_data &VM_OC_PUT_BLOCK); \ - ecma_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); \ - VM_GET_REGISTERS (frame_ctx_p)[0] = (value); \ - opcode_data &= (uint32_t) ~VM_OC_PUT_BLOCK; \ +#define VM_OPCODE_UNREACHABLE_BLOCK if (0) + +/** + * Decode CBC opcode with one literal argument. + * The decoded literal is placed into `left_value` + */ +#define VM_DECODE_LITERAL(op) \ + VM_OPCODE_UNREACHABLE_BLOCK \ + { \ + case op: \ + { \ + goto decode_one_literal; \ + } \ } /** - * Get the end of the existing topmost context + * Decode 2 CBC opcodes with one literal argument + * The decoded literal is placed into `left_value` */ -#define VM_LAST_CONTEXT_END() (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth) +#define VM_DECODE_LITERAL_2(op1, op2) \ + VM_OPCODE_UNREACHABLE_BLOCK \ + { \ + case op1: \ + case op2: \ + { \ + goto decode_one_literal; \ + } \ + } + +/** + * Decode CBC opcode with two literal arguments + * The first decoded literal is placed into `left_value` + * The second decoded literal is placed into `right_value` + */ +#define VM_DECODE_LITERAL_LITERAL(op) \ + VM_OPCODE_UNREACHABLE_BLOCK \ + { \ + case op: \ + { \ + goto decode_first_literal; \ + } \ + case VM_OPCODE_ONE_LITERAL (op): \ + { \ + goto decode_second_literal; \ + } \ + } + +/** + * Decode 2 CBC opcodes with two literal arguments + * The first decoded literal is placed into `left_value` + * The second decoded literal is placed into `right_value` + */ +#define VM_DECODE_LITERAL_LITERAL_2(op1, op2) \ + VM_OPCODE_UNREACHABLE_BLOCK \ + { \ + case op1: \ + case op2: \ + { \ + goto decode_first_literal; \ + } \ + case VM_OPCODE_ONE_LITERAL (op1): \ + case VM_OPCODE_ONE_LITERAL (op2): \ + { \ + goto decode_second_literal; \ + } \ + } + +/** + * Decode CBC opcode with this argument and one literal argument + * The frame context's this_value is placed into `left_value` + * The decoded literal is placed into `right_value` + */ +#define VM_DECODE_THIS_LITERAL(op) \ + VM_OPCODE_UNREACHABLE_BLOCK \ + { \ + case op: \ + { \ + goto decode_this_literal; \ + } \ + } + +/** + * Decode two CBC opcodes with this argument and one literal argument + * The frame context's this_value is placed into `left_value` + * The decoded literal is placed into `right_value` + */ +#define VM_DECODE_THIS_LITERAL_2(op1, op2) \ + VM_OPCODE_UNREACHABLE_BLOCK \ + { \ + case op1: \ + case op2: \ + { \ + goto decode_this_literal; \ + } \ + } + +/** + * Pop an element from the stack into `target` + */ +#define VM_POP_STACK(target) \ + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); \ + (target) = *(--stack_top_p) + +/** + * Pop two elements from the stack into `target1` and `target2` + */ +#define VM_POP_STACK_STACK(target1, target2) \ + VM_POP_STACK (target1); \ + VM_POP_STACK (target2) + +/** + * Decode CBC opcode with pop stack argument + * The popped element from the stack is placed into `left_value` + */ +#define VM_DECODE_STACK(op) \ + VM_OPCODE_UNREACHABLE_BLOCK \ + { \ + case op: \ + { \ + VM_POP_STACK (left_value); \ + } \ + } + +/** + * Decode 2 CBC opcodes with pop stack argument + * The popped element from the stack is placed into `left_value` + */ +#define VM_DECODE_STACK_2(op1, op2) \ + VM_OPCODE_UNREACHABLE_BLOCK \ + { \ + case op1: \ + case op2: \ + { \ + VM_POP_STACK (left_value); \ + } \ + } + +/** + * Decode CBC opcode with pop stack-stack argument + * The first popped element from the stack is placed into `right_value` + * The second popped element from the stack is placed into `left_value` + */ +#define VM_DECODE_STACK_STACK(op) \ + VM_OPCODE_UNREACHABLE_BLOCK \ + { \ + case op: \ + { \ + VM_POP_STACK_STACK (right_value, left_value); \ + } \ + } + +/** + * Decode 2 CBC opcodes with pop stack-stack argument + * The first popped element from the stack is placed into `right_value` + * The second popped element from the stack is placed into `left_value` + */ +#define VM_DECODE_STACK_STACK_2(op1, op2) \ + VM_OPCODE_UNREACHABLE_BLOCK \ + { \ + case op1: \ + case op2: \ + { \ + VM_POP_STACK_STACK (right_value, left_value); \ + } \ + } + +/** + * Decode CBC opcode with pop stack and one literal argument + * The popped element from the stack is placed into `left_value` + * The decoded literal is placed into `right_value` + */ +#define VM_DECODE_STACK_LITERAL(op) \ + VM_OPCODE_UNREACHABLE_BLOCK \ + { \ + case op: \ + { \ + goto decode_stack_literal; \ + } \ + } + +/** + * Decode 2 CBC opcodes with pop stack and one literal argument + * The popped element from the stack is placed into `left_value` + * The decoded literal is placed into `right_value` + */ +#define VM_DECODE_STACK_LITERAL_2(op1, op2) \ + VM_OPCODE_UNREACHABLE_BLOCK \ + { \ + case op1: \ + case op2: \ + { \ + goto decode_stack_literal; \ + } \ + } + +/** + * Decode CBC opcode with forward branch argument + * The decoded branch offset is placed into `branch_offset` + */ +#define VM_DECODE_FORWARD_BRANCH(op) \ + VM_OPCODE_UNREACHABLE_BLOCK \ + { \ + case op: \ + { \ + goto decode_forward_branch_1; \ + } \ + case op##_2: \ + { \ + goto decode_forward_branch_2; \ + } \ + case op##_3: \ + { \ + goto decode_forward_branch_3; \ + } \ + } + +/** + * Decode CBC opcode with backward branch argument + * The decoded branch offset is placed into `branch_offset` + */ +#define VM_DECODE_BACKWARD_BRANCH(op) \ + VM_OPCODE_UNREACHABLE_BLOCK \ + { \ + case op: \ + { \ + goto decode_backward_branch_1; \ + } \ + case op##_2: \ + { \ + goto decode_backward_branch_2; \ + } \ + case op##_3: \ + { \ + goto decode_backward_branch_3; \ + } \ + } + +/** + * Decode arguments of an arithmetic CBC opcode + */ +#define VM_DECODE_ARITHMETIC(op) \ + VM_DECODE_STACK_LITERAL (op##_RIGHT_LITERAL); \ + VM_DECODE_LITERAL_LITERAL (op##_TWO_LITERALS); \ + VM_DECODE_STACK_STACK (op) + +/** + * Decode CBC opcode with put result and one literal argument. + * The decoded literal is placed into `left_value` + */ +#define VM_DECODE_LITERAL_PUT_RESULT(op) \ + VM_OPCODE_UNREACHABLE_BLOCK \ + { \ + case op: \ + case op##_PUSH_RESULT: \ + case op##_BLOCK: \ + { \ + goto decode_one_literal; \ + } \ + } + +/** + * Generate VM opcode cases for CBC_EXT opcodes with put result + */ +#define VM_EXT_OPCODE_PUT_RESULT_CASE(op) \ + VM_EXT_OPCODE (op) : case VM_EXT_OPCODE (op##_PUSH_RESULT) : case VM_EXT_OPCODE (op##_BLOCK) + +/** + * Generate VM opcode cases for arithmetic CBC_EXT opcodes + */ +#define VM_EXT_OPCODE_ARITHMETIC_CASE(op) \ + VM_EXT_OPCODE_ONE_LITERAL (op##_RIGHT_LITERAL) : case VM_EXT_OPCODE_TWO_LITERALS (op##_TWO_LITERALS) + +/** + * VM_DECODE_STACK marco for CBC_EXT opcodes + */ +#define VM_DECODE_EXT_STACK(op) VM_DECODE_STACK (VM_EXT_OPCODE (op)) + +/** + * VM_DECODE_STACK_STACK marco for CBC_EXT opcodes + */ +#define VM_DECODE_EXT_STACK_STACK(op) VM_DECODE_STACK_STACK (VM_EXT_OPCODE (op)) + +/** + * VM_DECODE_STACK_LITERAL marco for CBC_EXT opcodes + */ +#define VM_DECODE_EXT_STACK_LITERAL(op) VM_DECODE_STACK_LITERAL (VM_EXT_OPCODE (op)) + +/** + * VM_DECODE_LITERAL marco for CBC_EXT opcodes + */ +#define VM_DECODE_EXT_LITERAL(op) VM_DECODE_LITERAL (VM_EXT_OPCODE (op)) + +/** + * VM_DECODE_LITERAL_LITERAL marco for CBC_EXT opcodes + */ +#define VM_DECODE_EXT_LITERAL_LITERAL(op) VM_DECODE_LITERAL_LITERAL (VM_EXT_OPCODE (op)) + +/** + * VM_DECODE_STACK_2 marco for CBC_EXT opcodes + */ +#define VM_DECODE_EXT_STACK_2(op1, op2) VM_DECODE_STACK_2 (VM_EXT_OPCODE (op1), VM_EXT_OPCODE (op2)) + +/** + * VM_DECODE_STACK_STACK_2 marco for CBC_EXT opcodes + */ +#define VM_DECODE_EXT_STACK_STACK_2(op1, op2) VM_DECODE_STACK_STACK_2 (VM_EXT_OPCODE (op1), VM_EXT_OPCODE (op2)) + +/** + * VM_DECODE_STACK_LITERAL_2 marco for CBC_EXT opcodes + */ +#define VM_DECODE_EXT_STACK_LITERAL_2(op1, op2) VM_DECODE_STACK_LITERAL_2 (VM_EXT_OPCODE (op1), VM_EXT_OPCODE (op2)) + +/** + * VM_DECODE_LITERAL_2 marco for CBC_EXT opcodes + */ +#define VM_DECODE_EXT_LITERAL_2(op1, op2) VM_DECODE_LITERAL_2 (VM_EXT_OPCODE (op1), VM_EXT_OPCODE (op2)) + +/** + * VM_DECODE_LITERAL_LITERAL_2 marco for CBC_EXT opcodes + */ +#define VM_DECODE_EXT_LITERAL_LITERAL_2(op1, op2) VM_DECODE_LITERAL_LITERAL_2 (VM_EXT_OPCODE (op1), VM_EXT_OPCODE (op2)) + +/** + * VM_DECODE_FORWARD_BRANCH macro for CBC_EXT opcodes + */ +#define VM_DECODE_EXT_FORWARD_BRANCH(op) \ + VM_OPCODE_UNREACHABLE_BLOCK \ + { \ + case VM_EXT_OPCODE (op): \ + { \ + goto decode_forward_branch_1; \ + } \ + case VM_EXT_OPCODE (op##_2): \ + { \ + goto decode_forward_branch_2; \ + } \ + case VM_EXT_OPCODE (op##_3): \ + { \ + goto decode_forward_branch_3; \ + } \ + } + +/** + * VM_DECODE_BACKWARD_BRANCH macro for CBC_EXT opcodes + */ +#define VM_DECODE_EXT_BACKWARD_BRANCH(op) \ + VM_OPCODE_UNREACHABLE_BLOCK \ + { \ + case VM_EXT_OPCODE (op): \ + { \ + goto decode_backward_branch_1; \ + } \ + case VM_EXT_OPCODE (op##_2): \ + { \ + goto decode_backward_branch_2; \ + } \ + case VM_EXT_OPCODE (op##_3): \ + { \ + goto decode_backward_branch_3; \ + } \ + } + +/** + * Decode arguments of an arithmetic CBC_EXT opcode + */ +#define VM_DECODE_EXT_ARITHMETIC(op) \ + VM_DECODE_EXT_STACK_LITERAL (op##_RIGHT_LITERAL); \ + VM_DECODE_EXT_LITERAL_LITERAL (op##_TWO_LITERALS); \ + VM_DECODE_EXT_STACK_STACK (op) + +/** + * Put result decode table for pre/post incr/decr opcodes + */ +static const uint8_t vm_incr_decr_flags[] = { + VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_NONE, + VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_STACK, + VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_BLOCK, + VM_PUT_RESULT_IDENT | VM_PUT_RESULT_NONE, + VM_PUT_RESULT_IDENT | VM_PUT_RESULT_STACK, + VM_PUT_RESULT_IDENT | VM_PUT_RESULT_BLOCK, + + VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_DECR | VM_PUT_RESULT_NONE, + VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_DECR | VM_PUT_RESULT_STACK, + VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_DECR | VM_PUT_RESULT_BLOCK, + VM_PUT_RESULT_IDENT | VM_PUT_RESULT_DECR | VM_PUT_RESULT_NONE, + VM_PUT_RESULT_IDENT | VM_PUT_RESULT_DECR | VM_PUT_RESULT_STACK, + VM_PUT_RESULT_IDENT | VM_PUT_RESULT_DECR | VM_PUT_RESULT_BLOCK, + + VM_PUT_RESULT_POST | VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_NONE, + VM_PUT_RESULT_POST | VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_STACK, + VM_PUT_RESULT_POST | VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_BLOCK, + VM_PUT_RESULT_POST | VM_PUT_RESULT_IDENT | VM_PUT_RESULT_NONE, + VM_PUT_RESULT_POST | VM_PUT_RESULT_IDENT | VM_PUT_RESULT_STACK, + VM_PUT_RESULT_POST | VM_PUT_RESULT_IDENT | VM_PUT_RESULT_BLOCK, + + VM_PUT_RESULT_POST | VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_DECR | VM_PUT_RESULT_NONE, + VM_PUT_RESULT_POST | VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_DECR | VM_PUT_RESULT_STACK, + VM_PUT_RESULT_POST | VM_PUT_RESULT_REFERENCE | VM_PUT_RESULT_DECR | VM_PUT_RESULT_BLOCK, + VM_PUT_RESULT_POST | VM_PUT_RESULT_IDENT | VM_PUT_RESULT_DECR | VM_PUT_RESULT_NONE, + VM_PUT_RESULT_POST | VM_PUT_RESULT_IDENT | VM_PUT_RESULT_DECR | VM_PUT_RESULT_STACK, + VM_PUT_RESULT_POST | VM_PUT_RESULT_IDENT | VM_PUT_RESULT_DECR | VM_PUT_RESULT_BLOCK, +}; /** * Run generic byte code. @@ -985,11 +1444,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ uint16_t ident_end; uint16_t const_literal_end; int32_t branch_offset = 0; - uint8_t branch_offset_length = 0; ecma_value_t left_value; ecma_value_t right_value; ecma_value_t result = ECMA_VALUE_EMPTY; bool is_strict = ((bytecode_header_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0); + uint8_t put_result_flags = VM_PUT_RESULT_NONE; /* Prepare for byte code execution. */ if (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_FULL_LITERAL_ENCODING)) @@ -1027,92 +1486,51 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ while (true) { const uint8_t *byte_code_start_p = byte_code_p; - uint8_t opcode = *byte_code_p++; - uint32_t opcode_data = opcode; - - if (opcode == CBC_EXT_OPCODE) - { - opcode = *byte_code_p++; - opcode_data = (uint32_t) ((CBC_END + 1) + opcode); - } - - opcode_data = vm_decode_table[opcode_data]; + uint16_t opcode = *byte_code_p++; left_value = ECMA_VALUE_UNDEFINED; right_value = ECMA_VALUE_UNDEFINED; - uint32_t operands = VM_OC_GET_ARGS_INDEX (opcode_data); - - if (operands >= VM_OC_GET_LITERAL) +dispatch_opcode: + switch (opcode) { - uint16_t literal_index; - READ_LITERAL_INDEX (literal_index); - READ_LITERAL (literal_index, left_value); - - if (operands != VM_OC_GET_LITERAL) + case VM_DECODE_ARGUMENT_OPCODE: { - switch (operands) - { - case VM_OC_GET_LITERAL_LITERAL: - { - uint16_t second_literal_index; - READ_LITERAL_INDEX (second_literal_index); - READ_LITERAL (second_literal_index, right_value); - break; - } - case VM_OC_GET_STACK_LITERAL: - { - JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); - right_value = left_value; - left_value = *(--stack_top_p); - break; - } - default: - { - JERRY_ASSERT (operands == VM_OC_GET_THIS_LITERAL); +decode_forward_branch_1: + branch_offset = *(byte_code_p++); - right_value = left_value; - left_value = ecma_copy_value (frame_ctx_p->this_binding); - break; - } + VM_OPCODE_UNREACHABLE_BLOCK + { +decode_forward_branch_2: + branch_offset = byte_code_p[0] << 8 | byte_code_p[1]; + byte_code_p += 2; + } + VM_OPCODE_UNREACHABLE_BLOCK + { +decode_forward_branch_3: + branch_offset = byte_code_p[0] << 16 | byte_code_p[1] << 8 | byte_code_p[2]; + byte_code_p += 3; } - } - } - else if (operands >= VM_OC_GET_STACK) - { - JERRY_ASSERT (operands == VM_OC_GET_STACK || operands == VM_OC_GET_STACK_STACK); - - JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); - left_value = *(--stack_top_p); - - if (operands == VM_OC_GET_STACK_STACK) - { - JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); - right_value = left_value; - left_value = *(--stack_top_p); - } - } - else if (operands == VM_OC_GET_BRANCH) - { - branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (opcode); - JERRY_ASSERT (branch_offset_length >= 1 && branch_offset_length <= 3); - branch_offset = *(byte_code_p++); + opcode = (uint16_t) (opcode + VM_OPCODE_DECODED_ARG); + goto dispatch_opcode; - if (JERRY_UNLIKELY (branch_offset_length != 1)) - { - branch_offset <<= 8; - branch_offset |= *(byte_code_p++); +decode_backward_branch_1: + branch_offset = -(*byte_code_p++); - if (JERRY_UNLIKELY (branch_offset_length == 3)) + VM_OPCODE_UNREACHABLE_BLOCK { - branch_offset <<= 8; - branch_offset |= *(byte_code_p++); +decode_backward_branch_2: + branch_offset = -(byte_code_p[0] << 8 | byte_code_p[1]); + byte_code_p += 2; + } + VM_OPCODE_UNREACHABLE_BLOCK + { +decode_backward_branch_3: + branch_offset = -(byte_code_p[0] << 16 | byte_code_p[1] << 8 | byte_code_p[2]); + byte_code_p += 3; } - } - if (opcode_data & VM_OC_BACKWARD_BRANCH) - { #if JERRY_VM_HALT if (JERRY_CONTEXT (vm_exec_stop_cb) != NULL && --JERRY_CONTEXT (vm_exec_stop_counter) == 0) { @@ -1143,115 +1561,150 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } #endif /* JERRY_VM_HALT */ - branch_offset = -branch_offset; - } - } + opcode = (uint16_t) (opcode + VM_OPCODE_DECODED_ARG); + goto dispatch_opcode; - switch (VM_OC_GROUP_GET_INDEX (opcode_data)) - { - case VM_OC_POP: + uint16_t literal_index; +decode_one_literal: + READ_LITERAL_INDEX (literal_index); + READ_LITERAL (literal_index, left_value); + + opcode = (uint16_t) (opcode + VM_OPCODE_DECODED_ARG); + goto dispatch_opcode; + +decode_second_literal: + left_value = right_value; + right_value = ECMA_VALUE_UNDEFINED; + + VM_OPCODE_UNREACHABLE_BLOCK + { +decode_stack_literal: + VM_POP_STACK (left_value); + } + VM_OPCODE_UNREACHABLE_BLOCK + { +decode_this_literal: + left_value = ecma_copy_value (frame_ctx_p->this_binding); + } + +decode_first_literal: + READ_LITERAL_INDEX (literal_index); + READ_LITERAL (literal_index, right_value); + + opcode = (uint16_t) (opcode + VM_OPCODE_DECODED_ARG); + goto dispatch_opcode; + } + case CBC_EXT_OPCODE: + { + opcode = (uint16_t) VM_EXT_OPCODE (*byte_code_p++); + goto dispatch_opcode; + } + case CBC_POP: { JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); ecma_free_value (*(--stack_top_p)); continue; } - case VM_OC_POP_BLOCK: + case CBC_POP_BLOCK: { ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); VM_GET_REGISTERS (frame_ctx_p)[0] = *(--stack_top_p); continue; } - case VM_OC_PUSH: + case VM_OPCODE_ONE_LITERAL (CBC_PUSH_LITERAL): { + VM_DECODE_LITERAL (CBC_PUSH_LITERAL); + *stack_top_p++ = left_value; continue; } - case VM_OC_PUSH_TWO: + case VM_OPCODE_ONE_LITERAL (CBC_PUSH_THIS_LITERAL): + case VM_OPCODE_TWO_LITERALS (CBC_PUSH_TWO_LITERALS): { + VM_DECODE_LITERAL_LITERAL (CBC_PUSH_TWO_LITERALS); + VM_DECODE_THIS_LITERAL (CBC_PUSH_THIS_LITERAL) + *stack_top_p++ = left_value; *stack_top_p++ = right_value; continue; } - case VM_OC_PUSH_THREE: + case VM_OPCODE_TWO_LITERALS (CBC_PUSH_THREE_LITERALS): { - uint16_t literal_index; - - *stack_top_p++ = left_value; - left_value = ECMA_VALUE_UNDEFINED; - - READ_LITERAL_INDEX (literal_index); - READ_LITERAL (literal_index, left_value); + VM_DECODE_LITERAL_LITERAL (CBC_PUSH_THREE_LITERALS); - *stack_top_p++ = right_value; *stack_top_p++ = left_value; - continue; + opcode = VM_OPCODE_ONE_LITERAL (CBC_PUSH_TWO_LITERALS); + goto decode_second_literal; } - case VM_OC_PUSH_UNDEFINED: + case CBC_PUSH_UNDEFINED: { *stack_top_p++ = ECMA_VALUE_UNDEFINED; continue; } - case VM_OC_PUSH_TRUE: + case CBC_PUSH_TRUE: { *stack_top_p++ = ECMA_VALUE_TRUE; continue; } - case VM_OC_PUSH_FALSE: + case CBC_PUSH_FALSE: { *stack_top_p++ = ECMA_VALUE_FALSE; continue; } - case VM_OC_PUSH_NULL: + case CBC_PUSH_NULL: { *stack_top_p++ = ECMA_VALUE_NULL; continue; } - case VM_OC_PUSH_THIS: + case CBC_PUSH_THIS: { *stack_top_p++ = ecma_copy_value (frame_ctx_p->this_binding); continue; } - case VM_OC_PUSH_0: + case CBC_PUSH_NUMBER_0: { *stack_top_p++ = ecma_make_integer_value (0); continue; } - case VM_OC_PUSH_POS_BYTE: + case CBC_PUSH_NUMBER_POS_BYTE: { ecma_integer_value_t number = *byte_code_p++; *stack_top_p++ = ecma_make_integer_value (number + 1); continue; } - case VM_OC_PUSH_NEG_BYTE: + case CBC_PUSH_NUMBER_NEG_BYTE: { ecma_integer_value_t number = *byte_code_p++; *stack_top_p++ = ecma_make_integer_value (-(number + 1)); continue; } - case VM_OC_PUSH_LIT_0: + case VM_OPCODE_ONE_LITERAL (CBC_PUSH_LITERAL_PUSH_NUMBER_0): { + VM_DECODE_LITERAL (CBC_PUSH_LITERAL_PUSH_NUMBER_0); stack_top_p[0] = left_value; stack_top_p[1] = ecma_make_integer_value (0); stack_top_p += 2; continue; } - case VM_OC_PUSH_LIT_POS_BYTE: + case VM_OPCODE_ONE_LITERAL (CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE): { + VM_DECODE_LITERAL (CBC_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE); ecma_integer_value_t number = *byte_code_p++; stack_top_p[0] = left_value; stack_top_p[1] = ecma_make_integer_value (number + 1); stack_top_p += 2; continue; } - case VM_OC_PUSH_LIT_NEG_BYTE: + case VM_OPCODE_ONE_LITERAL (CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE): { + VM_DECODE_LITERAL (CBC_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE); ecma_integer_value_t number = *byte_code_p++; stack_top_p[0] = left_value; stack_top_p[1] = ecma_make_integer_value (-(number + 1)); stack_top_p += 2; continue; } - case VM_OC_PUSH_OBJECT: + case CBC_CREATE_OBJECT: { ecma_object_t *obj_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE), 0, ECMA_OBJECT_TYPE_GENERAL); @@ -1259,8 +1712,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ *stack_top_p++ = ecma_make_object_value (obj_p); continue; } - case VM_OC_PUSH_NAMED_FUNC_EXPR: + case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_PUSH_NAMED_FUNC_EXPRESSION): { + VM_DECODE_EXT_LITERAL_LITERAL (CBC_EXT_PUSH_NAMED_FUNC_EXPRESSION); + ecma_object_t *func_p = ecma_get_object_from_value (left_value); JERRY_ASSERT (ecma_get_object_type (func_p) == ECMA_OBJECT_TYPE_FUNCTION); @@ -1281,12 +1736,13 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ *stack_top_p++ = left_value; continue; } - case VM_OC_CREATE_BINDING: + case CBC_CREATE_VAR: +#if JERRY_ESNEXT + case CBC_CREATE_LET: + case CBC_CREATE_CONST: + case CBC_CREATE_LOCAL: +#endif /* JERRY_ESNEXT */ { -#if !JERRY_ESNEXT - JERRY_ASSERT (opcode == CBC_CREATE_VAR); -#endif /* !JERRY_ESNEXT */ - uint32_t literal_index; READ_LITERAL_INDEX (literal_index); @@ -1321,7 +1777,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ continue; } - case VM_OC_VAR_EVAL: + case CBC_CREATE_VAR_EVAL: + case CBC_CREATE_VAR_FUNC_EVAL: { uint32_t literal_index; ecma_value_t lit_value = ECMA_VALUE_UNDEFINED; @@ -1413,15 +1870,22 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } continue; } + case VM_OPCODE_ONE_LITERAL (CBC_SET_VAR_FUNC): + { + VM_DECODE_LITERAL (CBC_SET_VAR_FUNC); + result = left_value; + left_value = ECMA_VALUE_UNDEFINED; + put_result_flags = VM_PUT_RESULT_NONE; + goto dispatch_put_ident; + } #if JERRY_ESNEXT - case VM_OC_EXT_VAR_EVAL: + case VM_EXT_OPCODE (CBC_EXT_CREATE_VAR_EVAL): + case VM_EXT_OPCODE (CBC_EXT_CREATE_VAR_FUNC_EVAL): { uint32_t literal_index; ecma_value_t lit_value = ECMA_VALUE_UNDEFINED; - JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE); - - if (opcode == CBC_EXT_CREATE_VAR_FUNC_EVAL) + if (opcode == VM_EXT_OPCODE (CBC_EXT_CREATE_VAR_FUNC_EVAL)) { uint32_t value_index; READ_LITERAL_INDEX (value_index); @@ -1486,7 +1950,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ continue; } #endif /* JERRY_ESNEXT */ - case VM_OC_CREATE_ARGUMENTS: + case VM_EXT_OPCODE (CBC_EXT_CREATE_ARGUMENTS): { uint32_t literal_index; READ_LITERAL_INDEX (literal_index); @@ -1517,14 +1981,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ continue; } #if JERRY_SNAPSHOT_EXEC - case VM_OC_SET_BYTECODE_PTR: + case CBC_SET_BYTECODE_PTR: { memcpy (&byte_code_p, byte_code_p++, sizeof (uintptr_t)); frame_ctx_p->byte_code_start_p = byte_code_p; continue; } #endif /* JERRY_SNAPSHOT_EXEC */ - case VM_OC_INIT_ARG_OR_FUNC: + case CBC_INIT_ARG_OR_FUNC: { uint32_t literal_index, value_index; ecma_value_t lit_value; @@ -1575,7 +2039,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ continue; } #if JERRY_ESNEXT - case VM_OC_CHECK_VAR: + case CBC_CHECK_VAR: { JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (frame_ctx_p->shared_p->bytecode_header_p->status_flags) == CBC_FUNCTION_SCRIPT); @@ -1599,7 +2063,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ continue; } - case VM_OC_CHECK_LET: + case CBC_CHECK_LET: { JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (frame_ctx_p->shared_p->bytecode_header_p->status_flags) == CBC_FUNCTION_SCRIPT); @@ -1645,8 +2109,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ continue; } - case VM_OC_ASSIGN_LET_CONST: + case VM_OPCODE_ONE_LITERAL (CBC_ASSIGN_LET_CONST_LITERAL): { + VM_DECODE_LITERAL (CBC_ASSIGN_LET_CONST_LITERAL); + VM_DECODE_STACK (CBC_ASSIGN_LET_CONST); + uint32_t literal_index; READ_LITERAL_INDEX (literal_index); @@ -1670,7 +2137,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } continue; } - case VM_OC_INIT_BINDING: + case CBC_INIT_ARG_OR_CATCH: + case CBC_INIT_LET: + case CBC_INIT_CONST: { uint32_t literal_index; @@ -1705,13 +2174,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_deref_if_object (value); continue; } - case VM_OC_THROW_CONST_ERROR: + case VM_EXT_OPCODE (CBC_EXT_THROW_ASSIGN_CONST_ERROR): { result = ecma_raise_type_error (ECMA_ERR_CONSTANT_BINDINGS_CANNOT_BE_REASSIGNED); goto error; } - case VM_OC_COPY_TO_GLOBAL: + case VM_OPCODE_ONE_LITERAL (CBC_COPY_TO_GLOBAL): { + VM_DECODE_LITERAL (CBC_COPY_TO_GLOBAL); + uint32_t literal_index; READ_LITERAL_INDEX (literal_index); @@ -1762,9 +2233,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } } - goto free_left_value; + ecma_fast_free_value (left_value); + continue; } - case VM_OC_COPY_FROM_ARG: + case VM_EXT_OPCODE (CBC_EXT_COPY_FROM_ARG): { uint32_t literal_index; READ_LITERAL_INDEX (literal_index); @@ -1789,38 +2261,45 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ property_value_p->value = ecma_copy_value_if_not_object (arg_prop_value_p->value); continue; } - case VM_OC_CLONE_CONTEXT: + case VM_EXT_OPCODE (CBC_EXT_CLONE_CONTEXT): + case VM_EXT_OPCODE (CBC_EXT_CLONE_FULL_CONTEXT): { - JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE); - - bool copy_values = (byte_code_start_p[1] == CBC_EXT_CLONE_FULL_CONTEXT); + bool copy_values = (opcode == VM_EXT_OPCODE (CBC_EXT_CLONE_FULL_CONTEXT)); frame_ctx_p->lex_env_p = ecma_clone_decl_lexical_environment (frame_ctx_p->lex_env_p, copy_values); continue; } - case VM_OC_SET__PROTO__: + case VM_EXT_OPCODE (CBC_EXT_SET__PROTO__): { + VM_POP_STACK (left_value); + result = ecma_builtin_object_object_set_proto (stack_top_p[-1], left_value); + if (ECMA_IS_VALUE_ERROR (result)) { goto error; } - goto free_left_value; + + ecma_fast_free_value (left_value); + continue; } - case VM_OC_CLASS_CALL_STATIC_BLOCK: + case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_CLASS_CALL_STATIC_BLOCK): { + VM_DECODE_EXT_LITERAL (CBC_EXT_CLASS_CALL_STATIC_BLOCK); + result = ecma_op_function_call (ecma_get_object_from_value (left_value), frame_ctx_p->this_binding, NULL, 0); if (ECMA_IS_VALUE_ERROR (result)) { goto error; } - goto free_left_value; + + ecma_fast_free_value (left_value); + continue; } - case VM_OC_PUSH_STATIC_FIELD_FUNC: + case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_PUSH_STATIC_FIELD_FUNC): + case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC): { - JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE - && (byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_FIELD_FUNC - || byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC)); + VM_DECODE_EXT_LITERAL_2 (CBC_EXT_PUSH_STATIC_FIELD_FUNC, CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC); bool push_computed = (byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC); ecma_value_t value = stack_top_p[-1]; @@ -1843,27 +2322,23 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } left_value = value; - /* FALLTHRU */ - } - case VM_OC_ADD_COMPUTED_FIELD: - { - JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE - && (byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC - || byte_code_start_p[1] == CBC_EXT_ADD_COMPUTED_FIELD - || byte_code_start_p[1] == CBC_EXT_ADD_STATIC_COMPUTED_FIELD)); - int index = (byte_code_start_p[1] == CBC_EXT_ADD_COMPUTED_FIELD) ? -2 : -4; + VM_DECODE_EXT_STACK_2 (CBC_EXT_ADD_COMPUTED_FIELD, CBC_EXT_ADD_STATIC_COMPUTED_FIELD); + + int index = (opcode == VM_EXT_OPCODE (CBC_EXT_ADD_COMPUTED_FIELD)) ? -2 : -4; result = opfunc_add_computed_field (stack_top_p[index], left_value); if (ECMA_IS_VALUE_ERROR (result)) { goto error; } - goto free_left_value; + + ecma_fast_free_value (left_value); + continue; } - case VM_OC_COPY_DATA_PROPERTIES: + case VM_EXT_OPCODE (CBC_EXT_COPY_DATA_PROPERTIES): { - left_value = *(--stack_top_p); + VM_POP_STACK (left_value); if (ecma_is_value_undefined (left_value) || ecma_is_value_null (left_value)) { @@ -1877,56 +2352,60 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ goto error; } - goto free_left_value; - } - case VM_OC_SET_COMPUTED_PROPERTY: - { - /* Swap values. */ - left_value ^= right_value; - right_value ^= left_value; - left_value ^= right_value; - /* FALLTHRU */ + ecma_fast_free_value (left_value); + continue; } -#endif /* JERRY_ESNEXT */ - case VM_OC_SET_PROPERTY: + case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL): { - JERRY_STATIC_ASSERT (VM_OC_NON_STATIC_FLAG == VM_OC_BACKWARD_BRANCH, - vm_oc_non_static_flag_must_be_equal_to_vm_oc_backward_branch); + VM_DECODE_EXT_STACK_LITERAL (CBC_EXT_SET_COMPUTED_PROPERTY_LITERAL); + VM_DECODE_EXT_STACK_STACK_2 (CBC_EXT_SET_COMPUTED_PROPERTY, CBC_EXT_SET_STATIC_COMPUTED_PROPERTY); - JERRY_ASSERT ((opcode_data >> VM_OC_NON_STATIC_SHIFT) <= 0x1); - - ecma_string_t *prop_name_p = ecma_op_to_property_key (right_value); - - if (JERRY_UNLIKELY (prop_name_p == NULL)) - { - result = ECMA_VALUE_ERROR; - goto error; - } + result = opfunc_set_data_property (stack_top_p, + left_value, + right_value, + opcode == VM_EXT_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_PROPERTY)); -#if JERRY_ESNEXT - if (JERRY_UNLIKELY (ecma_compare_ecma_string_to_magic_id (prop_name_p, LIT_MAGIC_STRING_PROTOTYPE)) - && !(opcode_data & VM_OC_NON_STATIC_FLAG)) + if (ECMA_IS_VALUE_ERROR (result)) { - result = ecma_raise_type_error (ECMA_ERR_CLASS_IS_NON_CONFIGURABLE); goto error; } - const int index = (int) (opcode_data >> VM_OC_NON_STATIC_SHIFT) - 2; -#else /* !JERRY_ESNEXT */ - const int index = -1; + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; + } #endif /* JERRY_ESNEXT */ + case VM_OPCODE_ONE_LITERAL (CBC_SET_PROPERTY): + case VM_OPCODE_TWO_LITERALS (CBC_SET_LITERAL_PROPERTY): + case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_SET_STATIC_PROPERTY): + case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_SET_STATIC_PROPERTY_LITERAL): + { + VM_DECODE_STACK_LITERAL_2 (CBC_SET_PROPERTY, VM_EXT_OPCODE (CBC_EXT_SET_STATIC_PROPERTY)); + VM_DECODE_LITERAL_LITERAL_2 (CBC_SET_LITERAL_PROPERTY, VM_EXT_OPCODE (CBC_EXT_SET_STATIC_PROPERTY_LITERAL)); - ecma_object_t *object_p = ecma_get_object_from_value (stack_top_p[index]); + result = + opfunc_set_data_property (stack_top_p, right_value, left_value, *byte_code_start_p == CBC_EXT_OPCODE); - opfunc_set_data_property (object_p, prop_name_p, left_value); - ecma_deref_ecma_string (prop_name_p); + if (ECMA_IS_VALUE_ERROR (result)) + { + goto error; + } - goto free_both_values; + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_SET_GETTER: - case VM_OC_SET_SETTER: + case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_SET_GETTER): + case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_SET_SETTER): + case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_SET_STATIC_GETTER): + case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_SET_STATIC_SETTER): { - JERRY_ASSERT ((opcode_data >> VM_OC_NON_STATIC_SHIFT) <= 0x1); + VM_DECODE_EXT_LITERAL_LITERAL_2 (CBC_EXT_SET_GETTER, CBC_EXT_SET_STATIC_GETTER); + VM_DECODE_EXT_LITERAL_LITERAL_2 (CBC_EXT_SET_SETTER, CBC_EXT_SET_STATIC_SETTER); + VM_DECODE_EXT_STACK_STACK_2 (CBC_EXT_SET_COMPUTED_GETTER, CBC_EXT_SET_STATIC_COMPUTED_GETTER); + VM_DECODE_EXT_STACK_STACK_2 (CBC_EXT_SET_COMPUTED_SETTER, CBC_EXT_SET_STATIC_COMPUTED_SETTER); + + JERRY_ASSERT (*byte_code_start_p == CBC_EXT_OPCODE); ecma_string_t *prop_name_p = ecma_op_to_property_key (left_value); @@ -1936,85 +2415,91 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ goto error; } + int index = -1; #if JERRY_ESNEXT - if (JERRY_UNLIKELY (ecma_compare_ecma_string_to_magic_id (prop_name_p, LIT_MAGIC_STRING_PROTOTYPE)) - && !(opcode_data & VM_OC_NON_STATIC_FLAG)) + bool is_static = (byte_code_start_p[1] - CBC_EXT_SET_GETTER) & 0x1; + + if (JERRY_UNLIKELY (is_static)) { - result = ecma_raise_type_error (ECMA_ERR_CLASS_IS_NON_CONFIGURABLE); - goto error; - } + if (JERRY_UNLIKELY (ecma_compare_ecma_string_to_magic_id (prop_name_p, LIT_MAGIC_STRING_PROTOTYPE))) + { + result = ecma_raise_type_error (ECMA_ERR_CLASS_IS_NON_CONFIGURABLE); + goto error; + } - const int index = (int) (opcode_data >> VM_OC_NON_STATIC_SHIFT) - 2; -#else /* !JERRY_ESNEXT */ - const int index = -1; + index--; + } #endif /* JERRY_ESNEXT */ - opfunc_set_accessor (VM_OC_GROUP_GET_INDEX (opcode_data) == VM_OC_SET_GETTER, - stack_top_p[index], - prop_name_p, - right_value); + opfunc_set_accessor (byte_code_start_p[1] < CBC_EXT_SET_SETTER, stack_top_p[index], prop_name_p, right_value); ecma_deref_ecma_string (prop_name_p); - goto free_both_values; + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_PUSH_ARRAY: + case CBC_CREATE_ARRAY: { - /* Note: this operation cannot throw an exception */ *stack_top_p++ = ecma_make_object_value (ecma_op_new_array_object (0)); continue; } #if JERRY_ESNEXT - case VM_OC_LOCAL_EVAL: + case VM_EXT_OPCODE (CBC_EXT_LOCAL_EVAL): { ECMA_CLEAR_LOCAL_PARSE_OPTS (); uint8_t parse_opts = *byte_code_p++; ECMA_SET_LOCAL_PARSE_OPTS (parse_opts); continue; } - case VM_OC_SUPER_CALL: + case VM_EXT_OPCODE_PUT_RESULT_CASE (CBC_EXT_SUPER_CALL): { uint8_t arguments_list_len = *byte_code_p++; - if (opcode >= CBC_EXT_SPREAD_SUPER_CALL) - { - stack_top_p -= arguments_list_len; - ecma_collection_t *arguments_p = opfunc_spread_arguments (stack_top_p, arguments_list_len); - - if (JERRY_UNLIKELY (arguments_p == NULL)) - { - result = ECMA_VALUE_ERROR; - goto error; - } + frame_ctx_p->call_operation = VM_EXEC_SUPER_CALL; + frame_ctx_p->byte_code_p = byte_code_start_p; + frame_ctx_p->stack_top_p = stack_top_p - arguments_list_len; + return ECMA_VALUE_UNDEFINED; + } + case VM_EXT_OPCODE_PUT_RESULT_CASE (CBC_EXT_SPREAD_SUPER_CALL): + { + uint8_t arguments_list_len = *byte_code_p++; + stack_top_p -= arguments_list_len; + ecma_collection_t *arguments_p = opfunc_spread_arguments (stack_top_p, arguments_list_len); - stack_top_p++; - ECMA_SET_INTERNAL_VALUE_POINTER (stack_top_p[-1], arguments_p); - } - else + if (JERRY_UNLIKELY (arguments_p == NULL)) { - stack_top_p -= arguments_list_len; + result = ECMA_VALUE_ERROR; + goto error; } + stack_top_p++; + ECMA_SET_INTERNAL_VALUE_POINTER (stack_top_p[-1], arguments_p); + frame_ctx_p->call_operation = VM_EXEC_SUPER_CALL; frame_ctx_p->byte_code_p = byte_code_start_p; frame_ctx_p->stack_top_p = stack_top_p; return ECMA_VALUE_UNDEFINED; } - case VM_OC_PUSH_CLASS_ENVIRONMENT: + case VM_EXT_OPCODE (CBC_EXT_PUSH_NAMED_CLASS_ENV): { uint16_t literal_index; - READ_LITERAL_INDEX (literal_index); + opfunc_push_class_environment (frame_ctx_p, &stack_top_p, literal_start_p[literal_index]); continue; } - case VM_OC_PUSH_IMPLICIT_CTOR: + case VM_EXT_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR): + case VM_EXT_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE): { - *stack_top_p++ = opfunc_create_implicit_class_constructor (opcode, frame_ctx_p->shared_p->bytecode_header_p); + bool is_herigate = opcode == VM_EXT_OPCODE (CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE); + *stack_top_p++ = opfunc_create_implicit_class_constructor (bytecode_header_p, is_herigate); continue; } - case VM_OC_DEFINE_FIELD: + case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_DEFINE_FIELD): { + VM_DECODE_EXT_STACK_LITERAL (CBC_EXT_DEFINE_FIELD); + result = opfunc_define_field (frame_ctx_p->this_binding, right_value, left_value); if (ECMA_IS_VALUE_ERROR (result)) @@ -2022,9 +2507,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ goto error; } - goto free_both_values; + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_ASSIGN_PRIVATE: + case VM_EXT_OPCODE_PUT_RESULT_CASE (CBC_EXT_ASSIGN_PRIVATE): { result = opfunc_private_set (stack_top_p[-3], stack_top_p[-2], stack_top_p[-1]); @@ -2038,11 +2525,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_free_value (stack_top_p[-1]); stack_top_p -= 3; - if (opcode_data & VM_OC_PUT_STACK) + if (opcode == VM_EXT_OPCODE (CBC_EXT_ASSIGN_PRIVATE_PUSH_RESULT)) { *stack_top_p++ = result; } - else if (opcode_data & VM_OC_PUT_BLOCK) + else if (opcode == VM_EXT_OPCODE (CBC_EXT_ASSIGN_PRIVATE_BLOCK)) { ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); VM_GET_REGISTERS (frame_ctx_p)[0] = result; @@ -2052,10 +2539,12 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_free_value (result); } - goto free_both_values; + continue; } - case VM_OC_PRIVATE_FIELD_ADD: + case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_PRIVATE_FIELD_ADD): { + VM_DECODE_EXT_STACK_LITERAL (CBC_EXT_PRIVATE_FIELD_ADD); + result = opfunc_private_field_add (frame_ctx_p->this_binding, right_value, left_value); if (ECMA_IS_VALUE_ERROR (result)) @@ -2063,10 +2552,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ goto error; } - goto free_both_values; + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_PRIVATE_PROP_GET: + case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL): { + VM_DECODE_EXT_STACK_LITERAL (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL); + result = opfunc_private_get (left_value, right_value); if (ECMA_IS_VALUE_ERROR (result)) @@ -2075,10 +2568,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_PRIVATE_PROP_REFERENCE: + case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_REFERENCE): { + VM_DECODE_EXT_LITERAL (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_REFERENCE); + result = opfunc_private_get (stack_top_p[-1], left_value); if (ECMA_IS_VALUE_ERROR (result)) @@ -2090,8 +2588,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ *stack_top_p++ = result; continue; } - case VM_OC_PRIVATE_IN: + case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_IN): { + VM_DECODE_EXT_STACK_LITERAL (CBC_EXT_PUSH_PRIVATE_PROP_LITERAL_IN); + result = opfunc_private_in (left_value, right_value); if (ECMA_IS_VALUE_ERROR (result)) @@ -2100,14 +2600,43 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; + } + case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_COLLECT_PRIVATE_FIELD): + case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_COLLECT_PRIVATE_STATIC_FIELD): + { + VM_DECODE_EXT_LITERAL_2 (CBC_EXT_COLLECT_PRIVATE_FIELD, CBC_EXT_COLLECT_PRIVATE_STATIC_FIELD); + + JERRY_ASSERT (*byte_code_start_p == CBC_EXT_OPCODE); + opfunc_collect_private_properties (stack_top_p[-2], left_value, ECMA_VALUE_UNDEFINED, byte_code_start_p[1]); + continue; + } + case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_COLLECT_PRIVATE_METHOD): + case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_COLLECT_PRIVATE_STATIC_METHOD): + { + VM_DECODE_EXT_LITERAL_LITERAL_2 (CBC_EXT_COLLECT_PRIVATE_METHOD, CBC_EXT_COLLECT_PRIVATE_STATIC_METHOD); + + JERRY_ASSERT (*byte_code_start_p == CBC_EXT_OPCODE); + opfunc_collect_private_properties (stack_top_p[-2], right_value, left_value, byte_code_start_p[1]); + continue; } - case VM_OC_COLLECT_PRIVATE_PROPERTY: + + case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_COLLECT_PRIVATE_GETTER): + case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_COLLECT_PRIVATE_SETTER): + case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_COLLECT_PRIVATE_STATIC_GETTER): + case VM_EXT_OPCODE_TWO_LITERALS (CBC_EXT_COLLECT_PRIVATE_STATIC_SETTER): { - opfunc_collect_private_properties (stack_top_p[-2], left_value, right_value, opcode); + VM_DECODE_EXT_LITERAL_LITERAL_2 (CBC_EXT_COLLECT_PRIVATE_GETTER, CBC_EXT_COLLECT_PRIVATE_STATIC_GETTER); + VM_DECODE_EXT_LITERAL_LITERAL_2 (CBC_EXT_COLLECT_PRIVATE_SETTER, CBC_EXT_COLLECT_PRIVATE_STATIC_SETTER); + + JERRY_ASSERT (*byte_code_start_p == CBC_EXT_OPCODE); + opfunc_collect_private_properties (stack_top_p[-2], left_value, right_value, byte_code_start_p[1]); continue; } - case VM_OC_INIT_CLASS: + case VM_EXT_OPCODE (CBC_EXT_INIT_CLASS): { result = opfunc_init_class (frame_ctx_p, stack_top_p); @@ -2117,22 +2646,23 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } continue; } - case VM_OC_FINALIZE_CLASS: + case VM_EXT_OPCODE (CBC_EXT_FINALIZE_NAMED_CLASS): { - JERRY_ASSERT (opcode == CBC_EXT_FINALIZE_NAMED_CLASS || opcode == CBC_EXT_FINALIZE_ANONYMOUS_CLASS); - - if (opcode == CBC_EXT_FINALIZE_NAMED_CLASS) - { - uint16_t literal_index; - READ_LITERAL_INDEX (literal_index); - left_value = literal_start_p[literal_index]; - } + uint16_t literal_index; + READ_LITERAL_INDEX (literal_index); - opfunc_finalize_class (frame_ctx_p, &stack_top_p, left_value); + opfunc_finalize_class (frame_ctx_p, &stack_top_p, literal_start_p[literal_index]); + continue; + } + case VM_EXT_OPCODE (CBC_EXT_FINALIZE_ANONYMOUS_CLASS): + { + opfunc_finalize_class (frame_ctx_p, &stack_top_p, ECMA_VALUE_UNDEFINED); continue; } - case VM_OC_SET_FIELD_INIT: + case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_SET_FIELD_INIT): { + VM_DECODE_EXT_LITERAL (CBC_EXT_SET_FIELD_INIT); + ecma_string_t *property_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_INIT); ecma_object_t *proto_object_p = ecma_get_object_from_value (stack_top_p[-1]); ecma_object_t *class_object_p = ecma_get_object_from_value (stack_top_p[-2]); @@ -2143,6 +2673,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_property_value_t *property_value_p = ecma_create_named_data_property (class_object_p, property_name_p, ECMA_PROPERTY_FIXED, NULL); property_value_p->value = left_value; + ecma_deref_object (initializer_func_p); property_name_p = ecma_get_internal_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED); ecma_property_t *property_p = ecma_find_named_property (class_object_p, property_name_p); @@ -2155,10 +2686,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ compact_collection_p = ecma_compact_collection_shrink (compact_collection_p); ECMA_SET_INTERNAL_VALUE_POINTER (property_value_p->value, compact_collection_p); } - - goto free_left_value; + continue; } - case VM_OC_RUN_FIELD_INIT: + case VM_EXT_OPCODE (CBC_EXT_RUN_FIELD_INIT): { JERRY_ASSERT (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_NON_ARROW_FUNC); result = opfunc_init_class_fields (frame_ctx_p->shared_p->function_object_p, frame_ctx_p->this_binding); @@ -2169,7 +2699,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } continue; } - case VM_OC_RUN_STATIC_FIELD_INIT: + case VM_EXT_OPCODE (CBC_EXT_RUN_STATIC_FIELD_INIT): { left_value = stack_top_p[-2]; stack_top_p[-2] = stack_top_p[-1]; @@ -2181,9 +2711,12 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { goto error; } - goto free_left_value; + + ecma_fast_free_value (left_value); + continue; } - case VM_OC_SET_NEXT_COMPUTED_FIELD: + case VM_EXT_OPCODE (CBC_EXT_SET_NEXT_COMPUTED_FIELD_ANONYMOUS_FUNC): + case VM_EXT_OPCODE (CBC_EXT_SET_NEXT_COMPUTED_FIELD): { ecma_integer_value_t next_index = ecma_get_integer_from_value (stack_top_p[-2]) + 1; stack_top_p[-2] = ecma_make_integer_value (next_index); @@ -2194,7 +2727,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ JERRY_ASSERT ((ecma_value_t) next_index < ECMA_COMPACT_COLLECTION_GET_SIZE (computed_class_fields_p)); ecma_value_t prop_name = computed_class_fields_p[next_index]; - if (opcode == CBC_EXT_SET_NEXT_COMPUTED_FIELD_ANONYMOUS_FUNC) + if (opcode == VM_EXT_OPCODE (CBC_EXT_SET_NEXT_COMPUTED_FIELD_ANONYMOUS_FUNC)) { ecma_object_t *func_obj_p = ecma_get_object_from_value (stack_top_p[-1]); @@ -2223,7 +2756,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_free_value (*(--stack_top_p)); continue; } - case VM_OC_PUSH_SUPER_CONSTRUCTOR: + case VM_EXT_OPCODE (CBC_EXT_PUSH_SUPER_CONSTRUCTOR): { result = ecma_op_function_get_super_constructor (vm_get_class_function (frame_ctx_p)); @@ -2235,7 +2768,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ *stack_top_p++ = result; continue; } - case VM_OC_RESOLVE_LEXICAL_THIS: + case VM_EXT_OPCODE (CBC_EXT_RESOLVE_LEXICAL_THIS): { result = ecma_op_get_this_binding (frame_ctx_p->lex_env_p); @@ -2247,118 +2780,160 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ *stack_top_p++ = result; continue; } - case VM_OC_OBJECT_LITERAL_HOME_ENV: + case VM_EXT_OPCODE (CBC_EXT_PUSH_OBJECT_SUPER_ENVIRONMENT): { - if (opcode == CBC_EXT_PUSH_OBJECT_SUPER_ENVIRONMENT) - { - ecma_value_t obj_value = stack_top_p[-1]; - ecma_object_t *obj_env_p = ecma_create_lex_env_class (frame_ctx_p->lex_env_p, 0); + ecma_value_t obj_value = stack_top_p[-1]; + ecma_object_t *obj_env_p = ecma_create_lex_env_class (frame_ctx_p->lex_env_p, 0); - ECMA_SET_NON_NULL_POINTER (obj_env_p->u1.bound_object_cp, ecma_get_object_from_value (obj_value)); - stack_top_p[-1] = ecma_make_object_value (obj_env_p); - *stack_top_p++ = obj_value; - } - else - { - JERRY_ASSERT (opcode == CBC_EXT_POP_OBJECT_SUPER_ENVIRONMENT); - ecma_deref_object (ecma_get_object_from_value (stack_top_p[-2])); - stack_top_p[-2] = stack_top_p[-1]; - stack_top_p--; - } + ECMA_SET_NON_NULL_POINTER (obj_env_p->u1.bound_object_cp, ecma_get_object_from_value (obj_value)); + stack_top_p[-1] = ecma_make_object_value (obj_env_p); + *stack_top_p++ = obj_value; continue; } - case VM_OC_SET_HOME_OBJECT: + case VM_EXT_OPCODE (CBC_EXT_POP_OBJECT_SUPER_ENVIRONMENT): { - int offset = opcode == CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED ? -1 : 0; + ecma_deref_object (ecma_get_object_from_value (stack_top_p[-2])); + stack_top_p[-2] = stack_top_p[-1]; + stack_top_p--; + continue; + } + case VM_EXT_OPCODE (CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT): + case VM_EXT_OPCODE (CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT_COMPUTED): + { + const int index = opcode - VM_EXT_OPCODE (CBC_EXT_OBJECT_LITERAL_SET_HOME_OBJECT); opfunc_set_home_object (ecma_get_object_from_value (stack_top_p[-1]), - ecma_get_object_from_value (stack_top_p[-3 + offset])); + ecma_get_object_from_value (stack_top_p[-3 - index])); continue; } - case VM_OC_SUPER_REFERENCE: + case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE): { - result = opfunc_form_super_reference (&stack_top_p, frame_ctx_p, left_value, opcode); + VM_DECODE_EXT_STACK (CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE) + VM_DECODE_EXT_LITERAL (CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE); + + result = opfunc_resolve_super (frame_ctx_p); if (ECMA_IS_VALUE_ERROR (result)) { goto error; } - goto free_left_value; + *stack_top_p++ = result; + *stack_top_p++ = left_value; + continue; } - case VM_OC_SET_FUNCTION_NAME: + case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_SUPER_PROP_LITERAL_REFERENCE): + case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_PUSH_SUPER_PROP_LITERAL): { - char *prefix_p = NULL; - lit_utf8_size_t prefix_size = 0; + VM_DECODE_EXT_STACK_2 (CBC_EXT_PUSH_SUPER_PROP, CBC_EXT_SUPER_PROP_REFERENCE) + VM_DECODE_EXT_LITERAL_2 (CBC_EXT_PUSH_SUPER_PROP_LITERAL, CBC_EXT_SUPER_PROP_LITERAL_REFERENCE); - if (opcode != CBC_EXT_SET_FUNCTION_NAME) + JERRY_ASSERT (*byte_code_start_p == CBC_EXT_OPCODE); + result = opfunc_resolve_super (frame_ctx_p); + + if (ECMA_IS_VALUE_ERROR (result)) { - ecma_value_t prop_name_value; + goto error; + } - if (opcode == CBC_EXT_SET_CLASS_NAME) - { - uint16_t literal_index; - READ_LITERAL_INDEX (literal_index); - prop_name_value = literal_start_p[literal_index]; - } - else - { - prop_name_value = stack_top_p[-2]; - } + right_value = result; + ecma_object_t *parent_p = ecma_get_object_from_value (right_value); + ecma_string_t *prop_name_p = ecma_op_to_property_key (left_value); - ecma_string_t *prop_name_p = ecma_op_to_property_key (prop_name_value); + if (prop_name_p == NULL) + { + result = ECMA_VALUE_ERROR; + goto error; + } - if (JERRY_UNLIKELY (prop_name_p == NULL)) - { - result = ECMA_VALUE_ERROR; - goto error; - } + result = ecma_op_object_get_with_receiver (parent_p, prop_name_p, frame_ctx_p->this_binding); + ecma_deref_ecma_string (prop_name_p); - left_value = ecma_make_prop_name_value (prop_name_p); + if (ECMA_IS_VALUE_ERROR (result)) + { + return result; + } - if (opcode != CBC_EXT_SET_CLASS_NAME) - { - ecma_ref_ecma_string (prop_name_p); - ecma_free_value (stack_top_p[-2]); - stack_top_p[-2] = left_value; - } + if (byte_code_start_p[1] >= CBC_EXT_SUPER_PROP_REFERENCE) + { + *stack_top_p++ = ecma_copy_value (frame_ctx_p->this_binding); + *stack_top_p++ = ECMA_VALUE_UNDEFINED; + } - if (opcode == CBC_EXT_SET_COMPUTED_GETTER_NAME || opcode == CBC_EXT_SET_COMPUTED_SETTER_NAME) - { - prefix_p = (opcode == CBC_EXT_SET_COMPUTED_GETTER_NAME) ? "get " : "set "; - prefix_size = 4; - } + *stack_top_p++ = result; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; + } + case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_SET_FUNCTION_NAME): + { + VM_DECODE_EXT_LITERAL (CBC_EXT_SET_FUNCTION_NAME); + + opfunc_set_function_name (stack_top_p[-1], left_value, NULL, 0); + + ecma_fast_free_value (left_value); + continue; + } + case VM_EXT_OPCODE (CBC_EXT_SET_CLASS_NAME): + case VM_EXT_OPCODE (CBC_EXT_SET_COMPUTED_FUNCTION_NAME): + case VM_EXT_OPCODE (CBC_EXT_SET_COMPUTED_GETTER_NAME): + case VM_EXT_OPCODE (CBC_EXT_SET_COMPUTED_SETTER_NAME): + { + char *prefix_p = NULL; + lit_utf8_size_t prefix_size = 0; + + ecma_value_t prop_name_value; + + if (opcode == VM_EXT_OPCODE (CBC_EXT_SET_CLASS_NAME)) + { + uint16_t literal_index; + READ_LITERAL_INDEX (literal_index); + prop_name_value = literal_start_p[literal_index]; + } + else + { + prop_name_value = stack_top_p[-2]; } - ecma_object_t *func_obj_p = ecma_get_object_from_value (stack_top_p[-1]); + ecma_string_t *prop_name_p = ecma_op_to_property_key (prop_name_value); - if (ecma_find_named_property (func_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_NAME)) != NULL) + if (JERRY_UNLIKELY (prop_name_p == NULL)) { - ecma_free_value (left_value); - continue; + result = ECMA_VALUE_ERROR; + goto error; } - ecma_property_value_t *value_p; - value_p = ecma_create_named_data_property (func_obj_p, - ecma_get_magic_string (LIT_MAGIC_STRING_NAME), - ECMA_PROPERTY_FLAG_CONFIGURABLE, - NULL); + left_value = ecma_make_prop_name_value (prop_name_p); - if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION) + if (opcode != VM_EXT_OPCODE (CBC_EXT_SET_CLASS_NAME)) { - ECMA_SET_SECOND_BIT_TO_POINTER_TAG (((ecma_extended_object_t *) func_obj_p)->u.function.scope_cp); + ecma_ref_ecma_string (prop_name_p); + ecma_free_value (stack_top_p[-2]); + stack_top_p[-2] = left_value; } - value_p->value = - ecma_op_function_form_name (ecma_get_prop_name_from_value (left_value), prefix_p, prefix_size); - ecma_free_value (left_value); + if (opcode == VM_EXT_OPCODE (CBC_EXT_SET_COMPUTED_GETTER_NAME)) + { + prefix_p = "get "; + prefix_size = 4; + } + else if (opcode == VM_EXT_OPCODE (CBC_EXT_SET_COMPUTED_SETTER_NAME)) + { + prefix_p = "set "; + prefix_size = 4; + } + + opfunc_set_function_name (stack_top_p[-1], left_value, prefix_p, prefix_size); + + ecma_fast_free_value (left_value); continue; } - case VM_OC_PUSH_SPREAD_ELEMENT: + case VM_EXT_OPCODE (CBC_EXT_PUSH_SPREAD_ELEMENT): { *stack_top_p++ = ECMA_VALUE_SPREAD_ELEMENT; continue; } - case VM_OC_PUSH_REST_OBJECT: + case VM_EXT_OPCODE (CBC_EXT_PUSH_REST_OBJECT): { vm_frame_ctx_shared_t *shared_p = frame_ctx_p->shared_p; @@ -2388,7 +2963,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ *stack_top_p++ = result; continue; } - case VM_OC_ITERATOR_CONTEXT_CREATE: + case VM_EXT_OPCODE (CBC_EXT_ITERATOR_CONTEXT_CREATE): { result = ecma_op_get_iterator (stack_top_p[-1], ECMA_VALUE_SYNC_ITERATOR, &left_value); @@ -2408,7 +2983,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ continue; } - case VM_OC_ITERATOR_STEP: + case VM_EXT_OPCODE (CBC_EXT_ITERATOR_STEP): { ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END (); @@ -2445,7 +3020,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ *stack_top_p++ = value; continue; } - case VM_OC_ITERATOR_CONTEXT_END: + case VM_EXT_OPCODE (CBC_EXT_ITERATOR_CONTEXT_END): { JERRY_ASSERT (VM_LAST_CONTEXT_END () == stack_top_p); @@ -2464,8 +3039,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ vm_stack_context_abort_variable_length (frame_ctx_p, stack_top_p, PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION); continue; } - case VM_OC_DEFAULT_INITIALIZER: + case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_DEFAULT_INITIALIZER): { + VM_DECODE_EXT_FORWARD_BRANCH (CBC_EXT_DEFAULT_INITIALIZER); + JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); if (stack_top_p[-1] != ECMA_VALUE_UNDEFINED) @@ -2477,7 +3054,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ stack_top_p--; continue; } - case VM_OC_REST_INITIALIZER: + case VM_EXT_OPCODE (CBC_EXT_REST_INITIALIZER): { ecma_object_t *array_p = ecma_op_new_array_object (0); JERRY_ASSERT (ecma_op_object_is_fast_array (array_p)); @@ -2522,13 +3099,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ *stack_top_p++ = ecma_make_object_value (array_p); continue; } - case VM_OC_OBJ_INIT_CONTEXT_CREATE: + case VM_EXT_OPCODE (CBC_EXT_OBJ_INIT_CONTEXT_CREATE): + case VM_EXT_OPCODE (CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE): { left_value = stack_top_p[-1]; vm_stack_context_type_t context_type = VM_CONTEXT_OBJ_INIT; uint32_t context_stack_allocation = PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION; - if (opcode == CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE) + if (opcode == VM_EXT_OPCODE (CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE)) { context_type = VM_CONTEXT_OBJ_INIT_REST; context_stack_allocation = PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION; @@ -2547,7 +3125,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } continue; } - case VM_OC_OBJ_INIT_CONTEXT_END: + case VM_EXT_OPCODE (CBC_EXT_OBJ_INIT_CONTEXT_END): { JERRY_ASSERT (stack_top_p == VM_LAST_CONTEXT_END ()); @@ -2561,7 +3139,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ stack_top_p = vm_stack_context_abort_variable_length (frame_ctx_p, stack_top_p, context_stack_allocation); continue; } - case VM_OC_OBJ_INIT_PUSH_REST: + case VM_EXT_OPCODE (CBC_EXT_OBJ_INIT_PUSH_REST): { ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END (); if (!ecma_op_require_object_coercible (last_context_end_p[-2])) @@ -2588,8 +3166,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ *stack_top_p++ = left_value; continue; } - case VM_OC_INITIALIZER_PUSH_NAME: + case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_INITIALIZER_PUSH_NAME_LITERAL): { + VM_DECODE_EXT_STACK (CBC_EXT_INITIALIZER_PUSH_NAME); + VM_DECODE_EXT_LITERAL (CBC_EXT_INITIALIZER_PUSH_NAME_LITERAL); + if (JERRY_UNLIKELY (!ecma_is_value_prop_name (left_value))) { ecma_string_t *property_key = ecma_op_to_property_key (left_value); @@ -2610,14 +3191,19 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_obj_p; ecma_fast_array_set_property (array_obj_p, ext_array_obj_p->u.array.length, left_value); + + result = left_value; /* FALLTHRU */ } - case VM_OC_INITIALIZER_PUSH_PROP: + case VM_EXT_OPCODE_ONE_LITERAL (CBC_EXT_INITIALIZER_PUSH_PROP_LITERAL): + case VM_EXT_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP): { + VM_DECODE_EXT_LITERAL (CBC_EXT_INITIALIZER_PUSH_PROP_LITERAL); + ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END (); ecma_value_t base = last_context_end_p[-2]; - if (opcode == CBC_EXT_INITIALIZER_PUSH_PROP) + if (opcode == VM_EXT_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP)) { left_value = *last_context_end_p++; while (last_context_end_p < stack_top_p) @@ -2636,9 +3222,13 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_left_value; + + ecma_fast_free_value (left_value); + continue; } - case VM_OC_SPREAD_ARGUMENTS: + case VM_EXT_OPCODE (CBC_EXT_SPREAD_NEW): + case VM_EXT_OPCODE_PUT_RESULT_CASE (CBC_EXT_SPREAD_CALL): + case VM_EXT_OPCODE_PUT_RESULT_CASE (CBC_EXT_SPREAD_CALL_PROP): { uint8_t arguments_list_len = *byte_code_p++; stack_top_p -= arguments_list_len; @@ -2659,7 +3249,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ frame_ctx_p->stack_top_p = stack_top_p; return ECMA_VALUE_UNDEFINED; } - case VM_OC_CREATE_GENERATOR: + case VM_EXT_OPCODE (CBC_EXT_CREATE_GENERATOR): { frame_ctx_p->call_operation = VM_EXEC_RETURN; frame_ctx_p->byte_code_p = byte_code_p; @@ -2670,14 +3260,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ return ecma_make_object_value ((ecma_object_t *) executable_object_p); } - case VM_OC_YIELD: + case VM_EXT_OPCODE (CBC_EXT_YIELD): + case VM_EXT_OPCODE (CBC_EXT_YIELD_ITERATOR): { frame_ctx_p->call_operation = VM_EXEC_RETURN; frame_ctx_p->byte_code_p = byte_code_p; frame_ctx_p->stack_top_p = --stack_top_p; return *stack_top_p; } - case VM_OC_ASYNC_YIELD: + case VM_EXT_OPCODE (CBC_EXT_ASYNC_YIELD): { ecma_extended_object_t *async_generator_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p); @@ -2688,7 +3279,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ frame_ctx_p->stack_top_p = --stack_top_p; return ECMA_VALUE_UNDEFINED; } - case VM_OC_ASYNC_YIELD_ITERATOR: + case VM_EXT_OPCODE (CBC_EXT_ASYNC_YIELD_ITERATOR): { ecma_extended_object_t *async_generator_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p); @@ -2728,7 +3319,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ frame_ctx_p->stack_top_p = stack_top_p; return ECMA_VALUE_UNDEFINED; } - case VM_OC_AWAIT: + case VM_EXT_OPCODE (CBC_EXT_AWAIT): { if (JERRY_UNLIKELY (!(frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_EXECUTABLE))) { @@ -2746,7 +3337,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } /* FALLTHRU */ } - case VM_OC_GENERATOR_AWAIT: + case VM_EXT_OPCODE (CBC_EXT_GENERATOR_AWAIT): { ecma_extended_object_t *async_generator_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p); @@ -2762,8 +3353,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ frame_ctx_p->stack_top_p = stack_top_p; return ECMA_VALUE_UNDEFINED; } - case VM_OC_EXT_RETURN: + case VM_EXT_OPCODE (CBC_EXT_RETURN_UNDEFINED): { + VM_DECODE_EXT_STACK (CBC_EXT_RETURN); result = left_value; left_value = ECMA_VALUE_UNDEFINED; @@ -2776,7 +3368,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ goto error; } - case VM_OC_ASYNC_EXIT: + case VM_EXT_OPCODE (CBC_EXT_ASYNC_EXIT): { JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); @@ -2819,8 +3411,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ frame_ctx_p->call_operation = VM_NO_EXEC_OP; return result; } - case VM_OC_STRING_CONCAT: + case VM_EXT_OPCODE_ARITHMETIC_CASE (CBC_EXT_STRING_CONCAT): { + VM_DECODE_EXT_ARITHMETIC (CBC_EXT_STRING_CONCAT); + ecma_string_t *left_str_p = ecma_op_to_string (left_value); if (JERRY_UNLIKELY (left_str_p == NULL)) @@ -2841,9 +3435,12 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_deref_ecma_string (right_str_p); *stack_top_p++ = ecma_make_string_value (result_str_p); - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_GET_TEMPLATE_OBJECT: + case VM_EXT_OPCODE (CBC_EXT_GET_TAGGED_TEMPLATE_LITERAL): { uint8_t tagged_idx = *byte_code_p++; ecma_collection_t *collection_p = ecma_compiled_code_get_tagged_template_collection (bytecode_header_p); @@ -2852,7 +3449,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ *stack_top_p++ = ecma_copy_value (collection_p->buffer_p[tagged_idx]); continue; } - case VM_OC_PUSH_NEW_TARGET: + case VM_EXT_OPCODE (CBC_EXT_PUSH_NEW_TARGET): { ecma_object_t *new_target_object_p = JERRY_CONTEXT (current_new_target_p); if (new_target_object_p == NULL) @@ -2866,7 +3463,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } continue; } - case VM_OC_REQUIRE_OBJECT_COERCIBLE: + case VM_EXT_OPCODE (CBC_EXT_REQUIRE_OBJECT_COERCIBLE): { if (!ecma_op_require_object_coercible (stack_top_p[-1])) { @@ -2875,46 +3472,91 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } continue; } - case VM_OC_ASSIGN_SUPER: + case VM_EXT_OPCODE_PUT_RESULT_CASE (CBC_EXT_ASSIGN_SUPER): { - result = opfunc_assign_super_reference (&stack_top_p, frame_ctx_p, opcode_data); + JERRY_ASSERT (*byte_code_start_p == CBC_EXT_OPCODE); + + ecma_value_t base_obj = ecma_op_to_object (stack_top_p[-3]); + + if (ECMA_IS_VALUE_ERROR (base_obj)) + { + return base_obj; + } + + ecma_object_t *base_obj_p = ecma_get_object_from_value (base_obj); + ecma_string_t *prop_name_p = ecma_op_to_property_key (stack_top_p[-2]); + + if (prop_name_p == NULL) + { + ecma_deref_object (base_obj_p); + result = ECMA_VALUE_ERROR; + goto error; + } + + result = ecma_op_object_put_with_receiver (base_obj_p, + prop_name_p, + stack_top_p[-1], + frame_ctx_p->this_binding, + is_strict); + + ecma_deref_ecma_string (prop_name_p); + ecma_deref_object (base_obj_p); if (ECMA_IS_VALUE_ERROR (result)) { goto error; } + + for (int32_t i = 1; i <= 3; i++) + { + ecma_free_value (stack_top_p[-i]); + } + + stack_top_p -= 3; + + if (opcode == VM_EXT_OPCODE (CBC_EXT_ASSIGN_SUPER_PUSH_RESULT)) + { + *stack_top_p++ = result; + } + else if (opcode == VM_EXT_OPCODE (CBC_EXT_ASSIGN_SUPER_BLOCK)) + { + ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); + VM_GET_REGISTERS (frame_ctx_p)[0] = result; + } + else + { + ecma_free_value (result); + } continue; } -#endif /* JERRY_ESNEXT */ - case VM_OC_PUSH_ELISON: - { - *stack_top_p++ = ECMA_VALUE_ARRAY_HOLE; - continue; - } - case VM_OC_APPEND_ARRAY: + case VM_EXT_OPCODE (CBC_EXT_SPREAD_ARRAY_APPEND): { uint16_t values_length = *byte_code_p++; stack_top_p -= values_length; -#if JERRY_ESNEXT - if (*byte_code_start_p == CBC_EXT_OPCODE) - { - values_length = (uint16_t) (values_length | OPFUNC_HAS_SPREAD_ELEMENT); - } -#endif /* JERRY_ESNEXT */ - result = opfunc_append_array (stack_top_p, values_length); + result = opfunc_append_to_spread_array (stack_top_p, values_length); -#if JERRY_ESNEXT if (ECMA_IS_VALUE_ERROR (result)) { goto error; } -#else /* !JERRY_ESNEXT */ - JERRY_ASSERT (ecma_is_value_empty (result)); + continue; + } #endif /* JERRY_ESNEXT */ + case CBC_PUSH_ELISION: + { + *stack_top_p++ = ECMA_VALUE_ARRAY_HOLE; + continue; + } + case CBC_ARRAY_APPEND: + { + uint16_t values_length = *byte_code_p++; + stack_top_p -= values_length; + + opfunc_append_array (stack_top_p, values_length); continue; } - case VM_OC_IDENT_REFERENCE: + case CBC_PUSH_IDENT_REFERENCE: { uint16_t literal_index; @@ -2949,8 +3591,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } continue; } - case VM_OC_PROP_GET: + case VM_OPCODE_ONE_LITERAL (CBC_PUSH_PROP_LITERAL): + case VM_OPCODE_ONE_LITERAL (CBC_PUSH_PROP_THIS_LITERAL): + case VM_OPCODE_TWO_LITERALS (CBC_PUSH_PROP_LITERAL_LITERAL): { + VM_DECODE_STACK_LITERAL (CBC_PUSH_PROP_LITERAL); + VM_DECODE_LITERAL_LITERAL (CBC_PUSH_PROP_LITERAL_LITERAL); + VM_DECODE_THIS_LITERAL (CBC_PUSH_PROP_THIS_LITERAL); + VM_DECODE_STACK_STACK (CBC_PUSH_PROP); + result = vm_op_get_value (left_value, right_value); if (ECMA_IS_VALUE_ERROR (result)) @@ -2959,79 +3608,78 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_PROP_REFERENCE: + case VM_OPCODE_ONE_LITERAL (CBC_PUSH_PROP_LITERAL_REFERENCE): { - /* Forms with reference requires preserving the base and offset. */ + VM_DECODE_LITERAL (CBC_PUSH_PROP_LITERAL_REFERENCE) + *stack_top_p++ = left_value; + goto vm_push_prop_reference; + } + case VM_OPCODE_TWO_LITERALS (CBC_PUSH_PROP_LITERAL_LITERAL_REFERENCE): + case VM_OPCODE_ONE_LITERAL (CBC_PUSH_PROP_THIS_LITERAL_REFERENCE): + { + VM_DECODE_LITERAL_LITERAL (CBC_PUSH_PROP_LITERAL_LITERAL_REFERENCE); + VM_DECODE_THIS_LITERAL (CBC_PUSH_PROP_THIS_LITERAL_REFERENCE); - if (opcode == CBC_PUSH_PROP_REFERENCE) - { - left_value = stack_top_p[-2]; - right_value = stack_top_p[-1]; - } - else if (opcode == CBC_PUSH_PROP_LITERAL_REFERENCE) - { - *stack_top_p++ = left_value; - right_value = left_value; - left_value = stack_top_p[-2]; - } - else - { - JERRY_ASSERT (opcode == CBC_PUSH_PROP_LITERAL_LITERAL_REFERENCE - || opcode == CBC_PUSH_PROP_THIS_LITERAL_REFERENCE); - *stack_top_p++ = left_value; - *stack_top_p++ = right_value; - } + *stack_top_p++ = left_value; + *stack_top_p++ = right_value; /* FALLTHRU */ } - case VM_OC_PROP_PRE_INCR: - case VM_OC_PROP_PRE_DECR: - case VM_OC_PROP_POST_INCR: - case VM_OC_PROP_POST_DECR: + case CBC_PUSH_PROP_REFERENCE: { - result = vm_op_get_value (left_value, right_value); +vm_push_prop_reference: + result = vm_op_get_value (stack_top_p[-2], stack_top_p[-1]); - if (opcode < CBC_PRE_INCR) + if (ECMA_IS_VALUE_ERROR (result)) { left_value = ECMA_VALUE_UNDEFINED; right_value = ECMA_VALUE_UNDEFINED; - } - - if (ECMA_IS_VALUE_ERROR (result)) - { goto error; } - if (opcode < CBC_PRE_INCR) + *stack_top_p++ = result; + continue; + } + case VM_OPCODE_PUT_RESULT_CASE (CBC_PRE_INCR): + case VM_OPCODE_PUT_RESULT_CASE (CBC_PRE_DECR): + case VM_OPCODE_PUT_RESULT_CASE (CBC_POST_INCR): + case VM_OPCODE_PUT_RESULT_CASE (CBC_POST_DECR): + { + left_value = vm_op_get_value (stack_top_p[-2], stack_top_p[-1]); + + if (ECMA_IS_VALUE_ERROR (left_value)) { - break; + result = left_value; + left_value = ECMA_VALUE_UNDEFINED; + goto error; } - - stack_top_p += 2; - left_value = result; - right_value = ECMA_VALUE_UNDEFINED; /* FALLTHRU */ } - case VM_OC_PRE_INCR: - case VM_OC_PRE_DECR: - case VM_OC_POST_INCR: - case VM_OC_POST_DECR: + case VM_OPCODE_ONE_LITERAL_PUT_RESULT_CASE (CBC_PRE_INCR_IDENT): + case VM_OPCODE_ONE_LITERAL_PUT_RESULT_CASE (CBC_PRE_DECR_IDENT): + case VM_OPCODE_ONE_LITERAL_PUT_RESULT_CASE (CBC_POST_INCR_IDENT): + case VM_OPCODE_ONE_LITERAL_PUT_RESULT_CASE (CBC_POST_DECR_IDENT): { - uint32_t opcode_flags = VM_OC_GROUP_GET_INDEX (opcode_data) - VM_OC_PROP_PRE_INCR; + VM_DECODE_LITERAL_PUT_RESULT (CBC_PRE_INCR_IDENT); + VM_DECODE_LITERAL_PUT_RESULT (CBC_PRE_DECR_IDENT); + VM_DECODE_LITERAL_PUT_RESULT (CBC_POST_INCR_IDENT); + VM_DECODE_LITERAL_PUT_RESULT (CBC_POST_DECR_IDENT); + + put_result_flags = vm_incr_decr_flags[*byte_code_start_p - CBC_PRE_INCR]; ecma_number_t result_number; byte_code_p = byte_code_start_p + 1; if (ecma_is_value_integer_number (left_value)) { - result = left_value; - left_value = ECMA_VALUE_UNDEFINED; - - ecma_integer_value_t int_value = (ecma_integer_value_t) result; + ecma_integer_value_t int_value = (ecma_integer_value_t) left_value; ecma_integer_value_t int_increase = 0; - if (opcode_flags & VM_OC_DECREMENT_OPERATOR_FLAG) + if (put_result_flags & VM_PUT_RESULT_DECR) { if (int_value > ECMA_INTEGER_NUMBER_MIN_SHIFTED) { @@ -3045,22 +3693,21 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ if (JERRY_LIKELY (int_increase != 0)) { + result = (ecma_value_t) (int_value + int_increase); + /* Postfix operators require the unmodifed number value. */ - if (opcode_flags & VM_OC_POST_INCR_DECR_OPERATOR_FLAG) + if (put_result_flags & VM_PUT_RESULT_POST) { - POST_INCREASE_DECREASE_PUT_RESULT (result); + goto post_incr_decr; } - result = (ecma_value_t) (int_value + int_increase); break; } - result_number = (ecma_number_t) ecma_get_integer_from_value (result); + result_number = (ecma_number_t) ecma_get_integer_from_value (left_value); } else if (ecma_is_value_float_number (left_value)) { - result = left_value; - left_value = ECMA_VALUE_UNDEFINED; - result_number = ecma_get_number_from_value (result); + result_number = ecma_get_number_from_value (left_value); } else { @@ -3072,105 +3719,146 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } ecma_free_value (left_value); - left_value = ECMA_VALUE_UNDEFINED; #if JERRY_BUILTIN_BIGINT if (JERRY_UNLIKELY (ecma_is_value_bigint (result))) { + left_value = result; ecma_bigint_unary_operation_type operation_type = ECMA_BIGINT_UNARY_INCREASE; - if (opcode_flags & VM_OC_DECREMENT_OPERATOR_FLAG) + if (put_result_flags & VM_PUT_RESULT_DECR) { operation_type = ECMA_BIGINT_UNARY_DECREASE; } - /* Postfix operators require the unmodifed number value. */ - if (opcode_flags & VM_OC_POST_INCR_DECR_OPERATOR_FLAG) - { - POST_INCREASE_DECREASE_PUT_RESULT (result); + result = ecma_bigint_unary (left_value, operation_type); - result = ecma_bigint_unary (result, operation_type); - } - else + if (ECMA_IS_VALUE_ERROR (result)) { - ecma_value_t original_value = result; - result = ecma_bigint_unary (original_value, operation_type); - ecma_free_value (original_value); + goto error; } - if (ECMA_IS_VALUE_ERROR (result)) + /* Postfix operators require the unmodifed number value. */ + if (put_result_flags & VM_PUT_RESULT_POST) { - goto error; + goto post_incr_decr; } + + ecma_free_value (left_value); break; } #endif /* JERRY_BUILTIN_BIGINT */ - result = ecma_make_number_value (result_number); + left_value = ecma_make_number_value (result_number); } ecma_number_t increase = ECMA_NUMBER_ONE; - if (opcode_flags & VM_OC_DECREMENT_OPERATOR_FLAG) + if (put_result_flags & VM_PUT_RESULT_DECR) { /* For decrement operators */ increase = ECMA_NUMBER_MINUS_ONE; } /* Postfix operators require the unmodifed number value. */ - if (opcode_flags & VM_OC_POST_INCR_DECR_OPERATOR_FLAG) + if (put_result_flags & VM_PUT_RESULT_POST) { - POST_INCREASE_DECREASE_PUT_RESULT (result); - result = ecma_make_number_value (result_number + increase); - break; + goto post_incr_decr; } - if (ecma_is_value_integer_number (result)) + if (ecma_is_value_integer_number (left_value)) { result = ecma_make_number_value (result_number + increase); } else { - result = ecma_update_float_number (result, result_number + increase); + result = ecma_update_float_number (left_value, result_number + increase); + } + break; + +post_incr_decr: + /* left_value holds the old value, result contains the new value */ + if (put_result_flags & VM_PUT_RESULT_STACK) + { + if (put_result_flags & VM_PUT_RESULT_IDENT) + { + JERRY_ASSERT (opcode == VM_OPCODE_ONE_LITERAL (CBC_POST_INCR_IDENT_PUSH_RESULT) + || opcode == VM_OPCODE_ONE_LITERAL (CBC_POST_DECR_IDENT_PUSH_RESULT)); + *stack_top_p++ = left_value; + } + else + { /* The parser ensures there is enough space for the extra value on the stack. See js-parser-expr.c. */ + JERRY_ASSERT (opcode == CBC_POST_INCR_PUSH_RESULT || opcode == CBC_POST_DECR_PUSH_RESULT); + stack_top_p++; + stack_top_p[-1] = stack_top_p[-2]; + stack_top_p[-2] = stack_top_p[-3]; + stack_top_p[-3] = left_value; + } + put_result_flags &= (uint8_t) ~VM_PUT_RESULT_STACK; + } + else + { + JERRY_ASSERT (put_result_flags & VM_PUT_RESULT_BLOCK); + ecma_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); + VM_GET_REGISTERS (frame_ctx_p)[0] = left_value; + put_result_flags &= (uint8_t) ~VM_PUT_RESULT_BLOCK; } + break; } - case VM_OC_ASSIGN: + case VM_OPCODE_PUT_RESULT_CASE (CBC_ASSIGN): + { + VM_POP_STACK (result); + put_result_flags = (uint8_t) (opcode - CBC_ASSIGN); + goto dispatch_put_reference; + } + case VM_OPCODE_PUT_RESULT_CASE (CBC_ASSIGN_SET_IDENT): { + VM_POP_STACK (result); + put_result_flags = (uint8_t) (opcode - CBC_ASSIGN_SET_IDENT); + goto dispatch_put_ident; + } + case VM_OPCODE_ONE_LITERAL_PUT_RESULT_CASE (CBC_ASSIGN_LITERAL_SET_IDENT): + { + VM_DECODE_LITERAL_PUT_RESULT (CBC_ASSIGN_LITERAL_SET_IDENT); + result = left_value; - left_value = ECMA_VALUE_UNDEFINED; - break; + put_result_flags = (uint8_t) (opcode - CBC_ASSIGN_LITERAL_SET_IDENT); + goto dispatch_put_ident; } - case VM_OC_MOV_IDENT: + case CBC_MOV_IDENT: { - uint32_t literal_index; + VM_POP_STACK (left_value); + uint32_t literal_index; READ_LITERAL_INDEX (literal_index); - JERRY_ASSERT (literal_index < register_end); - JERRY_ASSERT (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))); ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); VM_GET_REGISTER (frame_ctx_p, literal_index) = left_value; continue; } - case VM_OC_ASSIGN_PROP: + case VM_OPCODE_ONE_LITERAL_PUT_RESULT_CASE (CBC_ASSIGN_PROP_LITERAL): { + VM_DECODE_LITERAL_PUT_RESULT (CBC_ASSIGN_PROP_LITERAL); + result = stack_top_p[-1]; stack_top_p[-1] = left_value; - left_value = ECMA_VALUE_UNDEFINED; - break; + put_result_flags = (uint8_t) (opcode - CBC_ASSIGN_PROP_LITERAL); + goto dispatch_put_reference; } - case VM_OC_ASSIGN_PROP_THIS: + case VM_OPCODE_ONE_LITERAL_PUT_RESULT_CASE (CBC_ASSIGN_PROP_THIS_LITERAL): { + VM_DECODE_LITERAL_PUT_RESULT (CBC_ASSIGN_PROP_THIS_LITERAL); + result = stack_top_p[-1]; stack_top_p[-1] = ecma_copy_value (frame_ctx_p->this_binding); *stack_top_p++ = left_value; - left_value = ECMA_VALUE_UNDEFINED; - break; + put_result_flags = (uint8_t) (opcode - CBC_ASSIGN_PROP_THIS_LITERAL); + goto dispatch_put_reference; } - case VM_OC_RETURN_FUNCTION_END: + case CBC_RETURN_FUNCTION_END: { if (CBC_FUNCTION_GET_TYPE (bytecode_header_p->status_flags) == CBC_FUNCTION_SCRIPT) { @@ -3184,28 +3872,32 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ goto error; } - case VM_OC_RETURN: + case CBC_RETURN: { - JERRY_ASSERT (opcode == CBC_RETURN || opcode == CBC_RETURN_WITH_LITERAL); - + VM_POP_STACK (result); + goto error; + } + case VM_OPCODE_ONE_LITERAL (CBC_RETURN_WITH_LITERAL): + { + VM_DECODE_LITERAL (CBC_RETURN_WITH_LITERAL); result = left_value; left_value = ECMA_VALUE_UNDEFINED; goto error; } - case VM_OC_THROW: + case CBC_THROW: { - jcontext_raise_exception (left_value); + VM_POP_STACK (result); + jcontext_raise_exception (result); result = ECMA_VALUE_ERROR; - left_value = ECMA_VALUE_UNDEFINED; goto error; } - case VM_OC_THROW_REFERENCE_ERROR: + case VM_EXT_OPCODE (CBC_EXT_THROW_REFERENCE_ERROR): { result = ecma_raise_reference_error (ECMA_ERR_UNDEFINED_REFERENCE); goto error; } - case VM_OC_EVAL: + case CBC_EVAL: { JERRY_CONTEXT (status_flags) |= ECMA_STATUS_DIRECT_EVAL; JERRY_ASSERT ((*byte_code_p >= CBC_CALL && *byte_code_p <= CBC_CALL2_PROP_BLOCK) @@ -3213,21 +3905,30 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ && byte_code_p[1] <= CBC_EXT_SPREAD_CALL_PROP_BLOCK)); continue; } - case VM_OC_CALL: + case VM_OPCODE_PUT_RESULT_CASE (CBC_CALL): + case VM_OPCODE_PUT_RESULT_CASE (CBC_CALL_PROP): + case VM_OPCODE_PUT_RESULT_CASE (CBC_CALL0): + case VM_OPCODE_PUT_RESULT_CASE (CBC_CALL0_PROP): + case VM_OPCODE_PUT_RESULT_CASE (CBC_CALL1): + case VM_OPCODE_PUT_RESULT_CASE (CBC_CALL1_PROP): + case VM_OPCODE_PUT_RESULT_CASE (CBC_CALL2): + case VM_OPCODE_PUT_RESULT_CASE (CBC_CALL2_PROP): { frame_ctx_p->call_operation = VM_EXEC_CALL; frame_ctx_p->byte_code_p = byte_code_start_p; frame_ctx_p->stack_top_p = stack_top_p; return ECMA_VALUE_UNDEFINED; } - case VM_OC_NEW: + case CBC_NEW: + case CBC_NEW0: + case CBC_NEW1: { frame_ctx_p->call_operation = VM_EXEC_CONSTRUCT; frame_ctx_p->byte_code_p = byte_code_start_p; frame_ctx_p->stack_top_p = stack_top_p; return ECMA_VALUE_UNDEFINED; } - case VM_OC_ERROR: + case VM_EXT_OPCODE (CBC_EXT_ERROR): { JERRY_ASSERT (frame_ctx_p->byte_code_p[1] == CBC_EXT_ERROR); #if JERRY_DEBUGGER @@ -3237,7 +3938,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ result = ECMA_VALUE_ERROR; goto error; } - case VM_OC_RESOLVE_BASE_FOR_CALL: + case VM_EXT_OPCODE (CBC_EXT_RESOLVE_BASE): { ecma_value_t this_value = stack_top_p[-3]; @@ -3255,8 +3956,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ continue; } - case VM_OC_PROP_DELETE: + case CBC_DELETE_PUSH_RESULT: { + VM_POP_STACK_STACK (right_value, left_value); + result = vm_op_delete_prop (left_value, right_value, is_strict); if (ECMA_IS_VALUE_ERROR (result)) @@ -3267,12 +3970,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ JERRY_ASSERT (ecma_is_value_boolean (result)); *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_DELETE: + case CBC_DELETE_IDENT_PUSH_RESULT: { uint16_t literal_index; - READ_LITERAL_INDEX (literal_index); if (literal_index < register_end) @@ -3293,13 +3998,18 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ *stack_top_p++ = result; continue; } - case VM_OC_JUMP: + case VM_OPCODE_BRANCH_CASE (CBC_JUMP_FORWARD): + case VM_OPCODE_BRANCH_CASE (CBC_JUMP_BACKWARD): { + VM_DECODE_FORWARD_BRANCH (CBC_JUMP_FORWARD); + VM_DECODE_BACKWARD_BRANCH (CBC_JUMP_BACKWARD); byte_code_p = byte_code_start_p + branch_offset; continue; } - case VM_OC_BRANCH_IF_STRICT_EQUAL: + case VM_OPCODE_BRANCH_CASE (CBC_BRANCH_IF_STRICT_EQUAL): { + VM_DECODE_FORWARD_BRANCH (CBC_BRANCH_IF_STRICT_EQUAL); + ecma_value_t value = *(--stack_top_p); JERRY_ASSERT (stack_top_p > VM_GET_REGISTERS (frame_ctx_p) + register_end); @@ -3312,37 +4022,68 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_free_value (value); continue; } - case VM_OC_BRANCH_IF_TRUE: - case VM_OC_BRANCH_IF_FALSE: - case VM_OC_BRANCH_IF_LOGICAL_TRUE: - case VM_OC_BRANCH_IF_LOGICAL_FALSE: + case VM_OPCODE_BRANCH_CASE (CBC_BRANCH_IF_TRUE_FORWARD): + case VM_OPCODE_BRANCH_CASE (CBC_BRANCH_IF_TRUE_BACKWARD): { - uint32_t opcode_flags = VM_OC_GROUP_GET_INDEX (opcode_data) - VM_OC_BRANCH_IF_TRUE; - ecma_value_t value = *(--stack_top_p); + VM_DECODE_FORWARD_BRANCH (CBC_BRANCH_IF_TRUE_FORWARD); + VM_DECODE_BACKWARD_BRANCH (CBC_BRANCH_IF_TRUE_BACKWARD); - bool boolean_value = ecma_op_to_boolean (value); + ecma_value_t value = *(--stack_top_p); - if (opcode_flags & VM_OC_BRANCH_IF_FALSE_FLAG) + if (ecma_op_to_boolean (value)) { - boolean_value = !boolean_value; + byte_code_p = byte_code_start_p + branch_offset; } - if (boolean_value) + ecma_fast_free_value (value); + continue; + } + case VM_OPCODE_BRANCH_CASE (CBC_BRANCH_IF_FALSE_FORWARD): + case VM_OPCODE_BRANCH_CASE (CBC_BRANCH_IF_FALSE_BACKWARD): + { + VM_DECODE_FORWARD_BRANCH (CBC_BRANCH_IF_FALSE_FORWARD); + VM_DECODE_BACKWARD_BRANCH (CBC_BRANCH_IF_FALSE_BACKWARD); + + ecma_value_t value = *(--stack_top_p); + + if (!ecma_op_to_boolean (value)) { byte_code_p = byte_code_start_p + branch_offset; - if (opcode_flags & VM_OC_LOGICAL_BRANCH_FLAG) - { - /* "Push" the value back to the stack. */ - ++stack_top_p; - continue; - } } ecma_fast_free_value (value); continue; } + case VM_OPCODE_BRANCH_CASE (CBC_BRANCH_IF_LOGICAL_TRUE): + { + VM_DECODE_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_TRUE); + + if (ecma_op_to_boolean (stack_top_p[-1])) + { + byte_code_p = byte_code_start_p + branch_offset; + } + else + { + ecma_fast_free_value (*(--stack_top_p)); + } + continue; + } + case VM_OPCODE_BRANCH_CASE (CBC_BRANCH_IF_LOGICAL_FALSE): + { + VM_DECODE_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_FALSE); + + if (ecma_op_to_boolean (stack_top_p[-1])) + { + ecma_fast_free_value (*(--stack_top_p)); + } + else + { + byte_code_p = byte_code_start_p + branch_offset; + } + continue; + } #if JERRY_ESNEXT - case VM_OC_POP_REFERENCE: + case VM_EXT_OPCODE (CBC_EXT_POP_REFERENCE): { ecma_free_value (stack_top_p[-2]); ecma_free_value (stack_top_p[-3]); @@ -3350,8 +4091,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ stack_top_p -= 2; continue; } - case VM_OC_BRANCH_IF_NULLISH: + case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_BRANCH_IF_NULLISH): { + VM_DECODE_EXT_FORWARD_BRANCH (CBC_EXT_BRANCH_IF_NULLISH); + left_value = stack_top_p[-1]; if (!ecma_is_value_null (left_value) && !ecma_is_value_undefined (left_value)) @@ -3363,10 +4106,13 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ continue; } #endif /* JERRY_ESNEXT */ - case VM_OC_PLUS: - case VM_OC_MINUS: + case VM_OPCODE_ONE_LITERAL (CBC_PLUS_LITERAL): + case VM_OPCODE_ONE_LITERAL (CBC_NEGATE_LITERAL): { - result = opfunc_unary_operation (left_value, VM_OC_GROUP_GET_INDEX (opcode_data) == VM_OC_PLUS); + VM_DECODE_LITERAL_2 (CBC_PLUS_LITERAL, CBC_NEGATE_LITERAL) + VM_DECODE_STACK_2 (CBC_PLUS, CBC_NEGATE); + + result = opfunc_unary_operation (left_value, *byte_code_start_p < CBC_NEGATE); if (ECMA_IS_VALUE_ERROR (result)) { @@ -3374,23 +4120,35 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_left_value; + + ecma_fast_free_value (left_value); + continue; } - case VM_OC_NOT: + case VM_OPCODE_ONE_LITERAL (CBC_LOGICAL_NOT_LITERAL): { + VM_DECODE_LITERAL (CBC_LOGICAL_NOT_LITERAL); + VM_DECODE_STACK (CBC_LOGICAL_NOT); + *stack_top_p++ = ecma_make_boolean_value (!ecma_op_to_boolean (left_value)); JERRY_ASSERT (ecma_is_value_boolean (stack_top_p[-1])); - goto free_left_value; + + ecma_fast_free_value (left_value); + continue; } - case VM_OC_BIT_NOT: + case VM_OPCODE_ONE_LITERAL (CBC_BIT_NOT_LITERAL): { + VM_DECODE_LITERAL (CBC_BIT_NOT_LITERAL); + VM_DECODE_STACK (CBC_BIT_NOT); + JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1), direct_type_mask_must_fill_all_bits_before_the_value_starts); if (ecma_is_value_integer_number (left_value)) { *stack_top_p++ = (~ECMA_DIRECT_TYPE_MASK) ^ left_value; - goto free_left_value; + + ecma_fast_free_value (left_value); + continue; } result = do_number_bitwise_not (left_value); @@ -3401,17 +4159,23 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_left_value; + + ecma_fast_free_value (left_value); + continue; } - case VM_OC_VOID: + case VM_OPCODE_ONE_LITERAL (CBC_VOID_LITERAL): { + VM_DECODE_LITERAL (CBC_VOID_LITERAL); + VM_DECODE_STACK (CBC_VOID); + *stack_top_p++ = ECMA_VALUE_UNDEFINED; - goto free_left_value; + + ecma_fast_free_value (left_value); + continue; } - case VM_OC_TYPEOF_IDENT: + case CBC_TYPEOF_IDENT: { uint16_t literal_index; - READ_LITERAL_INDEX (literal_index); JERRY_ASSERT (literal_index < ident_end); @@ -3440,10 +4204,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ left_value = result; } - /* FALLTHRU */ - } - case VM_OC_TYPEOF: - { + + VM_DECODE_STACK (CBC_TYPEOF); + result = opfunc_typeof (left_value); if (ECMA_IS_VALUE_ERROR (result)) @@ -3452,10 +4215,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_left_value; + + ecma_fast_free_value (left_value); + continue; } - case VM_OC_ADD: + case VM_OPCODE_ARITHMETIC_CASE (CBC_ADD): { + VM_DECODE_ARITHMETIC (CBC_ADD); + if (ecma_are_values_integer_numbers (left_value, right_value)) { ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value); @@ -3491,15 +4258,18 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_SUB: + case VM_OPCODE_ARITHMETIC_CASE (CBC_SUBTRACT): { + VM_DECODE_ARITHMETIC (CBC_SUBTRACT); + JERRY_STATIC_ASSERT (ECMA_INTEGER_NUMBER_MAX * 2 <= INT32_MAX && ECMA_INTEGER_NUMBER_MIN * 2 >= INT32_MIN, doubled_ecma_numbers_must_fit_into_int32_range); - JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); - if (ecma_are_values_integer_numbers (left_value, right_value)) { ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value); @@ -3535,11 +4305,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_MUL: + case VM_OPCODE_ARITHMETIC_CASE (CBC_MULTIPLY): { - JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); + VM_DECODE_ARITHMETIC (CBC_MULTIPLY); JERRY_STATIC_ASSERT (ECMA_INTEGER_MULTIPLY_MAX * ECMA_INTEGER_MULTIPLY_MAX <= ECMA_INTEGER_NUMBER_MAX && -(ECMA_INTEGER_MULTIPLY_MAX * ECMA_INTEGER_MULTIPLY_MAX) >= ECMA_INTEGER_NUMBER_MIN, @@ -3590,11 +4363,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_DIV: + case VM_OPCODE_ARITHMETIC_CASE (CBC_DIVIDE): { - JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); + VM_DECODE_ARITHMETIC (CBC_DIVIDE); result = do_number_arithmetic (NUMBER_ARITHMETIC_DIVISION, left_value, right_value); @@ -3604,11 +4380,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_MOD: + case VM_OPCODE_ARITHMETIC_CASE (CBC_MODULO): { - JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); + VM_DECODE_ARITHMETIC (CBC_MODULO); if (ecma_are_values_integer_numbers (left_value, right_value)) { @@ -3635,11 +4414,16 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } #if JERRY_ESNEXT - case VM_OC_EXP: + case VM_OPCODE_ARITHMETIC_CASE (CBC_EXPONENTIATION): { + VM_DECODE_ARITHMETIC (CBC_EXPONENTIATION); + result = do_number_arithmetic (NUMBER_ARITHMETIC_EXPONENTIATION, left_value, right_value); if (ECMA_IS_VALUE_ERROR (result)) @@ -3648,11 +4432,16 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } #endif /* JERRY_ESNEXT */ - case VM_OC_EQUAL: + case VM_OPCODE_ARITHMETIC_CASE (CBC_EQUAL): { + VM_DECODE_ARITHMETIC (CBC_EQUAL); + result = opfunc_equality (left_value, right_value); if (ECMA_IS_VALUE_ERROR (result)) @@ -3661,10 +4450,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_NOT_EQUAL: + case VM_OPCODE_ARITHMETIC_CASE (CBC_NOT_EQUAL): { + VM_DECODE_ARITHMETIC (CBC_NOT_EQUAL); + result = opfunc_equality (left_value, right_value); if (ECMA_IS_VALUE_ERROR (result)) @@ -3673,28 +4467,37 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = ecma_invert_boolean_value (result); - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_STRICT_EQUAL: + case VM_OPCODE_ARITHMETIC_CASE (CBC_STRICT_EQUAL): { - bool is_equal = ecma_op_strict_equality_compare (left_value, right_value); + VM_DECODE_ARITHMETIC (CBC_STRICT_EQUAL); - result = ecma_make_boolean_value (is_equal); + bool is_equal = ecma_op_strict_equality_compare (left_value, right_value); + *stack_top_p++ = ecma_make_boolean_value (is_equal); - *stack_top_p++ = result; - goto free_both_values; + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_STRICT_NOT_EQUAL: + case VM_OPCODE_ARITHMETIC_CASE (CBC_STRICT_NOT_EQUAL): { - bool is_equal = ecma_op_strict_equality_compare (left_value, right_value); + VM_DECODE_ARITHMETIC (CBC_STRICT_NOT_EQUAL); - result = ecma_make_boolean_value (!is_equal); + bool is_equal = ecma_op_strict_equality_compare (left_value, right_value); + *stack_top_p++ = ecma_make_boolean_value (!is_equal); - *stack_top_p++ = result; - goto free_both_values; + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_BIT_OR: + case VM_OPCODE_ARITHMETIC_CASE (CBC_BIT_OR): { + VM_DECODE_ARITHMETIC (CBC_BIT_OR); + JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1), direct_type_mask_must_fill_all_bits_before_the_value_starts); @@ -3712,10 +4515,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_BIT_XOR: + case VM_OPCODE_ARITHMETIC_CASE (CBC_BIT_XOR): { + VM_DECODE_ARITHMETIC (CBC_BIT_XOR); + JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1), direct_type_mask_must_fill_all_bits_before_the_value_starts); @@ -3733,10 +4541,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_BIT_AND: + case VM_OPCODE_ARITHMETIC_CASE (CBC_BIT_AND): { + VM_DECODE_ARITHMETIC (CBC_BIT_AND); + JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1), direct_type_mask_must_fill_all_bits_before_the_value_starts); @@ -3754,10 +4567,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_LEFT_SHIFT: + case VM_OPCODE_ARITHMETIC_CASE (CBC_LEFT_SHIFT): { + VM_DECODE_ARITHMETIC (CBC_LEFT_SHIFT); + JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1), direct_type_mask_must_fill_all_bits_before_the_value_starts); @@ -3778,10 +4596,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_RIGHT_SHIFT: + case VM_OPCODE_ARITHMETIC_CASE (CBC_RIGHT_SHIFT): { + VM_DECODE_ARITHMETIC (CBC_RIGHT_SHIFT); + JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1), direct_type_mask_must_fill_all_bits_before_the_value_starts); @@ -3801,10 +4624,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_UNS_RIGHT_SHIFT: + case VM_OPCODE_ARITHMETIC_CASE (CBC_UNS_RIGHT_SHIFT): { + VM_DECODE_ARITHMETIC (CBC_UNS_RIGHT_SHIFT); + JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_MASK == ((1 << ECMA_DIRECT_SHIFT) - 1), direct_type_mask_must_fill_all_bits_before_the_value_starts); @@ -3824,10 +4652,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_LESS: + case VM_OPCODE_ARITHMETIC_CASE (CBC_LESS): { + VM_DECODE_ARITHMETIC (CBC_LESS); + if (ecma_are_values_integer_numbers (left_value, right_value)) { bool is_less = (ecma_integer_value_t) left_value < (ecma_integer_value_t) right_value; @@ -3837,7 +4670,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ if (*byte_code_p <= CBC_BRANCH_IF_TRUE_BACKWARD_3 && *byte_code_p >= CBC_BRANCH_IF_TRUE_BACKWARD) { byte_code_start_p = byte_code_p++; - branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (*byte_code_start_p); + uint8_t branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (*byte_code_start_p); JERRY_ASSERT (branch_offset_length >= 1 && branch_offset_length <= 3); if (is_less) @@ -3876,7 +4709,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_number_t right_number = ecma_get_number_from_value (right_value); *stack_top_p++ = ecma_make_boolean_value (left_number < right_number); - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } result = opfunc_relation (left_value, right_value, true, false); @@ -3887,10 +4723,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_GREATER: + case VM_OPCODE_ARITHMETIC_CASE (CBC_GREATER): { + VM_DECODE_ARITHMETIC (CBC_GREATER); + if (ecma_are_values_integer_numbers (left_value, right_value)) { ecma_integer_value_t left_integer = (ecma_integer_value_t) left_value; @@ -3906,7 +4747,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_number_t right_number = ecma_get_number_from_value (right_value); *stack_top_p++ = ecma_make_boolean_value (left_number > right_number); - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } result = opfunc_relation (left_value, right_value, false, false); @@ -3917,10 +4761,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_LESS_EQUAL: + case VM_OPCODE_ARITHMETIC_CASE (CBC_LESS_EQUAL): { + VM_DECODE_ARITHMETIC (CBC_LESS_EQUAL); + if (ecma_are_values_integer_numbers (left_value, right_value)) { ecma_integer_value_t left_integer = (ecma_integer_value_t) left_value; @@ -3936,7 +4785,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_number_t right_number = ecma_get_number_from_value (right_value); *stack_top_p++ = ecma_make_boolean_value (left_number <= right_number); - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } result = opfunc_relation (left_value, right_value, false, true); @@ -3947,10 +4799,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_GREATER_EQUAL: + case VM_OPCODE_ARITHMETIC_CASE (CBC_GREATER_EQUAL): { + VM_DECODE_ARITHMETIC (CBC_GREATER_EQUAL); + if (ecma_are_values_integer_numbers (left_value, right_value)) { ecma_integer_value_t left_integer = (ecma_integer_value_t) left_value; @@ -3966,7 +4823,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_number_t right_number = ecma_get_number_from_value (right_value); *stack_top_p++ = ecma_make_boolean_value (left_number >= right_number); - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } result = opfunc_relation (left_value, right_value, true, true); @@ -3977,10 +4837,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_IN: + case VM_OPCODE_ARITHMETIC_CASE (CBC_IN): { + VM_DECODE_ARITHMETIC (CBC_IN); + result = opfunc_in (left_value, right_value); if (ECMA_IS_VALUE_ERROR (result)) @@ -3989,10 +4854,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_INSTANCEOF: + case VM_OPCODE_ARITHMETIC_CASE (CBC_INSTANCEOF): { + VM_DECODE_ARITHMETIC (CBC_INSTANCEOF); + result = opfunc_instanceof (left_value, right_value); if (ECMA_IS_VALUE_ERROR (result)) @@ -4001,17 +4871,23 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } *stack_top_p++ = result; - goto free_both_values; + + ecma_fast_free_value (right_value); + ecma_fast_free_value (left_value); + continue; } - case VM_OC_BLOCK_CREATE_CONTEXT: + case VM_OPCODE_BRANCH_CASE (CBC_BLOCK_CREATE_CONTEXT): + case VM_EXT_OPCODE (CBC_EXT_TRY_CREATE_ENV): { + VM_DECODE_FORWARD_BRANCH (CBC_BLOCK_CREATE_CONTEXT); + #if JERRY_ESNEXT ecma_value_t *stack_context_top_p; stack_context_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth; JERRY_ASSERT (stack_context_top_p == stack_top_p || stack_context_top_p == stack_top_p - 1); - if (byte_code_start_p[0] != CBC_EXT_OPCODE) + if (opcode != VM_EXT_OPCODE (CBC_EXT_TRY_CREATE_ENV)) { branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); @@ -4028,8 +4904,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } else { - JERRY_ASSERT (byte_code_start_p[1] == CBC_EXT_TRY_CREATE_ENV); - JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_TRY || VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_CATCH || VM_GET_CONTEXT_TYPE (stack_context_top_p[-1]) == VM_CONTEXT_FINALLY_JUMP @@ -4052,8 +4926,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ continue; } - case VM_OC_WITH: + case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_WITH_CREATE_CONTEXT): { + VM_DECODE_EXT_FORWARD_BRANCH (CBC_EXT_WITH_CREATE_CONTEXT); + ecma_value_t value = *(--stack_top_p); ecma_object_t *object_p; ecma_object_t *with_env_p; @@ -4084,8 +4960,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ frame_ctx_p->lex_env_p = with_env_p; continue; } - case VM_OC_FOR_IN_INIT: + case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_FOR_IN_INIT): { + VM_DECODE_EXT_FORWARD_BRANCH (CBC_EXT_FOR_IN_INIT); + ecma_value_t value = *(--stack_top_p); JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); @@ -4127,7 +5005,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ #endif /* JERRY_ESNEXT */ continue; } - case VM_OC_FOR_IN_GET_NEXT: + case VM_EXT_OPCODE (CBC_EXT_FOR_IN_GET_NEXT): { ecma_value_t *context_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth; @@ -4143,8 +5021,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ context_top_p[-3]++; continue; } - case VM_OC_FOR_IN_HAS_NEXT: + case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_BRANCH_IF_FOR_IN_HAS_NEXT): { + VM_DECODE_EXT_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_IN_HAS_NEXT); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); ecma_collection_t *collection_p; @@ -4192,8 +5072,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ continue; } #if JERRY_ESNEXT - case VM_OC_FOR_OF_INIT: + case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_FOR_OF_INIT): { + VM_DECODE_EXT_FORWARD_BRANCH (CBC_EXT_FOR_OF_INIT); + ecma_value_t value = *(--stack_top_p); JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); @@ -4253,7 +5135,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } continue; } - case VM_OC_FOR_OF_GET_NEXT: + case VM_EXT_OPCODE (CBC_EXT_FOR_OF_GET_NEXT): { ecma_value_t *context_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth; JERRY_ASSERT (VM_GET_CONTEXT_TYPE (context_top_p[-1]) == VM_CONTEXT_FOR_OF @@ -4264,8 +5146,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ context_top_p[-2] = ECMA_VALUE_UNDEFINED; continue; } - case VM_OC_FOR_OF_HAS_NEXT: + case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_BRANCH_IF_FOR_OF_HAS_NEXT): { + VM_DECODE_EXT_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_OF_HAS_NEXT); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FOR_OF); JERRY_ASSERT (stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR); @@ -4303,8 +5187,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ byte_code_p = byte_code_start_p + branch_offset; continue; } - case VM_OC_FOR_AWAIT_OF_INIT: + case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_FOR_AWAIT_OF_INIT): { + VM_DECODE_EXT_FORWARD_BRANCH (CBC_EXT_FOR_AWAIT_OF_INIT); + ecma_value_t value = *(--stack_top_p); JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); @@ -4374,8 +5260,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } return result; } - case VM_OC_FOR_AWAIT_OF_HAS_NEXT: + case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_BRANCH_IF_FOR_AWAIT_OF_HAS_NEXT): { + VM_DECODE_EXT_BACKWARD_BRANCH (CBC_EXT_BRANCH_IF_FOR_AWAIT_OF_HAS_NEXT); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_FOR_AWAIT_OF); JERRY_ASSERT (stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR); @@ -4406,8 +5294,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ return ECMA_VALUE_UNDEFINED; } #endif /* JERRY_ESNEXT */ - case VM_OC_TRY: + case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_TRY_CREATE_CONTEXT): { + VM_DECODE_EXT_FORWARD_BRANCH (CBC_EXT_TRY_CREATE_CONTEXT); + /* Try opcode simply creates the try context. */ branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); @@ -4419,8 +5309,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_TRY, branch_offset); continue; } - case VM_OC_CATCH: + case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_CATCH): { + VM_DECODE_EXT_FORWARD_BRANCH (CBC_EXT_CATCH); + /* Catches are ignored and turned to jumps. */ JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); JERRY_ASSERT (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_TRY); @@ -4428,8 +5320,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ byte_code_p = byte_code_start_p + branch_offset; continue; } - case VM_OC_FINALLY: + case VM_EXT_OPCODE_BRANCH_CASE (CBC_EXT_FINALLY): { + VM_DECODE_EXT_FORWARD_BRANCH (CBC_EXT_FINALLY); + branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); @@ -4452,7 +5346,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ stack_top_p[-2] = (ecma_value_t) branch_offset; continue; } - case VM_OC_CONTEXT_END: + case CBC_CONTEXT_END: { JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); JERRY_ASSERT (!(stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR)); @@ -4541,8 +5435,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); continue; } - case VM_OC_JUMP_AND_EXIT_CONTEXT: + case VM_OPCODE_BRANCH_CASE (CBC_JUMP_FORWARD_EXIT_CONTEXT): { + VM_DECODE_FORWARD_BRANCH (CBC_JUMP_FORWARD_EXIT_CONTEXT); + JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); JERRY_ASSERT (!jcontext_has_pending_exception ()); @@ -4586,7 +5482,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ continue; } #if JERRY_MODULE_SYSTEM - case VM_OC_MODULE_IMPORT: + case VM_EXT_OPCODE (CBC_EXT_MODULE_IMPORT): { left_value = *(--stack_top_p); @@ -4618,7 +5514,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ *stack_top_p++ = result; continue; } - case VM_OC_MODULE_IMPORT_META: + case VM_EXT_OPCODE (CBC_EXT_MODULE_IMPORT_META): { ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_header_p)->script_value; cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); @@ -4654,7 +5550,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } #endif /* JERRY_MODULE_SYSTEM */ #if JERRY_DEBUGGER - case VM_OC_BREAKPOINT_ENABLED: + case CBC_BREAKPOINT_ENABLED: { if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_VM_IGNORE) { @@ -4675,7 +5571,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } continue; } - case VM_OC_BREAKPOINT_DISABLED: + case CBC_BREAKPOINT_DISABLED: { if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_VM_IGNORE) { @@ -4728,21 +5624,19 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ continue; } #endif /* JERRY_DEBUGGER */ - case VM_OC_NONE: default: { - JERRY_ASSERT (VM_OC_GROUP_GET_INDEX (opcode_data) == VM_OC_NONE); - - jerry_fatal (ERR_DISABLED_BYTE_CODE); + JERRY_UNREACHABLE (); } } - JERRY_ASSERT (VM_OC_HAS_PUT_RESULT (opcode_data)); + JERRY_ASSERT (put_result_flags != VM_PUT_RESULT_NONE); - if (opcode_data & VM_OC_PUT_IDENT) + if (put_result_flags & VM_PUT_RESULT_IDENT) { uint16_t literal_index; +dispatch_put_ident: READ_LITERAL_INDEX (literal_index); if (literal_index < register_end) @@ -4750,10 +5644,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index)); VM_GET_REGISTER (frame_ctx_p, literal_index) = result; - if (opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)) + if (!(put_result_flags & (VM_PUT_RESULT_STACK | VM_PUT_RESULT_BLOCK))) { - result = ecma_fast_copy_value (result); + continue; } + result = ecma_fast_copy_value (result); } else { @@ -4766,19 +5661,23 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { ecma_free_value (result); result = put_value_result; + left_value = ECMA_VALUE_UNDEFINED; goto error; } - if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) + if (!(put_result_flags & (VM_PUT_RESULT_STACK | VM_PUT_RESULT_BLOCK))) { ecma_fast_free_value (result); + continue; } } } - else if (opcode_data & VM_OC_PUT_REFERENCE) + else if (put_result_flags & VM_PUT_RESULT_REFERENCE) { - ecma_value_t property = *(--stack_top_p); - ecma_value_t base = *(--stack_top_p); + ecma_value_t property, base; +dispatch_put_reference: + property = *(--stack_top_p); + base = *(--stack_top_p); if (base == ECMA_VALUE_REGISTER_REF) { @@ -4786,9 +5685,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, property)); VM_GET_REGISTER (frame_ctx_p, property) = result; - if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) + if (!(put_result_flags & (VM_PUT_RESULT_STACK | VM_PUT_RESULT_BLOCK))) { - goto free_both_values; + continue; } result = ecma_fast_copy_value (result); } @@ -4800,31 +5699,33 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { ecma_free_value (result); result = set_value_result; + left_value = ECMA_VALUE_UNDEFINED; goto error; } - if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))) + if (!(put_result_flags & (VM_PUT_RESULT_STACK | VM_PUT_RESULT_BLOCK))) { ecma_fast_free_value (result); - goto free_both_values; + continue; } } } + else if (!(put_result_flags & (VM_PUT_RESULT_STACK | VM_PUT_RESULT_BLOCK))) + { + ecma_fast_free_value (result); + continue; + } - if (opcode_data & VM_OC_PUT_STACK) + if (put_result_flags & VM_PUT_RESULT_STACK) { *stack_top_p++ = result; } - else if (opcode_data & VM_OC_PUT_BLOCK) + else { + JERRY_ASSERT (put_result_flags & VM_PUT_RESULT_BLOCK); ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, 0)); VM_GET_REGISTERS (frame_ctx_p)[0] = result; } - -free_both_values: - ecma_fast_free_value (right_value); -free_left_value: - ecma_fast_free_value (left_value); } error: diff --git a/jerry-core/vm/vm.h b/jerry-core/vm/vm.h index 3cb1bdb931..f0df0253fa 100644 --- a/jerry-core/vm/vm.h +++ b/jerry-core/vm/vm.h @@ -29,459 +29,21 @@ * @{ */ -/** - * Each CBC opcode is transformed to three vm opcodes: - * - * - first opcode is a "get arguments" opcode which specifies - * the type (register, literal, stack, etc.) and number - * (from 0 to 2) of input arguments - * - second opcode is a "group" opcode which specifies - * the actual operation (add, increment, call, etc.) - * - third opcode is a "put result" opcode which specifies - * the destination where the result is stored (register, - * stack, etc.) - */ - -/** - * If VM_OC_GET_ARGS_INDEX(opcode) == VM_OC_GET_BRANCH, - * this flag signals that the branch is a backward branch. - */ -#define VM_OC_BACKWARD_BRANCH (1 << 15) - -/** - * Position of "get arguments" opcode. - */ -#define VM_OC_GET_ARGS_SHIFT 8 - -/** - * Mask of "get arguments" opcode. - */ -#define VM_OC_GET_ARGS_MASK 0x7 - -/** - * Generate the binary representation of a "get arguments" opcode. - */ -#define VM_OC_GET_ARGS_CREATE_INDEX(V) (((V) &VM_OC_GET_ARGS_MASK) << VM_OC_GET_ARGS_SHIFT) - -/** - * Extract the "get arguments" opcode. - */ -#define VM_OC_GET_ARGS_INDEX(O) ((O) & (VM_OC_GET_ARGS_MASK << VM_OC_GET_ARGS_SHIFT)) - -/** - * Checks whether the result is stored somewhere. - */ -#define VM_OC_HAS_GET_ARGS(V) ((V) & (VM_OC_GET_ARGS_MASK << VM_OC_GET_ARGS_SHIFT)) - -/** - * Argument getters that are part of the opcodes. - */ -typedef enum -{ - VM_OC_GET_NONE = VM_OC_GET_ARGS_CREATE_INDEX (0), /**< do nothing */ - VM_OC_GET_BRANCH = VM_OC_GET_ARGS_CREATE_INDEX (1), /**< branch argument */ - VM_OC_GET_STACK = VM_OC_GET_ARGS_CREATE_INDEX (2), /**< pop one element from the stack */ - VM_OC_GET_STACK_STACK = VM_OC_GET_ARGS_CREATE_INDEX (3), /**< pop two elements from the stack */ - - VM_OC_GET_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (4), /**< resolve literal */ - VM_OC_GET_LITERAL_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (5), /**< resolve two literals */ - VM_OC_GET_STACK_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (6), /**< pop one element from the stack - * and resolve a literal */ - VM_OC_GET_THIS_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (7), /**< get this and resolve a literal */ -} vm_oc_get_types; - -/** - * Mask of "group" opcode. - */ -#define VM_OC_GROUP_MASK 0xff - -/** - * Extract the "group" opcode. - */ -#define VM_OC_GROUP_GET_INDEX(O) ((O) &VM_OC_GROUP_MASK) - -/** - * Opcodes. - */ -typedef enum -{ - VM_OC_POP, /**< pop from stack */ - VM_OC_POP_BLOCK, /**< pop block */ - VM_OC_PUSH, /**< push one literal */ - VM_OC_PUSH_TWO, /**< push two literals */ - VM_OC_PUSH_THREE, /**< push three literals */ - VM_OC_PUSH_UNDEFINED, /**< push undefined value */ - VM_OC_PUSH_TRUE, /**< push true value */ - VM_OC_PUSH_FALSE, /**< push false value */ - VM_OC_PUSH_NULL, /**< push null value */ - VM_OC_PUSH_THIS, /**< push this */ - VM_OC_PUSH_0, /**< push number zero */ - VM_OC_PUSH_POS_BYTE, /**< push number between 1 and 256 */ - VM_OC_PUSH_NEG_BYTE, /**< push number between -1 and -256 */ - VM_OC_PUSH_LIT_0, /**< push literal and number zero */ - VM_OC_PUSH_LIT_POS_BYTE, /**< push literal and number between 1 and 256 */ - VM_OC_PUSH_LIT_NEG_BYTE, /**< push literal and number between -1 and -256 */ - VM_OC_PUSH_OBJECT, /**< push object */ - VM_OC_PUSH_NAMED_FUNC_EXPR, /**< push named function expression */ - VM_OC_SET_PROPERTY, /**< set property */ - - VM_OC_SET_GETTER, /**< set getter */ - VM_OC_SET_SETTER, /**< set setter */ - VM_OC_PUSH_ARRAY, /**< push array */ - VM_OC_PUSH_ELISON, /**< push elison */ - VM_OC_APPEND_ARRAY, /**< append array */ - VM_OC_IDENT_REFERENCE, /**< ident reference */ - VM_OC_PROP_REFERENCE, /**< prop reference */ - VM_OC_PROP_GET, /**< prop get */ - - /* These eight opcodes must be in this order. */ - VM_OC_PROP_PRE_INCR, /**< prefix increment of a property */ - VM_OC_PROP_PRE_DECR, /**< prop prefix decrement of a property */ - VM_OC_PROP_POST_INCR, /**< prop postfix increment of a property */ - VM_OC_PROP_POST_DECR, /**< prop postfix decrement of a property */ - VM_OC_PRE_INCR, /**< prefix increment */ - VM_OC_PRE_DECR, /**< prefix decrement */ - VM_OC_POST_INCR, /**< postfix increment */ - VM_OC_POST_DECR, /**< postfix decrement */ - - VM_OC_PROP_DELETE, /**< delete property */ - VM_OC_DELETE, /**< delete */ - - VM_OC_MOV_IDENT, /**< move identifier register reference */ - VM_OC_ASSIGN, /**< assign */ - VM_OC_ASSIGN_PROP, /**< assign property */ - VM_OC_ASSIGN_PROP_THIS, /**< assign prop this */ - - VM_OC_RETURN, /**< return */ - VM_OC_RETURN_FUNCTION_END, /**< return at the end of a function/script */ - VM_OC_THROW, /**< throw */ - VM_OC_THROW_REFERENCE_ERROR, /**< throw reference error */ - - VM_OC_EVAL, /**< eval */ - VM_OC_CALL, /**< call */ - VM_OC_NEW, /**< new */ - VM_OC_RESOLVE_BASE_FOR_CALL, /**< resolve base value before call */ - VM_OC_ERROR, /**< error while the vm_loop is suspended */ - - VM_OC_JUMP, /**< jump */ -#if JERRY_ESNEXT - VM_OC_BRANCH_IF_NULLISH, /** branch if undefined or null */ - VM_OC_POP_REFERENCE, /** prop identifier or property reference from the stack */ -#endif /* JERRY_ESNEXT */ - VM_OC_BRANCH_IF_STRICT_EQUAL, /**< branch if strict equal */ - - /* These four opcodes must be in this order. */ - VM_OC_BRANCH_IF_TRUE, /**< branch if true */ - VM_OC_BRANCH_IF_FALSE, /**< branch if false */ - VM_OC_BRANCH_IF_LOGICAL_TRUE, /**< branch if logical true */ - VM_OC_BRANCH_IF_LOGICAL_FALSE, /**< branch if logical false */ - - VM_OC_PLUS, /**< unary plus */ - VM_OC_MINUS, /**< unary minus */ - VM_OC_NOT, /**< not */ - VM_OC_BIT_NOT, /**< bitwise not */ - VM_OC_VOID, /**< void */ - VM_OC_TYPEOF_IDENT, /**< typeof identifier */ - VM_OC_TYPEOF, /**< typeof */ - - VM_OC_ADD, /**< binary add */ - VM_OC_SUB, /**< binary sub */ - VM_OC_MUL, /**< mul */ - VM_OC_DIV, /**< div */ - VM_OC_MOD, /**< mod */ -#if JERRY_ESNEXT - VM_OC_EXP, /**< exponentiation */ -#endif /* JERRY_ESNEXT */ - - VM_OC_EQUAL, /**< equal */ - VM_OC_NOT_EQUAL, /**< not equal */ - VM_OC_STRICT_EQUAL, /**< strict equal */ - VM_OC_STRICT_NOT_EQUAL, /**< strict not equal */ - VM_OC_LESS, /**< less */ - VM_OC_GREATER, /**< greater */ - VM_OC_LESS_EQUAL, /**< less equal */ - VM_OC_GREATER_EQUAL, /**< greater equal */ - VM_OC_IN, /**< in */ - VM_OC_INSTANCEOF, /**< instanceof */ - - VM_OC_BIT_OR, /**< bitwise or */ - VM_OC_BIT_XOR, /**< bitwise xor */ - VM_OC_BIT_AND, /**< bitwise and */ - VM_OC_LEFT_SHIFT, /**< left shift */ - VM_OC_RIGHT_SHIFT, /**< right shift */ - VM_OC_UNS_RIGHT_SHIFT, /**< unsigned right shift */ - - VM_OC_BLOCK_CREATE_CONTEXT, /**< create lexical environment for blocks enclosed in braces */ - VM_OC_WITH, /**< with */ - VM_OC_FOR_IN_INIT, /**< for-in init context */ - VM_OC_FOR_IN_GET_NEXT, /**< get next */ - VM_OC_FOR_IN_HAS_NEXT, /**< has next */ - - VM_OC_TRY, /**< try */ - VM_OC_CATCH, /**< catch */ - VM_OC_FINALLY, /**< finally */ - VM_OC_CONTEXT_END, /**< context end */ - VM_OC_JUMP_AND_EXIT_CONTEXT, /**< jump and exit context */ - - VM_OC_CREATE_BINDING, /**< create variables */ - VM_OC_CREATE_ARGUMENTS, /**< create arguments object */ - VM_OC_SET_BYTECODE_PTR, /**< setting bytecode pointer */ - VM_OC_VAR_EVAL, /**< variable and function evaluation */ -#if JERRY_ESNEXT - VM_OC_EXT_VAR_EVAL, /**< variable and function evaluation for - * functions with separate argument context */ -#endif /* JERRY_ESNEXT */ - VM_OC_INIT_ARG_OR_FUNC, /**< create and init a function or argument binding */ - -#if JERRY_DEBUGGER - VM_OC_BREAKPOINT_ENABLED, /**< enabled breakpoint for debugger */ - VM_OC_BREAKPOINT_DISABLED, /**< disabled breakpoint for debugger */ -#endif /* JERRY_DEBUGGER */ -#if JERRY_ESNEXT - VM_OC_CLASS_CALL_STATIC_BLOCK, /**< call the class static block */ - VM_OC_DEFINE_FIELD, /**< define class field */ - VM_OC_PRIVATE_PROP_REFERENCE, /**< reference to class private method */ - VM_OC_ASSIGN_PRIVATE, /**< assign to private field */ - VM_OC_PRIVATE_FIELD_ADD, /**< add private field */ - VM_OC_PRIVATE_PROP_GET, /**< get private field */ - VM_OC_PRIVATE_IN, /**< 'in' opcode handler for private identifiers */ - VM_OC_COLLECT_PRIVATE_PROPERTY, /**< collect private properties */ - VM_OC_CHECK_VAR, /**< check redeclared vars in the global scope */ - VM_OC_CHECK_LET, /**< check redeclared lets in the global scope */ - VM_OC_ASSIGN_LET_CONST, /**< assign values to let/const declarations */ - VM_OC_INIT_BINDING, /**< create and intialize a binding */ - VM_OC_THROW_CONST_ERROR, /**< throw invalid assignment to const variable error */ - VM_OC_COPY_TO_GLOBAL, /**< copy value to global lex env */ - VM_OC_COPY_FROM_ARG, /**< copy value from arg lex env */ - VM_OC_CLONE_CONTEXT, /**< clone lexical environment with let/const declarations */ - VM_OC_COPY_DATA_PROPERTIES, /**< copy data properties of an object */ - VM_OC_SET_COMPUTED_PROPERTY, /**< set computed property */ - - VM_OC_FOR_OF_INIT, /**< for-of init context */ - VM_OC_FOR_OF_GET_NEXT, /**< for-of get next */ - VM_OC_FOR_OF_HAS_NEXT, /**< for-of has next */ - VM_OC_FOR_AWAIT_OF_INIT, /**< for-await-of init context */ - VM_OC_FOR_AWAIT_OF_HAS_NEXT, /**< for-await-of has next */ - - VM_OC_LOCAL_EVAL, /**< eval in local context */ - VM_OC_SUPER_CALL, /**< call the 'super' constructor */ - VM_OC_PUSH_CLASS_ENVIRONMENT, /**< push class environment */ - VM_OC_PUSH_IMPLICIT_CTOR, /**< create implicit class constructor */ - VM_OC_INIT_CLASS, /**< initialize class */ - VM_OC_FINALIZE_CLASS, /**< finalize class */ - VM_OC_SET_FIELD_INIT, /**< store the class field initializer function */ - VM_OC_SET_STATIC_FIELD_INIT, /**< store the static class field initializer function */ - VM_OC_RUN_FIELD_INIT, /**< run the class field initializer function */ - VM_OC_RUN_STATIC_FIELD_INIT, /**< run the static class field initializer function */ - VM_OC_SET_NEXT_COMPUTED_FIELD, /**< set the next computed field of a class */ - VM_OC_PUSH_SUPER_CONSTRUCTOR, /**< getSuperConstructor operation */ - VM_OC_RESOLVE_LEXICAL_THIS, /**< resolve this_binding from from the lexical environment */ - VM_OC_SUPER_REFERENCE, /**< push super reference */ - VM_OC_SET_HOME_OBJECT, /**< set the [[HomeObject]] environment in an object literal */ - VM_OC_OBJECT_LITERAL_HOME_ENV, /**< create/destroy [[HomeObject]] environment of an object literal */ - VM_OC_SET_FUNCTION_NAME, /**< set function name property */ - - VM_OC_PUSH_SPREAD_ELEMENT, /**< push spread element */ - VM_OC_PUSH_REST_OBJECT, /**< push rest object */ - VM_OC_ITERATOR_CONTEXT_CREATE, /**< create iterator conext */ - VM_OC_ITERATOR_CONTEXT_END, /**< finalize iterator cotnext */ - VM_OC_ITERATOR_STEP, /**< IteratorStep abstract operation */ - VM_OC_OBJ_INIT_CONTEXT_CREATE, /**< create object initializer context */ - VM_OC_OBJ_INIT_CONTEXT_END, /**< finalize object initializer context */ - VM_OC_OBJ_INIT_PUSH_REST, /**< push the object with the rest properties */ - VM_OC_INITIALIZER_PUSH_NAME, /**< append string to name list array and push the string */ - VM_OC_DEFAULT_INITIALIZER, /**< default initializer inside a pattern */ - VM_OC_REST_INITIALIZER, /**< create rest object inside an array pattern */ - VM_OC_INITIALIZER_PUSH_PROP, /**< push property for object initializer */ - VM_OC_SPREAD_ARGUMENTS, /**< perform function call/construct with spreaded arguments */ - VM_OC_CREATE_GENERATOR, /**< create a generator object */ - VM_OC_YIELD, /**< yield operation */ - VM_OC_ASYNC_YIELD, /**< async yield operation */ - VM_OC_ASYNC_YIELD_ITERATOR, /**< async yield iterator operation */ - VM_OC_AWAIT, /**< await operation */ - VM_OC_GENERATOR_AWAIT, /**< generator await operation */ - VM_OC_EXT_RETURN, /**< return which also clears the stack */ - VM_OC_ASYNC_EXIT, /**< return from async function */ - VM_OC_STRING_CONCAT, /**< string concatenation */ - VM_OC_GET_TEMPLATE_OBJECT, /**< GetTemplateObject operation */ - VM_OC_PUSH_NEW_TARGET, /**< push new.target onto the stack */ - VM_OC_REQUIRE_OBJECT_COERCIBLE, /**< RequireObjectCoercible opretaion */ - VM_OC_ASSIGN_SUPER, /**< assign super reference */ - VM_OC_SET__PROTO__, /**< set prototype when __proto__: form is used */ - VM_OC_PUSH_STATIC_FIELD_FUNC, /**< push static field initializer function */ - VM_OC_ADD_COMPUTED_FIELD, /**< add computed field name */ -#endif /* JERRY_ESNEXT */ -#if JERRY_MODULE_SYSTEM - VM_OC_MODULE_IMPORT, /**< module dynamic import */ - VM_OC_MODULE_IMPORT_META, /**< module import.meta */ -#endif /* JERRY_MODULE_SYSTEM */ - - VM_OC_NONE, /**< a special opcode for unsupported byte codes */ -} vm_oc_types; - -/** - * Unused opcodes, but required by byte-code types. - */ -typedef enum -{ -#if !JERRY_ESNEXT - VM_OC_EXP = VM_OC_NONE, /**< exponentiation */ - VM_OC_BRANCH_IF_NULLISH = VM_OC_NONE, /** branch if undefined or null */ - VM_OC_POP_REFERENCE = VM_OC_NONE, /** prop identifier or property reference from the stack */ -#endif /* !JERRY_ESNEXT */ -#if !JERRY_DEBUGGER - VM_OC_BREAKPOINT_ENABLED = VM_OC_NONE, /**< enabled breakpoint for debugger is unused */ - VM_OC_BREAKPOINT_DISABLED = VM_OC_NONE, /**< disabled breakpoint for debugger is unused */ -#endif /* !JERRY_DEBUGGER */ -#if !JERRY_ESNEXT - VM_OC_CLASS_CALL_STATIC_BLOCK = VM_OC_NONE, /**< call the class static block */ - VM_OC_DEFINE_FIELD = VM_OC_NONE, /**< define class field */ - VM_OC_PRIVATE_PROP_REFERENCE = VM_OC_NONE, /* reference to class private method */ - VM_OC_ASSIGN_PRIVATE = VM_OC_NONE, /**< assign to private field */ - VM_OC_PRIVATE_FIELD_ADD = VM_OC_NONE, /**< add private field */ - VM_OC_PRIVATE_PROP_GET = VM_OC_NONE, /**< get private field */ - VM_OC_PRIVATE_IN = VM_OC_NONE, /**< 'in' opcode handler for private identifiers */ - VM_OC_COLLECT_PRIVATE_PROPERTY = VM_OC_NONE, /**< collect private properties */ - VM_OC_EXT_VAR_EVAL = VM_OC_NONE, /**< variable and function evaluation for - * functions with separate argument context */ - VM_OC_CHECK_VAR = VM_OC_NONE, /**< check redeclared vars in the global scope */ - VM_OC_CHECK_LET = VM_OC_NONE, /**< check redeclared lets in the global scope */ - VM_OC_ASSIGN_LET_CONST = VM_OC_NONE, /**< assign values to let/const declarations */ - VM_OC_INIT_BINDING = VM_OC_NONE, /**< create and intialize a binding */ - VM_OC_THROW_CONST_ERROR = VM_OC_NONE, /**< throw invalid assignment to const variable error */ - VM_OC_COPY_TO_GLOBAL = VM_OC_NONE, /**< copy value to global lex env */ - VM_OC_COPY_FROM_ARG = VM_OC_NONE, /**< copy value from arg lex env */ - VM_OC_CLONE_CONTEXT = VM_OC_NONE, /**< clone lexical environment with let/const declarations */ - VM_OC_COPY_DATA_PROPERTIES = VM_OC_NONE, /**< copy data properties of an object */ - VM_OC_SET_COMPUTED_PROPERTY = VM_OC_NONE, /**< set computed property is unused */ - - VM_OC_FOR_OF_INIT = VM_OC_NONE, /**< for-of init context */ - VM_OC_FOR_OF_GET_NEXT = VM_OC_NONE, /**< for-of get next */ - VM_OC_FOR_OF_HAS_NEXT = VM_OC_NONE, /**< for-of has next */ - VM_OC_FOR_AWAIT_OF_INIT = VM_OC_NONE, /**< for-await-of init context */ - VM_OC_FOR_AWAIT_OF_HAS_NEXT = VM_OC_NONE, /**< for-await-of has next */ - - VM_OC_LOCAL_EVAL = VM_OC_NONE, /**< eval in local context */ - VM_OC_SUPER_CALL = VM_OC_NONE, /**< call the 'super' constructor */ - VM_OC_PUSH_CLASS_ENVIRONMENT = VM_OC_NONE, /**< push class environment */ - VM_OC_PUSH_IMPLICIT_CTOR = VM_OC_NONE, /**< create implicit class constructor */ - VM_OC_INIT_CLASS = VM_OC_NONE, /**< initialize class */ - VM_OC_FINALIZE_CLASS = VM_OC_NONE, /**< finalize class */ - VM_OC_SET_FIELD_INIT = VM_OC_NONE, /**< store the class field initializer function */ - VM_OC_SET_STATIC_FIELD_INIT = VM_OC_NONE, /**< store the static class field initializer function */ - VM_OC_RUN_FIELD_INIT = VM_OC_NONE, /**< run the class field initializer function */ - VM_OC_RUN_STATIC_FIELD_INIT = VM_OC_NONE, /**< run the static class field initializer function */ - VM_OC_SET_NEXT_COMPUTED_FIELD = VM_OC_NONE, /**< set the next computed field of a class */ - VM_OC_PUSH_SUPER_CONSTRUCTOR = VM_OC_NONE, /**< getSuperConstructor operation */ - VM_OC_RESOLVE_LEXICAL_THIS = VM_OC_NONE, /**< resolve this_binding from from the lexical environment */ - VM_OC_SUPER_REFERENCE = VM_OC_NONE, /**< push super reference */ - VM_OC_SET_HOME_OBJECT = VM_OC_NONE, /**< set the [[HomeObject]] internal property in an object literal */ - VM_OC_OBJECT_LITERAL_HOME_ENV = VM_OC_NONE, /**< create/destroy [[HomeObject]] environment of an object literal */ - VM_OC_SET_FUNCTION_NAME = VM_OC_NONE, /**< set function name property */ - - VM_OC_PUSH_SPREAD_ELEMENT = VM_OC_NONE, /**< push spread element */ - VM_OC_PUSH_REST_OBJECT = VM_OC_NONE, /**< push rest object */ - VM_OC_ITERATOR_CONTEXT_CREATE = VM_OC_NONE, /**< create iterator context */ - VM_OC_ITERATOR_STEP = VM_OC_NONE, /**< IteratorStep abstract operation */ - VM_OC_ITERATOR_CONTEXT_END = VM_OC_NONE, /**< finalize iterator cotnext */ - VM_OC_OBJ_INIT_CONTEXT_CREATE = VM_OC_NONE, /**< create object initializer context */ - VM_OC_OBJ_INIT_CONTEXT_END = VM_OC_NONE, /**< finalize object initializer context */ - VM_OC_OBJ_INIT_PUSH_REST = VM_OC_NONE, /**< push the object with the rest properties */ - VM_OC_INITIALIZER_PUSH_NAME = VM_OC_NONE, /**< append string to name list array and push the string */ - VM_OC_DEFAULT_INITIALIZER = VM_OC_NONE, /**< default initializer inside a pattern */ - VM_OC_REST_INITIALIZER = VM_OC_NONE, /**< create rest object inside an array pattern */ - VM_OC_INITIALIZER_PUSH_PROP = VM_OC_NONE, /**< push property for object initializer */ - VM_OC_SPREAD_ARGUMENTS = VM_OC_NONE, /**< perform function call/construct with spreaded arguments */ - VM_OC_CREATE_GENERATOR = VM_OC_NONE, /**< create a generator object */ - VM_OC_YIELD = VM_OC_NONE, /**< yield operation */ - VM_OC_ASYNC_YIELD = VM_OC_NONE, /**< async yield operation */ - VM_OC_ASYNC_YIELD_ITERATOR = VM_OC_NONE, /**< async yield iterator operation */ - VM_OC_AWAIT = VM_OC_NONE, /**< await operation */ - VM_OC_GENERATOR_AWAIT = VM_OC_NONE, /**< generator await operation */ - VM_OC_EXT_RETURN = VM_OC_NONE, /**< return which also clears the stack */ - VM_OC_ASYNC_EXIT = VM_OC_NONE, /**< return from async function */ - VM_OC_STRING_CONCAT = VM_OC_NONE, /**< string concatenation */ - VM_OC_GET_TEMPLATE_OBJECT = VM_OC_NONE, /**< GetTemplateObject operation */ - VM_OC_PUSH_NEW_TARGET = VM_OC_NONE, /**< push new.target onto the stack */ - VM_OC_REQUIRE_OBJECT_COERCIBLE = VM_OC_NONE, /**< RequireObjectCoercible opretaion */ - VM_OC_ASSIGN_SUPER = VM_OC_NONE, /**< assign super reference */ - VM_OC_SET__PROTO__ = VM_OC_NONE, /**< set prototype when __proto__: form is used */ - VM_OC_PUSH_STATIC_FIELD_FUNC = VM_OC_NONE, /**< push static field initializer function */ - VM_OC_ADD_COMPUTED_FIELD = VM_OC_NONE, /**< add computed field name */ -#endif /* !JERRY_ESNEXT */ -#if !JERRY_MODULE_SYSTEM - VM_OC_MODULE_IMPORT = VM_OC_NONE, /**< module dynamic import */ - VM_OC_MODULE_IMPORT_META = VM_OC_NONE, /**< module import.meta */ -#endif /* JERRY_MODULE_SYSTEM */ - - VM_OC_UNUSED = VM_OC_NONE /**< placeholder if the list is empty */ -} vm_oc_unused_types; - -/** - * Decrement operator. - */ -#define VM_OC_DECREMENT_OPERATOR_FLAG 0x1 - -/** - * Postfix increment/decrement operator. - */ -#define VM_OC_POST_INCR_DECR_OPERATOR_FLAG 0x2 - -/** - * An named variable is updated by the increment/decrement operator. - */ -#define VM_OC_IDENT_INCR_DECR_OPERATOR_FLAG 0x4 - -/** - * Jump to target offset if input value is logical false. - */ -#define VM_OC_BRANCH_IF_FALSE_FLAG 0x1 - -/** - * Branch optimized for logical and/or opcodes. - */ -#define VM_OC_LOGICAL_BRANCH_FLAG 0x2 - -/** - * Bit index shift for non-static property initializers. - */ -#define VM_OC_NON_STATIC_SHIFT 15 - -/** - * This flag is set for static property initializers. - */ -#define VM_OC_NON_STATIC_FLAG (0x1 << VM_OC_NON_STATIC_SHIFT) - -/** - * Position of "put result" opcode. - */ -#define VM_OC_PUT_RESULT_SHIFT 11 - -/** - * Mask of "put result" opcode. - */ -#define VM_OC_PUT_RESULT_MASK 0xf - -/** - * Generate a "put result" opcode flag bit. - */ -#define VM_OC_PUT_RESULT_CREATE_FLAG(V) (((V) &VM_OC_PUT_RESULT_MASK) << VM_OC_PUT_RESULT_SHIFT) - -/** - * Checks whether the result is stored somewhere. - */ -#define VM_OC_HAS_PUT_RESULT(V) ((V) & (VM_OC_PUT_RESULT_MASK << VM_OC_PUT_RESULT_SHIFT)) - /** * Specify where the result is stored */ typedef enum { - VM_OC_PUT_IDENT = VM_OC_PUT_RESULT_CREATE_FLAG (0x1), - VM_OC_PUT_REFERENCE = VM_OC_PUT_RESULT_CREATE_FLAG (0x2), - VM_OC_PUT_STACK = VM_OC_PUT_RESULT_CREATE_FLAG (0x4), - VM_OC_PUT_BLOCK = VM_OC_PUT_RESULT_CREATE_FLAG (0x8), -} vm_oc_put_types; + /* These 3 flags must be in this order */ + VM_PUT_RESULT_NONE = 0, /**< result is not needed, can be free */ + VM_PUT_RESULT_STACK = 1 << 0, /**< result must be placed on to the stack */ + VM_PUT_RESULT_BLOCK = 1 << 1, /**< result must be placed on to frame's block result */ + + VM_PUT_RESULT_IDENT = 1 << 2, /**< assign to ident reference */ + VM_PUT_RESULT_REFERENCE = 1 << 4, /**< assign to property reference */ + VM_PUT_RESULT_DECR = 1 << 5, /**< unary -- flag */ + VM_PUT_RESULT_POST = 1 << 6, /**< post unary lvalue flag */ +} vm_put_result_flags_t; /** * Non-recursive vm_loop: the vm_loop can be suspended