Coverage Report

Created: 2026-05-16 06:46

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
229k
#  define SPECIALIZATION_FAIL(opcode, kind) ((void)0)
44
#endif  // Py_STATS
45
46
static void
47
fixup_getiter(_Py_CODEUNIT *instruction, int flags)
48
30.8k
{
49
    // Compiler can't know if types.coroutine() will be called,
50
    // so fix up here
51
30.8k
    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
30.8k
}
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
187k
{
65
187k
    #if ENABLE_SPECIALIZATION
66
187k
    _Py_BackoffCounter jump_counter, adaptive_counter, resume_counter;
67
187k
    if (enable_counters) {
68
187k
        PyThreadState *tstate = _PyThreadState_GET();
69
187k
        PyInterpreterState *interp = tstate->interp;
70
187k
        jump_counter = initial_jump_backoff_counter(&interp->opt_config);
71
187k
        adaptive_counter = adaptive_counter_warmup();
72
187k
        resume_counter = initial_resume_backoff_counter(&interp->opt_config);
73
187k
    }
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
187k
    int opcode = 0;
80
187k
    int oparg = 0;
81
    /* The last code unit cannot have a cache, so we don't need to check it */
82
7.84M
    for (Py_ssize_t i = 0; i < size-1; i++) {
83
7.65M
        opcode = instructions[i].op.code;
84
7.65M
        int caches = _PyOpcode_Caches[opcode];
85
7.65M
        oparg = (oparg << 8) | instructions[i].op.arg;
86
7.65M
        if (opcode == GET_ITER) {
87
30.8k
            fixup_getiter(&instructions[i], flags);
88
30.8k
        }
89
7.65M
        if (caches) {
90
            // The initial value depends on the opcode
91
2.46M
            switch (opcode) {
92
67.0k
                case JUMP_BACKWARD:
93
67.0k
                    instructions[i + 1].counter = jump_counter;
94
67.0k
                    break;
95
215k
                case RESUME:
96
215k
                    instructions[i + 1].counter = resume_counter;
97
215k
                    break;
98
138k
                case POP_JUMP_IF_FALSE:
99
211k
                case POP_JUMP_IF_TRUE:
100
221k
                case POP_JUMP_IF_NONE:
101
234k
                case POP_JUMP_IF_NOT_NONE:
102
234k
                    instructions[i + 1].cache = 0x5555;  // Alternating 0, 1 bits
103
234k
                    break;
104
1.95M
                default:
105
1.95M
                    instructions[i + 1].counter = adaptive_counter;
106
1.95M
                    break;
107
2.46M
            }
108
2.46M
            i += caches;
109
2.46M
        }
110
7.65M
        if (opcode != EXTENDED_ARG) {
111
7.61M
            oparg = 0;
112
7.61M
        }
113
7.65M
    }
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
187k
}
123
124
486k
#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.20k
#define SPEC_FAIL_CODE_COMPLEX_PARAMETERS 7
136
50.2k
#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
3.63k
#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
4.89k
#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.79M
{
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.79M
    instr->op.code = opcode;
341
7.79M
    return 1;
342
7.79M
#endif
343
7.79M
}
344
345
static inline void
346
set_counter(_Py_BackoffCounter *counter, _Py_BackoffCounter value)
347
9.30M
{
348
9.30M
    FT_ATOMIC_STORE_UINT16_RELAXED(counter->value_and_backoff,
349
9.30M
                                   value.value_and_backoff);
350
9.30M
}
351
352
static inline _Py_BackoffCounter
353
load_counter(_Py_BackoffCounter *counter)
354
2.86M
{
355
2.86M
    _Py_BackoffCounter result = {
356
2.86M
        .value_and_backoff =
357
2.86M
            FT_ATOMIC_LOAD_UINT16_RELAXED(counter->value_and_backoff)};
358
2.86M
    return result;
359
2.86M
}
360
361
static inline void
362
specialize(_Py_CODEUNIT *instr, uint8_t specialized_opcode)
363
4.93M
{
364
4.93M
    assert(!PyErr_Occurred());
365
4.93M
    if (!set_opcode(instr, specialized_opcode)) {
366
0
        STAT_INC(_PyOpcode_Deopt[specialized_opcode], failure);
367
0
        SPECIALIZATION_FAIL(_PyOpcode_Deopt[specialized_opcode],
368
0
                            SPEC_FAIL_OTHER);
369
0
        return;
370
0
    }
371
4.93M
    STAT_INC(_PyOpcode_Deopt[specialized_opcode], success);
372
4.93M
    set_counter((_Py_BackoffCounter *)instr + 1, adaptive_counter_cooldown());
373
4.93M
}
374
375
static inline void
376
unspecialize(_Py_CODEUNIT *instr)
377
2.86M
{
378
2.86M
    assert(!PyErr_Occurred());
379
2.86M
    uint8_t opcode = FT_ATOMIC_LOAD_UINT8_RELAXED(instr->op.code);
380
2.86M
    uint8_t generic_opcode = _PyOpcode_Deopt[opcode];
381
2.86M
    STAT_INC(generic_opcode, failure);
382
2.86M
    if (!set_opcode(instr, generic_opcode)) {
383
0
        SPECIALIZATION_FAIL(generic_opcode, SPEC_FAIL_OTHER);
384
0
        return;
385
0
    }
386
2.86M
    _Py_BackoffCounter *counter = (_Py_BackoffCounter *)instr + 1;
387
2.86M
    _Py_BackoffCounter cur = load_counter(counter);
388
2.86M
    set_counter(counter, adaptive_counter_backoff(cur));
389
2.86M
}
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.11k
    uint32_t keys_version = _PyDict_GetKeysVersionForCurrentState(
433
6.11k
            _PyInterpreterState_GET(), dict);
434
6.11k
    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.11k
    write_u32(cache->version, keys_version);
442
6.11k
    cache->index = (uint16_t)index;
443
6.11k
    specialize(instr, LOAD_ATTR_MODULE);
444
6.11k
    return 0;
445
6.11k
}
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
3.92M
{
510
3.92M
    if (descriptor == NULL) {
511
1.87M
        return ABSENT;
512
1.87M
    }
513
2.04M
    PyTypeObject *desc_cls = Py_TYPE(descriptor);
514
2.04M
    if (!(desc_cls->tp_flags & Py_TPFLAGS_IMMUTABLETYPE)) {
515
600
        return MUTABLE;
516
600
    }
517
2.04M
    if (desc_cls->tp_descr_set) {
518
215k
        if (desc_cls == &PyMemberDescr_Type) {
519
14.3k
            PyMemberDescrObject *member = (PyMemberDescrObject *)descriptor;
520
14.3k
            struct PyMemberDef *dmem = member->d_member;
521
14.3k
            if (dmem->type == Py_T_OBJECT_EX || dmem->type == _Py_T_OBJECT) {
522
14.0k
                return OBJECT_SLOT;
523
14.0k
            }
524
338
            return OTHER_SLOT;
525
14.3k
        }
526
201k
        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
196k
            return has_getattr ? GETSET_OVERRIDDEN : PROPERTY;
531
196k
        }
532
4.71k
        return OVERRIDING;
533
201k
    }
534
1.83M
    if (desc_cls->tp_descr_get) {
535
623k
        if (desc_cls->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR) {
536
616k
            return METHOD;
537
616k
        }
538
6.43k
        if (Py_IS_TYPE(descriptor, &PyClassMethodDescr_Type)) {
539
2.26k
            return BUILTIN_CLASSMETHOD;
540
2.26k
        }
541
4.16k
        if (Py_IS_TYPE(descriptor, &PyClassMethod_Type)) {
542
3.10k
            return PYTHON_CLASSMETHOD;
543
3.10k
        }
544
1.05k
        return NON_OVERRIDING;
545
4.16k
    }
546
1.20M
    return NON_DESCRIPTOR;
547
1.83M
}
548
549
static bool
550
descriptor_is_class(PyObject *descriptor, PyObject *name)
551
3.96M
{
552
3.96M
    return ((PyUnicode_CompareWithASCIIString(name, "__class__") == 0) &&
553
53.9k
            (descriptor == _PyType_Lookup(&PyBaseObject_Type, name)));
554
3.96M
}
555
556
static DescriptorClassification
557
3.76M
analyze_descriptor_load(PyTypeObject *type, PyObject *name, PyObject **descr, unsigned int *tp_version) {
558
3.76M
    bool has_getattr = false;
559
3.76M
    bool have_ga_version = false;
560
3.76M
    unsigned int ga_version;
561
3.76M
    getattrofunc getattro_slot = type->tp_getattro;
562
3.76M
    if (getattro_slot == PyObject_GenericGetAttr) {
563
        /* Normal attribute lookup; */
564
3.71M
        has_getattr = false;
565
3.71M
    }
566
52.0k
    else if (getattro_slot == _Py_slot_tp_getattr_hook ||
567
50.5k
        getattro_slot == _Py_slot_tp_getattro) {
568
        /* One or both of __getattribute__ or __getattr__ may have been
569
         overridden See typeobject.c for why these functions are special. */
570
50.5k
        PyObject *getattribute = _PyType_LookupRefAndVersion(type,
571
50.5k
                &_Py_ID(__getattribute__), &ga_version);
572
50.5k
        have_ga_version = true;
573
50.5k
        PyInterpreterState *interp = _PyInterpreterState_GET();
574
50.5k
        bool has_custom_getattribute = getattribute != NULL &&
575
50.5k
            getattribute != interp->callable_cache.object__getattribute__;
576
50.5k
        PyObject *getattr = _PyType_Lookup(type, &_Py_ID(__getattr__));
577
50.5k
        has_getattr = getattr != NULL;
578
50.5k
        if (has_custom_getattribute) {
579
0
            if (!has_getattr &&
580
0
                Py_IS_TYPE(getattribute, &PyFunction_Type)) {
581
0
                *descr = getattribute;
582
0
                *tp_version = ga_version;
583
0
                return GETATTRIBUTE_IS_PYTHON_FUNCTION;
584
0
            }
585
            /* Potentially both __getattr__ and __getattribute__ are set.
586
               Too complicated */
587
0
            Py_DECREF(getattribute);
588
0
            *descr = NULL;
589
0
            *tp_version = ga_version;
590
0
            return GETSET_OVERRIDDEN;
591
0
        }
592
        /* Potentially has __getattr__ but no custom __getattribute__.
593
           Fall through to usual descriptor analysis.
594
           Usual attribute lookup should only be allowed at runtime
595
           if we can guarantee that there is no way an exception can be
596
           raised. This means some specializations, e.g. specializing
597
           for property() isn't safe.
598
        */
599
50.5k
        Py_XDECREF(getattribute);
600
50.5k
    }
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.76M
    unsigned int descr_version;
607
3.76M
    PyObject *descriptor = _PyType_LookupRefAndVersion(type, name, &descr_version);
608
3.76M
    *descr = descriptor;
609
3.76M
    *tp_version = have_ga_version ? ga_version : descr_version;
610
3.76M
    if (descriptor_is_class(descriptor, name)) {
611
53.9k
        return DUNDER_CLASS;
612
53.9k
    }
613
3.71M
    return classify_descriptor(descriptor, has_getattr);
614
3.76M
}
615
616
static DescriptorClassification
617
analyze_descriptor_store(PyTypeObject *type, PyObject *name, PyObject **descr, unsigned int *tp_version)
618
196k
{
619
196k
    if (type->tp_setattro != PyObject_GenericSetAttr) {
620
1.00k
        *descr = NULL;
621
1.00k
        return GETSET_OVERRIDDEN;
622
1.00k
    }
623
195k
    PyObject *descriptor = _PyType_LookupRefAndVersion(type, name, tp_version);
624
195k
    *descr = descriptor;
625
195k
    if (descriptor_is_class(descriptor, name)) {
626
1
        return DUNDER_CLASS;
627
1
    }
628
195k
    return classify_descriptor(descriptor, false);
629
195k
}
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
708k
{
637
708k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
638
708k
    PyDictKeysObject *keys = ((PyHeapTypeObject *)type)->ht_cached_keys;
639
708k
    assert(PyUnicode_CheckExact(name));
640
708k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(owner);
641
708k
    Py_ssize_t index = _PyDictKeys_StringLookupSplit(keys, name);
642
708k
    assert (index != DKIX_ERROR);
643
708k
    if (index == DKIX_EMPTY) {
644
229
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_NOT_IN_KEYS);
645
229
        return 0;
646
229
    }
