Coverage Report

Created: 2026-06-21 06:15

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
238k
#  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.9k
{
49
    // Compiler can't know if types.coroutine() will be called,
50
    // so fix up here
51
30.9k
    if (instruction->op.arg) {
52
567
        if (flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE)) {
53
0
            instruction->op.arg = GET_ITER_YIELD_FROM_NO_CHECK;
54
0
        }
55
567
        else {
56
567
            instruction->op.arg = GET_ITER_YIELD_FROM_CORO_CHECK;
57
567
        }
58
567
    }
59
30.9k
}
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
191k
{
65
191k
    #if ENABLE_SPECIALIZATION
66
191k
    _Py_BackoffCounter jump_counter, adaptive_counter, resume_counter;
67
191k
    if (enable_counters) {
68
191k
        PyThreadState *tstate = _PyThreadState_GET();
69
191k
        PyInterpreterState *interp = tstate->interp;
70
191k
        jump_counter = initial_jump_backoff_counter(&interp->opt_config);
71
191k
        adaptive_counter = adaptive_counter_warmup();
72
191k
        resume_counter = initial_resume_backoff_counter(&interp->opt_config);
73
191k
    }
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
191k
    int opcode = 0;
80
191k
    int oparg = 0;
81
    /* The last code unit cannot have a cache, so we don't need to check it */
82
7.96M
    for (Py_ssize_t i = 0; i < size-1; i++) {
83
7.77M
        opcode = instructions[i].op.code;
84
7.77M
        int caches = _PyOpcode_Caches[opcode];
85
7.77M
        oparg = (oparg << 8) | instructions[i].op.arg;
86
7.77M
        if (opcode == GET_ITER) {
87
30.9k
            fixup_getiter(&instructions[i], flags);
88
30.9k
        }
89
7.77M
        if (caches) {
90
            // The initial value depends on the opcode
91
2.48M
            switch (opcode) {
92
68.0k
                case JUMP_BACKWARD:
93
68.0k
                    instructions[i + 1].counter = jump_counter;
94
68.0k
                    break;
95
220k
                case RESUME:
96
220k
                    instructions[i + 1].counter = resume_counter;
97
220k
                    break;
98
133k
                case POP_JUMP_IF_FALSE:
99
208k
                case POP_JUMP_IF_TRUE:
100
218k
                case POP_JUMP_IF_NONE:
101
230k
                case POP_JUMP_IF_NOT_NONE:
102
230k
                    instructions[i + 1].cache = 0x5555;  // Alternating 0, 1 bits
103
230k
                    break;
104
1.97M
                default:
105
1.97M
                    instructions[i + 1].counter = adaptive_counter;
106
1.97M
                    break;
107
2.48M
            }
108
2.48M
            i += caches;
109
2.48M
        }
110
7.77M
        if (opcode != EXTENDED_ARG) {
111
7.72M
            oparg = 0;
112
7.72M
        }
113
7.77M
    }
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
191k
}
123
124
509k
#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.44k
#define SPEC_FAIL_CODE_COMPLEX_PARAMETERS 7
136
52.1k
#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.54k
#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.71M
{
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.71M
    instr->op.code = opcode;
341
6.71M
    return 1;
342
6.71M
#endif
343
6.71M
}
344
345
static inline void
346
set_counter(_Py_BackoffCounter *counter, _Py_BackoffCounter value)
347
7.95M
{
348
7.95M
    FT_ATOMIC_STORE_UINT16_RELAXED(counter->value_and_backoff,
349
7.95M
                                   value.value_and_backoff);
350
7.95M
}
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
4.06M
{
364
4.06M
    assert(!PyErr_Occurred());
365
4.06M
    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
4.06M
    STAT_INC(_PyOpcode_Deopt[specialized_opcode], success);
372
4.06M
    set_counter((_Py_BackoffCounter *)instr + 1, adaptive_counter_cooldown());
373
4.06M
}
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.33k
{
413
6.33k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
414
6.33k
    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.33k
    PyObject *value;
419
6.33k
    Py_ssize_t index = _PyDict_LookupIndexAndValue(dict, name, &value);
420
6.33k
    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.33k
    assert(index != DKIX_ERROR);
425
6.33k
    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.33k
{
451
6.33k
    PyModuleObject *m = (PyModuleObject *)owner;
452
6.33k
    assert((Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0);
453
6.33k
    PyDictObject *dict = (PyDictObject *)m->md_dict;
454
6.33k
    if (dict == NULL) {
455
0
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_NO_DICT);
456
0
        return -1;
457
0
    }
458
6.33k
    int result;
459
6.33k
    Py_BEGIN_CRITICAL_SECTION(dict);
460
6.33k
    result = specialize_module_load_attr_lock_held(dict, instr, name);
461
6.33k
    Py_END_CRITICAL_SECTION();
462
6.33k
    return result;
463
6.33k
}
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.73M
{
510
2.73M
    if (descriptor == NULL) {
511
1.62M
        return ABSENT;
512
1.62M
    }
513
1.11M
    PyTypeObject *desc_cls = Py_TYPE(descriptor);
514
1.11M
    if (!(desc_cls->tp_flags & Py_TPFLAGS_IMMUTABLETYPE)) {
515
588
        return MUTABLE;
516
588
    }
517
1.11M
    if (desc_cls->tp_descr_set) {
518
224k
        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
345
            return OTHER_SLOT;
525
13.4k
        }
526
211k
        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
206k
            return has_getattr ? GETSET_OVERRIDDEN : PROPERTY;
531
206k
        }
532
4.61k
        return OVERRIDING;
533
211k
    }
534
890k
    if (desc_cls->tp_descr_get) {
535
361k
        if (desc_cls->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR) {
536
354k
            return METHOD;
537
354k
        }
538
7.23k
        if (Py_IS_TYPE(descriptor, &PyClassMethodDescr_Type)) {
539
2.71k
            return BUILTIN_CLASSMETHOD;
540
2.71k
        }
541
4.52k
        if (Py_IS_TYPE(descriptor, &PyClassMethod_Type)) {
542
3.51k
            return PYTHON_CLASSMETHOD;
543
3.51k
        }
544
1.01k
        return NON_OVERRIDING;
545
4.52k
    }
546
528k
    return NON_DESCRIPTOR;
547
890k
}
548
549
static bool
550
descriptor_is_class(PyObject *descriptor, PyObject *name)
551
2.77M
{
552
2.77M
    return ((PyUnicode_CompareWithASCIIString(name, "__class__") == 0) &&
553
56.2k
            (descriptor == _PyType_Lookup(&PyBaseObject_Type, name)));
554
2.77M
}
555
556
static DescriptorClassification
557
2.57M
analyze_descriptor_load(PyTypeObject *type, PyObject *name, PyObject **descr, unsigned int *tp_version) {
558
2.57M
    bool has_getattr = false;
559
2.57M
    bool have_ga_version = false;
560
2.57M
    unsigned int ga_version;
561
2.57M
    getattrofunc getattro_slot = type->tp_getattro;
562
2.57M
    if (getattro_slot == PyObject_GenericGetAttr) {
563
        /* Normal attribute lookup; */
564
2.52M
        has_getattr = false;
565
2.52M
    }
566
56.7k
    else if (getattro_slot == _Py_slot_tp_getattr_hook ||
567
55.0k
        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
55.0k
        PyObject *getattribute = _PyType_LookupRefAndVersion(type,
571
55.0k
                &_Py_ID(__getattribute__), &ga_version);
572
55.0k
        have_ga_version = true;
573
55.0k
        PyInterpreterState *interp = _PyInterpreterState_GET();
574
55.0k
        bool has_custom_getattribute = getattribute != NULL &&
575
55.0k
            getattribute != interp->callable_cache.object__getattribute__;
576
55.0k
        PyObject *getattr = _PyType_Lookup(type, &_Py_ID(__getattr__));
577
55.0k
        has_getattr = getattr != NULL;
578
55.0k
        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
55.0k
        Py_XDECREF(getattribute);
600
55.0k
    }
601
1.71k
    else {
602
1.71k
        *descr = NULL;
603
1.71k
        *tp_version = FT_ATOMIC_LOAD_UINT_RELAXED(type->tp_version_tag);
604
1.71k
        return GETSET_OVERRIDDEN;
605
1.71k
    }
606
2.57M
    unsigned int descr_version;
607
2.57M
    PyObject *descriptor = _PyType_LookupRefAndVersion(type, name, &descr_version);
608
2.57M
    *descr = descriptor;
609
2.57M
    *tp_version = have_ga_version ? ga_version : descr_version;
610
2.57M
    if (descriptor_is_class(descriptor, name)) {
611
56.2k
        return DUNDER_CLASS;
612
56.2k
    }
613
2.52M
    return classify_descriptor(descriptor, has_getattr);
614
2.57M
}
615
616
static DescriptorClassification
617
analyze_descriptor_store(PyTypeObject *type, PyObject *name, PyObject **descr, unsigned int *tp_version)
618
202k
{
619
202k
    if (type->tp_setattro != PyObject_GenericSetAttr) {
620
1.00k
        *descr = NULL;
621
1.00k
        return GETSET_OVERRIDDEN;
622
1.00k
    }
623
201k
    PyObject *descriptor = _PyType_LookupRefAndVersion(type, name, tp_version);
624
201k
    *descr = descriptor;
625
201k
    if (descriptor_is_class(descriptor, name)) {
626
1
        return DUNDER_CLASS;
627
1
    }
628
201k
    return classify_descriptor(descriptor, false);
629
201k
}
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
825k
{
637
825k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
638
825k
    PyDictKeysObject *keys = ((PyHeapTypeObject *)type)->ht_cached_keys;
639
825k
    assert(PyUnicode_CheckExact(name));
640
825k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(owner);
641
825k
    Py_ssize_t index = _PyDictKeys_StringLookupSplit(keys, name);
642
825k
    assert (index != DKIX_ERROR);
643
825k
    if (index == DKIX_EMPTY) {
644
232
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_NOT_IN_KEYS);
645
232
        return 0;
646
232
    }
647
825k
    assert(index >= 0);
648
825k
    assert(_PyObject_InlineValues(owner)->valid);
649
825k
    char *value_addr = (char *)&_PyObject_InlineValues(owner)->values[index];
650
825k
    Py_ssize_t offset = value_addr - (char *)owner;
651
825k
    if (offset != (uint16_t)offset) {
652
0
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_OUT_OF_RANGE);
653
0
        return 0;
654
0
    }
655
825k
    cache->index = (uint16_t)offset;
656
825k
    write_u32(cache->version, tp_version);
657
825k
    specialize(instr, values_op);
658
825k
    return 1;
659
825k
}
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
14.3k
{
667
14.3k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
668
669
14.3k
    _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
14.3k
    if (_PyDict_HasSplitTable(dict)) {
676
502
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_SPLIT_DICT);
677
502
        return 0;
678
502
    }
679
13.8k
    Py_ssize_t index = _PyDict_LookupIndex(dict, name);
680
13.8k
    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
10.7k
    cache->index = (uint16_t)index;
688
10.7k
    write_u32(cache->version, tp_version);
689
10.7k
    specialize(instr, hint_op);
690
10.7k
    return 1;
