Coverage Report

Created: 2025-07-18 06:09

/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
281k
#  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
30.9k
{
461
30.9k
    #if ENABLE_SPECIALIZATION_FT
462
30.9k
    _Py_BackoffCounter jump_counter, adaptive_counter;
463
30.9k
    if (enable_counters) {
464
30.9k
        jump_counter = initial_jump_backoff_counter();
465
30.9k
        adaptive_counter = adaptive_counter_warmup();
466
30.9k
    }
467
0
    else {
468
0
        jump_counter = initial_unreachable_backoff_counter();
469
0
        adaptive_counter = initial_unreachable_backoff_counter();
470
0
    }
471
30.9k
    int opcode = 0;
472
30.9k
    int oparg = 0;
473
    /* The last code unit cannot have a cache, so we don't need to check it */
474
1.46M
    for (Py_ssize_t i = 0; i < size-1; i++) {
475
1.43M
        opcode = instructions[i].op.code;
476
1.43M
        int caches = _PyOpcode_Caches[opcode];
477
1.43M
        oparg = (oparg << 8) | instructions[i].op.arg;
478
1.43M
        if (caches) {
479
            // The initial value depends on the opcode
480
412k
            switch (opcode) {
481
13.3k
                case JUMP_BACKWARD:
482
13.3k
                    instructions[i + 1].counter = jump_counter;
483
13.3k
                    break;
484
33.8k
                case POP_JUMP_IF_FALSE:
485
46.1k
                case POP_JUMP_IF_TRUE:
486
48.9k
                case POP_JUMP_IF_NONE:
487
52.5k
                case POP_JUMP_IF_NOT_NONE:
488
52.5k
                    instructions[i + 1].cache = 0x5555;  // Alternating 0, 1 bits
489
52.5k
                    break;
490
346k
                default:
491
346k
                    instructions[i + 1].counter = adaptive_counter;
492
346k
                    break;
493
412k
            }
494
412k
            i += caches;
495
412k
        }
496
1.43M
        if (opcode != EXTENDED_ARG) {
497
1.41M
            oparg = 0;
498
1.41M
        }
499
1.43M
    }
500
30.9k
    #endif /* ENABLE_SPECIALIZATION_FT */
501
30.9k
}
502
503
464k
#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
840
#define SPEC_FAIL_CODE_COMPLEX_PARAMETERS 7
515
13.6k
#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
9.63k
#define SPEC_FAIL_TO_BOOL_MAPPING     13
688
#define SPEC_FAIL_TO_BOOL_MEMORY_VIEW 14
689
24
#define SPEC_FAIL_TO_BOOL_NUMBER      15
690
9.41k
#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.99M
{
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.99M
    instr->op.code = opcode;
717
3.99M
    return 1;
718
3.99M
#endif
719
3.99M
}
720
721
static inline void
722
set_counter(_Py_BackoffCounter *counter, _Py_BackoffCounter value)
723
4.05M
{
724
4.05M
    FT_ATOMIC_STORE_UINT16_RELAXED(counter->value_and_backoff,
725
4.05M
                                   value.value_and_backoff);
726
4.05M
}
727
728
static inline _Py_BackoffCounter
729
load_counter(_Py_BackoffCounter *counter)
730
281k
{
731
281k
    _Py_BackoffCounter result = {
732
281k
        .value_and_backoff =
733
281k
            FT_ATOMIC_LOAD_UINT16_RELAXED(counter->value_and_backoff)};
734
281k
    return result;
735
281k
}
736
737
static inline void
738
specialize(_Py_CODEUNIT *instr, uint8_t specialized_opcode)
739
3.70M
{
740
3.70M
    assert(!PyErr_Occurred());
741
3.70M
    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.70M
    STAT_INC(_PyOpcode_Deopt[specialized_opcode], success);
748
3.70M
    set_counter((_Py_BackoffCounter *)instr + 1, adaptive_counter_cooldown());
749
3.70M
}
750
751
static inline void
752
unspecialize(_Py_CODEUNIT *instr)
753
281k
{
754
281k
    assert(!PyErr_Occurred());
755
281k
    uint8_t opcode = FT_ATOMIC_LOAD_UINT8_RELAXED(instr->op.code);
756
281k
    uint8_t generic_opcode = _PyOpcode_Deopt[opcode];
757
281k
    STAT_INC(generic_opcode, failure);
758
281k
    if (!set_opcode(instr, generic_opcode)) {
759
0
        SPECIALIZATION_FAIL(generic_opcode, SPEC_FAIL_OTHER);
760
0
        return;
761
0
    }
762
281k
    _Py_BackoffCounter *counter = (_Py_BackoffCounter *)instr + 1;
763
281k
    _Py_BackoffCounter cur = load_counter(counter);
764
281k
    set_counter(counter, adaptive_counter_backoff(cur));
765
281k
}
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.42k
{
774
2.42k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
775
2.42k
    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.42k
    Py_ssize_t index = _PyDict_LookupIndex(dict, &_Py_ID(__getattr__));
780
2.42k
    assert(index != DKIX_ERROR);
781
2.42k
    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.42k
    index = _PyDict_LookupIndex(dict, name);
786
2.42k
    assert (index != DKIX_ERROR);
787
2.42k
    if (index != (uint16_t)index) {
788
195
        SPECIALIZATION_FAIL(LOAD_ATTR,
789
195
                            index == DKIX_EMPTY ?
790
195
                            SPEC_FAIL_ATTR_MODULE_ATTR_NOT_FOUND :
791
195
                            SPEC_FAIL_OUT_OF_RANGE);
792
195
        return -1;
793
195
    }
794
2.22k
    uint32_t keys_version = _PyDict_GetKeysVersionForCurrentState(
795
2.22k
            _PyInterpreterState_GET(), dict);
796
2.22k
    if (keys_version == 0) {
797
0
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
798
0
        return -1;
799
0
    }
800
2.22k
    write_u32(cache->version, keys_version);
801
2.22k
    cache->index = (uint16_t)index;
802
2.22k
    specialize(instr, LOAD_ATTR_MODULE);
803
2.22k
    return 0;
804
2.22k
}
805
806
static int
807
specialize_module_load_attr(
808
    PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
809
2.42k
{
810
2.42k
    PyModuleObject *m = (PyModuleObject *)owner;
811
2.42k
    assert((Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0);
812
2.42k
    PyDictObject *dict = (PyDictObject *)m->md_dict;
813
2.42k
    if (dict == NULL) {
814
0
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_NO_DICT);
815
0
        return -1;
816
0
    }
817
2.42k
    int result;
818
2.42k
    Py_BEGIN_CRITICAL_SECTION(dict);
819
2.42k
    result = specialize_module_load_attr_lock_held(dict, instr, name);
820
2.42k
    Py_END_CRITICAL_SECTION();
821
2.42k
    return result;
822
2.42k
}
823
824
/* Attribute specialization */
825
826
Py_NO_INLINE void
827
148
_Py_Specialize_LoadSuperAttr(_PyStackRef global_super_st, _PyStackRef cls_st, _Py_CODEUNIT *instr, int load_method) {
828
148
    PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st);
829
148
    PyObject *cls = PyStackRef_AsPyObjectBorrow(cls_st);
830
831
148
    assert(ENABLE_SPECIALIZATION_FT);
832
148
    assert(_PyOpcode_Caches[LOAD_SUPER_ATTR] == INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR);
833
148
    if (global_super != (PyObject *)&PySuper_Type) {
834
0
        SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_SHADOWED);
835
0
        goto fail;
836
0
    }
837
148
    if (!PyType_Check(cls)) {
838
0
        SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_BAD_CLASS);
839
0
        goto fail;
840
0
    }
841
148
    uint8_t load_code = load_method ? LOAD_SUPER_ATTR_METHOD : LOAD_SUPER_ATTR_ATTR;
842
148
    specialize(instr, load_code);
843
148
    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
898k
{
869
898k
    if (descriptor == NULL) {
870
461k
        return ABSENT;
871
461k
    }
872
437k
    PyTypeObject *desc_cls = Py_TYPE(descriptor);
873
437k
    if (!(desc_cls->tp_flags & Py_TPFLAGS_IMMUTABLETYPE)) {
874
552
        return MUTABLE;
875
552
    }
876
437k
    if (desc_cls->tp_descr_set) {
877
222k
        if (desc_cls == &PyMemberDescr_Type) {
878
448
            PyMemberDescrObject *member = (PyMemberDescrObject *)descriptor;
879
448
            struct PyMemberDef *dmem = member->d_member;
880
448
            if (dmem->type == Py_T_OBJECT_EX || dmem->type == _Py_T_OBJECT) {
881
356
                return OBJECT_SLOT;
882
356
            }
883
92
            return OTHER_SLOT;
884
448
        }
885
221k
        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
218k
            return has_getattr ? GETSET_OVERRIDDEN : PROPERTY;
890
218k
        }
891
3.12k
        return OVERRIDING;
892
221k
    }
893
214k
    if (desc_cls->tp_descr_get) {
894
102k
        if (desc_cls->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR) {
895
101k
            return METHOD;
896
101k
        }
897
1.53k
        if (Py_IS_TYPE(descriptor, &PyClassMethodDescr_Type)) {
898
155
            return BUILTIN_CLASSMETHOD;
899
155
        }
900
1.37k
        if (Py_IS_TYPE(descriptor, &PyClassMethod_Type)) {
901
738
            return PYTHON_CLASSMETHOD;
902
738
        }
903
640
        return NON_OVERRIDING;
904
1.37k
    }
905
112k
    return NON_DESCRIPTOR;
906
214k
}
907
908
static bool
909
descriptor_is_class(PyObject *descriptor, PyObject *name)
910
957k
{
911
957k
    return ((PyUnicode_CompareWithASCIIString(name, "__class__") == 0) &&
912
957k
            (descriptor == _PyType_Lookup(&PyBaseObject_Type, name)));
913
957k
}
914
915
static DescriptorClassification
916
746k
analyze_descriptor_load(PyTypeObject *type, PyObject *name, PyObject **descr, unsigned int *tp_version) {
917
746k
    bool has_getattr = false;
918
746k
    bool have_ga_version = false;
919
746k
    unsigned int ga_version;
920
746k
    getattrofunc getattro_slot = type->tp_getattro;
921
746k
    if (getattro_slot == PyObject_GenericGetAttr) {
922
        /* Normal attribute lookup; */
923
746k
        has_getattr = false;
924
746k
    }
925
143
    else if (getattro_slot == _Py_slot_tp_getattr_hook ||
926
143
        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 (getattro_slot == _Py_slot_tp_getattro &&
939
0
                !has_getattr &&
940
0
                Py_IS_TYPE(getattribute, &PyFunction_Type)) {
941
0
                *descr = getattribute;
942
0
                *tp_version = ga_version;
943
0
                return GETATTRIBUTE_IS_PYTHON_FUNCTION;
944
0
            }
945
            /* Potentially both __getattr__ and __getattribute__ are set.
946
               Too complicated */
947
0
            Py_DECREF(getattribute);
948
0
            *descr = NULL;
949
0
            *tp_version = ga_version;
950
0
            return GETSET_OVERRIDDEN;
951
0
        }
952
        /* Potentially has __getattr__ but no custom __getattribute__.
953
           Fall through to usual descriptor analysis.
954
           Usual attribute lookup should only be allowed at runtime
955
           if we can guarantee that there is no way an exception can be
956
           raised. This means some specializations, e.g. specializing
957
           for property() isn't safe.
958
        */
959
0
        Py_XDECREF(getattribute);
960
0
    }
961
143
    else {
962
143
        *descr = NULL;
963
143
        *tp_version = FT_ATOMIC_LOAD_UINT_RELAXED(type->tp_version_tag);
964
143
        return GETSET_OVERRIDDEN;
965
143
    }
966
746k
    unsigned int descr_version;
967
746k
    PyObject *descriptor = _PyType_LookupRefAndVersion(type, name, &descr_version);
968
746k
    *descr = descriptor;
969
746k
    *tp_version = have_ga_version ? ga_version : descr_version;
970
746k
    if (descriptor_is_class(descriptor, name)) {
971
63.6k
        return DUNDER_CLASS;
972
63.6k
    }
973
682k
    return classify_descriptor(descriptor, has_getattr);
974
746k
}
975
976
static DescriptorClassification
977
analyze_descriptor_store(PyTypeObject *type, PyObject *name, PyObject **descr, unsigned int *tp_version)
978
211k
{
979
211k
    if (type->tp_setattro != PyObject_GenericSetAttr) {
980
127
        *descr = NULL;
981
127
        return GETSET_OVERRIDDEN;
982
127
    }
983
210k
    PyObject *descriptor = _PyType_LookupRefAndVersion(type, name, tp_version);
984
210k
    *descr = descriptor;
985
210k
    if (descriptor_is_class(descriptor, name)) {
986
0
        return DUNDER_CLASS;
987
0
    }
988
210k
    return classify_descriptor(descriptor, false);
989
210k
}
990
991
static int
992
specialize_dict_access_inline(
993
    PyObject *owner, _Py_CODEUNIT *instr, PyTypeObject *type,
994
    PyObject *name, unsigned int tp_version,
995
    int base_op, int values_op)
996
411k
{
997
411k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
998
411k
    PyDictKeysObject *keys = ((PyHeapTypeObject *)type)->ht_cached_keys;
999
411k
    assert(PyUnicode_CheckExact(name));
1000
411k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(owner);
1001
411k
    Py_ssize_t index = _PyDictKeys_StringLookupSplit(keys, name);
1002
411k
    assert (index != DKIX_ERROR);
1003
411k
    if (index == DKIX_EMPTY) {
1004
457
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_NOT_IN_KEYS);
1005
457
        return 0;
1006
457
    }
1007
410k
    assert(index >= 0);
1008
410k
    assert(_PyObject_InlineValues(owner)->valid);
1009
410k
    char *value_addr = (char *)&_PyObject_InlineValues(owner)->values[index];
1010
410k
    Py_ssize_t offset = value_addr - (char *)owner;
1011
410k
    if (offset != (uint16_t)offset) {
1012
0
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_OUT_OF_RANGE);
1013
0
        return 0;
1014
0
    }
1015
410k
    cache->index = (uint16_t)offset;
1016
410k
    write_u32(cache->version, tp_version);
1017
410k
    specialize(instr, values_op);
1018
410k
    return 1;
1019
410k
}
1020
1021
static int
1022
specialize_dict_access_hint(
1023
    PyDictObject *dict, _Py_CODEUNIT *instr, PyTypeObject *type,
1024
    PyObject *name, unsigned int tp_version,
1025
    int base_op, int hint_op)
1026
17.1k
{
1027
17.1k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
1028
1029
17.1k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(dict);
1030
#ifdef Py_GIL_DISABLED
1031
    _PyDict_EnsureSharedOnRead(dict);
1032
#endif
1033
1034
    // We found an instance with a __dict__.
1035
17.1k
    if (_PyDict_HasSplitTable(dict)) {
1036
325
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_SPLIT_DICT);
1037
325
        return 0;
1038
325
    }
1039
16.7k
    Py_ssize_t index = _PyDict_LookupIndex(dict, name);
