source: trunk/mod_optimizer/xc_optimizer.c

Last change on this file was 1561, checked in by moo, 6 weeks ago

fix build for older PHP

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