source: trunk/mod_optimizer/xc_optimizer.c @ 1279

Last change on this file since 1279 was 1279, checked in by moo, 14 months ago

optimizer: WIP improve finally handling

  • Property svn:eol-style set to native
File size: 17.4 KB
Line 
1#if 1
2#   define XCACHE_DEBUG
3#endif
4
5#include "xc_optimizer.h"
6#include "xcache/xc_extension.h"
7#include "xcache/xc_ini.h"
8#include "xcache/xc_utils.h"
9#include "util/xc_stack.h"
10#include "util/xc_trace.h"
11#include "xcache_globals.h"
12
13#include "ext/standard/info.h"
14
15#ifdef XCACHE_DEBUG
16#   include "xc_processor.h"
17#   include "xcache/xc_const_string.h"
18#   include "ext/standard/php_var.h"
19#endif
20
21#ifdef IS_CV
22#   define XCACHE_IS_CV IS_CV
23#else
24#   define XCACHE_IS_CV 16
25#endif
26
27#ifdef ZEND_ENGINE_2_4
28#   undef Z_OP_CONSTANT
29/* Z_OP_CONSTANT is used before pass_two is applied */
30#   define Z_OP_CONSTANT(op) op_array->literals[(op).constant].constant
31#endif
32
33typedef zend_uint bbid_t;
34#define BBID_INVALID ((bbid_t) -1)
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
45    bbid_t     fall;
46#ifdef ZEND_ENGINE_2
47    bbid_t     catch;
48#endif
49#ifdef ZEND_ENGINE_2_5
50    bbid_t     finally;
51#endif
52
53    zend_uint  opnum; /* opnum after joining basic block */
54} bb_t;
55/* }}} */
56
57/* basic blocks */
58typedef xc_stack_t bbs_t;
59
60/* op array helper functions */
61static int op_array_convert_switch(zend_op_array *op_array) /* {{{ */
62{
63    zend_uint i;
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;
72        zend_bool can_convert = 1;
73        int array_offset, nest_levels;
74
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
83            continue;
84
85        default:
86            continue;
87        }
88
89        if (Z_OP_TYPE(opline->op2) != IS_CONST
90         || Z_OP_CONSTANT(opline->op2).type != IS_LONG) {
91            return FAILURE;
92        }
93
94        nest_levels = Z_OP_CONSTANT(opline->op2).value.lval;
95
96        array_offset = Z_OP(opline->op1).opline_num;
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:
108#ifdef EXT_TYPE_FREE_ON_RETURN
109                    if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN))
110#endif
111                    {
112                        can_convert = 0;
113                    }
114                    break;
115                }
116            }
117            array_offset = jmp_to->parent;
118        } while (--nest_levels > 0);
119
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;
133        }
134    }
135
136    return SUCCESS;
137}
138/* }}} */
139/* {{{ op_flowinfo helper func */
140enum {
141    XC_OPNUM_INVALID = -1
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)
150{
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
159    switch (opline->opcode) {
160#ifdef ZEND_HANDLE_EXCEPTION
161    case ZEND_HANDLE_EXCEPTION:
162#endif
163    case ZEND_RETURN:
164#ifdef ZEND_FAST_RET
165    case ZEND_FAST_RET:
166#endif
167#ifdef ZEND_GENERATOR_RETURN
168    case ZEND_GENERATOR_RETURN:
169#endif
170    case ZEND_EXIT:
171        return SUCCESS; /* no fall */
172
173#ifdef ZEND_GOTO
174    case ZEND_GOTO:
175#endif
176    case ZEND_JMP:
177        fi->jmpout_op1 = Z_OP(opline->op1).opline_num;
178        return SUCCESS; /* no fall */
179
180#ifdef ZEND_FAST_CALL
181    case ZEND_FAST_CALL:
182        fi->jmpout_op1 = Z_OP(opline->op1).opline_num;
183        if (opline->extended_value) {
184            fi->jmpout_op2 = Z_OP(opline->op2).opline_num;
185        }
186        return SUCCESS; /* no fall */
187#endif
188
189    case ZEND_JMPZNZ:
190        fi->jmpout_op2 = Z_OP(opline->op2).opline_num;
191        fi->jmpout_ext = (int) opline->extended_value;
192        return SUCCESS; /* no fall */
193
194    case ZEND_JMPZ:
195    case ZEND_JMPNZ:
196    case ZEND_JMPZ_EX:
197    case ZEND_JMPNZ_EX:
198#ifdef ZEND_JMP_SET
199    case ZEND_JMP_SET:
200#endif
201#ifdef ZEND_JMP_SET_VAR
202    case ZEND_JMP_SET_VAR:
203#endif
204#ifdef ZEND_JMP_NO_CTOR
205    case ZEND_JMP_NO_CTOR:
206#endif
207#ifdef ZEND_NEW
208    case ZEND_NEW:
209#endif
210#ifdef ZEND_FE_RESET
211    case ZEND_FE_RESET:
212#endif     
213    case ZEND_FE_FETCH:
214        fi->jmpout_op2 = Z_OP(opline->op2).opline_num;
215        fi->fall = 1;
216        return SUCCESS;
217
218#ifdef ZEND_CATCH
219    case ZEND_CATCH:
220        fi->jmpout_ext = (int) opline->extended_value;
221        fi->fall = 1;
222        return SUCCESS;
223#endif
224
225    default:
226        return FAILURE;
227    }
228}
229/* }}} */
230#ifdef XCACHE_DEBUG
231static void op_snprint(zend_op_array *op_array, char *buf, int size, zend_uchar op_type, znode_op *op) /* {{{ */
232{
233    switch (op_type) {
234    case IS_CONST:
235        {
236            zval result;
237            zval *zv = &Z_OP_CONSTANT(*op);
238            TSRMLS_FETCH();
239
240            php_output_start_default(TSRMLS_C);
241            php_var_export(&zv, 1 TSRMLS_CC);
242            php_output_get_contents(&result TSRMLS_CC); 
243            php_output_end(TSRMLS_C);
244
245            snprintf(buf, size, Z_STRVAL(result));
246            zval_dtor(&result);
247        }
248        break;
249
250    case IS_TMP_VAR:
251        snprintf(buf, size, "t@%d", Z_OP(*op).var);
252        break;
253
254    case XCACHE_IS_CV:
255    case IS_VAR:
256        snprintf(buf, size, "v@%d", Z_OP(*op).var);
257        break;
258
259    case IS_UNUSED:
260        if (Z_OP(*op).opline_num) {
261            snprintf(buf, size, "u#%d", Z_OP(*op).opline_num);
262        }
263        else {
264            snprintf(buf, size, "-");
265        }
266        break;
267
268    default:
269        snprintf(buf, size, "%d %d", op_type, Z_OP(*op).var);
270    }
271}
272/* }}} */
273static void op_print(zend_op_array *op_array, int line, zend_op *first, zend_op *end) /* {{{ */
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];
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);
283        fprintf(stderr,
284                "%3d %3lu"
285                " %-25s%-5s%-20s%-20s%5lu\r\n"
286                , opline->lineno, (long) (opline - first + line)
287                , xc_get_opcode(opline->opcode), buf_r, buf_1, buf_2, opline->extended_value);
288    }
289}
290/* }}} */
291#endif
292
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
301    bb->fall       = BBID_INVALID;
302#ifdef ZEND_ENGINE_2
303    bb->catch      = BBID_INVALID;
304#endif
305#ifdef ZEND_ENGINE_2_5
306    bb->finally    = BBID_INVALID;
307#endif
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/* }}} */
332#ifdef XCACHE_DEBUG
333static void bb_print(bb_t *bb, zend_op_array *op_array) /* {{{ */
334{
335    int line = bb->opcodes - op_array->opcodes;
336    op_flowinfo_t fi;
337    zend_op *last = bb->opcodes + bb->count - 1;
338    bbid_t catchbbid = ZESW(BBID_INVALID, bb->catch);
339    bbid_t finallybbid;
340#ifdef ZEND_ENGINE_2_5
341    finallybbid = BBID_INVALID;
342#else
343    finallybbid = bb->finally;
344#endif
345
346    op_get_flowinfo(&fi, last);
347
348    fprintf(stderr,
349            "\r\n==== #%-3d cnt:%-3d lno:%-3d"
350            " %c%c"
351            " op1:%-3d op2:%-3d ext:%-3d fal:%-3d cat:%-3d fnl:%-3d %s ====\r\n"
352            , bb->id, bb->count, bb->alloc ? -1 : line
353            , bb->used ? 'U' : ' ', bb->alloc ? 'A' : ' '
354            , fi.jmpout_op1, fi.jmpout_op2, fi.jmpout_ext, bb->fall, catchbbid, finallybbid, xc_get_opcode(last->opcode)
355            );
356    op_print(op_array, line, bb->opcodes, last + 1);
357}
358/* }}} */
359#endif
360
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/* }}} */
371static void bbs_destroy(bbs_t *bbs) /* {{{ */
372{
373    bb_t *bb;
374    while (bbs_count(bbs)) {
375        bb = (bb_t *) xc_stack_pop(bbs);
376        bb_destroy(bb);
377    }
378    xc_stack_destroy(bbs);
379}
380/* }}} */
381#ifdef XCACHE_DEBUG
382static void bbs_print(bbs_t *bbs, zend_op_array *op_array) /* {{{ */
383{
384    int i;
385    for (i = 0; i < xc_stack_count(bbs); i ++) {
386        bb_print(bbs_get(bbs, i), op_array);
387    }
388}
389/* }}} */
390#endif
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/* }}} */
404static int bbs_build_from(bbs_t *bbs, zend_op_array *op_array, int count) /* {{{ */
405{
406    int i, start;
407    bb_t *bb;
408    bbid_t id;
409    op_flowinfo_t fi;
410    zend_op *opline;
411    ALLOCA_FLAG(opline_infos_use_heap)
412    typedef struct {
413        zend_bool isbbhead;
414        bbid_t bbid;
415#ifdef ZEND_ENGINE_2
416        bbid_t catchbbid;
417#endif
418#ifdef ZEND_ENGINE_2_5
419        bbid_t finallybbid;
420#endif
421    } oplineinfo_t;
422    oplineinfo_t *oplineinfos = xc_do_alloca(count * sizeof(oplineinfo_t), opline_infos_use_heap);
423
424    memset(oplineinfos, 0, count * sizeof(oplineinfo_t));
425
426    /* {{{ mark jmpin/jumpout */
427    oplineinfos[0].isbbhead = 1;
428    for (i = 0; i < count; i ++) {
429        if (op_get_flowinfo(&fi, &op_array->opcodes[i]) == SUCCESS) {
430            if (fi.jmpout_op1 != XC_OPNUM_INVALID) {
431                oplineinfos[fi.jmpout_op1].isbbhead = 1;
432            }
433            if (fi.jmpout_op2 != XC_OPNUM_INVALID) {
434                oplineinfos[fi.jmpout_op2].isbbhead = 1;
435            }
436            if (fi.jmpout_ext != XC_OPNUM_INVALID) {
437                oplineinfos[fi.jmpout_ext].isbbhead = 1;
438            }
439            if (i + 1 < count) {
440                oplineinfos[i + 1].isbbhead = 1;
441            }
442        }
443    }
444#ifdef ZEND_ENGINE_2
445    /* mark try start */
446    for (i = 0; i < op_array->last_try_catch; i ++) {
447        oplineinfos[op_array->try_catch_array[i].try_op].isbbhead = 1;
448    }
449#endif
450    /* }}} */
451    /* {{{ fill op lines with newly allocated id */
452    for (i = 0; i < count; i ++) {
453        oplineinfos[i].bbid = BBID_INVALID;
454    }
455
456    id = -1;
457    for (i = 0; i < count; i ++) {
458        if (oplineinfos[i].isbbhead) {
459            id ++;
460        }
461        oplineinfos[i].bbid = id;
462        TRACE("bbids[%d] = %d", i, id);
463    }
464    /* }}} */
465#ifdef ZEND_ENGINE_2
466    /* {{{ fill op lines with catch id */
467    for (i = 0; i < count; i ++) {
468        oplineinfos[i].catchbbid = BBID_INVALID;
469#   ifdef ZEND_ENGINE_2_5
470        oplineinfos[i].finallybbid = BBID_INVALID;
471#   endif
472    }
473
474    for (i = 0; i < op_array->last_try_catch; i ++) {
475        zend_uint j;
476        zend_try_catch_element *e = &op_array->try_catch_array[i];
477        for (j = e->try_op; j < e->catch_op; j ++) {
478            oplineinfos[j].catchbbid = oplineinfos[e->catch_op].bbid;
479        }
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
485    }
486#ifdef XCACHE_DEBUG
487    for (i = 0; i < count; i ++) {
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
493    }
494#endif
495    /* }}} */
496#endif
497    /* {{{ create basic blocks */
498    start = 0;
499    id = 0;
500    /* loop over to deal with the last block */
501    for (i = 1; i <= count; i ++) {
502        if (i < count && id == oplineinfos[i].bbid) {
503            continue;
504        }
505
506        opline = op_array->opcodes + start;
507        bb = bbs_new_bb_ex(bbs, opline, i - start);
508#ifdef ZEND_ENGINE_2
509        bb->catch = oplineinfos[start].catchbbid;
510#endif
511#ifdef ZEND_ENGINE_2_5
512        bb->finally = oplineinfos[start].finallybbid;
513#endif
514
515        /* last */
516        opline = bb->opcodes + bb->count - 1;
517        if (op_get_flowinfo(&fi, opline) == SUCCESS) {
518            if (fi.jmpout_op1 != XC_OPNUM_INVALID) {
519                Z_OP(opline->op1).opline_num = oplineinfos[fi.jmpout_op1].bbid;
520                assert(Z_OP(opline->op1).opline_num != BBID_INVALID);
521            }
522            if (fi.jmpout_op2 != XC_OPNUM_INVALID) {
523                Z_OP(opline->op2).opline_num = oplineinfos[fi.jmpout_op2].bbid;
524                assert(Z_OP(opline->op2).opline_num != BBID_INVALID);
525            }
526            if (fi.jmpout_ext != XC_OPNUM_INVALID) {
527                opline->extended_value = oplineinfos[fi.jmpout_ext].bbid;
528                assert(opline->extended_value != BBID_INVALID);
529            }
530            if (fi.fall && i + 1 < count) {
531                bb->fall = oplineinfos[i + 1].bbid;
532                TRACE("fall %d", bb->fall);
533                assert(bb->fall != BBID_INVALID);
534            }
535        }
536        if (i >= count) {
537            break;
538        }
539        start = i;
540        id = oplineinfos[i].bbid;
541    }
542    /* }}} */
543
544    xc_free_alloca(oplineinfos, opline_infos_use_heap);
545    return SUCCESS;
546}
547/* }}} */
548static void bbs_restore_opnum(bbs_t *bbs, zend_op_array *op_array) /* {{{ */
549{
550    int i;
551#ifdef ZEND_ENGINE_2
552    bbid_t lasttrybbid;
553    bbid_t lastcatchbbid;
554#endif
555#ifdef ZEND_ENGINE_2_5
556    bbid_t lastfinallybbid;
557#endif
558
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;
563
564        if (op_get_flowinfo(&fi, last) == SUCCESS) {
565            if (fi.jmpout_op1 != XC_OPNUM_INVALID) {
566                Z_OP(last->op1).opline_num = bbs_get(bbs, fi.jmpout_op1)->opnum;
567                assert(Z_OP(last->op1).opline_num != BBID_INVALID);
568            }
569            if (fi.jmpout_op2 != XC_OPNUM_INVALID) {
570                Z_OP(last->op2).opline_num = bbs_get(bbs, fi.jmpout_op2)->opnum;
571                assert(Z_OP(last->op2).opline_num != BBID_INVALID);
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
580#ifdef ZEND_ENGINE_2
581    lasttrybbid   = BBID_INVALID;
582    lastcatchbbid = BBID_INVALID;
583#ifdef ZEND_ENGINE_2_5
584    lastfinallybbid = BBID_INVALID;
585#endif
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
590        if (lastcatchbbid != bb->catch) {
591            if (lasttrybbid != BBID_INVALID) {
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;
596                op_array->try_catch_array[try_catch_offset].catch_op = lastcatchbbid != BBID_INVALID ? bbs_get(bbs, lastcatchbbid)->opnum : 0;
597                assert(lastcatchbbid != BBID_INVALID);
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
601            }
602            lasttrybbid   = i;
603            lastcatchbbid = bb->catch;
604#ifdef ZEND_ENGINE_2_5
605            lastfinallybbid = bb->finally;
606#endif
607        }
608    }
609    /* it is impossible to have last bb catched */
610#endif
611}
612/* }}} */
613
614/*
615 * optimize
616 */
617static int xc_optimize_op_array(zend_op_array *op_array TSRMLS_DC) /* {{{ */
618{
619    bbs_t bbs;
620
621    if (op_array->type != ZEND_USER_FUNCTION) {
622        return 0;
623    }
624
625#ifdef XCACHE_DEBUG
626#   if 0
627    TRACE("optimize file: %s", op_array->filename);
628    xc_dprint_zend_op_array(op_array, 0 TSRMLS_CC);
629#   endif
630    op_print(op_array, 0, op_array->opcodes, op_array->opcodes + op_array->last);
631#endif
632
633    if (op_array_convert_switch(op_array) == SUCCESS) {
634        bbs_init(&bbs);
635        if (bbs_build_from(&bbs, op_array, op_array->last) == SUCCESS) {
636            int i;
637#ifdef XCACHE_DEBUG
638            bbs_print(&bbs, op_array);
639#endif
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            }
645            bbs_restore_opnum(&bbs, op_array);
646        }
647        bbs_destroy(&bbs);
648    }
649
650#ifdef XCACHE_DEBUG
651#   if 0
652    TRACE("%s", "after compiles");
653    xc_dprint_zend_op_array(op_array, 0 TSRMLS_CC);
654#   endif
655    op_print(op_array, 0, op_array->opcodes, op_array->opcodes + op_array->last);
656#endif
657    return 0;
658}
659/* }}} */
660static void xc_optimizer_op_array_handler(zend_op_array *op_array) /* {{{ */
661{
662    TSRMLS_FETCH();
663    if (XG(optimizer)) {
664        xc_optimize_op_array(op_array TSRMLS_CC);
665    }
666}
667/* }}} */
668
669static int xc_coverager_zend_startup(zend_extension *extension) /* {{{ */
670{
671    return SUCCESS;
672}
673/* }}} */
674static void xc_coverager_zend_shutdown(zend_extension *extension) /* {{{ */
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,
685    xc_coverager_zend_startup,
686    xc_coverager_zend_shutdown,
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();
708    php_info_print_table_row(2, "XCache Optimizer Module", "enabled");
709    php_info_print_table_end();
710
711    DISPLAY_INI_ENTRIES();
712}
713/* }}} */
714static PHP_MINIT_FUNCTION(xcache_optimizer) /* {{{ */
715{
716    REGISTER_INI_ENTRIES();
717    return xcache_zend_extension_add(&xc_optimizer_zend_extension_entry, 0);
718}
719/* }}} */
720static PHP_MSHUTDOWN_FUNCTION(xcache_optimizer) /* {{{ */
721{
722    UNREGISTER_INI_ENTRIES();
723    return xcache_zend_extension_remove(&xc_optimizer_zend_extension_entry);
724}
725/* }}} */
726static zend_module_entry xcache_optimizer_module_entry = { /* {{{ */
727    STANDARD_MODULE_HEADER,
728    XCACHE_NAME " Optimizer",
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.