Coverage Report

Created: 2025-10-12 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Python/assemble.c
Line
Count
Source
1
#include "Python.h"
2
#include "pycore_code.h"            // write_location_entry_start()
3
#include "pycore_compile.h"
4
#include "pycore_instruction_sequence.h"
5
#include "pycore_opcode_utils.h"    // IS_BACKWARDS_JUMP_OPCODE
6
#include "pycore_opcode_metadata.h" // is_pseudo_target, _PyOpcode_Caches
7
#include "pycore_symtable.h"        // _Py_SourceLocation
8
9
#include <stdbool.h>
10
11
6.90k
#define DEFAULT_CODE_SIZE 128
12
6.90k
#define DEFAULT_LNOTAB_SIZE 16
13
6.90k
#define DEFAULT_CNOTAB_SIZE 32
14
15
#undef SUCCESS
16
#undef ERROR
17
691k
#define SUCCESS 0
18
6.90k
#define ERROR -1
19
20
#define RETURN_IF_ERROR(X)  \
21
757k
    if ((X) < 0) {          \
22
0
        return ERROR;       \
23
0
    }
24
25
typedef _Py_SourceLocation location;
26
typedef _PyInstruction instruction;
27
typedef _PyInstructionSequence instr_sequence;
28
29
static inline bool
30
same_location(location a, location b)
31
707k
{
32
707k
    return a.lineno == b.lineno &&
33
261k
           a.end_lineno == b.end_lineno &&
34
255k
           a.col_offset == b.col_offset &&
35
141k
           a.end_col_offset == b.end_col_offset;
36
707k
}
37
38
static int
39
instr_size(instruction *instr)
40
1.98M
{
41
1.98M
    int opcode = instr->i_opcode;
42
1.98M
    int oparg = instr->i_oparg;
43
1.98M
    assert(!IS_PSEUDO_INSTR(opcode));
44
1.98M
    assert(OPCODE_HAS_ARG(opcode) || oparg == 0);
45
1.98M
    int extended_args = (0xFFFFFF < oparg) + (0xFFFF < oparg) + (0xFF < oparg);
46
1.98M
    int caches = _PyOpcode_Caches[opcode];
47
1.98M
    return extended_args + 1 + caches;
48
1.98M
}
49
50
struct assembler {
51
    PyObject *a_bytecode;  /* bytes containing bytecode */
52
    int a_offset;              /* offset into bytecode */
53
    PyObject *a_except_table;  /* bytes containing exception table */
54
    int a_except_table_off;    /* offset into exception table */
55
    /* Location Info */
56
    int a_lineno;          /* lineno of last emitted instruction */
57
    PyObject* a_linetable; /* bytes containing location info */
58
    int a_location_off;    /* offset of last written location info frame */
59
};
60
61
static int
62
assemble_init(struct assembler *a, int firstlineno)
63
6.90k
{
64
6.90k
    memset(a, 0, sizeof(struct assembler));
65
6.90k
    a->a_lineno = firstlineno;
66
6.90k
    a->a_linetable = NULL;
67
6.90k
    a->a_location_off = 0;
68
6.90k
    a->a_except_table = NULL;
69
6.90k
    a->a_bytecode = PyBytes_FromStringAndSize(NULL, DEFAULT_CODE_SIZE);
70
6.90k
    if (a->a_bytecode == NULL) {
71
0
        goto error;
72
0
    }
73
6.90k
    a->a_linetable = PyBytes_FromStringAndSize(NULL, DEFAULT_CNOTAB_SIZE);
74
6.90k
    if (a->a_linetable == NULL) {
75
0
        goto error;
76
0
    }
77
6.90k
    a->a_except_table = PyBytes_FromStringAndSize(NULL, DEFAULT_LNOTAB_SIZE);
78
6.90k
    if (a->a_except_table == NULL) {
79
0
        goto error;
80
0
    }
81
6.90k
    return SUCCESS;
82
0
error:
83
0
    Py_XDECREF(a->a_bytecode);
84
0
    Py_XDECREF(a->a_linetable);
85
0
    Py_XDECREF(a->a_except_table);
86
0
    return ERROR;
87
6.90k
}
88
89
static void
90
assemble_free(struct assembler *a)
91
6.90k
{
92
6.90k
    Py_XDECREF(a->a_bytecode);
93
6.90k
    Py_XDECREF(a->a_linetable);
94
6.90k
    Py_XDECREF(a->a_except_table);
95
6.90k
}
96
97
static inline void
98
36.3k
write_except_byte(struct assembler *a, int byte) {
99
36.3k
    unsigned char *p = (unsigned char *) PyBytes_AS_STRING(a->a_except_table);
100
36.3k
    p[a->a_except_table_off++] = byte;
101
36.3k
}
102
103
10.7k
#define CONTINUATION_BIT 64
104
105
static void
106
assemble_emit_exception_table_item(struct assembler *a, int value, int msb)
107
25.6k
{
108
25.6k
    assert ((msb | 128) == 128);
109
25.6k
    assert(value >= 0 && value < (1 << 30));
110
25.6k
    if (value >= 1 << 24) {
111
0
        write_except_byte(a, (value >> 24) | CONTINUATION_BIT | msb);
112
0
        msb = 0;
113
0
    }
114
25.6k
    if (value >= 1 << 18) {
115
0
        write_except_byte(a, ((value >> 18)&0x3f) | CONTINUATION_BIT | msb);
116
0
        msb = 0;
117
0
    }
118
25.6k
    if (value >= 1 << 12) {
119
0
        write_except_byte(a, ((value >> 12)&0x3f) | CONTINUATION_BIT | msb);
120
0
        msb = 0;
121
0
    }
122
25.6k
    if (value >= 1 << 6) {
123
10.7k
        write_except_byte(a, ((value >> 6)&0x3f) | CONTINUATION_BIT | msb);
124
10.7k
        msb = 0;
125
10.7k
    }
126
25.6k
    write_except_byte(a, (value&0x3f) | msb);
127
25.6k
}
128
129
/* See InternalDocs/exception_handling.md for details of layout */
130
6.40k
#define MAX_SIZE_OF_ENTRY 20
131
132
static int
133
assemble_emit_exception_table_entry(struct assembler *a, int start, int end,
134
                                    int handler_offset,
135
                                    _PyExceptHandlerInfo *handler)
