Coverage Report

Created: 2026-10-17 06:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Python/flowgraph.c
Line
Count
Source
1
#include "Python.h"
2
#include "opcode.h"
3
#include "pycore_c_array.h"       // _Py_CArray_EnsureCapacity
4
#include "pycore_flowgraph.h"
5
#include "pycore_compile.h"
6
#include "pycore_intrinsics.h"
7
#include "pycore_pymem.h"         // _PyMem_IsPtrFreed()
8
#include "pycore_long.h"          // _PY_IS_SMALL_INT()
9
#include "pycore_hashtable.h"     // _Py_hashtable_t
10
11
#include "pycore_opcode_utils.h"
12
#include "pycore_opcode_metadata.h" // OPCODE_HAS_ARG, etc
13
#include "pycore_pystate.h"         // _PyInterpreterState_GET()
14
#include "pycore_stackref.h"        // PyStackRef_AsPyObjectBorrow()
15
16
#include <stdbool.h>
17
18
19
#undef SUCCESS
20
#undef ERROR
21
540k
#define SUCCESS 0
22
4.25k
#define ERROR -1
23
24
#define RETURN_IF_ERROR(X)  \
25
801k
    if ((X) == -1) {        \
26
0
        return ERROR;       \
27
0
    }
28
29
175k
#define DEFAULT_BLOCK_SIZE 16
30
31
typedef _Py_SourceLocation location;
32
typedef _PyJumpTargetLabel jump_target_label;
33
34
typedef struct _PyCfgInstruction {
35
    int i_opcode;
36
    int i_oparg;
37
    _Py_SourceLocation i_loc;
38
    struct _PyCfgBasicblock *i_target; /* target block (if jump instruction) */
39
    struct _PyCfgBasicblock *i_except; /* target block when exception is raised */
40
} cfg_instr;
41
42
typedef struct _PyCfgBasicblock {
43
    /* Each basicblock in a compilation unit is linked via b_list in the
44
       reverse order that blocks are allocated.  b_list points to the
45
       previously allocated block, not to be confused with b_next, which is
46
       next by control flow. */
47
    struct _PyCfgBasicblock *b_list;
48
    /* The label of this block if it is a jump target, -1 otherwise */
49
    _PyJumpTargetLabel b_label;
50
    /* Exception stack at start of block, used by assembler to create the exception handling table */
51
    struct _PyCfgExceptStack *b_exceptstack;
52
    /* pointer to an array of instructions, initially NULL */
53
    cfg_instr *b_instr;
54
    /* If b_next is non-NULL, it is a pointer to the next
55
       block reached by normal control flow. */
56
    struct _PyCfgBasicblock *b_next;
57
    /* number of instructions used */
58
    int b_iused;
59
    /* length of instruction array (b_instr) */
60
    int b_ialloc;
61
    /* Used by add_checks_for_loads_of_unknown_variables */
62
    uint64_t b_unsafe_locals_mask;
63
    /* Number of predecessors that a block has. */
64
    int b_predecessors;
65
    /* depth of stack upon entry of block, computed by stackdepth() */
66
    int b_startdepth;
67
    /* Basic block is an exception handler that preserves lasti */
68
    unsigned b_preserve_lasti : 1;
69
    /* Used by compiler passes to mark whether they have visited a basic block. */
70
    unsigned b_visited : 1;
71
    /* b_except_handler is used by the cold-detection algorithm to mark exception targets */
72
    unsigned b_except_handler : 1;
73
    /* b_cold is true if this block is not perf critical (like an exception handler) */
74
    unsigned b_cold : 1;
75
    /* b_warm is used by the cold-detection algorithm to mark blocks which are definitely not cold */
76
    unsigned b_warm : 1;
77
} basicblock;
78
79
80
struct _PyCfgBuilder {
81
    /* The entryblock, at which control flow begins. All blocks of the
82
       CFG are reachable through the b_next links */
83
    struct _PyCfgBasicblock *g_entryblock;
84
    /* Pointer to the most recently allocated block.  By following
85
       b_list links, you can reach all allocated blocks. */
86
    struct _PyCfgBasicblock *g_block_list;
87
    /* pointer to the block currently being constructed */
88
    struct _PyCfgBasicblock *g_curblock;
89
    /* label for the next instruction to be placed */
90
    _PyJumpTargetLabel g_current_label;
91
};
92
93
typedef struct _PyCfgBuilder cfg_builder;
94
95
178k
#define SAME_LABEL(L1, L2) ((L1).id == (L2).id)
96
178k
#define IS_LABEL(L) (!SAME_LABEL((L), (NO_LABEL)))
97
98
#define LOCATION(LNO, END_LNO, COL, END_COL) \
99
    ((const _Py_SourceLocation){(LNO), (END_LNO), (COL), (END_COL)})
100
101
static inline int
102
is_block_push(cfg_instr *i)
103
783k
{
104
783k
    assert(OPCODE_HAS_ARG(i->i_opcode) || !IS_BLOCK_PUSH_OPCODE(i->i_opcode));
105
783k
    return IS_BLOCK_PUSH_OPCODE(i->i_opcode);
106
783k
}
107
108
static inline int
109
is_jump(cfg_instr *i)
110
662k
{
111
662k
    return OPCODE_HAS_JUMP(i->i_opcode);
112
662k
}
113
114
/* One arg*/
115
#define INSTR_SET_OP1(I, OP, ARG) \
116
29.5k
    do { \
117
29.5k
        assert(OPCODE_HAS_ARG(OP)); \
118
29.5k
        cfg_instr *_instr__ptr_ = (I); \
119
29.5k
        _instr__ptr_->i_opcode = (OP); \
120
29.5k
        _instr__ptr_->i_oparg = (ARG); \
121
29.5k
    } while (0);
122
123
/* No args*/
124
#define INSTR_SET_OP0(I, OP) \
125
30.4k
    do { \
126
30.4k
        assert(!OPCODE_HAS_ARG(OP)); \
127
30.4k
        cfg_instr *_instr__ptr_ = (I); \
128
30.4k
        _instr__ptr_->i_opcode = (OP); \
129
30.4k
        _instr__ptr_->i_oparg = 0; \
130
30.4k
    } while (0);
131
132
#define INSTR_SET_LOC(I, LOC) \
133
3.81k
    do { \
134
3.81k
        cfg_instr *_instr__ptr_ = (I); \
135
3.81k
        _instr__ptr_->i_loc = (LOC); \
136
3.81k
    } while (0);
137
138
/***** Blocks *****/
139
140
/* Returns the offset of the next instruction in the current block's
141
   b_instr array.  Resizes the b_instr as necessary.
142
   Returns -1 on failure.
143
*/
144
static int
145
basicblock_next_instr(basicblock *b)
146
175k
{
147
175k
    assert(b != NULL);
148
175k
    _Py_c_array_t array = {
149
175k
        .array = (void*)b->b_instr,
150
175k
        .allocated_entries = b->b_ialloc,
151
175k
        .item_size = sizeof(cfg_instr),
152
175k
        .initial_num_entries = DEFAULT_BLOCK_SIZE,
153
175k
    };
154
155
175k
    RETURN_IF_ERROR(_Py_CArray_EnsureCapacity(&array, b->b_iused + 1));
156
175k
    b->b_instr = array.array;
157
175k
    b->b_ialloc = array.allocated_entries;
158
175k
    return b->b_iused++;
159
175k
}
160
161
static cfg_instr *
162
522k
basicblock_last_instr(const basicblock *b) {
163
522k
    assert(b->b_iused >= 0);
164
522k
    if (b->b_iused > 0) {
165
475k
        assert(b->b_instr != NULL);
166
475k
        return &b->b_instr[b->b_iused - 1];
167
475k
    }
168
46.5k
    return NULL;
169
522k
}
170
171
/* Allocate a new block and return a pointer to it.
172
   Returns NULL on error.
173
*/
174
175
static basicblock *
176
cfg_builder_new_block(cfg_builder *g)
177
16.5k
{
178
16.5k
    basicblock *b = (basicblock *)PyMem_Calloc(1, sizeof(basicblock));
179
16.5k
    if (b == NULL) {
180
0
        PyErr_NoMemory();
181
0
        return NULL;
182
0
    }
183
    /* Extend the singly linked list of blocks with new block. */
184
16.5k
    b->b_list = g->g_block_list;
185
16.5k
    g->g_block_list = b;
186
16.5k
    b->b_label = NO_LABEL;
187
16.5k
    return b;
188
16.5k
}
189
190
static int
191
basicblock_addop(basicblock *b, int opcode, int oparg, location loc)
192
171k
{
193
171k
    assert(IS_WITHIN_OPCODE_RANGE(opcode));
194
171k
    assert(!IS_ASSEMBLER_OPCODE(opcode));
195
171k
    assert(OPCODE_HAS_ARG(opcode) || HAS_TARGET(opcode) || oparg == 0);
196
171k
    assert(0 <= oparg && oparg < (1 << 30));
197
198
171k
    int off = basicblock_next_instr(b);
199
171k
    if (off < 0) {
200
0
        return ERROR;
201
0
    }
202
171k
    cfg_instr *i = &b->b_instr[off];
203
171k
    i->i_opcode = opcode;
204
171k
    i->i_oparg = oparg;
205
171k
    i->i_loc = loc;
206
    // memory is already zero initialized
207
171k
    assert(i->i_target == NULL);
208
171k
    assert(i->i_except == NULL);
209
210
171k
    return SUCCESS;
211
171k
}
212
213
static int
214
basicblock_add_jump(basicblock *b, int opcode, basicblock *target, location loc)
215
294
{
216
294
    cfg_instr *last = basicblock_last_instr(b);
217
294
    if (last && is_jump(last)) {
218
0
        return ERROR;
219
0
    }
220
221
294
    RETURN_IF_ERROR(
222
294
        basicblock_addop(b, opcode, target->b_label.id, loc));
223
294
    last = basicblock_last_instr(b);
224
294
    assert(last && last->i_opcode == opcode);
225
294
    last->i_target = target;
226
294
    return SUCCESS;
227
294
}
228
229
static inline int
230
basicblock_append_instructions(basicblock *to, basicblock *from)
231
911
{
232
2.53k
    for (int i = 0; i < from->b_iused; i++) {
233
1.62k
        int n = basicblock_next_instr(to);
234
1.62k
        if (n < 0) {
235
0
            return ERROR;
236
0
        }
237
1.62k
        to->b_instr[n] = from->b_instr[i];
238
1.62k
    }
239
911
    return SUCCESS;
240
911
}
241
242
static inline int
243
152k
basicblock_nofallthrough(const basicblock *b) {
244
152k
    cfg_instr *last = basicblock_last_instr(b);
245
152k
    return (last &&
246
142k
            (IS_SCOPE_EXIT_OPCODE(last->i_opcode) ||
247
76.0k
             IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode)));
248
152k
}
249
250
#define BB_NO_FALLTHROUGH(B) (basicblock_nofallthrough(B))
251
250k
#define BB_HAS_FALLTHROUGH(B) (!basicblock_nofallthrough(B))
252
253
static basicblock *
254
copy_basicblock(cfg_builder *g, basicblock *block)
255
214
{
256
    /* Cannot copy a block if it has a fallthrough, since
257
     * a block can only have one fallthrough predecessor.
258
     */
259
214
    assert(BB_NO_FALLTHROUGH(block));
260
214
    basicblock *result = cfg_builder_new_block(g);
261
214
    if (result == NULL) {
262
0
        return NULL;
263
0
    }
264
214
    if (basicblock_append_instructions(result, block) < 0) {
265
0
        return NULL;
266
0
    }
267
214
    return result;
268
214
}
269
270
static int
271
2.56k
basicblock_insert_instruction(basicblock *block, int pos, cfg_instr *instr) {
272
2.56k
    RETURN_IF_ERROR(basicblock_next_instr(block));
273
38.7k
    for (int i = block->b_iused - 1; i > pos; i--) {
274
36.2k
        block->b_instr[i] = block->b_instr[i-1];
275
36.2k
    }
276
2.56k
    block->b_instr[pos] = *instr;
277
2.56k
    return SUCCESS;
278
2.56k
}
279
280
/* For debugging purposes only */
281
#if 0
282
static void
283
dump_instr(cfg_instr *i)
284
{
285
    const char *jump = is_jump(i) ? "jump " : "";
286
287
    char arg[128];
288
289
    *arg = '\0';
290
    if (OPCODE_HAS_ARG(i->i_opcode)) {
291
        sprintf(arg, "arg: %d ", i->i_oparg);
292
    }
293
    if (HAS_TARGET(i->i_opcode)) {
294
        sprintf(arg, "target: %p [%d] ", i->i_target, i->i_oparg);
295
    }
296
    fprintf(stderr, "line: %d, %s (%d)  %s%s\n",
297
                    i->i_loc.lineno, _PyOpcode_OpName[i->i_opcode], i->i_opcode, arg, jump);
298
}
299
300
static inline int
301
basicblock_returns(const basicblock *b) {
302
    cfg_instr *last = basicblock_last_instr(b);
303
    return last && IS_RETURN_OPCODE(last->i_opcode);
304
}
305
306
static void
307
dump_basicblock(const basicblock *b, bool highlight)
308
{
309
    const char *b_return = basicblock_returns(b) ? "return " : "";
310
    if (highlight) {
311
        fprintf(stderr, ">>> ");
312
    }
313
    fprintf(stderr, "%d: [EH=%d CLD=%d WRM=%d NO_FT=%d %p] used: %d, depth: %d, preds: %d %s\n",
314
        b->b_label.id, b->b_except_handler, b->b_cold, b->b_warm, BB_NO_FALLTHROUGH(b), b, b->b_iused,
315
        b->b_startdepth, b->b_predecessors, b_return);
316
    int depth = b->b_startdepth;
317
    if (b->b_instr) {
318
        int i;
319
        for (i = 0; i < b->b_iused; i++) {
320
            fprintf(stderr, "  [%02d] depth: %d ", i, depth);
321
            dump_instr(b->b_instr + i);
322
323
            int popped = _PyOpcode_num_popped(b->b_instr[i].i_opcode, b->b_instr[i].i_oparg);
324
            int pushed = _PyOpcode_num_pushed(b->b_instr[i].i_opcode, b->b_instr[i].i_oparg);
325
            depth += (pushed - popped);
326
        }
327
    }
328
}
329
330
void
331
_PyCfgBuilder_DumpGraph(const basicblock *entryblock, const basicblock *mark)
332
{
333
    for (const basicblock *b = entryblock; b != NULL; b = b->b_next) {
334
        dump_basicblock(b, b == mark);
335
    }
336
}
337
338
#endif
339
340
341
/***** CFG construction and modification *****/
342
343
static basicblock *
344
cfg_builder_use_next_block(cfg_builder *g, basicblock *block)
345
11.8k
{
346
11.8k
    assert(block != NULL);
347
11.8k
    g->g_curblock->b_next = block;
348
11.8k
    g->g_curblock = block;
349
11.8k
    return block;
350
11.8k
}
351
352
static inline int
353
23.6k
basicblock_exits_scope(const basicblock *b) {
354
23.6k
    cfg_instr *last = basicblock_last_instr(b);
355
23.6k
    return last && IS_SCOPE_EXIT_OPCODE(last->i_opcode);
356
23.6k
}
357
358
static inline int
359
13.5k
basicblock_has_eval_break(const basicblock *b) {
360
71.4k
    for (int i = 0; i < b->b_iused; i++) {
361
62.8k
        if (OPCODE_HAS_EVAL_BREAK(b->b_instr[i].i_opcode)) {
362
4.97k
            return true;
363
4.97k
        }
364
62.8k
    }
365
8.61k
    return false;
366
13.5k
}
367
368
static bool
369
cfg_builder_current_block_is_terminated(cfg_builder *g)
370
172k
{
371
172k
    cfg_instr *last = basicblock_last_instr(g->g_curblock);
372
172k
    if (last && IS_TERMINATOR_OPCODE(last->i_opcode)) {
373
10.3k
        return true;
374
10.3k
    }
375
162k
    if (IS_LABEL(g->g_current_label)) {
376
1.53k
        if (last || IS_LABEL(g->g_curblock->b_label)) {
377
1.53k
            return true;
378
1.53k
        }
379
0
        else {
380
            /* current block is empty, label it */
381
0
            g->g_curblock->b_label = g->g_current_label;
382
0
            g->g_current_label = NO_LABEL;
383
0
        }
384
1.53k
    }
385
160k
    return false;
386
162k
}
387
388
static int
389
cfg_builder_maybe_start_new_block(cfg_builder *g)
390
172k
{
391
172k
    if (cfg_builder_current_block_is_terminated(g)) {
392
11.8k
        basicblock *b = cfg_builder_new_block(g);
393
11.8k
        if (b == NULL) {
394
0
            return ERROR;
395
0
        }
396
11.8k
        b->b_label = g->g_current_label;
397
11.8k
        g->g_current_label = NO_LABEL;
398
11.8k
        cfg_builder_use_next_block(g, b);
399
11.8k
    }
400
172k
    return SUCCESS;
401
172k
}
402
403
#ifndef NDEBUG
404
static bool
405
cfg_builder_check(cfg_builder *g)
406
{
407
    for (basicblock *block = g->g_block_list; block != NULL; block = block->b_list) {
408
        assert(!_PyMem_IsPtrFreed(block));
409
        if (block->b_instr != NULL) {
410
            assert(block->b_ialloc > 0);
411
            assert(block->b_iused >= 0);
412
            assert(block->b_ialloc >= block->b_iused);
413
        }
414
        else {
415
            assert (block->b_iused == 0);
416
            assert (block->b_ialloc == 0);
417
        }
418
    }
419
    return true;
420
}
421
#endif
422
423
static int
424
init_cfg_builder(cfg_builder *g)
425
4.26k
{
426
4.26k
    g->g_block_list = NULL;
427
4.26k
    basicblock *block = cfg_builder_new_block(g);
428
4.26k
    if (block == NULL) {
429
0
        return ERROR;
430
0
    }
431
4.26k
    g->g_curblock = g->g_entryblock = block;
432
4.26k
    g->g_current_label = NO_LABEL;
433
4.26k
    return SUCCESS;
434
4.26k
}
435
436
cfg_builder *
437
_PyCfgBuilder_New(void)
438
4.26k
{
439
4.26k
    cfg_builder *g = PyMem_Malloc(sizeof(cfg_builder));
440
4.26k
    if (g == NULL) {
441
0
        PyErr_NoMemory();
442
0
        return NULL;
443
0
    }
444
4.26k
    memset(g, 0, sizeof(cfg_builder));
445
4.26k
    if (init_cfg_builder(g) < 0) {
446
0
        PyMem_Free(g);
447
0
        return NULL;
448
0
    }
449
4.26k
    return g;
450
4.26k
}
451
452
void
453
_PyCfgBuilder_Free(cfg_builder *g)
454
4.26k
{
455
4.26k
    if (g == NULL) {
456
0
        return;
457
0
    }
458
4.26k
    assert(cfg_builder_check(g));
459
4.26k
    basicblock *b = g->g_block_list;
460
20.7k
    while (b != NULL) {
461
16.5k
        if (b->b_instr) {
462
16.5k
            PyMem_Free((void *)b->b_instr);
463
16.5k
        }
464
16.5k
        basicblock *next = b->b_list;
465
16.5k
        PyMem_Free((void *)b);
466
16.5k
        b = next;
467
16.5k
    }
468
4.26k
    PyMem_Free(g);
469
4.26k
}
470
471
int
472
_PyCfgBuilder_CheckSize(cfg_builder *g)
473
4.26k
{
474
4.26k
    int nblocks = 0;
475
20.3k
    for (basicblock *b = g->g_block_list; b != NULL; b = b->b_list) {
476
16.1k
        nblocks++;
477
16.1k
    }
478
4.26k
    if ((size_t)nblocks > SIZE_MAX / sizeof(basicblock *)) {
479
0
        PyErr_NoMemory();
480
0
        return ERROR;
481
0
    }
482
4.26k
    return SUCCESS;
483
4.26k
}
484
485
int
486
_PyCfgBuilder_UseLabel(cfg_builder *g, jump_target_label lbl)
487
5.22k
{
488
5.22k
    g->g_current_label = lbl;
489
5.22k
    return cfg_builder_maybe_start_new_block(g);
490
5.22k
}
491
492
int
493
_PyCfgBuilder_Addop(cfg_builder *g, int opcode, int oparg, location loc)
494
167k
{
495
167k
    RETURN_IF_ERROR(cfg_builder_maybe_start_new_block(g));
496
167k
    return basicblock_addop(g->g_curblock, opcode, oparg, loc);
497
167k
}
498
499
500
static basicblock *
501
next_nonempty_block(basicblock *b)
502
18.4k
{
503
19.1k
    while (b && b->b_iused == 0) {
504
691
        b = b->b_next;
505
691
    }
506
18.4k
    return b;
507
18.4k
}
508
509
/***** debugging helpers *****/
510
511
#ifndef NDEBUG
512
static int remove_redundant_nops(cfg_builder *g);
513
514
static bool
515
no_redundant_nops(cfg_builder *g) {
516
    if (remove_redundant_nops(g) != 0) {
517
        return false;
518
    }
519
    return true;
520
}
521
522
static bool
523
no_redundant_jumps(cfg_builder *g) {
524
    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
525
        cfg_instr *last = basicblock_last_instr(b);
526
        if (last != NULL) {
527
            if (IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode)) {
528
                basicblock *next = next_nonempty_block(b->b_next);
529
                basicblock *jump_target = next_nonempty_block(last->i_target);
530
                if (jump_target == next) {
531
                    assert(next);
532
                    if (last->i_loc.lineno == next->b_instr[0].i_loc.lineno) {
533
                        assert(0);
534
                        return false;
535
                    }
536
                }
537
            }
538
        }
539
    }
540
    return true;
541
}
542
#endif
543
544
/***** CFG preprocessing (jump targets and exceptions) *****/
545
546
static int
547
16.5k
normalize_jumps_in_block(cfg_builder *g, basicblock *b) {
548
16.5k
    cfg_instr *last = basicblock_last_instr(b);
549
16.5k
    if (last == NULL || !IS_CONDITIONAL_JUMP_OPCODE(last->i_opcode)) {
550
13.0k
        return SUCCESS;
551
13.0k
    }
552
16.5k
    assert(!IS_ASSEMBLER_OPCODE(last->i_opcode));
553
554
3.51k
    bool is_forward = last->i_target->b_visited == 0;
555
3.51k
    if (is_forward) {
556
3.36k
        RETURN_IF_ERROR(
557
3.36k
            basicblock_addop(b, NOT_TAKEN, 0, last->i_loc));
558
3.36k
        return SUCCESS;
559
3.36k
    }
560
561
150
    int reversed_opcode = 0;
562
150
    switch(last->i_opcode) {
563
0
        case POP_JUMP_IF_NOT_NONE:
564
0
            reversed_opcode = POP_JUMP_IF_NONE;
565
0
            break;
566
7
        case POP_JUMP_IF_NONE:
567
7
            reversed_opcode = POP_JUMP_IF_NOT_NONE;
568
7
            break;
569
125
        case POP_JUMP_IF_FALSE:
570
125
            reversed_opcode = POP_JUMP_IF_TRUE;
571
125
            break;
572
18
        case POP_JUMP_IF_TRUE:
573
18
            reversed_opcode = POP_JUMP_IF_FALSE;
574
18
            break;
575
150
    }
576
    /* transform 'conditional jump T' to
577
     * 'reversed_jump b_next' followed by 'jump_backwards T'
578
     */
579
580
150
    basicblock *target = last->i_target;
581
150
    basicblock *backwards_jump = cfg_builder_new_block(g);
582
150
    if (backwards_jump == NULL) {
583
0
        return ERROR;
584
0
    }
585
150
    RETURN_IF_ERROR(
586
150
        basicblock_addop(backwards_jump, NOT_TAKEN, 0, last->i_loc));
587
150
    RETURN_IF_ERROR(
588
150
        basicblock_add_jump(backwards_jump, JUMP, target, last->i_loc));
589
150
    backwards_jump->b_startdepth = target->b_startdepth;
590
150
    last->i_opcode = reversed_opcode;
591
150
    last->i_target = b->b_next;
592
593
150
    backwards_jump->b_cold = b->b_cold;
594
150
    backwards_jump->b_next = b->b_next;
595
150
    b->b_next = backwards_jump;
596
150
    return SUCCESS;
597
150
}
598
599
600
static int
601
normalize_jumps(cfg_builder *g)
602
4.26k
{
603
4.26k
    basicblock *entryblock = g->g_entryblock;
604
20.6k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
605
16.3k
        b->b_visited = 0;
606
16.3k
    }
