blob: c27878c1c7351eb2626706c4ecc53b32b940ed5c [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]))
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +000015#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 \
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +000017 || op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP)
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +000018#define ABSOLUTE_JUMP(op) (op==JUMP_ABSOLUTE || op==CONTINUE_LOOP \
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +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 Yasskin9de7ec72009-02-25 02:25:04 +000021#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) \
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +000026 (blocks[start]==blocks[start+bytes-1])
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000027
28/* Replace LOAD_CONST c1. LOAD_CONST c2 ... LOAD_CONST cn BUILD_TUPLE n
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +000029 with LOAD_CONST (c1, c2, ... cn).
Thomas Wouters00ee7ba2006-08-21 19:07:27 +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 Pitrou7f14f0d2010-05-09 16:14:21 +000033 Bails out with no change if one or more of the LOAD_CONSTs is missing.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000034 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{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +000039 PyObject *newconst, *constant;
40 Py_ssize_t i, arg, len_consts;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000041
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +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);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000048
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +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 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000061
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +000062 /* Append folded constant onto consts */
63 if (PyList_Append(consts, newconst)) {
64 Py_DECREF(newconst);
65 return 0;
66 }
67 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000068
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +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;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000075}
76
77/* Replace LOAD_CONST c1. LOAD_CONST c2 BINOP
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +000078 with LOAD_CONST binop(c1,c2)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000079 The consts table must still be in list form so that the
80 new constant can be appended.
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +000081 Called with codestr pointing to the first LOAD_CONST.
82 Abandons the transformation if the folding fails (i.e. 1+'a').
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000083 If the new constant is a sequence, only folds when the size
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +000084 is below a threshold value. That keeps pyc files from
85 becoming large in the presence of code like: (None,)*1000.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000086*/
87static int
88fold_binops_on_constants(unsigned char *codestr, PyObject *consts)
89{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +000090 PyObject *newconst, *v, *w;
91 Py_ssize_t len_consts, size;
92 int opcode;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000093
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +000094 /* Pre-conditions */
95 assert(PyList_CheckExact(consts));
96 assert(codestr[0] == LOAD_CONST);
97 assert(codestr[3] == LOAD_CONST);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000098
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +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_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);
Ezio Melotti2df6a932011-04-15 16:38:34 +0300127 /* #5057: if v is unicode, there might be differences between
128 wide and narrow builds in cases like '\U00012345'[0].
129 Wide builds will return a non-BMP char, whereas narrow builds
130 will return a surrogate. In both the cases skip the
131 optimization in order to produce compatible pycs.
132 */
133 if (newconst != NULL &&
134 PyUnicode_Check(v) && PyUnicode_Check(newconst)) {
135 Py_UNICODE ch = PyUnicode_AS_UNICODE(newconst)[0];
136#ifdef Py_UNICODE_WIDE
137 if (ch > 0xFFFF) {
138#else
139 if (ch >= 0xD800 && ch <= 0xDFFF) {
140#endif
141 Py_DECREF(newconst);
142 return 0;
143 }
144 }
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000145 break;
146 case BINARY_LSHIFT:
147 newconst = PyNumber_Lshift(v, w);
148 break;
149 case BINARY_RSHIFT:
150 newconst = PyNumber_Rshift(v, w);
151 break;
152 case BINARY_AND:
153 newconst = PyNumber_And(v, w);
154 break;
155 case BINARY_XOR:
156 newconst = PyNumber_Xor(v, w);
157 break;
158 case BINARY_OR:
159 newconst = PyNumber_Or(v, w);
160 break;
161 default:
162 /* Called with an unknown opcode */
163 PyErr_Format(PyExc_SystemError,
164 "unexpected binary operation %d on a constant",
165 opcode);
166 return 0;
167 }
168 if (newconst == NULL) {
169 PyErr_Clear();
170 return 0;
171 }
172 size = PyObject_Size(newconst);
173 if (size == -1)
174 PyErr_Clear();
175 else if (size > 20) {
176 Py_DECREF(newconst);
177 return 0;
178 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000179
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000180 /* Append folded constant into consts table */
181 len_consts = PyList_GET_SIZE(consts);
182 if (PyList_Append(consts, newconst)) {
183 Py_DECREF(newconst);
184 return 0;
185 }
186 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000187
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000188 /* Write NOP NOP NOP NOP LOAD_CONST newconst */
189 memset(codestr, NOP, 4);
190 codestr[4] = LOAD_CONST;
191 SETARG(codestr, 4, len_consts);
192 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000193}
194
195static int
196fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts)
197{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000198 PyObject *newconst=NULL, *v;
199 Py_ssize_t len_consts;
200 int opcode;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000201
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000202 /* Pre-conditions */
203 assert(PyList_CheckExact(consts));
204 assert(codestr[0] == LOAD_CONST);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000205
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000206 /* Create new constant */
207 v = PyList_GET_ITEM(consts, GETARG(codestr, 0));
208 opcode = codestr[3];
209 switch (opcode) {
210 case UNARY_NEGATIVE:
211 /* Preserve the sign of -0.0 */
212 if (PyObject_IsTrue(v) == 1)
213 newconst = PyNumber_Negative(v);
214 break;
215 case UNARY_INVERT:
216 newconst = PyNumber_Invert(v);
217 break;
218 default:
219 /* Called with an unknown opcode */
220 PyErr_Format(PyExc_SystemError,
221 "unexpected unary operation %d on a constant",
222 opcode);
223 return 0;
224 }
225 if (newconst == NULL) {
226 PyErr_Clear();
227 return 0;
228 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000229
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000230 /* Append folded constant into consts table */
231 len_consts = PyList_GET_SIZE(consts);
232 if (PyList_Append(consts, newconst)) {
233 Py_DECREF(newconst);
234 return 0;
235 }
236 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000237
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000238 /* Write NOP LOAD_CONST newconst */
239 codestr[0] = NOP;
240 codestr[1] = LOAD_CONST;
241 SETARG(codestr, 1, len_consts);
242 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000243}
244
245static unsigned int *
Christian Heimescc47b052008-03-25 14:56:36 +0000246markblocks(unsigned char *code, Py_ssize_t len)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000247{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000248 unsigned int *blocks = (unsigned int *)PyMem_Malloc(len*sizeof(int));
249 int i,j, opcode, blockcnt = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000250
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000251 if (blocks == NULL) {
252 PyErr_NoMemory();
253 return NULL;
254 }
255 memset(blocks, 0, len*sizeof(int));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000256
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000257 /* Mark labels in the first pass */
258 for (i=0 ; i<len ; i+=CODESIZE(opcode)) {
259 opcode = code[i];
260 switch (opcode) {
261 case FOR_ITER:
262 case JUMP_FORWARD:
263 case JUMP_IF_FALSE_OR_POP:
264 case JUMP_IF_TRUE_OR_POP:
265 case POP_JUMP_IF_FALSE:
266 case POP_JUMP_IF_TRUE:
267 case JUMP_ABSOLUTE:
268 case CONTINUE_LOOP:
269 case SETUP_LOOP:
270 case SETUP_EXCEPT:
271 case SETUP_FINALLY:
272 j = GETJUMPTGT(code, i);
273 blocks[j] = 1;
274 break;
275 }
276 }
277 /* Build block numbers in the second pass */
278 for (i=0 ; i<len ; i++) {
279 blockcnt += blocks[i]; /* increment blockcnt over labels */
280 blocks[i] = blockcnt;
281 }
282 return blocks;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000283}
284
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000285/* Helper to replace LOAD_NAME None/True/False with LOAD_CONST
286 Returns: 0 if no change, 1 if change, -1 if error */
287static int
288load_global(unsigned char *codestr, Py_ssize_t i, char *name, PyObject *consts)
289{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000290 Py_ssize_t j;
291 PyObject *obj;
292 if (name == NULL)
293 return 0;
294 if (strcmp(name, "None") == 0)
295 obj = Py_None;
296 else if (strcmp(name, "True") == 0)
297 obj = Py_True;
298 else if (strcmp(name, "False") == 0)
299 obj = Py_False;
300 else
301 return 0;
302 for (j = 0; j < PyList_GET_SIZE(consts); j++) {
303 if (PyList_GET_ITEM(consts, j) == obj)
304 break;
305 }
306 if (j == PyList_GET_SIZE(consts)) {
307 if (PyList_Append(consts, obj) < 0)
308 return -1;
309 }
310 assert(PyList_GET_ITEM(consts, j) == obj);
311 codestr[i] = LOAD_CONST;
312 SETARG(codestr, i, j);
313 return 1;
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000314}
315
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000316/* Perform basic peephole optimizations to components of a code object.
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000317 The consts object should still be in list form to allow new constants
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000318 to be appended.
319
Guido van Rossum0240b922007-02-26 21:23:50 +0000320 To keep the optimizer simple, it bails out (does nothing) for code that
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000321 has a length over 32,700, and does not calculate extended arguments.
Guido van Rossum0240b922007-02-26 21:23:50 +0000322 That allows us to avoid overflow and sign issues. Likewise, it bails when
323 the lineno table has complex encoding for gaps >= 255. EXTENDED_ARG can
324 appear before MAKE_FUNCTION; in this case both opcodes are skipped.
325 EXTENDED_ARG preceding any other opcode causes the optimizer to bail.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000326
327 Optimizations are restricted to simple transformations occuring within a
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000328 single basic block. All transformations keep the code size the same or
329 smaller. For those that reduce size, the gaps are initially filled with
330 NOPs. Later those NOPs are removed and the jump addresses retargeted in
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000331 a single pass. Line numbering is adjusted accordingly. */
332
333PyObject *
334PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
335 PyObject *lineno_obj)
336{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000337 Py_ssize_t i, j, codelen;
338 int nops, h, adj;
339 int tgt, tgttgt, opcode;
340 unsigned char *codestr = NULL;
341 unsigned char *lineno;
342 int *addrmap = NULL;
343 int new_line, cum_orig_line, last_line, tabsiz;
344 int cumlc=0, lastlc=0; /* Count runs of consecutive LOAD_CONSTs */
345 unsigned int *blocks = NULL;
346 char *name;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000347
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000348 /* Bail out if an exception is set */
349 if (PyErr_Occurred())
350 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000351
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000352 /* Bypass optimization when the lineno table is too complex */
353 assert(PyBytes_Check(lineno_obj));
354 lineno = (unsigned char*)PyBytes_AS_STRING(lineno_obj);
355 tabsiz = PyBytes_GET_SIZE(lineno_obj);
356 if (memchr(lineno, 255, tabsiz) != NULL)
357 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000358
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000359 /* Avoid situations where jump retargeting could overflow */
360 assert(PyBytes_Check(code));
361 codelen = PyBytes_GET_SIZE(code);
362 if (codelen > 32700)
363 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000364
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000365 /* Make a modifiable copy of the code string */
366 codestr = (unsigned char *)PyMem_Malloc(codelen);
367 if (codestr == NULL)
368 goto exitError;
369 codestr = (unsigned char *)memcpy(codestr,
370 PyBytes_AS_STRING(code), codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000371
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000372 /* Verify that RETURN_VALUE terminates the codestring. This allows
373 the various transformation patterns to look ahead several
374 instructions without additional checks to make sure they are not
375 looking beyond the end of the code string.
376 */
377 if (codestr[codelen-1] != RETURN_VALUE)
378 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000379
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000380 /* Mapping to new jump targets after NOPs are removed */
381 addrmap = (int *)PyMem_Malloc(codelen * sizeof(int));
382 if (addrmap == NULL)
383 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000384
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000385 blocks = markblocks(codestr, codelen);
386 if (blocks == NULL)
387 goto exitError;
388 assert(PyList_Check(consts));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000389
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000390 for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
391 reoptimize_current:
392 opcode = codestr[i];
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000393
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000394 lastlc = cumlc;
395 cumlc = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000396
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000397 switch (opcode) {
398 /* Replace UNARY_NOT POP_JUMP_IF_FALSE
399 with POP_JUMP_IF_TRUE */
400 case UNARY_NOT:
401 if (codestr[i+1] != POP_JUMP_IF_FALSE
402 || !ISBASICBLOCK(blocks,i,4))
403 continue;
404 j = GETARG(codestr, i+1);
405 codestr[i] = POP_JUMP_IF_TRUE;
406 SETARG(codestr, i, j);
407 codestr[i+3] = NOP;
408 goto reoptimize_current;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000409
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000410 /* not a is b --> a is not b
411 not a in b --> a not in b
412 not a is not b --> a is b
413 not a not in b --> a in b
414 */
415 case COMPARE_OP:
416 j = GETARG(codestr, i);
417 if (j < 6 || j > 9 ||
418 codestr[i+3] != UNARY_NOT ||
419 !ISBASICBLOCK(blocks,i,4))
420 continue;
421 SETARG(codestr, i, (j^1));
422 codestr[i+3] = NOP;
423 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000424
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000425 /* Replace LOAD_GLOBAL/LOAD_NAME None/True/False
426 with LOAD_CONST None/True/False */
427 case LOAD_NAME:
428 case LOAD_GLOBAL:
429 j = GETARG(codestr, i);
430 name = _PyUnicode_AsString(PyTuple_GET_ITEM(names, j));
431 h = load_global(codestr, i, name, consts);
432 if (h < 0)
433 goto exitError;
434 else if (h == 0)
435 continue;
436 cumlc = lastlc + 1;
437 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000438
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000439 /* Skip over LOAD_CONST trueconst
440 POP_JUMP_IF_FALSE xx. This improves
441 "while 1" performance. */
442 case LOAD_CONST:
443 cumlc = lastlc + 1;
444 j = GETARG(codestr, i);
445 if (codestr[i+3] != POP_JUMP_IF_FALSE ||
446 !ISBASICBLOCK(blocks,i,6) ||
447 !PyObject_IsTrue(PyList_GET_ITEM(consts, j)))
448 continue;
449 memset(codestr+i, NOP, 6);
450 cumlc = 0;
451 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000452
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000453 /* Try to fold tuples of constants (includes a case for lists
454 which are only used for "in" and "not in" tests).
455 Skip over BUILD_SEQN 1 UNPACK_SEQN 1.
456 Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2.
457 Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */
458 case BUILD_TUPLE:
459 case BUILD_LIST:
460 j = GETARG(codestr, i);
461 h = i - 3 * j;
462 if (h >= 0 &&
463 j <= lastlc &&
464 ((opcode == BUILD_TUPLE &&
465 ISBASICBLOCK(blocks, h, 3*(j+1))) ||
466 (opcode == BUILD_LIST &&
467 codestr[i+3]==COMPARE_OP &&
468 ISBASICBLOCK(blocks, h, 3*(j+2)) &&
469 (GETARG(codestr,i+3)==6 ||
470 GETARG(codestr,i+3)==7))) &&
471 tuple_of_constants(&codestr[h], j, consts)) {
472 assert(codestr[i] == LOAD_CONST);
473 cumlc = 1;
474 break;
475 }
476 if (codestr[i+3] != UNPACK_SEQUENCE ||
477 !ISBASICBLOCK(blocks,i,6) ||
478 j != GETARG(codestr, i+3))
479 continue;
480 if (j == 1) {
481 memset(codestr+i, NOP, 6);
482 } else if (j == 2) {
483 codestr[i] = ROT_TWO;
484 memset(codestr+i+1, NOP, 5);
485 } else if (j == 3) {
486 codestr[i] = ROT_THREE;
487 codestr[i+1] = ROT_TWO;
488 memset(codestr+i+2, NOP, 4);
489 }
490 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000491
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000492 /* Fold binary ops on constants.
493 LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */
494 case BINARY_POWER:
495 case BINARY_MULTIPLY:
496 case BINARY_TRUE_DIVIDE:
497 case BINARY_FLOOR_DIVIDE:
498 case BINARY_MODULO:
499 case BINARY_ADD:
500 case BINARY_SUBTRACT:
501 case BINARY_SUBSCR:
502 case BINARY_LSHIFT:
503 case BINARY_RSHIFT:
504 case BINARY_AND:
505 case BINARY_XOR:
506 case BINARY_OR:
507 if (lastlc >= 2 &&
508 ISBASICBLOCK(blocks, i-6, 7) &&
509 fold_binops_on_constants(&codestr[i-6], consts)) {
510 i -= 2;
511 assert(codestr[i] == LOAD_CONST);
512 cumlc = 1;
513 }
514 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000515
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000516 /* Fold unary ops on constants.
517 LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */
518 case UNARY_NEGATIVE:
519 case UNARY_INVERT:
520 if (lastlc >= 1 &&
521 ISBASICBLOCK(blocks, i-3, 4) &&
522 fold_unaryops_on_constants(&codestr[i-3], consts)) {
523 i -= 2;
524 assert(codestr[i] == LOAD_CONST);
525 cumlc = 1;
526 }
527 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000528
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000529 /* Simplify conditional jump to conditional jump where the
530 result of the first test implies the success of a similar
531 test or the failure of the opposite test.
532 Arises in code like:
533 "if a and b:"
534 "if a or b:"
535 "a and b or c"
536 "(a and b) and c"
537 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z
538 --> x:JUMP_IF_FALSE_OR_POP z
539 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z
540 --> x:POP_JUMP_IF_FALSE y+3
541 where y+3 is the instruction following the second test.
542 */
543 case JUMP_IF_FALSE_OR_POP:
544 case JUMP_IF_TRUE_OR_POP:
545 tgt = GETJUMPTGT(codestr, i);
546 j = codestr[tgt];
547 if (CONDITIONAL_JUMP(j)) {
548 /* NOTE: all possible jumps here are
549 absolute! */
550 if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) {
551 /* The second jump will be
552 taken iff the first is. */
553 tgttgt = GETJUMPTGT(codestr, tgt);
554 /* The current opcode inherits
555 its target's stack behaviour */
556 codestr[i] = j;
557 SETARG(codestr, i, tgttgt);
558 goto reoptimize_current;
559 } else {
560 /* The second jump is not taken
561 if the first is (so jump past
562 it), and all conditional
563 jumps pop their argument when
564 they're not taken (so change
565 the first jump to pop its
566 argument when it's taken). */
567 if (JUMPS_ON_TRUE(opcode))
568 codestr[i] = POP_JUMP_IF_TRUE;
569 else
570 codestr[i] = POP_JUMP_IF_FALSE;
571 SETARG(codestr, i, (tgt + 3));
572 goto reoptimize_current;
573 }
574 }
575 /* Intentional fallthrough */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000576
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000577 /* Replace jumps to unconditional jumps */
578 case POP_JUMP_IF_FALSE:
579 case POP_JUMP_IF_TRUE:
580 case FOR_ITER:
581 case JUMP_FORWARD:
582 case JUMP_ABSOLUTE:
583 case CONTINUE_LOOP:
584 case SETUP_LOOP:
585 case SETUP_EXCEPT:
586 case SETUP_FINALLY:
587 tgt = GETJUMPTGT(codestr, i);
588 /* Replace JUMP_* to a RETURN into just a RETURN */
589 if (UNCONDITIONAL_JUMP(opcode) &&
590 codestr[tgt] == RETURN_VALUE) {
591 codestr[i] = RETURN_VALUE;
592 memset(codestr+i+1, NOP, 2);
593 continue;
594 }
595 if (!UNCONDITIONAL_JUMP(codestr[tgt]))
596 continue;
597 tgttgt = GETJUMPTGT(codestr, tgt);
598 if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */
599 opcode = JUMP_ABSOLUTE;
600 if (!ABSOLUTE_JUMP(opcode))
601 tgttgt -= i + 3; /* Calc relative jump addr */
602 if (tgttgt < 0) /* No backward relative jumps */
603 continue;
604 codestr[i] = opcode;
605 SETARG(codestr, i, tgttgt);
606 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000607
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000608 case EXTENDED_ARG:
609 if (codestr[i+3] != MAKE_FUNCTION)
610 goto exitUnchanged;
611 /* don't visit MAKE_FUNCTION as GETARG will be wrong */
612 i += 3;
613 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000614
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000615 /* Replace RETURN LOAD_CONST None RETURN with just RETURN */
616 /* Remove unreachable JUMPs after RETURN */
617 case RETURN_VALUE:
618 if (i+4 >= codelen)
619 continue;
620 if (codestr[i+4] == RETURN_VALUE &&
621 ISBASICBLOCK(blocks,i,5))
622 memset(codestr+i+1, NOP, 4);
623 else if (UNCONDITIONAL_JUMP(codestr[i+1]) &&
624 ISBASICBLOCK(blocks,i,4))
625 memset(codestr+i+1, NOP, 3);
626 break;
627 }
628 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000629
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000630 /* Fixup linenotab */
631 for (i=0, nops=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
632 addrmap[i] = i - nops;
633 if (codestr[i] == NOP)
634 nops++;
635 }
636 cum_orig_line = 0;
637 last_line = 0;
638 for (i=0 ; i < tabsiz ; i+=2) {
639 cum_orig_line += lineno[i];
640 new_line = addrmap[cum_orig_line];
641 assert (new_line - last_line < 255);
642 lineno[i] =((unsigned char)(new_line - last_line));
643 last_line = new_line;
644 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000645
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000646 /* Remove NOPs and fixup jump targets */
647 for (i=0, h=0 ; i<codelen ; ) {
648 opcode = codestr[i];
649 switch (opcode) {
650 case NOP:
651 i++;
652 continue;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000653
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000654 case JUMP_ABSOLUTE:
655 case CONTINUE_LOOP:
656 case POP_JUMP_IF_FALSE:
657 case POP_JUMP_IF_TRUE:
658 case JUMP_IF_FALSE_OR_POP:
659 case JUMP_IF_TRUE_OR_POP:
660 j = addrmap[GETARG(codestr, i)];
661 SETARG(codestr, i, j);
662 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000663
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000664 case FOR_ITER:
665 case JUMP_FORWARD:
666 case SETUP_LOOP:
667 case SETUP_EXCEPT:
668 case SETUP_FINALLY:
669 j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3;
670 SETARG(codestr, i, j);
671 break;
672 }
673 adj = CODESIZE(opcode);
674 while (adj--)
675 codestr[h++] = codestr[i++];
676 }
677 assert(h + nops == codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000678
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000679 code = PyBytes_FromStringAndSize((char *)codestr, h);
680 PyMem_Free(addrmap);
681 PyMem_Free(codestr);
682 PyMem_Free(blocks);
683 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000684
Georg Brandl194da4a2009-08-13 09:34:05 +0000685 exitError:
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000686 code = NULL;
Georg Brandl194da4a2009-08-13 09:34:05 +0000687
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000688 exitUnchanged:
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000689 if (blocks != NULL)
690 PyMem_Free(blocks);
691 if (addrmap != NULL)
692 PyMem_Free(addrmap);
693 if (codestr != NULL)
694 PyMem_Free(codestr);
695 Py_XINCREF(code);
696 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000697}