Coverage Report

Created: 2026-04-12 06:54

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