Coverage Report

Created: 2025-10-12 06:48

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