Coverage Report

Created: 2025-11-30 06:38

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
241k
#  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
159k
{
47
159k
    #if ENABLE_SPECIALIZATION_FT
48
159k
    _Py_BackoffCounter jump_counter, adaptive_counter;
49
159k
    if (enable_counters) {
50
159k
        jump_counter = initial_jump_backoff_counter();
51
159k
        adaptive_counter = adaptive_counter_warmup();
52
159k
    }
53
0
    else {
54
0
        jump_counter = initial_unreachable_backoff_counter();
55
0
        adaptive_counter = initial_unreachable_backoff_counter();
56
0
    }
57
159k
    int opcode = 0;
58
159k
    int oparg = 0;
59
    /* The last code unit cannot have a cache, so we don't need to check it */
60
6.73M
    for (Py_ssize_t i = 0; i < size-1; i++) {
61
6.57M
        opcode = instructions[i].op.code;
62
6.57M
        int caches = _PyOpcode_Caches[opcode];
63
6.57M
        oparg = (oparg << 8) | instructions[i].op.arg;
64
6.57M
        if (caches) {
65
            // The initial value depends on the opcode
66
1.95M
            switch (opcode) {
67
44.8k
                case JUMP_BACKWARD:
68
44.8k
                    instructions[i + 1].counter = jump_counter;
69
44.8k
                    break;
70
136k
                case POP_JUMP_IF_FALSE:
71
183k
                case POP_JUMP_IF_TRUE:
72
199k
                case POP_JUMP_IF_NONE:
73
211k
                case POP_JUMP_IF_NOT_NONE:
74
211k
                    instructions[i + 1].cache = 0x5555;  // Alternating 0, 1 bits
75
211k
                    break;
76
1.70M
                default:
77
1.70M
                    instructions[i + 1].counter = adaptive_counter;
78
1.70M
                    break;
79
1.95M
            }
80
1.95M
            i += caches;
81
1.95M
        }
82
6.57M
        if (opcode != EXTENDED_ARG) {
83
6.55M
            oparg = 0;
84
6.55M
        }
85
6.57M
    }
86
159k
    #endif /* ENABLE_SPECIALIZATION_FT */
87
159k
}
88
89
481k
#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.37k
#define SPEC_FAIL_CODE_COMPLEX_PARAMETERS 7
101
24.9k
#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
5.72k
#define SPEC_FAIL_TO_BOOL_MAPPING     13
275
#define SPEC_FAIL_TO_BOOL_MEMORY_VIEW 14
276
34
#define SPEC_FAIL_TO_BOOL_NUMBER      15
277
5.65k
#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
6.25M
{
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
6.25M
    instr->op.code = opcode;
304
6.25M
    return 1;
305
6.25M
#endif
306
6.25M
}
307
308
static inline void
309
set_counter(_Py_BackoffCounter *counter, _Py_BackoffCounter value)
310
7.20M
{
311
7.20M
    FT_ATOMIC_STORE_UINT16_RELAXED(counter->value_and_backoff,
312
7.20M
                                   value.value_and_backoff);
313
7.20M
}
314
315
static inline _Py_BackoffCounter
316
load_counter(_Py_BackoffCounter *counter)
317
242k
{
318
242k
    _Py_BackoffCounter result = {
319
242k
        .value_and_backoff =
320
242k
            FT_ATOMIC_LOAD_UINT16_RELAXED(counter->value_and_backoff)};
321
242k
    return result;
322
242k
}
323
324
static inline void
325
specialize(_Py_CODEUNIT *instr, uint8_t specialized_opcode)
326
6.00M
{
327
6.00M
    assert(!PyErr_Occurred());
328
6.00M
    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
6.00M
    STAT_INC(_PyOpcode_Deopt[specialized_opcode], success);
335
6.00M
    set_counter((_Py_BackoffCounter *)instr + 1, adaptive_counter_cooldown());
336
6.00M
}
337
338
static inline void
339
unspecialize(_Py_CODEUNIT *instr)
340
242k
{
341
242k
    assert(!PyErr_Occurred());
342
242k
    uint8_t opcode = FT_ATOMIC_LOAD_UINT8_RELAXED(instr->op.code);
343
242k
    uint8_t generic_opcode = _PyOpcode_Deopt[opcode];
344
242k
    STAT_INC(generic_opcode, failure);
345
242k
    if (!set_opcode(instr, generic_opcode)) {
346
0
        SPECIALIZATION_FAIL(generic_opcode, SPEC_FAIL_OTHER);
347
0
        return;
348
0
    }
349
242k
    _Py_BackoffCounter *counter = (_Py_BackoffCounter *)instr + 1;
350
242k
    _Py_BackoffCounter cur = load_counter(counter);
351
242k
    set_counter(counter, adaptive_counter_backoff(cur));
352
242k
}
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.93k
{
361
4.93k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
362
4.93k
    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.93k
    Py_ssize_t index = _PyDict_LookupIndex(dict, &_Py_ID(__getattr__));
367
4.93k
    assert(index != DKIX_ERROR);
368
4.93k
    if (index != DKIX_EMPTY) {
369
508
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MODULE_ATTR_NOT_FOUND);
370
508
        return -1;
371
508
    }
372
4.42k
    index = _PyDict_LookupIndex(dict, name);
373
4.42k
    assert (index != DKIX_ERROR);
374
4.42k
    if (index != (uint16_t)index) {
375
254
        SPECIALIZATION_FAIL(LOAD_ATTR,
376
254
                            index == DKIX_EMPTY ?
377
254
                            SPEC_FAIL_ATTR_MODULE_ATTR_NOT_FOUND :
378
254
                            SPEC_FAIL_OUT_OF_RANGE);
379
254
        return -1;
380
254
    }
381
4.17k
    uint32_t keys_version = _PyDict_GetKeysVersionForCurrentState(
382
4.17k
            _PyInterpreterState_GET(), dict);
383
4.17k
    if (keys_version == 0) {
384
0
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
385
0
        return -1;
386
0
    }
387
4.17k
    write_u32(cache->version, keys_version);
388
4.17k
    cache->index = (uint16_t)index;
389
4.17k
    specialize(instr, LOAD_ATTR_MODULE);
390
4.17k
    return 0;
391
4.17k
}
392
393
static int
394
specialize_module_load_attr(
395
    PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
396
4.93k
{
397
4.93k
    PyModuleObject *m = (PyModuleObject *)owner;
398
4.93k
    assert((Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0);
399
4.93k
    PyDictObject *dict = (PyDictObject *)m->md_dict;
400
4.93k
    if (dict == NULL) {
401
0
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_NO_DICT);
402
0
        return -1;
403
0
    }
404
4.93k
    int result;
405
4.93k
    Py_BEGIN_CRITICAL_SECTION(dict);
406
4.93k
    result = specialize_module_load_attr_lock_held(dict, instr, name);
407
4.93k
    Py_END_CRITICAL_SECTION();
408
4.93k
    return result;
409
4.93k
}
410
411
/* Attribute specialization */
412
413
Py_NO_INLINE void
414
321
_Py_Specialize_LoadSuperAttr(_PyStackRef global_super_st, _PyStackRef cls_st, _Py_CODEUNIT *instr, int load_method) {
415
321
    PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st);
416
321
    PyObject *cls = PyStackRef_AsPyObjectBorrow(cls_st);
417
418
321
    assert(ENABLE_SPECIALIZATION_FT);
419
321
    assert(_PyOpcode_Caches[LOAD_SUPER_ATTR] == INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR);
420
321
    if (global_super != (PyObject *)&PySuper_Type) {
421
0
        SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_SHADOWED);
422
0
        goto fail;
423
0
    }
424
321
    if (!PyType_Check(cls)) {
425
0
        SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_BAD_CLASS);
426
0
        goto fail;
427
0
    }
428
321
    uint8_t load_code = load_method ? LOAD_SUPER_ATTR_METHOD : LOAD_SUPER_ATTR_ATTR;
429
321
    specialize(instr, load_code);
430
321
    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
3.41M
{
456
3.41M
    if (descriptor == NULL) {
457
1.34M
        return ABSENT;
458
1.34M
    }
459
2.07M
    PyTypeObject *desc_cls = Py_TYPE(descriptor);
460
2.07M
    if (!(desc_cls->tp_flags & Py_TPFLAGS_IMMUTABLETYPE)) {
461
388
        return MUTABLE;
462
388
    }
463
2.07M
    if (desc_cls->tp_descr_set) {
464
239k
        if (desc_cls == &PyMemberDescr_Type) {
465
20.2k
            PyMemberDescrObject *member = (PyMemberDescrObject *)descriptor;
466
20.2k
            struct PyMemberDef *dmem = member->d_member;
467
20.2k
            if (dmem->type == Py_T_OBJECT_EX || dmem->type == _Py_T_OBJECT) {
468
20.1k
                return OBJECT_SLOT;
469
20.1k
            }
470
98
            return OTHER_SLOT;
471
20.2k
        }
472
219k
        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
216k
            return has_getattr ? GETSET_OVERRIDDEN : PROPERTY;
477
216k
        }
478
3.05k
        return OVERRIDING;
479
219k
    }
480
1.83M
    if (desc_cls->tp_descr_get) {
481
508k
        if (desc_cls->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR) {
482
505k
            return METHOD;
483
505k
        }
484
2.77k
        if (Py_IS_TYPE(descriptor, &PyClassMethodDescr_Type)) {
485
223
            return BUILTIN_CLASSMETHOD;
486
223
        }
487
2.55k
        if (Py_IS_TYPE(descriptor, &PyClassMethod_Type)) {
488
1.81k
            return PYTHON_CLASSMETHOD;
489
1.81k
        }
490
736
        return NON_OVERRIDING;
491
2.55k
    }
492
1.32M
    return NON_DESCRIPTOR;
493
1.83M
}
494
495
static bool
496
descriptor_is_class(PyObject *descriptor, PyObject *name)
497
3.47M
{
498
3.47M
    return ((PyUnicode_CompareWithASCIIString(name, "__class__") == 0) &&
499
60.2k
            (descriptor == _PyType_Lookup(&PyBaseObject_Type, name)));
500
3.47M
}
501
502
static DescriptorClassification
503
3.25M
analyze_descriptor_load(PyTypeObject *type, PyObject *name, PyObject **descr, unsigned int *tp_version) {
504
3.25M
    bool has_getattr = false;
505
3.25M
    bool have_ga_version = false;
506
3.25M
    unsigned int ga_version;
507
3.25M
    getattrofunc getattro_slot = type->tp_getattro;
508
3.25M
    if (getattro_slot == PyObject_GenericGetAttr) {
509
        /* Normal attribute lookup; */
510
3.25M
        has_getattr = false;
511
3.25M
    }
512
274
    else if (getattro_slot == _Py_slot_tp_getattr_hook ||
513
210
        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
64
        PyObject *getattribute = _PyType_LookupRefAndVersion(type,
517
64
                &_Py_ID(__getattribute__), &ga_version);
518
64
        have_ga_version = true;
519
64
        PyInterpreterState *interp = _PyInterpreterState_GET();
520
64
        bool has_custom_getattribute = getattribute != NULL &&
521
64
            getattribute != interp->callable_cache.object__getattribute__;
522
64
        PyObject *getattr = _PyType_Lookup(type, &_Py_ID(__getattr__));
523
64
        has_getattr = getattr != NULL;
524
64
        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
64
        Py_XDECREF(getattribute);
546
64
    }
547
210
    else {
548
210
        *descr = NULL;
549
210
        *tp_version = FT_ATOMIC_LOAD_UINT_RELAXED(type->tp_version_tag);
550
210
        return GETSET_OVERRIDDEN;
551
210
    }
552
3.25M
    unsigned int descr_version;
553
3.25M
    PyObject *descriptor = _PyType_LookupRefAndVersion(type, name, &descr_version);
554
3.25M
    *descr = descriptor;
555
3.25M
    *tp_version = have_ga_version ? ga_version : descr_version;
556
3.25M
    if (descriptor_is_class(descriptor, name)) {
557
60.2k
        return DUNDER_CLASS;
558
60.2k
    }
559
3.19M
    return classify_descriptor(descriptor, has_getattr);
560
3.25M
}
561
562
static DescriptorClassification
563
analyze_descriptor_store(PyTypeObject *type, PyObject *name, PyObject **descr, unsigned int *tp_version)
564
213k
{
565
213k
    if (type->tp_setattro != PyObject_GenericSetAttr) {
566
342
        *descr = NULL;
567
342
        return GETSET_OVERRIDDEN;
568
342
    }
569
213k
    PyObject *descriptor = _PyType_LookupRefAndVersion(type, name, tp_version);
570
213k
    *descr = descriptor;
571
213k
    if (descriptor_is_class(descriptor, name)) {
572
4
        return DUNDER_CLASS;
573
4
    }
574
213k
    return classify_descriptor(descriptor, false);
575
213k
}
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
625k
{
583
625k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
584
625k
    PyDictKeysObject *keys = ((PyHeapTypeObject *)type)->ht_cached_keys;
585
625k
    assert(PyUnicode_CheckExact(name));
586
625k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(owner);
587
625k
    Py_ssize_t index = _PyDictKeys_StringLookupSplit(keys, name);
588
625k
    assert (index != DKIX_ERROR);
589
625k
    if (index == DKIX_EMPTY) {
590
242
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_NOT_IN_KEYS);
591
242
        return 0;
592
242
    }
