Skip to content

Commit b66320d

Browse files
committed
Attempt to fix zend_jit_constructor() for function JIT
NEW no longer emits VAR but TMP. This can elide a QM_ASSIGN and thus breaks an assumption that every NEW block (which is terminated by ZEND_CFG_STACKLESS) is followed by a single-predecessor block.
1 parent 30e866d commit b66320d

File tree

2 files changed

+17
-8
lines changed

2 files changed

+17
-8
lines changed

ext/opcache/jit/zend_jit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2845,7 +2845,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
28452845
const zend_op *next_opline = opline + 1;
28462846

28472847
ZEND_ASSERT(b + 1 == ssa->cfg.blocks[b].successors[0]);
2848-
zend_jit_constructor(&ctx, next_opline, op_array, ssa, call_level, b + 1);
2848+
zend_jit_constructor(&ctx, next_opline, op_array, ssa, call_level, b, b + 1);
28492849
}
28502850

28512851
/* We skip over the DO_FCALL, so decrement call_level ourselves. */

ext/opcache/jit/zend_jit_ir.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10728,7 +10728,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
1072810728
return 1;
1072910729
}
1073010730

10731-
static int zend_jit_constructor(zend_jit_ctx *jit, const zend_op *opline, const zend_op_array *op_array, zend_ssa *ssa, int call_level, int next_block)
10731+
static int zend_jit_constructor(zend_jit_ctx *jit, const zend_op *opline, const zend_op_array *op_array, zend_ssa *ssa, int call_level, int b, int next_block)
1073210732
{
1073310733
ir_ref if_skip_constructor = jit_IF_ex(jit, jit_CMP_IP(jit, IR_NE, opline), next_block);
1073410734

@@ -10744,18 +10744,27 @@ static int zend_jit_constructor(zend_jit_ctx *jit, const zend_op *opline, const
1074410744
}
1074510745
}
1074610746

10747+
/* Find the predecessor index of b in next_block. */
10748+
zend_basic_block *bb_next = &ssa->cfg.blocks[next_block];
10749+
int pred_i = -1;
10750+
for (pred_i = 0; pred_i < bb_next->predecessors_count; pred_i++) {
10751+
if (b == ssa->cfg.predecessors[bb_next->predecessor_offset + pred_i]) {
10752+
break;
10753+
}
10754+
}
10755+
ZEND_ASSERT(pred_i != -1);
10756+
1074710757
/* override predecessors of the next block */
10748-
ZEND_ASSERT(jit->ssa->cfg.blocks[next_block].predecessors_count == 1);
1074910758
if (!jit->ctx.control) {
10750-
ZEND_ASSERT(jit->bb_edges[jit->bb_predecessors[next_block]]);
10759+
ZEND_ASSERT(jit->bb_edges[jit->bb_predecessors[next_block] + pred_i]);
1075110760
ir_IF_TRUE(if_skip_constructor);
10752-
ir_MERGE_2(jit->bb_edges[jit->bb_predecessors[next_block]], ir_END());
10753-
jit->bb_edges[jit->bb_predecessors[next_block]] = ir_END();
10761+
ir_MERGE_2(jit->bb_edges[jit->bb_predecessors[next_block] + pred_i], ir_END());
10762+
jit->bb_edges[jit->bb_predecessors[next_block] + pred_i] = ir_END();
1075410763
} else {
10755-
ZEND_ASSERT(!jit->bb_edges[jit->bb_predecessors[next_block]]);
10764+
ZEND_ASSERT(!jit->bb_edges[jit->bb_predecessors[next_block] + pred_i]);
1075610765
/* merge current control path with the true branch of constructor skip condition */
1075710766
ir_MERGE_WITH_EMPTY_TRUE(if_skip_constructor);
10758-
jit->bb_edges[jit->bb_predecessors[next_block]] = ir_END();
10767+
jit->bb_edges[jit->bb_predecessors[next_block] + pred_i] = ir_END();
1075910768

1076010769
jit->b = -1;
1076110770
}

0 commit comments

Comments
 (0)