Coverage Report

Created: 2025-09-05 07:10

/src/cpython/Python/specialize.c
Line
Count
Source (jump to first uncovered line)
1
#include "Python.h"
2
3
#include "opcode.h"
4
5
#include "pycore_code.h"
6
#include "pycore_critical_section.h"
7
#include "pycore_descrobject.h"   // _PyMethodWrapper_Type
8
#include "pycore_dict.h"          // DICT_KEYS_UNICODE
9
#include "pycore_function.h"      // _PyFunction_GetVersionForCurrentState()
10
#include "pycore_interpframe.h"   // FRAME_SPECIALS_SIZE
11
#include "pycore_list.h"          // _PyListIterObject
12
#include "pycore_long.h"          // _PyLong_IsNonNegativeCompact()
13
#include "pycore_moduleobject.h"
14
#include "pycore_object.h"
15
#include "pycore_opcode_metadata.h" // _PyOpcode_Caches
16
#include "pycore_uop_metadata.h"    // _PyOpcode_uop_name
17
#include "pycore_uop_ids.h"       // MAX_UOP_ID
18
#include "pycore_opcode_utils.h"  // RESUME_AT_FUNC_START
19
#include "pycore_pylifecycle.h"   // _PyOS_URandomNonblock()
20
#include "pycore_runtime.h"       // _Py_ID()
21
#include "pycore_unicodeobject.h" // _PyUnicodeASCIIIter_Type
22
23
#include <stdlib.h> // rand()
24
25
extern const char *_PyUOpName(int index);
26
27
/* For guidance on adding or extending families of instructions see
28
 * InternalDocs/interpreter.md `Specialization` section.
29
 */
