blob: 5d536779acf894558c6fb593a3f8493a4c6e0960 [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
Stefan Krah472d2802011-09-21 19:08:39 +020069#define CONST_STACK_TOP() \
Antoine Pitrou17b880a2011-03-11 17:27:02 +010070 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);
186 break;
187 case BINARY_LSHIFT:
188 newconst = PyNumber_Lshift(v, w);
189 break;
190 case BINARY_RSHIFT:
191 newconst = PyNumber_Rshift(v, w);
192 break;
193 case BINARY_AND:
194 newconst = PyNumber_And(v, w);
195 break;
196 case BINARY_XOR:
197 newconst = PyNumber_Xor(v, w);
198 break;
199 case BINARY_OR:
200 newconst = PyNumber_Or(v, w);
201 break;
202 default:
203 /* Called with an unknown opcode */
204 PyErr_Format(PyExc_SystemError,
205 "unexpected binary operation %d on a constant",
206 opcode);
207 return 0;
208 }
209 if (newconst == NULL) {
Raymond Hettinger819a0642010-08-22 08:39:49 +0000210 if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
211 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000212 return 0;
213 }
214 size = PyObject_Size(newconst);
Raymond Hettinger819a0642010-08-22 08:39:49 +0000215 if (size == -1) {
216 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
217 return 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000218 PyErr_Clear();
Raymond Hettinger819a0642010-08-22 08:39:49 +0000219 } else if (size > 20) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000220 Py_DECREF(newconst);
221 return 0;
222 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000223
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000224 /* Append folded constant into consts table */
225 len_consts = PyList_GET_SIZE(consts);
226 if (PyList_Append(consts, newconst)) {
227 Py_DECREF(newconst);
228 return 0;
229 }
230 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000231
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000232 /* Write NOP NOP NOP NOP LOAD_CONST newconst */
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100233 codestr[-2] = LOAD_CONST;
234 SETARG(codestr, -2, len_consts);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000235 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000236}
237
238static int
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100239fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts, PyObject *v)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000240{
Mark Dickinson7c9e8032011-03-23 17:59:37 +0000241 PyObject *newconst;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000242 Py_ssize_t len_consts;
243 int opcode;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000244
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000245 /* Pre-conditions */
246 assert(PyList_CheckExact(consts));
247 assert(codestr[0] == LOAD_CONST);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000248
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000249 /* Create new constant */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000250 opcode = codestr[3];
251 switch (opcode) {
252 case UNARY_NEGATIVE:
Mark Dickinson7c9e8032011-03-23 17:59:37 +0000253 newconst = PyNumber_Negative(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000254 break;
255 case UNARY_INVERT:
256 newconst = PyNumber_Invert(v);
257 break;
258 case UNARY_POSITIVE:
259 newconst = PyNumber_Positive(v);
260 break;
261 default:
262 /* Called with an unknown opcode */
263 PyErr_Format(PyExc_SystemError,
264 "unexpected unary operation %d on a constant",
265 opcode);
266 return 0;
267 }
268 if (newconst == NULL) {
Raymond Hettinger819a0642010-08-22 08:39:49 +0000269 if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
270 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000271 return 0;
272 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000273
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000274 /* Append folded constant into consts table */
275 len_consts = PyList_GET_SIZE(consts);
276 if (PyList_Append(consts, newconst)) {
277 Py_DECREF(newconst);
278 return 0;
279 }
280 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000282 /* Write NOP LOAD_CONST newconst */
283 codestr[0] = NOP;
284 codestr[1] = LOAD_CONST;
285 SETARG(codestr, 1, len_consts);
286 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000287}
288
289static unsigned int *
Christian Heimescc47b052008-03-25 14:56:36 +0000290markblocks(unsigned char *code, Py_ssize_t len)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000291{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000292 unsigned int *blocks = (unsigned int *)PyMem_Malloc(len*sizeof(int));
293 int i,j, opcode, blockcnt = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000294
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000295 if (blocks == NULL) {
296 PyErr_NoMemory();
297 return NULL;
298 }
299 memset(blocks, 0, len*sizeof(int));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000300
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000301 /* Mark labels in the first pass */
302 for (i=0 ; i<len ; i+=CODESIZE(opcode)) {
303 opcode = code[i];
304 switch (opcode) {
305 case FOR_ITER:
306 case JUMP_FORWARD:
307 case JUMP_IF_FALSE_OR_POP:
308 case JUMP_IF_TRUE_OR_POP:
309 case POP_JUMP_IF_FALSE:
310 case POP_JUMP_IF_TRUE:
311 case JUMP_ABSOLUTE:
312 case CONTINUE_LOOP:
313 case SETUP_LOOP:
314 case SETUP_EXCEPT:
315 case SETUP_FINALLY:
316 case SETUP_WITH:
317 j = GETJUMPTGT(code, i);
318 blocks[j] = 1;
319 break;
320 }
321 }
322 /* Build block numbers in the second pass */
323 for (i=0 ; i<len ; i++) {
324 blockcnt += blocks[i]; /* increment blockcnt over labels */
325 blocks[i] = blockcnt;
326 }
327 return blocks;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000328}
329
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000330/* Helper to replace LOAD_NAME None/True/False with LOAD_CONST
331 Returns: 0 if no change, 1 if change, -1 if error */
332static int
333load_global(unsigned char *codestr, Py_ssize_t i, char *name, PyObject *consts)
334{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000335 Py_ssize_t j;
336 PyObject *obj;
337 if (name == NULL)
338 return 0;
339 if (strcmp(name, "None") == 0)
340 obj = Py_None;
341 else if (strcmp(name, "True") == 0)
342 obj = Py_True;
343 else if (strcmp(name, "False") == 0)
344 obj = Py_False;
345 else
346 return 0;
347 for (j = 0; j < PyList_GET_SIZE(consts); j++) {
348 if (PyList_GET_ITEM(consts, j) == obj)
349 break;
350 }
351 if (j == PyList_GET_SIZE(consts)) {
352 if (PyList_Append(consts, obj) < 0)
353 return -1;
354 }
355 assert(PyList_GET_ITEM(consts, j) == obj);
356 codestr[i] = LOAD_CONST;
357 SETARG(codestr, i, j);
358 return 1;
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000359}
360
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000361/* Perform basic peephole optimizations to components of a code object.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000362 The consts object should still be in list form to allow new constants
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000363 to be appended.
364
Guido van Rossum0240b922007-02-26 21:23:50 +0000365 To keep the optimizer simple, it bails out (does nothing) for code that
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000366 has a length over 32,700, and does not calculate extended arguments.
Guido van Rossum0240b922007-02-26 21:23:50 +0000367 That allows us to avoid overflow and sign issues. Likewise, it bails when
368 the lineno table has complex encoding for gaps >= 255. EXTENDED_ARG can
369 appear before MAKE_FUNCTION; in this case both opcodes are skipped.
370 EXTENDED_ARG preceding any other opcode causes the optimizer to bail.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000371
372 Optimizations are restricted to simple transformations occuring within a
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000373 single basic block. All transformations keep the code size the same or
374 smaller. For those that reduce size, the gaps are initially filled with
375 NOPs. Later those NOPs are removed and the jump addresses retargeted in
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000376 a single pass. Line numbering is adjusted accordingly. */
377
378PyObject *
379PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
380 PyObject *lineno_obj)
381{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000382 Py_ssize_t i, j, codelen;
383 int nops, h, adj;
384 int tgt, tgttgt, opcode;
385 unsigned char *codestr = NULL;
386 unsigned char *lineno;
387 int *addrmap = NULL;
388 int new_line, cum_orig_line, last_line, tabsiz;
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100389 PyObject **const_stack = NULL;
390 Py_ssize_t *load_const_stack = NULL;
391 Py_ssize_t const_stack_top = -1;
392 Py_ssize_t const_stack_size = 0;
393 int in_consts = 0; /* whether we are in a LOAD_CONST sequence */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000394 unsigned int *blocks = NULL;
395 char *name;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000396
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000397 /* Bail out if an exception is set */
398 if (PyErr_Occurred())
399 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000400
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000401 /* Bypass optimization when the lineno table is too complex */
402 assert(PyBytes_Check(lineno_obj));
403 lineno = (unsigned char*)PyBytes_AS_STRING(lineno_obj);
404 tabsiz = PyBytes_GET_SIZE(lineno_obj);
405 if (memchr(lineno, 255, tabsiz) != NULL)
406 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000407
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000408 /* Avoid situations where jump retargeting could overflow */
409 assert(PyBytes_Check(code));
410 codelen = PyBytes_GET_SIZE(code);
411 if (codelen > 32700)
412 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000413
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000414 /* Make a modifiable copy of the code string */
415 codestr = (unsigned char *)PyMem_Malloc(codelen);
416 if (codestr == NULL)
417 goto exitError;
418 codestr = (unsigned char *)memcpy(codestr,
419 PyBytes_AS_STRING(code), codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000420
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000421 /* Verify that RETURN_VALUE terminates the codestring. This allows
422 the various transformation patterns to look ahead several
423 instructions without additional checks to make sure they are not
424 looking beyond the end of the code string.
425 */
426 if (codestr[codelen-1] != RETURN_VALUE)
427 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000428
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000429 /* Mapping to new jump targets after NOPs are removed */
430 addrmap = (int *)PyMem_Malloc(codelen * sizeof(int));
431 if (addrmap == NULL)
432 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000433
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000434 blocks = markblocks(codestr, codelen);
435 if (blocks == NULL)
436 goto exitError;
437 assert(PyList_Check(consts));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000438
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100439 CONST_STACK_CREATE();
440
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000441 for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
442 reoptimize_current:
443 opcode = codestr[i];
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000444
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100445 if (!in_consts) {
446 CONST_STACK_RESET();
447 }
448 in_consts = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000449
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000450 switch (opcode) {
451 /* Replace UNARY_NOT POP_JUMP_IF_FALSE
452 with POP_JUMP_IF_TRUE */
453 case UNARY_NOT:
454 if (codestr[i+1] != POP_JUMP_IF_FALSE
455 || !ISBASICBLOCK(blocks,i,4))
456 continue;
457 j = GETARG(codestr, i+1);
458 codestr[i] = POP_JUMP_IF_TRUE;
459 SETARG(codestr, i, j);
460 codestr[i+3] = NOP;
461 goto reoptimize_current;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000462
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000463 /* not a is b --> a is not b
464 not a in b --> a not in b
465 not a is not b --> a is b
466 not a not in b --> a in b
467 */
468 case COMPARE_OP:
469 j = GETARG(codestr, i);
470 if (j < 6 || j > 9 ||
471 codestr[i+3] != UNARY_NOT ||
472 !ISBASICBLOCK(blocks,i,4))
473 continue;
474 SETARG(codestr, i, (j^1));
475 codestr[i+3] = NOP;
476 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000477
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000478 /* Replace LOAD_GLOBAL/LOAD_NAME None/True/False
479 with LOAD_CONST None/True/False */
480 case LOAD_NAME:
481 case LOAD_GLOBAL:
482 j = GETARG(codestr, i);
483 name = _PyUnicode_AsString(PyTuple_GET_ITEM(names, j));
484 h = load_global(codestr, i, name, consts);
485 if (h < 0)
486 goto exitError;
487 else if (h == 0)
488 continue;
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100489 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000490 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000491
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000492 /* Skip over LOAD_CONST trueconst
493 POP_JUMP_IF_FALSE xx. This improves
494 "while 1" performance. */
495 case LOAD_CONST:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100496 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000497 j = GETARG(codestr, i);
498 if (codestr[i+3] != POP_JUMP_IF_FALSE ||
499 !ISBASICBLOCK(blocks,i,6) ||
500 !PyObject_IsTrue(PyList_GET_ITEM(consts, j)))
501 continue;
502 memset(codestr+i, NOP, 6);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100503 CONST_STACK_RESET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000504 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000505
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000506 /* Try to fold tuples of constants (includes a case for lists and sets
507 which are only used for "in" and "not in" tests).
508 Skip over BUILD_SEQN 1 UNPACK_SEQN 1.
509 Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2.
510 Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */
511 case BUILD_TUPLE:
512 case BUILD_LIST:
513 case BUILD_SET:
514 j = GETARG(codestr, i);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100515 if (j == 0)
516 break;
517 h = CONST_STACK_OP_LASTN(j);
518 assert((h >= 0 || CONST_STACK_LEN() < j));
519 if (h >= 0 && j > 0 && j <= CONST_STACK_LEN() &&
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000520 ((opcode == BUILD_TUPLE &&
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100521 ISBASICBLOCK(blocks, h, i-h+3)) ||
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000522 ((opcode == BUILD_LIST || opcode == BUILD_SET) &&
523 codestr[i+3]==COMPARE_OP &&
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100524 ISBASICBLOCK(blocks, h, i-h+6) &&
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000525 (GETARG(codestr,i+3)==6 ||
526 GETARG(codestr,i+3)==7))) &&
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100527 tuple_of_constants(&codestr[i], j, consts, CONST_STACK_LASTN(j))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000528 assert(codestr[i] == LOAD_CONST);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100529 memset(&codestr[h], NOP, i - h);
530 CONST_STACK_POP(j);
531 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000532 break;
533 }
534 if (codestr[i+3] != UNPACK_SEQUENCE ||
535 !ISBASICBLOCK(blocks,i,6) ||
Raymond Hettinger0661e912011-03-15 15:03:36 -0700536 j != GETARG(codestr, i+3) ||
537 opcode == BUILD_SET)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000538 continue;
539 if (j == 1) {
540 memset(codestr+i, NOP, 6);
541 } else if (j == 2) {
542 codestr[i] = ROT_TWO;
543 memset(codestr+i+1, NOP, 5);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100544 CONST_STACK_RESET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000545 } else if (j == 3) {
546 codestr[i] = ROT_THREE;
547 codestr[i+1] = ROT_TWO;
548 memset(codestr+i+2, NOP, 4);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100549 CONST_STACK_RESET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000550 }
551 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000552
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000553 /* Fold binary ops on constants.
554 LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */
555 case BINARY_POWER:
556 case BINARY_MULTIPLY:
557 case BINARY_TRUE_DIVIDE:
558 case BINARY_FLOOR_DIVIDE:
559 case BINARY_MODULO:
560 case BINARY_ADD:
561 case BINARY_SUBTRACT:
562 case BINARY_SUBSCR:
563 case BINARY_LSHIFT:
564 case BINARY_RSHIFT:
565 case BINARY_AND:
566 case BINARY_XOR:
567 case BINARY_OR:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100568 /* NOTE: LOAD_CONST is saved at `i-2` since it has an arg
569 while BINOP hasn't */
570 h = CONST_STACK_OP_LASTN(2);
571 assert((h >= 0 || CONST_STACK_LEN() < 2));
572 if (h >= 0 &&
573 ISBASICBLOCK(blocks, h, i-h+1) &&
574 fold_binops_on_constants(&codestr[i], consts, CONST_STACK_LASTN(2))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000575 i -= 2;
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100576 memset(&codestr[h], NOP, i - h);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000577 assert(codestr[i] == LOAD_CONST);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100578 CONST_STACK_POP(2);
579 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000580 }
581 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000582
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000583 /* Fold unary ops on constants.
584 LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */
585 case UNARY_NEGATIVE:
586 case UNARY_INVERT:
587 case UNARY_POSITIVE:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100588 h = CONST_STACK_OP_LASTN(1);
589 assert((h >= 0 || CONST_STACK_LEN() < 1));
590 if (h >= 0 &&
591 ISBASICBLOCK(blocks, h, i-h+1) &&
592 fold_unaryops_on_constants(&codestr[i-3], consts, CONST_STACK_TOP())) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000593 i -= 2;
594 assert(codestr[i] == LOAD_CONST);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100595 CONST_STACK_POP(1);
596 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000597 }
598 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000600 /* Simplify conditional jump to conditional jump where the
601 result of the first test implies the success of a similar
602 test or the failure of the opposite test.
603 Arises in code like:
604 "if a and b:"
605 "if a or b:"
606 "a and b or c"
607 "(a and b) and c"
608 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z
609 --> x:JUMP_IF_FALSE_OR_POP z
610 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z
611 --> x:POP_JUMP_IF_FALSE y+3
612 where y+3 is the instruction following the second test.
613 */
614 case JUMP_IF_FALSE_OR_POP:
615 case JUMP_IF_TRUE_OR_POP:
616 tgt = GETJUMPTGT(codestr, i);
617 j = codestr[tgt];
618 if (CONDITIONAL_JUMP(j)) {
619 /* NOTE: all possible jumps here are
620 absolute! */
621 if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) {
622 /* The second jump will be
623 taken iff the first is. */
624 tgttgt = GETJUMPTGT(codestr, tgt);
625 /* The current opcode inherits
626 its target's stack behaviour */
627 codestr[i] = j;
628 SETARG(codestr, i, tgttgt);
629 goto reoptimize_current;
630 } else {
631 /* The second jump is not taken
632 if the first is (so jump past
633 it), and all conditional
634 jumps pop their argument when
635 they're not taken (so change
636 the first jump to pop its
637 argument when it's taken). */
638 if (JUMPS_ON_TRUE(opcode))
639 codestr[i] = POP_JUMP_IF_TRUE;
640 else
641 codestr[i] = POP_JUMP_IF_FALSE;
642 SETARG(codestr, i, (tgt + 3));
643 goto reoptimize_current;
644 }
645 }
646 /* Intentional fallthrough */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000647
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000648 /* Replace jumps to unconditional jumps */
649 case POP_JUMP_IF_FALSE:
650 case POP_JUMP_IF_TRUE:
651 case FOR_ITER:
652 case JUMP_FORWARD:
653 case JUMP_ABSOLUTE:
654 case CONTINUE_LOOP:
655 case SETUP_LOOP:
656 case SETUP_EXCEPT:
657 case SETUP_FINALLY:
658 case SETUP_WITH:
659 tgt = GETJUMPTGT(codestr, i);
660 /* Replace JUMP_* to a RETURN into just a RETURN */
661 if (UNCONDITIONAL_JUMP(opcode) &&
662 codestr[tgt] == RETURN_VALUE) {
663 codestr[i] = RETURN_VALUE;
664 memset(codestr+i+1, NOP, 2);
665 continue;
666 }
667 if (!UNCONDITIONAL_JUMP(codestr[tgt]))
668 continue;
669 tgttgt = GETJUMPTGT(codestr, tgt);
670 if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */
671 opcode = JUMP_ABSOLUTE;
672 if (!ABSOLUTE_JUMP(opcode))
673 tgttgt -= i + 3; /* Calc relative jump addr */
674 if (tgttgt < 0) /* No backward relative jumps */
675 continue;
676 codestr[i] = opcode;
677 SETARG(codestr, i, tgttgt);
678 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000679
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000680 case EXTENDED_ARG:
681 if (codestr[i+3] != MAKE_FUNCTION)
682 goto exitUnchanged;
683 /* don't visit MAKE_FUNCTION as GETARG will be wrong */
684 i += 3;
685 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000686
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000687 /* Replace RETURN LOAD_CONST None RETURN with just RETURN */
688 /* Remove unreachable JUMPs after RETURN */
689 case RETURN_VALUE:
690 if (i+4 >= codelen)
691 continue;
692 if (codestr[i+4] == RETURN_VALUE &&
693 ISBASICBLOCK(blocks,i,5))
694 memset(codestr+i+1, NOP, 4);
695 else if (UNCONDITIONAL_JUMP(codestr[i+1]) &&
696 ISBASICBLOCK(blocks,i,4))
697 memset(codestr+i+1, NOP, 3);
698 break;
699 }
700 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000701
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000702 /* Fixup linenotab */
703 for (i=0, nops=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
704 addrmap[i] = i - nops;
705 if (codestr[i] == NOP)
706 nops++;
707 }
708 cum_orig_line = 0;
709 last_line = 0;
710 for (i=0 ; i < tabsiz ; i+=2) {
711 cum_orig_line += lineno[i];
712 new_line = addrmap[cum_orig_line];
713 assert (new_line - last_line < 255);
714 lineno[i] =((unsigned char)(new_line - last_line));
715 last_line = new_line;
716 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000717
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000718 /* Remove NOPs and fixup jump targets */
719 for (i=0, h=0 ; i<codelen ; ) {
720 opcode = codestr[i];
721 switch (opcode) {
722 case NOP:
723 i++;
724 continue;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000725
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000726 case JUMP_ABSOLUTE:
727 case CONTINUE_LOOP:
728 case POP_JUMP_IF_FALSE:
729 case POP_JUMP_IF_TRUE:
730 case JUMP_IF_FALSE_OR_POP:
731 case JUMP_IF_TRUE_OR_POP:
732 j = addrmap[GETARG(codestr, i)];
733 SETARG(codestr, i, j);
734 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000735
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000736 case FOR_ITER:
737 case JUMP_FORWARD:
738 case SETUP_LOOP:
739 case SETUP_EXCEPT:
740 case SETUP_FINALLY:
741 case SETUP_WITH:
742 j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3;
743 SETARG(codestr, i, j);
744 break;
745 }
746 adj = CODESIZE(opcode);
747 while (adj--)
748 codestr[h++] = codestr[i++];
749 }
750 assert(h + nops == codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000751
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000752 code = PyBytes_FromStringAndSize((char *)codestr, h);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100753 CONST_STACK_DELETE();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000754 PyMem_Free(addrmap);
755 PyMem_Free(codestr);
756 PyMem_Free(blocks);
757 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000758
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000759 exitError:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000760 code = NULL;
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000761
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000762 exitUnchanged:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100763 CONST_STACK_DELETE();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000764 if (blocks != NULL)
765 PyMem_Free(blocks);
766 if (addrmap != NULL)
767 PyMem_Free(addrmap);
768 if (codestr != NULL)
769 PyMem_Free(codestr);
770 Py_XINCREF(code);
771 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000772}