@@ -367,20 +367,41 @@ static void replace_tmp_by_const(zend_op_array *op_array,
367
367
if (ZEND_OP1_TYPE (opline ) == IS_TMP_VAR &&
368
368
ZEND_OP1 (opline ).var == var ) {
369
369
370
- update_op1_const (op_array , opline , val TSRMLS_CC );
371
- /* TMP_VAR my be used only once */
372
- break ;
370
+ /* In most cases IS_TMP_VAR operand may be used only once.
371
+ * The operands are usually destroyed by the opcode handler.
372
+ * ZEND_CASE is an exception, that keeps operand unchanged,
373
+ * and allows its reuse. The number of ZEND_CASE instructions
374
+ * usually terminated by ZEND_FREE that finally kills the value.
375
+ */
376
+ if (opline -> opcode == ZEND_CASE ) {
377
+ zval old_val ;
378
+ old_val = * val ;
379
+ zval_copy_ctor (val );
380
+ update_op1_const (op_array , opline , val TSRMLS_CC );
381
+ * val = old_val ;
382
+ } else if (opline -> opcode == ZEND_FREE ) {
383
+ MAKE_NOP (opline );
384
+ break ;
385
+ } else {
386
+ update_op1_const (op_array , opline , val TSRMLS_CC );
387
+ val = NULL ;
388
+ break ;
389
+ }
373
390
}
374
391
375
392
if (ZEND_OP2_TYPE (opline ) == IS_TMP_VAR &&
376
393
ZEND_OP2 (opline ).var == var ) {
377
394
378
395
update_op2_const (op_array , opline , val TSRMLS_CC );
379
- /* TMP_VAR my be used only once */
396
+ /* TMP_VAR may be used only once */
397
+ val = NULL ;
380
398
break ;
381
399
}
382
400
opline ++ ;
383
401
}
402
+ if (val ) {
403
+ zval_dtor (val );
404
+ }
384
405
}
385
406
386
407
#include "Optimizer/nop_removal.c"
0 commit comments