30
31
#ifdef Py_STATS
32
GCStats _py_gc_stats[NUM_GENERATIONS] = { 0 };
33
static PyStats _Py_stats_struct = { .gc_stats = _py_gc_stats };
34
PyStats *_Py_stats = NULL;
35
36
#if PYSTATS_MAX_UOP_ID < MAX_UOP_ID
37
#error "Not enough space allocated for pystats. Increase PYSTATS_MAX_UOP_ID to at least MAX_UOP_ID"
38
#endif
39
40
#define ADD_STAT_TO_DICT(res, field) \
41
    do { \
42
        PyObject *val = PyLong_FromUnsignedLongLong(stats->field); \
43
        if (val == NULL) { \
44
            Py_DECREF(res); \
45
            return NULL; \
46
        } \
47
        if (PyDict_SetItemString(res, #field, val) == -1) { \
48
            Py_DECREF(res); \
49
            Py_DECREF(val); \
50
            return NULL; \
51
        } \
52
        Py_DECREF(val); \
53
    } while(0);
54
55
static PyObject*
56
stats_to_dict(SpecializationStats *stats)
57
{
58
    PyObject *res = PyDict_New();
59
    if (res == NULL) {
60
        return NULL;
61
    }
62
    ADD_STAT_TO_DICT(res, success);
63
    ADD_STAT_TO_DICT(res, failure);
64
    ADD_STAT_TO_DICT(res, hit);
65
    ADD_STAT_TO_DICT(res, deferred);
66
    ADD_STAT_TO_DICT(res, miss);
67
    ADD_STAT_TO_DICT(res, deopt);
68
    PyObject *failure_kinds = PyTuple_New(SPECIALIZATION_FAILURE_KINDS);
69
    if (failure_kinds == NULL) {
70
        Py_DECREF(res);
71
        return NULL;
72
    }
73
    for (int i = 0; i < SPECIALIZATION_FAILURE_KINDS; i++) {
74
        PyObject *stat = PyLong_FromUnsignedLongLong(stats->failure_kinds[i]);
75
        if (stat == NULL) {
76
            Py_DECREF(res);
77
            Py_DECREF(failure_kinds);
78
            return NULL;
79
        }
80
        PyTuple_SET_ITEM(failure_kinds, i, stat);
81
    }
82
    if (PyDict_SetItemString(res, "failure_kinds", failure_kinds)) {
83
        Py_DECREF(res);
84
        Py_DECREF(failure_kinds);
85
        return NULL;
86
    }
87
    Py_DECREF(failure_kinds);
88
    return res;
89
}
90
#undef ADD_STAT_TO_DICT
91
92
static int
93
add_stat_dict(
94
    PyObject *res,
95
    int opcode,
96
    const char *name) {
97
98
    SpecializationStats *stats = &_Py_stats_struct.opcode_stats[opcode].specialization;
99
    PyObject *d = stats_to_dict(stats);
100
    if (d == NULL) {
101
        return -1;
102
    }
103
    int err = PyDict_SetItemString(res, name, d);
104
    Py_DECREF(d);
105
    return err;
106
}
107
108
PyObject*
109
_Py_GetSpecializationStats(void) {
110
    PyObject *stats = PyDict_New();
111
    if (stats == NULL) {
112
        return NULL;
113
    }
114
    int err = 0;
115
    err += add_stat_dict(stats, CONTAINS_OP, "contains_op");
116
    err += add_stat_dict(stats, LOAD_SUPER_ATTR, "load_super_attr");
117
    err += add_stat_dict(stats, LOAD_ATTR, "load_attr");
118
    err += add_stat_dict(stats, LOAD_GLOBAL, "load_global");
119
    err += add_stat_dict(stats, STORE_SUBSCR, "store_subscr");
120
    err += add_stat_dict(stats, STORE_ATTR, "store_attr");
121
    err += add_stat_dict(stats, JUMP_BACKWARD, "jump_backward");
122
    err += add_stat_dict(stats, CALL, "call");
123
    err += add_stat_dict(stats, CALL_KW, "call_kw");
124
    err += add_stat_dict(stats, BINARY_OP, "binary_op");
125
    err += add_stat_dict(stats, COMPARE_OP, "compare_op");
126
    err += add_stat_dict(stats, UNPACK_SEQUENCE, "unpack_sequence");
127
    err += add_stat_dict(stats, FOR_ITER, "for_iter");
128
    err += add_stat_dict(stats, TO_BOOL, "to_bool");
129
    err += add_stat_dict(stats, SEND, "send");
130
    if (err < 0) {
131
        Py_DECREF(stats);
132
        return NULL;
133
    }
134
    return stats;
135
}
136
137
138
#define PRINT_STAT(i, field) \
139
    if (stats[i].field) { \
140
        fprintf(out, "    opcode[%s]." #field " : %" PRIu64 "\n", _PyOpcode_OpName[i], stats[i].field); \
141
    }
142
143
static void
144
print_spec_stats(FILE *out, OpcodeStats *stats)
145
{
146
    /* Mark some opcodes as specializable for stats,
147
     * even though we don't specialize them yet. */
148
    fprintf(out, "opcode[BINARY_SLICE].specializable : 1\n");
149
    fprintf(out, "opcode[STORE_SLICE].specializable : 1\n");
150
    fprintf(out, "opcode[GET_ITER].specializable : 1\n");
151
    for (int i = 0; i < 256; i++) {
152
        if (_PyOpcode_Caches[i]) {
153
            /* Ignore jumps as they cannot be specialized */
154
            switch (i) {
155
                case POP_JUMP_IF_FALSE:
156
                case POP_JUMP_IF_TRUE:
157
                case POP_JUMP_IF_NONE:
158
                case POP_JUMP_IF_NOT_NONE:
159
                case JUMP_BACKWARD:
160
                    break;
161
                default:
162
                    fprintf(out, "opcode[%s].specializable : 1\n", _PyOpcode_OpName[i]);
163
            }
164
        }
165
        PRINT_STAT(i, specialization.success);
166
        PRINT_STAT(i, specialization.failure);
167
        PRINT_STAT(i, specialization.hit);
168
        PRINT_STAT(i, specialization.deferred);
169
        PRINT_STAT(i, specialization.miss);
170
        PRINT_STAT(i, specialization.deopt);
171
        PRINT_STAT(i, execution_count);
172
        for (int j = 0; j < SPECIALIZATION_FAILURE_KINDS; j++) {
173
            uint64_t val = stats[i].specialization.failure_kinds[j];
174
            if (val) {
175
                fprintf(out, "    opcode[%s].specialization.failure_kinds[%d] : %"
176
                    PRIu64 "\n", _PyOpcode_OpName[i], j, val);
177
            }
178
        }
179
        for (int j = 0; j < 256; j++) {
180
            if (stats[i].pair_count[j]) {
181
                fprintf(out, "opcode[%s].pair_count[%s] : %" PRIu64 "\n",
182
                        _PyOpcode_OpName[i], _PyOpcode_OpName[j], stats[i].pair_count[j]);
183
            }
184
        }
185
    }
186
}
187
#undef PRINT_STAT
188
189
190
static void
191
print_call_stats(FILE *out, CallStats *stats)
192
{
193
    fprintf(out, "Calls to PyEval_EvalDefault: %" PRIu64 "\n", stats->pyeval_calls);
194
    fprintf(out, "Calls to Python functions inlined: %" PRIu64 "\n", stats->inlined_py_calls);
195
    fprintf(out, "Frames pushed: %" PRIu64 "\n", stats->frames_pushed);
196
    fprintf(out, "Frame objects created: %" PRIu64 "\n", stats->frame_objects_created);
197
    for (int i = 0; i < EVAL_CALL_KINDS; i++) {
198
        fprintf(out, "Calls via PyEval_EvalFrame[%d] : %" PRIu64 "\n", i, stats->eval_calls[i]);
199
    }
200
}
201
202
static void
203
print_object_stats(FILE *out, ObjectStats *stats)
204
{
205
    fprintf(out, "Object allocations from freelist: %" PRIu64 "\n", stats->from_freelist);
206
    fprintf(out, "Object frees to freelist: %" PRIu64 "\n", stats->to_freelist);
207
    fprintf(out, "Object allocations: %" PRIu64 "\n", stats->allocations);
208
    fprintf(out, "Object allocations to 512 bytes: %" PRIu64 "\n", stats->allocations512);
209
    fprintf(out, "Object allocations to 4 kbytes: %" PRIu64 "\n", stats->allocations4k);
210
    fprintf(out, "Object allocations over 4 kbytes: %" PRIu64 "\n", stats->allocations_big);
211
    fprintf(out, "Object frees: %" PRIu64 "\n", stats->frees);
212
    fprintf(out, "Object inline values: %" PRIu64 "\n", stats->inline_values);
213
    fprintf(out, "Object interpreter mortal increfs: %" PRIu64 "\n", stats->interpreter_increfs);
214
    fprintf(out, "Object interpreter mortal decrefs: %" PRIu64 "\n", stats->interpreter_decrefs);
215
    fprintf(out, "Object mortal increfs: %" PRIu64 "\n", stats->increfs);
216
    fprintf(out, "Object mortal decrefs: %" PRIu64 "\n", stats->decrefs);
217
    fprintf(out, "Object interpreter immortal increfs: %" PRIu64 "\n", stats->interpreter_immortal_increfs);
218
    fprintf(out, "Object interpreter immortal decrefs: %" PRIu64 "\n", stats->interpreter_immortal_decrefs);
219
    fprintf(out, "Object immortal increfs: %" PRIu64 "\n", stats->immortal_increfs);
220
    fprintf(out, "Object immortal decrefs: %" PRIu64 "\n", stats->immortal_decrefs);
221
    fprintf(out, "Object materialize dict (on request): %" PRIu64 "\n", stats->dict_materialized_on_request);
222
    fprintf(out, "Object materialize dict (new key): %" PRIu64 "\n", stats->dict_materialized_new_key);
223
    fprintf(out, "Object materialize dict (too big): %" PRIu64 "\n", stats->dict_materialized_too_big);
224
    fprintf(out, "Object materialize dict (str subclass): %" PRIu64 "\n", stats->dict_materialized_str_subclass);
225
    fprintf(out, "Object method cache hits: %" PRIu64 "\n", stats->type_cache_hits);
226
    fprintf(out, "Object method cache misses: %" PRIu64 "\n", stats->type_cache_misses);
227
    fprintf(out, "Object method cache collisions: %" PRIu64 "\n", stats->type_cache_collisions);
228
    fprintf(out, "Object method cache dunder hits: %" PRIu64 "\n", stats->type_cache_dunder_hits);
229
    fprintf(out, "Object method cache dunder misses: %" PRIu64 "\n", stats->type_cache_dunder_misses);
230
}
231
232
static void
233
print_gc_stats(FILE *out, GCStats *stats)
234
{
235
    for (int i = 0; i < NUM_GENERATIONS; i++) {
236
        fprintf(out, "GC[%d] collections: %" PRIu64 "\n", i, stats[i].collections);
237
        fprintf(out, "GC[%d] object visits: %" PRIu64 "\n", i, stats[i].object_visits);
238
        fprintf(out, "GC[%d] objects collected: %" PRIu64 "\n", i, stats[i].objects_collected);
239
        fprintf(out, "GC[%d] objects reachable from roots: %" PRIu64 "\n", i, stats[i].objects_transitively_reachable);
240
        fprintf(out, "GC[%d] objects not reachable from roots: %" PRIu64 "\n", i, stats[i].objects_not_transitively_reachable);
241
    }
242
}
243
244
#ifdef _Py_TIER2
245
static void
246
print_histogram(FILE *out, const char *name, uint64_t hist[_Py_UOP_HIST_SIZE])
247
{
248
    for (int i = 0; i < _Py_UOP_HIST_SIZE; i++) {
249
        fprintf(out, "%s[%" PRIu64"]: %" PRIu64 "\n", name, (uint64_t)1 << i, hist[i]);
250
    }
251
}
252
253
static void
254
print_optimization_stats(FILE *out, OptimizationStats *stats)
255
{
256
    fprintf(out, "Optimization attempts: %" PRIu64 "\n", stats->attempts);
257
    fprintf(out, "Optimization traces created: %" PRIu64 "\n", stats->traces_created);
258
    fprintf(out, "Optimization traces executed: %" PRIu64 "\n", stats->traces_executed);
259
    fprintf(out, "Optimization uops executed: %" PRIu64 "\n", stats->uops_executed);
260
    fprintf(out, "Optimization trace stack overflow: %" PRIu64 "\n", stats->trace_stack_overflow);
261
    fprintf(out, "Optimization trace stack underflow: %" PRIu64 "\n", stats->trace_stack_underflow);
262
    fprintf(out, "Optimization trace too long: %" PRIu64 "\n", stats->trace_too_long);
263
    fprintf(out, "Optimization trace too short: %" PRIu64 "\n", stats->trace_too_short);
264
    fprintf(out, "Optimization inner loop: %" PRIu64 "\n", stats->inner_loop);
265
    fprintf(out, "Optimization recursive call: %" PRIu64 "\n", stats->recursive_call);
266
    fprintf(out, "Optimization low confidence: %" PRIu64 "\n", stats->low_confidence);
267
    fprintf(out, "Optimization unknown callee: %" PRIu64 "\n", stats->unknown_callee);
268
    fprintf(out, "Executors invalidated: %" PRIu64 "\n", stats->executors_invalidated);
269
270
    print_histogram(out, "Trace length", stats->trace_length_hist);
271
    print_histogram(out, "Trace run length", stats->trace_run_length_hist);
272
    print_histogram(out, "Optimized trace length", stats->optimized_trace_length_hist);
273
274
    fprintf(out, "Optimization optimizer attempts: %" PRIu64 "\n", stats->optimizer_attempts);
275
    fprintf(out, "Optimization optimizer successes: %" PRIu64 "\n", stats->optimizer_successes);
276
    fprintf(out, "Optimization optimizer failure no memory: %" PRIu64 "\n",
277
            stats->optimizer_failure_reason_no_memory);
278
    fprintf(out, "Optimizer remove globals builtins changed: %" PRIu64 "\n", stats->remove_globals_builtins_changed);
279
    fprintf(out, "Optimizer remove globals incorrect keys: %" PRIu64 "\n", stats->remove_globals_incorrect_keys);
280
    for (int i = 0; i <= MAX_UOP_ID; i++) {
281
        if (stats->opcode[i].execution_count) {
282
            fprintf(out, "uops[%s].execution_count : %" PRIu64 "\n", _PyUOpName(i), stats->opcode[i].execution_count);
283
        }
284
        if (stats->opcode[i].miss) {
285
            fprintf(out, "uops[%s].specialization.miss : %" PRIu64 "\n", _PyUOpName(i), stats->opcode[i].miss);
286
        }
287
    }
288
    for (int i = 0; i < 256; i++) {
289
        if (stats->unsupported_opcode[i]) {
290
            fprintf(
291
                out,
292
                "unsupported_opcode[%s].count : %" PRIu64 "\n",
293
                _PyOpcode_OpName[i],
294
                stats->unsupported_opcode[i]
295
            );
296
        }
297
    }
298
299
    for (int i = 1; i <= MAX_UOP_ID; i++){
300
        for (int j = 1; j <= MAX_UOP_ID; j++) {
301
            if (stats->opcode[i].pair_count[j]) {
302
                fprintf(out, "uop[%s].pair_count[%s] : %" PRIu64 "\n",
303
                        _PyOpcode_uop_name[i], _PyOpcode_uop_name[j], stats->opcode[i].pair_count[j]);
304
            }
305
        }
306
    }
307
    for (int i = 0; i < MAX_UOP_ID; i++) {
308
        if (stats->error_in_opcode[i]) {
309
            fprintf(
310
                out,
311
                "error_in_opcode[%s].count : %" PRIu64 "\n",
312
                _PyUOpName(i),
313
                stats->error_in_opcode[i]
314
            );
315
        }
316
    }
317
    fprintf(out, "JIT total memory size: %" PRIu64 "\n", stats->jit_total_memory_size);
318
    fprintf(out, "JIT code size: %" PRIu64 "\n", stats->jit_code_size);
319
    fprintf(out, "JIT trampoline size: %" PRIu64 "\n", stats->jit_trampoline_size);
320
    fprintf(out, "JIT data size: %" PRIu64 "\n", stats->jit_data_size);
321
    fprintf(out, "JIT padding size: %" PRIu64 "\n", stats->jit_padding_size);
322
    fprintf(out, "JIT freed memory size: %" PRIu64 "\n", stats->jit_freed_memory_size);
323
324
    print_histogram(out, "Trace total memory size", stats->trace_total_memory_hist);
325
}
326
#endif
327
328
static void
329
print_rare_event_stats(FILE *out, RareEventStats *stats)
330
{
331
    fprintf(out, "Rare event (set_class): %" PRIu64 "\n", stats->set_class);
332
    fprintf(out, "Rare event (set_bases): %" PRIu64 "\n", stats->set_bases);
333
    fprintf(out, "Rare event (set_eval_frame_func): %" PRIu64 "\n", stats->set_eval_frame_func);
334
    fprintf(out, "Rare event (builtin_dict): %" PRIu64 "\n", stats->builtin_dict);
335
    fprintf(out, "Rare event (func_modification): %" PRIu64 "\n", stats->func_modification);
336
    fprintf(out, "Rare event (watched_dict_modification): %" PRIu64 "\n", stats->watched_dict_modification);
337
    fprintf(out, "Rare event (watched_globals_modification): %" PRIu64 "\n", stats->watched_globals_modification);
338
}
339
340
static void
341
print_stats(FILE *out, PyStats *stats)
342
{
343
    print_spec_stats(out, stats->opcode_stats);
344
    print_call_stats(out, &stats->call_stats);
345
    print_object_stats(out, &stats->object_stats);
346
    print_gc_stats(out, stats->gc_stats);
347
#ifdef _Py_TIER2
348
    print_optimization_stats(out, &stats->optimization_stats);
349
#endif
350
    print_rare_event_stats(out, &stats->rare_event_stats);
351
}
352
353
void
354
_Py_StatsOn(void)
355
{
356
    _Py_stats = &_Py_stats_struct;
357
}
358
359
void
360
_Py_StatsOff(void)
361
{
362
    _Py_stats = NULL;
363
}
364
365
void
366
_Py_StatsClear(void)
367
{
368
    memset(&_py_gc_stats, 0, sizeof(_py_gc_stats));
369
    memset(&_Py_stats_struct, 0, sizeof(_Py_stats_struct));
370
    _Py_stats_struct.gc_stats = _py_gc_stats;
371
}
372
373
static int
374
mem_is_zero(unsigned char *ptr, size_t size)
375
{
376
    for (size_t i=0; i < size; i++) {
377
        if (*ptr != 0) {
378
            return 0;
379
        }
380
        ptr++;
381
    }
382
    return 1;
383
}
384
385
int
386
_Py_PrintSpecializationStats(int to_file)
387
{
388
    PyStats *stats = &_Py_stats_struct;
389
#define MEM_IS_ZERO(DATA) mem_is_zero((unsigned char*)DATA, sizeof(*(DATA)))
390
    int is_zero = (
391
        MEM_IS_ZERO(stats->gc_stats)  // is a pointer
392
        && MEM_IS_ZERO(&stats->opcode_stats)
393
        && MEM_IS_ZERO(&stats->call_stats)
394
        && MEM_IS_ZERO(&stats->object_stats)
395
    );
396
#undef MEM_IS_ZERO
397
    if (is_zero) {
398
        // gh-108753: -X pystats command line was used, but then _stats_off()
399
        // and _stats_clear() have been called: in this case, avoid printing
400
        // useless "all zeros" statistics.
401
        return 0;
402
    }
403
404
    FILE *out = stderr;
405
    if (to_file) {
406
        /* Write to a file instead of stderr. */
407
# ifdef MS_WINDOWS
408
        const char *dirname = "c:\\temp\\py_stats\\";
409
# else
410
        const char *dirname = "/tmp/py_stats/";
411
# endif
412
        /* Use random 160 bit number as file name,
413
        * to avoid both accidental collisions and
414
        * symlink attacks. */
415
        unsigned char rand[20];
416
        char hex_name[41];
417
        _PyOS_URandomNonblock(rand, 20);
418
        for (int i = 0; i < 20; i++) {
419
            hex_name[2*i] = Py_hexdigits[rand[i]&15];
420
            hex_name[2*i+1] = Py_hexdigits[(rand[i]>>4)&15];
421
        }
422
        hex_name[40] = '\0';
423
        char buf[64];
424
        assert(strlen(dirname) + 40 + strlen(".txt") < 64);
425
        sprintf(buf, "%s%s.txt", dirname, hex_name);
426
        FILE *fout = fopen(buf, "w");
427
        if (fout) {
428
            out = fout;
429
        }
430
    }
431
    else {
432
        fprintf(out, "Specialization stats:\n");
433
    }
434
    print_stats(out, stats);
435
    if (out != stderr) {
436
        fclose(out);
437
    }
438
    return 1;
439
}
440
441
#define SPECIALIZATION_FAIL(opcode, kind) \
442
do { \
443
    if (_Py_stats) { \
444
        int _kind = (kind); \
445
        assert(_kind < SPECIALIZATION_FAILURE_KINDS); \
446
        _Py_stats->opcode_stats[opcode].specialization.failure_kinds[_kind]++; \
447
    } \
448
} while (0)
449
450
#endif  // Py_STATS
451
452
453
#ifndef SPECIALIZATION_FAIL
454
272k
#  define SPECIALIZATION_FAIL(opcode, kind) ((void)0)
455
#endif
456
457
// Initialize warmup counters and optimize instructions. This cannot fail.
458
void
459
_PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters)
460
32.8k
{
461
32.8k
    #if ENABLE_SPECIALIZATION_FT
462
32.8k
    _Py_BackoffCounter jump_counter, adaptive_counter;
463
32.8k
    if (enable_counters) {
464
32.8k
        jump_counter = initial_jump_backoff_counter();
465
32.8k
        adaptive_counter = adaptive_counter_warmup();
466
32.8k
    }
467
0
    else {
468
0
        jump_counter = initial_unreachable_backoff_counter();
469
0
        adaptive_counter = initial_unreachable_backoff_counter();
470
0
    }
471
32.8k
    int opcode = 0;
472
32.8k
    int oparg = 0;
473
    /* The last code unit cannot have a cache, so we don't need to check it */
474
1.57M
    for (Py_ssize_t i = 0; i < size-1; i++) {
475
1.54M
        opcode = instructions[i].op.code;
476
1.54M
        int caches = _PyOpcode_Caches[opcode];
477
1.54M
        oparg = (oparg << 8) | instructions[i].op.arg;
478
1.54M
        if (caches) {
479
            // The initial value depends on the opcode
480
445k
            switch (opcode) {
481
14.7k
                case JUMP_BACKWARD:
482
14.7k
                    instructions[i + 1].counter = jump_counter;
483
14.7k
                    break;
484
36.9k
                case POP_JUMP_IF_FALSE:
485
50.1k
                case POP_JUMP_IF_TRUE:
486
53.1k
                case POP_JUMP_IF_NONE:
487
57.0k
                case POP_JUMP_IF_NOT_NONE:
488
57.0k
                    instructions[i + 1].cache = 0x5555;  // Alternating 0, 1 bits
489
57.0k
                    break;
490
374k
                default:
491
374k
                    instructions[i + 1].counter = adaptive_counter;
492
374k
                    break;
493
445k
            }
494
445k
            i += caches;
495
445k
        }
496
1.54M
        if (opcode != EXTENDED_ARG) {
497
1.52M
            oparg = 0;
498
1.52M
        }
499
1.54M
    }
500
32.8k
    #endif /* ENABLE_SPECIALIZATION_FT */
501
32.8k
}
502
503
445k
#define SIMPLE_FUNCTION 0
504
505
/* Common */
506
507
#define SPEC_FAIL_OTHER 0
508
#define SPEC_FAIL_NO_DICT 1
509
#define SPEC_FAIL_OVERRIDDEN 2
510
#define SPEC_FAIL_OUT_OF_VERSIONS 3
511
#define SPEC_FAIL_OUT_OF_RANGE 4
512
#define SPEC_FAIL_EXPECTED_ERROR 5
513
#define SPEC_FAIL_WRONG_NUMBER_ARGUMENTS 6
514
902
#define SPEC_FAIL_CODE_COMPLEX_PARAMETERS 7
515
16.3k
#define SPEC_FAIL_CODE_NOT_OPTIMIZED 8
516
517
518
#define SPEC_FAIL_LOAD_GLOBAL_NON_DICT 17
519
#define SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT 18
520
521
/* Super */
522
523
#define SPEC_FAIL_SUPER_BAD_CLASS 9
524
#define SPEC_FAIL_SUPER_SHADOWED 10
525
526
/* Attributes */
527
528
#define SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR 9
529
#define SPEC_FAIL_ATTR_NON_OVERRIDING_DESCRIPTOR 10
530
#define SPEC_FAIL_ATTR_NOT_DESCRIPTOR 11
531
#define SPEC_FAIL_ATTR_METHOD 12
532
#define SPEC_FAIL_ATTR_MUTABLE_CLASS 13
533
#define SPEC_FAIL_ATTR_PROPERTY 14
534
#define SPEC_FAIL_ATTR_NON_OBJECT_SLOT 15
535
#define SPEC_FAIL_ATTR_READ_ONLY 16
536
#define SPEC_FAIL_ATTR_AUDITED_SLOT 17
537
#define SPEC_FAIL_ATTR_NOT_MANAGED_DICT 18
538
#define SPEC_FAIL_ATTR_NON_STRING 19
539
#define SPEC_FAIL_ATTR_MODULE_ATTR_NOT_FOUND 20
540
#define SPEC_FAIL_ATTR_SHADOWED 21
541
#define SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD 22
542
#define SPEC_FAIL_ATTR_CLASS_METHOD_OBJ 23
543
#define SPEC_FAIL_ATTR_OBJECT_SLOT 24
544
545
#define SPEC_FAIL_ATTR_INSTANCE_ATTRIBUTE 26
546
#define SPEC_FAIL_ATTR_METACLASS_ATTRIBUTE 27
547
#define SPEC_FAIL_ATTR_PROPERTY_NOT_PY_FUNCTION 28
548
#define SPEC_FAIL_ATTR_NOT_IN_KEYS 29
549
#define SPEC_FAIL_ATTR_NOT_IN_DICT 30
550
#define SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE 31
551
#define SPEC_FAIL_ATTR_CLASS_ATTR_DESCRIPTOR 32
552
#define SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD_OBJ 33
553
#define SPEC_FAIL_ATTR_METACLASS_OVERRIDDEN 34
554
#define SPEC_FAIL_ATTR_SPLIT_DICT 35
555
#define SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED 36
556
557
/* Binary subscr and store subscr */
558
559
#define SPEC_FAIL_SUBSCR_ARRAY_INT 9
560
#define SPEC_FAIL_SUBSCR_ARRAY_SLICE 10
561
#define SPEC_FAIL_SUBSCR_LIST_SLICE 11
562
#define SPEC_FAIL_SUBSCR_BUFFER_INT 12
563
#define SPEC_FAIL_SUBSCR_BUFFER_SLICE 13
564
565
/* Store subscr */
566
#define SPEC_FAIL_SUBSCR_BYTEARRAY_INT 18
567
#define SPEC_FAIL_SUBSCR_BYTEARRAY_SLICE 19
568
#define SPEC_FAIL_SUBSCR_PY_SIMPLE 20
569
#define SPEC_FAIL_SUBSCR_PY_OTHER 21
570
#define SPEC_FAIL_SUBSCR_DICT_SUBCLASS_NO_OVERRIDE 22
571
#define SPEC_FAIL_SUBSCR_NOT_HEAP_TYPE 23
572
573
/* Binary op */
574
575
#define SPEC_FAIL_BINARY_OP_ADD_DIFFERENT_TYPES          9
576
#define SPEC_FAIL_BINARY_OP_ADD_OTHER                   10
577
#define SPEC_FAIL_BINARY_OP_AND_DIFFERENT_TYPES         11
578
#define SPEC_FAIL_BINARY_OP_AND_INT                     12
579
#define SPEC_FAIL_BINARY_OP_AND_OTHER                   13
580
#define SPEC_FAIL_BINARY_OP_FLOOR_DIVIDE                14
581
#define SPEC_FAIL_BINARY_OP_LSHIFT                      15
582
#define SPEC_FAIL_BINARY_OP_MATRIX_MULTIPLY             16
583
#define SPEC_FAIL_BINARY_OP_MULTIPLY_DIFFERENT_TYPES    17
584
#define SPEC_FAIL_BINARY_OP_MULTIPLY_OTHER              18
585
#define SPEC_FAIL_BINARY_OP_OR                          19
586
#define SPEC_FAIL_BINARY_OP_POWER                       20
587
#define SPEC_FAIL_BINARY_OP_REMAINDER                   21
588
#define SPEC_FAIL_BINARY_OP_RSHIFT                      22
589
#define SPEC_FAIL_BINARY_OP_SUBTRACT_DIFFERENT_TYPES    23
590
#define SPEC_FAIL_BINARY_OP_SUBTRACT_OTHER              24
591
#define SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_DIFFERENT_TYPES 25
592
#define SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_FLOAT           26
593
#define SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_OTHER           27
594
#define SPEC_FAIL_BINARY_OP_XOR                         28
595
#define SPEC_FAIL_BINARY_OP_OR_INT                      29
596
#define SPEC_FAIL_BINARY_OP_OR_DIFFERENT_TYPES          30
597
#define SPEC_FAIL_BINARY_OP_XOR_INT                     31
598
#define SPEC_FAIL_BINARY_OP_XOR_DIFFERENT_TYPES         32
599
#define SPEC_FAIL_BINARY_OP_SUBSCR                      33
600
#define SPEC_FAIL_BINARY_OP_SUBSCR_LIST_SLICE           34
601
#define SPEC_FAIL_BINARY_OP_SUBSCR_TUPLE_SLICE          35
602
#define SPEC_FAIL_BINARY_OP_SUBSCR_STRING_SLICE         36
603
#define SPEC_FAIL_BINARY_OP_SUBSCR_NOT_HEAP_TYPE        37
604
#define SPEC_FAIL_BINARY_OP_SUBSCR_OTHER_SLICE          38
605
#define SPEC_FAIL_BINARY_OP_SUBSCR_MAPPINGPROXY         39
606
#define SPEC_FAIL_BINARY_OP_SUBSCR_RE_MATCH             40
607
#define SPEC_FAIL_BINARY_OP_SUBSCR_ARRAY                41
608
#define SPEC_FAIL_BINARY_OP_SUBSCR_DEQUE                42
609
#define SPEC_FAIL_BINARY_OP_SUBSCR_ENUMDICT             43
610
#define SPEC_FAIL_BINARY_OP_SUBSCR_STACKSUMMARY         44
611
#define SPEC_FAIL_BINARY_OP_SUBSCR_DEFAULTDICT          45
612
#define SPEC_FAIL_BINARY_OP_SUBSCR_COUNTER              46
613
#define SPEC_FAIL_BINARY_OP_SUBSCR_ORDEREDDICT          47
614
#define SPEC_FAIL_BINARY_OP_SUBSCR_BYTES                48
615
#define SPEC_FAIL_BINARY_OP_SUBSCR_STRUCTTIME           49
616
#define SPEC_FAIL_BINARY_OP_SUBSCR_RANGE                50
617
618
/* Calls */
619
620
#define SPEC_FAIL_CALL_INSTANCE_METHOD 11
621
#define SPEC_FAIL_CALL_CMETHOD 12
622
#define SPEC_FAIL_CALL_CFUNC_VARARGS 13
623
#define SPEC_FAIL_CALL_CFUNC_VARARGS_KEYWORDS 14
624
#define SPEC_FAIL_CALL_CFUNC_NOARGS 15
625
#define SPEC_FAIL_CALL_CFUNC_METHOD_FASTCALL_KEYWORDS 16
626
#define SPEC_FAIL_CALL_METH_DESCR_VARARGS 17
627
#define SPEC_FAIL_CALL_METH_DESCR_VARARGS_KEYWORDS 18
628
#define SPEC_FAIL_CALL_METH_DESCR_METHOD_FASTCALL_KEYWORDS 19
629
#define SPEC_FAIL_CALL_BAD_CALL_FLAGS 20
630
#define SPEC_FAIL_CALL_INIT_NOT_PYTHON 21
631
#define SPEC_FAIL_CALL_PEP_523 22
632
#define SPEC_FAIL_CALL_BOUND_METHOD 23
633
#define SPEC_FAIL_CALL_CLASS_MUTABLE 26
634
#define SPEC_FAIL_CALL_METHOD_WRAPPER 28
635
#define SPEC_FAIL_CALL_OPERATOR_WRAPPER 29
636
#define SPEC_FAIL_CALL_INIT_NOT_SIMPLE 30
637
#define SPEC_FAIL_CALL_METACLASS 31
638
#define SPEC_FAIL_CALL_INIT_NOT_INLINE_VALUES 32
639
640
/* COMPARE_OP */
641
#define SPEC_FAIL_COMPARE_OP_DIFFERENT_TYPES 12
642
#define SPEC_FAIL_COMPARE_OP_STRING 13
643
#define SPEC_FAIL_COMPARE_OP_BIG_INT 14
644
#define SPEC_FAIL_COMPARE_OP_BYTES 15
645
#define SPEC_FAIL_COMPARE_OP_TUPLE 16
646
#define SPEC_FAIL_COMPARE_OP_LIST 17
647
#define SPEC_FAIL_COMPARE_OP_SET 18
648
#define SPEC_FAIL_COMPARE_OP_BOOL 19
649
#define SPEC_FAIL_COMPARE_OP_BASEOBJECT 20
650
#define SPEC_FAIL_COMPARE_OP_FLOAT_LONG 21
651
#define SPEC_FAIL_COMPARE_OP_LONG_FLOAT 22
652
653
/* FOR_ITER and SEND */
654
#define SPEC_FAIL_ITER_GENERATOR 10
655
#define SPEC_FAIL_ITER_COROUTINE 11
656
#define SPEC_FAIL_ITER_ASYNC_GENERATOR 12
657
#define SPEC_FAIL_ITER_LIST 13
658
#define SPEC_FAIL_ITER_TUPLE 14
659
#define SPEC_FAIL_ITER_SET 15
660
#define SPEC_FAIL_ITER_STRING 16
661
#define SPEC_FAIL_ITER_BYTES 17
662
#define SPEC_FAIL_ITER_RANGE 18
663
#define SPEC_FAIL_ITER_ITERTOOLS 19
664
#define SPEC_FAIL_ITER_DICT_KEYS 20
665
#define SPEC_FAIL_ITER_DICT_ITEMS 21
666
#define SPEC_FAIL_ITER_DICT_VALUES 22
667
#define SPEC_FAIL_ITER_ENUMERATE 23
668
#define SPEC_FAIL_ITER_MAP 24
669
#define SPEC_FAIL_ITER_ZIP 25
670
#define SPEC_FAIL_ITER_SEQ_ITER 26
671
#define SPEC_FAIL_ITER_REVERSED_LIST 27
672
#define SPEC_FAIL_ITER_CALLABLE 28
673
#define SPEC_FAIL_ITER_ASCII_STRING 29
674
#define SPEC_FAIL_ITER_ASYNC_GENERATOR_SEND 30
675
#define SPEC_FAIL_ITER_SELF 31
676
677
// UNPACK_SEQUENCE
678
679
#define SPEC_FAIL_UNPACK_SEQUENCE_ITERATOR 9
680
#define SPEC_FAIL_UNPACK_SEQUENCE_SEQUENCE 10
681
682
// TO_BOOL
683
#define SPEC_FAIL_TO_BOOL_BYTEARRAY    9
684
#define SPEC_FAIL_TO_BOOL_BYTES       10
685
#define SPEC_FAIL_TO_BOOL_DICT        11
686
#define SPEC_FAIL_TO_BOOL_FLOAT       12
687
10.9k
#define SPEC_FAIL_TO_BOOL_MAPPING     13
688
#define SPEC_FAIL_TO_BOOL_MEMORY_VIEW 14
689
26
#define SPEC_FAIL_TO_BOOL_NUMBER      15
690
8.77k
#define SPEC_FAIL_TO_BOOL_SEQUENCE    16
691
#define SPEC_FAIL_TO_BOOL_SET         17
692
#define SPEC_FAIL_TO_BOOL_TUPLE       18
693
694
// CONTAINS_OP
695
#define SPEC_FAIL_CONTAINS_OP_STR        9
696
#define SPEC_FAIL_CONTAINS_OP_TUPLE      10
697
#define SPEC_FAIL_CONTAINS_OP_LIST       11
698
#define SPEC_FAIL_CONTAINS_OP_USER_CLASS 12
699
700
static inline int
701
set_opcode(_Py_CODEUNIT *instr, uint8_t opcode)
702
3.82M
{
703
#ifdef Py_GIL_DISABLED
704
    uint8_t old_op = _Py_atomic_load_uint8_relaxed(&instr->op.code);
705
    if (old_op >= MIN_INSTRUMENTED_OPCODE) {
706
        /* Lost race with instrumentation */
707
        return 0;
708
    }
709
    if (!_Py_atomic_compare_exchange_uint8(&instr->op.code, &old_op, opcode)) {
710
        /* Lost race with instrumentation */
711
        assert(old_op >= MIN_INSTRUMENTED_OPCODE);
712
        return 0;
713
    }
714
    return 1;
715
#else
716
3.82M
    instr->op.code = opcode;
717
3.82M
    return 1;
718
3.82M
#endif
719
3.82M
}
720
721
static inline void
722
set_counter(_Py_BackoffCounter *counter, _Py_BackoffCounter value)
723
3.89M
{
724
3.89M
    FT_ATOMIC_STORE_UINT16_RELAXED(counter->value_and_backoff,
725
3.89M
                                   value.value_and_backoff);
726
3.89M
}
727
728
static inline _Py_BackoffCounter
729
load_counter(_Py_BackoffCounter *counter)
730
272k
{
731
272k
    _Py_BackoffCounter result = {
732
272k
        .value_and_backoff =
733
272k
            FT_ATOMIC_LOAD_UINT16_RELAXED(counter->value_and_backoff)};
734
272k
    return result;
735
272k
}
736
737
static inline void
738
specialize(_Py_CODEUNIT *instr, uint8_t specialized_opcode)
739
3.54M
{
740
3.54M
    assert(!PyErr_Occurred());
741
3.54M
    if (!set_opcode(instr, specialized_opcode)) {
742
0
        STAT_INC(_PyOpcode_Deopt[specialized_opcode], failure);
743
0
        SPECIALIZATION_FAIL(_PyOpcode_Deopt[specialized_opcode],
744
0
                            SPEC_FAIL_OTHER);
745
0
        return;
746
0
    }
747
3.54M
    STAT_INC(_PyOpcode_Deopt[specialized_opcode], success);
748
3.54M
    set_counter((_Py_BackoffCounter *)instr + 1, adaptive_counter_cooldown());
749
3.54M
}
750
751
static inline void
752
unspecialize(_Py_CODEUNIT *instr)
753
272k
{
754
272k
    assert(!PyErr_Occurred());
755
272k
    uint8_t opcode = FT_ATOMIC_LOAD_UINT8_RELAXED(instr->op.code);
756
272k
    uint8_t generic_opcode = _PyOpcode_Deopt[opcode];
757
272k
    STAT_INC(generic_opcode, failure);
758
272k
    if (!set_opcode(instr, generic_opcode)) {
759
0
        SPECIALIZATION_FAIL(generic_opcode, SPEC_FAIL_OTHER);
760
0
        return;
761
0
    }
762
272k
    _Py_BackoffCounter *counter = (_Py_BackoffCounter *)instr + 1;
763
272k
    _Py_BackoffCounter cur = load_counter(counter);
764
272k
    set_counter(counter, adaptive_counter_backoff(cur));
765
272k
}
766
767
static int function_kind(PyCodeObject *code);
768
static bool function_check_args(PyObject *o, int expected_argcount, int opcode);
769
static uint32_t function_get_version(PyObject *o, int opcode);
770
771
static int
772
specialize_module_load_attr_lock_held(PyDictObject *dict, _Py_CODEUNIT *instr, PyObject *name)
773
2.52k
{
774
2.52k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
775
2.52k
    if (dict->ma_keys->dk_kind != DICT_KEYS_UNICODE) {
776
0
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NON_STRING);
777
0
        return -1;
778
0
    }
779
2.52k
    Py_ssize_t index = _PyDict_LookupIndex(dict, &_Py_ID(__getattr__));
780
2.52k
    assert(index != DKIX_ERROR);
781
2.52k
    if (index != DKIX_EMPTY) {
782
0
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MODULE_ATTR_NOT_FOUND);
783
0
        return -1;
784
0
    }
