bpo-29469: peephole: Remove const_stack (GH-4879) · python/cpython@87010e8 (original) (raw)
`@@ -23,51 +23,6 @@
`
23
23
` (blocks[start]==blocks[end])
`
24
24
``
25
25
``
26
``
`-
#define CONST_STACK_CREATE() { \
`
27
``
`-
const_stack_size = 256; \
`
28
``
`-
const_stack = PyMem_New(PyObject *, const_stack_size); \
`
29
``
`-
if (!const_stack) { \
`
30
``
`-
PyErr_NoMemory(); \
`
31
``
`-
goto exitError; \
`
32
``
`-
} \
`
33
``
`-
}
`
34
``
-
35
``
`-
#define CONST_STACK_DELETE() do { \
`
36
``
`-
if (const_stack) \
`
37
``
`-
PyMem_Free(const_stack); \
`
38
``
`-
} while(0)
`
39
``
-
40
``
`-
#define CONST_STACK_LEN() ((unsigned)(const_stack_top + 1))
`
41
``
-
42
``
`-
#define CONST_STACK_PUSH_OP(i) do { \
`
43
``
`-
PyObject *_x; \
`
44
``
`-
assert(_Py_OPCODE(codestr[i]) == LOAD_CONST); \
`
45
``
`-
assert(PyList_GET_SIZE(consts) > (Py_ssize_t)get_arg(codestr, i)); \
`
46
``
`-
_x = PyList_GET_ITEM(consts, get_arg(codestr, i)); \
`
47
``
`-
if (++const_stack_top >= const_stack_size) { \
`
48
``
`-
const_stack_size *= 2; \
`
49
``
`-
PyMem_Resize(const_stack, PyObject *, const_stack_size); \
`
50
``
`-
if (!const_stack) { \
`
51
``
`-
PyErr_NoMemory(); \
`
52
``
`-
goto exitError; \
`
53
``
`-
} \
`
54
``
`-
} \
`
55
``
`-
const_stack[const_stack_top] = _x; \
`
56
``
`-
in_consts = 1; \
`
57
``
`-
} while(0)
`
58
``
-
59
``
`-
#define CONST_STACK_RESET() do { \
`
60
``
`-
const_stack_top = -1; \
`
61
``
`-
} while(0)
`
62
``
-
63
``
`-
#define CONST_STACK_LASTN(i) \
`
64
``
`-
&const_stack[CONST_STACK_LEN() - i]
`
65
``
-
66
``
`-
#define CONST_STACK_POP(i) do { \
`
67
``
`-
assert(CONST_STACK_LEN() >= i); \
`
68
``
`-
const_stack_top -= i; \
`
69
``
`-
} while(0)
`
70
``
-
71
26
`/* Scans back N consecutive LOAD_CONST instructions, skipping NOPs,
`
72
27
` returns index of the Nth last's LOAD_CONST's EXTENDED_ARG prefix.
`
73
28
` Callers are responsible to check CONST_STACK_LEN beforehand.
`
`@@ -88,8 +43,7 @@ lastn_const_start(const _Py_CODEUNIT *codestr, Py_ssize_t i, Py_ssize_t n)
`
88
43
` }
`
89
44
` }
`
90
45
`else {
`
91
``
`-
assert(_Py_OPCODE(codestr[i]) == NOP ||
`
92
``
`-
_Py_OPCODE(codestr[i]) == EXTENDED_ARG);
`
``
46
`+
assert(_Py_OPCODE(codestr[i]) == EXTENDED_ARG);
`
93
47
` }
`
94
48
` }
`
95
49
`}
`
`@@ -172,39 +126,40 @@ copy_op_arg(_Py_CODEUNIT *codestr, Py_ssize_t i, unsigned char op,
`
172
126
` The consts table must still be in list form so that the
`
173
127
` new constant (c1, c2, ... cn) can be appended.
`
174
128
` Called with codestr pointing to the first LOAD_CONST.
`
175
``
`-
Bails out with no change if one or more of the LOAD_CONSTs is missing.
`
176
129
`*/
`
177
130
`static Py_ssize_t
`
178
131
`fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start,
`
179
``
`-
Py_ssize_t opcode_end, unsigned char opcode,
`
180
``
`-
PyObject *consts, PyObject **objs, int n)
`
``
132
`+
Py_ssize_t opcode_end, PyObject *consts, int n)
`
181
133
`{
`
182
``
`-
PyObject *newconst, *constant;
`
183
``
`-
Py_ssize_t i, len_consts;
`
184
``
-
185
134
`/* Pre-conditions */
`
186
135
`assert(PyList_CheckExact(consts));
`
187
136
``
188
137
`/* Buildup new tuple of constants */
`
189
``
`-
newconst = PyTuple_New(n);
`
``
138
`+
PyObject *newconst = PyTuple_New(n);
`
190
139
`if (newconst == NULL) {
`
191
140
`return -1;
`
192
141
` }
`
193
``
`-
for (i=0 ; i<n ; i++) {
`
194
``
`-
constant = objs[i];
`
``
142
+
``
143
`+
for (Py_ssize_t i = 0, pos = c_start; i < n; i++, pos++) {
`
``
144
`+
assert(pos < opcode_end);
`
``
145
`+
pos = find_op(codestr, pos);
`
``
146
`+
assert(_Py_OPCODE(codestr[pos]) == LOAD_CONST);
`
``
147
+
``
148
`+
unsigned int arg = get_arg(codestr, pos);
`
``
149
`+
PyObject *constant = PyList_GET_ITEM(consts, arg);
`
195
150
`Py_INCREF(constant);
`
196
151
`PyTuple_SET_ITEM(newconst, i, constant);
`
197
152
` }
`
198
153
``
199
154
`/* Append folded constant onto consts */
`
200
``
`-
len_consts = PyList_GET_SIZE(consts);
`
201
155
`if (PyList_Append(consts, newconst)) {
`
202
156
`Py_DECREF(newconst);
`
203
157
`return -1;
`
204
158
` }
`
205
159
`Py_DECREF(newconst);
`
206
160
``
207
``
`-
return copy_op_arg(codestr, c_start, LOAD_CONST, len_consts, opcode_end);
`
``
161
`+
return copy_op_arg(codestr, c_start, LOAD_CONST,
`
``
162
`+
PyList_GET_SIZE(consts)-1, opcode_end);
`
208
163
`}
`
209
164
``
210
165
`static unsigned int *
`
`@@ -274,10 +229,8 @@ PyCode_Optimize(PyObject code, PyObject consts, PyObject *names,
`
274
229
`unsigned char *lnotab;
`
275
230
`unsigned int cum_orig_offset, last_offset;
`
276
231
`Py_ssize_t tabsiz;
`
277
``
`-
PyObject **const_stack = NULL;
`
278
``
`-
Py_ssize_t const_stack_top = -1;
`
279
``
`-
Py_ssize_t const_stack_size = 0;
`
280
``
`-
int in_consts = 0; /* whether we are in a LOAD_CONST sequence */
`
``
232
`+
// Count runs of consecutive LOAD_CONSTs
`
``
233
`+
unsigned int cumlc = 0, lastlc = 0;
`
281
234
`unsigned int *blocks = NULL;
`
282
235
``
283
236
`/* Bail out if an exception is set */
`
`@@ -314,8 +267,6 @@ PyCode_Optimize(PyObject code, PyObject consts, PyObject *names,
`
314
267
` goto exitError;
`
315
268
`assert(PyList_Check(consts));
`
316
269
``
317
``
`-
CONST_STACK_CREATE();
`
318
``
-
319
270
`for (i=find_op(codestr, 0) ; i<codelen ; i=nexti) {
`
320
271
`opcode = _Py_OPCODE(codestr[i]);
`
321
272
`op_start = i;
`
`@@ -328,23 +279,21 @@ PyCode_Optimize(PyObject code, PyObject consts, PyObject *names,
`
328
279
`nexti++;
`
329
280
`nextop = nexti < codelen ? _Py_OPCODE(codestr[nexti]) : 0;
`
330
281
``
331
``
`-
if (!in_consts) {
`
332
``
`-
CONST_STACK_RESET();
`
333
``
`-
}
`
334
``
`-
in_consts = 0;
`
``
282
`+
lastlc = cumlc;
`
``
283
`+
cumlc = 0;
`
335
284
``
336
285
`switch (opcode) {
`
337
286
`/* Skip over LOAD_CONST trueconst
`
338
287
` POP_JUMP_IF_FALSE xx. This improves
`
339
288
` "while 1" performance. */
`
340
289
`case LOAD_CONST:
`
341
``
`-
CONST_STACK_PUSH_OP(i);
`
``
290
`+
cumlc = lastlc + 1;
`
342
291
`if (nextop != POP_JUMP_IF_FALSE ||
`
343
292
` !ISBASICBLOCK(blocks, op_start, i + 1) ||
`
344
293
` !PyObject_IsTrue(PyList_GET_ITEM(consts, get_arg(codestr, i))))
`
345
294
`break;
`
346
295
`fill_nops(codestr, op_start, nexti + 1);
`
347
``
`-
CONST_STACK_POP(1);
`
``
296
`+
cumlc = 0;
`
348
297
`break;
`
349
298
``
350
299
`/* Try to fold tuples of constants.
`
`@@ -353,15 +302,10 @@ PyCode_Optimize(PyObject code, PyObject consts, PyObject *names,
`
353
302
` Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */
`
354
303
`case BUILD_TUPLE:
`
355
304
`j = get_arg(codestr, i);
`
356
``
`-
if (j > 0 && CONST_STACK_LEN() >= j) {
`
``
305
`+
if (j > 0 && lastlc >= j) {
`
357
306
`h = lastn_const_start(codestr, op_start, j);
`
358
307
`if (ISBASICBLOCK(blocks, h, op_start)) {
`
359
``
`-
h = fold_tuple_on_constants(codestr, h, i + 1, opcode,
`
360
``
`-
consts, CONST_STACK_LASTN(j), j);
`
361
``
`-
if (h >= 0) {
`
362
``
`-
CONST_STACK_POP(j);
`
363
``
`-
CONST_STACK_PUSH_OP(h);
`
364
``
`-
}
`
``
308
`+
h = fold_tuple_on_constants(codestr, h, i+1, consts, j);
`
365
309
`break;
`
366
310
` }
`
367
311
` }
`
`@@ -374,12 +318,10 @@ PyCode_Optimize(PyObject code, PyObject consts, PyObject *names,
`
374
318
` } else if (j == 2) {
`
375
319
`codestr[op_start] = PACKOPARG(ROT_TWO, 0);
`
376
320
`fill_nops(codestr, op_start + 1, nexti + 1);
`
377
``
`-
CONST_STACK_RESET();
`
378
321
` } else if (j == 3) {
`
379
322
`codestr[op_start] = PACKOPARG(ROT_THREE, 0);
`
380
323
`codestr[op_start + 1] = PACKOPARG(ROT_TWO, 0);
`
381
324
`fill_nops(codestr, op_start + 2, nexti + 1);
`
382
``
`-
CONST_STACK_RESET();
`
383
325
` }
`
384
326
`break;
`
385
327
``
`@@ -538,7 +480,6 @@ PyCode_Optimize(PyObject code, PyObject consts, PyObject *names,
`
538
480
` }
`
539
481
`assert(h + (Py_ssize_t)nops == codelen);
`
540
482
``
541
``
`-
CONST_STACK_DELETE();
`
542
483
`PyMem_Free(blocks);
`
543
484
`code = PyBytes_FromStringAndSize((char *)codestr, h * sizeof(_Py_CODEUNIT));
`
544
485
`PyMem_Free(codestr);
`
`@@ -549,7 +490,6 @@ PyCode_Optimize(PyObject code, PyObject consts, PyObject *names,
`
549
490
``
550
491
`exitUnchanged:
`
551
492
`Py_XINCREF(code);
`
552
``
`-
CONST_STACK_DELETE();
`
553
493
`PyMem_Free(blocks);
`
554
494
`PyMem_Free(codestr);
`
555
495
`return code;
`