]> granicus.if.org Git - php/commitdiff
Don't undo/redo "pass two" for jump targets in opcache optimizer.
authorDmitry Stogov <dmitry@zend.com>
Tue, 17 Nov 2015 04:15:35 +0000 (07:15 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 17 Nov 2015 04:15:35 +0000 (07:15 +0300)
Zend/zend_compile.h
ext/opcache/Optimizer/block_pass.c
ext/opcache/Optimizer/nop_removal.c
ext/opcache/Optimizer/pass2.c
ext/opcache/Optimizer/pass3.c
ext/opcache/Optimizer/zend_optimizer.c
ext/opcache/Optimizer/zend_optimizer_internal.h

index ff74ec26e5b45f4ffbcf72ba407469248f634b54..ce7dc3aefc41e88708fae57e7bec57b06451d260 100644 (file)
@@ -530,6 +530,9 @@ struct _zend_execute_data {
 
 #define EX_VAR_TO_NUM(n)               (ZEND_CALL_VAR(NULL, n) - ZEND_CALL_VAR_NUM(NULL, 0))
 
+#define ZEND_OPLINE_TO_OFFSET(opline, target) \
+       ((char*)(target) - (char*)(opline))
+
 #define ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline_num) \
        ((char*)&(op_array)->opcodes[opline_num] - (char*)(opline))
 
@@ -545,6 +548,10 @@ struct _zend_execute_data {
 # define OP_JMP_ADDR(opline, node) \
        (node).jmp_addr
 
+# define ZEND_SET_OP_JMP_ADDR(opline, node, val) do { \
+               (node).jmp_addr = (val); \
+       } while (0)
+
 /* convert jump target from compile-time to run-time */
 # define ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, node) do { \
                (node).jmp_addr = (op_array)->opcodes + (node).opline_num; \
@@ -561,6 +568,10 @@ struct _zend_execute_data {
 # define OP_JMP_ADDR(opline, node) \
        ZEND_OFFSET_TO_OPLINE(opline, (node).jmp_offset)
 
+# define ZEND_SET_OP_JMP_ADDR(opline, node, val) do { \
+               (node).jmp_offset = ZEND_OPLINE_TO_OFFSET(opline, val); \
+       } while (0)
+
 /* convert jump target from compile-time to run-time */
 # define ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, node) do { \
                (node).jmp_offset = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, (node).opline_num); \
index 61f86f5ebb3e93544ec0a6e6f126a7f9b059255b..9a818cfe44cc4689434ec7363e057b314ceac7bf 100644 (file)
@@ -113,13 +113,14 @@ static inline void print_block(zend_code_block *block, zend_op *opcodes, char *t
 static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimizer_ctx *ctx)
 {
        zend_op *opline;
-       zend_op *end = op_array->opcodes + op_array->last;
+       zend_op *opcodes = op_array->opcodes;
+       zend_op *end = opcodes + op_array->last;
        zend_code_block *blocks, *cur_block;
        uint32_t opno = 0;
 
        memset(cfg, 0, sizeof(zend_cfg));
        blocks = cfg->blocks = zend_arena_calloc(&ctx->arena, op_array->last + 2, sizeof(zend_code_block));
-       opline = op_array->opcodes;
+       opline = opcodes;
        blocks[0].start_opline = opline;
        blocks[0].start_opline_no = 0;
        while (opline < end) {
@@ -128,7 +129,7 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz
                        case ZEND_JMP:
                        case ZEND_DECLARE_ANON_CLASS:
                        case ZEND_DECLARE_ANON_INHERITED_CLASS:
-                               START_BLOCK_OP(ZEND_OP1(opline).opline_num);
+                               START_BLOCK_OP(ZEND_OP1_JMP_ADDR(opline) - opcodes);
                                /* break missing intentionally */
                        case ZEND_RETURN:
                        case ZEND_RETURN_BY_REF:
@@ -139,14 +140,9 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz
                                /* start new block from this+1 */
                                START_BLOCK_OP(opno + 1);
                                break;
-                               /* TODO: if conditional jmp depends on constant,
-                                                don't start block that won't be executed */
-                       case ZEND_CATCH:
-                               START_BLOCK_OP(opline->extended_value);
-                               START_BLOCK_OP(opno + 1);
-                               break;
                        case ZEND_JMPZNZ:
-                               START_BLOCK_OP(opline->extended_value);
+                               START_BLOCK_OP(ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value) - opcodes);
+                               /* break missing intentionally */
                        case ZEND_JMPZ:
                        case ZEND_JMPNZ:
                        case ZEND_JMPZ_EX:
@@ -157,12 +153,13 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz
                        case ZEND_JMP_SET:
                        case ZEND_COALESCE:
                        case ZEND_ASSERT_CHECK:
-                               START_BLOCK_OP(ZEND_OP2(opline).opline_num);
+                               START_BLOCK_OP(ZEND_OP2_JMP_ADDR(opline) - opcodes);
                                START_BLOCK_OP(opno + 1);
                                break;
                        case ZEND_FE_FETCH_R:
                        case ZEND_FE_FETCH_RW:
-                               START_BLOCK_OP(opline->extended_value);
+                       case ZEND_CATCH:
+                               START_BLOCK_OP(ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value) - opcodes);
                                START_BLOCK_OP(opno + 1);
                                break;
                }