785
2.52k
    index = _PyDict_LookupIndex(dict, name);
786
2.52k
    assert (index != DKIX_ERROR);
787
2.52k
    if (index != (uint16_t)index) {
788
203
        SPECIALIZATION_FAIL(LOAD_ATTR,
789
203
                            index == DKIX_EMPTY ?
790
203
                            SPEC_FAIL_ATTR_MODULE_ATTR_NOT_FOUND :
791
203
                            SPEC_FAIL_OUT_OF_RANGE);
792
203
        return -1;
793
203
    }
794
2.32k
    uint32_t keys_version = _PyDict_GetKeysVersionForCurrentState(
795
2.32k
            _PyInterpreterState_GET(), dict);
796
2.32k
    if (keys_version == 0) {
797
0
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
798
0
        return -1;
799
0
    }
800
2.32k
    write_u32(cache->version, keys_version);
801
2.32k
    cache->index = (uint16_t)index;
802
2.32k
    specialize(instr, LOAD_ATTR_MODULE);
803
2.32k
    return 0;
804
2.32k
}
805
806
static int
807
specialize_module_load_attr(
808
    PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
809
2.52k
{
810
2.52k
    PyModuleObject *m = (PyModuleObject *)owner;
811
2.52k
    assert((Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0);
812
2.52k
    PyDictObject *dict = (PyDictObject *)m->md_dict;
813
2.52k
    if (dict == NULL) {
814
0
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_NO_DICT);
815
0
        return -1;
816
0
    }
817
2.52k
    int result;
818
2.52k
    Py_BEGIN_CRITICAL_SECTION(dict);
819
2.52k
    result = specialize_module_load_attr_lock_held(dict, instr, name);
820
2.52k
    Py_END_CRITICAL_SECTION();
821
2.52k
    return result;
822
2.52k
}
823
824
/* Attribute specialization */
825
826
Py_NO_INLINE void
827
157
_Py_Specialize_LoadSuperAttr(_PyStackRef global_super_st, _PyStackRef cls_st, _Py_CODEUNIT *instr, int load_method) {
828
157
    PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st);
829
157
    PyObject *cls = PyStackRef_AsPyObjectBorrow(cls_st);
830
831
157
    assert(ENABLE_SPECIALIZATION_FT);
832
157
    assert(_PyOpcode_Caches[LOAD_SUPER_ATTR] == INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR);
833
157
    if (global_super != (PyObject *)&PySuper_Type) {
834
0
        SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_SHADOWED);
835
0
        goto fail;
836
0
    }
837
157
    if (!PyType_Check(cls)) {
838
0
        SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_BAD_CLASS);
839
0
        goto fail;
840
0
    }
841
157
    uint8_t load_code = load_method ? LOAD_SUPER_ATTR_METHOD : LOAD_SUPER_ATTR_ATTR;
842
157
    specialize(instr, load_code);
843
157
    return;
844
0
fail:
845
0
    unspecialize(instr);
846
0
}
847
848
typedef enum {
849
    OVERRIDING, /* Is an overriding descriptor, and will remain so. */
850
    METHOD, /* Attribute has Py_TPFLAGS_METHOD_DESCRIPTOR set */
851
    PROPERTY, /* Is a property */
852
    OBJECT_SLOT, /* Is an object slot descriptor */
853
    OTHER_SLOT, /* Is a slot descriptor of another type */
854
    NON_OVERRIDING, /* Is another non-overriding descriptor, and is an instance of an immutable class*/
855
    BUILTIN_CLASSMETHOD, /* Builtin methods with METH_CLASS */
856
    PYTHON_CLASSMETHOD, /* Python classmethod(func) object */
857
    NON_DESCRIPTOR, /* Is not a descriptor, and is an instance of an immutable class */
858
    MUTABLE,   /* Instance of a mutable class; might, or might not, be a descriptor */
859
    ABSENT, /* Attribute is not present on the class */
860
    DUNDER_CLASS, /* __class__ attribute */
861
    GETSET_OVERRIDDEN, /* __getattribute__ or __setattr__ has been overridden */
862
    GETATTRIBUTE_IS_PYTHON_FUNCTION  /* Descriptor requires calling a Python __getattribute__ */
863
} DescriptorClassification;
864
865
866
static DescriptorClassification
867
classify_descriptor(PyObject *descriptor, bool has_getattr)
868
881k
{
869
881k
    if (descriptor == NULL) {
870
452k
        return ABSENT;
871
452k
    }
872
428k
    PyTypeObject *desc_cls = Py_TYPE(descriptor);
873
428k
    if (!(desc_cls->tp_flags & Py_TPFLAGS_IMMUTABLETYPE)) {
874
589
        return MUTABLE;
875
589
    }
876
427k
    if (desc_cls->tp_descr_set) {
877
210k
        if (desc_cls == &PyMemberDescr_Type) {
878
666
            PyMemberDescrObject *member = (PyMemberDescrObject *)descriptor;
879
666
            struct PyMemberDef *dmem = member->d_member;
880
666
            if (dmem->type == Py_T_OBJECT_EX || dmem->type == _Py_T_OBJECT) {
881
568
                return OBJECT_SLOT;
882
568
            }
883
98
            return OTHER_SLOT;
884
666
        }
885
209k
        if (desc_cls == &PyProperty_Type) {
886
            /* We can't detect at runtime whether an attribute exists
887
               with property. So that means we may have to call
888
               __getattr__. */
889
206k
            return has_getattr ? GETSET_OVERRIDDEN : PROPERTY;
890
206k
        }
891
3.06k
        return OVERRIDING;
892
209k
    }
893
217k
    if (desc_cls->tp_descr_get) {
894
124k
        if (desc_cls->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR) {
895
122k
            return METHOD;
896
122k
        }
897
1.56k
        if (Py_IS_TYPE(descriptor, &PyClassMethodDescr_Type)) {
898
161
            return BUILTIN_CLASSMETHOD;
899
161
        }
900
1.40k
        if (Py_IS_TYPE(descriptor, &PyClassMethod_Type)) {
901
741
            return PYTHON_CLASSMETHOD;
902
741
        }
903
659
        return NON_OVERRIDING;
904
1.40k
    }
905
93.4k
    return NON_DESCRIPTOR;
906
217k
}
907
908
static bool
909
descriptor_is_class(PyObject *descriptor, PyObject *name)
910
935k
{
911
935k
    return ((PyUnicode_CompareWithASCIIString(name, "__class__") == 0) &&
912
935k
            (descriptor == _PyType_Lookup(&PyBaseObject_Type, name)));
913
935k
}
914
915
static DescriptorClassification
916
735k
analyze_descriptor_load(PyTypeObject *type, PyObject *name, PyObject **descr, unsigned int *tp_version) {
917
735k
    bool has_getattr = false;
918
735k
    bool have_ga_version = false;
919
735k
    unsigned int ga_version;
920
735k
    getattrofunc getattro_slot = type->tp_getattro;
921
735k
    if (getattro_slot == PyObject_GenericGetAttr) {
922
        /* Normal attribute lookup; */
923
735k
        has_getattr = false;
924
735k
    }
925
158
    else if (getattro_slot == _Py_slot_tp_getattr_hook ||
926
158
        getattro_slot == _Py_slot_tp_getattro) {
927
        /* One or both of __getattribute__ or __getattr__ may have been
928
         overridden See typeobject.c for why these functions are special. */
929
0
        PyObject *getattribute = _PyType_LookupRefAndVersion(type,
930
0
                &_Py_ID(__getattribute__), &ga_version);
931
0
        have_ga_version = true;
932
0
        PyInterpreterState *interp = _PyInterpreterState_GET();
933
0
        bool has_custom_getattribute = getattribute != NULL &&
934
0
            getattribute != interp->callable_cache.object__getattribute__;
935
0
        PyObject *getattr = _PyType_Lookup(type, &_Py_ID(__getattr__));
936
0
        has_getattr = getattr != NULL;
937
0
        if (has_custom_getattribute) {
938
0
            if (!has_getattr &&
939
0
                Py_IS_TYPE(getattribute, &PyFunction_Type)) {
940
0
                *descr = getattribute;
941
0
                *tp_version = ga_version;
942
0
                return GETATTRIBUTE_IS_PYTHON_FUNCTION;
943
0
            }
944
            /* Potentially both __getattr__ and __getattribute__ are set.
945
               Too complicated */
946
0
            Py_DECREF(getattribute);
947
0
            *descr = NULL;
948
0
            *tp_version = ga_version;
949
0
            return GETSET_OVERRIDDEN;
950
0
        }
951
        /* Potentially has __getattr__ but no custom __getattribute__.
952
           Fall through to usual descriptor analysis.
953
           Usual attribute lookup should only be allowed at runtime
954
           if we can guarantee that there is no way an exception can be
955
           raised. This means some specializations, e.g. specializing
956
           for property() isn't safe.
957
        */
958
0
        Py_XDECREF(getattribute);
959
0
    }
960
158
    else {
961
158
        *descr = NULL;
962
158
        *tp_version = FT_ATOMIC_LOAD_UINT_RELAXED(type->tp_version_tag);
963
158
        return GETSET_OVERRIDDEN;
964
158
    }
965
735k
    unsigned int descr_version;
966
735k
    PyObject *descriptor = _PyType_LookupRefAndVersion(type, name, &descr_version);
967
735k
    *descr = descriptor;
968
735k
    *tp_version = have_ga_version ? ga_version : descr_version;
969
735k
    if (descriptor_is_class(descriptor, name)) {
970
59.4k
        return DUNDER_CLASS;
971
59.4k
    }
972
676k
    return classify_descriptor(descriptor, has_getattr);
973
735k
}
974
975
static DescriptorClassification
976
analyze_descriptor_store(PyTypeObject *type, PyObject *name, PyObject **descr, unsigned int *tp_version)
977
199k
{
978
199k
    if (type->tp_setattro != PyObject_GenericSetAttr) {
979
165
        *descr = NULL;
980
165
        return GETSET_OVERRIDDEN;
981
165
    }
982
199k
    PyObject *descriptor = _PyType_LookupRefAndVersion(type, name, tp_version);
983
199k
    *descr = descriptor;
984
199k
    if (descriptor_is_class(descriptor, name)) {
985
0
        return DUNDER_CLASS;
986
0
    }
987
199k
    return classify_descriptor(descriptor, false);
988
199k
}
989
990
static int
991
specialize_dict_access_inline(
992
    PyObject *owner, _Py_CODEUNIT *instr, PyTypeObject *type,
993
    PyObject *name, unsigned int tp_version,
994
    int base_op, int values_op)
995
364k
{
996
364k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
997
364k
    PyDictKeysObject *keys = ((PyHeapTypeObject *)type)->ht_cached_keys;
998
364k
    assert(PyUnicode_CheckExact(name));
999
364k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(owner);
1000
364k
    Py_ssize_t index = _PyDictKeys_StringLookupSplit(keys, name);
1001
364k
    assert (index != DKIX_ERROR);
1002
364k
    if (index == DKIX_EMPTY) {
1003
448
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_NOT_IN_KEYS);
1004
448
        return 0;
1005
448
    }
1006
364k
    assert(index >= 0);
1007
364k
    assert(_PyObject_InlineValues(owner)->valid);
1008
364k
    char *value_addr = (char *)&_PyObject_InlineValues(owner)->values[index];
1009
364k
    Py_ssize_t offset = value_addr - (char *)owner;
1010
364k
    if (offset != (uint16_t)offset) {
1011
0
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_OUT_OF_RANGE);
1012
0
        return 0;
1013
0
    }
1014
364k
    cache->index = (uint16_t)offset;
1015
364k
    write_u32(cache->version, tp_version);
1016
364k
    specialize(instr, values_op);
1017
364k
    return 1;
1018
364k
}
1019
1020
static int
1021
specialize_dict_access_hint(
1022
    PyDictObject *dict, _Py_CODEUNIT *instr, PyTypeObject *type,
1023
    PyObject *name, unsigned int tp_version,
1024
    int base_op, int hint_op)
1025
15.1k
{
1026
15.1k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
1027
1028
15.1k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(dict);
1029
#ifdef Py_GIL_DISABLED
1030
    _PyDict_EnsureSharedOnRead(dict);
1031
#endif
1032
1033
    // We found an instance with a __dict__.
1034
15.1k
    if (_PyDict_HasSplitTable(dict)) {
1035
329
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_SPLIT_DICT);
1036
329
        return 0;
1037
329
    }
1038
14.8k
    Py_ssize_t index = _PyDict_LookupIndex(dict, name);
1039
14.8k
    if (index != (uint16_t)index) {
1040
4.49k
        SPECIALIZATION_FAIL(base_op,
1041
4.49k
                            index == DKIX_EMPTY ?
1042
4.49k
                            SPEC_FAIL_ATTR_NOT_IN_DICT :
1043
4.49k
                            SPEC_FAIL_OUT_OF_RANGE);
1044
4.49k
        return 0;
1045
4.49k
    }
1046
10.3k
    cache->index = (uint16_t)index;
1047
10.3k
    write_u32(cache->version, tp_version);
1048
10.3k
    specialize(instr, hint_op);
1049
10.3k
    return 1;
1050
14.8k
}
1051
1052
1053
static int
1054
specialize_dict_access(
1055
    PyObject *owner, _Py_CODEUNIT *instr, PyTypeObject *type,
1056
    DescriptorClassification kind, PyObject *name, unsigned int tp_version,
1057
    int base_op, int values_op, int hint_op)
1058
382k
{
1059
382k
    assert(kind == NON_OVERRIDING || kind == NON_DESCRIPTOR || kind == ABSENT ||
1060
382k
        kind == BUILTIN_CLASSMETHOD || kind == PYTHON_CLASSMETHOD ||
1061
382k
        kind == METHOD);
1062
    // No descriptor, or non overriding.
1063
382k
    if ((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {
1064
2.64k
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);
1065
2.64k
        return 0;
1066
2.64k
    }
1067
380k
    if (type->tp_flags & Py_TPFLAGS_INLINE_VALUES &&
1068
380k
        FT_ATOMIC_LOAD_UINT8(_PyObject_InlineValues(owner)->valid) &&
1069
380k
        !(base_op == STORE_ATTR && _PyObject_GetManagedDict(owner) != NULL))
1070
364k
    {
1071
364k
        int res;
1072
364k
        Py_BEGIN_CRITICAL_SECTION(owner);
1073
364k
        PyDictObject *dict = _PyObject_GetManagedDict(owner);
1074
364k
        if (dict == NULL) {
1075
            // managed dict, not materialized, inline values valid
1076
364k
            res = specialize_dict_access_inline(owner, instr, type, name,
1077
364k
                                                tp_version, base_op, values_op);
1078
364k
        }
1079
0
        else {
1080
            // lost race and dict was created, fail specialization
1081
0
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OTHER);
1082
0
            res = 0;
1083
0
        }
1084
364k
        Py_END_CRITICAL_SECTION();
1085
364k
        return res;
1086
364k
    }
1087
15.3k
    else {
1088
15.3k
        PyDictObject *dict = _PyObject_GetManagedDict(owner);
1089
15.3k
        if (dict == NULL || !PyDict_CheckExact(dict)) {
1090
184
            SPECIALIZATION_FAIL(base_op, SPEC_FAIL_NO_DICT);
1091
184
            return 0;
1092
184
        }
1093
15.1k
        int res;
1094
15.1k
        Py_BEGIN_CRITICAL_SECTION(dict);
1095
        // materialized managed dict
1096
15.1k
        res = specialize_dict_access_hint(dict, instr, type, name,
1097
15.1k
                                          tp_version, base_op, hint_op);
1098
15.1k
        Py_END_CRITICAL_SECTION();
1099
15.1k
        return res;
1100
15.3k
    }
1101
380k
}
1102
1103
static int
1104
specialize_attr_loadclassattr(PyObject *owner, _Py_CODEUNIT *instr,
1105
                              PyObject *name, PyObject *descr,
1106
                              unsigned int tp_version,
1107
                              DescriptorClassification kind, bool is_method,
1108
                              uint32_t shared_keys_version);
1109
static int specialize_class_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name);
1110
1111
/* Returns true if instances of obj's class are
1112
 * likely to have `name` in their __dict__.
1113
 * For objects with inline values, we check in the shared keys.
1114
 * For other objects, we check their actual dictionary.
1115
 */