647
708k
    assert(index >= 0);
648
708k
    assert(_PyObject_InlineValues(owner)->valid);
649
708k
    char *value_addr = (char *)&_PyObject_InlineValues(owner)->values[index];
650
708k
    Py_ssize_t offset = value_addr - (char *)owner;
651
708k
    if (offset != (uint16_t)offset) {
652
0
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_OUT_OF_RANGE);
653
0
        return 0;
654
0
    }
655
708k
    cache->index = (uint16_t)offset;
656
708k
    write_u32(cache->version, tp_version);
657
708k
    specialize(instr, values_op);
658
708k
    return 1;
659
708k
}
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
13.7k
{
667
13.7k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
668
669
13.7k
    _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
13.7k
    if (_PyDict_HasSplitTable(dict)) {
676
475
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_SPLIT_DICT);
677
475
        return 0;
678
475
    }
679
13.2k
    Py_ssize_t index = _PyDict_LookupIndex(dict, name);
680
13.2k
    if (index != (uint16_t)index) {
681
3.47k
        SPECIALIZATION_FAIL(base_op,
682
3.47k
                            index == DKIX_EMPTY ?
683
3.47k
                            SPEC_FAIL_ATTR_NOT_IN_DICT :
684
3.47k
                            SPEC_FAIL_OUT_OF_RANGE);
685
3.47k
        return 0;
686
3.47k
    }
687
9.80k
    cache->index = (uint16_t)index;
688
9.80k
    write_u32(cache->version, tp_version);
689
9.80k
    specialize(instr, hint_op);
690
9.80k
    return 1;
691
13.2k
}
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
727k
{
700
727k
    assert(kind == NON_OVERRIDING || kind == NON_DESCRIPTOR || kind == ABSENT ||
701
727k
        kind == BUILTIN_CLASSMETHOD || kind == PYTHON_CLASSMETHOD ||
702
727k
        kind == METHOD);
703
    // No descriptor, or non overriding.
704
727k
    if ((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {
705
3.32k
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);
706
3.32k
        return 0;
707
3.32k
    }
708
724k
    if (type->tp_flags & Py_TPFLAGS_INLINE_VALUES &&
709
723k
        FT_ATOMIC_LOAD_UINT8(_PyObject_InlineValues(owner)->valid) &&
710
710k
        !(base_op == STORE_ATTR && _PyObject_GetManagedDict(owner) != NULL))
711
710k
    {
712
710k
        int res;
713
710k
        Py_BEGIN_CRITICAL_SECTION(owner);
714
710k
        PyDictObject *dict = _PyObject_GetManagedDict(owner);
715
710k
        if (dict == NULL) {
716
            // managed dict, not materialized, inline values valid
717
708k
            res = specialize_dict_access_inline(owner, instr, type, name,
718
708k
                                                tp_version, base_op, values_op);
719
708k
        }
720
1.33k
        else {
721
            // lost race and dict was created, fail specialization
722
1.33k
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OTHER);
723
1.33k
            res = 0;
724
1.33k
        }
725
710k
        Py_END_CRITICAL_SECTION();
726
710k
        return res;
727
710k
    }
728
13.9k
    else {
729
13.9k
        PyDictObject *dict = _PyObject_GetManagedDict(owner);
730
13.9k
        if (dict == NULL || !PyDict_CheckExact(dict)) {
731
238
            SPECIALIZATION_FAIL(base_op, SPEC_FAIL_NO_DICT);
732
238
            return 0;
733
238
        }
734
13.7k
        int res;
735
13.7k
        Py_BEGIN_CRITICAL_SECTION(dict);
736
        // materialized managed dict
737
13.7k
        res = specialize_dict_access_hint(dict, instr, type, name,
738
13.7k
                                          tp_version, base_op, hint_op);
739
13.7k
        Py_END_CRITICAL_SECTION();
740
13.7k
        return res;
741
13.9k
    }
742
724k
}
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.75M
{
760
3.75M
    PyTypeObject *cls = Py_TYPE(obj);
761
3.75M
    if ((cls->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {
762
825k
        return false;
763
825k
    }
764
2.93M
    if (cls->tp_flags & Py_TPFLAGS_INLINE_VALUES) {
765
2.84M
        PyDictKeysObject *keys = ((PyHeapTypeObject *)cls)->ht_cached_keys;
766
2.84M
        Py_ssize_t index =
767
2.84M
            _PyDictKeys_StringLookupAndVersion(keys, name, shared_keys_version);
768
2.84M
        return index >= 0;
769
2.84M
    }
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.75M
{
791
3.75M
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
792
3.75M
    PyTypeObject *type = Py_TYPE(owner);
793
3.75M
    if (tp_version == 0) {
794
797
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
795
797
        return -1;
796
797
    }
797
3.75M
    uint8_t oparg = FT_ATOMIC_LOAD_UINT8_RELAXED(instr->op.arg);
798
3.75M
    switch(kind) {
799
1.13k
        case OVERRIDING:
800
1.13k
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
801
1.13k
            return -1;
802
614k
        case METHOD:
803
614k
        {
804
614k
            if (shadow) {
805
98
                goto try_instance;
806
98
            }
807
614k
            if (oparg & 1) {
808
604k
                if (specialize_attr_loadclassattr(owner, instr, name, descr,
809
604k
                                                  tp_version, kind, true,
810
604k
                                                  shared_keys_version)) {
811
600k
                    return 0;
812
600k
                }
813
4.04k
                else {
814
4.04k
                    return -1;
815
4.04k
                }
816
604k
            }
817
10.0k
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
818
10.0k
            return -1;
819
614k
        }
820
196k
        case PROPERTY:
821
196k
        {
822
196k
            _PyLoadMethodCache *lm_cache = (_PyLoadMethodCache *)(instr + 1);
823
196k
            assert(Py_TYPE(descr) == &PyProperty_Type);
824
196k
            PyObject *fget = ((_PyPropertyObject *)descr)->prop_get;
825
196k
            if (fget == NULL) {
826
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
827
0
                return -1;
828
0
            }
829
196k
            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
196k
            if (!function_check_args(fget, 1, LOAD_ATTR)) {
834
0
                return -1;
835
0
            }
836
196k
            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
196k
            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
196k
            uint32_t func_version = function_get_version(fget, LOAD_ATTR);
852
196k
            if (func_version == 0) {
853
0
                return -1;
854
0
            }
855
196k
            assert(tp_version != 0);
856
196k
            write_u32(lm_cache->type_version, tp_version);
857
196k
            write_u32(lm_cache->keys_version, func_version);
858
            /* borrowed */
859
196k
            write_ptr(lm_cache->descr, fget);
860
196k
            specialize(instr, LOAD_ATTR_PROPERTY);
861
196k
            return 0;
862
196k
        }
863
13.1k
        case OBJECT_SLOT:
864
13.1k
        {
865
13.1k
            PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
866
13.1k
            struct PyMemberDef *dmem = member->d_member;
867
13.1k
            Py_ssize_t offset = dmem->offset;
868
13.1k
            if (!PyObject_TypeCheck(owner, member->d_common.d_type)) {
869
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
870
0
                return -1;
871
0
            }
872
13.1k
            if (dmem->flags & _Py_AFTER_ITEMS) {
873
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_SLOT_AFTER_ITEMS);
874
0
                return -1;
875
0
            }
876
13.1k
            if (dmem->flags & Py_AUDIT_READ) {
877
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_AUDITED_SLOT);
878
0
                return -1;
879
0
            }
880
13.1k
            if (offset != (uint16_t)offset) {
881
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE);
882
0
                return -1;
883
0
            }
884
13.1k
            assert(dmem->type == Py_T_OBJECT_EX || dmem->type == _Py_T_OBJECT);
885
13.1k
            assert(offset > 0);
886
13.1k
            cache->index = (uint16_t)offset;
887
13.1k
            write_u32(cache->version, tp_version);
888
13.1k
            specialize(instr, LOAD_ATTR_SLOT);
889
13.1k
            return 0;
890
13.1k
        }
891
53.9k
        case DUNDER_CLASS:
892
53.9k
        {
893
53.9k
            Py_ssize_t offset = offsetof(PyObject, ob_type);
894
53.9k
            assert(offset == (uint16_t)offset);
895
53.9k
            cache->index = (uint16_t)offset;
896
53.9k
            write_u32(cache->version, tp_version);
897
53.9k
            specialize(instr, LOAD_ATTR_SLOT);
898
53.9k
            return 0;
899
13.1k
        }
900
338
        case OTHER_SLOT:
901
338
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT);
902
338
            return -1;
903
363
        case MUTABLE:
904
363
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
905
363
            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
225
        case PYTHON_CLASSMETHOD:
944
403
        case NON_OVERRIDING:
945
403
            if (shadow) {
946
0
                goto try_instance;
947
0
            }
948
403
            return -1;
949
1.20M
        case NON_DESCRIPTOR:
950
1.20M
            if (shadow) {
951
368k
                goto try_instance;
952
368k
            }
953
833k
            if ((oparg & 1) == 0) {
954
832k
                if (specialize_attr_loadclassattr(owner, instr, name, descr,
955
832k
                                                  tp_version, kind, false,
956
832k
                                                  shared_keys_version)) {
957
832k
                    return 0;
958
832k
                }
959
832k
            }
960
515
            return -1;
961
1.67M
        case ABSENT:
962
1.67M
            if (shadow) {
963
169k
                goto try_instance;
964
169k
            }
965
1.50M
            set_counter((_Py_BackoffCounter*)instr + 1, adaptive_counter_cooldown());
966
1.50M
            return 0;
967
3.75M
    }
968
3.75M
    Py_UNREACHABLE();
969
537k
try_instance:
970
537k
    if (specialize_dict_access(owner, instr, type, kind, name, tp_version,
971
537k
                               LOAD_ATTR, LOAD_ATTR_INSTANCE_VALUE, LOAD_ATTR_WITH_HINT))
