Changeset 388 for python/vendor/current/Python/peephole.c
- Timestamp:
- Mar 19, 2014, 11:11:30 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
python/vendor/current/Python/peephole.c
r2 r388 13 13 14 14 #define GETARG(arr, i) ((int)((arr[i+2]<<8) + arr[i+1])) 15 #define UNCONDITIONAL_JUMP(op) (op==JUMP_ABSOLUTE || op==JUMP_FORWARD) 16 #define ABSOLUTE_JUMP(op) (op==JUMP_ABSOLUTE || op==CONTINUE_LOOP) 15 #define UNCONDITIONAL_JUMP(op) (op==JUMP_ABSOLUTE || op==JUMP_FORWARD) 16 #define CONDITIONAL_JUMP(op) (op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \ 17 || op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP) 18 #define ABSOLUTE_JUMP(op) (op==JUMP_ABSOLUTE || op==CONTINUE_LOOP \ 19 || op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \ 20 || op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP) 21 #define JUMPS_ON_TRUE(op) (op==POP_JUMP_IF_TRUE || op==JUMP_IF_TRUE_OR_POP) 17 22 #define GETJUMPTGT(arr, i) (GETARG(arr,i) + (ABSOLUTE_JUMP(arr[i]) ? 0 : i+3)) 18 23 #define SETARG(arr, i, val) arr[i+2] = val>>8; arr[i+1] = val & 255 19 24 #define CODESIZE(op) (HAS_ARG(op) ? 3 : 1) 20 25 #define ISBASICBLOCK(blocks, start, bytes) \ 21 26 (blocks[start]==blocks[start+bytes-1]) 22 27 23 28 /* Replace LOAD_CONST c1. LOAD_CONST c2 ... LOAD_CONST cn BUILD_TUPLE n 24 with 29 with LOAD_CONST (c1, c2, ... cn). 25 30 The consts table must still be in list form so that the 26 31 new constant (c1, c2, ... cn) can be appended. 27 32 Called with codestr pointing to the first LOAD_CONST. 28 Bails out with no change if one or more of the LOAD_CONSTs is missing. 33 Bails out with no change if one or more of the LOAD_CONSTs is missing. 29 34 Also works for BUILD_LIST when followed by an "in" or "not in" test. 30 35 */ … … 32 37 tuple_of_constants(unsigned char *codestr, Py_ssize_t n, PyObject *consts) 33 38 { 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 39 PyObject *newconst, *constant; 40 Py_ssize_t i, arg, len_consts; 41 42 /* Pre-conditions */ 43 assert(PyList_CheckExact(consts)); 44 assert(codestr[n*3] == BUILD_TUPLE || codestr[n*3] == BUILD_LIST); 45 assert(GETARG(codestr, (n*3)) == n); 46 for (i=0 ; i<n ; i++) 47 assert(codestr[i*3] == LOAD_CONST); 48 49 /* Buildup new tuple of constants */ 50 newconst = PyTuple_New(n); 51 if (newconst == NULL) 52 return 0; 53 len_consts = PyList_GET_SIZE(consts); 54 for (i=0 ; i<n ; i++) { 55 arg = GETARG(codestr, (i*3)); 56 assert(arg < len_consts); 57 constant = PyList_GET_ITEM(consts, arg); 58 Py_INCREF(constant); 59 PyTuple_SET_ITEM(newconst, i, constant); 60 } 61 62 /* Append folded constant onto consts */ 63 if (PyList_Append(consts, newconst)) { 64 Py_DECREF(newconst); 65 return 0; 66 } 67 Py_DECREF(newconst); 68 69 /* Write NOPs over old LOAD_CONSTS and 70 add a new LOAD_CONST newconst on top of the BUILD_TUPLE n */ 71 memset(codestr, NOP, n*3); 72 codestr[n*3] = LOAD_CONST; 73 SETARG(codestr, (n*3), len_consts); 74 return 1; 70 75 } 71 76 72 77 /* Replace LOAD_CONST c1. LOAD_CONST c2 BINOP 73 with 78 with LOAD_CONST binop(c1,c2) 74 79 The consts table must still be in list form so that the 75 80 new constant can be appended. 76 Called with codestr pointing to the first LOAD_CONST. 77 Abandons the transformation if the folding fails (i.e. 1+'a'). 81 Called with codestr pointing to the first LOAD_CONST. 82 Abandons the transformation if the folding fails (i.e. 1+'a'). 78 83 If the new constant is a sequence, only folds when the size 79 is below a threshold value. 80 becoming large in the presence of code like: 84 is below a threshold value. That keeps pyc files from 85 becoming large in the presence of code like: (None,)*1000. 81 86 */ 82 87 static int 83 88 fold_binops_on_constants(unsigned char *codestr, PyObject *consts) 84 89 { 85 PyObject *newconst, *v, *w; 86 Py_ssize_t len_consts, size; 87 int opcode; 88 89 /* Pre-conditions */ 90 assert(PyList_CheckExact(consts)); 91 assert(codestr[0] == LOAD_CONST); 92 assert(codestr[3] == LOAD_CONST); 93 94 /* Create new constant */ 95 v = PyList_GET_ITEM(consts, GETARG(codestr, 0)); 96 w = PyList_GET_ITEM(consts, GETARG(codestr, 3)); 97 opcode = codestr[6]; 98 switch (opcode) { 99 case BINARY_POWER: 100 newconst = PyNumber_Power(v, w, Py_None); 101 break; 102 case BINARY_MULTIPLY: 103 newconst = PyNumber_Multiply(v, w); 104 break; 105 case BINARY_DIVIDE: 106 /* Cannot fold this operation statically since 107 the result can depend on the run-time presence 108 of the -Qnew flag */ 109 return 0; 110 case BINARY_TRUE_DIVIDE: 111 newconst = PyNumber_TrueDivide(v, w); 112 break; 113 case BINARY_FLOOR_DIVIDE: 114 newconst = PyNumber_FloorDivide(v, w); 115 break; 116 case BINARY_MODULO: 117 newconst = PyNumber_Remainder(v, w); 118 break; 119 case BINARY_ADD: 120 newconst = PyNumber_Add(v, w); 121 break; 122 case BINARY_SUBTRACT: 123 newconst = PyNumber_Subtract(v, w); 124 break; 125 case BINARY_SUBSCR: 126 newconst = PyObject_GetItem(v, w); 127 break; 128 case BINARY_LSHIFT: 129 newconst = PyNumber_Lshift(v, w); 130 break; 131 case BINARY_RSHIFT: 132 newconst = PyNumber_Rshift(v, w); 133 break; 134 case BINARY_AND: 135 newconst = PyNumber_And(v, w); 136 break; 137 case BINARY_XOR: 138 newconst = PyNumber_Xor(v, w); 139 break; 140 case BINARY_OR: 141 newconst = PyNumber_Or(v, w); 142 break; 143 default: 144 /* Called with an unknown opcode */ 145 PyErr_Format(PyExc_SystemError, 146 "unexpected binary operation %d on a constant", 147 opcode); 148 return 0; 149 } 150 if (newconst == NULL) { 151 PyErr_Clear(); 152 return 0; 153 } 154 size = PyObject_Size(newconst); 155 if (size == -1) 156 PyErr_Clear(); 157 else if (size > 20) { 158 Py_DECREF(newconst); 159 return 0; 160 } 161 162 /* Append folded constant into consts table */ 163 len_consts = PyList_GET_SIZE(consts); 164 if (PyList_Append(consts, newconst)) { 165 Py_DECREF(newconst); 166 return 0; 167 } 168 Py_DECREF(newconst); 169 170 /* Write NOP NOP NOP NOP LOAD_CONST newconst */ 171 memset(codestr, NOP, 4); 172 codestr[4] = LOAD_CONST; 173 SETARG(codestr, 4, len_consts); 174 return 1; 90 PyObject *newconst, *v, *w; 91 Py_ssize_t len_consts, size; 92 int opcode; 93 94 /* Pre-conditions */ 95 assert(PyList_CheckExact(consts)); 96 assert(codestr[0] == LOAD_CONST); 97 assert(codestr[3] == LOAD_CONST); 98 99 /* Create new constant */ 100 v = PyList_GET_ITEM(consts, GETARG(codestr, 0)); 101 w = PyList_GET_ITEM(consts, GETARG(codestr, 3)); 102 opcode = codestr[6]; 103 switch (opcode) { 104 case BINARY_POWER: 105 newconst = PyNumber_Power(v, w, Py_None); 106 break; 107 case BINARY_MULTIPLY: 108 newconst = PyNumber_Multiply(v, w); 109 break; 110 case BINARY_DIVIDE: 111 /* Cannot fold this operation statically since 112 the result can depend on the run-time presence 113 of the -Qnew flag */ 114 return 0; 115 case BINARY_TRUE_DIVIDE: 116 newconst = PyNumber_TrueDivide(v, w); 117 break; 118 case BINARY_FLOOR_DIVIDE: 119 newconst = PyNumber_FloorDivide(v, w); 120 break; 121 case BINARY_MODULO: 122 newconst = PyNumber_Remainder(v, w); 123 break; 124 case BINARY_ADD: 125 newconst = PyNumber_Add(v, w); 126 break; 127 case BINARY_SUBTRACT: 128 newconst = PyNumber_Subtract(v, w); 129 break; 130 case BINARY_SUBSCR: 131 /* #5057: if v is unicode, there might be differences between 132 wide and narrow builds in cases like '\U00012345'[0] or 133 '\U00012345abcdef'[3], so it's better to skip the optimization 134 in order to produce compatible pycs. 135 */ 136 if (PyUnicode_Check(v)) 137 return 0; 138 newconst = PyObject_GetItem(v, w); 139 break; 140 case BINARY_LSHIFT: 141 newconst = PyNumber_Lshift(v, w); 142 break; 143 case BINARY_RSHIFT: 144 newconst = PyNumber_Rshift(v, w); 145 break; 146 case BINARY_AND: 147 newconst = PyNumber_And(v, w); 148 break; 149 case BINARY_XOR: 150 newconst = PyNumber_Xor(v, w); 151 break; 152 case BINARY_OR: 153 newconst = PyNumber_Or(v, w); 154 break; 155 default: 156 /* Called with an unknown opcode */ 157 PyErr_Format(PyExc_SystemError, 158 "unexpected binary operation %d on a constant", 159 opcode); 160 return 0; 161 } 162 if (newconst == NULL) { 163 PyErr_Clear(); 164 return 0; 165 } 166 size = PyObject_Size(newconst); 167 if (size == -1) 168 PyErr_Clear(); 169 else if (size > 20) { 170 Py_DECREF(newconst); 171 return 0; 172 } 173 174 /* Append folded constant into consts table */ 175 len_consts = PyList_GET_SIZE(consts); 176 if (PyList_Append(consts, newconst)) { 177 Py_DECREF(newconst); 178 return 0; 179 } 180 Py_DECREF(newconst); 181 182 /* Write NOP NOP NOP NOP LOAD_CONST newconst */ 183 memset(codestr, NOP, 4); 184 codestr[4] = LOAD_CONST; 185 SETARG(codestr, 4, len_consts); 186 return 1; 175 187 } 176 188 … … 178 190 fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts) 179 191 { 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 192 PyObject *newconst=NULL, *v; 193 Py_ssize_t len_consts; 194 int opcode; 195 196 /* Pre-conditions */ 197 assert(PyList_CheckExact(consts)); 198 assert(codestr[0] == LOAD_CONST); 199 200 /* Create new constant */ 201 v = PyList_GET_ITEM(consts, GETARG(codestr, 0)); 202 opcode = codestr[3]; 203 switch (opcode) { 204 case UNARY_NEGATIVE: 205 /* Preserve the sign of -0.0 */ 206 if (PyObject_IsTrue(v) == 1) 207 newconst = PyNumber_Negative(v); 208 break; 209 case UNARY_CONVERT: 210 newconst = PyObject_Repr(v); 211 break; 212 case UNARY_INVERT: 213 newconst = PyNumber_Invert(v); 214 break; 215 default: 216 /* Called with an unknown opcode */ 217 PyErr_Format(PyExc_SystemError, 218 "unexpected unary operation %d on a constant", 219 opcode); 220 return 0; 221 } 222 if (newconst == NULL) { 223 PyErr_Clear(); 224 return 0; 225 } 226 227 /* Append folded constant into consts table */ 228 len_consts = PyList_GET_SIZE(consts); 229 if (PyList_Append(consts, newconst)) { 230 Py_DECREF(newconst); 231 return 0; 232 } 233 Py_DECREF(newconst); 234 235 /* Write NOP LOAD_CONST newconst */ 236 codestr[0] = NOP; 237 codestr[1] = LOAD_CONST; 238 SETARG(codestr, 1, len_consts); 239 return 1; 228 240 } 229 241 … … 231 243 markblocks(unsigned char *code, Py_ssize_t len) 232 244 { 233 unsigned int *blocks = (unsigned int *)PyMem_Malloc(len*sizeof(int)); 234 int i,j, opcode, blockcnt = 0; 235 236 if (blocks == NULL) { 237 PyErr_NoMemory(); 238 return NULL; 239 } 240 memset(blocks, 0, len*sizeof(int)); 241 242 /* Mark labels in the first pass */ 243 for (i=0 ; i<len ; i+=CODESIZE(opcode)) { 244 opcode = code[i]; 245 switch (opcode) { 246 case FOR_ITER: 247 case JUMP_FORWARD: 248 case JUMP_IF_FALSE: 249 case JUMP_IF_TRUE: 250 case JUMP_ABSOLUTE: 251 case CONTINUE_LOOP: 252 case SETUP_LOOP: 253 case SETUP_EXCEPT: 254 case SETUP_FINALLY: 255 j = GETJUMPTGT(code, i); 256 blocks[j] = 1; 257 break; 258 } 259 } 260 /* Build block numbers in the second pass */ 261 for (i=0 ; i<len ; i++) { 262 blockcnt += blocks[i]; /* increment blockcnt over labels */ 263 blocks[i] = blockcnt; 264 } 265 return blocks; 245 unsigned int *blocks = (unsigned int *)PyMem_Malloc(len*sizeof(int)); 246 int i,j, opcode, blockcnt = 0; 247 248 if (blocks == NULL) { 249 PyErr_NoMemory(); 250 return NULL; 251 } 252 memset(blocks, 0, len*sizeof(int)); 253 254 /* Mark labels in the first pass */ 255 for (i=0 ; i<len ; i+=CODESIZE(opcode)) { 256 opcode = code[i]; 257 switch (opcode) { 258 case FOR_ITER: 259 case JUMP_FORWARD: 260 case JUMP_IF_FALSE_OR_POP: 261 case JUMP_IF_TRUE_OR_POP: 262 case POP_JUMP_IF_FALSE: 263 case POP_JUMP_IF_TRUE: 264 case JUMP_ABSOLUTE: 265 case CONTINUE_LOOP: 266 case SETUP_LOOP: 267 case SETUP_EXCEPT: 268 case SETUP_FINALLY: 269 case SETUP_WITH: 270 j = GETJUMPTGT(code, i); 271 blocks[j] = 1; 272 break; 273 } 274 } 275 /* Build block numbers in the second pass */ 276 for (i=0 ; i<len ; i++) { 277 blockcnt += blocks[i]; /* increment blockcnt over labels */ 278 blocks[i] = blockcnt; 279 } 280 return blocks; 266 281 } 267 282 268 283 /* Perform basic peephole optimizations to components of a code object. 269 The consts object should still be in list form to allow new constants 284 The consts object should still be in list form to allow new constants 270 285 to be appended. 271 286 272 287 To keep the optimizer simple, it bails out (does nothing) for code 273 containing extended arguments or that has a length over 32,700. That 274 allows us to avoid overflow and sign issues. 288 containing extended arguments or that has a length over 32,700. That 289 allows us to avoid overflow and sign issues. Likewise, it bails when 275 290 the lineno table has complex encoding for gaps >= 255. 276 291 277 292 Optimizations are restricted to simple transformations occuring within a 278 single basic block. All transformations keep the code size the same or279 smaller. For those that reduce size, the gaps are initially filled with 280 NOPs. Later those NOPs are removed and the jump addresses retargeted in 293 single basic block. All transformations keep the code size the same or 294 smaller. For those that reduce size, the gaps are initially filled with 295 NOPs. Later those NOPs are removed and the jump addresses retargeted in 281 296 a single pass. Line numbering is adjusted accordingly. */ 282 297 … … 285 300 PyObject *lineno_obj) 286 301 { 287 Py_ssize_t i, j, codelen; 288 int nops, h, adj; 289 int tgt, tgttgt, opcode; 290 unsigned char *codestr = NULL; 291 unsigned char *lineno; 292 int *addrmap = NULL; 293 int new_line, cum_orig_line, last_line, tabsiz; 294 int cumlc=0, lastlc=0; /* Count runs of consecutive LOAD_CONSTs */ 295 unsigned int *blocks = NULL; 296 char *name; 297 298 /* Bail out if an exception is set */ 299 if (PyErr_Occurred()) 300 goto exitError; 301 302 /* Bypass optimization when the lineno table is too complex */ 303 assert(PyString_Check(lineno_obj)); 304 lineno = (unsigned char*)PyString_AS_STRING(lineno_obj); 305 tabsiz = PyString_GET_SIZE(lineno_obj); 306 if (memchr(lineno, 255, tabsiz) != NULL) 307 goto exitUnchanged; 308 309 /* Avoid situations where jump retargeting could overflow */ 310 assert(PyString_Check(code)); 311 codelen = PyString_GET_SIZE(code); 312 if (codelen > 32700) 313 goto exitUnchanged; 314 315 /* Make a modifiable copy of the code string */ 316 codestr = (unsigned char *)PyMem_Malloc(codelen); 317 if (codestr == NULL) 318 goto exitError; 319 codestr = (unsigned char *)memcpy(codestr, 320 PyString_AS_STRING(code), codelen); 321 322 /* Verify that RETURN_VALUE terminates the codestring. This allows 323 the various transformation patterns to look ahead several 324 instructions without additional checks to make sure they are not 325 looking beyond the end of the code string. 326 */ 327 if (codestr[codelen-1] != RETURN_VALUE) 328 goto exitUnchanged; 329 330 /* Mapping to new jump targets after NOPs are removed */ 331 addrmap = (int *)PyMem_Malloc(codelen * sizeof(int)); 332 if (addrmap == NULL) 333 goto exitError; 334 335 blocks = markblocks(codestr, codelen); 336 if (blocks == NULL) 337 goto exitError; 338 assert(PyList_Check(consts)); 339 340 for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) { 341 opcode = codestr[i]; 342 343 lastlc = cumlc; 344 cumlc = 0; 345 346 switch (opcode) { 347 348 /* Replace UNARY_NOT JUMP_IF_FALSE POP_TOP with 349 with JUMP_IF_TRUE POP_TOP */ 350 case UNARY_NOT: 351 if (codestr[i+1] != JUMP_IF_FALSE || 352 codestr[i+4] != POP_TOP || 353 !ISBASICBLOCK(blocks,i,5)) 354 continue; 355 tgt = GETJUMPTGT(codestr, (i+1)); 356 if (codestr[tgt] != POP_TOP) 357 continue; 358 j = GETARG(codestr, i+1) + 1; 359 codestr[i] = JUMP_IF_TRUE; 360 SETARG(codestr, i, j); 361 codestr[i+3] = POP_TOP; 362 codestr[i+4] = NOP; 363 break; 364 365 /* not a is b --> a is not b 366 not a in b --> a not in b 367 not a is not b --> a is b 368 not a not in b --> a in b 369 */ 370 case COMPARE_OP: 371 j = GETARG(codestr, i); 372 if (j < 6 || j > 9 || 373 codestr[i+3] != UNARY_NOT || 374 !ISBASICBLOCK(blocks,i,4)) 375 continue; 376 SETARG(codestr, i, (j^1)); 377 codestr[i+3] = NOP; 378 break; 379 380 /* Replace LOAD_GLOBAL/LOAD_NAME None 381 with LOAD_CONST None */ 382 case LOAD_NAME: 383 case LOAD_GLOBAL: 384 j = GETARG(codestr, i); 385 name = PyString_AsString(PyTuple_GET_ITEM(names, j)); 386 if (name == NULL || strcmp(name, "None") != 0) 387 continue; 388 for (j=0 ; j < PyList_GET_SIZE(consts) ; j++) { 389 if (PyList_GET_ITEM(consts, j) == Py_None) 390 break; 391 } 392 if (j == PyList_GET_SIZE(consts)) { 393 if (PyList_Append(consts, Py_None) == -1) 394 goto exitError; 395 } 396 assert(PyList_GET_ITEM(consts, j) == Py_None); 397 codestr[i] = LOAD_CONST; 398 SETARG(codestr, i, j); 399 cumlc = lastlc + 1; 400 break; 401 402 /* Skip over LOAD_CONST trueconst 403 JUMP_IF_FALSE xx POP_TOP */ 404 case LOAD_CONST: 405 cumlc = lastlc + 1; 406 j = GETARG(codestr, i); 407 if (codestr[i+3] != JUMP_IF_FALSE || 408 codestr[i+6] != POP_TOP || 409 !ISBASICBLOCK(blocks,i,7) || 410 !PyObject_IsTrue(PyList_GET_ITEM(consts, j))) 411 continue; 412 memset(codestr+i, NOP, 7); 413 cumlc = 0; 414 break; 415 416 /* Try to fold tuples of constants (includes a case for lists 417 which are only used for "in" and "not in" tests). 418 Skip over BUILD_SEQN 1 UNPACK_SEQN 1. 419 Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2. 420 Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */ 421 case BUILD_TUPLE: 422 case BUILD_LIST: 423 j = GETARG(codestr, i); 424 h = i - 3 * j; 425 if (h >= 0 && 426 j <= lastlc && 427 ((opcode == BUILD_TUPLE && 428 ISBASICBLOCK(blocks, h, 3*(j+1))) || 429 (opcode == BUILD_LIST && 430 codestr[i+3]==COMPARE_OP && 431 ISBASICBLOCK(blocks, h, 3*(j+2)) && 432 (GETARG(codestr,i+3)==6 || 433 GETARG(codestr,i+3)==7))) && 434 tuple_of_constants(&codestr[h], j, consts)) { 435 assert(codestr[i] == LOAD_CONST); 436 cumlc = 1; 437 break; 438 } 439 if (codestr[i+3] != UNPACK_SEQUENCE || 440 !ISBASICBLOCK(blocks,i,6) || 441 j != GETARG(codestr, i+3)) 442 continue; 443 if (j == 1) { 444 memset(codestr+i, NOP, 6); 445 } else if (j == 2) { 446 codestr[i] = ROT_TWO; 447 memset(codestr+i+1, NOP, 5); 448 } else if (j == 3) { 449 codestr[i] = ROT_THREE; 450 codestr[i+1] = ROT_TWO; 451 memset(codestr+i+2, NOP, 4); 452 } 453 break; 454 455 /* Fold binary ops on constants. 456 LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */ 457 case BINARY_POWER: 458 case BINARY_MULTIPLY: 459 case BINARY_TRUE_DIVIDE: 460 case BINARY_FLOOR_DIVIDE: 461 case BINARY_MODULO: 462 case BINARY_ADD: 463 case BINARY_SUBTRACT: 464 case BINARY_SUBSCR: 465 case BINARY_LSHIFT: 466 case BINARY_RSHIFT: 467 case BINARY_AND: 468 case BINARY_XOR: 469 case BINARY_OR: 470 if (lastlc >= 2 && 471 ISBASICBLOCK(blocks, i-6, 7) && 472 fold_binops_on_constants(&codestr[i-6], consts)) { 473 i -= 2; 474 assert(codestr[i] == LOAD_CONST); 475 cumlc = 1; 476 } 477 break; 478 479 /* Fold unary ops on constants. 480 LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */ 481 case UNARY_NEGATIVE: 482 case UNARY_CONVERT: 483 case UNARY_INVERT: 484 if (lastlc >= 1 && 485 ISBASICBLOCK(blocks, i-3, 4) && 486 fold_unaryops_on_constants(&codestr[i-3], consts)) { 487 i -= 2; 488 assert(codestr[i] == LOAD_CONST); 489 cumlc = 1; 490 } 491 break; 492 493 /* Simplify conditional jump to conditional jump where the 494 result of the first test implies the success of a similar 495 test or the failure of the opposite test. 496 Arises in code like: 497 "if a and b:" 498 "if a or b:" 499 "a and b or c" 500 "(a and b) and c" 501 x:JUMP_IF_FALSE y y:JUMP_IF_FALSE z --> x:JUMP_IF_FALSE z 502 x:JUMP_IF_FALSE y y:JUMP_IF_TRUE z --> x:JUMP_IF_FALSE y+3 503 where y+3 is the instruction following the second test. 504 */ 505 case JUMP_IF_FALSE: 506 case JUMP_IF_TRUE: 507 tgt = GETJUMPTGT(codestr, i); 508 j = codestr[tgt]; 509 if (j == JUMP_IF_FALSE || j == JUMP_IF_TRUE) { 510 if (j == opcode) { 511 tgttgt = GETJUMPTGT(codestr, tgt) - i - 3; 512 SETARG(codestr, i, tgttgt); 513 } else { 514 tgt -= i; 515 SETARG(codestr, i, tgt); 516 } 517 break; 518 } 519 /* Intentional fallthrough */ 520 521 /* Replace jumps to unconditional jumps */ 522 case FOR_ITER: 523 case JUMP_FORWARD: 524 case JUMP_ABSOLUTE: 525 case CONTINUE_LOOP: 526 case SETUP_LOOP: 527 case SETUP_EXCEPT: 528 case SETUP_FINALLY: 529 tgt = GETJUMPTGT(codestr, i); 530 /* Replace JUMP_* to a RETURN into just a RETURN */ 531 if (UNCONDITIONAL_JUMP(opcode) && 532 codestr[tgt] == RETURN_VALUE) { 533 codestr[i] = RETURN_VALUE; 534 memset(codestr+i+1, NOP, 2); 535 continue; 536 } 537 if (!UNCONDITIONAL_JUMP(codestr[tgt])) 538 continue; 539 tgttgt = GETJUMPTGT(codestr, tgt); 540 if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */ 541 opcode = JUMP_ABSOLUTE; 542 if (!ABSOLUTE_JUMP(opcode)) 543 tgttgt -= i + 3; /* Calc relative jump addr */ 544 if (tgttgt < 0) /* No backward relative jumps */ 545 continue; 546 codestr[i] = opcode; 547 SETARG(codestr, i, tgttgt); 548 break; 549 550 case EXTENDED_ARG: 551 goto exitUnchanged; 552 553 /* Replace RETURN LOAD_CONST None RETURN with just RETURN */ 554 /* Remove unreachable JUMPs after RETURN */ 555 case RETURN_VALUE: 556 if (i+4 >= codelen) 557 continue; 558 if (codestr[i+4] == RETURN_VALUE && 559 ISBASICBLOCK(blocks,i,5)) 560 memset(codestr+i+1, NOP, 4); 561 else if (UNCONDITIONAL_JUMP(codestr[i+1]) && 562 ISBASICBLOCK(blocks,i,4)) 563 memset(codestr+i+1, NOP, 3); 564 break; 565 } 566 } 567 568 /* Fixup linenotab */ 569 for (i=0, nops=0 ; i<codelen ; i += CODESIZE(codestr[i])) { 570 addrmap[i] = i - nops; 571 if (codestr[i] == NOP) 572 nops++; 573 } 574 cum_orig_line = 0; 575 last_line = 0; 576 for (i=0 ; i < tabsiz ; i+=2) { 577 cum_orig_line += lineno[i]; 578 new_line = addrmap[cum_orig_line]; 579 assert (new_line - last_line < 255); 580 lineno[i] =((unsigned char)(new_line - last_line)); 581 last_line = new_line; 582 } 583 584 /* Remove NOPs and fixup jump targets */ 585 for (i=0, h=0 ; i<codelen ; ) { 586 opcode = codestr[i]; 587 switch (opcode) { 588 case NOP: 589 i++; 590 continue; 591 592 case JUMP_ABSOLUTE: 593 case CONTINUE_LOOP: 594 j = addrmap[GETARG(codestr, i)]; 595 SETARG(codestr, i, j); 596 break; 597 598 case FOR_ITER: 599 case JUMP_FORWARD: 600 case JUMP_IF_FALSE: 601 case JUMP_IF_TRUE: 602 case SETUP_LOOP: 603 case SETUP_EXCEPT: 604 case SETUP_FINALLY: 605 j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3; 606 SETARG(codestr, i, j); 607 break; 608 } 609 adj = CODESIZE(opcode); 610 while (adj--) 611 codestr[h++] = codestr[i++]; 612 } 613 assert(h + nops == codelen); 614 615 code = PyString_FromStringAndSize((char *)codestr, h); 616 PyMem_Free(addrmap); 617 PyMem_Free(codestr); 618 PyMem_Free(blocks); 619 return code; 302 Py_ssize_t i, j, codelen; 303 int nops, h, adj; 304 int tgt, tgttgt, opcode; 305 unsigned char *codestr = NULL; 306 unsigned char *lineno; 307 int *addrmap = NULL; 308 int new_line, cum_orig_line, last_line, tabsiz; 309 int cumlc=0, lastlc=0; /* Count runs of consecutive LOAD_CONSTs */ 310 unsigned int *blocks = NULL; 311 char *name; 312 313 /* Bail out if an exception is set */ 314 if (PyErr_Occurred()) 315 goto exitError; 316 317 /* Bypass optimization when the lineno table is too complex */ 318 assert(PyString_Check(lineno_obj)); 319 lineno = (unsigned char*)PyString_AS_STRING(lineno_obj); 320 tabsiz = PyString_GET_SIZE(lineno_obj); 321 if (memchr(lineno, 255, tabsiz) != NULL) 322 goto exitUnchanged; 323 324 /* Avoid situations where jump retargeting could overflow */ 325 assert(PyString_Check(code)); 326 codelen = PyString_GET_SIZE(code); 327 if (codelen > 32700) 328 goto exitUnchanged; 329 330 /* Make a modifiable copy of the code string */ 331 codestr = (unsigned char *)PyMem_Malloc(codelen); 332 if (codestr == NULL) 333 goto exitError; 334 codestr = (unsigned char *)memcpy(codestr, 335 PyString_AS_STRING(code), codelen); 336 337 /* Verify that RETURN_VALUE terminates the codestring. This allows 338 the various transformation patterns to look ahead several 339 instructions without additional checks to make sure they are not 340 looking beyond the end of the code string. 341 */ 342 if (codestr[codelen-1] != RETURN_VALUE) 343 goto exitUnchanged; 344 345 /* Mapping to new jump targets after NOPs are removed */ 346 addrmap = (int *)PyMem_Malloc(codelen * sizeof(int)); 347 if (addrmap == NULL) 348 goto exitError; 349 350 blocks = markblocks(codestr, codelen); 351 if (blocks == NULL) 352 goto exitError; 353 assert(PyList_Check(consts)); 354 355 for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) { 356 reoptimize_current: 357 opcode = codestr[i]; 358 359 lastlc = cumlc; 360 cumlc = 0; 361 362 switch (opcode) { 363 /* Replace UNARY_NOT POP_JUMP_IF_FALSE 364 with POP_JUMP_IF_TRUE */ 365 case UNARY_NOT: 366 if (codestr[i+1] != POP_JUMP_IF_FALSE 367 || !ISBASICBLOCK(blocks,i,4)) 368 continue; 369 j = GETARG(codestr, i+1); 370 codestr[i] = POP_JUMP_IF_TRUE; 371 SETARG(codestr, i, j); 372 codestr[i+3] = NOP; 373 goto reoptimize_current; 374 375 /* not a is b --> a is not b 376 not a in b --> a not in b 377 not a is not b --> a is b 378 not a not in b --> a in b 379 */ 380 case COMPARE_OP: 381 j = GETARG(codestr, i); 382 if (j < 6 || j > 9 || 383 codestr[i+3] != UNARY_NOT || 384 !ISBASICBLOCK(blocks,i,4)) 385 continue; 386 SETARG(codestr, i, (j^1)); 387 codestr[i+3] = NOP; 388 break; 389 390 /* Replace LOAD_GLOBAL/LOAD_NAME None 391 with LOAD_CONST None */ 392 case LOAD_NAME: 393 case LOAD_GLOBAL: 394 j = GETARG(codestr, i); 395 name = PyString_AsString(PyTuple_GET_ITEM(names, j)); 396 if (name == NULL || strcmp(name, "None") != 0) 397 continue; 398 for (j=0 ; j < PyList_GET_SIZE(consts) ; j++) { 399 if (PyList_GET_ITEM(consts, j) == Py_None) 400 break; 401 } 402 if (j == PyList_GET_SIZE(consts)) { 403 if (PyList_Append(consts, Py_None) == -1) 404 goto exitError; 405 } 406 assert(PyList_GET_ITEM(consts, j) == Py_None); 407 codestr[i] = LOAD_CONST; 408 SETARG(codestr, i, j); 409 cumlc = lastlc + 1; 410 break; 411 412 /* Skip over LOAD_CONST trueconst 413 POP_JUMP_IF_FALSE xx. This improves 414 "while 1" performance. */ 415 case LOAD_CONST: 416 cumlc = lastlc + 1; 417 j = GETARG(codestr, i); 418 if (codestr[i+3] != POP_JUMP_IF_FALSE || 419 !ISBASICBLOCK(blocks,i,6) || 420 !PyObject_IsTrue(PyList_GET_ITEM(consts, j))) 421 continue; 422 memset(codestr+i, NOP, 6); 423 cumlc = 0; 424 break; 425 426 /* Try to fold tuples of constants (includes a case for lists 427 which are only used for "in" and "not in" tests). 428 Skip over BUILD_SEQN 1 UNPACK_SEQN 1. 429 Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2. 430 Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */ 431 case BUILD_TUPLE: 432 case BUILD_LIST: 433 j = GETARG(codestr, i); 434 h = i - 3 * j; 435 if (h >= 0 && 436 j <= lastlc && 437 ((opcode == BUILD_TUPLE && 438 ISBASICBLOCK(blocks, h, 3*(j+1))) || 439 (opcode == BUILD_LIST && 440 codestr[i+3]==COMPARE_OP && 441 ISBASICBLOCK(blocks, h, 3*(j+2)) && 442 (GETARG(codestr,i+3)==6 || 443 GETARG(codestr,i+3)==7))) && 444 tuple_of_constants(&codestr[h], j, consts)) { 445 assert(codestr[i] == LOAD_CONST); 446 cumlc = 1; 447 break; 448 } 449 if (codestr[i+3] != UNPACK_SEQUENCE || 450 !ISBASICBLOCK(blocks,i,6) || 451 j != GETARG(codestr, i+3)) 452 continue; 453 if (j == 1) { 454 memset(codestr+i, NOP, 6); 455 } else if (j == 2) { 456 codestr[i] = ROT_TWO; 457 memset(codestr+i+1, NOP, 5); 458 } else if (j == 3) { 459 codestr[i] = ROT_THREE; 460 codestr[i+1] = ROT_TWO; 461 memset(codestr+i+2, NOP, 4); 462 } 463 break; 464 465 /* Fold binary ops on constants. 466 LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */ 467 case BINARY_POWER: 468 case BINARY_MULTIPLY: 469 case BINARY_TRUE_DIVIDE: 470 case BINARY_FLOOR_DIVIDE: 471 case BINARY_MODULO: 472 case BINARY_ADD: 473 case BINARY_SUBTRACT: 474 case BINARY_SUBSCR: 475 case BINARY_LSHIFT: 476 case BINARY_RSHIFT: 477 case BINARY_AND: 478 case BINARY_XOR: 479 case BINARY_OR: 480 if (lastlc >= 2 && 481 ISBASICBLOCK(blocks, i-6, 7) && 482 fold_binops_on_constants(&codestr[i-6], consts)) { 483 i -= 2; 484 assert(codestr[i] == LOAD_CONST); 485 cumlc = 1; 486 } 487 break; 488 489 /* Fold unary ops on constants. 490 LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */ 491 case UNARY_NEGATIVE: 492 case UNARY_CONVERT: 493 case UNARY_INVERT: 494 if (lastlc >= 1 && 495 ISBASICBLOCK(blocks, i-3, 4) && 496 fold_unaryops_on_constants(&codestr[i-3], consts)) { 497 i -= 2; 498 assert(codestr[i] == LOAD_CONST); 499 cumlc = 1; 500 } 501 break; 502 503 /* Simplify conditional jump to conditional jump where the 504 result of the first test implies the success of a similar 505 test or the failure of the opposite test. 506 Arises in code like: 507 "if a and b:" 508 "if a or b:" 509 "a and b or c" 510 "(a and b) and c" 511 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z 512 --> x:JUMP_IF_FALSE_OR_POP z 513 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z 514 --> x:POP_JUMP_IF_FALSE y+3 515 where y+3 is the instruction following the second test. 516 */ 517 case JUMP_IF_FALSE_OR_POP: 518 case JUMP_IF_TRUE_OR_POP: 519 tgt = GETJUMPTGT(codestr, i); 520 j = codestr[tgt]; 521 if (CONDITIONAL_JUMP(j)) { 522 /* NOTE: all possible jumps here are absolute! */ 523 if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) { 524 /* The second jump will be 525 taken iff the first is. */ 526 tgttgt = GETJUMPTGT(codestr, tgt); 527 /* The current opcode inherits 528 its target's stack behaviour */ 529 codestr[i] = j; 530 SETARG(codestr, i, tgttgt); 531 goto reoptimize_current; 532 } else { 533 /* The second jump is not taken if the first is (so 534 jump past it), and all conditional jumps pop their 535 argument when they're not taken (so change the 536 first jump to pop its argument when it's taken). */ 537 if (JUMPS_ON_TRUE(opcode)) 538 codestr[i] = POP_JUMP_IF_TRUE; 539 else 540 codestr[i] = POP_JUMP_IF_FALSE; 541 SETARG(codestr, i, (tgt + 3)); 542 goto reoptimize_current; 543 } 544 } 545 /* Intentional fallthrough */ 546 547 /* Replace jumps to unconditional jumps */ 548 case POP_JUMP_IF_FALSE: 549 case POP_JUMP_IF_TRUE: 550 case FOR_ITER: 551 case JUMP_FORWARD: 552 case JUMP_ABSOLUTE: 553 case CONTINUE_LOOP: 554 case SETUP_LOOP: 555 case SETUP_EXCEPT: 556 case SETUP_FINALLY: 557 case SETUP_WITH: 558 tgt = GETJUMPTGT(codestr, i); 559 /* Replace JUMP_* to a RETURN into just a RETURN */ 560 if (UNCONDITIONAL_JUMP(opcode) && 561 codestr[tgt] == RETURN_VALUE) { 562 codestr[i] = RETURN_VALUE; 563 memset(codestr+i+1, NOP, 2); 564 continue; 565 } 566 if (!UNCONDITIONAL_JUMP(codestr[tgt])) 567 continue; 568 tgttgt = GETJUMPTGT(codestr, tgt); 569 if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */ 570 opcode = JUMP_ABSOLUTE; 571 if (!ABSOLUTE_JUMP(opcode)) 572 tgttgt -= i + 3; /* Calc relative jump addr */ 573 if (tgttgt < 0) /* No backward relative jumps */ 574 continue; 575 codestr[i] = opcode; 576 SETARG(codestr, i, tgttgt); 577 break; 578 579 case EXTENDED_ARG: 580 goto exitUnchanged; 581 582 /* Replace RETURN LOAD_CONST None RETURN with just RETURN */ 583 /* Remove unreachable JUMPs after RETURN */ 584 case RETURN_VALUE: 585 if (i+4 >= codelen) 586 continue; 587 if (codestr[i+4] == RETURN_VALUE && 588 ISBASICBLOCK(blocks,i,5)) 589 memset(codestr+i+1, NOP, 4); 590 else if (UNCONDITIONAL_JUMP(codestr[i+1]) && 591 ISBASICBLOCK(blocks,i,4)) 592 memset(codestr+i+1, NOP, 3); 593 break; 594 } 595 } 596 597 /* Fixup linenotab */ 598 for (i=0, nops=0 ; i<codelen ; i += CODESIZE(codestr[i])) { 599 addrmap[i] = i - nops; 600 if (codestr[i] == NOP) 601 nops++; 602 } 603 cum_orig_line = 0; 604 last_line = 0; 605 for (i=0 ; i < tabsiz ; i+=2) { 606 cum_orig_line += lineno[i]; 607 new_line = addrmap[cum_orig_line]; 608 assert (new_line - last_line < 255); 609 lineno[i] =((unsigned char)(new_line - last_line)); 610 last_line = new_line; 611 } 612 613 /* Remove NOPs and fixup jump targets */ 614 for (i=0, h=0 ; i<codelen ; ) { 615 opcode = codestr[i]; 616 switch (opcode) { 617 case NOP: 618 i++; 619 continue; 620 621 case JUMP_ABSOLUTE: 622 case CONTINUE_LOOP: 623 case POP_JUMP_IF_FALSE: 624 case POP_JUMP_IF_TRUE: 625 case JUMP_IF_FALSE_OR_POP: 626 case JUMP_IF_TRUE_OR_POP: 627 j = addrmap[GETARG(codestr, i)]; 628 SETARG(codestr, i, j); 629 break; 630 631 case FOR_ITER: 632 case JUMP_FORWARD: 633 case SETUP_LOOP: 634 case SETUP_EXCEPT: 635 case SETUP_FINALLY: 636 case SETUP_WITH: 637 j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3; 638 SETARG(codestr, i, j); 639 break; 640 } 641 adj = CODESIZE(opcode); 642 while (adj--) 643 codestr[h++] = codestr[i++]; 644 } 645 assert(h + nops == codelen); 646 647 code = PyString_FromStringAndSize((char *)codestr, h); 648 PyMem_Free(addrmap); 649 PyMem_Free(codestr); 650 PyMem_Free(blocks); 651 return code; 620 652 621 653 exitError: 622 654 code = NULL; 623 655 624 656 exitUnchanged: 625 626 627 628 629 630 631 632 657 if (blocks != NULL) 658 PyMem_Free(blocks); 659 if (addrmap != NULL) 660 PyMem_Free(addrmap); 661 if (codestr != NULL) 662 PyMem_Free(codestr); 663 Py_XINCREF(code); 664 return code; 633 665 }
Note:
See TracChangeset
for help on using the changeset viewer.