1116
static bool
1117
instance_has_key(PyObject *obj, PyObject *name, uint32_t *shared_keys_version)
1118
733k
{
1119
733k
    PyTypeObject *cls = Py_TYPE(obj);
1120
733k
    if ((cls->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {
1121
103k
        return false;
1122
103k
    }
1123
629k
    if (cls->tp_flags & Py_TPFLAGS_INLINE_VALUES) {
1124
572k
        PyDictKeysObject *keys = ((PyHeapTypeObject *)cls)->ht_cached_keys;
1125
572k
        Py_ssize_t index =
1126
572k
            _PyDictKeys_StringLookupAndVersion(keys, name, shared_keys_version);
1127
572k
        return index >= 0;
1128
572k
    }
1129
57.4k
    PyDictObject *dict = _PyObject_GetManagedDict(obj);
1130
57.4k
    if (dict == NULL || !PyDict_CheckExact(dict)) {
1131
0
        return false;
1132
0
    }
1133
57.4k
    bool result;
1134
57.4k
    Py_BEGIN_CRITICAL_SECTION(dict);
1135
57.4k
    if (dict->ma_values) {
1136
57.4k
        result = false;
1137
57.4k
    }
1138
0
    else {
1139
0
        result = (_PyDict_LookupIndex(dict, name) >= 0);
1140
0
    }
1141
57.4k
    Py_END_CRITICAL_SECTION();
1142
57.4k
    return result;
1143
57.4k
}
1144
1145
static int
1146
do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name,
1147
                                 bool shadow, uint32_t shared_keys_version,
1148
                                 DescriptorClassification kind, PyObject *descr, unsigned int tp_version)
1149
733k
{
1150
733k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
1151
733k
    PyTypeObject *type = Py_TYPE(owner);
1152
733k
    if (tp_version == 0) {
1153
6.03k
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
1154
6.03k
        return -1;
1155
6.03k
    }
1156
727k
    uint8_t oparg = FT_ATOMIC_LOAD_UINT8_RELAXED(instr->op.arg);
1157
727k
    switch(kind) {
1158
170
        case OVERRIDING:
1159
170
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
1160
170
            return -1;
1161
119k
        case METHOD:
1162
119k
        {
1163
119k
            if (shadow) {
1164
72
                goto try_instance;
1165
72
            }
1166
119k
            if (oparg & 1) {
1167
61.8k
                if (specialize_attr_loadclassattr(owner, instr, name, descr,
1168
61.8k
                                                  tp_version, kind, true,
1169
61.8k
                                                  shared_keys_version)) {
1170
61.0k
                    return 0;
1171
61.0k
                }
1172
786
                else {
1173
786
                    return -1;
1174
786
                }
1175
61.8k
            }
1176
57.4k
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
1177
57.4k
            return -1;
1178
119k
        }
1179
206k
        case PROPERTY:
1180
206k
        {
1181
206k
            _PyLoadMethodCache *lm_cache = (_PyLoadMethodCache *)(instr + 1);
1182
206k
            assert(Py_TYPE(descr) == &PyProperty_Type);
1183
206k
            PyObject *fget = ((_PyPropertyObject *)descr)->prop_get;
1184
206k
            if (fget == NULL) {
1185
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
1186
0
                return -1;
1187
0
            }
1188
206k
            if (!Py_IS_TYPE(fget, &PyFunction_Type)) {
1189
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_PROPERTY_NOT_PY_FUNCTION);
1190
0
                return -1;
1191
0
            }
1192
206k
            if (!function_check_args(fget, 1, LOAD_ATTR)) {
1193
0
                return -1;
1194
0
            }
1195
206k
            if (oparg & 1) {
1196
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
1197
0
                return -1;
1198
0
            }
1199
            /* Don't specialize if PEP 523 is active */
1200
206k
            if (_PyInterpreterState_GET()->eval_frame) {
1201
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER);
1202
0
                return -1;
1203
0
            }
1204
            #ifdef Py_GIL_DISABLED
1205
            if (!_PyObject_HasDeferredRefcount(fget)) {
1206
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED);
1207
                return -1;
1208
            }
1209
            #endif
1210
206k
            assert(tp_version != 0);
1211
206k
            write_u32(lm_cache->type_version, tp_version);
1212
            /* borrowed */
1213
206k
            write_ptr(lm_cache->descr, fget);
1214
206k
            specialize(instr, LOAD_ATTR_PROPERTY);
1215
206k
            return 0;
1216
206k
        }
1217
394
        case OBJECT_SLOT:
1218
394
        {
1219
394
            PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
1220
394
            struct PyMemberDef *dmem = member->d_member;
1221
394
            Py_ssize_t offset = dmem->offset;
1222
394
            if (!PyObject_TypeCheck(owner, member->d_common.d_type)) {
1223
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
1224
0
                return -1;
1225
0
            }
1226
394
            if (dmem->flags & Py_AUDIT_READ) {
1227
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_AUDITED_SLOT);
1228
0
                return -1;
1229
0
            }
1230
394
            if (offset != (uint16_t)offset) {
1231
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE);
1232
0
                return -1;
1233
0
            }
1234
394
            assert(dmem->type == Py_T_OBJECT_EX || dmem->type == _Py_T_OBJECT);
1235
394
            assert(offset > 0);
1236
394
            cache->index = (uint16_t)offset;
1237
394
            write_u32(cache->version, tp_version);
1238
394
            specialize(instr, LOAD_ATTR_SLOT);
1239
394
            return 0;
1240
394
        }
1241
59.4k
        case DUNDER_CLASS:
1242
59.4k
        {
1243
59.4k
            Py_ssize_t offset = offsetof(PyObject, ob_type);
1244
59.4k
            assert(offset == (uint16_t)offset);
1245
59.4k
            cache->index = (uint16_t)offset;
1246
59.4k
            write_u32(cache->version, tp_version);
1247
59.4k
            specialize(instr, LOAD_ATTR_SLOT);
1248
59.4k
            return 0;
1249
394
        }
1250
98
        case OTHER_SLOT:
1251
98
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT);
1252
98
            return -1;
1253
233
        case MUTABLE:
1254
233
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
1255
233
            return -1;
1256
2
        case GETSET_OVERRIDDEN:
1257
2
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OVERRIDDEN);
1258
2
            return -1;
1259
0
        case GETATTRIBUTE_IS_PYTHON_FUNCTION:
1260
0
        {
1261
0
            assert(Py_IS_TYPE(descr, &PyFunction_Type));
1262
0
            _PyLoadMethodCache *lm_cache = (_PyLoadMethodCache *)(instr + 1);
1263
0
            if (!function_check_args(descr, 2, LOAD_ATTR)) {
1264
0
                return -1;
1265
0
            }
1266
0
            if (oparg & 1) {
1267
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
1268
0
                return -1;
1269
0
            }
1270
0
            uint32_t version = function_get_version(descr, LOAD_ATTR);
1271
0
            if (version == 0) {
1272
0
                return -1;
1273
0
            }
1274
            /* Don't specialize if PEP 523 is active */
1275
0
            if (_PyInterpreterState_GET()->eval_frame) {
1276
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER);
1277
0
                return -1;
1278
0
            }
1279
            #ifdef Py_GIL_DISABLED
1280
            if (!_PyObject_HasDeferredRefcount(descr)) {
1281
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED);
1282
                return -1;
1283
            }
1284
            #endif
1285
0
            write_u32(lm_cache->keys_version, version);
1286
            /* borrowed */
1287
0
            write_ptr(lm_cache->descr, descr);
1288
0
            write_u32(lm_cache->type_version, tp_version);
1289
0
            specialize(instr, LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN);
1290
0
            return 0;
1291
0
        }
1292
0
        case BUILTIN_CLASSMETHOD:
1293
126
        case PYTHON_CLASSMETHOD:
1294
237
        case NON_OVERRIDING:
1295
237
            if (shadow) {
1296
0
                goto try_instance;
1297
0
            }
1298
237
            return -1;
1299
91.1k
        case NON_DESCRIPTOR:
1300
91.1k
            if (shadow) {
1301
15.2k
                goto try_instance;
1302
15.2k
            }
1303
75.9k
            if ((oparg & 1) == 0) {
1304
75.9k
                if (specialize_attr_loadclassattr(owner, instr, name, descr,
1305
75.9k
                                                  tp_version, kind, false,
1306
75.9k
                                                  shared_keys_version)) {
1307
75.2k
                    return 0;
1308
75.2k
                }
1309
75.9k
            }
1310
658
            return -1;
1311
249k
        case ABSENT:
1312
249k
            if (shadow) {
1313
170k
                goto try_instance;
1314
170k
            }
1315
79.5k
            set_counter((_Py_BackoffCounter*)instr + 1, adaptive_counter_cooldown());
1316
79.5k
            return 0;
1317
727k
    }
1318
727k
    Py_UNREACHABLE();
1319
185k
try_instance:
1320
185k
    if (specialize_dict_access(owner, instr, type, kind, name, tp_version,
1321
185k
                               LOAD_ATTR, LOAD_ATTR_INSTANCE_VALUE, LOAD_ATTR_WITH_HINT))
1322
181k
    {
1323
181k
        return 0;
1324
181k
    }
1325
4.47k
    return -1;
1326
185k
}
1327
1328
static int
1329
specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name)
1330
733k
{
1331
    // 0 is not a valid version
1332
733k
    uint32_t shared_keys_version = 0;
1333
733k
    bool shadow = instance_has_key(owner, name, &shared_keys_version);
1334
733k
    PyObject *descr = NULL;
1335
733k
    unsigned int tp_version = 0;
1336
733k
    PyTypeObject *type = Py_TYPE(owner);
1337
733k
    DescriptorClassification kind = analyze_descriptor_load(type, name, &descr, &tp_version);
1338
733k
    int result = do_specialize_instance_load_attr(owner, instr, name, shadow, shared_keys_version, kind, descr, tp_version);
1339
733k
    Py_XDECREF(descr);
1340
733k
    return result;
1341
733k
}
1342
1343
Py_NO_INLINE void
1344
_Py_Specialize_LoadAttr(_PyStackRef owner_st, _Py_CODEUNIT *instr, PyObject *name)
1345
741k
{
1346
741k
    PyObject *owner = PyStackRef_AsPyObjectBorrow(owner_st);
1347
1348
741k
    assert(ENABLE_SPECIALIZATION_FT);
1349
741k
    assert(_PyOpcode_Caches[LOAD_ATTR] == INLINE_CACHE_ENTRIES_LOAD_ATTR);
1350
741k
    PyTypeObject *type = Py_TYPE(owner);
1351
741k
    bool fail;
1352
741k
    if (!_PyType_IsReady(type)) {
1353
        // We *might* not really need this check, but we inherited it from
1354
        // PyObject_GenericGetAttr and friends... and this way we still do the
1355
        // right thing if someone forgets to call PyType_Ready(type):
1356
0
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER);
1357
0
        fail = true;
1358
0
    }
1359
741k
    else if (Py_TYPE(owner)->tp_getattro == PyModule_Type.tp_getattro) {
1360
2.52k
        fail = specialize_module_load_attr(owner, instr, name);
1361
2.52k
    }
1362
738k
    else if (PyType_Check(owner)) {
1363
5.48k
        fail = specialize_class_load_attr(owner, instr, name);
1364
5.48k
    }
1365
733k
    else {
1366
733k
        fail = specialize_instance_load_attr(owner, instr, name);
1367
733k
    }
1368
1369
741k
    if (fail) {
1370
74.9k
        unspecialize(instr);
1371
74.9k
    }
1372
741k
}
1373
1374
Py_NO_INLINE void
1375
_Py_Specialize_StoreAttr(_PyStackRef owner_st, _Py_CODEUNIT *instr, PyObject *name)
1376
199k
{
1377
199k
    PyObject *owner = PyStackRef_AsPyObjectBorrow(owner_st);
1378
1379
199k
    assert(ENABLE_SPECIALIZATION_FT);
1380
199k
    assert(_PyOpcode_Caches[STORE_ATTR] == INLINE_CACHE_ENTRIES_STORE_ATTR);
1381
199k
    PyObject *descr = NULL;
1382
199k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
1383
199k
    PyTypeObject *type = Py_TYPE(owner);
1384
199k
    if (!_PyType_IsReady(type)) {
1385
        // We *might* not really need this check, but we inherited it from
1386
        // PyObject_GenericSetAttr and friends... and this way we still do the
1387
        // right thing if someone forgets to call PyType_Ready(type):
1388
0
        SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OTHER);
1389
0
        goto fail;
1390
0
    }
1391
199k
    if (PyModule_CheckExact(owner)) {
1392
415
        SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OVERRIDDEN);
1393
415
        goto fail;
1394
415
    }
1395
199k
    unsigned int tp_version = 0;
1396
199k
    DescriptorClassification kind = analyze_descriptor_store(type, name, &descr, &tp_version);
1397
199k
    if (tp_version == 0) {
1398
225
        goto fail;
1399
225
    }
1400
199k
    assert(descr != NULL || kind == ABSENT || kind == GETSET_OVERRIDDEN);
1401
199k
    switch(kind) {
1402
157
        case OVERRIDING:
1403
157
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
1404
157
            goto fail;
1405
12
        case METHOD:
1406
12
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_METHOD);
1407
12
            goto fail;
1408
16
        case PROPERTY:
1409
16
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_PROPERTY);
1410
16
            goto fail;
1411
174
        case OBJECT_SLOT:
1412
174
        {
1413
174
            PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
1414
174
            struct PyMemberDef *dmem = member->d_member;
1415
174
            Py_ssize_t offset = dmem->offset;
1416
174
            if (!PyObject_TypeCheck(owner, member->d_common.d_type)) {
1417
0
                SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_EXPECTED_ERROR);
1418
0
                goto fail;
1419
0
            }
1420
174
            if (dmem->flags & Py_READONLY) {
1421
0
                SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_READ_ONLY);
1422
0
                goto fail;
1423
0
            }
1424
174
            if (offset != (uint16_t)offset) {
1425
0
                SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OUT_OF_RANGE);
1426
0
                goto fail;
1427
0
            }
1428
174
            assert(dmem->type == Py_T_OBJECT_EX || dmem->type == _Py_T_OBJECT);
1429
174
            assert(offset > 0);
1430
174
            cache->index = (uint16_t)offset;
1431
174
            write_u32(cache->version, tp_version);
1432
174
            specialize(instr, STORE_ATTR_SLOT);
1433
174
            goto success;
1434
174
        }
1435
0
        case DUNDER_CLASS:
1436
0
        case OTHER_SLOT:
1437
0
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT);
1438
0
            goto fail;
1439
0
        case MUTABLE:
1440
0
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
1441
0
            goto fail;
1442
0
        case GETATTRIBUTE_IS_PYTHON_FUNCTION:
1443
0
        case GETSET_OVERRIDDEN:
1444
0
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OVERRIDDEN);
1445
0
            goto fail;
1446
0
        case BUILTIN_CLASSMETHOD:
1447
0
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD_OBJ);
1448
0
            goto fail;
1449
0
        case PYTHON_CLASSMETHOD:
1450
0
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_CLASS_METHOD_OBJ);
1451
0
            goto fail;
1452
0
        case NON_OVERRIDING:
1453
0
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_DESCRIPTOR);
1454
0
            goto fail;
1455
1.48k
        case NON_DESCRIPTOR:
1456
1.48k
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE);
1457
1.48k
            goto fail;
1458
197k
        case ABSENT:
1459
197k
            if (specialize_dict_access(owner, instr, type, kind, name, tp_version,
1460
197k
                                       STORE_ATTR, STORE_ATTR_INSTANCE_VALUE,
1461
197k
                                       STORE_ATTR_WITH_HINT)) {
1462
193k
                goto success;
1463
193k
            }
1464
199k
    }
1465
5.93k
fail:
1466
5.93k
    Py_XDECREF(descr);
1467
5.93k
    unspecialize(instr);
1468
5.93k
    return;
1469
193k
success:
1470
193k
    Py_XDECREF(descr);
1471
193k
    return;
1472
199k
}
1473
1474
#ifdef Py_STATS
1475
static int
1476
load_attr_fail_kind(DescriptorClassification kind)
1477
{
1478
    switch (kind) {
1479
        case OVERRIDING:
1480
            return SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR;
1481
        case METHOD:
1482
            return SPEC_FAIL_ATTR_METHOD;
1483
        case PROPERTY:
1484
            return SPEC_FAIL_ATTR_PROPERTY;
1485
        case OBJECT_SLOT:
1486
            return SPEC_FAIL_ATTR_OBJECT_SLOT;
1487
        case OTHER_SLOT:
1488
            return SPEC_FAIL_ATTR_NON_OBJECT_SLOT;
1489
        case DUNDER_CLASS:
1490
            return SPEC_FAIL_OTHER;
1491
        case MUTABLE:
1492
            return SPEC_FAIL_ATTR_MUTABLE_CLASS;
1493
        case GETSET_OVERRIDDEN:
1494
        case GETATTRIBUTE_IS_PYTHON_FUNCTION:
1495
            return SPEC_FAIL_OVERRIDDEN;
1496
        case BUILTIN_CLASSMETHOD:
1497
            return SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD;
1498
        case PYTHON_CLASSMETHOD:
1499
            return SPEC_FAIL_ATTR_CLASS_METHOD_OBJ;
1500
        case NON_OVERRIDING:
1501
            return SPEC_FAIL_ATTR_NON_OVERRIDING_DESCRIPTOR;
1502
        case NON_DESCRIPTOR:
1503
            return SPEC_FAIL_ATTR_NOT_DESCRIPTOR;
1504
        case ABSENT:
1505
            return SPEC_FAIL_ATTR_INSTANCE_ATTRIBUTE;
1506
    }
1507
    Py_UNREACHABLE();
1508
}
1509
#endif   // Py_STATS
1510
1511
static int
1512
specialize_class_load_attr(PyObject *owner, _Py_CODEUNIT *instr,
1513
                             PyObject *name)
1514
5.48k
{
1515
5.48k
    assert(PyType_Check(owner));
1516
5.48k
    PyTypeObject *cls = (PyTypeObject *)owner;
1517
5.48k
    _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1);
1518
5.48k
    if (Py_TYPE(cls)->tp_getattro != _Py_type_getattro) {
1519
0
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METACLASS_OVERRIDDEN);
1520
0
        return -1;
1521
0
    }
1522
5.48k
    unsigned int meta_version = 0;
1523
5.48k
    PyObject *metadescriptor = _PyType_LookupRefAndVersion(Py_TYPE(cls), name, &meta_version);
1524
5.48k
    DescriptorClassification metakind = classify_descriptor(metadescriptor, false);
1525
5.48k
    Py_XDECREF(metadescriptor);
1526
5.48k
    switch (metakind) {
1527
281
        case METHOD:
1528
384
        case NON_DESCRIPTOR:
1529
505
        case NON_OVERRIDING:
1530
505
        case BUILTIN_CLASSMETHOD:
1531
505
        case PYTHON_CLASSMETHOD:
1532
2.73k
        case ABSENT:
1533
2.73k
            break;
1534
2.74k
        default:
1535
2.74k
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METACLASS_ATTRIBUTE);
1536
2.74k
            return -1;
1537
5.48k
    }
1538
2.73k
    PyObject *descr = NULL;
1539
2.73k
    DescriptorClassification kind = 0;
1540
2.73k
    unsigned int tp_version = 0;
1541
2.73k
    kind = analyze_descriptor_load(cls, name, &descr, &tp_version);
1542
2.73k
    if (tp_version == 0) {
1543
36
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
1544
36
        Py_XDECREF(descr);
1545
36
        return -1;
1546
36
    }
1547
2.70k
    bool metaclass_check = false;
1548
2.70k
    if ((Py_TYPE(cls)->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) {
1549
1.05k
        metaclass_check = true;
1550
1.05k
        if (meta_version == 0) {
1551
0
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
1552
0
            Py_XDECREF(descr);
1553
0
            return -1;
1554
0
        }
1555
1.05k
    }
1556
2.70k
    switch (kind) {
1557
250
        case METHOD:
1558
889
        case NON_DESCRIPTOR:
1559
            #ifdef Py_GIL_DISABLED
1560
            if (!_PyObject_HasDeferredRefcount(descr)) {
1561
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED);
1562
                Py_XDECREF(descr);
1563
                return -1;
1564
            }
1565
            #endif
1566
889
            write_u32(cache->type_version, tp_version);
1567
889
            write_ptr(cache->descr, descr);
1568
889
            if (metaclass_check) {
1569
459
                write_u32(cache->keys_version, meta_version);
1570
459
                specialize(instr, LOAD_ATTR_CLASS_WITH_METACLASS_CHECK);
1571
459
            }
1572
430
            else {
1573
430
                specialize(instr, LOAD_ATTR_CLASS);
1574
430
            }
1575
889
            Py_XDECREF(descr);
1576
889
            return 0;
1577
#ifdef Py_STATS
1578
        case ABSENT:
1579
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
1580
            Py_XDECREF(descr);
1581
            return -1;
1582
#endif
1583
1.81k
        default:
1584
1.81k
            SPECIALIZATION_FAIL(LOAD_ATTR, load_attr_fail_kind(kind));
1585
1.81k
            Py_XDECREF(descr);
1586
1.81k
            return -1;
1587
2.70k
    }