593
625k
    assert(index >= 0);
594
625k
    assert(_PyObject_InlineValues(owner)->valid);
595
625k
    char *value_addr = (char *)&_PyObject_InlineValues(owner)->values[index];
596
625k
    Py_ssize_t offset = value_addr - (char *)owner;
597
625k
    if (offset != (uint16_t)offset) {
598
0
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_OUT_OF_RANGE);
599
0
        return 0;
600
0
    }
601
625k
    cache->index = (uint16_t)offset;
602
625k
    write_u32(cache->version, tp_version);
603
625k
    specialize(instr, values_op);
604
625k
    return 1;
605
625k
}
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
13.6k
{
613
13.6k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
614
615
13.6k
    _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
13.6k
    if (_PyDict_HasSplitTable(dict)) {
622
372
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_SPLIT_DICT);
623
372
        return 0;
624
372
    }
625
13.2k
    Py_ssize_t index = _PyDict_LookupIndex(dict, name);
626
13.2k
    if (index != (uint16_t)index) {
627
3.27k
        SPECIALIZATION_FAIL(base_op,
628
3.27k
                            index == DKIX_EMPTY ?
629
3.27k
                            SPEC_FAIL_ATTR_NOT_IN_DICT :
630
3.27k
                            SPEC_FAIL_OUT_OF_RANGE);
631
3.27k
        return 0;
632
3.27k
    }
633
9.98k
    cache->index = (uint16_t)index;
634
9.98k
    write_u32(cache->version, tp_version);
635
9.98k
    specialize(instr, hint_op);
636
9.98k
    return 1;
637
13.2k
}
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
643k
{
646
643k
    assert(kind == NON_OVERRIDING || kind == NON_DESCRIPTOR || kind == ABSENT ||
647
643k
        kind == BUILTIN_CLASSMETHOD || kind == PYTHON_CLASSMETHOD ||
648
643k
        kind == METHOD);
649
    // No descriptor, or non overriding.
650
643k
    if ((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {
651
4.04k
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);
652
4.04k
        return 0;
653
4.04k
    }
654
639k
    if (type->tp_flags & Py_TPFLAGS_INLINE_VALUES &&
655
638k
        FT_ATOMIC_LOAD_UINT8(_PyObject_InlineValues(owner)->valid) &&
656
625k
        !(base_op == STORE_ATTR && _PyObject_GetManagedDict(owner) != NULL))
657
625k
    {
658
625k
        int res;
659
625k
        Py_BEGIN_CRITICAL_SECTION(owner);
660
625k
        PyDictObject *dict = _PyObject_GetManagedDict(owner);
661
625k
        if (dict == NULL) {
662
            // managed dict, not materialized, inline values valid
663
625k
            res = specialize_dict_access_inline(owner, instr, type, name,
664
625k
                                                tp_version, base_op, values_op);
665
625k
        }
666
12
        else {
667
            // lost race and dict was created, fail specialization
668
12
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OTHER);
669
12
            res = 0;
670
12
        }
671
625k
        Py_END_CRITICAL_SECTION();
672
625k
        return res;
673
625k
    }
674
13.8k
    else {
675
13.8k
        PyDictObject *dict = _PyObject_GetManagedDict(owner);
676
13.8k
        if (dict == NULL || !PyDict_CheckExact(dict)) {
677
186
            SPECIALIZATION_FAIL(base_op, SPEC_FAIL_NO_DICT);
678
186
            return 0;
679
186
        }
680
13.6k
        int res;
681
13.6k
        Py_BEGIN_CRITICAL_SECTION(dict);
682
        // materialized managed dict
683
13.6k
        res = specialize_dict_access_hint(dict, instr, type, name,
684
13.6k
                                          tp_version, base_op, hint_op);
685
13.6k
        Py_END_CRITICAL_SECTION();
686
13.6k
        return res;
687
13.8k
    }
688
639k
}
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
3.25M
{
706
3.25M
    PyTypeObject *cls = Py_TYPE(obj);
707
3.25M
    if ((cls->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {
708
604k
        return false;
709
604k
    }
710
2.64M
    if (cls->tp_flags & Py_TPFLAGS_INLINE_VALUES) {
711
2.56M
        PyDictKeysObject *keys = ((PyHeapTypeObject *)cls)->ht_cached_keys;
712
2.56M
        Py_ssize_t index =
713
2.56M
            _PyDictKeys_StringLookupAndVersion(keys, name, shared_keys_version);
714
2.56M
        return index >= 0;
715
2.56M
    }
716
85.1k
    PyDictObject *dict = _PyObject_GetManagedDict(obj);
717
85.1k
    if (dict == NULL || !PyDict_CheckExact(dict)) {
718
0
        return false;
719
0
    }
720
85.1k
    bool result;
721
85.1k
    Py_BEGIN_CRITICAL_SECTION(dict);
722
85.1k
    if (dict->ma_values) {
723
85.1k
        result = false;
724
85.1k
    }
725
0
    else {
726
0
        result = (_PyDict_LookupIndex(dict, name) >= 0);
727
0
    }
728
85.1k
    Py_END_CRITICAL_SECTION();
729
85.1k
    return result;
730
85.1k
}
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
3.25M
{
737
3.25M
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
738
3.25M
    PyTypeObject *type = Py_TYPE(owner);
739
3.25M
    if (tp_version == 0) {
740
3.23k
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
741
3.23k
        return -1;
742
3.23k
    }
743
3.24M
    uint8_t oparg = FT_ATOMIC_LOAD_UINT8_RELAXED(instr->op.arg);
744
3.24M
    switch(kind) {
745
248
        case OVERRIDING:
746
248
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
747
248
            return -1;
748
503k
        case METHOD:
749
503k
        {
750
503k
            if (shadow) {
751
81
                goto try_instance;
752
81
            }
753
503k
            if (oparg & 1) {
754
467k
                if (specialize_attr_loadclassattr(owner, instr, name, descr,
755
467k
                                                  tp_version, kind, true,
756
467k
                                                  shared_keys_version)) {
757
464k
                    return 0;
758
464k
                }
759
2.47k
                else {
760
2.47k
                    return -1;
761
2.47k
                }
762
467k
            }
763
36.1k
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
764
36.1k
            return -1;
765
503k
        }
766
216k
        case PROPERTY:
767
216k
        {
768
216k
            _PyLoadMethodCache *lm_cache = (_PyLoadMethodCache *)(instr + 1);
769
216k
            assert(Py_TYPE(descr) == &PyProperty_Type);
770
216k
            PyObject *fget = ((_PyPropertyObject *)descr)->prop_get;
771
216k
            if (fget == NULL) {
772
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
773
0
                return -1;
774
0
            }
775
216k
            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
216k
            if (!function_check_args(fget, 1, LOAD_ATTR)) {
780
0
                return -1;
781
0
            }
782
216k
            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
216k
            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
216k
            assert(tp_version != 0);
798
216k
            write_u32(lm_cache->type_version, tp_version);
799
            /* borrowed */
800
216k
            write_ptr(lm_cache->descr, fget);
801
216k
            specialize(instr, LOAD_ATTR_PROPERTY);
802
216k
            return 0;
803
216k
        }
804
19.7k
        case OBJECT_SLOT:
805
19.7k
        {
806
19.7k
            PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
807
19.7k
            struct PyMemberDef *dmem = member->d_member;
808
19.7k
            Py_ssize_t offset = dmem->offset;
809
19.7k
            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
19.7k
            if (dmem->flags & Py_AUDIT_READ) {
814
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_AUDITED_SLOT);
815
0
                return -1;
816
0
            }
817
19.7k
            if (offset != (uint16_t)offset) {
818
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE);
819
0
                return -1;
820
0
            }
821
19.7k
            assert(dmem->type == Py_T_OBJECT_EX || dmem->type == _Py_T_OBJECT);
822
19.7k
            assert(offset > 0);
823
19.7k
            cache->index = (uint16_t)offset;
824
19.7k
            write_u32(cache->version, tp_version);
825
19.7k
            specialize(instr, LOAD_ATTR_SLOT);
826
19.7k
            return 0;
827
19.7k
        }
828
60.2k
        case DUNDER_CLASS:
829
60.2k
        {
830
60.2k
            Py_ssize_t offset = offsetof(PyObject, ob_type);
831
60.2k
            assert(offset == (uint16_t)offset);
832
60.2k
            cache->index = (uint16_t)offset;
833
60.2k
            write_u32(cache->version, tp_version);
834
60.2k
            specialize(instr, LOAD_ATTR_SLOT);
835
60.2k
            return 0;
836
19.7k
        }
837
98
        case OTHER_SLOT:
838
98
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT);
839
98
            return -1;
840
176
        case MUTABLE:
841
176
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
842
176
            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
181
        case PYTHON_CLASSMETHOD:
881
281
        case NON_OVERRIDING:
882
281
            if (shadow) {
883
0
                goto try_instance;
884
0
            }
885
281
            return -1;
886
1.32M
        case NON_DESCRIPTOR:
887
1.32M
            if (shadow) {
888
258k
                goto try_instance;
889
258k
            }
890
1.06M
            if ((oparg & 1) == 0) {
891
1.06M
                if (specialize_attr_loadclassattr(owner, instr, name, descr,
892
1.06M
                                                  tp_version, kind, false,
893
1.06M
                                                  shared_keys_version)) {
894
1.06M
                    return 0;
895
1.06M
                }
896
1.06M
            }
897
454
            return -1;
898
1.12M
        case ABSENT:
899
1.12M
            if (shadow) {
900
177k
                goto try_instance;
901
177k
            }
902
950k
            set_counter((_Py_BackoffCounter*)instr + 1, adaptive_counter_cooldown());
903
950k
            return 0;
904
3.24M
    }
905
3.24M
    Py_UNREACHABLE();
906
435k
try_instance:
907
435k
    if (specialize_dict_access(owner, instr, type, kind, name, tp_version,
908
435k
                               LOAD_ATTR, LOAD_ATTR_INSTANCE_VALUE, LOAD_ATTR_WITH_HINT))
909
432k
    {
910
432k
        return 0;
911
432k
    }
912
3.22k
    return -1;
913
435k
}
914
915
static int
916
specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name)
917
3.25M
{
918
    // 0 is not a valid version
919
3.25M
    uint32_t shared_keys_version = 0;
920
3.25M
    bool shadow = instance_has_key(owner, name, &shared_keys_version);
921
3.25M
    PyObject *descr = NULL;
922
3.25M
    unsigned int tp_version = 0;
923
3.25M
    PyTypeObject *type = Py_TYPE(owner);
924
3.25M
    DescriptorClassification kind = analyze_descriptor_load(type, name, &descr, &tp_version);
925
3.25M
    int result = do_specialize_instance_load_attr(owner, instr, name, shadow, shared_keys_version, kind, descr, tp_version);
926
3.25M
    Py_XDECREF(descr);
927
3.25M
    return result;
928
3.25M
}
929
930
Py_NO_INLINE void
931
_Py_Specialize_LoadAttr(_PyStackRef owner_st, _Py_CODEUNIT *instr, PyObject *name)
932
3.26M
{
933
3.26M
    PyObject *owner = PyStackRef_AsPyObjectBorrow(owner_st);
934
935
3.26M
    assert(ENABLE_SPECIALIZATION_FT);
936
3.26M
    assert(_PyOpcode_Caches[LOAD_ATTR] == INLINE_CACHE_ENTRIES_LOAD_ATTR);
937
3.26M
    PyTypeObject *type = Py_TYPE(owner);
938
3.26M
    bool fail;
939
3.26M
    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
3.26M
    else if (Py_TYPE(owner)->tp_getattro == PyModule_Type.tp_getattro) {
947
4.93k
        fail = specialize_module_load_attr(owner, instr, name);
948
4.93k
    }
949
3.25M
    else if (PyType_Check(owner)) {
950
6.80k
        fail = specialize_class_load_attr(owner, instr, name);
951
6.80k
    }
952
3.25M
    else {
953
3.25M
        fail = specialize_instance_load_attr(owner, instr, name);
954
3.25M
    }
955
956
3.26M
    if (fail) {
957
52.2k
        unspecialize(instr);
958
52.2k
    }
959
3.26M
}
960
961
Py_NO_INLINE void
962
_Py_Specialize_StoreAttr(_PyStackRef owner_st, _Py_CODEUNIT *instr, PyObject *name)
963
214k
{
964
214k
    PyObject *owner = PyStackRef_AsPyObjectBorrow(owner_st);
965
966
214k
    assert(ENABLE_SPECIALIZATION_FT);
967
214k
    assert(_PyOpcode_Caches[STORE_ATTR] == INLINE_CACHE_ENTRIES_STORE_ATTR);
968
214k
    PyObject *descr = NULL;
969
214k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
970
214k
    PyTypeObject *type = Py_TYPE(owner);
971
214k
    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
214k
    if (PyModule_CheckExact(owner)) {
979
476
        SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OVERRIDDEN);
980
476
        goto fail;
981
476
    }
982
213k
    unsigned int tp_version = 0;
983
213k
    DescriptorClassification kind = analyze_descriptor_store(type, name, &descr, &tp_version);
