Skip to content

Commit fbb9879

Browse files
committed
Port to new live-range computation mechanism
1 parent 142b09e commit fbb9879

File tree

2 files changed

+55
-35
lines changed

2 files changed

+55
-35
lines changed

Zend/zend_compile.c

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7336,22 +7336,10 @@ void zend_compile_assign_coalesce(znode *result, zend_ast *ast) /* {{{ */
73367336
/* Free DUPed expressions if there are any */
73377337
if (need_frees) {
73387338
uint32_t jump_opnum = zend_emit_jump(0);
7339-
uint32_t start_opnum = get_next_op_number();
73407339
zend_update_jump_target_to_next(coalesce_opnum);
73417340
ZEND_HASH_FOREACH_PTR(CG(memoized_exprs), node) {
73427341
if (node->op_type == IS_TMP_VAR || node->op_type == IS_VAR) {
7343-
/* Add additional live range for this variable, from the start of the current
7344-
* block to the FREE opcode. */
7345-
uint32_t free_opnum = get_next_op_number();
7346-
if (start_opnum != free_opnum) {
7347-
uint32_t live_range = zend_start_live_range(start_opnum);
7348-
zend_end_live_range(live_range, free_opnum, ZEND_LIVE_TMPVAR, node->u.op.var);
7349-
}
7350-
7351-
/* We don't use emit_op here because we're manually manging live ranges. */
7352-
opline = get_next_op();
7353-
opline->opcode = ZEND_FREE;
7354-
SET_NODE(opline->op1, node);
7342+
zend_emit_op(NULL, ZEND_FREE, node, NULL);
73557343
}
73567344
} ZEND_HASH_FOREACH_END();
73577345
zend_update_jump_target_to_next(jump_opnum);

Zend/zend_opcode.c

Lines changed: 54 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -547,12 +547,37 @@ static uint32_t zend_get_brk_cont_target(const zend_op_array *op_array, const ze
547547
return opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont;
548548
}
549549

550+
static void emit_live_range_raw(
551+
zend_op_array *op_array, uint32_t var_num, uint32_t kind, uint32_t start, uint32_t end,
552+
zend_op *orig_def_opline, zend_needs_live_range_cb needs_live_range) {
553+
zend_live_range *range;
554+
if (start == end) {
555+
/* Trivial live-range, no need to store it. */
556+
return;
557+
}
558+
559+
/* Check hook to determine whether a live range is necessary, e.g. based on type info. */
560+
if (needs_live_range && !needs_live_range(op_array, orig_def_opline)) {
561+
return;
562+
}
563+
564+
op_array->last_live_range++;
565+
op_array->live_range = erealloc(op_array->live_range,
566+
sizeof(zend_live_range) * op_array->last_live_range);
567+
568+
ZEND_ASSERT(start < end);
569+
range = &op_array->live_range[op_array->last_live_range - 1];
570+
range->var = (uint32_t) (intptr_t) ZEND_CALL_VAR_NUM(NULL, op_array->last_var + var_num);
571+
range->var |= kind;
572+
range->start = start;
573+
range->end = end;
574+
}
575+
550576
static void emit_live_range(
551577
zend_op_array *op_array, uint32_t var_num, uint32_t start, uint32_t end,
552578
zend_needs_live_range_cb needs_live_range) {
553579
zend_op *def_opline = &op_array->opcodes[start], *orig_def_opline = def_opline;
554580
zend_op *use_opline = &op_array->opcodes[end];
555-
zend_live_range *range;
556581
uint32_t kind = ZEND_LIVE_TMPVAR;
557582

558583
switch (def_opline->opcode) {
@@ -587,7 +612,8 @@ static void emit_live_range(
587612
break;
588613
/* Objects created via ZEND_NEW are only fully initialized
589614
* after the DO_FCALL (constructor call). */
590-
case ZEND_NEW: {
615+
case ZEND_NEW:
616+
{
591617
int level = 0;
592618
while (def_opline + 1 < use_opline) {
593619
def_opline++;
@@ -618,29 +644,35 @@ static void emit_live_range(
618644
}
619645
break;
620646
}
647+
case ZEND_COPY_TMP:
648+
{
649+
/* COPY_TMP has a split live-range: One from the definition until the use in
650+
* "null" branch, and another from the start of the "non-null" branch to the
651+
* FREE opcode. */
652+
zend_op *block_start_op = use_opline;
653+
while ((block_start_op-1)->opcode == ZEND_FREE) {
654+
block_start_op--;
655+
}
656+
start = block_start_op - op_array->opcodes;
657+
emit_live_range_raw(
658+
op_array, var_num, kind, start, end, orig_def_opline, needs_live_range);
659+
660+
do {
661+
use_opline--;
662+
} while (
663+
(use_opline->op1_type & (IS_TMP_VAR|IS_VAR) && use_opline->op1.var == var_num) ||
664+
(use_opline->op2_type & (IS_TMP_VAR|IS_VAR) && use_opline->op2.var == var_num)
665+
);
666+
start = def_opline + 1 - op_array->opcodes;
667+
end = use_opline - op_array->opcodes;
668+
emit_live_range_raw(
669+
op_array, var_num, kind, start, end, orig_def_opline, needs_live_range);
670+
return;
671+
}
621672
}
622673

623674
start = def_opline + 1 - op_array->opcodes;
624-
if (start == end) {
625-
/* Trivial live-range, no need to store it. */
626-
return;
627-
}
628-
629-
/* Check hook to determine whether a live range is necessary, e.g. based on type info. */
630-
if (needs_live_range && !needs_live_range(op_array, orig_def_opline)) {
631-
return;
632-
}
633-
634-
op_array->last_live_range++;
635-
op_array->live_range = erealloc(op_array->live_range,
636-
sizeof(zend_live_range) * op_array->last_live_range);
637-
638-
ZEND_ASSERT(start < end);
639-
range = &op_array->live_range[op_array->last_live_range - 1];
640-
range->var = (uint32_t) (intptr_t) ZEND_CALL_VAR_NUM(NULL, op_array->last_var + var_num);
641-
range->var |= kind;
642-
range->start = start;
643-
range->end = end;
675+
emit_live_range_raw(op_array, var_num, kind, start, end, orig_def_opline, needs_live_range);
644676
}
645677

646678
static zend_bool is_fake_def(zend_op *opline) {

0 commit comments

Comments
 (0)