1040
16.7k
    if (index != (uint16_t)index) {
1041
5.19k
        SPECIALIZATION_FAIL(base_op,
1042
5.19k
                            index == DKIX_EMPTY ?
1043
5.19k
                            SPEC_FAIL_ATTR_NOT_IN_DICT :
1044
5.19k
                            SPEC_FAIL_OUT_OF_RANGE);
1045
5.19k
        return 0;
1046
5.19k
    }
1047
11.5k
    cache->index = (uint16_t)index;
1048
11.5k
    write_u32(cache->version, tp_version);
1049
11.5k
    specialize(instr, hint_op);
1050
11.5k
    return 1;
1051
16.7k
}
1052
1053
1054
static int
1055
specialize_dict_access(
1056
    PyObject *owner, _Py_CODEUNIT *instr, PyTypeObject *type,
1057
    DescriptorClassification kind, PyObject *name, unsigned int tp_version,
1058
    int base_op, int values_op, int hint_op)
1059
431k
{
1060
431k
    assert(kind == NON_OVERRIDING || kind == NON_DESCRIPTOR || kind == ABSENT ||
1061
431k
        kind == BUILTIN_CLASSMETHOD || kind == PYTHON_CLASSMETHOD ||
1062
431k
        kind == METHOD);
1063
    // No descriptor, or non overriding.
1064
431k
    if ((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {
1065
2.99k
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);
1066
2.99k
        return 0;
1067
2.99k
    }
1068
428k
    if (type->tp_flags & Py_TPFLAGS_INLINE_VALUES &&
1069
428k
        FT_ATOMIC_LOAD_UINT8(_PyObject_InlineValues(owner)->valid) &&
1070
428k
        !(base_op == STORE_ATTR && _PyObject_GetManagedDict(owner) != NULL))
1071
411k
    {
1072
411k
        int res;
1073
411k
        Py_BEGIN_CRITICAL_SECTION(owner);
1074
411k
        PyDictObject *dict = _PyObject_GetManagedDict(owner);
1075
411k
        if (dict == NULL) {
1076
            // managed dict, not materialized, inline values valid
1077
411k
            res = specialize_dict_access_inline(owner, instr, type, name,
1078
411k
                                                tp_version, base_op, values_op);
1079
411k
        }
1080
0
        else {
1081
            // lost race and dict was created, fail specialization
1082
0
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OTHER);
1083
0
            res = 0;
1084
0
        }
1085
411k
        Py_END_CRITICAL_SECTION();
1086
411k
        return res;
1087
411k
    }
1088
17.2k
    else {
1089
17.2k
        PyDictObject *dict = _PyObject_GetManagedDict(owner);
1090
17.2k
        if (dict == NULL || !PyDict_CheckExact(dict)) {
1091
167
            SPECIALIZATION_FAIL(base_op, SPEC_FAIL_NO_DICT);
1092
167
            return 0;
1093
167
        }
1094
17.1k
        int res;
1095
17.1k
        Py_BEGIN_CRITICAL_SECTION(dict);
1096
        // materialized managed dict
1097
17.1k
        res = specialize_dict_access_hint(dict, instr, type, name,
1098
17.1k
                                          tp_version, base_op, hint_op);
1099
17.1k
        Py_END_CRITICAL_SECTION();
1100
17.1k
        return res;
1101
17.2k
    }
1102
428k
}
1103
1104
static int
1105
specialize_attr_loadclassattr(PyObject *owner, _Py_CODEUNIT *instr,
1106
                              PyObject *name, PyObject *descr,
1107
                              unsigned int tp_version,
1108
                              DescriptorClassification kind, bool is_method,
1109
                              uint32_t shared_keys_version);
1110
static int specialize_class_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name);
1111
1112
/* Returns true if instances of obj's class are
1113
 * likely to have `name` in their __dict__.
1114
 * For objects with inline values, we check in the shared keys.
1115
 * For other objects, we check their actual dictionary.
1116
 */
1117
static bool
1118
instance_has_key(PyObject *obj, PyObject *name, uint32_t *shared_keys_version)
1119
743k
{
1120
743k
    PyTypeObject *cls = Py_TYPE(obj);
1121
743k
    if ((cls->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {
1122
100k
        return false;
1123
100k
    }
1124
643k
    if (cls->tp_flags & Py_TPFLAGS_INLINE_VALUES) {
1125
598k
        PyDictKeysObject *keys = ((PyHeapTypeObject *)cls)->ht_cached_keys;
1126
598k
        Py_ssize_t index =
1127
598k
            _PyDictKeys_StringLookupAndVersion(keys, name, shared_keys_version);
1128
598k
        return index >= 0;
1129
598k
    }
1130
44.9k
    PyDictObject *dict = _PyObject_GetManagedDict(obj);
1131
44.9k
    if (dict == NULL || !PyDict_CheckExact(dict)) {
1132
0
        return false;
1133
0
    }
1134
44.9k
    bool result;
1135
44.9k
    Py_BEGIN_CRITICAL_SECTION(dict);
1136
44.9k
    if (dict->ma_values) {
1137
44.9k
        result = false;
1138
44.9k
    }
1139
0
    else {
1140
0
        result = (_PyDict_LookupIndex(dict, name) >= 0);
1141
0
    }
1142
44.9k
    Py_END_CRITICAL_SECTION();
1143
44.9k
    return result;
1144
44.9k
}
1145
1146
static int
1147
do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name,
1148
                                 bool shadow, uint32_t shared_keys_version,
1149
                                 DescriptorClassification kind, PyObject *descr, unsigned int tp_version)
1150
743k
{
1151
743k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
1152
743k
    PyTypeObject *type = Py_TYPE(owner);
1153
743k
    if (tp_version == 0) {
1154
6.85k
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
1155
6.85k
        return -1;
1156
6.85k
    }
1157
737k
    uint8_t oparg = FT_ATOMIC_LOAD_UINT8_RELAXED(instr->op.arg);
1158
737k
    switch(kind) {
1159
149
        case OVERRIDING:
1160
149
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
1161
149
            return -1;
1162
97.8k
        case METHOD:
1163
97.8k
        {
1164
97.8k
            if (shadow) {
1165
77
                goto try_instance;
1166
77
            }
1167
97.7k
            if (oparg & 1) {
1168
42.4k
                if (specialize_attr_loadclassattr(owner, instr, name, descr,
1169
42.4k
                                                  tp_version, kind, true,
1170
42.4k
                                                  shared_keys_version)) {
1171
41.7k
                    return 0;
1172
41.7k
                }
1173
679
                else {
1174
679
                    return -1;
1175
679
                }
1176
42.4k
            }
1177
55.2k
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
1178
55.2k
            return -1;
1179
97.7k
        }
1180
218k
        case PROPERTY:
1181
218k
        {
1182
218k
            _PyLoadMethodCache *lm_cache = (_PyLoadMethodCache *)(instr + 1);
1183
218k
            assert(Py_TYPE(descr) == &PyProperty_Type);
1184
218k
            PyObject *fget = ((_PyPropertyObject *)descr)->prop_get;
1185
218k
            if (fget == NULL) {
1186
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
1187
0
                return -1;
1188
0
            }
1189
218k
            if (!Py_IS_TYPE(fget, &PyFunction_Type)) {
1190
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_PROPERTY_NOT_PY_FUNCTION);
1191
0
                return -1;
1192
0
            }
1193
218k
            if (!function_check_args(fget, 1, LOAD_ATTR)) {
1194
0
                return -1;
1195
0
            }
1196
218k
            if (oparg & 1) {
1197
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
1198
0
                return -1;
1199
0
            }
1200
            /* Don't specialize if PEP 523 is active */
1201
218k
            if (_PyInterpreterState_GET()->eval_frame) {
1202
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER);
1203
0
                return -1;
1204
0
            }
1205
            #ifdef Py_GIL_DISABLED
1206
            if (!_PyObject_HasDeferredRefcount(fget)) {
1207
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED);
1208
                return -1;
1209
            }
1210
            #endif
1211
218k
            assert(tp_version != 0);
1212
218k
            write_u32(lm_cache->type_version, tp_version);
1213
            /* borrowed */
1214
218k
            write_ptr(lm_cache->descr, fget);
1215
218k
            specialize(instr, LOAD_ATTR_PROPERTY);
1216
218k
            return 0;
1217
218k
        }
1218
249
        case OBJECT_SLOT:
1219
249
        {
1220
249
            PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
1221
249
            struct PyMemberDef *dmem = member->d_member;
1222
249
            Py_ssize_t offset = dmem->offset;
1223
249
            if (!PyObject_TypeCheck(owner, member->d_common.d_type)) {
1224
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
1225
0
                return -1;
1226
0
            }
1227
249
            if (dmem->flags & Py_AUDIT_READ) {
1228
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_AUDITED_SLOT);
1229
0
                return -1;
1230
0
            }
1231
249
            if (offset != (uint16_t)offset) {
1232
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE);
1233
0
                return -1;
1234
0
            }
1235
249
            assert(dmem->type == Py_T_OBJECT_EX || dmem->type == _Py_T_OBJECT);
1236
249
            assert(offset > 0);
1237
249
            cache->index = (uint16_t)offset;
1238
249
            write_u32(cache->version, tp_version);
1239
249
            specialize(instr, LOAD_ATTR_SLOT);
1240
249
            return 0;
1241
249
        }
1242
63.6k
        case DUNDER_CLASS:
1243
63.6k
        {
1244
63.6k
            Py_ssize_t offset = offsetof(PyObject, ob_type);
1245
63.6k
            assert(offset == (uint16_t)offset);
1246
63.6k
            cache->index = (uint16_t)offset;
1247
63.6k
            write_u32(cache->version, tp_version);
1248
63.6k
            specialize(instr, LOAD_ATTR_SLOT);
1249
63.6k
            return 0;
1250
249
        }
1251
92
        case OTHER_SLOT:
1252
92
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT);
1253
92
            return -1;
1254
201
        case MUTABLE:
1255
201
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
1256
201
            return -1;
1257
0
        case GETSET_OVERRIDDEN:
1258
0
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OVERRIDDEN);
1259
0
            return -1;
1260
0
        case GETATTRIBUTE_IS_PYTHON_FUNCTION:
1261
0
        {
1262
0
            #ifndef Py_GIL_DISABLED
1263
            // In free-threaded builds it's possible for tp_getattro to change
1264
            // after the call to analyze_descriptor. That is fine: the version
1265
            // guard will fail.
1266
0
            assert(type->tp_getattro == _Py_slot_tp_getattro);
1267
0
            #endif
1268
0
            assert(Py_IS_TYPE(descr, &PyFunction_Type));
1269
0
            _PyLoadMethodCache *lm_cache = (_PyLoadMethodCache *)(instr + 1);
1270
0
            if (!function_check_args(descr, 2, LOAD_ATTR)) {
1271
0
                return -1;
1272
0
            }
1273
0
            if (oparg & 1) {
1274
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
1275
0
                return -1;
1276
0
            }
1277
0
            uint32_t version = function_get_version(descr, LOAD_ATTR);
1278
0
            if (version == 0) {
1279
0
                return -1;
1280
0
            }
1281
            /* Don't specialize if PEP 523 is active */
1282
0
            if (_PyInterpreterState_GET()->eval_frame) {
1283
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER);
1284
0
                return -1;
1285
0
            }
1286
            #ifdef Py_GIL_DISABLED
1287
            if (!_PyObject_HasDeferredRefcount(descr)) {
1288
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED);
1289
                return -1;
1290
            }
1291
            #endif
1292
0
            write_u32(lm_cache->keys_version, version);
1293
            /* borrowed */
1294
0
            write_ptr(lm_cache->descr, descr);
1295
0
            write_u32(lm_cache->type_version, tp_version);
1296
0
            specialize(instr, LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN);
1297
0
            return 0;
1298
0
        }
1299
0
        case BUILTIN_CLASSMETHOD:
1300
126
        case PYTHON_CLASSMETHOD:
1301
236
        case NON_OVERRIDING:
1302
236
            if (shadow) {
1303
0
                goto try_instance;
1304
0
            }
1305
236
            return -1;
1306
110k
        case NON_DESCRIPTOR:
1307
110k
            if (shadow) {
1308
44.4k
                goto try_instance;
1309
44.4k
            }
1310
65.7k
            if ((oparg & 1) == 0) {
1311
65.7k
                if (specialize_attr_loadclassattr(owner, instr, name, descr,
1312
65.7k
                                                  tp_version, kind, false,
1313
65.7k
                                                  shared_keys_version)) {
1314
65.0k
                    return 0;
1315
65.0k
                }
1316
65.7k
            }
1317
648
            return -1;
1318
245k
        case ABSENT:
1319
245k
            if (shadow) {
1320
177k
                goto try_instance;
1321
177k
            }
1322
67.8k
            set_counter((_Py_BackoffCounter*)instr + 1, adaptive_counter_cooldown());
1323
67.8k
            return 0;
1324
737k
    }
1325
737k
    Py_UNREACHABLE();
1326
222k
try_instance:
1327
222k
    if (specialize_dict_access(owner, instr, type, kind, name, tp_version,
1328
222k
                               LOAD_ATTR, LOAD_ATTR_INSTANCE_VALUE, LOAD_ATTR_WITH_HINT))
1329
217k
    {
1330
217k
        return 0;
1331
217k
    }
1332
5.18k
    return -1;
1333
222k
}
1334
1335
static int
1336
specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name)
1337
743k
{
1338
    // 0 is not a valid version
1339
743k
    uint32_t shared_keys_version = 0;
1340
743k
    bool shadow = instance_has_key(owner, name, &shared_keys_version);
1341
743k
    PyObject *descr = NULL;
1342
743k
    unsigned int tp_version = 0;
1343
743k
    PyTypeObject *type = Py_TYPE(owner);
1344
743k
    DescriptorClassification kind = analyze_descriptor_load(type, name, &descr, &tp_version);
1345
743k
    int result = do_specialize_instance_load_attr(owner, instr, name, shadow, shared_keys_version, kind, descr, tp_version);
1346
743k
    Py_XDECREF(descr);
1347
743k
    return result;
1348
743k
}
1349
1350
Py_NO_INLINE void
1351
_Py_Specialize_LoadAttr(_PyStackRef owner_st, _Py_CODEUNIT *instr, PyObject *name)
1352
751k
{
1353
751k
    PyObject *owner = PyStackRef_AsPyObjectBorrow(owner_st);
1354
1355
751k
    assert(ENABLE_SPECIALIZATION_FT);
1356
751k
    assert(_PyOpcode_Caches[LOAD_ATTR] == INLINE_CACHE_ENTRIES_LOAD_ATTR);
1357
751k
    PyTypeObject *type = Py_TYPE(owner);
1358
751k
    bool fail;
1359
751k
    if (!_PyType_IsReady(type)) {
1360
        // We *might* not really need this check, but we inherited it from
1361
        // PyObject_GenericGetAttr and friends... and this way we still do the
1362
        // right thing if someone forgets to call PyType_Ready(type):
1363
0
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER);
1364
0
        fail = true;
1365
0
    }