984
213k
    if (tp_version == 0) {
985
377
        goto fail;
986
377
    }
987
213k
    assert(descr != NULL || kind == ABSENT || kind == GETSET_OVERRIDDEN);
988
213k
    switch(kind) {
989
683
        case OVERRIDING:
990
683
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
991
683
            goto fail;
992
12
        case METHOD:
993
12
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_METHOD);
994
12
            goto fail;
995
28
        case PROPERTY:
996
28
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_PROPERTY);
997
28
            goto fail;
998
374
        case OBJECT_SLOT:
999
374
        {
1000
374
            PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
1001
374
            struct PyMemberDef *dmem = member->d_member;
1002
374
            Py_ssize_t offset = dmem->offset;
1003
374
            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
374
            if (dmem->flags & Py_READONLY) {
1008
0
                SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_READ_ONLY);
1009
0
                goto fail;
1010
0
            }
1011
374
            if (offset != (uint16_t)offset) {
1012
0
                SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OUT_OF_RANGE);
1013
0
                goto fail;
1014
0
            }
1015
374
            assert(dmem->type == Py_T_OBJECT_EX || dmem->type == _Py_T_OBJECT);
1016
374
            assert(offset > 0);
1017
374
            cache->index = (uint16_t)offset;
1018
374
            write_u32(cache->version, tp_version);
1019
374
            specialize(instr, STORE_ATTR_SLOT);
1020
374
            goto success;
1021
374
        }
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
4.58k
        case NON_DESCRIPTOR:
1043
4.58k
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE);
1044
4.58k
            goto fail;
1045
207k
        case ABSENT:
1046
207k
            if (specialize_dict_access(owner, instr, type, kind, name, tp_version,
1047
207k
                                       STORE_ATTR, STORE_ATTR_INSTANCE_VALUE,
1048
207k
                                       STORE_ATTR_WITH_HINT)) {
1049
202k
                goto success;
1050
202k
            }
1051
213k
    }
1052
11.0k
fail:
1053
11.0k
    Py_XDECREF(descr);
1054
11.0k
    unspecialize(instr);
1055
11.0k
    return;
1056
203k
success:
1057
203k
    Py_XDECREF(descr);
1058
203k
    return;
1059
213k
}
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.80k
{
1102
6.80k
    assert(PyType_Check(owner));
1103
6.80k
    PyTypeObject *cls = (PyTypeObject *)owner;
1104
6.80k
    _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1);
1105
6.80k
    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.80k
    unsigned int meta_version = 0;
1110
6.80k
    PyObject *metadescriptor = _PyType_LookupRefAndVersion(Py_TYPE(cls), name, &meta_version);
1111
6.80k
    DescriptorClassification metakind = classify_descriptor(metadescriptor, false);
1112
6.80k
    Py_XDECREF(metadescriptor);
1113
6.80k
    switch (metakind) {
1114
386
        case METHOD:
1115
571
        case NON_DESCRIPTOR:
1116
727
        case NON_OVERRIDING:
1117
727
        case BUILTIN_CLASSMETHOD:
1118
727
        case PYTHON_CLASSMETHOD:
1119
4.67k
        case ABSENT:
1120
4.67k
            break;
1121
2.12k
        default:
1122
2.12k
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METACLASS_ATTRIBUTE);
1123
2.12k
            return -1;
1124
6.80k
    }
1125
4.67k
    PyObject *descr = NULL;
1126
4.67k
    DescriptorClassification kind = 0;
1127
4.67k
    unsigned int tp_version = 0;
1128
4.67k
    kind = analyze_descriptor_load(cls, name, &descr, &tp_version);
1129
4.67k
    if (tp_version == 0) {
1130
152
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
1131
152
        Py_XDECREF(descr);
1132
152
        return -1;
1133
152
    }
1134
4.67k
    bool metaclass_check = false;
1135
4.52k
    if ((Py_TYPE(cls)->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) {
1136
1.34k
        metaclass_check = true;
1137
1.34k
        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.34k
    }
1143
4.52k
    switch (kind) {
1144
395
        case METHOD:
1145
1.66k
        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.66k
            write_u32(cache->type_version, tp_version);
1154
1.66k
            write_ptr(cache->descr, descr);
1155
1.66k
            if (metaclass_check) {
1156
847
                write_u32(cache->keys_version, meta_version);
1157
847
                specialize(instr, LOAD_ATTR_CLASS_WITH_METACLASS_CHECK);
1158
847
            }
1159
816
            else {
1160
816
                specialize(instr, LOAD_ATTR_CLASS);
1161
816
            }
1162
1.66k
            Py_XDECREF(descr);
1163
1.66k
            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.86k
        default:
1171
2.86k
            SPECIALIZATION_FAIL(LOAD_ATTR, load_attr_fail_kind(kind));
1172
2.86k
            Py_XDECREF(descr);
1173
2.86k
            return -1;
1174
4.52k
    }
1175
4.52k
}
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
1.53M
{
1187
1.53M
    _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1);
1188
1.53M
    PyTypeObject *owner_cls = Py_TYPE(owner);
1189
1190
1.53M
    assert(descr != NULL);
1191
1.53M
    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
1.53M
    unsigned long tp_flags = PyType_GetFlags(owner_cls);
1201
1.53M
    if (tp_flags & Py_TPFLAGS_INLINE_VALUES) {
1202
1.50M
        #ifndef Py_GIL_DISABLED
1203
1.50M
        assert(_PyDictKeys_StringLookup(
1204
1.50M
                   ((PyHeapTypeObject *)owner_cls)->ht_cached_keys, name) < 0);
1205
1.50M
        #endif
1206
1.50M
        if (shared_keys_version == 0) {
1207
0
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
1208
0
            return 0;
1209
0
        }
1210
1.50M
        write_u32(cache->keys_version, shared_keys_version);
1211
1.50M
        specialize(instr, is_method ? LOAD_ATTR_METHOD_WITH_VALUES : LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES);
1212
1.50M
    }
1213
25.2k
    else {
1214
25.2k
        Py_ssize_t dictoffset;
1215
25.2k
        if (tp_flags & Py_TPFLAGS_MANAGED_DICT) {
1216
682
            dictoffset = MANAGED_DICT_OFFSET;
1217
682
        }
1218
24.5k
        else {
1219
24.5k
            dictoffset = owner_cls->tp_dictoffset;
1220
24.5k
            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.5k
        }
1225
25.2k
        if (dictoffset == 0) {
1226
22.1k
            specialize(instr, is_method ? LOAD_ATTR_METHOD_NO_DICT : LOAD_ATTR_NONDESCRIPTOR_NO_DICT);
1227
22.1k
        }
1228
3.08k
        else if (is_method) {
1229
2.64k
            PyObject **addr = (PyObject **)((char *)owner + dictoffset);
1230
2.64k
            PyObject *dict = FT_ATOMIC_LOAD_PTR_ACQUIRE(*addr);
1231
2.64k
            if (dict) {
1232
2.47k
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);
1233
2.47k
                return 0;
1234
2.47k
            }
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
166
            dictoffset -= MANAGED_DICT_OFFSET;
1239
166
            assert(((uint16_t)dictoffset) == dictoffset);
1240
166
            cache->dict_offset = (uint16_t)dictoffset;
1241
166
            specialize(instr, LOAD_ATTR_METHOD_LAZY_DICT);
1242
166
        }
1243
444
        else {
1244
444
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE);
1245
444
            return 0;
1246
444
        }
1247
25.2k
    }
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
1.52M
    write_u32(cache->type_version, tp_version);
1263
1.52M
    write_ptr(cache->descr, descr);
1264
1.52M
    return 1;
1265
1.53M
}
1266
1267
1268
static void
1269
specialize_load_global_lock_held(
1270
    PyObject *globals, PyObject *builtins,
1271
    _Py_CODEUNIT *instr, PyObject *name)
1272
24.0k
{
1273
24.0k
    assert(ENABLE_SPECIALIZATION_FT);
1274
24.0k
    assert(_PyOpcode_Caches[LOAD_GLOBAL] == INLINE_CACHE_ENTRIES_LOAD_GLOBAL);
1275
    /* Use inline cache */
1276
24.0k
    _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)(instr + 1);
1277
24.0k
    assert(PyUnicode_CheckExact(name));
1278
24.0k
    if (!PyDict_CheckExact(globals)) {
1279
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_DICT);
1280
0
        goto fail;
1281
0
    }
1282
24.0k
    PyDictKeysObject * globals_keys = ((PyDictObject *)globals)->ma_keys;
1283
24.0k
    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
24.0k
    Py_ssize_t index = _PyDictKeys_StringLookup(globals_keys, name);
1288
24.0k
    if (index == DKIX_ERROR) {
1289
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_EXPECTED_ERROR);
1290
0
        goto fail;
1291
0
    }
1292
24.0k
    PyInterpreterState *interp = _PyInterpreterState_GET();
1293
24.0k
    if (index != DKIX_EMPTY) {
1294
14.3k
        if (index != (uint16_t)index) {
1295
0
            SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1296
0
            goto fail;
1297
0
        }
1298
14.3k
        uint32_t keys_version = _PyDict_GetKeysVersionForCurrentState(
1299
14.3k
                interp, (PyDictObject*) globals);
1300
14.3k
        if (keys_version == 0) {
1301
0
            SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
1302
0
            goto fail;
1303
0
        }
1304
14.3k
        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
14.3k
        cache->index = (uint16_t)index;
1309
14.3k
        cache->module_keys_version = (uint16_t)keys_version;
1310
14.3k
        specialize(instr, LOAD_GLOBAL_MODULE);
1311
14.3k
        return;
1312
14.3k
    }
1313
9.77k
    if (!PyDict_CheckExact(builtins)) {
1314
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_DICT);
1315
0
        goto fail;
1316
0
    }
1317
9.77k
    PyDictKeysObject * builtin_keys = ((PyDictObject *)builtins)->ma_keys;
1318
9.77k
    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
9.77k
    index = _PyDictKeys_StringLookup(builtin_keys, name);
1323
9.77k
    if (index == DKIX_ERROR) {
1324
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_EXPECTED_ERROR);
1325
0
        goto fail;
1326
0
    }
1327
9.77k
    if (index != (uint16_t)index) {
1328
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1329
0
        goto fail;
1330
0
    }
1331
9.77k
    uint32_t globals_version = _PyDict_GetKeysVersionForCurrentState(
1332
9.77k
            interp, (PyDictObject*) globals);
1333
9.77k
    if (globals_version == 0) {
1334
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
1335
0
        goto fail;
1336
0
    }
1337
9.77k
    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
9.77k
    uint32_t builtins_version = _PyDict_GetKeysVersionForCurrentState(
1342
9.77k
            interp, (PyDictObject*) builtins);
1343
9.77k
    if (builtins_version == 0) {
1344
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
1345
0
        goto fail;
1346
0
    }
1347
9.77k
    if (builtins_version > UINT16_MAX) {
1348
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1349
0
        goto fail;
1350
0
    }
1351
9.77k
    cache->index = (uint16_t)index;
1352
9.77k
    cache->module_keys_version = (uint16_t)globals_version;
1353
9.77k
    cache->builtin_keys_version = (uint16_t)builtins_version;
1354
9.77k
    specialize(instr, LOAD_GLOBAL_BUILTIN);
1355
9.77k
    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
24.0k
{
1365
24.0k
    Py_BEGIN_CRITICAL_SECTION2(globals, builtins);
1366
24.0k
    specialize_load_global_lock_held(globals, builtins, instr, name);
1367
24.0k
    Py_END_CRITICAL_SECTION2();
1368
24.0k
}
1369
1370
static int
1371
241k
function_kind(PyCodeObject *code) {
1372
241k
    int flags = code->co_flags;
1373
241k
    if ((flags & (CO_VARKEYWORDS | CO_VARARGS)) || code->co_kwonlyargcount) {
1374
1.37k
        return SPEC_FAIL_CODE_COMPLEX_PARAMETERS;
1375
1.37k
    }
1376
240k
    if ((flags & CO_OPTIMIZED) == 0) {
1377
0
        return SPEC_FAIL_CODE_NOT_OPTIMIZED;
1378
0
    }
1379
240k
    return SIMPLE_FUNCTION;
1380
240k
}
1381
1382
/* Returning false indicates a failure. */
1383
static bool
1384
function_check_args(PyObject *o, int expected_argcount, int opcode)
1385
216k
{
1386
216k
    assert(Py_IS_TYPE(o, &PyFunction_Type));
1387
216k
    PyFunctionObject *func = (PyFunctionObject *)o;
1388
216k
    PyCodeObject *fcode = (PyCodeObject *)func->func_code;
1389
216k
    int kind = function_kind(fcode);
1390
216k
    if (kind != SIMPLE_FUNCTION) {
1391
0
        SPECIALIZATION_FAIL(opcode, kind);
1392
0
        return false;
1393
0
    }
1394
216k
    if (fcode->co_argcount != expected_argcount) {
1395
0
        SPECIALIZATION_FAIL(opcode, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1396
0
        return false;
1397
0
    }
1398
216k
    return true;
1399
216k
}
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
9.73k
{
1483
9.73k
    PyObject *container = PyStackRef_AsPyObjectBorrow(container_st);
1484
9.73k
    PyObject *sub = PyStackRef_AsPyObjectBorrow(sub_st);
1485
1486
9.73k
    assert(ENABLE_SPECIALIZATION_FT);
1487
9.73k
    PyTypeObject *container_type = Py_TYPE(container);
1488
9.73k
    if (container_type == &PyList_Type) {
1489
337
        if (PyLong_CheckExact(sub)) {
1490
324
            if (_PyLong_IsNonNegativeCompact((PyLongObject *)sub)
1491
188
                && ((PyLongObject *)sub)->long_value.ob_digit[0] < (size_t)PyList_GET_SIZE(container))
1492
188
            {
1493
188
                specialize(instr, STORE_SUBSCR_LIST_INT);
1494
188
                return;
1495
188
            }
1496
136
            else {
1497
136
                SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);
1498
136
                unspecialize(instr);
1499
136
                return;
1500
136
            }
1501
324
        }
1502
13
        else if (PySlice_Check(sub)) {
1503
13
            SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_LIST_SLICE);
1504
13
            unspecialize(instr);
1505
13
            return;
1506
13
        }
1507
0
        else {
1508
0
            SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
1509
0
            unspecialize(instr);
1510
0
            return;
1511
0
        }
1512
337
    }
