blob: 104db8cb978cbe4aa67f301e3f151bd2c828a7c2 [file] [log] [blame]
Guido van Rossumd8faa362007-04-27 19:54:29 +00001/* Peephole optimizations for bytecode compiler. */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002
3#include "Python.h"
4
5#include "Python-ast.h"
6#include "node.h"
7#include "pyarena.h"
8#include "ast.h"
9#include "code.h"
10#include "compile.h"
11#include "symtable.h"
12#include "opcode.h"
13
14#define GETARG(arr, i) ((int)((arr[i+2]<<8) + arr[i+1]))
15#define UNCONDITIONAL_JUMP(op) (op==JUMP_ABSOLUTE || op==JUMP_FORWARD)
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +000016#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)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000022#define GETJUMPTGT(arr, i) (GETARG(arr,i) + (ABSOLUTE_JUMP(arr[i]) ? 0 : i+3))
23#define SETARG(arr, i, val) arr[i+2] = val>>8; arr[i+1] = val & 255
24#define CODESIZE(op) (HAS_ARG(op) ? 3 : 1)
25#define ISBASICBLOCK(blocks, start, bytes) \
26 (blocks[start]==blocks[start+bytes-1])
27
28/* Replace LOAD_CONST c1. LOAD_CONST c2 ... LOAD_CONST cn BUILD_TUPLE n
29 with LOAD_CONST (c1, c2, ... cn).
30 The consts table must still be in list form so that the
31 new constant (c1, c2, ... cn) can be appended.
32 Called with codestr pointing to the first LOAD_CONST.
33 Bails out with no change if one or more of the LOAD_CONSTs is missing.
34 Also works for BUILD_LIST when followed by an "in" or "not in" test.
35*/
36static int
Christian Heimescc47b052008-03-25 14:56:36 +000037tuple_of_constants(unsigned char *codestr, Py_ssize_t n, PyObject *consts)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000038{
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;
75}
76
77/* Replace LOAD_CONST c1. LOAD_CONST c2 BINOP
78 with LOAD_CONST binop(c1,c2)
79 The consts table must still be in list form so that the
80 new constant can be appended.
81 Called with codestr pointing to the first LOAD_CONST.
82 Abandons the transformation if the folding fails (i.e. 1+'a').
83 If the new constant is a sequence, only folds when the size
84 is below a threshold value. That keeps pyc files from
85 becoming large in the presence of code like: (None,)*1000.
86*/
87static int
88fold_binops_on_constants(unsigned char *codestr, PyObject *consts)
89{
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_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;
175}
176
177static int
178fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts)
179{
180 PyObject *newconst=NULL, *v;
181 Py_ssize_t len_consts;
182 int opcode;
183
184 /* Pre-conditions */
185 assert(PyList_CheckExact(consts));
186 assert(codestr[0] == LOAD_CONST);
187
188 /* Create new constant */
189 v = PyList_GET_ITEM(consts, GETARG(codestr, 0));
190 opcode = codestr[3];
191 switch (opcode) {
192 case UNARY_NEGATIVE:
193 /* Preserve the sign of -0.0 */
194 if (PyObject_IsTrue(v) == 1)
195 newconst = PyNumber_Negative(v);
196 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000197 case UNARY_INVERT:
198 newconst = PyNumber_Invert(v);
199 break;
Raymond Hettingeraf7adad2009-10-22 11:22:50 +0000200 case UNARY_POSITIVE:
201 newconst = PyNumber_Positive(v);
202 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000203 default:
204 /* Called with an unknown opcode */
205 PyErr_Format(PyExc_SystemError,
206 "unexpected unary operation %d on a constant",
207 opcode);
208 return 0;
209 }
210 if (newconst == NULL) {
211 PyErr_Clear();
212 return 0;
213 }
214
215 /* Append folded constant into consts table */
216 len_consts = PyList_GET_SIZE(consts);
217 if (PyList_Append(consts, newconst)) {
218 Py_DECREF(newconst);
219 return 0;
220 }
221 Py_DECREF(newconst);
222
223 /* Write NOP LOAD_CONST newconst */
224 codestr[0] = NOP;
225 codestr[1] = LOAD_CONST;
226 SETARG(codestr, 1, len_consts);
227 return 1;
228}
229
230static unsigned int *
Christian Heimescc47b052008-03-25 14:56:36 +0000231markblocks(unsigned char *code, Py_ssize_t len)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000232{
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:
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000248 case JUMP_IF_FALSE_OR_POP:
249 case JUMP_IF_TRUE_OR_POP:
250 case POP_JUMP_IF_FALSE:
251 case POP_JUMP_IF_TRUE:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000252 case JUMP_ABSOLUTE:
253 case CONTINUE_LOOP:
254 case SETUP_LOOP:
255 case SETUP_EXCEPT:
256 case SETUP_FINALLY:
Benjamin Peterson876b2f22009-06-28 03:18:59 +0000257 case SETUP_WITH:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000258 j = GETJUMPTGT(code, i);
259 blocks[j] = 1;
260 break;
261 }
262 }
263 /* Build block numbers in the second pass */
264 for (i=0 ; i<len ; i++) {
265 blockcnt += blocks[i]; /* increment blockcnt over labels */
266 blocks[i] = blockcnt;
267 }
268 return blocks;
269}
270
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000271/* Helper to replace LOAD_NAME None/True/False with LOAD_CONST
272 Returns: 0 if no change, 1 if change, -1 if error */
273static int
274load_global(unsigned char *codestr, Py_ssize_t i, char *name, PyObject *consts)
275{
276 Py_ssize_t j;
277 PyObject *obj;
278 if (name == NULL)
279 return 0;
280 if (strcmp(name, "None") == 0)
281 obj = Py_None;
282 else if (strcmp(name, "True") == 0)
283 obj = Py_True;
284 else if (strcmp(name, "False") == 0)
285 obj = Py_False;
286 else
287 return 0;
288 for (j = 0; j < PyList_GET_SIZE(consts); j++) {
289 if (PyList_GET_ITEM(consts, j) == obj)
290 break;
291 }
292 if (j == PyList_GET_SIZE(consts)) {
293 if (PyList_Append(consts, obj) < 0)
294 return -1;
295 }
296 assert(PyList_GET_ITEM(consts, j) == obj);
297 codestr[i] = LOAD_CONST;
298 SETARG(codestr, i, j);
299 return 1;
300}
301
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000302/* Perform basic peephole optimizations to components of a code object.
303 The consts object should still be in list form to allow new constants
304 to be appended.
305
Guido van Rossum0240b922007-02-26 21:23:50 +0000306 To keep the optimizer simple, it bails out (does nothing) for code that
307 has a length over 32,700, and does not calculate extended arguments.
308 That allows us to avoid overflow and sign issues. Likewise, it bails when
309 the lineno table has complex encoding for gaps >= 255. EXTENDED_ARG can
310 appear before MAKE_FUNCTION; in this case both opcodes are skipped.
311 EXTENDED_ARG preceding any other opcode causes the optimizer to bail.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000312
313 Optimizations are restricted to simple transformations occuring within a
314 single basic block. All transformations keep the code size the same or
315 smaller. For those that reduce size, the gaps are initially filled with
316 NOPs. Later those NOPs are removed and the jump addresses retargeted in
317 a single pass. Line numbering is adjusted accordingly. */
318
319PyObject *
320PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
321 PyObject *lineno_obj)
322{
323 Py_ssize_t i, j, codelen;
324 int nops, h, adj;
325 int tgt, tgttgt, opcode;
326 unsigned char *codestr = NULL;
327 unsigned char *lineno;
328 int *addrmap = NULL;
329 int new_line, cum_orig_line, last_line, tabsiz;
330 int cumlc=0, lastlc=0; /* Count runs of consecutive LOAD_CONSTs */
331 unsigned int *blocks = NULL;
332 char *name;
333
334 /* Bail out if an exception is set */
335 if (PyErr_Occurred())
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000336 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000337
338 /* Bypass optimization when the lineno table is too complex */
Christian Heimes72b710a2008-05-26 13:28:38 +0000339 assert(PyBytes_Check(lineno_obj));
340 lineno = (unsigned char*)PyBytes_AS_STRING(lineno_obj);
341 tabsiz = PyBytes_GET_SIZE(lineno_obj);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000342 if (memchr(lineno, 255, tabsiz) != NULL)
343 goto exitUnchanged;
344
345 /* Avoid situations where jump retargeting could overflow */
Christian Heimes72b710a2008-05-26 13:28:38 +0000346 assert(PyBytes_Check(code));
347 codelen = PyBytes_GET_SIZE(code);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000348 if (codelen > 32700)
349 goto exitUnchanged;
350
351 /* Make a modifiable copy of the code string */
352 codestr = (unsigned char *)PyMem_Malloc(codelen);
353 if (codestr == NULL)
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000354 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000355 codestr = (unsigned char *)memcpy(codestr,
Christian Heimes72b710a2008-05-26 13:28:38 +0000356 PyBytes_AS_STRING(code), codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000357
358 /* Verify that RETURN_VALUE terminates the codestring. This allows
359 the various transformation patterns to look ahead several
360 instructions without additional checks to make sure they are not
361 looking beyond the end of the code string.
362 */
363 if (codestr[codelen-1] != RETURN_VALUE)
364 goto exitUnchanged;
365
366 /* Mapping to new jump targets after NOPs are removed */
367 addrmap = (int *)PyMem_Malloc(codelen * sizeof(int));
368 if (addrmap == NULL)
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000369 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000370
371 blocks = markblocks(codestr, codelen);
372 if (blocks == NULL)
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000373 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000374 assert(PyList_Check(consts));
375
376 for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000377 reoptimize_current:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000378 opcode = codestr[i];
379
380 lastlc = cumlc;
381 cumlc = 0;
382
383 switch (opcode) {
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000384 /* Replace UNARY_NOT POP_JUMP_IF_FALSE
385 with POP_JUMP_IF_TRUE */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000386 case UNARY_NOT:
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000387 if (codestr[i+1] != POP_JUMP_IF_FALSE
388 || !ISBASICBLOCK(blocks,i,4))
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000389 continue;
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000390 j = GETARG(codestr, i+1);
391 codestr[i] = POP_JUMP_IF_TRUE;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000392 SETARG(codestr, i, j);
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000393 codestr[i+3] = NOP;
394 goto reoptimize_current;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000395
396 /* not a is b --> a is not b
397 not a in b --> a not in b
398 not a is not b --> a is b
399 not a not in b --> a in b
400 */
401 case COMPARE_OP:
402 j = GETARG(codestr, i);
403 if (j < 6 || j > 9 ||
404 codestr[i+3] != UNARY_NOT ||
405 !ISBASICBLOCK(blocks,i,4))
406 continue;
407 SETARG(codestr, i, (j^1));
408 codestr[i+3] = NOP;
409 break;
410
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000411 /* Replace LOAD_GLOBAL/LOAD_NAME None/True/False
412 with LOAD_CONST None/True/False */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000413 case LOAD_NAME:
414 case LOAD_GLOBAL:
415 j = GETARG(codestr, i);
Marc-André Lemburg4cc0f242008-08-07 18:54:33 +0000416 name = _PyUnicode_AsString(PyTuple_GET_ITEM(names, j));
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000417 h = load_global(codestr, i, name, consts);
418 if (h < 0)
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000419 goto exitError;
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000420 else if (h == 0)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000421 continue;
Guido van Rossumd8faa362007-04-27 19:54:29 +0000422 cumlc = lastlc + 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000423 break;
424
425 /* Skip over LOAD_CONST trueconst
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000426 POP_JUMP_IF_FALSE xx. This improves
427 "while 1" performance. */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000428 case LOAD_CONST:
429 cumlc = lastlc + 1;
430 j = GETARG(codestr, i);
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000431 if (codestr[i+3] != POP_JUMP_IF_FALSE ||
Jeffrey Yasskin4dd40522009-02-28 19:49:43 +0000432 !ISBASICBLOCK(blocks,i,6) ||
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000433 !PyObject_IsTrue(PyList_GET_ITEM(consts, j)))
434 continue;
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000435 memset(codestr+i, NOP, 6);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000436 cumlc = 0;
437 break;
438
439 /* Try to fold tuples of constants (includes a case for lists
440 which are only used for "in" and "not in" tests).
441 Skip over BUILD_SEQN 1 UNPACK_SEQN 1.
442 Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2.
443 Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */
444 case BUILD_TUPLE:
445 case BUILD_LIST:
446 j = GETARG(codestr, i);
447 h = i - 3 * j;
448 if (h >= 0 &&
449 j <= lastlc &&
450 ((opcode == BUILD_TUPLE &&
451 ISBASICBLOCK(blocks, h, 3*(j+1))) ||
452 (opcode == BUILD_LIST &&
453 codestr[i+3]==COMPARE_OP &&
454 ISBASICBLOCK(blocks, h, 3*(j+2)) &&
455 (GETARG(codestr,i+3)==6 ||
456 GETARG(codestr,i+3)==7))) &&
457 tuple_of_constants(&codestr[h], j, consts)) {
458 assert(codestr[i] == LOAD_CONST);
459 cumlc = 1;
460 break;
461 }
462 if (codestr[i+3] != UNPACK_SEQUENCE ||
463 !ISBASICBLOCK(blocks,i,6) ||
464 j != GETARG(codestr, i+3))
465 continue;
466 if (j == 1) {
467 memset(codestr+i, NOP, 6);
468 } else if (j == 2) {
469 codestr[i] = ROT_TWO;
470 memset(codestr+i+1, NOP, 5);
471 } else if (j == 3) {
472 codestr[i] = ROT_THREE;
473 codestr[i+1] = ROT_TWO;
474 memset(codestr+i+2, NOP, 4);
475 }
476 break;
477
478 /* Fold binary ops on constants.
479 LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */
480 case BINARY_POWER:
481 case BINARY_MULTIPLY:
482 case BINARY_TRUE_DIVIDE:
483 case BINARY_FLOOR_DIVIDE:
484 case BINARY_MODULO:
485 case BINARY_ADD:
486 case BINARY_SUBTRACT:
487 case BINARY_SUBSCR:
488 case BINARY_LSHIFT:
489 case BINARY_RSHIFT:
490 case BINARY_AND:
491 case BINARY_XOR:
492 case BINARY_OR:
493 if (lastlc >= 2 &&
494 ISBASICBLOCK(blocks, i-6, 7) &&
495 fold_binops_on_constants(&codestr[i-6], consts)) {
496 i -= 2;
497 assert(codestr[i] == LOAD_CONST);
498 cumlc = 1;
499 }
500 break;
501
502 /* Fold unary ops on constants.
503 LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */
504 case UNARY_NEGATIVE:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000505 case UNARY_INVERT:
Raymond Hettingeraf7adad2009-10-22 11:22:50 +0000506 case UNARY_POSITIVE:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000507 if (lastlc >= 1 &&
508 ISBASICBLOCK(blocks, i-3, 4) &&
509 fold_unaryops_on_constants(&codestr[i-3], consts)) {
510 i -= 2;
511 assert(codestr[i] == LOAD_CONST);
512 cumlc = 1;
513 }
514 break;
515
516 /* Simplify conditional jump to conditional jump where the
517 result of the first test implies the success of a similar
518 test or the failure of the opposite test.
519 Arises in code like:
520 "if a and b:"
521 "if a or b:"
522 "a and b or c"
523 "(a and b) and c"
Jeffrey Yasskin4dd40522009-02-28 19:49:43 +0000524 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z
525 --> x:JUMP_IF_FALSE_OR_POP z
526 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z
527 --> x:POP_JUMP_IF_FALSE y+3
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000528 where y+3 is the instruction following the second test.
529 */
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000530 case JUMP_IF_FALSE_OR_POP:
531 case JUMP_IF_TRUE_OR_POP:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000532 tgt = GETJUMPTGT(codestr, i);
533 j = codestr[tgt];
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000534 if (CONDITIONAL_JUMP(j)) {
535 /* NOTE: all possible jumps here are
536 absolute! */
537 if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) {
538 /* The second jump will be
539 taken iff the first is. */
540 tgttgt = GETJUMPTGT(codestr, tgt);
541 /* The current opcode inherits
542 its target's stack behaviour */
543 codestr[i] = j;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000544 SETARG(codestr, i, tgttgt);
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000545 goto reoptimize_current;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000546 } else {
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000547 /* The second jump is not taken
548 if the first is (so jump past
549 it), and all conditional
550 jumps pop their argument when
551 they're not taken (so change
552 the first jump to pop its
553 argument when it's taken). */
554 if (JUMPS_ON_TRUE(opcode))
555 codestr[i] = POP_JUMP_IF_TRUE;
556 else
557 codestr[i] = POP_JUMP_IF_FALSE;
558 SETARG(codestr, i, (tgt + 3));
559 goto reoptimize_current;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000560 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000561 }
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000562 /* Intentional fallthrough */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000563
564 /* Replace jumps to unconditional jumps */
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000565 case POP_JUMP_IF_FALSE:
566 case POP_JUMP_IF_TRUE:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000567 case FOR_ITER:
568 case JUMP_FORWARD:
569 case JUMP_ABSOLUTE:
570 case CONTINUE_LOOP:
571 case SETUP_LOOP:
572 case SETUP_EXCEPT:
573 case SETUP_FINALLY:
Benjamin Peterson876b2f22009-06-28 03:18:59 +0000574 case SETUP_WITH:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000575 tgt = GETJUMPTGT(codestr, i);
Thomas Wouters89f507f2006-12-13 04:49:30 +0000576 /* Replace JUMP_* to a RETURN into just a RETURN */
577 if (UNCONDITIONAL_JUMP(opcode) &&
578 codestr[tgt] == RETURN_VALUE) {
579 codestr[i] = RETURN_VALUE;
580 memset(codestr+i+1, NOP, 2);
581 continue;
582 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000583 if (!UNCONDITIONAL_JUMP(codestr[tgt]))
584 continue;
585 tgttgt = GETJUMPTGT(codestr, tgt);
586 if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */
587 opcode = JUMP_ABSOLUTE;
588 if (!ABSOLUTE_JUMP(opcode))
589 tgttgt -= i + 3; /* Calc relative jump addr */
590 if (tgttgt < 0) /* No backward relative jumps */
591 continue;
592 codestr[i] = opcode;
593 SETARG(codestr, i, tgttgt);
594 break;
595
596 case EXTENDED_ARG:
Guido van Rossum0240b922007-02-26 21:23:50 +0000597 if (codestr[i+3] != MAKE_FUNCTION)
598 goto exitUnchanged;
599 /* don't visit MAKE_FUNCTION as GETARG will be wrong */
600 i += 3;
601 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000602
603 /* Replace RETURN LOAD_CONST None RETURN with just RETURN */
Thomas Wouters89f507f2006-12-13 04:49:30 +0000604 /* Remove unreachable JUMPs after RETURN */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000605 case RETURN_VALUE:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000606 if (i+4 >= codelen)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000607 continue;
Thomas Wouters89f507f2006-12-13 04:49:30 +0000608 if (codestr[i+4] == RETURN_VALUE &&
609 ISBASICBLOCK(blocks,i,5))
610 memset(codestr+i+1, NOP, 4);
611 else if (UNCONDITIONAL_JUMP(codestr[i+1]) &&
612 ISBASICBLOCK(blocks,i,4))
613 memset(codestr+i+1, NOP, 3);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000614 break;
615 }
616 }
617
618 /* Fixup linenotab */
619 for (i=0, nops=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
620 addrmap[i] = i - nops;
621 if (codestr[i] == NOP)
622 nops++;
623 }
624 cum_orig_line = 0;
625 last_line = 0;
626 for (i=0 ; i < tabsiz ; i+=2) {
627 cum_orig_line += lineno[i];
628 new_line = addrmap[cum_orig_line];
629 assert (new_line - last_line < 255);
630 lineno[i] =((unsigned char)(new_line - last_line));
631 last_line = new_line;
632 }
633
634 /* Remove NOPs and fixup jump targets */
635 for (i=0, h=0 ; i<codelen ; ) {
636 opcode = codestr[i];
637 switch (opcode) {
638 case NOP:
639 i++;
640 continue;
641
642 case JUMP_ABSOLUTE:
643 case CONTINUE_LOOP:
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000644 case POP_JUMP_IF_FALSE:
645 case POP_JUMP_IF_TRUE:
646 case JUMP_IF_FALSE_OR_POP:
647 case JUMP_IF_TRUE_OR_POP:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000648 j = addrmap[GETARG(codestr, i)];
649 SETARG(codestr, i, j);
650 break;
651
652 case FOR_ITER:
653 case JUMP_FORWARD:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000654 case SETUP_LOOP:
655 case SETUP_EXCEPT:
656 case SETUP_FINALLY:
Benjamin Peterson876b2f22009-06-28 03:18:59 +0000657 case SETUP_WITH:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000658 j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3;
659 SETARG(codestr, i, j);
660 break;
661 }
662 adj = CODESIZE(opcode);
663 while (adj--)
664 codestr[h++] = codestr[i++];
665 }
666 assert(h + nops == codelen);
667
Christian Heimes72b710a2008-05-26 13:28:38 +0000668 code = PyBytes_FromStringAndSize((char *)codestr, h);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000669 PyMem_Free(addrmap);
670 PyMem_Free(codestr);
671 PyMem_Free(blocks);
672 return code;
673
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000674 exitError:
675 code = NULL;
676
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000677 exitUnchanged:
678 if (blocks != NULL)
679 PyMem_Free(blocks);
680 if (addrmap != NULL)
681 PyMem_Free(addrmap);
682 if (codestr != NULL)
683 PyMem_Free(codestr);
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000684 Py_XINCREF(code);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000685 return code;
686}