1366
751k
    else if (Py_TYPE(owner)->tp_getattro == PyModule_Type.tp_getattro) {
1367
2.42k
        fail = specialize_module_load_attr(owner, instr, name);
1368
2.42k
    }
1369
749k
    else if (PyType_Check(owner)) {
1370
5.37k
        fail = specialize_class_load_attr(owner, instr, name);
1371
5.37k
    }
1372
743k
    else {
1373
743k
        fail = specialize_instance_load_attr(owner, instr, name);
1374
743k
    }
1375
1376
751k
    if (fail) {
1377
74.1k
        unspecialize(instr);
1378
74.1k
    }
1379
751k
}
1380
1381
Py_NO_INLINE void
1382
_Py_Specialize_StoreAttr(_PyStackRef owner_st, _Py_CODEUNIT *instr, PyObject *name)
1383
211k
{
1384
211k
    PyObject *owner = PyStackRef_AsPyObjectBorrow(owner_st);
1385
1386
211k
    assert(ENABLE_SPECIALIZATION_FT);
1387
211k
    assert(_PyOpcode_Caches[STORE_ATTR] == INLINE_CACHE_ENTRIES_STORE_ATTR);
1388
211k
    PyObject *descr = NULL;
1389
211k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
1390
211k
    PyTypeObject *type = Py_TYPE(owner);
1391
211k
    if (!_PyType_IsReady(type)) {
1392
        // We *might* not really need this check, but we inherited it from
1393
        // PyObject_GenericSetAttr and friends... and this way we still do the
1394
        // right thing if someone forgets to call PyType_Ready(type):
1395
0
        SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OTHER);
1396
0
        goto fail;
1397
0
    }
1398
211k
    if (PyModule_CheckExact(owner)) {
1399
402
        SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OVERRIDDEN);
1400
402
        goto fail;
1401
402
    }
1402
211k
    unsigned int tp_version = 0;
1403
211k
    DescriptorClassification kind = analyze_descriptor_store(type, name, &descr, &tp_version);
1404
211k
    if (tp_version == 0) {
1405
187
        goto fail;
1406
187
    }
1407
210k
    assert(descr != NULL || kind == ABSENT || kind == GETSET_OVERRIDDEN);
1408
210k
    switch(kind) {
1409
128
        case OVERRIDING:
1410
128
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
1411
128
            goto fail;
1412
12
        case METHOD:
1413
12
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_METHOD);
1414
12
            goto fail;
1415
16
        case PROPERTY:
1416
16
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_PROPERTY);
1417
16
            goto fail;
1418
107
        case OBJECT_SLOT:
1419
107
        {
1420
107
            PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
1421
107
            struct PyMemberDef *dmem = member->d_member;
1422
107
            Py_ssize_t offset = dmem->offset;
1423
107
            if (!PyObject_TypeCheck(owner, member->d_common.d_type)) {
1424
0
                SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_EXPECTED_ERROR);
1425
0
                goto fail;
1426
0
            }
1427
107
            if (dmem->flags & Py_READONLY) {
1428
0
                SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_READ_ONLY);
1429
0
                goto fail;
1430
0
            }
1431
107
            if (offset != (uint16_t)offset) {
1432
0
                SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OUT_OF_RANGE);
1433
0
                goto fail;
1434
0
            }
1435
107
            assert(dmem->type == Py_T_OBJECT_EX || dmem->type == _Py_T_OBJECT);
1436
107
            assert(offset > 0);
1437
107
            cache->index = (uint16_t)offset;
1438
107
            write_u32(cache->version, tp_version);
1439
107
            specialize(instr, STORE_ATTR_SLOT);
1440
107
            goto success;
1441
107
        }
1442
0
        case DUNDER_CLASS:
1443
0
        case OTHER_SLOT:
1444
0
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT);
1445
0
            goto fail;
1446
0
        case MUTABLE:
1447
0
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
1448
0
            goto fail;
1449
0
        case GETATTRIBUTE_IS_PYTHON_FUNCTION:
1450
0
        case GETSET_OVERRIDDEN:
1451
0
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OVERRIDDEN);
1452
0
            goto fail;
1453
0
        case BUILTIN_CLASSMETHOD:
1454
0
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD_OBJ);
1455
0
            goto fail;
1456
0
        case PYTHON_CLASSMETHOD:
1457
0
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_CLASS_METHOD_OBJ);
1458
0
            goto fail;
1459
0
        case NON_OVERRIDING:
1460
0
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_DESCRIPTOR);
1461
0
            goto fail;
1462
1.29k
        case NON_DESCRIPTOR:
1463
1.29k
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE);
1464
1.29k
            goto fail;
1465
209k
        case ABSENT:
1466
209k
            if (specialize_dict_access(owner, instr, type, kind, name, tp_version,
1467
209k
                                       STORE_ATTR, STORE_ATTR_INSTANCE_VALUE,
1468
209k
                                       STORE_ATTR_WITH_HINT)) {
1469
205k
                goto success;
1470
205k
            }
1471
210k
    }
1472
6.00k
fail:
1473
6.00k
    Py_XDECREF(descr);
1474
6.00k
    unspecialize(instr);
1475
6.00k
    return;
1476
205k
success:
1477
205k
    Py_XDECREF(descr);
1478
205k
    return;
1479
210k
}
1480
1481
#ifdef Py_STATS
1482
static int
1483
load_attr_fail_kind(DescriptorClassification kind)
1484
{
1485
    switch (kind) {
1486
        case OVERRIDING:
1487
            return SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR;
1488
        case METHOD:
1489
            return SPEC_FAIL_ATTR_METHOD;
1490
        case PROPERTY:
1491
            return SPEC_FAIL_ATTR_PROPERTY;
1492
        case OBJECT_SLOT:
1493
            return SPEC_FAIL_ATTR_OBJECT_SLOT;
1494
        case OTHER_SLOT:
1495
            return SPEC_FAIL_ATTR_NON_OBJECT_SLOT;
1496
        case DUNDER_CLASS:
1497
            return SPEC_FAIL_OTHER;
1498
        case MUTABLE:
1499
            return SPEC_FAIL_ATTR_MUTABLE_CLASS;
1500
        case GETSET_OVERRIDDEN:
1501
        case GETATTRIBUTE_IS_PYTHON_FUNCTION:
1502
            return SPEC_FAIL_OVERRIDDEN;
1503
        case BUILTIN_CLASSMETHOD:
1504
            return SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD;
1505
        case PYTHON_CLASSMETHOD:
1506
            return SPEC_FAIL_ATTR_CLASS_METHOD_OBJ;
1507
        case NON_OVERRIDING:
1508
            return SPEC_FAIL_ATTR_NON_OVERRIDING_DESCRIPTOR;
1509
        case NON_DESCRIPTOR:
1510
            return SPEC_FAIL_ATTR_NOT_DESCRIPTOR;
1511
        case ABSENT:
1512
            return SPEC_FAIL_ATTR_INSTANCE_ATTRIBUTE;
1513
    }
1514
    Py_UNREACHABLE();
1515
}
1516
#endif   // Py_STATS
1517
1518
static int
1519
specialize_class_load_attr(PyObject *owner, _Py_CODEUNIT *instr,
1520
                             PyObject *name)
1521
5.37k
{
1522
5.37k
    assert(PyType_Check(owner));
1523
5.37k
    PyTypeObject *cls = (PyTypeObject *)owner;
1524
5.37k
    _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1);
1525
5.37k
    if (Py_TYPE(cls)->tp_getattro != _Py_type_getattro) {
1526
0
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METACLASS_OVERRIDDEN);
1527
0
        return -1;
1528
0
    }
1529
5.37k
    unsigned int meta_version = 0;
1530
5.37k
    PyObject *metadescriptor = _PyType_LookupRefAndVersion(Py_TYPE(cls), name, &meta_version);
1531
5.37k
    DescriptorClassification metakind = classify_descriptor(metadescriptor, false);
1532
5.37k
    Py_XDECREF(metadescriptor);
1533
5.37k
    switch (metakind) {
1534
164
        case METHOD:
1535
255
        case NON_DESCRIPTOR:
1536
366
        case NON_OVERRIDING:
1537
366
        case BUILTIN_CLASSMETHOD:
1538
366
        case PYTHON_CLASSMETHOD:
1539
2.52k
        case ABSENT:
1540
2.52k
            break;
1541
2.85k
        default:
1542
2.85k
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METACLASS_ATTRIBUTE);
1543
2.85k
            return -1;
1544
5.37k
    }
1545
2.52k
    PyObject *descr = NULL;
1546
2.52k
    DescriptorClassification kind = 0;
1547
2.52k
    unsigned int tp_version = 0;
1548
2.52k
    kind = analyze_descriptor_load(cls, name, &descr, &tp_version);
1549
2.52k
    if (tp_version == 0) {
1550
36
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
1551
36
        Py_XDECREF(descr);
1552
36
        return -1;
1553
36
    }
1554
2.48k
    bool metaclass_check = false;
1555
2.48k
    if ((Py_TYPE(cls)->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) {
1556
977
        metaclass_check = true;
1557
977
        if (meta_version == 0) {
1558
0
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
1559
0
            Py_XDECREF(descr);
1560
0
            return -1;
1561
0
        }
1562
977
    }
1563
2.48k
    switch (kind) {
1564
143
        case METHOD:
1565
726
        case NON_DESCRIPTOR:
1566
            #ifdef Py_GIL_DISABLED
1567
            if (!_PyObject_HasDeferredRefcount(descr)) {
1568
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED);
1569
                Py_XDECREF(descr);
1570
                return -1;
1571
            }
1572
            #endif
1573
726
            write_u32(cache->type_version, tp_version);
1574
726
            write_ptr(cache->descr, descr);
1575
726
            if (metaclass_check) {
1576
406
                write_u32(cache->keys_version, meta_version);
1577
406
                specialize(instr, LOAD_ATTR_CLASS_WITH_METACLASS_CHECK);
1578
406
            }
1579
320
            else {
1580
320
                specialize(instr, LOAD_ATTR_CLASS);
1581
320
            }
1582
726
            Py_XDECREF(descr);
1583
726
            return 0;
1584
#ifdef Py_STATS
1585
        case ABSENT:
1586
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
1587
            Py_XDECREF(descr);
1588
            return -1;
1589
#endif
1590
1.76k
        default:
1591
1.76k
            SPECIALIZATION_FAIL(LOAD_ATTR, load_attr_fail_kind(kind));
1592
1.76k
            Py_XDECREF(descr);
1593
1.76k
            return -1;
1594
2.48k
    }
1595
2.48k
}
1596
1597
// Please collect stats carefully before and after modifying. A subtle change
1598
// can cause a significant drop in cache hits. A possible test is
1599
// python.exe -m test_typing test_re test_dis test_zlib.
1600
static int
1601
specialize_attr_loadclassattr(PyObject *owner, _Py_CODEUNIT *instr,
1602
                              PyObject *name, PyObject *descr,
1603
                              unsigned int tp_version,
1604
                              DescriptorClassification kind, bool is_method,
1605
                              uint32_t shared_keys_version)
1606
108k
{
1607
108k
    _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1);
1608
108k
    PyTypeObject *owner_cls = Py_TYPE(owner);
1609
1610
108k
    assert(descr != NULL);
1611
108k
    assert((is_method && kind == METHOD) || (!is_method && kind == NON_DESCRIPTOR));
1612
1613
    #ifdef Py_GIL_DISABLED
1614
    if (!_PyObject_HasDeferredRefcount(descr)) {
1615
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED);
1616
        return 0;
1617
    }
1618
    #endif
1619
1620
108k
    unsigned long tp_flags = PyType_GetFlags(owner_cls);
1621
108k
    if (tp_flags & Py_TPFLAGS_INLINE_VALUES) {
1622
90.2k
        #ifndef Py_GIL_DISABLED
1623
90.2k
        assert(_PyDictKeys_StringLookup(
1624
90.2k
                   ((PyHeapTypeObject *)owner_cls)->ht_cached_keys, name) < 0);
1625
90.2k
        #endif
1626
90.2k
        if (shared_keys_version == 0) {
1627
0
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
1628
0
            return 0;
1629
0
        }
1630
90.2k
        write_u32(cache->keys_version, shared_keys_version);
1631
90.2k
        specialize(instr, is_method ? LOAD_ATTR_METHOD_WITH_VALUES : LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES);
1632
90.2k
    }
1633
17.8k
    else {
1634
17.8k
        Py_ssize_t dictoffset;
1635
17.8k
        if (tp_flags & Py_TPFLAGS_MANAGED_DICT) {
1636
672
            dictoffset = MANAGED_DICT_OFFSET;
1637
672
        }
1638
17.2k
        else {
1639
17.2k
            dictoffset = owner_cls->tp_dictoffset;
1640
17.2k
            if (dictoffset < 0 || dictoffset > INT16_MAX + MANAGED_DICT_OFFSET) {
1641
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE);
1642
0
                return 0;
1643
0
            }
1644
17.2k
        }
1645
17.8k
        if (dictoffset == 0) {
1646
16.5k
            specialize(instr, is_method ? LOAD_ATTR_METHOD_NO_DICT : LOAD_ATTR_NONDESCRIPTOR_NO_DICT);
1647
16.5k
        }
1648
1.36k
        else if (is_method) {
1649
721
            PyObject **addr = (PyObject **)((char *)owner + dictoffset);
1650
721
            PyObject *dict = FT_ATOMIC_LOAD_PTR_ACQUIRE(*addr);
1651
721
            if (dict) {
1652
679
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);
1653
679
                return 0;
1654
679
            }
1655
            /* Cache entries must be unsigned values, so we offset the
1656
             * dictoffset by MANAGED_DICT_OFFSET.
1657
             * We do the reverse offset in LOAD_ATTR_METHOD_LAZY_DICT */
1658
42
            dictoffset -= MANAGED_DICT_OFFSET;
1659
42
            assert(((uint16_t)dictoffset) == dictoffset);
1660
42
            cache->dict_offset = (uint16_t)dictoffset;
1661
42
            specialize(instr, LOAD_ATTR_METHOD_LAZY_DICT);
1662
42
        }
1663
648
        else {
1664
648
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE);
1665
648
            return 0;
1666
648
        }
1667
17.8k
    }
1668
    /* `descr` is borrowed. This is safe for methods (even inherited ones from
1669
    *  super classes!) as long as tp_version_tag is validated for two main reasons:
1670
    *
1671
    *  1. The class will always hold a reference to the method so it will
1672
    *  usually not be GC-ed. Should it be deleted in Python, e.g.
1673
    *  `del obj.meth`, tp_version_tag will be invalidated, because of reason 2.
1674
    *
1675
    *  2. The pre-existing type method cache (MCACHE) uses the same principles
1676
    *  of caching a borrowed descriptor. The MCACHE infrastructure does all the
1677
    *  heavy lifting for us. E.g. it invalidates tp_version_tag on any MRO
1678
    *  modification, on any type object change along said MRO, etc. (see
1679
    *  PyType_Modified usages in typeobject.c). The MCACHE has been
1680
    *  working since Python 2.6 and it's battle-tested.
1681
    */
1682
106k
    write_u32(cache->type_version, tp_version);