691
13.8k
}
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
844k
{
700
844k
    assert(kind == NON_OVERRIDING || kind == NON_DESCRIPTOR || kind == ABSENT ||
701
844k
        kind == BUILTIN_CLASSMETHOD || kind == PYTHON_CLASSMETHOD ||
702
844k
        kind == METHOD);
703
    // No descriptor, or non overriding.
704
844k
    if ((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {
705
2.36k
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);
706
2.36k
        return 0;
707
2.36k
    }
708
841k
    if (type->tp_flags & Py_TPFLAGS_INLINE_VALUES &&
709
841k
        FT_ATOMIC_LOAD_UINT8(_PyObject_InlineValues(owner)->valid) &&
710
827k
        !(base_op == STORE_ATTR && _PyObject_GetManagedDict(owner) != NULL))
711
827k
    {
712
827k
        int res;
713
827k
        Py_BEGIN_CRITICAL_SECTION(owner);
714
827k
        PyDictObject *dict = _PyObject_GetManagedDict(owner);
715
827k
        if (dict == NULL) {
716
            // managed dict, not materialized, inline values valid
717
825k
            res = specialize_dict_access_inline(owner, instr, type, name,
718
825k
                                                tp_version, base_op, values_op);
719
825k
        }
720
1.43k
        else {
721
            // lost race and dict was created, fail specialization
722
1.43k
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OTHER);
723
1.43k
            res = 0;
724
1.43k
        }
725
827k
        Py_END_CRITICAL_SECTION();
726
827k
        return res;
727
827k
    }
728
14.6k
    else {
729
14.6k
        PyDictObject *dict = _PyObject_GetManagedDict(owner);
730
14.6k
        if (dict == NULL || !PyDict_CheckExact(dict)) {
731
235
            SPECIALIZATION_FAIL(base_op, SPEC_FAIL_NO_DICT);
732
235
            return 0;
733
235
        }
734
14.3k
        int res;
735
14.3k
        Py_BEGIN_CRITICAL_SECTION(dict);
736
        // materialized managed dict
737
14.3k
        res = specialize_dict_access_hint(dict, instr, type, name,
738
14.3k
                                          tp_version, base_op, hint_op);
739
14.3k
        Py_END_CRITICAL_SECTION();
740
14.3k
        return res;
741
14.6k
    }
742
841k
}
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.56M
{
760
2.56M
    PyTypeObject *cls = Py_TYPE(obj);
761
2.56M
    if ((cls->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {
762
773k
        return false;
763
773k
    }
764
1.79M
    if (cls->tp_flags & Py_TPFLAGS_INLINE_VALUES) {
765
1.74M
        PyDictKeysObject *keys = ((PyHeapTypeObject *)cls)->ht_cached_keys;
766
1.74M
        Py_ssize_t index =
767
1.74M
            _PyDictKeys_StringLookupAndVersion(keys, name, shared_keys_version);
768
1.74M
        return index >= 0;
769
1.74M
    }
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
49.0k
    Py_BEGIN_CRITICAL_SECTION(dict);
776
49.0k
    if (dict->ma_values) {
777
49.0k
        result = false;
778
49.0k
    }
779
0
    else {
780
0
        result = (_PyDict_LookupIndex(dict, name) >= 0);
781
0
    }
782
49.0k
    Py_END_CRITICAL_SECTION();
783
49.0k
    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.56M
{
791
2.56M
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
792
2.56M
    PyTypeObject *type = Py_TYPE(owner);
793
2.56M
    if (tp_version == 0) {
794
773
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
795
773
        return -1;
796
773
    }
797
2.56M
    uint8_t oparg = FT_ATOMIC_LOAD_UINT8_RELAXED(instr->op.arg);
798
2.56M
    switch(kind) {
799
1.14k
        case OVERRIDING:
800
1.14k
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
801
1.14k
            return -1;
802
352k
        case METHOD:
803
352k
        {
804
352k
            if (shadow) {
805
85
                goto try_instance;
806
85
            }
807
352k
            if (oparg & 1) {
808
342k
                if (specialize_attr_loadclassattr(owner, instr, name, descr,
809
342k
                                                  tp_version, kind, true,
810
342k
                                                  shared_keys_version)) {
811
338k
                    return 0;
812
338k
                }
813
4.33k
                else {
814
4.33k
                    return -1;
815
4.33k
                }
816
342k
            }
817
9.74k
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
818
9.74k
            return -1;
819
352k
        }
820
206k
        case PROPERTY:
821
206k
        {
822
206k
            _PyLoadMethodCache *lm_cache = (_PyLoadMethodCache *)(instr + 1);
823
206k
            assert(Py_TYPE(descr) == &PyProperty_Type);
824
206k
            PyObject *fget = ((_PyPropertyObject *)descr)->prop_get;
825
206k
            if (fget == NULL) {
826
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
827
0
                return -1;
828
0
            }
829
206k
            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
206k
            if (!function_check_args(fget, 1, LOAD_ATTR)) {
834
0
                return -1;
835
0
            }
836
206k
            if (oparg & 1) {
837
16
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
838
16
                return -1;
839
16
            }
840
            /* Don't specialize if PEP 523 is active */
841
206k
            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
206k
            uint32_t func_version = function_get_version(fget, LOAD_ATTR);
852
206k
            if (func_version == 0) {
853
0
                return -1;
854
0
            }
855
206k
            assert(tp_version != 0);
856
206k
            write_u32(lm_cache->type_version, tp_version);
857
206k
            write_u32(lm_cache->keys_version, func_version);
858
            /* borrowed */
859
206k
            write_ptr(lm_cache->descr, fget);
860
206k
            specialize(instr, LOAD_ATTR_PROPERTY);
861
206k
            return 0;
862
206k
        }
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
56.2k
        case DUNDER_CLASS:
892
56.2k
        {
893
56.2k
            Py_ssize_t offset = offsetof(PyObject, ob_type);
894
56.2k
            assert(offset == (uint16_t)offset);
895
56.2k
            cache->index = (uint16_t)offset;
896
56.2k
            write_u32(cache->version, tp_version);
897
56.2k
            specialize(instr, LOAD_ATTR_SLOT);
898
56.2k
            return 0;
899
12.1k
        }
900
345
        case OTHER_SLOT:
901
345
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT);
902
345
            return -1;
903
357
        case MUTABLE:
904
357
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
905
357
            return -1;
906
1.45k
        case GETSET_OVERRIDDEN:
907
1.45k
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OVERRIDDEN);
908
1.45k
            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
232
        case PYTHON_CLASSMETHOD:
944
404
        case NON_OVERRIDING:
945
404
            if (shadow) {
946
0
                goto try_instance;
947
0
            }
948
404
            return -1;
949
524k
        case NON_DESCRIPTOR:
950
524k
            if (shadow) {
951
466k
                goto try_instance;
952
466k
            }
953
57.3k
            if ((oparg & 1) == 0) {
954
57.3k
                if (specialize_attr_loadclassattr(owner, instr, name, descr,
955
57.3k
                                                  tp_version, kind, false,
956
57.3k
                                                  shared_keys_version)) {
957
56.8k
                    return 0;
958
56.8k
                }
959
57.3k
            }
960
484
            return -1;
961
1.41M
        case ABSENT:
962
1.41M
            if (shadow) {
963
178k
                goto try_instance;
964
178k
            }
965
1.23M
            set_counter((_Py_BackoffCounter*)instr + 1, adaptive_counter_cooldown());
966
1.23M
            return 0;
967
2.56M
    }
968
2.56M
    Py_UNREACHABLE();
969
645k
try_instance:
970
645k
    if (specialize_dict_access(owner, instr, type, kind, name, tp_version,
971
645k
                               LOAD_ATTR, LOAD_ATTR_INSTANCE_VALUE, LOAD_ATTR_WITH_HINT))
972
641k
    {
973
641k
        return 0;
974
641k
    }
975
3.88k
    return -1;
976
645k
}
977
978
static int
979
specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name)
980
2.56M
{
981
    // 0 is not a valid version
982
2.56M
    uint32_t shared_keys_version = 0;
983
2.56M
    bool shadow = instance_has_key(owner, name, &shared_keys_version);
984
2.56M
    PyObject *descr = NULL;
985
2.56M
    unsigned int tp_version = 0;
986
2.56M
    PyTypeObject *type = Py_TYPE(owner);
987
2.56M
    DescriptorClassification kind = analyze_descriptor_load(type, name, &descr, &tp_version);
988
2.56M
    int result = do_specialize_instance_load_attr(owner, instr, name, shadow, shared_keys_version, kind, descr, tp_version);
989
2.56M
    Py_XDECREF(descr);
990
2.56M
    return result;
991
2.56M
}
992
993
Py_NO_INLINE void
994
_Py_Specialize_LoadAttr(_PyStackRef owner_st, _Py_CODEUNIT *instr, PyObject *name)
995
2.58M
{
996
2.58M
    PyObject *owner = PyStackRef_AsPyObjectBorrow(owner_st);
997
998
2.58M
    assert(ENABLE_SPECIALIZATION);
999
2.58M
    assert(_PyOpcode_Caches[LOAD_ATTR] == INLINE_CACHE_ENTRIES_LOAD_ATTR);
1000
2.58M
    PyTypeObject *type = Py_TYPE(owner);
1001
2.58M
    bool fail;
1002
2.58M
    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.58M
    else if (Py_TYPE(owner)->tp_getattro == PyModule_Type.tp_getattro) {
1010
6.33k
        fail = specialize_module_load_attr(owner, instr, name);
1011
6.33k
    }
1012
2.58M
    else if (PyType_Check(owner)) {
1013
14.2k
        fail = specialize_class_load_attr(owner, instr, name);
1014
14.2k
    }
1015
2.56M
    else {
1016
2.56M
        fail = specialize_instance_load_attr(owner, instr, name);
1017
2.56M
    }
1018
1019
2.58M
    if (fail) {
1020
33.0k
        unspecialize(instr);
1021
33.0k
    }
1022
2.58M
}
1023
1024
Py_NO_INLINE void
1025
_Py_Specialize_StoreAttr(_PyStackRef owner_st, _Py_CODEUNIT *instr, PyObject *name)
1026
203k
{
1027
203k
    PyObject *owner = PyStackRef_AsPyObjectBorrow(owner_st);
1028
1029
203k
    assert(ENABLE_SPECIALIZATION);
1030
203k
    assert(_PyOpcode_Caches[STORE_ATTR] == INLINE_CACHE_ENTRIES_STORE_ATTR);
1031
203k
    PyObject *descr = NULL;
1032
203k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
1033
203k
    PyTypeObject *type = Py_TYPE(owner);
1034
203k
    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
203k
    if (PyModule_CheckExact(owner)) {
1042
572
        SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OVERRIDDEN);
1043
572
        goto fail;
1044
572
    }
1045
202k
    unsigned int tp_version = 0;
1046
202k
    DescriptorClassification kind = analyze_descriptor_store(type, name, &descr, &tp_version);
1047
202k
    if (tp_version == 0) {
1048
1.04k
        goto fail;
1049
1.04k
    }
1050
202k
    assert(descr != NULL || kind == ABSENT || kind == GETSET_OVERRIDDEN);
1051
201k
    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
905
        case OBJECT_SLOT:
1062
905
        {
1063
905
            PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
1064
905
            struct PyMemberDef *dmem = member->d_member;
1065
905
            Py_ssize_t offset = dmem->offset;
1066
905
            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
905
            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
905
            if (dmem->flags & Py_READONLY) {
1075
0
                SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_READ_ONLY);
1076
0
                goto fail;
1077
0
            }
1078
905
            if (offset != (uint16_t)offset) {
1079
0
                SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OUT_OF_RANGE);
1080
0
                goto fail;
1081
0
            }
1082
905
            assert(dmem->type == Py_T_OBJECT_EX || dmem->type == _Py_T_OBJECT);
1083
905
            assert(offset > 0);
1084
905
            cache->index = (uint16_t)offset;
1085
905
            write_u32(cache->version, tp_version);
1086
905
            specialize(instr, STORE_ATTR_SLOT);
1087
905
            goto success;
1088
905
        }
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
0
        case MUTABLE:
1094
0
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
1095
0
            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
887
        case NON_DESCRIPTOR:
1110
887
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE);
1111
887
            goto fail;
1112
198k
        case ABSENT:
1113
198k
            if (specialize_dict_access(owner, instr, type, kind, name, tp_version,
1114
198k
                                       STORE_ATTR, STORE_ATTR_INSTANCE_VALUE,
1115
198k
                                       STORE_ATTR_WITH_HINT)) {
1116
194k
                goto success;
1117
194k
            }
1118
201k
    }
1119
7.49k
fail:
1120
7.49k
    Py_XDECREF(descr);
1121
7.49k
    unspecialize(instr);
1122
7.49k
    return;
1123
195k
success:
1124
195k
    Py_XDECREF(descr);
1125
195k
    return;
1126
201k
}
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
14.2k
{
1169
14.2k
    assert(PyType_Check(owner));
1170
14.2k
    PyTypeObject *cls = (PyTypeObject *)owner;
1171
14.2k
    _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1);
1172
14.2k
    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
14.2k
    unsigned int meta_version = 0;
1177
14.2k
    PyObject *metadescriptor = _PyType_LookupRefAndVersion(Py_TYPE(cls), name, &meta_version);
1178
14.2k
    DescriptorClassification metakind = classify_descriptor(metadescriptor, false);
1179
14.2k
    Py_XDECREF(metadescriptor);
1180
14.2k
    switch (metakind) {
1181
646
        case METHOD:
1182
923
        case NON_DESCRIPTOR:
1183
1.11k
        case NON_OVERRIDING:
1184
1.11k
        case BUILTIN_CLASSMETHOD:
1185
1.11k
        case PYTHON_CLASSMETHOD:
1186
11.6k
        case ABSENT:
1187
11.6k
            break;
1188
2.64k
        default:
1189
2.64k
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METACLASS_ATTRIBUTE);
1190
2.64k
            return -1;
1191
14.2k
    }
1192
11.6k
    PyObject *descr = NULL;
1193
11.6k
    DescriptorClassification kind = 0;
1194
11.6k
    unsigned int tp_version = 0;
1195
11.6k
    kind = analyze_descriptor_load(cls, name, &descr, &tp_version);
1196
11.6k
    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
11.6k
    bool metaclass_check = false;
1202
11.5k
    if ((Py_TYPE(cls)->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) {
1203
1.78k
        metaclass_check = true;
1204
1.78k
        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.78k
    }
1210
11.5k
    switch (kind) {
1211
231
        case MUTABLE:
1212
            // special case for enums which has Py_TYPE(descr) == cls
1213
            // so guarding on type version is sufficient
1214
231
            if (Py_TYPE(descr) != cls) {
1215
26
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
1216
26
                Py_XDECREF(descr);
1217
26
                return -1;
1218
26
            }
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
864
        case METHOD:
1226
4.43k
        case NON_DESCRIPTOR:
1227
#ifdef Py_GIL_DISABLED
1228
            maybe_enable_deferred_ref_count(descr);
1229
#endif
1230
4.43k
            write_ptr(cache->descr, descr);
1231
4.43k
            if (metaclass_check) {
1232
1.37k
                write_u32(cache->keys_version, tp_version);
1233
1.37k
                write_u32(cache->type_version, meta_version);
1234
1.37k
                specialize(instr, LOAD_ATTR_CLASS_WITH_METACLASS_CHECK);
1235
1.37k
            }
1236
3.05k
            else {
1237
3.05k
                write_u32(cache->type_version, tp_version);
1238
3.05k
                specialize(instr, LOAD_ATTR_CLASS);
1239
3.05k
            }
1240
4.43k
            Py_XDECREF(descr);
1241
4.43k
            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
7.05k
        default:
1249
7.05k
            SPECIALIZATION_FAIL(LOAD_ATTR, load_attr_fail_kind(kind));
1250
7.05k
            Py_XDECREF(descr);
1251
7.05k
            return -1;
1252
11.5k
    }
1253
11.5k
}
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
400k
{
1265
400k
    _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1);
1266
400k
    PyTypeObject *owner_cls = Py_TYPE(owner);
1267
1268
400k
    assert(descr != NULL);
1269
400k
    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
400k
    unsigned long tp_flags = PyType_GetFlags(owner_cls);
1279
400k
    if (tp_flags & Py_TPFLAGS_INLINE_VALUES) {
1280
372k
        #ifndef Py_GIL_DISABLED
1281
372k
        assert(_PyDictKeys_StringLookup(
1282
372k
                   ((PyHeapTypeObject *)owner_cls)->ht_cached_keys, name) < 0);
1283
372k
        #endif
1284
372k
        if (shared_keys_version == 0) {
1285
0
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
1286
0
            return 0;
1287
0
        }
1288
372k
        specialize(instr, is_method ? LOAD_ATTR_METHOD_WITH_VALUES : LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES);
1289
372k
    }
1290
27.2k
    else {
1291
27.2k
        Py_ssize_t dictoffset;
1292
27.2k
        if (tp_flags & Py_TPFLAGS_MANAGED_DICT) {
1293
425
            dictoffset = MANAGED_DICT_OFFSET;
1294
425
        }
1295
26.8k
        else {
1296
26.8k
            dictoffset = owner_cls->tp_dictoffset;
1297
26.8k
            if (dictoffset < 0 || dictoffset > INT16_MAX + MANAGED_DICT_OFFSET) {
1298
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE);
1299
0
                return 0;
1300
0
            }
1301
26.8k
        }
1302
27.2k
        if (dictoffset == 0) {
1303
22.2k
            specialize(instr, is_method ? LOAD_ATTR_METHOD_NO_DICT : LOAD_ATTR_NONDESCRIPTOR_NO_DICT);
1304
22.2k
        }
1305
5.02k
        else if (is_method) {
1306
4.56k
            PyObject **addr = (PyObject **)((char *)owner + dictoffset);
1307
4.56k
            PyObject *dict = FT_ATOMIC_LOAD_PTR_ACQUIRE(*addr);
1308
4.56k
            if (dict) {
1309
4.33k
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);
1310
4.33k
                return 0;
1311
4.33k
            }
1312
            /* Cache entries must be unsigned values, so we offset the
1313
             * dictoffset by MANAGED_DICT_OFFSET.
1314
             * We do the reverse offset in LOAD_ATTR_METHOD_LAZY_DICT */
1315
230
            dictoffset -= MANAGED_DICT_OFFSET;
1316
230
            assert(((uint16_t)dictoffset) == dictoffset);
1317
230
            cache->dict_offset = (uint16_t)dictoffset;
1318
230
            specialize(instr, LOAD_ATTR_METHOD_LAZY_DICT);
1319
230
        }
1320
461
        else {
1321
461
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE);
1322
461
            return 0;
1323
461
        }
1324
27.2k
    }
