Skip to content

Commit 9793cde

Browse files
committed
Improve jumps
1 parent 199ba86 commit 9793cde

File tree

1 file changed

+59
-14
lines changed

1 file changed

+59
-14
lines changed

Zend/zend_compile.c

Lines changed: 59 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6659,9 +6659,10 @@ static zend_type zend_compile_single_typename(zend_ast *ast);
66596659
static void zend_pm_context_init(zend_pm_context *context)
66606660
{
66616661
zend_stack_init(&context->labels, sizeof(uint32_t));
6662-
/* Avoid offset 0. */
6662+
/* Avoid offsets 0 and 1. */
66636663
uint32_t dummy = 0;
66646664
zend_stack_push(&context->labels, &dummy);
6665+
zend_stack_push(&context->labels, &dummy);
66656666

66666667
zend_stack_init(&context->bindings, sizeof(zend_pm_binding));
66676668
}
@@ -6700,6 +6701,7 @@ static void zend_pm_labels_replace(zend_pm_context *context, uint32_t start_opnu
67006701
}
67016702
break;
67026703
case ZEND_JMPZ_EX:
6704+
case ZEND_JMPNZ_EX:
67036705
if (opline->op2.opline_num >= label_lower_bound) {
67046706
opline->op2.opline_num = labels[-opline->op2.opline_num];
67056707
}
@@ -6716,6 +6718,42 @@ static void zend_pm_emit_jmpz_ex(znode *result, uint32_t opnum_target)
67166718
SET_NODE(opline->result, result);
67176719
}
67186720

6721+
static void zend_pm_emit_jmpnz_ex(znode *result, uint32_t opnum_target)
6722+
{
6723+
zend_op *opline = zend_emit_op(NULL, ZEND_JMPNZ_EX, result, NULL);
6724+
opline->op2.opline_num = opnum_target;
6725+
SET_NODE(opline->result, result);
6726+
}
6727+
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+
6733+
#if ZEND_DEBUG
6734+
uint32_t *labels = zend_stack_base(&context->labels);
6735+
uint32_t label_lower_bound = -zend_stack_count(&context->labels);
6736+
#endif
6737+
6738+
switch (opline->opcode) {
6739+
case ZEND_JMP:
6740+
#if ZEND_DEBUG
6741+
ZEND_ASSERT(opline->op1.opline_num >= label_lower_bound && labels[-opline->op1.opline_num] == op_array->last);
6742+
#endif
6743+
MAKE_NOP(opline);
6744+
op_array->last--;
6745+
break;
6746+
case ZEND_JMPZ_EX:
6747+
case ZEND_JMPNZ_EX:
6748+
#if ZEND_DEBUG
6749+
ZEND_ASSERT(opline->op2.opline_num >= label_lower_bound && labels[-opline->op2.opline_num] == op_array->last);
6750+
#endif
6751+
MAKE_NOP(opline);
6752+
op_array->last--;
6753+
break;
6754+
}
6755+
}
6756+
67196757
static void zend_pm_compile_expr_like(zend_ast *ast, znode *result, znode *expr_node, bool consume_expr, uint32_t false_opnum)
67206758
{
67216759
znode value;
@@ -6754,8 +6792,8 @@ static void zend_pm_compile_or(zend_ast *ast, znode *result, znode *expr_node, b
67546792
zend_pm_label_set_next(context, next_label);
67556793
}
67566794
next_label = zend_pm_label_create(context);
6757-
zend_compile_pattern(ast_list->child[i], result, expr_node, false, next_label, context);
6758-
zend_emit_jump(true_label);
6795+
zend_compile_pattern(ast_list->child[i], result, expr_node, false, (uint32_t)-1, context);
6796+
zend_pm_emit_jmpnz_ex(result, true_label);
67596797
}
67606798
zend_pm_label_set_next(context, next_label);
67616799

@@ -6933,6 +6971,11 @@ static void zend_pm_compile_container(
69336971

69346972
static void zend_compile_pattern(zend_ast *ast, znode *result, znode *expr_node, bool consume_expr, uint32_t false_opnum, zend_pm_context *context)
69356973
{
6974+
bool create_label = false_opnum == (uint32_t)-1;
6975+
if (create_label) {
6976+
false_opnum = zend_pm_label_create(context);
6977+
}
6978+
69366979
switch (ast->kind) {
69376980
case ZEND_AST_EXPR_LIKE_PATTERN:
69386981
zend_pm_compile_expr_like(ast, result, expr_node, consume_expr, false_opnum);
@@ -6957,6 +7000,11 @@ static void zend_compile_pattern(zend_ast *ast, znode *result, znode *expr_node,
69577000
break;
69587001
EMPTY_SWITCH_DEFAULT_CASE();
69597002
}
7003+
7004+
if (create_label) {
7005+
zend_pm_label_set_next(context, false_opnum);
7006+
zend_pm_kill_last_op_if_jmp(context);
7007+
}
69607008
}
69617009

69627010
static void zend_pm_count_bindings(zend_ast **ast_ptr, void *context)
@@ -7005,12 +7053,14 @@ static void zend_emit_is(znode *result, znode *expr_node, bool consume_expr, zen
70057053
}
70067054

70077055
uint32_t start_opnum = get_next_op_number();
7008-
uint32_t false_label = zend_pm_label_create(&context);
7056+
uint32_t false_label = context.num_bindings ? zend_pm_label_create(&context) : -1;
70097057
zend_compile_pattern(pattern_ast, result, &expr_copy_node, consume_expr, false_label, &context);
70107058

70117059
if (context.num_bindings) {
7012-
zend_pm_binding *binding = zend_stack_base(&context.bindings);
7013-
zend_pm_binding *binding_end = zend_stack_top(&context.bindings);
7060+
zend_pm_binding *binding, *binding_end;
7061+
7062+
binding = zend_stack_base(&context.bindings);
7063+
binding_end = zend_stack_top(&context.bindings);
70147064
zend_op *binding_init_op = &CG(active_op_array)->opcodes[first_binding_init_opnum];
70157065
while (binding <= binding_end) {
70167066
znode var_node;
@@ -7030,22 +7080,17 @@ static void zend_emit_is(znode *result, znode *expr_node, bool consume_expr, zen
70307080
binding++;
70317081
binding_init_op++;
70327082
}
7033-
}
7034-
7035-
if (context.num_bindings) {
70367083
uint32_t jmp_end = zend_emit_jump(0);
7037-
zend_pm_label_set_next(&context, false_label);
70387084

7039-
zend_pm_binding *binding = zend_stack_base(&context.bindings);
7040-
zend_pm_binding *binding_end = zend_stack_top(&context.bindings);
7085+
zend_pm_label_set_next(&context, false_label);
7086+
binding = zend_stack_base(&context.bindings);
7087+
binding_end = zend_stack_top(&context.bindings);
70417088
while (binding <= binding_end) {
70427089
zend_emit_op(NULL, ZEND_FREE, &binding->value, NULL);
70437090
binding++;
70447091
}
70457092

70467093
zend_update_jump_target_to_next(jmp_end);
7047-
} else {
7048-
zend_pm_label_set_next(&context, false_label);
70497094
}
70507095

70517096
zend_pm_labels_replace(&context, start_opnum);

0 commit comments

Comments
 (0)