Coverage Report

Created: 2025-11-11 06:44

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