@@ -210,9 +207,6 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz
                        cur_block->next = &blocks[opno];
                        /* what is the last OP of previous block? */
                        opline = blocks[opno].start_opline - 1;
-                       if (opline->opcode == ZEND_OP_DATA) {
-                               opline--;
-                       }
                        switch((unsigned)opline->opcode) {
                                case ZEND_RETURN:
                                case ZEND_RETURN_BY_REF:
@@ -222,25 +216,22 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz
                                case ZEND_FAST_RET:
                                        break;
                                case ZEND_JMP:
-                                       cur_block->op1_to = &blocks[ZEND_OP1(opline).opline_num];
+                                       cur_block->op1_to = &blocks[ZEND_OP1_JMP_ADDR(opline) - opcodes];
                                        break;
                                case ZEND_FAST_CALL:
                                case ZEND_DECLARE_ANON_CLASS:
                                case ZEND_DECLARE_ANON_INHERITED_CLASS:
-                                       cur_block->op1_to = &blocks[ZEND_OP1(opline).opline_num];
+                                       cur_block->op1_to = &blocks[ZEND_OP1_JMP_ADDR(opline) - opcodes];
                                        cur_block->follow_to = &blocks[opno];
                                        break;
                                case ZEND_JMPZNZ:
-                                       cur_block->op2_to = &blocks[ZEND_OP2(opline).opline_num];
-                                       cur_block->ext_to = &blocks[opline->extended_value];
-                                       break;
-                               case ZEND_CATCH:
-                                       cur_block->ext_to = &blocks[opline->extended_value];
-                                       cur_block->follow_to = &blocks[opno];
+                                       cur_block->op2_to = &blocks[ZEND_OP2_JMP_ADDR(opline) - opcodes];
+                                       cur_block->ext_to = &blocks[ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value) - opcodes];
                                        break;
                                case ZEND_FE_FETCH_R:
                                case ZEND_FE_FETCH_RW:
-                                       cur_block->ext_to = &blocks[opline->extended_value];
+                               case ZEND_CATCH:
+                                       cur_block->ext_to = &blocks[ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value) - opcodes];
                                        cur_block->follow_to = &blocks[opno];
                                        break;
                                case ZEND_JMPZ:
@@ -253,7 +244,7 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz
                                case ZEND_JMP_SET:
                                case ZEND_COALESCE:
                                case ZEND_ASSERT_CHECK:
-                                       cur_block->op2_to = &blocks[ZEND_OP2(opline).opline_num];
+                                       cur_block->op2_to = &blocks[ZEND_OP2_JMP_ADDR(opline) - op_array->opcodes];
                                        /* break missing intentionally */
                                default:
                                        /* next block follows this */