972
533k
    {
973
533k
        return 0;
974
533k
    }
975
4.01k
    return -1;
976
537k
}
977
978
static int
979
specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name)
980
3.75M
{
981
    // 0 is not a valid version
982
3.75M
    uint32_t shared_keys_version = 0;
983
3.75M
    bool shadow = instance_has_key(owner, name, &shared_keys_version);
984
3.75M
    PyObject *descr = NULL;
985
3.75M
    unsigned int tp_version = 0;
986
3.75M
    PyTypeObject *type = Py_TYPE(owner);
987
3.75M
    DescriptorClassification kind = analyze_descriptor_load(type, name, &descr, &tp_version);
988
3.75M
    int result = do_specialize_instance_load_attr(owner, instr, name, shadow, shared_keys_version, kind, descr, tp_version);
989
3.75M
    Py_XDECREF(descr);
990
3.75M
    return result;
991
3.75M
}
992
993
Py_NO_INLINE void
994
_Py_Specialize_LoadAttr(_PyStackRef owner_st, _Py_CODEUNIT *instr, PyObject *name)
995
3.77M
{
996
3.77M
    PyObject *owner = PyStackRef_AsPyObjectBorrow(owner_st);
997
998
3.77M
    assert(ENABLE_SPECIALIZATION);
999
3.77M
    assert(_PyOpcode_Caches[LOAD_ATTR] == INLINE_CACHE_ENTRIES_LOAD_ATTR);
1000
3.77M
    PyTypeObject *type = Py_TYPE(owner);
1001
3.77M
    bool fail;
1002
3.77M
    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.77M
    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.76M
    else if (PyType_Check(owner)) {
1013
13.4k
        fail = specialize_class_load_attr(owner, instr, name);
1014
13.4k
    }
1015
3.75M
    else {
1016
3.75M
        fail = specialize_instance_load_attr(owner, instr, name);
1017
3.75M
    }
1018
1019
3.77M
    if (fail) {
1020
32.2k
        unspecialize(instr);
1021
32.2k
    }
1022
3.77M
}
1023
1024
Py_NO_INLINE void
1025
_Py_Specialize_StoreAttr(_PyStackRef owner_st, _Py_CODEUNIT *instr, PyObject *name)
1026
196k
{
1027
196k
    PyObject *owner = PyStackRef_AsPyObjectBorrow(owner_st);
1028
1029
196k
    assert(ENABLE_SPECIALIZATION);
1030
196k
    assert(_PyOpcode_Caches[STORE_ATTR] == INLINE_CACHE_ENTRIES_STORE_ATTR);
1031
196k
    PyObject *descr = NULL;
1032
196k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
1033
196k
    PyTypeObject *type = Py_TYPE(owner);
1034
196k
    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
196k
    if (PyModule_CheckExact(owner)) {
1042
586
        SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OVERRIDDEN);
1043
586
        goto fail;
1044
586
    }
1045
196k
    unsigned int tp_version = 0;
1046
196k
    DescriptorClassification kind = analyze_descriptor_store(type, name, &descr, &tp_version);
1047
196k
    if (tp_version == 0) {
1048
1.03k
        goto fail;
1049
1.03k
    }
1050
196k
    assert(descr != NULL || kind == ABSENT || kind == GETSET_OVERRIDDEN);
1051
195k
    switch(kind) {
1052
962
        case OVERRIDING:
1053
962
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
1054
962
            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.63k
        case NON_DESCRIPTOR:
1110
3.63k
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE);
1111
3.63k
            goto fail;
1112
189k
        case ABSENT:
1113
189k
            if (specialize_dict_access(owner, instr, type, kind, name, tp_version,
1114
189k
                                       STORE_ATTR, STORE_ATTR_INSTANCE_VALUE,
1115
189k
                                       STORE_ATTR_WITH_HINT)) {
1116
184k
                goto success;
1117
184k
            }
1118
195k
    }
1119
11.3k
fail:
1120
11.3k
    Py_XDECREF(descr);
1121
11.3k
    unspecialize(instr);
1122
11.3k
    return;
1123
185k
success:
1124
185k
    Py_XDECREF(descr);
1125
185k
    return;
1126
195k
}
1127
1128
#ifdef Py_STATS
1129
static int
1130
load_attr_fail_kind(DescriptorClassification kind)
1131
{
1132
    switch (kind) {
1133
        case OVERRIDING:
1134
            return SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR;
1135
        case METHOD:
1136
            return SPEC_FAIL_ATTR_METHOD;
1137
        case PROPERTY:
1138
            return SPEC_FAIL_ATTR_PROPERTY;
1139
        case OBJECT_SLOT:
1140
            return SPEC_FAIL_ATTR_OBJECT_SLOT;
1141
        case OTHER_SLOT:
1142
            return SPEC_FAIL_ATTR_NON_OBJECT_SLOT;
1143
        case DUNDER_CLASS:
1144
            return SPEC_FAIL_OTHER;
1145
        case MUTABLE:
1146
            return SPEC_FAIL_ATTR_MUTABLE_CLASS;
1147
        case GETSET_OVERRIDDEN:
1148
        case GETATTRIBUTE_IS_PYTHON_FUNCTION:
1149
            return SPEC_FAIL_OVERRIDDEN;
1150
        case BUILTIN_CLASSMETHOD:
1151
            return SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD;
1152
        case PYTHON_CLASSMETHOD:
1153
            return SPEC_FAIL_ATTR_CLASS_METHOD_OBJ;
1154
        case NON_OVERRIDING:
1155
            return SPEC_FAIL_ATTR_NON_OVERRIDING_DESCRIPTOR;
1156
        case NON_DESCRIPTOR:
1157
            return SPEC_FAIL_ATTR_NOT_DESCRIPTOR;
1158
        case ABSENT:
1159
            return SPEC_FAIL_ATTR_INSTANCE_ATTRIBUTE;
1160
    }
1161
    Py_UNREACHABLE();
1162
}
1163
#endif   // Py_STATS
1164
1165
static int
1166
specialize_class_load_attr(PyObject *owner, _Py_CODEUNIT *instr,
1167
                             PyObject *name)
1168
13.4k
{
1169
13.4k
    assert(PyType_Check(owner));
1170
13.4k
    PyTypeObject *cls = (PyTypeObject *)owner;
1171
13.4k
    _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1);
1172
13.4k
    if (Py_TYPE(cls)->tp_getattro != _Py_type_getattro) {
1173
0
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METACLASS_OVERRIDDEN);
1174
0
        return -1;
1175
0
    }
1176
13.4k
    unsigned int meta_version = 0;
1177
13.4k
    PyObject *metadescriptor = _PyType_LookupRefAndVersion(Py_TYPE(cls), name, &meta_version);
1178
13.4k
    DescriptorClassification metakind = classify_descriptor(metadescriptor, false);
1179
13.4k
    Py_XDECREF(metadescriptor);
1180
13.4k
    switch (metakind) {
1181
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.7k
        case ABSENT:
1187
10.7k
            break;
1188
2.66k
        default:
1189
2.66k
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METACLASS_ATTRIBUTE);
1190
2.66k
            return -1;
1191
13.4k
    }
1192
10.7k
    PyObject *descr = NULL;
1193
10.7k
    DescriptorClassification kind = 0;
1194
10.7k
    unsigned int tp_version = 0;
1195
10.7k
    kind = analyze_descriptor_load(cls, name, &descr, &tp_version);
1196
10.7k
    if (tp_version == 0) {
1197
95
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
1198
95
        Py_XDECREF(descr);
1199
95
        return -1;
1200
95
    }
1201
10.7k
    bool metaclass_check = false;
1202
10.6k
    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.6k
    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.35k
        case NON_DESCRIPTOR:
1227
#ifdef Py_GIL_DISABLED
1228
            maybe_enable_deferred_ref_count(descr);
1229
#endif
1230
4.35k
            write_ptr(cache->descr, descr);
1231
4.35k
            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.90k
            else {
1237
2.90k
                write_u32(cache->type_version, tp_version);
1238
2.90k
                specialize(instr, LOAD_ATTR_CLASS);
1239
2.90k
            }
1240
4.35k
            Py_XDECREF(descr);
1241
4.35k
            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.25k
        default:
1249
6.25k
            SPECIALIZATION_FAIL(LOAD_ATTR, load_attr_fail_kind(kind));
1250
6.25k
            Py_XDECREF(descr);
1251
6.25k
            return -1;
1252
10.6k
    }
1253
10.6k
}
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.43M
{
1265
1.43M
    _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1);
1266
1.43M
    PyTypeObject *owner_cls = Py_TYPE(owner);
1267
1268
1.43M
    assert(descr != NULL);
1269
1.43M
    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.43M
    unsigned long tp_flags = PyType_GetFlags(owner_cls);
1279
1.43M
    if (tp_flags & Py_TPFLAGS_INLINE_VALUES) {
1280
1.41M
        #ifndef Py_GIL_DISABLED
1281
1.41M
        assert(_PyDictKeys_StringLookup(
1282
1.41M
                   ((PyHeapTypeObject *)owner_cls)->ht_cached_keys, name) < 0);
1283
1.41M
        #endif
1284
1.41M
        if (shared_keys_version == 0) {
1285
0
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
1286
0
            return 0;
1287
0
        }
1288
1.41M
        write_u32(cache->keys_version, shared_keys_version);
1289
1.41M
        specialize(instr, is_method ? LOAD_ATTR_METHOD_WITH_VALUES : LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES);
1290
1.41M
    }
1291
27.0k
    else {
1292
27.0k
        Py_ssize_t dictoffset;
1293
27.0k
        if (tp_flags & Py_TPFLAGS_MANAGED_DICT) {
1294
746
            dictoffset = MANAGED_DICT_OFFSET;
1295
746
        }
1296
26.2k
        else {
1297
26.2k
            dictoffset = owner_cls->tp_dictoffset;
1298
26.2k
            if (dictoffset < 0 || dictoffset > INT16_MAX + MANAGED_DICT_OFFSET) {
1299
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE);
1300
0
                return 0;
1301
0
            }
1302
26.2k
        }
1303
27.0k
        if (dictoffset == 0) {
1304
22.2k
            specialize(instr, is_method ? LOAD_ATTR_METHOD_NO_DICT : LOAD_ATTR_NONDESCRIPTOR_NO_DICT);
1305
22.2k
        }
1306
4.77k
        else if (is_method) {
1307
4.27k
            PyObject **addr = (PyObject **)((char *)owner + dictoffset);
1308
4.27k
            PyObject *dict = FT_ATOMIC_LOAD_PTR_ACQUIRE(*addr);
1309
4.27k
            if (dict) {
1310
4.04k
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);
1311
4.04k
                return 0;
1312
4.04k
            }
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
231
            dictoffset -= MANAGED_DICT_OFFSET;
1317
231
            assert(((uint16_t)dictoffset) == dictoffset);
1318
231
            cache->dict_offset = (uint16_t)dictoffset;
1319
231
            specialize(instr, LOAD_ATTR_METHOD_LAZY_DICT);
1320
231
        }
1321
492
        else {
1322
492
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE);
1323
492
            return 0;
