Changeset 308


Ignore:
Timestamp:
2006-12-09T04:44:45+01:00 (8 years ago)
Author:
moo
Message:

basic works on optimizer

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/optimizer.c

    r302 r308  
     1#if 1 
     2#define DEBUG 
     3#endif 
     4 
     5#include "utils.h" 
    16#include "optimizer.h" 
    2 #include "utils.h" 
    3  
     7/* the "vector" stack */ 
     8#include "stack.h" 
     9 
     10#ifdef DEBUG 
     11#   include "processor.h" 
     12#endif 
     13 
     14typedef int bbid_t; 
     15enum { 
     16    BBID_INVALID = -1, 
     17}; 
     18/* {{{ basic block */ 
     19typedef struct _bb_t { 
     20    bbid_t     id; 
     21    zend_bool  used; 
     22 
     23    zend_bool  alloc; 
     24    zend_op   *opcodes; 
     25    int        count; 
     26    int        size; 
     27 
     28    bbid_t     jmpout_op1; 
     29    bbid_t     jmpout_op2; 
     30    bbid_t     jmpout_ext; 
     31    bbid_t     follow; 
     32} bb_t; 
     33/* }}} */ 
     34 
     35/* basic blocks */ 
     36typedef xc_stack_t bbs_t; 
     37 
     38/* oparray help functions */ 
     39static int op_array_convert_switch(zend_op_array *op_array) /* {{{ */ 
     40{ 
     41    int i; 
     42 
     43    if (op_array->brk_cont_array == NULL) { 
     44        return SUCCESS; 
     45    } 
     46 
     47    for (i = 0; i < op_array->last; i ++) { 
     48        zend_op *opline = &op_array->opcodes[i]; 
     49        zend_brk_cont_element *jmp_to; 
     50        int array_offset, nest_levels, original_nest_levels; 
     51 
     52        if (opline->opcode != ZEND_BRK && opline->opcode != ZEND_CONT) { 
     53            continue; 
     54        } 
     55        if (opline->op2.op_type != IS_CONST 
     56         || opline->op2.u.constant.type != IS_LONG) { 
     57            return FAILURE; 
     58        } 
     59 
     60        nest_levels = opline->op2.u.constant.value.lval; 
     61        original_nest_levels = nest_levels; 
     62 
     63        array_offset = opline->op1.u.opline_num; 
     64        do { 
     65            if (array_offset == -1) { 
     66                /* this is a runtime error in ZE 
     67                zend_error(E_ERROR, "Cannot break/continue %d level%s", original_nest_levels, (original_nest_levels == 1) ? "" : "s"); 
     68                */ 
     69                return FAILURE; 
     70            } 
     71            jmp_to = &op_array->brk_cont_array[array_offset]; 
     72            if (nest_levels > 1) { 
     73                zend_op *brk_opline = &op_array->opcodes[jmp_to->brk]; 
     74 
     75                switch (brk_opline->opcode) { 
     76                case ZEND_SWITCH_FREE: 
     77                    break; 
     78                case ZEND_FREE: 
     79                    break; 
     80                } 
     81            } 
     82            array_offset = jmp_to->parent; 
     83        } while (--nest_levels > 0); 
     84 
     85        /* rewrite to jmp */ 
     86        if (opline->opcode == ZEND_BRK) { 
     87            opline->op1.u.opline_num = jmp_to->brk; 
     88        } 
     89        else { 
     90            opline->op1.u.opline_num = jmp_to->cont; 
     91        } 
     92        opline->op2.op_type = IS_UNUSED; 
     93        opline->opcode = ZEND_JMP; 
     94    } 
     95 
     96    if (op_array->brk_cont_array != NULL) { 
     97        efree(op_array->brk_cont_array); 
     98        op_array->brk_cont_array = NULL; 
     99    } 
     100    op_array->last_brk_cont = 0; 
     101    return SUCCESS; 
     102} 
     103/* }}} */ 
     104static int op_get_jmpout(bb_t *bb, zend_op *opcodes, zend_op *opline) /* {{{ */ 
     105{ 
     106    /* break=have follow */ 
     107    switch (opline->opcode) { 
     108    case ZEND_RETURN: 
     109    case ZEND_EXIT: 
     110        break; 
     111 
     112    case ZEND_JMP: 
     113        bb->jmpout_op1 = opline->op1.u.opline_num; 
     114        return SUCCESS; /* no follow */ 
     115 
     116    case ZEND_JMPZNZ: 
     117        bb->jmpout_ext = opline->extended_value; 
     118        bb->jmpout_op2 = opline->op2.u.opline_num; 
     119        break; 
     120 
     121    case ZEND_JMPZ: 
     122    case ZEND_JMPNZ: 
     123    case ZEND_JMPZ_EX: 
     124    case ZEND_JMPNZ_EX: 
     125#ifndef ZEND_ENGINE_2_1 
     126        /* Pre-PHP 5.1 only */ 
     127    case ZEND_JMP_NO_CTOR: 
     128#else        
     129    case ZEND_NEW: 
     130    case ZEND_FE_RESET: 
     131#endif       
     132    case ZEND_FE_FETCH: 
     133        bb->jmpout_op2 = opline->op2.u.opline_num; 
     134        break; 
     135 
     136    default: 
     137        return FAILURE; 
     138    } 
     139 
     140    return SUCCESS; 
     141} 
     142/* }}} */ 
     143 
     144/* 
     145 * basic block functions 
     146 */ 
     147 
     148static bb_t *bb_new_ex(zend_op *opcodes, int count) /* {{{ */ 
     149{ 
     150    bb_t *bb = (bb_t *) ecalloc(sizeof(bb_t), 1); 
     151 
     152    bb->jmpout_op1 = BBID_INVALID; 
     153    bb->jmpout_op2 = BBID_INVALID; 
     154    bb->jmpout_ext = BBID_INVALID; 
     155    bb->follow     = BBID_INVALID; 
     156 
     157    if (opcodes) { 
     158        bb->alloc   = 0; 
     159        bb->size    = bb->count = count; 
     160        bb->opcodes = opcodes; 
     161    } 
     162    else { 
     163        bb->alloc   = 1; 
     164        bb->size    = bb->count = 8; 
     165        bb->opcodes = ecalloc(sizeof(zend_op), bb->size); 
     166    } 
     167 
     168    return bb; 
     169} 
     170/* }}} */ 
     171#define bb_new() bb_new_ex(NULL, 0) 
     172static void bb_destroy(bb_t *bb) /* {{{ */ 
     173{ 
     174    if (bb->alloc) { 
     175        efree(bb->opcodes); 
     176    } 
     177    efree(bb); 
     178} 
     179/* }}} */ 
     180#define bbs_get(bbs, n) xc_stack_get(bbs, n) 
     181static void bbs_destroy(bbs_t *bbs) /* {{{ */ 
     182{ 
     183    bb_t *bb; 
     184    while (xc_stack_count(bbs)) { 
     185        bb = (bb_t *) xc_stack_pop(bbs); 
     186        bb_destroy(bb); 
     187    } 
     188} 
     189/* }}} */ 
     190#define bbs_init(bbs) xc_stack_init_ex(bbs, 16) 
     191static bb_t *bbs_add_bb(bbs_t *bbs, bb_t *bb) /* {{{ */ 
     192{ 
     193    bb->id = (bbid_t) xc_stack_count(bbs); 
     194    xc_stack_push(bbs, (void *) bb); 
     195    return bb; 
     196} 
     197/* }}} */ 
     198static bb_t *bbs_new_bb_ex(bbs_t *bbs, zend_op *opcodes, int count) /* {{{ */ 
     199{ 
     200    return bbs_add_bb(bbs, bb_new_ex(opcodes, count)); 
     201} 
     202/* }}} */ 
     203static int bbs_build_from(bbs_t *bbs, zend_op *opcodes, int count) /* {{{ */ 
     204{ 
     205    int i, prev; 
     206    bb_t bb, *pbb; 
     207    zend_bool *markjmpins  = do_alloca(count); 
     208    zend_bool *markjmpouts = do_alloca(count); 
     209 
     210    memset(markjmpins,  0, sizeof(zend_bool)); 
     211    memset(markjmpouts, 0, sizeof(zend_bool)); 
     212 
     213    for (i = 0; i < count; i ++) { 
     214        /* BBID_INVALID=invalidate line  
     215         * bb.jmpout_op1 bb.jmpout_op2 bb.jmpout_ext bb.follow means opline number here, not basicblock id 
     216         */ 
     217        bb.jmpout_op1 = bb.jmpout_op2 = BBID_INVALID; 
     218        bb.jmpout_ext = bb.follow     = BBID_INVALID; 
     219        if (op_get_jmpout(&bb, opcodes, &opcodes[i]) == SUCCESS) { 
     220            markjmpouts[i] = 1; 
     221 
     222            if (bb.jmpout_op1 != BBID_INVALID) { 
     223                markjmpins[bb.jmpout_op1] = 1; 
     224            } 
     225            if (bb.jmpout_op2 != BBID_INVALID) { 
     226                markjmpins[bb.jmpout_op2] = 1; 
     227            } 
     228            if (bb.jmpout_ext != BBID_INVALID) { 
     229                markjmpins[bb.jmpout_ext] = 1; 
     230            } 
     231 
     232            if (i < count && bb.follow != BBID_INVALID) { 
     233                markjmpins[i + 1] = 1; 
     234            } 
     235        } 
     236    } 
     237 
     238    prev = 0; 
     239    for (i = 1; i < count; i ++) { 
     240        if (markjmpins[i]) { 
     241            pbb = bbs_new_bb_ex(bbs, opcodes + prev, i - prev); 
     242            op_get_jmpout(pbb, opcodes, &opcodes[prev]); 
     243            prev = i; 
     244        } 
     245    } 
     246 
     247    if (prev != count - 1) { 
     248        pbb = bbs_new_bb_ex(bbs, opcodes + prev, count - prev); 
     249    } 
     250 
     251    return SUCCESS; 
     252} 
     253/* }}} */ 
     254 
     255/* 
     256 * optimize 
     257 */ 
    4258static int xc_optimize_op_array(zend_op_array *op_array TSRMLS_DC) /* {{{ */ 
    5259{ 
     260    bbs_t bbs; 
     261 
    6262    if (op_array->type != ZEND_USER_FUNCTION) { 
    7263        return 0; 
    8264    } 
    9 #if 0 
    10265    xc_undo_pass_two(op_array TSRMLS_CC); 
     266#ifdef DEBUG 
     267    TRACE("optimize file: %s", op_array->filename); 
     268    xc_dprint_zend_op_array(op_array, 0 TSRMLS_CC); 
     269#endif 
     270 
     271    if (op_array_convert_switch(op_array)) { 
     272        bbs_init(&bbs); 
     273        if (bbs_build_from(&bbs, op_array->opcodes, op_array->last)) { 
     274        } 
     275        bbs_destroy(&bbs); 
     276    } 
     277 
     278#ifdef DEBUG 
     279    TRACE("%s", "after compiles"); 
     280    xc_dprint_zend_op_array(op_array, 0 TSRMLS_CC); 
     281#endif 
    11282    xc_redo_pass_two(op_array TSRMLS_CC); 
    12     xc_dprint_zend_op_array(op_array, 0); 
    13 #endif 
    14283    return 0; 
    15284} 
Note: See TracChangeset for help on using the changeset viewer.