Changeset 326 for trunk/optimizer.c


Ignore:
Timestamp:
2006-12-10T18:17:59+01:00 (7 years ago)
Author:
moo
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.