Changeset 308
- Timestamp:
- 2006-12-09T04:44:45+01:00 (7 years ago)
- File:
-
- 1 edited
-
trunk/optimizer.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/optimizer.c
r302 r308 1 #if 1 2 #define DEBUG 3 #endif 4 5 #include "utils.h" 1 6 #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 14 typedef int bbid_t; 15 enum { 16 BBID_INVALID = -1, 17 }; 18 /* {{{ basic block */ 19 typedef 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 */ 36 typedef xc_stack_t bbs_t; 37 38 /* oparray help functions */ 39 static 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 /* }}} */ 104 static 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 148 static 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) 172 static 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) 181 static 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) 191 static 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 /* }}} */ 198 static 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 /* }}} */ 203 static 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 */ 4 258 static int xc_optimize_op_array(zend_op_array *op_array TSRMLS_DC) /* {{{ */ 5 259 { 260 bbs_t bbs; 261 6 262 if (op_array->type != ZEND_USER_FUNCTION) { 7 263 return 0; 8 264 } 9 #if 010 265 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 11 282 xc_redo_pass_two(op_array TSRMLS_CC); 12 xc_dprint_zend_op_array(op_array, 0);13 #endif14 283 return 0; 15 284 }
Note: See TracChangeset
for help on using the changeset viewer.