1324
492
        }
1325
27.0k
    }
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.43M
    write_u32(cache->type_version, tp_version);
1341
1.43M
    write_ptr(cache->descr, descr);
1342
1.43M
    return 1;
1343
1.43M
}
1344
1345
static void
1346
specialize_load_global_lock_held(
1347
    PyObject *globals, PyObject *builtins,
1348
    _Py_CODEUNIT *instr, PyObject *name)
1349
37.3k
{
1350
37.3k
    assert(ENABLE_SPECIALIZATION);
1351
37.3k
    assert(_PyOpcode_Caches[LOAD_GLOBAL] == INLINE_CACHE_ENTRIES_LOAD_GLOBAL);
1352
    /* Use inline cache */
1353
37.3k
    _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)(instr + 1);
1354
37.3k
    assert(PyUnicode_CheckExact(name));
1355
37.3k
    if (!PyDict_CheckExact(globals)) {
1356
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_DICT);
1357
0
        goto fail;
1358
0
    }
1359
37.3k
    PyDictKeysObject * globals_keys = ((PyDictObject *)globals)->ma_keys;
1360
37.3k
    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.3k
    PyObject *value;
1365
37.3k
    Py_ssize_t index = _PyDict_LookupIndexAndValue((PyDictObject *)globals, name, &value);
1366
37.3k
    if (index == DKIX_ERROR) {
1367
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_EXPECTED_ERROR);
1368
0
        goto fail;
1369
0
    }
1370
37.3k
    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.3k
    PyInterpreterState *interp = _PyInterpreterState_GET();
1375
37.3k
    if (index != DKIX_EMPTY) {
1376
21.9k
        if (index != (uint16_t)index) {
1377
0
            SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1378
0
            goto fail;
1379
0
        }
1380
21.9k
        uint32_t keys_version = _PyDict_GetKeysVersionForCurrentState(
1381
21.9k
                interp, (PyDictObject*) globals);
1382
21.9k
        if (keys_version == 0) {
1383
0
            SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
1384
0
            goto fail;
1385
0
        }
1386
21.9k
        if (keys_version != (uint16_t)keys_version) {
1387
0
            SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1388
0
            goto fail;
1389
0
        }
1390
#ifdef Py_GIL_DISABLED
1391
        maybe_enable_deferred_ref_count(value);
1392
#endif
1393
21.9k
        cache->index = (uint16_t)index;
1394
21.9k
        cache->module_keys_version = (uint16_t)keys_version;
1395
21.9k
        specialize(instr, LOAD_GLOBAL_MODULE);
1396
21.9k
        return;
1397
21.9k
    }
1398
15.3k
    if (!PyDict_CheckExact(builtins)) {
1399
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_DICT);
1400
0
        goto fail;
1401
0
    }
1402
15.3k
    PyDictKeysObject * builtin_keys = ((PyDictObject *)builtins)->ma_keys;
1403
15.3k
    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.3k
    index = _PyDictKeys_StringLookup(builtin_keys, name);
1408
15.3k
    if (index == DKIX_ERROR) {
1409
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_EXPECTED_ERROR);
1410
0
        goto fail;
1411
0
    }
1412
15.3k
    if (index != (uint16_t)index) {
1413
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1414
0
        goto fail;
1415
0
    }
1416
15.3k
    uint32_t globals_version = _PyDict_GetKeysVersionForCurrentState(
1417
15.3k
            interp, (PyDictObject*) globals);
1418
15.3k
    if (globals_version == 0) {
1419
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
1420
0
        goto fail;
1421
0
    }
1422
15.3k
    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.3k
    uint32_t builtins_version = _PyDict_GetKeysVersionForCurrentState(
1427
15.3k
            interp, (PyDictObject*) builtins);
1428
15.3k
    if (builtins_version == 0) {
1429
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
1430
0
        goto fail;
1431
0
    }
1432
15.3k
    if (builtins_version > UINT16_MAX) {
1433
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1434
0
        goto fail;
1435
0
    }
1436
15.3k
    cache->index = (uint16_t)index;
1437
15.3k
    cache->module_keys_version = (uint16_t)globals_version;
1438
15.3k
    cache->builtin_keys_version = (uint16_t)builtins_version;
1439
15.3k
    specialize(instr, LOAD_GLOBAL_BUILTIN);
1440
15.3k
    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.3k
{
1450
37.3k
    Py_BEGIN_CRITICAL_SECTION2(globals, builtins);
1451
37.3k
    specialize_load_global_lock_held(globals, builtins, instr, name);
1452
37.3k
    Py_END_CRITICAL_SECTION2();
1453
37.3k
}
1454
1455
static int
1456
247k
function_kind(PyCodeObject *code) {
1457
247k
    int flags = code->co_flags;
1458
247k
    if ((flags & (CO_VARKEYWORDS | CO_VARARGS)) || code->co_kwonlyargcount) {
1459
5.20k
        return SPEC_FAIL_CODE_COMPLEX_PARAMETERS;
1460
5.20k
    }
1461
242k
    if ((flags & CO_OPTIMIZED) == 0) {
1462
0
        return SPEC_FAIL_CODE_NOT_OPTIMIZED;
1463
0
    }
1464
242k
    return SIMPLE_FUNCTION;
1465
242k
}
1466
1467
/* Returning false indicates a failure. */
1468
static bool
1469
function_check_args(PyObject *o, int expected_argcount, int opcode)
1470
196k
{
1471
196k
    assert(Py_IS_TYPE(o, &PyFunction_Type));
1472
196k
    PyFunctionObject *func = (PyFunctionObject *)o;
1473
196k
    PyCodeObject *fcode = (PyCodeObject *)func->func_code;
1474
196k
    int kind = function_kind(fcode);
1475
196k
    if (kind != SIMPLE_FUNCTION) {
1476
0
        SPECIALIZATION_FAIL(opcode, kind);
1477
0
        return false;
1478
0
    }
1479
196k
    if (fcode->co_argcount != expected_argcount) {
1480
0
        SPECIALIZATION_FAIL(opcode, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1481
0
        return false;
1482
0
    }
1483
196k
    return true;
1484
196k
}
1485
1486
/* Returning 0 indicates a failure. */
1487
static uint32_t
1488
function_get_version(PyObject *o, int opcode)
1489
196k
{
1490
196k
    assert(Py_IS_TYPE(o, &PyFunction_Type));
1491
196k
    PyFunctionObject *func = (PyFunctionObject *)o;
1492
196k
    uint32_t version = _PyFunction_GetVersionForCurrentState(func);
1493
196k
    if (!_PyFunction_IsVersionValid(version)) {
1494
0
        SPECIALIZATION_FAIL(opcode, SPEC_FAIL_OUT_OF_VERSIONS);
1495
0
        return 0;
1496
0
    }
1497
196k
    return version;
1498
196k
}
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.1k
{
1568
18.1k
    PyObject *container = PyStackRef_AsPyObjectBorrow(container_st);
1569
18.1k
    PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st);
1570
1571
18.1k
    assert(ENABLE_SPECIALIZATION);
1572
18.1k
    PyTypeObject *container_type = Py_TYPE(container);
1573
18.1k
    if (container_type == &PyList_Type) {
1574
902
        if (PyLong_CheckExact(sub)) {
1575
879
            if (_PyLong_IsNonNegativeCompact((PyLongObject *)sub)
1576
272
                && ((PyLongObject *)sub)->long_value.ob_digit[0] < (size_t)PyList_GET_SIZE(container))
1577
272
            {
1578
272
                specialize(instr, STORE_SUBSCR_LIST_INT);
1579
272
                return;
1580
272
            }
1581
607
            else {
1582
607
                SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);
1583
607
                unspecialize(instr);
1584
607
                return;
1585
607
            }
1586
879
        }
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
902
    }
1598
17.2k
    if (container_type->tp_as_mapping != NULL &&
1599
17.2k
        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.3k
    SPECIALIZATION_FAIL(STORE_SUBSCR, store_subscr_fail_kind(container, sub));
1605
15.3k
    unspecialize(instr);
1606
15.3k
}
1607
1608
/* Returns a strong reference. */
1609
static PyObject *
1610
get_init_for_simple_managed_python_class(PyTypeObject *tp, unsigned int *tp_version)
1611
873
{
1612
873
    assert(tp->tp_new == PyBaseObject_Type.tp_new);
1613
873
    if (tp->tp_alloc != PyType_GenericAlloc) {
1614
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OVERRIDDEN);
1615
0
        return NULL;
1616
0
    }
1617
873
    unsigned long tp_flags = PyType_GetFlags(tp);
1618
873
    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
873
    PyObject *init = _PyType_LookupRefAndVersion(tp, &_Py_ID(__init__), tp_version);
1624
873
    if (init == NULL || !PyFunction_Check(init)) {
1625
193
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_INIT_NOT_PYTHON);
1626
193
        Py_XDECREF(init);
1627
193
        return NULL;
1628
193
    }
1629
680
    int kind = function_kind((PyCodeObject *)PyFunction_GET_CODE(init));
1630
680
    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
616
    return init;
1636
680
}
1637
1638
static int
1639
specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
1640
4.01k
{
1641
4.01k
    assert(PyType_Check(callable));
1642
4.01k
    PyTypeObject *tp = _PyType_CAST(callable);
1643
4.01k
    if (tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) {
1644
2.67k
        int oparg = instr->op.arg;
1645
2.67k
        if (nargs == 1 && oparg == 1) {
1646
1.76k
            if (tp == &PyUnicode_Type) {
1647
157
                specialize(instr, CALL_STR_1);
1648
157
                return 0;
1649
157
            }
1650
1.60k
            else if (tp == &PyType_Type) {
1651
319
                specialize(instr, CALL_TYPE_1);
1652
319
                return 0;
1653
319
            }
1654
1.28k
            else if (tp == &PyTuple_Type) {
1655
127
                specialize(instr, CALL_TUPLE_1);
1656
127
                return 0;
1657
127
            }
1658
1.76k
        }
1659
2.06k
        if (tp->tp_vectorcall != NULL) {
1660
1.41k
            specialize(instr, CALL_BUILTIN_CLASS);
1661
1.41k
            return 0;
1662
1.41k
        }
1663
650
        goto generic;
1664
2.06k
    }
1665
1.34k
    if (Py_TYPE(tp) != &PyType_Type) {
1666
90
        goto generic;
1667
90
    }
1668
1.25k
    if (tp->tp_new == PyBaseObject_Type.tp_new) {
1669
873
        unsigned int tp_version = 0;
1670
873
        PyObject *init = get_init_for_simple_managed_python_class(tp, &tp_version);
1671
873
        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
866
        if (init != NULL && _PyType_CacheInitForSpecialization(
1677
609
                                (PyHeapTypeObject *)tp, init, tp_version)) {
1678
609
            _PyCallCache *cache = (_PyCallCache *)(instr + 1);
1679
609
            write_u32(cache->func_version, tp_version);
1680
609
            specialize(instr, CALL_ALLOC_AND_ENTER_INIT);
1681
609
            Py_DECREF(init);
1682
609
            return 0;
1683
609
        }
1684
257
        Py_XDECREF(init);
1685
257
    }
1686
1.38k
generic:
1687
1.38k
    specialize(instr, CALL_NON_PY_GENERAL);
1688
1.38k
    return 0;
1689
1.25k
}
1690
1691
static int
1692
specialize_method_descriptor(PyMethodDescrObject *descr, PyObject *self_or_null,
1693
                             _Py_CODEUNIT *instr, int nargs)