1325
    /* `descr` is borrowed. This is safe for methods (even inherited ones from
1326
    *  super classes!) as long as tp_version_tag is validated for two main reasons:
1327
    *
1328
    *  1. The class will always hold a reference to the method so it will
1329
    *  usually not be GC-ed. Should it be deleted in Python, e.g.
1330
    *  `del obj.meth`, tp_version_tag will be invalidated, because of reason 2.
1331
    *
1332
    *  2. The pre-existing type method cache (MCACHE) uses the same principles
1333
    *  of caching a borrowed descriptor. The MCACHE infrastructure does all the
1334
    *  heavy lifting for us. E.g. it invalidates tp_version_tag on any MRO
1335
    *  modification, on any type object change along said MRO, etc. (see
1336
    *  PyType_Modified usages in typeobject.c). The MCACHE has been
1337
    *  working since Python 2.6 and it's battle-tested.
1338
    */
1339
395k
    write_u32(cache->type_version, tp_version);
1340
395k
    write_ptr(cache->descr, descr);
1341
395k
    return 1;
1342
400k
}
1343
1344
static void
1345
specialize_load_global_lock_held(
1346
    PyObject *globals, PyObject *builtins,
1347
    _Py_CODEUNIT *instr, PyObject *name)
1348
36.7k
{
1349
36.7k
    assert(ENABLE_SPECIALIZATION);
1350
36.7k
    assert(_PyOpcode_Caches[LOAD_GLOBAL] == INLINE_CACHE_ENTRIES_LOAD_GLOBAL);
1351
    /* Use inline cache */
1352
36.7k
    _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)(instr + 1);
1353
36.7k
    assert(PyUnicode_CheckExact(name));
1354
36.7k
    if (!PyDict_CheckExact(globals)) {
1355
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_DICT);
1356
0
        goto fail;
1357
0
    }
1358
36.7k
    PyDictKeysObject * globals_keys = ((PyDictObject *)globals)->ma_keys;
1359
36.7k
    if (globals_keys->dk_kind != DICT_KEYS_UNICODE) {
1360
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT);
1361
0
        goto fail;
1362
0
    }
1363
36.7k
    PyObject *value;
1364
36.7k
    Py_ssize_t index = _PyDict_LookupIndexAndValue((PyDictObject *)globals, name, &value);
1365
36.7k
    if (index == DKIX_ERROR) {
1366
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_EXPECTED_ERROR);
1367
0
        goto fail;
1368
0
    }
1369
36.7k
    if (value != NULL && PyLazyImport_CheckExact(value)) {
1370
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_ATTR_MODULE_LAZY_VALUE);
1371
0
        goto fail;
1372
0
    }
1373
36.7k
    PyInterpreterState *interp = _PyInterpreterState_GET();
1374
36.7k
    if (index != DKIX_EMPTY) {
1375
21.6k
        if (index != (uint16_t)index) {
1376
0
            SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1377
0
            goto fail;
1378
0
        }
1379
21.6k
        uint32_t keys_version = _PyDict_GetKeysVersionForCurrentState(
1380
21.6k
                interp, (PyDictObject*) globals);
1381
21.6k
        if (keys_version == 0) {
1382
0
            SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
1383
0
            goto fail;
1384
0
        }
1385
21.6k
        if (keys_version != (uint16_t)keys_version) {
1386
0
            SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1387
0
            goto fail;
1388
0
        }
1389
#ifdef Py_GIL_DISABLED
1390
        maybe_enable_deferred_ref_count(value);
1391
#endif
1392
21.6k
        cache->index = (uint16_t)index;
1393
21.6k
        cache->module_keys_version = (uint16_t)keys_version;
1394
21.6k
        specialize(instr, LOAD_GLOBAL_MODULE);
1395
21.6k
        return;
1396
21.6k
    }
1397
15.1k
    if (!PyDict_CheckExact(builtins)) {
1398
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_DICT);
1399
0
        goto fail;
1400
0
    }
1401
15.1k
    PyDictKeysObject * builtin_keys = ((PyDictObject *)builtins)->ma_keys;
1402
15.1k
    if (builtin_keys->dk_kind != DICT_KEYS_UNICODE) {
1403
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT);
1404
0
        goto fail;
1405
0
    }
1406
15.1k
    index = _PyDictKeys_StringLookup(builtin_keys, name);
1407
15.1k
    if (index == DKIX_ERROR) {
1408
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_EXPECTED_ERROR);
1409
0
        goto fail;
1410
0
    }
1411
15.1k
    if (index != (uint16_t)index) {
1412
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1413
0
        goto fail;
1414
0
    }
1415
15.1k
    uint32_t globals_version = _PyDict_GetKeysVersionForCurrentState(
1416
15.1k
            interp, (PyDictObject*) globals);
1417
15.1k
    if (globals_version == 0) {
1418
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
1419
0
        goto fail;
1420
0
    }
1421
15.1k
    if (globals_version != (uint16_t)globals_version) {
1422
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1423
0
        goto fail;
1424
0
    }
1425
15.1k
    uint32_t builtins_version = _PyDict_GetKeysVersionForCurrentState(
1426
15.1k
            interp, (PyDictObject*) builtins);
1427
15.1k
    if (builtins_version == 0) {
1428
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
1429
0
        goto fail;
1430
0
    }
1431
15.1k
    if (builtins_version > UINT16_MAX) {
1432
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1433
0
        goto fail;
1434
0
    }
1435
15.1k
    cache->index = (uint16_t)index;
1436
15.1k
    cache->module_keys_version = (uint16_t)globals_version;
1437
15.1k
    cache->builtin_keys_version = (uint16_t)builtins_version;
1438
15.1k
    specialize(instr, LOAD_GLOBAL_BUILTIN);
1439
15.1k
    return;
1440
0
fail:
1441
0
    unspecialize(instr);
1442
0
}
1443
1444
Py_NO_INLINE void
1445
_Py_Specialize_LoadGlobal(
1446
    PyObject *globals, PyObject *builtins,
1447
    _Py_CODEUNIT *instr, PyObject *name)
1448
36.7k
{
1449
36.7k
    Py_BEGIN_CRITICAL_SECTION2(globals, builtins);
1450
36.7k
    specialize_load_global_lock_held(globals, builtins, instr, name);
1451
36.7k
    Py_END_CRITICAL_SECTION2();
1452
36.7k
}
1453
1454
static int
1455
259k
function_kind(PyCodeObject *code) {
1456
259k
    int flags = code->co_flags;
1457
259k
    if ((flags & (CO_VARKEYWORDS | CO_VARARGS)) || code->co_kwonlyargcount) {
1458
5.44k
        return SPEC_FAIL_CODE_COMPLEX_PARAMETERS;
1459
5.44k
    }
1460
254k
    if ((flags & CO_OPTIMIZED) == 0) {
1461
0
        return SPEC_FAIL_CODE_NOT_OPTIMIZED;
1462
0
    }
1463
254k
    return SIMPLE_FUNCTION;
1464
254k
}
1465
1466
/* Returning false indicates a failure. */
1467
static bool
1468
function_check_args(PyObject *o, int expected_argcount, int opcode)
1469
206k
{
1470
206k
    assert(Py_IS_TYPE(o, &PyFunction_Type));
1471
206k
    PyFunctionObject *func = (PyFunctionObject *)o;
1472
206k
    PyCodeObject *fcode = (PyCodeObject *)func->func_code;
1473
206k
    int kind = function_kind(fcode);
1474
206k
    if (kind != SIMPLE_FUNCTION) {
1475
0
        SPECIALIZATION_FAIL(opcode, kind);
1476
0
        return false;
1477
0
    }
1478
206k
    if (fcode->co_argcount != expected_argcount) {
1479
0
        SPECIALIZATION_FAIL(opcode, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1480
0
        return false;
1481
0
    }
1482
206k
    return true;
1483
206k
}
1484
1485
/* Returning 0 indicates a failure. */
1486
static uint32_t
1487
function_get_version(PyObject *o, int opcode)
1488
206k
{
1489
206k
    assert(Py_IS_TYPE(o, &PyFunction_Type));
1490
206k
    PyFunctionObject *func = (PyFunctionObject *)o;
1491
206k
    uint32_t version = _PyFunction_GetVersionForCurrentState(func);
1492
206k
    if (!_PyFunction_IsVersionValid(version)) {
1493
0
        SPECIALIZATION_FAIL(opcode, SPEC_FAIL_OUT_OF_VERSIONS);
1494
0
        return 0;
1495
0
    }
1496
206k
    return version;
1497
206k
}
1498
1499
#ifdef Py_STATS
1500
static int
1501
store_subscr_fail_kind(PyObject *container, PyObject *sub)
1502
{
1503
    PyTypeObject *container_type = Py_TYPE(container);
1504
    PyMappingMethods *as_mapping = container_type->tp_as_mapping;
1505
    if (as_mapping && (as_mapping->mp_ass_subscript
1506
                       == PyDict_Type.tp_as_mapping->mp_ass_subscript)) {
1507
        return SPEC_FAIL_SUBSCR_DICT_SUBCLASS_NO_OVERRIDE;
1508
    }
1509
    if (PyObject_CheckBuffer(container)) {
1510
        if (PyLong_CheckExact(sub) && (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub))) {
1511
            return SPEC_FAIL_OUT_OF_RANGE;
1512
        }
1513
        else if (strcmp(container_type->tp_name, "array.array") == 0) {
1514
            if (PyLong_CheckExact(sub)) {
1515
                return SPEC_FAIL_SUBSCR_ARRAY_INT;
1516
            }
1517
            else if (PySlice_Check(sub)) {
1518
                return SPEC_FAIL_SUBSCR_ARRAY_SLICE;
1519
            }
1520
            else {
1521
                return SPEC_FAIL_OTHER;
1522
            }
1523
        }
1524
        else if (PyByteArray_CheckExact(container)) {
1525
            if (PyLong_CheckExact(sub)) {
1526
                return SPEC_FAIL_SUBSCR_BYTEARRAY_INT;
1527
            }
1528
            else if (PySlice_Check(sub)) {
1529
                return SPEC_FAIL_SUBSCR_BYTEARRAY_SLICE;
1530
            }
1531
            else {
1532
                return SPEC_FAIL_OTHER;
1533
            }
1534
        }
1535
        else {
1536
            if (PyLong_CheckExact(sub)) {
1537
                return SPEC_FAIL_SUBSCR_BUFFER_INT;
1538
            }
1539
            else if (PySlice_Check(sub)) {
1540
                return SPEC_FAIL_SUBSCR_BUFFER_SLICE;
1541
            }
1542
            else {
1543
                return SPEC_FAIL_OTHER;
1544
            }
1545
        }
1546
        return SPEC_FAIL_OTHER;
1547
    }
1548
    PyObject *descriptor = _PyType_Lookup(container_type, &_Py_ID(__setitem__));
1549
    if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {
1550
        PyFunctionObject *func = (PyFunctionObject *)descriptor;
1551
        PyCodeObject *code = (PyCodeObject *)func->func_code;
1552
        int kind = function_kind(code);
1553
        if (kind == SIMPLE_FUNCTION) {
1554
            return SPEC_FAIL_SUBSCR_PY_SIMPLE;
1555
        }
1556
        else {
1557
            return SPEC_FAIL_SUBSCR_PY_OTHER;
1558
        }
1559
    }
1560
    return SPEC_FAIL_OTHER;
1561
}
1562
#endif
1563
1564
Py_NO_INLINE void
1565
_Py_Specialize_StoreSubscr(_PyStackRef container_st, _PyStackRef sub_st, _Py_CODEUNIT *instr)
1566
18.5k
{
1567
18.5k
    PyObject *container = PyStackRef_AsPyObjectBorrow(container_st);
1568
18.5k
    PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st);
1569
1570
18.5k
    assert(ENABLE_SPECIALIZATION);
1571
18.5k
    PyTypeObject *container_type = Py_TYPE(container);
1572
18.5k
    if (container_type == &PyList_Type) {
1573
870
        if (PyLong_CheckExact(sub)) {
1574
851
            if (_PyLong_IsNonNegativeCompact((PyLongObject *)sub)
1575
250
                && ((PyLongObject *)sub)->long_value.ob_digit[0] < (size_t)PyList_GET_SIZE(container))
1576
250
            {
1577
250
                specialize(instr, STORE_SUBSCR_LIST_INT);
1578
250
                return;
1579
250
            }
1580
601
            else {
1581
601
                SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);
1582
601
                unspecialize(instr);
1583
601
                return;
1584
601
            }
1585
851
        }
1586
19
        else if (PySlice_Check(sub)) {
1587
19
            SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_LIST_SLICE);
1588
19
            unspecialize(instr);
1589
19
            return;
1590
19
        }
1591
0
        else {
1592
0
            SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
1593
0
            unspecialize(instr);
1594
0
            return;
1595
0
        }
1596
870
    }
1597
17.6k
    if (container_type->tp_as_mapping != NULL &&
1598
17.6k
        container_type->tp_as_mapping->mp_ass_subscript == _PyDict_StoreSubscript)
1599
1.84k
    {
1600
1.84k
        specialize(instr, STORE_SUBSCR_DICT);
1601
1.84k
        return;
1602
1.84k
    }
1603
15.8k
    SPECIALIZATION_FAIL(STORE_SUBSCR, store_subscr_fail_kind(container, sub));
1604
15.8k
    unspecialize(instr);
1605
15.8k
}
1606
1607
/* Returns a strong reference. */
1608
static PyObject *
1609
get_init_for_simple_managed_python_class(PyTypeObject *tp, unsigned int *tp_version)
1610
853
{
1611
853
    assert(tp->tp_new == PyBaseObject_Type.tp_new);
1612
853
    if (tp->tp_alloc != PyType_GenericAlloc) {
1613
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OVERRIDDEN);
1614
0
        return NULL;
1615
0
    }
1616
853
    unsigned long tp_flags = PyType_GetFlags(tp);
1617
853
    if (!(tp_flags & Py_TPFLAGS_HEAPTYPE)) {
1618
        /* Is this possible? */
1619
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_EXPECTED_ERROR);
1620
0
        return NULL;
1621
0
    }
1622
853
    PyObject *init = _PyType_LookupRefAndVersion(tp, &_Py_ID(__init__), tp_version);
1623
853
    if (init == NULL || !PyFunction_Check(init)) {
1624
196
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_INIT_NOT_PYTHON);
1625
196
        Py_XDECREF(init);
1626
196
        return NULL;
1627
196
    }
1628
657
    int kind = function_kind((PyCodeObject *)PyFunction_GET_CODE(init));
1629
657
    if (kind != SIMPLE_FUNCTION) {
1630
63
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_INIT_NOT_SIMPLE);
1631
63
        Py_DECREF(init);
1632
63
        return NULL;
1633
63
    }
1634
594
    return init;
