Coverage Report

Created: 2026-10-31 06:21

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