Coverage Report

Created: 2026-06-09 06:53

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