summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2020-09-16 14:22:36 +0300
committerDmitry Stogov <dmitry@zend.com>2020-09-16 14:22:36 +0300
commitf786c0e097f748b32a3aefb116c7d9dcc5bd3ee9 (patch)
treec05bde123773cc6e96c1dd7bf7f4618962326c15
parent0d99a5618f57f9bee25e1570962b8d7d83fce2b1 (diff)
downloadphp-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.c2
-rw-r--r--ext/opcache/jit/zend_jit_helpers.c45
-rw-r--r--ext/opcache/jit/zend_jit_trace.c15
-rw-r--r--ext/opcache/jit/zend_jit_x86.dasc26
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;
}