607
20.7k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
608
16.5k
        b->b_visited = 1;
609
16.5k
        RETURN_IF_ERROR(normalize_jumps_in_block(g, b));
610
16.5k
    }
611
4.26k
    return SUCCESS;
612
4.26k
}
613
614
static int
615
4.26k
check_cfg(cfg_builder *g) {
616
20.3k
    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
617
        /* Raise SystemError if jump or exit is not last instruction in the block. */
618
183k
        for (int i = 0; i < b->b_iused; i++) {
619
167k
            int opcode = b->b_instr[i].i_opcode;
620
167k
            assert(!IS_ASSEMBLER_OPCODE(opcode));
621
167k
            if (IS_TERMINATOR_OPCODE(opcode)) {
622
14.5k
                if (i != b->b_iused - 1) {
623
0
                    PyErr_SetString(PyExc_SystemError, "malformed control flow graph.");
624
0
                    return ERROR;
625
0
                }
626
14.5k
            }
627
167k
        }
628
16.1k
    }
629
4.26k
    return SUCCESS;
630
4.26k
}
631
632
static int
633
get_max_label(basicblock *entryblock)
634
16.0k
{
635
16.0k
    int lbl = -1;
636
80.0k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
637
63.9k
        if (b->b_label.id > lbl) {
638
19.3k
            lbl = b->b_label.id;
639
19.3k
        }
640
63.9k
    }
641
16.0k
    return lbl;
642
16.0k
}
643
644
/* Calculate the actual jump target from the target_label */
645
static int
646
translate_jump_labels_to_targets(basicblock *entryblock)
647
4.26k
{
648
4.26k
    int max_label = get_max_label(entryblock);
649
4.26k
    size_t mapsize = sizeof(basicblock *) * (max_label + 1);
650
4.26k
    basicblock **label2block = (basicblock **)PyMem_Malloc(mapsize);
651
4.26k
    if (!label2block) {
652
0
        PyErr_NoMemory();
653
0
        return ERROR;
654
0
    }
655
4.26k
    memset(label2block, 0, mapsize);
656
20.3k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
657
16.1k
        if (b->b_label.id >= 0) {
658
5.22k
            label2block[b->b_label.id] = b;
659
5.22k
        }
660
16.1k
    }
661
20.3k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
662
183k
        for (int i = 0; i < b->b_iused; i++) {
663
167k
            cfg_instr *instr = &b->b_instr[i];
664
167k
            assert(instr->i_target == NULL);
665
167k
            if (HAS_TARGET(instr->i_opcode)) {
666
6.51k
                int lbl = instr->i_oparg;
667
6.51k
                assert(lbl >= 0 && lbl <= max_label);
668
6.51k
                instr->i_target = label2block[lbl];
669
6.51k
                assert(instr->i_target != NULL);
670
6.51k
                assert(instr->i_target->b_label.id == lbl);
671
6.51k
            }
672
167k
        }
673
16.1k
    }
674
4.26k
    PyMem_Free(label2block);
675
4.26k
    return SUCCESS;
676
4.26k
}
677
678
static int
679
4.26k
mark_except_handlers(basicblock *entryblock) {
680
#ifndef NDEBUG
681
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
682
        assert(!b->b_except_handler);
683
    }
684
#endif
685
20.3k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
686
183k
        for (int i=0; i < b->b_iused; i++) {
687
167k
            cfg_instr *instr = &b->b_instr[i];
688
167k
            if (is_block_push(instr)) {
689
813
                instr->i_target->b_except_handler = 1;
690
813
            }
691
167k
        }
692
16.1k
    }
693
4.26k
    return SUCCESS;
694
4.26k
}
695
696
697
struct _PyCfgExceptStack {
698
    basicblock *handlers[CO_MAXBLOCKS+2];
699
    int depth;
700
};
701
702
703
static basicblock *
704
813
push_except_block(struct _PyCfgExceptStack *stack, cfg_instr *setup) {
705
813
    assert(is_block_push(setup));
706
813
    int opcode = setup->i_opcode;
707
813
    basicblock * target = setup->i_target;
708
813
    if (opcode == SETUP_WITH || opcode == SETUP_CLEANUP) {
709
521
        target->b_preserve_lasti = 1;
710
521
    }
711
813
    assert(stack->depth <= CO_MAXBLOCKS);
712
813
    stack->handlers[++stack->depth] = target;
713
813
    return target;
714
813
}
715
716
static basicblock *
717
730
pop_except_block(struct _PyCfgExceptStack *stack) {
718
730
    assert(stack->depth > 0);
719
730
    return stack->handlers[--stack->depth];
720
730
}
721
722
static basicblock *
723
13.1k
except_stack_top(struct _PyCfgExceptStack *stack) {
724
13.1k
    return stack->handlers[stack->depth];
725
13.1k
}
726
727
static struct _PyCfgExceptStack *
728
4.26k
make_except_stack(void) {
729
4.26k
    struct _PyCfgExceptStack *new = PyMem_Malloc(sizeof(struct _PyCfgExceptStack));
730
4.26k
    if (new == NULL) {
731
0
        PyErr_NoMemory();
732
0
        return NULL;
733
0
    }
734
4.26k
    new->depth = 0;
735
4.26k
    new->handlers[0] = NULL;
736
4.26k
    return new;
737
4.26k
}
738
739
static struct _PyCfgExceptStack *
740
4.03k
copy_except_stack(struct _PyCfgExceptStack *stack) {
741
4.03k
    struct _PyCfgExceptStack *copy = PyMem_Malloc(sizeof(struct _PyCfgExceptStack));
742
4.03k
    if (copy == NULL) {
743
0
        PyErr_NoMemory();
744
0
        return NULL;
745
0
    }
746
4.03k
    memcpy(copy, stack, sizeof(struct _PyCfgExceptStack));
747
4.03k
    return copy;
748
4.03k
}
749
750
static basicblock**
751
30.5k
make_cfg_traversal_stack(basicblock *entryblock) {
752
30.5k
    int nblocks = 0;
753
156k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
754
126k
        b->b_visited = 0;
755
126k
        nblocks++;
756
126k
    }
757
30.5k
    basicblock **stack = (basicblock **)PyMem_Malloc(sizeof(basicblock *) * nblocks);
758
30.5k
    if (!stack) {
759
0
        PyErr_NoMemory();
760
0
    }
761
30.5k
    return stack;
762
30.5k
}
763
764
/* Compute the stack effects of opcode with argument oparg.
765
766
   Some opcodes have different stack effect when jump to the target and
767
   when not jump. The 'jump' parameter specifies the case:
768
769
   * 0 -- when not jump
770
   * 1 -- when jump
771
   * -1 -- maximal
772
 */
773
typedef struct {
774
    /* The stack effect of the instruction. */
775
    int net;
776
} stack_effects;
777
778
Py_LOCAL(int)
779
get_stack_effects(int opcode, int oparg, int jump, stack_effects *effects)
780
155k
{
781
155k
    if (opcode < 0) {
782
0
        return -1;
783
0
    }
784
155k
    if ((opcode <= MAX_REAL_OPCODE) && (_PyOpcode_Deopt[opcode] != opcode)) {
785
        // Specialized instructions are not supported.
786
0
        return -1;
787
0
    }
788
155k
    int popped = _PyOpcode_num_popped(opcode, oparg);
789
155k
    int pushed = _PyOpcode_num_pushed(opcode, oparg);
790
155k
    if (popped < 0 || pushed < 0) {
791
0
        return -1;
792
0
    }
793
155k
    if (IS_BLOCK_PUSH_OPCODE(opcode) && !jump) {
794
813
        effects->net = 0;
795
813
        return 0;
796
813
    }
797
154k
    effects->net = pushed - popped;
798
154k
    return 0;
799
155k
}
800
801
Py_LOCAL_INLINE(int)
802
stackdepth_push(basicblock ***sp, basicblock *b, int depth)
803
15.6k
{
804
15.6k
    if (!(b->b_startdepth < 0 || b->b_startdepth == depth)) {
805
0
        PyErr_Format(PyExc_ValueError, "Invalid CFG, inconsistent stackdepth");
806
0
        return ERROR;
807
0
    }
808
15.6k
    if (b->b_startdepth < depth && b->b_startdepth < 100) {
809
13.1k
        assert(b->b_startdepth < 0);
810
13.1k
        b->b_startdepth = depth;
811
13.1k
        *(*sp)++ = b;
812
13.1k
    }
813
15.6k
    return SUCCESS;
814
15.6k
}
815
816
/* Find the flow path that needs the largest stack.  We assume that
817
 * cycles in the flow graph have no net effect on the stack depth.
818
 */
819
static int
820
calculate_stackdepth(cfg_builder *g)
821
4.26k
{
822
4.26k
    basicblock *entryblock = g->g_entryblock;
823
20.6k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
824
16.3k
        b->b_startdepth = INT_MIN;
825
16.3k
    }
826
4.26k
    basicblock **stack = make_cfg_traversal_stack(entryblock);
827
4.26k
    if (!stack) {
828
0
        return ERROR;
829
0
    }
830
831
832
4.26k
    int stackdepth = -1;
833
4.26k
    int maxdepth = 0;
834
4.26k
    basicblock **sp = stack;
835
4.26k
    if (stackdepth_push(&sp, entryblock, 0) < 0) {
836
0
        goto error;
837
0
    }
838
17.4k
    while (sp != stack) {
839
13.1k
        basicblock *b = *--sp;
840
13.1k
        int depth = b->b_startdepth;
841
13.1k
        assert(depth >= 0);
842
13.1k
        basicblock *next = b->b_next;
843
155k
        for (int i = 0; i < b->b_iused; i++) {
844
149k
            cfg_instr *instr = &b->b_instr[i];
845
149k
            stack_effects effects;
846
149k
            if (get_stack_effects(instr->i_opcode, instr->i_oparg, 0, &effects) < 0) {
847
0
                PyErr_Format(PyExc_SystemError,
848
0
                             "Invalid stack effect for opcode=%d, arg=%i",
849
0
                             instr->i_opcode, instr->i_oparg);
850
0
                goto error;
851
0
            }
852
149k
            int new_depth = depth + effects.net;
853
149k
            if (new_depth < 0) {
854
0
                PyErr_Format(PyExc_ValueError,
855
0
                             "Invalid CFG, stack underflow at line %d", instr->i_loc.lineno);
856
0
                goto error;
857
0
            }
858
149k
            maxdepth = Py_MAX(maxdepth, depth);
859
149k
            if (HAS_TARGET(instr->i_opcode) && instr->i_opcode != END_ASYNC_FOR) {
860
5.67k
                if (get_stack_effects(instr->i_opcode, instr->i_oparg, 1, &effects) < 0) {
861
0
                    PyErr_Format(PyExc_SystemError,
862
0
                                 "Invalid stack effect for opcode=%d, arg=%i",
863
0
                                 instr->i_opcode, instr->i_oparg);
864
0
                    goto error;
865
0
                }
866
5.67k
                int target_depth = depth + effects.net;
867
5.67k
                assert(target_depth >= 0); /* invalid code or bug in stackdepth() */
868
5.67k
                maxdepth = Py_MAX(maxdepth, depth);
869
5.67k
                if (stackdepth_push(&sp, instr->i_target, target_depth) < 0) {
870
0
                    goto error;
871
0
                }
872
5.67k
            }
873
149k
            depth = new_depth;
874
149k
            assert(!IS_ASSEMBLER_OPCODE(instr->i_opcode));
875
149k
            if (IS_UNCONDITIONAL_JUMP_OPCODE(instr->i_opcode) ||
876
148k
                IS_SCOPE_EXIT_OPCODE(instr->i_opcode))
877
7.47k
            {
878
                /* remaining code is dead */
879
7.47k
                next = NULL;
880
7.47k
                break;
881
7.47k
            }
882
149k
        }
883
13.1k
        if (next != NULL) {
884
5.68k
            assert(BB_HAS_FALLTHROUGH(b));
885
5.68k
            if (stackdepth_push(&sp, next, depth) < 0) {
886
0
                goto error;
887
0
            }
888
5.68k
        }
889
13.1k
    }
890
4.26k
    stackdepth = maxdepth;
891
4.26k
error:
892
4.26k
    PyMem_Free(stack);
893
4.26k
    return stackdepth;
894
4.26k
}
895
896
static int
897
4.26k
label_exception_targets(basicblock *entryblock) {
898
4.26k
    basicblock **todo_stack = make_cfg_traversal_stack(entryblock);
899
4.26k
    if (todo_stack == NULL) {
900
0
        return ERROR;
901
0
    }
902
4.26k
    struct _PyCfgExceptStack *except_stack = make_except_stack();
903
4.26k
    if (except_stack == NULL) {
904
0
        PyMem_Free(todo_stack);
905
0
        PyErr_NoMemory();
906
0
        return ERROR;
907
0
    }
908
4.26k
    except_stack->depth = 0;
909
4.26k
    todo_stack[0] = entryblock;
910
4.26k
    entryblock->b_visited = 1;
911
4.26k
    entryblock->b_exceptstack = except_stack;
912
4.26k
    basicblock **todo = &todo_stack[1];
913
4.26k
    basicblock *handler = NULL;
914
17.3k
    while (todo > todo_stack) {
915
13.1k
        todo--;
916
13.1k
        basicblock *b = todo[0];
917
13.1k
        assert(b->b_visited == 1);
918
13.1k
        except_stack = b->b_exceptstack;
919
13.1k
        assert(except_stack != NULL);
920
13.1k
        b->b_exceptstack = NULL;
921
13.1k
        handler = except_stack_top(except_stack);
922
13.1k
        int last_yield_except_depth = -1;
923
174k
        for (int i = 0; i < b->b_iused; i++) {
924
161k
            cfg_instr *instr = &b->b_instr[i];
925
161k
            if (is_block_push(instr)) {
926
813
                if (!instr->i_target->b_visited) {
927
813
                    struct _PyCfgExceptStack *copy = copy_except_stack(except_stack);
928
813
                    if (copy == NULL) {
929
0
                        goto error;
930
0
                    }
931
813
                    instr->i_target->b_exceptstack = copy;
932
813
                    todo[0] = instr->i_target;
933
813
                    instr->i_target->b_visited = 1;
934
813
                    todo++;
935
813
                }
936
813
                handler = push_except_block(except_stack, instr);
937
813
            }
938
160k
            else if (instr->i_opcode == POP_BLOCK) {
939
730
                handler = pop_except_block(except_stack);
940
730
                INSTR_SET_OP0(instr, NOP);
941
730
            }
942
159k
            else if (is_jump(instr)) {
943
5.47k
                instr->i_except = handler;
944
5.47k
                assert(i == b->b_iused -1);
945
5.47k
                if (!instr->i_target->b_visited) {
946
3.92k
                    if (BB_HAS_FALLTHROUGH(b)) {
947
3.22k
                        struct _PyCfgExceptStack *copy = copy_except_stack(except_stack);
948
3.22k
                        if (copy == NULL) {
949
0
                            goto error;
950
0
                        }
951
3.22k
                        instr->i_target->b_exceptstack = copy;
952
3.22k
                    }
953
703
                    else {
954
703
                        instr->i_target->b_exceptstack = except_stack;
955
703
                        except_stack = NULL;
956
703
                    }
957
3.92k
                    todo[0] = instr->i_target;
958
3.92k
                    instr->i_target->b_visited = 1;
959
3.92k
                    todo++;
960
3.92k
                }
961
5.47k
            }
962
154k
            else if (instr->i_opcode == YIELD_VALUE) {
963
141
                instr->i_except = handler;
964
141
                last_yield_except_depth = except_stack->depth;
965
141
            }
966
154k
            else if (instr->i_opcode == RESUME) {
967
4.43k
                instr->i_except = handler;
968
4.43k
                if (instr->i_oparg != RESUME_AT_FUNC_START && instr->i_oparg != RESUME_AT_GEN_EXPR_START) {
969
141
                    assert(last_yield_except_depth >= 0);
970
141
                    if (last_yield_except_depth == 1) {
971
113
                        instr->i_oparg |= RESUME_OPARG_DEPTH1_MASK;
972
113
                    }
973
141
                    last_yield_except_depth = -1;
974
141
                }
975
4.43k
            }
976
149k
            else if (instr->i_opcode == RETURN_GENERATOR) {
977
94
                instr->i_except = NULL;
978
94
            }
979
149k
            else {
980
149k
                instr->i_except = handler;
981
149k
            }
982
161k
        }
983
13.1k
        if (BB_HAS_FALLTHROUGH(b) && !b->b_next->b_visited) {
984
4.14k
            assert(except_stack != NULL);
985
4.14k
            b->b_next->b_exceptstack = except_stack;
986
4.14k
            todo[0] = b->b_next;
987
4.14k
            b->b_next->b_visited = 1;
988
4.14k
            todo++;
989
4.14k
        }
990
8.99k
        else if (except_stack != NULL) {
991
8.29k
           PyMem_Free(except_stack);
992
8.29k
        }
993
13.1k
    }
994
#ifdef Py_DEBUG
995
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
996
        assert(b->b_exceptstack == NULL);
997
    }
998
#endif
999
4.26k
    PyMem_Free(todo_stack);
1000
4.26k
    return SUCCESS;
1001
0
error:
1002
0
    PyMem_Free(todo_stack);
1003
0
    PyMem_Free(except_stack);
1004
0
    return ERROR;
1005
4.26k
}
1006
1007
/***** CFG optimizations *****/
1008
1009
static int
1010
8.52k
remove_unreachable(basicblock *entryblock) {
1011
41.0k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
1012
32.4k
        b->b_predecessors = 0;
1013
32.4k
    }
1014
8.52k
    basicblock **stack = make_cfg_traversal_stack(entryblock);
1015
8.52k
    if (stack == NULL) {
1016
0
        return ERROR;
1017
0
    }
1018
8.52k
    basicblock **sp = stack;
1019
8.52k
    entryblock->b_predecessors = 1;
1020
8.52k
    *sp++ = entryblock;
1021
8.52k
    entryblock->b_visited = 1;
1022
34.5k
    while (sp > stack) {
1023
26.0k
        basicblock *b = *(--sp);
1024
26.0k
        if (b->b_next && BB_HAS_FALLTHROUGH(b)) {
1025
10.8k
            if (!b->b_next->b_visited) {
1026
9.12k
                assert(b->b_next->b_predecessors == 0);
1027
9.12k
                *sp++ = b->b_next;
1028
9.12k
                b->b_next->b_visited = 1;
1029
9.12k
            }
1030
10.8k
            b->b_next->b_predecessors++;
1031
10.8k
        }
1032
339k
        for (int i = 0; i < b->b_iused; i++) {
1033
313k
            basicblock *target;
1034
313k
            cfg_instr *instr = &b->b_instr[i];
1035
313k
            if (is_jump(instr) || is_block_push(instr)) {
1036
11.6k
                target = instr->i_target;
1037
11.6k
                if (!target->b_visited) {
1038
8.38k
                    *sp++ = target;
1039
8.38k
                    target->b_visited = 1;
1040
8.38k
                }
1041
11.6k
                target->b_predecessors++;
1042
11.6k
            }
1043
313k
        }
1044
26.0k
    }
1045
8.52k
    PyMem_Free(stack);
1046
1047
    /* Delete unreachable instructions */
1048
41.0k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
1049
32.4k
       if (b->b_predecessors == 0) {
1050
6.45k
            b->b_iused = 0;
1051
6.45k
            b->b_except_handler = 0;
1052
6.45k
       }
1053
32.4k
    }
1054
8.52k
    return SUCCESS;
1055
8.52k
}
1056
1057
static int
1058
80.9k
basicblock_remove_redundant_nops(basicblock *bb) {
1059
    /* Remove NOPs when legal to do so. */
1060
80.9k
    int dest = 0;
1061
80.9k
    int prev_lineno = -1;
1062
787k
    for (int src = 0; src < bb->b_iused; src++) {
1063
706k
        int lineno = bb->b_instr[src].i_loc.lineno;
1064
706k
        if (bb->b_instr[src].i_opcode == NOP) {
1065
            /* Eliminate no-op if it doesn't have a line number */
1066
15.2k
            if (lineno < 0) {
1067
3.99k
                continue;
1068
3.99k
            }
1069
            /* or, if the previous instruction had the same line number. */
1070
11.2k
            if (prev_lineno == lineno) {
1071
9.40k
                continue;
1072
9.40k
            }
1073
            /* or, if the next instruction has same line number or no line number */
1074
1.85k
            if (src < bb->b_iused - 1) {
1075
1.70k
                int next_lineno = bb->b_instr[src+1].i_loc.lineno;
1076
1.70k
                if (next_lineno == lineno) {
1077
1.22k
                    continue;
1078
1.22k
                }
1079
488
                if (next_lineno < 0) {
1080
0
                    bb->b_instr[src+1].i_loc = bb->b_instr[src].i_loc;
1081
0
                    continue;
1082
0
                }
1083
488
            }
1084
143
            else {
1085
143
                basicblock *next = next_nonempty_block(bb->b_next);
1086
                /* or if last instruction in BB and next BB has same line number */
1087
143
                if (next) {
1088
143
                    location next_loc = NO_LOCATION;
1089
143
                    for (int next_i=0; next_i < next->b_iused; next_i++) {
1090
143
                        cfg_instr *instr = &next->b_instr[next_i];
1091
143
                        if (instr->i_opcode == NOP && instr->i_loc.lineno < 0) {
1092
                            /* Skip over NOPs without a location, they will be removed */
1093
0
                            continue;
1094
0
                        }
1095
143
                        next_loc = instr->i_loc;
1096
143
                        break;
1097
143
                    }
1098
143
                    if (lineno == next_loc.lineno) {
1099
0
                        continue;
1100
0
                    }
1101
143
                }
1102
143
            }
1103
1104
1.85k
        }
1105
691k
        if (dest != src) {
1106
55.7k
            bb->b_instr[dest] = bb->b_instr[src];
1107
55.7k
        }
1108
691k
        dest++;
1109
691k
        prev_lineno = lineno;
1110
691k
    }
1111
80.9k
    assert(dest <= bb->b_iused);
1112
80.9k
    int num_removed = bb->b_iused - dest;
1113
80.9k
    bb->b_iused = dest;
1114
80.9k
    memset(&bb->b_instr[dest], 0, sizeof(cfg_instr) * num_removed);
1115
80.9k
    return num_removed;
1116
80.9k
}
1117
1118
static int
1119
13.6k
remove_redundant_nops(cfg_builder *g) {
1120
13.6k
    int changes = 0;
1121
78.1k
    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
1122
64.5k
        int change = basicblock_remove_redundant_nops(b);
1123
64.5k
        RETURN_IF_ERROR(change);
1124
64.5k
        changes += change;
1125
64.5k
    }
1126
13.6k
    return changes;
1127
13.6k
}
1128
1129
static int loads_const(int opcode);
1130
1131
static int
1132
remove_redundant_nops_and_pairs(basicblock *entryblock)
1133
4.26k
{
1134
4.26k
    bool done = false;
1135
1136
8.52k
    while (! done) {
1137
4.26k
        done = true;
1138
4.26k
        cfg_instr *prev_instr = NULL;
1139
4.26k
        cfg_instr *instr = NULL;
1140
20.6k
        for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
1141
16.3k
            RETURN_IF_ERROR(basicblock_remove_redundant_nops(b));
1142
16.3k
            if (IS_LABEL(b->b_label)) {
1143
                /* this block is a jump target, forget instr */
1144
5.43k
                instr = NULL;
1145
5.43k
            }
1146
167k
            for (int i = 0; i < b->b_iused; i++) {
1147
151k
                prev_instr = instr;
1148
151k
                instr = &b->b_instr[i];
1149
151k
                int prev_opcode = prev_instr ? prev_instr->i_opcode : 0;
1150
151k
                int prev_oparg = prev_instr ? prev_instr->i_oparg : 0;
1151
151k
                int opcode = instr->i_opcode;
1152
151k
                bool is_redundant_pair = false;
1153
151k
                if (opcode == POP_TOP) {
1154
4.27k
                   if (loads_const(prev_opcode)) {
1155
0
                       is_redundant_pair = true;
1156
0
                   }
1157
4.27k
                   else if (prev_opcode == COPY && prev_oparg == 1) {
1158
0
                       is_redundant_pair = true;
1159
0
                   }
1160
4.27k
                }
1161
151k
                if (is_redundant_pair) {
1162
0
                    INSTR_SET_OP0(prev_instr, NOP);
1163
0
                    INSTR_SET_OP0(instr, NOP);
1164
0
                    done = false;
1165
0
                }
1166
151k
            }
1167
16.3k
            if ((instr && is_jump(instr)) || !BB_HAS_FALLTHROUGH(b)) {
1168
11.6k
                instr = NULL;
1169
11.6k
            }
1170
16.3k
        }
1171
4.26k
    }
