source: trunk/mod_optimizer/xc_optimizer.c @ 1280

Last change on this file since 1280 was 1280, checked in by moo, 15 months ago

optimizer: fix devel debug output

  • Property svn:eol-style set to native
File size: 17.4 KB
RevLine 
[1279]1#if 1
[543]2#   define XCACHE_DEBUG
[308]3#endif
4
[1026]5#include "xc_optimizer.h"
6#include "xcache/xc_extension.h"
7#include "xcache/xc_ini.h"
[1003]8#include "xcache/xc_utils.h"
9#include "util/xc_stack.h"
10#include "util/xc_trace.h"
[477]11#include "xcache_globals.h"
[1]12
[1026]13#include "ext/standard/info.h"
14
[543]15#ifdef XCACHE_DEBUG
[1003]16#   include "xc_processor.h"
17#   include "xcache/xc_const_string.h"
[331]18#   include "ext/standard/php_var.h"
[308]19#endif
20
[331]21#ifdef IS_CV
22#   define XCACHE_IS_CV IS_CV
23#else
24#   define XCACHE_IS_CV 16
25#endif
26
[822]27#ifdef ZEND_ENGINE_2_4
28#   undef Z_OP_CONSTANT
29/* Z_OP_CONSTANT is used before pass_two is applied */
[1276]30#   define Z_OP_CONSTANT(op) op_array->literals[(op).constant].constant
[822]31#endif
32
[1008]33typedef zend_uint bbid_t;
34#define BBID_INVALID ((bbid_t) -1)
[308]35/* {{{ basic block */
36typedef struct _bb_t {
37    bbid_t     id;
38    zend_bool  used;
39
40    zend_bool  alloc;
41    zend_op   *opcodes;
42    int        count;
43    int        size;
44
[312]45    bbid_t     fall;
[657]46#ifdef ZEND_ENGINE_2
[326]47    bbid_t     catch;
[657]48#endif
[1278]49#ifdef ZEND_ENGINE_2_5
50    bbid_t     finally;
51#endif
[326]52
[1008]53    zend_uint  opnum; /* opnum after joining basic block */
[308]54} bb_t;
55/* }}} */
56
57/* basic blocks */
58typedef xc_stack_t bbs_t;
59
[326]60/* op array helper functions */
[308]61static int op_array_convert_switch(zend_op_array *op_array) /* {{{ */
62{
[1008]63    zend_uint i;
[308]64
65    if (op_array->brk_cont_array == NULL) {
66        return SUCCESS;
67    }
68
69    for (i = 0; i < op_array->last; i ++) {
70        zend_op *opline = &op_array->opcodes[i];
71        zend_brk_cont_element *jmp_to;
[834]72        zend_bool can_convert = 1;
[1249]73        int array_offset, nest_levels;
[308]74
[834]75        switch (opline->opcode) {
76        case ZEND_BRK:
77        case ZEND_CONT:
78            break;
79
80#ifdef ZEND_GOTO
81        case ZEND_GOTO:
82#endif
[845]83            continue;
[834]84
85        default:
86            continue;
[308]87        }
[834]88
[716]89        if (Z_OP_TYPE(opline->op2) != IS_CONST
90         || Z_OP_CONSTANT(opline->op2).type != IS_LONG) {
[308]91            return FAILURE;
92        }
93
[716]94        nest_levels = Z_OP_CONSTANT(opline->op2).value.lval;
[308]95
[716]96        array_offset = Z_OP(opline->op1).opline_num;
[308]97        do {
98            if (array_offset == -1) {
99                return FAILURE;
100            }
101            jmp_to = &op_array->brk_cont_array[array_offset];
102            if (nest_levels > 1) {
103                zend_op *brk_opline = &op_array->opcodes[jmp_to->brk];
104
105                switch (brk_opline->opcode) {
106                case ZEND_SWITCH_FREE:
107                case ZEND_FREE:
[847]108#ifdef EXT_TYPE_FREE_ON_RETURN
109                    if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN))
110#endif
111                    {
[834]112                        can_convert = 0;
113                    }
[308]114                    break;
115                }
116            }
117            array_offset = jmp_to->parent;
118        } while (--nest_levels > 0);
119
[834]120        if (can_convert) {
121            /* rewrite to jmp */
122            switch (opline->opcode) {
123            case ZEND_BRK:
124                Z_OP(opline->op1).opline_num = jmp_to->brk;
125                break;
126
127            case ZEND_CONT:
128                Z_OP(opline->op1).opline_num = jmp_to->cont;
129                break;
130            }
131            Z_OP_TYPE(opline->op2) = IS_UNUSED;
132            opline->opcode = ZEND_JMP;
[308]133        }
134    }
135
136    return SUCCESS;
137}
138/* }}} */
[326]139/* {{{ op_flowinfo helper func */
140enum {
[1112]141    XC_OPNUM_INVALID = -1
[326]142};
143typedef struct {
144    int       jmpout_op1;
145    int       jmpout_op2;
146    int       jmpout_ext;
147    zend_bool fall;
148} op_flowinfo_t;
149static void op_flowinfo_init(op_flowinfo_t *fi)
[308]150{
[326]151    fi->jmpout_op1 = fi->jmpout_op2 = fi->jmpout_ext = XC_OPNUM_INVALID;
152    fi->fall = 0;
153}
154/* }}} */
155static int op_get_flowinfo(op_flowinfo_t *fi, zend_op *opline) /* {{{ */
156{
157    op_flowinfo_init(fi);
158
[308]159    switch (opline->opcode) {
[657]160#ifdef ZEND_HANDLE_EXCEPTION
[326]161    case ZEND_HANDLE_EXCEPTION:
[657]162#endif
[308]163    case ZEND_RETURN:
[1213]164#ifdef ZEND_FAST_RET
165    case ZEND_FAST_RET:
166#endif
167#ifdef ZEND_GENERATOR_RETURN
168    case ZEND_GENERATOR_RETURN:
169#endif
[308]170    case ZEND_EXIT:
[312]171        return SUCCESS; /* no fall */
[308]172
[1213]173#ifdef ZEND_GOTO
174    case ZEND_GOTO:
175#endif
[308]176    case ZEND_JMP:
[1279]177        fi->jmpout_op1 = Z_OP(opline->op1).opline_num;
178        return SUCCESS; /* no fall */
179
[1213]180#ifdef ZEND_FAST_CALL
181    case ZEND_FAST_CALL:
[716]182        fi->jmpout_op1 = Z_OP(opline->op1).opline_num;
[1279]183        if (opline->extended_value) {
184            fi->jmpout_op2 = Z_OP(opline->op2).opline_num;
185        }
[312]186        return SUCCESS; /* no fall */
[1279]187#endif
[308]188
189    case ZEND_JMPZNZ:
[716]190        fi->jmpout_op2 = Z_OP(opline->op2).opline_num;
[326]191        fi->jmpout_ext = (int) opline->extended_value;
192        return SUCCESS; /* no fall */
[308]193
194    case ZEND_JMPZ:
195    case ZEND_JMPNZ:
196    case ZEND_JMPZ_EX:
197    case ZEND_JMPNZ_EX:
[485]198#ifdef ZEND_JMP_SET
199    case ZEND_JMP_SET:
200#endif
[1208]201#ifdef ZEND_JMP_SET_VAR
202    case ZEND_JMP_SET_VAR:
203#endif
[326]204#ifdef ZEND_JMP_NO_CTOR
[308]205    case ZEND_JMP_NO_CTOR:
[326]206#endif
207#ifdef ZEND_NEW
[308]208    case ZEND_NEW:
[326]209#endif
210#ifdef ZEND_FE_RESET
[308]211    case ZEND_FE_RESET:
212#endif     
213    case ZEND_FE_FETCH:
[716]214        fi->jmpout_op2 = Z_OP(opline->op2).opline_num;
[1278]215        fi->fall = 1;
216        return SUCCESS;
[308]217
[326]218#ifdef ZEND_CATCH
219    case ZEND_CATCH:
220        fi->jmpout_ext = (int) opline->extended_value;
[1278]221        fi->fall = 1;
222        return SUCCESS;
[326]223#endif
224
[308]225    default:
226        return FAILURE;
227    }
228}
229/* }}} */
[543]230#ifdef XCACHE_DEBUG
[1276]231static void op_snprint(zend_op_array *op_array, char *buf, int size, zend_uchar op_type, znode_op *op) /* {{{ */
[331]232{
[716]233    switch (op_type) {
[331]234    case IS_CONST:
235        {
236            zval result;
[716]237            zval *zv = &Z_OP_CONSTANT(*op);
[331]238            TSRMLS_FETCH();
[308]239
[1276]240            php_output_start_default(TSRMLS_C);
[331]241            php_var_export(&zv, 1 TSRMLS_CC);
[1276]242            php_output_get_contents(&result TSRMLS_CC); 
[1280]243            php_output_discard(TSRMLS_C);
[331]244
245            snprintf(buf, size, Z_STRVAL(result));
246            zval_dtor(&result);
247        }
248        break;
249
250    case IS_TMP_VAR:
[716]251        snprintf(buf, size, "t@%d", Z_OP(*op).var);
[331]252        break;
253
254    case XCACHE_IS_CV:
255    case IS_VAR:
[716]256        snprintf(buf, size, "v@%d", Z_OP(*op).var);
[331]257        break;
258
259    case IS_UNUSED:
[716]260        if (Z_OP(*op).opline_num) {
[1250]261            snprintf(buf, size, "u#%d", Z_OP(*op).opline_num);
[331]262        }
263        else {
264            snprintf(buf, size, "-");
265        }
266        break;
267
268    default:
[1276]269        snprintf(buf, size, "%d %d", op_type, Z_OP(*op).var);
[331]270    }
271}
272/* }}} */
[1276]273static void op_print(zend_op_array *op_array, int line, zend_op *first, zend_op *end) /* {{{ */
[331]274{
275    zend_op *opline;
276    for (opline = first; opline < end; opline ++) {
277        char buf_r[20];
278        char buf_1[20];
279        char buf_2[20];
[1276]280        op_snprint(op_array, buf_r, sizeof(buf_r), Z_OP_TYPE(opline->result), &opline->result);
281        op_snprint(op_array, buf_1, sizeof(buf_1), Z_OP_TYPE(opline->op1),    &opline->op1);
282        op_snprint(op_array, buf_2, sizeof(buf_2), Z_OP_TYPE(opline->op2),    &opline->op2);
[333]283        fprintf(stderr,
[1276]284                "%3d %3lu"
[333]285                " %-25s%-5s%-20s%-20s%5lu\r\n"
[1276]286                , opline->lineno, (long) (opline - first + line)
[333]287                , xc_get_opcode(opline->opcode), buf_r, buf_1, buf_2, opline->extended_value);
[331]288    }
289}
290/* }}} */
291#endif
292
[308]293/*
294 * basic block functions
295 */
296
297static bb_t *bb_new_ex(zend_op *opcodes, int count) /* {{{ */
298{
299    bb_t *bb = (bb_t *) ecalloc(sizeof(bb_t), 1);
300
[312]301    bb->fall       = BBID_INVALID;
[657]302#ifdef ZEND_ENGINE_2
[326]303    bb->catch      = BBID_INVALID;
[657]304#endif
[1278]305#ifdef ZEND_ENGINE_2_5
306    bb->finally    = BBID_INVALID;
307#endif
[308]308
309    if (opcodes) {
310        bb->alloc   = 0;
311        bb->size    = bb->count = count;
312        bb->opcodes = opcodes;
313    }
314    else {
315        bb->alloc   = 1;
316        bb->size    = bb->count = 8;
317        bb->opcodes = ecalloc(sizeof(zend_op), bb->size);
318    }
319
320    return bb;
321}
322/* }}} */
323#define bb_new() bb_new_ex(NULL, 0)
324static void bb_destroy(bb_t *bb) /* {{{ */
325{
326    if (bb->alloc) {
327        efree(bb->opcodes);
328    }
329    efree(bb);
330}
331/* }}} */
[543]332#ifdef XCACHE_DEBUG
[1276]333static void bb_print(bb_t *bb, zend_op_array *op_array) /* {{{ */
[312]334{
[1276]335    int line = bb->opcodes - op_array->opcodes;
[326]336    op_flowinfo_t fi;
337    zend_op *last = bb->opcodes + bb->count - 1;
[1278]338    bbid_t catchbbid = ZESW(BBID_INVALID, bb->catch);
339    bbid_t finallybbid;
340#ifdef ZEND_ENGINE_2_5
341    finallybbid = BBID_INVALID;
[657]342#else
[1278]343    finallybbid = bb->finally;
[657]344#endif
[326]345
346    op_get_flowinfo(&fi, last);
347
[312]348    fprintf(stderr,
[333]349            "\r\n==== #%-3d cnt:%-3d lno:%-3d"
[312]350            " %c%c"
[1279]351            " op1:%-3d op2:%-3d ext:%-3d fal:%-3d cat:%-3d fnl:%-3d %s ====\r\n"
[331]352            , bb->id, bb->count, bb->alloc ? -1 : line
[312]353            , bb->used ? 'U' : ' ', bb->alloc ? 'A' : ' '
[1279]354            , fi.jmpout_op1, fi.jmpout_op2, fi.jmpout_ext, bb->fall, catchbbid, finallybbid, xc_get_opcode(last->opcode)
[312]355            );
[1276]356    op_print(op_array, line, bb->opcodes, last + 1);
[312]357}
358/* }}} */
359#endif
360
[330]361static bb_t *bbs_get(bbs_t *bbs, int n) /* {{{ */
362{
363    return (bb_t *) xc_stack_get(bbs, n);
364}
365/* }}} */
366static int bbs_count(bbs_t *bbs) /* {{{ */
367{
368    return xc_stack_count(bbs);
369}
370/* }}} */
[308]371static void bbs_destroy(bbs_t *bbs) /* {{{ */
372{
373    bb_t *bb;
[326]374    while (bbs_count(bbs)) {
[308]375        bb = (bb_t *) xc_stack_pop(bbs);
376        bb_destroy(bb);
377    }
[313]378    xc_stack_destroy(bbs);
[308]379}
380/* }}} */
[543]381#ifdef XCACHE_DEBUG
[1276]382static void bbs_print(bbs_t *bbs, zend_op_array *op_array) /* {{{ */
[312]383{
384    int i;
385    for (i = 0; i < xc_stack_count(bbs); i ++) {
[1276]386        bb_print(bbs_get(bbs, i), op_array);
[312]387    }
388}
389/* }}} */
390#endif
[308]391#define bbs_init(bbs) xc_stack_init_ex(bbs, 16)
392static bb_t *bbs_add_bb(bbs_t *bbs, bb_t *bb) /* {{{ */
393{
394    bb->id = (bbid_t) xc_stack_count(bbs);
395    xc_stack_push(bbs, (void *) bb);
396    return bb;
397}
398/* }}} */
399static bb_t *bbs_new_bb_ex(bbs_t *bbs, zend_op *opcodes, int count) /* {{{ */
400{
401    return bbs_add_bb(bbs, bb_new_ex(opcodes, count));
402}
403/* }}} */
[326]404static int bbs_build_from(bbs_t *bbs, zend_op_array *op_array, int count) /* {{{ */
[308]405{
[326]406    int i, start;
[1279]407    bb_t *bb;
[312]408    bbid_t id;
[326]409    op_flowinfo_t fi;
410    zend_op *opline;
[1279]411    ALLOCA_FLAG(opline_infos_use_heap)
412    typedef struct {
413        zend_bool isbbhead;
414        bbid_t bbid;
[1278]415#ifdef ZEND_ENGINE_2
[1279]416        bbid_t catchbbid;
[1278]417#endif
418#ifdef ZEND_ENGINE_2_5
[1279]419        bbid_t finallybbid;
[1278]420#endif
[1279]421    } oplineinfo_t;
422    oplineinfo_t *oplineinfos = xc_do_alloca(count * sizeof(oplineinfo_t), opline_infos_use_heap);
[308]423
[1279]424    memset(oplineinfos, 0, count * sizeof(oplineinfo_t));
425
[312]426    /* {{{ mark jmpin/jumpout */
[1279]427    oplineinfos[0].isbbhead = 1;
[308]428    for (i = 0; i < count; i ++) {
[326]429        if (op_get_flowinfo(&fi, &op_array->opcodes[i]) == SUCCESS) {
430            if (fi.jmpout_op1 != XC_OPNUM_INVALID) {
[1279]431                oplineinfos[fi.jmpout_op1].isbbhead = 1;
[308]432            }
[326]433            if (fi.jmpout_op2 != XC_OPNUM_INVALID) {
[1279]434                oplineinfos[fi.jmpout_op2].isbbhead = 1;
[308]435            }
[326]436            if (fi.jmpout_ext != XC_OPNUM_INVALID) {
[1279]437                oplineinfos[fi.jmpout_ext].isbbhead = 1;
[308]438            }
[326]439            if (i + 1 < count) {
[1279]440                oplineinfos[i + 1].isbbhead = 1;
[326]441            }
[308]442        }
443    }
[657]444#ifdef ZEND_ENGINE_2
[326]445    /* mark try start */
446    for (i = 0; i < op_array->last_try_catch; i ++) {
[1279]447        oplineinfos[op_array->try_catch_array[i].try_op].isbbhead = 1;
[326]448    }
[657]449#endif
[312]450    /* }}} */
[326]451    /* {{{ fill op lines with newly allocated id */
[312]452    for (i = 0; i < count; i ++) {
[1279]453        oplineinfos[i].bbid = BBID_INVALID;
[312]454    }
[308]455
[326]456    id = -1;
457    for (i = 0; i < count; i ++) {
[1279]458        if (oplineinfos[i].isbbhead) {
[326]459            id ++;
[312]460        }
[1279]461        oplineinfos[i].bbid = id;
[326]462        TRACE("bbids[%d] = %d", i, id);
[308]463    }
[312]464    /* }}} */
[657]465#ifdef ZEND_ENGINE_2
[326]466    /* {{{ fill op lines with catch id */
467    for (i = 0; i < count; i ++) {
[1279]468        oplineinfos[i].catchbbid = BBID_INVALID;
469#   ifdef ZEND_ENGINE_2_5
470        oplineinfos[i].finallybbid = BBID_INVALID;
471#   endif
[326]472    }
473
474    for (i = 0; i < op_array->last_try_catch; i ++) {
[1008]475        zend_uint j;
[326]476        zend_try_catch_element *e = &op_array->try_catch_array[i];
477        for (j = e->try_op; j < e->catch_op; j ++) {
[1279]478            oplineinfos[j].catchbbid = oplineinfos[e->catch_op].bbid;
[326]479        }
[1279]480#   ifdef ZEND_ENGINE_2_5
481        for (j = e->finally_op; j < e->finally_end; j ++) {
482            oplineinfos[j].finallybbid = oplineinfos[e->finally_op].bbid;
483        }
484#   endif
[326]485    }
[543]486#ifdef XCACHE_DEBUG
[326]487    for (i = 0; i < count; i ++) {
[1279]488#   ifdef ZEND_ENGINE_2_5
489        TRACE("catch/finallybbids[%d] = %d, %d", i, oplineinfos[i].catchbbid, oplineinfos[i].finallybbid);
490#   else
491        TRACE("catchbbids[%d] = %d", i, oplineinfos[i].catchbbid);
492#   endif
[326]493    }
494#endif
495    /* }}} */
[657]496#endif
[312]497    /* {{{ create basic blocks */
[326]498    start = 0;
[312]499    id = 0;
[326]500    /* loop over to deal with the last block */
501    for (i = 1; i <= count; i ++) {
[1279]502        if (i < count && id == oplineinfos[i].bbid) {
[312]503            continue;
504        }
[308]505
[326]506        opline = op_array->opcodes + start;
[1279]507        bb = bbs_new_bb_ex(bbs, opline, i - start);
[657]508#ifdef ZEND_ENGINE_2
[1279]509        bb->catch = oplineinfos[start].catchbbid;
[657]510#endif
[1279]511#ifdef ZEND_ENGINE_2_5
512        bb->finally = oplineinfos[start].finallybbid;
513#endif
[326]514
515        /* last */
[1279]516        opline = bb->opcodes + bb->count - 1;
[326]517        if (op_get_flowinfo(&fi, opline) == SUCCESS) {
518            if (fi.jmpout_op1 != XC_OPNUM_INVALID) {
[1279]519                Z_OP(opline->op1).opline_num = oplineinfos[fi.jmpout_op1].bbid;
[716]520                assert(Z_OP(opline->op1).opline_num != BBID_INVALID);
[312]521            }
[326]522            if (fi.jmpout_op2 != XC_OPNUM_INVALID) {
[1279]523                Z_OP(opline->op2).opline_num = oplineinfos[fi.jmpout_op2].bbid;
[716]524                assert(Z_OP(opline->op2).opline_num != BBID_INVALID);
[312]525            }
[326]526            if (fi.jmpout_ext != XC_OPNUM_INVALID) {
[1279]527                opline->extended_value = oplineinfos[fi.jmpout_ext].bbid;
[326]528                assert(opline->extended_value != BBID_INVALID);
[312]529            }
[326]530            if (fi.fall && i + 1 < count) {
[1279]531                bb->fall = oplineinfos[i + 1].bbid;
532                TRACE("fall %d", bb->fall);
533                assert(bb->fall != BBID_INVALID);
[312]534            }
535        }
[326]536        if (i >= count) {
537            break;
538        }
[332]539        start = i;
[1279]540        id = oplineinfos[i].bbid;
[312]541    }
542    /* }}} */
543
[1279]544    xc_free_alloca(oplineinfos, opline_infos_use_heap);
[308]545    return SUCCESS;
546}
547/* }}} */
[330]548static void bbs_restore_opnum(bbs_t *bbs, zend_op_array *op_array) /* {{{ */
[326]549{
550    int i;
[657]551#ifdef ZEND_ENGINE_2
[330]552    bbid_t lasttrybbid;
[369]553    bbid_t lastcatchbbid;
[657]554#endif
[1278]555#ifdef ZEND_ENGINE_2_5
556    bbid_t lastfinallybbid;
557#endif
[330]558
[326]559    for (i = 0; i < bbs_count(bbs); i ++) {
560        op_flowinfo_t fi;
561        bb_t *bb = bbs_get(bbs, i);
562        zend_op *last = bb->opcodes + bb->count - 1;
[308]563
[326]564        if (op_get_flowinfo(&fi, last) == SUCCESS) {
565            if (fi.jmpout_op1 != XC_OPNUM_INVALID) {
[716]566                Z_OP(last->op1).opline_num = bbs_get(bbs, fi.jmpout_op1)->opnum;
567                assert(Z_OP(last->op1).opline_num != BBID_INVALID);
[326]568            }
569            if (fi.jmpout_op2 != XC_OPNUM_INVALID) {
[716]570                Z_OP(last->op2).opline_num = bbs_get(bbs, fi.jmpout_op2)->opnum;
571                assert(Z_OP(last->op2).opline_num != BBID_INVALID);
[326]572            }
573            if (fi.jmpout_ext != XC_OPNUM_INVALID) {
574                last->extended_value = bbs_get(bbs, fi.jmpout_ext)->opnum;
575                assert(last->extended_value != BBID_INVALID);
576            }
577        }
578    }
579
[657]580#ifdef ZEND_ENGINE_2
[369]581    lasttrybbid   = BBID_INVALID;
582    lastcatchbbid = BBID_INVALID;
[1278]583#ifdef ZEND_ENGINE_2_5
584    lastfinallybbid = BBID_INVALID;
585#endif
[330]586    op_array->last_try_catch = 0;
587    for (i = 0; i < bbs_count(bbs); i ++) {
588        bb_t *bb = bbs_get(bbs, i);
589
[369]590        if (lastcatchbbid != bb->catch) {
[1278]591            if (lasttrybbid != BBID_INVALID) {
[330]592                int try_catch_offset = op_array->last_try_catch ++;
593
594                op_array->try_catch_array = erealloc(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch);
595                op_array->try_catch_array[try_catch_offset].try_op = bbs_get(bbs, lasttrybbid)->opnum;
[1278]596                op_array->try_catch_array[try_catch_offset].catch_op = lastcatchbbid != BBID_INVALID ? bbs_get(bbs, lastcatchbbid)->opnum : 0;
[1279]597                assert(lastcatchbbid != BBID_INVALID);
[1278]598#ifdef ZEND_ENGINE_2_5
599                op_array->try_catch_array[try_catch_offset].finally_op = lastfinallybbid != BBID_INVALID ? bbs_get(bbs, lastfinallybbid)->opnum : 0;
600#endif
[330]601            }
[369]602            lasttrybbid   = i;
603            lastcatchbbid = bb->catch;
[1278]604#ifdef ZEND_ENGINE_2_5
605            lastfinallybbid = bb->finally;
606#endif
[330]607        }
608    }
609    /* it is impossible to have last bb catched */
[657]610#endif
[326]611}
612/* }}} */
613
[308]614/*
615 * optimize
616 */
[1]617static int xc_optimize_op_array(zend_op_array *op_array TSRMLS_DC) /* {{{ */
618{
[308]619    bbs_t bbs;
620
[1]621    if (op_array->type != ZEND_USER_FUNCTION) {
622        return 0;
623    }
[335]624
[543]625#ifdef XCACHE_DEBUG
[312]626#   if 0
[308]627    TRACE("optimize file: %s", op_array->filename);
628    xc_dprint_zend_op_array(op_array, 0 TSRMLS_CC);
[312]629#   endif
[1276]630    op_print(op_array, 0, op_array->opcodes, op_array->opcodes + op_array->last);
[308]631#endif
632
[312]633    if (op_array_convert_switch(op_array) == SUCCESS) {
[308]634        bbs_init(&bbs);
[326]635        if (bbs_build_from(&bbs, op_array, op_array->last) == SUCCESS) {
636            int i;
[543]637#ifdef XCACHE_DEBUG
[1276]638            bbs_print(&bbs, op_array);
[312]639#endif
[326]640            /* TODO: calc opnum after basic block move */
641            for (i = 0; i < bbs_count(&bbs); i ++) {
642                bb_t *bb = bbs_get(&bbs, i);
643                bb->opnum = bb->opcodes - op_array->opcodes;
644            }
[330]645            bbs_restore_opnum(&bbs, op_array);
[308]646        }
647        bbs_destroy(&bbs);
648    }
649
[543]650#ifdef XCACHE_DEBUG
[312]651#   if 0
[308]652    TRACE("%s", "after compiles");
653    xc_dprint_zend_op_array(op_array, 0 TSRMLS_CC);
[312]654#   endif
[1276]655    op_print(op_array, 0, op_array->opcodes, op_array->opcodes + op_array->last);
[308]656#endif
[1]657    return 0;
658}
659/* }}} */
[1026]660static void xc_optimizer_op_array_handler(zend_op_array *op_array) /* {{{ */
[335]661{
[477]662    TSRMLS_FETCH();
663    if (XG(optimizer)) {
664        xc_optimize_op_array(op_array TSRMLS_CC);
[316]665    }
[1]666}
667/* }}} */
[1026]668
[1033]669static int xc_coverager_zend_startup(zend_extension *extension) /* {{{ */
[1026]670{
671    return SUCCESS;
672}
673/* }}} */
[1033]674static void xc_coverager_zend_shutdown(zend_extension *extension) /* {{{ */
[1026]675{
676}
677/* }}} */
678/* {{{ zend extension definition structure */
679static zend_extension xc_optimizer_zend_extension_entry = {
680    XCACHE_NAME " Optimizer",
681    XCACHE_VERSION,
682    XCACHE_AUTHOR,
683    XCACHE_URL,
684    XCACHE_COPYRIGHT,
[1033]685    xc_coverager_zend_startup,
686    xc_coverager_zend_shutdown,
[1026]687    NULL,           /* activate_func_t */
688    NULL,           /* deactivate_func_t */
689    NULL,           /* message_handler_func_t */
690    xc_optimizer_op_array_handler,
691    NULL,           /* statement_handler_func_t */
692    NULL,           /* fcall_begin_handler_func_t */
693    NULL,           /* fcall_end_handler_func_t */
694    NULL,           /* op_array_ctor_func_t */
695    NULL,           /* op_array_dtor_func_t */
696    STANDARD_ZEND_EXTENSION_PROPERTIES
697};
698/* }}} */
699
700/* {{{ ini */
701PHP_INI_BEGIN()
702    STD_PHP_INI_BOOLEAN("xcache.optimizer",              "0", PHP_INI_ALL,    OnUpdateBool,        optimizer,         zend_xcache_globals, xcache_globals)
703PHP_INI_END()
704/* }}} */
705static PHP_MINFO_FUNCTION(xcache_optimizer) /* {{{ */
706{
707    php_info_print_table_start();
[1043]708    php_info_print_table_row(2, "XCache Optimizer Module", "enabled");
[1026]709    php_info_print_table_end();
710
711    DISPLAY_INI_ENTRIES();
712}
713/* }}} */
714static PHP_MINIT_FUNCTION(xcache_optimizer) /* {{{ */
715{
716    REGISTER_INI_ENTRIES();
[1047]717    return xcache_zend_extension_add(&xc_optimizer_zend_extension_entry, 0);
[1026]718}
719/* }}} */
720static PHP_MSHUTDOWN_FUNCTION(xcache_optimizer) /* {{{ */
721{
722    UNREGISTER_INI_ENTRIES();
[1045]723    return xcache_zend_extension_remove(&xc_optimizer_zend_extension_entry);
[1026]724}
725/* }}} */
726static zend_module_entry xcache_optimizer_module_entry = { /* {{{ */
727    STANDARD_MODULE_HEADER,
[1043]728    XCACHE_NAME " Optimizer",
[1026]729    NULL,
730    PHP_MINIT(xcache_optimizer),
731    PHP_MSHUTDOWN(xcache_optimizer),
732    NULL,
733    NULL,
734    PHP_MINFO(xcache_optimizer),
735    XCACHE_VERSION,
736#ifdef PHP_GINIT
737    NO_MODULE_GLOBALS,
738#endif
739#ifdef ZEND_ENGINE_2
740    NULL,
741#else
742    NULL,
743    NULL,
744#endif
745    STANDARD_MODULE_PROPERTIES_EX
746};
747/* }}} */
748int xc_optimizer_startup_module() /* {{{ */
749{
750    return zend_startup_module(&xcache_optimizer_module_entry);
751}
752/* }}} */
Note: See TracBrowser for help on using the repository browser.