blob: f972e1611e662969a485654268e1ecd14ebcb163 [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:
135 newconst = PyObject_GetItem(v, w);
136 break;
137 case BINARY_LSHIFT:
138 newconst = PyNumber_Lshift(v, w);
139 break;
140 case BINARY_RSHIFT:
141 newconst = PyNumber_Rshift(v, w);
142 break;
143 case BINARY_AND:
144 newconst = PyNumber_And(v, w);
145 break;
146 case BINARY_XOR:
147 newconst = PyNumber_Xor(v, w);
148 break;
149 case BINARY_OR:
150 newconst = PyNumber_Or(v, w);
151 break;
152 default:
153 /* Called with an unknown opcode */
154 PyErr_Format(PyExc_SystemError,
155 "unexpected binary operation %d on a constant",
156 opcode);
157 return 0;
158 }
159 if (newconst == NULL) {
Raymond Hettinger819a0642010-08-22 08:39:49 +0000160 if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
161 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000162 return 0;
163 }
164 size = PyObject_Size(newconst);
Raymond Hettinger819a0642010-08-22 08:39:49 +0000165 if (size == -1) {
166 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
167 return 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000168 PyErr_Clear();
Raymond Hettinger819a0642010-08-22 08:39:49 +0000169 } else if (size > 20) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000170 Py_DECREF(newconst);
171 return 0;
172 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000173
Antoine Pitrouf95a1b32010-05-09 15:52:27 +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);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000181
Antoine Pitrouf95a1b32010-05-09 15:52:27 +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;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000187}
188
189static int
190fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts)
191{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000192 PyObject *newconst=NULL, *v;
193 Py_ssize_t len_consts;
194 int opcode;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000195
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000196 /* Pre-conditions */
197 assert(PyList_CheckExact(consts));
198 assert(codestr[0] == LOAD_CONST);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000199
Antoine Pitrouf95a1b32010-05-09 15:52:27 +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_INVERT:
210 newconst = PyNumber_Invert(v);
211 break;
212 case UNARY_POSITIVE:
213 newconst = PyNumber_Positive(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) {
Raymond Hettinger819a0642010-08-22 08:39:49 +0000223 if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
224 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000225 return 0;
226 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000227
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000228 /* Append folded constant into consts table */
229 len_consts = PyList_GET_SIZE(consts);
230 if (PyList_Append(consts, newconst)) {
231 Py_DECREF(newconst);
232 return 0;
233 }
234 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000235
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000236 /* Write NOP LOAD_CONST newconst */
237 codestr[0] = NOP;
238 codestr[1] = LOAD_CONST;
239 SETARG(codestr, 1, len_consts);
240 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000241}
242
243static unsigned int *
Christian Heimescc47b052008-03-25 14:56:36 +0000244markblocks(unsigned char *code, Py_ssize_t len)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000245{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000246 unsigned int *blocks = (unsigned int *)PyMem_Malloc(len*sizeof(int));
247 int i,j, opcode, blockcnt = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000248
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000249 if (blocks == NULL) {
250 PyErr_NoMemory();
251 return NULL;
252 }
253 memset(blocks, 0, len*sizeof(int));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000254
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000255 /* Mark labels in the first pass */
256 for (i=0 ; i<len ; i+=CODESIZE(opcode)) {
257 opcode = code[i];
258 switch (opcode) {
259 case FOR_ITER:
260 case JUMP_FORWARD:
261 case JUMP_IF_FALSE_OR_POP:
262 case JUMP_IF_TRUE_OR_POP:
263 case POP_JUMP_IF_FALSE:
264 case POP_JUMP_IF_TRUE:
265 case JUMP_ABSOLUTE:
266 case CONTINUE_LOOP:
267 case SETUP_LOOP:
268 case SETUP_EXCEPT:
269 case SETUP_FINALLY:
270 case SETUP_WITH:
271 j = GETJUMPTGT(code, i);
272 blocks[j] = 1;
273 break;
274 }
275 }
276 /* Build block numbers in the second pass */
277 for (i=0 ; i<len ; i++) {
278 blockcnt += blocks[i]; /* increment blockcnt over labels */
279 blocks[i] = blockcnt;
280 }
281 return blocks;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000282}
283
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000284/* Helper to replace LOAD_NAME None/True/False with LOAD_CONST
285 Returns: 0 if no change, 1 if change, -1 if error */
286static int
287load_global(unsigned char *codestr, Py_ssize_t i, char *name, PyObject *consts)
288{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000289 Py_ssize_t j;
290 PyObject *obj;
291 if (name == NULL)
292 return 0;
293 if (strcmp(name, "None") == 0)
294 obj = Py_None;
295 else if (strcmp(name, "True") == 0)
296 obj = Py_True;
297 else if (strcmp(name, "False") == 0)
298 obj = Py_False;
299 else
300 return 0;
301 for (j = 0; j < PyList_GET_SIZE(consts); j++) {
302 if (PyList_GET_ITEM(consts, j) == obj)
303 break;
304 }
305 if (j == PyList_GET_SIZE(consts)) {
306 if (PyList_Append(consts, obj) < 0)
307 return -1;
308 }
309 assert(PyList_GET_ITEM(consts, j) == obj);
310 codestr[i] = LOAD_CONST;
311 SETARG(codestr, i, j);
312 return 1;
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000313}
314
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000315/* Perform basic peephole optimizations to components of a code object.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000316 The consts object should still be in list form to allow new constants
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000317 to be appended.
318
Guido van Rossum0240b922007-02-26 21:23:50 +0000319 To keep the optimizer simple, it bails out (does nothing) for code that
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000320 has a length over 32,700, and does not calculate extended arguments.
Guido van Rossum0240b922007-02-26 21:23:50 +0000321 That allows us to avoid overflow and sign issues. Likewise, it bails when
322 the lineno table has complex encoding for gaps >= 255. EXTENDED_ARG can
323 appear before MAKE_FUNCTION; in this case both opcodes are skipped.
324 EXTENDED_ARG preceding any other opcode causes the optimizer to bail.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000325
326 Optimizations are restricted to simple transformations occuring within a
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000327 single basic block. All transformations keep the code size the same or
328 smaller. For those that reduce size, the gaps are initially filled with
329 NOPs. Later those NOPs are removed and the jump addresses retargeted in
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000330 a single pass. Line numbering is adjusted accordingly. */
331
332PyObject *
333PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
334 PyObject *lineno_obj)
335{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000336 Py_ssize_t i, j, codelen;
337 int nops, h, adj;
338 int tgt, tgttgt, opcode;
339 unsigned char *codestr = NULL;
340 unsigned char *lineno;
341 int *addrmap = NULL;
342 int new_line, cum_orig_line, last_line, tabsiz;
343 int cumlc=0, lastlc=0; /* Count runs of consecutive LOAD_CONSTs */
344 unsigned int *blocks = NULL;
345 char *name;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000346
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000347 /* Bail out if an exception is set */
348 if (PyErr_Occurred())
349 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000350
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000351 /* Bypass optimization when the lineno table is too complex */
352 assert(PyBytes_Check(lineno_obj));
353 lineno = (unsigned char*)PyBytes_AS_STRING(lineno_obj);
354 tabsiz = PyBytes_GET_SIZE(lineno_obj);
355 if (memchr(lineno, 255, tabsiz) != NULL)
356 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000357
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000358 /* Avoid situations where jump retargeting could overflow */
359 assert(PyBytes_Check(code));
360 codelen = PyBytes_GET_SIZE(code);
361 if (codelen > 32700)
362 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000363
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000364 /* Make a modifiable copy of the code string */
365 codestr = (unsigned char *)PyMem_Malloc(codelen);
366 if (codestr == NULL)
367 goto exitError;
368 codestr = (unsigned char *)memcpy(codestr,
369 PyBytes_AS_STRING(code), codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000370
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000371 /* Verify that RETURN_VALUE terminates the codestring. This allows
372 the various transformation patterns to look ahead several
373 instructions without additional checks to make sure they are not
374 looking beyond the end of the code string.
375 */
376 if (codestr[codelen-1] != RETURN_VALUE)
377 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000378
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000379 /* Mapping to new jump targets after NOPs are removed */
380 addrmap = (int *)PyMem_Malloc(codelen * sizeof(int));
381 if (addrmap == NULL)
382 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000383
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000384 blocks = markblocks(codestr, codelen);
385 if (blocks == NULL)
386 goto exitError;
387 assert(PyList_Check(consts));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000388
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000389 for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
390 reoptimize_current:
391 opcode = codestr[i];
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000392
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000393 lastlc = cumlc;
394 cumlc = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000395
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000396 switch (opcode) {
397 /* Replace UNARY_NOT POP_JUMP_IF_FALSE
398 with POP_JUMP_IF_TRUE */
399 case UNARY_NOT:
400 if (codestr[i+1] != POP_JUMP_IF_FALSE
401 || !ISBASICBLOCK(blocks,i,4))
402 continue;
403 j = GETARG(codestr, i+1);
404 codestr[i] = POP_JUMP_IF_TRUE;
405 SETARG(codestr, i, j);
406 codestr[i+3] = NOP;
407 goto reoptimize_current;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000408
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000409 /* not a is b --> a is not b
410 not a in b --> a not in b
411 not a is not b --> a is b
412 not a not in b --> a in b
413 */
414 case COMPARE_OP:
415 j = GETARG(codestr, i);
416 if (j < 6 || j > 9 ||
417 codestr[i+3] != UNARY_NOT ||
418 !ISBASICBLOCK(blocks,i,4))
419 continue;
420 SETARG(codestr, i, (j^1));
421 codestr[i+3] = NOP;
422 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000423
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000424 /* Replace LOAD_GLOBAL/LOAD_NAME None/True/False
425 with LOAD_CONST None/True/False */
426 case LOAD_NAME:
427 case LOAD_GLOBAL:
428 j = GETARG(codestr, i);
429 name = _PyUnicode_AsString(PyTuple_GET_ITEM(names, j));
430 h = load_global(codestr, i, name, consts);
431 if (h < 0)
432 goto exitError;
433 else if (h == 0)
434 continue;
435 cumlc = lastlc + 1;
436 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000437
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000438 /* Skip over LOAD_CONST trueconst
439 POP_JUMP_IF_FALSE xx. This improves
440 "while 1" performance. */
441 case LOAD_CONST:
442 cumlc = lastlc + 1;
443 j = GETARG(codestr, i);
444 if (codestr[i+3] != POP_JUMP_IF_FALSE ||
445 !ISBASICBLOCK(blocks,i,6) ||
446 !PyObject_IsTrue(PyList_GET_ITEM(consts, j)))
447 continue;
448 memset(codestr+i, NOP, 6);
449 cumlc = 0;
450 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000451
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000452 /* Try to fold tuples of constants (includes a case for lists and sets
453 which are only used for "in" and "not in" tests).
454 Skip over BUILD_SEQN 1 UNPACK_SEQN 1.
455 Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2.
456 Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */
457 case BUILD_TUPLE:
458 case BUILD_LIST:
459 case BUILD_SET:
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 || opcode == BUILD_SET) &&
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 Pitrouf95a1b32010-05-09 15:52:27 +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 Pitrouf95a1b32010-05-09 15:52:27 +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 case UNARY_POSITIVE:
521 if (lastlc >= 1 &&
522 ISBASICBLOCK(blocks, i-3, 4) &&
523 fold_unaryops_on_constants(&codestr[i-3], consts)) {
524 i -= 2;
525 assert(codestr[i] == LOAD_CONST);
526 cumlc = 1;
527 }
528 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000529
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000530 /* Simplify conditional jump to conditional jump where the
531 result of the first test implies the success of a similar
532 test or the failure of the opposite test.
533 Arises in code like:
534 "if a and b:"
535 "if a or b:"
536 "a and b or c"
537 "(a and b) and c"
538 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z
539 --> x:JUMP_IF_FALSE_OR_POP z
540 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z
541 --> x:POP_JUMP_IF_FALSE y+3
542 where y+3 is the instruction following the second test.
543 */
544 case JUMP_IF_FALSE_OR_POP:
545 case JUMP_IF_TRUE_OR_POP:
546 tgt = GETJUMPTGT(codestr, i);
547 j = codestr[tgt];
548 if (CONDITIONAL_JUMP(j)) {
549 /* NOTE: all possible jumps here are
550 absolute! */
551 if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) {
552 /* The second jump will be
553 taken iff the first is. */
554 tgttgt = GETJUMPTGT(codestr, tgt);
555 /* The current opcode inherits
556 its target's stack behaviour */
557 codestr[i] = j;
558 SETARG(codestr, i, tgttgt);
559 goto reoptimize_current;
560 } else {
561 /* The second jump is not taken
562 if the first is (so jump past
563 it), and all conditional
564 jumps pop their argument when
565 they're not taken (so change
566 the first jump to pop its
567 argument when it's taken). */
568 if (JUMPS_ON_TRUE(opcode))
569 codestr[i] = POP_JUMP_IF_TRUE;
570 else
571 codestr[i] = POP_JUMP_IF_FALSE;
572 SETARG(codestr, i, (tgt + 3));
573 goto reoptimize_current;
574 }
575 }
576 /* Intentional fallthrough */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000577
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000578 /* Replace jumps to unconditional jumps */
579 case POP_JUMP_IF_FALSE:
580 case POP_JUMP_IF_TRUE:
581 case FOR_ITER:
582 case JUMP_FORWARD:
583 case JUMP_ABSOLUTE:
584 case CONTINUE_LOOP:
585 case SETUP_LOOP:
586 case SETUP_EXCEPT:
587 case SETUP_FINALLY:
588 case SETUP_WITH:
589 tgt = GETJUMPTGT(codestr, i);
590 /* Replace JUMP_* to a RETURN into just a RETURN */
591 if (UNCONDITIONAL_JUMP(opcode) &&
592 codestr[tgt] == RETURN_VALUE) {
593 codestr[i] = RETURN_VALUE;
594 memset(codestr+i+1, NOP, 2);
595 continue;
596 }
597 if (!UNCONDITIONAL_JUMP(codestr[tgt]))
598 continue;
599 tgttgt = GETJUMPTGT(codestr, tgt);
600 if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */
601 opcode = JUMP_ABSOLUTE;
602 if (!ABSOLUTE_JUMP(opcode))
603 tgttgt -= i + 3; /* Calc relative jump addr */
604 if (tgttgt < 0) /* No backward relative jumps */
605 continue;
606 codestr[i] = opcode;
607 SETARG(codestr, i, tgttgt);
608 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000609
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000610 case EXTENDED_ARG:
611 if (codestr[i+3] != MAKE_FUNCTION)
612 goto exitUnchanged;
613 /* don't visit MAKE_FUNCTION as GETARG will be wrong */
614 i += 3;
615 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000616
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000617 /* Replace RETURN LOAD_CONST None RETURN with just RETURN */
618 /* Remove unreachable JUMPs after RETURN */
619 case RETURN_VALUE:
620 if (i+4 >= codelen)
621 continue;
622 if (codestr[i+4] == RETURN_VALUE &&
623 ISBASICBLOCK(blocks,i,5))
624 memset(codestr+i+1, NOP, 4);
625 else if (UNCONDITIONAL_JUMP(codestr[i+1]) &&
626 ISBASICBLOCK(blocks,i,4))
627 memset(codestr+i+1, NOP, 3);
628 break;
629 }
630 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000631
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000632 /* Fixup linenotab */
633 for (i=0, nops=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
634 addrmap[i] = i - nops;
635 if (codestr[i] == NOP)
636 nops++;
637 }
638 cum_orig_line = 0;
639 last_line = 0;
640 for (i=0 ; i < tabsiz ; i+=2) {
641 cum_orig_line += lineno[i];
642 new_line = addrmap[cum_orig_line];
643 assert (new_line - last_line < 255);
644 lineno[i] =((unsigned char)(new_line - last_line));
645 last_line = new_line;
646 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000647
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000648 /* Remove NOPs and fixup jump targets */
649 for (i=0, h=0 ; i<codelen ; ) {
650 opcode = codestr[i];
651 switch (opcode) {
652 case NOP:
653 i++;
654 continue;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000655
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000656 case JUMP_ABSOLUTE:
657 case CONTINUE_LOOP:
658 case POP_JUMP_IF_FALSE:
659 case POP_JUMP_IF_TRUE:
660 case JUMP_IF_FALSE_OR_POP:
661 case JUMP_IF_TRUE_OR_POP:
662 j = addrmap[GETARG(codestr, i)];
663 SETARG(codestr, i, j);
664 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000666 case FOR_ITER:
667 case JUMP_FORWARD:
668 case SETUP_LOOP:
669 case SETUP_EXCEPT:
670 case SETUP_FINALLY:
671 case SETUP_WITH:
672 j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3;
673 SETARG(codestr, i, j);
674 break;
675 }
676 adj = CODESIZE(opcode);
677 while (adj--)
678 codestr[h++] = codestr[i++];
679 }
680 assert(h + nops == codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000681
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000682 code = PyBytes_FromStringAndSize((char *)codestr, h);
683 PyMem_Free(addrmap);
684 PyMem_Free(codestr);
685 PyMem_Free(blocks);
686 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000687
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000688 exitError:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000689 code = NULL;
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000690
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000691 exitUnchanged:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000692 if (blocks != NULL)
693 PyMem_Free(blocks);
694 if (addrmap != NULL)
695 PyMem_Free(addrmap);
696 if (codestr != NULL)
697 PyMem_Free(codestr);
698 Py_XINCREF(code);
699 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000700}