blob: fb6cd03c8685a86c5b20b37dfb511f9a6d7f4882 [file] [log] [blame]
Raymond Hettinger20e11992007-03-02 19:20:46 +00001/* Peephole optimizations for bytecode compiler. */
Jeremy Hylton644dddc2006-08-21 16:19:37 +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]))
Antoine Pitrouc83ea132010-05-09 14:46:46 +000015#define UNCONDITIONAL_JUMP(op) (op==JUMP_ABSOLUTE || op==JUMP_FORWARD)
Jeffrey Yasskin68d68522009-02-28 19:03:21 +000016#define CONDITIONAL_JUMP(op) (op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \
Antoine Pitrouc83ea132010-05-09 14:46:46 +000017 || op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP)
Jeffrey Yasskin68d68522009-02-28 19:03:21 +000018#define ABSOLUTE_JUMP(op) (op==JUMP_ABSOLUTE || op==CONTINUE_LOOP \
Antoine Pitrouc83ea132010-05-09 14:46:46 +000019 || op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \
20 || op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP)
Jeffrey Yasskin68d68522009-02-28 19:03:21 +000021#define JUMPS_ON_TRUE(op) (op==POP_JUMP_IF_TRUE || op==JUMP_IF_TRUE_OR_POP)
Jeremy Hylton644dddc2006-08-21 16:19:37 +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) \
Antoine Pitrouc83ea132010-05-09 14:46:46 +000026 (blocks[start]==blocks[start+bytes-1])
Jeremy Hylton644dddc2006-08-21 16:19:37 +000027
28/* Replace LOAD_CONST c1. LOAD_CONST c2 ... LOAD_CONST cn BUILD_TUPLE n
Antoine Pitrouc83ea132010-05-09 14:46:46 +000029 with LOAD_CONST (c1, c2, ... cn).
Jeremy Hylton644dddc2006-08-21 16:19:37 +000030 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.
Antoine Pitrouc83ea132010-05-09 14:46:46 +000033 Bails out with no change if one or more of the LOAD_CONSTs is missing.
Jeremy Hylton644dddc2006-08-21 16:19:37 +000034 Also works for BUILD_LIST when followed by an "in" or "not in" test.
35*/
36static int
Neal Norwitz4677fbf72008-03-25 04:18:18 +000037tuple_of_constants(unsigned char *codestr, Py_ssize_t n, PyObject *consts)
Jeremy Hylton644dddc2006-08-21 16:19:37 +000038{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000039 PyObject *newconst, *constant;
40 Py_ssize_t i, arg, len_consts;
Jeremy Hylton644dddc2006-08-21 16:19:37 +000041
Antoine Pitrouc83ea132010-05-09 14:46:46 +000042 /* 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);
Jeremy Hylton644dddc2006-08-21 16:19:37 +000048
Antoine Pitrouc83ea132010-05-09 14:46:46 +000049 /* 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 }
Jeremy Hylton644dddc2006-08-21 16:19:37 +000061
Antoine Pitrouc83ea132010-05-09 14:46:46 +000062 /* Append folded constant onto consts */
63 if (PyList_Append(consts, newconst)) {
64 Py_DECREF(newconst);
65 return 0;
66 }
67 Py_DECREF(newconst);
Jeremy Hylton644dddc2006-08-21 16:19:37 +000068
Antoine Pitrouc83ea132010-05-09 14:46:46 +000069 /* 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;
Jeremy Hylton644dddc2006-08-21 16:19:37 +000075}
76
77/* Replace LOAD_CONST c1. LOAD_CONST c2 BINOP
Antoine Pitrouc83ea132010-05-09 14:46:46 +000078 with LOAD_CONST binop(c1,c2)
Jeremy Hylton644dddc2006-08-21 16:19:37 +000079 The consts table must still be in list form so that the
80 new constant can be appended.
Antoine Pitrouc83ea132010-05-09 14:46:46 +000081 Called with codestr pointing to the first LOAD_CONST.
82 Abandons the transformation if the folding fails (i.e. 1+'a').
Jeremy Hylton644dddc2006-08-21 16:19:37 +000083 If the new constant is a sequence, only folds when the size
Antoine Pitrouc83ea132010-05-09 14:46:46 +000084 is below a threshold value. That keeps pyc files from
85 becoming large in the presence of code like: (None,)*1000.
Jeremy Hylton644dddc2006-08-21 16:19:37 +000086*/
87static int
88fold_binops_on_constants(unsigned char *codestr, PyObject *consts)
89{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000090 PyObject *newconst, *v, *w;
91 Py_ssize_t len_consts, size;
92 int opcode;
Jeremy Hylton644dddc2006-08-21 16:19:37 +000093
Antoine Pitrouc83ea132010-05-09 14:46:46 +000094 /* Pre-conditions */
95 assert(PyList_CheckExact(consts));
96 assert(codestr[0] == LOAD_CONST);
97 assert(codestr[3] == LOAD_CONST);
Jeremy Hylton644dddc2006-08-21 16:19:37 +000098
Antoine Pitrouc83ea132010-05-09 14:46:46 +000099 /* 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:
Ezio Melottic283a852011-04-15 16:14:04 +0300131 /* #5057: if v is unicode, there might be differences between
Ezio Melottic18cc0e2012-11-05 00:03:21 +0200132 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);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000139 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 }
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000173
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000174 /* 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);
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000181
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000182 /* 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;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000187}
188
189static int
190fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts)
191{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000192 PyObject *newconst=NULL, *v;
193 Py_ssize_t len_consts;
194 int opcode;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000195
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000196 /* Pre-conditions */
197 assert(PyList_CheckExact(consts));
198 assert(codestr[0] == LOAD_CONST);
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000199
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000200 /* 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 }
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000226
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000227 /* 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);
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000234
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000235 /* Write NOP LOAD_CONST newconst */
236 codestr[0] = NOP;
237 codestr[1] = LOAD_CONST;
238 SETARG(codestr, 1, len_consts);
239 return 1;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000240}
241
242static unsigned int *
Neal Norwitz4677fbf72008-03-25 04:18:18 +0000243markblocks(unsigned char *code, Py_ssize_t len)
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000244{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000245 unsigned int *blocks = (unsigned int *)PyMem_Malloc(len*sizeof(int));
246 int i,j, opcode, blockcnt = 0;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000247
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000248 if (blocks == NULL) {
249 PyErr_NoMemory();
250 return NULL;
251 }
252 memset(blocks, 0, len*sizeof(int));
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000253
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000254 /* 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;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000281}
282
283/* Perform basic peephole optimizations to components of a code object.
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000284 The consts object should still be in list form to allow new constants
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000285 to be appended.
286
287 To keep the optimizer simple, it bails out (does nothing) for code
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000288 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
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000290 the lineno table has complex encoding for gaps >= 255.
291
292 Optimizations are restricted to simple transformations occuring within a
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000293 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
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000296 a single pass. Line numbering is adjusted accordingly. */
297
298PyObject *
299PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
300 PyObject *lineno_obj)
301{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000302 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;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000312
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000313 /* Bail out if an exception is set */
314 if (PyErr_Occurred())
315 goto exitError;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000316
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000317 /* 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;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000323
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000324 /* 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;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000329
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000330 /* 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);
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000336
Raymond Hettingerdee8af22012-07-20 17:47:59 -0700337 /* Verify that RETURN_VALUE terminates the codestring. This allows
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000338 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;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000344
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000345 /* Mapping to new jump targets after NOPs are removed */
346 addrmap = (int *)PyMem_Malloc(codelen * sizeof(int));
347 if (addrmap == NULL)
348 goto exitError;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000349
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000350 blocks = markblocks(codestr, codelen);
351 if (blocks == NULL)
352 goto exitError;
353 assert(PyList_Check(consts));
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000354
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000355 for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
356 reoptimize_current:
357 opcode = codestr[i];
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000358
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000359 lastlc = cumlc;
360 cumlc = 0;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000361
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000362 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;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000374
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000375 /* 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;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000389
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000390 /* 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;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000411
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000412 /* 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;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000425
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000426 /* 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;
Raymond Hettingerdee8af22012-07-20 17:47:59 -0700435 if (h >= 0 &&
436 j <= lastlc &&
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000437 ((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;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000464
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000465 /* 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:
Raymond Hettingerdee8af22012-07-20 17:47:59 -0700480 if (lastlc >= 2 &&
481 ISBASICBLOCK(blocks, i-6, 7) &&
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000482 fold_binops_on_constants(&codestr[i-6], consts)) {
483 i -= 2;
484 assert(codestr[i] == LOAD_CONST);
485 cumlc = 1;
486 }
487 break;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000488
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000489 /* Fold unary ops on constants.
Raymond Hettingerdee8af22012-07-20 17:47:59 -0700490 LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000491 case UNARY_NEGATIVE:
492 case UNARY_CONVERT:
493 case UNARY_INVERT:
Raymond Hettingerdee8af22012-07-20 17:47:59 -0700494 if (lastlc >= 1 &&
495 ISBASICBLOCK(blocks, i-3, 4) &&
496 fold_unaryops_on_constants(&codestr[i-3], consts)) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000497 i -= 2;
498 assert(codestr[i] == LOAD_CONST);
499 cumlc = 1;
500 }
501 break;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000502
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000503 /* 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)) {
Raymond Hettingerdee8af22012-07-20 17:47:59 -0700522 /* NOTE: all possible jumps here are absolute! */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000523 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 {
Raymond Hettingerdee8af22012-07-20 17:47:59 -0700533 /* 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). */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000537 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 */
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000546
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000547 /* 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))
Raymond Hettingerdee8af22012-07-20 17:47:59 -0700572 tgttgt -= i + 3; /* Calc relative jump addr */
573 if (tgttgt < 0) /* No backward relative jumps */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000574 continue;
575 codestr[i] = opcode;
576 SETARG(codestr, i, tgttgt);
577 break;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000578
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000579 case EXTENDED_ARG:
580 goto exitUnchanged;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000581
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000582 /* 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 }
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000596
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000597 /* 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 }
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000612
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000613 /* 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;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000620
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000621 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;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000630
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000631 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);
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000646
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000647 code = PyString_FromStringAndSize((char *)codestr, h);
648 PyMem_Free(addrmap);
649 PyMem_Free(codestr);
650 PyMem_Free(blocks);
651 return code;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000652
Georg Brandle323e0e2009-06-29 14:44:49 +0000653 exitError:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000654 code = NULL;
Georg Brandle323e0e2009-06-29 14:44:49 +0000655
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000656 exitUnchanged:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000657 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;
Jeremy Hylton644dddc2006-08-21 16:19:37 +0000665}