]> granicus.if.org Git - php/commitdiff
Optimize code for FETCH_THIS + INIT_METHOD_CALL/ASSIGN_OBJ_OP/etc
authorDmitry Stogov <dmitry@zend.com>
Wed, 16 Sep 2020 11:22:36 +0000 (14:22 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 16 Sep 2020 11:22:36 +0000 (14:22 +0300)
ext/opcache/jit/zend_jit_disasm_x86.c
ext/opcache/jit/zend_jit_helpers.c
ext/opcache/jit/zend_jit_trace.c
ext/opcache/jit/zend_jit_x86.dasc

index 07884ad03a52c4d3a8c8884cdc1c173323ed1e64..a470179917e6d776671c237c8c4a807c5532b27a 100644 (file)
@@ -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);
index 03e4041f0aab1c01e077e8544698721ecbf910ef..240311719dce10d22d4192837e5d5a0468b42814 100644 (file)
@@ -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;
index e8cc51cd7f3a7b14bf5f2fbf022d5a3addf9b881..8fa26e700bf2ddd5cd092ed979d17dd162374c19 100644 (file)
@@ -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)) {
index 927ed9081f14a270e1eafa082fdf946a7c12b5f6..4fccf22d38a6e65ce67ee8fe21b1d5e5898bd2b3 100644 (file)
@@ -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;
        }