1513
9.39k
    if (container_type == &PyDict_Type) {
1514
1.38k
        specialize(instr, STORE_SUBSCR_DICT);
1515
1.38k
        return;
1516
1.38k
    }
1517
8.01k
    SPECIALIZATION_FAIL(STORE_SUBSCR, store_subscr_fail_kind(container, sub));
1518
8.01k
    unspecialize(instr);
1519
8.01k
}
1520
1521
/* Returns a strong reference. */
1522
static PyObject *
1523
get_init_for_simple_managed_python_class(PyTypeObject *tp, unsigned int *tp_version)
1524
648
{
1525
648
    assert(tp->tp_new == PyBaseObject_Type.tp_new);
1526
648
    if (tp->tp_alloc != PyType_GenericAlloc) {
1527
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OVERRIDDEN);
1528
0
        return NULL;
1529
0
    }
1530
648
    unsigned long tp_flags = PyType_GetFlags(tp);
1531
648
    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
648
    PyObject *init = _PyType_LookupRefAndVersion(tp, &_Py_ID(__init__), tp_version);
1537
648
    if (init == NULL || !PyFunction_Check(init)) {
1538
266
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_INIT_NOT_PYTHON);
1539
266
        Py_XDECREF(init);
1540
266
        return NULL;
1541
266
    }
1542
382
    int kind = function_kind((PyCodeObject *)PyFunction_GET_CODE(init));
1543
382
    if (kind != SIMPLE_FUNCTION) {
1544
36
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_INIT_NOT_SIMPLE);
1545
36
        Py_DECREF(init);
1546
36
        return NULL;
1547
36
    }
1548
346
    return init;
1549
382
}
1550
1551
static int
1552
specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
1553
2.62k
{
1554
2.62k
    assert(PyType_Check(callable));
1555
2.62k
    PyTypeObject *tp = _PyType_CAST(callable);
1556
2.62k
    if (tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) {
1557
1.62k
        int oparg = instr->op.arg;
1558
1.62k
        if (nargs == 1 && oparg == 1) {
1559
1.06k
            if (tp == &PyUnicode_Type) {
1560
111
                specialize(instr, CALL_STR_1);
1561
111
                return 0;
1562
111
            }
1563
954
            else if (tp == &PyType_Type) {
1564
227
                specialize(instr, CALL_TYPE_1);
1565
227
                return 0;
1566
227
            }
1567
727
            else if (tp == &PyTuple_Type) {
1568
99
                specialize(instr, CALL_TUPLE_1);
1569
99
                return 0;
1570
99
            }
1571
1.06k
        }
1572
1.18k
        if (tp->tp_vectorcall != NULL) {
1573
811
            specialize(instr, CALL_BUILTIN_CLASS);
1574
811
            return 0;
1575
811
        }
1576
377
        goto generic;
1577
1.18k
    }
1578
1.00k
    if (Py_TYPE(tp) != &PyType_Type) {
1579
41
        goto generic;
1580
41
    }
1581
961
    if (tp->tp_new == PyBaseObject_Type.tp_new) {
1582
648
        unsigned int tp_version = 0;
1583
648
        PyObject *init = get_init_for_simple_managed_python_class(tp, &tp_version);
1584
648
        if (!tp_version) {
1585
7
            SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
1586
7
            Py_XDECREF(init);
1587
7
            return -1;
1588
7
        }
1589
641
        if (init != NULL && _PyType_CacheInitForSpecialization(
1590
339
                                (PyHeapTypeObject *)tp, init, tp_version)) {
1591
339
            _PyCallCache *cache = (_PyCallCache *)(instr + 1);
1592
339
            write_u32(cache->func_version, tp_version);
1593
339
            specialize(instr, CALL_ALLOC_AND_ENTER_INIT);
1594
339
            Py_DECREF(init);
1595
339
            return 0;
1596
339
        }
1597
302
        Py_XDECREF(init);
1598
302
    }
1599
1.03k
generic:
1600
1.03k
    specialize(instr, CALL_NON_PY_GENERAL);
1601
1.03k
    return 0;
1602
961
}
1603
1604
static int
1605
specialize_method_descriptor(PyMethodDescrObject *descr, PyObject *self_or_null,
1606
                             _Py_CODEUNIT *instr, int nargs)
1607
481k
{
1608
481k
    switch (descr->d_method->ml_flags &
1609
481k
        (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
1610
481k
        METH_KEYWORDS | METH_METHOD)) {
1611
2.48k
        case METH_NOARGS: {
1612
2.48k
            if (nargs != 1) {
1613
0
                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1614
0
                return -1;
1615
0
            }
1616
2.48k
            specialize(instr, CALL_METHOD_DESCRIPTOR_NOARGS);
1617
2.48k
            return 0;
1618
2.48k
        }
1619
393k
        case METH_O: {
1620
393k
            if (nargs != 2) {
1621
0
                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1622
0
                return -1;
1623
0
            }
1624
393k
            PyInterpreterState *interp = _PyInterpreterState_GET();
1625
393k
            PyObject *list_append = interp->callable_cache.list_append;
1626
393k
            _Py_CODEUNIT next = instr[INLINE_CACHE_ENTRIES_CALL + 1];
1627
393k
            bool pop = (next.op.code == POP_TOP);
1628
393k
            int oparg = instr->op.arg;
1629
393k
            if ((PyObject *)descr == list_append && oparg == 1 && pop) {
1630
387k
                assert(self_or_null != NULL);
1631
387k
                if (PyList_CheckExact(self_or_null)) {
1632
715
                    specialize(instr, CALL_LIST_APPEND);
1633
715
                    return 0;
1634
715
                }
1635
387k
            }
1636
393k
            specialize(instr, CALL_METHOD_DESCRIPTOR_O);
1637
393k
            return 0;
1638
393k
        }
1639
2.82k
        case METH_FASTCALL: {
1640
2.82k
            specialize(instr, CALL_METHOD_DESCRIPTOR_FAST);
1641
2.82k
            return 0;
1642
393k
        }
1643
81.5k
        case METH_FASTCALL | METH_KEYWORDS: {
1644
81.5k
            specialize(instr, CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS);
1645
81.5k
            return 0;
1646
393k
        }
1647
481k
    }
1648
308
    specialize(instr, CALL_NON_PY_GENERAL);
1649
308
    return 0;
1650
481k
}
1651
1652
static int
1653
specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
1654
                   bool bound_method)
1655
24.6k
{
1656
24.6k
    _PyCallCache *cache = (_PyCallCache *)(instr + 1);
1657
24.6k
    PyCodeObject *code = (PyCodeObject *)func->func_code;
1658
24.6k
    int kind = function_kind(code);
1659
    /* Don't specialize if PEP 523 is active */
1660
24.6k
    if (_PyInterpreterState_GET()->eval_frame) {
1661
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
1662
0
        return -1;
1663
0
    }
1664
24.6k
    if (func->vectorcall != _PyFunction_Vectorcall) {
1665
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_VECTORCALL);
1666
0
        return -1;
1667
0
    }
1668
24.6k
    int argcount = -1;
1669
24.6k
    if (kind == SPEC_FAIL_CODE_NOT_OPTIMIZED) {
1670
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CODE_NOT_OPTIMIZED);
1671
0
        return -1;
1672
0
    }
1673
24.6k
    if (kind == SIMPLE_FUNCTION) {
1674
23.5k
        argcount = code->co_argcount;
1675
23.5k
    }
1676
24.6k
    int version = _PyFunction_GetVersionForCurrentState(func);
1677
24.6k
    if (!_PyFunction_IsVersionValid(version)) {
1678
2
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
1679
2
        return -1;
1680
2
    }
1681
24.6k
    write_u32(cache->func_version, version);
1682
24.6k
    uint8_t opcode;
1683
24.6k
    if (argcount == nargs + bound_method) {
1684
23.2k
        opcode =
1685
23.2k
            bound_method ? CALL_BOUND_METHOD_EXACT_ARGS : CALL_PY_EXACT_ARGS;
1686
23.2k
    }
1687
1.35k
    else {
1688
1.35k
        opcode = bound_method ? CALL_BOUND_METHOD_GENERAL : CALL_PY_GENERAL;
1689
1.35k
    }
1690
24.6k
    specialize(instr, opcode);
1691
24.6k
    return 0;
1692
24.6k
}
1693
1694
1695
static int
1696
specialize_py_call_kw(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
1697
                   bool bound_method)
1698
318
{
1699
318
    _PyCallCache *cache = (_PyCallCache *)(instr + 1);
1700
318
    PyCodeObject *code = (PyCodeObject *)func->func_code;
1701
318
    int kind = function_kind(code);
1702
    /* Don't specialize if PEP 523 is active */
1703
318
    if (_PyInterpreterState_GET()->eval_frame) {
1704
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
1705
0
        return -1;
1706
0
    }
1707
318
    if (func->vectorcall != _PyFunction_Vectorcall) {
1708
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_VECTORCALL);
1709
0
        return -1;
1710
0
    }
1711
318
    if (kind == SPEC_FAIL_CODE_NOT_OPTIMIZED) {
1712
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CODE_NOT_OPTIMIZED);
1713
0
        return -1;
1714
0
    }
1715
318
    int version = _PyFunction_GetVersionForCurrentState(func);
1716
318
    if (!_PyFunction_IsVersionValid(version)) {
1717
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
1718
0
        return -1;
1719
0
    }
1720
318
    write_u32(cache->func_version, version);
1721
318
    specialize(instr, bound_method ? CALL_KW_BOUND_METHOD : CALL_KW_PY);
1722
318
    return 0;
1723
318
}
1724
1725
static int
1726
specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
1727
1.38M
{
1728
1.38M
    if (PyCFunction_GET_FUNCTION(callable) == NULL) {
1729
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OTHER);
1730
0
        return 1;
1731
0
    }
1732
1.38M
    switch (PyCFunction_GET_FLAGS(callable) &
1733
1.38M
        (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
1734
1.38M
        METH_KEYWORDS | METH_METHOD)) {
1735
1.37M
        case METH_O: {
1736
1.37M
            if (nargs != 1) {
1737
0
                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1738
0
                return 1;
1739
0
            }
1740
            /* len(o) */
1741
1.37M
            PyInterpreterState *interp = _PyInterpreterState_GET();
1742
1.37M
            if (callable == interp->callable_cache.len && instr->op.arg == 1) {
1743
1.41k
                specialize(instr, CALL_LEN);
1744
1.41k
                return 0;
1745
1.41k
            }
1746
1.36M
            specialize(instr, CALL_BUILTIN_O);
1747
1.36M
            return 0;
1748
1.37M
        }
1749
12.2k
        case METH_FASTCALL: {
1750
12.2k
            if (nargs == 2) {
1751
                /* isinstance(o1, o2) */
1752
2.37k
                PyInterpreterState *interp = _PyInterpreterState_GET();
1753
2.37k
                if (callable == interp->callable_cache.isinstance && instr->op.arg == 2) {
1754
1.22k
                    specialize(instr, CALL_ISINSTANCE);
1755
1.22k
                    return 0;
1756
1.22k
                }
1757
2.37k
            }
1758
11.0k
            specialize(instr, CALL_BUILTIN_FAST);
1759
11.0k
            return 0;
1760
12.2k
        }
1761
1.20k
        case METH_FASTCALL | METH_KEYWORDS: {
1762
1.20k
            specialize(instr, CALL_BUILTIN_FAST_WITH_KEYWORDS);
1763
1.20k
            return 0;
1764
12.2k
        }
1765
522
        default:
1766
522
            specialize(instr, CALL_NON_PY_GENERAL);
1767
522
            return 0;
1768
1.38M
    }