1635
657
}
1636
1637
static int
1638
specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
1639
3.92k
{
1640
3.92k
    assert(PyType_Check(callable));
1641
3.92k
    PyTypeObject *tp = _PyType_CAST(callable);
1642
3.92k
    if (tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) {
1643
2.61k
        int oparg = instr->op.arg;
1644
2.61k
        if (nargs == 1 && oparg == 1) {
1645
1.74k
            if (tp == &PyUnicode_Type) {
1646
155
                specialize(instr, CALL_STR_1);
1647
155
                return 0;
1648
155
            }
1649
1.59k
            else if (tp == &PyType_Type) {
1650
311
                specialize(instr, CALL_TYPE_1);
1651
311
                return 0;
1652
311
            }
1653
1.28k
            else if (tp == &PyTuple_Type) {
1654
125
                specialize(instr, CALL_TUPLE_1);
1655
125
                return 0;
1656
125
            }
1657
1.74k
        }
1658
2.02k
        if (tp->tp_vectorcall != NULL) {
1659
1.41k
            specialize(instr, CALL_BUILTIN_CLASS);
1660
1.41k
            return 0;
1661
1.41k
        }
1662
610
        goto generic;
1663
2.02k
    }
1664
1.31k
    if (Py_TYPE(tp) != &PyType_Type) {
1665
85
        goto generic;
1666
85
    }
1667
1.23k
    if (tp->tp_new == PyBaseObject_Type.tp_new) {
1668
853
        unsigned int tp_version = 0;
1669
853
        PyObject *init = get_init_for_simple_managed_python_class(tp, &tp_version);
1670
853
        if (!tp_version) {
1671
7
            SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
1672
7
            Py_XDECREF(init);
1673
7
            return -1;
1674
7
        }
1675
846
        if (init != NULL && _PyType_CacheInitForSpecialization(
1676
587
                                (PyHeapTypeObject *)tp, init, tp_version)) {
1677
587
            _PyCallCache *cache = (_PyCallCache *)(instr + 1);
1678
587
            write_u32(cache->func_version, tp_version);
1679
587
            specialize(instr, CALL_ALLOC_AND_ENTER_INIT);
1680
587
            Py_DECREF(init);
1681
587
            return 0;
1682
587
        }
1683
259
        Py_XDECREF(init);
1684
259
    }
1685
1.33k
generic:
1686
1.33k
    specialize(instr, CALL_NON_PY_GENERAL);
1687
1.33k
    return 0;
1688
1.23k
}
1689
1690
static int
1691
specialize_method_descriptor(PyMethodDescrObject *descr, PyObject *self_or_null,
1692
                             _Py_CODEUNIT *instr, int nargs)
1693
472k
{
1694
472k
    switch (descr->d_method->ml_flags &
1695
472k
        (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
1696
472k
        METH_KEYWORDS | METH_METHOD)) {
1697
40.9k
        case METH_NOARGS: {
1698
40.9k
            if (nargs != 1) {
1699
0
                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1700
0
                return -1;
1701
0
            }
1702
40.9k
            specialize(instr, CALL_METHOD_DESCRIPTOR_NOARGS);
1703
40.9k
            return 0;
1704
40.9k
        }
1705
357k
        case METH_O: {
1706
357k
            if (nargs != 2) {
1707
0
                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1708
0
                return -1;
1709
0
            }
1710
357k
            PyInterpreterState *interp = _PyInterpreterState_GET();
1711
357k
            PyObject *list_append = interp->callable_cache.list_append;
1712
357k
            int oparg = instr->op.arg;
1713
357k
            if ((PyObject *)descr == list_append && oparg == 1) {
1714
350k
                assert(self_or_null != NULL);
1715
350k
                if (PyList_CheckExact(self_or_null)) {
1716
1.03k
                    specialize(instr, CALL_LIST_APPEND);
1717
1.03k
                    return 0;
1718
1.03k
                }
1719
350k
            }
1720
356k
            specialize(instr, CALL_METHOD_DESCRIPTOR_O);
1721
356k
            return 0;
1722
357k
        }
1723
3.72k
        case METH_FASTCALL: {
1724
3.72k
            specialize(instr, CALL_METHOD_DESCRIPTOR_FAST);
1725
3.72k
            return 0;
1726
357k
        }
1727
69.8k
        case METH_FASTCALL | METH_KEYWORDS: {
1728
69.8k
            specialize(instr, CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS);
1729
69.8k
            return 0;
1730
357k
        }
1731
472k
    }
1732
451
    specialize(instr, CALL_NON_PY_GENERAL);
1733
451
    return 0;
1734
472k
}
1735
1736
static int
1737
specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
1738
                   bool bound_method)
1739
48.0k
{
1740
48.0k
    _PyCallCache *cache = (_PyCallCache *)(instr + 1);
1741
48.0k
    PyCodeObject *code = (PyCodeObject *)func->func_code;
1742
48.0k
    int kind = function_kind(code);
1743
    /* Don't specialize if PEP 523 is active */
1744
48.0k
    if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) {
1745
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
1746
0
        return -1;
1747
0
    }
1748
48.0k
    if (func->vectorcall != _PyFunction_Vectorcall) {
1749
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_VECTORCALL);
1750
0
        return -1;
1751
0
    }
1752
48.0k
    int argcount = -1;
1753
48.0k
    if (kind == SPEC_FAIL_CODE_NOT_OPTIMIZED) {
1754
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CODE_NOT_OPTIMIZED);
1755
0
        return -1;
1756
0
    }
1757
48.0k
    if (kind == SIMPLE_FUNCTION) {
1758
46.5k
        argcount = code->co_argcount;
1759
46.5k
    }
1760
48.0k
    int version = _PyFunction_GetVersionForCurrentState(func);
1761
48.0k
    if (!_PyFunction_IsVersionValid(version)) {
1762
63
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
1763
63
        return -1;
1764
63
    }
1765
47.9k
    write_u32(cache->func_version, version);
1766
47.9k
    uint8_t opcode;
1767
47.9k
    if (argcount == nargs + bound_method) {
1768
46.0k
        opcode =
1769
46.0k
            bound_method ? CALL_BOUND_METHOD_EXACT_ARGS : CALL_PY_EXACT_ARGS;
1770
46.0k
    }
1771
1.90k
    else {
1772
1.90k
        opcode = bound_method ? CALL_BOUND_METHOD_GENERAL : CALL_PY_GENERAL;
1773
1.90k
    }
1774
47.9k
    specialize(instr, opcode);
1775
47.9k
    return 0;
1776
48.0k
}
1777
1778
1779
static int
1780
specialize_py_call_kw(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
1781
                   bool bound_method)
1782
4.05k
{
1783
4.05k
    _PyCallCache *cache = (_PyCallCache *)(instr + 1);
1784
4.05k
    PyCodeObject *code = (PyCodeObject *)func->func_code;
1785
4.05k
    int kind = function_kind(code);
1786
    /* Don't specialize if PEP 523 is active */
1787
4.05k
    if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) {
1788
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
1789
0
        return -1;
1790
0
    }
1791
4.05k
    if (func->vectorcall != _PyFunction_Vectorcall) {
1792
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_VECTORCALL);
1793
0
        return -1;
1794
0
    }
1795
4.05k
    if (kind == SPEC_FAIL_CODE_NOT_OPTIMIZED) {
1796
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CODE_NOT_OPTIMIZED);
1797
0
        return -1;
1798
0
    }
1799
4.05k
    int version = _PyFunction_GetVersionForCurrentState(func);
1800
4.05k
    if (!_PyFunction_IsVersionValid(version)) {
1801
80
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
1802
80
        return -1;
1803
80
    }
1804
3.97k
    write_u32(cache->func_version, version);
1805
3.97k
    specialize(instr, bound_method ? CALL_KW_BOUND_METHOD : CALL_KW_PY);
1806
3.97k
    return 0;
1807
4.05k
}
1808
1809
static int
1810
specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
1811
434k
{
1812
434k
    if (PyCFunction_GET_FUNCTION(callable) == NULL) {
1813
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OTHER);
1814
0
        return 1;
1815
0
    }
1816
434k
    switch (PyCFunction_GET_FLAGS(callable) &
1817
434k
        (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
1818
434k
        METH_KEYWORDS | METH_METHOD)) {
1819
38.8k
        case METH_O: {
1820
38.8k
            if (nargs != 1) {
1821
0
                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1822
0
                return 1;
1823
0
            }
1824
            /* len(o) */
1825
38.8k
            PyInterpreterState *interp = _PyInterpreterState_GET();
1826
38.8k
            if (callable == interp->callable_cache.len && instr->op.arg == 1) {
1827
2.06k
                specialize(instr, CALL_LEN);
1828
2.06k
                return 0;
1829
2.06k
            }
1830
36.8k
            specialize(instr, CALL_BUILTIN_O);
1831
36.8k
            return 0;
1832
38.8k
        }
1833
21.4k
        case METH_FASTCALL: {
1834
21.4k
            if (nargs == 2) {
1835
                /* isinstance(o1, o2) */
1836
3.69k
                PyInterpreterState *interp = _PyInterpreterState_GET();
1837
3.69k
                if (callable == interp->callable_cache.isinstance && instr->op.arg == 2) {
1838
2.04k
                    specialize(instr, CALL_ISINSTANCE);
1839
2.04k
                    return 0;
1840
2.04k
                }
1841
3.69k
            }
1842
19.3k
            specialize(instr, CALL_BUILTIN_FAST);
1843
19.3k
            return 0;
1844
21.4k
        }
1845
374k
        case METH_FASTCALL | METH_KEYWORDS: {
1846
374k
            specialize(instr, CALL_BUILTIN_FAST_WITH_KEYWORDS);
1847
374k
            return 0;
1848
21.4k
        }
1849
591
        default:
1850
591
            specialize(instr, CALL_NON_PY_GENERAL);
1851
591
            return 0;
1852
434k
    }
1853
434k
}
1854
1855
Py_NO_INLINE void
1856
_Py_Specialize_Call(_PyStackRef callable_st, _PyStackRef self_or_null_st, _Py_CODEUNIT *instr, int nargs)
1857
971k
{
1858
971k
    PyObject *callable = PyStackRef_AsPyObjectBorrow(callable_st);
1859
1860
971k
    assert(ENABLE_SPECIALIZATION);
1861
971k
    assert(_PyOpcode_Caches[CALL] == INLINE_CACHE_ENTRIES_CALL);
1862
971k
    assert(_Py_OPCODE(*instr) != INSTRUMENTED_CALL);
1863
971k
    int fail;
1864
971k
    if (PyCFunction_CheckExact(callable)) {
1865
434k
        fail = specialize_c_call(callable, instr, nargs);
1866
434k
    }
1867
536k
    else if (PyFunction_Check(callable)) {
1868
40.7k
        fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs, false);
1869
40.7k
    }
1870
495k
    else if (PyType_Check(callable)) {
1871
3.92k
        fail = specialize_class_call(callable, instr, nargs);
1872
3.92k
    }
1873
491k
    else if (Py_IS_TYPE(callable, &PyMethodDescr_Type)) {
1874
472k
        PyObject *self_or_null = PyStackRef_AsPyObjectBorrow(self_or_null_st);
1875
472k
        fail = specialize_method_descriptor((PyMethodDescrObject *)callable,
1876
472k
                                            self_or_null, instr, nargs);
1877
472k
    }
1878
19.7k
    else if (PyMethod_Check(callable)) {
1879
7.26k
        PyObject *func = ((PyMethodObject *)callable)->im_func;
1880
7.26k
        if (PyFunction_Check(func)) {
1881
7.25k
            fail = specialize_py_call((PyFunctionObject *)func, instr, nargs, true);
1882
7.25k
        }
1883
8
        else {
1884
8
            SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_BOUND_METHOD);
1885
8
            fail = -1;
1886
8
        }
1887
7.26k
    }
1888
12.4k
    else {
1889
12.4k
        specialize(instr, CALL_NON_PY_GENERAL);
1890
12.4k
        fail = 0;
1891
12.4k
    }
1892
971k
    if (fail) {
1893
78
        unspecialize(instr);
1894
78
    }
1895
971k
}
1896
1897
Py_NO_INLINE void
1898
_Py_Specialize_CallKw(_PyStackRef callable_st, _Py_CODEUNIT *instr, int nargs)
1899
4.71k
{
1900
4.71k
    PyObject *callable = PyStackRef_AsPyObjectBorrow(callable_st);
1901
1902
4.71k
    assert(ENABLE_SPECIALIZATION);
1903
4.71k
    assert(_PyOpcode_Caches[CALL_KW] == INLINE_CACHE_ENTRIES_CALL_KW);
1904
4.71k
    assert(_Py_OPCODE(*instr) != INSTRUMENTED_CALL_KW);
1905
4.71k
    int fail;
1906
4.71k
    if (PyFunction_Check(callable)) {
1907
710
        fail = specialize_py_call_kw((PyFunctionObject *)callable, instr, nargs, false);
1908
710
    }
1909
4.00k
    else if (PyMethod_Check(callable)) {
1910
3.34k
        PyObject *func = ((PyMethodObject *)callable)->im_func;
1911
3.34k
        if (PyFunction_Check(func)) {
1912
3.34k
            fail = specialize_py_call_kw((PyFunctionObject *)func, instr, nargs, true);
1913
3.34k
        }
1914
0
        else {
1915
0
            SPECIALIZATION_FAIL(CALL_KW, SPEC_FAIL_CALL_BOUND_METHOD);
1916
0
            fail = -1;
1917
0
        }
1918
3.34k
    }
1919
661
    else {
1920
661
        specialize(instr, CALL_KW_NON_PY);
1921
661
        fail = 0;
1922
661
    }
1923
4.71k
    if (fail) {
1924
80
        unspecialize(instr);
1925
80
    }
1926
4.71k
}
1927
1928
#ifdef Py_STATS
1929
static int
1930
binary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs)
1931
{
1932
    switch (oparg) {
1933
        case NB_ADD:
1934
        case NB_INPLACE_ADD:
1935
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1936
                return SPEC_FAIL_BINARY_OP_ADD_DIFFERENT_TYPES;
1937
            }
1938
            return SPEC_FAIL_BINARY_OP_ADD_OTHER;
1939
        case NB_AND:
1940
        case NB_INPLACE_AND:
1941
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1942
                return SPEC_FAIL_BINARY_OP_AND_DIFFERENT_TYPES;
1943
            }
1944
            if (PyLong_CheckExact(lhs)) {
1945
                return SPEC_FAIL_BINARY_OP_AND_INT;
1946
            }
1947
            return SPEC_FAIL_BINARY_OP_AND_OTHER;
1948
        case NB_FLOOR_DIVIDE:
1949
        case NB_INPLACE_FLOOR_DIVIDE:
1950
            return SPEC_FAIL_BINARY_OP_FLOOR_DIVIDE;
1951
        case NB_LSHIFT:
1952
        case NB_INPLACE_LSHIFT:
1953
            return SPEC_FAIL_BINARY_OP_LSHIFT;
1954
        case NB_MATRIX_MULTIPLY:
1955
        case NB_INPLACE_MATRIX_MULTIPLY:
1956
            return SPEC_FAIL_BINARY_OP_MATRIX_MULTIPLY;
1957
        case NB_MULTIPLY:
1958
        case NB_INPLACE_MULTIPLY:
1959
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1960
                return SPEC_FAIL_BINARY_OP_MULTIPLY_DIFFERENT_TYPES;
1961
            }
1962
            return SPEC_FAIL_BINARY_OP_MULTIPLY_OTHER;
1963
        case NB_OR:
1964
        case NB_INPLACE_OR:
1965
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1966
                return SPEC_FAIL_BINARY_OP_OR_DIFFERENT_TYPES;
1967
            }