1172
4.26k
    return SUCCESS;
1173
4.26k
}
1174
1175
static int
1176
9.36k
remove_redundant_jumps(cfg_builder *g) {
1177
    /* If a non-empty block ends with a jump instruction, check if the next
1178
     * non-empty block reached through normal flow control is the target
1179
     * of that jump. If it is, then the jump instruction is redundant and
1180
     * can be deleted.
1181
     *
1182
     * Return the number of changes applied, or -1 on error.
1183
     */
1184
1185
9.36k
    int changes = 0;
1186
57.5k
    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
1187
48.2k
        cfg_instr *last = basicblock_last_instr(b);
1188
48.2k
        if (last == NULL) {
1189
8.24k
            continue;
1190
8.24k
        }
1191
48.2k
        assert(!IS_ASSEMBLER_OPCODE(last->i_opcode));
1192
39.9k
        if (IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode)) {
1193
4.17k
            basicblock* jump_target = next_nonempty_block(last->i_target);
1194
4.17k
            if (jump_target == NULL) {
1195
0
                PyErr_SetString(PyExc_SystemError, "jump with NULL target");
1196
0
                return ERROR;
1197
0
            }
1198
4.17k
            basicblock *next = next_nonempty_block(b->b_next);
1199
4.17k
            if (jump_target == next) {
1200
169
                changes++;
1201
169
                INSTR_SET_OP0(last, NOP);
1202
169
            }
1203
4.17k
        }
1204
39.9k
    }
1205
1206
9.36k
    return changes;
1207
9.36k
}
1208
1209
static inline bool
1210
15.0k
basicblock_has_no_lineno(basicblock *b) {
1211
18.6k
    for (int i = 0; i < b->b_iused; i++) {
1212
17.0k
        if (b->b_instr[i].i_loc.lineno >= 0) {
1213
13.4k
            return false;
1214
13.4k
        }
1215
17.0k
    }
1216
1.58k
    return true;
1217
15.0k
}
1218
1219
/* Maximum size of basic block that should be copied in optimizer */
1220
750
#define MAX_COPY_SIZE 4
1221
1222
/* If this block ends with an unconditional jump to a small exit block or
1223
 * a block that has no line numbers (and no fallthrough), then
1224
 * remove the jump and extend this block with the target.
1225
 * Returns 1 if extended, 0 if no change, and -1 on error.
1226
 */
1227
static int
1228
21.3k
basicblock_inline_small_or_no_lineno_blocks(basicblock *bb) {
1229
21.3k
    cfg_instr *last = basicblock_last_instr(bb);
1230
21.3k
    if (last == NULL) {
1231
0
        return 0;
1232
0
    }
1233
21.3k
    if (!IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode)) {
1234
18.7k
        return 0;
1235
18.7k
    }
1236
2.61k
    basicblock *target = last->i_target;
1237
2.61k
    bool small_exit_block = (basicblock_exits_scope(target) &&
1238
750
                             target->b_iused <= MAX_COPY_SIZE);
1239
2.61k
    bool no_lineno_no_fallthrough = (basicblock_has_no_lineno(target) &&
1240
618
                                     !BB_HAS_FALLTHROUGH(target));
1241
2.61k
    if (small_exit_block || no_lineno_no_fallthrough) {
1242
697
        assert(is_jump(last));
1243
697
        int removed_jump_opcode = last->i_opcode;
1244
697
        INSTR_SET_OP0(last, NOP);
1245
697
        RETURN_IF_ERROR(basicblock_append_instructions(bb, target));
1246
697
        if (no_lineno_no_fallthrough) {
1247
618
            last = basicblock_last_instr(bb);
1248
618
            if (IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode) &&
1249
183
                removed_jump_opcode == JUMP)
1250
19
            {
1251
                /* Make sure we don't lose eval breaker checks */
1252
19
                last->i_opcode = JUMP;
1253
19
            }
1254
618
        }
1255
697
        target->b_predecessors--;
1256
697
        return 1;
1257
697
    }
1258
1.91k
    return 0;
1259
2.61k
}
1260
1261
static int
1262
4.26k
inline_small_or_no_lineno_blocks(basicblock *entryblock) {
1263
4.26k
    bool changes;
1264
4.59k
    do {
1265
4.59k
        changes = false;
1266
25.9k
        for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
1267
21.3k
            int res = basicblock_inline_small_or_no_lineno_blocks(b);
1268
21.3k
            RETURN_IF_ERROR(res);
1269
21.3k
            if (res) {
1270
697
                changes = true;
1271
697
            }
1272
21.3k
        }
1273
4.59k
    } while(changes); /* every change removes a jump, ensuring convergence */
1274
4.26k
    return changes;
1275
4.26k
}
1276
1277
// Attempt to eliminate jumps to jumps by updating inst to jump to
1278
// target->i_target using the provided opcode. Return whether or not the
1279
// optimization was successful.
1280
static bool
1281
jump_thread(basicblock *bb, cfg_instr *inst, cfg_instr *target, int opcode)
1282
144
{
1283
144
    assert(is_jump(inst));
1284
144
    assert(is_jump(target));
1285
144
    assert(inst == basicblock_last_instr(bb));
1286
    // bpo-45773: If inst->i_target == target->i_target, then nothing actually
1287
    // changes (and we fall into an infinite loop):
1288
144
    if (inst->i_target != target->i_target) {
1289
        /* Change inst to NOP and append a jump to target->i_target. The
1290
         * NOP will be removed later if it's not needed for the lineno.
1291
         */
1292
144
        INSTR_SET_OP0(inst, NOP);
1293
1294
144
        RETURN_IF_ERROR(
1295
144
            basicblock_add_jump(
1296
144
                bb, opcode, target->i_target, target->i_loc));
1297
1298
144
        return true;
1299
144
    }
1300
0
    return false;
1301
144
}
1302
1303
static int
1304
loads_const(int opcode)
1305
175k
{
1306
175k
    return OPCODE_HAS_CONST(opcode)
1307
151k
        || opcode == LOAD_SMALL_INT
1308
134k
        || opcode == LOAD_COMMON_CONSTANT;
1309
175k
}
1310
1311
/* Returns new reference */
1312
static PyObject*
1313
get_const_value(int opcode, int oparg, PyObject *co_consts)
1314
60.8k
{
1315
60.8k
    PyObject *constant = NULL;
1316
60.8k
    assert(loads_const(opcode));
1317
60.8k
    if (opcode == LOAD_CONST) {
1318
58.5k
        assert(PyList_Check(co_consts));
1319
58.5k
        Py_ssize_t n = PyList_GET_SIZE(co_consts);
1320
58.5k
        if (oparg < 0 || oparg >= n) {
1321
0
            PyErr_Format(PyExc_ValueError,
1322
0
                         "LOAD_CONST index %d is out of range for consts (len=%zd)",
1323
0
                         oparg, n);
1324
0
            return NULL;
1325
0
        }
1326
58.5k
        constant = PyList_GET_ITEM(co_consts, oparg);
1327
58.5k
    }
1328
60.8k
    if (opcode == LOAD_SMALL_INT) {
1329
1.86k
        return PyLong_FromLong(oparg);
1330
1.86k
    }
1331
59.0k
    if (opcode == LOAD_COMMON_CONSTANT) {
1332
457
        assert(oparg < NUM_COMMON_CONSTANTS);
1333
457
        return PyStackRef_AsPyObjectBorrow(
1334
457
            _PyInterpreterState_GET()->common_consts[oparg]);
1335
457
    }
1336
1337
58.5k
    if (constant == NULL) {
1338
0
        PyErr_SetString(PyExc_SystemError,
1339
0
                        "Internal error: failed to get value of a constant");
1340
0
        return NULL;
1341
0
    }
1342
58.5k
    return Py_NewRef(constant);
1343
58.5k
}
1344
1345
// Steals a reference to newconst.
1346
static int
1347
add_const(PyObject *newconst, PyObject *consts, PyObject *const_cache,
1348
          _Py_hashtable_t *consts_index)
1349
2.09k
{
1350
2.09k
    if (_PyCompile_ConstCacheMergeOne(const_cache, &newconst) < 0) {
1351
0
        Py_DECREF(newconst);
1352
0
        return -1;
1353
0
    }
1354
1355
2.09k
    _Py_hashtable_entry_t *entry = _Py_hashtable_get_entry(consts_index, (void *)newconst);
1356
2.09k
    if (entry != NULL) {
1357
1.42k
        Py_DECREF(newconst);
1358
1.42k
        return (int)(uintptr_t)entry->value;
1359
1.42k
    }
1360
1361
667
    Py_ssize_t index = PyList_GET_SIZE(consts);
1362
667
    if ((size_t)index >= (size_t)INT_MAX - 1) {
1363
0
        PyErr_SetString(PyExc_OverflowError, "too many constants");
1364
0
        Py_DECREF(newconst);
1365
0
        return -1;
1366
0
    }
1367
667
    if (PyList_Append(consts, newconst)) {
1368
0
        Py_DECREF(newconst);
1369
0
        return -1;
1370
0
    }
1371
1372
667
    if (_Py_hashtable_set(consts_index, (void *)newconst, (void *)(uintptr_t)index) < 0) {
1373
0
        PyList_SetSlice(consts, index, index + 1, NULL);
1374
0
        Py_DECREF(newconst);
1375
0
        PyErr_NoMemory();
1376
0
        return -1;
1377
0
    }
1378
1379
667
    Py_DECREF(newconst);
1380
667
    return (int)index;
1381
667
}
1382
1383
/*
1384
  Traverse the instructions of the basic block backwards from index "start", skipping over NOPs.
1385
  Try to collect "size" number of consecutive instructions that load constants into the array "instrs".
1386
  Caller must make sure that length of "instrs" is sufficient to fit in at least "size" instructions.
1387
1388
  Return boolean indicating whether "size" such instructions were found.
1389
*/
1390
static bool
1391
get_const_loading_instrs(basicblock *bb, int start, cfg_instr **instrs, int size)
1392
5.28k
{
1393
5.28k
    assert(start < bb->b_iused);
1394
5.28k
    assert(size >= 0);
1395
5.28k
    assert(size <= _PY_STACK_USE_GUIDELINE);
1396
1397
9.81k
    for (; start >= 0 && size > 0; start--) {
1398
7.24k
        cfg_instr *instr = &bb->b_instr[start];
1399
7.24k
        if (instr->i_opcode == NOP) {
1400
113
            continue;
1401
113
        }
1402
7.13k
        if (!loads_const(instr->i_opcode)) {
1403
2.71k
            return false;
1404
2.71k
        }
1405
4.41k
        instrs[--size] = instr;
1406
4.41k
    }
1407
1408
2.56k
    return size == 0;
1409
5.28k
}
1410
1411
/*
1412
  Change every instruction in "instrs" NOP and set its location to NO_LOCATION.
1413
  Caller must make sure "instrs" has at least "size" elements.
1414
*/
1415
static void
1416
nop_out(cfg_instr **instrs, int size)
1417
2.68k
{
1418
6.48k
    for (int i = 0; i < size; i++) {
1419
3.79k
        cfg_instr *instr = instrs[i];
1420
3.79k
        assert(instr->i_opcode != NOP);
1421
3.79k
        INSTR_SET_OP0(instr, NOP);
1422
3.79k
        INSTR_SET_LOC(instr, NO_LOCATION);
1423
3.79k
    }
1424
2.68k
}
1425
1426
/* Does not steal reference to "newconst".
1427
   Return 1 if changed instruction to LOAD_SMALL_INT.
1428
   Return 0 if could not change instruction to LOAD_SMALL_INT.
1429
   Return -1 on error.
1430
*/
1431
static int
1432
maybe_instr_make_load_smallint(cfg_instr *instr, PyObject *newconst,
1433
                               PyObject *consts, PyObject *const_cache)
1434
38.3k
{
1435
38.3k
    if (PyLong_CheckExact(newconst)) {
1436
19.8k
        int overflow;
1437
19.8k
        long val = PyLong_AsLongAndOverflow(newconst, &overflow);
1438
19.8k
        if (val == -1 && PyErr_Occurred()) {
1439
0
            return -1;
1440
0
        }
1441
19.8k
        if (!overflow && _PY_IS_SMALL_INT(val) && 0 <= val && val <= 255) {
1442
14.7k
            assert(_Py_IsImmortal(newconst));
1443
14.7k
            INSTR_SET_OP1(instr, LOAD_SMALL_INT, (int)val);
1444
14.7k
            return 1;
1445
14.7k
        }
1446
19.8k
    }
1447
23.5k
    return 0;
1448
38.3k
}
1449
1450
/* Does not steal reference to "newconst".
1451
   Return 1 if changed instruction to LOAD_COMMON_CONSTANT.
1452
   Return 0 if could not change instruction to LOAD_COMMON_CONSTANT.
1453
   Return -1 on error.
1454
*/
1455
static int
1456
maybe_instr_make_load_common_const(cfg_instr *instr, PyObject *newconst)
1457
23.2k
{
1458
23.2k
    int oparg;
1459
23.2k
    if (newconst == Py_None) {
1460
3.93k
        oparg = CONSTANT_NONE;
1461
3.93k
    }
1462
19.3k
    else if (newconst == Py_True) {
1463
353
        oparg = CONSTANT_TRUE;
1464
353
    }
1465
18.9k
    else if (newconst == Py_False) {
1466
502
        oparg = CONSTANT_FALSE;
1467
502
    }
1468
18.4k
    else if (PyUnicode_CheckExact(newconst)
1469
7.47k
             && PyUnicode_GET_LENGTH(newconst) == 0) {
1470
122
        oparg = CONSTANT_EMPTY_STR;
1471
122
    }
1472
18.3k
    else if (PyTuple_CheckExact(newconst)
1473
2.29k
             && PyTuple_GET_SIZE(newconst) == 0) {
1474
631
        oparg = CONSTANT_EMPTY_TUPLE;
1475
631
    }
1476
17.7k
    else if (PyLong_CheckExact(newconst)) {
1477
5.07k
        int overflow;
1478
5.07k
        long val = PyLong_AsLongAndOverflow(newconst, &overflow);
1479
5.07k
        if (val == -1 && PyErr_Occurred()) {
1480
0
            return -1;
1481
0
        }
1482
5.07k
        if (overflow || val != -1) {
1483
4.62k
            return 0;
1484
4.62k
        }
1485
449
        oparg = CONSTANT_MINUS_ONE;
1486
449
    }
1487
12.6k
    else {
1488
12.6k
        return 0;
1489
12.6k
    }
1490
23.2k
    assert(_Py_IsImmortal(newconst));
1491
5.98k
    INSTR_SET_OP1(instr, LOAD_COMMON_CONSTANT, oparg);
1492
5.98k
    return 1;
1493
23.2k
}
1494
1495
/* Steals reference to "newconst" */
1496
static int
1497
instr_make_load_const(cfg_instr *instr, PyObject *newconst,
1498
                      PyObject *consts, PyObject *const_cache,
1499
                      _Py_hashtable_t *consts_index)
1500
2.41k
{
1501
2.41k
    int res = maybe_instr_make_load_smallint(instr, newconst, consts, const_cache);
1502
2.41k
    if (res < 0) {
1503
0
        Py_DECREF(newconst);
1504
0
        return ERROR;
1505
0
    }
1506
2.41k
    if (res > 0) {
1507
3
        return SUCCESS;
1508
3
    }
1509
2.41k
    res = maybe_instr_make_load_common_const(instr, newconst);
1510
2.41k
    if (res < 0) {
1511
0
        Py_DECREF(newconst);
1512
0
        return ERROR;
1513
0
    }
1514
2.41k
    if (res > 0) {
1515
478
        return SUCCESS;
1516
478
    }
1517
1.93k
    int oparg = add_const(newconst, consts, const_cache, consts_index);
1518
1.93k
    RETURN_IF_ERROR(oparg);
1519
1.93k
    INSTR_SET_OP1(instr, LOAD_CONST, oparg);
1520
1.93k
    return SUCCESS;
1521
1.93k
}
1522
1523
/* Replace LOAD_CONST c1, LOAD_CONST c2 ... LOAD_CONST cn, BUILD_TUPLE n
1524
   with    LOAD_CONST (c1, c2, ... cn).
1525
   The consts table must still be in list form so that the
1526
   new constant (c1, c2, ... cn) can be appended.
1527
   Called with codestr pointing to the first LOAD_CONST.
1528
*/
1529
static int
1530
fold_tuple_of_constants(basicblock *bb, int i, PyObject *consts,
1531
                        PyObject *const_cache, _Py_hashtable_t *consts_index)
1532
2.02k
{
1533
    /* Pre-conditions */
1534
2.02k
    assert(PyDict_CheckExact(const_cache));
1535
2.02k
    assert(PyList_CheckExact(consts));
1536
1537
2.02k
    cfg_instr *instr = &bb->b_instr[i];
1538
2.02k
    assert(instr->i_opcode == BUILD_TUPLE);
1539
1540
2.02k
    int seq_size = instr->i_oparg;
1541
2.02k
    if (seq_size > _PY_STACK_USE_GUIDELINE) {
1542
0
        return SUCCESS;
1543
0
    }
1544
1545
2.02k
    cfg_instr *const_instrs[_PY_STACK_USE_GUIDELINE];
1546
2.02k
    if (!get_const_loading_instrs(bb, i-1, const_instrs, seq_size)) {
1547
        /* not a const sequence */
1548
1.36k
        return SUCCESS;
1549
1.36k
    }
1550
1551
657
    PyObject *const_tuple = PyTuple_New((Py_ssize_t)seq_size);
1552
657
    if (const_tuple == NULL) {
1553
0
        return ERROR;
1554
0
    }
1555
1556
1.55k
    for (int i = 0; i < seq_size; i++) {
1557
895
        cfg_instr *inst = const_instrs[i];
1558
895
        assert(loads_const(inst->i_opcode));
1559
895
        PyObject *element = get_const_value(inst->i_opcode, inst->i_oparg, consts);
1560
895
        if (element == NULL) {
1561
0
            Py_DECREF(const_tuple);
1562
0
            return ERROR;
1563
0
        }
1564
895
        PyTuple_SET_ITEM(const_tuple, i, element);
1565
895
    }
1566
1567
657
    nop_out(const_instrs, seq_size);
1568
657
    return instr_make_load_const(instr, const_tuple, consts, const_cache, consts_index);
1569
657
}
1570
1571
/* Replace:
1572
    BUILD_LIST/BUILD_SET 0
1573
    LOAD_CONST c1
1574
    LIST_APPEND/SET_ADD 1
1575
    LOAD_CONST c2
1576
    LIST_APPEND/SET_ADD 1
1577
    ...
1578
    LOAD_CONST cN
1579
    LIST_APPEND/SET_ADD 1
1580
    [CALL_INTRINSIC_1 INTRINSIC_LIST_TO_TUPLE]   <-- optional
1581
   with:
1582
    LOAD_CONST (c1, c2, ... cN)
1583
   The instruction at `i` is either the LIST_TO_TUPLE intrinsic (so the
1584
   immediately preceding non-NOP instruction is expected to be a
1585
   LIST_APPEND, and only the BUILD_LIST/LIST_APPEND form is considered),
1586
   or the trailing LIST_APPEND or SET_ADD itself, in which case the
1587
   matching BUILD_LIST/BUILD_SET start is selected from its opcode, and
1588
   for sets the result is wrapped in a frozenset.
1589
*/
1590
static int
1591
fold_constant_seq_into_load_const(basicblock *bb, int i,
1592
                                  PyObject *consts, PyObject *const_cache,
1593
                                  _Py_hashtable_t *consts_index)
1594
45
{
1595
45
    assert(PyDict_CheckExact(const_cache));
1596
45
    assert(PyList_CheckExact(consts));
1597
45
    assert(i >= 0);
1598
45
    assert(i < bb->b_iused);
1599
1600
45
    cfg_instr *target = &bb->b_instr[i];
1601
45
    assert(target->i_opcode == LIST_APPEND || target->i_opcode == SET_ADD ||
1602
45
           (target->i_opcode == CALL_INTRINSIC_1 &&
1603
45
            target->i_oparg == INTRINSIC_LIST_TO_TUPLE));
1604
45
    bool expected_append = target->i_opcode == CALL_INTRINSIC_1;
1605
45
    int append_op = expected_append ? LIST_APPEND : target->i_opcode;
1606
45
    assert(append_op == LIST_APPEND || append_op == SET_ADD);
1607
45
    int build_op = append_op == LIST_APPEND ? BUILD_LIST : BUILD_SET;
1608
45
    int consts_found = 0;
1609
    /* Walking backward from `i`, we expect LIST_APPEND/SET_ADD and
1610
       LOAD_CONST to alternate. If `i` is the trailing LIST_TO_TUPLE
1611
       intrinsic, the next instruction back is an APPEND. If `i` is the
1612
       trailing APPEND itself, the next instruction back is a LOAD_CONST. */
1613
45
    bool expect_append = expected_append;
1614
1615
5.68k
    for (int pos = i - 1; pos >= 0; pos--) {
1616
5.68k
        cfg_instr *instr = &bb->b_instr[pos];
1617
5.68k
        int opcode = instr->i_opcode;
1618
5.68k
        int oparg = instr->i_oparg;
1619
1620
5.68k
        if (opcode == NOP) {
1621
1.66k
            continue;
1622
1.66k
        }
1623
1624
4.01k
        if (opcode == build_op && oparg == 0) {
1625
2
            if (!expect_append) {
1626
                /* Not a sequence start. */
1627
0
                return SUCCESS;
1628
0
            }
1629
1630
            /* Sequence start, we are done. */
1631
2
            PyObject *newconst = PyTuple_New((Py_ssize_t)consts_found);
1632
2
            if (newconst == NULL) {
1633
0
                return ERROR;
1634
0
            }
1635
1636
2
            int newpos_start = expected_append ? i - 1 : i;
1637
128
            for (int newpos = newpos_start; newpos >= pos; newpos--) {
1638
126
                instr = &bb->b_instr[newpos];
1639
126
                if (instr->i_opcode == NOP) {
1640
0
                    continue;
1641
0
                }
1642
126
                if (loads_const(instr->i_opcode)) {
1643
62
                    PyObject *constant = get_const_value(instr->i_opcode, instr->i_oparg, consts);
1644
62
                    if (constant == NULL) {
1645
0
                        Py_DECREF(newconst);
1646
0
                        return ERROR;
1647
0
                    }
1648
62
                    assert(consts_found > 0);
1649
62
                    PyTuple_SET_ITEM(newconst, --consts_found, constant);
1650
62
                }
1651
126
                nop_out(&instr, 1);
1652
126
            }
1653
2
            assert(consts_found == 0);
1654
1655
2
            if (build_op == BUILD_SET) {
1656
2
                PyObject *frozen = PyFrozenSet_New(newconst);
1657
2
                Py_DECREF(newconst);
1658
2
                if (frozen == NULL) {
1659
0
                    return ERROR;
1660
0
                }
1661
2
                newconst = frozen;
1662
2
            }
1663
2
            return instr_make_load_const(target, newconst, consts, const_cache, consts_index);
1664
2
        }
1665
1666
4.01k
        if (expect_append) {
1667
2.02k
            if (opcode != append_op || oparg != 1) {
1668
41
                return SUCCESS;
1669
41
            }
1670
2.02k
        }
1671
1.98k
        else {
1672
1.98k
            if (!loads_const(opcode)) {
1673
2
                return SUCCESS;
1674
2
            }
1675
1.98k
            consts_found++;
1676
1.98k
        }
1677
1678
3.97k
        expect_append = !expect_append;
1679
3.97k
    }
1680
1681
    /* Did not find sequence start. */
1682
0
    return SUCCESS;
1683
45
}
1684
1685
822
#define MIN_CONST_SEQUENCE_SIZE 3
1686
/*
1687
Optimize lists and sets for:
1688
    1. "for" loop, comprehension or "in"/"not in" tests:
1689
           Change literal list or set of constants into constant
1690
           tuple or frozenset respectively. Change list of
1691
           non-constants into tuple.
1692
    2. Constant literal lists/set with length >= MIN_CONST_SEQUENCE_SIZE:
1693
           Replace LOAD_CONST c1, LOAD_CONST c2 ... LOAD_CONST cN, BUILD_LIST N
1694
           with BUILD_LIST 0, LOAD_CONST (c1, c2, ... cN), LIST_EXTEND 1,
1695
           or BUILD_SET & SET_UPDATE respectively.
1696
*/
1697
static int
1698
optimize_lists_and_sets(basicblock *bb, int i, int nextop,
1699
                        PyObject *consts, PyObject *const_cache,
1700
                        _Py_hashtable_t *consts_index)