1588
2.70k
}
1589
1590
// Please collect stats carefully before and after modifying. A subtle change
1591
// can cause a significant drop in cache hits. A possible test is
1592
// python.exe -m test_typing test_re test_dis test_zlib.
1593
static int
1594
specialize_attr_loadclassattr(PyObject *owner, _Py_CODEUNIT *instr,
1595
                              PyObject *name, PyObject *descr,
1596
                              unsigned int tp_version,
1597
                              DescriptorClassification kind, bool is_method,
1598
                              uint32_t shared_keys_version)
1599
137k
{
1600
137k
    _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1);
1601
137k
    PyTypeObject *owner_cls = Py_TYPE(owner);
1602
1603
137k
    assert(descr != NULL);
1604
137k
    assert((is_method && kind == METHOD) || (!is_method && kind == NON_DESCRIPTOR));
1605
1606
    #ifdef Py_GIL_DISABLED
1607
    if (!_PyObject_HasDeferredRefcount(descr)) {
1608
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED);
1609
        return 0;
1610
    }
1611
    #endif
1612
1613
137k
    unsigned long tp_flags = PyType_GetFlags(owner_cls);
1614
137k
    if (tp_flags & Py_TPFLAGS_INLINE_VALUES) {
1615
118k
        #ifndef Py_GIL_DISABLED
1616
118k
        assert(_PyDictKeys_StringLookup(
1617
118k
                   ((PyHeapTypeObject *)owner_cls)->ht_cached_keys, name) < 0);
1618
118k
        #endif
1619
118k
        if (shared_keys_version == 0) {
1620
0
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
1621
0
            return 0;
1622
0
        }
1623
118k
        write_u32(cache->keys_version, shared_keys_version);
1624
118k
        specialize(instr, is_method ? LOAD_ATTR_METHOD_WITH_VALUES : LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES);
1625
118k
    }
1626
19.1k
    else {
1627
19.1k
        Py_ssize_t dictoffset;
1628
19.1k
        if (tp_flags & Py_TPFLAGS_MANAGED_DICT) {
1629
781
            dictoffset = MANAGED_DICT_OFFSET;
1630
781
        }
1631
18.4k
        else {
1632
18.4k
            dictoffset = owner_cls->tp_dictoffset;
1633
18.4k
            if (dictoffset < 0 || dictoffset > INT16_MAX + MANAGED_DICT_OFFSET) {
1634
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE);
1635
0
                return 0;
1636
0
            }
1637
18.4k
        }
1638
19.1k
        if (dictoffset == 0) {
1639
17.6k
            specialize(instr, is_method ? LOAD_ATTR_METHOD_NO_DICT : LOAD_ATTR_NONDESCRIPTOR_NO_DICT);
1640
17.6k
        }
1641
1.48k
        else if (is_method) {
1642
828
            PyObject **addr = (PyObject **)((char *)owner + dictoffset);
1643
828
            PyObject *dict = FT_ATOMIC_LOAD_PTR_ACQUIRE(*addr);
1644
828
            if (dict) {
1645
786
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);
1646
786
                return 0;
1647
786
            }
1648
            /* Cache entries must be unsigned values, so we offset the
1649
             * dictoffset by MANAGED_DICT_OFFSET.
1650
             * We do the reverse offset in LOAD_ATTR_METHOD_LAZY_DICT */
1651
42
            dictoffset -= MANAGED_DICT_OFFSET;
1652
42
            assert(((uint16_t)dictoffset) == dictoffset);
1653
42
            cache->dict_offset = (uint16_t)dictoffset;
1654
42
            specialize(instr, LOAD_ATTR_METHOD_LAZY_DICT);
1655
42
        }
1656
658
        else {
1657
658
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE);
1658
658
            return 0;
1659
658
        }
1660
19.1k
    }
1661
    /* `descr` is borrowed. This is safe for methods (even inherited ones from
1662
    *  super classes!) as long as tp_version_tag is validated for two main reasons:
1663
    *
1664
    *  1. The class will always hold a reference to the method so it will
1665
    *  usually not be GC-ed. Should it be deleted in Python, e.g.
1666
    *  `del obj.meth`, tp_version_tag will be invalidated, because of reason 2.
1667
    *
1668
    *  2. The pre-existing type method cache (MCACHE) uses the same principles
1669
    *  of caching a borrowed descriptor. The MCACHE infrastructure does all the
1670
    *  heavy lifting for us. E.g. it invalidates tp_version_tag on any MRO
1671
    *  modification, on any type object change along said MRO, etc. (see
1672
    *  PyType_Modified usages in typeobject.c). The MCACHE has been
1673
    *  working since Python 2.6 and it's battle-tested.
1674
    */
1675
136k
    write_u32(cache->type_version, tp_version);
1676
136k
    write_ptr(cache->descr, descr);
1677
136k
    return 1;
1678
137k
}
1679
1680
1681
static void
1682
specialize_load_global_lock_held(
1683
    PyObject *globals, PyObject *builtins,
1684
    _Py_CODEUNIT *instr, PyObject *name)
1685
13.3k
{
1686
13.3k
    assert(ENABLE_SPECIALIZATION_FT);
1687
13.3k
    assert(_PyOpcode_Caches[LOAD_GLOBAL] == INLINE_CACHE_ENTRIES_LOAD_GLOBAL);
1688
    /* Use inline cache */
1689
13.3k
    _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)(instr + 1);
1690
13.3k
    assert(PyUnicode_CheckExact(name));
1691
13.3k
    if (!PyDict_CheckExact(globals)) {
1692
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_DICT);
1693
0
        goto fail;
1694
0
    }
1695
13.3k
    PyDictKeysObject * globals_keys = ((PyDictObject *)globals)->ma_keys;
1696
13.3k
    if (!DK_IS_UNICODE(globals_keys)) {
1697
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT);
1698
0
        goto fail;
1699
0
    }
1700
13.3k
    Py_ssize_t index = _PyDictKeys_StringLookup(globals_keys, name);
1701
13.3k
    if (index == DKIX_ERROR) {
1702
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_EXPECTED_ERROR);
1703
0
        goto fail;
1704
0
    }
1705
13.3k
    PyInterpreterState *interp = _PyInterpreterState_GET();
1706
13.3k
    if (index != DKIX_EMPTY) {
1707
7.99k
        if (index != (uint16_t)index) {
1708
0
            SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1709
0
            goto fail;
1710
0
        }
1711
7.99k
        uint32_t keys_version = _PyDict_GetKeysVersionForCurrentState(
1712
7.99k
                interp, (PyDictObject*) globals);
1713
7.99k
        if (keys_version == 0) {
1714
0
            SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
1715
0
            goto fail;
1716
0
        }
1717
7.99k
        if (keys_version != (uint16_t)keys_version) {
1718
0
            SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1719
0
            goto fail;
1720
0
        }
1721
7.99k
        cache->index = (uint16_t)index;
1722
7.99k
        cache->module_keys_version = (uint16_t)keys_version;
1723
7.99k
        specialize(instr, LOAD_GLOBAL_MODULE);
1724
7.99k
        return;
1725
7.99k
    }
1726
5.34k
    if (!PyDict_CheckExact(builtins)) {
1727
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_DICT);
1728
0
        goto fail;
1729
0
    }
1730
5.34k
    PyDictKeysObject * builtin_keys = ((PyDictObject *)builtins)->ma_keys;
1731
5.34k
    if (!DK_IS_UNICODE(builtin_keys)) {
1732
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT);
1733
0
        goto fail;
1734
0
    }
1735
5.34k
    index = _PyDictKeys_StringLookup(builtin_keys, name);
1736
5.34k
    if (index == DKIX_ERROR) {
1737
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_EXPECTED_ERROR);
1738
0
        goto fail;
1739
0
    }
1740
5.34k
    if (index != (uint16_t)index) {
1741
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1742
0
        goto fail;
1743
0
    }
1744
5.34k
    uint32_t globals_version = _PyDict_GetKeysVersionForCurrentState(
1745
5.34k
            interp, (PyDictObject*) globals);
1746
5.34k
    if (globals_version == 0) {
1747
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
1748
0
        goto fail;
1749
0
    }
1750
5.34k
    if (globals_version != (uint16_t)globals_version) {
1751
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1752
0
        goto fail;
1753
0
    }
1754
5.34k
    uint32_t builtins_version = _PyDict_GetKeysVersionForCurrentState(
1755
5.34k
            interp, (PyDictObject*) builtins);
1756
5.34k
    if (builtins_version == 0) {
1757
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
1758
0
        goto fail;
1759
0
    }
1760
5.34k
    if (builtins_version > UINT16_MAX) {
1761
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1762
0
        goto fail;
1763
0
    }
1764
5.34k
    cache->index = (uint16_t)index;
1765
5.34k
    cache->module_keys_version = (uint16_t)globals_version;
1766
5.34k
    cache->builtin_keys_version = (uint16_t)builtins_version;
1767
5.34k
    specialize(instr, LOAD_GLOBAL_BUILTIN);
1768
5.34k
    return;
1769
0
fail:
1770
0
    unspecialize(instr);
1771
0
}
1772
1773
Py_NO_INLINE void
1774
_Py_Specialize_LoadGlobal(
1775
    PyObject *globals, PyObject *builtins,
1776
    _Py_CODEUNIT *instr, PyObject *name)
1777
13.3k
{
1778
13.3k
    Py_BEGIN_CRITICAL_SECTION2(globals, builtins);
1779
13.3k
    specialize_load_global_lock_held(globals, builtins, instr, name);
1780
13.3k
    Py_END_CRITICAL_SECTION2();
1781
13.3k
}
1782
1783
static int
1784
223k
function_kind(PyCodeObject *code) {
1785
223k
    int flags = code->co_flags;
1786
223k
    if ((flags & (CO_VARKEYWORDS | CO_VARARGS)) || code->co_kwonlyargcount) {
1787
902
        return SPEC_FAIL_CODE_COMPLEX_PARAMETERS;
1788
902
    }
1789
222k
    if ((flags & CO_OPTIMIZED) == 0) {
1790
0
        return SPEC_FAIL_CODE_NOT_OPTIMIZED;
1791
0
    }
1792
222k
    return SIMPLE_FUNCTION;
1793
222k
}
1794
1795
/* Returning false indicates a failure. */
1796
static bool
1797
function_check_args(PyObject *o, int expected_argcount, int opcode)
1798
206k
{
1799
206k
    assert(Py_IS_TYPE(o, &PyFunction_Type));
1800
206k
    PyFunctionObject *func = (PyFunctionObject *)o;
1801
206k
    PyCodeObject *fcode = (PyCodeObject *)func->func_code;
1802
206k
    int kind = function_kind(fcode);
1803
206k
    if (kind != SIMPLE_FUNCTION) {
1804
0
        SPECIALIZATION_FAIL(opcode, kind);
1805
0
        return false;
1806
0
    }
1807
206k
    if (fcode->co_argcount != expected_argcount) {
1808
0
        SPECIALIZATION_FAIL(opcode, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1809
0
        return false;
1810
0
    }
1811
206k
    return true;
1812
206k
}
1813
1814
/* Returning 0 indicates a failure. */
1815
static uint32_t
1816
function_get_version(PyObject *o, int opcode)
1817
0
{
1818
0
    assert(Py_IS_TYPE(o, &PyFunction_Type));
1819
0
    PyFunctionObject *func = (PyFunctionObject *)o;
1820
0
    uint32_t version = _PyFunction_GetVersionForCurrentState(func);
1821
0
    if (!_PyFunction_IsVersionValid(version)) {
1822
0
        SPECIALIZATION_FAIL(opcode, SPEC_FAIL_OUT_OF_VERSIONS);
1823
0
        return 0;
1824
0
    }
1825
0
    return version;
1826
0
}
1827
1828
#ifdef Py_STATS
1829
static int
1830
store_subscr_fail_kind(PyObject *container, PyObject *sub)
1831
{
1832
    PyTypeObject *container_type = Py_TYPE(container);
1833
    PyMappingMethods *as_mapping = container_type->tp_as_mapping;
1834
    if (as_mapping && (as_mapping->mp_ass_subscript
1835
                       == PyDict_Type.tp_as_mapping->mp_ass_subscript)) {
1836
        return SPEC_FAIL_SUBSCR_DICT_SUBCLASS_NO_OVERRIDE;
1837
    }
1838
    if (PyObject_CheckBuffer(container)) {
1839
        if (PyLong_CheckExact(sub) && (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub))) {
1840
            return SPEC_FAIL_OUT_OF_RANGE;
1841
        }
1842
        else if (strcmp(container_type->tp_name, "array.array") == 0) {
1843
            if (PyLong_CheckExact(sub)) {
1844
                return SPEC_FAIL_SUBSCR_ARRAY_INT;
1845
            }
1846
            else if (PySlice_Check(sub)) {
1847
                return SPEC_FAIL_SUBSCR_ARRAY_SLICE;
1848
            }
1849
            else {
1850
                return SPEC_FAIL_OTHER;
1851
            }
1852
        }
1853
        else if (PyByteArray_CheckExact(container)) {
1854
            if (PyLong_CheckExact(sub)) {
1855
                return SPEC_FAIL_SUBSCR_BYTEARRAY_INT;
1856
            }
1857
            else if (PySlice_Check(sub)) {
1858
                return SPEC_FAIL_SUBSCR_BYTEARRAY_SLICE;
1859
            }
1860
            else {
1861
                return SPEC_FAIL_OTHER;
1862
            }
1863
        }
1864
        else {
1865
            if (PyLong_CheckExact(sub)) {
1866
                return SPEC_FAIL_SUBSCR_BUFFER_INT;
1867
            }
1868
            else if (PySlice_Check(sub)) {
1869
                return SPEC_FAIL_SUBSCR_BUFFER_SLICE;
1870
            }
1871
            else {
1872
                return SPEC_FAIL_OTHER;
1873
            }
1874
        }
1875
        return SPEC_FAIL_OTHER;
1876
    }
1877
    PyObject *descriptor = _PyType_Lookup(container_type, &_Py_ID(__setitem__));
1878
    if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {
1879
        PyFunctionObject *func = (PyFunctionObject *)descriptor;
1880
        PyCodeObject *code = (PyCodeObject *)func->func_code;
1881
        int kind = function_kind(code);
1882
        if (kind == SIMPLE_FUNCTION) {
1883
            return SPEC_FAIL_SUBSCR_PY_SIMPLE;
1884
        }
1885
        else {
1886
            return SPEC_FAIL_SUBSCR_PY_OTHER;
1887
        }
1888
    }
1889
    return SPEC_FAIL_OTHER;
1890
}
1891
#endif
1892
1893
Py_NO_INLINE void
1894
_Py_Specialize_StoreSubscr(_PyStackRef container_st, _PyStackRef sub_st, _Py_CODEUNIT *instr)
1895
1.21k
{
1896
1.21k
    PyObject *container = PyStackRef_AsPyObjectBorrow(container_st);
1897
1.21k
    PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st);
1898
1899
1.21k
    assert(ENABLE_SPECIALIZATION_FT);
1900
1.21k
    PyTypeObject *container_type = Py_TYPE(container);
1901
1.21k
    if (container_type == &PyList_Type) {
1902
170
        if (PyLong_CheckExact(sub)) {
1903
168
            if (_PyLong_IsNonNegativeCompact((PyLongObject *)sub)
1904
168
                && ((PyLongObject *)sub)->long_value.ob_digit[0] < (size_t)PyList_GET_SIZE(container))
1905
112
            {
1906
112
                specialize(instr, STORE_SUBSCR_LIST_INT);
1907
112
                return;
1908
112
            }
1909
56
            else {
1910
56
                SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);
1911
56
                unspecialize(instr);
1912
56
                return;
1913
56
            }
1914
168
        }
1915
2
        else if (PySlice_Check(sub)) {
1916
2
            SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_LIST_SLICE);
1917
2
            unspecialize(instr);
1918
2
            return;
1919
2
        }
1920
0
        else {
1921
0
            SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
1922
0
            unspecialize(instr);
1923
0
            return;
1924
0
        }
1925
170
    }
1926
1.04k
    if (container_type == &PyDict_Type) {
1927
745
        specialize(instr, STORE_SUBSCR_DICT);
1928
745
        return;
1929
745
    }
1930
299
    SPECIALIZATION_FAIL(STORE_SUBSCR, store_subscr_fail_kind(container, sub));
1931
299
    unspecialize(instr);
1932
299
}
1933
1934
/* Returns a strong reference. */
1935
static PyObject *
1936
get_init_for_simple_managed_python_class(PyTypeObject *tp, unsigned int *tp_version)
1937
377
{
1938
377
    assert(tp->tp_new == PyBaseObject_Type.tp_new);
1939
377
    if (tp->tp_alloc != PyType_GenericAlloc) {
1940
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OVERRIDDEN);
1941
0
        return NULL;
1942
0
    }
1943
377
    unsigned long tp_flags = PyType_GetFlags(tp);
1944
377
    if (!(tp_flags & Py_TPFLAGS_HEAPTYPE)) {
1945
        /* Is this possible? */
1946
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_EXPECTED_ERROR);
1947
0
        return NULL;
1948
0
    }
1949
377
    PyObject *init = _PyType_LookupRefAndVersion(tp, &_Py_ID(__init__), tp_version);
1950
377
    if (init == NULL || !PyFunction_Check(init)) {
1951
146
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_INIT_NOT_PYTHON);
1952
146
        Py_XDECREF(init);
1953
146
        return NULL;
1954
146
    }
1955
231
    int kind = function_kind((PyCodeObject *)PyFunction_GET_CODE(init));
1956
231
    if (kind != SIMPLE_FUNCTION) {
1957
17
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_INIT_NOT_SIMPLE);
1958
17
        Py_DECREF(init);
1959
17
        return NULL;
1960
17
    }
1961
214
    return init;
1962
231
}
1963
1964
static int
1965
specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
1966
1.52k
{
1967
1.52k
    assert(PyType_Check(callable));
1968
1.52k
    PyTypeObject *tp = _PyType_CAST(callable);
1969
1.52k
    if (tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) {
1970
948
        int oparg = instr->op.arg;
1971
948
        if (nargs == 1 && oparg == 1) {
1972
600
            if (tp == &PyUnicode_Type) {
1973
74
                specialize(instr, CALL_STR_1);
1974
74
                return 0;
1975
74
            }
1976
526
            else if (tp == &PyType_Type) {
1977
119
                specialize(instr, CALL_TYPE_1);
1978
119
                return 0;
1979
119
            }
1980
407
            else if (tp == &PyTuple_Type) {
1981
48
                specialize(instr, CALL_TUPLE_1);
1982
48
                return 0;
1983
48
            }
1984
600
        }
1985
707
        if (tp->tp_vectorcall != NULL) {
1986
473
            specialize(instr, CALL_BUILTIN_CLASS);
1987
473
            return 0;
1988
473
        }
1989
234
        goto generic;
1990
707
    }
1991
580
    if (Py_TYPE(tp) != &PyType_Type) {
1992
21
        goto generic;
1993
21
    }
1994
559
    if (tp->tp_new == PyBaseObject_Type.tp_new) {
1995
377
        unsigned int tp_version = 0;
1996
377
        PyObject *init = get_init_for_simple_managed_python_class(tp, &tp_version);
1997
377
        if (!tp_version) {
1998
12
            SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
1999
12
            Py_XDECREF(init);
2000
12
            return -1;
2001
12
        }
2002
365
        if (init != NULL && _PyType_CacheInitForSpecialization(
2003
202
                                (PyHeapTypeObject *)tp, init, tp_version)) {
2004
202
            _PyCallCache *cache = (_PyCallCache *)(instr + 1);
2005
202
            write_u32(cache->func_version, tp_version);
2006
202
            specialize(instr, CALL_ALLOC_AND_ENTER_INIT);
2007
202
            Py_DECREF(init);
2008
202
            return 0;
2009
202
        }
2010
163
        Py_XDECREF(init);
2011
163
    }
2012
600
generic:
2013
600
    specialize(instr, CALL_NON_PY_GENERAL);
2014
600
    return 0;
2015
559
}
2016
2017
static int
2018
specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr,
2019
                             int nargs)