1968
            if (PyLong_CheckExact(lhs)) {
1969
                return SPEC_FAIL_BINARY_OP_OR_INT;
1970
            }
1971
            return SPEC_FAIL_BINARY_OP_OR;
1972
        case NB_POWER:
1973
        case NB_INPLACE_POWER:
1974
            return SPEC_FAIL_BINARY_OP_POWER;
1975
        case NB_REMAINDER:
1976
        case NB_INPLACE_REMAINDER:
1977
            return SPEC_FAIL_BINARY_OP_REMAINDER;
1978
        case NB_RSHIFT:
1979
        case NB_INPLACE_RSHIFT:
1980
            return SPEC_FAIL_BINARY_OP_RSHIFT;
1981
        case NB_SUBTRACT:
1982
        case NB_INPLACE_SUBTRACT:
1983
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1984
                return SPEC_FAIL_BINARY_OP_SUBTRACT_DIFFERENT_TYPES;
1985
            }
1986
            return SPEC_FAIL_BINARY_OP_SUBTRACT_OTHER;
1987
        case NB_TRUE_DIVIDE:
1988
        case NB_INPLACE_TRUE_DIVIDE:
1989
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1990
                return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_DIFFERENT_TYPES;
1991
            }
1992
            if (PyFloat_CheckExact(lhs)) {
1993
                return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_FLOAT;
1994
            }
1995
            return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_OTHER;
1996
        case NB_XOR:
1997
        case NB_INPLACE_XOR:
1998
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1999
                return SPEC_FAIL_BINARY_OP_XOR_DIFFERENT_TYPES;
2000
            }
2001
            if (PyLong_CheckExact(lhs)) {
2002
                return SPEC_FAIL_BINARY_OP_XOR_INT;
2003
            }
2004
            return SPEC_FAIL_BINARY_OP_XOR;
2005
        case NB_SUBSCR:
2006
            if (PyList_CheckExact(lhs)) {
2007
                if (PyLong_CheckExact(rhs) && !_PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
2008
                    return SPEC_FAIL_OUT_OF_RANGE;
2009
                }
2010
                if (PySlice_Check(rhs)) {
2011
                    return SPEC_FAIL_BINARY_OP_SUBSCR_LIST_SLICE;
2012
                }
2013
            }
2014
            if (PyTuple_CheckExact(lhs)) {
2015
                if (PyLong_CheckExact(rhs) && !_PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
2016
                    return SPEC_FAIL_OUT_OF_RANGE;
2017
                }
2018
                if (PySlice_Check(rhs)) {
2019
                    return SPEC_FAIL_BINARY_OP_SUBSCR_TUPLE_SLICE;
2020
                }
2021
            }
2022
            if (PyUnicode_CheckExact(lhs)) {
2023
                if (PyLong_CheckExact(rhs) && !_PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
2024
                    return SPEC_FAIL_OUT_OF_RANGE;
2025
                }
2026
                if (PySlice_Check(rhs)) {
2027
                    return SPEC_FAIL_BINARY_OP_SUBSCR_STRING_SLICE;
2028
                }
2029
            }
2030
            unsigned int tp_version;
2031
            PyTypeObject *container_type = Py_TYPE(lhs);
2032
            PyObject *descriptor = _PyType_LookupRefAndVersion(container_type, &_Py_ID(__getitem__), &tp_version);
2033
            if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {
2034
                if (!(container_type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
2035
                    Py_DECREF(descriptor);
2036
                    return SPEC_FAIL_BINARY_OP_SUBSCR_NOT_HEAP_TYPE;
2037
                }
2038
                PyFunctionObject *func = (PyFunctionObject *)descriptor;
2039
                PyCodeObject *fcode = (PyCodeObject *)func->func_code;
2040
                int kind = function_kind(fcode);
2041
                if (kind != SIMPLE_FUNCTION) {
2042
                    Py_DECREF(descriptor);
2043
                    return kind;
2044
                }
2045
                if (fcode->co_argcount != 2) {
2046
                    Py_DECREF(descriptor);
2047
                    return SPEC_FAIL_WRONG_NUMBER_ARGUMENTS;
2048
                }
2049
2050
                if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) {
2051
                    /* Don't specialize if PEP 523 is active */
2052
                    Py_DECREF(descriptor);
2053
                    return SPEC_FAIL_OTHER;
2054
                }
2055
            }
2056
            Py_XDECREF(descriptor);
2057
2058
            if (PyObject_TypeCheck(lhs, &PyDictProxy_Type)) {
2059
                return SPEC_FAIL_BINARY_OP_SUBSCR_MAPPINGPROXY;
2060
            }
2061
2062
            if (PyObject_TypeCheck(lhs, &PyBytes_Type)) {
2063
                return SPEC_FAIL_BINARY_OP_SUBSCR_BYTES;
2064
            }
2065
2066
            if (PyObject_TypeCheck(lhs, &PyRange_Type)) {
2067
                return SPEC_FAIL_BINARY_OP_SUBSCR_RANGE;
2068
            }
2069
2070
            if (strcmp(container_type->tp_name, "array.array") == 0) {
2071
                return SPEC_FAIL_BINARY_OP_SUBSCR_ARRAY;
2072
            }
2073
2074
            if (strcmp(container_type->tp_name, "re.Match") == 0) {
2075
                return SPEC_FAIL_BINARY_OP_SUBSCR_RE_MATCH;
2076
            }
2077
2078
            if (strcmp(container_type->tp_name, "collections.deque") == 0) {
2079
                return SPEC_FAIL_BINARY_OP_SUBSCR_DEQUE;
2080
            }
2081
2082
            if (strcmp(_PyType_Name(container_type), "EnumDict") == 0) {
2083
                return SPEC_FAIL_BINARY_OP_SUBSCR_ENUMDICT;
2084
            }
2085
2086
            if (strcmp(container_type->tp_name, "StackSummary") == 0) {
2087
                return SPEC_FAIL_BINARY_OP_SUBSCR_STACKSUMMARY;
2088
            }
2089
2090
            if (strcmp(container_type->tp_name, "collections.defaultdict") == 0) {
2091
                return SPEC_FAIL_BINARY_OP_SUBSCR_DEFAULTDICT;
2092
            }
2093
2094
            if (strcmp(container_type->tp_name, "Counter") == 0) {
2095
                return SPEC_FAIL_BINARY_OP_SUBSCR_COUNTER;
2096
            }
2097
2098
            if (strcmp(container_type->tp_name, "collections.OrderedDict") == 0) {
2099
                return SPEC_FAIL_BINARY_OP_SUBSCR_ORDEREDDICT;
2100
            }
2101
2102
            if (strcmp(container_type->tp_name, "time.struct_time") == 0) {
2103
                return SPEC_FAIL_BINARY_OP_SUBSCR_STRUCTTIME;
2104
            }
2105
2106
            if (PySlice_Check(rhs)) {
2107
                return SPEC_FAIL_BINARY_OP_SUBSCR_OTHER_SLICE;
2108
            }
2109
            return SPEC_FAIL_BINARY_OP_SUBSCR;
2110
    }
2111
    Py_UNREACHABLE();
2112
}
2113
#endif
2114
2115
/** Binary Op Specialization Extensions */
2116
2117
/* long-long */
2118
2119
static inline int
2120
is_compactlong(PyObject *v)
2121
162M
{
2122
162M
    return PyLong_CheckExact(v) &&
2123
162M
           _PyLong_IsCompact((PyLongObject *)v);
2124
162M
}
2125
2126
#define SEQ_INT_MULTIPLY_ACTION(NAME, REPEAT, SEQ, COUNT) \
2127
    static PyObject * \
2128
    (NAME)(PyObject *lhs, PyObject *rhs) \
2129
525k
    { \
2130
525k
        Py_ssize_t count = PyLong_AsSsize_t(COUNT); \
2131
525k
        if (count == -1 && PyErr_Occurred()) { \
2132
0
            return NULL; \
2133
0
        } \
2134
525k
        return REPEAT(SEQ, count); \
2135
525k
    }
2136
326k
SEQ_INT_MULTIPLY_ACTION(str_int_multiply,   _PyUnicode_Repeat, lhs, rhs)
2137
0
SEQ_INT_MULTIPLY_ACTION(int_str_multiply,   _PyUnicode_Repeat, rhs, lhs)
2138
91.2k
SEQ_INT_MULTIPLY_ACTION(bytes_int_multiply, _PyBytes_Repeat,   lhs, rhs)
2139
107k
SEQ_INT_MULTIPLY_ACTION(int_bytes_multiply, _PyBytes_Repeat,   rhs, lhs)
2140
0
SEQ_INT_MULTIPLY_ACTION(tuple_int_multiply, _PyTuple_Repeat,   lhs, rhs)
2141
0
SEQ_INT_MULTIPLY_ACTION(int_tuple_multiply, _PyTuple_Repeat,   rhs, lhs)
2142
#undef SEQ_INT_MULTIPLY_ACTION
2143
2144
static int
2145
compactlongs_guard(PyObject *lhs, PyObject *rhs)
2146
81.2M
{
2147
81.2M
    return (is_compactlong(lhs) && is_compactlong(rhs));
2148
81.2M
}
2149
2150
#define BITWISE_LONGS_ACTION(NAME, OP) \
2151
    static PyObject * \
2152
    (NAME)(PyObject *lhs, PyObject *rhs) \
2153
81.2M
    { \
2154
81.2M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2155
81.2M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2156
81.2M
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2157
81.2M
    }
specialize.c:compactlongs_or
Line
Count
Source
2153
1.53M
    { \
2154
1.53M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2155
1.53M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2156
1.53M
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2157
1.53M
    }
specialize.c:compactlongs_and
Line
Count
Source
2153
79.6M
    { \
2154
79.6M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2155
79.6M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2156
79.6M
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2157
79.6M
    }
specialize.c:compactlongs_xor
Line
Count
Source
2153
79
    { \
2154
79
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2155
79
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2156
79
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2157
79
    }
2158
BITWISE_LONGS_ACTION(compactlongs_or, |)
2159
BITWISE_LONGS_ACTION(compactlongs_and, &)
2160
BITWISE_LONGS_ACTION(compactlongs_xor, ^)
2161
#undef BITWISE_LONGS_ACTION
2162
2163
/* float-long */
2164
2165
static inline int
2166
float_compactlong_guard(PyObject *lhs, PyObject *rhs)
2167
1.18M
{
2168
1.18M
    return (
2169
1.18M
        PyFloat_CheckExact(lhs) &&
2170
1.16M
        !isnan(PyFloat_AS_DOUBLE(lhs)) &&
2171
1.18M
        PyLong_CheckExact(rhs) &&
2172
1.16M
        _PyLong_IsCompact((PyLongObject *)rhs)
2173
1.18M
    );
2174
1.18M
}
2175
2176
static inline int
2177
nonzero_float_compactlong_guard(PyObject *lhs, PyObject *rhs)
2178
497k
{
2179
497k
    return (
2180
497k
        float_compactlong_guard(lhs, rhs) && !_PyLong_IsZero((PyLongObject*)rhs)
2181
497k
    );
2182
497k
}
2183
2184
#define FLOAT_LONG_ACTION(NAME, OP) \
2185
    static PyObject * \
2186
    (NAME)(PyObject *lhs, PyObject *rhs) \
2187
1.15M
    { \
2188
1.15M
        double lhs_val = PyFloat_AS_DOUBLE(lhs); \
2189
1.15M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2190
1.15M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2191
1.15M
    }
Unexecuted instantiation: specialize.c:float_compactlong_add
specialize.c:float_compactlong_subtract
Line
Count
Source
2187
107
    { \
2188
107
        double lhs_val = PyFloat_AS_DOUBLE(lhs); \
2189
107
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2190
107
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2191
107
    }
specialize.c:float_compactlong_true_div
Line
Count
Source
2187
497k
    { \
2188
497k
        double lhs_val = PyFloat_AS_DOUBLE(lhs); \
2189
497k
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2190
497k
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2191
497k
    }
specialize.c:float_compactlong_multiply
Line
Count
Source
2187
661k
    { \
2188
661k
        double lhs_val = PyFloat_AS_DOUBLE(lhs); \
2189
661k
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2190
661k
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2191
661k
    }
2192
FLOAT_LONG_ACTION(float_compactlong_add, +)
2193
FLOAT_LONG_ACTION(float_compactlong_subtract, -)
2194
FLOAT_LONG_ACTION(float_compactlong_multiply, *)
2195
FLOAT_LONG_ACTION(float_compactlong_true_div, /)
2196
#undef FLOAT_LONG_ACTION
2197
2198
/*  long-float */
2199
2200
static inline int
2201
compactlong_float_guard(PyObject *lhs, PyObject *rhs)
2202
8.31M
{
2203
8.31M
    return (
2204
8.31M
        PyLong_CheckExact(lhs) &&
2205
8.31M
        _PyLong_IsCompact((PyLongObject *)lhs) &&
2206
8.31M
        PyFloat_CheckExact(rhs) &&
2207
8.28M
        !isnan(PyFloat_AS_DOUBLE(rhs))
2208
8.31M
    );
2209
8.31M
}
2210
2211
static inline int
2212
nonzero_compactlong_float_guard(PyObject *lhs, PyObject *rhs)
2213
23
{
2214
23
    return (
2215
23
        compactlong_float_guard(lhs, rhs) && PyFloat_AS_DOUBLE(rhs) != 0.0
2216
23
    );
2217
23
}
2218
2219
#define LONG_FLOAT_ACTION(NAME, OP) \
2220
    static PyObject * \
2221
    (NAME)(PyObject *lhs, PyObject *rhs) \
2222
8.28M
    { \
2223
8.28M
        double rhs_val = PyFloat_AS_DOUBLE(rhs); \
2224
8.28M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2225
8.28M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2226
8.28M
    }
specialize.c:compactlong_float_add
Line
Count
Source
2222
4.85k
    { \
2223
4.85k
        double rhs_val = PyFloat_AS_DOUBLE(rhs); \
2224
4.85k
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2225
4.85k
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2226
4.85k
    }
specialize.c:compactlong_float_subtract
Line
Count
Source
2222
4.13M
    { \
2223
4.13M
        double rhs_val = PyFloat_AS_DOUBLE(rhs); \
2224
4.13M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2225
4.13M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2226
4.13M
    }
Unexecuted instantiation: specialize.c:compactlong_float_true_div
specialize.c:compactlong_float_multiply
Line
Count
Source
2222
4.14M
    { \
2223
4.14M
        double rhs_val = PyFloat_AS_DOUBLE(rhs); \
2224
4.14M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2225
4.14M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2226
4.14M
    }
