blob: 4bc65dcc312b2dbd77137c42d86083b639ab0f0e [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);
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{
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100241 PyObject *newconst=NULL/*, *v*/;
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:
253 /* Preserve the sign of -0.0 */
254 if (PyObject_IsTrue(v) == 1)
255 newconst = PyNumber_Negative(v);
256 break;
257 case UNARY_INVERT:
258 newconst = PyNumber_Invert(v);
259 break;
260 case UNARY_POSITIVE:
261 newconst = PyNumber_Positive(v);
262 break;
263 default:
264 /* Called with an unknown opcode */
265 PyErr_Format(PyExc_SystemError,
266 "unexpected unary operation %d on a constant",
267 opcode);
268 return 0;
269 }
270 if (newconst == NULL) {
Raymond Hettinger819a0642010-08-22 08:39:49 +0000271 if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
272 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000273 return 0;
274 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000275
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000276 /* Append folded constant into consts table */
277 len_consts = PyList_GET_SIZE(consts);
278 if (PyList_Append(consts, newconst)) {
279 Py_DECREF(newconst);
280 return 0;
281 }
282 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000283
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000284 /* Write NOP LOAD_CONST newconst */
285 codestr[0] = NOP;
286 codestr[1] = LOAD_CONST;
287 SETARG(codestr, 1, len_consts);
288 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000289}
290
291static unsigned int *
Christian Heimescc47b052008-03-25 14:56:36 +0000292markblocks(unsigned char *code, Py_ssize_t len)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000293{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000294 unsigned int *blocks = (unsigned int *)PyMem_Malloc(len*sizeof(int));
295 int i,j, opcode, blockcnt = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000296
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000297 if (blocks == NULL) {
298 PyErr_NoMemory();
299 return NULL;
300 }
301 memset(blocks, 0, len*sizeof(int));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000302
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000303 /* Mark labels in the first pass */
304 for (i=0 ; i<len ; i+=CODESIZE(opcode)) {
305 opcode = code[i];
306 switch (opcode) {
307 case FOR_ITER:
308 case JUMP_FORWARD:
309 case JUMP_IF_FALSE_OR_POP:
310 case JUMP_IF_TRUE_OR_POP:
311 case POP_JUMP_IF_FALSE:
312 case POP_JUMP_IF_TRUE:
313 case JUMP_ABSOLUTE:
314 case CONTINUE_LOOP:
315 case SETUP_LOOP:
316 case SETUP_EXCEPT:
317 case SETUP_FINALLY:
318 case SETUP_WITH:
319 j = GETJUMPTGT(code, i);
320 blocks[j] = 1;
321 break;
322 }
323 }
324 /* Build block numbers in the second pass */
325 for (i=0 ; i<len ; i++) {
326 blockcnt += blocks[i]; /* increment blockcnt over labels */
327 blocks[i] = blockcnt;
328 }
329 return blocks;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000330}
331
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000332/* Helper to replace LOAD_NAME None/True/False with LOAD_CONST
333 Returns: 0 if no change, 1 if change, -1 if error */
334static int
335load_global(unsigned char *codestr, Py_ssize_t i, char *name, PyObject *consts)
336{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000337 Py_ssize_t j;
338 PyObject *obj;
339 if (name == NULL)
340 return 0;
341 if (strcmp(name, "None") == 0)
342 obj = Py_None;
343 else if (strcmp(name, "True") == 0)
344 obj = Py_True;
345 else if (strcmp(name, "False") == 0)
346 obj = Py_False;
347 else
348 return 0;
349 for (j = 0; j < PyList_GET_SIZE(consts); j++) {
350 if (PyList_GET_ITEM(consts, j) == obj)
351 break;
352 }
353 if (j == PyList_GET_SIZE(consts)) {
354 if (PyList_Append(consts, obj) < 0)
355 return -1;
356 }
357 assert(PyList_GET_ITEM(consts, j) == obj);
358 codestr[i] = LOAD_CONST;
359 SETARG(codestr, i, j);
360 return 1;
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000361}
362
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000363/* Perform basic peephole optimizations to components of a code object.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000364 The consts object should still be in list form to allow new constants
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000365 to be appended.
366
Guido van Rossum0240b922007-02-26 21:23:50 +0000367 To keep the optimizer simple, it bails out (does nothing) for code that
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000368 has a length over 32,700, and does not calculate extended arguments.
Guido van Rossum0240b922007-02-26 21:23:50 +0000369 That allows us to avoid overflow and sign issues. Likewise, it bails when
370 the lineno table has complex encoding for gaps >= 255. EXTENDED_ARG can
371 appear before MAKE_FUNCTION; in this case both opcodes are skipped.
372 EXTENDED_ARG preceding any other opcode causes the optimizer to bail.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000373
374 Optimizations are restricted to simple transformations occuring within a
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000375 single basic block. All transformations keep the code size the same or
376 smaller. For those that reduce size, the gaps are initially filled with
377 NOPs. Later those NOPs are removed and the jump addresses retargeted in
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000378 a single pass. Line numbering is adjusted accordingly. */
379
380PyObject *
381PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
382 PyObject *lineno_obj)
383{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000384 Py_ssize_t i, j, codelen;
385 int nops, h, adj;
386 int tgt, tgttgt, opcode;
387 unsigned char *codestr = NULL;
388 unsigned char *lineno;
389 int *addrmap = NULL;
390 int new_line, cum_orig_line, last_line, tabsiz;
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100391 PyObject **const_stack = NULL;
392 Py_ssize_t *load_const_stack = NULL;
393 Py_ssize_t const_stack_top = -1;
394 Py_ssize_t const_stack_size = 0;
395 int in_consts = 0; /* whether we are in a LOAD_CONST sequence */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000396 unsigned int *blocks = NULL;
397 char *name;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000398
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000399 /* Bail out if an exception is set */
400 if (PyErr_Occurred())
401 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000402
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000403 /* Bypass optimization when the lineno table is too complex */
404 assert(PyBytes_Check(lineno_obj));
405 lineno = (unsigned char*)PyBytes_AS_STRING(lineno_obj);
406 tabsiz = PyBytes_GET_SIZE(lineno_obj);
407 if (memchr(lineno, 255, tabsiz) != NULL)
408 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000409
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000410 /* Avoid situations where jump retargeting could overflow */
411 assert(PyBytes_Check(code));
412 codelen = PyBytes_GET_SIZE(code);
413 if (codelen > 32700)
414 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000415
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000416 /* Make a modifiable copy of the code string */
417 codestr = (unsigned char *)PyMem_Malloc(codelen);
418 if (codestr == NULL)
419 goto exitError;
420 codestr = (unsigned char *)memcpy(codestr,
421 PyBytes_AS_STRING(code), codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000422
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000423 /* Verify that RETURN_VALUE terminates the codestring. This allows
424 the various transformation patterns to look ahead several
425 instructions without additional checks to make sure they are not
426 looking beyond the end of the code string.
427 */
428 if (codestr[codelen-1] != RETURN_VALUE)
429 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000430
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000431 /* Mapping to new jump targets after NOPs are removed */
432 addrmap = (int *)PyMem_Malloc(codelen * sizeof(int));
433 if (addrmap == NULL)
434 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000435
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000436 blocks = markblocks(codestr, codelen);
437 if (blocks == NULL)
438 goto exitError;
439 assert(PyList_Check(consts));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000440
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100441 CONST_STACK_CREATE();
442
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000443 for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
444 reoptimize_current:
445 opcode = codestr[i];
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000446
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100447 if (!in_consts) {
448 CONST_STACK_RESET();
449 }
450 in_consts = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000451
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000452 switch (opcode) {
453 /* Replace UNARY_NOT POP_JUMP_IF_FALSE
454 with POP_JUMP_IF_TRUE */
455 case UNARY_NOT:
456 if (codestr[i+1] != POP_JUMP_IF_FALSE
457 || !ISBASICBLOCK(blocks,i,4))
458 continue;
459 j = GETARG(codestr, i+1);
460 codestr[i] = POP_JUMP_IF_TRUE;
461 SETARG(codestr, i, j);
462 codestr[i+3] = NOP;
463 goto reoptimize_current;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000464
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000465 /* not a is b --> a is not b
466 not a in b --> a not in b
467 not a is not b --> a is b
468 not a not in b --> a in b
469 */
470 case COMPARE_OP:
471 j = GETARG(codestr, i);
472 if (j < 6 || j > 9 ||
473 codestr[i+3] != UNARY_NOT ||
474 !ISBASICBLOCK(blocks,i,4))
475 continue;
476 SETARG(codestr, i, (j^1));
477 codestr[i+3] = NOP;
478 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000479
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000480 /* Replace LOAD_GLOBAL/LOAD_NAME None/True/False
481 with LOAD_CONST None/True/False */
482 case LOAD_NAME:
483 case LOAD_GLOBAL:
484 j = GETARG(codestr, i);
485 name = _PyUnicode_AsString(PyTuple_GET_ITEM(names, j));
486 h = load_global(codestr, i, name, consts);
487 if (h < 0)
488 goto exitError;
489 else if (h == 0)
490 continue;
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100491 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000492 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000493
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000494 /* Skip over LOAD_CONST trueconst
495 POP_JUMP_IF_FALSE xx. This improves
496 "while 1" performance. */
497 case LOAD_CONST:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100498 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000499 j = GETARG(codestr, i);
500 if (codestr[i+3] != POP_JUMP_IF_FALSE ||
501 !ISBASICBLOCK(blocks,i,6) ||
502 !PyObject_IsTrue(PyList_GET_ITEM(consts, j)))
503 continue;
504 memset(codestr+i, NOP, 6);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100505 CONST_STACK_RESET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000506 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000507
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000508 /* Try to fold tuples of constants (includes a case for lists and sets
509 which are only used for "in" and "not in" tests).
510 Skip over BUILD_SEQN 1 UNPACK_SEQN 1.
511 Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2.
512 Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */
513 case BUILD_TUPLE:
514 case BUILD_LIST:
515 case BUILD_SET:
516 j = GETARG(codestr, i);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100517 if (j == 0)
518 break;
519 h = CONST_STACK_OP_LASTN(j);
520 assert((h >= 0 || CONST_STACK_LEN() < j));
521 if (h >= 0 && j > 0 && j <= CONST_STACK_LEN() &&
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000522 ((opcode == BUILD_TUPLE &&
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100523 ISBASICBLOCK(blocks, h, i-h+3)) ||
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000524 ((opcode == BUILD_LIST || opcode == BUILD_SET) &&
525 codestr[i+3]==COMPARE_OP &&
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100526 ISBASICBLOCK(blocks, h, i-h+6) &&
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000527 (GETARG(codestr,i+3)==6 ||
528 GETARG(codestr,i+3)==7))) &&
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100529 tuple_of_constants(&codestr[i], j, consts, CONST_STACK_LASTN(j))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000530 assert(codestr[i] == LOAD_CONST);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100531 memset(&codestr[h], NOP, i - h);
532 CONST_STACK_POP(j);
533 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000534 break;
535 }
536 if (codestr[i+3] != UNPACK_SEQUENCE ||
537 !ISBASICBLOCK(blocks,i,6) ||
Raymond Hettinger0661e912011-03-15 15:03:36 -0700538 j != GETARG(codestr, i+3) ||
539 opcode == BUILD_SET)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000540 continue;
541 if (j == 1) {
542 memset(codestr+i, NOP, 6);
543 } else if (j == 2) {
544 codestr[i] = ROT_TWO;
545 memset(codestr+i+1, NOP, 5);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100546 CONST_STACK_RESET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000547 } else if (j == 3) {
548 codestr[i] = ROT_THREE;
549 codestr[i+1] = ROT_TWO;
550 memset(codestr+i+2, NOP, 4);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100551 CONST_STACK_RESET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000552 }
553 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000554
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000555 /* Fold binary ops on constants.
556 LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */
557 case BINARY_POWER:
558 case BINARY_MULTIPLY:
559 case BINARY_TRUE_DIVIDE:
560 case BINARY_FLOOR_DIVIDE:
561 case BINARY_MODULO:
562 case BINARY_ADD:
563 case BINARY_SUBTRACT:
564 case BINARY_SUBSCR:
565 case BINARY_LSHIFT:
566 case BINARY_RSHIFT:
567 case BINARY_AND:
568 case BINARY_XOR:
569 case BINARY_OR:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100570 /* NOTE: LOAD_CONST is saved at `i-2` since it has an arg
571 while BINOP hasn't */
572 h = CONST_STACK_OP_LASTN(2);
573 assert((h >= 0 || CONST_STACK_LEN() < 2));
574 if (h >= 0 &&
575 ISBASICBLOCK(blocks, h, i-h+1) &&
576 fold_binops_on_constants(&codestr[i], consts, CONST_STACK_LASTN(2))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000577 i -= 2;
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100578 memset(&codestr[h], NOP, i - h);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000579 assert(codestr[i] == LOAD_CONST);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100580 CONST_STACK_POP(2);
581 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000582 }
583 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000584
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000585 /* Fold unary ops on constants.
586 LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */
587 case UNARY_NEGATIVE:
588 case UNARY_INVERT:
589 case UNARY_POSITIVE:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100590 h = CONST_STACK_OP_LASTN(1);
591 assert((h >= 0 || CONST_STACK_LEN() < 1));
592 if (h >= 0 &&
593 ISBASICBLOCK(blocks, h, i-h+1) &&
594 fold_unaryops_on_constants(&codestr[i-3], consts, CONST_STACK_TOP())) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000595 i -= 2;
596 assert(codestr[i] == LOAD_CONST);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100597 CONST_STACK_POP(1);
598 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000599 }
600 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000601
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000602 /* Simplify conditional jump to conditional jump where the
603 result of the first test implies the success of a similar
604 test or the failure of the opposite test.
605 Arises in code like:
606 "if a and b:"
607 "if a or b:"
608 "a and b or c"
609 "(a and b) and c"
610 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z
611 --> x:JUMP_IF_FALSE_OR_POP z
612 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z
613 --> x:POP_JUMP_IF_FALSE y+3
614 where y+3 is the instruction following the second test.
615 */
616 case JUMP_IF_FALSE_OR_POP:
617 case JUMP_IF_TRUE_OR_POP:
618 tgt = GETJUMPTGT(codestr, i);
619 j = codestr[tgt];
620 if (CONDITIONAL_JUMP(j)) {
621 /* NOTE: all possible jumps here are
622 absolute! */
623 if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) {
624 /* The second jump will be
625 taken iff the first is. */
626 tgttgt = GETJUMPTGT(codestr, tgt);
627 /* The current opcode inherits
628 its target's stack behaviour */
629 codestr[i] = j;
630 SETARG(codestr, i, tgttgt);
631 goto reoptimize_current;
632 } else {
633 /* The second jump is not taken
634 if the first is (so jump past
635 it), and all conditional
636 jumps pop their argument when
637 they're not taken (so change
638 the first jump to pop its
639 argument when it's taken). */
640 if (JUMPS_ON_TRUE(opcode))
641 codestr[i] = POP_JUMP_IF_TRUE;
642 else
643 codestr[i] = POP_JUMP_IF_FALSE;
644 SETARG(codestr, i, (tgt + 3));
645 goto reoptimize_current;
646 }
647 }
648 /* Intentional fallthrough */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000649
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000650 /* Replace jumps to unconditional jumps */
651 case POP_JUMP_IF_FALSE:
652 case POP_JUMP_IF_TRUE:
653 case FOR_ITER:
654 case JUMP_FORWARD:
655 case JUMP_ABSOLUTE:
656 case CONTINUE_LOOP:
657 case SETUP_LOOP:
658 case SETUP_EXCEPT:
659 case SETUP_FINALLY:
660 case SETUP_WITH:
661 tgt = GETJUMPTGT(codestr, i);
662 /* Replace JUMP_* to a RETURN into just a RETURN */
663 if (UNCONDITIONAL_JUMP(opcode) &&
664 codestr[tgt] == RETURN_VALUE) {
665 codestr[i] = RETURN_VALUE;
666 memset(codestr+i+1, NOP, 2);
667 continue;
668 }
669 if (!UNCONDITIONAL_JUMP(codestr[tgt]))
670 continue;
671 tgttgt = GETJUMPTGT(codestr, tgt);
672 if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */
673 opcode = JUMP_ABSOLUTE;
674 if (!ABSOLUTE_JUMP(opcode))
675 tgttgt -= i + 3; /* Calc relative jump addr */
676 if (tgttgt < 0) /* No backward relative jumps */
677 continue;
678 codestr[i] = opcode;
679 SETARG(codestr, i, tgttgt);
680 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000681
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000682 case EXTENDED_ARG:
683 if (codestr[i+3] != MAKE_FUNCTION)
684 goto exitUnchanged;
685 /* don't visit MAKE_FUNCTION as GETARG will be wrong */
686 i += 3;
687 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000688
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000689 /* Replace RETURN LOAD_CONST None RETURN with just RETURN */
690 /* Remove unreachable JUMPs after RETURN */
691 case RETURN_VALUE:
692 if (i+4 >= codelen)
693 continue;
694 if (codestr[i+4] == RETURN_VALUE &&
695 ISBASICBLOCK(blocks,i,5))
696 memset(codestr+i+1, NOP, 4);
697 else if (UNCONDITIONAL_JUMP(codestr[i+1]) &&
698 ISBASICBLOCK(blocks,i,4))
699 memset(codestr+i+1, NOP, 3);
700 break;
701 }
702 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000703
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000704 /* Fixup linenotab */
705 for (i=0, nops=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
706 addrmap[i] = i - nops;
707 if (codestr[i] == NOP)
708 nops++;
709 }
710 cum_orig_line = 0;
711 last_line = 0;
712 for (i=0 ; i < tabsiz ; i+=2) {
713 cum_orig_line += lineno[i];
714 new_line = addrmap[cum_orig_line];
715 assert (new_line - last_line < 255);
716 lineno[i] =((unsigned char)(new_line - last_line));
717 last_line = new_line;
718 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000719
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000720 /* Remove NOPs and fixup jump targets */
721 for (i=0, h=0 ; i<codelen ; ) {
722 opcode = codestr[i];
723 switch (opcode) {
724 case NOP:
725 i++;
726 continue;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000727
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000728 case JUMP_ABSOLUTE:
729 case CONTINUE_LOOP:
730 case POP_JUMP_IF_FALSE:
731 case POP_JUMP_IF_TRUE:
732 case JUMP_IF_FALSE_OR_POP:
733 case JUMP_IF_TRUE_OR_POP:
734 j = addrmap[GETARG(codestr, i)];
735 SETARG(codestr, i, j);
736 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000737
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000738 case FOR_ITER:
739 case JUMP_FORWARD:
740 case SETUP_LOOP:
741 case SETUP_EXCEPT:
742 case SETUP_FINALLY:
743 case SETUP_WITH:
744 j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3;
745 SETARG(codestr, i, j);
746 break;
747 }
748 adj = CODESIZE(opcode);
749 while (adj--)
750 codestr[h++] = codestr[i++];
751 }
752 assert(h + nops == codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000753
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000754 code = PyBytes_FromStringAndSize((char *)codestr, h);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100755 CONST_STACK_DELETE();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000756 PyMem_Free(addrmap);
757 PyMem_Free(codestr);
758 PyMem_Free(blocks);
759 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000760
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000761 exitError:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000762 code = NULL;
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000763
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000764 exitUnchanged:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100765 CONST_STACK_DELETE();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000766 if (blocks != NULL)
767 PyMem_Free(blocks);
768 if (addrmap != NULL)
769 PyMem_Free(addrmap);
770 if (codestr != NULL)
771 PyMem_Free(codestr);
772 Py_XINCREF(code);
773 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000774}