@@ -45,6 +45,7 @@ void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
45
45
int call = 0 ;
46
46
void * checkpoint ;
47
47
optimizer_call_info * call_stack ;
48
+ zend_bool had_fcall ;
48
49
49
50
if (op_array -> last < 2 ) {
50
51
return ;
@@ -80,6 +81,7 @@ void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
80
81
case ZEND_DO_FCALL_BY_NAME :
81
82
case ZEND_DO_UNPACK_FCALL :
82
83
call -- ;
84
+ had_fcall = call != 0 ; /* we must not replace ZEND_SEND_VAL after a DO_FCALL inside nested calls */
83
85
if (call_stack [call ].func && call_stack [call ].opline ) {
84
86
zend_op * fcall = call_stack [call ].opline ;
85
87
@@ -139,13 +141,32 @@ void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
139
141
}
140
142
break ;
141
143
case ZEND_SEND_VAL_EX :
142
- if (call_stack [call - 1 ].func ) {
143
- if (ARG_MUST_BE_SENT_BY_REF (call_stack [call - 1 ].func , opline -> op2 .num )) {
144
- /* We won't convert it into_DO_FCALL to emit error at run-time */
145
- call_stack [call - 1 ].opline = NULL ;
146
- } else {
147
- opline -> opcode = ZEND_SEND_VAL ;
144
+ if (!call_stack [call - 1 ].func ) {
145
+ break ;
146
+ }
147
+ if (ARG_MUST_BE_SENT_BY_REF (call_stack [call - 1 ].func , opline -> op2 .num )) {
148
+ /* We won't convert it into_DO_FCALL to emit error at run-time */
149
+ call_stack [call - 1 ].opline = NULL ;
150
+ break ;
151
+ }
152
+
153
+ opline -> opcode = ZEND_SEND_VAL ;
154
+ /* break intentionally missing */
155
+ case ZEND_SEND_VAL :
156
+ if (!had_fcall && opline -> op1_type == IS_TMP_VAR ) {
157
+ zend_op * orig = opline ;
158
+ while (-- orig >= op_array -> opcodes ) {
159
+ if (orig -> op1 .var == opline -> op1 .var && orig -> op1_type == IS_TMP_VAR ) {
160
+ orig -> op1 .var = opline -> result .var ;
161
+ }
162
+ if (orig -> op2 .var == opline -> op2 .var && orig -> op2_type == IS_TMP_VAR ) {
163
+ orig -> op2 .var = opline -> result .var ;
164
+ }
165
+ if (orig -> result .var == opline -> op1 .var && orig -> result_type == IS_TMP_VAR ) {
166
+ orig -> result .var = opline -> result .var ;
167
+ }
148
168
}
169
+ opline -> opcode = ZEND_NOP ;
149
170
}
150
171
break ;
151
172
case ZEND_SEND_VAR_EX :
0 commit comments