1701
411
{
1702
411
    assert(PyDict_CheckExact(const_cache));
1703
411
    assert(PyList_CheckExact(consts));
1704
1705
411
    cfg_instr *instr = &bb->b_instr[i];
1706
411
    assert(instr->i_opcode == BUILD_LIST || instr->i_opcode == BUILD_SET);
1707
1708
411
    bool contains_or_iter = nextop == GET_ITER || nextop == CONTAINS_OP;
1709
411
    int seq_size = instr->i_oparg;
1710
411
    if (seq_size > _PY_STACK_USE_GUIDELINE ||
1711
411
        (seq_size < MIN_CONST_SEQUENCE_SIZE && !contains_or_iter))
1712
261
    {
1713
261
        return SUCCESS;
1714
261
    }
1715
1716
150
    cfg_instr *const_instrs[_PY_STACK_USE_GUIDELINE];
1717
150
    if (!get_const_loading_instrs(bb, i-1, const_instrs, seq_size)) {  /* not a const sequence */
1718
5
        if (contains_or_iter && instr->i_opcode == BUILD_LIST) {
1719
            /* iterate over a tuple instead of list */
1720
0
            INSTR_SET_OP1(instr, BUILD_TUPLE, instr->i_oparg);
1721
0
        }
1722
5
        return SUCCESS;
1723
5
    }
1724
1725
145
    PyObject *const_result = PyTuple_New((Py_ssize_t)seq_size);
1726
145
    if (const_result == NULL) {
1727
0
        return ERROR;
1728
0
    }
1729
1730
1.13k
    for (int i = 0; i < seq_size; i++) {
1731
988
        cfg_instr *inst = const_instrs[i];
1732
988
        assert(loads_const(inst->i_opcode));
1733
988
        PyObject *element = get_const_value(inst->i_opcode, inst->i_oparg, consts);
1734
988
        if (element == NULL) {
1735
0
            Py_DECREF(const_result);
1736
0
            return ERROR;
1737
0
        }
1738
988
        PyTuple_SET_ITEM(const_result, i, element);
1739
988
    }
1740
1741
145
    if (instr->i_opcode == BUILD_SET) {
1742
133
        PyObject *frozenset = PyFrozenSet_New(const_result);
1743
133
        if (frozenset == NULL) {
1744
0
            Py_DECREF(const_result);
1745
0
            return ERROR;
1746
0
        }
1747
133
        Py_SETREF(const_result, frozenset);
1748
133
    }
1749
1750
145
    int index = add_const(const_result, consts, const_cache, consts_index);
1751
145
    RETURN_IF_ERROR(index);
1752
145
    nop_out(const_instrs, seq_size);
1753
1754
145
    if (contains_or_iter) {
1755
123
        INSTR_SET_OP1(instr, LOAD_CONST, index);
1756
123
    }
1757
22
    else {
1758
22
        assert(i >= 2);
1759
22
        assert(instr->i_opcode == BUILD_LIST || instr->i_opcode == BUILD_SET);
1760
1761
22
        INSTR_SET_LOC(&bb->b_instr[i-2], instr->i_loc);
1762
1763
22
        INSTR_SET_OP1(&bb->b_instr[i-2], instr->i_opcode, 0);
1764
22
        INSTR_SET_OP1(&bb->b_instr[i-1], LOAD_CONST, index);
1765
22
        INSTR_SET_OP1(&bb->b_instr[i], instr->i_opcode == BUILD_LIST ? LIST_EXTEND : SET_UPDATE, 1);
1766
22
    }
1767
145
    return SUCCESS;
1768
145
}
1769
1770
/* Check whether the total number of items in the (possibly nested) collection obj exceeds
1771
 * limit. Return a negative number if it does, and a non-negative number otherwise.
1772
 * Used to avoid creating constants which are slow to hash.
1773
 */
1774
static Py_ssize_t
1775
const_folding_check_complexity(PyObject *obj, Py_ssize_t limit)
1776
0
{
1777
0
    if (PyTuple_Check(obj)) {
1778
0
        Py_ssize_t i;
1779
0
        limit -= PyTuple_GET_SIZE(obj);
1780
0
        for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++) {
1781
0
            limit = const_folding_check_complexity(PyTuple_GET_ITEM(obj, i), limit);
1782
0
            if (limit < 0) {
1783
0
                return limit;
1784
0
            }
1785
0
        }
1786
0
    }
1787
0
    return limit;
1788
0
}
1789
1790
63
#define MAX_INT_SIZE           128  /* bits */
1791
0
#define MAX_COLLECTION_SIZE    256  /* items */
1792
2
#define MAX_STR_SIZE          4096  /* characters */
1793
0
#define MAX_TOTAL_ITEMS       1024  /* including nested collections */
1794
1795
static PyObject *
1796
const_folding_safe_multiply(PyObject *v, PyObject *w)
1797
6
{
1798
6
    if (PyLong_Check(v) && PyLong_Check(w) &&
1799
2
        !_PyLong_IsZero((PyLongObject *)v) && !_PyLong_IsZero((PyLongObject *)w)
1800
6
    ) {
1801
2
        int64_t vbits = _PyLong_NumBits(v);
1802
2
        int64_t wbits = _PyLong_NumBits(w);
1803
2
        assert(vbits >= 0);
1804
2
        assert(wbits >= 0);
1805
2
        if (vbits + wbits > MAX_INT_SIZE) {
1806
0
            return NULL;
1807
0
        }
1808
2
    }
1809
4
    else if (PyLong_Check(v) && PyTuple_Check(w)) {
1810
0
        Py_ssize_t size = PyTuple_GET_SIZE(w);
1811
0
        if (size) {
1812
0
            long n = PyLong_AsLong(v);
1813
0
            if (n < 0 || n > MAX_COLLECTION_SIZE / size) {
1814
0
                return NULL;
1815
0
            }
1816
0
            if (n && const_folding_check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) {
1817
0
                return NULL;
1818
0
            }
1819
0
        }
1820
0
    }
1821
4
    else if (PyLong_Check(v) && (PyUnicode_Check(w) || PyBytes_Check(w))) {
1822
2
        Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH(w) :
1823
2
                                               PyBytes_GET_SIZE(w);
1824
2
        if (size) {
1825
2
            long n = PyLong_AsLong(v);
1826
2
            if (n < 0 || n > MAX_STR_SIZE / size) {
1827
0
                return NULL;
1828
0
            }
1829
2
        }
1830
2
    }
1831
2
    else if (PyLong_Check(w) &&
1832
2
             (PyTuple_Check(v) || PyUnicode_Check(v) || PyBytes_Check(v)))
1833
2
    {
1834
2
        return const_folding_safe_multiply(w, v);
1835
2
    }
1836
1837
4
    return PyNumber_Multiply(v, w);
1838
6
}
1839
1840
static PyObject *
1841
const_folding_safe_power(PyObject *v, PyObject *w)
1842
1
{
1843
1
    if (PyLong_Check(v) && PyLong_Check(w) &&
1844
1
        !_PyLong_IsZero((PyLongObject *)v) && _PyLong_IsPositive((PyLongObject *)w)
1845
1
    ) {
1846
1
        int64_t vbits = _PyLong_NumBits(v);
1847
1
        size_t wbits = PyLong_AsSize_t(w);
1848
1
        assert(vbits >= 0);
1849
1
        if (wbits == (size_t)-1) {
1850
0
            return NULL;
1851
0
        }
1852
1
        if ((uint64_t)vbits > MAX_INT_SIZE / wbits) {
1853
0
            return NULL;
1854
0
        }
1855
1
    }
1856
1857
1
    return PyNumber_Power(v, w, Py_None);
1858
1
}
1859
1860
static PyObject *
1861
const_folding_safe_lshift(PyObject *v, PyObject *w)
1862
20
{
1863
20
    if (PyLong_Check(v) && PyLong_Check(w) &&
1864
20
        !_PyLong_IsZero((PyLongObject *)v) && !_PyLong_IsZero((PyLongObject *)w)
1865
20
    ) {
1866
20
        int64_t vbits = _PyLong_NumBits(v);
1867
20
        size_t wbits = PyLong_AsSize_t(w);
1868
20
        assert(vbits >= 0);
1869
20
        if (wbits == (size_t)-1) {
1870
0
            return NULL;
1871
0
        }
1872
20
        if (wbits > MAX_INT_SIZE || (uint64_t)vbits > MAX_INT_SIZE - wbits) {
1873
0
            return NULL;
1874
0
        }
1875
20
    }
1876
1877
20
    return PyNumber_Lshift(v, w);
1878
20
}
1879
1880
static PyObject *
1881
const_folding_safe_mod(PyObject *v, PyObject *w)
1882
0
{
1883
0
    if (PyUnicode_Check(v) || PyBytes_Check(v)) {
1884
0
        return NULL;
1885
0
    }
1886
1887
0
    return PyNumber_Remainder(v, w);
1888
0
}
1889
1890
static PyObject *
1891
eval_const_binop(PyObject *left, int op, PyObject *right)
1892
30
{
1893
30
    assert(left != NULL && right != NULL);
1894
30
    assert(op >= 0 && op <= NB_OPARG_LAST);
1895
1896
30
    PyObject *result = NULL;
1897
30
    switch (op) {
1898
1
        case NB_ADD:
1899
1
            result = PyNumber_Add(left, right);
1900
1
            break;
1901
1
        case NB_SUBTRACT:
1902
1
            result = PyNumber_Subtract(left, right);
1903
1
            break;
1904
4
        case NB_MULTIPLY:
1905
4
            result = const_folding_safe_multiply(left, right);
1906
4
            break;
1907
0
        case NB_TRUE_DIVIDE:
1908
0
            result = PyNumber_TrueDivide(left, right);
1909
0
            break;
1910
0
        case NB_FLOOR_DIVIDE:
1911
0
            result = PyNumber_FloorDivide(left, right);
1912
0
            break;
1913
0
        case NB_REMAINDER:
1914
0
            result = const_folding_safe_mod(left, right);
1915
0
            break;
1916
1
        case NB_POWER:
1917
1
            result = const_folding_safe_power(left, right);
1918
1
            break;
1919
20
        case NB_LSHIFT:
1920
20
            result = const_folding_safe_lshift(left, right);
1921
20
            break;
1922
0
        case NB_RSHIFT:
1923
0
            result = PyNumber_Rshift(left, right);
1924
0
            break;
1925
0
        case NB_OR:
1926
0
            result = PyNumber_Or(left, right);
1927
0
            break;
1928
0
        case NB_XOR:
1929
0
            result = PyNumber_Xor(left, right);
1930
0
            break;
1931
0
        case NB_AND:
1932
0
            result = PyNumber_And(left, right);
1933
0
            break;
1934
3
        case NB_SUBSCR:
1935
3
            result = PyObject_GetItem(left, right);
1936
3
            break;
1937
0
        case NB_MATRIX_MULTIPLY:
1938
            // No builtin constants implement matrix multiplication
1939
0
            break;
1940
0
        default:
1941
0
            Py_UNREACHABLE();
1942
30
    }
1943
30
    return result;
1944
30
}
1945
1946
static int
1947
fold_const_binop(basicblock *bb, int i, PyObject *consts,
1948
                 PyObject *const_cache, _Py_hashtable_t *consts_index)
1949
1.37k
{
1950
1.40k
    #define BINOP_OPERAND_COUNT 2
1951
1.37k
    assert(PyDict_CheckExact(const_cache));
1952
1.37k
    assert(PyList_CheckExact(consts));
1953
1954
1.37k
    cfg_instr *binop = &bb->b_instr[i];
1955
1.37k
    assert(binop->i_opcode == BINARY_OP);
1956
1957
1.37k
    cfg_instr *operands_instrs[BINOP_OPERAND_COUNT];
1958
1.37k
    if (!get_const_loading_instrs(bb, i-1, operands_instrs, BINOP_OPERAND_COUNT)) {
1959
        /* not a const sequence */
1960
1.34k
        return SUCCESS;
1961
1.34k
    }
1962
1963
30
    cfg_instr *lhs_instr = operands_instrs[0];
1964
30
    assert(loads_const(lhs_instr->i_opcode));
1965
30
    PyObject *lhs = get_const_value(lhs_instr->i_opcode, lhs_instr->i_oparg, consts);
1966
30
    if (lhs == NULL) {
1967
0
        return ERROR;
1968
0
    }
1969
1970
30
    cfg_instr *rhs_instr = operands_instrs[1];
1971
30
    assert(loads_const(rhs_instr->i_opcode));
1972
30
    PyObject *rhs = get_const_value(rhs_instr->i_opcode, rhs_instr->i_oparg, consts);
1973
30
    if (rhs == NULL) {
1974
0
        Py_DECREF(lhs);
1975
0
        return ERROR;
1976
0
    }
1977
1978
30
    PyObject *newconst = eval_const_binop(lhs, binop->i_oparg, rhs);
1979
30
    Py_DECREF(lhs);
1980
30
    Py_DECREF(rhs);
1981
30
    if (newconst == NULL) {
1982
0
        if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
1983
0
            return ERROR;
1984
0
        }
1985
0
        PyErr_Clear();
1986
0
        return SUCCESS;
1987
0
    }
1988
1989
30
    nop_out(operands_instrs, BINOP_OPERAND_COUNT);
1990
30
    return instr_make_load_const(binop, newconst, consts, const_cache, consts_index);
1991
30
}
1992
1993
static PyObject *
1994
eval_const_unaryop(PyObject *operand, int opcode, int oparg)
1995
1.72k
{
1996
1.72k
    assert(operand != NULL);
1997
1.72k
    assert(
1998
1.72k
        opcode == UNARY_NEGATIVE ||
1999
1.72k
        opcode == UNARY_INVERT ||
2000
1.72k
        opcode == UNARY_NOT ||
2001
1.72k
        (opcode == CALL_INTRINSIC_1 && oparg == INTRINSIC_UNARY_POSITIVE)
2002
1.72k
    );
2003
1.72k
    PyObject *result;
2004
1.72k
    switch (opcode) {
2005
1.72k
        case UNARY_NEGATIVE:
2006
1.72k
            result = PyNumber_Negative(operand);
2007
1.72k
            break;
2008
0
        case UNARY_INVERT:
2009
            // XXX: This should be removed once the ~bool depreciation expires.
2010
0
            if (PyBool_Check(operand)) {
2011
0
                return NULL;
2012
0
            }
2013
0
            result = PyNumber_Invert(operand);
2014
0
            break;
2015
0
        case UNARY_NOT: {
2016
0
            int r = PyObject_IsTrue(operand);
2017
0
            if (r < 0) {
2018
0
                return NULL;
2019
0
            }
2020
0
            result = PyBool_FromLong(!r);
2021
0
            break;
2022
0
        }
2023
0
        case CALL_INTRINSIC_1:
2024
0
            if (oparg != INTRINSIC_UNARY_POSITIVE) {
2025
0
                Py_UNREACHABLE();
2026
0
            }
2027
0
            result = PyNumber_Positive(operand);
2028
0
            break;
2029
0
        default:
2030
0
            Py_UNREACHABLE();
2031
1.72k
    }
2032
1.72k
    return result;
2033
1.72k
}
2034
2035
static int
2036
fold_const_unaryop(basicblock *bb, int i, PyObject *consts,
2037
                   PyObject *const_cache, _Py_hashtable_t *consts_index)
2038
1.73k
{
2039
3.46k
    #define UNARYOP_OPERAND_COUNT 1
2040
1.73k
    assert(PyDict_CheckExact(const_cache));
2041
1.73k
    assert(PyList_CheckExact(consts));
2042
1.73k
    cfg_instr *unaryop = &bb->b_instr[i];
2043
2044
1.73k
    cfg_instr *operand_instr;
2045
1.73k
    if (!get_const_loading_instrs(bb, i-1, &operand_instr, UNARYOP_OPERAND_COUNT)) {
2046
        /* not a const */
2047
10
        return SUCCESS;
2048
10
    }
2049
2050
1.73k
    assert(loads_const(operand_instr->i_opcode));
2051
1.72k
    PyObject *operand = get_const_value(
2052
1.72k
        operand_instr->i_opcode,
2053
1.72k
        operand_instr->i_oparg,
2054
1.72k
        consts
2055
1.72k
    );
2056
1.72k
    if (operand == NULL) {
2057
0
        return ERROR;
2058
0
    }
2059
2060
1.72k
    PyObject *newconst = eval_const_unaryop(operand, unaryop->i_opcode, unaryop->i_oparg);
2061
1.72k
    Py_DECREF(operand);
2062
1.72k
    if (newconst == NULL) {
2063
0
        if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
2064
0
            return ERROR;
2065
0
        }
2066
0
        PyErr_Clear();
2067
0
        return SUCCESS;
2068
0
    }
2069
2070
1.72k
    if (unaryop->i_opcode == UNARY_NOT) {
2071
0
        assert(PyBool_Check(newconst));
2072
0
    }
2073
1.72k
    nop_out(&operand_instr, UNARYOP_OPERAND_COUNT);
2074
1.72k
    return instr_make_load_const(unaryop, newconst, consts, const_cache, consts_index);
2075
1.72k
}
2076
2077
1.23k
#define VISITED (-1)
2078
2079
// Replace an arbitrary run of SWAPs and NOPs with an optimal one that has the
2080
// same effect.
2081
static int
2082
swaptimize(basicblock *block, int *ix)
2083
484
{
2084
    // NOTE: "./python -m test test_patma" serves as a good, quick stress test
2085
    // for this function. Make sure to blow away cached *.pyc files first!
2086
484
    assert(*ix < block->b_iused);
2087
484
    cfg_instr *instructions = &block->b_instr[*ix];
2088
    // Find the length of the current sequence of SWAPs and NOPs, and record the
2089
    // maximum depth of the stack manipulations:
2090
484
    assert(instructions[0].i_opcode == SWAP);
2091
484
    int depth = instructions[0].i_oparg;
2092
484
    int len = 0;
2093
484
    int more = false;
2094
484
    int limit = block->b_iused - *ix;
2095
598
    while (++len < limit) {
2096
598
        int opcode = instructions[len].i_opcode;
2097
598
        if (opcode == SWAP) {
2098
95
            depth = Py_MAX(depth, instructions[len].i_oparg);
2099
95
            more = true;
2100
95
        }
2101
503
        else if (opcode != NOP) {
2102
484
            break;
2103
484
        }
2104
598
    }
2105
    // It's already optimal if there's only one SWAP:
2106
484
    if (!more) {
2107
389
        return SUCCESS;
2108
389
    }
2109
    // Create an array with elements {0, 1, 2, ..., depth - 1}:
2110
95
    int *stack = PyMem_Malloc(depth * sizeof(int));
2111
95
    if (stack == NULL) {
2112
0
        PyErr_NoMemory();
2113
0
        return ERROR;
2114
0
    }
2115
380
    for (int i = 0; i < depth; i++) {
2116
285
        stack[i] = i;
2117
285
    }
2118
    // Simulate the combined effect of these instructions by "running" them on
2119
    // our "stack":
2120
285
    for (int i = 0; i < len; i++) {
2121
190
        if (instructions[i].i_opcode == SWAP) {
2122
190
            int oparg = instructions[i].i_oparg;
2123
190
            int top = stack[0];
2124
            // SWAPs are 1-indexed:
2125
190
            stack[0] = stack[oparg - 1];
2126
190
            stack[oparg - 1] = top;
2127
190
        }
2128
190
    }
2129
    // Now we can begin! Our approach here is based on a solution to a closely
2130
    // related problem (https://cs.stackexchange.com/a/13938). It's easiest to
2131
    // think of this algorithm as determining the steps needed to efficiently
2132
    // "un-shuffle" our stack. By performing the moves in *reverse* order,
2133
    // though, we can efficiently *shuffle* it! For this reason, we will be
2134
    // replacing instructions starting from the *end* of the run. Since the
2135
    // solution is optimal, we don't need to worry about running out of space:
2136
95
    int current = len - 1;
2137
380
    for (int i = 0; i < depth; i++) {
2138
        // Skip items that have already been visited, or just happen to be in
2139
        // the correct location:
2140
285
        if (stack[i] == VISITED || stack[i] == i) {
2141
190
            continue;
2142
190
        }
2143
        // Okay, we've found an item that hasn't been visited. It forms a cycle
2144
        // with other items; traversing the cycle and swapping each item with
2145
        // the next will put them all in the correct place. The weird
2146
        // loop-and-a-half is necessary to insert 0 into every cycle, since we
2147
        // can only swap from that position:
2148
95
        int j = i;
2149
380
        while (true) {
2150
            // Skip the actual swap if our item is zero, since swapping the top
2151
            // item with itself is pointless:
2152
380
            if (j) {
2153
190
                assert(0 <= current);
2154
                // SWAPs are 1-indexed:
2155
190
                instructions[current].i_opcode = SWAP;
2156
190
                instructions[current--].i_oparg = j + 1;
2157
190
            }
2158
380
            if (stack[j] == VISITED) {
2159
                // Completed the cycle:
2160
95
                assert(j == i);
2161
95
                break;
2162
95
            }
2163
285
            int next_j = stack[j];
2164
285
            stack[j] = VISITED;
2165
285
            j = next_j;
2166
285
        }
2167
95
    }
2168
    // NOP out any unused instructions:
2169
95
    while (0 <= current) {
2170
0
        INSTR_SET_OP0(&instructions[current--], NOP);
2171
0
    }
2172
95
    PyMem_Free(stack);
2173
95
    *ix += len - 1;
2174
95
    return SUCCESS;
2175
95
}
2176
2177
2178
// This list is pretty small, since it's only okay to reorder opcodes that:
2179
// - can't affect control flow (like jumping or raising exceptions)
2180
// - can't invoke arbitrary code (besides finalizers)
2181
// - only touch the TOS (and pop it when finished)
2182
#define SWAPPABLE(opcode) \
2183
789
    ((opcode) == STORE_FAST || \
2184
789
     (opcode) == STORE_FAST_MAYBE_NULL || \
2185
789
     (opcode) == POP_TOP)
2186
2187
#define STORES_TO(instr) \
2188
171
    (((instr).i_opcode == STORE_FAST || \
2189
171
      (instr).i_opcode == STORE_FAST_MAYBE_NULL) \
2190
171
     ? (instr).i_oparg : -1)