1769
1.38M
}
1770
1771
Py_NO_INLINE void
1772
_Py_Specialize_Call(_PyStackRef callable_st, _PyStackRef self_or_null_st, _Py_CODEUNIT *instr, int nargs)
1773
1.90M
{
1774
1.90M
    PyObject *callable = PyStackRef_AsPyObjectBorrow(callable_st);
1775
1776
1.90M
    assert(ENABLE_SPECIALIZATION_FT);
1777
1.90M
    assert(_PyOpcode_Caches[CALL] == INLINE_CACHE_ENTRIES_CALL);
1778
1.90M
    assert(_Py_OPCODE(*instr) != INSTRUMENTED_CALL);
1779
1.90M
    int fail;
1780
1.90M
    if (PyCFunction_CheckExact(callable)) {
1781
1.38M
        fail = specialize_c_call(callable, instr, nargs);
1782
1.38M
    }
1783
518k
    else if (PyFunction_Check(callable)) {
1784
21.4k
        fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs, false);
1785
21.4k
    }
1786
497k
    else if (PyType_Check(callable)) {
1787
2.62k
        fail = specialize_class_call(callable, instr, nargs);
1788
2.62k
    }
1789
494k
    else if (Py_IS_TYPE(callable, &PyMethodDescr_Type)) {
1790
481k
        PyObject *self_or_null = PyStackRef_AsPyObjectBorrow(self_or_null_st);
1791
481k
        fail = specialize_method_descriptor((PyMethodDescrObject *)callable,
1792
481k
                                            self_or_null, instr, nargs);
1793
481k
    }
1794
13.3k
    else if (PyMethod_Check(callable)) {
1795
3.20k
        PyObject *func = ((PyMethodObject *)callable)->im_func;
1796
3.20k
        if (PyFunction_Check(func)) {
1797
3.20k
            fail = specialize_py_call((PyFunctionObject *)func, instr, nargs, true);
1798
3.20k
        }
1799
0
        else {
1800
0
            SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_BOUND_METHOD);
1801
0
            fail = -1;
1802
0
        }
1803
3.20k
    }
1804
10.1k
    else {
1805
10.1k
        specialize(instr, CALL_NON_PY_GENERAL);
1806
10.1k
        fail = 0;
1807
10.1k
    }
1808
1.90M
    if (fail) {
1809
9
        unspecialize(instr);
1810
9
    }
1811
1.90M
}
1812
1813
Py_NO_INLINE void
1814
_Py_Specialize_CallKw(_PyStackRef callable_st, _Py_CODEUNIT *instr, int nargs)
1815
780
{
1816
780
    PyObject *callable = PyStackRef_AsPyObjectBorrow(callable_st);
1817
1818
780
    assert(ENABLE_SPECIALIZATION_FT);
1819
780
    assert(_PyOpcode_Caches[CALL_KW] == INLINE_CACHE_ENTRIES_CALL_KW);
1820
780
    assert(_Py_OPCODE(*instr) != INSTRUMENTED_CALL_KW);
1821
780
    int fail;
1822
780
    if (PyFunction_Check(callable)) {
1823
304
        fail = specialize_py_call_kw((PyFunctionObject *)callable, instr, nargs, false);
1824
304
    }
1825
476
    else if (PyMethod_Check(callable)) {
1826
14
        PyObject *func = ((PyMethodObject *)callable)->im_func;
1827
14
        if (PyFunction_Check(func)) {
1828
14
            fail = specialize_py_call_kw((PyFunctionObject *)func, instr, nargs, true);
1829
14
        }
1830
0
        else {
1831
0
            SPECIALIZATION_FAIL(CALL_KW, SPEC_FAIL_CALL_BOUND_METHOD);
1832
0
            fail = -1;
1833
0
        }
1834
14
    }
1835
462
    else {
1836
462
        specialize(instr, CALL_KW_NON_PY);
1837
462
        fail = 0;
1838
462
    }
1839
780
    if (fail) {
1840
0
        unspecialize(instr);
1841
0
    }
1842
780
}
1843
1844
#ifdef Py_STATS
1845
static int
1846
binary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs)
1847
{
1848
    switch (oparg) {
1849
        case NB_ADD:
1850
        case NB_INPLACE_ADD:
1851
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1852
                return SPEC_FAIL_BINARY_OP_ADD_DIFFERENT_TYPES;
1853
            }
1854
            return SPEC_FAIL_BINARY_OP_ADD_OTHER;
1855
        case NB_AND:
1856
        case NB_INPLACE_AND:
1857
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1858
                return SPEC_FAIL_BINARY_OP_AND_DIFFERENT_TYPES;
1859
            }
1860
            if (PyLong_CheckExact(lhs)) {
1861
                return SPEC_FAIL_BINARY_OP_AND_INT;
1862
            }
1863
            return SPEC_FAIL_BINARY_OP_AND_OTHER;
1864
        case NB_FLOOR_DIVIDE:
1865
        case NB_INPLACE_FLOOR_DIVIDE:
1866
            return SPEC_FAIL_BINARY_OP_FLOOR_DIVIDE;
1867
        case NB_LSHIFT:
1868
        case NB_INPLACE_LSHIFT:
1869
            return SPEC_FAIL_BINARY_OP_LSHIFT;
1870
        case NB_MATRIX_MULTIPLY:
1871
        case NB_INPLACE_MATRIX_MULTIPLY:
1872
            return SPEC_FAIL_BINARY_OP_MATRIX_MULTIPLY;
1873
        case NB_MULTIPLY:
1874
        case NB_INPLACE_MULTIPLY:
1875
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1876
                return SPEC_FAIL_BINARY_OP_MULTIPLY_DIFFERENT_TYPES;
1877
            }
1878
            return SPEC_FAIL_BINARY_OP_MULTIPLY_OTHER;
1879
        case NB_OR:
1880
        case NB_INPLACE_OR:
1881
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1882
                return SPEC_FAIL_BINARY_OP_OR_DIFFERENT_TYPES;
1883
            }
1884
            if (PyLong_CheckExact(lhs)) {
1885
                return SPEC_FAIL_BINARY_OP_OR_INT;
1886
            }
1887
            return SPEC_FAIL_BINARY_OP_OR;
1888
        case NB_POWER:
1889
        case NB_INPLACE_POWER:
1890
            return SPEC_FAIL_BINARY_OP_POWER;
1891
        case NB_REMAINDER:
1892
        case NB_INPLACE_REMAINDER:
1893
            return SPEC_FAIL_BINARY_OP_REMAINDER;
1894
        case NB_RSHIFT:
1895
        case NB_INPLACE_RSHIFT:
1896
            return SPEC_FAIL_BINARY_OP_RSHIFT;
1897
        case NB_SUBTRACT:
1898
        case NB_INPLACE_SUBTRACT:
1899
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1900
                return SPEC_FAIL_BINARY_OP_SUBTRACT_DIFFERENT_TYPES;
1901
            }
1902
            return SPEC_FAIL_BINARY_OP_SUBTRACT_OTHER;
1903
        case NB_TRUE_DIVIDE:
1904
        case NB_INPLACE_TRUE_DIVIDE:
1905
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1906
                return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_DIFFERENT_TYPES;
1907
            }
1908
            if (PyFloat_CheckExact(lhs)) {
1909
                return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_FLOAT;
1910
            }
1911
            return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_OTHER;
1912
        case NB_XOR:
1913
        case NB_INPLACE_XOR:
1914
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1915
                return SPEC_FAIL_BINARY_OP_XOR_DIFFERENT_TYPES;
1916
            }
1917
            if (PyLong_CheckExact(lhs)) {
1918
                return SPEC_FAIL_BINARY_OP_XOR_INT;
1919
            }
1920
            return SPEC_FAIL_BINARY_OP_XOR;
1921
        case NB_SUBSCR:
1922
            if (PyList_CheckExact(lhs)) {
1923
                if (PyLong_CheckExact(rhs) && !_PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
1924
                    return SPEC_FAIL_OUT_OF_RANGE;
1925
                }
1926
                if (PySlice_Check(rhs)) {
1927
                    return SPEC_FAIL_BINARY_OP_SUBSCR_LIST_SLICE;
1928
                }
1929
            }
1930
            if (PyTuple_CheckExact(lhs)) {
1931
                if (PyLong_CheckExact(rhs) && !_PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
1932
                    return SPEC_FAIL_OUT_OF_RANGE;
1933
                }
1934
                if (PySlice_Check(rhs)) {
1935
                    return SPEC_FAIL_BINARY_OP_SUBSCR_TUPLE_SLICE;
1936
                }
1937
            }
1938
            if (PyUnicode_CheckExact(lhs)) {
1939
                if (PyLong_CheckExact(rhs) && !_PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
1940
                    return SPEC_FAIL_OUT_OF_RANGE;
1941
                }
1942
                if (PySlice_Check(rhs)) {
1943
                    return SPEC_FAIL_BINARY_OP_SUBSCR_STRING_SLICE;
1944
                }
1945
            }
1946
            unsigned int tp_version;
1947
            PyTypeObject *container_type = Py_TYPE(lhs);
1948
            PyObject *descriptor = _PyType_LookupRefAndVersion(container_type, &_Py_ID(__getitem__), &tp_version);
1949
            if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {
1950
                if (!(container_type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
1951
                    Py_DECREF(descriptor);
1952
                    return SPEC_FAIL_BINARY_OP_SUBSCR_NOT_HEAP_TYPE;
1953
                }
1954
                PyFunctionObject *func = (PyFunctionObject *)descriptor;
1955
                PyCodeObject *fcode = (PyCodeObject *)func->func_code;
1956
                int kind = function_kind(fcode);
1957
                if (kind != SIMPLE_FUNCTION) {
1958
                    Py_DECREF(descriptor);
1959
                    return kind;
1960
                }
1961
                if (fcode->co_argcount != 2) {
1962
                    Py_DECREF(descriptor);
1963
                    return SPEC_FAIL_WRONG_NUMBER_ARGUMENTS;
1964
                }
1965
1966
                if (_PyInterpreterState_GET()->eval_frame) {
1967
                    /* Don't specialize if PEP 523 is active */
1968
                    Py_DECREF(descriptor);
1969
                    return SPEC_FAIL_OTHER;
1970
                }
1971
            }
1972
            Py_XDECREF(descriptor);
1973
1974
            if (PyObject_TypeCheck(lhs, &PyDictProxy_Type)) {
1975
                return SPEC_FAIL_BINARY_OP_SUBSCR_MAPPINGPROXY;
1976
            }
1977
1978
            if (PyObject_TypeCheck(lhs, &PyBytes_Type)) {
1979
                return SPEC_FAIL_BINARY_OP_SUBSCR_BYTES;
1980
            }
1981
1982
            if (PyObject_TypeCheck(lhs, &PyRange_Type)) {
1983
                return SPEC_FAIL_BINARY_OP_SUBSCR_RANGE;
1984
            }
1985
1986
            if (strcmp(container_type->tp_name, "array.array") == 0) {
1987
                return SPEC_FAIL_BINARY_OP_SUBSCR_ARRAY;
1988
            }
1989
1990
            if (strcmp(container_type->tp_name, "re.Match") == 0) {
1991
                return SPEC_FAIL_BINARY_OP_SUBSCR_RE_MATCH;
1992
            }
1993
1994
            if (strcmp(container_type->tp_name, "collections.deque") == 0) {
1995
                return SPEC_FAIL_BINARY_OP_SUBSCR_DEQUE;
1996
            }
1997
1998
            if (strcmp(_PyType_Name(container_type), "EnumDict") == 0) {
1999
                return SPEC_FAIL_BINARY_OP_SUBSCR_ENUMDICT;
2000
            }
2001
2002
            if (strcmp(container_type->tp_name, "StackSummary") == 0) {
2003
                return SPEC_FAIL_BINARY_OP_SUBSCR_STACKSUMMARY;
2004
            }
2005
2006
            if (strcmp(container_type->tp_name, "collections.defaultdict") == 0) {
2007
                return SPEC_FAIL_BINARY_OP_SUBSCR_DEFAULTDICT;
2008
            }
2009
2010
            if (strcmp(container_type->tp_name, "Counter") == 0) {
2011
                return SPEC_FAIL_BINARY_OP_SUBSCR_COUNTER;
2012
            }
2013
2014
            if (strcmp(container_type->tp_name, "collections.OrderedDict") == 0) {
2015
                return SPEC_FAIL_BINARY_OP_SUBSCR_ORDEREDDICT;
2016
            }
2017
2018
            if (strcmp(container_type->tp_name, "time.struct_time") == 0) {
2019
                return SPEC_FAIL_BINARY_OP_SUBSCR_STRUCTTIME;
2020
            }
2021
2022
            if (PySlice_Check(rhs)) {
2023
                return SPEC_FAIL_BINARY_OP_SUBSCR_OTHER_SLICE;
2024
            }
2025
            return SPEC_FAIL_BINARY_OP_SUBSCR;
2026
    }
2027
    Py_UNREACHABLE();
2028
}
2029
#endif
2030
2031
/** Binary Op Specialization Extensions */
2032
2033
/* long-long */
2034
2035
static inline int
2036
is_compactlong(PyObject *v)
2037
136M
{
2038
136M
    return PyLong_CheckExact(v) &&
2039
136M
           _PyLong_IsCompact((PyLongObject *)v);
2040
136M
}
2041
2042
static int
2043
compactlongs_guard(PyObject *lhs, PyObject *rhs)
2044
68.0M
{
2045
68.0M
    return (is_compactlong(lhs) && is_compactlong(rhs));
2046
68.0M
}
2047
2048
#define BITWISE_LONGS_ACTION(NAME, OP) \
2049
    static PyObject * \
2050
    (NAME)(PyObject *lhs, PyObject *rhs) \
