blob: b2c0279b7380e83525fd8423db83f0f9080b2d35 [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"
Serhiy Storchakab0f80b02016-05-24 09:15:14 +030011#include "wordcode_helpers.h"
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000012
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)
Serhiy Storchakab0f80b02016-05-24 09:15:14 +030020#define GETJUMPTGT(arr, i) (get_arg(arr, i) + (ABSOLUTE_JUMP(arr[i]) ? 0 : i+2))
21#define ISBASICBLOCK(blocks, start, end) \
22 (blocks[start]==blocks[end])
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000023
Antoine Pitrou17b880a2011-03-11 17:27:02 +010024
25#define CONST_STACK_CREATE() { \
26 const_stack_size = 256; \
27 const_stack = PyMem_New(PyObject *, const_stack_size); \
Serhiy Storchakab0f80b02016-05-24 09:15:14 +030028 if (!const_stack) { \
Antoine Pitrou17b880a2011-03-11 17:27:02 +010029 PyErr_NoMemory(); \
30 goto exitError; \
31 } \
32 }
33
34#define CONST_STACK_DELETE() do { \
35 if (const_stack) \
36 PyMem_Free(const_stack); \
Antoine Pitrou17b880a2011-03-11 17:27:02 +010037 } while(0)
38
Serhiy Storchakab0f80b02016-05-24 09:15:14 +030039#define CONST_STACK_LEN() ((unsigned)(const_stack_top + 1))
Antoine Pitrou17b880a2011-03-11 17:27:02 +010040
41#define CONST_STACK_PUSH_OP(i) do { \
42 PyObject *_x; \
43 assert(codestr[i] == LOAD_CONST); \
Serhiy Storchakab0f80b02016-05-24 09:15:14 +030044 assert(PyList_GET_SIZE(consts) > (Py_ssize_t)get_arg(codestr, i)); \
45 _x = PyList_GET_ITEM(consts, get_arg(codestr, i)); \
Antoine Pitrou17b880a2011-03-11 17:27:02 +010046 if (++const_stack_top >= const_stack_size) { \
47 const_stack_size *= 2; \
48 PyMem_Resize(const_stack, PyObject *, const_stack_size); \
Serhiy Storchakab0f80b02016-05-24 09:15:14 +030049 if (!const_stack) { \
Antoine Pitrou17b880a2011-03-11 17:27:02 +010050 PyErr_NoMemory(); \
51 goto exitError; \
52 } \
53 } \
Antoine Pitrou17b880a2011-03-11 17:27:02 +010054 const_stack[const_stack_top] = _x; \
55 in_consts = 1; \
56 } while(0)
57
58#define CONST_STACK_RESET() do { \
59 const_stack_top = -1; \
60 } while(0)
61
Antoine Pitrou17b880a2011-03-11 17:27:02 +010062#define CONST_STACK_LASTN(i) \
Serhiy Storchakab0f80b02016-05-24 09:15:14 +030063 &const_stack[CONST_STACK_LEN() - i]
Antoine Pitrou17b880a2011-03-11 17:27:02 +010064
65#define CONST_STACK_POP(i) do { \
Serhiy Storchakab0f80b02016-05-24 09:15:14 +030066 assert(CONST_STACK_LEN() >= i); \
Antoine Pitrou17b880a2011-03-11 17:27:02 +010067 const_stack_top -= i; \
68 } while(0)
69
Serhiy Storchakab0f80b02016-05-24 09:15:14 +030070/* Scans back N consecutive LOAD_CONST instructions, skipping NOPs,
71 returns index of the Nth last's LOAD_CONST's EXTENDED_ARG prefix.
72 Callers are responsible to check CONST_STACK_LEN beforehand.
73*/
74static Py_ssize_t
75lastn_const_start(unsigned char *codestr, Py_ssize_t i, Py_ssize_t n)
76{
77 assert(n > 0 && (i&1) == 0);
78 for (;;) {
79 i -= 2;
80 assert(i >= 0);
81 if (codestr[i] == LOAD_CONST) {
82 if (!--n) {
83 while (i > 0 && codestr[i-2] == EXTENDED_ARG) {
84 i -= 2;
85 }
86 return i;
87 }
88 }
89 else {
90 assert(codestr[i] == NOP || codestr[i] == EXTENDED_ARG);
91 }
92 }
93}
Antoine Pitrou17b880a2011-03-11 17:27:02 +010094
Serhiy Storchakab0f80b02016-05-24 09:15:14 +030095/* Scans through EXTENDED ARGs, seeking the index of the effective opcode */
96static Py_ssize_t
97find_op(unsigned char *codestr, Py_ssize_t i)
98{
99 assert((i&1) == 0);
100 while (codestr[i] == EXTENDED_ARG) {
101 i += 2;
102 }
103 return i;
104}
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100105
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300106/* Given the index of the effective opcode,
107 scan back to construct the oparg with EXTENDED_ARG */
108static unsigned int
109get_arg(unsigned char *codestr, Py_ssize_t i)
110{
111 unsigned int oparg = codestr[i+1];
112 assert((i&1) == 0);
113 if (i >= 2 && codestr[i-2] == EXTENDED_ARG) {
114 oparg |= codestr[i-1] << 8;
115 if (i >= 4 && codestr[i-4] == EXTENDED_ARG) {
116 oparg |= codestr[i-3] << 16;
117 if (i >= 6 && codestr[i-6] == EXTENDED_ARG) {
118 oparg |= codestr[i-5] << 24;
119 }
120 }
121 }
122 return oparg;
123}
124
125/* Given the index of the effective opcode,
126 attempt to replace the argument, taking into account EXTENDED_ARG.
127 Returns -1 on failure, or the new op index on success */
128static Py_ssize_t
129set_arg(unsigned char *codestr, Py_ssize_t i, unsigned int oparg)
130{
131 unsigned int curarg = get_arg(codestr, i);
132 int curilen, newilen;
133 if (curarg == oparg)
134 return i;
135 curilen = instrsize(curarg);
136 newilen = instrsize(oparg);
137 if (curilen < newilen) {
138 return -1;
139 }
140
141 write_op_arg(codestr + i + 2 - curilen, codestr[i], oparg, newilen);
142 memset(codestr + i + 2 - curilen + newilen, NOP, curilen - newilen);
143 return i-curilen+newilen;
144}
145
146/* Attempt to write op/arg at end of specified region of memory.
147 Preceding memory in the region is overwritten with NOPs.
148 Returns -1 on failure, op index on success */
149static Py_ssize_t
150copy_op_arg(unsigned char *codestr, Py_ssize_t i, unsigned char op,
151 unsigned int oparg, Py_ssize_t maxi)
152{
153 int ilen = instrsize(oparg);
154 assert((i&1) == 0);
155 if (i + ilen > maxi) {
156 return -1;
157 }
158 write_op_arg(codestr + maxi - ilen, op, oparg, ilen);
159 memset(codestr + i, NOP, maxi - i - ilen);
160 return maxi - 2;
161}
162
163/* Replace LOAD_CONST c1, LOAD_CONST c2 ... LOAD_CONST cn, BUILD_TUPLE n
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000164 with LOAD_CONST (c1, c2, ... cn).
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000165 The consts table must still be in list form so that the
166 new constant (c1, c2, ... cn) can be appended.
167 Called with codestr pointing to the first LOAD_CONST.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000168 Bails out with no change if one or more of the LOAD_CONSTs is missing.
Antoine Pitroub7fbcd32010-01-16 18:37:38 +0000169 Also works for BUILD_LIST and BUILT_SET when followed by an "in" or "not in"
170 test; for BUILD_SET it assembles a frozenset rather than a tuple.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000171*/
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300172static Py_ssize_t
173fold_tuple_on_constants(unsigned char *codestr, Py_ssize_t c_start,
174 Py_ssize_t opcode_end, unsigned char opcode,
175 PyObject *consts, PyObject **objs, int n)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000176{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000177 PyObject *newconst, *constant;
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100178 Py_ssize_t i, len_consts;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000179
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000180 /* Pre-conditions */
181 assert(PyList_CheckExact(consts));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000182
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000183 /* Buildup new tuple of constants */
184 newconst = PyTuple_New(n);
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300185 if (newconst == NULL) {
186 return -1;
187 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000188 for (i=0 ; i<n ; i++) {
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100189 constant = objs[i];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000190 Py_INCREF(constant);
191 PyTuple_SET_ITEM(newconst, i, constant);
192 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000193
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000194 /* If it's a BUILD_SET, use the PyTuple we just built to create a
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300195 PyFrozenSet, and use that as the constant instead: */
196 if (opcode == BUILD_SET) {
197 Py_SETREF(newconst, PyFrozenSet_New(newconst));
198 if (newconst == NULL) {
199 return -1;
200 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000201 }
Antoine Pitroub7fbcd32010-01-16 18:37:38 +0000202
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000203 /* Append folded constant onto consts */
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300204 len_consts = PyList_GET_SIZE(consts);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000205 if (PyList_Append(consts, newconst)) {
206 Py_DECREF(newconst);
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300207 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000208 }
209 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000210
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300211 return copy_op_arg(codestr, c_start, LOAD_CONST, len_consts, opcode_end);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000212}
213
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300214/* Replace LOAD_CONST c1, LOAD_CONST c2, BINOP
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000215 with LOAD_CONST binop(c1,c2)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000216 The consts table must still be in list form so that the
217 new constant can be appended.
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100218 Called with codestr pointing to the BINOP.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000219 Abandons the transformation if the folding fails (i.e. 1+'a').
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000220 If the new constant is a sequence, only folds when the size
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000221 is below a threshold value. That keeps pyc files from
222 becoming large in the presence of code like: (None,)*1000.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000223*/
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300224static Py_ssize_t
225fold_binops_on_constants(unsigned char *codestr, Py_ssize_t c_start,
226 Py_ssize_t opcode_end, unsigned char opcode,
227 PyObject *consts, PyObject **objs)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000228{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000229 PyObject *newconst, *v, *w;
230 Py_ssize_t len_consts, size;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000231
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000232 /* Pre-conditions */
233 assert(PyList_CheckExact(consts));
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300234 len_consts = PyList_GET_SIZE(consts);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000235
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000236 /* Create new constant */
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100237 v = objs[0];
238 w = objs[1];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000239 switch (opcode) {
240 case BINARY_POWER:
241 newconst = PyNumber_Power(v, w, Py_None);
242 break;
243 case BINARY_MULTIPLY:
244 newconst = PyNumber_Multiply(v, w);
245 break;
246 case BINARY_TRUE_DIVIDE:
247 newconst = PyNumber_TrueDivide(v, w);
248 break;
249 case BINARY_FLOOR_DIVIDE:
250 newconst = PyNumber_FloorDivide(v, w);
251 break;
252 case BINARY_MODULO:
253 newconst = PyNumber_Remainder(v, w);
254 break;
255 case BINARY_ADD:
256 newconst = PyNumber_Add(v, w);
257 break;
258 case BINARY_SUBTRACT:
259 newconst = PyNumber_Subtract(v, w);
260 break;
261 case BINARY_SUBSCR:
262 newconst = PyObject_GetItem(v, w);
263 break;
264 case BINARY_LSHIFT:
265 newconst = PyNumber_Lshift(v, w);
266 break;
267 case BINARY_RSHIFT:
268 newconst = PyNumber_Rshift(v, w);
269 break;
270 case BINARY_AND:
271 newconst = PyNumber_And(v, w);
272 break;
273 case BINARY_XOR:
274 newconst = PyNumber_Xor(v, w);
275 break;
276 case BINARY_OR:
277 newconst = PyNumber_Or(v, w);
278 break;
279 default:
280 /* Called with an unknown opcode */
281 PyErr_Format(PyExc_SystemError,
282 "unexpected binary operation %d on a constant",
283 opcode);
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300284 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000285 }
286 if (newconst == NULL) {
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300287 if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
Raymond Hettinger819a0642010-08-22 08:39:49 +0000288 PyErr_Clear();
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300289 }
290 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000291 }
292 size = PyObject_Size(newconst);
Raymond Hettinger819a0642010-08-22 08:39:49 +0000293 if (size == -1) {
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300294 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
295 return -1;
296 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000297 PyErr_Clear();
Raymond Hettinger819a0642010-08-22 08:39:49 +0000298 } else if (size > 20) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000299 Py_DECREF(newconst);
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300300 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000301 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000302
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000303 /* Append folded constant into consts table */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000304 if (PyList_Append(consts, newconst)) {
305 Py_DECREF(newconst);
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300306 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000307 }
308 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000309
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300310 return copy_op_arg(codestr, c_start, LOAD_CONST, len_consts, opcode_end);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000311}
312
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300313static Py_ssize_t
314fold_unaryops_on_constants(unsigned char *codestr, Py_ssize_t c_start,
315 Py_ssize_t opcode_end, unsigned char opcode,
316 PyObject *consts, PyObject *v)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000317{
Mark Dickinson7c9e8032011-03-23 17:59:37 +0000318 PyObject *newconst;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000319 Py_ssize_t len_consts;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000320
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000321 /* Pre-conditions */
322 assert(PyList_CheckExact(consts));
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300323 len_consts = PyList_GET_SIZE(consts);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000324
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000325 /* Create new constant */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000326 switch (opcode) {
327 case UNARY_NEGATIVE:
Mark Dickinson7c9e8032011-03-23 17:59:37 +0000328 newconst = PyNumber_Negative(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000329 break;
330 case UNARY_INVERT:
331 newconst = PyNumber_Invert(v);
332 break;
333 case UNARY_POSITIVE:
334 newconst = PyNumber_Positive(v);
335 break;
336 default:
337 /* Called with an unknown opcode */
338 PyErr_Format(PyExc_SystemError,
339 "unexpected unary operation %d on a constant",
340 opcode);
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300341 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000342 }
343 if (newconst == NULL) {
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300344 if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
Raymond Hettinger819a0642010-08-22 08:39:49 +0000345 PyErr_Clear();
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300346 }
347 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000348 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000349
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000350 /* Append folded constant into consts table */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000351 if (PyList_Append(consts, newconst)) {
352 Py_DECREF(newconst);
Victor Stinnerc82729e2013-11-14 01:21:00 +0100353 PyErr_Clear();
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300354 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000355 }
356 Py_DECREF(newconst);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000357
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300358 return copy_op_arg(codestr, c_start, LOAD_CONST, len_consts, opcode_end);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000359}
360
361static unsigned int *
Christian Heimescc47b052008-03-25 14:56:36 +0000362markblocks(unsigned char *code, Py_ssize_t len)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000363{
Serhiy Storchaka1a1ff292015-02-16 13:28:22 +0200364 unsigned int *blocks = PyMem_New(unsigned int, len);
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300365 int i, j, opcode, blockcnt = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000366
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000367 if (blocks == NULL) {
368 PyErr_NoMemory();
369 return NULL;
370 }
371 memset(blocks, 0, len*sizeof(int));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000372
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000373 /* Mark labels in the first pass */
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300374 for (i=0 ; i<len ; i+=2) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000375 opcode = code[i];
376 switch (opcode) {
377 case FOR_ITER:
378 case JUMP_FORWARD:
379 case JUMP_IF_FALSE_OR_POP:
380 case JUMP_IF_TRUE_OR_POP:
381 case POP_JUMP_IF_FALSE:
382 case POP_JUMP_IF_TRUE:
383 case JUMP_ABSOLUTE:
384 case CONTINUE_LOOP:
385 case SETUP_LOOP:
386 case SETUP_EXCEPT:
387 case SETUP_FINALLY:
388 case SETUP_WITH:
Yury Selivanov75445082015-05-11 22:57:16 -0400389 case SETUP_ASYNC_WITH:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000390 j = GETJUMPTGT(code, i);
391 blocks[j] = 1;
392 break;
393 }
394 }
395 /* Build block numbers in the second pass */
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300396 for (i=0 ; i<len ; i+=2) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000397 blockcnt += blocks[i]; /* increment blockcnt over labels */
398 blocks[i] = blockcnt;
399 }
400 return blocks;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000401}
402
403/* Perform basic peephole optimizations to components of a code object.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000404 The consts object should still be in list form to allow new constants
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000405 to be appended.
406
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300407 To keep the optimizer simple, it bails when the lineno table has complex
408 encoding for gaps >= 255.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000409
Martin Panter46f50722016-05-26 05:35:26 +0000410 Optimizations are restricted to simple transformations occurring within a
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000411 single basic block. All transformations keep the code size the same or
412 smaller. For those that reduce size, the gaps are initially filled with
413 NOPs. Later those NOPs are removed and the jump addresses retargeted in
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300414 a single pass. */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000415
416PyObject *
417PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100418 PyObject *lnotab_obj)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000419{
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300420 Py_ssize_t h, i, nexti, op_start, codelen, tgt;
421 unsigned int j, nops;
422 unsigned char opcode, nextop;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000423 unsigned char *codestr = NULL;
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100424 unsigned char *lnotab;
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300425 unsigned int cum_orig_offset, last_offset;
Serhiy Storchaka67559bf2015-02-16 21:13:24 +0200426 Py_ssize_t tabsiz;
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100427 PyObject **const_stack = NULL;
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100428 Py_ssize_t const_stack_top = -1;
429 Py_ssize_t const_stack_size = 0;
430 int in_consts = 0; /* whether we are in a LOAD_CONST sequence */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000431 unsigned int *blocks = NULL;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000432
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000433 /* Bail out if an exception is set */
434 if (PyErr_Occurred())
435 goto exitError;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000436
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100437 /* Bypass optimization when the lnotab table is too complex */
438 assert(PyBytes_Check(lnotab_obj));
439 lnotab = (unsigned char*)PyBytes_AS_STRING(lnotab_obj);
440 tabsiz = PyBytes_GET_SIZE(lnotab_obj);
441 assert(tabsiz == 0 || Py_REFCNT(lnotab_obj) == 1);
442 if (memchr(lnotab, 255, tabsiz) != NULL) {
443 /* 255 value are used for multibyte bytecode instructions */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000444 goto exitUnchanged;
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100445 }
446 /* Note: -128 and 127 special values for line number delta are ok,
447 the peephole optimizer doesn't modify line numbers. */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000448
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000449 assert(PyBytes_Check(code));
450 codelen = PyBytes_GET_SIZE(code);
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300451 assert(codelen % 2 == 0);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000452
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000453 /* Make a modifiable copy of the code string */
454 codestr = (unsigned char *)PyMem_Malloc(codelen);
Victor Stinnere0af3a82013-07-09 00:32:04 +0200455 if (codestr == NULL) {
456 PyErr_NoMemory();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000457 goto exitError;
Victor Stinnere0af3a82013-07-09 00:32:04 +0200458 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000459 codestr = (unsigned char *)memcpy(codestr,
460 PyBytes_AS_STRING(code), codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000461
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000462 blocks = markblocks(codestr, codelen);
463 if (blocks == NULL)
464 goto exitError;
465 assert(PyList_Check(consts));
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000466
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100467 CONST_STACK_CREATE();
468
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300469 for (i=find_op(codestr, 0) ; i<codelen ; i=nexti) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000470 opcode = codestr[i];
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300471 op_start = i;
472 while (op_start >= 2 && codestr[op_start-2] == EXTENDED_ARG) {
473 op_start -= 2;
474 }
475
476 nexti = i + 2;
477 while (nexti < codelen && codestr[nexti] == EXTENDED_ARG)
478 nexti += 2;
479 nextop = nexti < codelen ? codestr[nexti] : 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000480
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100481 if (!in_consts) {
482 CONST_STACK_RESET();
483 }
484 in_consts = 0;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000485
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000486 switch (opcode) {
487 /* Replace UNARY_NOT POP_JUMP_IF_FALSE
488 with POP_JUMP_IF_TRUE */
489 case UNARY_NOT:
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300490 if (nextop != POP_JUMP_IF_FALSE
491 || !ISBASICBLOCK(blocks, op_start, i+2))
492 break;
493 memset(codestr + op_start, NOP, i - op_start + 2);
494 codestr[nexti] = POP_JUMP_IF_TRUE;
495 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000496
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000497 /* not a is b --> a is not b
498 not a in b --> a not in b
499 not a is not b --> a is b
500 not a not in b --> a in b
501 */
502 case COMPARE_OP:
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300503 j = get_arg(codestr, i);
504 if (j < 6 || j > 9 ||
505 nextop != UNARY_NOT ||
506 !ISBASICBLOCK(blocks, op_start, i + 2))
507 break;
508 codestr[i+1] = (j^1);
509 memset(codestr + i + 2, NOP, nexti - i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000510 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000511
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000512 /* Skip over LOAD_CONST trueconst
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300513 POP_JUMP_IF_FALSE xx. This improves
514 "while 1" performance. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000515 case LOAD_CONST:
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100516 CONST_STACK_PUSH_OP(i);
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300517 if (nextop != POP_JUMP_IF_FALSE ||
518 !ISBASICBLOCK(blocks, op_start, i + 2) ||
519 !PyObject_IsTrue(PyList_GET_ITEM(consts, get_arg(codestr, i))))
520 break;
521 memset(codestr + op_start, NOP, nexti - op_start + 2);
522 CONST_STACK_POP(1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000523 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000524
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300525 /* Try to fold tuples of constants (includes a case for lists
526 and sets which are only used for "in" and "not in" tests).
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000527 Skip over BUILD_SEQN 1 UNPACK_SEQN 1.
528 Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2.
529 Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */
530 case BUILD_TUPLE:
531 case BUILD_LIST:
532 case BUILD_SET:
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300533 j = get_arg(codestr, i);
534 if (j > 0 && CONST_STACK_LEN() >= j) {
535 h = lastn_const_start(codestr, op_start, j);
536 if ((opcode == BUILD_TUPLE &&
537 ISBASICBLOCK(blocks, h, op_start)) ||
538 ((opcode == BUILD_LIST || opcode == BUILD_SET) &&
539 ((nextop==COMPARE_OP &&
540 (codestr[nexti+1]==6 ||
541 codestr[nexti+1]==7)) ||
542 nextop == GET_ITER) && ISBASICBLOCK(blocks, h, i + 2))) {
543 h = fold_tuple_on_constants(codestr, h, i+2, opcode,
544 consts, CONST_STACK_LASTN(j), j);
545 if (h >= 0) {
546 CONST_STACK_POP(j);
547 CONST_STACK_PUSH_OP(h);
548 }
549 break;
550 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000551 }
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300552 if (nextop != UNPACK_SEQUENCE ||
553 !ISBASICBLOCK(blocks, op_start, i + 2) ||
554 j != get_arg(codestr, nexti) ||
Raymond Hettinger0661e912011-03-15 15:03:36 -0700555 opcode == BUILD_SET)
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300556 break;
557 if (j < 2) {
558 memset(codestr+op_start, NOP, nexti - op_start + 2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000559 } else if (j == 2) {
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300560 codestr[op_start] = ROT_TWO;
561 codestr[op_start + 1] = 0;
562 memset(codestr + op_start + 2, NOP, nexti - op_start);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100563 CONST_STACK_RESET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000564 } else if (j == 3) {
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300565 codestr[op_start] = ROT_THREE;
566 codestr[op_start + 1] = 0;
567 codestr[op_start + 2] = ROT_TWO;
568 codestr[op_start + 3] = 0;
569 memset(codestr + op_start + 4, NOP, nexti - op_start - 2);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100570 CONST_STACK_RESET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000571 }
572 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000573
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000574 /* Fold binary ops on constants.
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300575 LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000576 case BINARY_POWER:
577 case BINARY_MULTIPLY:
578 case BINARY_TRUE_DIVIDE:
579 case BINARY_FLOOR_DIVIDE:
580 case BINARY_MODULO:
581 case BINARY_ADD:
582 case BINARY_SUBTRACT:
583 case BINARY_SUBSCR:
584 case BINARY_LSHIFT:
585 case BINARY_RSHIFT:
586 case BINARY_AND:
587 case BINARY_XOR:
588 case BINARY_OR:
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300589 if (CONST_STACK_LEN() < 2)
590 break;
591 h = lastn_const_start(codestr, op_start, 2);
592 if (ISBASICBLOCK(blocks, h, op_start)) {
593 h = fold_binops_on_constants(codestr, h, i+2, opcode,
594 consts, CONST_STACK_LASTN(2));
595 if (h >= 0) {
596 CONST_STACK_POP(2);
597 CONST_STACK_PUSH_OP(h);
598 }
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 /* Fold unary ops on constants.
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300603 LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000604 case UNARY_NEGATIVE:
605 case UNARY_INVERT:
606 case UNARY_POSITIVE:
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300607 if (CONST_STACK_LEN() < 1)
608 break;
609 h = lastn_const_start(codestr, op_start, 1);
610 if (ISBASICBLOCK(blocks, h, op_start)) {
611 h = fold_unaryops_on_constants(codestr, h, i+2, opcode,
612 consts, *CONST_STACK_LASTN(1));
613 if (h >= 0) {
614 CONST_STACK_POP(1);
615 CONST_STACK_PUSH_OP(h);
616 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000617 }
618 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000619
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000620 /* Simplify conditional jump to conditional jump where the
621 result of the first test implies the success of a similar
622 test or the failure of the opposite test.
623 Arises in code like:
624 "if a and b:"
625 "if a or b:"
626 "a and b or c"
627 "(a and b) and c"
628 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z
629 --> x:JUMP_IF_FALSE_OR_POP z
630 x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300631 --> x:POP_JUMP_IF_FALSE y+2
632 where y+2 is the instruction following the second test.
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000633 */
634 case JUMP_IF_FALSE_OR_POP:
635 case JUMP_IF_TRUE_OR_POP:
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300636 h = get_arg(codestr, i);
637 tgt = find_op(codestr, h);
638
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000639 j = codestr[tgt];
640 if (CONDITIONAL_JUMP(j)) {
Raymond Hettinger08eef3f2016-08-07 20:20:33 -0700641 /* NOTE: all possible jumps here are absolute. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000642 if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) {
Raymond Hettinger08eef3f2016-08-07 20:20:33 -0700643 /* The second jump will be taken iff the first is.
644 The current opcode inherits its target's
645 stack effect */
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300646 h = set_arg(codestr, i, get_arg(codestr, tgt));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000647 } else {
Raymond Hettinger08eef3f2016-08-07 20:20:33 -0700648 /* The second jump is not taken if the first is (so
649 jump past it), and all conditional jumps pop their
650 argument when they're not taken (so change the
651 first jump to pop its argument when it's taken). */
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300652 h = set_arg(codestr, i, tgt + 2);
653 j = opcode == JUMP_IF_TRUE_OR_POP ?
654 POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE;
655 }
656
657 if (h >= 0) {
658 nexti = h;
659 codestr[nexti] = j;
660 break;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000661 }
662 }
663 /* Intentional fallthrough */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000664
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000665 /* Replace jumps to unconditional jumps */
666 case POP_JUMP_IF_FALSE:
667 case POP_JUMP_IF_TRUE:
668 case FOR_ITER:
669 case JUMP_FORWARD:
670 case JUMP_ABSOLUTE:
671 case CONTINUE_LOOP:
672 case SETUP_LOOP:
673 case SETUP_EXCEPT:
674 case SETUP_FINALLY:
675 case SETUP_WITH:
Yury Selivanov75445082015-05-11 22:57:16 -0400676 case SETUP_ASYNC_WITH:
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300677 h = GETJUMPTGT(codestr, i);
678 tgt = find_op(codestr, h);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000679 /* Replace JUMP_* to a RETURN into just a RETURN */
680 if (UNCONDITIONAL_JUMP(opcode) &&
681 codestr[tgt] == RETURN_VALUE) {
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300682 codestr[op_start] = RETURN_VALUE;
683 codestr[op_start + 1] = 0;
684 memset(codestr + op_start + 2, NOP, i - op_start);
685 } else if (UNCONDITIONAL_JUMP(codestr[tgt])) {
686 j = GETJUMPTGT(codestr, tgt);
687 if (opcode == JUMP_FORWARD) { /* JMP_ABS can go backwards */
688 opcode = JUMP_ABSOLUTE;
689 } else if (!ABSOLUTE_JUMP(opcode)) {
690 if ((Py_ssize_t)j < i + 2) {
691 break; /* No backward relative jumps */
692 }
693 j -= i + 2; /* Calc relative jump addr */
694 }
695 copy_op_arg(codestr, op_start, opcode, j, i+2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000696 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000697 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000698
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300699 /* Remove unreachable ops after RETURN */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000700 case RETURN_VALUE:
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300701 h = i + 2;
702 while (h + 2 < codelen && ISBASICBLOCK(blocks, i, h + 2)) {
703 h += 2;
704 }
705 if (h > i + 2) {
706 memset(codestr + i + 2, NOP, h - i);
707 nexti = find_op(codestr, h);
708 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000709 break;
710 }
711 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000712
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100713 /* Fixup lnotab */
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300714 for (i=0, nops=0 ; i<codelen ; i += 2) {
Serhiy Storchaka67559bf2015-02-16 21:13:24 +0200715 assert(i - nops <= INT_MAX);
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100716 /* original code offset => new code offset */
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300717 blocks[i] = i - nops;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000718 if (codestr[i] == NOP)
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300719 nops += 2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000720 }
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100721 cum_orig_offset = 0;
722 last_offset = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000723 for (i=0 ; i < tabsiz ; i+=2) {
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300724 unsigned int offset_delta, new_offset;
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100725 cum_orig_offset += lnotab[i];
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300726 assert((cum_orig_offset & 1) == 0);
727 new_offset = blocks[cum_orig_offset];
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100728 offset_delta = new_offset - last_offset;
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300729 assert(offset_delta <= 255);
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100730 lnotab[i] = (unsigned char)offset_delta;
731 last_offset = new_offset;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000732 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000733
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000734 /* Remove NOPs and fixup jump targets */
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300735 for (op_start=0, i=0, h=0 ; i<codelen ; i+=2, op_start=i) {
736 j = codestr[i+1];
737 while (codestr[i] == EXTENDED_ARG) {
738 i += 2;
739 j = j<<8 | codestr[i+1];
740 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000741 opcode = codestr[i];
742 switch (opcode) {
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300743 case NOP:continue;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000744
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000745 case JUMP_ABSOLUTE:
746 case CONTINUE_LOOP:
747 case POP_JUMP_IF_FALSE:
748 case POP_JUMP_IF_TRUE:
749 case JUMP_IF_FALSE_OR_POP:
750 case JUMP_IF_TRUE_OR_POP:
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300751 j = blocks[j];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000752 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000753
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000754 case FOR_ITER:
755 case JUMP_FORWARD:
756 case SETUP_LOOP:
757 case SETUP_EXCEPT:
758 case SETUP_FINALLY:
759 case SETUP_WITH:
Yury Selivanov75445082015-05-11 22:57:16 -0400760 case SETUP_ASYNC_WITH:
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300761 j = blocks[j + i + 2] - blocks[i] - 2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000762 break;
763 }
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300764 nexti = i - op_start + 2;
765 if (instrsize(j) > nexti)
766 goto exitUnchanged;
767 /* If instrsize(j) < nexti, we'll emit EXTENDED_ARG 0 */
768 write_op_arg(codestr + h, opcode, j, nexti);
769 h += nexti;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000770 }
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300771 assert(h + (Py_ssize_t)nops == codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000772
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100773 CONST_STACK_DELETE();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000774 PyMem_Free(blocks);
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300775 code = PyBytes_FromStringAndSize((char *)codestr, h);
776 PyMem_Free(codestr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000777 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000778
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000779 exitError:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000780 code = NULL;
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000781
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000782 exitUnchanged:
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300783 Py_XINCREF(code);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100784 CONST_STACK_DELETE();
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100785 PyMem_Free(blocks);
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100786 PyMem_Free(codestr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000787 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000788}