2191
2192
static int
2193
next_swappable_instruction(basicblock *block, int i, int lineno)
2194
747
{
2195
766
    while (++i < block->b_iused) {
2196
761
        cfg_instr *instruction = &block->b_instr[i];
2197
761
        if (0 <= lineno && instruction->i_loc.lineno != lineno) {
2198
            // Optimizing across this instruction could cause user-visible
2199
            // changes in the names bound between line tracing events!
2200
3
            return -1;
2201
3
        }
2202
758
        if (instruction->i_opcode == NOP) {
2203
19
            continue;
2204
19
        }
2205
739
        if (SWAPPABLE(instruction->i_opcode)) {
2206
342
            return i;
2207
342
        }
2208
397
        return -1;
2209
739
    }
2210
5
    return -1;
2211
747
}
2212
2213
// Attempt to apply SWAPs statically by swapping *instructions* rather than
2214
// stack items. For example, we can replace SWAP(2), POP_TOP, STORE_FAST(42)
2215
// with the more efficient NOP, STORE_FAST(42), POP_TOP.
2216
static void
2217
apply_static_swaps(basicblock *block, int i)
2218
484
{
2219
    // SWAPs are to our left, and potential swaperands are to our right:
2220
613
    for (; 0 <= i; i--) {
2221
584
        assert(i < block->b_iused);
2222
584
        cfg_instr *swap = &block->b_instr[i];
2223
584
        if (swap->i_opcode != SWAP) {
2224
100
            if (swap->i_opcode == NOP || SWAPPABLE(swap->i_opcode)) {
2225
                // Nope, but we know how to handle these. Keep looking:
2226
50
                continue;
2227
50
            }
2228
            // We can't reason about what this instruction does. Bail:
2229
50
            return;
2230
100
        }
2231
484
        int j = next_swappable_instruction(block, i, -1);
2232
484
        if (j < 0) {
2233
255
            return;
2234
255
        }
2235
229
        int k = j;
2236
229
        int lineno = block->b_instr[j].i_loc.lineno;
2237
342
        for (int count = swap->i_oparg - 1; 0 < count; count--) {
2238
263
            k = next_swappable_instruction(block, k, lineno);
2239
263
            if (k < 0) {
2240
150
                return;
2241
150
            }
2242
263
        }
2243
        // The reordering is not safe if the two instructions to be swapped
2244
        // store to the same location, or if any intervening instruction stores
2245
        // to the same location as either of them.
2246
79
        int store_j = STORES_TO(block->b_instr[j]);
2247
79
        int store_k = STORES_TO(block->b_instr[k]);
2248
79
        if (store_j >= 0 || store_k >= 0) {
2249
79
            if (store_j == store_k) {
2250
0
                return;
2251
0
            }
2252
92
            for (int idx = j + 1; idx < k; idx++) {
2253
13
                int store_idx = STORES_TO(block->b_instr[idx]);
2254
13
                if (store_idx >= 0 && (store_idx == store_j || store_idx == store_k)) {
2255
0
                    return;
2256
0
                }
2257
13
            }
2258
79
        }
2259
2260
        // Success!
2261
79
        INSTR_SET_OP0(swap, NOP);
2262
79
        cfg_instr temp = block->b_instr[j];
2263
79
        block->b_instr[j] = block->b_instr[k];
2264
79
        block->b_instr[k] = temp;
2265
79
    }
2266
484
}
2267
2268
static int
2269
basicblock_optimize_load_const(PyObject *const_cache, basicblock *bb,
2270
                               PyObject *consts, _Py_hashtable_t *consts_index)
2271
16.3k
{
2272
16.3k
    assert(PyDict_CheckExact(const_cache));
2273
16.3k
    assert(PyList_CheckExact(consts));
2274
16.3k
    int opcode = 0;
2275
16.3k
    int oparg = 0;
2276
178k
    for (int i = 0; i < bb->b_iused; i++) {
2277
162k
        cfg_instr *inst = &bb->b_instr[i];
2278
162k
        if (inst->i_opcode == LOAD_CONST) {
2279
35.9k
            PyObject *constant = get_const_value(inst->i_opcode, inst->i_oparg, consts);
2280
35.9k
            if (constant == NULL) {
2281
0
                return ERROR;
2282
0
            }
2283
35.9k
            int res = maybe_instr_make_load_smallint(inst, constant, consts, const_cache);
2284
35.9k
            Py_DECREF(constant);
2285
35.9k
            if (res < 0) {
2286
0
                return ERROR;
2287
0
            }
2288
35.9k
        }
2289
162k
        bool is_copy_of_load_const = (opcode == LOAD_CONST &&
2290
21.1k
                                      inst->i_opcode == COPY &&
2291
9
                                      inst->i_oparg == 1);
2292
162k
        if (! is_copy_of_load_const) {
2293
162k
            opcode = inst->i_opcode;
2294
162k
            oparg = inst->i_oparg;
2295
162k
        }
2296
162k
        assert(!IS_ASSEMBLER_OPCODE(opcode));
2297
162k
        if (!loads_const(opcode)) {
2298
126k
            continue;
2299
126k
        }
2300
36.0k
        int nextop = i+1 < bb->b_iused ? bb->b_instr[i+1].i_opcode : 0;
2301
36.0k
        switch(nextop) {
2302
16
            case POP_JUMP_IF_FALSE:
2303
16
            case POP_JUMP_IF_TRUE:
2304
16
            case JUMP_IF_FALSE:
2305
16
            case JUMP_IF_TRUE:
2306
16
            {
2307
                /* Remove LOAD_CONST const; conditional jump */
2308
16
                PyObject* cnt = get_const_value(opcode, oparg, consts);
2309
16
                if (cnt == NULL) {
2310
0
                    return ERROR;
2311
0
                }
2312
16
                int is_true = PyObject_IsTrue(cnt);
2313
16
                Py_DECREF(cnt);
2314
16
                if (is_true == -1) {
2315
0
                    return ERROR;
2316
0
                }
2317
16
                if (PyCompile_OpcodeStackEffect(nextop, 0) == -1) {
2318
                    /* POP_JUMP_IF_FALSE or POP_JUMP_IF_TRUE */
2319
16
                    INSTR_SET_OP0(inst, NOP);
2320
16
                }
2321
16
                int jump_if_true = (nextop == POP_JUMP_IF_TRUE || nextop == JUMP_IF_TRUE);
2322
16
                if (is_true == jump_if_true) {
2323
0
                    bb->b_instr[i+1].i_opcode = JUMP;
2324
0
                }
2325
16
                else {
2326
16
                    INSTR_SET_OP0(&bb->b_instr[i + 1], NOP);
2327
16
                }
2328
16
                break;
2329
16
            }
2330
324
            case IS_OP:
2331
324
            {
2332
                // Fold to POP_JUMP_IF_NONE:
2333
                // - LOAD_CONST(None) IS_OP(0) POP_JUMP_IF_TRUE
2334
                // - LOAD_CONST(None) IS_OP(1) POP_JUMP_IF_FALSE
2335
                // - LOAD_CONST(None) IS_OP(0) TO_BOOL POP_JUMP_IF_TRUE
2336
                // - LOAD_CONST(None) IS_OP(1) TO_BOOL POP_JUMP_IF_FALSE
2337
                // Fold to POP_JUMP_IF_NOT_NONE:
2338
                // - LOAD_CONST(None) IS_OP(0) POP_JUMP_IF_FALSE
2339
                // - LOAD_CONST(None) IS_OP(1) POP_JUMP_IF_TRUE
2340
                // - LOAD_CONST(None) IS_OP(0) TO_BOOL POP_JUMP_IF_FALSE
2341
                // - LOAD_CONST(None) IS_OP(1) TO_BOOL POP_JUMP_IF_TRUE
2342
324
                PyObject *cnt = get_const_value(opcode, oparg, consts);
2343
324
                if (cnt == NULL) {
2344
0
                    return ERROR;
2345
0
                }
2346
324
                if (!Py_IsNone(cnt)) {
2347
33
                    Py_DECREF(cnt);
2348
33
                    break;
2349
33
                }
2350
291
                if (bb->b_iused <= i + 2) {
2351
0
                    break;
2352
0
                }
2353
291
                cfg_instr *is_instr = &bb->b_instr[i + 1];
2354
291
                cfg_instr *jump_instr = &bb->b_instr[i + 2];
2355
                // Get rid of TO_BOOL regardless:
2356
291
                if (jump_instr->i_opcode == TO_BOOL) {
2357
284
                    INSTR_SET_OP0(jump_instr, NOP);
2358
284
                    if (bb->b_iused <= i + 3) {
2359
0
                        break;
2360
0
                    }
2361
284
                    jump_instr = &bb->b_instr[i + 3];
2362
284
                }
2363
291
                bool invert = is_instr->i_oparg;
2364
291
                if (jump_instr->i_opcode == POP_JUMP_IF_FALSE) {
2365
272
                    invert = !invert;
2366
272
                }
2367
19
                else if (jump_instr->i_opcode != POP_JUMP_IF_TRUE) {
2368
7
                    break;
2369
7
                }
2370
284
                INSTR_SET_OP0(inst, NOP);
2371
284
                INSTR_SET_OP0(is_instr, NOP);
2372
284
                jump_instr->i_opcode = invert ? POP_JUMP_IF_NOT_NONE
2373
284
                                              : POP_JUMP_IF_NONE;
2374
284
                break;
2375
291
            }
2376
16
            case TO_BOOL:
2377
16
            {
2378
16
                PyObject *cnt = get_const_value(opcode, oparg, consts);
2379
16
                if (cnt == NULL) {
2380
0
                    return ERROR;
2381
0
                }
2382
16
                int is_true = PyObject_IsTrue(cnt);
2383
16
                Py_DECREF(cnt);
2384
16
                if (is_true == -1) {
2385
0
                    return ERROR;
2386
0
                }
2387
16
                cnt = PyBool_FromLong(is_true);
2388
16
                int index = add_const(cnt, consts, const_cache, consts_index);
2389
16
                if (index < 0) {
2390
0
                    return ERROR;
2391
0
                }
2392
16
                INSTR_SET_OP0(inst, NOP);
2393
16
                INSTR_SET_OP1(&bb->b_instr[i + 1], LOAD_CONST, index);
2394
16
                break;
2395
16
            }
2396
36.0k
        }
2397
36.0k
        if (inst->i_opcode == LOAD_CONST) {
2398
20.8k
            PyObject *constant = get_const_value(inst->i_opcode, inst->i_oparg, consts);
2399
20.8k
            if (constant == NULL) {
2400
0
                return ERROR;
2401
0
            }
2402
20.8k
            int res = maybe_instr_make_load_common_const(inst, constant);
2403
20.8k
            Py_DECREF(constant);
2404
20.8k
            if (res < 0) {
2405
0
                return ERROR;
2406
0
            }
2407
20.8k
        }
2408
36.0k
    }
2409
16.3k
    return SUCCESS;
2410
16.3k
}
2411
2412
static int
2413
optimize_load_const(PyObject *const_cache, cfg_builder *g, PyObject *consts,
2414
4.26k
                    _Py_hashtable_t *consts_index) {
2415
20.6k
    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
2416
16.3k
        RETURN_IF_ERROR(basicblock_optimize_load_const(const_cache, b, consts, consts_index));
2417
16.3k
    }
2418
4.26k
    return SUCCESS;
2419
4.26k
}
2420
2421
static int
2422
optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts,
2423
                     _Py_hashtable_t *consts_index)
2424
16.3k
{
2425
16.3k
    assert(PyDict_CheckExact(const_cache));
2426
16.3k
    assert(PyList_CheckExact(consts));
2427
16.3k
    cfg_instr nop;
2428
16.3k
    INSTR_SET_OP0(&nop, NOP);
2429
178k
    for (int i = 0; i < bb->b_iused; i++) {
2430
162k
        cfg_instr *inst = &bb->b_instr[i];
2431
162k
        cfg_instr *target;
2432
162k
        int opcode = inst->i_opcode;
2433
162k
        int oparg = inst->i_oparg;
2434
162k
        if (HAS_TARGET(opcode)) {
2435
6.09k
            assert(inst->i_target->b_iused > 0);
2436
6.09k
            target = &inst->i_target->b_instr[0];
2437
6.09k
            assert(!IS_ASSEMBLER_OPCODE(target->i_opcode));
2438
6.09k
        }
2439
156k
        else {
2440
156k
            target = &nop;
2441
156k
        }
2442
162k
        int nextop = i+1 < bb->b_iused ? bb->b_instr[i+1].i_opcode : 0;
2443
162k
        assert(!IS_ASSEMBLER_OPCODE(opcode));
2444
162k
        switch (opcode) {
2445
            /* Try to fold tuples of constants.
2446
               Skip over BUILD_TUPLE(1) UNPACK_SEQUENCE(1).
2447
               Replace BUILD_TUPLE(2) UNPACK_SEQUENCE(2) with SWAP(2).
2448
               Replace BUILD_TUPLE(3) UNPACK_SEQUENCE(3) with SWAP(3). */
2449
2.07k
            case BUILD_TUPLE:
2450
2.07k
                if (nextop == UNPACK_SEQUENCE && oparg == bb->b_instr[i+1].i_oparg) {
2451
54
                    switch(oparg) {
2452
0
                        case 1:
2453
0
                            INSTR_SET_OP0(inst, NOP);
2454
0
                            INSTR_SET_OP0(&bb->b_instr[i + 1], NOP);
2455
0
                            continue;
2456
44
                        case 2:
2457
53
                        case 3:
2458
53
                            INSTR_SET_OP0(inst, NOP);
2459
53
                            bb->b_instr[i+1].i_opcode = SWAP;
2460
53
                            continue;
2461
54
                    }
2462
54
                }
2463
2.02k
                RETURN_IF_ERROR(fold_tuple_of_constants(bb, i, consts, const_cache, consts_index));
2464
2.02k
                break;
2465
260
            case BUILD_LIST:
2466
411
            case BUILD_SET:
2467
411
                RETURN_IF_ERROR(optimize_lists_and_sets(bb, i, nextop, consts, const_cache, consts_index));
2468
411
                break;
2469
128
            case POP_JUMP_IF_NOT_NONE:
2470
291
            case POP_JUMP_IF_NONE:
2471
291
                switch (target->i_opcode) {
2472
7
                    case JUMP:
2473
7
                        i -= jump_thread(bb, inst, target, inst->i_opcode);
2474
291
                }
2475
291
                break;
2476
2.23k
            case POP_JUMP_IF_FALSE:
2477
2.23k
                switch (target->i_opcode) {
2478
121
                    case JUMP:
2479
121
                        i -= jump_thread(bb, inst, target, POP_JUMP_IF_FALSE);
2480
2.23k
                }
2481
2.23k
                break;
2482
2.23k
            case POP_JUMP_IF_TRUE:
2483
573
                switch (target->i_opcode) {
2484
16
                    case JUMP:
2485
16
                        i -= jump_thread(bb, inst, target, POP_JUMP_IF_TRUE);
2486
573
                }
2487
573
                break;
2488
573
            case JUMP_IF_FALSE:
2489
504
                switch (target->i_opcode) {
2490
0
                    case JUMP:
2491
0
                    case JUMP_IF_FALSE:
2492
0
                        i -= jump_thread(bb, inst, target, JUMP_IF_FALSE);
2493
0
                        continue;
2494
2
                    case JUMP_IF_TRUE:
2495
                        // No need to check for loops here, a block's b_next
2496
                        // cannot point to itself.
2497
2
                        assert(inst->i_target != inst->i_target->b_next);
2498
2
                        inst->i_target = inst->i_target->b_next;
2499
2
                        i--;
2500
2
                        continue;
2501
504
                }
2502
502
                break;
2503
502
            case JUMP_IF_TRUE:
2504
57
                switch (target->i_opcode) {
2505
0
                    case JUMP:
2506
0
                    case JUMP_IF_TRUE:
2507
0
                        i -= jump_thread(bb, inst, target, JUMP_IF_TRUE);
2508
0
                        continue;
2509
0
                    case JUMP_IF_FALSE:
2510
                        // No need to check for loops here, a block's b_next
2511
                        // cannot point to itself.
2512
0
                        assert(inst->i_target != inst->i_target->b_next);
2513
0
                        inst->i_target = inst->i_target->b_next;
2514
0
                        i--;
2515
0
                        continue;
2516
57
                }
2517
57
                break;
2518
657
            case JUMP:
2519
1.24k
            case JUMP_NO_INTERRUPT:
2520
1.24k
                switch (target->i_opcode) {
2521
0
                    case JUMP:
2522
0
                        i -= jump_thread(bb, inst, target, JUMP);
2523
0
                        continue;
2524
0
                    case JUMP_NO_INTERRUPT:
2525
0
                        i -= jump_thread(bb, inst, target, opcode);
2526
0
                        continue;
2527
1.24k
                }
2528
1.24k
                break;
2529
1.24k
            case FOR_ITER:
2530
355
                if (target->i_opcode == JUMP) {
2531
                    /* This will not work now because the jump (at target) could
2532
                     * be forward or backward and FOR_ITER only jumps forward. We
2533
                     * can re-enable this if ever we implement a backward version
2534
                     * of FOR_ITER.
2535
                     */
2536
                    /*
2537
                    i -= jump_thread(bb, inst, target, FOR_ITER);
2538
                    */
2539
0
                }
2540
355
                break;
2541
3.56k
            case STORE_FAST:
2542
3.56k
                if (opcode == nextop &&
2543
332
                    oparg == bb->b_instr[i+1].i_oparg &&
2544
14
                    bb->b_instr[i].i_loc.lineno == bb->b_instr[i+1].i_loc.lineno) {
2545
14
                    bb->b_instr[i].i_opcode = POP_TOP;
2546
14
                    bb->b_instr[i].i_oparg = 0;
2547
14
                }
2548
3.56k
                break;
2549
579
            case SWAP:
2550
579
                if (oparg == 1) {
2551
0
                    INSTR_SET_OP0(inst, NOP);
2552
0
                }
2553
579
                break;
2554
5.84k
            case LOAD_GLOBAL:
2555
5.84k
                if (nextop == PUSH_NULL && (oparg & 1) == 0) {
2556
2.38k
                    INSTR_SET_OP1(inst, LOAD_GLOBAL, oparg | 1);
2557
2.38k
                    INSTR_SET_OP0(&bb->b_instr[i + 1], NOP);
2558
2.38k
                }
2559
5.84k
                break;
2560
1.82k
            case COMPARE_OP:
2561
1.82k
                if (nextop == TO_BOOL) {
2562
587
                    INSTR_SET_OP0(inst, NOP);
2563
587
                    INSTR_SET_OP1(&bb->b_instr[i + 1], COMPARE_OP, oparg | 16);
2564
587
                    continue;
2565
587
                }
2566
1.23k
                break;
2567
1.23k
            case CONTAINS_OP:
2568
1.43k
            case IS_OP:
2569
1.43k
                if (nextop == TO_BOOL) {
2570
699
                    INSTR_SET_OP0(inst, NOP);
2571
699
                    INSTR_SET_OP1(&bb->b_instr[i + 1], opcode, oparg);
2572
699
                    continue;
2573
699
                }
2574
736
                if (nextop == UNARY_NOT) {
2575
0
                    INSTR_SET_OP0(inst, NOP);
2576
0
                    int inverted = oparg ^ 1;
2577
0
                    assert(inverted == 0 || inverted == 1);
2578
0
                    INSTR_SET_OP1(&bb->b_instr[i + 1], opcode, inverted);
2579
0
                    continue;
2580
0
                }
2581
736
                break;
2582
1.16k
            case TO_BOOL:
2583
1.16k
                if (nextop == TO_BOOL) {
2584
0
                    INSTR_SET_OP0(inst, NOP);
2585
0
                    continue;
2586
0
                }
2587
1.16k
                break;
2588
1.16k
            case UNARY_NOT:
2589
7
                if (nextop == TO_BOOL) {
2590
0
                    INSTR_SET_OP0(inst, NOP);
2591
0
                    INSTR_SET_OP0(&bb->b_instr[i + 1], UNARY_NOT);
2592
0
                    continue;
2593
0
                }
2594
7
                if (nextop == UNARY_NOT) {
2595
0
                    INSTR_SET_OP0(inst, NOP);
2596
0
                    INSTR_SET_OP0(&bb->b_instr[i + 1], NOP);
2597
0
                    continue;
2598
0
                }
2599
7
                _Py_FALLTHROUGH;
2600
7
            case UNARY_INVERT:
2601
1.73k
            case UNARY_NEGATIVE:
2602
1.73k
                RETURN_IF_ERROR(fold_const_unaryop(bb, i, consts, const_cache, consts_index));
2603
1.73k
                break;
2604
145
            case CALL_INTRINSIC_1:
2605
145
                if (oparg == INTRINSIC_LIST_TO_TUPLE) {
2606
43
                    RETURN_IF_ERROR(fold_constant_seq_into_load_const(bb, i, consts, const_cache, consts_index));
2607
43
                    if (inst->i_opcode == CALL_INTRINSIC_1 && nextop == GET_ITER) {
2608
0
                        INSTR_SET_OP0(inst, NOP);
2609
0
                    }
2610
43
                }
2611
102
                else if (oparg == INTRINSIC_UNARY_POSITIVE) {
2612
0
                    RETURN_IF_ERROR(fold_const_unaryop(bb, i, consts, const_cache, consts_index));
2613
0
                }
2614
145
                break;
2615
2.14k
            case LIST_APPEND:
2616
2.20k
            case SET_ADD:
2617
2.20k
                if (oparg == 1 && (nextop == GET_ITER || nextop == CONTAINS_OP)) {
2618
2
                    RETURN_IF_ERROR(fold_constant_seq_into_load_const(
2619
2
                        bb, i, consts, const_cache, consts_index));
2620
2
                }
2621
2.20k
                break;
2622
2.20k
            case BINARY_OP:
2623
1.37k
                RETURN_IF_ERROR(fold_const_binop(bb, i, consts, const_cache, consts_index));
2624
1.37k
                break;
2625
162k
        }
2626
162k
    }
2627
2628
178k
    for (int i = 0; i < bb->b_iused; i++) {
2629
162k
        cfg_instr *inst = &bb->b_instr[i];
2630
162k
        if (inst->i_opcode == SWAP) {
2631
484
            if (swaptimize(bb, &i) < 0) {
2632
0
                goto error;
2633
0
            }
2634
484
            apply_static_swaps(bb, i);
2635
484
        }
2636
162k
    }
2637
16.3k
    return SUCCESS;
2638
0
error:
2639
0
    return ERROR;
2640
16.3k
}
2641
2642
static int resolve_line_numbers(cfg_builder *g, int firstlineno);
2643
2644
static int
2645
remove_redundant_nops_and_jumps(cfg_builder *g)
2646
8.84k
{
2647
8.84k
    int removed_nops, removed_jumps;
2648
9.36k
    do {
2649
        /* Convergence is guaranteed because the number of
2650
         * redundant jumps and nops only decreases.
2651
         */
2652
9.36k
        removed_nops = remove_redundant_nops(g);
2653
9.36k
        RETURN_IF_ERROR(removed_nops);
2654
9.36k
        removed_jumps = remove_redundant_jumps(g);
2655
9.36k
        RETURN_IF_ERROR(removed_jumps);
2656
9.36k
    } while(removed_nops + removed_jumps > 0);
2657
8.84k
    return SUCCESS;
2658
8.84k
}
2659
2660
/* Perform optimizations on a control flow graph.
2661
   The consts object should still be in list form to allow new constants
2662
   to be appended.
2663
2664
   Code trasnformations that reduce code size initially fill the gaps with
2665
   NOPs.  Later those NOPs are removed.
2666
*/
2667
static int
2668
optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache,
2669
             _Py_hashtable_t *consts_index, int firstlineno)
2670
4.26k
{
2671
4.26k
    assert(PyDict_CheckExact(const_cache));
2672
4.26k
    RETURN_IF_ERROR(check_cfg(g));
2673
4.26k
    RETURN_IF_ERROR(inline_small_or_no_lineno_blocks(g->g_entryblock));
2674
4.26k
    RETURN_IF_ERROR(remove_unreachable(g->g_entryblock));
2675
4.26k
    RETURN_IF_ERROR(resolve_line_numbers(g, firstlineno));
2676
4.26k
    RETURN_IF_ERROR(optimize_load_const(const_cache, g, consts, consts_index));
2677
20.6k
    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
2678
16.3k
        RETURN_IF_ERROR(optimize_basic_block(const_cache, b, consts, consts_index));
2679
16.3k
    }
2680
4.26k
    RETURN_IF_ERROR(remove_redundant_nops_and_pairs(g->g_entryblock));
2681
4.26k
    RETURN_IF_ERROR(remove_unreachable(g->g_entryblock));
2682
4.26k
    RETURN_IF_ERROR(remove_redundant_nops_and_jumps(g));
2683
4.26k
    assert(no_redundant_jumps(g));
2684
4.26k
    return SUCCESS;
