From 62ebccc9380829bb7cfc0a0ae7eed5694c025a89 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 3 Jun 2024 22:42:44 +0200 Subject: [PATCH 1/3] Indent current code --- Zend/Optimizer/zend_cfg.c | 120 +++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 59 deletions(-) diff --git a/Zend/Optimizer/zend_cfg.c b/Zend/Optimizer/zend_cfg.c index 4d3d62137b9e3..f2b4874e4eefc 100644 --- a/Zend/Optimizer/zend_cfg.c +++ b/Zend/Optimizer/zend_cfg.c @@ -28,76 +28,78 @@ static void zend_mark_reachable(zend_op *opcodes, zend_cfg *cfg, zend_basic_bloc { zend_basic_block *blocks = cfg->blocks; - while (1) { - int i; - - b->flags |= ZEND_BB_REACHABLE; - if (b->successors_count == 0) { - b->flags |= ZEND_BB_EXIT; - return; - } + { + while (1) { + int i; + + b->flags |= ZEND_BB_REACHABLE; + if (b->successors_count == 0) { + b->flags |= ZEND_BB_EXIT; + return; + } - for (i = 0; i < b->successors_count; i++) { - zend_basic_block *succ = blocks + b->successors[i]; + for (i = 0; i < b->successors_count; i++) { + zend_basic_block* succ = blocks + b->successors[i]; - if (b->len != 0) { - uint8_t opcode = opcodes[b->start + b->len - 1].opcode; - if (opcode == ZEND_MATCH) { - succ->flags |= ZEND_BB_TARGET; - } else if (opcode == ZEND_SWITCH_LONG || opcode == ZEND_SWITCH_STRING) { - if (i == b->successors_count - 1) { - succ->flags |= ZEND_BB_FOLLOW | ZEND_BB_TARGET; - } else { - succ->flags |= ZEND_BB_TARGET; - } - } else if (b->successors_count == 1) { - if (opcode == ZEND_JMP) { + if (b->len != 0) { + uint8_t opcode = opcodes[b->start + b->len - 1].opcode; + if (opcode == ZEND_MATCH) { succ->flags |= ZEND_BB_TARGET; - } else { - succ->flags |= ZEND_BB_FOLLOW; - - if ((cfg->flags & ZEND_CFG_STACKLESS)) { - if (opcode == ZEND_INCLUDE_OR_EVAL || - opcode == ZEND_GENERATOR_CREATE || - opcode == ZEND_YIELD || - opcode == ZEND_YIELD_FROM || - opcode == ZEND_DO_FCALL || - opcode == ZEND_DO_UCALL || - opcode == ZEND_DO_FCALL_BY_NAME) { - succ->flags |= ZEND_BB_ENTRY; - } + } else if (opcode == ZEND_SWITCH_LONG || opcode == ZEND_SWITCH_STRING) { + if (i == b->successors_count - 1) { + succ->flags |= ZEND_BB_FOLLOW | ZEND_BB_TARGET; + } else { + succ->flags |= ZEND_BB_TARGET; } - if ((cfg->flags & ZEND_CFG_RECV_ENTRY)) { - if (opcode == ZEND_RECV || - opcode == ZEND_RECV_INIT) { - succ->flags |= ZEND_BB_RECV_ENTRY; + } else if (b->successors_count == 1) { + if (opcode == ZEND_JMP) { + succ->flags |= ZEND_BB_TARGET; + } else { + succ->flags |= ZEND_BB_FOLLOW; + + if ((cfg->flags & ZEND_CFG_STACKLESS)) { + if (opcode == ZEND_INCLUDE_OR_EVAL || + opcode == ZEND_GENERATOR_CREATE || + opcode == ZEND_YIELD || + opcode == ZEND_YIELD_FROM || + opcode == ZEND_DO_FCALL || + opcode == ZEND_DO_UCALL || + opcode == ZEND_DO_FCALL_BY_NAME) { + succ->flags |= ZEND_BB_ENTRY; + } + } + if ((cfg->flags & ZEND_CFG_RECV_ENTRY)) { + if (opcode == ZEND_RECV || + opcode == ZEND_RECV_INIT) { + succ->flags |= ZEND_BB_RECV_ENTRY; + } } } - } - } else { - ZEND_ASSERT(b->successors_count == 2); - if (i == 0) { - succ->flags |= ZEND_BB_TARGET; } else { - succ->flags |= ZEND_BB_FOLLOW; + ZEND_ASSERT(b->successors_count == 2); + if (i == 0) { + succ->flags |= ZEND_BB_TARGET; + } else { + succ->flags |= ZEND_BB_FOLLOW; + } } + } else { + succ->flags |= ZEND_BB_FOLLOW; } - } else { - succ->flags |= ZEND_BB_FOLLOW; - } - if (i == b->successors_count - 1) { - /* Tail call optimization */ - if (succ->flags & ZEND_BB_REACHABLE) { - return; - } + if (i == b->successors_count - 1) { + /* Tail call optimization */ + if (succ->flags & ZEND_BB_REACHABLE) { + return; + } - b = succ; - break; - } else { - /* Recursively check reachability */ - if (!(succ->flags & ZEND_BB_REACHABLE)) { - zend_mark_reachable(opcodes, cfg, succ); + b = succ; + break; + } else { + /* Recursively check reachability */ + if (!(succ->flags & ZEND_BB_REACHABLE)) { + zend_mark_reachable(opcodes, cfg, succ); + } } } } From d2b79af306cc5b3924971fe1b236cbe153d347b7 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 3 Jun 2024 23:02:55 +0200 Subject: [PATCH 2/3] Change CFG reachability algorithm to an iterative algorithm --- Zend/Optimizer/zend_cfg.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/Zend/Optimizer/zend_cfg.c b/Zend/Optimizer/zend_cfg.c index f2b4874e4eefc..0c0174fa587ef 100644 --- a/Zend/Optimizer/zend_cfg.c +++ b/Zend/Optimizer/zend_cfg.c @@ -28,14 +28,23 @@ static void zend_mark_reachable(zend_op *opcodes, zend_cfg *cfg, zend_basic_bloc { zend_basic_block *blocks = cfg->blocks; - { - while (1) { + zend_worklist work; + ALLOCA_FLAG(list_use_heap) + ZEND_WORKLIST_ALLOCA(&work, cfg->blocks_count, list_use_heap); + + zend_worklist_push(&work, b - cfg->blocks); + + while (zend_worklist_len(&work)) { + b = cfg->blocks + zend_worklist_pop(&work); + + bool finished = false; + while (!finished) { int i; b->flags |= ZEND_BB_REACHABLE; if (b->successors_count == 0) { b->flags |= ZEND_BB_EXIT; - return; + break; } for (i = 0; i < b->successors_count; i++) { @@ -90,7 +99,8 @@ static void zend_mark_reachable(zend_op *opcodes, zend_cfg *cfg, zend_basic_bloc if (i == b->successors_count - 1) { /* Tail call optimization */ if (succ->flags & ZEND_BB_REACHABLE) { - return; + finished = true; + break; } b = succ; @@ -98,12 +108,14 @@ static void zend_mark_reachable(zend_op *opcodes, zend_cfg *cfg, zend_basic_bloc } else { /* Recursively check reachability */ if (!(succ->flags & ZEND_BB_REACHABLE)) { - zend_mark_reachable(opcodes, cfg, succ); + zend_worklist_push(&work, succ - cfg->blocks); } } } } } + + ZEND_WORKLIST_FREE_ALLOCA(&work, list_use_heap); } /* }}} */ From 1943c2d3d74cf2b07960e2fd32c3b34225deb5ec Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 4 Jun 2024 20:02:43 +0200 Subject: [PATCH 3/3] Remove tail call optimization --- Zend/Optimizer/zend_cfg.c | 113 +++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 64 deletions(-) diff --git a/Zend/Optimizer/zend_cfg.c b/Zend/Optimizer/zend_cfg.c index 0c0174fa587ef..2a0fe369cfc6a 100644 --- a/Zend/Optimizer/zend_cfg.c +++ b/Zend/Optimizer/zend_cfg.c @@ -35,82 +35,67 @@ static void zend_mark_reachable(zend_op *opcodes, zend_cfg *cfg, zend_basic_bloc zend_worklist_push(&work, b - cfg->blocks); while (zend_worklist_len(&work)) { + int i; b = cfg->blocks + zend_worklist_pop(&work); - bool finished = false; - while (!finished) { - int i; - - b->flags |= ZEND_BB_REACHABLE; - if (b->successors_count == 0) { - b->flags |= ZEND_BB_EXIT; - break; - } + b->flags |= ZEND_BB_REACHABLE; + if (b->successors_count == 0) { + b->flags |= ZEND_BB_EXIT; + continue; + } - for (i = 0; i < b->successors_count; i++) { - zend_basic_block* succ = blocks + b->successors[i]; + for (i = 0; i < b->successors_count; i++) { + zend_basic_block *succ = blocks + b->successors[i]; - if (b->len != 0) { - uint8_t opcode = opcodes[b->start + b->len - 1].opcode; - if (opcode == ZEND_MATCH) { + if (b->len != 0) { + uint8_t opcode = opcodes[b->start + b->len - 1].opcode; + if (opcode == ZEND_MATCH) { + succ->flags |= ZEND_BB_TARGET; + } else if (opcode == ZEND_SWITCH_LONG || opcode == ZEND_SWITCH_STRING) { + if (i == b->successors_count - 1) { + succ->flags |= ZEND_BB_FOLLOW | ZEND_BB_TARGET; + } else { succ->flags |= ZEND_BB_TARGET; - } else if (opcode == ZEND_SWITCH_LONG || opcode == ZEND_SWITCH_STRING) { - if (i == b->successors_count - 1) { - succ->flags |= ZEND_BB_FOLLOW | ZEND_BB_TARGET; - } else { - succ->flags |= ZEND_BB_TARGET; - } - } else if (b->successors_count == 1) { - if (opcode == ZEND_JMP) { - succ->flags |= ZEND_BB_TARGET; - } else { - succ->flags |= ZEND_BB_FOLLOW; - - if ((cfg->flags & ZEND_CFG_STACKLESS)) { - if (opcode == ZEND_INCLUDE_OR_EVAL || - opcode == ZEND_GENERATOR_CREATE || - opcode == ZEND_YIELD || - opcode == ZEND_YIELD_FROM || - opcode == ZEND_DO_FCALL || - opcode == ZEND_DO_UCALL || - opcode == ZEND_DO_FCALL_BY_NAME) { - succ->flags |= ZEND_BB_ENTRY; - } - } - if ((cfg->flags & ZEND_CFG_RECV_ENTRY)) { - if (opcode == ZEND_RECV || - opcode == ZEND_RECV_INIT) { - succ->flags |= ZEND_BB_RECV_ENTRY; - } + } + } else if (b->successors_count == 1) { + if (opcode == ZEND_JMP) { + succ->flags |= ZEND_BB_TARGET; + } else { + succ->flags |= ZEND_BB_FOLLOW; + + if ((cfg->flags & ZEND_CFG_STACKLESS)) { + if (opcode == ZEND_INCLUDE_OR_EVAL || + opcode == ZEND_GENERATOR_CREATE || + opcode == ZEND_YIELD || + opcode == ZEND_YIELD_FROM || + opcode == ZEND_DO_FCALL || + opcode == ZEND_DO_UCALL || + opcode == ZEND_DO_FCALL_BY_NAME) { + succ->flags |= ZEND_BB_ENTRY; } } - } else { - ZEND_ASSERT(b->successors_count == 2); - if (i == 0) { - succ->flags |= ZEND_BB_TARGET; - } else { - succ->flags |= ZEND_BB_FOLLOW; + if ((cfg->flags & ZEND_CFG_RECV_ENTRY)) { + if (opcode == ZEND_RECV || + opcode == ZEND_RECV_INIT) { + succ->flags |= ZEND_BB_RECV_ENTRY; + } } } } else { - succ->flags |= ZEND_BB_FOLLOW; - } - - if (i == b->successors_count - 1) { - /* Tail call optimization */ - if (succ->flags & ZEND_BB_REACHABLE) { - finished = true; - break; - } - - b = succ; - break; - } else { - /* Recursively check reachability */ - if (!(succ->flags & ZEND_BB_REACHABLE)) { - zend_worklist_push(&work, succ - cfg->blocks); + ZEND_ASSERT(b->successors_count == 2); + if (i == 0) { + succ->flags |= ZEND_BB_TARGET; + } else { + succ->flags |= ZEND_BB_FOLLOW; } } + } else { + succ->flags |= ZEND_BB_FOLLOW; + } + + /* Check reachability of successor */ + if (!(succ->flags & ZEND_BB_REACHABLE)) { + zend_worklist_push(&work, succ - cfg->blocks); } } }