@@ -774,13 +765,8 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
                                case ZEND_JMPZNZ:
                                {
                                        /* T = BOOL_NOT(X) + JMPZNZ(T,L1,L2) -> NOP, JMPZNZ(X,L2,L1) */
-                                       int op_t;
                                        zend_code_block *op_b;
 
-                                       op_t = opline->extended_value;
-                                       opline->extended_value = ZEND_OP2(opline).opline_num;
-                                       ZEND_OP2(opline).opline_num = op_t;
-
                                        op_b = block->ext_to;
                                        block->ext_to = block->op2_to;
                                        block->op2_to = op_b;
@@ -1087,36 +1073,35 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
 static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
 {
        zend_code_block *blocks = cfg->blocks;
-       zend_op *new_opcodes = emalloc(op_array->last * sizeof(zend_op));
-       zend_op *opline = new_opcodes;
-       zend_code_block *cur_block = blocks;
+       zend_op *new_opcodes;
+       zend_op *opline;
+       zend_code_block *cur_block;
+       int len = 0;
 
-       /* Copy code of reachable blocks into a single buffer */
-       while (cur_block) {
-               if (cur_block->access) {
-                       memcpy(opline, cur_block->start_opline, cur_block->len * sizeof(zend_op));
-                       cur_block->start_opline = opline;
-                       opline += cur_block->len;
-                       if ((opline - 1)->opcode == ZEND_JMP) {
+       for (cur_block = blocks; cur_block; cur_block = cur_block->next) {
+               if (cur_block->access && cur_block->len) {
+                       opline = cur_block->start_opline + cur_block->len - 1;
+                       if (opline->opcode == ZEND_JMP) {
                                zend_code_block *next;
+
                                next = cur_block->next;
-                               while (next && !next->access) {
+                               while (next && (!next->access || !next->len)) {
                                        next = next->next;
                                }
                                if (next && next == cur_block->op1_to) {
                                        /* JMP to the next block - strip it */
                                        cur_block->follow_to = cur_block->op1_to;
                                        cur_block->op1_to = NULL;
-                                       MAKE_NOP((opline - 1));
-                                       opline--;
+                                       MAKE_NOP(opline);
                                        cur_block->len--;
                                }
                        }
-               } else {
+                       len += cur_block->len;
+               } else if (cur_block->start_opline && cur_block->len) {
                        /* this block will not be used, delete all constants there */
                        zend_op *_opl;
                        zend_op *end = cur_block->start_opline + cur_block->len;
-                       for (_opl = cur_block->start_opline; _opl && _opl < end; _opl++) {
+                       for (_opl = cur_block->start_opline; _opl < end; _opl++) {
                                if (ZEND_OP1_TYPE(_opl) == IS_CONST) {
                                        literal_dtor(&ZEND_OP1_LITERAL(_opl));
                                }
@@ -1125,10 +1110,20 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
                                }
                        }
                }
-               cur_block = cur_block->next;
        }
 
-       op_array->last = opline-new_opcodes;
+       op_array->last = len;
+       new_opcodes = emalloc(op_array->last * sizeof(zend_op));
+       opline = new_opcodes;
+
+       /* Copy code of reachable blocks into a single buffer */
+       for (cur_block = blocks; cur_block; cur_block = cur_block->next) {
+               if (cur_block->access && cur_block->len) {
+                       memcpy(opline, cur_block->start_opline, cur_block->len * sizeof(zend_op));
+                       cur_block->start_opline = opline;
+                       opline += cur_block->len;
+               }
+       }
 
        /* adjust exception jump targets */
        if (op_array->last_try_catch) {
@@ -1153,27 +1148,25 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
        }
 
     /* adjust jump targets */
+       efree(op_array->opcodes);
+       op_array->opcodes = new_opcodes;
+
        for (cur_block = blocks; cur_block; cur_block = cur_block->next) {
                if (!cur_block->access) {
                        continue;
                }
                opline = cur_block->start_opline + cur_block->len - 1;
-               if (opline->opcode == ZEND_OP_DATA) {
-                       opline--;
-               }
                if (cur_block->op1_to) {
-                       ZEND_OP1(opline).opline_num = cur_block->op1_to->start_opline - new_opcodes;
+                       ZEND_SET_OP_JMP_ADDR(opline, opline->op1, cur_block->op1_to->start_opline);
                }
                if (cur_block->op2_to) {
-                       ZEND_OP2(opline).opline_num = cur_block->op2_to->start_opline - new_opcodes;
+                       ZEND_SET_OP_JMP_ADDR(opline, opline->op2, cur_block->op2_to->start_opline);
                }
                if (cur_block->ext_to) {
-                       opline->extended_value = cur_block->ext_to->start_opline - new_opcodes;
+                       opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, cur_block->ext_to->start_opline);
                }
                print_block(cur_block, new_opcodes, "Out ");
        }
-       efree(op_array->opcodes);
-       op_array->opcodes = erealloc(new_opcodes, op_array->last * sizeof(zend_op));
 
        /* adjust early binding list */
        if (op_array->early_binding != (uint32_t)-1) {
index 75e84c76444e808b09124ced19f1d1648fb4efea..52967d16fd14177d9b0ea3c3653655313d492626 100644 (file)
@@ -45,9 +45,9 @@ void zend_optimizer_nop_removal(zend_op_array *op_array)
        for (opline = op_array->opcodes; opline < end; opline++) {
 
                /* Kill JMP-over-NOP-s */
-               if (opline->opcode == ZEND_JMP && ZEND_OP1(opline).opline_num > i) {
+               if (opline->opcode == ZEND_JMP && ZEND_OP1_JMP_ADDR(opline) > op_array->opcodes + i) {
                        /* check if there are only NOPs under the branch */
-                       zend_op *target = op_array->opcodes + ZEND_OP1(opline).opline_num - 1;
+                       zend_op *target = ZEND_OP1_JMP_ADDR(opline) - 1;
 
                        while (target->opcode == ZEND_NOP) {
                                target--;
@@ -63,7 +63,37 @@ void zend_optimizer_nop_removal(zend_op_array *op_array)
                        shift++;
                } else {
                        if (shift) {
-                               op_array->opcodes[new_count] = *opline;
+                               zend_op *new_opline = op_array->opcodes + new_count;
+
+                               *new_opline = *opline;
+                               switch (new_opline->opcode) {
+                                       case ZEND_JMP:
+                                       case ZEND_FAST_CALL:
+                                       case ZEND_DECLARE_ANON_CLASS:
+                                       case ZEND_DECLARE_ANON_INHERITED_CLASS:
+                                               ZEND_SET_OP_JMP_ADDR(new_opline, new_opline->op1, ZEND_OP1_JMP_ADDR(opline));
+                                               break;
+                                       case ZEND_JMPZNZ:
+                                               new_opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, new_opline, ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value));
+                                               /* break missing intentionally */
+                                       case ZEND_JMPZ:
+                                       case ZEND_JMPNZ:
+                                       case ZEND_JMPZ_EX:
+                                       case ZEND_JMPNZ_EX:
+                                       case ZEND_FE_RESET_R:
+                                       case ZEND_FE_RESET_RW:
+                                       case ZEND_NEW:
+                                       case ZEND_JMP_SET:
+                                       case ZEND_COALESCE:
+                                       case ZEND_ASSERT_CHECK:
+                                               ZEND_SET_OP_JMP_ADDR(new_opline, new_opline->op2, ZEND_OP2_JMP_ADDR(opline));
+                                               break;
+                                       case ZEND_FE_FETCH_R:
+                                       case ZEND_FE_FETCH_RW:
+                                       case ZEND_CATCH:
+                                               new_opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, new_opline, ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value));
+                                               break;
+                               }
                        }
                        new_count++;
                }
@@ -80,8 +110,11 @@ void zend_optimizer_nop_removal(zend_op_array *op_array)
                                case ZEND_FAST_CALL:
                                case ZEND_DECLARE_ANON_CLASS:
                                case ZEND_DECLARE_ANON_INHERITED_CLASS:
-                                       ZEND_OP1(opline).opline_num -= shiftlist[ZEND_OP1(opline).opline_num];
+                                       ZEND_SET_OP_JMP_ADDR(opline, opline->op1, ZEND_OP1_JMP_ADDR(opline) - shiftlist[ZEND_OP1_JMP_ADDR(opline) - op_array->opcodes]);
                                        break;
+                               case ZEND_JMPZNZ:
+                                       opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value) - shiftlist[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)]);
+                                       /* break missing intentionally */
                                case ZEND_JMPZ:
                                case ZEND_JMPNZ:
                                case ZEND_JMPZ_EX:
@@ -92,18 +125,12 @@ void zend_optimizer_nop_removal(zend_op_array *op_array)
                                case ZEND_JMP_SET:
                                case ZEND_COALESCE:
                                case ZEND_ASSERT_CHECK:
-                                       ZEND_OP2(opline).opline_num -= shiftlist[ZEND_OP2(opline).opline_num];
+                                       ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(opline) - shiftlist[ZEND_OP2_JMP_ADDR(opline) - op_array->opcodes]);
                                        break;
                                case ZEND_FE_FETCH_R:
                                case ZEND_FE_FETCH_RW:
-                                       opline->extended_value -= shiftlist[opline->extended_value];
-                                       break;
-                               case ZEND_JMPZNZ:
-                                       ZEND_OP2(opline).opline_num -= shiftlist[ZEND_OP2(opline).opline_num];
-                                       opline->extended_value -= shiftlist[opline->extended_value];
-                                       break;
                                case ZEND_CATCH:
-                                       opline->extended_value -= shiftlist[opline->extended_value];
+                                       opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value) - shiftlist[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)]);
                                        break;
                        }
                }
