Changeset 326
- Timestamp:
- 2006-12-10T18:17:59+01:00 (6 years ago)
- File:
-
- 1 edited
-
trunk/optimizer.c (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/optimizer.c
r316 r326 10 10 #ifdef DEBUG 11 11 # include "processor.h" 12 # include "const_string.h" 12 13 #endif 13 14 … … 26 27 int size; 27 28 28 bbid_t jmpout_op1;29 bbid_t jmpout_op2;30 bbid_t jmpout_ext;31 29 bbid_t fall; 30 bbid_t catch; 31 32 int opnum; /* opnum after joining basic block */ 32 33 } bb_t; 33 34 /* }}} */ … … 36 37 typedef xc_stack_t bbs_t; 37 38 38 /* op array helpfunctions */39 /* op array helper functions */ 39 40 static int op_array_convert_switch(zend_op_array *op_array) /* {{{ */ 40 41 { … … 102 103 } 103 104 /* }}} */ 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 */ 106 enum { 107 XC_OPNUM_INVALID = -1, 108 }; 109 typedef struct { 110 int jmpout_op1; 111 int jmpout_op2; 112 int jmpout_ext; 113 zend_bool fall; 114 } op_flowinfo_t; 115 static 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 /* }}} */ 121 static int op_get_flowinfo(op_flowinfo_t *fi, zend_op *opline) /* {{{ */ 122 { 123 op_flowinfo_init(fi); 124 106 125 /* break=will fall */ 107 126 switch (opline->opcode) { 127 case ZEND_HANDLE_EXCEPTION: 108 128 case ZEND_RETURN: 109 129 case ZEND_EXIT: … … 111 131 112 132 case ZEND_JMP: 113 *jmpout_op1 = opline->op1.u.opline_num;133 fi->jmpout_op1 = opline->op1.u.opline_num; 114 134 return SUCCESS; /* no fall */ 115 135 116 136 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 */ 120 140 121 141 case ZEND_JMPZ: … … 123 143 case ZEND_JMPZ_EX: 124 144 case ZEND_JMPNZ_EX: 125 #ifndef ZEND_ENGINE_2_1 126 /* Pre-PHP 5.1 only */ 145 #ifdef ZEND_JMP_NO_CTOR 127 146 case ZEND_JMP_NO_CTOR: 128 #else 147 #endif 148 #ifdef ZEND_NEW 129 149 case ZEND_NEW: 150 #endif 151 #ifdef ZEND_FE_RESET 130 152 case ZEND_FE_RESET: 131 153 #endif 132 154 case ZEND_FE_FETCH: 133 *jmpout_op2 = opline->op2.u.opline_num;155 fi->jmpout_op2 = opline->op2.u.opline_num; 134 156 break; 157 158 #ifdef ZEND_CATCH 159 case ZEND_CATCH: 160 fi->jmpout_ext = (int) opline->extended_value; 161 break; 162 #endif 135 163 136 164 default: … … 138 166 } 139 167 140 *fall = 1;168 fi->fall = 1; 141 169 return SUCCESS; 142 170 } … … 151 179 bb_t *bb = (bb_t *) ecalloc(sizeof(bb_t), 1); 152 180 153 bb->jmpout_op1 = BBID_INVALID;154 bb->jmpout_op2 = BBID_INVALID;155 bb->jmpout_ext = BBID_INVALID;156 181 bb->fall = BBID_INVALID; 182 bb->catch = BBID_INVALID; 157 183 158 184 if (opcodes) { … … 182 208 static void bb_print(bb_t *bb, zend_op *opcodes) /* {{{ */ 183 209 { 210 op_flowinfo_t fi; 211 zend_op *last = bb->opcodes + bb->count - 1; 212 213 op_get_flowinfo(&fi, last); 214 184 215 fprintf(stderr, 185 216 "%3d %3d %3d" 186 217 " %c%c" 187 " %3d %3d %3d %3d \r\n"188 , bb->id, bb->count, bb-> opcodes - opcodes218 " %3d %3d %3d %3d %3d %s\r\n" 219 , bb->id, bb->count, bb->alloc ? -1 : bb->opcodes - opcodes 189 220 , bb->used ? 'U' : ' ', bb->alloc ? 'A' : ' ' 190 , bb->jmpout_op1, bb->jmpout_op2, bb->jmpout_ext, bb->fall221 , fi.jmpout_op1, fi.jmpout_op2, fi.jmpout_ext, bb->fall, bb->catch, xc_get_opcode(last->opcode) 191 222 ); 192 223 } … … 194 225 #endif 195 226 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) 197 229 static void bbs_destroy(bbs_t *bbs) /* {{{ */ 198 230 { 199 231 bb_t *bb; 200 while ( xc_stack_count(bbs)) {232 while (bbs_count(bbs)) { 201 233 bb = (bb_t *) xc_stack_pop(bbs); 202 234 bb_destroy(bb); … … 209 241 { 210 242 int i; 243 fprintf(stderr, 244 " id cnt lno" 245 " UA" 246 " op1 op2 ext fal cat opcode\r\n" 247 ); 211 248 for (i = 0; i < xc_stack_count(bbs); i ++) { 212 249 bb_print(bbs_get(bbs, i), opcodes); … … 228 265 } 229 266 /* }}} */ 230 static int bbs_build_from(bbs_t *bbs, zend_op *opcodes, int count) /* {{{ */231 { 232 int i, prev;267 static int bbs_build_from(bbs_t *bbs, zend_op_array *op_array, int count) /* {{{ */ 268 { 269 int i, start; 233 270 bb_t *pbb; 234 271 bbid_t id; 235 int jmpout_op1, jmpout_op2, jmpout_ext;236 zend_ bool fall;272 op_flowinfo_t fi; 273 zend_op *opline; 237 274 bbid_t *bbids = do_alloca(count * sizeof(bbid_t)); 238 zend_bool *markjmpins = do_alloca(count * sizeof(zend_bool));239 zend_bool *mark jmpouts= 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)); 240 277 241 278 /* {{{ mark jmpin/jumpout */ 242 memset(mark jmpins, 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; 245 282 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; 261 301 } 262 302 /* }}} */ 263 /* {{{ fill op codes with newly allocated id */303 /* {{{ fill op lines with newly allocated id */ 264 304 for (i = 0; i < count; i ++) { 265 305 bbids[i] = BBID_INVALID; 266 306 } 267 307 268 prev = 0; 308 /* 309 start = 0; 269 310 id = 0; 270 311 for (i = 1; i < count; i ++) { 271 if (mark jmpins[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; 274 315 } 275 316 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 285 351 /* }}} */ 286 352 /* {{{ create basic blocks */ 287 prev= 0;353 start = 0; 288 354 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]) { 291 358 continue; 292 359 } 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; 293 390 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 } 319 392 /* }}} */ 320 393 394 free_alloca(catchbbids); 321 395 free_alloca(bbids); 322 free_alloca(markjmpins); 323 free_alloca(markjmpouts); 396 free_alloca(markbbhead); 324 397 return SUCCESS; 398 } 399 /* }}} */ 400 static 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 */ 325 425 } 326 426 /* }}} */ … … 346 446 if (op_array_convert_switch(op_array) == SUCCESS) { 347 447 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; 349 450 #ifdef DEBUG 350 451 bbs_print(&bbs, op_array->opcodes); 351 452 #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); 352 459 } 353 460 bbs_destroy(&bbs);
Note: See TracChangeset
for help on using the changeset viewer.