2227
LONG_FLOAT_ACTION(compactlong_float_add, +)
2228
LONG_FLOAT_ACTION(compactlong_float_subtract, -)
2229
LONG_FLOAT_ACTION(compactlong_float_multiply, *)
2230
LONG_FLOAT_ACTION(compactlong_float_true_div, /)
2231
#undef LONG_FLOAT_ACTION
2232
2233
static _PyBinaryOpSpecializationDescr binaryop_extend_descrs[] = {
2234
    /* long-long arithmetic: guards also check _PyLong_IsCompact, so
2235
       type alone is not sufficient to eliminate the guard. */
2236
    {NB_OR, compactlongs_guard, compactlongs_or, &PyLong_Type, 1, NULL, NULL},
2237
    {NB_AND, compactlongs_guard, compactlongs_and, &PyLong_Type, 1, NULL, NULL},
2238
    {NB_XOR, compactlongs_guard, compactlongs_xor, &PyLong_Type, 1, NULL, NULL},
2239
    {NB_INPLACE_OR, compactlongs_guard, compactlongs_or, &PyLong_Type, 1, NULL, NULL},
2240
    {NB_INPLACE_AND, compactlongs_guard, compactlongs_and, &PyLong_Type, 1, NULL, NULL},
2241
    {NB_INPLACE_XOR, compactlongs_guard, compactlongs_xor, &PyLong_Type, 1, NULL, NULL},
2242
2243
    /* float-long arithmetic: guards also check NaN and compactness. */
2244
    {NB_ADD, float_compactlong_guard, float_compactlong_add, &PyFloat_Type, 1, NULL, NULL},
2245
    {NB_SUBTRACT, float_compactlong_guard, float_compactlong_subtract, &PyFloat_Type, 1, NULL, NULL},
2246
    {NB_TRUE_DIVIDE, nonzero_float_compactlong_guard, float_compactlong_true_div, &PyFloat_Type, 1, NULL, NULL},
2247
    {NB_MULTIPLY, float_compactlong_guard, float_compactlong_multiply, &PyFloat_Type, 1, NULL, NULL},
2248
    {NB_INPLACE_ADD, float_compactlong_guard, float_compactlong_add, &PyFloat_Type, 1, NULL, NULL},
2249
    {NB_INPLACE_SUBTRACT, float_compactlong_guard, float_compactlong_subtract, &PyFloat_Type, 1, NULL, NULL},
2250
    {NB_INPLACE_TRUE_DIVIDE, nonzero_float_compactlong_guard, float_compactlong_true_div, &PyFloat_Type, 1, NULL, NULL},
2251
    {NB_INPLACE_MULTIPLY, float_compactlong_guard, float_compactlong_multiply, &PyFloat_Type, 1, NULL, NULL},
2252
2253
    /* long-float arithmetic: guards also check NaN and compactness. */
2254
    {NB_ADD, compactlong_float_guard, compactlong_float_add, &PyFloat_Type, 1, NULL, NULL},
2255
    {NB_SUBTRACT, compactlong_float_guard, compactlong_float_subtract, &PyFloat_Type, 1, NULL, NULL},
2256
    {NB_TRUE_DIVIDE, nonzero_compactlong_float_guard, compactlong_float_true_div, &PyFloat_Type, 1, NULL, NULL},
2257
    {NB_MULTIPLY, compactlong_float_guard, compactlong_float_multiply, &PyFloat_Type, 1, NULL, NULL},
2258
    {NB_INPLACE_ADD, compactlong_float_guard, compactlong_float_add, &PyFloat_Type, 1, NULL, NULL},
2259
    {NB_INPLACE_SUBTRACT, compactlong_float_guard, compactlong_float_subtract, &PyFloat_Type, 1, NULL, NULL},
2260
    {NB_INPLACE_TRUE_DIVIDE, nonzero_compactlong_float_guard, compactlong_float_true_div, &PyFloat_Type, 1, NULL, NULL},
2261
    {NB_INPLACE_MULTIPLY, compactlong_float_guard, compactlong_float_multiply, &PyFloat_Type, 1, NULL, NULL},
2262
2263
    /* list-list concatenation: _PyList_Concat always allocates a new list */
2264
    {NB_ADD, NULL, _PyList_Concat, &PyList_Type, 1, &PyList_Type, &PyList_Type},
2265
    /* tuple-tuple concatenation: _PyTuple_Concat has a zero-length shortcut
2266
       that can return one of the operands, so the result is not guaranteed
2267
       to be a freshly allocated object. */
2268
    {NB_ADD, NULL, _PyTuple_Concat, &PyTuple_Type, 0, &PyTuple_Type, &PyTuple_Type},
2269
2270
    /* str * int / int * str: call _PyUnicode_Repeat directly.
2271
       _PyUnicode_Repeat returns the original when n == 1. */
2272
    {NB_MULTIPLY, NULL, str_int_multiply, &PyUnicode_Type, 0, &PyUnicode_Type, &PyLong_Type},
2273
    {NB_MULTIPLY, NULL, int_str_multiply, &PyUnicode_Type, 0, &PyLong_Type, &PyUnicode_Type},
2274
    {NB_INPLACE_MULTIPLY, NULL, str_int_multiply, &PyUnicode_Type, 0, &PyUnicode_Type, &PyLong_Type},
2275
    {NB_INPLACE_MULTIPLY, NULL, int_str_multiply, &PyUnicode_Type, 0, &PyLong_Type, &PyUnicode_Type},
2276
2277
    /* bytes + bytes: bytes_concat may return an operand when one side
2278
       is empty, so result is not always unique. */
2279
    {NB_ADD, NULL, _PyBytes_Concat, &PyBytes_Type, 0, &PyBytes_Type, &PyBytes_Type},
2280
    {NB_INPLACE_ADD, NULL, _PyBytes_Concat, &PyBytes_Type, 0, &PyBytes_Type, &PyBytes_Type},
2281
2282
    /* bytes * int / int * bytes: call _PyBytes_Repeat directly.
2283
       _PyBytes_Repeat returns the original when n == 1. */
2284
    {NB_MULTIPLY, NULL, bytes_int_multiply, &PyBytes_Type, 0, &PyBytes_Type, &PyLong_Type},
2285
    {NB_MULTIPLY, NULL, int_bytes_multiply, &PyBytes_Type, 0, &PyLong_Type, &PyBytes_Type},
2286
    {NB_INPLACE_MULTIPLY, NULL, bytes_int_multiply, &PyBytes_Type, 0, &PyBytes_Type, &PyLong_Type},
2287
    {NB_INPLACE_MULTIPLY, NULL, int_bytes_multiply, &PyBytes_Type, 0, &PyLong_Type, &PyBytes_Type},
2288
2289
    /* tuple * int / int * tuple: call _PyTuple_Repeat directly.
2290
       _PyTuple_Repeat returns the original when n == 1. */
2291
    {NB_MULTIPLY, NULL, tuple_int_multiply, &PyTuple_Type, 0, &PyTuple_Type, &PyLong_Type},
2292
    {NB_MULTIPLY, NULL, int_tuple_multiply, &PyTuple_Type, 0, &PyLong_Type, &PyTuple_Type},
2293
    {NB_INPLACE_MULTIPLY, NULL, tuple_int_multiply, &PyTuple_Type, 0, &PyTuple_Type, &PyLong_Type},
2294
    {NB_INPLACE_MULTIPLY, NULL, int_tuple_multiply, &PyTuple_Type, 0, &PyLong_Type, &PyTuple_Type},
2295
2296
    /* dict | dict */
2297
    {NB_OR, NULL, _PyDict_Or, &PyDict_Type, 1, &PyDict_Type, &PyDict_Type},
2298
    {NB_INPLACE_OR, NULL, _PyDict_IOr, &PyDict_Type, 0, &PyDict_Type, &PyDict_Type},
2299
};
2300
2301
static int
2302
binary_op_extended_specialization(PyObject *lhs, PyObject *rhs, int oparg,
2303
                                  _PyBinaryOpSpecializationDescr **descr)
2304
60.8k
{
2305
60.8k
    size_t n = sizeof(binaryop_extend_descrs)/sizeof(_PyBinaryOpSpecializationDescr);
2306
2.44M
    for (size_t i = 0; i < n; i++) {
2307
2.38M
        _PyBinaryOpSpecializationDescr *d = &binaryop_extend_descrs[i];
2308
2.38M
        if (d->oparg != oparg) {
2309
2.27M
            continue;
2310
2.27M
        }
2311
112k
        int match = (d->guard != NULL)
2312
112k
            ? d->guard(lhs, rhs)
2313
112k
            : (Py_TYPE(lhs) == d->lhs_type && Py_TYPE(rhs) == d->rhs_type);
2314
112k
        if (match) {
2315
1.39k
            *descr = d;
2316
1.39k
            return 1;
2317
1.39k
        }
2318
112k
    }
2319
59.4k
    return 0;
2320
60.8k
}
2321
2322
Py_NO_INLINE void
2323
_Py_Specialize_BinaryOp(_PyStackRef lhs_st, _PyStackRef rhs_st, _Py_CODEUNIT *instr,
2324
                        int oparg, _PyStackRef *locals)
2325
1.30M
{
2326
1.30M
    PyObject *lhs = PyStackRef_AsPyObjectBorrow(lhs_st);
2327
1.30M
    PyObject *rhs = PyStackRef_AsPyObjectBorrow(rhs_st);
2328
1.30M
    assert(ENABLE_SPECIALIZATION);
2329
1.30M
    assert(_PyOpcode_Caches[BINARY_OP] == INLINE_CACHE_ENTRIES_BINARY_OP);
2330
2331
1.30M
    _PyBinaryOpCache *cache = (_PyBinaryOpCache *)(instr + 1);
2332
1.30M
    if (instr->op.code == BINARY_OP_EXTEND) {
2333
73
        write_ptr(cache->external_cache, NULL);
2334
73
    }
2335
2336
1.30M
    switch (oparg) {
2337
14.4k
        case NB_ADD:
2338
33.1k
        case NB_INPLACE_ADD:
2339
33.1k
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2340
2.52k
                break;
2341
2.52k
            }
2342
30.5k
            if (PyUnicode_CheckExact(lhs)) {
2343
715
                _Py_CODEUNIT next = instr[INLINE_CACHE_ENTRIES_BINARY_OP + 1];
2344
715
                bool to_store = (next.op.code == STORE_FAST);
2345
715
                if (to_store && PyStackRef_AsPyObjectBorrow(locals[next.op.arg]) == lhs) {
2346
146
                    specialize(instr, BINARY_OP_INPLACE_ADD_UNICODE);
2347
146
                    return;
2348
146
                }
2349
569
                specialize(instr, BINARY_OP_ADD_UNICODE);
2350
569
                return;
2351
715
            }
2352
29.8k
            if (_PyLong_CheckExactAndCompact(lhs) && _PyLong_CheckExactAndCompact(rhs)) {
2353
6.88k
                specialize(instr, BINARY_OP_ADD_INT);
2354
6.88k
                return;
2355
6.88k
            }
2356
22.9k
            if (PyFloat_CheckExact(lhs)) {
2357
7
                specialize(instr, BINARY_OP_ADD_FLOAT);
2358
7
                return;
2359
7
            }
2360
22.9k
            break;
2361
22.9k
        case NB_MULTIPLY:
2362
1.95k
        case NB_INPLACE_MULTIPLY:
2363
1.95k
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2364
197
                break;
2365
197
            }
2366
1.75k
            if (_PyLong_CheckExactAndCompact(lhs) && _PyLong_CheckExactAndCompact(rhs)) {
2367
451
                specialize(instr, BINARY_OP_MULTIPLY_INT);
2368
451
                return;
2369
451
            }
2370
1.30k
            if (PyFloat_CheckExact(lhs)) {
2371
22
                specialize(instr, BINARY_OP_MULTIPLY_FLOAT);
2372
22
                return;
2373
22
            }
2374
1.28k
            break;
2375
2.72k
        case NB_SUBTRACT:
2376
2.80k
        case NB_INPLACE_SUBTRACT:
2377
2.80k
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2378
24
                break;
2379
24
            }
2380
2.78k
            if (_PyLong_CheckExactAndCompact(lhs) && _PyLong_CheckExactAndCompact(rhs)) {
2381
1.49k
                specialize(instr, BINARY_OP_SUBTRACT_INT);
2382
1.49k
                return;
2383
1.49k
            }
2384
1.28k
            if (PyFloat_CheckExact(lhs)) {
2385
20
                specialize(instr, BINARY_OP_SUBTRACT_FLOAT);
2386
20
                return;
2387
20
            }
2388
1.26k
            break;
2389
1.25M
        case NB_SUBSCR:
2390
1.25M
            if (PyLong_CheckExact(rhs) && _PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
2391
1.24M
                if (PyList_CheckExact(lhs)) {
2392
49.2k
                    specialize(instr, BINARY_OP_SUBSCR_LIST_INT);
2393
49.2k
                    return;
2394
49.2k
                }
2395
1.19M
                if (PyTuple_CheckExact(lhs)) {
2396
1.04k
                    specialize(instr, BINARY_OP_SUBSCR_TUPLE_INT);
2397
1.04k
                    return;
2398
1.04k
                }
2399
1.19M
                if (PyUnicode_CheckExact(lhs) && _PyLong_IsNonNegativeCompact((PyLongObject*)rhs)) {
2400
1.18M
                    if (PyUnicode_IS_COMPACT_ASCII(lhs)) {
2401
1.64k
                        specialize(instr, BINARY_OP_SUBSCR_STR_INT);
2402
1.64k
                        return;
2403
1.18M
                    } else {
2404
1.18M
                        specialize(instr, BINARY_OP_SUBSCR_USTR_INT);
2405
1.18M
                        return;
2406
1.18M
                    }
2407
1.18M
                }
2408
1.19M
            }
2409
17.6k
            if (Py_TYPE(lhs)->tp_as_mapping != NULL &&
2410
17.4k
                Py_TYPE(lhs)->tp_as_mapping->mp_subscript == _PyDict_Subscript)
2411
901
            {
2412
901
                specialize(instr, BINARY_OP_SUBSCR_DICT);
2413
901
                return;
2414
901
            }
2415
16.7k
            if (PyList_CheckExact(lhs) && PySlice_Check(rhs)) {
2416
79
                specialize(instr, BINARY_OP_SUBSCR_LIST_SLICE);
2417
79
                return;
2418
79
            }
2419
16.6k
            unsigned int tp_version;
2420
16.6k
            PyTypeObject *container_type = Py_TYPE(lhs);
2421
16.6k
            PyObject *descriptor = _PyType_LookupRefAndVersion(container_type, &_Py_ID(__getitem__), &tp_version);
2422
16.6k
            if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type &&
2423
239
                container_type->tp_flags & Py_TPFLAGS_HEAPTYPE)
2424
239
            {
2425
239
                PyFunctionObject *func = (PyFunctionObject *)descriptor;
2426
239
                PyCodeObject *fcode = (PyCodeObject *)func->func_code;
2427
239
                int kind = function_kind(fcode);
2428
239
                PyHeapTypeObject *ht = (PyHeapTypeObject *)container_type;
2429
239
                if (kind == SIMPLE_FUNCTION &&
2430
239
                    fcode->co_argcount == 2 &&
2431
239
                    _PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET()) && /* Don't specialize if PEP 523 is active */
2432
239
                    _PyType_CacheGetItemForSpecialization(ht, descriptor, (uint32_t)tp_version))
2433
239
                {
2434
239
                    specialize(instr, BINARY_OP_SUBSCR_GETITEM);
2435
239
                    Py_DECREF(descriptor);
2436
239
                    return;
2437
239
                }
2438
239
            }
2439
16.3k
            Py_XDECREF(descriptor);
