diff options
author | Nikita Popov <nikic@php.net> | 2016-11-12 18:49:50 +0100 |
---|---|---|
committer | Nikita Popov <nikic@php.net> | 2016-11-12 18:49:50 +0100 |
commit | 9dcc76f4c8068c8afed9a30d7ed79cce98bece92 (patch) | |
tree | 20c5463fde84ca43e47e3a0cbefee0cb837baad9 | |
parent | 0c76451c85387e32767430ed9adaa5504b42ee91 (diff) | |
parent | 5f4f83220a6a33ad3ec56f36ca65cc641aae4445 (diff) | |
download | php-git-9dcc76f4c8068c8afed9a30d7ed79cce98bece92.tar.gz |
Merge branch 'PHP-7.1'
-rw-r--r-- | ext/opcache/Optimizer/optimize_func_calls.c | 22 | ||||
-rw-r--r-- | ext/opcache/tests/wrong_inlining_005.phpt | 22 |
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! |