1683
106k
    write_ptr(cache->descr, descr);
1684
106k
    return 1;
1685
108k
}
1686
1687
1688
static void
1689
specialize_load_global_lock_held(
1690
    PyObject *globals, PyObject *builtins,
1691
    _Py_CODEUNIT *instr, PyObject *name)
1692
12.2k
{
1693
12.2k
    assert(ENABLE_SPECIALIZATION_FT);
1694
12.2k
    assert(_PyOpcode_Caches[LOAD_GLOBAL] == INLINE_CACHE_ENTRIES_LOAD_GLOBAL);
1695
    /* Use inline cache */
1696
12.2k
    _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)(instr + 1);
1697
12.2k
    assert(PyUnicode_CheckExact(name));
1698
12.2k
    if (!PyDict_CheckExact(globals)) {
1699
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_DICT);
1700
0
        goto fail;
1701
0
    }
1702
12.2k
    PyDictKeysObject * globals_keys = ((PyDictObject *)globals)->ma_keys;
1703
12.2k
    if (!DK_IS_UNICODE(globals_keys)) {
1704
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT);
1705
0
        goto fail;
1706
0
    }
1707
12.2k
    Py_ssize_t index = _PyDictKeys_StringLookup(globals_keys, name);
1708
12.2k
    if (index == DKIX_ERROR) {
1709
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_EXPECTED_ERROR);
1710
0
        goto fail;
1711
0
    }
1712
12.2k
    PyInterpreterState *interp = _PyInterpreterState_GET();
1713
12.2k
    if (index != DKIX_EMPTY) {
1714
7.36k
        if (index != (uint16_t)index) {
1715
0
            SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1716
0
            goto fail;
1717
0
        }
1718
7.36k
        uint32_t keys_version = _PyDict_GetKeysVersionForCurrentState(
1719
7.36k
                interp, (PyDictObject*) globals);
1720
7.36k
        if (keys_version == 0) {
1721
0
            SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
1722
0
            goto fail;
1723
0
        }
1724
7.36k
        if (keys_version != (uint16_t)keys_version) {
1725
0
            SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1726
0
            goto fail;
1727
0
        }
1728
7.36k
        cache->index = (uint16_t)index;
1729
7.36k
        cache->module_keys_version = (uint16_t)keys_version;
1730
7.36k
        specialize(instr, LOAD_GLOBAL_MODULE);
1731
7.36k
        return;
1732
7.36k
    }
1733
4.84k
    if (!PyDict_CheckExact(builtins)) {
1734
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_DICT);
1735
0
        goto fail;
1736
0
    }
1737
4.84k
    PyDictKeysObject * builtin_keys = ((PyDictObject *)builtins)->ma_keys;
1738
4.84k
    if (!DK_IS_UNICODE(builtin_keys)) {
1739
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT);
1740
0
        goto fail;
1741
0
    }
1742
4.84k
    index = _PyDictKeys_StringLookup(builtin_keys, name);
1743
4.84k
    if (index == DKIX_ERROR) {
1744
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_EXPECTED_ERROR);
1745
0
        goto fail;
1746
0
    }
1747
4.84k
    if (index != (uint16_t)index) {
1748
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1749
0
        goto fail;
1750
0
    }
1751
4.84k
    uint32_t globals_version = _PyDict_GetKeysVersionForCurrentState(
1752
4.84k
            interp, (PyDictObject*) globals);
1753
4.84k
    if (globals_version == 0) {
1754
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
1755
0
        goto fail;
1756
0
    }
1757
4.84k
    if (globals_version != (uint16_t)globals_version) {
1758
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1759
0
        goto fail;
1760
0
    }
1761
4.84k
    uint32_t builtins_version = _PyDict_GetKeysVersionForCurrentState(
1762
4.84k
            interp, (PyDictObject*) builtins);
1763
4.84k
    if (builtins_version == 0) {
1764
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
1765
0
        goto fail;
1766
0
    }
1767
4.84k
    if (builtins_version > UINT16_MAX) {
1768
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1769
0
        goto fail;
1770
0
    }
1771
4.84k
    cache->index = (uint16_t)index;
1772
4.84k
    cache->module_keys_version = (uint16_t)globals_version;
1773
4.84k
    cache->builtin_keys_version = (uint16_t)builtins_version;
1774
4.84k
    specialize(instr, LOAD_GLOBAL_BUILTIN);
1775
4.84k
    return;
1776
0
fail:
1777
0
    unspecialize(instr);
1778
0
}
1779
1780
Py_NO_INLINE void
1781
_Py_Specialize_LoadGlobal(
1782
    PyObject *globals, PyObject *builtins,
1783
    _Py_CODEUNIT *instr, PyObject *name)
1784
12.2k
{
1785
12.2k
    Py_BEGIN_CRITICAL_SECTION2(globals, builtins);
1786
12.2k
    specialize_load_global_lock_held(globals, builtins, instr, name);
1787
12.2k
    Py_END_CRITICAL_SECTION2();
1788
12.2k
}
1789
1790
static int
1791
232k
function_kind(PyCodeObject *code) {
1792
232k
    int flags = code->co_flags;
1793
232k
    if ((flags & (CO_VARKEYWORDS | CO_VARARGS)) || code->co_kwonlyargcount) {
1794
840
        return SPEC_FAIL_CODE_COMPLEX_PARAMETERS;
1795
840
    }
1796
231k
    if ((flags & CO_OPTIMIZED) == 0) {
1797
0
        return SPEC_FAIL_CODE_NOT_OPTIMIZED;
1798
0
    }
1799
231k
    return SIMPLE_FUNCTION;
1800
231k
}
1801
1802
/* Returning false indicates a failure. */
1803
static bool
1804
function_check_args(PyObject *o, int expected_argcount, int opcode)
1805
218k
{
1806
218k
    assert(Py_IS_TYPE(o, &PyFunction_Type));
1807
218k
    PyFunctionObject *func = (PyFunctionObject *)o;
1808
218k
    PyCodeObject *fcode = (PyCodeObject *)func->func_code;
1809
218k
    int kind = function_kind(fcode);
1810
218k
    if (kind != SIMPLE_FUNCTION) {
1811
0
        SPECIALIZATION_FAIL(opcode, kind);
1812
0
        return false;
1813
0
    }
1814
218k
    if (fcode->co_argcount != expected_argcount) {
1815
0
        SPECIALIZATION_FAIL(opcode, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1816
0
        return false;
1817
0
    }
1818
218k
    return true;
1819
218k
}
1820
1821
/* Returning 0 indicates a failure. */
1822
static uint32_t
1823
function_get_version(PyObject *o, int opcode)
1824
0
{
1825
0
    assert(Py_IS_TYPE(o, &PyFunction_Type));
1826
0
    PyFunctionObject *func = (PyFunctionObject *)o;
1827
0
    uint32_t version = _PyFunction_GetVersionForCurrentState(func);
1828
0
    if (!_PyFunction_IsVersionValid(version)) {
1829
0
        SPECIALIZATION_FAIL(opcode, SPEC_FAIL_OUT_OF_VERSIONS);
1830
0
        return 0;
1831
0
    }
1832
0
    return version;
1833
0
}
1834
1835
#ifdef Py_STATS
1836
static int
1837
store_subscr_fail_kind(PyObject *container, PyObject *sub)
1838
{
1839
    PyTypeObject *container_type = Py_TYPE(container);
1840
    PyMappingMethods *as_mapping = container_type->tp_as_mapping;
1841
    if (as_mapping && (as_mapping->mp_ass_subscript
1842
                       == PyDict_Type.tp_as_mapping->mp_ass_subscript)) {
1843
        return SPEC_FAIL_SUBSCR_DICT_SUBCLASS_NO_OVERRIDE;
1844
    }
1845
    if (PyObject_CheckBuffer(container)) {
1846
        if (PyLong_CheckExact(sub) && (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub))) {
1847
            return SPEC_FAIL_OUT_OF_RANGE;
1848
        }
1849
        else if (strcmp(container_type->tp_name, "array.array") == 0) {
1850
            if (PyLong_CheckExact(sub)) {
1851
                return SPEC_FAIL_SUBSCR_ARRAY_INT;
1852
            }
1853
            else if (PySlice_Check(sub)) {
1854
                return SPEC_FAIL_SUBSCR_ARRAY_SLICE;
1855
            }
1856
            else {
1857
                return SPEC_FAIL_OTHER;
1858
            }
1859
        }
1860
        else if (PyByteArray_CheckExact(container)) {
1861
            if (PyLong_CheckExact(sub)) {
1862
                return SPEC_FAIL_SUBSCR_BYTEARRAY_INT;
1863
            }
1864
            else if (PySlice_Check(sub)) {
1865
                return SPEC_FAIL_SUBSCR_BYTEARRAY_SLICE;
1866
            }
1867
            else {
1868
                return SPEC_FAIL_OTHER;
1869
            }
1870
        }
1871
        else {
1872
            if (PyLong_CheckExact(sub)) {
1873
                return SPEC_FAIL_SUBSCR_BUFFER_INT;
1874
            }
1875
            else if (PySlice_Check(sub)) {
1876
                return SPEC_FAIL_SUBSCR_BUFFER_SLICE;
1877
            }
1878
            else {
1879
                return SPEC_FAIL_OTHER;
1880
            }
1881
        }
1882
        return SPEC_FAIL_OTHER;
1883
    }
1884
    PyObject *descriptor = _PyType_Lookup(container_type, &_Py_ID(__setitem__));
1885
    if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {
1886
        PyFunctionObject *func = (PyFunctionObject *)descriptor;
1887
        PyCodeObject *code = (PyCodeObject *)func->func_code;
1888
        int kind = function_kind(code);
1889
        if (kind == SIMPLE_FUNCTION) {
1890
            return SPEC_FAIL_SUBSCR_PY_SIMPLE;
1891
        }
1892
        else {
1893
            return SPEC_FAIL_SUBSCR_PY_OTHER;
1894
        }
1895
    }
1896
    return SPEC_FAIL_OTHER;
1897
}
1898
#endif
1899
1900
Py_NO_INLINE void
1901
_Py_Specialize_StoreSubscr(_PyStackRef container_st, _PyStackRef sub_st, _Py_CODEUNIT *instr)
1902
1.10k
{
1903
1.10k
    PyObject *container = PyStackRef_AsPyObjectBorrow(container_st);
1904
1.10k
    PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st);
1905
1906
1.10k
    assert(ENABLE_SPECIALIZATION_FT);
1907
1.10k
    PyTypeObject *container_type = Py_TYPE(container);
1908
1.10k
    if (container_type == &PyList_Type) {
1909
152
        if (PyLong_CheckExact(sub)) {
1910
150
            if (_PyLong_IsNonNegativeCompact((PyLongObject *)sub)
1911
150
                && ((PyLongObject *)sub)->long_value.ob_digit[0] < (size_t)PyList_GET_SIZE(container))
1912
99
            {
1913
99
                specialize(instr, STORE_SUBSCR_LIST_INT);
1914
99
                return;
1915
99
            }
1916
51
            else {
1917
51
                SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);
1918
51
                unspecialize(instr);
1919
51
                return;
1920
51
            }
1921
150
        }
1922
2
        else if (PySlice_Check(sub)) {
1923
2
            SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_LIST_SLICE);
1924
2
            unspecialize(instr);
1925
2
            return;
1926
2
        }
1927
0
        else {
1928
0
            SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
1929
0
            unspecialize(instr);
1930
0
            return;
1931
0
        }
1932
152
    }
1933
954
    if (container_type == &PyDict_Type) {
1934
672
        specialize(instr, STORE_SUBSCR_DICT);
1935
672
        return;
1936
672
    }
1937
282
    SPECIALIZATION_FAIL(STORE_SUBSCR, store_subscr_fail_kind(container, sub));
1938
282
    unspecialize(instr);
1939
282
}
1940
1941
/* Returns a strong reference. */
1942
static PyObject *
1943
get_init_for_simple_managed_python_class(PyTypeObject *tp, unsigned int *tp_version)
1944
365
{
1945
365
    assert(tp->tp_new == PyBaseObject_Type.tp_new);
1946
365
    if (tp->tp_alloc != PyType_GenericAlloc) {
1947
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OVERRIDDEN);
1948
0
        return NULL;
1949
0
    }
1950
365
    unsigned long tp_flags = PyType_GetFlags(tp);
1951
365
    if (!(tp_flags & Py_TPFLAGS_HEAPTYPE)) {
1952
        /* Is this possible? */
1953
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_EXPECTED_ERROR);
1954
0
        return NULL;
1955
0
    }
1956
365
    PyObject *init = _PyType_LookupRefAndVersion(tp, &_Py_ID(__init__), tp_version);
1957
365
    if (init == NULL || !PyFunction_Check(init)) {
1958
156
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_INIT_NOT_PYTHON);
1959
156
        Py_XDECREF(init);
1960
156
        return NULL;
1961
156
    }
1962
209
    int kind = function_kind((PyCodeObject *)PyFunction_GET_CODE(init));
1963
209
    if (kind != SIMPLE_FUNCTION) {
1964
17
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_INIT_NOT_SIMPLE);
1965
17
        Py_DECREF(init);
1966
17
        return NULL;
1967
17
    }
1968
192
    return init;
1969
209
}
1970
1971
static int
1972
specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
1973
1.40k
{
1974
1.40k
    assert(PyType_Check(callable));
1975
1.40k
    PyTypeObject *tp = _PyType_CAST(callable);
1976
1.40k
    if (tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) {
1977
846
        int oparg = instr->op.arg;
1978
846
        if (nargs == 1 && oparg == 1) {
1979
521
            if (tp == &PyUnicode_Type) {
1980
71
                specialize(instr, CALL_STR_1);
1981
71
                return 0;
1982
71
            }
1983
450
            else if (tp == &PyType_Type) {
1984
94
                specialize(instr, CALL_TYPE_1);
1985
94
                return 0;
1986
94
            }
1987
356
            else if (tp == &PyTuple_Type) {
1988
42
                specialize(instr, CALL_TUPLE_1);
1989
42
                return 0;
1990
42
            }
1991
521
        }
1992
639
        if (tp->tp_vectorcall != NULL) {
1993
428
            specialize(instr, CALL_BUILTIN_CLASS);
1994
428
            return 0;
1995
428
        }
1996
211
        goto generic;
1997
639
    }
1998
562
    if (Py_TYPE(tp) != &PyType_Type) {
1999
17
        goto generic;
2000
17
    }
2001
545
    if (tp->tp_new == PyBaseObject_Type.tp_new) {
2002
365
        unsigned int tp_version = 0;
2003
365
        PyObject *init = get_init_for_simple_managed_python_class(tp, &tp_version);
2004
365
        if (!tp_version) {
2005
12
            SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
2006
12
            Py_XDECREF(init);
2007
12
            return -1;
2008
12
        }
2009
353
        if (init != NULL && _PyType_CacheInitForSpecialization(
2010
180
                                (PyHeapTypeObject *)tp, init, tp_version)) {
2011
180
            _PyCallCache *cache = (_PyCallCache *)(instr + 1);
2012
180
            write_u32(cache->func_version, tp_version);
2013
180
            specialize(instr, CALL_ALLOC_AND_ENTER_INIT);
2014
180
            Py_DECREF(init);
2015
180
            return 0;
2016
180
        }
2017
173
        Py_XDECREF(init);
2018
173
    }
2019
581
generic:
2020
581
    specialize(instr, CALL_NON_PY_GENERAL);
2021
581
    return 0;
2022
545
}
2023
2024
static int
2025
specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr,
2026
                             int nargs)
