diff --git a/Zend/tests/bug80046.phpt b/Zend/tests/bug80046.phpt new file mode 100644 index 00000000000..87a493c2030 --- /dev/null +++ b/Zend/tests/bug80046.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #80046: FREE for SWITCH_STRING optimized away +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECT-- +Default diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index 68555115f81..7b9fb2afca7 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -967,7 +967,15 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op if (b->len == 0) { continue; } - if (b->flags & ZEND_BB_REACHABLE) { + if (b->flags & (ZEND_BB_REACHABLE|ZEND_BB_UNREACHABLE_FREE)) { + if (b->flags & ZEND_BB_UNREACHABLE_FREE) { + /* Only keep the FREE for the loop var */ + ZEND_ASSERT(op_array->opcodes[b->start].opcode == ZEND_FREE + || op_array->opcodes[b->start].opcode == ZEND_FE_FREE); + len += b->len = 1; + continue; + } + opline = op_array->opcodes + b->start + b->len - 1; if (opline->opcode == ZEND_JMP) { zend_basic_block *next = b + 1; @@ -1005,7 +1013,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op /* Copy code of reachable blocks into a single buffer */ for (b = blocks; b < end; b++) { - if (b->flags & ZEND_BB_REACHABLE) { + if (b->flags & (ZEND_BB_REACHABLE|ZEND_BB_UNREACHABLE_FREE)) { memcpy(opline, op_array->opcodes + b->start, b->len * sizeof(zend_op)); b->start = opline - new_opcodes; opline += b->len; @@ -1131,7 +1139,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op /* rebuild map (just for printing) */ memset(cfg->map, -1, sizeof(int) * op_array->last); for (n = 0; n < cfg->blocks_count; n++) { - if (cfg->blocks[n].flags & ZEND_BB_REACHABLE) { + if (cfg->blocks[n].flags & (ZEND_BB_REACHABLE|ZEND_BB_UNREACHABLE_FREE)) { cfg->map[cfg->blocks[n].start] = n; } } diff --git a/ext/opcache/Optimizer/zend_cfg.c b/ext/opcache/Optimizer/zend_cfg.c index b8088924f97..127fca5dca8 100644 --- a/ext/opcache/Optimizer/zend_cfg.c +++ b/ext/opcache/Optimizer/zend_cfg.c @@ -593,9 +593,8 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b } /* Build CFG, Step 4, Mark Reachable Basic Blocks */ - zend_mark_reachable_blocks(op_array, cfg, 0); - cfg->flags |= flags; + zend_mark_reachable_blocks(op_array, cfg, 0); return SUCCESS; }