136
6.40k
{
137
6.40k
    Py_ssize_t len = PyBytes_GET_SIZE(a->a_except_table);
138
6.40k
    if (a->a_except_table_off + MAX_SIZE_OF_ENTRY >= len) {
139
2.03k
        RETURN_IF_ERROR(_PyBytes_Resize(&a->a_except_table, len * 2));
140
2.03k
    }
141
6.40k
    int size = end-start;
142
6.40k
    assert(end > start);
143
6.40k
    int target = handler_offset;
144
6.40k
    int depth = handler->h_startdepth - 1;
145
6.40k
    if (handler->h_preserve_lasti > 0) {
146
4.35k
        depth -= 1;
147
4.35k
    }
148
6.40k
    assert(depth >= 0);
149
6.40k
    int depth_lasti = (depth<<1) | handler->h_preserve_lasti;
150
6.40k
    assemble_emit_exception_table_item(a, start, (1<<7));
151
6.40k
    assemble_emit_exception_table_item(a, size, 0);
152
6.40k
    assemble_emit_exception_table_item(a, target, 0);
153
6.40k
    assemble_emit_exception_table_item(a, depth_lasti, 0);
154
6.40k
    return SUCCESS;
155
6.40k
}
156
157
static int
158
assemble_exception_table(struct assembler *a, instr_sequence *instrs)
159
6.90k
{
160
6.90k
    int ioffset = 0;
161
6.90k
    _PyExceptHandlerInfo handler;
162
6.90k
    handler.h_label = -1;
163
6.90k
    handler.h_startdepth = -1;
164
6.90k
    handler.h_preserve_lasti = -1;
165
6.90k
    int start = -1;
166
360k
    for (int i = 0; i < instrs->s_used; i++) {
167
353k
        instruction *instr = &instrs->s_instrs[i];
168
353k
        if (instr->i_except_handler_info.h_label != handler.h_label) {
169
11.9k
            if (handler.h_label >= 0) {
170
6.40k
                int handler_offset = instrs->s_instrs[handler.h_label].i_offset;
171
6.40k
                RETURN_IF_ERROR(
172
6.40k
                    assemble_emit_exception_table_entry(a, start, ioffset,
173
6.40k
                                                        handler_offset,
174
6.40k
                                                        &handler));
175
6.40k
            }
176
11.9k
            start = ioffset;
177
11.9k
            handler = instr->i_except_handler_info;
178
11.9k
        }
179
353k
        ioffset += instr_size(instr);
180
353k
    }
181
6.90k
    if (handler.h_label >= 0) {
182
0
        int handler_offset = instrs->s_instrs[handler.h_label].i_offset;
183
0
        RETURN_IF_ERROR(assemble_emit_exception_table_entry(a, start, ioffset,
184
0
                                                            handler_offset,
185
0
                                                            &handler));
186
0
    }
187
6.90k
    return SUCCESS;
188
6.90k
}
189
190
191
/* Code location emitting code. See locations.md for a description of the format. */
192
193
#define MSB 0x80
194
195
static void
196
write_location_byte(struct assembler* a, int val)
197
309k
{
198
309k
    PyBytes_AS_STRING(a->a_linetable)[a->a_location_off] = val&255;
199
309k
    a->a_location_off++;
200
309k
}
201
202
203
static uint8_t *
204
location_pointer(struct assembler* a)
205
477k
{
206
477k
    return (uint8_t *)PyBytes_AS_STRING(a->a_linetable) +
207
477k
        a->a_location_off;
208
477k
}
209
210
static void
211
write_location_first_byte(struct assembler* a, int code, int length)
212
270k
{
213
270k
    a->a_location_off += write_location_entry_start(
214
270k
        location_pointer(a), code, length);
215
270k
}
216
217
static void
218
write_location_varint(struct assembler* a, unsigned int val)
219
155k
{
220
155k
    uint8_t *ptr = location_pointer(a);
221
155k
    a->a_location_off += write_varint(ptr, val);
222
155k
}
223
224
225
static void
226
write_location_signed_varint(struct assembler* a, int val)
227
52.0k
{
228
52.0k
    uint8_t *ptr = location_pointer(a);
229
52.0k
    a->a_location_off += write_signed_varint(ptr, val);
230
52.0k
}
231
232
static void
233
write_location_info_short_form(struct assembler* a, int length, int column, int end_column)
234
119k
{
235
119k
    assert(length > 0 &&  length <= 8);
236
119k
    int column_low_bits = column & 7;
237
119k
    int column_group = column >> 3;
238
119k
    assert(column < 80);
239
119k
    assert(end_column >= column);
240
119k
    assert(end_column - column < 16);
241
119k
    write_location_first_byte(a, PY_CODE_LOCATION_INFO_SHORT0 + column_group, length);
242
119k
    write_location_byte(a, (column_low_bits << 4) | (end_column - column));
243
119k
}
244
245
static void
246
write_location_info_oneline_form(struct assembler* a, int length, int line_delta, int column, int end_column)
247
95.1k
{
248
95.1k
    assert(length > 0 &&  length <= 8);
249
95.1k
    assert(line_delta >= 0 && line_delta < 3);
250
95.1k
    assert(column < 128);
251
95.1k
    assert(end_column < 128);
252
95.1k
    write_location_first_byte(a, PY_CODE_LOCATION_INFO_ONE_LINE0 + line_delta, length);
253
95.1k
    write_location_byte(a, column);
254
95.1k
    write_location_byte(a, end_column);
255
95.1k
}
256
257
static void
258
write_location_info_long_form(struct assembler* a, location loc, int length)
259
51.7k
{
260
51.7k
    assert(length > 0 &&  length <= 8);
261
51.7k
    write_location_first_byte(a, PY_CODE_LOCATION_INFO_LONG, length);
262
51.7k
    write_location_signed_varint(a, loc.lineno - a->a_lineno);
263
51.7k
    assert(loc.end_lineno >= loc.lineno);
264
51.7k
    write_location_varint(a, loc.end_lineno - loc.lineno);
265
51.7k
    write_location_varint(a, loc.col_offset + 1);
266
51.7k
    write_location_varint(a, loc.end_col_offset + 1);
267
51.7k
}
268
269
static void
270
write_location_info_none(struct assembler* a, int length)
271
3.98k
{
272
3.98k
    write_location_first_byte(a, PY_CODE_LOCATION_INFO_NONE, length);
273
3.98k
}
274
275
static void
276
write_location_info_no_column(struct assembler* a, int length, int line_delta)
277
380
{
278
380
    write_location_first_byte(a, PY_CODE_LOCATION_INFO_NO_COLUMNS, length);
279
380
    write_location_signed_varint(a, line_delta);
280
380
}
281
282
270k
#define THEORETICAL_MAX_ENTRY_SIZE 25 /* 1 + 6 + 6 + 6 + 6 */
283
284
285
static int
286
write_location_info_entry(struct assembler* a, location loc, int isize)
287
270k
{
288
270k
    Py_ssize_t len = PyBytes_GET_SIZE(a->a_linetable);
289
270k
    if (a->a_location_off + THEORETICAL_MAX_ENTRY_SIZE >= len) {
290
12.3k
        assert(len > THEORETICAL_MAX_ENTRY_SIZE);
291
12.3k
        RETURN_IF_ERROR(_PyBytes_Resize(&a->a_linetable, len*2));
292
12.3k
    }
293
270k
    if (loc.lineno == NO_LOCATION.lineno) {
294
3.98k
        write_location_info_none(a, isize);
295
3.98k
        return SUCCESS;
296
3.98k
    }
297
266k
    int line_delta = loc.lineno - a->a_lineno;
298
266k
    int column = loc.col_offset;
299
266k
    int end_column = loc.end_col_offset;
300
266k
    if (column < 0 || end_column < 0) {
301
380
        if (loc.end_lineno == loc.lineno || loc.end_lineno < 0) {
302
380
            write_location_info_no_column(a, isize, line_delta);
303
380
            a->a_lineno = loc.lineno;
304
380
            return SUCCESS;
305
380
        }
306
380
    }
307
266k
    else if (loc.end_lineno == loc.lineno) {
308
237k
        if (line_delta == 0 && column < 80 && end_column - column < 16 && end_column >= column) {
309
119k
            write_location_info_short_form(a, isize, column, end_column);
310
119k
            return SUCCESS;
311
119k
        }
312
118k
        if (line_delta >= 0 && line_delta < 3 && column < 128 && end_column < 128) {
313
95.1k
            write_location_info_oneline_form(a, isize, line_delta, column, end_column);
314
95.1k
            a->a_lineno = loc.lineno;
315
95.1k
            return SUCCESS;
316
95.1k
        }
317
118k
    }
318
51.7k
    write_location_info_long_form(a, loc, isize);
319
51.7k
    a->a_lineno = loc.lineno;
320
51.7k
    return SUCCESS;
321
266k
}
322
323
static int
324
assemble_emit_location(struct assembler* a, location loc, int isize)
325
249k
{
326
249k
    if (isize == 0) {
327
5.45k
        return SUCCESS;
328
5.45k
    }
329
270k
    while (isize > 8) {
330
26.5k
        RETURN_IF_ERROR(write_location_info_entry(a, loc, 8));
331
26.5k
        isize -= 8;
332
26.5k
    }
333
243k
    return write_location_info_entry(a, loc, isize);
334
243k
}
335
336
static int
337
assemble_location_info(struct assembler *a, instr_sequence *instrs,
338
                       int firstlineno)
