blob: 7ae599bb119f034aee33baaf607f7e1d5eee8b24 [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"
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00007#include "ast.h"
8#include "code.h"
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00009#include "symtable.h"
10#include "opcode.h"
11
12#define GETARG(arr, i) ((int)((arr[i+2]<<8) + arr[i+1]))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000013#define UNCONDITIONAL_JUMP(op) (op==JUMP_ABSOLUTE || op==JUMP_FORWARD)
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +000014#define CONDITIONAL_JUMP(op) (op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000015 || op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP)
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +000016#define ABSOLUTE_JUMP(op) (op==JUMP_ABSOLUTE || op==CONTINUE_LOOP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000017 || op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \
18 || op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP)
Jeffrey Yasskin9de7ec72009-02-25 02:25:04 +000019#define JUMPS_ON_TRUE(op) (op==POP_JUMP_IF_TRUE || op==JUMP_IF_TRUE_OR_POP)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000020#define GETJUMPTGT(arr, i) (GETARG(arr,i) + (ABSOLUTE_JUMP(arr[i]) ? 0 : i+3))
21#define SETARG(arr, i, val) arr[i+2] = val>>8; arr[i+1] = val & 255
22#define CODESIZE(op) (HAS_ARG(op) ? 3 : 1)
23#define ISBASICBLOCK(blocks, start, bytes) \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000024 (blocks[start]==blocks[start+bytes-1])
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000025
26/* Replace LOAD_CONST c1. LOAD_CONST c2 ... LOAD_CONST cn BUILD_TUPLE n
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000027 with LOAD_CONST (c1, c2, ... cn).
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000028 The consts table must still be in list form so that the
29 new constant (c1, c2, ... cn) can be appended.
30 Called with codestr pointing to the first LOAD_CONST.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000031 Bails out with no change if one or more of the LOAD_CONSTs is missing.
Antoine Pitroub7fbcd32010-01-16 18:37:38 +000032 Also works for BUILD_LIST and BUILT_SET when followed by an "in" or "not in"
33 test; for BUILD_SET it assembles a frozenset rather than a tuple.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000034*/
35static int
Christian Heimescc47b052008-03-25 14:56:36 +000036tuple_of_constants(unsigned char *codestr, Py_ssize_t n, PyObject *consts)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000037{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000038 PyObject *newconst, *constant;
39 Py_ssize_t i, arg, len_consts;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000040
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000041 /* Pre-conditions */
42 assert(PyList_CheckExact(consts));
43 assert(codestr[n*3] == BUILD_TUPLE || codestr[n*3] == BUILD_LIST || codestr[n*3] == BUILD_SET);
44 assert(GETARG(codestr, (n*3)) == n);
45 for (i=0 ; i<n ; i++)
46 assert(codestr[i*3] == LOAD_CONST);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000047
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000048 /* Buildup new tuple of constants */
49 newconst = PyTuple_New(n);
50 if (newconst == NULL)
51 return 0;
52 len_consts = PyList_GET_SIZE(consts);
53 for (i=0 ; i<n ; i++) {
54 arg = GETARG(codestr, (i*3));
55 assert(arg < len_consts);
56 constant = PyList_GET_ITEM(consts, arg);
57 Py_INCREF(constant);
58 PyTuple_SET_ITEM(newconst, i, constant);
59 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000060
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000061 /* If it's a BUILD_SET, use the PyTuple we just built to create a
62 PyFrozenSet, and use that as the constant instead: */
63 if (codestr[n*3] == BUILD_SET) {
64 PyObject *tuple = newconst;
65 newconst = PyFrozenSet_New(tuple);
66 Py_DECREF(tuple);
67 if (newconst == NULL)
68 return 0;
69 }
Antoine Pitroub7fbcd32010-01-16 18:37:38 +000070
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000071 /* Append folded constant onto consts */
72 if (PyList_Append(consts, newconst)) {
73 Py_DECREF(newconst);
74 return 0;
75 }
76 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000077
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000078 /* Write NOPs over old LOAD_CONSTS and
79 add a new LOAD_CONST newconst on top of the BUILD_TUPLE n */
80 memset(codestr, NOP, n*3);
81 codestr[n*3] = LOAD_CONST;
82 SETARG(codestr, (n*3), len_consts);
83 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000084}
85
86/* Replace LOAD_CONST c1. LOAD_CONST c2 BINOP
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000087 with LOAD_CONST binop(c1,c2)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000088 The consts table must still be in list form so that the
89 new constant can be appended.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000090 Called with codestr pointing to the first LOAD_CONST.
91 Abandons the transformation if the folding fails (i.e. 1+'a').
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000092 If the new constant is a sequence, only folds when the size
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000093 is below a threshold value. That keeps pyc files from
94 becoming large in the presence of code like: (None,)*1000.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000095*/
96static int
97fold_binops_on_constants(unsigned char *codestr, PyObject *consts)
98{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000099 PyObject *newconst, *v, *w;
100 Py_ssize_t len_consts, size;
101 int opcode;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000102
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000103 /* Pre-conditions */
104 assert(PyList_CheckExact(consts));
105 assert(codestr[0] == LOAD_CONST);
106 assert(codestr[3] == LOAD_CONST);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000107
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000108 /* Create new constant */
109 v = PyList_GET_ITEM(consts, GETARG(codestr, 0));
110 w = PyList_GET_ITEM(consts, GETARG(codestr, 3));
111 opcode = codestr[6];
112 switch (opcode) {
113 case BINARY_POWER:
114 newconst = PyNumber_Power(v, w, Py_None);
115 break;
116 case BINARY_MULTIPLY:
117 newconst = PyNumber_Multiply(v, w);
118 break;
119 case BINARY_TRUE_DIVIDE:
120 newconst = PyNumber_TrueDivide(v, w);
121 break;
122 case BINARY_FLOOR_DIVIDE:
123 newconst = PyNumber_FloorDivide(v, w);
124 break;
125 case BINARY_MODULO:
126 newconst = PyNumber_Remainder(v, w);
127 break;
128 case BINARY_ADD:
129 newconst = PyNumber_Add(v, w);
130 break;
131 case BINARY_SUBTRACT:
132 newconst = PyNumber_Subtract(v, w);
133 break;
134 case BINARY_SUBSCR:
Ezio Melotti2df6a932011-04-15 16:38:34 +0300135 /* #5057: if v is unicode, there might be differences between
Ezio Melotti6c5f5212012-11-05 00:06:32 +0200136 wide and narrow builds in cases like '\U00012345'[0] or
137 '\U00012345abcdef'[3], so it's better to skip the optimization
138 in order to produce compatible pycs.
139 */
140 if (PyUnicode_Check(v))
141 return 0;
142 newconst = PyObject_GetItem(v, w);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000143 break;
144 case BINARY_LSHIFT:
145 newconst = PyNumber_Lshift(v, w);
146 break;
147 case BINARY_RSHIFT:
148 newconst = PyNumber_Rshift(v, w);
149 break;
150 case BINARY_AND:
151 newconst = PyNumber_And(v, w);
152 break;
153 case BINARY_XOR:
154 newconst = PyNumber_Xor(v, w);
155 break;
156 case BINARY_OR:
157 newconst = PyNumber_Or(v, w);
158 break;
159 default:
160 /* Called with an unknown opcode */
161 PyErr_Format(PyExc_SystemError,
162 "unexpected binary operation %d on a constant",
163 opcode);
164 return 0;
165 }
166 if (newconst == NULL) {
Raymond Hettinger819a0642010-08-22 08:39:49 +0000167 if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
168 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000169 return 0;
170 }
171 size = PyObject_Size(newconst);
Raymond Hettinger819a0642010-08-22 08:39:49 +0000172 if (size == -1) {
173 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
174 return 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000175 PyErr_Clear();
Raymond Hettinger819a0642010-08-22 08:39:49 +0000176 } else if (size > 20) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000177 Py_DECREF(newconst);
178 return 0;
179 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000180
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000181 /* Append folded constant into consts table */
182 len_consts = PyList_GET_SIZE(consts);
183 if (PyList_Append(consts, newconst)) {
184 Py_DECREF(newconst);
185 return 0;
186 }
187 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000188
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000189 /* Write NOP NOP NOP NOP LOAD_CONST newconst */
190 memset(codestr, NOP, 4);
191 codestr[4] = LOAD_CONST;
192 SETARG(codestr, 4, len_consts);
193 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000194}
195
196static int
197fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts)
198{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000199 PyObject *newconst=NULL, *v;
200 Py_ssize_t len_consts;
201 int opcode;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000202
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000203 /* Pre-conditions */
204 assert(PyList_CheckExact(consts));
205 assert(codestr[0] == LOAD_CONST);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000206
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000207 /* Create new constant */
208 v = PyList_GET_ITEM(consts, GETARG(codestr, 0));
209 opcode = codestr[3];
210 switch (opcode) {
211 case UNARY_NEGATIVE:
212 /* Preserve the sign of -0.0 */
213 if (PyObject_IsTrue(v) == 1)
214 newconst = PyNumber_Negative(v);
215 break;
216 case UNARY_INVERT:
217 newconst = PyNumber_Invert(v);
218 break;
219 case UNARY_POSITIVE:
220 newconst = PyNumber_Positive(v);
221 break;
222 default:
223 /* Called with an unknown opcode */
224 PyErr_Format(PyExc_SystemError,
225 "unexpected unary operation %d on a constant",
226 opcode);
227 return 0;
228 }
229 if (newconst == NULL) {
Raymond Hettinger819a0642010-08-22 08:39:49 +0000230 if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
231 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000232 return 0;
233 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000234
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000235 /* Append folded constant into consts table */
236 len_consts = PyList_GET_SIZE(consts);
237 if (PyList_Append(consts, newconst)) {
238 Py_DECREF(newconst);
239 return 0;
240 }
241 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000242
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000243 /* Write NOP LOAD_CONST newconst */
244 codestr[0] = NOP;
245 codestr[1] = LOAD_CONST;
246 SETARG(codestr, 1, len_consts);
247 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000248}
249
250static unsigned int *
Christian Heimescc47b052008-03-25 14:56:36 +0000251markblocks(unsigned char *code, Py_ssize_t len)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000252{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000253 unsigned int *blocks = (unsigned int *)PyMem_Malloc(len*sizeof(int));
254 int i,j, opcode, blockcnt = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000255
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000256 if (blocks == NULL) {
257 PyErr_NoMemory();
258 return NULL;
259 }
260 memset(blocks, 0, len*sizeof(int));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000261
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000262 /* Mark labels in the first pass */
263 for (i=0 ; i<len ; i+=CODESIZE(opcode)) {
264 opcode = code[i];
265 switch (opcode) {
266 case FOR_ITER:
267 case JUMP_FORWARD:
268 case JUMP_IF_FALSE_OR_POP:
269 case JUMP_IF_TRUE_OR_POP:
270 case POP_JUMP_IF_FALSE:
271 case POP_JUMP_IF_TRUE:
272 case JUMP_ABSOLUTE:
273 case CONTINUE_LOOP:
274 case SETUP_LOOP:
275 case SETUP_EXCEPT:
276 case SETUP_FINALLY:
277 case SETUP_WITH:
278 j = GETJUMPTGT(code, i);
279 blocks[j] = 1;
280 break;
281 }
282 }
283 /* Build block numbers in the second pass */
284 for (i=0 ; i<len ; i++) {
285 blockcnt += blocks[i]; /* increment blockcnt over labels */
286 blocks[i] = blockcnt;
287 }
288 return blocks;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000289}
290
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000291/* Helper to replace LOAD_NAME None/True/False with LOAD_CONST
292 Returns: 0 if no change, 1 if change, -1 if error */
293static int
294load_global(unsigned char *codestr, Py_ssize_t i, char *name, PyObject *consts)
295{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000296 Py_ssize_t j;
297 PyObject *obj;
298 if (name == NULL)
299 return 0;
300 if (strcmp(name, "None") == 0)
301 obj = Py_None;
302 else if (strcmp(name, "True") == 0)
303 obj = Py_True;
304 else if (strcmp(name, "False") == 0)
305 obj = Py_False;
306 else
307 return 0;
308 for (j = 0; j < PyList_GET_SIZE(consts); j++) {
309 if (PyList_GET_ITEM(consts, j) == obj)
310 break;
311 }
312 if (j == PyList_GET_SIZE(consts)) {
313 if (PyList_Append(consts, obj) < 0)
314 return -1;
315 }
316 assert(PyList_GET_ITEM(consts, j) == obj);
317 codestr[i] = LOAD_CONST;
318 SETARG(codestr, i, j);
319 return 1;
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000320}
321
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000322/* Perform basic peephole optimizations to components of a code object.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000323 The consts object should still be in list form to allow new constants
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000324 to be appended.
325
Guido van Rossum0240b922007-02-26 21:23:50 +0000326 To keep the optimizer simple, it bails out (does nothing) for code that
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000327 has a length over 32,700, and does not calculate extended arguments.
Guido van Rossum0240b922007-02-26 21:23:50 +0000328 That allows us to avoid overflow and sign issues. Likewise, it bails when
329 the lineno table has complex encoding for gaps >= 255. EXTENDED_ARG can
330 appear before MAKE_FUNCTION; in this case both opcodes are skipped.
331 EXTENDED_ARG preceding any other opcode causes the optimizer to bail.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000332
333 Optimizations are restricted to simple transformations occuring within a
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000334 single basic block. All transformations keep the code size the same or
335 smaller. For those that reduce size, the gaps are initially filled with
336 NOPs. Later those NOPs are removed and the jump addresses retargeted in
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000337 a single pass. Line numbering is adjusted accordingly. */
338
339PyObject *
340PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
341 PyObject *lineno_obj)
342{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000343 Py_ssize_t i, j, codelen;
344 int nops, h, adj;
345 int tgt, tgttgt, opcode;
346 unsigned char *codestr = NULL;
347 unsigned char *lineno;
348 int *addrmap = NULL;
349 int new_line, cum_orig_line, last_line, tabsiz;
350 int cumlc=0, lastlc=0; /* Count runs of consecutive LOAD_CONSTs */
351 unsigned int *blocks = NULL;
352 char *name;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000353
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000354 /* Bail out if an exception is set */
355 if (PyErr_Occurred())
356 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000357
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000358 /* Bypass optimization when the lineno table is too complex */
359 assert(PyBytes_Check(lineno_obj));
360 lineno = (unsigned char*)PyBytes_AS_STRING(lineno_obj);
361 tabsiz = PyBytes_GET_SIZE(lineno_obj);
362 if (memchr(lineno, 255, tabsiz) != NULL)
363 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000364
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000365 /* Avoid situations where jump retargeting could overflow */
366 assert(PyBytes_Check(code));
367 codelen = PyBytes_GET_SIZE(code);
368 if (codelen > 32700)
369 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000370
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000371 /* Make a modifiable copy of the code string */
372 codestr = (unsigned char *)PyMem_Malloc(codelen);
373 if (codestr == NULL)
374 goto exitError;
375 codestr = (unsigned char *)memcpy(codestr,
376 PyBytes_AS_STRING(code), codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000377
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000378 /* Verify that RETURN_VALUE terminates the codestring. This allows
379 the various transformation patterns to look ahead several
380 instructions without additional checks to make sure they are not
381 looking beyond the end of the code string.
382 */
383 if (codestr[codelen-1] != RETURN_VALUE)
384 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000385
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000386 /* Mapping to new jump targets after NOPs are removed */
387 addrmap = (int *)PyMem_Malloc(codelen * sizeof(int));
388 if (addrmap == NULL)
389 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000390
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000391 blocks = markblocks(codestr, codelen);
392 if (blocks == NULL)
393 goto exitError;
394 assert(PyList_Check(consts));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000395
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000396 for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
397 reoptimize_current:
398 opcode = codestr[i];
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000399
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000400 lastlc = cumlc;
401 cumlc = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000402
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000403 switch (opcode) {
404 /* Replace UNARY_NOT POP_JUMP_IF_FALSE
405 with POP_JUMP_IF_TRUE */
406 case UNARY_NOT:
407 if (codestr[i+1] != POP_JUMP_IF_FALSE
408 || !ISBASICBLOCK(blocks,i,4))
409 continue;
410 j = GETARG(codestr, i+1);
411 codestr[i] = POP_JUMP_IF_TRUE;
412 SETARG(codestr, i, j);
413 codestr[i+3] = NOP;
414 goto reoptimize_current;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000415
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000416 /* not a is b --> a is not b
417 not a in b --> a not in b
418 not a is not b --> a is b
419 not a not in b --> a in b
420 */
421 case COMPARE_OP:
422 j = GETARG(codestr, i);
423 if (j < 6 || j > 9 ||
424 codestr[i+3] != UNARY_NOT ||
425 !ISBASICBLOCK(blocks,i,4))
426 continue;
427 SETARG(codestr, i, (j^1));
428 codestr[i+3] = NOP;
429 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000430
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000431 /* Replace LOAD_GLOBAL/LOAD_NAME None/True/False
432 with LOAD_CONST None/True/False */
433 case LOAD_NAME:
434 case LOAD_GLOBAL:
435 j = GETARG(codestr, i);
436 name = _PyUnicode_AsString(PyTuple_GET_ITEM(names, j));
437 h = load_global(codestr, i, name, consts);
438 if (h < 0)
439 goto exitError;
440 else if (h == 0)
441 continue;
442 cumlc = lastlc + 1;
443 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000444
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000445 /* Skip over LOAD_CONST trueconst
446 POP_JUMP_IF_FALSE xx. This improves
447 "while 1" performance. */
448 case LOAD_CONST:
449 cumlc = lastlc + 1;
450 j = GETARG(codestr, i);
451 if (codestr[i+3] != POP_JUMP_IF_FALSE ||
452 !ISBASICBLOCK(blocks,i,6) ||
453 !PyObject_IsTrue(PyList_GET_ITEM(consts, j)))
454 continue;
455 memset(codestr+i, NOP, 6);
456 cumlc = 0;
457 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000458
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000459 /* Try to fold tuples of constants (includes a case for lists and sets
460 which are only used for "in" and "not in" tests).
461 Skip over BUILD_SEQN 1 UNPACK_SEQN 1.
462 Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2.
463 Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */
464 case BUILD_TUPLE:
465 case BUILD_LIST:
466 case BUILD_SET:
467 j = GETARG(codestr, i);
468 h = i - 3 * j;
469 if (h >= 0 &&
470 j <= lastlc &&
471 ((opcode == BUILD_TUPLE &&
472 ISBASICBLOCK(blocks, h, 3*(j+1))) ||
473 ((opcode == BUILD_LIST || opcode == BUILD_SET) &&
474 codestr[i+3]==COMPARE_OP &&
475 ISBASICBLOCK(blocks, h, 3*(j+2)) &&
476 (GETARG(codestr,i+3)==6 ||
477 GETARG(codestr,i+3)==7))) &&
478 tuple_of_constants(&codestr[h], j, consts)) {
479 assert(codestr[i] == LOAD_CONST);
480 cumlc = 1;
481 break;
482 }
483 if (codestr[i+3] != UNPACK_SEQUENCE ||
484 !ISBASICBLOCK(blocks,i,6) ||
Raymond Hettinger29dcaad2011-03-15 14:50:16 -0700485 j != GETARG(codestr, i+3) ||
486 opcode == BUILD_SET)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000487 continue;
488 if (j == 1) {
489 memset(codestr+i, NOP, 6);
490 } else if (j == 2) {
491 codestr[i] = ROT_TWO;
492 memset(codestr+i+1, NOP, 5);
493 } else if (j == 3) {
494 codestr[i] = ROT_THREE;
495 codestr[i+1] = ROT_TWO;
496 memset(codestr+i+2, NOP, 4);
497 }
498 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000499
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000500 /* Fold binary ops on constants.
501 LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */
502 case BINARY_POWER:
503 case BINARY_MULTIPLY:
504 case BINARY_TRUE_DIVIDE:
505 case BINARY_FLOOR_DIVIDE:
506 case BINARY_MODULO:
507 case BINARY_ADD:
508 case BINARY_SUBTRACT:
509 case BINARY_SUBSCR:
510 case BINARY_LSHIFT:
511 case BINARY_RSHIFT:
512 case BINARY_AND:
513 case BINARY_XOR:
514 case BINARY_OR:
515 if (lastlc >= 2 &&
516 ISBASICBLOCK(blocks, i-6, 7) &&
517 fold_binops_on_constants(&codestr[i-6], consts)) {
518 i -= 2;
519 assert(codestr[i] == LOAD_CONST);
520 cumlc = 1;
521 }
522 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000524 /* Fold unary ops on constants.
525 LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */
526 case UNARY_NEGATIVE:
527 case UNARY_INVERT:
528 case UNARY_POSITIVE:
529 if (lastlc >= 1 &&
530 ISBASICBLOCK(blocks, i-3, 4) &&
531 fold_unaryops_on_constants(&codestr[i-3], consts)) {
532 i -= 2;
533 assert(codestr[i] == LOAD_CONST);
534 cumlc = 1;
535 }
536 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000537
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000538 /* Simplify conditional jump to conditional jump where the
539 result of the first test implies the success of a similar
540 test or the failure of the opposite test.
541 Arises in code like:
542 "if a and b:"
543 "if a or b:"
544 "a and b or c"
545 "(a and b) and c"
546 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z
547 --> x:JUMP_IF_FALSE_OR_POP z
548 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z
549 --> x:POP_JUMP_IF_FALSE y+3
550 where y+3 is the instruction following the second test.
551 */
552 case JUMP_IF_FALSE_OR_POP:
553 case JUMP_IF_TRUE_OR_POP:
554 tgt = GETJUMPTGT(codestr, i);
555 j = codestr[tgt];
556 if (CONDITIONAL_JUMP(j)) {
557 /* NOTE: all possible jumps here are
558 absolute! */
559 if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) {
560 /* The second jump will be
561 taken iff the first is. */
562 tgttgt = GETJUMPTGT(codestr, tgt);
563 /* The current opcode inherits
564 its target's stack behaviour */
565 codestr[i] = j;
566 SETARG(codestr, i, tgttgt);
567 goto reoptimize_current;
568 } else {
569 /* The second jump is not taken
570 if the first is (so jump past
571 it), and all conditional
572 jumps pop their argument when
573 they're not taken (so change
574 the first jump to pop its
575 argument when it's taken). */
576 if (JUMPS_ON_TRUE(opcode))
577 codestr[i] = POP_JUMP_IF_TRUE;
578 else
579 codestr[i] = POP_JUMP_IF_FALSE;
580 SETARG(codestr, i, (tgt + 3));
581 goto reoptimize_current;
582 }
583 }
584 /* Intentional fallthrough */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000585
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000586 /* Replace jumps to unconditional jumps */
587 case POP_JUMP_IF_FALSE:
588 case POP_JUMP_IF_TRUE:
589 case FOR_ITER:
590 case JUMP_FORWARD:
591 case JUMP_ABSOLUTE:
592 case CONTINUE_LOOP:
593 case SETUP_LOOP:
594 case SETUP_EXCEPT:
595 case SETUP_FINALLY:
596 case SETUP_WITH:
597 tgt = GETJUMPTGT(codestr, i);
598 /* Replace JUMP_* to a RETURN into just a RETURN */
599 if (UNCONDITIONAL_JUMP(opcode) &&
600 codestr[tgt] == RETURN_VALUE) {
601 codestr[i] = RETURN_VALUE;
602 memset(codestr+i+1, NOP, 2);
603 continue;
604 }
605 if (!UNCONDITIONAL_JUMP(codestr[tgt]))
606 continue;
607 tgttgt = GETJUMPTGT(codestr, tgt);
608 if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */
609 opcode = JUMP_ABSOLUTE;
610 if (!ABSOLUTE_JUMP(opcode))
611 tgttgt -= i + 3; /* Calc relative jump addr */
612 if (tgttgt < 0) /* No backward relative jumps */
613 continue;
614 codestr[i] = opcode;
615 SETARG(codestr, i, tgttgt);
616 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000617
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000618 case EXTENDED_ARG:
619 if (codestr[i+3] != MAKE_FUNCTION)
620 goto exitUnchanged;
621 /* don't visit MAKE_FUNCTION as GETARG will be wrong */
622 i += 3;
623 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000624
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000625 /* Replace RETURN LOAD_CONST None RETURN with just RETURN */
626 /* Remove unreachable JUMPs after RETURN */
627 case RETURN_VALUE:
628 if (i+4 >= codelen)
629 continue;
630 if (codestr[i+4] == RETURN_VALUE &&
631 ISBASICBLOCK(blocks,i,5))
632 memset(codestr+i+1, NOP, 4);
633 else if (UNCONDITIONAL_JUMP(codestr[i+1]) &&
634 ISBASICBLOCK(blocks,i,4))
635 memset(codestr+i+1, NOP, 3);
636 break;
637 }
638 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000639
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000640 /* Fixup linenotab */
641 for (i=0, nops=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
642 addrmap[i] = i - nops;
643 if (codestr[i] == NOP)
644 nops++;
645 }
646 cum_orig_line = 0;
647 last_line = 0;
648 for (i=0 ; i < tabsiz ; i+=2) {
649 cum_orig_line += lineno[i];
650 new_line = addrmap[cum_orig_line];
651 assert (new_line - last_line < 255);
652 lineno[i] =((unsigned char)(new_line - last_line));
653 last_line = new_line;
654 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000655
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000656 /* Remove NOPs and fixup jump targets */
657 for (i=0, h=0 ; i<codelen ; ) {
658 opcode = codestr[i];
659 switch (opcode) {
660 case NOP:
661 i++;
662 continue;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000663
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000664 case JUMP_ABSOLUTE:
665 case CONTINUE_LOOP:
666 case POP_JUMP_IF_FALSE:
667 case POP_JUMP_IF_TRUE:
668 case JUMP_IF_FALSE_OR_POP:
669 case JUMP_IF_TRUE_OR_POP:
670 j = addrmap[GETARG(codestr, i)];
671 SETARG(codestr, i, j);
672 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000674 case FOR_ITER:
675 case JUMP_FORWARD:
676 case SETUP_LOOP:
677 case SETUP_EXCEPT:
678 case SETUP_FINALLY:
679 case SETUP_WITH:
680 j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3;
681 SETARG(codestr, i, j);
682 break;
683 }
684 adj = CODESIZE(opcode);
685 while (adj--)
686 codestr[h++] = codestr[i++];
687 }
688 assert(h + nops == codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000689
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000690 code = PyBytes_FromStringAndSize((char *)codestr, h);
691 PyMem_Free(addrmap);
692 PyMem_Free(codestr);
693 PyMem_Free(blocks);
694 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000695
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000696 exitError:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000697 code = NULL;
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000698
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000699 exitUnchanged:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000700 if (blocks != NULL)
701 PyMem_Free(blocks);
702 if (addrmap != NULL)
703 PyMem_Free(addrmap);
704 if (codestr != NULL)
705 PyMem_Free(codestr);
706 Py_XINCREF(code);
707 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000708}