blob: 7deb02d267a5b7c62525a9f0b991a24224978425 [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 Pitrouf95a1b32010-05-09 15:52:27 +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 Pitrouf95a1b32010-05-09 15:52:27 +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 Pitrouf95a1b32010-05-09 15:52:27 +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 Pitrouf95a1b32010-05-09 15:52:27 +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 Pitrouf95a1b32010-05-09 15:52:27 +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 Pitrouf95a1b32010-05-09 15:52:27 +000033 Bails out with no change if one or more of the LOAD_CONSTs is missing.
Antoine Pitroub7fbcd32010-01-16 18:37:38 +000034 Also works for BUILD_LIST and BUILT_SET when followed by an "in" or "not in"
35 test; for BUILD_SET it assembles a frozenset rather than a tuple.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000036*/
37static int
Christian Heimescc47b052008-03-25 14:56:36 +000038tuple_of_constants(unsigned char *codestr, Py_ssize_t n, PyObject *consts)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000039{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000040 PyObject *newconst, *constant;
41 Py_ssize_t i, arg, len_consts;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000042
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000043 /* Pre-conditions */
44 assert(PyList_CheckExact(consts));
45 assert(codestr[n*3] == BUILD_TUPLE || codestr[n*3] == BUILD_LIST || codestr[n*3] == BUILD_SET);
46 assert(GETARG(codestr, (n*3)) == n);
47 for (i=0 ; i<n ; i++)
48 assert(codestr[i*3] == LOAD_CONST);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000049
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000050 /* Buildup new tuple of constants */
51 newconst = PyTuple_New(n);
52 if (newconst == NULL)
53 return 0;
54 len_consts = PyList_GET_SIZE(consts);
55 for (i=0 ; i<n ; i++) {
56 arg = GETARG(codestr, (i*3));
57 assert(arg < len_consts);
58 constant = PyList_GET_ITEM(consts, arg);
59 Py_INCREF(constant);
60 PyTuple_SET_ITEM(newconst, i, constant);
61 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000062
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000063 /* If it's a BUILD_SET, use the PyTuple we just built to create a
64 PyFrozenSet, and use that as the constant instead: */
65 if (codestr[n*3] == BUILD_SET) {
66 PyObject *tuple = newconst;
67 newconst = PyFrozenSet_New(tuple);
68 Py_DECREF(tuple);
69 if (newconst == NULL)
70 return 0;
71 }
Antoine Pitroub7fbcd32010-01-16 18:37:38 +000072
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000073 /* Append folded constant onto consts */
74 if (PyList_Append(consts, newconst)) {
75 Py_DECREF(newconst);
76 return 0;
77 }
78 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000079
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000080 /* Write NOPs over old LOAD_CONSTS and
81 add a new LOAD_CONST newconst on top of the BUILD_TUPLE n */
82 memset(codestr, NOP, n*3);
83 codestr[n*3] = LOAD_CONST;
84 SETARG(codestr, (n*3), len_consts);
85 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000086}
87
88/* Replace LOAD_CONST c1. LOAD_CONST c2 BINOP
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000089 with LOAD_CONST binop(c1,c2)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000090 The consts table must still be in list form so that the
91 new constant can be appended.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000092 Called with codestr pointing to the first LOAD_CONST.
93 Abandons the transformation if the folding fails (i.e. 1+'a').
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000094 If the new constant is a sequence, only folds when the size
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000095 is below a threshold value. That keeps pyc files from
96 becoming large in the presence of code like: (None,)*1000.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000097*/
98static int
99fold_binops_on_constants(unsigned char *codestr, PyObject *consts)
100{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000101 PyObject *newconst, *v, *w;
102 Py_ssize_t len_consts, size;
103 int opcode;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000104
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000105 /* Pre-conditions */
106 assert(PyList_CheckExact(consts));
107 assert(codestr[0] == LOAD_CONST);
108 assert(codestr[3] == LOAD_CONST);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000109
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000110 /* Create new constant */
111 v = PyList_GET_ITEM(consts, GETARG(codestr, 0));
112 w = PyList_GET_ITEM(consts, GETARG(codestr, 3));
113 opcode = codestr[6];
114 switch (opcode) {
115 case BINARY_POWER:
116 newconst = PyNumber_Power(v, w, Py_None);
117 break;
118 case BINARY_MULTIPLY:
119 newconst = PyNumber_Multiply(v, w);
120 break;
121 case BINARY_TRUE_DIVIDE:
122 newconst = PyNumber_TrueDivide(v, w);
123 break;
124 case BINARY_FLOOR_DIVIDE:
125 newconst = PyNumber_FloorDivide(v, w);
126 break;
127 case BINARY_MODULO:
128 newconst = PyNumber_Remainder(v, w);
129 break;
130 case BINARY_ADD:
131 newconst = PyNumber_Add(v, w);
132 break;
133 case BINARY_SUBTRACT:
134 newconst = PyNumber_Subtract(v, w);
135 break;
136 case BINARY_SUBSCR:
137 newconst = PyObject_GetItem(v, w);
138 break;
139 case BINARY_LSHIFT:
140 newconst = PyNumber_Lshift(v, w);
141 break;
142 case BINARY_RSHIFT:
143 newconst = PyNumber_Rshift(v, w);
144 break;
145 case BINARY_AND:
146 newconst = PyNumber_And(v, w);
147 break;
148 case BINARY_XOR:
149 newconst = PyNumber_Xor(v, w);
150 break;
151 case BINARY_OR:
152 newconst = PyNumber_Or(v, w);
153 break;
154 default:
155 /* Called with an unknown opcode */
156 PyErr_Format(PyExc_SystemError,
157 "unexpected binary operation %d on a constant",
158 opcode);
159 return 0;
160 }
161 if (newconst == NULL) {
162 PyErr_Clear();
163 return 0;
164 }
165 size = PyObject_Size(newconst);
166 if (size == -1)
167 PyErr_Clear();
168 else if (size > 20) {
169 Py_DECREF(newconst);
170 return 0;
171 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000172
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000173 /* Append folded constant into consts table */
174 len_consts = PyList_GET_SIZE(consts);
175 if (PyList_Append(consts, newconst)) {
176 Py_DECREF(newconst);
177 return 0;
178 }
179 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000180
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000181 /* Write NOP NOP NOP NOP LOAD_CONST newconst */
182 memset(codestr, NOP, 4);
183 codestr[4] = LOAD_CONST;
184 SETARG(codestr, 4, len_consts);
185 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000186}
187
188static int
189fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts)
190{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000191 PyObject *newconst=NULL, *v;
192 Py_ssize_t len_consts;
193 int opcode;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000194
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000195 /* Pre-conditions */
196 assert(PyList_CheckExact(consts));
197 assert(codestr[0] == LOAD_CONST);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000198
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000199 /* Create new constant */
200 v = PyList_GET_ITEM(consts, GETARG(codestr, 0));
201 opcode = codestr[3];
202 switch (opcode) {
203 case UNARY_NEGATIVE:
204 /* Preserve the sign of -0.0 */
205 if (PyObject_IsTrue(v) == 1)
206 newconst = PyNumber_Negative(v);
207 break;
208 case UNARY_INVERT:
209 newconst = PyNumber_Invert(v);
210 break;
211 case UNARY_POSITIVE:
212 newconst = PyNumber_Positive(v);
213 break;
214 default:
215 /* Called with an unknown opcode */
216 PyErr_Format(PyExc_SystemError,
217 "unexpected unary operation %d on a constant",
218 opcode);
219 return 0;
220 }
221 if (newconst == NULL) {
222 PyErr_Clear();
223 return 0;
224 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000225
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000226 /* Append folded constant into consts table */
227 len_consts = PyList_GET_SIZE(consts);
228 if (PyList_Append(consts, newconst)) {
229 Py_DECREF(newconst);
230 return 0;
231 }
232 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000233
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000234 /* Write NOP LOAD_CONST newconst */
235 codestr[0] = NOP;
236 codestr[1] = LOAD_CONST;
237 SETARG(codestr, 1, len_consts);
238 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000239}
240
241static unsigned int *
Christian Heimescc47b052008-03-25 14:56:36 +0000242markblocks(unsigned char *code, Py_ssize_t len)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000243{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000244 unsigned int *blocks = (unsigned int *)PyMem_Malloc(len*sizeof(int));
245 int i,j, opcode, blockcnt = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000246
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000247 if (blocks == NULL) {
248 PyErr_NoMemory();
249 return NULL;
250 }
251 memset(blocks, 0, len*sizeof(int));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000252
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000253 /* Mark labels in the first pass */
254 for (i=0 ; i<len ; i+=CODESIZE(opcode)) {
255 opcode = code[i];
256 switch (opcode) {
257 case FOR_ITER:
258 case JUMP_FORWARD:
259 case JUMP_IF_FALSE_OR_POP:
260 case JUMP_IF_TRUE_OR_POP:
261 case POP_JUMP_IF_FALSE:
262 case POP_JUMP_IF_TRUE:
263 case JUMP_ABSOLUTE:
264 case CONTINUE_LOOP:
265 case SETUP_LOOP:
266 case SETUP_EXCEPT:
267 case SETUP_FINALLY:
268 case SETUP_WITH:
269 j = GETJUMPTGT(code, i);
270 blocks[j] = 1;
271 break;
272 }
273 }
274 /* Build block numbers in the second pass */
275 for (i=0 ; i<len ; i++) {
276 blockcnt += blocks[i]; /* increment blockcnt over labels */
277 blocks[i] = blockcnt;
278 }
279 return blocks;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000280}
281
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000282/* Helper to replace LOAD_NAME None/True/False with LOAD_CONST
283 Returns: 0 if no change, 1 if change, -1 if error */
284static int
285load_global(unsigned char *codestr, Py_ssize_t i, char *name, PyObject *consts)
286{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000287 Py_ssize_t j;
288 PyObject *obj;
289 if (name == NULL)
290 return 0;
291 if (strcmp(name, "None") == 0)
292 obj = Py_None;
293 else if (strcmp(name, "True") == 0)
294 obj = Py_True;
295 else if (strcmp(name, "False") == 0)
296 obj = Py_False;
297 else
298 return 0;
299 for (j = 0; j < PyList_GET_SIZE(consts); j++) {
300 if (PyList_GET_ITEM(consts, j) == obj)
301 break;
302 }
303 if (j == PyList_GET_SIZE(consts)) {
304 if (PyList_Append(consts, obj) < 0)
305 return -1;
306 }
307 assert(PyList_GET_ITEM(consts, j) == obj);
308 codestr[i] = LOAD_CONST;
309 SETARG(codestr, i, j);
310 return 1;
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000311}
312
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000313/* Perform basic peephole optimizations to components of a code object.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000314 The consts object should still be in list form to allow new constants
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000315 to be appended.
316
Guido van Rossum0240b922007-02-26 21:23:50 +0000317 To keep the optimizer simple, it bails out (does nothing) for code that
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000318 has a length over 32,700, and does not calculate extended arguments.
Guido van Rossum0240b922007-02-26 21:23:50 +0000319 That allows us to avoid overflow and sign issues. Likewise, it bails when
320 the lineno table has complex encoding for gaps >= 255. EXTENDED_ARG can
321 appear before MAKE_FUNCTION; in this case both opcodes are skipped.
322 EXTENDED_ARG preceding any other opcode causes the optimizer to bail.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000323
324 Optimizations are restricted to simple transformations occuring within a
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000325 single basic block. All transformations keep the code size the same or
326 smaller. For those that reduce size, the gaps are initially filled with
327 NOPs. Later those NOPs are removed and the jump addresses retargeted in
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000328 a single pass. Line numbering is adjusted accordingly. */
329
330PyObject *
331PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
332 PyObject *lineno_obj)
333{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000334 Py_ssize_t i, j, codelen;
335 int nops, h, adj;
336 int tgt, tgttgt, opcode;
337 unsigned char *codestr = NULL;
338 unsigned char *lineno;
339 int *addrmap = NULL;
340 int new_line, cum_orig_line, last_line, tabsiz;
341 int cumlc=0, lastlc=0; /* Count runs of consecutive LOAD_CONSTs */
342 unsigned int *blocks = NULL;
343 char *name;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000344
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000345 /* Bail out if an exception is set */
346 if (PyErr_Occurred())
347 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000348
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000349 /* Bypass optimization when the lineno table is too complex */
350 assert(PyBytes_Check(lineno_obj));
351 lineno = (unsigned char*)PyBytes_AS_STRING(lineno_obj);
352 tabsiz = PyBytes_GET_SIZE(lineno_obj);
353 if (memchr(lineno, 255, tabsiz) != NULL)
354 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000355
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000356 /* Avoid situations where jump retargeting could overflow */
357 assert(PyBytes_Check(code));
358 codelen = PyBytes_GET_SIZE(code);
359 if (codelen > 32700)
360 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000361
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000362 /* Make a modifiable copy of the code string */
363 codestr = (unsigned char *)PyMem_Malloc(codelen);
364 if (codestr == NULL)
365 goto exitError;
366 codestr = (unsigned char *)memcpy(codestr,
367 PyBytes_AS_STRING(code), codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000368
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000369 /* Verify that RETURN_VALUE terminates the codestring. This allows
370 the various transformation patterns to look ahead several
371 instructions without additional checks to make sure they are not
372 looking beyond the end of the code string.
373 */
374 if (codestr[codelen-1] != RETURN_VALUE)
375 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000376
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000377 /* Mapping to new jump targets after NOPs are removed */
378 addrmap = (int *)PyMem_Malloc(codelen * sizeof(int));
379 if (addrmap == NULL)
380 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000382 blocks = markblocks(codestr, codelen);
383 if (blocks == NULL)
384 goto exitError;
385 assert(PyList_Check(consts));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000386
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000387 for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
388 reoptimize_current:
389 opcode = codestr[i];
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000390
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000391 lastlc = cumlc;
392 cumlc = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000393
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000394 switch (opcode) {
395 /* Replace UNARY_NOT POP_JUMP_IF_FALSE
396 with POP_JUMP_IF_TRUE */
397 case UNARY_NOT:
398 if (codestr[i+1] != POP_JUMP_IF_FALSE
399 || !ISBASICBLOCK(blocks,i,4))
400 continue;
401 j = GETARG(codestr, i+1);
402 codestr[i] = POP_JUMP_IF_TRUE;
403 SETARG(codestr, i, j);
404 codestr[i+3] = NOP;
405 goto reoptimize_current;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000406
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000407 /* not a is b --> a is not b
408 not a in b --> a not in b
409 not a is not b --> a is b
410 not a not in b --> a in b
411 */
412 case COMPARE_OP:
413 j = GETARG(codestr, i);
414 if (j < 6 || j > 9 ||
415 codestr[i+3] != UNARY_NOT ||
416 !ISBASICBLOCK(blocks,i,4))
417 continue;
418 SETARG(codestr, i, (j^1));
419 codestr[i+3] = NOP;
420 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000421
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000422 /* Replace LOAD_GLOBAL/LOAD_NAME None/True/False
423 with LOAD_CONST None/True/False */
424 case LOAD_NAME:
425 case LOAD_GLOBAL:
426 j = GETARG(codestr, i);
427 name = _PyUnicode_AsString(PyTuple_GET_ITEM(names, j));
428 h = load_global(codestr, i, name, consts);
429 if (h < 0)
430 goto exitError;
431 else if (h == 0)
432 continue;
433 cumlc = lastlc + 1;
434 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000435
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000436 /* Skip over LOAD_CONST trueconst
437 POP_JUMP_IF_FALSE xx. This improves
438 "while 1" performance. */
439 case LOAD_CONST:
440 cumlc = lastlc + 1;
441 j = GETARG(codestr, i);
442 if (codestr[i+3] != POP_JUMP_IF_FALSE ||
443 !ISBASICBLOCK(blocks,i,6) ||
444 !PyObject_IsTrue(PyList_GET_ITEM(consts, j)))
445 continue;
446 memset(codestr+i, NOP, 6);
447 cumlc = 0;
448 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000449
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000450 /* Try to fold tuples of constants (includes a case for lists and sets
451 which are only used for "in" and "not in" tests).
452 Skip over BUILD_SEQN 1 UNPACK_SEQN 1.
453 Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2.
454 Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */
455 case BUILD_TUPLE:
456 case BUILD_LIST:
457 case BUILD_SET:
458 j = GETARG(codestr, i);
459 h = i - 3 * j;
460 if (h >= 0 &&
461 j <= lastlc &&
462 ((opcode == BUILD_TUPLE &&
463 ISBASICBLOCK(blocks, h, 3*(j+1))) ||
464 ((opcode == BUILD_LIST || opcode == BUILD_SET) &&
465 codestr[i+3]==COMPARE_OP &&
466 ISBASICBLOCK(blocks, h, 3*(j+2)) &&
467 (GETARG(codestr,i+3)==6 ||
468 GETARG(codestr,i+3)==7))) &&
469 tuple_of_constants(&codestr[h], j, consts)) {
470 assert(codestr[i] == LOAD_CONST);
471 cumlc = 1;
472 break;
473 }
474 if (codestr[i+3] != UNPACK_SEQUENCE ||
475 !ISBASICBLOCK(blocks,i,6) ||
476 j != GETARG(codestr, i+3))
477 continue;
478 if (j == 1) {
479 memset(codestr+i, NOP, 6);
480 } else if (j == 2) {
481 codestr[i] = ROT_TWO;
482 memset(codestr+i+1, NOP, 5);
483 } else if (j == 3) {
484 codestr[i] = ROT_THREE;
485 codestr[i+1] = ROT_TWO;
486 memset(codestr+i+2, NOP, 4);
487 }
488 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000489
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000490 /* Fold binary ops on constants.
491 LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */
492 case BINARY_POWER:
493 case BINARY_MULTIPLY:
494 case BINARY_TRUE_DIVIDE:
495 case BINARY_FLOOR_DIVIDE:
496 case BINARY_MODULO:
497 case BINARY_ADD:
498 case BINARY_SUBTRACT:
499 case BINARY_SUBSCR:
500 case BINARY_LSHIFT:
501 case BINARY_RSHIFT:
502 case BINARY_AND:
503 case BINARY_XOR:
504 case BINARY_OR:
505 if (lastlc >= 2 &&
506 ISBASICBLOCK(blocks, i-6, 7) &&
507 fold_binops_on_constants(&codestr[i-6], consts)) {
508 i -= 2;
509 assert(codestr[i] == LOAD_CONST);
510 cumlc = 1;
511 }
512 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000513
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000514 /* Fold unary ops on constants.
515 LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */
516 case UNARY_NEGATIVE:
517 case UNARY_INVERT:
518 case UNARY_POSITIVE:
519 if (lastlc >= 1 &&
520 ISBASICBLOCK(blocks, i-3, 4) &&
521 fold_unaryops_on_constants(&codestr[i-3], consts)) {
522 i -= 2;
523 assert(codestr[i] == LOAD_CONST);
524 cumlc = 1;
525 }
526 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000527
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000528 /* Simplify conditional jump to conditional jump where the
529 result of the first test implies the success of a similar
530 test or the failure of the opposite test.
531 Arises in code like:
532 "if a and b:"
533 "if a or b:"
534 "a and b or c"
535 "(a and b) and c"
536 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z
537 --> x:JUMP_IF_FALSE_OR_POP z
538 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z
539 --> x:POP_JUMP_IF_FALSE y+3
540 where y+3 is the instruction following the second test.
541 */
542 case JUMP_IF_FALSE_OR_POP:
543 case JUMP_IF_TRUE_OR_POP:
544 tgt = GETJUMPTGT(codestr, i);
545 j = codestr[tgt];
546 if (CONDITIONAL_JUMP(j)) {
547 /* NOTE: all possible jumps here are
548 absolute! */
549 if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) {
550 /* The second jump will be
551 taken iff the first is. */
552 tgttgt = GETJUMPTGT(codestr, tgt);
553 /* The current opcode inherits
554 its target's stack behaviour */
555 codestr[i] = j;
556 SETARG(codestr, i, tgttgt);
557 goto reoptimize_current;
558 } else {
559 /* The second jump is not taken
560 if the first is (so jump past
561 it), and all conditional
562 jumps pop their argument when
563 they're not taken (so change
564 the first jump to pop its
565 argument when it's taken). */
566 if (JUMPS_ON_TRUE(opcode))
567 codestr[i] = POP_JUMP_IF_TRUE;
568 else
569 codestr[i] = POP_JUMP_IF_FALSE;
570 SETARG(codestr, i, (tgt + 3));
571 goto reoptimize_current;
572 }
573 }
574 /* Intentional fallthrough */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000575
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000576 /* Replace jumps to unconditional jumps */
577 case POP_JUMP_IF_FALSE:
578 case POP_JUMP_IF_TRUE:
579 case FOR_ITER:
580 case JUMP_FORWARD:
581 case JUMP_ABSOLUTE:
582 case CONTINUE_LOOP:
583 case SETUP_LOOP:
584 case SETUP_EXCEPT:
585 case SETUP_FINALLY:
586 case SETUP_WITH:
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 Pitrouf95a1b32010-05-09 15:52:27 +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 Pitrouf95a1b32010-05-09 15:52:27 +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 Pitrouf95a1b32010-05-09 15:52:27 +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 Pitrouf95a1b32010-05-09 15:52:27 +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 Pitrouf95a1b32010-05-09 15:52:27 +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 Pitrouf95a1b32010-05-09 15:52:27 +0000664 case FOR_ITER:
665 case JUMP_FORWARD:
666 case SETUP_LOOP:
667 case SETUP_EXCEPT:
668 case SETUP_FINALLY:
669 case SETUP_WITH:
670 j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3;
671 SETARG(codestr, i, j);
672 break;
673 }
674 adj = CODESIZE(opcode);
675 while (adj--)
676 codestr[h++] = codestr[i++];
677 }
678 assert(h + nops == codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000679
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000680 code = PyBytes_FromStringAndSize((char *)codestr, h);
681 PyMem_Free(addrmap);
682 PyMem_Free(codestr);
683 PyMem_Free(blocks);
684 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000685
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000686 exitError:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000687 code = NULL;
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000688
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000689 exitUnchanged:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000690 if (blocks != NULL)
691 PyMem_Free(blocks);
692 if (addrmap != NULL)
693 PyMem_Free(addrmap);
694 if (codestr != NULL)
695 PyMem_Free(codestr);
696 Py_XINCREF(code);
697 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000698}