diff options
author | Dmitry Stogov <dmitry@zend.com> | 2020-09-16 14:22:36 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2020-09-16 14:22:36 +0300 |
commit | f786c0e097f748b32a3aefb116c7d9dcc5bd3ee9 (patch) | |
tree | c05bde123773cc6e96c1dd7bf7f4618962326c15 | |
parent | 0d99a5618f57f9bee25e1570962b8d7d83fce2b1 (diff) | |
download | php-git-f786c0e097f748b32a3aefb116c7d9dcc5bd3ee9.tar.gz |
Optimize code for FETCH_THIS + INIT_METHOD_CALL/ASSIGN_OBJ_OP/etc
-rw-r--r-- | ext/opcache/jit/zend_jit_disasm_x86.c | 2 | ||||
-rw-r--r-- | ext/opcache/jit/zend_jit_helpers.c | 45 | ||||
-rw-r--r-- | ext/opcache/jit/zend_jit_trace.c | 15 | ||||
-rw-r--r-- | ext/opcache/jit/zend_jit_x86.dasc | 26 |
4 files changed, 58 insertions, 30 deletions
diff --git a/ext/opcache/jit/zend_jit_disasm_x86.c b/ext/opcache/jit/zend_jit_disasm_x86.c index 07884ad03a..a470179917 100644 --- a/ext/opcache/jit/zend_jit_disasm_x86.c +++ b/ext/opcache/jit/zend_jit_disasm_x86.c @@ -399,9 +399,11 @@ static int zend_jit_disasm_init(void) REGISTER_HELPER(zend_jit_find_func_helper); REGISTER_HELPER(zend_jit_find_ns_func_helper); REGISTER_HELPER(zend_jit_find_method_helper); + REGISTER_HELPER(zend_jit_find_method_tmp_helper); REGISTER_HELPER(zend_jit_push_static_metod_call_frame); REGISTER_HELPER(zend_jit_push_static_metod_call_frame_tmp); REGISTER_HELPER(zend_jit_invalid_method_call); + REGISTER_HELPER(zend_jit_invalid_method_call_tmp); REGISTER_HELPER(zend_jit_unref_helper); REGISTER_HELPER(zend_jit_extend_stack_helper); REGISTER_HELPER(zend_jit_int_extend_stack_helper); diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 03e4041f0a..240311719d 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -107,9 +107,15 @@ static ZEND_COLD void ZEND_FASTCALL zend_jit_invalid_method_call(zval *object) } zend_throw_error(NULL, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_zval_type_name(object)); - if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { - zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - } +} + +static ZEND_COLD void ZEND_FASTCALL zend_jit_invalid_method_call_tmp(zval *object) +{ + zend_execute_data *execute_data = EG(current_execute_data); + const zend_op *opline = EX(opline); + + zend_jit_invalid_method_call(object); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); } static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_method(const zend_class_entry *ce, const zend_string *method) @@ -136,17 +142,13 @@ static zend_function* ZEND_FASTCALL zend_jit_find_method_helper(zend_object *obj zend_execute_data *execute_data = EG(current_execute_data); const zend_op *opline = EX(opline); zend_class_entry *called_scope = obj->ce; - zend_object *orig_obj = obj; zend_function *fbc; - fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), function_name + 1); + fbc = obj->handlers->get_method(obj_ptr, Z_STR_P(function_name), function_name + 1); if (UNEXPECTED(fbc == NULL)) { if (EXPECTED(!EG(exception))) { zend_undefined_method(called_scope, Z_STR_P(function_name)); } - if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) { - zend_objects_store_del(orig_obj); - } return NULL; } @@ -154,14 +156,7 @@ static zend_function* ZEND_FASTCALL zend_jit_find_method_helper(zend_object *obj zend_init_func_run_time_cache(&fbc->op_array); } - if (UNEXPECTED(obj != orig_obj)) { - if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { - GC_ADDREF(obj); - if (GC_DELREF(orig_obj) == 0) { - zend_objects_store_del(orig_obj); - } - } - *obj_ptr = obj; + if (UNEXPECTED(obj != *obj_ptr)) { return fbc; } @@ -172,6 +167,24 @@ static zend_function* ZEND_FASTCALL zend_jit_find_method_helper(zend_object *obj return fbc; } +static zend_function* ZEND_FASTCALL zend_jit_find_method_tmp_helper(zend_object *obj, zval *function_name, zend_object **obj_ptr) +{ + zend_function *fbc; + + fbc = zend_jit_find_method_helper(obj, function_name, obj_ptr); + if (!fbc) { + if (GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + } + } else if (obj != *obj_ptr) { + GC_ADDREF(obj); + if (GC_DELREF(obj) == 0) { + zend_objects_store_del(obj); + } + } + return fbc; +} + static zend_execute_data* ZEND_FASTCALL zend_jit_push_static_metod_call_frame(zend_object *obj, zend_function *fbc, uint32_t num_args) { zend_class_entry *scope = obj->ce; diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index e8cc51cd7f..8fa26e700b 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -2827,7 +2827,10 @@ static zend_bool zend_jit_may_delay_fetch_this(zend_ssa *ssa, const zend_op **ss } opline = ssa_opcodes[use]; - if (opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG) { + if (opline->opcode == ZEND_INIT_METHOD_CALL) { + return (opline->op2_type == IS_CONST && + Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) == IS_STRING); + } else if (opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG) { if (!JIT_G(current_frame) || !JIT_G(current_frame)->call || !JIT_G(current_frame)->call->func @@ -2837,7 +2840,12 @@ static zend_bool zend_jit_may_delay_fetch_this(zend_ssa *ssa, const zend_op **ss } else if (opline->opcode != ZEND_FETCH_OBJ_R && opline->opcode != ZEND_FETCH_OBJ_IS && opline->opcode != ZEND_FETCH_OBJ_W - && opline->opcode != ZEND_ASSIGN_OBJ) { + && opline->opcode != ZEND_ASSIGN_OBJ + && opline->opcode != ZEND_ASSIGN_OBJ_OP + && opline->opcode != ZEND_PRE_INC_OBJ + && opline->opcode != ZEND_PRE_DEC_OBJ + && opline->opcode != ZEND_POST_INC_OBJ + && opline->opcode != ZEND_POST_DEC_OBJ) { return 0; } @@ -5001,9 +5009,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par op1_addr = 0; } else { op1_info = OP1_INFO(); - if (!(op1_info & MAY_BE_OBJECT)) { - goto generic_dynamic_call; - } op1_addr = OP1_REG_ADDR(); if (orig_op1_type != IS_UNKNOWN && (orig_op1_type & IS_TRACE_REFERENCE)) { diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 927ed9081f..4fccf22d38 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -8477,7 +8477,7 @@ typedef struct _zend_closure { zif_handler orig_internal_handler; } zend_closure; -static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, zend_function *func, zend_bool is_closure) +static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, zend_function *func, zend_bool is_closure, zend_bool use_this) { uint32_t used_stack; @@ -8599,7 +8599,7 @@ static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, zen | // Z_PTR(call->This) = obj; | mov r1, aword T1 | mov aword EX:RX->This.value.ptr, r1 - if (opline->op1_type == IS_UNUSED) { + if (opline->op1_type == IS_UNUSED || use_this) { | // call->call_info |= ZEND_CALL_HAS_THIS; if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) { | mov dword EX:RX->This.u1.type_info, ZEND_CALL_HAS_THIS @@ -9038,7 +9038,7 @@ static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t |3: } - if (!zend_jit_push_call_frame(Dst, opline, func, 0)) { + if (!zend_jit_push_call_frame(Dst, opline, func, 0, 0)) { return 0; } @@ -9116,7 +9116,11 @@ static int zend_jit_init_method_call(dasm_State **Dst, | LOAD_ZVAL_ADDR FCARG1a, op1_addr } | SET_EX_OPLINE opline, r0 - | EXT_CALL zend_jit_invalid_method_call, r0 + if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && !use_this) { + | EXT_CALL zend_jit_invalid_method_call_tmp, r0 + } else { + | EXT_CALL zend_jit_invalid_method_call, r0 + } | jmp ->exception_handler |.code } @@ -9169,7 +9173,11 @@ static int zend_jit_init_method_call(dasm_State **Dst, | push r0 |.endif | SET_EX_OPLINE opline, r0 - | EXT_CALL zend_jit_find_method_helper, r0 + if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && !use_this) { + | EXT_CALL zend_jit_find_method_tmp_helper, r0 + } else { + | EXT_CALL zend_jit_find_method_helper, r0 + } | test r0, r0 | jz ->exception_handler |.if not(X64) @@ -9247,7 +9255,7 @@ static int zend_jit_init_method_call(dasm_State **Dst, | sub r4, 12 | push opline->extended_value |.endif - if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { + if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && !use_this) { | EXT_CALL zend_jit_push_static_metod_call_frame_tmp, r0 } else { | EXT_CALL zend_jit_push_static_metod_call_frame, r0 @@ -9255,7 +9263,7 @@ static int zend_jit_init_method_call(dasm_State **Dst, |.if not(X64) | add r4, 12 |.endif - if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { + if ((opline->op1_type & (IS_VAR|IS_TMP_VAR) && !use_this)) { | test r0, r0 | jz ->exception_handler } @@ -9268,7 +9276,7 @@ static int zend_jit_init_method_call(dasm_State **Dst, } if (!func || (func->common.fn_flags & ZEND_ACC_STATIC) == 0) { - if (!zend_jit_push_call_frame(Dst, opline, func, 0)) { + if (!zend_jit_push_call_frame(Dst, opline, func, 0, use_this)) { return 0; } } @@ -9366,7 +9374,7 @@ static int zend_jit_init_closure_call(dasm_State **Dst, } } - if (!zend_jit_push_call_frame(Dst, opline, func, 1)) { + if (!zend_jit_push_call_frame(Dst, opline, func, 1, 0)) { return 0; } |