blob: 4bf786e3ea3994fdab6c0c6c98e4da4aab2760eb [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) {
Serhiy Storchaka576f1322016-01-05 21:27:54 +0200121 Py_SETREF(newconst, PyFrozenSet_New(newconst));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000122 if (newconst == NULL)
123 return 0;
124 }
Antoine Pitroub7fbcd32010-01-16 18:37:38 +0000125
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000126 /* Append folded constant onto consts */
127 if (PyList_Append(consts, newconst)) {
128 Py_DECREF(newconst);
129 return 0;
130 }
131 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000132
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000133 /* Write NOPs over old LOAD_CONSTS and
134 add a new LOAD_CONST newconst on top of the BUILD_TUPLE n */
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100135 codestr[0] = LOAD_CONST;
136 SETARG(codestr, 0, len_consts);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000137 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000138}
139
140/* Replace LOAD_CONST c1. LOAD_CONST c2 BINOP
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000141 with LOAD_CONST binop(c1,c2)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000142 The consts table must still be in list form so that the
143 new constant can be appended.
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100144 Called with codestr pointing to the BINOP.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000145 Abandons the transformation if the folding fails (i.e. 1+'a').
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000146 If the new constant is a sequence, only folds when the size
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000147 is below a threshold value. That keeps pyc files from
148 becoming large in the presence of code like: (None,)*1000.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000149*/
150static int
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100151fold_binops_on_constants(unsigned char *codestr, PyObject *consts, PyObject **objs)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000152{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000153 PyObject *newconst, *v, *w;
154 Py_ssize_t len_consts, size;
155 int opcode;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000156
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000157 /* Pre-conditions */
158 assert(PyList_CheckExact(consts));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000159
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000160 /* Create new constant */
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100161 v = objs[0];
162 w = objs[1];
163 opcode = codestr[0];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000164 switch (opcode) {
165 case BINARY_POWER:
166 newconst = PyNumber_Power(v, w, Py_None);
167 break;
168 case BINARY_MULTIPLY:
169 newconst = PyNumber_Multiply(v, w);
170 break;
171 case BINARY_TRUE_DIVIDE:
172 newconst = PyNumber_TrueDivide(v, w);
173 break;
174 case BINARY_FLOOR_DIVIDE:
175 newconst = PyNumber_FloorDivide(v, w);
176 break;
177 case BINARY_MODULO:
178 newconst = PyNumber_Remainder(v, w);
179 break;
180 case BINARY_ADD:
181 newconst = PyNumber_Add(v, w);
182 break;
183 case BINARY_SUBTRACT:
184 newconst = PyNumber_Subtract(v, w);
185 break;
186 case BINARY_SUBSCR:
187 newconst = PyObject_GetItem(v, w);
188 break;
189 case BINARY_LSHIFT:
190 newconst = PyNumber_Lshift(v, w);
191 break;
192 case BINARY_RSHIFT:
193 newconst = PyNumber_Rshift(v, w);
194 break;
195 case BINARY_AND:
196 newconst = PyNumber_And(v, w);
197 break;
198 case BINARY_XOR:
199 newconst = PyNumber_Xor(v, w);
200 break;
201 case BINARY_OR:
202 newconst = PyNumber_Or(v, w);
203 break;
204 default:
205 /* Called with an unknown opcode */
206 PyErr_Format(PyExc_SystemError,
207 "unexpected binary operation %d on a constant",
208 opcode);
209 return 0;
210 }
211 if (newconst == NULL) {
Raymond Hettinger819a0642010-08-22 08:39:49 +0000212 if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
213 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000214 return 0;
215 }
216 size = PyObject_Size(newconst);
Raymond Hettinger819a0642010-08-22 08:39:49 +0000217 if (size == -1) {
218 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
219 return 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000220 PyErr_Clear();
Raymond Hettinger819a0642010-08-22 08:39:49 +0000221 } else if (size > 20) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000222 Py_DECREF(newconst);
223 return 0;
224 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000225
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000226 /* Append folded constant into consts table */
227 len_consts = PyList_GET_SIZE(consts);
228 if (PyList_Append(consts, newconst)) {
229 Py_DECREF(newconst);
230 return 0;
231 }
232 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000233
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000234 /* Write NOP NOP NOP NOP LOAD_CONST newconst */
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100235 codestr[-2] = LOAD_CONST;
236 SETARG(codestr, -2, len_consts);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000237 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000238}
239
240static int
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100241fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts, PyObject *v)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000242{
Mark Dickinson7c9e8032011-03-23 17:59:37 +0000243 PyObject *newconst;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000244 Py_ssize_t len_consts;
245 int opcode;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000246
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000247 /* Pre-conditions */
248 assert(PyList_CheckExact(consts));
249 assert(codestr[0] == LOAD_CONST);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000250
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000251 /* Create new constant */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000252 opcode = codestr[3];
253 switch (opcode) {
254 case UNARY_NEGATIVE:
Mark Dickinson7c9e8032011-03-23 17:59:37 +0000255 newconst = PyNumber_Negative(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000256 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);
Victor Stinnerc82729e2013-11-14 01:21:00 +0100280 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000281 return 0;
282 }
283 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000284
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000285 /* Write NOP LOAD_CONST newconst */
286 codestr[0] = NOP;
287 codestr[1] = LOAD_CONST;
288 SETARG(codestr, 1, len_consts);
289 return 1;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000290}
291
292static unsigned int *
Christian Heimescc47b052008-03-25 14:56:36 +0000293markblocks(unsigned char *code, Py_ssize_t len)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000294{
Serhiy Storchaka1a1ff292015-02-16 13:28:22 +0200295 unsigned int *blocks = PyMem_New(unsigned int, len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000296 int i,j, opcode, blockcnt = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000297
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000298 if (blocks == NULL) {
299 PyErr_NoMemory();
300 return NULL;
301 }
302 memset(blocks, 0, len*sizeof(int));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000303
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000304 /* Mark labels in the first pass */
305 for (i=0 ; i<len ; i+=CODESIZE(opcode)) {
306 opcode = code[i];
307 switch (opcode) {
308 case FOR_ITER:
309 case JUMP_FORWARD:
310 case JUMP_IF_FALSE_OR_POP:
311 case JUMP_IF_TRUE_OR_POP:
312 case POP_JUMP_IF_FALSE:
313 case POP_JUMP_IF_TRUE:
314 case JUMP_ABSOLUTE:
315 case CONTINUE_LOOP:
316 case SETUP_LOOP:
317 case SETUP_EXCEPT:
318 case SETUP_FINALLY:
319 case SETUP_WITH:
Yury Selivanov75445082015-05-11 22:57:16 -0400320 case SETUP_ASYNC_WITH:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000321 j = GETJUMPTGT(code, i);
322 blocks[j] = 1;
323 break;
324 }
325 }
326 /* Build block numbers in the second pass */
327 for (i=0 ; i<len ; i++) {
328 blockcnt += blocks[i]; /* increment blockcnt over labels */
329 blocks[i] = blockcnt;
330 }
331 return blocks;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000332}
333
334/* Perform basic peephole optimizations to components of a code object.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000335 The consts object should still be in list form to allow new constants
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000336 to be appended.
337
Guido van Rossum0240b922007-02-26 21:23:50 +0000338 To keep the optimizer simple, it bails out (does nothing) for code that
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000339 has a length over 32,700, and does not calculate extended arguments.
Guido van Rossum0240b922007-02-26 21:23:50 +0000340 That allows us to avoid overflow and sign issues. Likewise, it bails when
341 the lineno table has complex encoding for gaps >= 255. EXTENDED_ARG can
342 appear before MAKE_FUNCTION; in this case both opcodes are skipped.
343 EXTENDED_ARG preceding any other opcode causes the optimizer to bail.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000344
345 Optimizations are restricted to simple transformations occuring within a
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000346 single basic block. All transformations keep the code size the same or
347 smaller. For those that reduce size, the gaps are initially filled with
348 NOPs. Later those NOPs are removed and the jump addresses retargeted in
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000349 a single pass. Line numbering is adjusted accordingly. */
350
351PyObject *
352PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
353 PyObject *lineno_obj)
354{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000355 Py_ssize_t i, j, codelen;
356 int nops, h, adj;
357 int tgt, tgttgt, opcode;
358 unsigned char *codestr = NULL;
359 unsigned char *lineno;
360 int *addrmap = NULL;
Serhiy Storchaka67559bf2015-02-16 21:13:24 +0200361 int new_line, cum_orig_line, last_line;
362 Py_ssize_t tabsiz;
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100363 PyObject **const_stack = NULL;
364 Py_ssize_t *load_const_stack = NULL;
365 Py_ssize_t const_stack_top = -1;
366 Py_ssize_t const_stack_size = 0;
367 int in_consts = 0; /* whether we are in a LOAD_CONST sequence */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000368 unsigned int *blocks = NULL;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000369
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000370 /* Bail out if an exception is set */
371 if (PyErr_Occurred())
372 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000373
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000374 /* Bypass optimization when the lineno table is too complex */
375 assert(PyBytes_Check(lineno_obj));
376 lineno = (unsigned char*)PyBytes_AS_STRING(lineno_obj);
377 tabsiz = PyBytes_GET_SIZE(lineno_obj);
378 if (memchr(lineno, 255, tabsiz) != NULL)
379 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000380
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000381 /* Avoid situations where jump retargeting could overflow */
382 assert(PyBytes_Check(code));
383 codelen = PyBytes_GET_SIZE(code);
384 if (codelen > 32700)
385 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000386
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000387 /* Make a modifiable copy of the code string */
388 codestr = (unsigned char *)PyMem_Malloc(codelen);
Victor Stinnere0af3a82013-07-09 00:32:04 +0200389 if (codestr == NULL) {
390 PyErr_NoMemory();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000391 goto exitError;
Victor Stinnere0af3a82013-07-09 00:32:04 +0200392 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000393 codestr = (unsigned char *)memcpy(codestr,
394 PyBytes_AS_STRING(code), codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000395
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000396 /* Verify that RETURN_VALUE terminates the codestring. This allows
397 the various transformation patterns to look ahead several
398 instructions without additional checks to make sure they are not
399 looking beyond the end of the code string.
400 */
401 if (codestr[codelen-1] != RETURN_VALUE)
402 goto exitUnchanged;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000403
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000404 /* Mapping to new jump targets after NOPs are removed */
Serhiy Storchaka1a1ff292015-02-16 13:28:22 +0200405 addrmap = PyMem_New(int, codelen);
Victor Stinnere0af3a82013-07-09 00:32:04 +0200406 if (addrmap == NULL) {
407 PyErr_NoMemory();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000408 goto exitError;
Victor Stinnere0af3a82013-07-09 00:32:04 +0200409 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000410
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000411 blocks = markblocks(codestr, codelen);
412 if (blocks == NULL)
413 goto exitError;
414 assert(PyList_Check(consts));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000415
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100416 CONST_STACK_CREATE();
417
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000418 for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
419 reoptimize_current:
420 opcode = codestr[i];
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000421
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100422 if (!in_consts) {
423 CONST_STACK_RESET();
424 }
425 in_consts = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000426
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000427 switch (opcode) {
428 /* Replace UNARY_NOT POP_JUMP_IF_FALSE
429 with POP_JUMP_IF_TRUE */
430 case UNARY_NOT:
431 if (codestr[i+1] != POP_JUMP_IF_FALSE
432 || !ISBASICBLOCK(blocks,i,4))
433 continue;
434 j = GETARG(codestr, i+1);
435 codestr[i] = POP_JUMP_IF_TRUE;
436 SETARG(codestr, i, j);
437 codestr[i+3] = NOP;
438 goto reoptimize_current;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000439
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000440 /* not a is b --> a is not b
441 not a in b --> a not in b
442 not a is not b --> a is b
443 not a not in b --> a in b
444 */
445 case COMPARE_OP:
446 j = GETARG(codestr, i);
447 if (j < 6 || j > 9 ||
448 codestr[i+3] != UNARY_NOT ||
449 !ISBASICBLOCK(blocks,i,4))
450 continue;
451 SETARG(codestr, i, (j^1));
452 codestr[i+3] = NOP;
453 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000454
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000455 /* Skip over LOAD_CONST trueconst
456 POP_JUMP_IF_FALSE xx. This improves
457 "while 1" performance. */
458 case LOAD_CONST:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100459 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000460 j = GETARG(codestr, i);
461 if (codestr[i+3] != POP_JUMP_IF_FALSE ||
462 !ISBASICBLOCK(blocks,i,6) ||
463 !PyObject_IsTrue(PyList_GET_ITEM(consts, j)))
464 continue;
465 memset(codestr+i, NOP, 6);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100466 CONST_STACK_RESET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000467 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000468
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000469 /* Try to fold tuples of constants (includes a case for lists and sets
470 which are only used for "in" and "not in" tests).
471 Skip over BUILD_SEQN 1 UNPACK_SEQN 1.
472 Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2.
473 Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */
474 case BUILD_TUPLE:
475 case BUILD_LIST:
476 case BUILD_SET:
477 j = GETARG(codestr, i);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100478 if (j == 0)
479 break;
480 h = CONST_STACK_OP_LASTN(j);
481 assert((h >= 0 || CONST_STACK_LEN() < j));
482 if (h >= 0 && j > 0 && j <= CONST_STACK_LEN() &&
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000483 ((opcode == BUILD_TUPLE &&
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100484 ISBASICBLOCK(blocks, h, i-h+3)) ||
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000485 ((opcode == BUILD_LIST || opcode == BUILD_SET) &&
486 codestr[i+3]==COMPARE_OP &&
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100487 ISBASICBLOCK(blocks, h, i-h+6) &&
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000488 (GETARG(codestr,i+3)==6 ||
489 GETARG(codestr,i+3)==7))) &&
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100490 tuple_of_constants(&codestr[i], j, consts, CONST_STACK_LASTN(j))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000491 assert(codestr[i] == LOAD_CONST);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100492 memset(&codestr[h], NOP, i - h);
493 CONST_STACK_POP(j);
494 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000495 break;
496 }
497 if (codestr[i+3] != UNPACK_SEQUENCE ||
498 !ISBASICBLOCK(blocks,i,6) ||
Raymond Hettinger0661e912011-03-15 15:03:36 -0700499 j != GETARG(codestr, i+3) ||
500 opcode == BUILD_SET)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000501 continue;
502 if (j == 1) {
503 memset(codestr+i, NOP, 6);
504 } else if (j == 2) {
505 codestr[i] = ROT_TWO;
506 memset(codestr+i+1, NOP, 5);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100507 CONST_STACK_RESET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000508 } else if (j == 3) {
509 codestr[i] = ROT_THREE;
510 codestr[i+1] = ROT_TWO;
511 memset(codestr+i+2, NOP, 4);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100512 CONST_STACK_RESET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000513 }
514 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000515
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000516 /* Fold binary ops on constants.
517 LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */
518 case BINARY_POWER:
519 case BINARY_MULTIPLY:
520 case BINARY_TRUE_DIVIDE:
521 case BINARY_FLOOR_DIVIDE:
522 case BINARY_MODULO:
523 case BINARY_ADD:
524 case BINARY_SUBTRACT:
525 case BINARY_SUBSCR:
526 case BINARY_LSHIFT:
527 case BINARY_RSHIFT:
528 case BINARY_AND:
529 case BINARY_XOR:
530 case BINARY_OR:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100531 /* NOTE: LOAD_CONST is saved at `i-2` since it has an arg
532 while BINOP hasn't */
533 h = CONST_STACK_OP_LASTN(2);
534 assert((h >= 0 || CONST_STACK_LEN() < 2));
535 if (h >= 0 &&
536 ISBASICBLOCK(blocks, h, i-h+1) &&
537 fold_binops_on_constants(&codestr[i], consts, CONST_STACK_LASTN(2))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000538 i -= 2;
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100539 memset(&codestr[h], NOP, i - h);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000540 assert(codestr[i] == LOAD_CONST);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100541 CONST_STACK_POP(2);
542 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000543 }
544 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000545
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000546 /* Fold unary ops on constants.
547 LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */
548 case UNARY_NEGATIVE:
549 case UNARY_INVERT:
550 case UNARY_POSITIVE:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100551 h = CONST_STACK_OP_LASTN(1);
552 assert((h >= 0 || CONST_STACK_LEN() < 1));
553 if (h >= 0 &&
554 ISBASICBLOCK(blocks, h, i-h+1) &&
555 fold_unaryops_on_constants(&codestr[i-3], consts, CONST_STACK_TOP())) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000556 i -= 2;
557 assert(codestr[i] == LOAD_CONST);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100558 CONST_STACK_POP(1);
559 CONST_STACK_PUSH_OP(i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000560 }
561 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000562
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000563 /* Simplify conditional jump to conditional jump where the
564 result of the first test implies the success of a similar
565 test or the failure of the opposite test.
566 Arises in code like:
567 "if a and b:"
568 "if a or b:"
569 "a and b or c"
570 "(a and b) and c"
571 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z
572 --> x:JUMP_IF_FALSE_OR_POP z
573 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z
574 --> x:POP_JUMP_IF_FALSE y+3
575 where y+3 is the instruction following the second test.
576 */
577 case JUMP_IF_FALSE_OR_POP:
578 case JUMP_IF_TRUE_OR_POP:
579 tgt = GETJUMPTGT(codestr, i);
580 j = codestr[tgt];
581 if (CONDITIONAL_JUMP(j)) {
582 /* NOTE: all possible jumps here are
583 absolute! */
584 if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) {
585 /* The second jump will be
586 taken iff the first is. */
587 tgttgt = GETJUMPTGT(codestr, tgt);
588 /* The current opcode inherits
589 its target's stack behaviour */
590 codestr[i] = j;
591 SETARG(codestr, i, tgttgt);
592 goto reoptimize_current;
593 } else {
594 /* The second jump is not taken
595 if the first is (so jump past
596 it), and all conditional
597 jumps pop their argument when
598 they're not taken (so change
599 the first jump to pop its
600 argument when it's taken). */
601 if (JUMPS_ON_TRUE(opcode))
602 codestr[i] = POP_JUMP_IF_TRUE;
603 else
604 codestr[i] = POP_JUMP_IF_FALSE;
605 SETARG(codestr, i, (tgt + 3));
606 goto reoptimize_current;
607 }
608 }
609 /* Intentional fallthrough */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000610
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000611 /* Replace jumps to unconditional jumps */
612 case POP_JUMP_IF_FALSE:
613 case POP_JUMP_IF_TRUE:
614 case FOR_ITER:
615 case JUMP_FORWARD:
616 case JUMP_ABSOLUTE:
617 case CONTINUE_LOOP:
618 case SETUP_LOOP:
619 case SETUP_EXCEPT:
620 case SETUP_FINALLY:
621 case SETUP_WITH:
Yury Selivanov75445082015-05-11 22:57:16 -0400622 case SETUP_ASYNC_WITH:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000623 tgt = GETJUMPTGT(codestr, i);
624 /* Replace JUMP_* to a RETURN into just a RETURN */
625 if (UNCONDITIONAL_JUMP(opcode) &&
626 codestr[tgt] == RETURN_VALUE) {
627 codestr[i] = RETURN_VALUE;
628 memset(codestr+i+1, NOP, 2);
629 continue;
630 }
631 if (!UNCONDITIONAL_JUMP(codestr[tgt]))
632 continue;
633 tgttgt = GETJUMPTGT(codestr, tgt);
634 if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */
635 opcode = JUMP_ABSOLUTE;
636 if (!ABSOLUTE_JUMP(opcode))
637 tgttgt -= i + 3; /* Calc relative jump addr */
638 if (tgttgt < 0) /* No backward relative jumps */
639 continue;
640 codestr[i] = opcode;
641 SETARG(codestr, i, tgttgt);
642 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000643
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000644 case EXTENDED_ARG:
645 if (codestr[i+3] != MAKE_FUNCTION)
646 goto exitUnchanged;
647 /* don't visit MAKE_FUNCTION as GETARG will be wrong */
648 i += 3;
649 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000650
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000651 /* Replace RETURN LOAD_CONST None RETURN with just RETURN */
652 /* Remove unreachable JUMPs after RETURN */
653 case RETURN_VALUE:
654 if (i+4 >= codelen)
655 continue;
656 if (codestr[i+4] == RETURN_VALUE &&
657 ISBASICBLOCK(blocks,i,5))
658 memset(codestr+i+1, NOP, 4);
659 else if (UNCONDITIONAL_JUMP(codestr[i+1]) &&
660 ISBASICBLOCK(blocks,i,4))
661 memset(codestr+i+1, NOP, 3);
662 break;
663 }
664 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000666 /* Fixup linenotab */
667 for (i=0, nops=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
Serhiy Storchaka67559bf2015-02-16 21:13:24 +0200668 assert(i - nops <= INT_MAX);
669 addrmap[i] = (int)(i - nops);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000670 if (codestr[i] == NOP)
671 nops++;
672 }
673 cum_orig_line = 0;
674 last_line = 0;
675 for (i=0 ; i < tabsiz ; i+=2) {
676 cum_orig_line += lineno[i];
677 new_line = addrmap[cum_orig_line];
678 assert (new_line - last_line < 255);
679 lineno[i] =((unsigned char)(new_line - last_line));
680 last_line = new_line;
681 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000682
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000683 /* Remove NOPs and fixup jump targets */
684 for (i=0, h=0 ; i<codelen ; ) {
685 opcode = codestr[i];
686 switch (opcode) {
687 case NOP:
688 i++;
689 continue;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000690
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000691 case JUMP_ABSOLUTE:
692 case CONTINUE_LOOP:
693 case POP_JUMP_IF_FALSE:
694 case POP_JUMP_IF_TRUE:
695 case JUMP_IF_FALSE_OR_POP:
696 case JUMP_IF_TRUE_OR_POP:
697 j = addrmap[GETARG(codestr, i)];
698 SETARG(codestr, i, j);
699 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000700
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000701 case FOR_ITER:
702 case JUMP_FORWARD:
703 case SETUP_LOOP:
704 case SETUP_EXCEPT:
705 case SETUP_FINALLY:
706 case SETUP_WITH:
Yury Selivanov75445082015-05-11 22:57:16 -0400707 case SETUP_ASYNC_WITH:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000708 j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3;
709 SETARG(codestr, i, j);
710 break;
711 }
712 adj = CODESIZE(opcode);
713 while (adj--)
714 codestr[h++] = codestr[i++];
715 }
716 assert(h + nops == codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000717
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000718 code = PyBytes_FromStringAndSize((char *)codestr, h);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100719 CONST_STACK_DELETE();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000720 PyMem_Free(addrmap);
721 PyMem_Free(codestr);
722 PyMem_Free(blocks);
723 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000724
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000725 exitError:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000726 code = NULL;
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000727
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000728 exitUnchanged:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100729 CONST_STACK_DELETE();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000730 if (blocks != NULL)
731 PyMem_Free(blocks);
732 if (addrmap != NULL)
733 PyMem_Free(addrmap);
734 if (codestr != NULL)
735 PyMem_Free(codestr);
736 Py_XINCREF(code);
737 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000738}