Skip to content

Commit c6e9505

Browse files
committed
Adjust branching
Instead of killing the last jump, avoid emitting it in the first place.
1 parent 8a4a6f0 commit c6e9505

File tree

1 file changed

+42
-67
lines changed

1 file changed

+42
-67
lines changed

Zend/zend_compile.c

Lines changed: 42 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -6641,6 +6641,10 @@ static void zend_compile_pipe(znode *result, zend_ast *ast)
66416641
zend_compile_expr(result, fcall_ast);
66426642
}
66436643

6644+
/* Exit in a joined branch for true/false, leaving the evaluated result in the
6645+
* given temporary. */
6646+
#define ZEND_PM_LABEL_EMPTY ((uint32_t)-1)
6647+
66446648
typedef struct {
66456649
bool inside_or_pattern;
66466650
zend_stack labels;
@@ -6725,51 +6729,16 @@ static void zend_pm_emit_jmpnz_ex(znode *result, uint32_t opnum_target)
67256729
SET_NODE(opline->result, result);
67266730
}
67276731

6728-
static void zend_pm_kill_last_op_if_jmp(zend_pm_context *context)
6729-
{
6730-
zend_op_array *op_array = CG(active_op_array);
6731-
zend_op *opline = &op_array->opcodes[op_array->last - 1];
6732-
uint32_t *labels = zend_stack_base(&context->labels);
6733-
uint32_t label_lower_bound = -zend_stack_count(&context->labels);
6734-
6735-
uint32_t label_idx;
6736-
switch (opline->opcode) {
6737-
case ZEND_JMP:
6738-
label_idx = opline->op1.opline_num;
6739-
break;
6740-
case ZEND_JMPZ_EX:
6741-
case ZEND_JMPNZ_EX:
6742-
label_idx = opline->op2.opline_num;
6743-
break;
6744-
default:
6745-
return;
6746-
}
6747-
6748-
ZEND_ASSERT(label_idx >= label_lower_bound);
6749-
uint32_t label_target = labels[-label_idx];
6750-
ZEND_ASSERT(label_target == op_array->last);
6751-
6752-
MAKE_NOP(opline);
6753-
op_array->last--;
6754-
6755-
uint32_t *label = labels;
6756-
uint32_t *label_end = zend_stack_top(&context->labels);
6757-
while (label <= label_end) {
6758-
if (*label == label_target) {
6759-
(*label)--;
6760-
}
6761-
label++;
6762-
}
6763-
}
6764-
67656732
static void zend_pm_compile_expr_like(zend_ast *ast, znode *result, znode *expr_node, bool consume_expr, uint32_t false_opnum)
67666733
{
67676734
znode value;
67686735
zend_compile_expr(&value, ast->child[0]);
67696736
zend_op *opline = zend_emit_op_tmp(NULL, expr_node->op_type == IS_CV || consume_expr ? ZEND_IS_IDENTICAL : ZEND_CASE_STRICT, expr_node, &value);
67706737
SET_NODE(opline->result, result);
67716738

6772-
zend_pm_emit_jmpz_ex(result, false_opnum);
6739+
if (false_opnum != ZEND_PM_LABEL_EMPTY) {
6740+
zend_pm_emit_jmpz_ex(result, false_opnum);
6741+
}
67736742
}
67746743

