blob: 4e657fa176eda1f153d32e229b5bd84177545d4d [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))
Serhiy Storchaka67559bf2015-02-16 21:13:24 +020021#define SETARG(arr, i, val) do { \
22 assert(0 <= val && val <= 0xffff); \
23 arr[i+2] = (unsigned char)(((unsigned int)val)>>8); \
24 arr[i+1] = (unsigned char)(((unsigned int)val) & 255); \
25} while(0)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000026#define CODESIZE(op) (HAS_ARG(op) ? 3 : 1)
27#define ISBASICBLOCK(blocks, start, bytes) \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000028 (blocks[start]==blocks[start+bytes-1])
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000029
Antoine Pitrou17b880a2011-03-11 17:27:02 +010030
31#define CONST_STACK_CREATE() { \
32 const_stack_size = 256; \
33 const_stack = PyMem_New(PyObject *, const_stack_size); \
34 load_const_stack = PyMem_New(Py_ssize_t, const_stack_size); \
35 if (!const_stack || !load_const_stack) { \
36 PyErr_NoMemory(); \
37 goto exitError; \
38 } \
39 }
40
41#define CONST_STACK_DELETE() do { \
42 if (const_stack) \
43 PyMem_Free(const_stack); \
44 if (load_const_stack) \
45 PyMem_Free(load_const_stack); \
46 } while(0)
47
48#define CONST_STACK_LEN() (const_stack_top + 1)
49
50#define CONST_STACK_PUSH_OP(i) do { \
51 PyObject *_x; \
52 assert(codestr[i] == LOAD_CONST); \
53 assert(PyList_GET_SIZE(consts) > GETARG(codestr, i)); \
54 _x = PyList_GET_ITEM(consts, GETARG(codestr, i)); \
55 if (++const_stack_top >= const_stack_size) { \
56 const_stack_size *= 2; \
57 PyMem_Resize(const_stack, PyObject *, const_stack_size); \
58 PyMem_Resize(load_const_stack, Py_ssize_t, const_stack_size); \
59 if (!const_stack || !load_const_stack) { \
60 PyErr_NoMemory(); \
61 goto exitError; \
62 } \
63 } \
64 load_const_stack[const_stack_top] = i; \
65 const_stack[const_stack_top] = _x; \
66 in_consts = 1; \
67 } while(0)
68
69#define CONST_STACK_RESET() do { \
70 const_stack_top = -1; \
71 } while(0)
72
Stefan Krah472d2802011-09-21 19:08:39 +020073#define CONST_STACK_TOP() \
Antoine Pitrou17b880a2011-03-11 17:27:02 +010074 const_stack[const_stack_top]
75
76#define CONST_STACK_LASTN(i) \
77 &const_stack[const_stack_top - i + 1]
78
79#define CONST_STACK_POP(i) do { \
80 assert(const_stack_top + 1 >= i); \
81 const_stack_top -= i; \
82 } while(0)
83
84#define CONST_STACK_OP_LASTN(i) \
85 ((const_stack_top >= i - 1) ? load_const_stack[const_stack_top - i + 1] : -1)
86
87
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000088/* Replace LOAD_CONST c1. LOAD_CONST c2 ... LOAD_CONST cn BUILD_TUPLE n
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000089 with LOAD_CONST (c1, c2, ... cn).
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000090 The consts table must still be in list form so that the
91 new constant (c1, c2, ... cn) can be appended.
92 Called with codestr pointing to the first LOAD_CONST.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000093 Bails out with no change if one or more of the LOAD_CONSTs is missing.
Antoine Pitroub7fbcd32010-01-16 18:37:38 +000094 Also works for BUILD_LIST and BUILT_SET when followed by an "in" or "not in"
95 test; for BUILD_SET it assembles a frozenset rather than a tuple.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000096*/
97static int
Antoine Pitrou17b880a2011-03-11 17:27:02 +010098tuple_of_constants(unsigned char *codestr, Py_ssize_t n,
99 PyObject *consts, PyObject **objs)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000100{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000101 PyObject *newconst, *constant;
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100102 Py_ssize_t i, len_consts;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000103
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000104 /* Pre-conditions */
105 assert(PyList_CheckExact(consts));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000106
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000107 /* Buildup new tuple of constants */
108 newconst = PyTuple_New(n);
109 if (newconst == NULL)
110 return 0;
111 len_consts = PyList_GET_SIZE(consts);
112 for (i=0 ; i<n ; i++) {
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100113 constant = objs[i];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000114 Py_INCREF(constant);
115 PyTuple_SET_ITEM(newconst, i, constant);
116 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000117
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000118 /* If it's a BUILD_SET, use the PyTuple we just built to create a
119 PyFrozenSet, and use that as the constant instead: */
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100120 if (codestr[0] == BUILD_SET) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000121 PyObject *tuple = newconst;
122 newconst = PyFrozenSet_New(tuple);
123 Py_DECREF(tuple);
124 if (newconst == NULL)
125 return 0;
126 }
Antoine Pitroub7fbcd32010-01-16 18:37:38 +0000127
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000128 /* Append folded constant onto consts */
129 if (PyList_Append(consts, newconst)) {
130 Py_DECREF(newconst);
131 return 0;
132 }
133 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000134
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000135 /* Write NOPs over old LOAD_CONSTS and
136 add a new LOAD_CONST newconst on top of the BUILD_TUPLE n */
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100137 codestr[0] = LOAD_CONST;
138 SETARG(codestr, 0, len_consts);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000139 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000140}
141
142/* Replace LOAD_CONST c1. LOAD_CONST c2 BINOP
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000143 with LOAD_CONST binop(c1,c2)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000144 The consts table must still be in list form so that the
145 new constant can be appended.
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100146 Called with codestr pointing to the BINOP.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000147 Abandons the transformation if the folding fails (i.e. 1+'a').
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000148 If the new constant is a sequence, only folds when the size
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000149 is below a threshold value. That keeps pyc files from
150 becoming large in the presence of code like: (None,)*1000.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000151*/
152static int
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100153fold_binops_on_constants(unsigned char *codestr, PyObject *consts, PyObject **objs)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000154{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000155 PyObject *newconst, *v, *w;
156 Py_ssize_t len_consts, size;
157 int opcode;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000158
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000159 /* Pre-conditions */
160 assert(PyList_CheckExact(consts));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000161
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000162 /* Create new constant */
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100163 v = objs[0];
164 w = objs[1];
165 opcode = codestr[0];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000166 switch (opcode) {
167 case BINARY_POWER:
168 newconst = PyNumber_Power(v, w, Py_None);
169 break;
170 case BINARY_MULTIPLY:
171 newconst = PyNumber_Multiply(v, w);
172 break;
173 case BINARY_TRUE_DIVIDE:
174 newconst = PyNumber_TrueDivide(v, w);
175 break;
176 case BINARY_FLOOR_DIVIDE:
177 newconst = PyNumber_FloorDivide(v, w);
178 break;
179 case BINARY_MODULO:
180 newconst = PyNumber_Remainder(v, w);
181 break;
182 case BINARY_ADD:
183 newconst = PyNumber_Add(v, w);
184 break;
185 case BINARY_SUBTRACT:
186 newconst = PyNumber_Subtract(v, w);
187 break;
188 case BINARY_SUBSCR:
189 newconst = PyObject_GetItem(v, w);
190 break;
191 case BINARY_LSHIFT:
192 newconst = PyNumber_Lshift(v, w);
193 break;
194 case BINARY_RSHIFT:
195 newconst = PyNumber_Rshift(v, w);
196 break;
197 case BINARY_AND:
198 newconst = PyNumber_And(v, w);
199 break;
200 case BINARY_XOR:
201 newconst = PyNumber_Xor(v, w);
202 break;
203 case BINARY_OR:
204 newconst = PyNumber_Or(v, w);
205 break;
206 default:
207 /* Called with an unknown opcode */
208 PyErr_Format(PyExc_SystemError,
209 "unexpected binary operation %d on a constant",
210 opcode);
211 return 0;
212 }
213 if (newconst == NULL) {
Raymond Hettinger819a0642010-08-22 08:39:49 +0000214 if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
215 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000216 return 0;
217 }
218 size = PyObject_Size(newconst);
Raymond Hettinger819a0642010-08-22 08:39:49 +0000219 if (size == -1) {
220 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
221 return 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000222 PyErr_Clear();
Raymond Hettinger819a0642010-08-22 08:39:49 +0000223 } else if (size > 20) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000224 Py_DECREF(newconst);
225 return 0;
226 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000227
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000228 /* Append folded constant into consts table */
229 len_consts = PyList_GET_SIZE(consts);
230 if (PyList_Append(consts, newconst)) {
231 Py_DECREF(newconst);
232 return 0;
233 }
234 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000235
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000236 /* Write NOP NOP NOP NOP LOAD_CONST newconst */
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100237 codestr[-2] = LOAD_CONST;
238 SETARG(codestr, -2, len_consts);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000239 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000240}
241
242static int
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100243fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts, PyObject *v)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000244{
Mark Dickinson7c9e8032011-03-23 17:59:37 +0000245 PyObject *newconst;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000246 Py_ssize_t len_consts;
247 int opcode;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000248
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000249 /* Pre-conditions */
250 assert(PyList_CheckExact(consts));
251 assert(codestr[0] == LOAD_CONST);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000252
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000253 /* Create new constant */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000254 opcode = codestr[3];
255 switch (opcode) {
256 case UNARY_NEGATIVE:
Mark Dickinson7c9e8032011-03-23 17:59:37 +0000257 newconst = PyNumber_Negative(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000258 break;
259 case UNARY_INVERT:
260 newconst = PyNumber_Invert(v);
261 break;
262 case UNARY_POSITIVE:
263 newconst = PyNumber_Positive(v);
264 break;
265 default:
266 /* Called with an unknown opcode */
267 PyErr_Format(PyExc_SystemError,
268 "unexpected unary operation %d on a constant",
269 opcode);
270 return 0;
271 }
272 if (newconst == NULL) {
Raymond Hettinger819a0642010-08-22 08:39:49 +0000273 if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
274 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000275 return 0;
276 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000277
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000278 /* Append folded constant into consts table */
279 len_consts = PyList_GET_SIZE(consts);
280 if (PyList_Append(consts, newconst)) {
281 Py_DECREF(newconst);
Victor Stinnerc82729e2013-11-14 01:21:00 +0100282 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000283 return 0;
284 }
285 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000286
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000287 /* Write NOP LOAD_CONST newconst */
288 codestr[0] = NOP;
289 codestr[1] = LOAD_CONST;
290 SETARG(codestr, 1, len_consts);
291 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000292}
293
294static unsigned int *
Christian Heimescc47b052008-03-25 14:56:36 +0000295markblocks(unsigned char *code, Py_ssize_t len)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000296{
Serhiy Storchaka1a1ff292015-02-16 13:28:22 +0200297 unsigned int *blocks = PyMem_New(unsigned int, len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000298 int i,j, opcode, blockcnt = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000299
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000300 if (blocks == NULL) {
301 PyErr_NoMemory();
302 return NULL;
303 }
304 memset(blocks, 0, len*sizeof(int));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000305
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000306 /* Mark labels in the first pass */
307 for (i=0 ; i<len ; i+=CODESIZE(opcode)) {
308 opcode = code[i];
309 switch (opcode) {
310 case FOR_ITER:
311 case JUMP_FORWARD:
312 case JUMP_IF_FALSE_OR_POP:
313 case JUMP_IF_TRUE_OR_POP:
314 case POP_JUMP_IF_FALSE:
315 case POP_JUMP_IF_TRUE:
316 case JUMP_ABSOLUTE:
317 case CONTINUE_LOOP:
318 case SETUP_LOOP:
319 case SETUP_EXCEPT:
320 case SETUP_FINALLY:
321 case SETUP_WITH:
Yury Selivanov75445082015-05-11 22:57:16 -0400322 case SETUP_ASYNC_WITH:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000323 j = GETJUMPTGT(code, i);
324 blocks[j] = 1;
325 break;
326 }
327 }
328 /* Build block numbers in the second pass */
329 for (i=0 ; i<len ; i++) {
330 blockcnt += blocks[i]; /* increment blockcnt over labels */
331 blocks[i] = blockcnt;
332 }
333 return blocks;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000334}
335
336/* Perform basic peephole optimizations to components of a code object.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000337 The consts object should still be in list form to allow new constants
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000338 to be appended.
339
Guido van Rossum0240b922007-02-26 21:23:50 +0000340 To keep the optimizer simple, it bails out (does nothing) for code that
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000341 has a length over 32,700, and does not calculate extended arguments.
Guido van Rossum0240b922007-02-26 21:23:50 +0000342 That allows us to avoid overflow and sign issues. Likewise, it bails when
343 the lineno table has complex encoding for gaps >= 255. EXTENDED_ARG can
344 appear before MAKE_FUNCTION; in this case both opcodes are skipped.
345 EXTENDED_ARG preceding any other opcode causes the optimizer to bail.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000346
Martin Panter46f50722016-05-26 05:35:26 +0000347 Optimizations are restricted to simple transformations occurring within a
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000348 single basic block. All transformations keep the code size the same or
349 smaller. For those that reduce size, the gaps are initially filled with
350 NOPs. Later those NOPs are removed and the jump addresses retargeted in
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000351 a single pass. Line numbering is adjusted accordingly. */
352
353PyObject *
354PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
355 PyObject *lineno_obj)
356{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000357 Py_ssize_t i, j, codelen;
358 int nops, h, adj;
359 int tgt, tgttgt, opcode;
360 unsigned char *codestr = NULL;
361 unsigned char *lineno;
362 int *addrmap = NULL;
Serhiy Storchaka67559bf2015-02-16 21:13:24 +0200363 int new_line, cum_orig_line, last_line;
364 Py_ssize_t tabsiz;
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100365 PyObject **const_stack = NULL;
366 Py_ssize_t *load_const_stack = NULL;
367 Py_ssize_t const_stack_top = -1;
368 Py_ssize_t const_stack_size = 0;
369 int in_consts = 0; /* whether we are in a LOAD_CONST sequence */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000370 unsigned int *blocks = NULL;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000371
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000372 /* Bail out if an exception is set */
373 if (PyErr_Occurred())
374 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000375
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000376 /* Bypass optimization when the lineno table is too complex */
377 assert(PyBytes_Check(lineno_obj));
378 lineno = (unsigned char*)PyBytes_AS_STRING(lineno_obj);
379 tabsiz = PyBytes_GET_SIZE(lineno_obj);
380 if (memchr(lineno, 255, tabsiz) != NULL)
381 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000382
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000383 /* Avoid situations where jump retargeting could overflow */
384 assert(PyBytes_Check(code));
385 codelen = PyBytes_GET_SIZE(code);
386 if (codelen > 32700)
387 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000388
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000389 /* Make a modifiable copy of the code string */
390 codestr = (unsigned char *)PyMem_Malloc(codelen);
Victor Stinnere0af3a82013-07-09 00:32:04 +0200391 if (codestr == NULL) {
392 PyErr_NoMemory();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000393 goto exitError;
Victor Stinnere0af3a82013-07-09 00:32:04 +0200394 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000395 codestr = (unsigned char *)memcpy(codestr,
396 PyBytes_AS_STRING(code), codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000397
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000398 /* Verify that RETURN_VALUE terminates the codestring. This allows
399 the various transformation patterns to look ahead several
400 instructions without additional checks to make sure they are not
401 looking beyond the end of the code string.
402 */
403 if (codestr[codelen-1] != RETURN_VALUE)
404 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000405
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000406 /* Mapping to new jump targets after NOPs are removed */
Serhiy Storchaka1a1ff292015-02-16 13:28:22 +0200407 addrmap = PyMem_New(int, codelen);
Victor Stinnere0af3a82013-07-09 00:32:04 +0200408 if (addrmap == NULL) {
409 PyErr_NoMemory();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000410 goto exitError;
Victor Stinnere0af3a82013-07-09 00:32:04 +0200411 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000412
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000413 blocks = markblocks(codestr, codelen);
414 if (blocks == NULL)
415 goto exitError;
416 assert(PyList_Check(consts));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000417
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100418 CONST_STACK_CREATE();
419
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000420 for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
421 reoptimize_current:
422 opcode = codestr[i];
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000423
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100424 if (!in_consts) {
425 CONST_STACK_RESET();
426 }
427 in_consts = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000428
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000429 switch (opcode) {
430 /* Replace UNARY_NOT POP_JUMP_IF_FALSE
431 with POP_JUMP_IF_TRUE */
432 case UNARY_NOT:
433 if (codestr[i+1] != POP_JUMP_IF_FALSE
434 || !ISBASICBLOCK(blocks,i,4))
435 continue;
436 j = GETARG(codestr, i+1);
437 codestr[i] = POP_JUMP_IF_TRUE;
438 SETARG(codestr, i, j);
439 codestr[i+3] = NOP;
440 goto reoptimize_current;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000441
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000442 /* not a is b --> a is not b
443 not a in b --> a not in b
444 not a is not b --> a is b
445 not a not in b --> a in b
446 */
447 case COMPARE_OP:
448 j = GETARG(codestr, i);
449 if (j < 6 || j > 9 ||
450 codestr[i+3] != UNARY_NOT ||
451 !ISBASICBLOCK(blocks,i,4))
452 continue;
453 SETARG(codestr, i, (j^1));
454 codestr[i+3] = NOP;
455 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000456
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000457 /* Skip over LOAD_CONST trueconst
458 POP_JUMP_IF_FALSE xx. This improves
459 "while 1" performance. */
460 case LOAD_CONST:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100461 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000462 j = GETARG(codestr, i);
463 if (codestr[i+3] != POP_JUMP_IF_FALSE ||
464 !ISBASICBLOCK(blocks,i,6) ||
465 !PyObject_IsTrue(PyList_GET_ITEM(consts, j)))
466 continue;
467 memset(codestr+i, NOP, 6);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100468 CONST_STACK_RESET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000469 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000470
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000471 /* Try to fold tuples of constants (includes a case for lists and sets
472 which are only used for "in" and "not in" tests).
473 Skip over BUILD_SEQN 1 UNPACK_SEQN 1.
474 Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2.
475 Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */
476 case BUILD_TUPLE:
477 case BUILD_LIST:
478 case BUILD_SET:
479 j = GETARG(codestr, i);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100480 if (j == 0)
481 break;
482 h = CONST_STACK_OP_LASTN(j);
483 assert((h >= 0 || CONST_STACK_LEN() < j));
484 if (h >= 0 && j > 0 && j <= CONST_STACK_LEN() &&
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000485 ((opcode == BUILD_TUPLE &&
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100486 ISBASICBLOCK(blocks, h, i-h+3)) ||
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000487 ((opcode == BUILD_LIST || opcode == BUILD_SET) &&
488 codestr[i+3]==COMPARE_OP &&
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100489 ISBASICBLOCK(blocks, h, i-h+6) &&
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000490 (GETARG(codestr,i+3)==6 ||
491 GETARG(codestr,i+3)==7))) &&
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100492 tuple_of_constants(&codestr[i], j, consts, CONST_STACK_LASTN(j))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000493 assert(codestr[i] == LOAD_CONST);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100494 memset(&codestr[h], NOP, i - h);
495 CONST_STACK_POP(j);
496 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000497 break;
498 }
499 if (codestr[i+3] != UNPACK_SEQUENCE ||
500 !ISBASICBLOCK(blocks,i,6) ||
Raymond Hettinger0661e912011-03-15 15:03:36 -0700501 j != GETARG(codestr, i+3) ||
502 opcode == BUILD_SET)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000503 continue;
504 if (j == 1) {
505 memset(codestr+i, NOP, 6);
506 } else if (j == 2) {
507 codestr[i] = ROT_TWO;
508 memset(codestr+i+1, NOP, 5);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100509 CONST_STACK_RESET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000510 } else if (j == 3) {
511 codestr[i] = ROT_THREE;
512 codestr[i+1] = ROT_TWO;
513 memset(codestr+i+2, NOP, 4);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100514 CONST_STACK_RESET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000515 }
516 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000517
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000518 /* Fold binary ops on constants.
519 LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */
520 case BINARY_POWER:
521 case BINARY_MULTIPLY:
522 case BINARY_TRUE_DIVIDE:
523 case BINARY_FLOOR_DIVIDE:
524 case BINARY_MODULO:
525 case BINARY_ADD:
526 case BINARY_SUBTRACT:
527 case BINARY_SUBSCR:
528 case BINARY_LSHIFT:
529 case BINARY_RSHIFT:
530 case BINARY_AND:
531 case BINARY_XOR:
532 case BINARY_OR:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100533 /* NOTE: LOAD_CONST is saved at `i-2` since it has an arg
534 while BINOP hasn't */
535 h = CONST_STACK_OP_LASTN(2);
536 assert((h >= 0 || CONST_STACK_LEN() < 2));
537 if (h >= 0 &&
538 ISBASICBLOCK(blocks, h, i-h+1) &&
539 fold_binops_on_constants(&codestr[i], consts, CONST_STACK_LASTN(2))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000540 i -= 2;
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100541 memset(&codestr[h], NOP, i - h);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000542 assert(codestr[i] == LOAD_CONST);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100543 CONST_STACK_POP(2);
544 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000545 }
546 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000547
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000548 /* Fold unary ops on constants.
549 LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */
550 case UNARY_NEGATIVE:
551 case UNARY_INVERT:
552 case UNARY_POSITIVE:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100553 h = CONST_STACK_OP_LASTN(1);
554 assert((h >= 0 || CONST_STACK_LEN() < 1));
555 if (h >= 0 &&
556 ISBASICBLOCK(blocks, h, i-h+1) &&
557 fold_unaryops_on_constants(&codestr[i-3], consts, CONST_STACK_TOP())) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000558 i -= 2;
559 assert(codestr[i] == LOAD_CONST);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100560 CONST_STACK_POP(1);
561 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000562 }
563 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000564
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000565 /* Simplify conditional jump to conditional jump where the
566 result of the first test implies the success of a similar
567 test or the failure of the opposite test.
568 Arises in code like:
569 "if a and b:"
570 "if a or b:"
571 "a and b or c"
572 "(a and b) and c"
573 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z
574 --> x:JUMP_IF_FALSE_OR_POP z
575 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z
576 --> x:POP_JUMP_IF_FALSE y+3
577 where y+3 is the instruction following the second test.
578 */
579 case JUMP_IF_FALSE_OR_POP:
580 case JUMP_IF_TRUE_OR_POP:
581 tgt = GETJUMPTGT(codestr, i);
582 j = codestr[tgt];
583 if (CONDITIONAL_JUMP(j)) {
584 /* NOTE: all possible jumps here are
585 absolute! */
586 if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) {
587 /* The second jump will be
588 taken iff the first is. */
589 tgttgt = GETJUMPTGT(codestr, tgt);
590 /* The current opcode inherits
591 its target's stack behaviour */
592 codestr[i] = j;
593 SETARG(codestr, i, tgttgt);
594 goto reoptimize_current;
595 } else {
596 /* The second jump is not taken
597 if the first is (so jump past
598 it), and all conditional
599 jumps pop their argument when
600 they're not taken (so change
601 the first jump to pop its
602 argument when it's taken). */
603 if (JUMPS_ON_TRUE(opcode))
604 codestr[i] = POP_JUMP_IF_TRUE;
605 else
606 codestr[i] = POP_JUMP_IF_FALSE;
607 SETARG(codestr, i, (tgt + 3));
608 goto reoptimize_current;
609 }
610 }
611 /* Intentional fallthrough */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000612
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000613 /* Replace jumps to unconditional jumps */
614 case POP_JUMP_IF_FALSE:
615 case POP_JUMP_IF_TRUE:
616 case FOR_ITER:
617 case JUMP_FORWARD:
618 case JUMP_ABSOLUTE:
619 case CONTINUE_LOOP:
620 case SETUP_LOOP:
621 case SETUP_EXCEPT:
622 case SETUP_FINALLY:
623 case SETUP_WITH:
Yury Selivanov75445082015-05-11 22:57:16 -0400624 case SETUP_ASYNC_WITH:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000625 tgt = GETJUMPTGT(codestr, i);
626 /* Replace JUMP_* to a RETURN into just a RETURN */
627 if (UNCONDITIONAL_JUMP(opcode) &&
628 codestr[tgt] == RETURN_VALUE) {
629 codestr[i] = RETURN_VALUE;
630 memset(codestr+i+1, NOP, 2);
631 continue;
632 }
633 if (!UNCONDITIONAL_JUMP(codestr[tgt]))
634 continue;
635 tgttgt = GETJUMPTGT(codestr, tgt);
636 if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */
637 opcode = JUMP_ABSOLUTE;
638 if (!ABSOLUTE_JUMP(opcode))
639 tgttgt -= i + 3; /* Calc relative jump addr */
640 if (tgttgt < 0) /* No backward relative jumps */
641 continue;
642 codestr[i] = opcode;
643 SETARG(codestr, i, tgttgt);
644 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000645
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000646 case EXTENDED_ARG:
647 if (codestr[i+3] != MAKE_FUNCTION)
648 goto exitUnchanged;
649 /* don't visit MAKE_FUNCTION as GETARG will be wrong */
650 i += 3;
651 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000652
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000653 /* Replace RETURN LOAD_CONST None RETURN with just RETURN */
654 /* Remove unreachable JUMPs after RETURN */
655 case RETURN_VALUE:
656 if (i+4 >= codelen)
657 continue;
658 if (codestr[i+4] == RETURN_VALUE &&
659 ISBASICBLOCK(blocks,i,5))
660 memset(codestr+i+1, NOP, 4);
661 else if (UNCONDITIONAL_JUMP(codestr[i+1]) &&
662 ISBASICBLOCK(blocks,i,4))
663 memset(codestr+i+1, NOP, 3);
664 break;
665 }
666 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000667
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000668 /* Fixup linenotab */
669 for (i=0, nops=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
Serhiy Storchaka67559bf2015-02-16 21:13:24 +0200670 assert(i - nops <= INT_MAX);
671 addrmap[i] = (int)(i - nops);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000672 if (codestr[i] == NOP)
673 nops++;
674 }
675 cum_orig_line = 0;
676 last_line = 0;
677 for (i=0 ; i < tabsiz ; i+=2) {
678 cum_orig_line += lineno[i];
679 new_line = addrmap[cum_orig_line];
680 assert (new_line - last_line < 255);
681 lineno[i] =((unsigned char)(new_line - last_line));
682 last_line = new_line;
683 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000684
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000685 /* Remove NOPs and fixup jump targets */
686 for (i=0, h=0 ; i<codelen ; ) {
687 opcode = codestr[i];
688 switch (opcode) {
689 case NOP:
690 i++;
691 continue;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000692
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000693 case JUMP_ABSOLUTE:
694 case CONTINUE_LOOP:
695 case POP_JUMP_IF_FALSE:
696 case POP_JUMP_IF_TRUE:
697 case JUMP_IF_FALSE_OR_POP:
698 case JUMP_IF_TRUE_OR_POP:
699 j = addrmap[GETARG(codestr, i)];
700 SETARG(codestr, i, j);
701 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000702
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000703 case FOR_ITER:
704 case JUMP_FORWARD:
705 case SETUP_LOOP:
706 case SETUP_EXCEPT:
707 case SETUP_FINALLY:
708 case SETUP_WITH:
Yury Selivanov75445082015-05-11 22:57:16 -0400709 case SETUP_ASYNC_WITH:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000710 j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3;
711 SETARG(codestr, i, j);
712 break;
713 }
714 adj = CODESIZE(opcode);
715 while (adj--)
716 codestr[h++] = codestr[i++];
717 }
718 assert(h + nops == codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000719
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000720 code = PyBytes_FromStringAndSize((char *)codestr, h);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100721 CONST_STACK_DELETE();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000722 PyMem_Free(addrmap);
723 PyMem_Free(codestr);
724 PyMem_Free(blocks);
725 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000726
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000727 exitError:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000728 code = NULL;
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000729
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000730 exitUnchanged:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100731 CONST_STACK_DELETE();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000732 if (blocks != NULL)
733 PyMem_Free(blocks);
734 if (addrmap != NULL)
735 PyMem_Free(addrmap);
736 if (codestr != NULL)
737 PyMem_Free(codestr);
738 Py_XINCREF(code);
739 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000740}