Coverage Report

Created: 2026-01-17 06:16

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