2685
4.26k
}
2686
2687
static void
2688
make_super_instruction(cfg_instr *inst1, cfg_instr *inst2, int super_op)
2689
4.60k
{
2690
4.60k
    int32_t line1 = inst1->i_loc.lineno;
2691
4.60k
    int32_t line2 = inst2->i_loc.lineno;
2692
    /* Skip if instructions are on different lines */
2693
4.60k
    if (line1 >= 0 && line2 >= 0 && line1 != line2) {
2694
1.43k
        return;
2695
1.43k
    }
2696
3.17k
    if (inst1->i_oparg >= 16 || inst2->i_oparg >= 16) {
2697
169
        return;
2698
169
    }
2699
3.00k
    INSTR_SET_OP1(inst1, super_op, (inst1->i_oparg << 4) | inst2->i_oparg);
2700
3.00k
    INSTR_SET_OP0(inst2, NOP);
2701
3.00k
}
2702
2703
static int
2704
insert_superinstructions(cfg_builder *g)
2705
4.26k
{
2706
20.6k
    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
2707
2708
167k
        for (int i = 0; i < b->b_iused; i++) {
2709
151k
            cfg_instr *inst = &b->b_instr[i];
2710
151k
            int nextop = i+1 < b->b_iused ? b->b_instr[i+1].i_opcode : 0;
2711
151k
            switch(inst->i_opcode) {
2712
16.2k
                case LOAD_FAST:
2713
16.2k
                    if (nextop == LOAD_FAST) {
2714
2.94k
                        make_super_instruction(inst, &b->b_instr[i + 1], LOAD_FAST_LOAD_FAST);
2715
2.94k
                    }
2716
16.2k
                    break;
2717
3.34k
                case STORE_FAST:
2718
3.34k
                    switch (nextop) {
2719
1.40k
                        case LOAD_FAST:
2720
1.40k
                            make_super_instruction(inst, &b->b_instr[i + 1], STORE_FAST_LOAD_FAST);
2721
1.40k
                            break;
2722
256
                        case STORE_FAST:
2723
256
                            make_super_instruction(inst, &b->b_instr[i + 1], STORE_FAST_STORE_FAST);
2724
256
                            break;
2725
3.34k
                    }
2726
3.34k
                    break;
2727
151k
            }
2728
151k
        }
2729
16.3k
    }
2730
4.26k
    int res = remove_redundant_nops(g);
2731
4.26k
    assert(no_redundant_nops(g));
2732
4.26k
    return res;
2733
4.26k
}
2734
2735
#define NOT_LOCAL -1
2736
3.45k
#define DUMMY_INSTR -1
2737
2738
typedef struct {
2739
    // Index of instruction that produced the reference or DUMMY_INSTR.
2740
    int instr;
2741
2742
    // The local to which the reference refers or NOT_LOCAL.
2743
    int local;
2744
} ref;
2745
2746
typedef struct {
2747
    ref *refs;
2748
    Py_ssize_t size;
2749
    Py_ssize_t capacity;
2750
} ref_stack;
2751
2752
static int
2753
ref_stack_push(ref_stack *stack, ref r)
2754
122k
{
2755
122k
    if (stack->size == stack->capacity) {
2756
4.26k
        Py_ssize_t new_cap = Py_MAX(32, stack->capacity * 2);
2757
4.26k
        ref *refs = PyMem_Realloc(stack->refs, sizeof(*stack->refs) * new_cap);
2758
4.26k
        if (refs == NULL) {
2759
0
            PyErr_NoMemory();
2760
0
            return -1;
2761
0
        }
2762
4.26k
        stack->refs = refs;
2763
4.26k
        stack->capacity = new_cap;
2764
4.26k
    }
2765
122k
    stack->refs[stack->size] = r;
2766
122k
    stack->size++;
2767
122k
    return 0;
2768
122k
}
2769
2770
static ref
2771
ref_stack_pop(ref_stack *stack)
2772
109k
{
2773
109k
    assert(stack->size > 0);
2774
109k
    stack->size--;
2775
109k
    ref r = stack->refs[stack->size];
2776
109k
    return r;
2777
109k
}
2778
2779
static void
2780
ref_stack_swap_top(ref_stack *stack, Py_ssize_t off)
2781
369
{
2782
369
    Py_ssize_t idx = stack->size - off;
2783
369
    assert(idx >= 0 && idx < stack->size);
2784
369
    ref tmp = stack->refs[idx];
2785
369
    stack->refs[idx] = stack->refs[stack->size - 1];
2786
369
    stack->refs[stack->size - 1] = tmp;
2787
369
}
2788
2789
static ref
2790
ref_stack_at(ref_stack *stack, Py_ssize_t idx)
2791
16.1k
{
2792
16.1k
    assert(idx >= 0 && idx < stack->size);
2793
16.1k
    return stack->refs[idx];
2794
16.1k
}
2795
2796
static void
2797
ref_stack_clear(ref_stack *stack)
2798
11.7k
{
2799
11.7k
    stack->size = 0;
2800
11.7k
}
2801
2802
static void
2803
ref_stack_fini(ref_stack *stack)
2804
4.26k
{
2805
4.26k
    if (stack->refs != NULL) {
2806
4.26k
        PyMem_Free(stack->refs);
2807
4.26k
    }
2808
4.26k
    stack->refs = NULL;
2809
4.26k
    stack->capacity = 0;
2810
4.26k
    stack->size = 0;
2811
4.26k
}
2812
2813
typedef enum {
2814
    // The loaded reference is still on the stack when the local is killed
2815
    SUPPORT_KILLED  = 1,
2816
    // The loaded reference is stored into a local
2817
    STORED_AS_LOCAL = 2,
2818
    // The loaded reference is still on the stack at the end of the basic block
2819
    REF_UNCONSUMED  = 4,
2820
} LoadFastInstrFlag;
2821
2822
static void
2823
kill_local(uint8_t *instr_flags, ref_stack *refs, int local)
2824
3.51k
{
2825
6.29k
    for (Py_ssize_t i = 0; i < refs->size; i++) {
2826
2.78k
        ref r = ref_stack_at(refs, i);
2827
2.78k
        if (r.local == local) {
2828
4
            assert(r.instr >= 0);
2829
4
            instr_flags[r.instr] |= SUPPORT_KILLED;
2830
4
        }
2831
2.78k
    }
2832
3.51k
}
2833
2834
static void
2835
store_local(uint8_t *instr_flags, ref_stack *refs, int local, ref r)
2836
3.45k
{
2837
3.45k
    kill_local(instr_flags, refs, local);
2838
3.45k
    if (r.instr != DUMMY_INSTR) {
2839
3.05k
        instr_flags[r.instr] |= STORED_AS_LOCAL;
2840
3.05k
    }
2841
3.45k
}
2842
2843
static void
2844
load_fast_push_block(basicblock ***sp, basicblock *target,
2845
                     Py_ssize_t start_depth)
2846
9.81k
{
2847
9.81k
    assert(target->b_startdepth >= 0 && target->b_startdepth == start_depth);
2848
9.81k
    if (!target->b_visited) {
2849
7.50k
        target->b_visited = 1;
2850
7.50k
        *(*sp)++ = target;
2851
7.50k
    }
2852
9.81k
}
2853
2854
/*
2855
 * Strength reduce LOAD_FAST{_LOAD_FAST} instructions into faster variants that
2856
 * load borrowed references onto the operand stack.
2857
 *
2858
 * This is only safe when we can prove that the reference in the frame outlives
2859
 * the borrowed reference produced by the instruction. We make this tractable
2860
 * by enforcing the following lifetimes:
2861
 *
2862
 * 1. Borrowed references loaded onto the operand stack live until the end of
2863
 *    the instruction that consumes them from the stack. Any borrowed
2864
 *    references that would escape into the heap (e.g. into frame objects or
2865
 *    generators) are converted into new, strong references.
2866
 *
2867
 * 2. Locals live until they are either killed by an instruction
2868
 *    (e.g. STORE_FAST) or the frame is unwound. Any local that is overwritten
2869
 *    via `f_locals` is added to a tuple owned by the frame object.
2870
 *
2871
 * To simplify the problem of detecting which supporting references in the
2872
 * frame are killed by instructions that overwrite locals, we only allow
2873
 * borrowed references to be stored as a local in the frame if they were passed
2874
 * as an argument. {RETURN,YIELD}_VALUE convert borrowed references into new,
2875
 * strong references.
2876
 *
2877
 * Using the above, we can optimize any LOAD_FAST{_LOAD_FAST} instructions
2878
 * that meet the following criteria:
2879
 *
2880
 * 1. The produced reference must be consumed from the stack before the
2881
 *    supporting reference in the frame is killed.
2882
 *
2883
 * 2. The produced reference cannot be stored as a local.
2884
 *
2885
 * We use abstract interpretation to identify instructions that meet these
2886
 * criteria. For each basic block, we simulate the effect the bytecode has on a
2887
 * stack of abstract references and note any instructions that violate the
2888
 * criteria above. Once we've processed all the instructions in a block, any
2889
 * non-violating LOAD_FAST{_LOAD_FAST} can be optimized.
2890
 */
2891
static int
2892
optimize_load_fast(cfg_builder *g)
2893
4.26k
{
2894
4.26k
    int status;
2895
4.26k
    ref_stack refs = {0};
2896
4.26k
    int max_instrs = 0;
2897
4.26k
    basicblock *entryblock = g->g_entryblock;
2898
20.7k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
2899
16.5k
        max_instrs = Py_MAX(max_instrs, b->b_iused);
2900
16.5k
    }
2901
4.26k
    size_t instr_flags_size = max_instrs * sizeof(uint8_t);
2902
4.26k
    uint8_t *instr_flags = PyMem_Malloc(instr_flags_size);
2903
4.26k
    if (instr_flags == NULL) {
2904
0
        PyErr_NoMemory();
2905
0
        return ERROR;
2906
0
    }
2907
4.26k
    basicblock **blocks = make_cfg_traversal_stack(entryblock);
2908
4.26k
    if (blocks == NULL) {
2909
0
        status = ERROR;
2910
0
        goto done;
2911
0
    }
2912
4.26k
    basicblock **sp = blocks;
2913
4.26k
    *sp = entryblock;
2914
4.26k
    sp++;
2915
4.26k
    entryblock->b_startdepth = 0;
2916
4.26k
    entryblock->b_visited = 1;
2917
2918
4.26k
    #define PUSH_REF(instr, local)                \
2919
122k
        do {                                      \
2920
122k
            if (ref_stack_push(&refs, (ref){(instr), (local)}) < 0) { \
2921
0
                status = ERROR;                   \
2922
0
                goto done;                        \
2923
0
            }                                     \
2924
122k
        } while(0)
2925
2926
16.0k
    while (sp != blocks) {
2927
11.7k
        basicblock *block = *--sp;
2928
11.7k
        assert(block->b_startdepth > -1);
2929
2930
        // Reset per-block state.
2931
11.7k
        memset(instr_flags, 0, block->b_iused * sizeof(*instr_flags));
2932
2933
        // Reset the stack of refs. We don't track references on the stack
2934
        // across basic blocks, but the bytecode will expect their
2935
        // presence. Add dummy references as necessary.
2936
11.7k
        ref_stack_clear(&refs);
2937
19.5k
        for (int i = 0; i < block->b_startdepth; i++) {
2938
7.77k
            PUSH_REF(DUMMY_INSTR, NOT_LOCAL);
2939
7.77k
        }
2940
2941
159k
        for (int i = 0; i < block->b_iused; i++) {
2942
147k
            cfg_instr *instr = &block->b_instr[i];
2943
147k
            int opcode = instr->i_opcode;
2944
147k
            int oparg = instr->i_oparg;
2945
147k
            assert(opcode != EXTENDED_ARG);
2946
147k
            switch (opcode) {
2947
                // Opcodes that load and store locals
2948
0
                case DELETE_FAST: {
2949
0
                    kill_local(instr_flags, &refs, oparg);
2950
0
                    break;
2951
0
                }
2952
2953
14.3k
                case LOAD_FAST: {
2954
14.3k
                    PUSH_REF(i, oparg);
2955
14.3k
                    break;
2956
14.3k
                }
2957
2958
14.3k
                case LOAD_FAST_AND_CLEAR: {
2959
62
                    kill_local(instr_flags, &refs, oparg);
2960
62
                    PUSH_REF(i, oparg);
2961
62
                    break;
2962
62
                }
2963
2964
2.70k
                case LOAD_FAST_LOAD_FAST: {
2965
2.70k
                    PUSH_REF(i, oparg >> 4);
2966
2.70k
                    PUSH_REF(i, oparg & 15);
2967
2.70k
                    break;
2968
2.70k
                }
2969
2970
3.00k
                case STORE_FAST: {
2971
3.00k
                    ref r = ref_stack_pop(&refs);
2972
3.00k
                    store_local(instr_flags, &refs, oparg, r);
2973
3.00k
                    break;
2974
2.70k
                }
2975
2976
39
                case STORE_FAST_LOAD_FAST: {
2977
                    // STORE_FAST
2978
39
                    ref r = ref_stack_pop(&refs);
2979
39
                    store_local(instr_flags, &refs, oparg >> 4, r);
2980
                    // LOAD_FAST
2981
39
                    PUSH_REF(i, oparg & 15);
2982
39
                    break;
2983
39
                }
2984
2985
203
                case STORE_FAST_STORE_FAST: {
2986
                    // STORE_FAST
2987
203
                    ref r = ref_stack_pop(&refs);
2988
203
                    store_local(instr_flags, &refs, oparg >> 4, r);
2989
                    // STORE_FAST
2990
203
                    r = ref_stack_pop(&refs);
2991
203
                    store_local(instr_flags, &refs, oparg & 15, r);
2992
203
                    break;
2993
39
                }
2994
2995
                // Opcodes that shuffle values on the stack
2996
934
                case COPY: {
2997
934
                    assert(oparg > 0);
2998
934
                    Py_ssize_t idx = refs.size - oparg;
2999
934
                    ref r = ref_stack_at(&refs, idx);
3000
934
                    PUSH_REF(r.instr, r.local);
3001
934
                    break;
3002
934
                }
3003
3004
934
                case SWAP: {
3005
369
                    assert(oparg >= 2);
3006
369
                    ref_stack_swap_top(&refs, oparg);
3007
369
                    break;
3008
934
                }
3009
3010
                // We treat opcodes that do not consume all of their inputs on
3011
                // a case by case basis, as we have no generic way of knowing
3012
                // how many inputs should be left on the stack.
3013
3014
                // Opcodes that consume no inputs
3015
1.21k
                case FORMAT_SIMPLE:
3016
1.21k
                case GET_ANEXT:
3017
1.56k
                case GET_ITER:
3018
1.56k
                case GET_LEN:
3019
2.30k
                case IMPORT_FROM:
3020
2.30k
                case MATCH_KEYS:
3021
2.30k
                case MATCH_MAPPING:
3022
2.30k
                case MATCH_SEQUENCE:
3023
2.30k
                case WITH_EXCEPT_START: {
3024
2.30k
                    int num_popped = _PyOpcode_num_popped(opcode, oparg);
3025
2.30k
                    int num_pushed = _PyOpcode_num_pushed(opcode, oparg);
3026
2.30k
                    int net_pushed = num_pushed - num_popped;
3027
2.30k
                    assert(net_pushed >= 0);
3028
3.39k
                    for (int j = 0; j < net_pushed; j++) {
3029
1.09k
                        PUSH_REF(i, NOT_LOCAL);
3030
1.09k
                    }
3031
2.30k
                    break;
3032
2.30k
                }
3033
3034
                // Opcodes that consume some inputs and push no new values
3035
2.30k
                case DICT_MERGE:
3036
451
                case DICT_UPDATE:
3037
2.59k
                case LIST_APPEND:
3038
2.64k
                case LIST_EXTEND:
3039
9.04k
                case MAP_ADD:
3040
9.04k
                case RERAISE:
3041
9.04k
                case SET_ADD:
3042
9.06k
                case SET_UPDATE: {
3043
9.06k
                    int num_popped = _PyOpcode_num_popped(opcode, oparg);
3044
9.06k
                    int num_pushed = _PyOpcode_num_pushed(opcode, oparg);
3045
9.06k
                    int net_popped = num_popped - num_pushed;
3046
9.06k
                    assert(net_popped > 0);
3047
24.5k
                    for (int i = 0; i < net_popped; i++) {
3048
15.4k
                        ref_stack_pop(&refs);
3049
15.4k
                    }
3050
9.06k
                    break;
3051
9.04k
                }
3052
3053
21
                case END_SEND: {
3054
21
                    assert(_PyOpcode_num_popped(opcode, oparg) == 3);
3055
21
                    assert(_PyOpcode_num_pushed(opcode, oparg) == 1);
3056
21
                    ref tos = ref_stack_pop(&refs);
3057
21
                    ref_stack_pop(&refs);
3058
21
                    ref_stack_pop(&refs);
3059
21
                    PUSH_REF(tos.instr, tos.local);
3060
21
                    break;
3061
21
                }
3062
3063
1.36k
                case SET_FUNCTION_ATTRIBUTE: {
3064
1.36k
                    assert(_PyOpcode_num_popped(opcode, oparg) == 2);
3065
1.36k
                    assert(_PyOpcode_num_pushed(opcode, oparg) == 1);
3066
1.36k
                    ref tos = ref_stack_pop(&refs);
3067
1.36k
                    ref_stack_pop(&refs);
3068
1.36k
                    PUSH_REF(tos.instr, tos.local);
3069
1.36k
                    break;
3070
1.36k
                }
3071
3072
                // Opcodes that consume some inputs and push new values
3073
1.36k
                case CHECK_EXC_MATCH: {
3074
0
                    ref_stack_pop(&refs);
3075
0
                    PUSH_REF(i, NOT_LOCAL);
3076
0
                    break;
3077
0
                }
3078
3079
349
                case FOR_ITER: {
3080
349
                    load_fast_push_block(&sp, instr->i_target, refs.size + 1);
3081
349
                    PUSH_REF(i, NOT_LOCAL);
3082
349
                    break;
3083
349
                }
3084
3085
10.0k
                case LOAD_ATTR:
3086
10.1k
                case LOAD_SUPER_ATTR: {
3087
10.1k
                    ref self = ref_stack_pop(&refs);
3088
10.1k
                    if (opcode == LOAD_SUPER_ATTR) {
3089
135
                        ref_stack_pop(&refs);
3090
135
                        ref_stack_pop(&refs);
3091
135
                    }
3092
10.1k
                    PUSH_REF(i, NOT_LOCAL);
3093
10.1k
                    if (oparg & 1) {
3094
                        // A method call; conservatively assume that self is pushed
3095
                        // back onto the stack
3096
2.84k
                        PUSH_REF(self.instr, self.local);
3097
2.84k
                    }
3098
10.1k
                    break;
3099
10.1k
                }
3100
3101
10.1k
                case LOAD_SPECIAL:
3102
178
                case PUSH_EXC_INFO: {
3103
178
                    ref tos = ref_stack_pop(&refs);
3104
178
                    PUSH_REF(i, NOT_LOCAL);
3105
178
                    PUSH_REF(tos.instr, tos.local);
3106
178
                    break;
3107
178
                }
3108
3109
178
                case SEND: {
3110
21
                    load_fast_push_block(&sp, instr->i_target, refs.size);
3111
21
                    ref_stack_pop(&refs);
3112
21
                    PUSH_REF(i, NOT_LOCAL);
3113
21
                    break;
3114
21
                }
3115
3116
                // Opcodes that consume all of their inputs
3117
102k
                default: {
3118
102k
                    int num_popped = _PyOpcode_num_popped(opcode, oparg);
3119
102k
                    int num_pushed = _PyOpcode_num_pushed(opcode, oparg);
3120
102k
                    if (HAS_TARGET(instr->i_opcode)) {
3121
4.14k
                        load_fast_push_block(&sp, instr->i_target, refs.size - num_popped + num_pushed);
3122
4.14k
                    }
3123
102k
                    if (!IS_BLOCK_PUSH_OPCODE(instr->i_opcode)) {
3124
                        // Block push opcodes only affect the stack when jumping
3125
                        // to the target.
3126
179k
                        for (int j = 0; j < num_popped; j++) {
3127
77.3k
                            ref_stack_pop(&refs);
3128
77.3k
                        }
3129
179k
                        for (int j = 0; j < num_pushed; j++) {
3130
77.4k
                            PUSH_REF(i, NOT_LOCAL);
3131
77.4k
                        }
3132
102k
                    }
3133
102k
                    break;
3134
102k
                }
3135
147k
            }
3136
147k
        }
3137
3138
        // Push fallthrough block
3139
11.7k
        if (BB_HAS_FALLTHROUGH(block)) {
3140
5.29k
            assert(block->b_next != NULL);
3141
5.29k
            load_fast_push_block(&sp, block->b_next, refs.size);
3142
5.29k
        }
3143
3144
        // Mark instructions that produce values that are on the stack at the
3145
        // end of the basic block
3146
24.2k
        for (Py_ssize_t i = 0; i < refs.size; i++) {
3147
12.4k
            ref r = ref_stack_at(&refs, i);
3148
12.4k
            if (r.instr != -1) {
3149
7.50k
                instr_flags[r.instr] |= REF_UNCONSUMED;
3150
7.50k
            }
3151
12.4k
        }
3152
3153
        // Optimize instructions
3154
159k
        for (int i = 0; i < block->b_iused; i++) {
3155
147k
            if (!instr_flags[i]) {
3156
137k
                cfg_instr *instr = &block->b_instr[i];
3157
137k
                switch (instr->i_opcode) {
3158
13.9k
                    case LOAD_FAST:
3159
13.9k
                        instr->i_opcode = LOAD_FAST_BORROW;
3160
13.9k
                        break;
3161
2.69k
                    case LOAD_FAST_LOAD_FAST:
3162
2.69k
                        instr->i_opcode = LOAD_FAST_BORROW_LOAD_FAST_BORROW;
3163
2.69k
                        break;
3164
120k
                    default:
3165
120k
                        break;
3166
137k
                }
3167
137k
            }
3168
147k
        }
3169
11.7k
    }
3170
3171
4.26k
    #undef PUSH_REF
3172
3173
4.26k
    status = SUCCESS;
3174
3175
4.26k
done:
3176
4.26k
    ref_stack_fini(&refs);
3177
4.26k
    PyMem_Free(instr_flags);
3178
4.26k
    PyMem_Free(blocks);
3179
4.26k
    return status;
