Coverage Report

Created: 2026-07-14 06:16

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