index 143167f816cd8160d845576158779846e7af0a04..3573c1038c1cbdbf8d73b54fcfc618fa1c09f221 100644 (file)
@@ -154,15 +154,15 @@ void zend_optimizer_pass2(zend_op_array *op_array)
                                if ((opline + 1)->opcode == ZEND_JMP) {
                                        /* JMPZ(X, L1), JMP(L2) => JMPZNZ(X, L1, L2) */
                                        /* JMPNZ(X, L1), JMP(L2) => JMPZNZ(X, L2, L1) */
-                                       if (ZEND_OP2(opline).opline_num == ZEND_OP1(opline + 1).opline_num) {
+                                       if (ZEND_OP2_JMP_ADDR(opline) == ZEND_OP1_JMP_ADDR(opline + 1)) {
                                                /* JMPZ(X, L1), JMP(L1) => NOP, JMP(L1) */
                                                MAKE_NOP(opline);
                                        } else {
                                                if (opline->opcode == ZEND_JMPZ) {
-                                                       opline->extended_value = ZEND_OP1(opline + 1).opline_num;
+                                                       opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, ZEND_OP1_JMP_ADDR(opline + 1));
                                                } else {
-                                                       opline->extended_value = ZEND_OP2(opline).opline_num;
-                                                       COPY_NODE(opline->op2, (opline + 1)->op1);
+                                                       opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, ZEND_OP2_JMP_ADDR(opline));
+                                                       ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP1_JMP_ADDR(opline + 1));
                                                }
                                                opline->opcode = ZEND_JMPZNZ;
                                        }
