Coverage Report

Created: 2026-03-08 06:40

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