Skip to content

Commit cf93621

Browse files
committed
Merge branch 'PHP-7.4'
* PHP-7.4: Fix handling of non-final loop var free in sccp
2 parents 1695d3e + 2d03b63 commit cf93621

File tree

5 files changed

+26
-7
lines changed

5 files changed

+26
-7
lines changed

ext/opcache/Optimizer/scdf.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,7 @@ static zend_bool kept_alive_by_loop_var_free(scdf_ctx *scdf, uint32_t block_idx)
195195
}
196196
for (i = block->start; i < block->start + block->len; i++) {
197197
zend_op *opline = &op_array->opcodes[i];
198-
if (opline->opcode == ZEND_FE_FREE ||
199-
(opline->opcode == ZEND_FREE && opline->extended_value == ZEND_FREE_SWITCH)) {
198+
if (zend_optimizer_is_loop_var_free(opline)) {
200199
int ssa_var = scdf->ssa->ops[i].op1_use;
201200
if (ssa_var >= 0) {
202201
int op_num = scdf->ssa->vars[ssa_var].definition;

ext/opcache/Optimizer/zend_cfg.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,7 @@ static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg *
208208

209209
for (j = b->start; j < b->start + b->len; j++) {
210210
zend_op *opline = &op_array->opcodes[j];
211-
if (opline->opcode == ZEND_FE_FREE ||
212-
(opline->opcode == ZEND_FREE && opline->extended_value == ZEND_FREE_SWITCH)
213-
) {
211+
if (zend_optimizer_is_loop_var_free(opline)) {
214212
zend_op *def_opline = zend_optimizer_get_loop_var_def(op_array, opline);
215213
if (def_opline) {
216214
uint32_t def_block = block_map[def_opline - op_array->opcodes];

ext/opcache/Optimizer/zend_optimizer.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -904,8 +904,7 @@ uint32_t zend_optimizer_classify_function(zend_string *name, uint32_t num_args)
904904

905905
zend_op *zend_optimizer_get_loop_var_def(const zend_op_array *op_array, zend_op *free_opline) {
906906
uint32_t var = free_opline->op1.var;
907-
ZEND_ASSERT(free_opline->opcode == ZEND_FE_FREE ||
908-
(free_opline->opcode == ZEND_FREE && free_opline->extended_value == ZEND_FREE_SWITCH));
907+
ZEND_ASSERT(zend_optimizer_is_loop_var_free(free_opline));
909908

910909
while (--free_opline >= op_array->opcodes) {
911910
if ((free_opline->result_type & (IS_TMP_VAR|IS_VAR)) && free_opline->result.var == var) {

ext/opcache/Optimizer/zend_optimizer_internal.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ typedef struct _zend_optimizer_ctx {
7171
target = src; \
7272
} while (0)
7373

74+
static inline zend_bool zend_optimizer_is_loop_var_free(const zend_op *opline) {
75+
return (opline->opcode == ZEND_FE_FREE && opline->extended_value != ZEND_FREE_ON_RETURN)
76+
|| (opline->opcode == ZEND_FREE && opline->extended_value == ZEND_FREE_SWITCH);
77+
}
78+
7479
int zend_optimizer_add_literal(zend_op_array *op_array, zval *zv);
7580
int zend_optimizer_get_persistent_constant(zend_string *name, zval *result, int copy);
7681
void zend_optimizer_collect_constant(zend_optimizer_ctx *ctx, zval *name, zval* value);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Check that SCCP correctly handles non-terminating frees of loop variables
3+
--FILE--
4+
<?php
5+
function test() {
6+
$arr = [];
7+
foreach ($arr as $item) {
8+
if (!empty($result)) {
9+
return $result;
10+
}
11+
}
12+
return 2;
13+
}
14+
15+
var_dump(test());
16+
?>
17+
--EXPECT--
18+
int(2)

0 commit comments

Comments
 (0)