2027
497k
{
2028
497k
    switch (descr->d_method->ml_flags &
2029
497k
        (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
2030
497k
        METH_KEYWORDS | METH_METHOD)) {
2031
629
        case METH_NOARGS: {
2032
629
            if (nargs != 1) {
2033
0
                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
2034
0
                return -1;
2035
0
            }
2036
629
            specialize(instr, CALL_METHOD_DESCRIPTOR_NOARGS);
2037
629
            return 0;
2038
629
        }
2039
411k
        case METH_O: {
2040
411k
            if (nargs != 2) {
2041
0
                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
2042
0
                return -1;
2043
0
            }
2044
411k
            PyInterpreterState *interp = _PyInterpreterState_GET();
2045
411k
            PyObject *list_append = interp->callable_cache.list_append;
2046
411k
            _Py_CODEUNIT next = instr[INLINE_CACHE_ENTRIES_CALL + 1];
2047
411k
            bool pop = (next.op.code == POP_TOP);
2048
411k
            int oparg = instr->op.arg;
2049
411k
            if ((PyObject *)descr == list_append && oparg == 1 && pop) {
2050
405k
                specialize(instr, CALL_LIST_APPEND);
2051
405k
                return 0;
2052
405k
            }
2053
6.78k
            specialize(instr, CALL_METHOD_DESCRIPTOR_O);
2054
6.78k
            return 0;
2055
411k
        }
2056
1.63k
        case METH_FASTCALL: {
2057
1.63k
            specialize(instr, CALL_METHOD_DESCRIPTOR_FAST);
2058
1.63k
            return 0;
2059
411k
        }
2060
83.3k
        case METH_FASTCALL | METH_KEYWORDS: {
2061
83.3k
            specialize(instr, CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS);
2062
83.3k
            return 0;
2063
411k
        }
2064
497k
    }
2065
266
    specialize(instr, CALL_NON_PY_GENERAL);
2066
266
    return 0;
2067
497k
}
2068
2069
static int
2070
specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
2071
                   bool bound_method)
2072
13.4k
{
2073
13.4k
    _PyCallCache *cache = (_PyCallCache *)(instr + 1);
2074
13.4k
    PyCodeObject *code = (PyCodeObject *)func->func_code;
2075
13.4k
    int kind = function_kind(code);
2076
    /* Don't specialize if PEP 523 is active */
2077
13.4k
    if (_PyInterpreterState_GET()->eval_frame) {
2078
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
2079
0
        return -1;
2080
0
    }
2081
13.4k
    int argcount = -1;
2082
13.4k
    if (kind == SPEC_FAIL_CODE_NOT_OPTIMIZED) {
2083
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CODE_NOT_OPTIMIZED);
2084
0
        return -1;
2085
0
    }
2086
13.4k
    if (kind == SIMPLE_FUNCTION) {
2087
12.7k
        argcount = code->co_argcount;
2088
12.7k
    }
2089
13.4k
    int version = _PyFunction_GetVersionForCurrentState(func);
2090
13.4k
    if (!_PyFunction_IsVersionValid(version)) {
2091
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
2092
0
        return -1;
2093
0
    }
2094
13.4k
    write_u32(cache->func_version, version);
2095
13.4k
    uint8_t opcode;
2096
13.4k
    if (argcount == nargs + bound_method) {
2097
12.5k
        opcode =
2098
12.5k
            bound_method ? CALL_BOUND_METHOD_EXACT_ARGS : CALL_PY_EXACT_ARGS;
2099
12.5k
    }
2100
867
    else {
2101
867
        opcode = bound_method ? CALL_BOUND_METHOD_GENERAL : CALL_PY_GENERAL;
2102
867
    }
2103
13.4k
    specialize(instr, opcode);
2104
13.4k
    return 0;
2105
13.4k
}
2106
2107
2108
static int
2109
specialize_py_call_kw(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
2110
                   bool bound_method)
2111
144
{
2112
144
    _PyCallCache *cache = (_PyCallCache *)(instr + 1);
2113
144
    PyCodeObject *code = (PyCodeObject *)func->func_code;
2114
144
    int kind = function_kind(code);
2115
    /* Don't specialize if PEP 523 is active */
2116
144
    if (_PyInterpreterState_GET()->eval_frame) {
2117
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
2118
0
        return -1;
2119
0
    }
2120
144
    if (kind == SPEC_FAIL_CODE_NOT_OPTIMIZED) {
2121
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CODE_NOT_OPTIMIZED);
2122
0
        return -1;
2123
0
    }
2124
144
    int version = _PyFunction_GetVersionForCurrentState(func);
2125
144
    if (!_PyFunction_IsVersionValid(version)) {
2126
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
2127
0
        return -1;
2128
0
    }
2129
144
    write_u32(cache->func_version, version);
2130
144
    specialize(instr, bound_method ? CALL_KW_BOUND_METHOD : CALL_KW_PY);
2131
144
    return 0;
2132
144
}
2133
2134
static int
2135
specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
2136
1.09M
{
2137
1.09M
    if (PyCFunction_GET_FUNCTION(callable) == NULL) {
2138
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OTHER);
2139
0
        return 1;
2140
0
    }
2141
1.09M
    switch (PyCFunction_GET_FLAGS(callable) &
2142
1.09M
        (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
2143
1.09M
        METH_KEYWORDS | METH_METHOD)) {
2144
1.09M
        case METH_O: {
2145
1.09M
            if (nargs != 1) {
2146
0
                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
2147
0
                return 1;
2148
0
            }
2149
            /* len(o) */
2150
1.09M
            PyInterpreterState *interp = _PyInterpreterState_GET();
2151
1.09M
            if (callable == interp->callable_cache.len && instr->op.arg == 1) {
2152
762
                specialize(instr, CALL_LEN);
2153
762
                return 0;
2154
762
            }
2155
1.09M
            specialize(instr, CALL_BUILTIN_O);
2156
1.09M
            return 0;
2157
1.09M
        }
2158
1.65k
        case METH_FASTCALL: {
2159
1.65k
            if (nargs == 2) {
2160
                /* isinstance(o1, o2) */
2161
1.12k
                PyInterpreterState *interp = _PyInterpreterState_GET();
2162
1.12k
                if (callable == interp->callable_cache.isinstance && instr->op.arg == 2) {
2163
560
                    specialize(instr, CALL_ISINSTANCE);
2164
560
                    return 0;
2165
560
                }
2166
1.12k
            }
2167
1.09k
            specialize(instr, CALL_BUILTIN_FAST);
2168
1.09k
            return 0;
2169
1.65k
        }
2170
434
        case METH_FASTCALL | METH_KEYWORDS: {
2171
434
            specialize(instr, CALL_BUILTIN_FAST_WITH_KEYWORDS);
2172
434
            return 0;
2173
1.65k
        }
2174
295
        default:
2175
295
            specialize(instr, CALL_NON_PY_GENERAL);
2176
295
            return 0;
2177
1.09M
    }
2178
1.09M
}
2179
2180
Py_NO_INLINE void
2181
_Py_Specialize_Call(_PyStackRef callable_st, _Py_CODEUNIT *instr, int nargs)
2182
1.61M
{
2183
1.61M
    PyObject *callable = PyStackRef_AsPyObjectBorrow(callable_st);
2184
2185
1.61M
    assert(ENABLE_SPECIALIZATION_FT);
2186
1.61M
    assert(_PyOpcode_Caches[CALL] == INLINE_CACHE_ENTRIES_CALL);
2187
1.61M
    assert(_Py_OPCODE(*instr) != INSTRUMENTED_CALL);
2188
1.61M
    int fail;
2189
1.61M
    if (PyCFunction_CheckExact(callable)) {
2190
1.09M
        fail = specialize_c_call(callable, instr, nargs);
2191
1.09M
    }
2192
515k
    else if (PyFunction_Check(callable)) {
2193
10.6k
        fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs, false);
2194
10.6k
    }
2195
505k
    else if (PyType_Check(callable)) {
2196
1.40k
        fail = specialize_class_call(callable, instr, nargs);
2197
1.40k
    }
2198
503k
    else if (Py_IS_TYPE(callable, &PyMethodDescr_Type)) {
2199
497k
        fail = specialize_method_descriptor((PyMethodDescrObject *)callable, instr, nargs);
2200
497k
    }
2201
6.11k
    else if (PyMethod_Check(callable)) {
2202
2.85k
        PyObject *func = ((PyMethodObject *)callable)->im_func;
2203
2.85k
        if (PyFunction_Check(func)) {
2204
2.85k
            fail = specialize_py_call((PyFunctionObject *)func, instr, nargs, true);
2205
2.85k
        }
2206
0
        else {
2207
0
            SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_BOUND_METHOD);
2208
0
            fail = -1;
2209
0
        }
2210
2.85k
    }
2211
3.26k
    else {
2212
3.26k
        specialize(instr, CALL_NON_PY_GENERAL);
2213
3.26k
        fail = 0;
2214
3.26k
    }
2215
1.61M
    if (fail) {
2216
12
        unspecialize(instr);
2217
12
    }
2218
1.61M
}
2219
2220
Py_NO_INLINE void
2221
_Py_Specialize_CallKw(_PyStackRef callable_st, _Py_CODEUNIT *instr, int nargs)
2222
390
{
2223
390
    PyObject *callable = PyStackRef_AsPyObjectBorrow(callable_st);
2224
2225
390
    assert(ENABLE_SPECIALIZATION_FT);
2226
390
    assert(_PyOpcode_Caches[CALL_KW] == INLINE_CACHE_ENTRIES_CALL_KW);
2227
390
    assert(_Py_OPCODE(*instr) != INSTRUMENTED_CALL_KW);
2228
390
    int fail;
2229
390
    if (PyFunction_Check(callable)) {
2230
144
        fail = specialize_py_call_kw((PyFunctionObject *)callable, instr, nargs, false);
2231
144
    }
2232
246
    else if (PyMethod_Check(callable)) {
2233
0
        PyObject *func = ((PyMethodObject *)callable)->im_func;
2234
0
        if (PyFunction_Check(func)) {
2235
0
            fail = specialize_py_call_kw((PyFunctionObject *)func, instr, nargs, true);
2236
0
        }
2237
0
        else {
2238
0
            SPECIALIZATION_FAIL(CALL_KW, SPEC_FAIL_CALL_BOUND_METHOD);
2239
0
            fail = -1;
2240
0
        }
2241
0
    }
2242
246
    else {
2243
246
        specialize(instr, CALL_KW_NON_PY);
2244
246
        fail = 0;
2245
246
    }
2246
390
    if (fail) {
2247
0
        unspecialize(instr);
2248
0
    }
2249
390
}
2250
2251
#ifdef Py_STATS
2252
static int
2253
binary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs)
2254
{
2255
    switch (oparg) {
2256
        case NB_ADD:
2257
        case NB_INPLACE_ADD:
2258
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2259
                return SPEC_FAIL_BINARY_OP_ADD_DIFFERENT_TYPES;
2260
            }
2261
            return SPEC_FAIL_BINARY_OP_ADD_OTHER;
2262
        case NB_AND:
2263
        case NB_INPLACE_AND:
2264
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2265
                return SPEC_FAIL_BINARY_OP_AND_DIFFERENT_TYPES;
2266
            }
2267
            if (PyLong_CheckExact(lhs)) {
2268
                return SPEC_FAIL_BINARY_OP_AND_INT;
2269
            }
2270
            return SPEC_FAIL_BINARY_OP_AND_OTHER;
2271
        case NB_FLOOR_DIVIDE:
2272
        case NB_INPLACE_FLOOR_DIVIDE:
2273
            return SPEC_FAIL_BINARY_OP_FLOOR_DIVIDE;
2274
        case NB_LSHIFT:
2275
        case NB_INPLACE_LSHIFT:
2276
            return SPEC_FAIL_BINARY_OP_LSHIFT;
2277
        case NB_MATRIX_MULTIPLY:
2278
        case NB_INPLACE_MATRIX_MULTIPLY:
2279
            return SPEC_FAIL_BINARY_OP_MATRIX_MULTIPLY;
2280
        case NB_MULTIPLY:
2281
        case NB_INPLACE_MULTIPLY:
2282
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2283
                return SPEC_FAIL_BINARY_OP_MULTIPLY_DIFFERENT_TYPES;
2284
            }
2285
            return SPEC_FAIL_BINARY_OP_MULTIPLY_OTHER;
2286
        case NB_OR:
2287
        case NB_INPLACE_OR:
2288
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2289
                return SPEC_FAIL_BINARY_OP_OR_DIFFERENT_TYPES;
2290
            }
2291
            if (PyLong_CheckExact(lhs)) {
2292
                return SPEC_FAIL_BINARY_OP_OR_INT;
2293
            }
2294
            return SPEC_FAIL_BINARY_OP_OR;
2295
        case NB_POWER:
2296
        case NB_INPLACE_POWER:
2297
            return SPEC_FAIL_BINARY_OP_POWER;
2298
        case NB_REMAINDER:
2299
        case NB_INPLACE_REMAINDER:
2300
            return SPEC_FAIL_BINARY_OP_REMAINDER;
2301
        case NB_RSHIFT:
2302
        case NB_INPLACE_RSHIFT:
2303
            return SPEC_FAIL_BINARY_OP_RSHIFT;
2304
        case NB_SUBTRACT:
2305
        case NB_INPLACE_SUBTRACT:
2306
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2307
                return SPEC_FAIL_BINARY_OP_SUBTRACT_DIFFERENT_TYPES;
2308
            }
2309
            return SPEC_FAIL_BINARY_OP_SUBTRACT_OTHER;
2310
        case NB_TRUE_DIVIDE:
2311
        case NB_INPLACE_TRUE_DIVIDE:
2312
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2313
                return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_DIFFERENT_TYPES;
2314
            }
2315
            if (PyFloat_CheckExact(lhs)) {
2316
                return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_FLOAT;
2317
            }
2318
            return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_OTHER;
2319
        case NB_XOR:
2320
        case NB_INPLACE_XOR:
2321
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2322
                return SPEC_FAIL_BINARY_OP_XOR_DIFFERENT_TYPES;
2323
            }
2324
            if (PyLong_CheckExact(lhs)) {
2325
                return SPEC_FAIL_BINARY_OP_XOR_INT;
2326
            }
2327
            return SPEC_FAIL_BINARY_OP_XOR;
2328
        case NB_SUBSCR:
2329
            if (PyList_CheckExact(lhs)) {
2330
                if (PyLong_CheckExact(rhs) && !_PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
2331
                    return SPEC_FAIL_OUT_OF_RANGE;
2332
                }
2333
                if (PySlice_Check(rhs)) {
2334
                    return SPEC_FAIL_BINARY_OP_SUBSCR_LIST_SLICE;
2335
                }
2336
            }