2051
68.0M
    { \
2052
68.0M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2053
68.0M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2054
68.0M
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2055
68.0M
    }
specialize.c:compactlongs_or
Line
Count
Source
2051
1.16M
    { \
2052
1.16M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2053
1.16M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2054
1.16M
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2055
1.16M
    }
specialize.c:compactlongs_and
Line
Count
Source
2051
66.9M
    { \
2052
66.9M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2053
66.9M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2054
66.9M
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2055
66.9M
    }
specialize.c:compactlongs_xor
Line
Count
Source
2051
28
    { \
2052
28
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2053
28
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2054
28
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2055
28
    }
2056
BITWISE_LONGS_ACTION(compactlongs_or, |)
2057
BITWISE_LONGS_ACTION(compactlongs_and, &)
2058
BITWISE_LONGS_ACTION(compactlongs_xor, ^)
2059
#undef BITWISE_LONGS_ACTION
2060
2061
/* float-long */
2062
2063
static inline int
2064
float_compactlong_guard(PyObject *lhs, PyObject *rhs)
2065
5.16M
{
2066
5.16M
    return (
2067
5.16M
        PyFloat_CheckExact(lhs) &&
2068
5.15M
        !isnan(PyFloat_AsDouble(lhs)) &&
2069
5.16M
        PyLong_CheckExact(rhs) &&
2070
5.15M
        _PyLong_IsCompact((PyLongObject *)rhs)
2071
5.16M
    );
2072
5.16M
}
2073
2074
static inline int
2075
nonzero_float_compactlong_guard(PyObject *lhs, PyObject *rhs)
2076
2.57M
{
2077
2.57M
    return (
2078
2.57M
        float_compactlong_guard(lhs, rhs) && !PyLong_IsZero(rhs)
2079
2.57M
    );
2080
2.57M
}
2081
2082
#define FLOAT_LONG_ACTION(NAME, OP) \
2083
    static PyObject * \
2084
    (NAME)(PyObject *lhs, PyObject *rhs) \
2085
5.15M
    { \
2086
5.15M
        double lhs_val = PyFloat_AsDouble(lhs); \
2087
5.15M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2088
5.15M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2089
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
2085
2.57M
    { \
2086
2.57M
        double lhs_val = PyFloat_AsDouble(lhs); \
2087
2.57M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2088
2.57M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2089
2.57M
    }
specialize.c:float_compactlong_multiply
Line
Count
Source
2085
2.57M
    { \
2086
2.57M
        double lhs_val = PyFloat_AsDouble(lhs); \
2087
2.57M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2088
2.57M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2089
2.57M
    }
2090
FLOAT_LONG_ACTION(float_compactlong_add, +)
2091
FLOAT_LONG_ACTION(float_compactlong_subtract, -)
2092
FLOAT_LONG_ACTION(float_compactlong_multiply, *)
2093
FLOAT_LONG_ACTION(float_compactlong_true_div, /)
2094
#undef FLOAT_LONG_ACTION
2095
2096
/*  long-float */
2097
2098
static inline int
2099
compactlong_float_guard(PyObject *lhs, PyObject *rhs)
2100
9.80k
{
2101
9.80k
    return (
2102
9.80k
        PyLong_CheckExact(lhs) &&
2103
9.00k
        _PyLong_IsCompact((PyLongObject *)lhs) &&
2104
9.80k
        PyFloat_CheckExact(rhs) &&
2105
0
        !isnan(PyFloat_AsDouble(rhs))
2106
9.80k
    );
2107
9.80k
}
2108
2109
static inline int
2110
nonzero_compactlong_float_guard(PyObject *lhs, PyObject *rhs)
2111
15
{
2112
15
    return (
2113
15
        compactlong_float_guard(lhs, rhs) && PyFloat_AsDouble(rhs) != 0.0
2114
15
    );
2115
15
}
2116
2117
#define LONG_FLOAT_ACTION(NAME, OP) \
2118
    static PyObject * \
2119
    (NAME)(PyObject *lhs, PyObject *rhs) \
2120
0
    { \
2121
0
        double rhs_val = PyFloat_AsDouble(rhs); \
2122
0
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2123
0
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2124
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
2125
LONG_FLOAT_ACTION(compactlong_float_add, +)
2126
LONG_FLOAT_ACTION(compactlong_float_subtract, -)
2127
LONG_FLOAT_ACTION(compactlong_float_multiply, *)
2128
LONG_FLOAT_ACTION(compactlong_float_true_div, /)
2129
#undef LONG_FLOAT_ACTION
2130
2131
static _PyBinaryOpSpecializationDescr binaryop_extend_descrs[] = {
2132
    /* long-long arithmetic */
2133
    {NB_OR, compactlongs_guard, compactlongs_or},
2134
    {NB_AND, compactlongs_guard, compactlongs_and},
2135
    {NB_XOR, compactlongs_guard, compactlongs_xor},
2136
    {NB_INPLACE_OR, compactlongs_guard, compactlongs_or},
2137
    {NB_INPLACE_AND, compactlongs_guard, compactlongs_and},
2138
    {NB_INPLACE_XOR, compactlongs_guard, compactlongs_xor},
2139
2140
    /* float-long arithemetic */
2141
    {NB_ADD, float_compactlong_guard, float_compactlong_add},
2142
    {NB_SUBTRACT, float_compactlong_guard, float_compactlong_subtract},
2143
    {NB_TRUE_DIVIDE, nonzero_float_compactlong_guard, float_compactlong_true_div},
2144
    {NB_MULTIPLY, float_compactlong_guard, float_compactlong_multiply},
2145
2146
    /* float-float arithmetic */
2147
    {NB_ADD, compactlong_float_guard, compactlong_float_add},
2148
    {NB_SUBTRACT, compactlong_float_guard, compactlong_float_subtract},
2149
    {NB_TRUE_DIVIDE, nonzero_compactlong_float_guard, compactlong_float_true_div},
2150
    {NB_MULTIPLY, compactlong_float_guard, compactlong_float_multiply},
2151
};
2152
2153
static int
2154
binary_op_extended_specialization(PyObject *lhs, PyObject *rhs, int oparg,
2155
                                  _PyBinaryOpSpecializationDescr **descr)
2156
42.5k
{
2157
42.5k
    size_t n = sizeof(binaryop_extend_descrs)/sizeof(_PyBinaryOpSpecializationDescr);
2158
627k
    for (size_t i = 0; i < n; i++) {
2159
585k
        _PyBinaryOpSpecializationDescr *d = &binaryop_extend_descrs[i];
2160
585k
        if (d->oparg == oparg && d->guard(lhs, rhs)) {
2161
903
            *descr = d;
2162
903
            return 1;
2163
903
        }
2164
585k
    }
2165
41.6k
    return 0;
2166
42.5k
}
2167
2168
Py_NO_INLINE void
2169
_Py_Specialize_BinaryOp(_PyStackRef lhs_st, _PyStackRef rhs_st, _Py_CODEUNIT *instr,
2170
                        int oparg, _PyStackRef *locals)
2171
1.41M
{
2172
1.41M
    PyObject *lhs = PyStackRef_AsPyObjectBorrow(lhs_st);
2173
1.41M
    PyObject *rhs = PyStackRef_AsPyObjectBorrow(rhs_st);
2174
1.41M
    assert(ENABLE_SPECIALIZATION_FT);
2175
1.41M
    assert(_PyOpcode_Caches[BINARY_OP] == INLINE_CACHE_ENTRIES_BINARY_OP);
2176
2177
1.41M
    _PyBinaryOpCache *cache = (_PyBinaryOpCache *)(instr + 1);
2178
1.41M
    if (instr->op.code == BINARY_OP_EXTEND) {
2179
0
        write_ptr(cache->external_cache, NULL);
2180
0
    }
2181
2182
1.41M
    switch (oparg) {
2183
12.3k
        case NB_ADD:
2184
27.6k
        case NB_INPLACE_ADD:
2185
27.6k
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2186
66
                break;
2187
66
            }
2188
27.5k
            if (PyUnicode_CheckExact(lhs)) {
2189
498
                _Py_CODEUNIT next = instr[INLINE_CACHE_ENTRIES_BINARY_OP + 1];
2190
498
                bool to_store = (next.op.code == STORE_FAST);
2191
498
                if (to_store && PyStackRef_AsPyObjectBorrow(locals[next.op.arg]) == lhs) {
2192
117
                    specialize(instr, BINARY_OP_INPLACE_ADD_UNICODE);
2193
117
                    return;
2194
117
                }
2195
381
                specialize(instr, BINARY_OP_ADD_UNICODE);
2196
381
                return;
2197
498
            }
2198
27.0k
            if (_PyLong_CheckExactAndCompact(lhs) && _PyLong_CheckExactAndCompact(rhs)) {
2199
5.57k
                specialize(instr, BINARY_OP_ADD_INT);
2200
5.57k
                return;
2201
5.57k
            }
2202
21.4k
            if (PyFloat_CheckExact(lhs)) {
2203
0
                specialize(instr, BINARY_OP_ADD_FLOAT);
2204
0
                return;
2205
0
            }
2206
21.4k
            break;
2207
21.4k
        case NB_MULTIPLY:
2208
922
        case NB_INPLACE_MULTIPLY:
2209
922
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2210
289
                break;
2211
289
            }
2212
633
            if (_PyLong_CheckExactAndCompact(lhs) && _PyLong_CheckExactAndCompact(rhs)) {
2213
207
                specialize(instr, BINARY_OP_MULTIPLY_INT);
2214
207
                return;
2215
207
            }
2216
426
            if (PyFloat_CheckExact(lhs)) {
2217
2
                specialize(instr, BINARY_OP_MULTIPLY_FLOAT);
2218
2
                return;
2219
2
            }
2220
424
            break;
2221
717
        case NB_SUBTRACT:
2222
751
        case NB_INPLACE_SUBTRACT:
2223
751
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2224
0
                break;
2225
0
            }
2226
751
            if (_PyLong_CheckExactAndCompact(lhs) && _PyLong_CheckExactAndCompact(rhs)) {
2227
522
                specialize(instr, BINARY_OP_SUBTRACT_INT);
2228
522
                return;
2229
522
            }
2230
229
            if (PyFloat_CheckExact(lhs)) {
2231
0
                specialize(instr, BINARY_OP_SUBTRACT_FLOAT);
2232
0
                return;
2233
0
            }
2234
229
            break;
2235
1.37M
        case NB_SUBSCR:
2236
1.37M
            if (PyLong_CheckExact(rhs) && _PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
2237
1.36M
                if (PyList_CheckExact(lhs)) {
2238
20.0k
                    specialize(instr, BINARY_OP_SUBSCR_LIST_INT);
2239
20.0k
                    return;
2240
20.0k
                }
2241
1.34M
                if (PyTuple_CheckExact(lhs)) {
2242
751
                    specialize(instr, BINARY_OP_SUBSCR_TUPLE_INT);
2243
751
                    return;
2244
751
                }
2245
1.34M
                if (PyUnicode_CheckExact(lhs)) {
2246
1.33M
                    specialize(instr, BINARY_OP_SUBSCR_STR_INT);
2247
1.33M
                    return;
2248
1.33M
                }
2249
1.34M
            }
2250
11.3k
            if (PyDict_CheckExact(lhs)) {
2251
531
                specialize(instr, BINARY_OP_SUBSCR_DICT);
2252
531
                return;
2253
531
            }
2254
10.8k
            if (PyList_CheckExact(lhs) && PySlice_Check(rhs)) {
2255
54
                specialize(instr, BINARY_OP_SUBSCR_LIST_SLICE);
2256
54
                return;
2257
54
            }
2258
10.7k
            unsigned int tp_version;
2259
10.7k
            PyTypeObject *container_type = Py_TYPE(lhs);
2260
10.7k
            PyObject *descriptor = _PyType_LookupRefAndVersion(container_type, &_Py_ID(__getitem__), &tp_version);
2261
10.7k
            if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type &&
2262
181
                container_type->tp_flags & Py_TPFLAGS_HEAPTYPE)
2263
181
            {
2264
181
                PyFunctionObject *func = (PyFunctionObject *)descriptor;
2265
181
                PyCodeObject *fcode = (PyCodeObject *)func->func_code;
2266
181
                int kind = function_kind(fcode);
2267
181
                PyHeapTypeObject *ht = (PyHeapTypeObject *)container_type;
2268
181
                if (kind == SIMPLE_FUNCTION &&
2269
181
                    fcode->co_argcount == 2 &&
2270
181
                    !_PyInterpreterState_GET()->eval_frame && /* Don't specialize if PEP 523 is active */
2271
181
                    _PyType_CacheGetItemForSpecialization(ht, descriptor, (uint32_t)tp_version))
2272
181
                {
2273
181
                    specialize(instr, BINARY_OP_SUBSCR_GETITEM);
2274
181
                    Py_DECREF(descriptor);
2275
181
                    return;
2276
181
                }
2277
181
            }
2278
10.5k
            Py_XDECREF(descriptor);
2279
10.5k
            break;
2280
1.41M
    }
2281
2282
42.5k
    _PyBinaryOpSpecializationDescr *descr;