2020
447k
{
2021
447k
    switch (descr->d_method->ml_flags &
2022
447k
        (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
2023
447k
        METH_KEYWORDS | METH_METHOD)) {
2024
711
        case METH_NOARGS: {
2025
711
            if (nargs != 1) {
2026
0
                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
2027
0
                return -1;
2028
0
            }
2029
711
            specialize(instr, CALL_METHOD_DESCRIPTOR_NOARGS);
2030
711
            return 0;
2031
711
        }
2032
367k
        case METH_O: {
2033
367k
            if (nargs != 2) {
2034
0
                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
2035
0
                return -1;
2036
0
            }
2037
367k
            PyInterpreterState *interp = _PyInterpreterState_GET();
2038
367k
            PyObject *list_append = interp->callable_cache.list_append;
2039
367k
            _Py_CODEUNIT next = instr[INLINE_CACHE_ENTRIES_CALL + 1];
2040
367k
            bool pop = (next.op.code == POP_TOP);
2041
367k
            int oparg = instr->op.arg;
2042
367k
            if ((PyObject *)descr == list_append && oparg == 1 && pop) {
2043
360k
                specialize(instr, CALL_LIST_APPEND);
2044
360k
                return 0;
2045
360k
            }
2046
6.93k
            specialize(instr, CALL_METHOD_DESCRIPTOR_O);
2047
6.93k
            return 0;
2048
367k
        }
2049
1.68k
        case METH_FASTCALL: {
2050
1.68k
            specialize(instr, CALL_METHOD_DESCRIPTOR_FAST);
2051
1.68k
            return 0;
2052
367k
        }
2053
76.8k
        case METH_FASTCALL | METH_KEYWORDS: {
2054
76.8k
            specialize(instr, CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS);
2055
76.8k
            return 0;
2056
367k
        }
2057
447k
    }
2058
212
    specialize(instr, CALL_NON_PY_GENERAL);
2059
212
    return 0;
2060
447k
}
2061
2062
static int
2063
specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
2064
                   bool bound_method)
2065
16.2k
{
2066
16.2k
    _PyCallCache *cache = (_PyCallCache *)(instr + 1);
2067
16.2k
    PyCodeObject *code = (PyCodeObject *)func->func_code;
2068
16.2k
    int kind = function_kind(code);
2069
    /* Don't specialize if PEP 523 is active */
2070
16.2k
    if (_PyInterpreterState_GET()->eval_frame) {
2071
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
2072
0
        return -1;
2073
0
    }
2074
16.2k
    int argcount = -1;
2075
16.2k
    if (kind == SPEC_FAIL_CODE_NOT_OPTIMIZED) {
2076
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CODE_NOT_OPTIMIZED);
2077
0
        return -1;
2078
0
    }
2079
16.2k
    if (kind == SIMPLE_FUNCTION) {
2080
15.4k
        argcount = code->co_argcount;
2081
15.4k
    }
2082
16.2k
    int version = _PyFunction_GetVersionForCurrentState(func);
2083
16.2k
    if (!_PyFunction_IsVersionValid(version)) {
2084
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
2085
0
        return -1;
2086
0
    }
2087
16.2k
    write_u32(cache->func_version, version);
2088
16.2k
    uint8_t opcode;
2089
16.2k
    if (argcount == nargs + bound_method) {
2090
15.3k
        opcode =
2091
15.3k
            bound_method ? CALL_BOUND_METHOD_EXACT_ARGS : CALL_PY_EXACT_ARGS;
2092
15.3k
    }
2093
885
    else {
2094
885
        opcode = bound_method ? CALL_BOUND_METHOD_GENERAL : CALL_PY_GENERAL;
2095
885
    }
2096
16.2k
    specialize(instr, opcode);
2097
16.2k
    return 0;
2098
16.2k
}
2099
2100
2101
static int
2102
specialize_py_call_kw(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
2103
                   bool bound_method)
2104
192
{
2105
192
    _PyCallCache *cache = (_PyCallCache *)(instr + 1);
2106
192
    PyCodeObject *code = (PyCodeObject *)func->func_code;
2107
192
    int kind = function_kind(code);
2108
    /* Don't specialize if PEP 523 is active */
2109
192
    if (_PyInterpreterState_GET()->eval_frame) {
2110
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
2111
0
        return -1;
2112
0
    }
2113
192
    if (kind == SPEC_FAIL_CODE_NOT_OPTIMIZED) {
2114
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CODE_NOT_OPTIMIZED);
2115
0
        return -1;
2116
0
    }
2117
192
    int version = _PyFunction_GetVersionForCurrentState(func);
2118
192
    if (!_PyFunction_IsVersionValid(version)) {
2119
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
2120
0
        return -1;
2121
0
    }
2122
192
    write_u32(cache->func_version, version);
2123
192
    specialize(instr, bound_method ? CALL_KW_BOUND_METHOD : CALL_KW_PY);
2124
192
    return 0;
2125
192
}
2126
2127
static int
2128
specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
2129
1.14M
{
2130
1.14M
    if (PyCFunction_GET_FUNCTION(callable) == NULL) {
2131
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OTHER);
2132
0
        return 1;
2133
0
    }
2134
1.14M
    switch (PyCFunction_GET_FLAGS(callable) &
2135
1.14M
        (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
2136
1.14M
        METH_KEYWORDS | METH_METHOD)) {
2137
1.14M
        case METH_O: {
2138
1.14M
            if (nargs != 1) {
2139
0
                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
2140
0
                return 1;
2141
0
            }
2142
            /* len(o) */
2143
1.14M
            PyInterpreterState *interp = _PyInterpreterState_GET();
2144
1.14M
            if (callable == interp->callable_cache.len && instr->op.arg == 1) {
2145
821
                specialize(instr, CALL_LEN);
2146
821
                return 0;
2147
821
            }
2148
1.13M
            specialize(instr, CALL_BUILTIN_O);
2149
1.13M
            return 0;
2150
1.14M
        }
2151
1.84k
        case METH_FASTCALL: {
2152
1.84k
            if (nargs == 2) {
2153
                /* isinstance(o1, o2) */
2154
1.26k
                PyInterpreterState *interp = _PyInterpreterState_GET();
2155
1.26k
                if (callable == interp->callable_cache.isinstance && instr->op.arg == 2) {
2156
649
                    specialize(instr, CALL_ISINSTANCE);
2157
649
                    return 0;
2158
649
                }
2159
1.26k
            }
2160
1.19k
            specialize(instr, CALL_BUILTIN_FAST);
2161
1.19k
            return 0;
2162
1.84k
        }
2163
466
        case METH_FASTCALL | METH_KEYWORDS: {
2164
466
            specialize(instr, CALL_BUILTIN_FAST_WITH_KEYWORDS);
2165
466
            return 0;
2166
1.84k
        }
2167
302
        default:
2168
302
            specialize(instr, CALL_NON_PY_GENERAL);
2169
302
            return 0;
2170
1.14M
    }
2171
1.14M
}
2172
2173
Py_NO_INLINE void
2174
_Py_Specialize_Call(_PyStackRef callable_st, _Py_CODEUNIT *instr, int nargs)
2175
1.61M
{
2176
1.61M
    PyObject *callable = PyStackRef_AsPyObjectBorrow(callable_st);
2177
2178
1.61M
    assert(ENABLE_SPECIALIZATION_FT);
2179
1.61M
    assert(_PyOpcode_Caches[CALL] == INLINE_CACHE_ENTRIES_CALL);
2180
1.61M
    assert(_Py_OPCODE(*instr) != INSTRUMENTED_CALL);
2181
1.61M
    int fail;
2182
1.61M
    if (PyCFunction_CheckExact(callable)) {
2183
1.14M
        fail = specialize_c_call(callable, instr, nargs);
2184
1.14M
    }
2185
470k
    else if (PyFunction_Check(callable)) {
2186
13.2k
        fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs, false);
2187
13.2k
    }
2188
457k
    else if (PyType_Check(callable)) {
2189
1.52k
        fail = specialize_class_call(callable, instr, nargs);
2190
1.52k
    }
2191
456k
    else if (Py_IS_TYPE(callable, &PyMethodDescr_Type)) {
2192
447k
        fail = specialize_method_descriptor((PyMethodDescrObject *)callable, instr, nargs);
2193
447k
    }
2194
8.90k
    else if (PyMethod_Check(callable)) {
2195
2.94k
        PyObject *func = ((PyMethodObject *)callable)->im_func;
2196
2.94k
        if (PyFunction_Check(func)) {
2197
2.94k
            fail = specialize_py_call((PyFunctionObject *)func, instr, nargs, true);
2198
2.94k
        }
2199
0
        else {
2200
0
            SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_BOUND_METHOD);
2201
0
            fail = -1;
2202
0
        }
2203
2.94k
    }
2204
5.96k
    else {
2205
5.96k
        specialize(instr, CALL_NON_PY_GENERAL);
2206
5.96k
        fail = 0;
2207
5.96k
    }
2208
1.61M
    if (fail) {
2209
12
        unspecialize(instr);
2210
12
    }
2211
1.61M
}
2212
2213
Py_NO_INLINE void
2214
_Py_Specialize_CallKw(_PyStackRef callable_st, _Py_CODEUNIT *instr, int nargs)
2215
447
{
2216
447
    PyObject *callable = PyStackRef_AsPyObjectBorrow(callable_st);
2217
2218
447
    assert(ENABLE_SPECIALIZATION_FT);
2219
447
    assert(_PyOpcode_Caches[CALL_KW] == INLINE_CACHE_ENTRIES_CALL_KW);
2220
447
    assert(_Py_OPCODE(*instr) != INSTRUMENTED_CALL_KW);
2221
447
    int fail;
2222
447
    if (PyFunction_Check(callable)) {
2223
190
        fail = specialize_py_call_kw((PyFunctionObject *)callable, instr, nargs, false);
2224
190
    }
2225
257
    else if (PyMethod_Check(callable)) {
2226
2
        PyObject *func = ((PyMethodObject *)callable)->im_func;
2227
2
        if (PyFunction_Check(func)) {
2228
2
            fail = specialize_py_call_kw((PyFunctionObject *)func, instr, nargs, true);
2229
2
        }
2230
0
        else {
2231
0
            SPECIALIZATION_FAIL(CALL_KW, SPEC_FAIL_CALL_BOUND_METHOD);
2232
0
            fail = -1;
2233
0
        }
2234
2
    }
2235
255
    else {
2236
255
        specialize(instr, CALL_KW_NON_PY);
2237
255
        fail = 0;
2238
255
    }
2239
447
    if (fail) {
2240
0
        unspecialize(instr);
2241
0
    }
2242
447
}
2243
2244
#ifdef Py_STATS
2245
static int
2246
binary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs)
2247
{
2248
    switch (oparg) {
2249
        case NB_ADD:
2250
        case NB_INPLACE_ADD:
2251
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2252
                return SPEC_FAIL_BINARY_OP_ADD_DIFFERENT_TYPES;
2253
            }
2254
            return SPEC_FAIL_BINARY_OP_ADD_OTHER;
2255
        case NB_AND:
2256
        case NB_INPLACE_AND:
2257
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2258
                return SPEC_FAIL_BINARY_OP_AND_DIFFERENT_TYPES;
2259
            }
2260
            if (PyLong_CheckExact(lhs)) {
2261
                return SPEC_FAIL_BINARY_OP_AND_INT;
2262
            }
2263
            return SPEC_FAIL_BINARY_OP_AND_OTHER;
2264
        case NB_FLOOR_DIVIDE:
2265
        case NB_INPLACE_FLOOR_DIVIDE:
2266
            return SPEC_FAIL_BINARY_OP_FLOOR_DIVIDE;
2267
        case NB_LSHIFT:
2268
        case NB_INPLACE_LSHIFT:
2269
            return SPEC_FAIL_BINARY_OP_LSHIFT;
2270
        case NB_MATRIX_MULTIPLY:
2271
        case NB_INPLACE_MATRIX_MULTIPLY:
2272
            return SPEC_FAIL_BINARY_OP_MATRIX_MULTIPLY;
2273
        case NB_MULTIPLY:
2274
        case NB_INPLACE_MULTIPLY:
2275
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2276
                return SPEC_FAIL_BINARY_OP_MULTIPLY_DIFFERENT_TYPES;
2277
            }
2278
            return SPEC_FAIL_BINARY_OP_MULTIPLY_OTHER;
2279
        case NB_OR:
2280
        case NB_INPLACE_OR:
2281
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2282
                return SPEC_FAIL_BINARY_OP_OR_DIFFERENT_TYPES;
2283
            }
2284
            if (PyLong_CheckExact(lhs)) {
2285
                return SPEC_FAIL_BINARY_OP_OR_INT;
2286
            }
2287
            return SPEC_FAIL_BINARY_OP_OR;
2288
        case NB_POWER:
2289
        case NB_INPLACE_POWER:
2290
            return SPEC_FAIL_BINARY_OP_POWER;
2291
        case NB_REMAINDER:
2292
        case NB_INPLACE_REMAINDER:
2293
            return SPEC_FAIL_BINARY_OP_REMAINDER;
2294
        case NB_RSHIFT:
2295
        case NB_INPLACE_RSHIFT:
2296
            return SPEC_FAIL_BINARY_OP_RSHIFT;
2297
        case NB_SUBTRACT:
2298
        case NB_INPLACE_SUBTRACT:
2299
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2300
                return SPEC_FAIL_BINARY_OP_SUBTRACT_DIFFERENT_TYPES;
2301
            }
2302
            return SPEC_FAIL_BINARY_OP_SUBTRACT_OTHER;
2303
        case NB_TRUE_DIVIDE:
2304
        case NB_INPLACE_TRUE_DIVIDE:
2305
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2306
                return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_DIFFERENT_TYPES;
2307
            }
2308
            if (PyFloat_CheckExact(lhs)) {
2309
                return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_FLOAT;
2310
            }
2311
            return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_OTHER;
2312
        case NB_XOR:
2313
        case NB_INPLACE_XOR:
2314
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2315
                return SPEC_FAIL_BINARY_OP_XOR_DIFFERENT_TYPES;
2316
            }
2317
            if (PyLong_CheckExact(lhs)) {
2318
                return SPEC_FAIL_BINARY_OP_XOR_INT;
2319
            }
2320
            return SPEC_FAIL_BINARY_OP_XOR;
2321
        case NB_SUBSCR:
2322
            if (PyList_CheckExact(lhs)) {
2323
                if (PyLong_CheckExact(rhs) && !_PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
2324
                    return SPEC_FAIL_OUT_OF_RANGE;
2325
                }
2326
                if (PySlice_Check(rhs)) {
2327
                    return SPEC_FAIL_BINARY_OP_SUBSCR_LIST_SLICE;
2328
                }
2329
            }
2330
            if (PyTuple_CheckExact(lhs)) {
2331
                if (PyLong_CheckExact(rhs) && !_PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
2332
                    return SPEC_FAIL_OUT_OF_RANGE;
2333
                }
2334
                if (PySlice_Check(rhs)) {
2335
                    return SPEC_FAIL_BINARY_OP_SUBSCR_TUPLE_SLICE;
2336
                }
2337
            }
2338
            if (PyUnicode_CheckExact(lhs)) {
2339
                if (PyLong_CheckExact(rhs) && !_PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
2340
                    return SPEC_FAIL_OUT_OF_RANGE;
2341
                }
2342
                if (PySlice_Check(rhs)) {
2343
                    return SPEC_FAIL_BINARY_OP_SUBSCR_STRING_SLICE;
2344
                }
2345
            }
2346
            unsigned int tp_version;
2347
            PyTypeObject *container_type = Py_TYPE(lhs);
2348
            PyObject *descriptor = _PyType_LookupRefAndVersion(container_type, &_Py_ID(__getitem__), &tp_version);
2349
            if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {
2350
                if (!(container_type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
2351
                    Py_DECREF(descriptor);
2352
                    return SPEC_FAIL_BINARY_OP_SUBSCR_NOT_HEAP_TYPE;
2353
                }
2354
                PyFunctionObject *func = (PyFunctionObject *)descriptor;
2355
                PyCodeObject *fcode = (PyCodeObject *)func->func_code;
2356
                int kind = function_kind(fcode);
2357
                if (kind != SIMPLE_FUNCTION) {
2358
                    Py_DECREF(descriptor);
2359
                    return kind;
2360
                }
2361
                if (fcode->co_argcount != 2) {
2362
                    Py_DECREF(descriptor);
2363
                    return SPEC_FAIL_WRONG_NUMBER_ARGUMENTS;
2364
                }
2365
2366
                if (_PyInterpreterState_GET()->eval_frame) {
2367
                    /* Don't specialize if PEP 523 is active */
2368
                    Py_DECREF(descriptor);
2369
                    return SPEC_FAIL_OTHER;
2370
                }
2371
            }
2372
            Py_XDECREF(descriptor);
2373
2374
            if (PyObject_TypeCheck(lhs, &PyDictProxy_Type)) {
2375
                return SPEC_FAIL_BINARY_OP_SUBSCR_MAPPINGPROXY;
2376
            }
2377
2378
            if (PyObject_TypeCheck(lhs, &PyBytes_Type)) {
2379
                return SPEC_FAIL_BINARY_OP_SUBSCR_BYTES;
2380
            }
2381
2382
            if (PyObject_TypeCheck(lhs, &PyRange_Type)) {
2383
                return SPEC_FAIL_BINARY_OP_SUBSCR_RANGE;
2384
            }
2385
2386
            if (strcmp(container_type->tp_name, "array.array") == 0) {
2387
                return SPEC_FAIL_BINARY_OP_SUBSCR_ARRAY;
2388
            }
2389
2390
            if (strcmp(container_type->tp_name, "re.Match") == 0) {
2391
                return SPEC_FAIL_BINARY_OP_SUBSCR_RE_MATCH;
2392
            }
2393
2394
            if (strcmp(container_type->tp_name, "collections.deque") == 0) {
2395
                return SPEC_FAIL_BINARY_OP_SUBSCR_DEQUE;
2396
            }
2397
2398
            if (strcmp(_PyType_Name(container_type), "EnumDict") == 0) {
2399
                return SPEC_FAIL_BINARY_OP_SUBSCR_ENUMDICT;
2400
            }
2401
2402
            if (strcmp(container_type->tp_name, "StackSummary") == 0) {
2403
                return SPEC_FAIL_BINARY_OP_SUBSCR_STACKSUMMARY;
2404
            }
2405
2406
            if (strcmp(container_type->tp_name, "collections.defaultdict") == 0) {
2407
                return SPEC_FAIL_BINARY_OP_SUBSCR_DEFAULTDICT;
2408
            }
2409
2410
            if (strcmp(container_type->tp_name, "Counter") == 0) {
2411
                return SPEC_FAIL_BINARY_OP_SUBSCR_COUNTER;
2412
            }
2413
2414
            if (strcmp(container_type->tp_name, "collections.OrderedDict") == 0) {
2415
                return SPEC_FAIL_BINARY_OP_SUBSCR_ORDEREDDICT;
2416
            }
2417
2418
            if (strcmp(container_type->tp_name, "time.struct_time") == 0) {
2419
                return SPEC_FAIL_BINARY_OP_SUBSCR_STRUCTTIME;
2420
            }
2421
2422
            if (PySlice_Check(rhs)) {
2423
                return SPEC_FAIL_BINARY_OP_SUBSCR_OTHER_SLICE;
2424
            }
2425
            return SPEC_FAIL_BINARY_OP_SUBSCR;
2426
    }
2427
    Py_UNREACHABLE();
2428
}
2429
#endif
2430
2431
/** Binary Op Specialization Extensions */
2432
2433
/* long-long */
2434
2435
static inline int
2436
is_compactlong(PyObject *v)
2437
1.22M
{
2438
1.22M
    return PyLong_CheckExact(v) &&
2439
1.22M
           _PyLong_IsCompact((PyLongObject *)v);
2440
1.22M
}
2441
2442
static int
2443
compactlongs_guard(PyObject *lhs, PyObject *rhs)
2444
610k
{
2445
610k
    return (is_compactlong(lhs) && is_compactlong(rhs));
2446
610k
}
2447
2448
#define BITWISE_LONGS_ACTION(NAME, OP) \
2449
    static PyObject * \
