mirror of
https://github.com/php/php-src.git
synced 2024-09-21 18:07:23 +00:00
Fixed bug #80046
We already protect against optimizing away loop frees in DFA pass, but not in block pass.
This commit is contained in:
parent
658ad4d046
commit
8516434a56
1
NEWS
1
NEWS
@ -19,6 +19,7 @@ PHP NEWS
|
|||||||
- OPcache:
|
- OPcache:
|
||||||
. Fixed bug #80002 (calc free space for new interned string is wrong).
|
. Fixed bug #80002 (calc free space for new interned string is wrong).
|
||||||
(t-matsuno)
|
(t-matsuno)
|
||||||
|
. Fixed bug #80046 (FREE for SWITCH_STRING optimized away). (Nikita)
|
||||||
|
|
||||||
- PDO:
|
- PDO:
|
||||||
. Fixed bug #80027 (Terrible performance using $query->fetch on queries with
|
. Fixed bug #80027 (Terrible performance using $query->fetch on queries with
|
||||||
|
22
Zend/tests/bug80046.phpt
Normal file
22
Zend/tests/bug80046.phpt
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
--TEST--
|
||||||
|
Bug #80046: FREE for SWITCH_STRING optimized away
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function test($foo) {
|
||||||
|
switch ($foo . 'Bar') {
|
||||||
|
case 'A':
|
||||||
|
throw new Exception('A');
|
||||||
|
default:
|
||||||
|
throw new Exception('Default');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
test('Foo');
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo $e->getMessage(), "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
Default
|
@ -921,7 +921,15 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op
|
|||||||
if (b->len == 0) {
|
if (b->len == 0) {
|
||||||
continue;
|
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;
|
opline = op_array->opcodes + b->start + b->len - 1;
|
||||||
if (opline->opcode == ZEND_JMP) {
|
if (opline->opcode == ZEND_JMP) {
|
||||||
zend_basic_block *next = b + 1;
|
zend_basic_block *next = b + 1;
|
||||||
@ -959,7 +967,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 */
|
/* Copy code of reachable blocks into a single buffer */
|
||||||
for (b = blocks; b < end; b++) {
|
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));
|
memcpy(opline, op_array->opcodes + b->start, b->len * sizeof(zend_op));
|
||||||
b->start = opline - new_opcodes;
|
b->start = opline - new_opcodes;
|
||||||
opline += b->len;
|
opline += b->len;
|
||||||
@ -1083,7 +1091,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op
|
|||||||
/* rebuild map (just for printing) */
|
/* rebuild map (just for printing) */
|
||||||
memset(cfg->map, -1, sizeof(int) * op_array->last);
|
memset(cfg->map, -1, sizeof(int) * op_array->last);
|
||||||
for (n = 0; n < cfg->blocks_count; n++) {
|
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;
|
cfg->map[cfg->blocks[n].start] = n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -575,9 +575,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 */
|
/* Build CFG, Step 4, Mark Reachable Basic Blocks */
|
||||||
zend_mark_reachable_blocks(op_array, cfg, 0);
|
|
||||||
|
|
||||||
cfg->flags |= flags;
|
cfg->flags |= flags;
|
||||||
|
zend_mark_reachable_blocks(op_array, cfg, 0);
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user