1694
451k
{
1695
451k
    switch (descr->d_method->ml_flags &
1696
451k
        (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
1697
451k
        METH_KEYWORDS | METH_METHOD)) {
1698
37.6k
        case METH_NOARGS: {
1699
37.6k
            if (nargs != 1) {
1700
0
                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1701
0
                return -1;
1702
0
            }
1703
37.6k
            specialize(instr, CALL_METHOD_DESCRIPTOR_NOARGS);
1704
37.6k
            return 0;
1705
37.6k
        }
1706
343k
        case METH_O: {
1707
343k
            if (nargs != 2) {
1708
0
                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1709
0
                return -1;
1710
0
            }
1711
343k
            PyInterpreterState *interp = _PyInterpreterState_GET();
1712
343k
            PyObject *list_append = interp->callable_cache.list_append;
1713
343k
            int oparg = instr->op.arg;
1714
343k
            if ((PyObject *)descr == list_append && oparg == 1) {
1715
337k
                assert(self_or_null != NULL);
1716
337k
                if (PyList_CheckExact(self_or_null)) {
1717
1.08k
                    specialize(instr, CALL_LIST_APPEND);
1718
1.08k
                    return 0;
1719
1.08k
                }
1720
337k
            }
1721
342k
            specialize(instr, CALL_METHOD_DESCRIPTOR_O);
1722
342k
            return 0;
1723
343k
        }
1724
3.70k
        case METH_FASTCALL: {
1725
3.70k
            specialize(instr, CALL_METHOD_DESCRIPTOR_FAST);
1726
3.70k
            return 0;
1727
343k
        }
1728
66.0k
        case METH_FASTCALL | METH_KEYWORDS: {
1729
66.0k
            specialize(instr, CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS);
1730
66.0k
            return 0;
1731
343k
        }
1732
451k
    }
1733
470
    specialize(instr, CALL_NON_PY_GENERAL);
1734
470
    return 0;
1735
451k
}
1736
1737
static int
1738
specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
1739
                   bool bound_method)
1740
46.4k
{
1741
46.4k
    _PyCallCache *cache = (_PyCallCache *)(instr + 1);
1742
46.4k
    PyCodeObject *code = (PyCodeObject *)func->func_code;
1743
46.4k
    int kind = function_kind(code);
1744
    /* Don't specialize if PEP 523 is active */
1745
46.4k
    if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) {
1746
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
1747
0
        return -1;
1748
0
    }
1749
46.4k
    if (func->vectorcall != _PyFunction_Vectorcall) {
1750
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_VECTORCALL);
1751
0
        return -1;
1752
0
    }
1753
46.4k
    int argcount = -1;
1754
46.4k
    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.4k
    if (kind == SIMPLE_FUNCTION) {
1759
44.9k
        argcount = code->co_argcount;
1760
44.9k
    }
1761
46.4k
    int version = _PyFunction_GetVersionForCurrentState(func);
1762
46.4k
    if (!_PyFunction_IsVersionValid(version)) {
1763
62
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
1764
62
        return -1;
1765
62
    }
1766
46.3k
    write_u32(cache->func_version, version);
1767
46.3k
    uint8_t opcode;
1768
46.3k
    if (argcount == nargs + bound_method) {
1769
44.4k
        opcode =
1770
44.4k
            bound_method ? CALL_BOUND_METHOD_EXACT_ARGS : CALL_PY_EXACT_ARGS;
1771
44.4k
    }
1772
1.92k
    else {
1773
1.92k
        opcode = bound_method ? CALL_BOUND_METHOD_GENERAL : CALL_PY_GENERAL;
1774
1.92k
    }
1775
46.3k
    specialize(instr, opcode);
1776
46.3k
    return 0;
1777
46.4k
}
1778
1779
1780
static int
1781
specialize_py_call_kw(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
1782
                   bool bound_method)
1783
3.80k
{
1784
3.80k
    _PyCallCache *cache = (_PyCallCache *)(instr + 1);
1785
3.80k
    PyCodeObject *code = (PyCodeObject *)func->func_code;
1786
3.80k
    int kind = function_kind(code);
1787
    /* Don't specialize if PEP 523 is active */
1788
3.80k
    if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) {
1789
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
1790
0
        return -1;
1791
0
    }
1792
3.80k
    if (func->vectorcall != _PyFunction_Vectorcall) {
1793
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_VECTORCALL);
1794
0
        return -1;
1795
0
    }
1796
3.80k
    if (kind == SPEC_FAIL_CODE_NOT_OPTIMIZED) {
1797
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CODE_NOT_OPTIMIZED);
1798
0
        return -1;
1799
0
    }
1800
3.80k
    int version = _PyFunction_GetVersionForCurrentState(func);
1801
3.80k
    if (!_PyFunction_IsVersionValid(version)) {
1802
77
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
1803
77
        return -1;
1804
77
    }
1805
3.72k
    write_u32(cache->func_version, version);
1806
3.72k
    specialize(instr, bound_method ? CALL_KW_BOUND_METHOD : CALL_KW_PY);
1807
3.72k
    return 0;
1808
3.80k
}
1809
1810
static int
1811
specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
1812
363k
{
1813
363k
    if (PyCFunction_GET_FUNCTION(callable) == NULL) {
1814
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OTHER);
1815
0
        return 1;
1816
0
    }
1817
363k
    switch (PyCFunction_GET_FLAGS(callable) &
1818
363k
        (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
1819
363k
        METH_KEYWORDS | METH_METHOD)) {
1820
37.6k
        case METH_O: {
1821
37.6k
            if (nargs != 1) {
1822
0
                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1823
0
                return 1;
1824
0
            }
1825
            /* len(o) */
1826
37.6k
            PyInterpreterState *interp = _PyInterpreterState_GET();
1827
37.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
35.5k
            specialize(instr, CALL_BUILTIN_O);
1832
35.5k
            return 0;
1833
37.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
303k
        case METH_FASTCALL | METH_KEYWORDS: {
1847
303k
            specialize(instr, CALL_BUILTIN_FAST_WITH_KEYWORDS);
1848
303k
            return 0;
1849
21.5k
        }
1850
606
        default:
1851
606
            specialize(instr, CALL_NON_PY_GENERAL);
1852
606
            return 0;
1853
363k
    }
1854
363k
}
1855
1856
Py_NO_INLINE void
1857
_Py_Specialize_Call(_PyStackRef callable_st, _PyStackRef self_or_null_st, _Py_CODEUNIT *instr, int nargs)
1858
878k
{
1859
878k
    PyObject *callable = PyStackRef_AsPyObjectBorrow(callable_st);
1860
1861
878k
    assert(ENABLE_SPECIALIZATION);
1862
878k
    assert(_PyOpcode_Caches[CALL] == INLINE_CACHE_ENTRIES_CALL);
1863
878k
    assert(_Py_OPCODE(*instr) != INSTRUMENTED_CALL);
1864
878k
    int fail;
1865
878k
    if (PyCFunction_CheckExact(callable)) {
1866
363k
        fail = specialize_c_call(callable, instr, nargs);
1867
363k
    }
1868
514k
    else if (PyFunction_Check(callable)) {
1869
39.5k
        fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs, false);
1870
39.5k
    }
1871
475k
    else if (PyType_Check(callable)) {
1872
4.01k
        fail = specialize_class_call(callable, instr, nargs);
1873
4.01k
    }
1874
470k
    else if (Py_IS_TYPE(callable, &PyMethodDescr_Type)) {
1875
451k
        PyObject *self_or_null = PyStackRef_AsPyObjectBorrow(self_or_null_st);
1876
451k
        fail = specialize_method_descriptor((PyMethodDescrObject *)callable,
1877
451k
                                            self_or_null, instr, nargs);
1878
451k
    }
1879
19.2k
    else if (PyMethod_Check(callable)) {
1880
6.86k
        PyObject *func = ((PyMethodObject *)callable)->im_func;
1881
6.86k
        if (PyFunction_Check(func)) {
1882
6.85k
            fail = specialize_py_call((PyFunctionObject *)func, instr, nargs, true);
1883
6.85k
        }
1884
4
        else {
1885
4
            SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_BOUND_METHOD);
1886
4
            fail = -1;
1887
4
        }
1888
6.86k
    }
1889
12.3k
    else {
1890
12.3k
        specialize(instr, CALL_NON_PY_GENERAL);
1891
12.3k
        fail = 0;
1892
12.3k
    }
1893
878k
    if (fail) {
1894
73
        unspecialize(instr);
1895
73
    }
1896
878k
}
1897
1898
Py_NO_INLINE void
1899
_Py_Specialize_CallKw(_PyStackRef callable_st, _Py_CODEUNIT *instr, int nargs)
1900
4.46k
{
1901
4.46k
    PyObject *callable = PyStackRef_AsPyObjectBorrow(callable_st);
1902
1903
4.46k
    assert(ENABLE_SPECIALIZATION);
1904
4.46k
    assert(_PyOpcode_Caches[CALL_KW] == INLINE_CACHE_ENTRIES_CALL_KW);
1905
4.46k
    assert(_Py_OPCODE(*instr) != INSTRUMENTED_CALL_KW);
1906
4.46k
    int fail;
1907
4.46k
    if (PyFunction_Check(callable)) {
1908
717
        fail = specialize_py_call_kw((PyFunctionObject *)callable, instr, nargs, false);
1909
717
    }
1910
3.74k
    else if (PyMethod_Check(callable)) {
1911
3.08k
        PyObject *func = ((PyMethodObject *)callable)->im_func;
1912
3.08k
        if (PyFunction_Check(func)) {
1913
3.08k
            fail = specialize_py_call_kw((PyFunctionObject *)func, instr, nargs, true);
1914
3.08k
        }
1915
0
        else {
1916
0
            SPECIALIZATION_FAIL(CALL_KW, SPEC_FAIL_CALL_BOUND_METHOD);
1917
0
            fail = -1;
1918
0
        }
1919
3.08k
    }
1920
658
    else {
1921
658
        specialize(instr, CALL_KW_NON_PY);
1922
658
        fail = 0;
1923
658
    }
1924
4.46k
    if (fail) {
1925
77
        unspecialize(instr);
1926
77
    }
1927
4.46k
}
1928
1929
#ifdef Py_STATS
1930
static int
1931
binary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs)
1932
{
1933
    switch (oparg) {
1934
        case NB_ADD:
1935
        case NB_INPLACE_ADD:
1936
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1937
                return SPEC_FAIL_BINARY_OP_ADD_DIFFERENT_TYPES;
1938
            }
1939
            return SPEC_FAIL_BINARY_OP_ADD_OTHER;
1940
        case NB_AND:
1941
        case NB_INPLACE_AND:
1942
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1943
                return SPEC_FAIL_BINARY_OP_AND_DIFFERENT_TYPES;
1944
            }