2337
            if (PyTuple_CheckExact(lhs)) {
2338
                if (PyLong_CheckExact(rhs) && !_PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
2339
                    return SPEC_FAIL_OUT_OF_RANGE;
2340
                }
2341
                if (PySlice_Check(rhs)) {
2342
                    return SPEC_FAIL_BINARY_OP_SUBSCR_TUPLE_SLICE;
2343
                }
2344
            }
2345
            if (PyUnicode_CheckExact(lhs)) {
2346
                if (PyLong_CheckExact(rhs) && !_PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
2347
                    return SPEC_FAIL_OUT_OF_RANGE;
2348
                }
2349
                if (PySlice_Check(rhs)) {
2350
                    return SPEC_FAIL_BINARY_OP_SUBSCR_STRING_SLICE;
2351
                }
2352
            }
2353
            unsigned int tp_version;
2354
            PyTypeObject *container_type = Py_TYPE(lhs);
2355
            PyObject *descriptor = _PyType_LookupRefAndVersion(container_type, &_Py_ID(__getitem__), &tp_version);
2356
            if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {
2357
                if (!(container_type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
2358
                    Py_DECREF(descriptor);
2359
                    return SPEC_FAIL_BINARY_OP_SUBSCR_NOT_HEAP_TYPE;
2360
                }
2361
                PyFunctionObject *func = (PyFunctionObject *)descriptor;
2362
                PyCodeObject *fcode = (PyCodeObject *)func->func_code;
2363
                int kind = function_kind(fcode);
2364
                if (kind != SIMPLE_FUNCTION) {
2365
                    Py_DECREF(descriptor);
2366
                    return kind;
2367
                }
2368
                if (fcode->co_argcount != 2) {
2369
                    Py_DECREF(descriptor);
2370
                    return SPEC_FAIL_WRONG_NUMBER_ARGUMENTS;
2371
                }
2372
2373
                if (_PyInterpreterState_GET()->eval_frame) {
2374
                    /* Don't specialize if PEP 523 is active */
2375
                    Py_DECREF(descriptor);
2376
                    return SPEC_FAIL_OTHER;
2377
                }
2378
            }
2379
            Py_XDECREF(descriptor);
2380
2381
            if (PyObject_TypeCheck(lhs, &PyDictProxy_Type)) {
2382
                return SPEC_FAIL_BINARY_OP_SUBSCR_MAPPINGPROXY;
2383
            }
2384
2385
            if (PyObject_TypeCheck(lhs, &PyBytes_Type)) {
2386
                return SPEC_FAIL_BINARY_OP_SUBSCR_BYTES;
2387
            }
2388
2389
            if (PyObject_TypeCheck(lhs, &PyRange_Type)) {
2390
                return SPEC_FAIL_BINARY_OP_SUBSCR_RANGE;
2391
            }
2392
2393
            if (strcmp(container_type->tp_name, "array.array") == 0) {
2394
                return SPEC_FAIL_BINARY_OP_SUBSCR_ARRAY;
2395
            }
2396
2397
            if (strcmp(container_type->tp_name, "re.Match") == 0) {
2398
                return SPEC_FAIL_BINARY_OP_SUBSCR_RE_MATCH;
2399
            }
2400
2401
            if (strcmp(container_type->tp_name, "collections.deque") == 0) {
2402
                return SPEC_FAIL_BINARY_OP_SUBSCR_DEQUE;
2403
            }
2404
2405
            if (strcmp(_PyType_Name(container_type), "EnumDict") == 0) {
2406
                return SPEC_FAIL_BINARY_OP_SUBSCR_ENUMDICT;
2407
            }
2408
2409
            if (strcmp(container_type->tp_name, "StackSummary") == 0) {
2410
                return SPEC_FAIL_BINARY_OP_SUBSCR_STACKSUMMARY;
2411
            }
2412
2413
            if (strcmp(container_type->tp_name, "collections.defaultdict") == 0) {
2414
                return SPEC_FAIL_BINARY_OP_SUBSCR_DEFAULTDICT;
2415
            }
2416
2417
            if (strcmp(container_type->tp_name, "Counter") == 0) {
2418
                return SPEC_FAIL_BINARY_OP_SUBSCR_COUNTER;
2419
            }
2420
2421
            if (strcmp(container_type->tp_name, "collections.OrderedDict") == 0) {
2422
                return SPEC_FAIL_BINARY_OP_SUBSCR_ORDEREDDICT;
2423
            }
2424
2425
            if (strcmp(container_type->tp_name, "time.struct_time") == 0) {
2426
                return SPEC_FAIL_BINARY_OP_SUBSCR_STRUCTTIME;
2427
            }
2428
2429
            if (PySlice_Check(rhs)) {
2430
                return SPEC_FAIL_BINARY_OP_SUBSCR_OTHER_SLICE;
2431
            }
2432
            return SPEC_FAIL_BINARY_OP_SUBSCR;
2433
    }
2434
    Py_UNREACHABLE();
2435
}
2436
#endif
2437
2438
/** Binary Op Specialization Extensions */
2439
2440
/* long-long */
2441
2442
static inline int
2443
is_compactlong(PyObject *v)
2444
970k
{
2445
970k
    return PyLong_CheckExact(v) &&
2446
970k
           _PyLong_IsCompact((PyLongObject *)v);
2447
970k
}
2448
2449
static int
2450
compactlongs_guard(PyObject *lhs, PyObject *rhs)
2451
485k
{
2452
485k
    return (is_compactlong(lhs) && is_compactlong(rhs));
2453
485k
}
2454
2455
#define BITWISE_LONGS_ACTION(NAME, OP) \
2456
    static PyObject * \
2457
    (NAME)(PyObject *lhs, PyObject *rhs) \
2458
484k
    { \
2459
484k
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2460
484k
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2461
484k
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2462
484k
    }
specialize.c:compactlongs_or
Line
Count
Source
2458
459k
    { \
2459
459k
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2460
459k
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2461
459k
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2462
459k
    }
specialize.c:compactlongs_and
Line
Count
Source
2458
25.2k
    { \
2459
25.2k
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2460
25.2k
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2461
25.2k
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2462
25.2k
    }
specialize.c:compactlongs_xor
Line
Count
Source
2458
22
    { \
2459
22
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2460
22
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2461
22
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2462
22
    }
2463
BITWISE_LONGS_ACTION(compactlongs_or, |)
2464
BITWISE_LONGS_ACTION(compactlongs_and, &)
2465
BITWISE_LONGS_ACTION(compactlongs_xor, ^)
2466
#undef BITWISE_LONGS_ACTION
2467
2468
/* float-long */
2469
2470
static inline int
2471
float_compactlong_guard(PyObject *lhs, PyObject *rhs)
2472
5.29M
{
2473
5.29M
    return (
2474
5.29M
        PyFloat_CheckExact(lhs) &&
2475
5.29M
        !isnan(PyFloat_AsDouble(lhs)) &&
2476
5.29M
        PyLong_CheckExact(rhs) &&
2477
5.29M
        _PyLong_IsCompact((PyLongObject *)rhs)
2478
5.29M
    );
2479
5.29M
}
2480
2481
static inline int
2482
nonzero_float_compactlong_guard(PyObject *lhs, PyObject *rhs)
2483
2.64M
{
2484
2.64M
    return (
2485
2.64M
        float_compactlong_guard(lhs, rhs) && !PyLong_IsZero(rhs)
2486
2.64M
    );
2487
2.64M
}
2488
2489
#define FLOAT_LONG_ACTION(NAME, OP) \
2490
    static PyObject * \
2491
    (NAME)(PyObject *lhs, PyObject *rhs) \
2492
5.29M
    { \
2493
5.29M
        double lhs_val = PyFloat_AsDouble(lhs); \
2494
5.29M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2495
5.29M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2496
5.29M
    }
Unexecuted instantiation: specialize.c:float_compactlong_add
Unexecuted instantiation: specialize.c:float_compactlong_subtract
specialize.c:float_compactlong_true_div
Line
Count
Source
2492
2.64M
    { \
2493
2.64M
        double lhs_val = PyFloat_AsDouble(lhs); \
2494
2.64M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2495
2.64M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2496
2.64M
    }
specialize.c:float_compactlong_multiply
Line
Count
Source
2492
2.64M
    { \
2493
2.64M
        double lhs_val = PyFloat_AsDouble(lhs); \
2494
2.64M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2495
2.64M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2496
2.64M
    }
2497
FLOAT_LONG_ACTION(float_compactlong_add, +)
2498
FLOAT_LONG_ACTION(float_compactlong_subtract, -)
2499
FLOAT_LONG_ACTION(float_compactlong_multiply, *)
2500
FLOAT_LONG_ACTION(float_compactlong_true_div, /)
2501
#undef FLOAT_LONG_ACTION
2502
2503
/*  long-float */
2504
2505
static inline int
2506
compactlong_float_guard(PyObject *lhs, PyObject *rhs)
2507
715
{
2508
715
    return (
2509
715
        PyLong_CheckExact(lhs) &&
2510
715
        _PyLong_IsCompact((PyLongObject *)lhs) &&
2511
715
        PyFloat_CheckExact(rhs) &&
2512
715
        !isnan(PyFloat_AsDouble(rhs))
2513
715
    );
2514
715
}
2515
2516
static inline int
2517
nonzero_compactlong_float_guard(PyObject *lhs, PyObject *rhs)
2518
22
{
2519
22
    return (
2520
22
        compactlong_float_guard(lhs, rhs) && PyFloat_AsDouble(rhs) != 0.0
2521
22
    );
2522
22
}
2523
2524
#define LONG_FLOAT_ACTION(NAME, OP) \
2525
    static PyObject * \
2526
    (NAME)(PyObject *lhs, PyObject *rhs) \
2527
0
    { \
2528
0
        double rhs_val = PyFloat_AsDouble(rhs); \
2529
0
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2530
0
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2531
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
2532
LONG_FLOAT_ACTION(compactlong_float_add, +)
2533
LONG_FLOAT_ACTION(compactlong_float_subtract, -)
2534
LONG_FLOAT_ACTION(compactlong_float_multiply, *)
2535
LONG_FLOAT_ACTION(compactlong_float_true_div, /)
2536
#undef LONG_FLOAT_ACTION
2537
2538
static _PyBinaryOpSpecializationDescr binaryop_extend_descrs[] = {
2539
    /* long-long arithmetic */
2540
    {NB_OR, compactlongs_guard, compactlongs_or},
2541
    {NB_AND, compactlongs_guard, compactlongs_and},
2542
    {NB_XOR, compactlongs_guard, compactlongs_xor},
2543
    {NB_INPLACE_OR, compactlongs_guard, compactlongs_or},
2544
    {NB_INPLACE_AND, compactlongs_guard, compactlongs_and},
2545
    {NB_INPLACE_XOR, compactlongs_guard, compactlongs_xor},
2546
2547
    /* float-long arithemetic */
2548
    {NB_ADD, float_compactlong_guard, float_compactlong_add},
2549
    {NB_SUBTRACT, float_compactlong_guard, float_compactlong_subtract},
2550
    {NB_TRUE_DIVIDE, nonzero_float_compactlong_guard, float_compactlong_true_div},
2551
    {NB_MULTIPLY, float_compactlong_guard, float_compactlong_multiply},
2552
2553
    /* float-float arithmetic */
2554
    {NB_ADD, compactlong_float_guard, compactlong_float_add},
2555
    {NB_SUBTRACT, compactlong_float_guard, compactlong_float_subtract},
2556
    {NB_TRUE_DIVIDE, nonzero_compactlong_float_guard, compactlong_float_true_div},
2557
    {NB_MULTIPLY, compactlong_float_guard, compactlong_float_multiply},
2558
};
2559
2560
static int
2561
binary_op_extended_specialization(PyObject *lhs, PyObject *rhs, int oparg,
2562
                                  _PyBinaryOpSpecializationDescr **descr)
2563
29.4k
{
2564
29.4k
    size_t n = sizeof(binaryop_extend_descrs)/sizeof(_PyBinaryOpSpecializationDescr);
2565
436k
    for (size_t i = 0; i < n; i++) {
2566
407k
        _PyBinaryOpSpecializationDescr *d = &binaryop_extend_descrs[i];
2567
407k
        if (d->oparg == oparg && d->guard(lhs, rhs)) {
2568
463
            *descr = d;
2569
463
            return 1;
2570
463
        }
2571
407k
    }
2572
29.0k
    return 0;
2573
29.4k
}
2574
2575
Py_NO_INLINE void
2576
_Py_Specialize_BinaryOp(_PyStackRef lhs_st, _PyStackRef rhs_st, _Py_CODEUNIT *instr,
2577
                        int oparg, _PyStackRef *locals)
2578
1.16M
{
2579
1.16M
    PyObject *lhs = PyStackRef_AsPyObjectBorrow(lhs_st);
2580
1.16M
    PyObject *rhs = PyStackRef_AsPyObjectBorrow(rhs_st);
2581
1.16M
    assert(ENABLE_SPECIALIZATION_FT);
2582
1.16M
    assert(_PyOpcode_Caches[BINARY_OP] == INLINE_CACHE_ENTRIES_BINARY_OP);
2583
2584
1.16M
    _PyBinaryOpCache *cache = (_PyBinaryOpCache *)(instr + 1);
2585
1.16M
    if (instr->op.code == BINARY_OP_EXTEND) {
2586
0
        write_ptr(cache->external_cache, NULL);
2587
0
    }
2588
2589
1.16M
    switch (oparg) {
2590
972
        case NB_ADD:
2591
2.33k
        case NB_INPLACE_ADD:
2592
2.33k
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2593
26
                break;
2594
26
            }
2595
2.31k
            if (PyUnicode_CheckExact(lhs)) {
2596
261
                _Py_CODEUNIT next = instr[INLINE_CACHE_ENTRIES_BINARY_OP + 1];
2597
261
                bool to_store = (next.op.code == STORE_FAST);
2598
261
                if (to_store && PyStackRef_AsPyObjectBorrow(locals[next.op.arg]) == lhs) {
2599
60
                    specialize(instr, BINARY_OP_INPLACE_ADD_UNICODE);
2600
60
                    return;
2601
60
                }
2602
201
                specialize(instr, BINARY_OP_ADD_UNICODE);
2603
201
                return;
2604
261
            }
2605
2.05k
            if (PyLong_CheckExact(lhs)) {
2606
1.56k
                specialize(instr, BINARY_OP_ADD_INT);
2607
1.56k
                return;
2608
1.56k
            }
2609
489
            if (PyFloat_CheckExact(lhs)) {
2610
0
                specialize(instr, BINARY_OP_ADD_FLOAT);
2611
0
                return;
2612
0
            }
2613
489
            break;
2614
2.63k
        case NB_MULTIPLY:
2615
2.63k
        case NB_INPLACE_MULTIPLY:
2616
2.63k
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2617
233
                break;
2618
233
            }
2619
2.40k
            if (PyLong_CheckExact(lhs)) {
2620
2.40k
                specialize(instr, BINARY_OP_MULTIPLY_INT);
2621
2.40k
                return;
2622
2.40k
            }
2623
0
            if (PyFloat_CheckExact(lhs)) {
2624
0
                specialize(instr, BINARY_OP_MULTIPLY_FLOAT);
2625
0
                return;
2626
0
            }
2627
0
            break;
2628
267
        case NB_SUBTRACT:
2629
285
        case NB_INPLACE_SUBTRACT:
2630
285
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2631
0
                break;
2632
0
            }
