blob: 9d06963e2cf322c8c774feb7a42d5924e6b5119d [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) {
Raymond Hettinger819a0642010-08-22 08:39:49 +0000162 if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
163 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000164 return 0;
165 }
166 size = PyObject_Size(newconst);
Raymond Hettinger819a0642010-08-22 08:39:49 +0000167 if (size == -1) {
168 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
169 return 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000170 PyErr_Clear();
Raymond Hettinger819a0642010-08-22 08:39:49 +0000171 } else if (size > 20) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000172 Py_DECREF(newconst);
173 return 0;
174 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000175
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000176 /* Append folded constant into consts table */
177 len_consts = PyList_GET_SIZE(consts);
178 if (PyList_Append(consts, newconst)) {
179 Py_DECREF(newconst);
180 return 0;
181 }
182 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000183
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000184 /* Write NOP NOP NOP NOP LOAD_CONST newconst */
185 memset(codestr, NOP, 4);
186 codestr[4] = LOAD_CONST;
187 SETARG(codestr, 4, len_consts);
188 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000189}
190
191static int
192fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts)
193{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000194 PyObject *newconst=NULL, *v;
195 Py_ssize_t len_consts;
196 int opcode;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000197
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000198 /* Pre-conditions */
199 assert(PyList_CheckExact(consts));
200 assert(codestr[0] == LOAD_CONST);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000201
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000202 /* Create new constant */
203 v = PyList_GET_ITEM(consts, GETARG(codestr, 0));
204 opcode = codestr[3];
205 switch (opcode) {
206 case UNARY_NEGATIVE:
207 /* Preserve the sign of -0.0 */
208 if (PyObject_IsTrue(v) == 1)
209 newconst = PyNumber_Negative(v);
210 break;
211 case UNARY_INVERT:
212 newconst = PyNumber_Invert(v);
213 break;
214 case UNARY_POSITIVE:
215 newconst = PyNumber_Positive(v);
216 break;
217 default:
218 /* Called with an unknown opcode */
219 PyErr_Format(PyExc_SystemError,
220 "unexpected unary operation %d on a constant",
221 opcode);
222 return 0;
223 }
224 if (newconst == NULL) {
Raymond Hettinger819a0642010-08-22 08:39:49 +0000225 if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
226 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000227 return 0;
228 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000229
Antoine Pitrouf95a1b32010-05-09 15:52:27 +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 Pitrouf95a1b32010-05-09 15:52:27 +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 Pitrouf95a1b32010-05-09 15:52:27 +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 Pitrouf95a1b32010-05-09 15:52:27 +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 Pitrouf95a1b32010-05-09 15:52:27 +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 case SETUP_WITH:
273 j = GETJUMPTGT(code, i);
274 blocks[j] = 1;
275 break;
276 }
277 }
278 /* Build block numbers in the second pass */
279 for (i=0 ; i<len ; i++) {
280 blockcnt += blocks[i]; /* increment blockcnt over labels */
281 blocks[i] = blockcnt;
282 }
283 return blocks;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000284}
285
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000286/* Helper to replace LOAD_NAME None/True/False with LOAD_CONST
287 Returns: 0 if no change, 1 if change, -1 if error */
288static int
289load_global(unsigned char *codestr, Py_ssize_t i, char *name, PyObject *consts)
290{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000291 Py_ssize_t j;
292 PyObject *obj;
293 if (name == NULL)
294 return 0;
295 if (strcmp(name, "None") == 0)
296 obj = Py_None;
297 else if (strcmp(name, "True") == 0)
298 obj = Py_True;
299 else if (strcmp(name, "False") == 0)
300 obj = Py_False;
301 else
302 return 0;
303 for (j = 0; j < PyList_GET_SIZE(consts); j++) {
304 if (PyList_GET_ITEM(consts, j) == obj)
305 break;
306 }
307 if (j == PyList_GET_SIZE(consts)) {
308 if (PyList_Append(consts, obj) < 0)
309 return -1;
310 }
311 assert(PyList_GET_ITEM(consts, j) == obj);
312 codestr[i] = LOAD_CONST;
313 SETARG(codestr, i, j);
314 return 1;
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000315}
316
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000317/* Perform basic peephole optimizations to components of a code object.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000318 The consts object should still be in list form to allow new constants
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000319 to be appended.
320
Guido van Rossum0240b922007-02-26 21:23:50 +0000321 To keep the optimizer simple, it bails out (does nothing) for code that
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000322 has a length over 32,700, and does not calculate extended arguments.
Guido van Rossum0240b922007-02-26 21:23:50 +0000323 That allows us to avoid overflow and sign issues. Likewise, it bails when
324 the lineno table has complex encoding for gaps >= 255. EXTENDED_ARG can
325 appear before MAKE_FUNCTION; in this case both opcodes are skipped.
326 EXTENDED_ARG preceding any other opcode causes the optimizer to bail.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000327
328 Optimizations are restricted to simple transformations occuring within a
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000329 single basic block. All transformations keep the code size the same or
330 smaller. For those that reduce size, the gaps are initially filled with
331 NOPs. Later those NOPs are removed and the jump addresses retargeted in
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000332 a single pass. Line numbering is adjusted accordingly. */
333
334PyObject *
335PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
336 PyObject *lineno_obj)
337{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000338 Py_ssize_t i, j, codelen;
339 int nops, h, adj;
340 int tgt, tgttgt, opcode;
341 unsigned char *codestr = NULL;
342 unsigned char *lineno;
343 int *addrmap = NULL;
344 int new_line, cum_orig_line, last_line, tabsiz;
345 int cumlc=0, lastlc=0; /* Count runs of consecutive LOAD_CONSTs */
346 unsigned int *blocks = NULL;
347 char *name;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000348
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000349 /* Bail out if an exception is set */
350 if (PyErr_Occurred())
351 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000352
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000353 /* Bypass optimization when the lineno table is too complex */
354 assert(PyBytes_Check(lineno_obj));
355 lineno = (unsigned char*)PyBytes_AS_STRING(lineno_obj);
356 tabsiz = PyBytes_GET_SIZE(lineno_obj);
357 if (memchr(lineno, 255, tabsiz) != NULL)
358 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000359
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000360 /* Avoid situations where jump retargeting could overflow */
361 assert(PyBytes_Check(code));
362 codelen = PyBytes_GET_SIZE(code);
363 if (codelen > 32700)
364 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000365
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000366 /* Make a modifiable copy of the code string */
367 codestr = (unsigned char *)PyMem_Malloc(codelen);
368 if (codestr == NULL)
369 goto exitError;
370 codestr = (unsigned char *)memcpy(codestr,
371 PyBytes_AS_STRING(code), codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000372
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000373 /* Verify that RETURN_VALUE terminates the codestring. This allows
374 the various transformation patterns to look ahead several
375 instructions without additional checks to make sure they are not
376 looking beyond the end of the code string.
377 */
378 if (codestr[codelen-1] != RETURN_VALUE)
379 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000380
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000381 /* Mapping to new jump targets after NOPs are removed */
382 addrmap = (int *)PyMem_Malloc(codelen * sizeof(int));
383 if (addrmap == NULL)
384 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000385
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000386 blocks = markblocks(codestr, codelen);
387 if (blocks == NULL)
388 goto exitError;
389 assert(PyList_Check(consts));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000390
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000391 for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
392 reoptimize_current:
393 opcode = codestr[i];
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000394
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000395 lastlc = cumlc;
396 cumlc = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000397
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000398 switch (opcode) {
399 /* Replace UNARY_NOT POP_JUMP_IF_FALSE
400 with POP_JUMP_IF_TRUE */
401 case UNARY_NOT:
402 if (codestr[i+1] != POP_JUMP_IF_FALSE
403 || !ISBASICBLOCK(blocks,i,4))
404 continue;
405 j = GETARG(codestr, i+1);
406 codestr[i] = POP_JUMP_IF_TRUE;
407 SETARG(codestr, i, j);
408 codestr[i+3] = NOP;
409 goto reoptimize_current;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000410
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000411 /* not a is b --> a is not b
412 not a in b --> a not in b
413 not a is not b --> a is b
414 not a not in b --> a in b
415 */
416 case COMPARE_OP:
417 j = GETARG(codestr, i);
418 if (j < 6 || j > 9 ||
419 codestr[i+3] != UNARY_NOT ||
420 !ISBASICBLOCK(blocks,i,4))
421 continue;
422 SETARG(codestr, i, (j^1));
423 codestr[i+3] = NOP;
424 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000425
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000426 /* Replace LOAD_GLOBAL/LOAD_NAME None/True/False
427 with LOAD_CONST None/True/False */
428 case LOAD_NAME:
429 case LOAD_GLOBAL:
430 j = GETARG(codestr, i);
431 name = _PyUnicode_AsString(PyTuple_GET_ITEM(names, j));
432 h = load_global(codestr, i, name, consts);
433 if (h < 0)
434 goto exitError;
435 else if (h == 0)
436 continue;
437 cumlc = lastlc + 1;
438 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000439
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000440 /* Skip over LOAD_CONST trueconst
441 POP_JUMP_IF_FALSE xx. This improves
442 "while 1" performance. */
443 case LOAD_CONST:
444 cumlc = lastlc + 1;
445 j = GETARG(codestr, i);
446 if (codestr[i+3] != POP_JUMP_IF_FALSE ||
447 !ISBASICBLOCK(blocks,i,6) ||
448 !PyObject_IsTrue(PyList_GET_ITEM(consts, j)))
449 continue;
450 memset(codestr+i, NOP, 6);
451 cumlc = 0;
452 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000453
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000454 /* Try to fold tuples of constants (includes a case for lists and sets
455 which are only used for "in" and "not in" tests).
456 Skip over BUILD_SEQN 1 UNPACK_SEQN 1.
457 Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2.
458 Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */
459 case BUILD_TUPLE:
460 case BUILD_LIST:
461 case BUILD_SET:
462 j = GETARG(codestr, i);
463 h = i - 3 * j;
464 if (h >= 0 &&
465 j <= lastlc &&
466 ((opcode == BUILD_TUPLE &&
467 ISBASICBLOCK(blocks, h, 3*(j+1))) ||
468 ((opcode == BUILD_LIST || opcode == BUILD_SET) &&
469 codestr[i+3]==COMPARE_OP &&
470 ISBASICBLOCK(blocks, h, 3*(j+2)) &&
471 (GETARG(codestr,i+3)==6 ||
472 GETARG(codestr,i+3)==7))) &&
473 tuple_of_constants(&codestr[h], j, consts)) {
474 assert(codestr[i] == LOAD_CONST);
475 cumlc = 1;
476 break;
477 }
478 if (codestr[i+3] != UNPACK_SEQUENCE ||
479 !ISBASICBLOCK(blocks,i,6) ||
480 j != GETARG(codestr, i+3))
481 continue;
482 if (j == 1) {
483 memset(codestr+i, NOP, 6);
484 } else if (j == 2) {
485 codestr[i] = ROT_TWO;
486 memset(codestr+i+1, NOP, 5);
487 } else if (j == 3) {
488 codestr[i] = ROT_THREE;
489 codestr[i+1] = ROT_TWO;
490 memset(codestr+i+2, NOP, 4);
491 }
492 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000493
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000494 /* Fold binary ops on constants.
495 LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */
496 case BINARY_POWER:
497 case BINARY_MULTIPLY:
498 case BINARY_TRUE_DIVIDE:
499 case BINARY_FLOOR_DIVIDE:
500 case BINARY_MODULO:
501 case BINARY_ADD:
502 case BINARY_SUBTRACT:
503 case BINARY_SUBSCR:
504 case BINARY_LSHIFT:
505 case BINARY_RSHIFT:
506 case BINARY_AND:
507 case BINARY_XOR:
508 case BINARY_OR:
509 if (lastlc >= 2 &&
510 ISBASICBLOCK(blocks, i-6, 7) &&
511 fold_binops_on_constants(&codestr[i-6], consts)) {
512 i -= 2;
513 assert(codestr[i] == LOAD_CONST);
514 cumlc = 1;
515 }
516 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000517
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000518 /* Fold unary ops on constants.
519 LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */
520 case UNARY_NEGATIVE:
521 case UNARY_INVERT:
522 case UNARY_POSITIVE:
523 if (lastlc >= 1 &&
524 ISBASICBLOCK(blocks, i-3, 4) &&
525 fold_unaryops_on_constants(&codestr[i-3], consts)) {
526 i -= 2;
527 assert(codestr[i] == LOAD_CONST);
528 cumlc = 1;
529 }
530 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000531
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000532 /* Simplify conditional jump to conditional jump where the
533 result of the first test implies the success of a similar
534 test or the failure of the opposite test.
535 Arises in code like:
536 "if a and b:"
537 "if a or b:"
538 "a and b or c"
539 "(a and b) and c"
540 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z
541 --> x:JUMP_IF_FALSE_OR_POP z
542 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z
543 --> x:POP_JUMP_IF_FALSE y+3
544 where y+3 is the instruction following the second test.
545 */
546 case JUMP_IF_FALSE_OR_POP:
547 case JUMP_IF_TRUE_OR_POP:
548 tgt = GETJUMPTGT(codestr, i);
549 j = codestr[tgt];
550 if (CONDITIONAL_JUMP(j)) {
551 /* NOTE: all possible jumps here are
552 absolute! */
553 if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) {
554 /* The second jump will be
555 taken iff the first is. */
556 tgttgt = GETJUMPTGT(codestr, tgt);
557 /* The current opcode inherits
558 its target's stack behaviour */
559 codestr[i] = j;
560 SETARG(codestr, i, tgttgt);
561 goto reoptimize_current;
562 } else {
563 /* The second jump is not taken
564 if the first is (so jump past
565 it), and all conditional
566 jumps pop their argument when
567 they're not taken (so change
568 the first jump to pop its
569 argument when it's taken). */
570 if (JUMPS_ON_TRUE(opcode))
571 codestr[i] = POP_JUMP_IF_TRUE;
572 else
573 codestr[i] = POP_JUMP_IF_FALSE;
574 SETARG(codestr, i, (tgt + 3));
575 goto reoptimize_current;
576 }
577 }
578 /* Intentional fallthrough */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000579
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000580 /* Replace jumps to unconditional jumps */
581 case POP_JUMP_IF_FALSE:
582 case POP_JUMP_IF_TRUE:
583 case FOR_ITER:
584 case JUMP_FORWARD:
585 case JUMP_ABSOLUTE:
586 case CONTINUE_LOOP:
587 case SETUP_LOOP:
588 case SETUP_EXCEPT:
589 case SETUP_FINALLY:
590 case SETUP_WITH:
591 tgt = GETJUMPTGT(codestr, i);
592 /* Replace JUMP_* to a RETURN into just a RETURN */
593 if (UNCONDITIONAL_JUMP(opcode) &&
594 codestr[tgt] == RETURN_VALUE) {
595 codestr[i] = RETURN_VALUE;
596 memset(codestr+i+1, NOP, 2);
597 continue;
598 }
599 if (!UNCONDITIONAL_JUMP(codestr[tgt]))
600 continue;
601 tgttgt = GETJUMPTGT(codestr, tgt);
602 if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */
603 opcode = JUMP_ABSOLUTE;
604 if (!ABSOLUTE_JUMP(opcode))
605 tgttgt -= i + 3; /* Calc relative jump addr */
606 if (tgttgt < 0) /* No backward relative jumps */
607 continue;
608 codestr[i] = opcode;
609 SETARG(codestr, i, tgttgt);
610 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000611
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000612 case EXTENDED_ARG:
613 if (codestr[i+3] != MAKE_FUNCTION)
614 goto exitUnchanged;
615 /* don't visit MAKE_FUNCTION as GETARG will be wrong */
616 i += 3;
617 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000618
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000619 /* Replace RETURN LOAD_CONST None RETURN with just RETURN */
620 /* Remove unreachable JUMPs after RETURN */
621 case RETURN_VALUE:
622 if (i+4 >= codelen)
623 continue;
624 if (codestr[i+4] == RETURN_VALUE &&
625 ISBASICBLOCK(blocks,i,5))
626 memset(codestr+i+1, NOP, 4);
627 else if (UNCONDITIONAL_JUMP(codestr[i+1]) &&
628 ISBASICBLOCK(blocks,i,4))
629 memset(codestr+i+1, NOP, 3);
630 break;
631 }
632 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000633
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000634 /* Fixup linenotab */
635 for (i=0, nops=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
636 addrmap[i] = i - nops;
637 if (codestr[i] == NOP)
638 nops++;
639 }
640 cum_orig_line = 0;
641 last_line = 0;
642 for (i=0 ; i < tabsiz ; i+=2) {
643 cum_orig_line += lineno[i];
644 new_line = addrmap[cum_orig_line];
645 assert (new_line - last_line < 255);
646 lineno[i] =((unsigned char)(new_line - last_line));
647 last_line = new_line;
648 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000649
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000650 /* Remove NOPs and fixup jump targets */
651 for (i=0, h=0 ; i<codelen ; ) {
652 opcode = codestr[i];
653 switch (opcode) {
654 case NOP:
655 i++;
656 continue;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000657
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000658 case JUMP_ABSOLUTE:
659 case CONTINUE_LOOP:
660 case POP_JUMP_IF_FALSE:
661 case POP_JUMP_IF_TRUE:
662 case JUMP_IF_FALSE_OR_POP:
663 case JUMP_IF_TRUE_OR_POP:
664 j = addrmap[GETARG(codestr, i)];
665 SETARG(codestr, i, j);
666 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000667
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000668 case FOR_ITER:
669 case JUMP_FORWARD:
670 case SETUP_LOOP:
671 case SETUP_EXCEPT:
672 case SETUP_FINALLY:
673 case SETUP_WITH:
674 j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3;
675 SETARG(codestr, i, j);
676 break;
677 }
678 adj = CODESIZE(opcode);
679 while (adj--)
680 codestr[h++] = codestr[i++];
681 }
682 assert(h + nops == codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000683
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000684 code = PyBytes_FromStringAndSize((char *)codestr, h);
685 PyMem_Free(addrmap);
686 PyMem_Free(codestr);
687 PyMem_Free(blocks);
688 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000689
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000690 exitError:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000691 code = NULL;
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000692
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000693 exitUnchanged:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000694 if (blocks != NULL)
695 PyMem_Free(blocks);
696 if (addrmap != NULL)
697 PyMem_Free(addrmap);
698 if (codestr != NULL)
699 PyMem_Free(codestr);
700 Py_XINCREF(code);
701 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000702}