Changeset 308 in svn


Ignore:
Timestamp:
2006-12-09T04:44:45+01:00 (9 years ago)
Author:
Xuefer
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.