2633
285
            if (PyLong_CheckExact(lhs)) {
2634
285
                specialize(instr, BINARY_OP_SUBTRACT_INT);
2635
285
                return;
2636
285
            }
2637
0
            if (PyFloat_CheckExact(lhs)) {
2638
0
                specialize(instr, BINARY_OP_SUBTRACT_FLOAT);
2639
0
                return;
2640
0
            }
2641
0
            break;
2642
1.14M
        case NB_SUBSCR:
2643
1.14M
            if (PyLong_CheckExact(rhs) && _PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
2644
1.13M
                if (PyList_CheckExact(lhs)) {
2645
4.02k
                    specialize(instr, BINARY_OP_SUBSCR_LIST_INT);
2646
4.02k
                    return;
2647
4.02k
                }
2648
1.12M
                if (PyTuple_CheckExact(lhs)) {
2649
438
                    specialize(instr, BINARY_OP_SUBSCR_TUPLE_INT);
2650
438
                    return;
2651
438
                }
2652
1.12M
                if (PyUnicode_CheckExact(lhs)) {
2653
1.12M
                    specialize(instr, BINARY_OP_SUBSCR_STR_INT);
2654
1.12M
                    return;
2655
1.12M
                }
2656
1.12M
            }
2657
19.4k
            if (PyDict_CheckExact(lhs)) {
2658
276
                specialize(instr, BINARY_OP_SUBSCR_DICT);
2659
276
                return;
2660
276
            }
2661
19.1k
            if (PyList_CheckExact(lhs) && PySlice_Check(rhs)) {
2662
29
                specialize(instr, BINARY_OP_SUBSCR_LIST_SLICE);
2663
29
                return;
2664
29
            }
2665
19.1k
            unsigned int tp_version;
2666
19.1k
            PyTypeObject *container_type = Py_TYPE(lhs);
2667
19.1k
            PyObject *descriptor = _PyType_LookupRefAndVersion(container_type, &_Py_ID(__getitem__), &tp_version);
2668
19.1k
            if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type &&
2669
19.1k
                container_type->tp_flags & Py_TPFLAGS_HEAPTYPE)
2670
80
            {
2671
80
                PyFunctionObject *func = (PyFunctionObject *)descriptor;
2672
80
                PyCodeObject *fcode = (PyCodeObject *)func->func_code;
2673
80
                int kind = function_kind(fcode);
2674
80
                PyHeapTypeObject *ht = (PyHeapTypeObject *)container_type;
2675
80
                if (kind == SIMPLE_FUNCTION &&
2676
80
                    fcode->co_argcount == 2 &&
2677
80
                    !_PyInterpreterState_GET()->eval_frame && /* Don't specialize if PEP 523 is active */
2678
80
                    _PyType_CacheGetItemForSpecialization(ht, descriptor, (uint32_t)tp_version))
2679
80
                {
2680
80
                    specialize(instr, BINARY_OP_SUBSCR_GETITEM);
2681
80
                    Py_DECREF(descriptor);
2682
80
                    return;
2683
80
                }
2684
80
            }
2685
19.0k
            Py_XDECREF(descriptor);
2686
19.0k
            break;
2687
1.16M
    }
2688
2689
29.4k
    _PyBinaryOpSpecializationDescr *descr;
2690
29.4k
    if (binary_op_extended_specialization(lhs, rhs, oparg, &descr)) {
2691
463
        specialize(instr, BINARY_OP_EXTEND);
2692
463
        write_ptr(cache->external_cache, (void*)descr);
2693
463
        return;
2694
463
    }
2695
2696
29.0k
    SPECIALIZATION_FAIL(BINARY_OP, binary_op_fail_kind(oparg, lhs, rhs));
2697
29.0k
    unspecialize(instr);
2698
29.0k
    return;
2699
29.4k
}
2700
2701
2702
#ifdef Py_STATS
2703
static int
2704
compare_op_fail_kind(PyObject *lhs, PyObject *rhs)
2705
{
2706
    if (Py_TYPE(lhs) != Py_TYPE(rhs)) {
2707
        if (PyFloat_CheckExact(lhs) && PyLong_CheckExact(rhs)) {
2708
            return SPEC_FAIL_COMPARE_OP_FLOAT_LONG;
2709
        }
2710
        if (PyLong_CheckExact(lhs) && PyFloat_CheckExact(rhs)) {
2711
            return SPEC_FAIL_COMPARE_OP_LONG_FLOAT;
2712
        }
2713
        return SPEC_FAIL_COMPARE_OP_DIFFERENT_TYPES;
2714
    }
2715
    if (PyBytes_CheckExact(lhs)) {
2716
        return SPEC_FAIL_COMPARE_OP_BYTES;
2717
    }
2718
    if (PyTuple_CheckExact(lhs)) {
2719
        return SPEC_FAIL_COMPARE_OP_TUPLE;
2720
    }
2721
    if (PyList_CheckExact(lhs)) {
2722
        return SPEC_FAIL_COMPARE_OP_LIST;
2723
    }
2724
    if (PySet_CheckExact(lhs) || PyFrozenSet_CheckExact(lhs)) {
2725
        return SPEC_FAIL_COMPARE_OP_SET;
2726
    }
2727
    if (PyBool_Check(lhs)) {
2728
        return SPEC_FAIL_COMPARE_OP_BOOL;
2729
    }
2730
    if (Py_TYPE(lhs)->tp_richcompare == PyBaseObject_Type.tp_richcompare) {
2731
        return SPEC_FAIL_COMPARE_OP_BASEOBJECT;
2732
    }
2733
    return SPEC_FAIL_OTHER;
2734
}
2735
#endif   // Py_STATS
2736
2737
Py_NO_INLINE void
2738
_Py_Specialize_CompareOp(_PyStackRef lhs_st, _PyStackRef rhs_st, _Py_CODEUNIT *instr,
2739
                         int oparg)
2740
19.5k
{
2741
19.5k
    PyObject *lhs = PyStackRef_AsPyObjectBorrow(lhs_st);
2742
19.5k
    PyObject *rhs = PyStackRef_AsPyObjectBorrow(rhs_st);
2743
19.5k
    uint8_t specialized_op;
2744
2745
19.5k
    assert(ENABLE_SPECIALIZATION_FT);
2746
19.5k
    assert(_PyOpcode_Caches[COMPARE_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP);
2747
    // All of these specializations compute boolean values, so they're all valid
2748
    // regardless of the fifth-lowest oparg bit.
2749
19.5k
    if (Py_TYPE(lhs) != Py_TYPE(rhs)) {
2750
5.87k
        SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
2751
5.87k
        goto failure;
2752
5.87k
    }
2753
13.6k
    if (PyFloat_CheckExact(lhs)) {
2754
18
        specialized_op = COMPARE_OP_FLOAT;
2755
18
        goto success;
2756
18
    }
2757
13.6k
    if (PyLong_CheckExact(lhs)) {
2758
5.64k
        if (_PyLong_IsCompact((PyLongObject *)lhs) && _PyLong_IsCompact((PyLongObject *)rhs)) {
2759
2.63k
            specialized_op = COMPARE_OP_INT;
2760
2.63k
            goto success;
2761
2.63k
        }
2762
3.01k
        else {
2763
3.01k
            SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_BIG_INT);
2764
3.01k
            goto failure;
2765
3.01k
        }
2766
5.64k
    }
2767
8.02k
    if (PyUnicode_CheckExact(lhs)) {
2768
7.66k
        int cmp = oparg >> 5;
2769
7.66k
        if (cmp != Py_EQ && cmp != Py_NE) {
2770
6.42k
            SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_STRING);
2771
6.42k
            goto failure;
2772
6.42k
        }
2773
1.24k
        else {
2774
1.24k
            specialized_op = COMPARE_OP_STR;
2775
1.24k
            goto success;
2776
1.24k
        }
2777
7.66k
    }
2778
361
    SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
2779
15.6k
failure:
2780
15.6k
    unspecialize(instr);
2781
15.6k
    return;
2782
3.89k
success:
2783
3.89k
    specialize(instr, specialized_op);
2784
3.89k
}
2785
2786
#ifdef Py_STATS
2787
static int
2788
unpack_sequence_fail_kind(PyObject *seq)
2789
{
2790
    if (PySequence_Check(seq)) {
2791
        return SPEC_FAIL_UNPACK_SEQUENCE_SEQUENCE;
2792
    }
2793
    if (PyIter_Check(seq)) {
2794
        return SPEC_FAIL_UNPACK_SEQUENCE_ITERATOR;
2795
    }
2796
    return SPEC_FAIL_OTHER;
2797
}
2798
#endif   // Py_STATS
2799
2800
Py_NO_INLINE void
2801
_Py_Specialize_UnpackSequence(_PyStackRef seq_st, _Py_CODEUNIT *instr, int oparg)
2802
12.1k
{
2803
12.1k
    PyObject *seq = PyStackRef_AsPyObjectBorrow(seq_st);
2804
2805
12.1k
    assert(ENABLE_SPECIALIZATION_FT);
2806
12.1k
    assert(_PyOpcode_Caches[UNPACK_SEQUENCE] ==
2807
12.1k
           INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE);
2808
12.1k
    if (PyTuple_CheckExact(seq)) {
2809
1.00k
        if (PyTuple_GET_SIZE(seq) != oparg) {
2810
0
            SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_EXPECTED_ERROR);
2811
0
            unspecialize(instr);
2812
0
            return;
2813
0
        }
2814
1.00k
        if (PyTuple_GET_SIZE(seq) == 2) {
2815
513
            specialize(instr, UNPACK_SEQUENCE_TWO_TUPLE);
2816
513
            return;
2817
513
        }
2818
495
        specialize(instr, UNPACK_SEQUENCE_TUPLE);
2819
495
        return;
2820
1.00k
    }
2821
11.1k
    if (PyList_CheckExact(seq)) {
2822
10.6k
        if (PyList_GET_SIZE(seq) != oparg) {
2823
7.96k
            SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_EXPECTED_ERROR);
2824
7.96k
            unspecialize(instr);
2825
7.96k
            return;
2826
7.96k
        }
2827
2.64k
        specialize(instr, UNPACK_SEQUENCE_LIST);
2828
2.64k
        return;
2829
10.6k
    }
2830
585
    SPECIALIZATION_FAIL(UNPACK_SEQUENCE, unpack_sequence_fail_kind(seq));
2831
585
    unspecialize(instr);
2832
585
}
2833
2834
#ifdef Py_STATS
2835
int
2836
 _PySpecialization_ClassifyIterator(PyObject *iter)
