From 6fa126e966d343b45f84d9eac114c14b73aef5a8 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 18 Jun 2020 18:54:32 +0300 Subject: [PATCH] MAY_BE_INDIRECT inference --- Zend/zend_type_info.h | 1 + ext/opcache/Optimizer/zend_inference.c | 27 +++++++++++++++++++++++-- ext/opcache/Optimizer/zend_inference.h | 2 +- ext/opcache/jit/zend_jit_x86.dasc | 28 ++++++++++++-------------- 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/Zend/zend_type_info.h b/Zend/zend_type_info.h index bace8014bf..9dc90d142b 100644 --- a/Zend/zend_type_info.h +++ b/Zend/zend_type_info.h @@ -61,5 +61,6 @@ #define MAY_BE_ARRAY_KEY_ANY (MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_KEY_STRING) #define MAY_BE_CLASS (1<<23) +#define MAY_BE_INDIRECT (1<<24) #endif /* ZEND_TYPE_INFO_H */ diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index 0c0a2921c9..5a29165aec 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -1983,6 +1983,9 @@ uint32_t zend_array_element_type(uint32_t t1, int write, int insert) tmp |= MAY_BE_RC1 | MAY_BE_RCN; } } + if (write) { + tmp |= MAY_BE_INDIRECT; + } } if (t1 & MAY_BE_STRING) { tmp |= MAY_BE_STRING | MAY_BE_RC1; @@ -3398,7 +3401,7 @@ static zend_always_inline int _zend_update_type_info( tmp = zend_fetch_prop_type(script, zend_fetch_prop_info(op_array, ssa, opline, ssa_op), &ce); if (opline->result_type != IS_TMP_VAR) { - tmp |= MAY_BE_REF; + tmp |= MAY_BE_REF | MAY_BE_INDIRECT; } UPDATE_SSA_TYPE(tmp, ssa_op->result_def); if (ce) { @@ -3415,7 +3418,7 @@ static zend_always_inline int _zend_update_type_info( tmp = zend_fetch_prop_type(script, zend_fetch_static_prop_info(script, op_array, ssa, opline), &ce); if (opline->result_type != IS_TMP_VAR) { - tmp |= MAY_BE_REF; + tmp |= MAY_BE_REF | MAY_BE_INDIRECT; } UPDATE_SSA_TYPE(tmp, ssa_op->result_def); if (ce) { @@ -3524,6 +3527,26 @@ unknown_opcode: tmp |= MAY_BE_RC1 | MAY_BE_RCN; } else { tmp |= MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN; + switch (opline->opcode) { + case ZEND_FETCH_W: + case ZEND_FETCH_RW: + case ZEND_FETCH_FUNC_ARG: + case ZEND_FETCH_UNSET: + case ZEND_FETCH_DIM_W: + case ZEND_FETCH_DIM_RW: + case ZEND_FETCH_DIM_FUNC_ARG: + case ZEND_FETCH_DIM_UNSET: + case ZEND_FETCH_OBJ_W: + case ZEND_FETCH_OBJ_RW: + case ZEND_FETCH_OBJ_FUNC_ARG: + case ZEND_FETCH_OBJ_UNSET: + case ZEND_FETCH_STATIC_PROP_W: + case ZEND_FETCH_STATIC_PROP_RW: + case ZEND_FETCH_STATIC_PROP_FUNC_ARG: + case ZEND_FETCH_STATIC_PROP_UNSET: + tmp |= MAY_BE_INDIRECT; + break; + } } UPDATE_SSA_TYPE(tmp, ssa_op->result_def); } diff --git a/ext/opcache/Optimizer/zend_inference.h b/ext/opcache/Optimizer/zend_inference.h index da103e4bb5..525159a72b 100644 --- a/ext/opcache/Optimizer/zend_inference.h +++ b/ext/opcache/Optimizer/zend_inference.h @@ -195,7 +195,7 @@ static zend_always_inline uint32_t get_ssa_var_info(const zend_ssa *ssa, int ssa if (ssa->var_info && ssa_var_num >= 0) { return ssa->var_info[ssa_var_num].type; } else { - return MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF; + return MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_INDIRECT | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF; } } diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 576bb7badb..b4306f5bdb 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -1323,7 +1323,7 @@ static void* dasm_labels[zend_lb_MAX]; // zval should be in FCARG1a |.macro ZVAL_DTOR_FUNC, var_info, opline // arg1 must be in FCARG1a || do { -|| if (has_concrete_type((var_info) & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) { +|| if (has_concrete_type((var_info) & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_INDIRECT))) { || zend_uchar type = concrete_type((var_info) & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)); || if (type == IS_STRING && !ZEND_DEBUG) { | EXT_CALL _efree, r0 @@ -1355,7 +1355,7 @@ static void* dasm_labels[zend_lb_MAX]; |.macro ZVAL_PTR_DTOR, addr, op_info, gc, cold, opline || if ((op_info) & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) { -|| if ((op_info) & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_OBJECT|MAY_BE_RESOURCE))) { +|| if ((op_info) & ((MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_INDIRECT)-(MAY_BE_OBJECT|MAY_BE_RESOURCE))) { | // if (Z_REFCOUNTED_P(cv)) { || if (cold) { | IF_ZVAL_REFCOUNTED addr, >1 @@ -8916,12 +8916,15 @@ static int zend_jit_send_ref(dasm_State **Dst, const zend_op *opline, const zend } if (opline->op1_type == IS_VAR) { - | LOAD_ZVAL_ADDR r0, op1_addr - | // if (EXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) { - | IF_NOT_Z_TYPE r0, IS_INDIRECT, >1 - | // ret = Z_INDIRECT_P(ret); - | GET_Z_PTR r0, r0 - |1: + if (op1_info & MAY_BE_INDIRECT) { + | LOAD_ZVAL_ADDR r0, op1_addr + | // if (EXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) { + | IF_NOT_Z_TYPE r0, IS_INDIRECT, >1 + | // ret = Z_INDIRECT_P(ret); + | GET_Z_PTR r0, r0 + |1: + op1_addr = ZEND_ADDR_MEM_ZVAL(ZREG_R0, 0); + } } else if (opline->op1_type == IS_CV) { if (op1_info & MAY_BE_UNDEF) { if (op1_info & (MAY_BE_ANY|MAY_BE_REF)) { @@ -8939,13 +8942,8 @@ static int zend_jit_send_ref(dasm_State **Dst, const zend_op *opline, const zend if (op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) { if (op1_info & MAY_BE_REF) { - if (opline->op1_type == IS_VAR) { - | IF_NOT_Z_TYPE r0, IS_REFERENCE, >2 - | GET_Z_PTR r1, r0 - } else { - | IF_NOT_ZVAL_TYPE op1_addr, IS_REFERENCE, >2 - | GET_ZVAL_PTR r1, op1_addr - } + | IF_NOT_ZVAL_TYPE op1_addr, IS_REFERENCE, >2 + | GET_ZVAL_PTR r1, op1_addr | GC_ADDREF r1 | SET_ZVAL_PTR arg_addr, r1 | SET_ZVAL_TYPE_INFO arg_addr, IS_REFERENCE_EX -- 2.40.0