2450
    (NAME)(PyObject *lhs, PyObject *rhs) \
2451
609k
    { \
2452
609k
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2453
609k
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2454
609k
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2455
609k
    }
specialize.c:compactlongs_or
Line
Count
Source
2451
587k
    { \
2452
587k
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2453
587k
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2454
587k
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2455
587k
    }
specialize.c:compactlongs_and
Line
Count
Source
2451
22.3k
    { \
2452
22.3k
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2453
22.3k
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2454
22.3k
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2455
22.3k
    }
specialize.c:compactlongs_xor
Line
Count
Source
2451
22
    { \
2452
22
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2453
22
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2454
22
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2455
22
    }
2456
BITWISE_LONGS_ACTION(compactlongs_or, |)
2457
BITWISE_LONGS_ACTION(compactlongs_and, &)
2458
BITWISE_LONGS_ACTION(compactlongs_xor, ^)
2459
#undef BITWISE_LONGS_ACTION
2460
2461
/* float-long */
2462
2463
static inline int
2464
float_compactlong_guard(PyObject *lhs, PyObject *rhs)
2465
5.50M
{
2466
5.50M
    return (
2467
5.50M
        PyFloat_CheckExact(lhs) &&
2468
5.50M
        !isnan(PyFloat_AsDouble(lhs)) &&
2469
5.50M
        PyLong_CheckExact(rhs) &&
2470
5.50M
        _PyLong_IsCompact((PyLongObject *)rhs)
2471
5.50M
    );
2472
5.50M
}
2473
2474
static inline int
2475
nonzero_float_compactlong_guard(PyObject *lhs, PyObject *rhs)
2476
2.75M
{
2477
2.75M
    return (
2478
2.75M
        float_compactlong_guard(lhs, rhs) && !PyLong_IsZero(rhs)
2479
2.75M
    );
2480
2.75M
}
2481
2482
#define FLOAT_LONG_ACTION(NAME, OP) \
2483
    static PyObject * \
2484
    (NAME)(PyObject *lhs, PyObject *rhs) \
2485
5.50M
    { \
2486
5.50M
        double lhs_val = PyFloat_AsDouble(lhs); \
2487
5.50M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2488
5.50M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2489
5.50M
    }
Unexecuted instantiation: specialize.c:float_compactlong_add
Unexecuted instantiation: specialize.c:float_compactlong_subtract
specialize.c:float_compactlong_true_div
Line
Count
Source
2485
2.75M
    { \
2486
2.75M
        double lhs_val = PyFloat_AsDouble(lhs); \
2487
2.75M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2488
2.75M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2489
2.75M
    }
specialize.c:float_compactlong_multiply
Line
Count
Source
2485
2.75M
    { \
2486
2.75M
        double lhs_val = PyFloat_AsDouble(lhs); \
2487
2.75M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2488
2.75M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2489
2.75M
    }
2490
FLOAT_LONG_ACTION(float_compactlong_add, +)
2491
FLOAT_LONG_ACTION(float_compactlong_subtract, -)
2492
FLOAT_LONG_ACTION(float_compactlong_multiply, *)
2493
FLOAT_LONG_ACTION(float_compactlong_true_div, /)
2494
#undef FLOAT_LONG_ACTION
2495
2496
/*  long-float */
2497
2498
static inline int
2499
compactlong_float_guard(PyObject *lhs, PyObject *rhs)
2500
1.60k
{
2501
1.60k
    return (
2502
1.60k
        PyLong_CheckExact(lhs) &&
2503
1.60k
        _PyLong_IsCompact((PyLongObject *)lhs) &&
2504
1.60k
        PyFloat_CheckExact(rhs) &&
2505
1.60k
        !isnan(PyFloat_AsDouble(rhs))
2506
1.60k
    );
2507
1.60k
}
2508
2509
static inline int
2510
nonzero_compactlong_float_guard(PyObject *lhs, PyObject *rhs)
2511
22
{
2512
22
    return (
2513
22
        compactlong_float_guard(lhs, rhs) && PyFloat_AsDouble(rhs) != 0.0
2514
22
    );
2515
22
}
2516
2517
#define LONG_FLOAT_ACTION(NAME, OP) \
2518
    static PyObject * \
2519
    (NAME)(PyObject *lhs, PyObject *rhs) \
2520
0
    { \
2521
0
        double rhs_val = PyFloat_AsDouble(rhs); \
2522
0
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2523
0
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2524
0
    }
Unexecuted instantiation: specialize.c:compactlong_float_add
Unexecuted instantiation: specialize.c:compactlong_float_subtract
Unexecuted instantiation: specialize.c:compactlong_float_true_div
Unexecuted instantiation: specialize.c:compactlong_float_multiply
2525
LONG_FLOAT_ACTION(compactlong_float_add, +)
2526
LONG_FLOAT_ACTION(compactlong_float_subtract, -)
2527
LONG_FLOAT_ACTION(compactlong_float_multiply, *)
2528
LONG_FLOAT_ACTION(compactlong_float_true_div, /)
2529
#undef LONG_FLOAT_ACTION
2530
2531
static _PyBinaryOpSpecializationDescr binaryop_extend_descrs[] = {
2532
    /* long-long arithmetic */
2533
    {NB_OR, compactlongs_guard, compactlongs_or},
2534
    {NB_AND, compactlongs_guard, compactlongs_and},
2535
    {NB_XOR, compactlongs_guard, compactlongs_xor},
2536
    {NB_INPLACE_OR, compactlongs_guard, compactlongs_or},
2537
    {NB_INPLACE_AND, compactlongs_guard, compactlongs_and},
2538
    {NB_INPLACE_XOR, compactlongs_guard, compactlongs_xor},
2539
2540
    /* float-long arithemetic */
2541
    {NB_ADD, float_compactlong_guard, float_compactlong_add},
2542
    {NB_SUBTRACT, float_compactlong_guard, float_compactlong_subtract},
2543
    {NB_TRUE_DIVIDE, nonzero_float_compactlong_guard, float_compactlong_true_div},
2544
    {NB_MULTIPLY, float_compactlong_guard, float_compactlong_multiply},
2545
2546
    /* float-float arithmetic */
2547
    {NB_ADD, compactlong_float_guard, compactlong_float_add},
2548
    {NB_SUBTRACT, compactlong_float_guard, compactlong_float_subtract},
2549
    {NB_TRUE_DIVIDE, nonzero_compactlong_float_guard, compactlong_float_true_div},
2550
    {NB_MULTIPLY, compactlong_float_guard, compactlong_float_multiply},
2551
};
2552
2553
static int
2554
binary_op_extended_specialization(PyObject *lhs, PyObject *rhs, int oparg,
2555
                                  _PyBinaryOpSpecializationDescr **descr)
2556
29.0k
{
2557
29.0k
    size_t n = sizeof(binaryop_extend_descrs)/sizeof(_PyBinaryOpSpecializationDescr);
2558
429k
    for (size_t i = 0; i < n; i++) {
2559
400k
        _PyBinaryOpSpecializationDescr *d = &binaryop_extend_descrs[i];
2560
400k
        if (d->oparg == oparg && d->guard(lhs, rhs)) {
2561
511
            *descr = d;
2562
511
            return 1;
2563
511
        }
2564
400k
    }
2565
28.5k
    return 0;
2566
29.0k
}
2567
2568
Py_NO_INLINE void
2569
_Py_Specialize_BinaryOp(_PyStackRef lhs_st, _PyStackRef rhs_st, _Py_CODEUNIT *instr,
2570
                        int oparg, _PyStackRef *locals)
2571
1.03M
{
2572
1.03M
    PyObject *lhs = PyStackRef_AsPyObjectBorrow(lhs_st);
2573
1.03M
    PyObject *rhs = PyStackRef_AsPyObjectBorrow(rhs_st);
2574
1.03M
    assert(ENABLE_SPECIALIZATION_FT);
2575
1.03M
    assert(_PyOpcode_Caches[BINARY_OP] == INLINE_CACHE_ENTRIES_BINARY_OP);
2576
2577
1.03M
    _PyBinaryOpCache *cache = (_PyBinaryOpCache *)(instr + 1);
2578
1.03M
    if (instr->op.code == BINARY_OP_EXTEND) {
2579
0
        write_ptr(cache->external_cache, NULL);
2580
0
    }
2581
2582
1.03M
    switch (oparg) {
2583
1.03k
        case NB_ADD:
2584
1.77k
        case NB_INPLACE_ADD:
2585
1.77k
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2586
27
                break;
2587
27
            }
2588
1.74k
            if (PyUnicode_CheckExact(lhs)) {
2589
301
                _Py_CODEUNIT next = instr[INLINE_CACHE_ENTRIES_BINARY_OP + 1];
2590
301
                bool to_store = (next.op.code == STORE_FAST);
2591
301
                if (to_store && PyStackRef_AsPyObjectBorrow(locals[next.op.arg]) == lhs) {
2592
66
                    specialize(instr, BINARY_OP_INPLACE_ADD_UNICODE);
2593
66
                    return;
2594
66
                }
2595
235
                specialize(instr, BINARY_OP_ADD_UNICODE);
2596
235
                return;
2597
301
            }
2598
1.44k
            if (_PyLong_CheckExactAndCompact(lhs) && _PyLong_CheckExactAndCompact(rhs)) {
2599
458
                specialize(instr, BINARY_OP_ADD_INT);
2600
458
                return;
2601
458
            }
2602
989
            if (PyFloat_CheckExact(lhs)) {
2603
0
                specialize(instr, BINARY_OP_ADD_FLOAT);
2604
0
                return;
2605
0
            }
2606
989
            break;
2607
1.27k
        case NB_MULTIPLY:
2608
1.27k
        case NB_INPLACE_MULTIPLY:
2609
1.27k
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2610
271
                break;
2611
271
            }
2612
1.00k
            if (_PyLong_CheckExactAndCompact(lhs) && _PyLong_CheckExactAndCompact(rhs)) {
2613
199
                specialize(instr, BINARY_OP_MULTIPLY_INT);
2614
199
                return;
2615
199
            }
2616
803
            if (PyFloat_CheckExact(lhs)) {
2617
0
                specialize(instr, BINARY_OP_MULTIPLY_FLOAT);
2618
0
                return;
2619
0
            }
2620
803
            break;
2621
803
        case NB_SUBTRACT:
2622
323
        case NB_INPLACE_SUBTRACT:
2623
323
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2624
0
                break;
2625
0
            }
2626
323
            if (_PyLong_CheckExactAndCompact(lhs) && _PyLong_CheckExactAndCompact(rhs)) {
2627
307
                specialize(instr, BINARY_OP_SUBTRACT_INT);
2628
307
                return;
2629
307
            }
2630
16
            if (PyFloat_CheckExact(lhs)) {
2631
0
                specialize(instr, BINARY_OP_SUBTRACT_FLOAT);
2632
0
                return;
2633
0
            }
2634
16
            break;
2635
1.02M
        case NB_SUBSCR:
2636
1.02M
            if (PyLong_CheckExact(rhs) && _PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
2637
1.00M
                if (PyList_CheckExact(lhs)) {
2638
4.28k
                    specialize(instr, BINARY_OP_SUBSCR_LIST_INT);
2639
4.28k
                    return;
2640
4.28k
                }
2641
1.00M
                if (PyTuple_CheckExact(lhs)) {
2642
462
                    specialize(instr, BINARY_OP_SUBSCR_TUPLE_INT);
2643
462
                    return;
2644
462
                }
2645
999k
                if (PyUnicode_CheckExact(lhs)) {
2646
997k
                    specialize(instr, BINARY_OP_SUBSCR_STR_INT);
2647
997k
                    return;
2648
997k
                }
2649
999k
            }
2650
18.3k
            if (PyDict_CheckExact(lhs)) {
2651
297
                specialize(instr, BINARY_OP_SUBSCR_DICT);
2652
297
                return;
2653
297
            }
2654
18.0k
            if (PyList_CheckExact(lhs) && PySlice_Check(rhs)) {
2655
31
                specialize(instr, BINARY_OP_SUBSCR_LIST_SLICE);
2656
31
                return;
2657
31
            }
2658
17.9k
            unsigned int tp_version;
2659
17.9k
            PyTypeObject *container_type = Py_TYPE(lhs);
2660
17.9k
            PyObject *descriptor = _PyType_LookupRefAndVersion(container_type, &_Py_ID(__getitem__), &tp_version);
2661
17.9k
            if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type &&
2662
17.9k
                container_type->tp_flags & Py_TPFLAGS_HEAPTYPE)
2663
89
            {
2664
89
                PyFunctionObject *func = (PyFunctionObject *)descriptor;
2665
89
                PyCodeObject *fcode = (PyCodeObject *)func->func_code;
2666
89
                int kind = function_kind(fcode);
2667
89
                PyHeapTypeObject *ht = (PyHeapTypeObject *)container_type;
2668
89
                if (kind == SIMPLE_FUNCTION &&
2669
89
                    fcode->co_argcount == 2 &&
2670
89
                    !_PyInterpreterState_GET()->eval_frame && /* Don't specialize if PEP 523 is active */
2671
89
                    _PyType_CacheGetItemForSpecialization(ht, descriptor, (uint32_t)tp_version))
2672
89
                {
2673
89
                    specialize(instr, BINARY_OP_SUBSCR_GETITEM);
2674
89
                    Py_DECREF(descriptor);
2675
89
                    return;
2676
89
                }
2677
89
            }
2678
17.8k
            Py_XDECREF(descriptor);
2679
17.8k
            break;
2680
1.03M
    }
2681
2682
29.0k
    _PyBinaryOpSpecializationDescr *descr;
2683
29.0k
    if (binary_op_extended_specialization(lhs, rhs, oparg, &descr)) {
2684
511
        specialize(instr, BINARY_OP_EXTEND);
2685
511
        write_ptr(cache->external_cache, (void*)descr);
2686
511
        return;
2687
511
    }
2688
2689
28.5k
    SPECIALIZATION_FAIL(BINARY_OP, binary_op_fail_kind(oparg, lhs, rhs));
2690
28.5k
    unspecialize(instr);
2691
28.5k
    return;
2692
29.0k
}
2693
2694
2695
#ifdef Py_STATS
2696
static int
2697
compare_op_fail_kind(PyObject *lhs, PyObject *rhs)
2698
{
2699
    if (Py_TYPE(lhs) != Py_TYPE(rhs)) {
2700
        if (PyFloat_CheckExact(lhs) && PyLong_CheckExact(rhs)) {
2701
            return SPEC_FAIL_COMPARE_OP_FLOAT_LONG;
2702
        }
2703
        if (PyLong_CheckExact(lhs) && PyFloat_CheckExact(rhs)) {
2704
            return SPEC_FAIL_COMPARE_OP_LONG_FLOAT;
2705
        }
2706
        return SPEC_FAIL_COMPARE_OP_DIFFERENT_TYPES;
2707
    }
2708
    if (PyBytes_CheckExact(lhs)) {
2709
        return SPEC_FAIL_COMPARE_OP_BYTES;
2710
    }
2711
    if (PyTuple_CheckExact(lhs)) {
2712
        return SPEC_FAIL_COMPARE_OP_TUPLE;
2713
    }
2714
    if (PyList_CheckExact(lhs)) {
2715
        return SPEC_FAIL_COMPARE_OP_LIST;
2716
    }
2717
    if (PySet_CheckExact(lhs) || PyFrozenSet_CheckExact(lhs)) {
2718
        return SPEC_FAIL_COMPARE_OP_SET;
2719
    }
2720
    if (PyBool_Check(lhs)) {
2721
        return SPEC_FAIL_COMPARE_OP_BOOL;
2722
    }
2723
    if (Py_TYPE(lhs)->tp_richcompare == PyBaseObject_Type.tp_richcompare) {
2724
        return SPEC_FAIL_COMPARE_OP_BASEOBJECT;
2725
    }
2726
    return SPEC_FAIL_OTHER;
2727
}
2728
#endif   // Py_STATS
2729
2730
Py_NO_INLINE void
2731
_Py_Specialize_CompareOp(_PyStackRef lhs_st, _PyStackRef rhs_st, _Py_CODEUNIT *instr,
2732
                         int oparg)
2733
18.9k
{
2734
18.9k
    PyObject *lhs = PyStackRef_AsPyObjectBorrow(lhs_st);
2735
18.9k
    PyObject *rhs = PyStackRef_AsPyObjectBorrow(rhs_st);
2736
18.9k
    uint8_t specialized_op;
2737
2738
18.9k
    assert(ENABLE_SPECIALIZATION_FT);
2739
18.9k
    assert(_PyOpcode_Caches[COMPARE_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP);
2740
    // All of these specializations compute boolean values, so they're all valid
2741
    // regardless of the fifth-lowest oparg bit.
2742
18.9k
    if (Py_TYPE(lhs) != Py_TYPE(rhs)) {
2743
6.05k
        SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
2744
6.05k
        goto failure;
2745
6.05k
    }
2746
12.8k
    if (PyFloat_CheckExact(lhs)) {
2747
18
        specialized_op = COMPARE_OP_FLOAT;
2748
18
        goto success;
2749
18
    }
2750
12.8k
    if (PyLong_CheckExact(lhs)) {
2751
6.51k
        if (_PyLong_IsCompact((PyLongObject *)lhs) && _PyLong_IsCompact((PyLongObject *)rhs)) {
2752
3.07k
            specialized_op = COMPARE_OP_INT;
2753
3.07k
            goto success;
2754
3.07k
        }
2755
3.43k
        else {
2756
3.43k
            SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_BIG_INT);
2757
3.43k
            goto failure;
2758
3.43k
        }
2759
6.51k
    }
2760
6.35k
    if (PyUnicode_CheckExact(lhs)) {
2761
5.92k
        int cmp = oparg >> 5;
2762
5.92k
        if (cmp != Py_EQ && cmp != Py_NE) {
2763
4.65k
            SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_STRING);
2764
4.65k
            goto failure;
2765
4.65k
        }
2766
1.26k
        else {
2767
1.26k
            specialized_op = COMPARE_OP_STR;
2768
1.26k
            goto success;
2769
1.26k
        }
2770
5.92k
    }
2771
434
    SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
2772
14.5k
failure:
2773
14.5k
    unspecialize(instr);
2774
14.5k
    return;
2775
4.35k
success:
2776
4.35k
    specialize(instr, specialized_op);
2777
4.35k
}
2778
2779
#ifdef Py_STATS
2780
static int
2781
unpack_sequence_fail_kind(PyObject *seq)
2782
{
2783
    if (PySequence_Check(seq)) {
2784
        return SPEC_FAIL_UNPACK_SEQUENCE_SEQUENCE;
2785
    }
2786
    if (PyIter_Check(seq)) {
2787
        return SPEC_FAIL_UNPACK_SEQUENCE_ITERATOR;
2788
    }
2789
    return SPEC_FAIL_OTHER;
2790
}
2791
#endif   // Py_STATS
2792
2793
Py_NO_INLINE void
2794
_Py_Specialize_UnpackSequence(_PyStackRef seq_st, _Py_CODEUNIT *instr, int oparg)
2795
11.1k
{
2796
11.1k
    PyObject *seq = PyStackRef_AsPyObjectBorrow(seq_st);
2797
2798
11.1k
    assert(ENABLE_SPECIALIZATION_FT);
2799
11.1k
    assert(_PyOpcode_Caches[UNPACK_SEQUENCE] ==
2800
11.1k
           INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE);
2801
11.1k
    if (PyTuple_CheckExact(seq)) {
2802
1.04k
        if (PyTuple_GET_SIZE(seq) != oparg) {
2803
0
            SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_EXPECTED_ERROR);
2804
0
            unspecialize(instr);
2805
0
            return;
2806
0
        }
2807
1.04k
        if (PyTuple_GET_SIZE(seq) == 2) {
2808
565
            specialize(instr, UNPACK_SEQUENCE_TWO_TUPLE);
2809
565
            return;
2810
565
        }
2811
481
        specialize(instr, UNPACK_SEQUENCE_TUPLE);
2812
481
        return;
2813
1.04k
    }