2440
16.3k
            break;
2441
1.30M
    }
2442
2443
60.8k
    _PyBinaryOpSpecializationDescr *descr;
2444
60.8k
    if (binary_op_extended_specialization(lhs, rhs, oparg, &descr)) {
2445
1.39k
        specialize(instr, BINARY_OP_EXTEND);
2446
1.39k
        write_ptr(cache->external_cache, (void*)descr);
2447
1.39k
        return;
2448
1.39k
    }
2449
2450
59.4k
    SPECIALIZATION_FAIL(BINARY_OP, binary_op_fail_kind(oparg, lhs, rhs));
2451
59.4k
    unspecialize(instr);
2452
59.4k
    return;
2453
60.8k
}
2454
2455
2456
#ifdef Py_STATS
2457
static int
2458
compare_op_fail_kind(PyObject *lhs, PyObject *rhs)
2459
{
2460
    if (Py_TYPE(lhs) != Py_TYPE(rhs)) {
2461
        if (PyFloat_CheckExact(lhs) && PyLong_CheckExact(rhs)) {
2462
            return SPEC_FAIL_COMPARE_OP_FLOAT_LONG;
2463
        }
2464
        if (PyLong_CheckExact(lhs) && PyFloat_CheckExact(rhs)) {
2465
            return SPEC_FAIL_COMPARE_OP_LONG_FLOAT;
2466
        }
2467
        return SPEC_FAIL_COMPARE_OP_DIFFERENT_TYPES;
2468
    }
2469
    if (PyBytes_CheckExact(lhs)) {
2470
        return SPEC_FAIL_COMPARE_OP_BYTES;
2471
    }
2472
    if (PyTuple_CheckExact(lhs)) {
2473
        return SPEC_FAIL_COMPARE_OP_TUPLE;
2474
    }
2475
    if (PyList_CheckExact(lhs)) {
2476
        return SPEC_FAIL_COMPARE_OP_LIST;
2477
    }
2478
    if (PySet_CheckExact(lhs) || PyFrozenSet_CheckExact(lhs)) {
2479
        return SPEC_FAIL_COMPARE_OP_SET;
2480
    }
2481
    if (PyBool_Check(lhs)) {
2482
        return SPEC_FAIL_COMPARE_OP_BOOL;
2483
    }
2484
    if (Py_TYPE(lhs)->tp_richcompare == PyBaseObject_Type.tp_richcompare) {
2485
        return SPEC_FAIL_COMPARE_OP_BASEOBJECT;
2486
    }
2487
    return SPEC_FAIL_OTHER;
2488
}
2489
#endif   // Py_STATS
2490
2491
Py_NO_INLINE void
2492
_Py_Specialize_CompareOp(_PyStackRef lhs_st, _PyStackRef rhs_st, _Py_CODEUNIT *instr,
2493
                         int oparg)
2494
26.7k
{
2495
26.7k
    PyObject *lhs = PyStackRef_AsPyObjectBorrow(lhs_st);
2496
26.7k
    PyObject *rhs = PyStackRef_AsPyObjectBorrow(rhs_st);
2497
26.7k
    uint8_t specialized_op;
2498
2499
26.7k
    assert(ENABLE_SPECIALIZATION);
2500
26.7k
    assert(_PyOpcode_Caches[COMPARE_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP);
2501
    // All of these specializations compute boolean values, so they're all valid
2502
    // regardless of the fifth-lowest oparg bit.
2503
26.7k
    if (Py_TYPE(lhs) != Py_TYPE(rhs)) {
2504
4.89k
        SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
2505
4.89k
        goto failure;
2506
4.89k
    }
2507
21.8k
    if (PyFloat_CheckExact(lhs)) {
2508
64
        specialized_op = COMPARE_OP_FLOAT;
2509
64
        goto success;
2510
64
    }
2511
21.7k
    if (PyLong_CheckExact(lhs)) {
2512
13.3k
        if (_PyLong_IsCompact((PyLongObject *)lhs) && _PyLong_IsCompact((PyLongObject *)rhs)) {
2513
6.66k
            specialized_op = COMPARE_OP_INT;
2514
6.66k
            goto success;
2515
6.66k
        }
2516
6.64k
        else {
2517
6.64k
            SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_BIG_INT);
2518
6.64k
            goto failure;
2519
6.64k
        }
2520
13.3k
    }
2521
8.46k
    if (PyUnicode_CheckExact(lhs)) {
2522
6.02k
        int cmp = oparg >> 5;
2523
6.02k
        if (cmp != Py_EQ && cmp != Py_NE) {
2524
3.49k
            SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_STRING);
2525
3.49k
            goto failure;
2526
3.49k
        }
2527
2.52k
        else {
2528
2.52k
            specialized_op = COMPARE_OP_STR;
2529
2.52k
            goto success;
2530
2.52k
        }
2531
6.02k
    }
2532
2.43k
    SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
2533
17.4k
failure:
2534
17.4k
    unspecialize(instr);
2535
17.4k
    return;
2536
9.26k
success:
2537
9.26k
    specialize(instr, specialized_op);
2538
9.26k
}
2539
2540
#ifdef Py_STATS
2541
static int
2542
unpack_sequence_fail_kind(PyObject *seq)
2543
{
2544
    if (PySequence_Check(seq)) {
2545
        return SPEC_FAIL_UNPACK_SEQUENCE_SEQUENCE;
2546
    }
2547
    if (PyIter_Check(seq)) {
2548
        return SPEC_FAIL_UNPACK_SEQUENCE_ITERATOR;
2549
    }
2550
    return SPEC_FAIL_OTHER;
2551
}
2552
#endif   // Py_STATS
2553
2554
Py_NO_INLINE void
2555
_Py_Specialize_UnpackSequence(_PyStackRef seq_st, _Py_CODEUNIT *instr, int oparg)
2556
6.33k
{
2557
6.33k
    PyObject *seq = PyStackRef_AsPyObjectBorrow(seq_st);
2558
2559
6.33k
    assert(ENABLE_SPECIALIZATION);
2560
6.33k
    assert(_PyOpcode_Caches[UNPACK_SEQUENCE] ==
2561
6.33k
           INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE);
2562
6.33k
    if (PyTuple_CheckExact(seq)) {
2563
2.16k
        if (PyTuple_GET_SIZE(seq) != oparg) {
2564
0
            SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_EXPECTED_ERROR);
2565
0
            unspecialize(instr);
2566
0
            return;
2567
0
        }
2568
2.16k
        if (PyTuple_GET_SIZE(seq) == 2) {
2569
1.43k
            specialize(instr, UNPACK_SEQUENCE_TWO_TUPLE);
2570
1.43k
            return;
2571
1.43k
        }
2572
730
        specialize(instr, UNPACK_SEQUENCE_TUPLE);
2573
730
        return;
2574
2.16k
    }
2575
4.17k
    if (PyList_CheckExact(seq)) {
2576
4.01k
        if (PyList_GET_SIZE(seq) != oparg) {
2577
2.66k
            SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_EXPECTED_ERROR);
2578
2.66k
            unspecialize(instr);
2579
2.66k
            return;
2580
2.66k
        }
2581
1.34k
        specialize(instr, UNPACK_SEQUENCE_LIST);
2582
1.34k
        return;
2583
4.01k
    }
2584
154
    SPECIALIZATION_FAIL(UNPACK_SEQUENCE, unpack_sequence_fail_kind(seq));
2585
154
    unspecialize(instr);
2586
154
}
2587
2588
#ifdef Py_STATS
2589
int
2590
 _PySpecialization_ClassifyIterator(PyObject *iter)
2591
{
2592
    if (PyGen_CheckExact(iter)) {
2593
        return SPEC_FAIL_ITER_GENERATOR;
2594
    }
2595
    if (PyCoro_CheckExact(iter)) {
2596
        return SPEC_FAIL_ITER_COROUTINE;
2597
    }
2598
    if (PyAsyncGen_CheckExact(iter)) {
2599
        return SPEC_FAIL_ITER_ASYNC_GENERATOR;
2600
    }
2601
    if (PyAsyncGenASend_CheckExact(iter)) {
2602
        return SPEC_FAIL_ITER_ASYNC_GENERATOR_SEND;
2603
    }
2604
    PyTypeObject *t = Py_TYPE(iter);
2605
    if (t == &PyListIter_Type) {
2606
        return SPEC_FAIL_ITER_LIST;
2607
    }
2608
    if (t == &PyTupleIter_Type) {
2609
        return SPEC_FAIL_ITER_TUPLE;
2610
    }
2611
    if (t == &PyDictIterKey_Type) {
2612
        return SPEC_FAIL_ITER_DICT_KEYS;
2613
    }
2614
    if (t == &PyDictIterValue_Type) {
2615
        return SPEC_FAIL_ITER_DICT_VALUES;
2616
    }
2617
    if (t == &PyDictIterItem_Type) {
2618
        return SPEC_FAIL_ITER_DICT_ITEMS;
2619
    }
2620
    if (t == &PySetIter_Type) {
2621
        return SPEC_FAIL_ITER_SET;
2622
    }
2623
    if (t == &PyUnicodeIter_Type) {
2624
        return SPEC_FAIL_ITER_STRING;
2625
    }
2626
    if (t == &PyBytesIter_Type) {
2627
        return SPEC_FAIL_ITER_BYTES;
2628
    }
2629
    if (t == &PyRangeIter_Type) {
2630
        return SPEC_FAIL_ITER_RANGE;
2631
    }
2632
    if (t == &PyEnum_Type) {
2633
        return SPEC_FAIL_ITER_ENUMERATE;
2634
    }
2635
    if (t == &PyMap_Type) {
2636
        return SPEC_FAIL_ITER_MAP;
2637
    }
2638
    if (t == &PyZip_Type) {
2639
        return SPEC_FAIL_ITER_ZIP;
2640
    }
2641
    if (t == &PySeqIter_Type) {
2642
        return SPEC_FAIL_ITER_SEQ_ITER;
2643
    }
2644
    if (t == &PyListRevIter_Type) {
2645
        return SPEC_FAIL_ITER_REVERSED_LIST;
2646
    }
2647
    if (t == &_PyUnicodeASCIIIter_Type) {
2648
        return SPEC_FAIL_ITER_ASCII_STRING;
2649
    }
2650
    const char *name = t->tp_name;
2651
    if (strncmp(name, "itertools", 9) == 0) {
2652
        return SPEC_FAIL_ITER_ITERTOOLS;
2653
    }
2654
    if (strncmp(name, "callable_iterator", 17) == 0) {
2655
        return SPEC_FAIL_ITER_CALLABLE;
2656
    }
2657
    return SPEC_FAIL_OTHER;
2658
}
2659
#endif   // Py_STATS
2660
2661
Py_NO_INLINE void
2662
_Py_Specialize_ForIter(_PyStackRef iter, _PyStackRef null_or_index, _Py_CODEUNIT *instr, int oparg)
2663
58.6k
{
2664
58.6k
    assert(ENABLE_SPECIALIZATION);
2665
58.6k
    assert(_PyOpcode_Caches[FOR_ITER] == INLINE_CACHE_ENTRIES_FOR_ITER);
2666
58.6k
    PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
2667
58.6k
    PyTypeObject *tp = Py_TYPE(iter_o);
2668
2669
58.6k
    if (PyStackRef_IsNull(null_or_index)) {
2670
51.4k
        if (tp == &PyRangeIter_Type) {
2671
#ifdef Py_GIL_DISABLED
2672
            // Only specialize for uniquely referenced iterators, so that we know
2673
            // they're only referenced by this one thread. This is more limiting
2674
            // than we need (even `it = iter(mylist); for item in it:` won't get
2675
            // specialized) but we don't have a way to check whether we're the only
2676
            // _thread_ who has access to the object.
2677
            if (!_PyObject_IsUniquelyReferenced(iter_o)) {
2678
                goto failure;
2679
            }
2680
#endif
2681
256
            specialize(instr, FOR_ITER_RANGE);
2682
256
            return;
2683
256
        }
2684
51.1k
        else if (tp == &PyGen_Type && oparg <= SHRT_MAX) {
2685
642
            assert(instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == END_FOR  ||
2686
642
                instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == INSTRUMENTED_END_FOR
2687
642
            );
2688
            /* Don't specialize if PEP 523 is active */
2689
642
            if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) {
2690
0
                goto failure;
2691
0
            }
2692
642
            specialize(instr, FOR_ITER_GEN);
2693
642
            return;
2694
642
        }
2695
51.4k
    }
2696
7.25k
    else {
2697
7.25k
        if (tp->_tp_iteritem != NULL) {
2698
7.25k
            if (tp == &PyList_Type) {
2699
    #ifdef Py_GIL_DISABLED
2700
                // Only specialize for lists owned by this thread or shared
2701
                if (!_Py_IsOwnedByCurrentThread(iter_o) && !_PyObject_GC_IS_SHARED(iter_o)) {
2702
                    goto failure;
2703
                }
2704
    #endif
2705
5.61k
                specialize(instr, FOR_ITER_LIST);
2706
5.61k
                return;
2707
5.61k
            }
2708
1.63k
            else if (tp == &PyTuple_Type) {
2709
1.47k
                specialize(instr, FOR_ITER_TUPLE);
2710
1.47k
                return;
2711
1.47k
            }
2712
7.25k
        }
2713
159
        specialize(instr, FOR_ITER_VIRTUAL);
2714
159
        return;
2715
7.25k
    }
2716
50.5k
failure:
2717
50.5k
    SPECIALIZATION_FAIL(FOR_ITER,
2718
50.5k
                        _PySpecialization_ClassifyIterator(iter_o));
2719
50.5k
    unspecialize(instr);
2720
50.5k
}
2721
2722
Py_NO_INLINE void
2723
_Py_Specialize_Send(_PyStackRef receiver_st, _Py_CODEUNIT *instr)
2724
560
{
2725
560
    PyObject *receiver = PyStackRef_AsPyObjectBorrow(receiver_st);
2726
2727
560
    assert(ENABLE_SPECIALIZATION);
2728
560
    assert(_PyOpcode_Caches[SEND] == INLINE_CACHE_ENTRIES_SEND);
2729
560
    PyTypeObject *tp = Py_TYPE(receiver);
2730
560
    if (tp == &PyGen_Type || tp == &PyCoro_Type) {
2731
        /* Don't specialize if PEP 523 is active */
2732
277
        if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) {
2733
0
            SPECIALIZATION_FAIL(SEND, SPEC_FAIL_OTHER);
2734
0
            goto failure;
2735
0
        }
2736
277
        specialize(instr, SEND_GEN);
2737
277
        return;
2738
277
    }
2739
283
    if (tp->_tp_iteritem != NULL) {
2740
283
        specialize(instr, SEND_VIRTUAL);
2741
283
        return;
2742
283
    }
2743
0
    if (tp == &_PyAsyncGenASend_Type) {
2744
0
        specialize(instr, SEND_ASYNC_GEN);
2745
0
        return;
2746
0
    }
2747
0
    SPECIALIZATION_FAIL(SEND,
2748
0
                        _PySpecialization_ClassifyIterator(receiver));
2749
0
failure:
2750
0
    unspecialize(instr);