339
6.90k
{
340
6.90k
    a->a_lineno = firstlineno;
341
6.90k
    location loc = NO_LOCATION;
342
360k
    for (int i = instrs->s_used-1; i >= 0; i--) {
343
353k
        instruction *instr = &instrs->s_instrs[i];
344
353k
        if (same_location(instr->i_loc, NEXT_LOCATION)) {
345
9
            if (IS_TERMINATOR_OPCODE(instr->i_opcode)) {
346
0
                instr->i_loc = NO_LOCATION;
347
0
            }
348
9
            else {
349
9
                assert(i < instrs->s_used-1);
350
9
                instr->i_loc = instr[1].i_loc;
351
9
            }
352
9
        }
353
353k
    }
354
6.90k
    int size = 0;
355
360k
    for (int i = 0; i < instrs->s_used; i++) {
356
353k
        instruction *instr = &instrs->s_instrs[i];
357
353k
        if (!same_location(loc, instr->i_loc)) {
358
242k
                RETURN_IF_ERROR(assemble_emit_location(a, loc, size));
359
242k
                loc = instr->i_loc;
360
242k
                size = 0;
361
242k
        }
362
353k
        size += instr_size(instr);
363
353k
    }
364
6.90k
    RETURN_IF_ERROR(assemble_emit_location(a, loc, size));
365
6.90k
    return SUCCESS;
366
6.90k
}
367
368
static void
369
write_instr(_Py_CODEUNIT *codestr, instruction *instr, int ilen)
370
353k
{
371
353k
    int opcode = instr->i_opcode;
372
353k
    assert(!IS_PSEUDO_INSTR(opcode));
373
353k
    int oparg = instr->i_oparg;
374
353k
    assert(OPCODE_HAS_ARG(opcode) || oparg == 0);
375
353k
    int caches = _PyOpcode_Caches[opcode];
376
353k
    switch (ilen - caches) {
377
0
        case 4:
378
0
            codestr->op.code = EXTENDED_ARG;
379
0
            codestr->op.arg = (oparg >> 24) & 0xFF;
380
0
            codestr++;
381
0
            _Py_FALLTHROUGH;
382
0
        case 3:
383
0
            codestr->op.code = EXTENDED_ARG;
384
0
            codestr->op.arg = (oparg >> 16) & 0xFF;
385
0
            codestr++;
386
0
            _Py_FALLTHROUGH;
387
6.71k
        case 2:
388
6.71k
            codestr->op.code = EXTENDED_ARG;
389
6.71k
            codestr->op.arg = (oparg >> 8) & 0xFF;
390
6.71k
            codestr++;
391
6.71k
            _Py_FALLTHROUGH;
392
353k
        case 1:
393
353k
            codestr->op.code = opcode;
394
353k
            codestr->op.arg = oparg & 0xFF;
395
353k
            codestr++;
396
353k
            break;
397
0
        default:
398
0
            Py_UNREACHABLE();
399
353k
    }
400
764k
    while (caches--) {
401
410k
        codestr->op.code = CACHE;
402
410k
        codestr->op.arg = 0;
403
410k
        codestr++;
404
410k
    }
405
353k
}
406
407
/* assemble_emit_instr()
408
   Extend the bytecode with a new instruction.
409
   Update lnotab if necessary.
410
*/
411
412
static int
413
assemble_emit_instr(struct assembler *a, instruction *instr)
414
353k
{
415
353k
    Py_ssize_t len = PyBytes_GET_SIZE(a->a_bytecode);
416
353k
    _Py_CODEUNIT *code;
417
418
353k
    int size = instr_size(instr);
419
353k
    if (a->a_offset + size >= len / (int)sizeof(_Py_CODEUNIT)) {
420
5.16k
        if (len > PY_SSIZE_T_MAX / 2) {
421
0
            return ERROR;
422
0
        }
423
5.16k
        RETURN_IF_ERROR(_PyBytes_Resize(&a->a_bytecode, len * 2));
424
5.16k
    }
425
353k
    code = (_Py_CODEUNIT *)PyBytes_AS_STRING(a->a_bytecode) + a->a_offset;
426
353k
    a->a_offset += size;
427
353k
    write_instr(code, instr, size);
428
353k
    return SUCCESS;
429
353k
}
430
431
static int
432
assemble_emit(struct assembler *a, instr_sequence *instrs,
433
              int first_lineno, PyObject *const_cache)