2283
42.5k
    if (binary_op_extended_specialization(lhs, rhs, oparg, &descr)) {
2284
903
        specialize(instr, BINARY_OP_EXTEND);
2285
903
        write_ptr(cache->external_cache, (void*)descr);
2286
903
        return;
2287
903
    }
2288
2289
41.6k
    SPECIALIZATION_FAIL(BINARY_OP, binary_op_fail_kind(oparg, lhs, rhs));
2290
41.6k
    unspecialize(instr);
2291
41.6k
    return;
2292
42.5k
}
2293
2294
2295
#ifdef Py_STATS
2296
static int
2297
compare_op_fail_kind(PyObject *lhs, PyObject *rhs)
2298
{
2299
    if (Py_TYPE(lhs) != Py_TYPE(rhs)) {
2300
        if (PyFloat_CheckExact(lhs) && PyLong_CheckExact(rhs)) {
2301
            return SPEC_FAIL_COMPARE_OP_FLOAT_LONG;
2302
        }
2303
        if (PyLong_CheckExact(lhs) && PyFloat_CheckExact(rhs)) {
2304
            return SPEC_FAIL_COMPARE_OP_LONG_FLOAT;
2305
        }
2306
        return SPEC_FAIL_COMPARE_OP_DIFFERENT_TYPES;
2307
    }
2308
    if (PyBytes_CheckExact(lhs)) {
2309
        return SPEC_FAIL_COMPARE_OP_BYTES;
2310
    }
2311
    if (PyTuple_CheckExact(lhs)) {
2312
        return SPEC_FAIL_COMPARE_OP_TUPLE;
2313
    }
2314
    if (PyList_CheckExact(lhs)) {
2315
        return SPEC_FAIL_COMPARE_OP_LIST;
2316
    }
2317
    if (PySet_CheckExact(lhs) || PyFrozenSet_CheckExact(lhs)) {
2318
        return SPEC_FAIL_COMPARE_OP_SET;
2319
    }
2320
    if (PyBool_Check(lhs)) {
2321
        return SPEC_FAIL_COMPARE_OP_BOOL;
2322
    }
2323
    if (Py_TYPE(lhs)->tp_richcompare == PyBaseObject_Type.tp_richcompare) {
2324
        return SPEC_FAIL_COMPARE_OP_BASEOBJECT;
2325
    }
2326
    return SPEC_FAIL_OTHER;
2327
}
2328
#endif   // Py_STATS
2329
2330
Py_NO_INLINE void
2331
_Py_Specialize_CompareOp(_PyStackRef lhs_st, _PyStackRef rhs_st, _Py_CODEUNIT *instr,
2332
                         int oparg)
2333
12.2k
{
2334
12.2k
    PyObject *lhs = PyStackRef_AsPyObjectBorrow(lhs_st);
2335
12.2k
    PyObject *rhs = PyStackRef_AsPyObjectBorrow(rhs_st);
2336
12.2k
    uint8_t specialized_op;
2337
2338
12.2k
    assert(ENABLE_SPECIALIZATION_FT);
2339
12.2k
    assert(_PyOpcode_Caches[COMPARE_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP);
2340
    // All of these specializations compute boolean values, so they're all valid
2341
    // regardless of the fifth-lowest oparg bit.
2342
12.2k
    if (Py_TYPE(lhs) != Py_TYPE(rhs)) {
2343
3.06k
        SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
2344
3.06k
        goto failure;
2345
3.06k
    }
2346
9.21k
    if (PyFloat_CheckExact(lhs)) {
2347
31
        specialized_op = COMPARE_OP_FLOAT;
2348
31
        goto success;
2349
31
    }
2350
9.18k
    if (PyLong_CheckExact(lhs)) {
2351
4.35k
        if (_PyLong_IsCompact((PyLongObject *)lhs) && _PyLong_IsCompact((PyLongObject *)rhs)) {
2352
2.59k
            specialized_op = COMPARE_OP_INT;
2353
2.59k
            goto success;
2354
2.59k
        }
2355
1.76k
        else {
2356
1.76k
            SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_BIG_INT);
2357
1.76k
            goto failure;
2358
1.76k
        }
2359
4.35k
    }
2360
4.82k
    if (PyUnicode_CheckExact(lhs)) {
2361
3.68k
        int cmp = oparg >> 5;
2362
3.68k
        if (cmp != Py_EQ && cmp != Py_NE) {
2363
1.76k
            SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_STRING);
2364
1.76k
            goto failure;
2365
1.76k
        }
2366
1.91k
        else {
2367
1.91k
            specialized_op = COMPARE_OP_STR;
2368
1.91k
            goto success;
2369
1.91k
        }
2370
3.68k
    }
2371
1.14k
    SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
2372
7.73k
failure:
2373
7.73k
    unspecialize(instr);
2374
7.73k
    return;
2375
4.54k
success:
2376
4.54k
    specialize(instr, specialized_op);
2377
4.54k
}
2378
2379
#ifdef Py_STATS
2380
static int
2381
unpack_sequence_fail_kind(PyObject *seq)
2382
{
2383
    if (PySequence_Check(seq)) {
2384
        return SPEC_FAIL_UNPACK_SEQUENCE_SEQUENCE;
2385
    }
2386
    if (PyIter_Check(seq)) {
2387
        return SPEC_FAIL_UNPACK_SEQUENCE_ITERATOR;
2388
    }
2389
    return SPEC_FAIL_OTHER;
2390
}
2391
#endif   // Py_STATS
2392
2393
Py_NO_INLINE void
2394
_Py_Specialize_UnpackSequence(_PyStackRef seq_st, _Py_CODEUNIT *instr, int oparg)
2395
5.95k
{
2396
5.95k
    PyObject *seq = PyStackRef_AsPyObjectBorrow(seq_st);
2397
2398
5.95k
    assert(ENABLE_SPECIALIZATION_FT);
2399
5.95k
    assert(_PyOpcode_Caches[UNPACK_SEQUENCE] ==
2400
5.95k
           INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE);
2401
5.95k
    if (PyTuple_CheckExact(seq)) {
2402
1.61k
        if (PyTuple_GET_SIZE(seq) != oparg) {
2403
0
            SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_EXPECTED_ERROR);
2404
0
            unspecialize(instr);
2405
0
            return;
2406
0
        }
2407
1.61k
        if (PyTuple_GET_SIZE(seq) == 2) {
2408
940
            specialize(instr, UNPACK_SEQUENCE_TWO_TUPLE);
2409
940
            return;
2410
940
        }
2411
674
        specialize(instr, UNPACK_SEQUENCE_TUPLE);
2412
674
        return;
2413
1.61k
    }
2414
4.34k
    if (PyList_CheckExact(seq)) {
2415
3.98k
        if (PyList_GET_SIZE(seq) != oparg) {
2416
2.71k
            SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_EXPECTED_ERROR);
2417
2.71k
            unspecialize(instr);
2418
2.71k
            return;
2419
2.71k
        }
2420
1.26k
        specialize(instr, UNPACK_SEQUENCE_LIST);
2421
1.26k
        return;
2422
3.98k
    }
2423
365
    SPECIALIZATION_FAIL(UNPACK_SEQUENCE, unpack_sequence_fail_kind(seq));
2424
365
    unspecialize(instr);
2425
365
}
2426
2427
#ifdef Py_STATS
2428
int
2429
 _PySpecialization_ClassifyIterator(PyObject *iter)
