Coverage Report

Created: 2026-05-30 06:18

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