diff options
author | Dmitry Stogov <dmitry@zend.com> | 2014-05-26 10:12:10 +0400 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2014-05-26 10:12:10 +0400 |
commit | 24a86dbb6f7cf7c7ea498d96d290d32e4e2e5a9b (patch) | |
tree | 749598b8f4f0cecfc94d0a66e25bc34032222fe9 | |
parent | 370256ad4bf1e3d0c388911d3a75f693fe4ca5b0 (diff) | |
parent | 19be8b676cd8cc16af35dd47b8f74f750f40f694 (diff) | |
download | php-git-24a86dbb6f7cf7c7ea498d96d290d32e4e2e5a9b.tar.gz |
Merge branch 'PHP-5.5' into PHP-5.6
* PHP-5.5:
Fixed issue #183 (TMP_VAR is not only used once)
-rw-r--r-- | ext/opcache/Optimizer/zend_optimizer.c | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index 973ba3aaac..fc7d0a29b3 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -367,20 +367,41 @@ static void replace_tmp_by_const(zend_op_array *op_array, if (ZEND_OP1_TYPE(opline) == IS_TMP_VAR && ZEND_OP1(opline).var == var) { - update_op1_const(op_array, opline, val TSRMLS_CC); - /* TMP_VAR my be used only once */ - break; + /* In most cases IS_TMP_VAR operand may be used only once. + * The operands are usually destroyed by the opcode handler. + * ZEND_CASE is an exception, that keeps operand unchanged, + * and allows its reuse. The number of ZEND_CASE instructions + * usually terminated by ZEND_FREE that finally kills the value. + */ + if (opline->opcode == ZEND_CASE) { + zval old_val; + old_val = *val; + zval_copy_ctor(val); + update_op1_const(op_array, opline, val TSRMLS_CC); + *val = old_val; + } else if (opline->opcode == ZEND_FREE) { + MAKE_NOP(opline); + break; + } else { + update_op1_const(op_array, opline, val TSRMLS_CC); + val = NULL; + break; + } } if (ZEND_OP2_TYPE(opline) == IS_TMP_VAR && ZEND_OP2(opline).var == var) { update_op2_const(op_array, opline, val TSRMLS_CC); - /* TMP_VAR my be used only once */ + /* TMP_VAR may be used only once */ + val = NULL; break; } opline++; } + if (val) { + zval_dtor(val); + } } #include "Optimizer/nop_removal.c" |