2837
{
2838
    if (PyGen_CheckExact(iter)) {
2839
        return SPEC_FAIL_ITER_GENERATOR;
2840
    }
2841
    if (PyCoro_CheckExact(iter)) {
2842
        return SPEC_FAIL_ITER_COROUTINE;
2843
    }
2844
    if (PyAsyncGen_CheckExact(iter)) {
2845
        return SPEC_FAIL_ITER_ASYNC_GENERATOR;
2846
    }
2847
    if (PyAsyncGenASend_CheckExact(iter)) {
2848
        return SPEC_FAIL_ITER_ASYNC_GENERATOR_SEND;
2849
    }
2850
    PyTypeObject *t = Py_TYPE(iter);
2851
    if (t == &PyListIter_Type) {
2852
        return SPEC_FAIL_ITER_LIST;
2853
    }
2854
    if (t == &PyTupleIter_Type) {
2855
        return SPEC_FAIL_ITER_TUPLE;
2856
    }
2857
    if (t == &PyDictIterKey_Type) {
2858
        return SPEC_FAIL_ITER_DICT_KEYS;
2859
    }
2860
    if (t == &PyDictIterValue_Type) {
2861
        return SPEC_FAIL_ITER_DICT_VALUES;
2862
    }
2863
    if (t == &PyDictIterItem_Type) {
2864
        return SPEC_FAIL_ITER_DICT_ITEMS;
2865
    }
2866
    if (t == &PySetIter_Type) {
2867
        return SPEC_FAIL_ITER_SET;
2868
    }
2869
    if (t == &PyUnicodeIter_Type) {
2870
        return SPEC_FAIL_ITER_STRING;
2871
    }
2872
    if (t == &PyBytesIter_Type) {
2873
        return SPEC_FAIL_ITER_BYTES;
2874
    }
2875
    if (t == &PyRangeIter_Type) {
2876
        return SPEC_FAIL_ITER_RANGE;
2877
    }
2878
    if (t == &PyEnum_Type) {
2879
        return SPEC_FAIL_ITER_ENUMERATE;
2880
    }
2881
    if (t == &PyMap_Type) {
2882
        return SPEC_FAIL_ITER_MAP;
2883
    }
2884
    if (t == &PyZip_Type) {
2885
        return SPEC_FAIL_ITER_ZIP;
2886
    }
2887
    if (t == &PySeqIter_Type) {
2888
        return SPEC_FAIL_ITER_SEQ_ITER;
2889
    }
2890
    if (t == &PyListRevIter_Type) {
2891
        return SPEC_FAIL_ITER_REVERSED_LIST;
2892
    }
2893
    if (t == &_PyUnicodeASCIIIter_Type) {
2894
        return SPEC_FAIL_ITER_ASCII_STRING;
2895
    }
2896
    const char *name = t->tp_name;
2897
    if (strncmp(name, "itertools", 9) == 0) {
2898
        return SPEC_FAIL_ITER_ITERTOOLS;
2899
    }
2900
    if (strncmp(name, "callable_iterator", 17) == 0) {
2901
        return SPEC_FAIL_ITER_CALLABLE;
2902
    }
2903
    return SPEC_FAIL_OTHER;
2904
}
2905
#endif   // Py_STATS
2906
2907
Py_NO_INLINE void
2908
_Py_Specialize_ForIter(_PyStackRef iter, _PyStackRef null_or_index, _Py_CODEUNIT *instr, int oparg)
2909
98.4k
{
2910
98.4k
    assert(ENABLE_SPECIALIZATION_FT);
2911
98.4k
    assert(_PyOpcode_Caches[FOR_ITER] == INLINE_CACHE_ENTRIES_FOR_ITER);
2912
98.4k
    PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
2913
98.4k
    PyTypeObject *tp = Py_TYPE(iter_o);
2914
2915
98.4k
    if (PyStackRef_IsNull(null_or_index)) {
2916
#ifdef Py_GIL_DISABLED
2917
        // Only specialize for uniquely referenced iterators, so that we know
2918
        // they're only referenced by this one thread. This is more limiting
2919
        // than we need (even `it = iter(mylist); for item in it:` won't get
2920
        // specialized) but we don't have a way to check whether we're the only
2921
        // _thread_ who has access to the object.
2922
        if (!_PyObject_IsUniquelyReferenced(iter_o)) {
2923
            goto failure;
2924
        }
2925
#endif
2926
97.4k
        if (tp == &PyRangeIter_Type) {
2927
81
            specialize(instr, FOR_ITER_RANGE);
2928
81
            return;
2929
81
        }
2930
97.3k
        else if (tp == &PyGen_Type && oparg <= SHRT_MAX) {
2931
            // Generators are very much not thread-safe, so don't worry about
2932
            // the specialization not being thread-safe.
2933
540
            assert(instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == END_FOR  ||
2934
540
                instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == INSTRUMENTED_END_FOR
2935
540
            );
2936
            /* Don't specialize if PEP 523 is active */
2937
540
            if (_PyInterpreterState_GET()->eval_frame) {
2938
0
                goto failure;
2939
0
            }
2940
540
            specialize(instr, FOR_ITER_GEN);
2941
540
            return;
2942
540
        }
2943
97.4k
    }
2944
1.00k
    else {
2945
1.00k
        if (tp == &PyList_Type) {
2946
#ifdef Py_GIL_DISABLED
2947
            // Only specialize for lists owned by this thread or shared
2948
            if (!_Py_IsOwnedByCurrentThread(iter_o) && !_PyObject_GC_IS_SHARED(iter_o)) {
2949
                goto failure;
2950
            }
2951
#endif
2952
535
            specialize(instr, FOR_ITER_LIST);
2953
535
            return;
2954
535
        }
2955
469
        else if (tp == &PyTuple_Type) {
2956
469
            specialize(instr, FOR_ITER_TUPLE);
2957
469
            return;
2958
469
        }
2959
1.00k
    }
2960
96.8k
failure:
2961
96.8k
    SPECIALIZATION_FAIL(FOR_ITER,
2962
96.8k
                        _PySpecialization_ClassifyIterator(iter_o));
2963
96.8k
    unspecialize(instr);
2964
96.8k
}
2965
2966
Py_NO_INLINE void
2967
_Py_Specialize_Send(_PyStackRef receiver_st, _Py_CODEUNIT *instr)
2968
4.81k
{
2969
4.81k
    PyObject *receiver = PyStackRef_AsPyObjectBorrow(receiver_st);
2970
2971
4.81k
    assert(ENABLE_SPECIALIZATION_FT);
2972
4.81k
    assert(_PyOpcode_Caches[SEND] == INLINE_CACHE_ENTRIES_SEND);
2973
4.81k
    PyTypeObject *tp = Py_TYPE(receiver);
2974
4.81k
    if (tp == &PyGen_Type || tp == &PyCoro_Type) {
2975
        /* Don't specialize if PEP 523 is active */
2976
1.06k
        if (_PyInterpreterState_GET()->eval_frame) {
2977
0
            SPECIALIZATION_FAIL(SEND, SPEC_FAIL_OTHER);
2978
0
            goto failure;
2979
0
        }
2980
1.06k
        specialize(instr, SEND_GEN);
2981
1.06k
        return;
2982
1.06k
    }
2983
3.75k
    SPECIALIZATION_FAIL(SEND,
2984
3.75k
                        _PySpecialization_ClassifyIterator(receiver));
2985
3.75k
failure:
2986
3.75k
    unspecialize(instr);
2987
3.75k
}
2988
2989
#ifdef Py_STATS
2990
static int
2991
to_bool_fail_kind(PyObject *value)
2992
{
2993
    if (PyByteArray_CheckExact(value)) {
2994
        return SPEC_FAIL_TO_BOOL_BYTEARRAY;
2995
    }
2996
    if (PyBytes_CheckExact(value)) {
2997
        return SPEC_FAIL_TO_BOOL_BYTES;
2998
    }
2999
    if (PyDict_CheckExact(value)) {
3000
        return SPEC_FAIL_TO_BOOL_DICT;
3001
    }
3002
    if (PyFloat_CheckExact(value)) {
3003
        return SPEC_FAIL_TO_BOOL_FLOAT;
3004
    }
3005
    if (PyMemoryView_Check(value)) {
3006
        return SPEC_FAIL_TO_BOOL_MEMORY_VIEW;
3007
    }
3008
    if (PyAnySet_CheckExact(value)) {
3009
        return SPEC_FAIL_TO_BOOL_SET;
3010
    }
3011
    if (PyTuple_CheckExact(value)) {
3012
        return SPEC_FAIL_TO_BOOL_TUPLE;
3013
    }
3014
    return SPEC_FAIL_OTHER;
3015
}
3016
#endif  // Py_STATS
3017
3018
static int
3019
check_type_always_true(PyTypeObject *ty)
3020
66.5k
{
3021
66.5k
    PyNumberMethods *nb = ty->tp_as_number;
3022
66.5k
    if (nb && nb->nb_bool) {
3023
24
        return SPEC_FAIL_TO_BOOL_NUMBER;
3024
24
    }
3025
66.5k
    PyMappingMethods *mp = ty->tp_as_mapping;
3026
66.5k
    if (mp && mp->mp_length) {
3027
9.63k
        return SPEC_FAIL_TO_BOOL_MAPPING;
3028
9.63k
    }
3029
56.9k
    PySequenceMethods *sq = ty->tp_as_sequence;
3030
56.9k
    if (sq && sq->sq_length) {
3031
9.41k
      return SPEC_FAIL_TO_BOOL_SEQUENCE;
3032
9.41k
    }
3033
47.5k
    return 0;
3034
56.9k
}
3035
3036
Py_NO_INLINE void
3037
_Py_Specialize_ToBool(_PyStackRef value_o, _Py_CODEUNIT *instr)
3038
140k
{
3039
140k
    assert(ENABLE_SPECIALIZATION_FT);
3040
140k
    assert(_PyOpcode_Caches[TO_BOOL] == INLINE_CACHE_ENTRIES_TO_BOOL);
3041
140k
    _PyToBoolCache *cache = (_PyToBoolCache *)(instr + 1);
3042
140k
    PyObject *value = PyStackRef_AsPyObjectBorrow(value_o);
3043
140k
    uint8_t specialized_op;
3044
140k
    if (PyBool_Check(value)) {
3045
2.12k
        specialized_op = TO_BOOL_BOOL;
3046
2.12k
        goto success;
3047
2.12k
    }
3048
138k
    if (PyLong_CheckExact(value)) {
3049
1.45k
        specialized_op = TO_BOOL_INT;
3050
1.45k
        goto success;
3051
1.45k
    }
3052
136k
    if (PyList_CheckExact(value)) {
3053
202
        specialized_op = TO_BOOL_LIST;
3054
202
        goto success;
3055
202
    }
3056
136k
    if (Py_IsNone(value)) {
3057
57.8k
        specialized_op = TO_BOOL_NONE;
3058
57.8k
        goto success;
3059
57.8k
    }
3060
78.8k
    if (PyUnicode_CheckExact(value)) {
3061
11.1k
        specialized_op = TO_BOOL_STR;
3062
11.1k
        goto success;
3063
11.1k
    }
3064
67.6k
    if (PyType_HasFeature(Py_TYPE(value), Py_TPFLAGS_HEAPTYPE)) {
3065
66.5k
        unsigned int version = 0;
3066
66.5k
        int err = _PyType_Validate(Py_TYPE(value), check_type_always_true, &version);
3067
66.5k
        if (err < 0) {
3068
0
            SPECIALIZATION_FAIL(TO_BOOL, SPEC_FAIL_OUT_OF_VERSIONS);
3069
0
            goto failure;
3070
0
        }
3071
66.5k
        else if (err > 0) {
3072
19.0k
            SPECIALIZATION_FAIL(TO_BOOL, err);
3073
19.0k
            goto failure;
3074
19.0k
        }
3075
3076
47.5k
        assert(err == 0);
3077
47.5k
        assert(version);
3078
47.5k
        write_u32(cache->version, version);
3079
47.5k
        specialized_op = TO_BOOL_ALWAYS_TRUE;
3080
47.5k
        goto success;
3081
66.5k
    }
3082
3083
1.06k
    SPECIALIZATION_FAIL(TO_BOOL, to_bool_fail_kind(value));
3084
20.1k
failure:
3085
20.1k
    unspecialize(instr);
3086
20.1k
    return;
3087
120k
success:
3088
120k
    specialize(instr, specialized_op);
3089
120k
}
3090
3091
#ifdef Py_STATS
3092
static int
3093
containsop_fail_kind(PyObject *value) {
3094
    if (PyUnicode_CheckExact(value)) {
3095
        return SPEC_FAIL_CONTAINS_OP_STR;
3096
    }
3097
    if (PyList_CheckExact(value)) {
3098
        return SPEC_FAIL_CONTAINS_OP_LIST;
3099
    }
3100
    if (PyTuple_CheckExact(value)) {
3101
        return SPEC_FAIL_CONTAINS_OP_TUPLE;
3102
    }
3103
    if (PyType_Check(value)) {
3104
        return SPEC_FAIL_CONTAINS_OP_USER_CLASS;
3105
    }
3106
    return SPEC_FAIL_OTHER;
3107
}
3108
#endif
3109
3110
Py_NO_INLINE void
3111
_Py_Specialize_ContainsOp(_PyStackRef value_st, _Py_CODEUNIT *instr)
3112
27.6k
{
3113
27.6k
    PyObject *value = PyStackRef_AsPyObjectBorrow(value_st);
3114
3115
27.6k
    assert(ENABLE_SPECIALIZATION_FT);
3116
27.6k
    assert(_PyOpcode_Caches[CONTAINS_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP);
3117
27.6k
    if (PyDict_CheckExact(value)) {
3118
238
        specialize(instr, CONTAINS_OP_DICT);
3119
238
        return;
3120
238
    }
3121
27.3k
    if (PySet_CheckExact(value) || PyFrozenSet_CheckExact(value)) {
3122
264
        specialize(instr, CONTAINS_OP_SET);
3123
264
        return;
3124
264
    }
3125
3126
27.1k
    SPECIALIZATION_FAIL(CONTAINS_OP, containsop_fail_kind(value));
3127
27.1k
    unspecialize(instr);
3128
27.1k
    return;
3129
27.3k
}
3130
3131
#ifdef Py_STATS
3132
void
3133
_Py_GatherStats_GetIter(_PyStackRef iterable)
3134
{
3135
    PyTypeObject *tp = PyStackRef_TYPE(iterable);
3136
    int kind = SPEC_FAIL_OTHER;
3137
    if (tp == &PyTuple_Type) {
3138
        kind = SPEC_FAIL_ITER_TUPLE;
3139
    }
3140
    else if (tp == &PyList_Type) {
3141
        kind = SPEC_FAIL_ITER_LIST;
3142
    }
3143
    else if (tp == &PyDict_Type) {
3144
        kind = SPEC_FAIL_ITER_DICT_KEYS;
3145
    }
3146
    else if (tp == &PySet_Type) {
3147
        kind = SPEC_FAIL_ITER_SET;
3148
    }
3149
    else if (tp == &PyBytes_Type) {
3150
        kind = SPEC_FAIL_ITER_BYTES;
3151
    }
3152
    else if (tp == &PyEnum_Type) {
3153
        kind = SPEC_FAIL_ITER_ENUMERATE;
3154
    }
3155
    else if (tp == &PyUnicode_Type) {
3156
        kind = SPEC_FAIL_ITER_STRING;
3157
    }
3158
    else if (tp == &PyGen_Type) {
3159
        kind = SPEC_FAIL_ITER_GENERATOR;
3160
    }
3161
    else if (tp == &PyCoro_Type) {
3162
        kind = SPEC_FAIL_ITER_COROUTINE;
3163
    }
3164
    else if (tp == &PyAsyncGen_Type) {
3165
        kind = SPEC_FAIL_ITER_ASYNC_GENERATOR;
3166
    }
3167
    else if (tp == &_PyAsyncGenASend_Type) {
3168
        kind = SPEC_FAIL_ITER_ASYNC_GENERATOR_SEND;
3169
    }
3170
    else if (tp->tp_iter == PyObject_SelfIter) {
3171
        kind = SPEC_FAIL_ITER_SELF;
3172
    }
3173
    SPECIALIZATION_FAIL(GET_ITER, kind);
3174
}
3175
#endif
3176
3177
3178
/* Code init cleanup.
3179
 * CALL_ALLOC_AND_ENTER_INIT will set up
3180
 * the frame to execute the EXIT_INIT_CHECK
3181
 * instruction.
3182
 * Ends with a RESUME so that it is not traced.
3183
 * This is used as a plain code object, not a function,
3184
 * so must not access globals or builtins.
3185
 * There are a few other constraints imposed on the code
3186
 * by the free-threaded build:
3187
 *
3188
 * 1. The RESUME instruction must not be executed. Otherwise we may attempt to
3189
 *    free the statically allocated TLBC array.
3190
 * 2. It must contain no specializable instructions. Specializing multiple
3191
 *    copies of the same bytecode is not thread-safe in free-threaded builds.
3192
 *
3193
 * This should be dynamically allocated if either of those restrictions need to
3194
 * be lifted.
3195
 */
3196
3197
#define NO_LOC_4 (128 | (PY_CODE_LOCATION_INFO_NONE << 3) | 3)
3198
3199
static const PyBytesObject no_location = {
3200
    PyVarObject_HEAD_INIT(&PyBytes_Type, 1)
3201
    .ob_sval = { NO_LOC_4 }
3202
};
3203
3204
#ifdef Py_GIL_DISABLED
3205
static _PyCodeArray init_cleanup_tlbc = {
3206
    .size = 1,
3207
    .entries = {(char*) &_Py_InitCleanup.co_code_adaptive},
3208
};
3209
#endif
3210
3211
const struct _PyCode8 _Py_InitCleanup = {
3212
    _PyVarObject_HEAD_INIT(&PyCode_Type, 3),
3213
    .co_consts = (PyObject *)&_Py_SINGLETON(tuple_empty),
3214
    .co_names = (PyObject *)&_Py_SINGLETON(tuple_empty),
3215
    .co_exceptiontable = (PyObject *)&_Py_SINGLETON(bytes_empty),
3216
    .co_flags = CO_OPTIMIZED | CO_NO_MONITORING_EVENTS,
3217
    .co_localsplusnames = (PyObject *)&_Py_SINGLETON(tuple_empty),
3218
    .co_localspluskinds = (PyObject *)&_Py_SINGLETON(bytes_empty),
3219
    .co_filename = &_Py_ID(__init__),
3220
    .co_name = &_Py_ID(__init__),
3221
    .co_qualname = &_Py_ID(__init__),
3222
    .co_linetable = (PyObject *)&no_location,
3223
    ._co_firsttraceable = 4,
3224
    .co_stacksize = 2,
3225
    .co_framesize = 2 + FRAME_SPECIALS_SIZE,
3226
#ifdef Py_GIL_DISABLED
3227
    .co_tlbc = &init_cleanup_tlbc,
3228
#endif
3229
    .co_code_adaptive = {
3230
        EXIT_INIT_CHECK, 0,
3231
        RETURN_VALUE, 0,
3232
        RESUME, RESUME_AT_FUNC_START,
3233
    }
3234
};