blob: 23735b0a31a7d17d83dd23f874e7751091abf64f [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;
200 default:
201 /* Called with an unknown opcode */
202 PyErr_Format(PyExc_SystemError,
203 "unexpected unary operation %d on a constant",
204 opcode);
205 return 0;
206 }
207 if (newconst == NULL) {
208 PyErr_Clear();
209 return 0;
210 }
211
212 /* Append folded constant into consts table */
213 len_consts = PyList_GET_SIZE(consts);
214 if (PyList_Append(consts, newconst)) {
215 Py_DECREF(newconst);
216 return 0;
217 }
218 Py_DECREF(newconst);
219
220 /* Write NOP LOAD_CONST newconst */
221 codestr[0] = NOP;
222 codestr[1] = LOAD_CONST;
223 SETARG(codestr, 1, len_consts);
224 return 1;
225}
226
227static unsigned int *
Christian Heimescc47b052008-03-25 14:56:36 +0000228markblocks(unsigned char *code, Py_ssize_t len)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000229{
230 unsigned int *blocks = (unsigned int *)PyMem_Malloc(len*sizeof(int));
231 int i,j, opcode, blockcnt = 0;
232
233 if (blocks == NULL) {
234 PyErr_NoMemory();
235 return NULL;
236 }
237 memset(blocks, 0, len*sizeof(int));
238
239 /* Mark labels in the first pass */
240 for (i=0 ; i<len ; i+=CODESIZE(opcode)) {
241 opcode = code[i];
242 switch (opcode) {
243 case FOR_ITER:
244 case JUMP_FORWARD:
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000245 case JUMP_IF_FALSE_OR_POP:
246 case JUMP_IF_TRUE_OR_POP:
247 case POP_JUMP_IF_FALSE:
248 case POP_JUMP_IF_TRUE:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000249 case JUMP_ABSOLUTE:
250 case CONTINUE_LOOP:
251 case SETUP_LOOP:
252 case SETUP_EXCEPT:
253 case SETUP_FINALLY:
Benjamin Peterson876b2f22009-06-28 03:18:59 +0000254 case SETUP_WITH:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000255 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;
266}
267
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000268/* Helper to replace LOAD_NAME None/True/False with LOAD_CONST
269 Returns: 0 if no change, 1 if change, -1 if error */
270static int
271load_global(unsigned char *codestr, Py_ssize_t i, char *name, PyObject *consts)
272{
273 Py_ssize_t j;
274 PyObject *obj;
275 if (name == NULL)
276 return 0;
277 if (strcmp(name, "None") == 0)
278 obj = Py_None;
279 else if (strcmp(name, "True") == 0)
280 obj = Py_True;
281 else if (strcmp(name, "False") == 0)
282 obj = Py_False;
283 else
284 return 0;
285 for (j = 0; j < PyList_GET_SIZE(consts); j++) {
286 if (PyList_GET_ITEM(consts, j) == obj)
287 break;
288 }
289 if (j == PyList_GET_SIZE(consts)) {
290 if (PyList_Append(consts, obj) < 0)
291 return -1;
292 }
293 assert(PyList_GET_ITEM(consts, j) == obj);
294 codestr[i] = LOAD_CONST;
295 SETARG(codestr, i, j);
296 return 1;
297}
298
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000299/* Perform basic peephole optimizations to components of a code object.
300 The consts object should still be in list form to allow new constants
301 to be appended.
302
Guido van Rossum0240b922007-02-26 21:23:50 +0000303 To keep the optimizer simple, it bails out (does nothing) for code that
304 has a length over 32,700, and does not calculate extended arguments.
305 That allows us to avoid overflow and sign issues. Likewise, it bails when
306 the lineno table has complex encoding for gaps >= 255. EXTENDED_ARG can
307 appear before MAKE_FUNCTION; in this case both opcodes are skipped.
308 EXTENDED_ARG preceding any other opcode causes the optimizer to bail.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000309
310 Optimizations are restricted to simple transformations occuring within a
311 single basic block. All transformations keep the code size the same or
312 smaller. For those that reduce size, the gaps are initially filled with
313 NOPs. Later those NOPs are removed and the jump addresses retargeted in
314 a single pass. Line numbering is adjusted accordingly. */
315
316PyObject *
317PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
318 PyObject *lineno_obj)
319{
320 Py_ssize_t i, j, codelen;
321 int nops, h, adj;
322 int tgt, tgttgt, opcode;
323 unsigned char *codestr = NULL;
324 unsigned char *lineno;
325 int *addrmap = NULL;
326 int new_line, cum_orig_line, last_line, tabsiz;
327 int cumlc=0, lastlc=0; /* Count runs of consecutive LOAD_CONSTs */
328 unsigned int *blocks = NULL;
329 char *name;
330
331 /* Bail out if an exception is set */
332 if (PyErr_Occurred())
333 goto exitUnchanged;
334
335 /* Bypass optimization when the lineno table is too complex */
Christian Heimes72b710a2008-05-26 13:28:38 +0000336 assert(PyBytes_Check(lineno_obj));
337 lineno = (unsigned char*)PyBytes_AS_STRING(lineno_obj);
338 tabsiz = PyBytes_GET_SIZE(lineno_obj);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000339 if (memchr(lineno, 255, tabsiz) != NULL)
340 goto exitUnchanged;
341
342 /* Avoid situations where jump retargeting could overflow */
Christian Heimes72b710a2008-05-26 13:28:38 +0000343 assert(PyBytes_Check(code));
344 codelen = PyBytes_GET_SIZE(code);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000345 if (codelen > 32700)
346 goto exitUnchanged;
347
348 /* Make a modifiable copy of the code string */
349 codestr = (unsigned char *)PyMem_Malloc(codelen);
350 if (codestr == NULL)
351 goto exitUnchanged;
352 codestr = (unsigned char *)memcpy(codestr,
Christian Heimes72b710a2008-05-26 13:28:38 +0000353 PyBytes_AS_STRING(code), codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000354
355 /* Verify that RETURN_VALUE terminates the codestring. This allows
356 the various transformation patterns to look ahead several
357 instructions without additional checks to make sure they are not
358 looking beyond the end of the code string.
359 */
360 if (codestr[codelen-1] != RETURN_VALUE)
361 goto exitUnchanged;
362
363 /* Mapping to new jump targets after NOPs are removed */
364 addrmap = (int *)PyMem_Malloc(codelen * sizeof(int));
365 if (addrmap == NULL)
366 goto exitUnchanged;
367
368 blocks = markblocks(codestr, codelen);
369 if (blocks == NULL)
370 goto exitUnchanged;
371 assert(PyList_Check(consts));
372
373 for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000374 reoptimize_current:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000375 opcode = codestr[i];
376
377 lastlc = cumlc;
378 cumlc = 0;
379
380 switch (opcode) {
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000381 /* Replace UNARY_NOT POP_JUMP_IF_FALSE
382 with POP_JUMP_IF_TRUE */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000383 case UNARY_NOT:
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000384 if (codestr[i+1] != POP_JUMP_IF_FALSE
385 || !ISBASICBLOCK(blocks,i,4))
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000386 continue;
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000387 j = GETARG(codestr, i+1);
388 codestr[i] = POP_JUMP_IF_TRUE;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000389 SETARG(codestr, i, j);
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000390 codestr[i+3] = NOP;
391 goto reoptimize_current;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000392
393 /* not a is b --> a is not b
394 not a in b --> a not in b
395 not a is not b --> a is b
396 not a not in b --> a in b
397 */
398 case COMPARE_OP:
399 j = GETARG(codestr, i);
400 if (j < 6 || j > 9 ||
401 codestr[i+3] != UNARY_NOT ||
402 !ISBASICBLOCK(blocks,i,4))
403 continue;
404 SETARG(codestr, i, (j^1));
405 codestr[i+3] = NOP;
406 break;
407
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000408 /* Replace LOAD_GLOBAL/LOAD_NAME None/True/False
409 with LOAD_CONST None/True/False */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000410 case LOAD_NAME:
411 case LOAD_GLOBAL:
412 j = GETARG(codestr, i);
Marc-André Lemburg4cc0f242008-08-07 18:54:33 +0000413 name = _PyUnicode_AsString(PyTuple_GET_ITEM(names, j));
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000414 h = load_global(codestr, i, name, consts);
415 if (h < 0)
416 goto exitUnchanged;
417 else if (h == 0)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000418 continue;
Guido van Rossumd8faa362007-04-27 19:54:29 +0000419 cumlc = lastlc + 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000420 break;
421
422 /* Skip over LOAD_CONST trueconst
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000423 POP_JUMP_IF_FALSE xx. This improves
424 "while 1" performance. */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000425 case LOAD_CONST:
426 cumlc = lastlc + 1;
427 j = GETARG(codestr, i);
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000428 if (codestr[i+3] != POP_JUMP_IF_FALSE ||
Jeffrey Yasskin4dd40522009-02-28 19:49:43 +0000429 !ISBASICBLOCK(blocks,i,6) ||
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000430 !PyObject_IsTrue(PyList_GET_ITEM(consts, j)))
431 continue;
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000432 memset(codestr+i, NOP, 6);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000433 cumlc = 0;
434 break;
435
436 /* Try to fold tuples of constants (includes a case for lists
437 which are only used for "in" and "not in" tests).
438 Skip over BUILD_SEQN 1 UNPACK_SEQN 1.
439 Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2.
440 Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */
441 case BUILD_TUPLE:
442 case BUILD_LIST:
443 j = GETARG(codestr, i);
444 h = i - 3 * j;
445 if (h >= 0 &&
446 j <= lastlc &&
447 ((opcode == BUILD_TUPLE &&
448 ISBASICBLOCK(blocks, h, 3*(j+1))) ||
449 (opcode == BUILD_LIST &&
450 codestr[i+3]==COMPARE_OP &&
451 ISBASICBLOCK(blocks, h, 3*(j+2)) &&
452 (GETARG(codestr,i+3)==6 ||
453 GETARG(codestr,i+3)==7))) &&
454 tuple_of_constants(&codestr[h], j, consts)) {
455 assert(codestr[i] == LOAD_CONST);
456 cumlc = 1;
457 break;
458 }
459 if (codestr[i+3] != UNPACK_SEQUENCE ||
460 !ISBASICBLOCK(blocks,i,6) ||
461 j != GETARG(codestr, i+3))
462 continue;
463 if (j == 1) {
464 memset(codestr+i, NOP, 6);
465 } else if (j == 2) {
466 codestr[i] = ROT_TWO;
467 memset(codestr+i+1, NOP, 5);
468 } else if (j == 3) {
469 codestr[i] = ROT_THREE;
470 codestr[i+1] = ROT_TWO;
471 memset(codestr+i+2, NOP, 4);
472 }
473 break;
474
475 /* Fold binary ops on constants.
476 LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */
477 case BINARY_POWER:
478 case BINARY_MULTIPLY:
479 case BINARY_TRUE_DIVIDE:
480 case BINARY_FLOOR_DIVIDE:
481 case BINARY_MODULO:
482 case BINARY_ADD:
483 case BINARY_SUBTRACT:
484 case BINARY_SUBSCR:
485 case BINARY_LSHIFT:
486 case BINARY_RSHIFT:
487 case BINARY_AND:
488 case BINARY_XOR:
489 case BINARY_OR:
490 if (lastlc >= 2 &&
491 ISBASICBLOCK(blocks, i-6, 7) &&
492 fold_binops_on_constants(&codestr[i-6], consts)) {
493 i -= 2;
494 assert(codestr[i] == LOAD_CONST);
495 cumlc = 1;
496 }
497 break;
498
499 /* Fold unary ops on constants.
500 LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */
501 case UNARY_NEGATIVE:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000502 case UNARY_INVERT:
503 if (lastlc >= 1 &&
504 ISBASICBLOCK(blocks, i-3, 4) &&
505 fold_unaryops_on_constants(&codestr[i-3], consts)) {
506 i -= 2;
507 assert(codestr[i] == LOAD_CONST);
508 cumlc = 1;
509 }
510 break;
511
512 /* Simplify conditional jump to conditional jump where the
513 result of the first test implies the success of a similar
514 test or the failure of the opposite test.
515 Arises in code like:
516 "if a and b:"
517 "if a or b:"
518 "a and b or c"
519 "(a and b) and c"
Jeffrey Yasskin4dd40522009-02-28 19:49:43 +0000520 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z
521 --> x:JUMP_IF_FALSE_OR_POP z
522 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z
523 --> x:POP_JUMP_IF_FALSE y+3
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000524 where y+3 is the instruction following the second test.
525 */
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000526 case JUMP_IF_FALSE_OR_POP:
527 case JUMP_IF_TRUE_OR_POP:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000528 tgt = GETJUMPTGT(codestr, i);
529 j = codestr[tgt];
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000530 if (CONDITIONAL_JUMP(j)) {
531 /* NOTE: all possible jumps here are
532 absolute! */
533 if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) {
534 /* The second jump will be
535 taken iff the first is. */
536 tgttgt = GETJUMPTGT(codestr, tgt);
537 /* The current opcode inherits
538 its target's stack behaviour */
539 codestr[i] = j;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000540 SETARG(codestr, i, tgttgt);
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000541 goto reoptimize_current;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000542 } else {
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000543 /* The second jump is not taken
544 if the first is (so jump past
545 it), and all conditional
546 jumps pop their argument when
547 they're not taken (so change
548 the first jump to pop its
549 argument when it's taken). */
550 if (JUMPS_ON_TRUE(opcode))
551 codestr[i] = POP_JUMP_IF_TRUE;
552 else
553 codestr[i] = POP_JUMP_IF_FALSE;
554 SETARG(codestr, i, (tgt + 3));
555 goto reoptimize_current;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000556 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000557 }
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000558 /* Intentional fallthrough */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000559
560 /* Replace jumps to unconditional jumps */
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000561 case POP_JUMP_IF_FALSE:
562 case POP_JUMP_IF_TRUE:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000563 case FOR_ITER:
564 case JUMP_FORWARD:
565 case JUMP_ABSOLUTE:
566 case CONTINUE_LOOP:
567 case SETUP_LOOP:
568 case SETUP_EXCEPT:
569 case SETUP_FINALLY:
Benjamin Peterson876b2f22009-06-28 03:18:59 +0000570 case SETUP_WITH:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000571 tgt = GETJUMPTGT(codestr, i);
Thomas Wouters89f507f2006-12-13 04:49:30 +0000572 /* Replace JUMP_* to a RETURN into just a RETURN */
573 if (UNCONDITIONAL_JUMP(opcode) &&
574 codestr[tgt] == RETURN_VALUE) {
575 codestr[i] = RETURN_VALUE;
576 memset(codestr+i+1, NOP, 2);
577 continue;
578 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000579 if (!UNCONDITIONAL_JUMP(codestr[tgt]))
580 continue;
581 tgttgt = GETJUMPTGT(codestr, tgt);
582 if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */
583 opcode = JUMP_ABSOLUTE;
584 if (!ABSOLUTE_JUMP(opcode))
585 tgttgt -= i + 3; /* Calc relative jump addr */
586 if (tgttgt < 0) /* No backward relative jumps */
587 continue;
588 codestr[i] = opcode;
589 SETARG(codestr, i, tgttgt);
590 break;
591
592 case EXTENDED_ARG:
Guido van Rossum0240b922007-02-26 21:23:50 +0000593 if (codestr[i+3] != MAKE_FUNCTION)
594 goto exitUnchanged;
595 /* don't visit MAKE_FUNCTION as GETARG will be wrong */
596 i += 3;
597 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000598
599 /* Replace RETURN LOAD_CONST None RETURN with just RETURN */
Thomas Wouters89f507f2006-12-13 04:49:30 +0000600 /* Remove unreachable JUMPs after RETURN */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000601 case RETURN_VALUE:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000602 if (i+4 >= codelen)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000603 continue;
Thomas Wouters89f507f2006-12-13 04:49:30 +0000604 if (codestr[i+4] == RETURN_VALUE &&
605 ISBASICBLOCK(blocks,i,5))
606 memset(codestr+i+1, NOP, 4);
607 else if (UNCONDITIONAL_JUMP(codestr[i+1]) &&
608 ISBASICBLOCK(blocks,i,4))
609 memset(codestr+i+1, NOP, 3);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000610 break;
611 }
612 }
613
614 /* Fixup linenotab */
615 for (i=0, nops=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
616 addrmap[i] = i - nops;
617 if (codestr[i] == NOP)
618 nops++;
619 }
620 cum_orig_line = 0;
621 last_line = 0;
622 for (i=0 ; i < tabsiz ; i+=2) {
623 cum_orig_line += lineno[i];
624 new_line = addrmap[cum_orig_line];
625 assert (new_line - last_line < 255);
626 lineno[i] =((unsigned char)(new_line - last_line));
627 last_line = new_line;
628 }
629
630 /* Remove NOPs and fixup jump targets */
631 for (i=0, h=0 ; i<codelen ; ) {
632 opcode = codestr[i];
633 switch (opcode) {
634 case NOP:
635 i++;
636 continue;
637
638 case JUMP_ABSOLUTE:
639 case CONTINUE_LOOP:
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +0000640 case POP_JUMP_IF_FALSE:
641 case POP_JUMP_IF_TRUE:
642 case JUMP_IF_FALSE_OR_POP:
643 case JUMP_IF_TRUE_OR_POP:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000644 j = addrmap[GETARG(codestr, i)];
645 SETARG(codestr, i, j);
646 break;
647
648 case FOR_ITER:
649 case JUMP_FORWARD:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000650 case SETUP_LOOP:
651 case SETUP_EXCEPT:
652 case SETUP_FINALLY:
Benjamin Peterson876b2f22009-06-28 03:18:59 +0000653 case SETUP_WITH:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000654 j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3;
655 SETARG(codestr, i, j);
656 break;
657 }
658 adj = CODESIZE(opcode);
659 while (adj--)
660 codestr[h++] = codestr[i++];
661 }
662 assert(h + nops == codelen);
663
Christian Heimes72b710a2008-05-26 13:28:38 +0000664 code = PyBytes_FromStringAndSize((char *)codestr, h);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000665 PyMem_Free(addrmap);
666 PyMem_Free(codestr);
667 PyMem_Free(blocks);
668 return code;
669
670 exitUnchanged:
671 if (blocks != NULL)
672 PyMem_Free(blocks);
673 if (addrmap != NULL)
674 PyMem_Free(addrmap);
675 if (codestr != NULL)
676 PyMem_Free(codestr);
677 Py_INCREF(code);
678 return code;
679}