blob: 781498ecf25f2ed42acd1024e337b2c1546df24e [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
Antoine Pitrou17b880a2011-03-11 17:27:02 +010026
27#define CONST_STACK_CREATE() { \
28 const_stack_size = 256; \
29 const_stack = PyMem_New(PyObject *, const_stack_size); \
30 load_const_stack = PyMem_New(Py_ssize_t, const_stack_size); \
31 if (!const_stack || !load_const_stack) { \
32 PyErr_NoMemory(); \
33 goto exitError; \
34 } \
35 }
36
37#define CONST_STACK_DELETE() do { \
38 if (const_stack) \
39 PyMem_Free(const_stack); \
40 if (load_const_stack) \
41 PyMem_Free(load_const_stack); \
42 } while(0)
43
44#define CONST_STACK_LEN() (const_stack_top + 1)
45
46#define CONST_STACK_PUSH_OP(i) do { \
47 PyObject *_x; \
48 assert(codestr[i] == LOAD_CONST); \
49 assert(PyList_GET_SIZE(consts) > GETARG(codestr, i)); \
50 _x = PyList_GET_ITEM(consts, GETARG(codestr, i)); \
51 if (++const_stack_top >= const_stack_size) { \
52 const_stack_size *= 2; \
53 PyMem_Resize(const_stack, PyObject *, const_stack_size); \
54 PyMem_Resize(load_const_stack, Py_ssize_t, const_stack_size); \
55 if (!const_stack || !load_const_stack) { \
56 PyErr_NoMemory(); \
57 goto exitError; \
58 } \
59 } \
60 load_const_stack[const_stack_top] = i; \
61 const_stack[const_stack_top] = _x; \
62 in_consts = 1; \
63 } while(0)
64
65#define CONST_STACK_RESET() do { \
66 const_stack_top = -1; \
67 } while(0)
68
69#define CONST_STACK_TOP(x) \
70 const_stack[const_stack_top]
71
72#define CONST_STACK_LASTN(i) \
73 &const_stack[const_stack_top - i + 1]
74
75#define CONST_STACK_POP(i) do { \
76 assert(const_stack_top + 1 >= i); \
77 const_stack_top -= i; \
78 } while(0)
79
80#define CONST_STACK_OP_LASTN(i) \
81 ((const_stack_top >= i - 1) ? load_const_stack[const_stack_top - i + 1] : -1)
82
83
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000084/* Replace LOAD_CONST c1. LOAD_CONST c2 ... LOAD_CONST cn BUILD_TUPLE n
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000085 with LOAD_CONST (c1, c2, ... cn).
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000086 The consts table must still be in list form so that the
87 new constant (c1, c2, ... cn) can be appended.
88 Called with codestr pointing to the first LOAD_CONST.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000089 Bails out with no change if one or more of the LOAD_CONSTs is missing.
Antoine Pitroub7fbcd32010-01-16 18:37:38 +000090 Also works for BUILD_LIST and BUILT_SET when followed by an "in" or "not in"
91 test; for BUILD_SET it assembles a frozenset rather than a tuple.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000092*/
93static int
Antoine Pitrou17b880a2011-03-11 17:27:02 +010094tuple_of_constants(unsigned char *codestr, Py_ssize_t n,
95 PyObject *consts, PyObject **objs)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000096{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000097 PyObject *newconst, *constant;
Antoine Pitrou17b880a2011-03-11 17:27:02 +010098 Py_ssize_t i, len_consts;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000099
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000100 /* Pre-conditions */
101 assert(PyList_CheckExact(consts));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000102
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000103 /* Buildup new tuple of constants */
104 newconst = PyTuple_New(n);
105 if (newconst == NULL)
106 return 0;
107 len_consts = PyList_GET_SIZE(consts);
108 for (i=0 ; i<n ; i++) {
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100109 constant = objs[i];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000110 Py_INCREF(constant);
111 PyTuple_SET_ITEM(newconst, i, constant);
112 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000113
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000114 /* If it's a BUILD_SET, use the PyTuple we just built to create a
115 PyFrozenSet, and use that as the constant instead: */
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100116 if (codestr[0] == BUILD_SET) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000117 PyObject *tuple = newconst;
118 newconst = PyFrozenSet_New(tuple);
119 Py_DECREF(tuple);
120 if (newconst == NULL)
121 return 0;
122 }
Antoine Pitroub7fbcd32010-01-16 18:37:38 +0000123
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000124 /* Append folded constant onto consts */
125 if (PyList_Append(consts, newconst)) {
126 Py_DECREF(newconst);
127 return 0;
128 }
129 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000130
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000131 /* Write NOPs over old LOAD_CONSTS and
132 add a new LOAD_CONST newconst on top of the BUILD_TUPLE n */
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100133 codestr[0] = LOAD_CONST;
134 SETARG(codestr, 0, len_consts);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000135 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000136}
137
138/* Replace LOAD_CONST c1. LOAD_CONST c2 BINOP
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000139 with LOAD_CONST binop(c1,c2)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000140 The consts table must still be in list form so that the
141 new constant can be appended.
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100142 Called with codestr pointing to the BINOP.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000143 Abandons the transformation if the folding fails (i.e. 1+'a').
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000144 If the new constant is a sequence, only folds when the size
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000145 is below a threshold value. That keeps pyc files from
146 becoming large in the presence of code like: (None,)*1000.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000147*/
148static int
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100149fold_binops_on_constants(unsigned char *codestr, PyObject *consts, PyObject **objs)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000150{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000151 PyObject *newconst, *v, *w;
152 Py_ssize_t len_consts, size;
153 int opcode;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000154
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000155 /* Pre-conditions */
156 assert(PyList_CheckExact(consts));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000157
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000158 /* Create new constant */
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100159 v = objs[0];
160 w = objs[1];
161 opcode = codestr[0];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000162 switch (opcode) {
163 case BINARY_POWER:
164 newconst = PyNumber_Power(v, w, Py_None);
165 break;
166 case BINARY_MULTIPLY:
167 newconst = PyNumber_Multiply(v, w);
168 break;
169 case BINARY_TRUE_DIVIDE:
170 newconst = PyNumber_TrueDivide(v, w);
171 break;
172 case BINARY_FLOOR_DIVIDE:
173 newconst = PyNumber_FloorDivide(v, w);
174 break;
175 case BINARY_MODULO:
176 newconst = PyNumber_Remainder(v, w);
177 break;
178 case BINARY_ADD:
179 newconst = PyNumber_Add(v, w);
180 break;
181 case BINARY_SUBTRACT:
182 newconst = PyNumber_Subtract(v, w);
183 break;
184 case BINARY_SUBSCR:
185 newconst = PyObject_GetItem(v, w);
Ezio Melotti2df6a932011-04-15 16:38:34 +0300186 /* #5057: if v is unicode, there might be differences between
187 wide and narrow builds in cases like '\U00012345'[0].
188 Wide builds will return a non-BMP char, whereas narrow builds
189 will return a surrogate. In both the cases skip the
190 optimization in order to produce compatible pycs.
191 */
192 if (newconst != NULL &&
193 PyUnicode_Check(v) && PyUnicode_Check(newconst)) {
194 Py_UNICODE ch = PyUnicode_AS_UNICODE(newconst)[0];
195#ifdef Py_UNICODE_WIDE
196 if (ch > 0xFFFF) {
197#else
198 if (ch >= 0xD800 && ch <= 0xDFFF) {
199#endif
200 Py_DECREF(newconst);
201 return 0;
202 }
203 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000204 break;
205 case BINARY_LSHIFT:
206 newconst = PyNumber_Lshift(v, w);
207 break;
208 case BINARY_RSHIFT:
209 newconst = PyNumber_Rshift(v, w);
210 break;
211 case BINARY_AND:
212 newconst = PyNumber_And(v, w);
213 break;
214 case BINARY_XOR:
215 newconst = PyNumber_Xor(v, w);
216 break;
217 case BINARY_OR:
218 newconst = PyNumber_Or(v, w);
219 break;
220 default:
221 /* Called with an unknown opcode */
222 PyErr_Format(PyExc_SystemError,
223 "unexpected binary operation %d on a constant",
224 opcode);
225 return 0;
226 }
227 if (newconst == NULL) {
Raymond Hettinger819a0642010-08-22 08:39:49 +0000228 if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
229 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000230 return 0;
231 }
232 size = PyObject_Size(newconst);
Raymond Hettinger819a0642010-08-22 08:39:49 +0000233 if (size == -1) {
234 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
235 return 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000236 PyErr_Clear();
Raymond Hettinger819a0642010-08-22 08:39:49 +0000237 } else if (size > 20) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000238 Py_DECREF(newconst);
239 return 0;
240 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000241
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000242 /* Append folded constant into consts table */
243 len_consts = PyList_GET_SIZE(consts);
244 if (PyList_Append(consts, newconst)) {
245 Py_DECREF(newconst);
246 return 0;
247 }
248 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000249
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000250 /* Write NOP NOP NOP NOP LOAD_CONST newconst */
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100251 codestr[-2] = LOAD_CONST;
252 SETARG(codestr, -2, len_consts);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000253 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000254}
255
256static int
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100257fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts, PyObject *v)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000258{
Mark Dickinson7c9e8032011-03-23 17:59:37 +0000259 PyObject *newconst;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000260 Py_ssize_t len_consts;
261 int opcode;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000262
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000263 /* Pre-conditions */
264 assert(PyList_CheckExact(consts));
265 assert(codestr[0] == LOAD_CONST);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000266
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000267 /* Create new constant */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000268 opcode = codestr[3];
269 switch (opcode) {
270 case UNARY_NEGATIVE:
Mark Dickinson7c9e8032011-03-23 17:59:37 +0000271 newconst = PyNumber_Negative(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000272 break;
273 case UNARY_INVERT:
274 newconst = PyNumber_Invert(v);
275 break;
276 case UNARY_POSITIVE:
277 newconst = PyNumber_Positive(v);
278 break;
279 default:
280 /* Called with an unknown opcode */
281 PyErr_Format(PyExc_SystemError,
282 "unexpected unary operation %d on a constant",
283 opcode);
284 return 0;
285 }
286 if (newconst == NULL) {
Raymond Hettinger819a0642010-08-22 08:39:49 +0000287 if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
288 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000289 return 0;
290 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000291
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000292 /* Append folded constant into consts table */
293 len_consts = PyList_GET_SIZE(consts);
294 if (PyList_Append(consts, newconst)) {
295 Py_DECREF(newconst);
296 return 0;
297 }
298 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000299
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000300 /* Write NOP LOAD_CONST newconst */
301 codestr[0] = NOP;
302 codestr[1] = LOAD_CONST;
303 SETARG(codestr, 1, len_consts);
304 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000305}
306
307static unsigned int *
Christian Heimescc47b052008-03-25 14:56:36 +0000308markblocks(unsigned char *code, Py_ssize_t len)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000309{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000310 unsigned int *blocks = (unsigned int *)PyMem_Malloc(len*sizeof(int));
311 int i,j, opcode, blockcnt = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000313 if (blocks == NULL) {
314 PyErr_NoMemory();
315 return NULL;
316 }
317 memset(blocks, 0, len*sizeof(int));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000318
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000319 /* Mark labels in the first pass */
320 for (i=0 ; i<len ; i+=CODESIZE(opcode)) {
321 opcode = code[i];
322 switch (opcode) {
323 case FOR_ITER:
324 case JUMP_FORWARD:
325 case JUMP_IF_FALSE_OR_POP:
326 case JUMP_IF_TRUE_OR_POP:
327 case POP_JUMP_IF_FALSE:
328 case POP_JUMP_IF_TRUE:
329 case JUMP_ABSOLUTE:
330 case CONTINUE_LOOP:
331 case SETUP_LOOP:
332 case SETUP_EXCEPT:
333 case SETUP_FINALLY:
334 case SETUP_WITH:
335 j = GETJUMPTGT(code, i);
336 blocks[j] = 1;
337 break;
338 }
339 }
340 /* Build block numbers in the second pass */
341 for (i=0 ; i<len ; i++) {
342 blockcnt += blocks[i]; /* increment blockcnt over labels */
343 blocks[i] = blockcnt;
344 }
345 return blocks;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000346}
347
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000348/* Helper to replace LOAD_NAME None/True/False with LOAD_CONST
349 Returns: 0 if no change, 1 if change, -1 if error */
350static int
351load_global(unsigned char *codestr, Py_ssize_t i, char *name, PyObject *consts)
352{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000353 Py_ssize_t j;
354 PyObject *obj;
355 if (name == NULL)
356 return 0;
357 if (strcmp(name, "None") == 0)
358 obj = Py_None;
359 else if (strcmp(name, "True") == 0)
360 obj = Py_True;
361 else if (strcmp(name, "False") == 0)
362 obj = Py_False;
363 else
364 return 0;
365 for (j = 0; j < PyList_GET_SIZE(consts); j++) {
366 if (PyList_GET_ITEM(consts, j) == obj)
367 break;
368 }
369 if (j == PyList_GET_SIZE(consts)) {
370 if (PyList_Append(consts, obj) < 0)
371 return -1;
372 }
373 assert(PyList_GET_ITEM(consts, j) == obj);
374 codestr[i] = LOAD_CONST;
375 SETARG(codestr, i, j);
376 return 1;
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000377}
378
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000379/* Perform basic peephole optimizations to components of a code object.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000380 The consts object should still be in list form to allow new constants
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000381 to be appended.
382
Guido van Rossum0240b922007-02-26 21:23:50 +0000383 To keep the optimizer simple, it bails out (does nothing) for code that
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000384 has a length over 32,700, and does not calculate extended arguments.
Guido van Rossum0240b922007-02-26 21:23:50 +0000385 That allows us to avoid overflow and sign issues. Likewise, it bails when
386 the lineno table has complex encoding for gaps >= 255. EXTENDED_ARG can
387 appear before MAKE_FUNCTION; in this case both opcodes are skipped.
388 EXTENDED_ARG preceding any other opcode causes the optimizer to bail.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000389
390 Optimizations are restricted to simple transformations occuring within a
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000391 single basic block. All transformations keep the code size the same or
392 smaller. For those that reduce size, the gaps are initially filled with
393 NOPs. Later those NOPs are removed and the jump addresses retargeted in
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000394 a single pass. Line numbering is adjusted accordingly. */
395
396PyObject *
397PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
398 PyObject *lineno_obj)
399{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000400 Py_ssize_t i, j, codelen;
401 int nops, h, adj;
402 int tgt, tgttgt, opcode;
403 unsigned char *codestr = NULL;
404 unsigned char *lineno;
405 int *addrmap = NULL;
406 int new_line, cum_orig_line, last_line, tabsiz;
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100407 PyObject **const_stack = NULL;
408 Py_ssize_t *load_const_stack = NULL;
409 Py_ssize_t const_stack_top = -1;
410 Py_ssize_t const_stack_size = 0;
411 int in_consts = 0; /* whether we are in a LOAD_CONST sequence */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000412 unsigned int *blocks = NULL;
413 char *name;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000414
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000415 /* Bail out if an exception is set */
416 if (PyErr_Occurred())
417 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000418
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000419 /* Bypass optimization when the lineno table is too complex */
420 assert(PyBytes_Check(lineno_obj));
421 lineno = (unsigned char*)PyBytes_AS_STRING(lineno_obj);
422 tabsiz = PyBytes_GET_SIZE(lineno_obj);
423 if (memchr(lineno, 255, tabsiz) != NULL)
424 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000425
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000426 /* Avoid situations where jump retargeting could overflow */
427 assert(PyBytes_Check(code));
428 codelen = PyBytes_GET_SIZE(code);
429 if (codelen > 32700)
430 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000431
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000432 /* Make a modifiable copy of the code string */
433 codestr = (unsigned char *)PyMem_Malloc(codelen);
434 if (codestr == NULL)
435 goto exitError;
436 codestr = (unsigned char *)memcpy(codestr,
437 PyBytes_AS_STRING(code), codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000438
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000439 /* Verify that RETURN_VALUE terminates the codestring. This allows
440 the various transformation patterns to look ahead several
441 instructions without additional checks to make sure they are not
442 looking beyond the end of the code string.
443 */
444 if (codestr[codelen-1] != RETURN_VALUE)
445 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000446
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000447 /* Mapping to new jump targets after NOPs are removed */
448 addrmap = (int *)PyMem_Malloc(codelen * sizeof(int));
449 if (addrmap == NULL)
450 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000451
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000452 blocks = markblocks(codestr, codelen);
453 if (blocks == NULL)
454 goto exitError;
455 assert(PyList_Check(consts));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000456
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100457 CONST_STACK_CREATE();
458
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000459 for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
460 reoptimize_current:
461 opcode = codestr[i];
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000462
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100463 if (!in_consts) {
464 CONST_STACK_RESET();
465 }
466 in_consts = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000467
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000468 switch (opcode) {
469 /* Replace UNARY_NOT POP_JUMP_IF_FALSE
470 with POP_JUMP_IF_TRUE */
471 case UNARY_NOT:
472 if (codestr[i+1] != POP_JUMP_IF_FALSE
473 || !ISBASICBLOCK(blocks,i,4))
474 continue;
475 j = GETARG(codestr, i+1);
476 codestr[i] = POP_JUMP_IF_TRUE;
477 SETARG(codestr, i, j);
478 codestr[i+3] = NOP;
479 goto reoptimize_current;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000480
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000481 /* not a is b --> a is not b
482 not a in b --> a not in b
483 not a is not b --> a is b
484 not a not in b --> a in b
485 */
486 case COMPARE_OP:
487 j = GETARG(codestr, i);
488 if (j < 6 || j > 9 ||
489 codestr[i+3] != UNARY_NOT ||
490 !ISBASICBLOCK(blocks,i,4))
491 continue;
492 SETARG(codestr, i, (j^1));
493 codestr[i+3] = NOP;
494 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000495
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000496 /* Replace LOAD_GLOBAL/LOAD_NAME None/True/False
497 with LOAD_CONST None/True/False */
498 case LOAD_NAME:
499 case LOAD_GLOBAL:
500 j = GETARG(codestr, i);
501 name = _PyUnicode_AsString(PyTuple_GET_ITEM(names, j));
502 h = load_global(codestr, i, name, consts);
503 if (h < 0)
504 goto exitError;
505 else if (h == 0)
506 continue;
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100507 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000508 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000509
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000510 /* Skip over LOAD_CONST trueconst
511 POP_JUMP_IF_FALSE xx. This improves
512 "while 1" performance. */
513 case LOAD_CONST:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100514 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000515 j = GETARG(codestr, i);
516 if (codestr[i+3] != POP_JUMP_IF_FALSE ||
517 !ISBASICBLOCK(blocks,i,6) ||
518 !PyObject_IsTrue(PyList_GET_ITEM(consts, j)))
519 continue;
520 memset(codestr+i, NOP, 6);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100521 CONST_STACK_RESET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000522 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000524 /* Try to fold tuples of constants (includes a case for lists and sets
525 which are only used for "in" and "not in" tests).
526 Skip over BUILD_SEQN 1 UNPACK_SEQN 1.
527 Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2.
528 Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */
529 case BUILD_TUPLE:
530 case BUILD_LIST:
531 case BUILD_SET:
532 j = GETARG(codestr, i);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100533 if (j == 0)
534 break;
535 h = CONST_STACK_OP_LASTN(j);
536 assert((h >= 0 || CONST_STACK_LEN() < j));
537 if (h >= 0 && j > 0 && j <= CONST_STACK_LEN() &&
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000538 ((opcode == BUILD_TUPLE &&
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100539 ISBASICBLOCK(blocks, h, i-h+3)) ||
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000540 ((opcode == BUILD_LIST || opcode == BUILD_SET) &&
541 codestr[i+3]==COMPARE_OP &&
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100542 ISBASICBLOCK(blocks, h, i-h+6) &&
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000543 (GETARG(codestr,i+3)==6 ||
544 GETARG(codestr,i+3)==7))) &&
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100545 tuple_of_constants(&codestr[i], j, consts, CONST_STACK_LASTN(j))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000546 assert(codestr[i] == LOAD_CONST);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100547 memset(&codestr[h], NOP, i - h);
548 CONST_STACK_POP(j);
549 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000550 break;
551 }
552 if (codestr[i+3] != UNPACK_SEQUENCE ||
553 !ISBASICBLOCK(blocks,i,6) ||
Raymond Hettinger0661e912011-03-15 15:03:36 -0700554 j != GETARG(codestr, i+3) ||
555 opcode == BUILD_SET)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000556 continue;
557 if (j == 1) {
558 memset(codestr+i, NOP, 6);
559 } else if (j == 2) {
560 codestr[i] = ROT_TWO;
561 memset(codestr+i+1, NOP, 5);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100562 CONST_STACK_RESET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000563 } else if (j == 3) {
564 codestr[i] = ROT_THREE;
565 codestr[i+1] = ROT_TWO;
566 memset(codestr+i+2, NOP, 4);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100567 CONST_STACK_RESET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000568 }
569 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000570
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000571 /* Fold binary ops on constants.
572 LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */
573 case BINARY_POWER:
574 case BINARY_MULTIPLY:
575 case BINARY_TRUE_DIVIDE:
576 case BINARY_FLOOR_DIVIDE:
577 case BINARY_MODULO:
578 case BINARY_ADD:
579 case BINARY_SUBTRACT:
580 case BINARY_SUBSCR:
581 case BINARY_LSHIFT:
582 case BINARY_RSHIFT:
583 case BINARY_AND:
584 case BINARY_XOR:
585 case BINARY_OR:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100586 /* NOTE: LOAD_CONST is saved at `i-2` since it has an arg
587 while BINOP hasn't */
588 h = CONST_STACK_OP_LASTN(2);
589 assert((h >= 0 || CONST_STACK_LEN() < 2));
590 if (h >= 0 &&
591 ISBASICBLOCK(blocks, h, i-h+1) &&
592 fold_binops_on_constants(&codestr[i], consts, CONST_STACK_LASTN(2))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000593 i -= 2;
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100594 memset(&codestr[h], NOP, i - h);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000595 assert(codestr[i] == LOAD_CONST);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100596 CONST_STACK_POP(2);
597 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000598 }
599 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000600
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000601 /* Fold unary ops on constants.
602 LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */
603 case UNARY_NEGATIVE:
604 case UNARY_INVERT:
605 case UNARY_POSITIVE:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100606 h = CONST_STACK_OP_LASTN(1);
607 assert((h >= 0 || CONST_STACK_LEN() < 1));
608 if (h >= 0 &&
609 ISBASICBLOCK(blocks, h, i-h+1) &&
610 fold_unaryops_on_constants(&codestr[i-3], consts, CONST_STACK_TOP())) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000611 i -= 2;
612 assert(codestr[i] == LOAD_CONST);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100613 CONST_STACK_POP(1);
614 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000615 }
616 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000617
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000618 /* Simplify conditional jump to conditional jump where the
619 result of the first test implies the success of a similar
620 test or the failure of the opposite test.
621 Arises in code like:
622 "if a and b:"
623 "if a or b:"
624 "a and b or c"
625 "(a and b) and c"
626 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z
627 --> x:JUMP_IF_FALSE_OR_POP z
628 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z
629 --> x:POP_JUMP_IF_FALSE y+3
630 where y+3 is the instruction following the second test.
631 */
632 case JUMP_IF_FALSE_OR_POP:
633 case JUMP_IF_TRUE_OR_POP:
634 tgt = GETJUMPTGT(codestr, i);
635 j = codestr[tgt];
636 if (CONDITIONAL_JUMP(j)) {
637 /* NOTE: all possible jumps here are
638 absolute! */
639 if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) {
640 /* The second jump will be
641 taken iff the first is. */
642 tgttgt = GETJUMPTGT(codestr, tgt);
643 /* The current opcode inherits
644 its target's stack behaviour */
645 codestr[i] = j;
646 SETARG(codestr, i, tgttgt);
647 goto reoptimize_current;
648 } else {
649 /* The second jump is not taken
650 if the first is (so jump past
651 it), and all conditional
652 jumps pop their argument when
653 they're not taken (so change
654 the first jump to pop its
655 argument when it's taken). */
656 if (JUMPS_ON_TRUE(opcode))
657 codestr[i] = POP_JUMP_IF_TRUE;
658 else
659 codestr[i] = POP_JUMP_IF_FALSE;
660 SETARG(codestr, i, (tgt + 3));
661 goto reoptimize_current;
662 }
663 }
664 /* Intentional fallthrough */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000666 /* Replace jumps to unconditional jumps */
667 case POP_JUMP_IF_FALSE:
668 case POP_JUMP_IF_TRUE:
669 case FOR_ITER:
670 case JUMP_FORWARD:
671 case JUMP_ABSOLUTE:
672 case CONTINUE_LOOP:
673 case SETUP_LOOP:
674 case SETUP_EXCEPT:
675 case SETUP_FINALLY:
676 case SETUP_WITH:
677 tgt = GETJUMPTGT(codestr, i);
678 /* Replace JUMP_* to a RETURN into just a RETURN */
679 if (UNCONDITIONAL_JUMP(opcode) &&
680 codestr[tgt] == RETURN_VALUE) {
681 codestr[i] = RETURN_VALUE;
682 memset(codestr+i+1, NOP, 2);
683 continue;
684 }
685 if (!UNCONDITIONAL_JUMP(codestr[tgt]))
686 continue;
687 tgttgt = GETJUMPTGT(codestr, tgt);
688 if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */
689 opcode = JUMP_ABSOLUTE;
690 if (!ABSOLUTE_JUMP(opcode))
691 tgttgt -= i + 3; /* Calc relative jump addr */
692 if (tgttgt < 0) /* No backward relative jumps */
693 continue;
694 codestr[i] = opcode;
695 SETARG(codestr, i, tgttgt);
696 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000697
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000698 case EXTENDED_ARG:
699 if (codestr[i+3] != MAKE_FUNCTION)
700 goto exitUnchanged;
701 /* don't visit MAKE_FUNCTION as GETARG will be wrong */
702 i += 3;
703 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000704
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000705 /* Replace RETURN LOAD_CONST None RETURN with just RETURN */
706 /* Remove unreachable JUMPs after RETURN */
707 case RETURN_VALUE:
708 if (i+4 >= codelen)
709 continue;
710 if (codestr[i+4] == RETURN_VALUE &&
711 ISBASICBLOCK(blocks,i,5))
712 memset(codestr+i+1, NOP, 4);
713 else if (UNCONDITIONAL_JUMP(codestr[i+1]) &&
714 ISBASICBLOCK(blocks,i,4))
715 memset(codestr+i+1, NOP, 3);
716 break;
717 }
718 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000719
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000720 /* Fixup linenotab */
721 for (i=0, nops=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
722 addrmap[i] = i - nops;
723 if (codestr[i] == NOP)
724 nops++;
725 }
726 cum_orig_line = 0;
727 last_line = 0;
728 for (i=0 ; i < tabsiz ; i+=2) {
729 cum_orig_line += lineno[i];
730 new_line = addrmap[cum_orig_line];
731 assert (new_line - last_line < 255);
732 lineno[i] =((unsigned char)(new_line - last_line));
733 last_line = new_line;
734 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000735
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000736 /* Remove NOPs and fixup jump targets */
737 for (i=0, h=0 ; i<codelen ; ) {
738 opcode = codestr[i];
739 switch (opcode) {
740 case NOP:
741 i++;
742 continue;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000743
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000744 case JUMP_ABSOLUTE:
745 case CONTINUE_LOOP:
746 case POP_JUMP_IF_FALSE:
747 case POP_JUMP_IF_TRUE:
748 case JUMP_IF_FALSE_OR_POP:
749 case JUMP_IF_TRUE_OR_POP:
750 j = addrmap[GETARG(codestr, i)];
751 SETARG(codestr, i, j);
752 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000753
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000754 case FOR_ITER:
755 case JUMP_FORWARD:
756 case SETUP_LOOP:
757 case SETUP_EXCEPT:
758 case SETUP_FINALLY:
759 case SETUP_WITH:
760 j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3;
761 SETARG(codestr, i, j);
762 break;
763 }
764 adj = CODESIZE(opcode);
765 while (adj--)
766 codestr[h++] = codestr[i++];
767 }
768 assert(h + nops == codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000769
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000770 code = PyBytes_FromStringAndSize((char *)codestr, h);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100771 CONST_STACK_DELETE();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000772 PyMem_Free(addrmap);
773 PyMem_Free(codestr);
774 PyMem_Free(blocks);
775 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000776
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000777 exitError:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000778 code = NULL;
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000779
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000780 exitUnchanged:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100781 CONST_STACK_DELETE();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000782 if (blocks != NULL)
783 PyMem_Free(blocks);
784 if (addrmap != NULL)
785 PyMem_Free(addrmap);
786 if (codestr != NULL)
787 PyMem_Free(codestr);
788 Py_XINCREF(code);
789 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000790}