diff options
author | Dmitry Stogov <dmitry@zend.com> | 2020-07-06 17:55:23 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2020-07-06 17:55:23 +0300 |
commit | ff3c40206ce43f53610bbbe032493df1513e60d4 (patch) | |
tree | 26c42d2b3123d3c14143d1c1a89aa0a5e2b50022 | |
parent | b35255ad21a4e441f2304d944014c0649e37d712 (diff) | |
download | php-git-ff3c40206ce43f53610bbbe032493df1513e60d4.tar.gz |
More accurate reference-counter inference
-rw-r--r-- | ext/opcache/Optimizer/zend_inference.c | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index 0f79e92a9f..76cc15f2da 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -3398,10 +3398,26 @@ static zend_always_inline int _zend_update_type_info( case ZEND_FETCH_OBJ_UNSET: case ZEND_FETCH_OBJ_FUNC_ARG: if (ssa_op->result_def >= 0) { - tmp = zend_fetch_prop_type(script, - zend_fetch_prop_info(op_array, ssa, opline, ssa_op), &ce); + zend_property_info *prop_info = zend_fetch_prop_info(op_array, ssa, opline, ssa_op); + + tmp = zend_fetch_prop_type(script, prop_info, &ce); if (opline->result_type != IS_TMP_VAR) { tmp |= MAY_BE_REF | MAY_BE_INDIRECT; + } else if (prop_info) { + /* FETCH_OBJ_R/IS for plain property increments reference counter, + so it can't be 1 */ + tmp &= ~MAY_BE_RC1; + } else { + zend_class_entry *ce = NULL; + + if (opline->op1_type == IS_UNUSED) { + ce = op_array->scope; + } else if (ssa_op->op1_use >= 0 && !ssa->var_info[ssa_op->op1_use].is_instanceof) { + ce = ssa->var_info[ssa_op->op1_use].ce; + } + if (ce && !ce->create_object && !ce->__get) { + tmp &= ~MAY_BE_RC1; + } } UPDATE_SSA_TYPE(tmp, ssa_op->result_def); if (ce) { @@ -3419,6 +3435,8 @@ static zend_always_inline int _zend_update_type_info( zend_fetch_static_prop_info(script, op_array, ssa, opline), &ce); if (opline->result_type != IS_TMP_VAR) { tmp |= MAY_BE_REF | MAY_BE_INDIRECT; + } else { + tmp &= ~MAY_BE_RC1; } UPDATE_SSA_TYPE(tmp, ssa_op->result_def); if (ce) { @@ -3523,7 +3541,11 @@ unknown_opcode: if (ssa_op->result_def >= 0) { tmp = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF; if (opline->result_type == IS_TMP_VAR) { - tmp |= MAY_BE_RC1 | MAY_BE_RCN; + if (opline->opcode == ZEND_FETCH_R || opline->opcode == ZEND_FETCH_IS) { + tmp |= MAY_BE_RCN; + } else { + tmp |= MAY_BE_RC1 | MAY_BE_RCN; + } } else { tmp |= MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN; switch (opline->opcode) { |