1945
            if (PyLong_CheckExact(lhs)) {
1946
                return SPEC_FAIL_BINARY_OP_AND_INT;
1947
            }
1948
            return SPEC_FAIL_BINARY_OP_AND_OTHER;
1949
        case NB_FLOOR_DIVIDE:
1950
        case NB_INPLACE_FLOOR_DIVIDE:
1951
            return SPEC_FAIL_BINARY_OP_FLOOR_DIVIDE;
1952
        case NB_LSHIFT:
1953
        case NB_INPLACE_LSHIFT:
1954
            return SPEC_FAIL_BINARY_OP_LSHIFT;
1955
        case NB_MATRIX_MULTIPLY:
1956
        case NB_INPLACE_MATRIX_MULTIPLY:
1957
            return SPEC_FAIL_BINARY_OP_MATRIX_MULTIPLY;
1958
        case NB_MULTIPLY:
1959
        case NB_INPLACE_MULTIPLY:
1960
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1961
                return SPEC_FAIL_BINARY_OP_MULTIPLY_DIFFERENT_TYPES;
1962
            }
1963
            return SPEC_FAIL_BINARY_OP_MULTIPLY_OTHER;
1964
        case NB_OR:
1965
        case NB_INPLACE_OR:
1966
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1967
                return SPEC_FAIL_BINARY_OP_OR_DIFFERENT_TYPES;
1968
            }
1969
            if (PyLong_CheckExact(lhs)) {
1970
                return SPEC_FAIL_BINARY_OP_OR_INT;
1971
            }
1972
            return SPEC_FAIL_BINARY_OP_OR;
1973
        case NB_POWER:
1974
        case NB_INPLACE_POWER:
1975
            return SPEC_FAIL_BINARY_OP_POWER;
1976
        case NB_REMAINDER:
1977
        case NB_INPLACE_REMAINDER:
1978
            return SPEC_FAIL_BINARY_OP_REMAINDER;
1979
        case NB_RSHIFT:
1980
        case NB_INPLACE_RSHIFT:
1981
            return SPEC_FAIL_BINARY_OP_RSHIFT;
1982
        case NB_SUBTRACT:
1983
        case NB_INPLACE_SUBTRACT:
1984
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1985
                return SPEC_FAIL_BINARY_OP_SUBTRACT_DIFFERENT_TYPES;
1986
            }
1987
            return SPEC_FAIL_BINARY_OP_SUBTRACT_OTHER;
1988
        case NB_TRUE_DIVIDE:
1989
        case NB_INPLACE_TRUE_DIVIDE:
1990
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1991
                return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_DIFFERENT_TYPES;
1992
            }
1993
            if (PyFloat_CheckExact(lhs)) {
1994
                return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_FLOAT;
1995
            }
1996
            return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_OTHER;
1997
        case NB_XOR:
1998
        case NB_INPLACE_XOR:
1999
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2000
                return SPEC_FAIL_BINARY_OP_XOR_DIFFERENT_TYPES;
2001
            }
2002
            if (PyLong_CheckExact(lhs)) {
2003
                return SPEC_FAIL_BINARY_OP_XOR_INT;
2004
            }
2005
            return SPEC_FAIL_BINARY_OP_XOR;
2006
        case NB_SUBSCR:
2007
            if (PyList_CheckExact(lhs)) {
2008
                if (PyLong_CheckExact(rhs) && !_PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
2009
                    return SPEC_FAIL_OUT_OF_RANGE;
2010
                }
2011
                if (PySlice_Check(rhs)) {
2012
                    return SPEC_FAIL_BINARY_OP_SUBSCR_LIST_SLICE;
2013
                }
2014
            }
2015
            if (PyTuple_CheckExact(lhs)) {
2016
                if (PyLong_CheckExact(rhs) && !_PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
2017
                    return SPEC_FAIL_OUT_OF_RANGE;
2018
                }
2019
                if (PySlice_Check(rhs)) {
2020
                    return SPEC_FAIL_BINARY_OP_SUBSCR_TUPLE_SLICE;
2021
                }
2022
            }
2023
            if (PyUnicode_CheckExact(lhs)) {
2024
                if (PyLong_CheckExact(rhs) && !_PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
2025
                    return SPEC_FAIL_OUT_OF_RANGE;
2026
                }
2027
                if (PySlice_Check(rhs)) {
2028
                    return SPEC_FAIL_BINARY_OP_SUBSCR_STRING_SLICE;
2029
                }
2030
            }
2031
            unsigned int tp_version;
2032
            PyTypeObject *container_type = Py_TYPE(lhs);
2033
            PyObject *descriptor = _PyType_LookupRefAndVersion(container_type, &_Py_ID(__getitem__), &tp_version);
2034
            if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {
2035
                if (!(container_type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
2036
                    Py_DECREF(descriptor);
2037
                    return SPEC_FAIL_BINARY_OP_SUBSCR_NOT_HEAP_TYPE;
2038
                }
2039
                PyFunctionObject *func = (PyFunctionObject *)descriptor;
2040
                PyCodeObject *fcode = (PyCodeObject *)func->func_code;
2041
                int kind = function_kind(fcode);
2042
                if (kind != SIMPLE_FUNCTION) {
2043
                    Py_DECREF(descriptor);
2044
                    return kind;
2045
                }
2046
                if (fcode->co_argcount != 2) {
2047
                    Py_DECREF(descriptor);
2048
                    return SPEC_FAIL_WRONG_NUMBER_ARGUMENTS;
2049
                }
2050
2051
                if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) {
2052
                    /* Don't specialize if PEP 523 is active */
2053
                    Py_DECREF(descriptor);
2054
                    return SPEC_FAIL_OTHER;
2055
                }
2056
            }
2057
            Py_XDECREF(descriptor);
2058
2059
            if (PyObject_TypeCheck(lhs, &PyDictProxy_Type)) {
2060
                return SPEC_FAIL_BINARY_OP_SUBSCR_MAPPINGPROXY;
2061
            }
2062
2063
            if (PyObject_TypeCheck(lhs, &PyBytes_Type)) {
2064
                return SPEC_FAIL_BINARY_OP_SUBSCR_BYTES;
2065
            }
2066
2067
            if (PyObject_TypeCheck(lhs, &PyRange_Type)) {
2068
                return SPEC_FAIL_BINARY_OP_SUBSCR_RANGE;
2069
            }
2070
2071
            if (strcmp(container_type->tp_name, "array.array") == 0) {
2072
                return SPEC_FAIL_BINARY_OP_SUBSCR_ARRAY;
2073
            }
2074
2075
            if (strcmp(container_type->tp_name, "re.Match") == 0) {
2076
                return SPEC_FAIL_BINARY_OP_SUBSCR_RE_MATCH;
2077
            }
2078
2079
            if (strcmp(container_type->tp_name, "collections.deque") == 0) {
2080
                return SPEC_FAIL_BINARY_OP_SUBSCR_DEQUE;
2081
            }
2082
2083
            if (strcmp(_PyType_Name(container_type), "EnumDict") == 0) {
2084
                return SPEC_FAIL_BINARY_OP_SUBSCR_ENUMDICT;
2085
            }
2086
2087
            if (strcmp(container_type->tp_name, "StackSummary") == 0) {
2088
                return SPEC_FAIL_BINARY_OP_SUBSCR_STACKSUMMARY;
2089
            }
2090
2091
            if (strcmp(container_type->tp_name, "collections.defaultdict") == 0) {
2092
                return SPEC_FAIL_BINARY_OP_SUBSCR_DEFAULTDICT;
2093
            }
2094
2095
            if (strcmp(container_type->tp_name, "Counter") == 0) {
2096
                return SPEC_FAIL_BINARY_OP_SUBSCR_COUNTER;
2097
            }
2098
2099
            if (strcmp(container_type->tp_name, "collections.OrderedDict") == 0) {
2100
                return SPEC_FAIL_BINARY_OP_SUBSCR_ORDEREDDICT;
2101
            }
2102
2103
            if (strcmp(container_type->tp_name, "time.struct_time") == 0) {
2104
                return SPEC_FAIL_BINARY_OP_SUBSCR_STRUCTTIME;
2105
            }
2106
2107
            if (PySlice_Check(rhs)) {
2108
                return SPEC_FAIL_BINARY_OP_SUBSCR_OTHER_SLICE;
2109
            }
2110
            return SPEC_FAIL_BINARY_OP_SUBSCR;
2111
    }
2112
    Py_UNREACHABLE();
2113
}
2114
#endif
2115
2116
/** Binary Op Specialization Extensions */
2117
2118
/* long-long */
2119
2120
static inline int
2121
is_compactlong(PyObject *v)
2122
154M
{
2123
154M
    return PyLong_CheckExact(v) &&
2124
154M
           _PyLong_IsCompact((PyLongObject *)v);
2125
154M
}
2126
2127
#define SEQ_INT_MULTIPLY_ACTION(NAME, REPEAT, SEQ, COUNT) \
2128
    static PyObject * \
2129
    (NAME)(PyObject *lhs, PyObject *rhs) \
2130
534k
    { \
2131
534k
        Py_ssize_t count = PyLong_AsSsize_t(COUNT); \
2132
534k
        if (count == -1 && PyErr_Occurred()) { \
2133
0
            return NULL; \
2134
0
        } \
2135
534k
        return REPEAT(SEQ, count); \
2136
534k
    }
2137
344k
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
99.1k
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
77.1M
{
2148
77.1M
    return (is_compactlong(lhs) && is_compactlong(rhs));
2149
77.1M
}
2150
2151
#define BITWISE_LONGS_ACTION(NAME, OP) \
2152
    static PyObject * \
2153
    (NAME)(PyObject *lhs, PyObject *rhs) \
2154
77.1M
    { \
2155
77.1M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2156
77.1M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2157
77.1M
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2158
77.1M
    }
specialize.c:compactlongs_or
Line
Count
Source
2154
1.50M
    { \
2155
1.50M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2156
1.50M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2157
1.50M
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2158
1.50M
    }