434
6.90k
{
435
6.90k
    RETURN_IF_ERROR(assemble_init(a, first_lineno));
436
437
360k
    for (int i = 0; i < instrs->s_used; i++) {
438
353k
        instruction *instr = &instrs->s_instrs[i];
439
353k
        RETURN_IF_ERROR(assemble_emit_instr(a, instr));
440
353k
    }
441
442
6.90k
    RETURN_IF_ERROR(assemble_location_info(a, instrs, a->a_lineno));
443
444
6.90k
    RETURN_IF_ERROR(assemble_exception_table(a, instrs));
445
446
6.90k
    RETURN_IF_ERROR(_PyBytes_Resize(&a->a_except_table, a->a_except_table_off));
447
6.90k
    RETURN_IF_ERROR(_PyCompile_ConstCacheMergeOne(const_cache, &a->a_except_table));
448
449
6.90k
    RETURN_IF_ERROR(_PyBytes_Resize(&a->a_linetable, a->a_location_off));
450
6.90k
    RETURN_IF_ERROR(_PyCompile_ConstCacheMergeOne(const_cache, &a->a_linetable));
451
452
6.90k
    RETURN_IF_ERROR(_PyBytes_Resize(&a->a_bytecode, a->a_offset * sizeof(_Py_CODEUNIT)));
453
6.90k
    RETURN_IF_ERROR(_PyCompile_ConstCacheMergeOne(const_cache, &a->a_bytecode));
454
6.90k
    return SUCCESS;
455
6.90k
}
456
457
static PyObject *
458
dict_keys_inorder(PyObject *dict, Py_ssize_t offset)
459
6.90k
{
460
6.90k
    PyObject *tuple, *k, *v;
461
6.90k
    Py_ssize_t pos = 0, size = PyDict_GET_SIZE(dict);
462
463
6.90k
    tuple = PyTuple_New(size);
464
6.90k
    if (tuple == NULL)
465
0
        return NULL;
466
52.2k
    while (PyDict_Next(dict, &pos, &k, &v)) {
467
45.3k
        Py_ssize_t i = PyLong_AsSsize_t(v);
468
45.3k
        if (i == -1 && PyErr_Occurred()) {
469
0
            Py_DECREF(tuple);
470
0
            return NULL;
471
0
        }
472
45.3k
        assert((i - offset) < size);
473
45.3k
        assert((i - offset) >= 0);
474
45.3k
        PyTuple_SET_ITEM(tuple, i - offset, Py_NewRef(k));
475
45.3k
    }
476
6.90k
    return tuple;
477
6.90k
}
478
479
// This is in codeobject.c.
480
extern void _Py_set_localsplus_info(int, PyObject *, unsigned char,
481
                                   PyObject *, PyObject *);
