@@ -284,20 +284,41 @@ static void replace_tmp_by_const(zend_op_array *op_array,
284
284
if (ZEND_OP1_TYPE (opline ) == IS_TMP_VAR &&
285
285
ZEND_OP1 (opline ).var == var ) {
286
286
287
- update_op1_const (op_array , opline , val TSRMLS_CC );
288
- /* TMP_VAR my be used only once */
289
- break ;
287
+ /* In most cases IS_TMP_VAR operand may be used only once.
288
+ * The operands are usually destroyed by the opcode handler.
289
+ * ZEND_CASE is an exception, that keeps operand unchanged,
290
+ * and allows its reuse. The number of ZEND_CASE instructions
291
+ * usually terminated by ZEND_FREE that finally kills the value.
292
+ */
293
+ if (opline -> opcode == ZEND_CASE ) {
294
+ zval old_val ;
295
+ old_val = * val ;
296
+ zval_copy_ctor (val );
297
+ update_op1_const (op_array , opline , val TSRMLS_CC );
298
+ * val = old_val ;
299
+ } else if (opline -> opcode == ZEND_FREE ) {
300
+ MAKE_NOP (opline );
301
+ break ;
302
+ } else {
303
+ update_op1_const (op_array , opline , val TSRMLS_CC );
304
+ val = NULL ;
305
+ break ;
306
+ }
290
307
}
291
308
292
309
if (ZEND_OP2_TYPE (opline ) == IS_TMP_VAR &&
293
310
ZEND_OP2 (opline ).var == var ) {
294
311
295
312
update_op2_const (op_array , opline , val TSRMLS_CC );
296
- /* TMP_VAR my be used only once */
313
+ /* TMP_VAR may be used only once */
314
+ val = NULL ;
297
315
break ;
298
316
}
299
317
opline ++ ;
300
318
}
319
+ if (val ) {
320
+ zval_dtor (val );
321
+ }
301
322
}
302
323
303
324
#include "Optimizer/nop_removal.c"
0 commit comments