specialize.c:compactlongs_and
Line
Count
Source
2154
75.6M
    { \
2155
75.6M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2156
75.6M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2157
75.6M
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2158
75.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.07M
{
2169
1.07M
    return (
2170
1.07M
        PyFloat_CheckExact(lhs) &&
2171
1.05M
        !isnan(PyFloat_AS_DOUBLE(lhs)) &&
2172
1.07M
        PyLong_CheckExact(rhs) &&
2173
1.05M
        _PyLong_IsCompact((PyLongObject *)rhs)
2174
1.07M
    );
2175
1.07M
}
2176
2177
static inline int
2178
nonzero_float_compactlong_guard(PyObject *lhs, PyObject *rhs)
2179
452k
{
2180
452k
    return (
2181
452k
        float_compactlong_guard(lhs, rhs) && !_PyLong_IsZero((PyLongObject*)rhs)
2182
452k
    );
2183
452k
}
2184
2185
#define FLOAT_LONG_ACTION(NAME, OP) \
2186
    static PyObject * \
2187
    (NAME)(PyObject *lhs, PyObject *rhs) \
2188
1.05M
    { \
2189
1.05M
        double lhs_val = PyFloat_AS_DOUBLE(lhs); \
2190
1.05M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2191
1.05M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2192
1.05M
    }
Unexecuted instantiation: specialize.c:float_compactlong_add
specialize.c:float_compactlong_subtract
Line
Count
Source
2188
100
    { \
2189
100
        double lhs_val = PyFloat_AS_DOUBLE(lhs); \
2190
100
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2191
100
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2192
100
    }
specialize.c:float_compactlong_true_div
Line
Count
Source
2188
452k
    { \
2189
452k
        double lhs_val = PyFloat_AS_DOUBLE(lhs); \
2190
452k
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2191
452k
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2192
452k
    }
specialize.c:float_compactlong_multiply
Line
Count
Source
2188
602k
    { \
2189
602k
        double lhs_val = PyFloat_AS_DOUBLE(lhs); \
2190
602k
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2191
602k
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2192
602k
    }
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.49M
{
2204
6.49M
    return (
2205
6.49M
        PyLong_CheckExact(lhs) &&
2206
6.49M
        _PyLong_IsCompact((PyLongObject *)lhs) &&
2207
6.49M
        PyFloat_CheckExact(rhs) &&
2208
6.47M
        !isnan(PyFloat_AS_DOUBLE(rhs))
2209
6.49M
    );
2210
6.49M
}
2211
2212
static inline int
2213
nonzero_compactlong_float_guard(PyObject *lhs, PyObject *rhs)
2214
19
{
2215
19
    return (
2216
19
        compactlong_float_guard(lhs, rhs) && PyFloat_AS_DOUBLE(rhs) != 0.0
2217
19
    );
2218
19
}
2219
2220
#define LONG_FLOAT_ACTION(NAME, OP) \
2221
    static PyObject * \
2222
    (NAME)(PyObject *lhs, PyObject *rhs) \
2223
6.47M
    { \
2224
6.47M
        double rhs_val = PyFloat_AS_DOUBLE(rhs); \
2225
6.47M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2226
6.47M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2227
6.47M
    }
specialize.c:compactlong_float_add
Line
Count
Source
2223
4.78k
    { \
2224
4.78k
        double rhs_val = PyFloat_AS_DOUBLE(rhs); \
2225
4.78k
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2226
4.78k
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2227
4.78k
    }
specialize.c:compactlong_float_subtract
Line
Count
Source
2223
3.22M
    { \
2224
3.22M
        double rhs_val = PyFloat_AS_DOUBLE(rhs); \
2225
3.22M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2226
3.22M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2227
3.22M
    }
Unexecuted instantiation: specialize.c:compactlong_float_true_div
specialize.c:compactlong_float_multiply
Line
Count
Source
2223
3.23M
    { \
2224
3.23M
        double rhs_val = PyFloat_AS_DOUBLE(rhs); \
2225
3.23M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2226
3.23M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2227
3.23M
    }
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
52.4k
{
2306
52.4k
    size_t n = sizeof(binaryop_extend_descrs)/sizeof(_PyBinaryOpSpecializationDescr);
2307
2.09M
    for (size_t i = 0; i < n; i++) {
2308
2.04M
        _PyBinaryOpSpecializationDescr *d = &binaryop_extend_descrs[i];
2309
2.04M
        if (d->oparg != oparg) {
2310
1.95M
            continue;
2311
1.95M
        }
2312
96.5k
        int match = (d->guard != NULL)
2313
96.5k
            ? d->guard(lhs, rhs)
2314
96.5k
            : (Py_TYPE(lhs) == d->lhs_type && Py_TYPE(rhs) == d->rhs_type);
2315
96.5k
        if (match) {
2316
1.42k
            *descr = d;
2317
1.42k
            return 1;
2318
1.42k
        }
2319
96.5k
    }
2320
50.9k
    return 0;
2321
52.4k
}
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.30M
{
2327
1.30M
    PyObject *lhs = PyStackRef_AsPyObjectBorrow(lhs_st);
2328
1.30M
    PyObject *rhs = PyStackRef_AsPyObjectBorrow(rhs_st);
2329
1.30M
    assert(ENABLE_SPECIALIZATION);
2330
1.30M
    assert(_PyOpcode_Caches[BINARY_OP] == INLINE_CACHE_ENTRIES_BINARY_OP);
2331
2332
1.30M
    _PyBinaryOpCache *cache = (_PyBinaryOpCache *)(instr + 1);
2333
1.30M
    if (instr->op.code == BINARY_OP_EXTEND) {
2334
66
        write_ptr(cache->external_cache, NULL);
2335
66
    }
2336
2337
1.30M
    switch (oparg) {
2338
14.6k
        case NB_ADD:
2339
26.8k
        case NB_INPLACE_ADD:
2340
26.8k
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2341
2.09k
                break;
2342
2.09k
            }
2343
24.7k
            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.0k
            if (_PyLong_CheckExactAndCompact(lhs) && _PyLong_CheckExactAndCompact(rhs)) {
2354
5.91k
                specialize(instr, BINARY_OP_ADD_INT);
2355
5.91k
                return;
2356
5.91k
            }
2357
18.1k
            if (PyFloat_CheckExact(lhs)) {
2358
7
                specialize(instr, BINARY_OP_ADD_FLOAT);
2359
7
                return;
2360
7
            }
2361
18.0k
            break;
2362
18.0k
        case NB_MULTIPLY:
2363
1.95k
        case NB_INPLACE_MULTIPLY:
2364
1.95k
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2365
204
                break;
2366
204
            }
2367
1.75k
            if (_PyLong_CheckExactAndCompact(lhs) && _PyLong_CheckExactAndCompact(rhs)) {
2368
455
                specialize(instr, BINARY_OP_MULTIPLY_INT);
2369
455
                return;
2370
455
            }
2371
1.29k
            if (PyFloat_CheckExact(lhs)) {
2372
14
                specialize(instr, BINARY_OP_MULTIPLY_FLOAT);
2373
14
                return;
2374
14
            }
2375
1.28k
            break;
2376
2.55k
        case NB_SUBTRACT:
2377
2.63k
        case NB_INPLACE_SUBTRACT:
2378
2.63k
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2379
24
                break;
2380
24
            }
2381
2.61k
            if (_PyLong_CheckExactAndCompact(lhs) && _PyLong_CheckExactAndCompact(rhs)) {
2382
1.44k
                specialize(instr, BINARY_OP_SUBTRACT_INT);
2383
1.44k
                return;
2384
1.44k
            }
2385
1.16k
            if (PyFloat_CheckExact(lhs)) {
2386
32
                specialize(instr, BINARY_OP_SUBTRACT_FLOAT);
2387
32
                return;
2388
32
            }
2389
1.13k
            break;
2390
1.26M
        case NB_SUBSCR:
2391
1.26M
            if (PyLong_CheckExact(rhs) && _PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
2392
1.25M
                if (PyList_CheckExact(lhs)) {
2393
49.4k
                    specialize(instr, BINARY_OP_SUBSCR_LIST_INT);
2394
49.4k
                    return;
2395
49.4k
                }
2396
1.20M
                if (PyTuple_CheckExact(lhs)) {
2397
1.07k
                    specialize(instr, BINARY_OP_SUBSCR_TUPLE_INT);
2398
1.07k
                    return;
2399
1.07k
                }
2400
1.20M
                if (PyUnicode_CheckExact(lhs) && _PyLong_IsNonNegativeCompact((PyLongObject*)rhs)) {
2401
1.19M
                    if (PyUnicode_IS_COMPACT_ASCII(lhs)) {
2402
1.60k
                        specialize(instr, BINARY_OP_SUBSCR_STR_INT);
2403
1.60k
                        return;
2404
1.19M
                    } else {
2405
1.19M
                        specialize(instr, BINARY_OP_SUBSCR_USTR_INT);
2406
1.19M
                        return;
2407
1.19M
                    }
2408
1.19M
                }
2409
1.20M
            }
2410
16.0k
            if (Py_TYPE(lhs)->tp_as_mapping != NULL &&
2411
15.9k
                Py_TYPE(lhs)->tp_as_mapping->mp_subscript == _PyDict_Subscript)
2412
934
            {
2413
934
                specialize(instr, BINARY_OP_SUBSCR_DICT);
2414
934
                return;
2415
934
            }
2416
15.1k
            if (PyList_CheckExact(lhs) && PySlice_Check(rhs)) {
2417
81
                specialize(instr, BINARY_OP_SUBSCR_LIST_SLICE);
2418
81
                return;
2419
81
            }
2420
15.0k
            unsigned int tp_version;
2421
15.0k
            PyTypeObject *container_type = Py_TYPE(lhs);
2422
15.0k
            PyObject *descriptor = _PyType_LookupRefAndVersion(container_type, &_Py_ID(__getitem__), &tp_version);
2423
15.0k
            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
14.8k
            Py_XDECREF(descriptor);
2441
14.8k
            break;
2442
1.30M
    }
2443
2444
52.4k
    _PyBinaryOpSpecializationDescr *descr;
2445
52.4k
    if (binary_op_extended_specialization(lhs, rhs, oparg, &descr)) {
2446
1.42k
        specialize(instr, BINARY_OP_EXTEND);
2447
1.42k
        write_ptr(cache->external_cache, (void*)descr);
2448
1.42k
        return;
2449
1.42k
    }
2450
2451
50.9k
    SPECIALIZATION_FAIL(BINARY_OP, binary_op_fail_kind(oparg, lhs, rhs));
2452
50.9k
    unspecialize(instr);
2453
50.9k
    return;
2454
52.4k
}
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
25.8k
{
2496
25.8k
    PyObject *lhs = PyStackRef_AsPyObjectBorrow(lhs_st);
2497
25.8k
    PyObject *rhs = PyStackRef_AsPyObjectBorrow(rhs_st);
2498
25.8k
    uint8_t specialized_op;
2499
2500
25.8k
    assert(ENABLE_SPECIALIZATION);
2501
25.8k
    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
25.8k
    if (Py_TYPE(lhs) != Py_TYPE(rhs)) {
2505
4.39k
        SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
2506
4.39k
        goto failure;
2507
4.39k
    }
2508
21.4k
    if (PyFloat_CheckExact(lhs)) {
2509
64
        specialized_op = COMPARE_OP_FLOAT;
2510
64
        goto success;
2511
64
    }
2512
21.4k
    if (PyLong_CheckExact(lhs)) {
2513
12.9k
        if (_PyLong_IsCompact((PyLongObject *)lhs) && _PyLong_IsCompact((PyLongObject *)rhs)) {
2514
6.51k
            specialized_op = COMPARE_OP_INT;
2515
6.51k
            goto success;
2516
6.51k
        }
2517
6.47k
        else {
2518
6.47k
            SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_BIG_INT);
2519
6.47k
            goto failure;
2520
6.47k
        }
2521
12.9k
    }
2522
8.44k
    if (PyUnicode_CheckExact(lhs)) {
2523
6.30k
        int cmp = oparg >> 5;
2524
6.30k
        if (cmp != Py_EQ && cmp != Py_NE) {
2525
3.73k
            SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_STRING);
2526
3.73k
            goto failure;
2527
3.73k
        }