482
483
static int
484
compute_localsplus_info(_PyCompile_CodeUnitMetadata *umd, int nlocalsplus,
485
                        int flags, PyObject *names, PyObject *kinds)
486
6.90k
{
487
6.90k
    PyObject *k, *v;
488
6.90k
    Py_ssize_t pos = 0;
489
490
    // Set the locals kinds.  Arg vars fill the first portion of the list.
491
6.90k
    struct {
492
6.90k
        int count;
493
6.90k
        _PyLocals_Kind kind;
494
6.90k
    }  argvarkinds[6] = {
495
6.90k
        {(int)umd->u_posonlyargcount, CO_FAST_ARG_POS},
496
6.90k
        {(int)umd->u_argcount, CO_FAST_ARG_POS | CO_FAST_ARG_KW},
497
6.90k
        {(int)umd->u_kwonlyargcount, CO_FAST_ARG_KW},
498
6.90k
        {!!(flags & CO_VARARGS), CO_FAST_ARG_VAR | CO_FAST_ARG_POS},
499
6.90k
        {!!(flags & CO_VARKEYWORDS), CO_FAST_ARG_VAR | CO_FAST_ARG_KW},
500
6.90k
        {-1, 0},  // the remaining local vars
501
6.90k
    };
502
6.90k
    int max = 0;
503
48.3k
    for (int i = 0; i < 6; i++) {
504
41.4k
        max = argvarkinds[i].count < 0
505
41.4k
            ? INT_MAX
506
41.4k
            : max + argvarkinds[i].count;
507
60.7k
        while (pos < max && PyDict_Next(umd->u_varnames, &pos, &k, &v)) {
508
19.2k
            int offset = PyLong_AsInt(v);
509
19.2k
            if (offset == -1 && PyErr_Occurred()) {
510
0
                return ERROR;
511
0
            }
512
19.2k
            assert(offset >= 0);
513
19.2k
            assert(offset < nlocalsplus);
514
515
19.2k
            _PyLocals_Kind kind = CO_FAST_LOCAL | argvarkinds[i].kind;
516
517
19.2k
            int has_key = PyDict_Contains(umd->u_fasthidden, k);
518
19.2k
            RETURN_IF_ERROR(has_key);
519
19.2k
            if (has_key) {
520
18
                kind |= CO_FAST_HIDDEN;
521
18
            }
522
523
19.2k
            has_key = PyDict_Contains(umd->u_cellvars, k);
524
19.2k
            RETURN_IF_ERROR(has_key);
525
19.2k
            if (has_key) {
526
419
                kind |= CO_FAST_CELL;
527
419
            }
528
529
19.2k
            _Py_set_localsplus_info(offset, k, kind, names, kinds);
530
19.2k
        }
531
41.4k
    }
532
6.90k
    int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames);
