summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2016-11-12 18:49:50 +0100
committerNikita Popov <nikic@php.net>2016-11-12 18:49:50 +0100
commit9dcc76f4c8068c8afed9a30d7ed79cce98bece92 (patch)
tree20c5463fde84ca43e47e3a0cbefee0cb837baad9
parent0c76451c85387e32767430ed9adaa5504b42ee91 (diff)
parent5f4f83220a6a33ad3ec56f36ca65cc641aae4445 (diff)
downloadphp-git-9dcc76f4c8068c8afed9a30d7ed79cce98bece92.tar.gz
Merge branch 'PHP-7.1'
-rw-r--r--ext/opcache/Optimizer/optimize_func_calls.c22
-rw-r--r--ext/opcache/tests/wrong_inlining_005.phpt22
2 files changed, 38 insertions, 6 deletions
diff --git a/ext/opcache/Optimizer/optimize_func_calls.c b/ext/opcache/Optimizer/optimize_func_calls.c
index f9a42db79e..3480a9a6ee 100644
--- a/ext/opcache/Optimizer/optimize_func_calls.c
+++ b/ext/opcache/Optimizer/optimize_func_calls.c
@@ -71,8 +71,6 @@ static void zend_delete_call_instructions(zend_op *opline)
break;
case ZEND_SEND_VAL:
case ZEND_SEND_VAR:
- case ZEND_SEND_VAR_NO_REF:
- case ZEND_SEND_REF:
if (call == 0) {
if (opline->op1_type == IS_CONST) {
MAKE_NOP(opline);
@@ -102,6 +100,8 @@ static void zend_try_inline_call(zend_op_array *op_array, zend_op *fcall, zend_o
zend_op *ret_opline = func->op_array.opcodes + func->op_array.num_args;
if (ret_opline->op1_type == IS_CONST) {
+ uint32_t i, num_args = func->op_array.num_args;
+ num_args += (func->op_array.fn_flags & ZEND_ACC_VARIADIC) != 0;
if (fcall->opcode == ZEND_INIT_METHOD_CALL && fcall->op1_type == IS_UNUSED) {
/* TODO: we can't inlne methods, because $this may be used
@@ -109,17 +109,27 @@ static void zend_try_inline_call(zend_op_array *op_array, zend_op *fcall, zend_o
*/
return;
}
+
+ for (i = 0; i < num_args; i++) {
+ /* Don't inline functions with by-reference arguments. This would require
+ * correct handling of INDIRECT arguments. */
+ if (func->op_array.arg_info[i].pass_by_reference) {
+ return;
+ }
+ }
+
if (fcall->extended_value < func->op_array.num_args) {
/* don't inline funcions with named constants in default arguments */
- uint32_t n = fcall->extended_value;
+ i = fcall->extended_value;
do {
- if (Z_CONSTANT_P(RT_CONSTANT(&func->op_array, func->op_array.opcodes[n].op2))) {
+ if (Z_CONSTANT_P(RT_CONSTANT(&func->op_array, func->op_array.opcodes[i].op2))) {
return;
}
- n++;
- } while (n < func->op_array.num_args);
+ i++;
+ } while (i < func->op_array.num_args);
}
+
if (RETURN_VALUE_USED(opline)) {
zval zv;
diff --git a/ext/opcache/tests/wrong_inlining_005.phpt b/ext/opcache/tests/wrong_inlining_005.phpt
new file mode 100644
index 0000000000..b34cd1b12f
--- /dev/null
+++ b/ext/opcache/tests/wrong_inlining_005.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Inlining of functions with ref arguments
+--FILE--
+<?php
+
+function by_ref(&$var)
+{
+}
+function &get_array() {
+ $array = [new stdClass];
+ return $array;
+}
+function test()
+{
+ by_ref(get_array()[0]);
+ print "ok!\n";
+}
+test();
+
+?>
+--EXPECT--
+ok!