2528
2.56k
        else {
2529
2.56k
            specialized_op = COMPARE_OP_STR;
2530
2.56k
            goto success;
2531
2.56k
        }
2532
6.30k
    }
2533
2.14k
    SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
2534
16.7k
failure:
2535
16.7k
    unspecialize(instr);
2536
16.7k
    return;
2537
9.14k
success:
2538
9.14k
    specialize(instr, specialized_op);
2539
9.14k
}
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.33k
{
2558
6.33k
    PyObject *seq = PyStackRef_AsPyObjectBorrow(seq_st);
2559
2560
6.33k
    assert(ENABLE_SPECIALIZATION);
2561
6.33k
    assert(_PyOpcode_Caches[UNPACK_SEQUENCE] ==
2562
6.33k
           INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE);
2563
6.33k
    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.47k
            specialize(instr, UNPACK_SEQUENCE_TWO_TUPLE);
2571
1.47k
            return;
2572
1.47k
        }
2573
730
        specialize(instr, UNPACK_SEQUENCE_TUPLE);
2574
730
        return;
2575
2.20k
    }
2576
4.13k
    if (PyList_CheckExact(seq)) {
2577
3.98k
        if (PyList_GET_SIZE(seq) != oparg) {
2578
2.59k
            SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_EXPECTED_ERROR);
2579
2.59k
            unspecialize(instr);
2580
2.59k
            return;
2581
2.59k
        }
2582
1.39k
        specialize(instr, UNPACK_SEQUENCE_LIST);
2583
1.39k
        return;
2584
3.98k
    }
2585
146
    SPECIALIZATION_FAIL(UNPACK_SEQUENCE, unpack_sequence_fail_kind(seq));
2586
146
    unspecialize(instr);
2587
146
}
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
59.4k
{
2665
59.4k
    assert(ENABLE_SPECIALIZATION);
2666
59.4k
    assert(_PyOpcode_Caches[FOR_ITER] == INLINE_CACHE_ENTRIES_FOR_ITER);
2667
59.4k
    PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
2668
59.4k
    PyTypeObject *tp = Py_TYPE(iter_o);
2669
2670
59.4k
    if (PyStackRef_IsNull(null_or_index)) {
2671
52.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
271
            specialize(instr, FOR_ITER_RANGE);
2683
271
            return;
2684
271
        }
2685
51.8k
        else if (tp == &PyGen_Type && oparg <= SHRT_MAX) {
2686
670
            assert(instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == END_FOR  ||
2687
670
                instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == INSTRUMENTED_END_FOR
2688
670
            );
2689
            /* Don't specialize if PEP 523 is active */
2690
670
            if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) {
2691
0
                goto failure;
2692
0
            }
2693
670
            specialize(instr, FOR_ITER_GEN);
2694
670
            return;
2695
670
        }
2696
52.0k
    }
2697
7.33k
    else {
2698
7.33k
        if (tp->_tp_iteritem != NULL) {
2699
7.33k
            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.33k
        }
2714
162
        specialize(instr, FOR_ITER_VIRTUAL);
2715
162
        return;
2716
7.33k
    }
2717
51.1k
failure:
2718
51.1k
    SPECIALIZATION_FAIL(FOR_ITER,
2719
51.1k
                        _PySpecialization_ClassifyIterator(iter_o));
2720
51.1k
    unspecialize(instr);
2721
51.1k
}
2722
2723
Py_NO_INLINE void
2724
_Py_Specialize_Send(_PyStackRef receiver_st, _Py_CODEUNIT *instr)
2725
578
{
2726
578
    PyObject *receiver = PyStackRef_AsPyObjectBorrow(receiver_st);
2727
2728
578
    assert(ENABLE_SPECIALIZATION);
2729
578
    assert(_PyOpcode_Caches[SEND] == INLINE_CACHE_ENTRIES_SEND);
2730
578
    PyTypeObject *tp = Py_TYPE(receiver);
2731
578
    if (tp == &PyGen_Type || tp == &PyCoro_Type) {
2732
        /* Don't specialize if PEP 523 is active */
2733
286
        if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) {
2734
0
            SPECIALIZATION_FAIL(SEND, SPEC_FAIL_OTHER);
2735
0
            goto failure;
2736
0
        }
2737
286
        specialize(instr, SEND_GEN);
2738
286
        return;
2739
286
    }
2740
292
    if (tp->_tp_iteritem != NULL) {
2741
292
        specialize(instr, SEND_VIRTUAL);
2742
292
        return;
2743
292
    }
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
68.1k
{
2808
68.1k
    PyNumberMethods *nb = ty->tp_as_number;
2809
68.1k
    if (nb && nb->nb_bool) {
2810
51
        return SPEC_FAIL_TO_BOOL_NUMBER;
2811
51
    }
2812
68.1k
    PyMappingMethods *mp = ty->tp_as_mapping;
2813
68.1k
    if (mp && mp->mp_length) {
2814
3.63k
        return SPEC_FAIL_TO_BOOL_MAPPING;
2815
3.63k
    }
2816
64.4k
    PySequenceMethods *sq = ty->tp_as_sequence;
2817
64.4k
    if (sq && sq->sq_length) {
2818
4.89k
      return SPEC_FAIL_TO_BOOL_SEQUENCE;
2819
4.89k
    }
2820
59.6k
    return 0;
2821
64.4k
}
2822
2823
Py_NO_INLINE void
2824
_Py_Specialize_ToBool(_PyStackRef value_o, _Py_CODEUNIT *instr)
2825
220k
{
2826
220k
    assert(ENABLE_SPECIALIZATION);
2827
220k
    assert(_PyOpcode_Caches[TO_BOOL] == INLINE_CACHE_ENTRIES_TO_BOOL);
2828
220k
    _PyToBoolCache *cache = (_PyToBoolCache *)(instr + 1);
2829
220k
    PyObject *value = PyStackRef_AsPyObjectBorrow(value_o);
2830
220k
    uint8_t specialized_op;
2831
220k
    if (PyBool_Check(value)) {
2832
21.4k
        specialized_op = TO_BOOL_BOOL;
2833
21.4k
        goto success;
2834
21.4k
    }
2835
199k
    if (PyLong_CheckExact(value)) {
2836
7.26k
        specialized_op = TO_BOOL_INT;
2837
7.26k
        goto success;
2838
7.26k
    }
2839
192k
    if (PyList_CheckExact(value)) {
2840
564
        specialized_op = TO_BOOL_LIST;
2841
564
        goto success;
2842
564
    }
2843
191k
    if (Py_IsNone(value)) {
2844
87.7k
        specialized_op = TO_BOOL_NONE;
2845
87.7k
        goto success;
2846
87.7k
    }
2847
103k
    if (PyUnicode_CheckExact(value)) {
2848
30.9k
        specialized_op = TO_BOOL_STR;
2849
30.9k
        goto success;
2850
30.9k
    }
2851
72.9k
    if (PyType_HasFeature(Py_TYPE(value), Py_TPFLAGS_HEAPTYPE)) {
2852
68.1k
        unsigned int version = 0;
2853
68.1k
        int err = _PyType_Validate(Py_TYPE(value), check_type_always_true, &version);
2854
68.1k
        if (err < 0) {
2855
0
            SPECIALIZATION_FAIL(TO_BOOL, SPEC_FAIL_OUT_OF_VERSIONS);
2856
0
            goto failure;
2857
0
        }
2858
68.1k
        else if (err > 0) {
2859
8.58k
            SPECIALIZATION_FAIL(TO_BOOL, err);
2860
8.58k
            goto failure;
2861
8.58k
        }
2862
2863
68.1k
        assert(err == 0);
2864
59.6k
        assert(version);
2865
59.6k
        write_u32(cache->version, version);
2866
59.6k
        specialized_op = TO_BOOL_ALWAYS_TRUE;
2867
59.6k
        goto success;
2868
68.1k
    }
2869
2870
4.78k
    SPECIALIZATION_FAIL(TO_BOOL, to_bool_fail_kind(value));
2871
13.3k
failure:
2872
13.3k
    unspecialize(instr);
2873
13.3k
    return;
2874
207k
success:
2875
207k
    specialize(instr, specialized_op);
2876
207k
}
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
30.6k
{
2900
30.6k
    PyObject *value = PyStackRef_AsPyObjectBorrow(value_st);
2901
2902
30.6k
    assert(ENABLE_SPECIALIZATION);
2903
30.6k
    assert(_PyOpcode_Caches[CONTAINS_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP);
2904
30.6k
    if (PyAnyDict_CheckExact(value)) {
2905
715
        specialize(instr, CONTAINS_OP_DICT);
2906
715
        return;
2907
715
    }
2908
29.9k
    if (PySet_CheckExact(value) || PyFrozenSet_CheckExact(value)) {
2909
669
        specialize(instr, CONTAINS_OP_SET);
2910
669
        return;
2911
669
    }
2912
2913
29.3k
    SPECIALIZATION_FAIL(CONTAINS_OP, containsop_fail_kind(value));
2914
29.3k
    unspecialize(instr);
2915
29.3k
    return;
2916
29.9k
}
2917
2918
void
2919
_Py_Specialize_GetIter(_PyStackRef iterable, _Py_CODEUNIT *instr)
2920
9.77k
{
2921
9.77k
    assert(ENABLE_SPECIALIZATION);
2922
9.77k
    PyTypeObject *tp = PyStackRef_TYPE(iterable);
2923
9.77k
    if (tp->_tp_iteritem != NULL) {
2924
2.37k
        specialize(instr, GET_ITER_VIRTUAL);
2925
2.37k
        return;
2926
2.37k
    }
2927
7.39k
    if (tp->tp_iter == PyObject_SelfIter) {
2928
570
        specialize(instr, GET_ITER_SELF);
2929
570
        return;
2930
570
    }
2931
6.82k
    SPECIALIZATION_FAIL(GET_ITER,
2932
6.82k
        tp == &PyCoro_Type ? SPEC_FAIL_ITER_COROUTINE : SPEC_FAIL_OTHER);
2933
6.82k
    unspecialize(instr);
2934
6.82k
}
2935
2936
void
2937
_Py_Specialize_Resume(_Py_CODEUNIT *instr, PyThreadState *tstate, _PyInterpreterFrame *frame)
2938
2.72M
{
2939
2.72M
    if (tstate->tracing == 0 && instr->op.code == RESUME) {
2940
91.4k
        if (tstate->interp->jit) {
2941
0
            PyCodeObject *co = (PyCodeObject *)PyStackRef_AsPyObjectBorrow(frame->f_executable);
2942
0
            if (co != NULL &&
2943
0
                PyCode_Check(co) &&
2944
0
                (co->co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) == 0) {
2945
0
                specialize(instr, RESUME_CHECK_JIT);
2946
0
                set_counter((_Py_BackoffCounter *)instr + 1, initial_resume_backoff_counter(&tstate->interp->opt_config));
2947
0
                return;
2948
0
            }
2949
0
        }
2950
91.4k
        specialize(instr, RESUME_CHECK);
2951
91.4k
        return;
2952
91.4k
    }
2953
2.63M
    unspecialize(instr);
2954
2.63M
    return;
2955
2.72M
}
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
};