3180
4.26k
}
3181
3182
// helper functions for add_checks_for_loads_of_unknown_variables
3183
static inline void
3184
maybe_push(basicblock *b, uint64_t unsafe_mask, basicblock ***sp)
3185
43.5k
{
3186
    // Push b if the unsafe mask is giving us any new information.
3187
    // To avoid overflowing the stack, only allow each block once.
3188
    // Use b->b_visited=1 to mean that b is currently on the stack.
3189
43.5k
    uint64_t both = b->b_unsafe_locals_mask | unsafe_mask;
3190
43.5k
    if (b->b_unsafe_locals_mask != both) {
3191
5.92k
        b->b_unsafe_locals_mask = both;
3192
        // More work left to do.
3193
5.92k
        if (!b->b_visited) {
3194
            // not on the stack, so push it.
3195
5.87k
            *(*sp)++ = b;
3196
5.87k
            b->b_visited = 1;
3197
5.87k
        }
3198
5.92k
    }
3199
43.5k
}
3200
3201
static void
3202
scan_block_for_locals(basicblock *b, basicblock ***sp)
3203
19.7k
{
3204
    // bit i is set if local i is potentially uninitialized
3205
19.7k
    uint64_t unsafe_mask = b->b_unsafe_locals_mask;
3206
157k
    for (int i = 0; i < b->b_iused; i++) {
3207
137k
        cfg_instr *instr = &b->b_instr[i];
3208
137k
        assert(instr->i_opcode != EXTENDED_ARG);
3209
137k
        if (instr->i_except != NULL) {
3210
23.8k
            maybe_push(instr->i_except, unsafe_mask, sp);
3211
23.8k
        }
3212
137k
        if (instr->i_oparg >= 64) {
3213
6.69k
            continue;
3214
6.69k
        }
3215
137k
        assert(instr->i_oparg >= 0);
3216
131k
        uint64_t bit = (uint64_t)1 << instr->i_oparg;
3217
131k
        switch (instr->i_opcode) {
3218
116
            case DELETE_FAST:
3219
240
            case LOAD_FAST_AND_CLEAR:
3220
488
            case STORE_FAST_MAYBE_NULL:
3221
488
                unsafe_mask |= bit;
3222
488
                break;
3223
6.89k
            case STORE_FAST:
3224
6.89k
                unsafe_mask &= ~bit;
3225
6.89k
                break;
3226
30
            case LOAD_FAST_CHECK:
3227
                // If this doesn't raise, then the local is defined.
3228
30
                unsafe_mask &= ~bit;
3229
30
                break;
3230
27.6k
            case LOAD_FAST:
3231
27.6k
                if (unsafe_mask & bit) {
3232
30
                    instr->i_opcode = LOAD_FAST_CHECK;
3233
30
                }
3234
27.6k
                unsafe_mask &= ~bit;
3235
27.6k
                break;
3236
131k
        }
3237
131k
    }
3238
19.7k
    if (b->b_next && BB_HAS_FALLTHROUGH(b)) {
3239
8.96k
        maybe_push(b->b_next, unsafe_mask, sp);
3240
8.96k
    }
3241
19.7k
    cfg_instr *last = basicblock_last_instr(b);
3242
19.7k
    if (last && is_jump(last)) {
3243
7.96k
        assert(last->i_target != NULL);
3244
7.96k
        maybe_push(last->i_target, unsafe_mask, sp);
3245
7.96k
    }
3246
19.7k
}
3247
3248
static int
3249
fast_scan_many_locals(basicblock *entryblock, int nlocals)
3250
0
{
3251
0
    assert(nlocals > 64);
3252
0
    Py_ssize_t *states = PyMem_Calloc(nlocals - 64, sizeof(Py_ssize_t));
3253
0
    if (states == NULL) {
3254
0
        PyErr_NoMemory();
3255
0
        return ERROR;
3256
0
    }
3257
0
    Py_ssize_t blocknum = 0;
3258
    // state[i - 64] == blocknum if local i is guaranteed to
3259
    // be initialized, i.e., if it has had a previous LOAD_FAST or
3260
    // STORE_FAST within that basicblock (not followed by
3261
    // DELETE_FAST/LOAD_FAST_AND_CLEAR/STORE_FAST_MAYBE_NULL).
3262
0
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
3263
0
        blocknum++;
3264
0
        for (int i = 0; i < b->b_iused; i++) {
3265
0
            cfg_instr *instr = &b->b_instr[i];
3266
0
            assert(instr->i_opcode != EXTENDED_ARG);
3267
0
            int arg = instr->i_oparg;
3268
0
            if (arg < 64) {
3269
0
                continue;
3270
0
            }
3271
0
            assert(arg >= 0);
3272
0
            switch (instr->i_opcode) {
3273
0
                case DELETE_FAST:
3274
0
                case LOAD_FAST_AND_CLEAR:
3275
0
                case STORE_FAST_MAYBE_NULL:
3276
0
                    states[arg - 64] = blocknum - 1;
3277
0
                    break;
3278
0
                case STORE_FAST:
3279
0
                    states[arg - 64] = blocknum;
3280
0
                    break;
3281
0
                case LOAD_FAST:
3282
0
                    if (states[arg - 64] != blocknum) {
3283
0
                        instr->i_opcode = LOAD_FAST_CHECK;
3284
0
                    }
3285
0
                    states[arg - 64] = blocknum;
3286
0
                    break;
3287
0
                    Py_UNREACHABLE();
3288
0
            }
3289
0
        }
3290
0
    }
3291
0
    PyMem_Free(states);
3292
0
    return SUCCESS;
3293
0
}
3294
3295
static int
3296
remove_unused_consts(basicblock *entryblock, PyObject *consts)
3297
4.26k
{
3298
4.26k
    assert(PyList_CheckExact(consts));
3299
4.26k
    Py_ssize_t nconsts = PyList_GET_SIZE(consts);
3300
4.26k
    if (nconsts == 0) {
3301
4
        return SUCCESS;  /* nothing to do */
3302
4
    }
3303
3304
4.25k
    Py_ssize_t *index_map = NULL;
3305
4.25k
    Py_ssize_t *reverse_index_map = NULL;
3306
4.25k
    int err = ERROR;
3307
3308
4.25k
    index_map = PyMem_Malloc(nconsts * sizeof(Py_ssize_t));
3309
4.25k
    if (index_map == NULL) {
3310
0
        PyErr_NoMemory();
3311
0
        goto end;
3312
0
    }
3313
26.0k
    for (Py_ssize_t i = 1; i < nconsts; i++) {
3314
21.7k
        index_map[i] = -1;
3315
21.7k
    }
3316
    // The first constant may be docstring; keep it always.
3317
4.25k
    index_map[0] = 0;
3318
3319
    /* mark used consts */
3320
20.6k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
3321
167k
        for (int i = 0; i < b->b_iused; i++) {
3322
151k
            int opcode = b->b_instr[i].i_opcode;
3323
151k
            if (OPCODE_HAS_CONST(opcode)) {
3324
15.9k
                int index = b->b_instr[i].i_oparg;
3325
15.9k
                index_map[index] = index;
3326
15.9k
            }
3327
151k
        }
3328
16.3k
    }
3329
    /* now index_map[i] == i if consts[i] is used, -1 otherwise */
3330
    /* condense consts */
3331
4.25k
    Py_ssize_t n_used_consts = 0;
3332
30.2k
    for (Py_ssize_t i = 0; i < nconsts; i++) {
3333
26.0k
        if (index_map[i] != -1) {
3334
14.8k
            assert(index_map[i] == i);
3335
14.8k
            index_map[n_used_consts++] = index_map[i];
3336
14.8k
        }
3337
26.0k
    }
3338
4.25k
    if (n_used_consts == nconsts) {
3339
        /* nothing to do */
3340
1.04k
        err = SUCCESS;
3341
1.04k
        goto end;
3342
1.04k
    }
3343
3344
    /* move all used consts to the beginning of the consts list */
3345
4.25k
    assert(n_used_consts < nconsts);
3346
16.9k
    for (Py_ssize_t i = 0; i < n_used_consts; i++) {
3347
13.7k
        Py_ssize_t old_index = index_map[i];
3348
13.7k
        assert(i <= old_index && old_index < nconsts);
3349
13.7k
        if (i != old_index) {
3350
7.07k
            PyObject *value = PyList_GET_ITEM(consts, index_map[i]);
3351
7.07k
            assert(value != NULL);
3352
7.07k
            PyList_SetItem(consts, i, Py_NewRef(value));
3353
7.07k
        }
3354
13.7k
    }
3355
3356
    /* truncate the consts list at its new size */
3357
3.21k
    if (PyList_SetSlice(consts, n_used_consts, nconsts, NULL) < 0) {
3358
0
        goto end;
3359
0
    }
3360
    /* adjust const indices in the bytecode */
3361
3.21k
    reverse_index_map = PyMem_Malloc(nconsts * sizeof(Py_ssize_t));
3362
3.21k
    if (reverse_index_map == NULL) {
3363
0
        PyErr_NoMemory();
3364
0
        goto end;
3365
0
    }
3366
28.1k
    for (Py_ssize_t i = 0; i < nconsts; i++) {
3367
24.9k
        reverse_index_map[i] = -1;
3368
24.9k
    }
3369
16.9k
    for (Py_ssize_t i = 0; i < n_used_consts; i++) {
3370
13.7k
        assert(index_map[i] != -1);
3371
13.7k
        assert(reverse_index_map[index_map[i]] == -1);
3372
13.7k
        reverse_index_map[index_map[i]] = i;
3373
13.7k
    }
3374
3375
16.8k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
3376
151k
        for (int i = 0; i < b->b_iused; i++) {
3377
137k
            int opcode = b->b_instr[i].i_opcode;
3378
137k
            if (OPCODE_HAS_CONST(opcode)) {
3379
15.7k
                int index = b->b_instr[i].i_oparg;
3380
15.7k
                assert(reverse_index_map[index] >= 0);
3381
15.7k
                assert(reverse_index_map[index] < n_used_consts);
3382
15.7k
                b->b_instr[i].i_oparg = (int)reverse_index_map[index];
3383
15.7k
            }
3384
137k
        }
3385
13.6k
    }
3386
3387
3.21k
    err = SUCCESS;
3388
4.25k
end:
3389
4.25k
    PyMem_Free(index_map);
3390
4.25k
    PyMem_Free(reverse_index_map);
3391
4.25k
    return err;
3392
3.21k
}
3393
3394
3395
3396
static int
3397
add_checks_for_loads_of_uninitialized_variables(basicblock *entryblock,
3398
                                                int nlocals,
3399
                                                int nparams)
3400
4.26k
{
3401
4.26k
    if (nlocals == 0) {
3402
1.57k
        return SUCCESS;
3403
1.57k
    }
3404
2.68k
    if (nlocals > 64) {
3405
        // To avoid O(nlocals**2) compilation, locals beyond the first
3406
        // 64 are only analyzed one basicblock at a time: initialization
3407
        // info is not passed between basicblocks.
3408
0
        if (fast_scan_many_locals(entryblock, nlocals) < 0) {
3409
0
            return ERROR;
3410
0
        }
3411
0
        nlocals = 64;
3412
0
    }
3413
2.68k
    basicblock **stack = make_cfg_traversal_stack(entryblock);
3414
2.68k
    if (stack == NULL) {
3415
0
        return ERROR;
3416
0
    }
3417
2.68k
    basicblock **sp = stack;
3418
3419
    // First origin of being uninitialized:
3420
    // The non-parameter locals in the entry block.
3421
2.68k
    uint64_t start_mask = 0;
3422
5.20k
    for (int i = nparams; i < nlocals; i++) {
3423
2.52k
        start_mask |= (uint64_t)1 << i;
3424
2.52k
    }
3425
2.68k
    maybe_push(entryblock, start_mask, &sp);
3426
3427
    // Second origin of being uninitialized:
3428
    // There could be DELETE_FAST somewhere, so
3429
    // be sure to scan each basicblock at least once.
3430
16.5k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
3431
13.8k
        scan_block_for_locals(b, &sp);
3432
13.8k
    }
3433
    // Now propagate the uncertainty from the origins we found: Use
3434
    // LOAD_FAST_CHECK for any LOAD_FAST where the local could be undefined.
3435
8.56k
    while (sp > stack) {
3436
5.87k
        basicblock *b = *--sp;
3437
        // mark as no longer on stack
3438
5.87k
        b->b_visited = 0;
3439
5.87k
        scan_block_for_locals(b, &sp);
3440
5.87k
    }
3441
2.68k
    PyMem_Free(stack);
3442
2.68k
    return SUCCESS;
3443
2.68k
}
3444
3445
3446
static int
3447
3.26k
mark_warm(basicblock *entryblock) {
3448
3.26k
    basicblock **stack = make_cfg_traversal_stack(entryblock);
3449
3.26k
    if (stack == NULL) {
3450
0
        return ERROR;
3451
0
    }
3452
3.26k
    basicblock **sp = stack;
3453
3454
3.26k
    *sp++ = entryblock;
3455
3.26k
    entryblock->b_visited = 1;
3456
13.7k
    while (sp > stack) {
3457
10.5k
        basicblock *b = *(--sp);
3458
10.5k
        assert(!b->b_except_handler);
3459
10.5k
        b->b_warm = 1;
3460
10.5k
        basicblock *next = b->b_next;
3461
10.5k
        if (next && BB_HAS_FALLTHROUGH(b) && !next->b_visited) {
3462
4.30k
            *sp++ = next;
3463
4.30k
            next->b_visited = 1;
3464
4.30k
        }
3465
110k
        for (int i=0; i < b->b_iused; i++) {
3466
99.5k
            cfg_instr *instr = &b->b_instr[i];
3467
99.5k
            if (is_jump(instr) && !instr->i_target->b_visited) {
3468
2.96k
                *sp++ = instr->i_target;
3469
2.96k
                instr->i_target->b_visited = 1;
3470
2.96k
            }
3471
99.5k
        }
3472
10.5k
    }
3473
3.26k
    PyMem_Free(stack);
3474
3.26k
    return SUCCESS;
3475
3.26k
}
3476
3477
static int
3478
3.26k
mark_cold(basicblock *entryblock) {
3479
18.6k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
3480
15.3k
        assert(!b->b_cold && !b->b_warm);
3481
15.3k
    }
3482
3.26k
    if (mark_warm(entryblock) < 0) {
3483
0
        return ERROR;
3484
0
    }
3485
3486
3.26k
    basicblock **stack = make_cfg_traversal_stack(entryblock);
3487
3.26k
    if (stack == NULL) {
3488
0
        return ERROR;
3489
0
    }
3490
3491
3.26k
    basicblock **sp = stack;
3492
18.6k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
3493
15.3k
        if (b->b_except_handler) {
3494
813
            assert(!b->b_warm);
3495
813
            *sp++ = b;
3496
813
            b->b_visited = 1;
3497
813
        }
3498
15.3k
    }
3499
3500
4.78k
    while (sp > stack) {
3501
1.52k
        basicblock *b = *(--sp);
3502
1.52k
        b->b_cold = 1;
3503
1.52k
        basicblock *next = b->b_next;
3504
1.52k
        if (next && BB_HAS_FALLTHROUGH(b)) {
3505
390
            if (!next->b_warm && !next->b_visited) {
3506
360
                *sp++ = next;
3507
360
                next->b_visited = 1;
3508
360
            }
3509
390
        }
3510
8.01k
        for (int i = 0; i < b->b_iused; i++) {
3511
6.49k
            cfg_instr *instr = &b->b_instr[i];
3512
6.49k
            if (is_jump(instr)) {
3513
475
                assert(i == b->b_iused - 1);
3514
475
                basicblock *target = b->b_instr[i].i_target;
3515
475
                if (!target->b_warm && !target->b_visited) {
3516
351
                    *sp++ = target;
3517
351
                    target->b_visited = 1;
3518
351
                }
3519
475
            }
3520
6.49k
        }
3521
1.52k
    }
3522
3.26k
    PyMem_Free(stack);
3523
3.26k
    return SUCCESS;
3524
3.26k
}
3525
3526
3527
static int
3528
4.26k
push_cold_blocks_to_end(cfg_builder *g) {
3529
4.26k
    basicblock *entryblock = g->g_entryblock;
3530
4.26k
    if (entryblock->b_next == NULL) {
3531
        /* single basicblock, no need to reorder */
3532
999
        return SUCCESS;
3533
999
    }
3534
3.26k
    RETURN_IF_ERROR(mark_cold(entryblock));
3535
3536
3.26k
    int next_lbl = get_max_label(g->g_entryblock) + 1;
3537
3538
    /* If we have a cold block with fallthrough to a warm block, add */
3539
    /* an explicit jump instead of fallthrough */
3540
18.6k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
3541
15.3k
        if (b->b_cold && BB_HAS_FALLTHROUGH(b) && b->b_next && b->b_next->b_warm) {
3542
21
            basicblock *explicit_jump = cfg_builder_new_block(g);
3543
21
            if (explicit_jump == NULL) {
3544
0
                return ERROR;
3545
0
            }
3546
21
            if (!IS_LABEL(b->b_next->b_label)) {
3547
0
                b->b_next->b_label.id = next_lbl++;
3548
0
            }
3549
21
            basicblock_addop(explicit_jump, JUMP_NO_INTERRUPT, b->b_next->b_label.id,
3550
21
                             NO_LOCATION);
3551
21
            explicit_jump->b_cold = 1;
3552
21
            explicit_jump->b_next = b->b_next;
3553
21
            explicit_jump->b_predecessors = 1;
3554
21
            b->b_next = explicit_jump;
3555
3556
            /* set target */
3557
21
            cfg_instr *last = basicblock_last_instr(explicit_jump);
3558
21
            last->i_target = explicit_jump->b_next;
3559
21
        }
3560
15.3k
    }
3561
3562
3.26k
    assert(!entryblock->b_cold);  /* First block can't be cold */
3563
3.26k
    basicblock *cold_blocks = NULL;
3564
3.26k
    basicblock *cold_blocks_tail = NULL;
3565
3566
3.26k
    basicblock *b = entryblock;
3567
3.86k
    while(b->b_next) {
3568
3.86k
        assert(!b->b_cold);
3569
14.4k
        while (b->b_next && !b->b_next->b_cold) {
3570
10.5k
            b = b->b_next;
3571
10.5k
        }
3572
3.86k
        if (b->b_next == NULL) {
3573
            /* no more cold blocks */
3574
3.26k
            break;
3575
3.26k
        }
3576
3577
        /* b->b_next is the beginning of a cold streak */
3578
3.86k
        assert(!b->b_cold && b->b_next->b_cold);
3579
3580
602
        basicblock *b_end = b->b_next;
3581
1.54k
        while (b_end->b_next && b_end->b_next->b_cold) {
3582
943
            b_end = b_end->b_next;
3583
943
        }
3584
3585
        /* b_end is the end of the cold streak */
3586
602
        assert(b_end && b_end->b_cold);
3587
602
        assert(b_end->b_next == NULL || !b_end->b_next->b_cold);
3588
3589
602
        if (cold_blocks == NULL) {
3590
319
            cold_blocks = b->b_next;
3591
319
        }
3592
283
        else {
3593
283
            cold_blocks_tail->b_next = b->b_next;
3594
283
        }
3595
602
        cold_blocks_tail = b_end;
3596
602
        b->b_next = b_end->b_next;
3597
602
        b_end->b_next = NULL;
3598
602
    }
3599
3.26k
    assert(b != NULL && b->b_next == NULL);
3600
3.26k
    b->b_next = cold_blocks;
3601
3602
3.26k
    if (cold_blocks != NULL) {
3603
319
        RETURN_IF_ERROR(remove_redundant_nops_and_jumps(g));
3604
319
    }
3605
3.26k
    return SUCCESS;
3606
3.26k
}
3607
3608
static int
3609
convert_pseudo_conditional_jumps(cfg_builder *g)
3610
4.26k
{
3611
4.26k
    basicblock *entryblock = g->g_entryblock;
3612
20.6k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
3613
164k
        for (int i = 0; i < b->b_iused; i++) {
3614
148k
            cfg_instr *instr = &b->b_instr[i];
3615
148k
            if (instr->i_opcode == JUMP_IF_FALSE || instr->i_opcode == JUMP_IF_TRUE) {
3616
559
                assert(i == b->b_iused - 1);
3617
559
                instr->i_opcode = instr->i_opcode == JUMP_IF_FALSE ?
3618
502
                                          POP_JUMP_IF_FALSE : POP_JUMP_IF_TRUE;
3619
559
                location loc = instr->i_loc;
3620
559
                basicblock *except = instr->i_except;
3621
559
                cfg_instr copy = {
3622
559
                            .i_opcode = COPY,
3623
559
                            .i_oparg = 1,
3624
559
                            .i_loc = loc,
3625
559
                            .i_target = NULL,
3626
559
                            .i_except = except,
3627
559
                };
3628
559
                RETURN_IF_ERROR(basicblock_insert_instruction(b, i++, &copy));
3629
559
                cfg_instr to_bool = {
3630
559
                            .i_opcode = TO_BOOL,
3631
559
                            .i_oparg = 0,
3632
559
                            .i_loc = loc,
3633
559
                            .i_target = NULL,
3634
559
                            .i_except = except,
3635
559
                };
3636
559
                RETURN_IF_ERROR(basicblock_insert_instruction(b, i++, &to_bool));
3637
559
            }
3638
148k
        }
3639
16.3k
    }
3640
4.26k
    return SUCCESS;
3641
4.26k
}
3642
3643
static int
3644
convert_pseudo_ops(cfg_builder *g)
3645
4.26k
{
3646
4.26k
    basicblock *entryblock = g->g_entryblock;
3647
20.6k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
3648
167k
        for (int i = 0; i < b->b_iused; i++) {
3649
150k
            cfg_instr *instr = &b->b_instr[i];
3650
150k
            if (is_block_push(instr)) {
3651
813
                INSTR_SET_OP0(instr, NOP);
3652
813
            }
3653
150k
            else if (instr->i_opcode == LOAD_CLOSURE) {
3654
1.13k
                assert(is_pseudo_target(LOAD_CLOSURE, LOAD_FAST));
3655
1.13k
                instr->i_opcode = LOAD_FAST;
3656
1.13k
            }
3657
148k
            else if (instr->i_opcode == STORE_FAST_MAYBE_NULL) {
3658
124
                assert(is_pseudo_target(STORE_FAST_MAYBE_NULL, STORE_FAST));
3659
124
                instr->i_opcode = STORE_FAST;
3660
124
            }
3661
150k
        }
3662
16.3k
    }
3663
4.26k
    return remove_redundant_nops_and_jumps(g);
3664
4.26k
}
3665
3666
static inline bool
3667
21.0k
is_exit_or_eval_check_without_lineno(basicblock *b) {
3668
21.0k
    if (basicblock_exits_scope(b) || basicblock_has_eval_break(b)) {
3669
12.4k
        return basicblock_has_no_lineno(b);
3670
12.4k
    }
3671
8.61k
    else {
3672
8.61k
        return false;
3673
8.61k
    }
3674
21.0k
}
3675
3676
3677
/* PEP 626 mandates that the f_lineno of a frame is correct
3678
 * after a frame terminates. It would be prohibitively expensive
3679
 * to continuously update the f_lineno field at runtime,
3680
 * so we make sure that all exiting instruction (raises and returns)
3681
 * have a valid line number, allowing us to compute f_lineno lazily.
3682
 * We can do this by duplicating the exit blocks without line number
3683
 * so that none have more than one predecessor. We can then safely
3684
 * copy the line number from the sole predecessor block.
3685
 */
3686
static int
3687
duplicate_exits_without_lineno(cfg_builder *g)
3688
8.52k
{
3689
8.52k
    int next_lbl = get_max_label(g->g_entryblock) + 1;
3690
3691
    /* Copy all exit blocks without line number that are targets of a jump.
3692
     */
3693
8.52k
    basicblock *entryblock = g->g_entryblock;
3694
41.2k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
3695
32.7k
        cfg_instr *last = basicblock_last_instr(b);
3696
32.7k
        if (last == NULL) {
3697
6.45k
            continue;
3698
6.45k
        }
3699
26.2k
        if (is_jump(last)) {
3700
10.0k
            basicblock *target = next_nonempty_block(last->i_target);
3701
10.0k
            if (is_exit_or_eval_check_without_lineno(target) && target->b_predecessors > 1) {
3702
214
                basicblock *new_target = copy_basicblock(g, target);
3703
214
                if (new_target == NULL) {
3704
0
                    return ERROR;
3705
0
                }
3706
214
                new_target->b_instr[0].i_loc = last->i_loc;
3707
214
                last->i_target = new_target;
3708
214
                target->b_predecessors--;
3709
214
                new_target->b_predecessors = 1;
3710
214
                new_target->b_next = target->b_next;
3711
214
                new_target->b_label.id = next_lbl++;
3712
214
                target->b_next = new_target;
3713
214
            }
3714
10.0k
        }
3715
26.2k
    }
3716
3717
    /* Any remaining reachable exit blocks without line number can only be reached by
3718
     * fall through, and thus can only have a single predecessor */
3719
41.2k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
3720
32.7k
        if (BB_HAS_FALLTHROUGH(b) && b->b_next && b->b_iused > 0) {
3721
11.0k
            if (is_exit_or_eval_check_without_lineno(b->b_next)) {
3722
328
                cfg_instr *last = basicblock_last_instr(b);
3723
328
                assert(last != NULL);
3724
328
                b->b_next->b_instr[0].i_loc = last->i_loc;
3725
328
            }
3726
11.0k
        }
3727
32.7k
    }
3728
8.52k
    return SUCCESS;
3729
8.52k
}
3730
3731
3732
/* If an instruction has no line number, but it's predecessor in the BB does,
3733
 * then copy the line number. If a successor block has no line number, and only
3734
 * one predecessor, then inherit the line number.
3735
 * This ensures that all exit blocks (with one predecessor) receive a line number.
3736
 * Also reduces the size of the line number table,
3737
 * but has no impact on the generated line number events.
3738
 */