533
534
    // This counter mirrors the fix done in fix_cell_offsets().
535
6.90k
    int numdropped = 0, cellvar_offset = -1;
536
6.90k
    pos = 0;
537
8.30k
    while (PyDict_Next(umd->u_cellvars, &pos, &k, &v)) {
538
1.39k
        int has_name = PyDict_Contains(umd->u_varnames, k);
539
1.39k
        RETURN_IF_ERROR(has_name);
540
1.39k
        if (has_name) {
541
            // Skip cells that are already covered by locals.
542
419
            numdropped += 1;
543
419
            continue;
544
419
        }
545
546
973
        cellvar_offset = PyLong_AsInt(v);
547
973
        if (cellvar_offset == -1 && PyErr_Occurred()) {
548
0
            return ERROR;
549
0
        }
550
973
        assert(cellvar_offset >= 0);
551
973
        cellvar_offset += nlocals - numdropped;
552
973
        assert(cellvar_offset < nlocalsplus);
553
973
        _Py_set_localsplus_info(cellvar_offset, k, CO_FAST_CELL, names, kinds);
554
973
    }
555
556
6.90k
    pos = 0;
557
8.11k
    while (PyDict_Next(umd->u_freevars, &pos, &k, &v)) {
558
1.20k
        int offset = PyLong_AsInt(v);
559
1.20k
        if (offset == -1 && PyErr_Occurred()) {
560
0
            return ERROR;
561
0
        }
562
1.20k
        assert(offset >= 0);
563
1.20k
        offset += nlocals - numdropped;
564
1.20k
        assert(offset < nlocalsplus);
565
        /* XXX If the assertion below fails it is most likely because a freevar
566
           was added to u_freevars with the wrong index due to not taking into
567
           account cellvars already present, see gh-128632. */
568
1.20k
        assert(offset > cellvar_offset);
569
1.20k
        _Py_set_localsplus_info(offset, k, CO_FAST_FREE, names, kinds);
570
1.20k
    }
571
6.90k
    return SUCCESS;
572
6.90k
}
573
574
static PyCodeObject *
575
makecode(_PyCompile_CodeUnitMetadata *umd, struct assembler *a, PyObject *const_cache,
576
         PyObject *constslist, int maxdepth, int nlocalsplus, int code_flags,
577
         PyObject *filename)
