38
38
typedef struct _optimizer_call_info {
39
39
zend_function * func ;
40
40
zend_op * opline ;
41
- zend_op * check_func_arg_opline ;
41
+ zend_op * last_check_func_arg_opline ;
42
42
bool is_prototype ;
43
43
bool try_inline ;
44
44
uint32_t func_arg_num ;
@@ -255,9 +255,10 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
255
255
if (ARG_SHOULD_BE_SENT_BY_REF (call_stack [call - 1 ].func , call_stack [call - 1 ].func_arg_num )) {
256
256
/* There's no TMP specialization for FETCH_OBJ_W/FETCH_DIM_W. Avoid
257
257
* converting it and error at runtime in the FUNC_ARG variant. */
258
- if ((opline -> opcode == ZEND_FETCH_OBJ_FUNC_ARG || opline -> opcode == ZEND_FETCH_DIM_FUNC_ARG ) && opline -> op1_type == IS_TMP_VAR ) {
258
+ if ((opline -> opcode == ZEND_FETCH_OBJ_FUNC_ARG || opline -> opcode == ZEND_FETCH_DIM_FUNC_ARG )
259
+ && (opline -> op1_type == IS_TMP_VAR || call_stack [call - 1 ].last_check_func_arg_opline == NULL )) {
259
260
/* Don't remove the associated CHECK_FUNC_ARG opcode. */
260
- call_stack [call - 1 ].check_func_arg_opline = NULL ;
261
+ call_stack [call - 1 ].last_check_func_arg_opline = NULL ;
261
262
break ;
262
263
}
263
264
if (opline -> opcode != ZEND_FETCH_STATIC_PROP_FUNC_ARG ) {
@@ -280,7 +281,7 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
280
281
opline -> opcode = ZEND_FETCH_STATIC_PROP_R ;
281
282
}
282
283
}
283
- MAKE_NOP (call_stack [call - 1 ].check_func_arg_opline );
284
+ MAKE_NOP (call_stack [call - 1 ].last_check_func_arg_opline );
284
285
}
285
286
break ;
286
287
case ZEND_SEND_VAL_EX :
@@ -307,11 +308,20 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
307
308
308
309
if (has_known_send_mode (& call_stack [call - 1 ], opline -> op2 .num )) {
309
310
call_stack [call - 1 ].func_arg_num = opline -> op2 .num ;
310
- call_stack [call - 1 ].check_func_arg_opline = opline ;
311
+ call_stack [call - 1 ].last_check_func_arg_opline = opline ;
311
312
}
312
313
break ;
313
- case ZEND_SEND_VAR_EX :
314
314
case ZEND_SEND_FUNC_ARG :
315
+ /* Don't transform SEND_FUNC_ARG if any FETCH opcodes weren't transformed. */
316
+ if (call_stack [call - 1 ].last_check_func_arg_opline == NULL ) {
317
+ if (opline -> op2_type == IS_CONST ) {
318
+ call_stack [call - 1 ].try_inline = 0 ;
319
+ }
320
+ break ;
321
+ }
322
+ call_stack [call - 1 ].last_check_func_arg_opline = NULL ;
323
+ ZEND_FALLTHROUGH ;
324
+ case ZEND_SEND_VAR_EX :
315
325
if (opline -> op2_type == IS_CONST ) {
316
326
call_stack [call - 1 ].try_inline = 0 ;
317
327
break ;
0 commit comments