From 24817b27f9fb954f8722cdecaca55ee71ada8e2a Mon Sep 17 00:00:00 2001 From: Robert Fancsik Date: Thu, 29 Nov 2018 09:00:22 +0100 Subject: [PATCH] Optimize property call opcodes (#2609) In with contexts the object base value must be resolved before executing a call operation. Since this happens rarely the base resolving code paths has been seperated to an other VM opcode so these extra checks do not burden the general property call steps. JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu --- jerry-core/include/jerryscript-snapshot.h | 2 +- jerry-core/parser/js/byte-code.h | 2 ++ jerry-core/parser/js/js-parser-expr.c | 2 ++ jerry-core/vm/vm.c | 38 +++++++++++------------ jerry-core/vm/vm.h | 1 + tests/unit-core/test-snapshot.c | 2 +- 6 files changed, 26 insertions(+), 21 deletions(-) diff --git a/jerry-core/include/jerryscript-snapshot.h b/jerry-core/include/jerryscript-snapshot.h index 6416739c8..29b6b9080 100644 --- a/jerry-core/include/jerryscript-snapshot.h +++ b/jerry-core/include/jerryscript-snapshot.h @@ -30,7 +30,7 @@ extern "C" /** * Jerry snapshot format version. */ -#define JERRY_SNAPSHOT_VERSION (19u) +#define JERRY_SNAPSHOT_VERSION (20u) /** * Flags for jerry_generate_snapshot and jerry_generate_function_snapshot. diff --git a/jerry-core/parser/js/byte-code.h b/jerry-core/parser/js/byte-code.h index ba558b03d..34dc876b2 100644 --- a/jerry-core/parser/js/byte-code.h +++ b/jerry-core/parser/js/byte-code.h @@ -590,6 +590,8 @@ VM_OC_SET_GETTER | VM_OC_GET_STACK_LITERAL) \ CBC_OPCODE (CBC_EXT_SET_STATIC_COMPUTED_SETTER, CBC_HAS_LITERAL_ARG, -1, \ VM_OC_SET_SETTER | VM_OC_GET_STACK_LITERAL) \ + CBC_OPCODE (CBC_EXT_RESOLVE_BASE, CBC_NO_FLAG, 0, \ + VM_OC_RESOLVE_BASE_FOR_CALL) \ \ /* Class opcodes */ \ CBC_OPCODE (CBC_EXT_INHERIT_AND_SET_CONSTRUCTOR, CBC_NO_FLAG, 0, \ diff --git a/jerry-core/parser/js/js-parser-expr.c b/jerry-core/parser/js/js-parser-expr.c index 1d8de008c..a42027b62 100644 --- a/jerry-core/parser/js/js-parser-expr.c +++ b/jerry-core/parser/js/js-parser-expr.c @@ -1556,6 +1556,8 @@ parser_process_unary_expression (parser_context_t *context_p) /**< context */ CBC_PUSH_IDENT_REFERENCE, context_p->last_cbc.third_literal_index); } + + parser_emit_cbc_ext (context_p, CBC_EXT_RESOLVE_BASE); } } diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index c0d8e313e..3333eba86 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -476,26 +476,8 @@ opfunc_call (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ bool is_call_prop = ((opcode - CBC_CALL) % 6) >= 3; - ecma_value_t this_value = ECMA_VALUE_UNDEFINED; ecma_value_t *stack_top_p = frame_ctx_p->stack_top_p - arguments_list_len; - - if (is_call_prop) - { - this_value = stack_top_p[-3]; - - if (this_value == ECMA_VALUE_REGISTER_REF) - { - /* Lexical environment cannot be 'this' value. */ - stack_top_p[-2] = ECMA_VALUE_UNDEFINED; - this_value = ECMA_VALUE_UNDEFINED; - } - else if (vm_get_implicit_this_value (&this_value)) - { - ecma_free_value (stack_top_p[-3]); - stack_top_p[-3] = this_value; - } - } - + ecma_value_t this_value = is_call_prop ? stack_top_p[-3] : ECMA_VALUE_UNDEFINED; ecma_value_t func_value = stack_top_p[-1]; ecma_value_t completion_value; @@ -1978,6 +1960,24 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ *stack_top_p++ = result; continue; } + case VM_OC_RESOLVE_BASE_FOR_CALL: + { + ecma_value_t this_value = stack_top_p[-3]; + + if (this_value == ECMA_VALUE_REGISTER_REF) + { + /* Lexical environment cannot be 'this' value. */ + stack_top_p[-2] = ECMA_VALUE_UNDEFINED; + stack_top_p[-3] = ECMA_VALUE_UNDEFINED; + } + else if (vm_get_implicit_this_value (&this_value)) + { + ecma_free_value (stack_top_p[-3]); + stack_top_p[-3] = this_value; + } + + continue; + } case VM_OC_PROP_DELETE: { result = vm_op_delete_prop (left_value, right_value, is_strict); diff --git a/jerry-core/vm/vm.h b/jerry-core/vm/vm.h index 0dc8649d3..92f248c26 100644 --- a/jerry-core/vm/vm.h +++ b/jerry-core/vm/vm.h @@ -158,6 +158,7 @@ typedef enum 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_JUMP, /**< jump */ VM_OC_BRANCH_IF_STRICT_EQUAL, /**< branch if stric equal */ diff --git a/tests/unit-core/test-snapshot.c b/tests/unit-core/test-snapshot.c index aa9f85fe0..219d8181f 100644 --- a/tests/unit-core/test-snapshot.c +++ b/tests/unit-core/test-snapshot.c @@ -223,7 +223,7 @@ main (void) /* Check the snapshot data. Unused bytes should be filled with zeroes */ const uint8_t expected_data[] = { - 0x4A, 0x52, 0x52, 0x59, 0x13, 0x00, 0x00, 0x00, + 0x4A, 0x52, 0x52, 0x59, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,