578
6.90k
{
579
6.90k
    PyCodeObject *co = NULL;
580
6.90k
    PyObject *names = NULL;
581
6.90k
    PyObject *consts = NULL;
582
6.90k
    PyObject *localsplusnames = NULL;
583
6.90k
    PyObject *localspluskinds = NULL;
584
6.90k
    names = dict_keys_inorder(umd->u_names, 0);
585
6.90k
    if (!names) {
586
0
        goto error;
587
0
    }
588
6.90k
    if (_PyCompile_ConstCacheMergeOne(const_cache, &names) < 0) {
589
0
        goto error;
590
0
    }
591
592
6.90k
    consts = PyList_AsTuple(constslist); /* PyCode_New requires a tuple */
593
6.90k
    if (consts == NULL) {
594
0
        goto error;
595
0
    }
596
6.90k
    if (_PyCompile_ConstCacheMergeOne(const_cache, &consts) < 0) {
597
0
        goto error;
598
0
    }
599
600
6.90k
    assert(umd->u_posonlyargcount < INT_MAX);
601
6.90k
    assert(umd->u_argcount < INT_MAX);
602
6.90k
    assert(umd->u_kwonlyargcount < INT_MAX);
603
6.90k
    int posonlyargcount = (int)umd->u_posonlyargcount;
604
6.90k
    int posorkwargcount = (int)umd->u_argcount;
605
6.90k
    assert(INT_MAX - posonlyargcount - posorkwargcount > 0);
606
6.90k
    int kwonlyargcount = (int)umd->u_kwonlyargcount;
607
608
6.90k
    localsplusnames = PyTuple_New(nlocalsplus);
609
6.90k
    if (localsplusnames == NULL) {
610
0
        goto error;
611
0
    }
612
6.90k
    localspluskinds = PyBytes_FromStringAndSize(NULL, nlocalsplus);
613
6.90k
    if (localspluskinds == NULL) {
614
0
        goto error;
615
0
    }
616
6.90k
    if (compute_localsplus_info(
617
6.90k
            umd, nlocalsplus, code_flags,
618
6.90k
            localsplusnames, localspluskinds) == ERROR)
619
0
    {
620
0
        goto error;
621
0
    }
622
623
6.90k
    struct _PyCodeConstructor con = {
624
6.90k
        .filename = filename,
625
6.90k
        .name = umd->u_name,
626
6.90k
        .qualname = umd->u_qualname ? umd->u_qualname : umd->u_name,
627
6.90k
        .flags = code_flags,
628
629
6.90k
        .code = a->a_bytecode,
630
6.90k
        .firstlineno = umd->u_firstlineno,
631
6.90k
        .linetable = a->a_linetable,
632
633
6.90k
        .consts = consts,
634
6.90k
        .names = names,
635
636
6.90k
        .localsplusnames = localsplusnames,
637
6.90k
        .localspluskinds = localspluskinds,
638
639
6.90k
        .argcount = posonlyargcount + posorkwargcount,
640
6.90k
        .posonlyargcount = posonlyargcount,
641
6.90k
        .kwonlyargcount = kwonlyargcount,
642
643
6.90k
        .stacksize = maxdepth,
644
645
6.90k
        .exceptiontable = a->a_except_table,
646
6.90k
    };
647
648
6.90k
   if (_PyCode_Validate(&con) < 0) {
649
0
        goto error;
650
0
    }
651
652
6.90k
    if (_PyCompile_ConstCacheMergeOne(const_cache, &localsplusnames) < 0) {
653
0
        goto error;
654
0
    }
655
6.90k
    con.localsplusnames = localsplusnames;
656
657
6.90k
    co = _PyCode_New(&con);
658
6.90k
    if (co == NULL) {
659
0
        goto error;
660
0
    }
661
662
6.90k
error:
663
6.90k
    Py_XDECREF(names);
664
6.90k
    Py_XDECREF(consts);
665
6.90k
    Py_XDECREF(localsplusnames);
666
6.90k
    Py_XDECREF(localspluskinds);
667
6.90k
    return co;
668
6.90k
}
669
670
671
// The offset (in code units) of the END_SEND from the SEND in the `yield from` sequence.
672
0
#define END_SEND_OFFSET 5
673
674
static int
675
resolve_jump_offsets(instr_sequence *instrs)
676
6.90k
{
677
    /* Compute the size of each instruction and fixup jump args.
678
     * Replace instruction index with position in bytecode.
679
     */
680
681
360k
    for (int i = 0; i < instrs->s_used; i++) {
682
353k
        instruction *instr = &instrs->s_instrs[i];
683
353k
        if (OPCODE_HAS_JUMP(instr->i_opcode)) {
684
19.8k
            instr->i_target = instr->i_oparg;
685
19.8k
        }
686
353k
    }
687
688
6.90k
    int extended_arg_recompile;
689
690
7.16k
    do {
691
7.16k
        int totsize = 0;
692
456k
        for (int i = 0; i < instrs->s_used; i++) {
693
449k
            instruction *instr = &instrs->s_instrs[i];
694
449k
            instr->i_offset = totsize;
695
449k
            int isize = instr_size(instr);
696
449k
            totsize += isize;
697
449k
        }
698
7.16k
        extended_arg_recompile = 0;
699
700
7.16k
        int offset = 0;
701
456k
        for (int i = 0; i < instrs->s_used; i++) {
702
449k
            instruction *instr = &instrs->s_instrs[i];
703
449k
            int isize = instr_size(instr);
704
            /* jump offsets are computed relative to
705
             * the instruction pointer after fetching
706
             * the jump instruction.
707
             */
708
449k
            offset += isize;
709
449k
            if (OPCODE_HAS_JUMP(instr->i_opcode)) {
710
27.5k
                instruction *target = &instrs->s_instrs[instr->i_target];
711
27.5k
                instr->i_oparg = target->i_offset;
712
27.5k
                if (instr->i_opcode == END_ASYNC_FOR) {
713
                    // sys.monitoring needs to be able to find the matching END_SEND
714
                    // but the target is the SEND, so we adjust it here.
715
0
                    instr->i_oparg = offset - instr->i_oparg - END_SEND_OFFSET;
716
0
                }
717
27.5k
                else if (instr->i_oparg < offset) {
718
5.77k
                    assert(IS_BACKWARDS_JUMP_OPCODE(instr->i_opcode));
719
5.77k
                    instr->i_oparg = offset - instr->i_oparg;
720
5.77k
                }
721
21.8k
                else {
722
21.8k
                    assert(!IS_BACKWARDS_JUMP_OPCODE(instr->i_opcode));
723
21.8k
                    instr->i_oparg = instr->i_oparg - offset;
724
21.8k
                }
725
27.5k
                if (instr_size(instr) != isize) {
726
3.04k
                    extended_arg_recompile = 1;
727
3.04k
                }
728
27.5k
            }
729
449k
        }
730
    /* XXX: This is an awful hack that could hurt performance, but
731
        on the bright side it should work until we come up
732
        with a better solution.
733
734
        The issue is that in the first loop instr_size() is
735
        called, and it requires i_oparg be set appropriately.
736
        There is a bootstrap problem because i_oparg is
737
        calculated in the second loop above.
738
739
        So we loop until we stop seeing new EXTENDED_ARGs.
740
        The only EXTENDED_ARGs that could be popping up are
741
        ones in jump instructions.  So this should converge
742
        fairly quickly.
743
    */
744
7.16k
    } while (extended_arg_recompile);
745
6.90k
    return SUCCESS;
746
6.90k
}
747
748
static int
749
resolve_unconditional_jumps(instr_sequence *instrs)
750
6.90k
{
751
    /* Resolve directions of unconditional jumps */
752
753
360k
    for (int i = 0; i < instrs->s_used; i++) {
754
353k
        instruction *instr = &instrs->s_instrs[i];
755
353k
        bool is_forward = (instr->i_oparg > i);
756
353k
        switch(instr->i_opcode) {
757
3.86k
            case JUMP:
758
3.86k
                assert(is_pseudo_target(JUMP, JUMP_FORWARD));
759
3.86k
                assert(is_pseudo_target(JUMP, JUMP_BACKWARD));
760
3.86k
                instr->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
761
3.86k
                break;
762
1.89k
            case JUMP_NO_INTERRUPT:
763
1.89k
                assert(is_pseudo_target(JUMP_NO_INTERRUPT, JUMP_FORWARD));
764
1.89k
                assert(is_pseudo_target(JUMP_NO_INTERRUPT, JUMP_BACKWARD_NO_INTERRUPT));
765
1.89k
                instr->i_opcode = is_forward ?
766
1.46k
                    JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
767
1.89k
                break;
768
347k
            default:
769
347k
                if (OPCODE_HAS_JUMP(instr->i_opcode) &&
770
14.0k
                    IS_PSEUDO_INSTR(instr->i_opcode)) {
771
0
                    Py_UNREACHABLE();
772
0
                }
773
353k
        }
774
353k
    }
775
6.90k
    return SUCCESS;
776
6.90k
}
777
778
PyCodeObject *
779
_PyAssemble_MakeCodeObject(_PyCompile_CodeUnitMetadata *umd, PyObject *const_cache,
780
                           PyObject *consts, int maxdepth, instr_sequence *instrs,
781
                           int nlocalsplus, int code_flags, PyObject *filename)
782
6.90k
{
783
6.90k
    if (_PyInstructionSequence_ApplyLabelMap(instrs) < 0) {
784
0
        return NULL;
785
0
    }
786
6.90k
    if (resolve_unconditional_jumps(instrs) < 0) {
787
0
        return NULL;
788
0
    }
789
6.90k
    if (resolve_jump_offsets(instrs) < 0) {
790
0
        return NULL;
791
0
    }
792
6.90k
    PyCodeObject *co = NULL;
793
794
6.90k
    struct assembler a;
795
6.90k
    int res = assemble_emit(&a, instrs, umd->u_firstlineno, const_cache);
796
6.90k
    if (res == SUCCESS) {
797
6.90k
        co = makecode(umd, &a, const_cache, consts, maxdepth, nlocalsplus,
798
6.90k
                      code_flags, filename);
799
6.90k
    }
800
6.90k
    assemble_free(&a);
801
6.90k
    return co;
802
6.90k
}