2751
0
}
2752
2753
Py_NO_INLINE void
2754
_Py_Specialize_CallFunctionEx(_PyStackRef func_st, _Py_CODEUNIT *instr)
2755
633
{
2756
633
    PyObject *func = PyStackRef_AsPyObjectBorrow(func_st);
2757
2758
633
    assert(ENABLE_SPECIALIZATION);
2759
633
    assert(_PyOpcode_Caches[CALL_FUNCTION_EX] == INLINE_CACHE_ENTRIES_CALL_FUNCTION_EX);
2760
2761
633
    if (Py_TYPE(func) == &PyFunction_Type &&
2762
181
        ((PyFunctionObject *)func)->vectorcall == _PyFunction_Vectorcall) {
2763
181
        if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) {
2764
0
            goto failure;
2765
0
        }
2766
181
        specialize(instr, CALL_EX_PY);
2767
181
        return;
2768
181
    }
2769
452
    specialize(instr, CALL_EX_NON_PY_GENERAL);
2770
452
    return;
2771
0
failure:
2772
0
    unspecialize(instr);
2773
0
}
2774
2775
#ifdef Py_STATS
2776
static int
2777
to_bool_fail_kind(PyObject *value)
2778
{
2779
    if (PyByteArray_CheckExact(value)) {
2780
        return SPEC_FAIL_TO_BOOL_BYTEARRAY;
2781
    }
2782
    if (PyBytes_CheckExact(value)) {
2783
        return SPEC_FAIL_TO_BOOL_BYTES;
2784
    }
2785
    if (PyDict_CheckExact(value)) {
2786
        return SPEC_FAIL_TO_BOOL_DICT;
2787
    }
2788
    if (PyFloat_CheckExact(value)) {
2789
        return SPEC_FAIL_TO_BOOL_FLOAT;
2790
    }
2791
    if (PyMemoryView_Check(value)) {
2792
        return SPEC_FAIL_TO_BOOL_MEMORY_VIEW;
2793
    }
2794
    if (PyAnySet_CheckExact(value)) {
2795
        return SPEC_FAIL_TO_BOOL_SET;
2796
    }
2797
    if (PyTuple_CheckExact(value)) {
2798
        return SPEC_FAIL_TO_BOOL_TUPLE;
2799
    }
2800
    return SPEC_FAIL_OTHER;
2801
}
2802
#endif  // Py_STATS
2803
2804
static int
2805
check_type_always_true(PyTypeObject *ty)
2806
65.7k
{
2807
65.7k
    PyNumberMethods *nb = ty->tp_as_number;
2808
65.7k
    if (nb && nb->nb_bool) {
2809
49
        return SPEC_FAIL_TO_BOOL_NUMBER;
2810
49
    }
2811
65.7k
    PyMappingMethods *mp = ty->tp_as_mapping;
2812
65.7k
    if (mp && mp->mp_length) {
2813
4.54k
        return SPEC_FAIL_TO_BOOL_MAPPING;
2814
4.54k
    }
2815
61.1k
    PySequenceMethods *sq = ty->tp_as_sequence;
2816
61.1k
    if (sq && sq->sq_length) {
2817
5.25k
      return SPEC_FAIL_TO_BOOL_SEQUENCE;
2818
5.25k
    }
2819
55.9k
    return 0;
2820
61.1k
}
2821
2822
Py_NO_INLINE void
2823
_Py_Specialize_ToBool(_PyStackRef value_o, _Py_CODEUNIT *instr)
2824
181k
{
2825
181k
    assert(ENABLE_SPECIALIZATION);
2826
181k
    assert(_PyOpcode_Caches[TO_BOOL] == INLINE_CACHE_ENTRIES_TO_BOOL);
2827
181k
    _PyToBoolCache *cache = (_PyToBoolCache *)(instr + 1);
2828
181k
    PyObject *value = PyStackRef_AsPyObjectBorrow(value_o);
2829
181k
    uint8_t specialized_op;
2830
181k
    if (PyBool_Check(value)) {
2831
10.9k
        specialized_op = TO_BOOL_BOOL;
2832
10.9k
        goto success;
2833
10.9k
    }
2834
170k
    if (PyLong_CheckExact(value)) {
2835
7.16k
        specialized_op = TO_BOOL_INT;
2836
7.16k
        goto success;
2837
7.16k
    }
2838
163k
    if (PyList_CheckExact(value)) {
2839
534
        specialized_op = TO_BOOL_LIST;
2840
534
        goto success;
2841
534
    }
2842
162k
    if (Py_IsNone(value)) {
2843
74.8k
        specialized_op = TO_BOOL_NONE;
2844
74.8k
        goto success;
2845
74.8k
    }
2846
88.0k
    if (PyUnicode_CheckExact(value)) {
2847
17.5k
        specialized_op = TO_BOOL_STR;
2848
17.5k
        goto success;
2849
17.5k
    }
2850
70.4k
    if (PyType_HasFeature(Py_TYPE(value), Py_TPFLAGS_HEAPTYPE)) {
2851
65.7k
        unsigned int version = 0;
2852
65.7k
        int err = _PyType_Validate(Py_TYPE(value), check_type_always_true, &version);
2853
65.7k
        if (err < 0) {
2854
0
            SPECIALIZATION_FAIL(TO_BOOL, SPEC_FAIL_OUT_OF_VERSIONS);
2855
0
            goto failure;
2856
0
        }
2857
65.7k
        else if (err > 0) {
2858
9.84k
            SPECIALIZATION_FAIL(TO_BOOL, err);
2859
9.84k
            goto failure;
2860
9.84k
        }
2861
2862
65.7k
        assert(err == 0);
2863
55.9k
        assert(version);
2864
55.9k
        write_u32(cache->version, version);
2865
55.9k
        specialized_op = TO_BOOL_ALWAYS_TRUE;
2866
55.9k
        goto success;
2867
65.7k
    }
2868
2869
4.66k
    SPECIALIZATION_FAIL(TO_BOOL, to_bool_fail_kind(value));
2870
14.5k
failure:
2871
14.5k
    unspecialize(instr);
2872
14.5k
    return;
2873
167k
success:
2874
167k
    specialize(instr, specialized_op);
2875
167k
}
2876
2877
#ifdef Py_STATS
2878
static int
2879
containsop_fail_kind(PyObject *value) {
2880
    if (PyUnicode_CheckExact(value)) {
2881
        return SPEC_FAIL_CONTAINS_OP_STR;
2882
    }
2883
    if (PyList_CheckExact(value)) {
2884
        return SPEC_FAIL_CONTAINS_OP_LIST;
2885
    }
2886
    if (PyTuple_CheckExact(value)) {
2887
        return SPEC_FAIL_CONTAINS_OP_TUPLE;
2888
    }
2889
    if (PyType_Check(value)) {
2890
        return SPEC_FAIL_CONTAINS_OP_USER_CLASS;
2891
    }
2892
    return SPEC_FAIL_OTHER;
2893
}
2894
#endif
2895
2896
Py_NO_INLINE void
2897
_Py_Specialize_ContainsOp(_PyStackRef value_st, _Py_CODEUNIT *instr)
2898
32.3k
{
2899
32.3k
    PyObject *value = PyStackRef_AsPyObjectBorrow(value_st);
2900
2901
32.3k
    assert(ENABLE_SPECIALIZATION);
2902
32.3k
    assert(_PyOpcode_Caches[CONTAINS_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP);
2903
32.3k
    if (PyAnyDict_CheckExact(value)) {
2904
700
        specialize(instr, CONTAINS_OP_DICT);
2905
700
        return;
2906
700
    }
2907
31.6k
    if (PySet_CheckExact(value) || PyFrozenSet_CheckExact(value)) {
2908
655
        specialize(instr, CONTAINS_OP_SET);
2909
655
        return;
2910
655
    }
2911
2912
30.9k
    SPECIALIZATION_FAIL(CONTAINS_OP, containsop_fail_kind(value));
2913
30.9k
    unspecialize(instr);
2914
30.9k
    return;
2915
31.6k
}
2916
2917
void
2918
_Py_Specialize_GetIter(_PyStackRef iterable, _Py_CODEUNIT *instr)
2919
9.87k
{
2920
9.87k
    assert(ENABLE_SPECIALIZATION);
2921
9.87k
    PyTypeObject *tp = PyStackRef_TYPE(iterable);
2922
9.87k
    if (tp->_tp_iteritem != NULL) {
2923
2.30k
        specialize(instr, GET_ITER_VIRTUAL);
2924
2.30k
        return;
2925
2.30k
    }
2926
7.57k
    if (tp->tp_iter == PyObject_SelfIter) {
2927
575
        specialize(instr, GET_ITER_SELF);
2928
575
        return;
2929
575
    }
2930
6.99k
    SPECIALIZATION_FAIL(GET_ITER,
2931
6.99k
        tp == &PyCoro_Type ? SPEC_FAIL_ITER_COROUTINE : SPEC_FAIL_OTHER);
2932
6.99k
    unspecialize(instr);
2933
6.99k
}
2934
2935
void
2936
_Py_Specialize_Resume(_Py_CODEUNIT *instr, PyThreadState *tstate, _PyInterpreterFrame *frame)
2937
2.50M
{
2938
2.50M
    if (tstate->tracing == 0 && instr->op.code == RESUME) {
2939
92.1k
        if (tstate->interp->jit) {
2940
0
            PyCodeObject *co = (PyCodeObject *)PyStackRef_AsPyObjectBorrow(frame->f_executable);
2941
0
            if (co != NULL &&
2942
0
                PyCode_Check(co) &&
2943
0
                (co->co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) == 0) {
2944
0
                specialize(instr, RESUME_CHECK_JIT);
2945
0
                set_counter((_Py_BackoffCounter *)instr + 1, initial_resume_backoff_counter(&tstate->interp->opt_config));
2946
0
                return;
2947
0
            }
2948
0
        }
2949
92.1k
        specialize(instr, RESUME_CHECK);
2950
92.1k
        return;
2951
92.1k
    }
2952
2.40M
    unspecialize(instr);
2953
2.40M
    return;
2954
2.50M
}
2955
2956
#ifdef Py_STATS
2957
void
2958
_Py_GatherStats_GetIter(_PyStackRef iterable)
2959
{
2960
    PyTypeObject *tp = PyStackRef_TYPE(iterable);
2961
    int kind = SPEC_FAIL_OTHER;
2962
    if (tp == &PyTuple_Type) {
2963
        kind = SPEC_FAIL_ITER_TUPLE;
2964
    }
2965
    else if (tp == &PyList_Type) {
2966
        kind = SPEC_FAIL_ITER_LIST;
2967
    }
2968
    else if (tp == &PyDict_Type) {
2969
        kind = SPEC_FAIL_ITER_DICT_KEYS;
2970
    }
2971
    else if (tp == &PySet_Type) {
2972
        kind = SPEC_FAIL_ITER_SET;
2973
    }
2974
    else if (tp == &PyBytes_Type) {
2975
        kind = SPEC_FAIL_ITER_BYTES;
2976
    }
2977
    else if (tp == &PyEnum_Type) {
2978
        kind = SPEC_FAIL_ITER_ENUMERATE;
2979
    }
2980
    else if (tp == &PyUnicode_Type) {
2981
        kind = SPEC_FAIL_ITER_STRING;
2982
    }
2983
    else if (tp == &PyGen_Type) {
2984
        kind = SPEC_FAIL_ITER_GENERATOR;
2985
    }
2986
    else if (tp == &PyCoro_Type) {
2987
        kind = SPEC_FAIL_ITER_COROUTINE;
2988
    }
2989
    else if (tp == &PyAsyncGen_Type) {
2990
        kind = SPEC_FAIL_ITER_ASYNC_GENERATOR;
2991
    }
2992
    else if (tp == &_PyAsyncGenASend_Type) {
2993
        kind = SPEC_FAIL_ITER_ASYNC_GENERATOR_SEND;
2994
    }
2995
    else if (tp->tp_iter == PyObject_SelfIter) {
2996
        kind = SPEC_FAIL_ITER_SELF;
2997
    }
2998
    SPECIALIZATION_FAIL(GET_ITER, kind);
2999
}
3000
#endif
3001
3002
3003
/* Code init cleanup.
3004
 * CALL_ALLOC_AND_ENTER_INIT will set up
3005
 * the frame to execute the EXIT_INIT_CHECK
3006
 * instruction.
3007
 * Ends with a RESUME so that it is not traced.
3008
 * This is used as a plain code object, not a function,
3009
 * so must not access globals or builtins.
3010
 * There are a few other constraints imposed on the code
3011
 * by the free-threaded build:
3012
 *
3013
 * 1. The RESUME instruction must not be executed. Otherwise we may attempt to
3014
 *    free the statically allocated TLBC array.
3015
 * 2. It must contain no specializable instructions. Specializing multiple
3016
 *    copies of the same bytecode is not thread-safe in free-threaded builds.
3017
 *
3018
 * This should be dynamically allocated if either of those restrictions need to
3019
 * be lifted.
3020
 */
3021
3022
#define NO_LOC_4 (128 | (PY_CODE_LOCATION_INFO_NONE << 3) | 3)
3023
3024
static const PyBytesObject no_location = {
3025
    PyVarObject_HEAD_INIT(&PyBytes_Type, 1)
3026
    .ob_sval = { NO_LOC_4 }
3027
};
3028
3029
#ifdef Py_GIL_DISABLED
3030
static _PyCodeArray init_cleanup_tlbc = {
3031
    .size = 1,
3032
    .entries = {(char*) &_Py_InitCleanup.co_code_adaptive},
3033
};
3034
#endif
3035
3036
const struct _PyCode8 _Py_InitCleanup = {
3037
    _PyVarObject_HEAD_INIT(&PyCode_Type, 3),
3038
    .co_consts = (PyObject *)&_Py_SINGLETON(tuple_empty),
3039
    .co_names = (PyObject *)&_Py_SINGLETON(tuple_empty),
3040
    .co_exceptiontable = (PyObject *)&_Py_SINGLETON(bytes_empty),
3041
    .co_flags = CO_OPTIMIZED | CO_NO_MONITORING_EVENTS,
3042
    .co_localsplusnames = (PyObject *)&_Py_SINGLETON(tuple_empty),
3043
    .co_localspluskinds = (PyObject *)&_Py_SINGLETON(bytes_empty),
3044
    .co_filename = &_Py_ID(__init__),
3045
    .co_name = &_Py_ID(__init__),
3046
    .co_qualname = &_Py_ID(__init__),
3047
    .co_linetable = (PyObject *)&no_location,
3048
    ._co_firsttraceable = 4,
3049
    .co_stacksize = 2,
3050
    .co_framesize = 2 + FRAME_SPECIALS_SIZE,
3051
#ifdef Py_GIL_DISABLED
3052
    .co_tlbc = &init_cleanup_tlbc,
3053
#endif
3054
    .co_code_adaptive = {
3055
        EXIT_INIT_CHECK, 0,
3056
        RETURN_VALUE, 0,
3057
        RESUME, RESUME_AT_FUNC_START,
3058
        CACHE, 0, /* RESUME's cache */
3059
    }
3060
};