Coverage Report

Created: 2026-09-01 06:32

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