Coverage Report

Created: 2026-10-31 06:21

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