blob: 62625f7f45e3d5f55673c96904eb219d6842493f [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)) {
641 /* NOTE: all possible jumps here are
642 absolute! */
643 if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) {
644 /* The second jump will be
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300645 taken iff the first is.
646 The current opcode inherits
647 its target's stack effect */
648 h = set_arg(codestr, i, get_arg(codestr, tgt));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000649 } else {
650 /* The second jump is not taken
651 if the first is (so jump past
652 it), and all conditional
653 jumps pop their argument when
654 they're not taken (so change
655 the first jump to pop its
656 argument when it's taken). */
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300657 h = set_arg(codestr, i, tgt + 2);
658 j = opcode == JUMP_IF_TRUE_OR_POP ?
659 POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE;
660 }
661
662 if (h >= 0) {
663 nexti = h;
664 codestr[nexti] = j;
665 break;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000666 }
667 }
668 /* Intentional fallthrough */
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000669
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000670 /* Replace jumps to unconditional jumps */
671 case POP_JUMP_IF_FALSE:
672 case POP_JUMP_IF_TRUE:
673 case FOR_ITER:
674 case JUMP_FORWARD:
675 case JUMP_ABSOLUTE:
676 case CONTINUE_LOOP:
677 case SETUP_LOOP:
678 case SETUP_EXCEPT:
679 case SETUP_FINALLY:
680 case SETUP_WITH:
Yury Selivanov75445082015-05-11 22:57:16 -0400681 case SETUP_ASYNC_WITH:
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300682 h = GETJUMPTGT(codestr, i);
683 tgt = find_op(codestr, h);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000684 /* Replace JUMP_* to a RETURN into just a RETURN */
685 if (UNCONDITIONAL_JUMP(opcode) &&
686 codestr[tgt] == RETURN_VALUE) {
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300687 codestr[op_start] = RETURN_VALUE;
688 codestr[op_start + 1] = 0;
689 memset(codestr + op_start + 2, NOP, i - op_start);
690 } else if (UNCONDITIONAL_JUMP(codestr[tgt])) {
691 j = GETJUMPTGT(codestr, tgt);
692 if (opcode == JUMP_FORWARD) { /* JMP_ABS can go backwards */
693 opcode = JUMP_ABSOLUTE;
694 } else if (!ABSOLUTE_JUMP(opcode)) {
695 if ((Py_ssize_t)j < i + 2) {
696 break; /* No backward relative jumps */
697 }
698 j -= i + 2; /* Calc relative jump addr */
699 }
700 copy_op_arg(codestr, op_start, opcode, j, i+2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000701 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000702 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000703
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300704 /* Remove unreachable ops after RETURN */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000705 case RETURN_VALUE:
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300706 h = i + 2;
707 while (h + 2 < codelen && ISBASICBLOCK(blocks, i, h + 2)) {
708 h += 2;
709 }
710 if (h > i + 2) {
711 memset(codestr + i + 2, NOP, h - i);
712 nexti = find_op(codestr, h);
713 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000714 break;
715 }
716 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000717
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100718 /* Fixup lnotab */
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300719 for (i=0, nops=0 ; i<codelen ; i += 2) {
Serhiy Storchaka67559bf2015-02-16 21:13:24 +0200720 assert(i - nops <= INT_MAX);
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100721 /* original code offset => new code offset */
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300722 blocks[i] = i - nops;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000723 if (codestr[i] == NOP)
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300724 nops += 2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000725 }
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100726 cum_orig_offset = 0;
727 last_offset = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000728 for (i=0 ; i < tabsiz ; i+=2) {
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300729 unsigned int offset_delta, new_offset;
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100730 cum_orig_offset += lnotab[i];
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300731 assert((cum_orig_offset & 1) == 0);
732 new_offset = blocks[cum_orig_offset];
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100733 offset_delta = new_offset - last_offset;
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300734 assert(offset_delta <= 255);
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100735 lnotab[i] = (unsigned char)offset_delta;
736 last_offset = new_offset;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000737 }
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000738
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000739 /* Remove NOPs and fixup jump targets */
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300740 for (op_start=0, i=0, h=0 ; i<codelen ; i+=2, op_start=i) {
741 j = codestr[i+1];
742 while (codestr[i] == EXTENDED_ARG) {
743 i += 2;
744 j = j<<8 | codestr[i+1];
745 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000746 opcode = codestr[i];
747 switch (opcode) {
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300748 case NOP:continue;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000749
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000750 case JUMP_ABSOLUTE:
751 case CONTINUE_LOOP:
752 case POP_JUMP_IF_FALSE:
753 case POP_JUMP_IF_TRUE:
754 case JUMP_IF_FALSE_OR_POP:
755 case JUMP_IF_TRUE_OR_POP:
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300756 j = blocks[j];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000757 break;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000758
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000759 case FOR_ITER:
760 case JUMP_FORWARD:
761 case SETUP_LOOP:
762 case SETUP_EXCEPT:
763 case SETUP_FINALLY:
764 case SETUP_WITH:
Yury Selivanov75445082015-05-11 22:57:16 -0400765 case SETUP_ASYNC_WITH:
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300766 j = blocks[j + i + 2] - blocks[i] - 2;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000767 break;
768 }
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300769 nexti = i - op_start + 2;
770 if (instrsize(j) > nexti)
771 goto exitUnchanged;
772 /* If instrsize(j) < nexti, we'll emit EXTENDED_ARG 0 */
773 write_op_arg(codestr + h, opcode, j, nexti);
774 h += nexti;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000775 }
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300776 assert(h + (Py_ssize_t)nops == codelen);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000777
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100778 CONST_STACK_DELETE();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000779 PyMem_Free(blocks);
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300780 code = PyBytes_FromStringAndSize((char *)codestr, h);
781 PyMem_Free(codestr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000782 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000783
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000784 exitError:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000785 code = NULL;
Alexandre Vassalotti6f828182009-07-21 02:51:58 +0000786
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000787 exitUnchanged:
Serhiy Storchakab0f80b02016-05-24 09:15:14 +0300788 Py_XINCREF(code);
Antoine Pitrou17b880a2011-03-11 17:27:02 +0100789 CONST_STACK_DELETE();
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100790 PyMem_Free(blocks);
Victor Stinnerf3914eb2016-01-20 12:16:21 +0100791 PyMem_Free(codestr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000792 return code;
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000793}