2814
10.0k
    if (PyList_CheckExact(seq)) {
2815
9.41k
        if (PyList_GET_SIZE(seq) != oparg) {
2816
7.36k
            SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_EXPECTED_ERROR);
2817
7.36k
            unspecialize(instr);
2818
7.36k
            return;
2819
7.36k
        }
2820
2.04k
        specialize(instr, UNPACK_SEQUENCE_LIST);
2821
2.04k
        return;
2822
9.41k
    }
2823
652
    SPECIALIZATION_FAIL(UNPACK_SEQUENCE, unpack_sequence_fail_kind(seq));
2824
652
    unspecialize(instr);
2825
652
}
2826
2827
#ifdef Py_STATS
2828
int
2829
 _PySpecialization_ClassifyIterator(PyObject *iter)
2830
{
2831
    if (PyGen_CheckExact(iter)) {
2832
        return SPEC_FAIL_ITER_GENERATOR;
2833
    }
2834
    if (PyCoro_CheckExact(iter)) {
2835
        return SPEC_FAIL_ITER_COROUTINE;
2836
    }
2837
    if (PyAsyncGen_CheckExact(iter)) {
2838
        return SPEC_FAIL_ITER_ASYNC_GENERATOR;
2839
    }
2840
    if (PyAsyncGenASend_CheckExact(iter)) {
2841
        return SPEC_FAIL_ITER_ASYNC_GENERATOR_SEND;
2842
    }
2843
    PyTypeObject *t = Py_TYPE(iter);
2844
    if (t == &PyListIter_Type) {
2845
        return SPEC_FAIL_ITER_LIST;
2846
    }
2847
    if (t == &PyTupleIter_Type) {
2848
        return SPEC_FAIL_ITER_TUPLE;
2849
    }
2850
    if (t == &PyDictIterKey_Type) {
2851
        return SPEC_FAIL_ITER_DICT_KEYS;
2852
    }
2853
    if (t == &PyDictIterValue_Type) {
2854
        return SPEC_FAIL_ITER_DICT_VALUES;
2855
    }
2856
    if (t == &PyDictIterItem_Type) {
2857
        return SPEC_FAIL_ITER_DICT_ITEMS;
2858
    }
2859
    if (t == &PySetIter_Type) {
2860
        return SPEC_FAIL_ITER_SET;
2861
    }
2862
    if (t == &PyUnicodeIter_Type) {
2863
        return SPEC_FAIL_ITER_STRING;
2864
    }
2865
    if (t == &PyBytesIter_Type) {
2866
        return SPEC_FAIL_ITER_BYTES;
2867
    }
2868
    if (t == &PyRangeIter_Type) {
2869
        return SPEC_FAIL_ITER_RANGE;
2870
    }
2871
    if (t == &PyEnum_Type) {
2872
        return SPEC_FAIL_ITER_ENUMERATE;
2873
    }
2874
    if (t == &PyMap_Type) {
2875
        return SPEC_FAIL_ITER_MAP;
2876
    }
2877
    if (t == &PyZip_Type) {
2878
        return SPEC_FAIL_ITER_ZIP;
2879
    }
2880
    if (t == &PySeqIter_Type) {
2881
        return SPEC_FAIL_ITER_SEQ_ITER;
2882
    }
2883
    if (t == &PyListRevIter_Type) {
2884
        return SPEC_FAIL_ITER_REVERSED_LIST;
2885
    }
2886
    if (t == &_PyUnicodeASCIIIter_Type) {
2887
        return SPEC_FAIL_ITER_ASCII_STRING;
2888
    }
2889
    const char *name = t->tp_name;
2890
    if (strncmp(name, "itertools", 9) == 0) {
2891
        return SPEC_FAIL_ITER_ITERTOOLS;
2892
    }
2893
    if (strncmp(name, "callable_iterator", 17) == 0) {
2894
        return SPEC_FAIL_ITER_CALLABLE;
2895
    }
2896
    return SPEC_FAIL_OTHER;
2897
}
2898
#endif   // Py_STATS
2899
2900
Py_NO_INLINE void
2901
_Py_Specialize_ForIter(_PyStackRef iter, _PyStackRef null_or_index, _Py_CODEUNIT *instr, int oparg)
2902
92.7k
{
2903
92.7k
    assert(ENABLE_SPECIALIZATION_FT);
2904
92.7k
    assert(_PyOpcode_Caches[FOR_ITER] == INLINE_CACHE_ENTRIES_FOR_ITER);
2905
92.7k
    PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
2906
92.7k
    PyTypeObject *tp = Py_TYPE(iter_o);
2907
2908
92.7k
    if (PyStackRef_IsNull(null_or_index)) {
2909
#ifdef Py_GIL_DISABLED
2910
        // Only specialize for uniquely referenced iterators, so that we know
2911
        // they're only referenced by this one thread. This is more limiting
2912
        // than we need (even `it = iter(mylist); for item in it:` won't get
2913
        // specialized) but we don't have a way to check whether we're the only
2914
        // _thread_ who has access to the object.
2915
        if (!_PyObject_IsUniquelyReferenced(iter_o)) {
2916
            goto failure;
2917
        }
2918
#endif
2919
91.5k
        if (tp == &PyRangeIter_Type) {
2920
86
            specialize(instr, FOR_ITER_RANGE);
2921
86
            return;
2922
86
        }
2923
91.5k
        else if (tp == &PyGen_Type && oparg <= SHRT_MAX) {
2924
            // Generators are very much not thread-safe, so don't worry about
2925
            // the specialization not being thread-safe.
2926
472
            assert(instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == END_FOR  ||
2927
472
                instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == INSTRUMENTED_END_FOR
2928
472
            );
2929
            /* Don't specialize if PEP 523 is active */
2930
472
            if (_PyInterpreterState_GET()->eval_frame) {
2931
0
                goto failure;
2932
0
            }
2933
472
            specialize(instr, FOR_ITER_GEN);
2934
472
            return;
2935
472
        }
2936
91.5k
    }
2937
1.11k
    else {
2938
1.11k
        if (tp == &PyList_Type) {
2939
#ifdef Py_GIL_DISABLED
2940
            // Only specialize for lists owned by this thread or shared
2941
            if (!_Py_IsOwnedByCurrentThread(iter_o) && !_PyObject_GC_IS_SHARED(iter_o)) {
2942
                goto failure;
2943
            }
2944
#endif
2945
587
            specialize(instr, FOR_ITER_LIST);
2946
587
            return;
2947
587
        }
2948
526
        else if (tp == &PyTuple_Type) {
2949
526
            specialize(instr, FOR_ITER_TUPLE);
2950
526
            return;
2951
526
        }
2952
1.11k
    }
2953
91.0k
failure:
2954
91.0k
    SPECIALIZATION_FAIL(FOR_ITER,
2955
91.0k
                        _PySpecialization_ClassifyIterator(iter_o));
2956
91.0k
    unspecialize(instr);
2957
91.0k
}
2958
2959
Py_NO_INLINE void
2960
_Py_Specialize_Send(_PyStackRef receiver_st, _Py_CODEUNIT *instr)
2961
4.42k
{
2962
4.42k
    PyObject *receiver = PyStackRef_AsPyObjectBorrow(receiver_st);
2963
2964
4.42k
    assert(ENABLE_SPECIALIZATION_FT);
2965
4.42k
    assert(_PyOpcode_Caches[SEND] == INLINE_CACHE_ENTRIES_SEND);
2966
4.42k
    PyTypeObject *tp = Py_TYPE(receiver);
2967
4.42k
    if (tp == &PyGen_Type || tp == &PyCoro_Type) {
2968
        /* Don't specialize if PEP 523 is active */
2969
960
        if (_PyInterpreterState_GET()->eval_frame) {
2970
0
            SPECIALIZATION_FAIL(SEND, SPEC_FAIL_OTHER);
2971
0
            goto failure;
2972
0
        }
2973
960
        specialize(instr, SEND_GEN);
2974
960
        return;
2975
960
    }
2976
3.46k
    SPECIALIZATION_FAIL(SEND,
2977
3.46k
                        _PySpecialization_ClassifyIterator(receiver));
2978
3.46k
failure:
2979
3.46k
    unspecialize(instr);
2980
3.46k
}
2981
2982
#ifdef Py_STATS
2983
static int
2984
to_bool_fail_kind(PyObject *value)
2985
{
2986
    if (PyByteArray_CheckExact(value)) {
2987
        return SPEC_FAIL_TO_BOOL_BYTEARRAY;
2988
    }
2989
    if (PyBytes_CheckExact(value)) {
2990
        return SPEC_FAIL_TO_BOOL_BYTES;
2991
    }
2992
    if (PyDict_CheckExact(value)) {
2993
        return SPEC_FAIL_TO_BOOL_DICT;
2994
    }
2995
    if (PyFloat_CheckExact(value)) {
2996
        return SPEC_FAIL_TO_BOOL_FLOAT;
2997
    }
2998
    if (PyMemoryView_Check(value)) {
2999
        return SPEC_FAIL_TO_BOOL_MEMORY_VIEW;
3000
    }
3001
    if (PyAnySet_CheckExact(value)) {
3002
        return SPEC_FAIL_TO_BOOL_SET;
3003
    }
3004
    if (PyTuple_CheckExact(value)) {
3005
        return SPEC_FAIL_TO_BOOL_TUPLE;
3006
    }
3007
    return SPEC_FAIL_OTHER;
3008
}
3009
#endif  // Py_STATS
3010
3011
static int
3012
check_type_always_true(PyTypeObject *ty)
3013
65.2k
{
3014
65.2k
    PyNumberMethods *nb = ty->tp_as_number;
3015
65.2k
    if (nb && nb->nb_bool) {
3016
26
        return SPEC_FAIL_TO_BOOL_NUMBER;
3017
26
    }
3018
65.2k
    PyMappingMethods *mp = ty->tp_as_mapping;
3019
65.2k
    if (mp && mp->mp_length) {
3020
10.9k
        return SPEC_FAIL_TO_BOOL_MAPPING;
3021
10.9k
    }
3022
54.2k
    PySequenceMethods *sq = ty->tp_as_sequence;
3023
54.2k
    if (sq && sq->sq_length) {
3024
8.77k
      return SPEC_FAIL_TO_BOOL_SEQUENCE;
3025
8.77k
    }
3026
45.5k
    return 0;
3027
54.2k
}
3028
3029
Py_NO_INLINE void
3030
_Py_Specialize_ToBool(_PyStackRef value_o, _Py_CODEUNIT *instr)
3031
143k
{
3032
143k
    assert(ENABLE_SPECIALIZATION_FT);
3033
143k
    assert(_PyOpcode_Caches[TO_BOOL] == INLINE_CACHE_ENTRIES_TO_BOOL);
3034
143k
    _PyToBoolCache *cache = (_PyToBoolCache *)(instr + 1);
3035
143k
    PyObject *value = PyStackRef_AsPyObjectBorrow(value_o);
3036
143k
    uint8_t specialized_op;
3037
143k
    if (PyBool_Check(value)) {
3038
2.43k
        specialized_op = TO_BOOL_BOOL;
3039
2.43k
        goto success;
3040
2.43k
    }
3041
141k
    if (PyLong_CheckExact(value)) {
3042
1.63k
        specialized_op = TO_BOOL_INT;
3043
1.63k
        goto success;
3044
1.63k
    }
3045
139k
    if (PyList_CheckExact(value)) {
3046
223
        specialized_op = TO_BOOL_LIST;
3047
223
        goto success;
3048
223
    }
3049
139k
    if (Py_IsNone(value)) {
3050
58.4k
        specialized_op = TO_BOOL_NONE;
3051
58.4k
        goto success;
3052
58.4k
    }
3053
80.7k
    if (PyUnicode_CheckExact(value)) {
3054
14.3k
        specialized_op = TO_BOOL_STR;
3055
14.3k
        goto success;
3056
14.3k
    }
3057
66.3k
    if (PyType_HasFeature(Py_TYPE(value), Py_TPFLAGS_HEAPTYPE)) {
3058
65.2k
        unsigned int version = 0;
3059
65.2k
        int err = _PyType_Validate(Py_TYPE(value), check_type_always_true, &version);
3060
65.2k
        if (err < 0) {
3061
0
            SPECIALIZATION_FAIL(TO_BOOL, SPEC_FAIL_OUT_OF_VERSIONS);
3062
0
            goto failure;
3063
0
        }
3064
65.2k
        else if (err > 0) {
3065
19.7k
            SPECIALIZATION_FAIL(TO_BOOL, err);
3066
19.7k
            goto failure;
3067
19.7k
        }
3068
3069
45.5k
        assert(err == 0);
3070
45.5k
        assert(version);
3071
45.5k
        write_u32(cache->version, version);
3072
45.5k
        specialized_op = TO_BOOL_ALWAYS_TRUE;
3073
45.5k
        goto success;
3074
65.2k
    }
3075
3076
1.09k
    SPECIALIZATION_FAIL(TO_BOOL, to_bool_fail_kind(value));
3077
20.8k
failure:
3078
20.8k
    unspecialize(instr);
3079
20.8k
    return;
3080
122k
success:
3081
122k
    specialize(instr, specialized_op);
3082
122k
}
3083
3084
#ifdef Py_STATS
3085
static int
3086
containsop_fail_kind(PyObject *value) {
3087
    if (PyUnicode_CheckExact(value)) {
3088
        return SPEC_FAIL_CONTAINS_OP_STR;
3089
    }
3090
    if (PyList_CheckExact(value)) {
3091
        return SPEC_FAIL_CONTAINS_OP_LIST;
3092
    }
3093
    if (PyTuple_CheckExact(value)) {
3094
        return SPEC_FAIL_CONTAINS_OP_TUPLE;
3095
    }
3096
    if (PyType_Check(value)) {
3097
        return SPEC_FAIL_CONTAINS_OP_USER_CLASS;
3098
    }
3099
    return SPEC_FAIL_OTHER;
3100
}
3101
#endif
3102
3103
Py_NO_INLINE void
3104
_Py_Specialize_ContainsOp(_PyStackRef value_st, _Py_CODEUNIT *instr)
3105
25.8k
{
3106
25.8k
    PyObject *value = PyStackRef_AsPyObjectBorrow(value_st);
3107
3108
25.8k
    assert(ENABLE_SPECIALIZATION_FT);
3109
25.8k
    assert(_PyOpcode_Caches[CONTAINS_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP);
3110
25.8k
    if (PyDict_CheckExact(value)) {
3111
253
        specialize(instr, CONTAINS_OP_DICT);
3112
253
        return;
3113
253
    }
3114
25.5k
    if (PySet_CheckExact(value) || PyFrozenSet_CheckExact(value)) {
3115
273
        specialize(instr, CONTAINS_OP_SET);
3116
273
        return;
3117
273
    }
3118
3119
25.2k
    SPECIALIZATION_FAIL(CONTAINS_OP, containsop_fail_kind(value));
3120
25.2k
    unspecialize(instr);
3121
25.2k
    return;
3122
25.5k
}
3123
3124
#ifdef Py_STATS
3125
void
3126
_Py_GatherStats_GetIter(_PyStackRef iterable)
3127
{
3128
    PyTypeObject *tp = PyStackRef_TYPE(iterable);
3129
    int kind = SPEC_FAIL_OTHER;
3130
    if (tp == &PyTuple_Type) {
3131
        kind = SPEC_FAIL_ITER_TUPLE;
3132
    }
3133
    else if (tp == &PyList_Type) {
3134
        kind = SPEC_FAIL_ITER_LIST;
3135
    }
3136
    else if (tp == &PyDict_Type) {
3137
        kind = SPEC_FAIL_ITER_DICT_KEYS;
3138
    }
3139
    else if (tp == &PySet_Type) {
3140
        kind = SPEC_FAIL_ITER_SET;
3141
    }
3142
    else if (tp == &PyBytes_Type) {
3143
        kind = SPEC_FAIL_ITER_BYTES;
3144
    }
3145
    else if (tp == &PyEnum_Type) {
3146
        kind = SPEC_FAIL_ITER_ENUMERATE;
3147
    }
3148
    else if (tp == &PyUnicode_Type) {
3149
        kind = SPEC_FAIL_ITER_STRING;
3150
    }
3151
    else if (tp == &PyGen_Type) {
3152
        kind = SPEC_FAIL_ITER_GENERATOR;
3153
    }
3154
    else if (tp == &PyCoro_Type) {
3155
        kind = SPEC_FAIL_ITER_COROUTINE;
3156
    }
3157
    else if (tp == &PyAsyncGen_Type) {
3158
        kind = SPEC_FAIL_ITER_ASYNC_GENERATOR;
3159
    }
3160
    else if (tp == &_PyAsyncGenASend_Type) {
3161
        kind = SPEC_FAIL_ITER_ASYNC_GENERATOR_SEND;
3162
    }
3163
    else if (tp->tp_iter == PyObject_SelfIter) {
3164
        kind = SPEC_FAIL_ITER_SELF;
3165
    }
3166
    SPECIALIZATION_FAIL(GET_ITER, kind);
3167
}
3168
#endif
3169
3170
3171
/* Code init cleanup.
3172
 * CALL_ALLOC_AND_ENTER_INIT will set up
3173
 * the frame to execute the EXIT_INIT_CHECK
3174
 * instruction.
3175
 * Ends with a RESUME so that it is not traced.
3176
 * This is used as a plain code object, not a function,
3177
 * so must not access globals or builtins.
3178
 * There are a few other constraints imposed on the code
3179
 * by the free-threaded build:
3180
 *
3181
 * 1. The RESUME instruction must not be executed. Otherwise we may attempt to
3182
 *    free the statically allocated TLBC array.
3183
 * 2. It must contain no specializable instructions. Specializing multiple
3184
 *    copies of the same bytecode is not thread-safe in free-threaded builds.
3185
 *
3186
 * This should be dynamically allocated if either of those restrictions need to
3187
 * be lifted.
3188
 */
3189
3190
#define NO_LOC_4 (128 | (PY_CODE_LOCATION_INFO_NONE << 3) | 3)
3191
3192
static const PyBytesObject no_location = {
3193
    PyVarObject_HEAD_INIT(&PyBytes_Type, 1)
3194
    .ob_sval = { NO_LOC_4 }
3195
};
3196
3197
#ifdef Py_GIL_DISABLED
3198
static _PyCodeArray init_cleanup_tlbc = {
3199
    .size = 1,
3200
    .entries = {(char*) &_Py_InitCleanup.co_code_adaptive},
3201
};
3202
#endif
3203
3204
const struct _PyCode8 _Py_InitCleanup = {
3205
    _PyVarObject_HEAD_INIT(&PyCode_Type, 3),
3206
    .co_consts = (PyObject *)&_Py_SINGLETON(tuple_empty),
3207
    .co_names = (PyObject *)&_Py_SINGLETON(tuple_empty),
3208
    .co_exceptiontable = (PyObject *)&_Py_SINGLETON(bytes_empty),
3209
    .co_flags = CO_OPTIMIZED | CO_NO_MONITORING_EVENTS,
3210
    .co_localsplusnames = (PyObject *)&_Py_SINGLETON(tuple_empty),
3211
    .co_localspluskinds = (PyObject *)&_Py_SINGLETON(bytes_empty),
3212
    .co_filename = &_Py_ID(__init__),
3213
    .co_name = &_Py_ID(__init__),
3214
    .co_qualname = &_Py_ID(__init__),
3215
    .co_linetable = (PyObject *)&no_location,
3216
    ._co_firsttraceable = 4,
3217
    .co_stacksize = 2,
3218
    .co_framesize = 2 + FRAME_SPECIALS_SIZE,
3219
#ifdef Py_GIL_DISABLED
3220
    .co_tlbc = &init_cleanup_tlbc,
3221
#endif
3222
    .co_code_adaptive = {
3223
        EXIT_INIT_CHECK, 0,
3224
        RETURN_VALUE, 0,
3225
        RESUME, RESUME_AT_FUNC_START,
3226
    }
3227
};