Changeset 326 in svn


Ignore:
Timestamp:
2006-12-10T18:17:59+01:00 (8 years ago)
Author:
Xuefer
Message:

optimizer: handle try/catch and make all opnum(opline_num) to be bbid_t inside optimization

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/optimizer.c

    r316 r326  
    1010#ifdef DEBUG
    1111#   include "processor.h"
     12#   include "const_string.h"
    1213#endif
    1314
     
    2627    int        size;
    2728
    28     bbid_t     jmpout_op1;
    29     bbid_t     jmpout_op2;
    30     bbid_t     jmpout_ext;
    3129    bbid_t     fall;
     30    bbid_t     catch;
     31
     32    int        opnum; /* opnum after joining basic block */
    3233} bb_t;
    3334/* }}} */
     
    3637typedef xc_stack_t bbs_t;
    3738
    38 /* oparray help functions */
     39/* op array helper functions */
    3940static int op_array_convert_switch(zend_op_array *op_array) /* {{{ */
    4041{
     
    102103}
    103104/* }}} */
    104 static int op_get_jmpout(int *jmpout_op1, int *jmpout_op2, int *jmpout_ext, zend_bool *fall, zend_op *opline) /* {{{ */
    105 {
     105/* {{{ op_flowinfo helper func */
     106enum {
     107    XC_OPNUM_INVALID = -1,
     108};
     109typedef struct {
     110    int       jmpout_op1;
     111    int       jmpout_op2;
     112    int       jmpout_ext;
     113    zend_bool fall;
     114} op_flowinfo_t;
     115static void op_flowinfo_init(op_flowinfo_t *fi)
     116{
     117    fi->jmpout_op1 = fi->jmpout_op2 = fi->jmpout_ext = XC_OPNUM_INVALID;
     118    fi->fall = 0;
     119}
     120/* }}} */
     121static int op_get_flowinfo(op_flowinfo_t *fi, zend_op *opline) /* {{{ */
     122{
     123    op_flowinfo_init(fi);
     124
    106125    /* break=will fall */
    107126    switch (opline->opcode) {
     127    case ZEND_HANDLE_EXCEPTION:
    108128    case ZEND_RETURN:
    109129    case ZEND_EXIT:
     
    111131
    112132    case ZEND_JMP:
    113         *jmpout_op1 = opline->op1.u.opline_num;
     133        fi->jmpout_op1 = opline->op1.u.opline_num;
    114134        return SUCCESS; /* no fall */
    115135
    116136    case ZEND_JMPZNZ:
    117         *jmpout_ext = opline->extended_value;
    118         *jmpout_op2 = opline->op2.u.opline_num;
    119         break;
     137        fi->jmpout_op2 = opline->op2.u.opline_num;
     138        fi->jmpout_ext = (int) opline->extended_value;
     139        return SUCCESS; /* no fall */
    120140
    121141    case ZEND_JMPZ:
     
    123143    case ZEND_JMPZ_EX:
    124144    case ZEND_JMPNZ_EX:
    125 #ifndef ZEND_ENGINE_2_1
    126         /* Pre-PHP 5.1 only */
     145#ifdef ZEND_JMP_NO_CTOR
    127146    case ZEND_JMP_NO_CTOR:
    128 #else       
     147#endif
     148#ifdef ZEND_NEW
    129149    case ZEND_NEW:
     150#endif
     151#ifdef ZEND_FE_RESET
    130152    case ZEND_FE_RESET:
    131153#endif     
    132154    case ZEND_FE_FETCH:
    133         *jmpout_op2 = opline->op2.u.opline_num;
     155        fi->jmpout_op2 = opline->op2.u.opline_num;
    134156        break;
     157
     158#ifdef ZEND_CATCH
     159    case ZEND_CATCH:
     160        fi->jmpout_ext = (int) opline->extended_value;
     161        break;
     162#endif
    135163
    136164    default:
     
    138166    }
    139167
    140     *fall = 1;
     168    fi->fall = 1;
    141169    return SUCCESS;
    142170}
     
    151179    bb_t *bb = (bb_t *) ecalloc(sizeof(bb_t), 1);
    152180
    153     bb->jmpout_op1 = BBID_INVALID;
    154     bb->jmpout_op2 = BBID_INVALID;
    155     bb->jmpout_ext = BBID_INVALID;
    156181    bb->fall       = BBID_INVALID;
     182    bb->catch      = BBID_INVALID;
    157183
    158184    if (opcodes) {
     
    182208static void bb_print(bb_t *bb, zend_op *opcodes) /* {{{ */
    183209{
     210    op_flowinfo_t fi;
     211    zend_op *last = bb->opcodes + bb->count - 1;
     212
     213    op_get_flowinfo(&fi, last);
     214
    184215    fprintf(stderr,
    185216            "%3d %3d %3d"
    186217            " %c%c"
    187             " %3d %3d %3d %3d\r\n"
    188             , bb->id, bb->count, bb->opcodes - opcodes
     218            " %3d %3d %3d %3d %3d %s\r\n"
     219            , bb->id, bb->count, bb->alloc ? -1 : bb->opcodes - opcodes
    189220            , bb->used ? 'U' : ' ', bb->alloc ? 'A' : ' '
    190             , bb->jmpout_op1, bb->jmpout_op2, bb->jmpout_ext, bb->fall
     221            , fi.jmpout_op1, fi.jmpout_op2, fi.jmpout_ext, bb->fall, bb->catch, xc_get_opcode(last->opcode)
    191222            );
    192223}
     
    194225#endif
    195226
    196 #define bbs_get(bbs, n) xc_stack_get(bbs, n)
     227#define bbs_get(bbs, n) ((bb_t *) xc_stack_get(bbs, n))
     228#define bbs_count(bbs) xc_stack_count(bbs)
    197229static void bbs_destroy(bbs_t *bbs) /* {{{ */
    198230{
    199231    bb_t *bb;
    200     while (xc_stack_count(bbs)) {
     232    while (bbs_count(bbs)) {
    201233        bb = (bb_t *) xc_stack_pop(bbs);
    202234        bb_destroy(bb);
     
    209241{
    210242    int i;
     243    fprintf(stderr,
     244            " id cnt lno"
     245            " UA"
     246            " op1 op2 ext fal cat opcode\r\n"
     247            );
    211248    for (i = 0; i < xc_stack_count(bbs); i ++) {
    212249        bb_print(bbs_get(bbs, i), opcodes);
     
    228265}
    229266/* }}} */
    230 static int bbs_build_from(bbs_t *bbs, zend_op *opcodes, int count) /* {{{ */
    231 {
    232     int i, prev;
     267static int bbs_build_from(bbs_t *bbs, zend_op_array *op_array, int count) /* {{{ */
     268{
     269    int i, start;
    233270    bb_t *pbb;
    234271    bbid_t id;
    235     int jmpout_op1, jmpout_op2, jmpout_ext;
    236     zend_bool fall;
     272    op_flowinfo_t fi;
     273    zend_op *opline;
    237274    bbid_t *bbids          = do_alloca(count * sizeof(bbid_t));
    238     zend_bool *markjmpins  = do_alloca(count * sizeof(zend_bool));
    239     zend_bool *markjmpouts = do_alloca(count * sizeof(zend_bool));
     275    bbid_t *catchbbids     = do_alloca(count * sizeof(bbid_t));
     276    zend_bool *markbbhead = do_alloca(count * sizeof(zend_bool));
    240277
    241278    /* {{{ mark jmpin/jumpout */
    242     memset(markjmpins,  0, count * sizeof(zend_bool));
    243     memset(markjmpouts, 0, count * sizeof(zend_bool));
    244 
     279    memset(markbbhead,  0, count * sizeof(zend_bool));
     280
     281    markbbhead[0] = 1;
    245282    for (i = 0; i < count; i ++) {
    246         jmpout_op1 = jmpout_op2 = jmpout_ext = -1;
    247         fall = 0;
    248         if (op_get_jmpout(&jmpout_op1, &jmpout_op2, &jmpout_ext, &fall, &opcodes[i]) == SUCCESS) {
    249             markjmpouts[i] = 1;
    250 
    251             if (jmpout_op1 != -1) {
    252                 markjmpins[jmpout_op1] = 1;
    253             }
    254             if (jmpout_op2 != -1) {
    255                 markjmpins[jmpout_op2] = 1;
    256             }
    257             if (jmpout_ext != -1) {
    258                 markjmpins[jmpout_ext] = 1;
    259             }
    260         }
     283        if (op_get_flowinfo(&fi, &op_array->opcodes[i]) == SUCCESS) {
     284            if (fi.jmpout_op1 != XC_OPNUM_INVALID) {
     285                markbbhead[fi.jmpout_op1] = 1;
     286            }
     287            if (fi.jmpout_op2 != XC_OPNUM_INVALID) {
     288                markbbhead[fi.jmpout_op2] = 1;
     289            }
     290            if (fi.jmpout_ext != XC_OPNUM_INVALID) {
     291                markbbhead[fi.jmpout_ext] = 1;
     292            }
     293            if (i + 1 < count) {
     294                markbbhead[i + 1] = 1;
     295            }
     296        }
     297    }
     298    /* mark try start */
     299    for (i = 0; i < op_array->last_try_catch; i ++) {
     300        markbbhead[op_array->try_catch_array[i].try_op] = 1;
    261301    }
    262302    /* }}} */
    263     /* {{{ fill opcodes with newly allocated id */
     303    /* {{{ fill op lines with newly allocated id */
    264304    for (i = 0; i < count; i ++) {
    265305        bbids[i] = BBID_INVALID;
    266306    }
    267307
    268     prev = 0;
     308    /*
     309    start = 0;
    269310    id = 0;
    270311    for (i = 1; i < count; i ++) {
    271         if (markjmpins[i] || markjmpouts[i - 1]) {
    272             for (; prev < i; prev ++) {
    273                 bbids[prev] = id;
     312        if (markbbhead[i]) {
     313            for (; start < i; start ++) {
     314                bbids[start] = id;
    274315            }
    275316            id ++;
    276             prev = i;
    277         }
    278     }
    279 
    280     if (prev < count) {
    281         for (; prev < i; prev ++) {
    282             bbids[prev] = id;
    283         }
    284     }
     317            start = i;
     318        }
     319    }
     320
     321    for (; start < count; start ++) {
     322        bbids[start] = id;
     323    }
     324    */
     325    id = -1;
     326    for (i = 0; i < count; i ++) {
     327        if (markbbhead[i]) {
     328            id ++;
     329        }
     330        bbids[i] = id;
     331        TRACE("bbids[%d] = %d", i, id);
     332    }
     333    /* }}} */
     334    /* {{{ fill op lines with catch id */
     335    for (i = 0; i < count; i ++) {
     336        catchbbids[i] = BBID_INVALID;
     337    }
     338
     339    for (i = 0; i < op_array->last_try_catch; i ++) {
     340        int j;
     341        zend_try_catch_element *e = &op_array->try_catch_array[i];
     342        for (j = e->try_op; j < e->catch_op; j ++) {
     343            catchbbids[j] = bbids[e->catch_op];
     344        }
     345    }
     346#ifdef DEBUG
     347    for (i = 0; i < count; i ++) {
     348        TRACE("catchbbids[%d] = %d", i, catchbbids[i]);
     349    }
     350#endif
    285351    /* }}} */
    286352    /* {{{ create basic blocks */
    287     prev = 0;
     353    start = 0;
    288354    id = 0;
    289     for (i = 1; i < count; i ++) {
    290         if (id == bbids[i]) {
     355    /* loop over to deal with the last block */
     356    for (i = 1; i <= count; i ++) {
     357        if (i < count && id == bbids[i]) {
    291358            continue;
    292359        }
     360
     361        opline = op_array->opcodes + start;
     362        pbb = bbs_new_bb_ex(bbs, opline, i - start);
     363        pbb->catch = catchbbids[start];
     364
     365        /* last */
     366        opline = pbb->opcodes + pbb->count - 1;
     367        if (op_get_flowinfo(&fi, opline) == SUCCESS) {
     368            if (fi.jmpout_op1 != XC_OPNUM_INVALID) {
     369                opline->op1.u.opline_num = bbids[fi.jmpout_op1];
     370                assert(opline->op1.u.opline_num != BBID_INVALID);
     371            }
     372            if (fi.jmpout_op2 != XC_OPNUM_INVALID) {
     373                opline->op2.u.opline_num = bbids[fi.jmpout_op2];
     374                assert(opline->op2.u.opline_num != BBID_INVALID);
     375            }
     376            if (fi.jmpout_ext != XC_OPNUM_INVALID) {
     377                opline->extended_value = bbids[fi.jmpout_ext];
     378                assert(opline->extended_value != BBID_INVALID);
     379            }
     380            if (fi.fall && i + 1 < count) {
     381                pbb->fall = bbids[i + 1];
     382                TRACE("fall %d", pbb->fall);
     383                assert(pbb->fall != BBID_INVALID);
     384            }
     385        }
     386        if (i >= count) {
     387            break;
     388        }
     389        start = i + 1;
    293390        id = bbids[i];
    294 
    295         pbb = bbs_new_bb_ex(bbs, opcodes + prev, i - prev);
    296         jmpout_op1 = jmpout_op2 = jmpout_ext = -1;
    297         fall = 0;
    298         if (op_get_jmpout(&jmpout_op1, &jmpout_op2, &jmpout_ext, &fall, &opcodes[prev]) == SUCCESS) {
    299             if (jmpout_op1 != -1) {
    300                 pbb->jmpout_op1 = bbids[jmpout_op1];
    301                 assert(pbb->jmpout_op1 != BBID_INVALID);
    302             }
    303             if (jmpout_op2 != -1) {
    304                 pbb->jmpout_op2 = bbids[jmpout_op2];
    305                 assert(pbb->jmpout_op2 != BBID_INVALID);
    306             }
    307             if (jmpout_ext != -1) {
    308                 pbb->jmpout_ext = bbids[jmpout_ext];
    309                 assert(pbb->jmpout_ext != BBID_INVALID);
    310             }
    311             if (fall && i + 1 < count) {
    312                 pbb->fall = bbids[i + 1];
    313                 assert(pbb->fall != BBID_INVALID);
    314             }
    315         }
    316         prev = i + 1;
    317     }
    318     assert(prev == count);
     391    }
    319392    /* }}} */
    320393
     394    free_alloca(catchbbids);
    321395    free_alloca(bbids);
    322     free_alloca(markjmpins);
    323     free_alloca(markjmpouts);
     396    free_alloca(markbbhead);
    324397    return SUCCESS;
     398}
     399/* }}} */
     400static void bbs_restore_opnum(bbs_t *bbs) /* {{{ */
     401{
     402    int i;
     403    for (i = 0; i < bbs_count(bbs); i ++) {
     404        op_flowinfo_t fi;
     405        bb_t *bb = bbs_get(bbs, i);
     406        zend_op *last = bb->opcodes + bb->count - 1;
     407
     408        if (op_get_flowinfo(&fi, last) == SUCCESS) {
     409            if (fi.jmpout_op1 != XC_OPNUM_INVALID) {
     410                last->op1.u.opline_num = bbs_get(bbs, fi.jmpout_op1)->opnum;
     411                assert(last->op1.u.opline_num != BBID_INVALID);
     412            }
     413            if (fi.jmpout_op2 != XC_OPNUM_INVALID) {
     414                last->op2.u.opline_num = bbs_get(bbs, fi.jmpout_op2)->opnum;
     415                assert(last->op2.u.opline_num != BBID_INVALID);
     416            }
     417            if (fi.jmpout_ext != XC_OPNUM_INVALID) {
     418                last->extended_value = bbs_get(bbs, fi.jmpout_ext)->opnum;
     419                assert(last->extended_value != BBID_INVALID);
     420            }
     421        }
     422    }
     423
     424    /* TODO: rebuild zend_try_catch_element here */
    325425}
    326426/* }}} */
     
    346446    if (op_array_convert_switch(op_array) == SUCCESS) {
    347447        bbs_init(&bbs);
    348         if (bbs_build_from(&bbs, op_array->opcodes, op_array->last) == SUCCESS) {
     448        if (bbs_build_from(&bbs, op_array, op_array->last) == SUCCESS) {
     449            int i;
    349450#ifdef DEBUG
    350451            bbs_print(&bbs, op_array->opcodes);
    351452#endif
     453            /* TODO: calc opnum after basic block move */
     454            for (i = 0; i < bbs_count(&bbs); i ++) {
     455                bb_t *bb = bbs_get(&bbs, i);
     456                bb->opnum = bb->opcodes - op_array->opcodes;
     457            }
     458            bbs_restore_opnum(&bbs);
    352459        }
    353460        bbs_destroy(&bbs);
Note: See TracChangeset for help on using the changeset viewer.