67756744
static void zend_pm_verify_parenthesized_compound_pattern(zend_ast *ast, zend_ast_kind kind)
@@ -6791,27 +6760,31 @@ static void zend_pm_compile_or(zend_ast *ast, znode *result, znode *expr_node, b
67916760
context->inside_or_pattern = true;
67926761

67936762
zend_ast_list *ast_list = zend_ast_get_list(ast);
6794-
uint32_t true_label = zend_pm_label_create(context);
6795-
uint32_t false_label = consume_expr ? zend_pm_label_create(context) : false_opnum;
6763+
uint32_t end_label = zend_pm_label_create(context);
6764+
bool create_false_label = consume_expr || false_opnum == ZEND_PM_LABEL_EMPTY;
6765+
uint32_t false_label = create_false_label ? end_label : false_opnum;
67966766
uint32_t next_label = 0;
67976767

67986768
for (uint32_t i = 0; i < ast_list->children - 1; i++) {
67996769
if (next_label) {
68006770
zend_pm_label_set_next(context, next_label);
68016771
}
68026772
next_label = zend_pm_label_create(context);
6803-
zend_compile_pattern(ast_list->child[i], result, expr_node, false, (uint32_t)-1, context);
6804-
zend_pm_emit_jmpnz_ex(result, true_label);
6773+
zend_compile_pattern(ast_list->child[i], result, expr_node, false, ZEND_PM_LABEL_EMPTY, context);
6774+
zend_pm_emit_jmpnz_ex(result, end_label);
68056775
}
68066776
zend_pm_label_set_next(context, next_label);
68076777

68086778
zend_compile_pattern(ast_list->child[ast_list->children - 1], result, expr_node, false, false_label, context);
68096779

6810-
zend_pm_label_set_next(context, true_label);
6811-
if (consume_expr) {
6812-
zend_pm_label_set_next(context, false_label);
6813-
zend_emit_op(NULL, ZEND_FREE, expr_node, NULL);
6814-
zend_pm_emit_jmpz_ex(result, false_opnum);
6780+
zend_pm_label_set_next(context, end_label);
6781+
if (create_false_label) {
6782+
if (consume_expr) {
6783+
zend_emit_op(NULL, ZEND_FREE, expr_node, NULL);
6784+
}
6785+
if (false_opnum != ZEND_PM_LABEL_EMPTY) {
6786+
zend_pm_emit_jmpz_ex(result, false_opnum);
6787+
}
68156788
}
68166789

68176790
context->inside_or_pattern = false;
@@ -6822,16 +6795,21 @@ static void zend_pm_compile_and(zend_ast *ast, znode *result, znode *expr_node,
68226795
zend_pm_verify_parenthesized_compound_pattern(ast, ZEND_AST_OR_PATTERN);
68236796

68246797
zend_ast_list *ast_list = zend_ast_get_list(ast);
6825-
uint32_t false_label = consume_expr ? zend_pm_label_create(context) : false_opnum;
6798+
bool create_false_label = consume_expr || false_opnum == ZEND_PM_LABEL_EMPTY;
6799+
uint32_t false_label = create_false_label ? zend_pm_label_create(context) : false_opnum;
68266800

68276801
for (uint32_t i = 0; i < ast_list->children; i++) {
68286802
zend_compile_pattern(ast_list->child[i], result, expr_node, false, false_label, context);
68296803
}
68306804

6831-
if (consume_expr) {
6805+
if (create_false_label) {
68326806
zend_pm_label_set_next(context, false_label);
6833-
zend_emit_op(NULL, ZEND_FREE, expr_node, NULL);
6834-
zend_pm_emit_jmpz_ex(result, false_opnum);
6807+
if (consume_expr) {
6808+
zend_emit_op(NULL, ZEND_FREE, expr_node, NULL);
6809+
}
6810+
if (false_opnum != ZEND_PM_LABEL_EMPTY) {
6811+
zend_pm_emit_jmpz_ex(result, false_opnum);
6812+
}
68356813
}
68366814
}
68376815

@@ -6858,7 +6836,9 @@ static void zend_pm_compile_type(zend_ast *ast, znode *result, znode *expr_node,
68586836
if (consume_expr) {
68596837
zend_emit_op(NULL, ZEND_FREE, expr_node, NULL);
68606838
}
6861-
zend_pm_emit_jmpz_ex(result, false_opnum);
6839+
if (false_opnum != ZEND_PM_LABEL_EMPTY) {
6840+
zend_pm_emit_jmpz_ex(result, false_opnum);
6841+
}
68626842
}
68636843

68646844
static void zend_pm_copy_tmp(znode *dest, znode *src, bool consume)
@@ -6910,7 +6890,8 @@ static void zend_pm_compile_container(
69106890
) {
69116891
znode expr_copy_node;
69126892

6913-
uint32_t false_label = consume_expr ? zend_pm_label_create(context) : false_opnum;
6893+
bool create_false_label = consume_expr || false_opnum == ZEND_PM_LABEL_EMPTY;
6894+
uint32_t false_label = create_false_label ? zend_pm_label_create(context) : false_opnum;
69146895
zend_ast_list *element_list = zend_ast_get_list(ast->child[0]);
69156896

69166897
/* Make sure the value is actually of the right type. */
@@ -6966,10 +6947,14 @@ static void zend_pm_compile_container(
69666947
zend_compile_pattern(element_value_ast, result, &element_value_node, true, false_label, context);
69676948
}
69686949

6969-
if (consume_expr) {
6950+
if (create_false_label) {
69706951
zend_pm_label_set_next(context, false_label);
6971-
zend_emit_op(NULL, ZEND_FREE, expr_node, NULL);
6972-
zend_pm_emit_jmpz_ex(result, false_opnum);
6952+
if (consume_expr) {
6953+
zend_emit_op(NULL, ZEND_FREE, expr_node, NULL);
6954+
}
6955+
if (false_opnum != ZEND_PM_LABEL_EMPTY) {
6956+
zend_pm_emit_jmpz_ex(result, false_opnum);
6957+
}
69736958
}
69746959

69756960
if (has_implicit && has_explicit) {
@@ -6979,11 +6964,6 @@ static void zend_pm_compile_container(
69796964

69806965
static void zend_compile_pattern(zend_ast *ast, znode *result, znode *expr_node, bool consume_expr, uint32_t false_opnum, zend_pm_context *context)
69816966
{
6982-
bool create_label = false_opnum == (uint32_t)-1;
6983-
if (create_label) {
6984-
false_opnum = zend_pm_label_create(context);
6985-
}
6986-
69876967
switch (ast->kind) {
69886968
case ZEND_AST_EXPR_LIKE_PATTERN:
69896969
zend_pm_compile_expr_like(ast, result, expr_node, consume_expr, false_opnum);
@@ -7008,11 +6988,6 @@ static void zend_compile_pattern(zend_ast *ast, znode *result, znode *expr_node,
70086988
break;
70096989
EMPTY_SWITCH_DEFAULT_CASE();
70106990
}
7011-
7012-
if (create_label) {
7013-
zend_pm_label_set_next(context, false_opnum);
7014-
zend_pm_kill_last_op_if_jmp(context);
7015-
}
70166991
}
70176992

70186993
static void zend_pm_count_bindings(zend_ast **ast_ptr, void *context)
@@ -7061,7 +7036,7 @@ static void zend_emit_is(znode *result, znode *expr_node, bool consume_expr, zen
70617036
}
70627037

70637038
uint32_t start_opnum = get_next_op_number();
7064-
uint32_t false_label = context.num_bindings ? zend_pm_label_create(&context) : -1;
7039+
uint32_t false_label = context.num_bindings ? zend_pm_label_create(&context) : ZEND_PM_LABEL_EMPTY;
70657040
zend_compile_pattern(pattern_ast, result, &expr_copy_node, consume_expr, false_label, &context);
70667041

70677042
if (context.num_bindings) {

0 commit comments

Comments
 (0)