@@ -171,14 +171,15 @@ void zend_optimizer_pass2(zend_op_array *op_array)
 
                        case ZEND_JMPZNZ:
                                if (ZEND_OP1_TYPE(opline) == IS_CONST) {
-                                       int opline_num;
+                                       zend_op *target_opline;
+
                                        if (zend_is_true(&ZEND_OP1_LITERAL(opline))) {
-                                               opline_num = opline->extended_value; /* JMPNZ */
+                                               target_opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value); /* JMPNZ */
                                        } else {
-                                               opline_num = ZEND_OP2(opline).opline_num; /* JMPZ */
+                                               target_opline = ZEND_OP2_JMP_ADDR(opline); /* JMPZ */
                                        }
                                        literal_dtor(&ZEND_OP1_LITERAL(opline));
-                                       ZEND_OP1(opline).opline_num = opline_num;
+                                       ZEND_SET_OP_JMP_ADDR(opline, opline->op1, target_opline);
                                        ZEND_OP1_TYPE(opline) = IS_UNUSED;
                                        opline->opcode = ZEND_JMP;
                                }
index 2a74717f1045b093abed98ec7c7343867cfbb9cb..fb3a01e26db1df589badf9aaf38127a50253e611 100644 (file)
 /* we use "jmp_hitlist" to avoid infinity loops during jmp optimization */
 #define CHECK_JMP(target, label)                       \
        for (i=0; i<jmp_hitlist_count; i++) {   \
-               if (jmp_hitlist[i] == ZEND_OP1(&op_array->opcodes[target]).opline_num) {                \
+               if (jmp_hitlist[i] == ZEND_OP1_JMP_ADDR(target)) {              \
                        goto label;                                             \
                }                                                                       \
        }                                                                               \
-       jmp_hitlist[jmp_hitlist_count++] = ZEND_OP1(&op_array->opcodes[target]).opline_num;
+       jmp_hitlist[jmp_hitlist_count++] = ZEND_OP1_JMP_ADDR(target);
 
 #define CHECK_JMP2(target, label)                      \
        for (i=0; i<jmp_hitlist_count; i++) {   \
-               if (jmp_hitlist[i] == ZEND_OP2(&op_array->opcodes[target]).opline_num) {                \
+               if (jmp_hitlist[i] == ZEND_OP2_JMP_ADDR(target)) {              \
                        goto label;                                             \
                }                                                                       \
        }                                                                               \
-       jmp_hitlist[jmp_hitlist_count++] = ZEND_OP2(&op_array->opcodes[target]).opline_num;
+       jmp_hitlist[jmp_hitlist_count++] = ZEND_OP2_JMP_ADDR(target);
 
 void zend_optimizer_pass3(zend_op_array *op_array)
 {
        zend_op *opline;
        zend_op *end = op_array->opcodes + op_array->last;
-       uint32_t *jmp_hitlist;
+       zend_op **jmp_hitlist;
        int jmp_hitlist_count;
        int i;
        uint32_t opline_num = 0;
        ALLOCA_FLAG(use_heap);
 
-       jmp_hitlist = (uint32_t *)do_alloca(sizeof(uint32_t)*op_array->last, use_heap);
+       jmp_hitlist = (zend_op**)do_alloca(sizeof(zend_op*)*op_array->last, use_heap);
        opline = op_array->opcodes;
 
        while (opline < end) {
@@ -167,17 +167,17 @@ void zend_optimizer_pass3(zend_op_array *op_array)
                                }
 
                                /* convert L: JMP L+1 to NOP */
-                               if (ZEND_OP1(opline).opline_num == opline_num + 1) {
+                               if (ZEND_OP1_JMP_ADDR(opline) == opline + 1) {
                                        MAKE_NOP(opline);
                                        goto done_jmp_optimization;
                                }
 
                                /* convert JMP L1 ... L1: JMP L2 to JMP L2 .. L1: JMP L2 */
-                               while (ZEND_OP1(opline).opline_num < op_array->last
-                                               && op_array->opcodes[ZEND_OP1(opline).opline_num].opcode == ZEND_JMP) {
-                                       int target = ZEND_OP1(opline).opline_num;
+                               while (ZEND_OP1_JMP_ADDR(opline) < end
+                                               && ZEND_OP1_JMP_ADDR(opline)->opcode == ZEND_JMP) {
+                                       zend_op *target = ZEND_OP1_JMP_ADDR(opline);
                                        CHECK_JMP(target, done_jmp_optimization);
-                                       ZEND_OP1(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num;
+                                       ZEND_SET_OP_JMP_ADDR(opline, opline->op1, ZEND_OP1_JMP_ADDR(target));
                                }
                                break;
 
@@ -187,10 +187,10 @@ void zend_optimizer_pass3(zend_op_array *op_array)
                                        break;
                                }
 
-                               while (ZEND_OP2(opline).opline_num < op_array->last) {
-                                       int target = ZEND_OP2(opline).opline_num;
-                                       if (op_array->opcodes[target].opcode == ZEND_JMP) {
-                                               ZEND_OP2(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num;
+                               while (ZEND_OP2_JMP_ADDR(opline) < end) {
+                                       zend_op *target = ZEND_OP2_JMP_ADDR(opline);
+                                       if (target->opcode == ZEND_JMP) {
+                                               ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP1_JMP_ADDR(target));
                                        } else {
                                                break;
                                        }
@@ -202,40 +202,41 @@ void zend_optimizer_pass3(zend_op_array *op_array)
                                        break;
                                }
 
-                               while (ZEND_OP2(opline).opline_num < op_array->last) {
-                                       int target = ZEND_OP2(opline).opline_num;
+                               while (ZEND_OP2_JMP_ADDR(opline) < end) {
+                                       zend_op *target = ZEND_OP2_JMP_ADDR(opline);
 
-                                       if (op_array->opcodes[target].opcode == ZEND_JMP) {
+                                       if (target->opcode == ZEND_JMP) {
                                                /* plain JMP */
                                                /* JMPZ(X,L1), L1: JMP(L2) => JMPZ(X,L2), L1: JMP(L2) */
                                                CHECK_JMP(target, done_jmp_optimization);
-                                               ZEND_OP2(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num;
-                                       } else if (op_array->opcodes[target].opcode == opline->opcode &&
-                                                  SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
+                                               ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP1_JMP_ADDR(target));
+                                       } else if (target->opcode == opline->opcode &&
+                                                  SAME_VAR(opline->op1, target->op1)) {
                                                /* same opcode and same var as this opcode */
                                                /* JMPZ(X,L1), L1: JMPZ(X,L2) => JMPZ(X,L2), L1: JMPZ(X,L2) */
                                                CHECK_JMP2(target, done_jmp_optimization);
-                                               ZEND_OP2(opline).opline_num = ZEND_OP2(&op_array->opcodes[target]).opline_num;
-                                       } else if (op_array->opcodes[target].opcode == opline->opcode + 3 &&
-                                                  SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
+                                               ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(target));
+                                       } else if (target->opcode == opline->opcode + 3 &&
+                                                  SAME_VAR(opline->op1, target->op1)) {
                                                /* convert JMPZ(X,L1), L1: T JMPZ_EX(X,L2) to
                                                   T = JMPZ_EX(X, L2) */
-                                               ZEND_OP2(opline).opline_num = ZEND_OP2(&op_array->opcodes[target]).opline_num;opline->opcode += 3;
-                                               COPY_NODE(opline->result, op_array->opcodes[target].result);
+                                               ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(target));
+                                               opline->opcode += 3;
+                                               COPY_NODE(opline->result, target->result);
                                                break;
-                                       } else if (op_array->opcodes[target].opcode == INV_COND(opline->opcode) &&
-                                                  SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
+                                       } else if (target->opcode == INV_COND(opline->opcode) &&
+                                                  SAME_VAR(opline->op1, target->op1)) {
                                                /* convert JMPZ(X,L1), L1: JMPNZ(X,L2) to
                                                   JMPZ(X,L1+1) */
-                                               ZEND_OP2(opline).opline_num = target + 1;
+                                               ZEND_SET_OP_JMP_ADDR(opline, opline->op2, target + 1);
                                                break;
-                                       } else if (op_array->opcodes[target].opcode == INV_COND_EX(opline->opcode) &&
-                                                  SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
+                                       } else if (target->opcode == INV_COND_EX(opline->opcode) &&
+                                                  SAME_VAR(opline->op1, target->op1)) {
                                                /* convert JMPZ(X,L1), L1: T = JMPNZ_EX(X,L2) to
                                                   T = JMPZ_EX(X,L1+1) */
-                                               ZEND_OP2(opline).opline_num = target + 1;
+                                               ZEND_SET_OP_JMP_ADDR(opline, opline->op2, target + 1);
                                                opline->opcode += 3;
-                                               COPY_NODE(opline->result, op_array->opcodes[target].result);
+                                               COPY_NODE(opline->result, target->result);
                                                break;
                                        } else {
                                                break;
@@ -254,7 +255,7 @@ void zend_optimizer_pass3(zend_op_array *op_array)
 
                                        /* convert L: T = JMPZ_EX X,L+1 to T = BOOL(X) */
                                        /* convert L: T = JMPZ_EX T,L+1 to NOP */
-                                       if (ZEND_OP2(opline).opline_num == opline_num + 1) {
+                                       if (ZEND_OP2_JMP_ADDR(opline) == opline + 1) {
                                                if (ZEND_OP1(opline).var == ZEND_RESULT(opline).var) {
                                                        MAKE_NOP(opline);
                                                } else {
@@ -264,36 +265,38 @@ void zend_optimizer_pass3(zend_op_array *op_array)
                                                goto done_jmp_optimization;
                                        }
 
-                                       while (ZEND_OP2(opline).opline_num < op_array->last) {
-                                               int target = ZEND_OP2(opline).opline_num;
-                                               if (SAME_OPCODE_EX(opline->opcode, op_array->opcodes[target].opcode) &&
-                                                       SAME_VAR(op_array->opcodes[target].op1, T)) {
+                                       while (ZEND_OP2_JMP_ADDR(opline) < end) {
+                                               zend_op *target = ZEND_OP2_JMP_ADDR(opline);
+
+                                               if (SAME_OPCODE_EX(opline->opcode, target->opcode) &&
+                                                       SAME_VAR(target->op1, T)) {
                                                        /* Check for JMPZ_EX to JMPZ[_EX] with the same condition, either with _EX or not */
-                                                       if (op_array->opcodes[target].opcode == opline->opcode) {
+                                                       if (target->opcode == opline->opcode) {
                                                                /* change T only if we have _EX opcode there */
-                                                               COPY_NODE(T, op_array->opcodes[target].result);
+                                                               COPY_NODE(T, target->result);
                                                        }
                                                        CHECK_JMP2(target, continue_jmp_ex_optimization);
-                                                       ZEND_OP2(opline).opline_num = ZEND_OP2(&op_array->opcodes[target]).opline_num;
-                                               } else if (op_array->opcodes[target].opcode == ZEND_JMPZNZ &&
-                                                                 SAME_VAR(op_array->opcodes[target].op1, T)) {
+                                                       ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(target));
+                                               } else if (target->opcode == ZEND_JMPZNZ &&
+                                                                 SAME_VAR(target->op1, T)) {
                                                        /* Check for JMPZNZ with same cond variable */
-                                                       int new_target;
+                                                       zend_op *new_target;
+
                                                        CHECK_JMP2(target, continue_jmp_ex_optimization);
                                                        if (opline->opcode == ZEND_JMPZ_EX) {
-                                                               new_target = ZEND_OP2(&op_array->opcodes[target]).opline_num;
+                                                               new_target = ZEND_OP2_JMP_ADDR(target);
                                                        } else {
                                                                /* JMPNZ_EX */
-                                                               new_target = op_array->opcodes[target].extended_value;
+                                                               new_target = ZEND_OFFSET_TO_OPLINE(target, target->extended_value);
                                                        }
-                                                       ZEND_OP2(opline).opline_num = new_target;
-                                               } else if ((op_array->opcodes[target].opcode == INV_EX_COND_EX(opline->opcode) ||
-                                                                       op_array->opcodes[target].opcode == INV_EX_COND(opline->opcode)) &&
-                                                                       SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
+                                                       ZEND_SET_OP_JMP_ADDR(opline, opline->op2, new_target);
+                                               } else if ((target->opcode == INV_EX_COND_EX(opline->opcode) ||
+                                                                       target->opcode == INV_EX_COND(opline->opcode)) &&
+                                                                       SAME_VAR(opline->op1, target->op1)) {
                                                   /* convert JMPZ_EX(X,L1), L1: JMPNZ_EX(X,L2) to
                                                          JMPZ_EX(X,L1+1) */
-                                                  ZEND_OP2(opline).opline_num = target + 1;
-                                                  break;
+                                                       ZEND_SET_OP_JMP_ADDR(opline, opline->op2, target + 1);
+                                                       break;
                                                } else {
                                                        break;
                                                }
@@ -385,19 +388,19 @@ continue_jmp_ex_optimization:
                                }
 
                                /* JMPZNZ(X,L1,L2), L1: JMP(L3) => JMPZNZ(X,L3,L2), L1: JMP(L3) */
-                               while (ZEND_OP2(opline).opline_num < op_array->last
-                                               && op_array->opcodes[ZEND_OP2(opline).opline_num].opcode == ZEND_JMP) {
-                                       int target = ZEND_OP2(opline).opline_num;
+                               while (ZEND_OP2_JMP_ADDR(opline) < end
+                                               && ZEND_OP2_JMP_ADDR(opline)->opcode == ZEND_JMP) {
+                                       zend_op *target = ZEND_OP2_JMP_ADDR(opline);
                                        CHECK_JMP(target, continue_jmpznz_optimization);
-                                       ZEND_OP2(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num;
+                                       ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP1_JMP_ADDR(target));
                                }
 continue_jmpznz_optimization:
                                /* JMPZNZ(X,L1,L2), L2: JMP(L3) => JMPZNZ(X,L1,L3), L2: JMP(L3) */
-                               while (opline->extended_value < op_array->last
-                                               && op_array->opcodes[opline->extended_value].opcode == ZEND_JMP) {
-                                       int target = opline->extended_value;
+                               while (ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value) < end
+                                               && ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value)->opcode == ZEND_JMP) {
+                                       zend_op *target = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value);
                                        CHECK_JMP(target, done_jmp_optimization);
-                                       opline->extended_value = ZEND_OP1(&op_array->opcodes[target]).opline_num;
+                                       opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, ZEND_OP1_JMP_ADDR(target));
                                }
                                break;
 
index 9fb7493054ae3b2a4132ffba09b00976064bdeb4..a1cfda5e3f86c43f14d04f8edf48e4a3bf701e1f 100644 (file)
@@ -608,38 +608,6 @@ static void zend_optimize_op_array(zend_op_array      *op_array,
                if (opline->op2_type == IS_CONST) {
                        ZEND_PASS_TWO_UNDO_CONSTANT(op_array, opline->op2);
                }
-               switch (opline->opcode) {
-                       case ZEND_JMP:
-                       case ZEND_FAST_CALL:
-                       case ZEND_DECLARE_ANON_CLASS:
-                       case ZEND_DECLARE_ANON_INHERITED_CLASS:
-                               ZEND_PASS_TWO_UNDO_JMP_TARGET(op_array, opline, ZEND_OP1(opline));
-                               break;
-                       case ZEND_CATCH:
-                               /* relative offset into absolute index */
-                               opline->extended_value = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value);
-                               break;
-                       case ZEND_JMPZNZ:
-                               /* relative offset into absolute index */
-                               opline->extended_value = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value);
-                               /* break omitted intentionally */
-                       case ZEND_JMPZ:
-                       case ZEND_JMPNZ:
-                       case ZEND_JMPZ_EX:
-                       case ZEND_JMPNZ_EX:
-                       case ZEND_JMP_SET:
-                       case ZEND_COALESCE:
-                       case ZEND_NEW:
-                       case ZEND_FE_RESET_R:
-                       case ZEND_FE_RESET_RW:
-                       case ZEND_ASSERT_CHECK:
-                               ZEND_PASS_TWO_UNDO_JMP_TARGET(op_array, opline, ZEND_OP2(opline));
-                               break;
-                       case ZEND_FE_FETCH_R:
-                       case ZEND_FE_FETCH_RW:
-                               opline->extended_value = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value);
-                               break;
-               }
                opline++;
        }
 
@@ -656,38 +624,6 @@ static void zend_optimize_op_array(zend_op_array      *op_array,
                if (opline->op2_type == IS_CONST) {
                        ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2);
                }
-               switch (opline->opcode) {
-                       case ZEND_JMP:
-                       case ZEND_FAST_CALL:
-                       case ZEND_DECLARE_ANON_CLASS:
-                       case ZEND_DECLARE_ANON_INHERITED_CLASS:
-                               ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, ZEND_OP1(opline));
-                               break;
-                       case ZEND_CATCH:
-                               /* absolute index to relative offset */
-                               opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
-                               break;
-                       case ZEND_JMPZNZ:
-                               /* absolute index to relative offset */
-                               opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
-                               /* break omitted intentionally */
-                       case ZEND_JMPZ:
-                       case ZEND_JMPNZ:
-                       case ZEND_JMPZ_EX:
-                       case ZEND_JMPNZ_EX:
-                       case ZEND_JMP_SET:
-                       case ZEND_COALESCE:
-                       case ZEND_NEW:
-                       case ZEND_FE_RESET_R:
-                       case ZEND_FE_RESET_RW:
-                       case ZEND_ASSERT_CHECK:
-                               ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, ZEND_OP2(opline));
-                               break;
-                       case ZEND_FE_FETCH_R:
-                       case ZEND_FE_FETCH_RW:
-                               opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
-                               break;
-               }
                ZEND_VM_SET_OPCODE_HANDLER(opline);
                opline++;
        }
index 7f8962e3ab3dc8fbe325d2b428780b8c9abe07bb..414bc0a515b6685ef0aa38281b13f97d1aadbee2 100644 (file)
 #define ZEND_OP1_TYPE(opline)                  (opline)->op1_type
 #define ZEND_OP1(opline)                               (opline)->op1
 #define ZEND_OP1_LITERAL(opline)               (op_array)->literals[(opline)->op1.constant]
+#define ZEND_OP1_JMP_ADDR(opline)              OP_JMP_ADDR(opline, (opline)->op1)
 #define ZEND_OP2_TYPE(opline)                  (opline)->op2_type
 #define ZEND_OP2(opline)                               (opline)->op2
 #define ZEND_OP2_LITERAL(opline)               (op_array)->literals[(opline)->op2.constant]
+#define ZEND_OP2_JMP_ADDR(opline)              OP_JMP_ADDR(opline, (opline)->op2)
 
 #define VAR_NUM(v) EX_VAR_TO_NUM(v)
 #define NUM_VAR(v) ((uint32_t)(zend_uintptr_t)ZEND_CALL_VAR_NUM(0, v))