3739
3740
static inline void
3741
maybe_propagate_location(basicblock *b, int i, location loc)
3742
323k
{
3743
323k
    assert(b->b_iused > i);
3744
323k
    if (b->b_instr[i].i_loc.lineno == NO_LOCATION.lineno) {
3745
17.1k
         b->b_instr[i].i_loc = loc;
3746
17.1k
    }
3747
323k
}
3748
3749
static void
3750
propagate_line_numbers(basicblock *entryblock)
3751
8.52k
{
3752
41.2k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
3753
32.7k
        cfg_instr *last = basicblock_last_instr(b);
3754
32.7k
        if (last == NULL) {
3755
6.45k
            continue;
3756
6.45k
        }
3757
3758
26.2k
        location prev_location = NO_LOCATION;
3759
336k
        for (int i = 0; i < b->b_iused; i++) {
3760
310k
            maybe_propagate_location(b, i, prev_location);
3761
310k
            prev_location = b->b_instr[i].i_loc;
3762
310k
        }
3763
26.2k
        if (BB_HAS_FALLTHROUGH(b) && b->b_next->b_predecessors == 1) {
3764
8.08k
            if (b->b_next->b_iused > 0) {
3765
8.08k
                maybe_propagate_location(b->b_next, 0, prev_location);
3766
8.08k
            }
3767
8.08k
        }
3768
26.2k
        if (is_jump(last)) {
3769
10.0k
            basicblock *target = last->i_target;
3770
10.0k
            while (target->b_iused == 0 && target->b_predecessors == 1) {
3771
0
                target = target->b_next;
3772
0
            }
3773
10.0k
            if (target->b_predecessors == 1) {
3774
4.70k
                maybe_propagate_location(target, 0, prev_location);
3775
4.70k
            }
3776
10.0k
        }
3777
26.2k
    }
3778
8.52k
}
3779
3780
static int
3781
resolve_line_numbers(cfg_builder *g, int firstlineno)
3782
8.52k
{
3783
8.52k
    RETURN_IF_ERROR(duplicate_exits_without_lineno(g));
3784
8.52k
    propagate_line_numbers(g->g_entryblock);
3785
8.52k
    return SUCCESS;
3786
8.52k
}
3787
3788
int
3789
_PyCfg_OptimizeCodeUnit(cfg_builder *g, PyObject *consts, PyObject *const_cache,
3790
                        int nlocals, int nparams, int firstlineno)
3791
4.26k
{
3792
4.26k
    assert(cfg_builder_check(g));
3793
4.26k
    assert(g->g_entryblock->b_iused > 0);
3794
    /** Preprocessing **/
3795
    /* Map labels to targets and mark exception handlers */
3796
4.26k
    RETURN_IF_ERROR(translate_jump_labels_to_targets(g->g_entryblock));
3797
4.26k
    RETURN_IF_ERROR(mark_except_handlers(g->g_entryblock));
3798
4.26k
    RETURN_IF_ERROR(label_exception_targets(g->g_entryblock));
3799
3800
    /** Optimization **/
3801
3802
4.26k
    _Py_hashtable_t *consts_index = _Py_hashtable_new(
3803
4.26k
        _Py_hashtable_hash_ptr, _Py_hashtable_compare_direct);
3804
4.26k
    if (consts_index == NULL) {
3805
0
        PyErr_NoMemory();
3806
0
        return ERROR;
3807
0
    }
3808
3809
29.6k
    for (Py_ssize_t i = 0; i < PyList_GET_SIZE(consts); i++) {
3810
25.3k
        PyObject *item = PyList_GET_ITEM(consts, i);
3811
25.3k
        if (_Py_hashtable_get_entry(consts_index, (void *)item) != NULL) {
3812
0
            continue;
3813
0
        }
3814
25.3k
        if (_Py_hashtable_set(consts_index, (void *)item,
3815
25.3k
                              (void *)(uintptr_t)i) < 0) {
3816
0
            _Py_hashtable_destroy(consts_index);
3817
0
            PyErr_NoMemory();
3818
0
            return ERROR;
3819
0
        }
3820
25.3k
    }
3821
3822
4.26k
    int ret = optimize_cfg(g, consts, const_cache, consts_index, firstlineno);
3823
3824
4.26k
    _Py_hashtable_destroy(consts_index);
3825
3826
4.26k
    RETURN_IF_ERROR(ret);
3827
3828
4.26k
    RETURN_IF_ERROR(remove_unused_consts(g->g_entryblock, consts));
3829
4.26k
    RETURN_IF_ERROR(
3830
4.26k
        add_checks_for_loads_of_uninitialized_variables(
3831
4.26k
            g->g_entryblock, nlocals, nparams));
3832
4.26k
    RETURN_IF_ERROR(insert_superinstructions(g));
3833
3834
4.26k
    RETURN_IF_ERROR(push_cold_blocks_to_end(g));
3835
4.26k
    RETURN_IF_ERROR(resolve_line_numbers(g, firstlineno));
3836
    // temporarily remove assert. See https://github.com/python/cpython/issues/125845
3837
    // assert(all_exits_have_lineno(g->g_entryblock));
3838
4.26k
    return SUCCESS;
3839
4.26k
}
3840
3841
static int *
3842
build_cellfixedoffsets(_PyCompile_CodeUnitMetadata *umd)
3843
4.26k
{
3844
4.26k
    int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames);
3845
4.26k
    int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars);
3846
4.26k
    int nfreevars = (int)PyDict_GET_SIZE(umd->u_freevars);
3847
3848
4.26k
    int noffsets = ncellvars + nfreevars;
3849
4.26k
    int *fixed = PyMem_New(int, noffsets);
3850
4.26k
    if (fixed == NULL) {
3851
0
        PyErr_NoMemory();
3852
0
        return NULL;
3853
0
    }
3854
5.93k
    for (int i = 0; i < noffsets; i++) {
3855
1.66k
        fixed[i] = nlocals + i;
3856
1.66k
    }
3857
3858
4.26k
    PyObject *varname, *cellindex;
3859
4.26k
    Py_ssize_t pos = 0;
3860
5.16k
    while (PyDict_Next(umd->u_cellvars, &pos, &varname, &cellindex)) {
3861
902
        PyObject *varindex;
3862
902
        if (PyDict_GetItemRef(umd->u_varnames, varname, &varindex) < 0) {
3863
0
            goto error;
3864
0
        }
3865
902
        if (varindex == NULL) {
3866
426
            continue;
3867
426
        }
3868
3869
476
        int argoffset = PyLong_AsInt(varindex);
3870
476
        Py_DECREF(varindex);
3871
476
        if (argoffset == -1 && PyErr_Occurred()) {
3872
0
            goto error;
3873
0
        }
3874
3875
476
        int oldindex = PyLong_AsInt(cellindex);
3876
476
        if (oldindex == -1 && PyErr_Occurred()) {
3877
0
            goto error;
3878
0
        }
3879
476
        fixed[oldindex] = argoffset;
3880
476
    }
3881
4.26k
    return fixed;
3882
3883
0
error:
3884
0
    PyMem_Free(fixed);
3885
0
    return NULL;
3886
4.26k
}
3887
3888
#define IS_GENERATOR(CF) \
3889
    ((CF) & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR))
3890
3891
static int
3892
insert_prefix_instructions(_PyCompile_CodeUnitMetadata *umd, basicblock *entryblock,
3893
                           int *fixed, int nfreevars)
3894
4.26k
{
3895
4.26k
    assert(umd->u_firstlineno > 0);
3896
3897
    /* Set up cells for any variable that escapes, to be put in a closure. */
3898
4.26k
    const int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars);
3899
4.26k
    if (ncellvars) {
3900
        // umd->u_cellvars has the cells out of order so we sort them
3901
        // before adding the MAKE_CELL instructions.  Note that we
3902
        // adjust for arg cells, which come first.
3903
671
        const int nvars = ncellvars + (int)PyDict_GET_SIZE(umd->u_varnames);
3904
671
        int *sorted = PyMem_RawCalloc(nvars, sizeof(int));
3905
671
        if (sorted == NULL) {
3906
0
            PyErr_NoMemory();
3907
0
            return ERROR;
3908
0
        }
3909
1.57k
        for (int i = 0; i < ncellvars; i++) {
3910
902
            sorted[fixed[i]] = i + 1;
3911
902
        }
3912
2.01k
        for (int i = 0, ncellsused = 0; ncellsused < ncellvars; i++) {
3913
1.34k
            int oldindex = sorted[i] - 1;
3914
1.34k
            if (oldindex == -1) {
3915
438
                continue;
3916
438
            }
3917
902
            cfg_instr make_cell = {
3918
902
                .i_opcode = MAKE_CELL,
3919
                // This will get fixed in offset_derefs().
3920
902
                .i_oparg = oldindex,
3921
902
                .i_loc = NO_LOCATION,
3922
902
                .i_target = NULL,
3923
902
                .i_except = NULL,
3924
902
            };
3925
902
            if (basicblock_insert_instruction(entryblock, ncellsused, &make_cell) < 0) {
3926
0
                PyMem_RawFree(sorted);
3927
0
                return ERROR;
3928
0
            }
3929
902
            ncellsused += 1;
3930
902
        }
3931
671
        PyMem_RawFree(sorted);
3932
671
    }
3933
3934
4.26k
    if (nfreevars) {
3935
540
        cfg_instr copy_frees = {
3936
540
            .i_opcode = COPY_FREE_VARS,
3937
540
            .i_oparg = nfreevars,
3938
540
            .i_loc = NO_LOCATION,
3939
540
            .i_target = NULL,
3940
540
            .i_except = NULL,
3941
540
        };
3942
540
        RETURN_IF_ERROR(basicblock_insert_instruction(entryblock, 0, &copy_frees));
3943
540
    }
3944
3945
4.26k
    return SUCCESS;
3946
4.26k
}
3947
3948
static int
3949
fix_cell_offsets(_PyCompile_CodeUnitMetadata *umd, basicblock *entryblock, int *fixedmap)
3950
4.26k
{
3951
4.26k
    int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames);
3952
4.26k
    int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars);
3953
4.26k
    int nfreevars = (int)PyDict_GET_SIZE(umd->u_freevars);
3954
4.26k
    int noffsets = ncellvars + nfreevars;
3955
3956
    // First deal with duplicates (arg cells).
3957
4.26k
    int numdropped = 0;
3958
5.93k
    for (int i = 0; i < noffsets ; i++) {
3959
1.66k
        if (fixedmap[i] == i + nlocals) {
3960
1.19k
            fixedmap[i] -= numdropped;
3961
1.19k
        }
3962
476
        else {
3963
            // It was a duplicate (cell/arg).
3964
476
            numdropped += 1;
3965
476
        }
3966
1.66k
    }
3967
3968
    // Then update offsets, either relative to locals or by cell2arg.
3969
20.6k
    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
3970
167k
        for (int i = 0; i < b->b_iused; i++) {
3971
150k
            cfg_instr *inst = &b->b_instr[i];
3972
            // This is called before extended args are generated.
3973
150k
            assert(inst->i_opcode != EXTENDED_ARG);
3974
150k
            int oldoffset = inst->i_oparg;
3975
150k
            switch(inst->i_opcode) {
3976
902
                case MAKE_CELL:
3977
2.03k
                case LOAD_CLOSURE:
3978
3.91k
                case LOAD_DEREF:
3979
4.35k
                case STORE_DEREF:
3980
4.35k
                case DELETE_DEREF:
3981
4.35k
                case LOAD_FROM_DICT_OR_DEREF:
3982
4.35k
                    assert(oldoffset >= 0);
3983
4.35k
                    assert(oldoffset < noffsets);
3984
4.35k
                    assert(fixedmap[oldoffset] >= 0);
3985
4.35k
                    inst->i_oparg = fixedmap[oldoffset];
3986
150k
            }
3987
150k
        }
3988
16.3k
    }
3989
3990
4.26k
    return numdropped;
3991
4.26k
}
3992
3993
static int
3994
prepare_localsplus(_PyCompile_CodeUnitMetadata *umd, cfg_builder *g)
3995
4.26k
{
3996
4.26k
    assert(PyDict_GET_SIZE(umd->u_varnames) < INT_MAX);
3997
4.26k
    assert(PyDict_GET_SIZE(umd->u_cellvars) < INT_MAX);
3998
4.26k
    assert(PyDict_GET_SIZE(umd->u_freevars) < INT_MAX);
3999
4.26k
    int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames);
4000
4.26k
    int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars);
4001
4.26k
    int nfreevars = (int)PyDict_GET_SIZE(umd->u_freevars);
4002
4.26k
    assert(INT_MAX - nlocals - ncellvars > 0);
4003
4.26k
    assert(INT_MAX - nlocals - ncellvars - nfreevars > 0);
4004
4.26k
    int nlocalsplus = nlocals + ncellvars + nfreevars;
4005
4.26k
    int* cellfixedoffsets = build_cellfixedoffsets(umd);
4006
4.26k
    if (cellfixedoffsets == NULL) {
4007
0
        return ERROR;
4008
0
    }
4009
4010
    // This must be called before fix_cell_offsets().
4011
4.26k
    if (insert_prefix_instructions(umd, g->g_entryblock, cellfixedoffsets, nfreevars)) {
4012
0
        PyMem_Free(cellfixedoffsets);
4013
0
        return ERROR;
4014
0
    }
4015
4016
4.26k
    int numdropped = fix_cell_offsets(umd, g->g_entryblock, cellfixedoffsets);
4017
4.26k
    PyMem_Free(cellfixedoffsets);  // At this point we're done with it.
4018
4.26k
    cellfixedoffsets = NULL;
4019
4.26k
    if (numdropped < 0) {
4020
0
        return ERROR;
4021
0
    }
4022
4023
4.26k
    nlocalsplus -= numdropped;
4024
4.26k
    return nlocalsplus;
4025
4.26k
}
4026
4027
cfg_builder *
4028
_PyCfg_FromInstructionSequence(_PyInstructionSequence *seq)
4029
4.26k
{
4030
4.26k
    if (_PyInstructionSequence_ApplyLabelMap(seq) < 0) {
4031
0
        return NULL;
4032
0
    }
4033
4.26k
    cfg_builder *g = _PyCfgBuilder_New();
4034
4.26k
    if (g == NULL) {
4035
0
        return NULL;
4036
0
    }
4037
172k
    for (int i = 0; i < seq->s_used; i++) {
4038
168k
        seq->s_instrs[i].i_target = 0;
4039
168k
    }
4040
172k
    for (int i = 0; i < seq->s_used; i++) {
4041
168k
        _PyInstruction *instr = &seq->s_instrs[i];
4042
168k
        if (HAS_TARGET(instr->i_opcode)) {
4043
6.51k
            assert(instr->i_oparg >= 0 && instr->i_oparg < seq->s_used);
4044
6.51k
            seq->s_instrs[instr->i_oparg].i_target = 1;
4045
6.51k
        }
4046
168k
    }
4047
4.26k
    int offset = 0;
4048
172k
    for (int i = 0; i < seq->s_used; i++) {
4049
168k
        _PyInstruction *instr = &seq->s_instrs[i];
4050
168k
        if (instr->i_opcode == ANNOTATIONS_PLACEHOLDER) {
4051
728
            if (seq->s_annotations_code != NULL) {
4052
1
                assert(seq->s_annotations_code->s_labelmap_size == 0
4053
1
                    && seq->s_annotations_code->s_nested == NULL);
4054
4
                for (int j = 0; j < seq->s_annotations_code->s_used; j++) {
4055
3
                    _PyInstruction *ann_instr = &seq->s_annotations_code->s_instrs[j];
4056
3
                    assert(!HAS_TARGET(ann_instr->i_opcode));
4057
3
                    if (_PyCfgBuilder_Addop(g, ann_instr->i_opcode, ann_instr->i_oparg, ann_instr->i_loc) < 0) {
4058
0
                        goto error;
4059
0
                    }
4060
3
                }
4061
1
                offset += seq->s_annotations_code->s_used - 1;
4062
1
            }
4063
727
            else {
4064
727
                offset -= 1;
4065
727
            }
4066
728
            continue;
4067
728
        }
4068
167k
        if (instr->i_target) {
4069
5.22k
            jump_target_label lbl_ = {i + offset};
4070
5.22k
            if (_PyCfgBuilder_UseLabel(g, lbl_) < 0) {
4071
0
                goto error;
4072
0
            }
4073
5.22k
        }
4074
167k
        int opcode = instr->i_opcode;
4075
167k
        int oparg = instr->i_oparg;
4076
167k
        if (HAS_TARGET(opcode)) {
4077
6.51k
            oparg += offset;
4078
6.51k
        }
4079
167k
        if (_PyCfgBuilder_Addop(g, opcode, oparg, instr->i_loc) < 0) {
4080
0
            goto error;
4081
0
        }
4082
167k
    }
4083
4.26k
    if (_PyCfgBuilder_CheckSize(g) < 0) {
4084
0
        goto error;
4085
0
    }
4086
4.26k
    return g;
4087
0
error:
4088
0
    _PyCfgBuilder_Free(g);
4089
0
    return NULL;
4090
4.26k
}
4091
4092
int
4093
_PyCfg_ToInstructionSequence(cfg_builder *g, _PyInstructionSequence *seq)
4094
4.26k
{
4095
4.26k
    int lbl = 0;
4096
20.7k
    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
4097
16.5k
        b->b_label = (jump_target_label){lbl};
4098
16.5k
        lbl += 1;
4099
16.5k
    }
4100
20.7k
    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
4101
16.5k
        RETURN_IF_ERROR(_PyInstructionSequence_UseLabel(seq, b->b_label.id));
4102
170k
        for (int i = 0; i < b->b_iused; i++) {
4103
153k
            cfg_instr *instr = &b->b_instr[i];
4104
153k
            if (HAS_TARGET(instr->i_opcode)) {
4105
                /* Set oparg to the label id (it will later be mapped to an offset) */
4106
5.01k
                instr->i_oparg = instr->i_target->b_label.id;
4107
5.01k
            }
4108
153k
            RETURN_IF_ERROR(
4109
153k
                _PyInstructionSequence_Addop(
4110
153k
                    seq, instr->i_opcode, instr->i_oparg, instr->i_loc));
4111
4112
153k
            _PyExceptHandlerInfo *hi = &seq->s_instrs[seq->s_used-1].i_except_handler_info;
4113
153k
            if (instr->i_except != NULL) {
4114
13.1k
                hi->h_label = instr->i_except->b_label.id;
4115
13.1k
                hi->h_startdepth = instr->i_except->b_startdepth;
4116
13.1k
                hi->h_preserve_lasti = instr->i_except->b_preserve_lasti;
4117
13.1k
            }
4118
140k
            else {
4119
140k
                hi->h_label = -1;
4120
140k
            }
4121
153k
        }
4122
16.5k
    }
4123
4.26k
    if (_PyInstructionSequence_ApplyLabelMap(seq) < 0) {
4124
0
        return ERROR;
4125
0
    }
4126
4.26k
    return SUCCESS;
4127
4.26k
}
4128
4129
4130
int
4131
_PyCfg_OptimizedCfgToInstructionSequence(cfg_builder *g,
4132
                                     _PyCompile_CodeUnitMetadata *umd,
4133
                                     int *stackdepth, int *nlocalsplus,
4134
                                     _PyInstructionSequence *seq)
4135
4.26k
{
4136
4.26k
    RETURN_IF_ERROR(convert_pseudo_conditional_jumps(g));
4137
4138
4.26k
    *stackdepth = calculate_stackdepth(g);
4139
4.26k
    if (*stackdepth < 0) {
4140
0
        return ERROR;
4141
0
    }
4142
4143
4.26k
    *nlocalsplus = prepare_localsplus(umd, g);
4144
4.26k
    if (*nlocalsplus < 0) {
4145
0
        return ERROR;
4146
0
    }
4147
4148
4.26k
    RETURN_IF_ERROR(convert_pseudo_ops(g));
4149
4150
    /* Order of basic blocks must have been determined by now */
4151
4152
4.26k
    RETURN_IF_ERROR(normalize_jumps(g));
4153
4.26k
    assert(no_redundant_jumps(g));
4154
4155
    /* Can't modify the bytecode after inserting instructions that produce
4156
     * borrowed references.
4157
     */
4158
4.26k
    RETURN_IF_ERROR(optimize_load_fast(g));
4159
4160
    /* Can't modify the bytecode after computing jump offsets. */
4161
4.26k
    if (_PyCfg_ToInstructionSequence(g, seq) < 0) {
4162
0
        return ERROR;
4163
0
    }
4164
4165
4.26k
    return SUCCESS;
4166
4.26k
}
4167
4168
/* This is used by _PyCompile_Assemble to fill in the jump and exception
4169
 * targets in a synthetic CFG (which is not the output of the builtin compiler).
4170
 */
4171
int
4172
_PyCfg_JumpLabelsToTargets(cfg_builder *g)
4173
0
{
4174
0
    RETURN_IF_ERROR(translate_jump_labels_to_targets(g->g_entryblock));
4175
0
    RETURN_IF_ERROR(label_exception_targets(g->g_entryblock));
4176
0
    return SUCCESS;
4177
0
}
4178
4179
/* Exported API functions */
4180
4181
int
4182
PyCompile_OpcodeStackEffectWithJump(int opcode, int oparg, int jump)
4183
0
{
4184
0
    stack_effects effs;
4185
0
    if (get_stack_effects(opcode, oparg, jump, &effs) < 0) {
4186
0
        return PY_INVALID_STACK_EFFECT;
4187
0
    }
4188
0
    return effs.net;
4189
0
}
4190
4191
int
4192
PyCompile_OpcodeStackEffect(int opcode, int oparg)
4193
16
{
4194
16
    stack_effects effs;
4195
16
    if (get_stack_effects(opcode, oparg, -1, &effs) < 0) {
4196
0
        return PY_INVALID_STACK_EFFECT;
4197
0
    }
4198
16
    return effs.net;
4199
16
}
4200
4201
/* Access to compiler optimizations for unit tests.
4202
4203
 * _PyCompile_OptimizeCfg takes an instruction list, constructs
4204
 * a CFG, optimizes it and converts back to an instruction list.
4205
 */
4206
4207
static PyObject *
4208
cfg_to_instruction_sequence(cfg_builder *g)
4209
0
{
4210
0
    _PyInstructionSequence *seq = (_PyInstructionSequence *)_PyInstructionSequence_New();
4211
0
    if (seq == NULL) {
4212
0
        return NULL;
4213
0
    }
4214
0
    if (_PyCfg_ToInstructionSequence(g, seq) < 0) {
4215
0
        PyInstructionSequence_Fini(seq);
4216
0
        return NULL;
4217
0
    }
4218
0
    return (PyObject*)seq;
4219
0
}
4220
4221
PyObject *
4222
_PyCompile_OptimizeCfg(PyObject *seq, PyObject *consts, int nlocals)
4223
0
{
4224
0
    if (!_PyInstructionSequence_Check(seq)) {
4225
0
        PyErr_SetString(PyExc_ValueError, "expected an instruction sequence");
4226
0
        return NULL;
4227
0
    }
4228
0
    if (!PyList_Check(consts)) {
4229
0
        PyErr_SetString(PyExc_TypeError, "consts must be a list");
4230
0
        return NULL;
4231
0
    }
4232
0
    PyObject *const_cache = PyDict_New();
4233
0
    if (const_cache == NULL) {
4234
0
        return NULL;
4235
0
    }
4236
4237
0
    PyObject *res = NULL;
4238
0
    cfg_builder *g = _PyCfg_FromInstructionSequence((_PyInstructionSequence*)seq);
4239
0
    if (g == NULL) {
4240
0
        goto error;
4241
0
    }
4242
0
    int nparams = 0, firstlineno = 1;
4243
0
    if (_PyCfg_OptimizeCodeUnit(g, consts, const_cache, nlocals,
4244
0
                                nparams, firstlineno) < 0) {
4245
0
        goto error;
4246
0
    }
4247
4248
0
    if (calculate_stackdepth(g) == ERROR) {
4249
0
        goto error;
4250
0
    }
4251
4252
0
    if (optimize_load_fast(g) != SUCCESS) {
4253
0
        goto error;
4254
0
    }
4255
4256
0
    res = cfg_to_instruction_sequence(g);
4257
0
error:
4258
0
    Py_DECREF(const_cache);
4259
0
    _PyCfgBuilder_Free(g);
4260
0
    return res;
4261
0
}