2430
{
2431
    if (PyGen_CheckExact(iter)) {
2432
        return SPEC_FAIL_ITER_GENERATOR;
2433
    }
2434
    if (PyCoro_CheckExact(iter)) {
2435
        return SPEC_FAIL_ITER_COROUTINE;
2436
    }
2437
    if (PyAsyncGen_CheckExact(iter)) {
2438
        return SPEC_FAIL_ITER_ASYNC_GENERATOR;
2439
    }
2440
    if (PyAsyncGenASend_CheckExact(iter)) {
2441
        return SPEC_FAIL_ITER_ASYNC_GENERATOR_SEND;
2442
    }
2443
    PyTypeObject *t = Py_TYPE(iter);
2444
    if (t == &PyListIter_Type) {
2445
        return SPEC_FAIL_ITER_LIST;
2446
    }
2447
    if (t == &PyTupleIter_Type) {
2448
        return SPEC_FAIL_ITER_TUPLE;
2449
    }
2450
    if (t == &PyDictIterKey_Type) {
2451
        return SPEC_FAIL_ITER_DICT_KEYS;
2452
    }
2453
    if (t == &PyDictIterValue_Type) {
2454
        return SPEC_FAIL_ITER_DICT_VALUES;
2455
    }
2456
    if (t == &PyDictIterItem_Type) {
2457
        return SPEC_FAIL_ITER_DICT_ITEMS;
2458
    }
2459
    if (t == &PySetIter_Type) {
2460
        return SPEC_FAIL_ITER_SET;
2461
    }
2462
    if (t == &PyUnicodeIter_Type) {
2463
        return SPEC_FAIL_ITER_STRING;
2464
    }
2465
    if (t == &PyBytesIter_Type) {
2466
        return SPEC_FAIL_ITER_BYTES;
2467
    }
2468
    if (t == &PyRangeIter_Type) {
2469
        return SPEC_FAIL_ITER_RANGE;
2470
    }
2471
    if (t == &PyEnum_Type) {
2472
        return SPEC_FAIL_ITER_ENUMERATE;
2473
    }
2474
    if (t == &PyMap_Type) {
2475
        return SPEC_FAIL_ITER_MAP;
2476
    }
2477
    if (t == &PyZip_Type) {
2478
        return SPEC_FAIL_ITER_ZIP;
2479
    }
2480
    if (t == &PySeqIter_Type) {
2481
        return SPEC_FAIL_ITER_SEQ_ITER;
2482
    }
2483
    if (t == &PyListRevIter_Type) {
2484
        return SPEC_FAIL_ITER_REVERSED_LIST;
2485
    }
2486
    if (t == &_PyUnicodeASCIIIter_Type) {
2487
        return SPEC_FAIL_ITER_ASCII_STRING;
2488
    }
2489
    const char *name = t->tp_name;
2490
    if (strncmp(name, "itertools", 9) == 0) {
2491
        return SPEC_FAIL_ITER_ITERTOOLS;
2492
    }
2493
    if (strncmp(name, "callable_iterator", 17) == 0) {
2494
        return SPEC_FAIL_ITER_CALLABLE;
2495
    }
2496
    return SPEC_FAIL_OTHER;
2497
}
2498
#endif   // Py_STATS
2499
2500
Py_NO_INLINE void
2501
_Py_Specialize_ForIter(_PyStackRef iter, _PyStackRef null_or_index, _Py_CODEUNIT *instr, int oparg)
2502
76.0k
{
2503
76.0k
    assert(ENABLE_SPECIALIZATION_FT);
2504
76.0k
    assert(_PyOpcode_Caches[FOR_ITER] == INLINE_CACHE_ENTRIES_FOR_ITER);
2505
76.0k
    PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
2506
76.0k
    PyTypeObject *tp = Py_TYPE(iter_o);
2507
2508
76.0k
    if (PyStackRef_IsNull(null_or_index)) {
2509
#ifdef Py_GIL_DISABLED
2510
        // Only specialize for uniquely referenced iterators, so that we know
2511
        // they're only referenced by this one thread. This is more limiting
2512
        // than we need (even `it = iter(mylist); for item in it:` won't get
2513
        // specialized) but we don't have a way to check whether we're the only
2514
        // _thread_ who has access to the object.
2515
        if (!_PyObject_IsUniquelyReferenced(iter_o)) {
2516
            goto failure;
2517
        }
2518
#endif
2519
69.4k
        if (tp == &PyRangeIter_Type) {
2520
133
            specialize(instr, FOR_ITER_RANGE);
2521
133
            return;
2522
133
        }
2523
69.3k
        else if (tp == &PyGen_Type && oparg <= SHRT_MAX) {
2524
            // Generators are very much not thread-safe, so don't worry about
2525
            // the specialization not being thread-safe.
2526
406
            assert(instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == END_FOR  ||
2527
406
                instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == INSTRUMENTED_END_FOR
2528
406
            );
2529
            /* Don't specialize if PEP 523 is active */
2530
406
            if (_PyInterpreterState_GET()->eval_frame) {
2531
0
                goto failure;
2532
0
            }
2533
406
            specialize(instr, FOR_ITER_GEN);
2534
406
            return;
2535
406
        }
2536
69.4k
    }
2537
6.57k
    else {
2538
6.57k
        if (tp == &PyList_Type) {
2539
#ifdef Py_GIL_DISABLED
2540
            // Only specialize for lists owned by this thread or shared
2541
            if (!_Py_IsOwnedByCurrentThread(iter_o) && !_PyObject_GC_IS_SHARED(iter_o)) {
2542
                goto failure;
2543
            }
2544
#endif
2545
5.59k
            specialize(instr, FOR_ITER_LIST);
2546
5.59k
            return;
2547
5.59k
        }
2548
977
        else if (tp == &PyTuple_Type) {
2549
977
            specialize(instr, FOR_ITER_TUPLE);
2550
977
            return;
2551
977
        }
2552
6.57k
    }
2553
68.9k
failure:
2554
68.9k
    SPECIALIZATION_FAIL(FOR_ITER,
2555
68.9k
                        _PySpecialization_ClassifyIterator(iter_o));
2556
68.9k
    unspecialize(instr);
2557
68.9k
}
2558
2559
Py_NO_INLINE void
2560
_Py_Specialize_Send(_PyStackRef receiver_st, _Py_CODEUNIT *instr)
2561
3.07k
{
2562
3.07k
    PyObject *receiver = PyStackRef_AsPyObjectBorrow(receiver_st);
2563
2564
3.07k
    assert(ENABLE_SPECIALIZATION_FT);
2565
3.07k
    assert(_PyOpcode_Caches[SEND] == INLINE_CACHE_ENTRIES_SEND);
2566
3.07k
    PyTypeObject *tp = Py_TYPE(receiver);
2567
3.07k
    if (tp == &PyGen_Type || tp == &PyCoro_Type) {
2568
        /* Don't specialize if PEP 523 is active */
2569
797
        if (_PyInterpreterState_GET()->eval_frame) {
2570
0
            SPECIALIZATION_FAIL(SEND, SPEC_FAIL_OTHER);
2571
0
            goto failure;
2572
0
        }
2573
797
        specialize(instr, SEND_GEN);
2574
797
        return;
2575
797
    }
2576
2.27k
    SPECIALIZATION_FAIL(SEND,
2577
2.27k
                        _PySpecialization_ClassifyIterator(receiver));
2578
2.27k
failure:
2579
2.27k
    unspecialize(instr);
2580
2.27k
}
2581
2582
#ifdef Py_STATS
2583
static int
2584
to_bool_fail_kind(PyObject *value)
2585
{
2586
    if (PyByteArray_CheckExact(value)) {
2587
        return SPEC_FAIL_TO_BOOL_BYTEARRAY;
2588
    }
2589
    if (PyBytes_CheckExact(value)) {
2590
        return SPEC_FAIL_TO_BOOL_BYTES;
2591
    }
2592
    if (PyDict_CheckExact(value)) {
2593
        return SPEC_FAIL_TO_BOOL_DICT;
2594
    }
2595
    if (PyFloat_CheckExact(value)) {
2596
        return SPEC_FAIL_TO_BOOL_FLOAT;
2597
    }
2598
    if (PyMemoryView_Check(value)) {
2599
        return SPEC_FAIL_TO_BOOL_MEMORY_VIEW;
2600
    }
2601
    if (PyAnySet_CheckExact(value)) {
2602
        return SPEC_FAIL_TO_BOOL_SET;
2603
    }
2604
    if (PyTuple_CheckExact(value)) {
2605
        return SPEC_FAIL_TO_BOOL_TUPLE;
2606
    }
2607
    return SPEC_FAIL_OTHER;
2608
}
2609
#endif  // Py_STATS
2610
2611
static int
2612
check_type_always_true(PyTypeObject *ty)
2613
77.7k
{
2614
77.7k
    PyNumberMethods *nb = ty->tp_as_number;
2615
77.7k
    if (nb && nb->nb_bool) {
2616
34
        return SPEC_FAIL_TO_BOOL_NUMBER;
2617
34
    }
2618
77.7k
    PyMappingMethods *mp = ty->tp_as_mapping;
2619
77.7k
    if (mp && mp->mp_length) {
2620
5.72k
        return SPEC_FAIL_TO_BOOL_MAPPING;
2621
5.72k
    }
2622
71.9k
    PySequenceMethods *sq = ty->tp_as_sequence;
2623
71.9k
    if (sq && sq->sq_length) {
2624
5.65k
      return SPEC_FAIL_TO_BOOL_SEQUENCE;
2625
5.65k
    }
2626
66.3k
    return 0;
2627
71.9k
}
2628
2629
Py_NO_INLINE void
2630
_Py_Specialize_ToBool(_PyStackRef value_o, _Py_CODEUNIT *instr)
2631
243k
{
2632
243k
    assert(ENABLE_SPECIALIZATION_FT);
2633
243k
    assert(_PyOpcode_Caches[TO_BOOL] == INLINE_CACHE_ENTRIES_TO_BOOL);
2634
243k
    _PyToBoolCache *cache = (_PyToBoolCache *)(instr + 1);
2635
243k
    PyObject *value = PyStackRef_AsPyObjectBorrow(value_o);
2636
243k
    uint8_t specialized_op;
2637
243k
    if (PyBool_Check(value)) {
2638
21.0k
        specialized_op = TO_BOOL_BOOL;
2639
21.0k
        goto success;
2640
21.0k
    }
2641
222k
    if (PyLong_CheckExact(value)) {
2642
4.00k
        specialized_op = TO_BOOL_INT;
2643
4.00k
        goto success;
2644
4.00k
    }
2645
218k
    if (PyList_CheckExact(value)) {
2646
402
        specialized_op = TO_BOOL_LIST;
2647
402
        goto success;
2648
402
    }
2649
218k
    if (Py_IsNone(value)) {
2650
96.0k
        specialized_op = TO_BOOL_NONE;
2651
96.0k
        goto success;
2652
96.0k
    }
2653
122k
    if (PyUnicode_CheckExact(value)) {
2654
40.5k
        specialized_op = TO_BOOL_STR;
2655
40.5k
        goto success;
2656
40.5k
    }
2657
81.7k
    if (PyType_HasFeature(Py_TYPE(value), Py_TPFLAGS_HEAPTYPE)) {
2658
77.7k
        unsigned int version = 0;
2659
77.7k
        int err = _PyType_Validate(Py_TYPE(value), check_type_always_true, &version);
2660
77.7k
        if (err < 0) {
2661
0
            SPECIALIZATION_FAIL(TO_BOOL, SPEC_FAIL_OUT_OF_VERSIONS);
2662
0
            goto failure;
2663
0
        }
2664
77.7k
        else if (err > 0) {
2665
11.4k
            SPECIALIZATION_FAIL(TO_BOOL, err);
2666
11.4k
            goto failure;
2667
11.4k
        }
2668
2669
77.7k
        assert(err == 0);
2670
66.3k
        assert(version);
2671
66.3k
        write_u32(cache->version, version);
2672
66.3k
        specialized_op = TO_BOOL_ALWAYS_TRUE;
2673
66.3k
        goto success;
2674
77.7k
    }
2675
2676
4.03k
    SPECIALIZATION_FAIL(TO_BOOL, to_bool_fail_kind(value));
2677
15.4k
failure:
2678
15.4k
    unspecialize(instr);
2679
15.4k
    return;
2680
228k
success:
2681
228k
    specialize(instr, specialized_op);
2682
228k
}
2683
2684
#ifdef Py_STATS
2685
static int
2686
containsop_fail_kind(PyObject *value) {
2687
    if (PyUnicode_CheckExact(value)) {
2688
        return SPEC_FAIL_CONTAINS_OP_STR;
2689
    }
2690
    if (PyList_CheckExact(value)) {
2691
        return SPEC_FAIL_CONTAINS_OP_LIST;
2692
    }
2693
    if (PyTuple_CheckExact(value)) {
2694
        return SPEC_FAIL_CONTAINS_OP_TUPLE;
2695
    }
2696
    if (PyType_Check(value)) {
2697
        return SPEC_FAIL_CONTAINS_OP_USER_CLASS;
2698
    }
2699
    return SPEC_FAIL_OTHER;
2700
}
2701
#endif
2702
2703
Py_NO_INLINE void
2704
_Py_Specialize_ContainsOp(_PyStackRef value_st, _Py_CODEUNIT *instr)
2705
32.4k
{
2706
32.4k
    PyObject *value = PyStackRef_AsPyObjectBorrow(value_st);
2707
2708
32.4k
    assert(ENABLE_SPECIALIZATION_FT);
2709
32.4k
    assert(_PyOpcode_Caches[CONTAINS_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP);
2710
32.4k
    if (PyDict_CheckExact(value)) {
2711
489
        specialize(instr, CONTAINS_OP_DICT);
2712
489
        return;
2713
489
    }
2714
31.9k
    if (PySet_CheckExact(value) || PyFrozenSet_CheckExact(value)) {
2715
472
        specialize(instr, CONTAINS_OP_SET);
2716
472
        return;
2717
472
    }
2718
2719
31.5k
    SPECIALIZATION_FAIL(CONTAINS_OP, containsop_fail_kind(value));
2720
31.5k
    unspecialize(instr);
2721
31.5k
    return;
2722
31.9k
}
2723
2724
#ifdef Py_STATS
2725
void
2726
_Py_GatherStats_GetIter(_PyStackRef iterable)
2727
{
2728
    PyTypeObject *tp = PyStackRef_TYPE(iterable);
2729
    int kind = SPEC_FAIL_OTHER;
2730
    if (tp == &PyTuple_Type) {
2731
        kind = SPEC_FAIL_ITER_TUPLE;
2732
    }
2733
    else if (tp == &PyList_Type) {
2734
        kind = SPEC_FAIL_ITER_LIST;
2735
    }
2736
    else if (tp == &PyDict_Type) {
2737
        kind = SPEC_FAIL_ITER_DICT_KEYS;
2738
    }
2739
    else if (tp == &PySet_Type) {
2740
        kind = SPEC_FAIL_ITER_SET;
2741
    }
2742
    else if (tp == &PyBytes_Type) {
2743
        kind = SPEC_FAIL_ITER_BYTES;
2744
    }
2745
    else if (tp == &PyEnum_Type) {
2746
        kind = SPEC_FAIL_ITER_ENUMERATE;
2747
    }
2748
    else if (tp == &PyUnicode_Type) {
2749
        kind = SPEC_FAIL_ITER_STRING;
2750
    }
2751
    else if (tp == &PyGen_Type) {
2752
        kind = SPEC_FAIL_ITER_GENERATOR;
2753
    }
2754
    else if (tp == &PyCoro_Type) {
2755
        kind = SPEC_FAIL_ITER_COROUTINE;
2756
    }
2757
    else if (tp == &PyAsyncGen_Type) {
2758
        kind = SPEC_FAIL_ITER_ASYNC_GENERATOR;
2759
    }
2760
    else if (tp == &_PyAsyncGenASend_Type) {
2761
        kind = SPEC_FAIL_ITER_ASYNC_GENERATOR_SEND;
2762
    }
2763
    else if (tp->tp_iter == PyObject_SelfIter) {
2764
        kind = SPEC_FAIL_ITER_SELF;
2765
    }
2766
    SPECIALIZATION_FAIL(GET_ITER, kind);
2767
}
2768
#endif
2769
2770
2771
/* Code init cleanup.
2772
 * CALL_ALLOC_AND_ENTER_INIT will set up
2773
 * the frame to execute the EXIT_INIT_CHECK
2774
 * instruction.
2775
 * Ends with a RESUME so that it is not traced.
2776
 * This is used as a plain code object, not a function,
2777
 * so must not access globals or builtins.
2778
 * There are a few other constraints imposed on the code
2779
 * by the free-threaded build:
2780
 *
2781
 * 1. The RESUME instruction must not be executed. Otherwise we may attempt to
2782
 *    free the statically allocated TLBC array.
2783
 * 2. It must contain no specializable instructions. Specializing multiple
2784
 *    copies of the same bytecode is not thread-safe in free-threaded builds.
2785
 *
2786
 * This should be dynamically allocated if either of those restrictions need to
2787
 * be lifted.
2788
 */
2789
2790
#define NO_LOC_4 (128 | (PY_CODE_LOCATION_INFO_NONE << 3) | 3)
2791
2792
static const PyBytesObject no_location = {
2793
    PyVarObject_HEAD_INIT(&PyBytes_Type, 1)
2794
    .ob_sval = { NO_LOC_4 }
2795
};
2796
2797
#ifdef Py_GIL_DISABLED
2798
static _PyCodeArray init_cleanup_tlbc = {
2799
    .size = 1,
2800
    .entries = {(char*) &_Py_InitCleanup.co_code_adaptive},
2801
};
2802
#endif
2803
2804
const struct _PyCode8 _Py_InitCleanup = {
2805
    _PyVarObject_HEAD_INIT(&PyCode_Type, 3),
2806
    .co_consts = (PyObject *)&_Py_SINGLETON(tuple_empty),
2807
    .co_names = (PyObject *)&_Py_SINGLETON(tuple_empty),
2808
    .co_exceptiontable = (PyObject *)&_Py_SINGLETON(bytes_empty),
2809
    .co_flags = CO_OPTIMIZED | CO_NO_MONITORING_EVENTS,
2810
    .co_localsplusnames = (PyObject *)&_Py_SINGLETON(tuple_empty),
2811
    .co_localspluskinds = (PyObject *)&_Py_SINGLETON(bytes_empty),
2812
    .co_filename = &_Py_ID(__init__),
2813
    .co_name = &_Py_ID(__init__),
2814
    .co_qualname = &_Py_ID(__init__),
2815
    .co_linetable = (PyObject *)&no_location,
2816
    ._co_firsttraceable = 4,
2817
    .co_stacksize = 2,
2818
    .co_framesize = 2 + FRAME_SPECIALS_SIZE,
2819
#ifdef Py_GIL_DISABLED
2820
    .co_tlbc = &init_cleanup_tlbc,
2821
#endif
2822
    .co_code_adaptive = {
2823
        EXIT_INIT_CHECK, 0,
2824
        RETURN_VALUE, 0,
2825
        RESUME, RESUME_AT_FUNC_START,
2826
    }
2827
};