Coverage Report

Created: 2026-10-17 06:15

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
230k
#  define SPECIALIZATION_FAIL(opcode, kind) ((void)0)
45
#endif  // Py_STATS
46
47
static void
48
fixup_getiter(_Py_CODEUNIT *instruction, int flags)
49
29.3k
{
50
    // Compiler can't know if types.coroutine() will be called,
51
    // so fix up here
52
29.3k
    if (instruction->op.arg) {
53
603
        if (flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE)) {
54
0
            instruction->op.arg = GET_ITER_YIELD_FROM_NO_CHECK;
55
0
        }
56
603
        else {
57
603
            instruction->op.arg = GET_ITER_YIELD_FROM_CORO_CHECK;
58
603
        }
59
603
    }
60
29.3k
}
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
170k
{
66
170k
    #if ENABLE_SPECIALIZATION
67
170k
    _Py_BackoffCounter jump_counter, adaptive_counter, resume_counter;
68
170k
    if (enable_counters) {
69
170k
        PyThreadState *tstate = _PyThreadState_GET();
70
170k
        PyInterpreterState *interp = tstate->interp;
71
170k
        jump_counter = initial_jump_backoff_counter(&interp->opt_config);
72
170k
        adaptive_counter = adaptive_counter_warmup();
73
170k
        resume_counter = initial_resume_backoff_counter(&interp->opt_config);
74
170k
    }
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
170k
    int opcode = 0;
81
170k
    int oparg = 0;
82
    /* The last code unit cannot have a cache, so we don't need to check it */
83
7.24M
    for (Py_ssize_t i = 0; i < size-1; i++) {
84
7.07M
        opcode = instructions[i].op.code;
85
7.07M
        int caches = _PyOpcode_Caches[opcode];
86
7.07M
        oparg = (oparg << 8) | instructions[i].op.arg;
87
7.07M
        if (opcode == GET_ITER) {
88
29.3k
            fixup_getiter(&instructions[i], flags);
89
29.3k
        }
90
7.07M
        if (caches) {
91
            // The initial value depends on the opcode
92
2.27M
            switch (opcode) {
93
63.2k
                case JUMP_BACKWARD:
94
63.2k
                    instructions[i + 1].counter = jump_counter;
95
63.2k
                    break;
96
195k
                case RESUME:
97
195k
                    instructions[i + 1].counter = resume_counter;
98
195k
                    break;
99
133k
                case POP_JUMP_IF_FALSE:
100
200k
                case POP_JUMP_IF_TRUE:
101
210k
                case POP_JUMP_IF_NONE:
102
223k
                case POP_JUMP_IF_NOT_NONE:
103
223k
                    instructions[i + 1].cache = 0x5555;  // Alternating 0, 1 bits
104
223k
                    break;
105
1.78M
                default:
106
1.78M
                    instructions[i + 1].counter = adaptive_counter;
107
1.78M
                    break;
108
2.27M
            }
109
2.27M
            i += caches;
110
2.27M
        }
111
7.07M
        if (opcode != EXTENDED_ARG) {
112
7.02M
            oparg = 0;
113
7.02M
        }
114
7.07M
    }
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
170k
}
125
126
515k
#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
3.81k
#define SPEC_FAIL_CODE_COMPLEX_PARAMETERS 7
138
50.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.34k
#define SPEC_FAIL_TO_BOOL_MAPPING     13
314
#define SPEC_FAIL_TO_BOOL_MEMORY_VIEW 14
315
49
#define SPEC_FAIL_TO_BOOL_NUMBER      15
316
5.08k
#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
6.94M
{
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
6.94M
    instr->op.code = opcode;
343
6.94M
    return 1;
344
6.94M
#endif
345
6.94M
}
346
347
static inline void
348
set_counter(_Py_BackoffCounter *counter, _Py_BackoffCounter value)
349
8.47M
{
350
8.47M
    FT_ATOMIC_STORE_UINT16_RELAXED(counter->value_and_backoff,
351
8.47M
                                   value.value_and_backoff);
352
8.47M
}
353
354
static inline _Py_BackoffCounter
355
load_counter(_Py_BackoffCounter *counter)
356
2.19M
{
357
2.19M
    _Py_BackoffCounter result = {
358
2.19M
        .value_and_backoff =
359
2.19M
            FT_ATOMIC_LOAD_UINT16_RELAXED(counter->value_and_backoff)};
360
2.19M
    return result;
361
2.19M
}
362
363
static inline void
364
specialize(_Py_CODEUNIT *instr, uint8_t specialized_opcode)
365
4.75M
{
366
4.75M
    assert(!PyErr_Occurred());
367
4.75M
    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
4.75M
    STAT_INC(_PyOpcode_Deopt[specialized_opcode], success);
374
4.75M
    set_counter((_Py_BackoffCounter *)instr + 1, adaptive_counter_cooldown());
375
4.75M
}
376
377
static inline void
378
unspecialize(_Py_CODEUNIT *instr)
379
2.19M
{
380
2.19M
    assert(!PyErr_Occurred());
381
2.19M
    uint8_t opcode = FT_ATOMIC_LOAD_UINT8_RELAXED(instr->op.code);
382
2.19M
    uint8_t generic_opcode = _PyOpcode_Deopt[opcode];
383
2.19M
    STAT_INC(generic_opcode, failure);
384
2.19M
    if (!set_opcode(instr, generic_opcode)) {
385
0
        SPECIALIZATION_FAIL(generic_opcode, SPEC_FAIL_OTHER);
386
0
        return;
387
0
    }
388
2.19M
    _Py_BackoffCounter *counter = (_Py_BackoffCounter *)instr + 1;
389
2.19M
    _Py_BackoffCounter cur = load_counter(counter);
390
2.19M
    set_counter(counter, adaptive_counter_backoff(cur));
391
2.19M
}
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.79k
{
415
6.79k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
416
6.79k
    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.79k
    PyObject *value;
421
6.79k
    Py_ssize_t index = _PyDict_LookupIndexAndValue(dict, name, &value);
422
6.79k
    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.79k
    assert(index != DKIX_ERROR);
427
6.79k
    if (index != (uint16_t)index) {
428
324
        SPECIALIZATION_FAIL(LOAD_ATTR,
429
324
                            index == DKIX_EMPTY ?
430
324
                            SPEC_FAIL_ATTR_MODULE_ATTR_NOT_FOUND :
431
324
                            SPEC_FAIL_OUT_OF_RANGE);
432
324
        return -1;
433
324
    }
434
6.46k
    uint32_t keys_version = _PyDict_GetKeysVersionForCurrentState(
435
6.46k
            _PyInterpreterState_GET(), dict);
436
6.46k
    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.46k
    write_u32(cache->version, keys_version);
444
6.46k
    cache->index = (uint16_t)index;
445
6.46k
    specialize(instr, LOAD_ATTR_MODULE);
446
6.46k
    return 0;
447
6.46k
}
448
449
static int
450
specialize_module_load_attr(
451
    PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
452
6.79k
{
453
6.79k
    PyModuleObject *m = (PyModuleObject *)owner;
454
6.79k
    assert((Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0);
455
6.79k
    PyDictObject *dict = (PyDictObject *)m->md_dict;
456
6.79k
    if (dict == NULL) {
457
0
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_NO_DICT);
458
0
        return -1;
459
0
    }
460
6.79k
    int result;
461
6.79k
    Py_BEGIN_CRITICAL_SECTION(dict);
462
6.79k
    result = specialize_module_load_attr_lock_held(dict, instr, name);
463
6.79k
    Py_END_CRITICAL_SECTION();
464
6.79k
    return result;
465
6.79k
}
466
467
/* Attribute specialization */
468
469
Py_NO_INLINE void
470
484
_Py_Specialize_LoadSuperAttr(_PyStackRef global_super_st, _PyStackRef cls_st, _Py_CODEUNIT *instr, int load_method) {
471
484
    PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st);
472
484
    PyObject *cls = PyStackRef_AsPyObjectBorrow(cls_st);
473
474
484
    assert(ENABLE_SPECIALIZATION);
475
484
    assert(_PyOpcode_Caches[LOAD_SUPER_ATTR] == INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR);
476
484
    if (global_super != (PyObject *)&PySuper_Type) {
477
0
        SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_SHADOWED);
478
0
        goto fail;
479
0
    }
480
484
    if (!PyType_Check(cls)) {
481
0
        SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_BAD_CLASS);
482
0
        goto fail;
483
0
    }
484
484
    uint8_t load_code = load_method ? LOAD_SUPER_ATTR_METHOD : LOAD_SUPER_ATTR_ATTR;
485
484
    specialize(instr, load_code);
486
484
    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.23M
{
512
4.23M
    if (descriptor == NULL) {
513
1.90M
        return ABSENT;
514
1.90M
    }
515
2.32M
    PyTypeObject *desc_cls = Py_TYPE(descriptor);
516
2.32M
    if (!(desc_cls->tp_flags & Py_TPFLAGS_IMMUTABLETYPE)) {
517
491
        return MUTABLE;
518
491
    }
519
2.32M
    if (desc_cls->tp_descr_set) {
520
224k
        if (desc_cls == &PyMemberDescr_Type) {
521
11.2k
            PyMemberDescrObject *member = (PyMemberDescrObject *)descriptor;
522
11.2k
            struct PyMemberDef *dmem = member->d_member;
523
11.2k
            if (dmem->type == Py_T_OBJECT_EX || dmem->type == _Py_T_OBJECT) {
524
10.9k
                return OBJECT_SLOT;
525
10.9k
            }
526
345
            return OTHER_SLOT;
527
11.2k
        }
528
212k
        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
207k
            return has_getattr ? GETSET_OVERRIDDEN : PROPERTY;
533
207k
        }
534
5.56k
        return OVERRIDING;
535
212k
    }
536
2.09M
    if (desc_cls->tp_descr_get) {
537
653k
        if (desc_cls->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR) {
538
647k
            return METHOD;
539
647k
        }
540
6.18k
        if (Py_IS_TYPE(descriptor, &PyClassMethodDescr_Type)) {
541
1.99k
            return BUILTIN_CLASSMETHOD;
542
1.99k
        }
543
4.19k
        if (Py_IS_TYPE(descriptor, &PyClassMethod_Type)) {
544
3.17k
            return PYTHON_CLASSMETHOD;
545
3.17k
        }
546
1.01k
        return NON_OVERRIDING;
547
4.19k
    }
548
1.44M
    return NON_DESCRIPTOR;
549
2.09M
}
550
551
static bool
552
descriptor_is_class(PyObject *descriptor, PyObject *name)
553
4.28M
{
554
4.28M
    return ((PyUnicode_CompareWithASCIIString(name, "__class__") == 0) &&
555
61.6k
            (descriptor == _PyType_Lookup(&PyBaseObject_Type, name)));
556
4.28M
}
557
558
static DescriptorClassification
559
4.07M
analyze_descriptor_load(PyTypeObject *type, PyObject *name, PyObject **descr, unsigned int *tp_version) {
560
4.07M
    bool has_getattr = false;
561
4.07M
    bool have_ga_version = false;
562
4.07M
    unsigned int ga_version;
563
4.07M
    getattrofunc getattro_slot = type->tp_getattro;
564
4.07M
    if (getattro_slot == PyObject_GenericGetAttr) {
565
        /* Normal attribute lookup; */
566
4.04M
        has_getattr = false;
567
4.04M
    }
568
27.4k
    else if (getattro_slot == _Py_slot_tp_getattr_hook ||
569
26.3k
        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
26.3k
        PyObject *getattribute = _PyType_LookupRefAndVersion(type,
573
26.3k
                &_Py_ID(__getattribute__), &ga_version);
574
26.3k
        have_ga_version = true;
575
26.3k
        PyInterpreterState *interp = _PyInterpreterState_GET();
576
26.3k
        bool has_custom_getattribute = getattribute != NULL &&
577
26.3k
            getattribute != interp->callable_cache.object__getattribute__;
578
26.3k
        PyObject *getattr = _PyType_Lookup(type, &_Py_ID(__getattr__));
579
26.3k
        has_getattr = getattr != NULL;
580
26.3k
        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
26.3k
        Py_XDECREF(getattribute);
602
26.3k
    }
603
1.11k
    else {
604
1.11k
        *descr = NULL;
605
1.11k
        *tp_version = FT_ATOMIC_LOAD_UINT_RELAXED(type->tp_version_tag);
606
1.11k
        return GETSET_OVERRIDDEN;
607
1.11k
    }
608
4.07M
    unsigned int descr_version;
609
4.07M
    PyObject *descriptor = _PyType_LookupRefAndVersion(type, name, &descr_version);
610
4.07M
    *descr = descriptor;
611
4.07M
    *tp_version = have_ga_version ? ga_version : descr_version;
612
4.07M
    if (descriptor_is_class(descriptor, name)) {
613
61.6k
        return DUNDER_CLASS;
614
61.6k
    }
615
4.01M
    return classify_descriptor(descriptor, has_getattr);
616
4.07M
}
617
618
static DescriptorClassification
619
analyze_descriptor_store(PyTypeObject *type, PyObject *name, PyObject **descr, unsigned int *tp_version)
620
207k
{
621
207k
    if (type->tp_setattro != PyObject_GenericSetAttr) {
622
974
        *descr = NULL;
623
974
        return GETSET_OVERRIDDEN;
624
974
    }
625
206k
    PyObject *descriptor = _PyType_LookupRefAndVersion(type, name, tp_version);
626
206k
    *descr = descriptor;
627
206k
    if (descriptor_is_class(descriptor, name)) {
628
0
        return DUNDER_CLASS;
629
0
    }
630
206k
    return classify_descriptor(descriptor, false);
631
206k
}
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
213
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_NOT_IN_KEYS);
647
213
        return 0;
648
213
    }
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
18.3k
{
669
18.3k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
670
671
18.3k
    _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
18.3k
    if (_PyDict_HasSplitTable(dict)) {
678
514
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_SPLIT_DICT);
679
514
        return 0;
680
514
    }
681
17.7k
    Py_ssize_t index = _PyDict_LookupIndex(dict, name);
682
17.7k
    if (index != (uint16_t)index) {
683
4.68k
        SPECIALIZATION_FAIL(base_op,
684
4.68k
                            index == DKIX_EMPTY ?
685
4.68k
                            SPEC_FAIL_ATTR_NOT_IN_DICT :
686
4.68k
                            SPEC_FAIL_OUT_OF_RANGE);
687
4.68k
        return 0;
688
4.68k
    }
689
13.1k
    cache->index = (uint16_t)index;
690
13.1k
    write_u32(cache->version, tp_version);
691
13.1k
    specialize(instr, hint_op);
692
13.1k
    return 1;
693
17.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
747k
{
702
747k
    assert(kind == NON_OVERRIDING || kind == NON_DESCRIPTOR || kind == ABSENT ||
703
747k
        kind == BUILTIN_CLASSMETHOD || kind == PYTHON_CLASSMETHOD ||
704
747k
        kind == METHOD);
705
    // No descriptor, or non overriding.
706
747k
    if ((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {
707
3.75k
        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);
708
3.75k
        return 0;
709
3.75k
    }
710
743k
    if (type->tp_flags & Py_TPFLAGS_INLINE_VALUES &&
711
743k
        FT_ATOMIC_LOAD_UINT8(_PyObject_InlineValues(owner)->valid) &&
712
725k
        !(base_op == STORE_ATTR && _PyObject_GetManagedDict(owner) != NULL))
713
725k
    {
714
725k
        int res;
715
725k
        Py_BEGIN_CRITICAL_SECTION(owner);
716
725k
        PyDictObject *dict = _PyObject_GetManagedDict(owner);
717
725k
        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
769
        else {
723
            // lost race and dict was created, fail specialization
724
769
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OTHER);
725
769
            res = 0;
726
769
        }
727
725k
        Py_END_CRITICAL_SECTION();
728
725k
        return res;
729
725k
    }
730
18.5k
    else {
731
18.5k
        PyDictObject *dict = _PyObject_GetManagedDict(owner);
732
18.5k
        if (dict == NULL || !PyDict_CheckExact(dict)) {
733
236
            SPECIALIZATION_FAIL(base_op, SPEC_FAIL_NO_DICT);
734
236
            return 0;
735
236
        }
736
18.3k
        int res;
737
18.3k
        Py_BEGIN_CRITICAL_SECTION(dict);
738
        // materialized managed dict
739
18.3k
        res = specialize_dict_access_hint(dict, instr, type, name,
740
18.3k
                                          tp_version, base_op, hint_op);
741
18.3k
        Py_END_CRITICAL_SECTION();
742
18.3k
        return res;
743
18.5k
    }
744
743k
}
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.06M
{
762
4.06M
    PyTypeObject *cls = Py_TYPE(obj);
763
4.06M
    if ((cls->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {
764
838k
        return false;
765
838k
    }
766
3.22M
    if (cls->tp_flags & Py_TPFLAGS_INLINE_VALUES) {
767
3.22M
        PyDictKeysObject *keys = ((PyHeapTypeObject *)cls)->ht_cached_keys;
768
3.22M
        Py_ssize_t index =
769
3.22M
            _PyDictKeys_StringLookupAndVersion(keys, name, shared_keys_version);
770
3.22M
        return index >= 0;
771
3.22M
    }
772
1.51k
    PyDictObject *dict = _PyObject_GetManagedDict(obj);
773
1.51k
    if (dict == NULL || !PyDict_CheckExact(dict)) {
774
28
        return false;
775
28
    }
776
1.51k
    bool result;
777
1.48k
    Py_BEGIN_CRITICAL_SECTION(dict);
778
1.48k
    if (dict->ma_values) {
779
1.48k
        result = false;
780
1.48k
    }
781
0
    else {
782
0
        result = (_PyDict_LookupIndex(dict, name) >= 0);
783
0
    }
784
1.48k
    Py_END_CRITICAL_SECTION();
785
1.48k
    return result;
786
1.51k
}
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.06M
{
793
4.06M
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
794
4.06M
    PyTypeObject *type = Py_TYPE(owner);
795
4.06M
    if (tp_version == 0) {
796
666
        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
797
666
        return -1;
798
666
    }
799
4.06M
    uint8_t oparg = FT_ATOMIC_LOAD_UINT8_RELAXED(instr->op.arg);
800
4.06M
    switch(kind) {
801
1.28k
        case OVERRIDING:
802
1.28k
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
803
1.28k
            return -1;
804
646k
        case METHOD:
805
646k
        {
806
646k
            if (shadow) {
807
95
                goto try_instance;
808
95
            }
809
646k
            if (oparg & 1) {
810
632k
                if (specialize_attr_loadclassattr(owner, instr, name, descr,
811
632k
                                                  tp_version, kind, true,
812
632k
                                                  shared_keys_version)) {
813
628k
                    return 0;
814
628k
                }
815
3.55k
                else {
816
3.55k
                    return -1;
817
3.55k
                }
818
632k
            }
819
13.9k
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
820
13.9k
            return -1;
821
646k
        }
822
207k
        case PROPERTY:
823
207k
        {
824
207k
            _PyLoadMethodCache *lm_cache = (_PyLoadMethodCache *)(instr + 1);
825
207k
            assert(Py_TYPE(descr) == &PyProperty_Type);
826
207k
            PyObject *fget = ((_PyPropertyObject *)descr)->prop_get;
827
207k
            if (fget == NULL) {
828
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
829
0
                return -1;
830
0
            }
831
207k
            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
207k
            if (!function_check_args(fget, 1, LOAD_ATTR)) {
836
0
                return -1;
837
0
            }
838
207k
            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
207k
            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
207k
            uint32_t func_version = function_get_version(fget, LOAD_ATTR);
854
207k
            if (func_version == 0) {
855
0
                return -1;
856
0
            }
857
207k
            assert(tp_version != 0);
858
207k
            write_u32(lm_cache->type_version, tp_version);
859
207k
            write_u32(lm_cache->keys_version, func_version);
860
            /* borrowed */
861
207k
            write_ptr(lm_cache->descr, fget);
862
207k
            specialize(instr, LOAD_ATTR_PROPERTY);
863
207k
            return 0;
864
207k
        }
865
10.1k
        case OBJECT_SLOT:
866
10.1k
        {
867
10.1k
            PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
868
10.1k
            struct PyMemberDef *dmem = member->d_member;
869
10.1k
            Py_ssize_t offset = dmem->offset;
870
10.1k
            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
10.1k
            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
10.1k
            if (dmem->flags & Py_AUDIT_READ) {
879
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_AUDITED_SLOT);
880
0
                return -1;
881
0
            }
882
10.1k
            if (offset != (uint16_t)offset) {
883
0
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE);
884
0
                return -1;
885
0
            }
886
10.1k
            assert(dmem->type == Py_T_OBJECT_EX || dmem->type == _Py_T_OBJECT);
887
10.1k
            assert(offset > 0);
888
10.1k
            cache->index = (uint16_t)offset;
889
10.1k
            write_u32(cache->version, tp_version);
890
10.1k
            specialize(instr, LOAD_ATTR_SLOT);
891
10.1k
            return 0;
892
10.1k
        }
893
61.6k
        case DUNDER_CLASS:
894
61.6k
        {
895
61.6k
            Py_ssize_t offset = offsetof(PyObject, ob_type);
896
61.6k
            assert(offset == (uint16_t)offset);
897
61.6k
            cache->index = (uint16_t)offset;
898
61.6k
            write_u32(cache->version, tp_version);
899
61.6k
            specialize(instr, LOAD_ATTR_SLOT);
900
61.6k
            return 0;
901
10.1k
        }
902
345
        case OTHER_SLOT:
903
345
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT);
904
345
            return -1;
905
254
        case MUTABLE:
906
254
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
907
254
            return -1;
908
854
        case GETSET_OVERRIDDEN:
909
854
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OVERRIDDEN);
910
854
            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
223
        case PYTHON_CLASSMETHOD:
946
400
        case NON_OVERRIDING:
947
400
            if (shadow) {
948
0
                goto try_instance;
949
0
            }
950
400
            return -1;
951
1.43M
        case NON_DESCRIPTOR:
952
1.43M
            if (shadow) {
953
375k
                goto try_instance;
954
375k
            }
955
1.06M
            if ((oparg & 1) == 0) {
956
1.06M
                if (specialize_attr_loadclassattr(owner, instr, name, descr,
957
1.06M
                                                  tp_version, kind, false,
958
1.06M
                                                  shared_keys_version)) {
959
1.06M
                    return 0;
960
1.06M
                }
961
1.06M
            }
962
501
            return -1;
963
1.69M
        case ABSENT:
964
1.69M
            if (shadow) {
965
172k
                goto try_instance;
966
172k
            }
967
1.52M
            set_counter((_Py_BackoffCounter*)instr + 1, adaptive_counter_cooldown());
968
1.52M
            return 0;
969
4.06M
    }
970
4.06M
    Py_UNREACHABLE();
971
548k
try_instance:
972
548k
    if (specialize_dict_access(owner, instr, type, kind, name, tp_version,
973
548k
                               LOAD_ATTR, LOAD_ATTR_INSTANCE_VALUE, LOAD_ATTR_WITH_HINT))
974
543k
    {
975
543k
        return 0;
976
543k
    }
977
4.63k
    return -1;
978
548k
}
979
980
static int
981
specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name)
982
4.06M
{
983
    // 0 is not a valid version
984
4.06M
    PyObject *descr = NULL;
985
4.06M
    unsigned int tp_version = 0;
986
4.06M
    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.06M
    DescriptorClassification kind = analyze_descriptor_load(type, name, &descr, &tp_version);
991
4.06M
    uint32_t shared_keys_version = 0;
992
4.06M
    bool shadow = instance_has_key(owner, name, &shared_keys_version);
993
4.06M
    int result = do_specialize_instance_load_attr(owner, instr, name, shadow, shared_keys_version, kind, descr, tp_version);
994
4.06M
    Py_XDECREF(descr);
995
4.06M
    return result;
996
4.06M
}
997
998
Py_NO_INLINE void
999
_Py_Specialize_LoadAttr(_PyStackRef owner_st, _Py_CODEUNIT *instr, PyObject *name)
1000
4.08M
{
1001
4.08M
    PyObject *owner = PyStackRef_AsPyObjectBorrow(owner_st);
1002
1003
4.08M
    assert(ENABLE_SPECIALIZATION);
1004
4.08M
    assert(_PyOpcode_Caches[LOAD_ATTR] == INLINE_CACHE_ENTRIES_LOAD_ATTR);
1005
4.08M
    PyTypeObject *type = Py_TYPE(owner);
1006
4.08M
    bool fail;
1007
4.08M
    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.08M
    else if (Py_TYPE(owner)->tp_getattro == PyModule_Type.tp_getattro) {
1015
6.79k
        fail = specialize_module_load_attr(owner, instr, name);
1016
6.79k
    }
1017
4.07M
    else if (PyType_Check(owner)) {
1018
12.3k
        fail = specialize_class_load_attr(owner, instr, name);
1019
12.3k
    }
1020
4.06M
    else {
1021
4.06M
        fail = specialize_instance_load_attr(owner, instr, name);
1022
4.06M
    }
1023
1024
4.08M
    if (fail) {
1025
35.6k
        unspecialize(instr);
1026
35.6k
    }
1027
4.08M
}
1028
1029
Py_NO_INLINE void
1030
_Py_Specialize_StoreAttr(_PyStackRef owner_st, _Py_CODEUNIT *instr, PyObject *name)
1031
207k
{
1032
207k
    PyObject *owner = PyStackRef_AsPyObjectBorrow(owner_st);
1033
1034
207k
    assert(ENABLE_SPECIALIZATION);
1035
207k
    assert(_PyOpcode_Caches[STORE_ATTR] == INLINE_CACHE_ENTRIES_STORE_ATTR);
1036
207k
    PyObject *descr = NULL;
1037
207k
    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
1038
207k
    PyTypeObject *type = Py_TYPE(owner);
1039
207k
    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
207k
    if (PyModule_CheckExact(owner)) {
1047
582
        SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OVERRIDDEN);
1048
582
        goto fail;
1049
582
    }
1050
207k
    unsigned int tp_version = 0;
1051
207k
    DescriptorClassification kind = analyze_descriptor_store(type, name, &descr, &tp_version);
1052
207k
    if (tp_version == 0) {
1053
1.01k
        goto fail;
1054
1.01k
    }
1055
207k
    assert(descr != NULL || kind == ABSENT || kind == GETSET_OVERRIDDEN);
1056
206k
    switch(kind) {
1057
1.61k
        case OVERRIDING:
1058
1.61k
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
1059
1.61k
            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
759
        case OBJECT_SLOT:
1067
759
        {
1068
759
            PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
1069
759
            struct PyMemberDef *dmem = member->d_member;
1070
759
            Py_ssize_t offset = dmem->offset;
1071
759
            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
759
            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
759
            if (dmem->flags & Py_READONLY) {
1080
0
                SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_READ_ONLY);
1081
0
                goto fail;
1082
0
            }
1083
759
            if (offset != (uint16_t)offset) {
1084
0
                SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OUT_OF_RANGE);
1085
0
                goto fail;
1086
0
            }
1087
759
            assert(dmem->type == Py_T_OBJECT_EX || dmem->type == _Py_T_OBJECT);
1088
759
            assert(offset > 0);
1089
759
            cache->index = (uint16_t)offset;
1090
759
            write_u32(cache->version, tp_version);
1091
759
            specialize(instr, STORE_ATTR_SLOT);
1092
759
            goto success;
1093
759
        }
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.03k
        case NON_DESCRIPTOR:
1115
4.03k
            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE);
1116
4.03k
            goto fail;
1117
199k
        case ABSENT:
1118
199k
            if (specialize_dict_access(owner, instr, type, kind, name, tp_version,
1119
199k
                                       STORE_ATTR, STORE_ATTR_INSTANCE_VALUE,
1120
199k
                                       STORE_ATTR_WITH_HINT)) {
1121
194k
                goto success;
1122
194k
            }
1123
206k
    }
1124
12.8k
fail:
1125
12.8k
    Py_XDECREF(descr);
1126
12.8k
    unspecialize(instr);
1127
12.8k
    return;
1128
194k
success:
1129
194k
    Py_XDECREF(descr);
1130
194k
    return;
1131
206k
}
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.3k
{
1174
12.3k
    assert(PyType_Check(owner));
1175
12.3k
    PyTypeObject *cls = (PyTypeObject *)owner;
1176
12.3k
    _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1);
1177
12.3k
    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.3k
    unsigned int meta_version = 0;
1182
12.3k
    PyObject *metadescriptor = _PyType_LookupRefAndVersion(Py_TYPE(cls), name, &meta_version);
1183
12.3k
    DescriptorClassification metakind = classify_descriptor(metadescriptor, false);
1184
12.3k
    Py_XDECREF(metadescriptor);
1185
12.3k
    switch (metakind) {
1186
650
        case METHOD:
1187
931
        case NON_DESCRIPTOR:
1188
1.12k
        case NON_OVERRIDING:
1189
1.12k
        case BUILTIN_CLASSMETHOD:
1190
1.12k
        case PYTHON_CLASSMETHOD:
1191
9.66k
        case ABSENT:
1192
9.66k
            break;
1193
2.71k
        default:
1194
2.71k
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METACLASS_ATTRIBUTE);
1195
2.71k
            return -1;
1196
12.3k
    }
1197
9.66k
    PyObject *descr = NULL;
1198
9.66k
    DescriptorClassification kind = 0;
1199
9.66k
    unsigned int tp_version = 0;
1200
9.66k
    kind = analyze_descriptor_load(cls, name, &descr, &tp_version);
1201
9.66k
    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.66k
    bool metaclass_check = false;
1207
9.58k
    if ((Py_TYPE(cls)->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) {
1208
1.78k
        metaclass_check = true;
1209
1.78k
        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.78k
    }
1215
9.58k
    switch (kind) {
1216
237
        case MUTABLE:
1217
            // special case for enums which has Py_TYPE(descr) == cls
1218
            // so guarding on type version is sufficient
1219
237
            if (Py_TYPE(descr) != cls) {
1220
25
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
1221
25
                Py_XDECREF(descr);
1222
25
                return -1;
1223
25
            }
1224
212
            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
212
            _Py_FALLTHROUGH;
1230
873
        case METHOD:
1231
3.55k
        case NON_DESCRIPTOR:
1232
#ifdef Py_GIL_DISABLED
1233
            maybe_enable_deferred_ref_count(descr);
1234
#endif
1235
3.55k
            write_ptr(cache->descr, descr);
1236
3.55k
            if (metaclass_check) {
1237
1.38k
                write_u32(cache->keys_version, tp_version);
1238
1.38k
                write_u32(cache->type_version, meta_version);
1239
1.38k
                specialize(instr, LOAD_ATTR_CLASS_WITH_METACLASS_CHECK);
1240
1.38k
            }
1241
2.16k
            else {
1242
2.16k
                write_u32(cache->type_version, tp_version);
1243
2.16k
                specialize(instr, LOAD_ATTR_CLASS);
1244
2.16k
            }
1245
3.55k
            Py_XDECREF(descr);
1246
3.55k
            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.00k
        default:
1254
6.00k
            SPECIALIZATION_FAIL(LOAD_ATTR, load_attr_fail_kind(kind));
1255
6.00k
            Py_XDECREF(descr);
1256
6.00k
            return -1;
1257
9.58k
    }
1258
9.58k
}
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.69M
{
1270
1.69M
    _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1);
1271
1.69M
    PyTypeObject *owner_cls = Py_TYPE(owner);
1272
1273
1.69M
    assert(descr != NULL);
1274
1.69M
    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.69M
    unsigned long tp_flags = PyType_GetFlags(owner_cls);
1284
1.69M
    if (tp_flags & Py_TPFLAGS_INLINE_VALUES) {
1285
1.66M
        #ifndef Py_GIL_DISABLED
1286
1.66M
        assert(_PyDictKeys_StringLookup(
1287
1.66M
                   ((PyHeapTypeObject *)owner_cls)->ht_cached_keys, name) < 0);
1288
1.66M
        #endif
1289
1.66M
        if (shared_keys_version == 0) {
1290
0
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
1291
0
            return 0;
1292
0
        }
1293
1.66M
        specialize(instr, is_method ? LOAD_ATTR_METHOD_WITH_VALUES : LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES);
1294
1.66M
    }
1295
25.6k
    else {
1296
25.6k
        Py_ssize_t dictoffset;
1297
25.6k
        if (tp_flags & Py_TPFLAGS_MANAGED_DICT) {
1298
320
            dictoffset = MANAGED_DICT_OFFSET;
1299
320
        }
1300
25.3k
        else {
1301
25.3k
            dictoffset = owner_cls->tp_dictoffset;
1302
25.3k
            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
25.3k
        }
1307
25.6k
        if (dictoffset == 0) {
1308
21.3k
            specialize(instr, is_method ? LOAD_ATTR_METHOD_NO_DICT : LOAD_ATTR_NONDESCRIPTOR_NO_DICT);
1309
21.3k
        }
1310
4.26k
        else if (is_method) {
1311
3.79k
            PyObject **addr = (PyObject **)((char *)owner + dictoffset);
1312
3.79k
            PyObject *dict = FT_ATOMIC_LOAD_PTR_ACQUIRE(*addr);
1313
3.79k
            if (dict) {
1314
3.55k
                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);
1315
3.55k
                return 0;
1316
3.55k
            }
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
239
            dictoffset -= MANAGED_DICT_OFFSET;
1321
239
            assert(((uint16_t)dictoffset) == dictoffset);
1322
239
            cache->dict_offset = (uint16_t)dictoffset;
1323
239
            specialize(instr, LOAD_ATTR_METHOD_LAZY_DICT);
1324
239
        }
1325
478
        else {
1326
478
            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE);
1327
478
            return 0;
1328
478
        }
1329
25.6k
    }
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.69M
    write_u32(cache->type_version, tp_version);
1345
1.69M
    write_ptr(cache->descr, descr);
1346
1.69M
    return 1;
1347
1.69M
}
1348
1349
static void
1350
specialize_load_global_lock_held(
1351
    PyObject *globals, PyObject *builtins,
1352
    _Py_CODEUNIT *instr, PyObject *name)
1353
39.0k
{
1354
39.0k
    assert(ENABLE_SPECIALIZATION);
1355
39.0k
    assert(_PyOpcode_Caches[LOAD_GLOBAL] == INLINE_CACHE_ENTRIES_LOAD_GLOBAL);
1356
    /* Use inline cache */
1357
39.0k
    _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)(instr + 1);
1358
39.0k
    assert(PyUnicode_CheckExact(name));
1359
39.0k
    if (!PyDict_CheckExact(globals)) {
1360
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_DICT);
1361
0
        goto fail;
1362
0
    }
1363
39.0k
    PyDictKeysObject * globals_keys = ((PyDictObject *)globals)->ma_keys;
1364
39.0k
    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
39.0k
    PyObject *value;
1369
39.0k
    Py_ssize_t index = _PyDict_LookupIndexAndValue((PyDictObject *)globals, name, &value);
1370
39.0k
    if (index == DKIX_ERROR) {
1371
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_EXPECTED_ERROR);
1372
0
        goto fail;
1373
0
    }
1374
39.0k
    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
39.0k
    PyInterpreterState *interp = _PyInterpreterState_GET();
1379
39.0k
    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.8k
    if (!PyDict_CheckExact(builtins)) {
1404
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_DICT);
1405
0
        goto fail;
1406
0
    }
1407
15.8k
    PyDictKeysObject * builtin_keys = ((PyDictObject *)builtins)->ma_keys;
1408
15.8k
    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.8k
    index = _PyDict_LookupIndexAndValue((PyDictObject *)builtins, name, &value);
1413
15.8k
    if (index == DKIX_ERROR) {
1414
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_EXPECTED_ERROR);
1415
0
        goto fail;
1416
0
    }
1417
15.8k
    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.8k
    if (index != (uint16_t)index) {
1422
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1423
0
        goto fail;
1424
0
    }
1425
15.8k
    uint32_t globals_version = _PyDict_GetKeysVersionForCurrentState(
1426
15.8k
            interp, (PyDictObject*) globals);
1427
15.8k
    if (globals_version == 0) {
1428
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
1429
0
        goto fail;
1430
0
    }
1431
15.8k
    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.8k
    PyDict_Watch(MODULE_WATCHER_ID, globals);
1436
15.8k
    uint32_t builtins_version = _PyDict_GetKeysVersionForCurrentState(
1437
15.8k
            interp, (PyDictObject*) builtins);
1438
15.8k
    if (builtins_version == 0) {
1439
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
1440
0
        goto fail;
1441
0
    }
1442
15.8k
    if (builtins_version > UINT16_MAX) {
1443
0
        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1444
0
        goto fail;
1445
0
    }
1446
15.8k
    PyDict_Watch(MODULE_WATCHER_ID, builtins);
1447
15.8k
    cache->index = (uint16_t)index;
1448
15.8k
    cache->module_keys_version = (uint16_t)globals_version;
1449
15.8k
    cache->builtin_keys_version = (uint16_t)builtins_version;
1450
15.8k
    specialize(instr, LOAD_GLOBAL_BUILTIN);
1451
15.8k
    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
39.0k
{
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
39.0k
    Py_BEGIN_CRITICAL_SECTION2(globals, builtins);
1470
39.0k
    specialize_load_global_lock_held(globals, builtins, instr, name);
1471
39.0k
    Py_END_CRITICAL_SECTION2();
1472
39.0k
}
1473
1474
static int
1475
260k
function_kind(PyCodeObject *code) {
1476
260k
    int flags = code->co_flags;
1477
260k
    if ((flags & (CO_VARKEYWORDS | CO_VARARGS)) || code->co_kwonlyargcount) {
1478
3.81k
        return SPEC_FAIL_CODE_COMPLEX_PARAMETERS;
1479
3.81k
    }
1480
256k
    if ((flags & CO_OPTIMIZED) == 0) {
1481
0
        return SPEC_FAIL_CODE_NOT_OPTIMIZED;
1482
0
    }
1483
256k
    return SIMPLE_FUNCTION;
1484
256k
}
1485
1486
/* Returning false indicates a failure. */
1487
static bool
1488
function_check_args(PyObject *o, int expected_argcount, int opcode)
1489
207k
{
1490
207k
    assert(Py_IS_TYPE(o, &PyFunction_Type));
1491
207k
    PyFunctionObject *func = (PyFunctionObject *)o;
1492
207k
    PyCodeObject *fcode = (PyCodeObject *)func->func_code;
1493
207k
    int kind = function_kind(fcode);
1494
207k
    if (kind != SIMPLE_FUNCTION) {
1495
0
        SPECIALIZATION_FAIL(opcode, kind);
1496
0
        return false;
1497
0
    }
1498
207k
    if (fcode->co_argcount != expected_argcount) {
1499
0
        SPECIALIZATION_FAIL(opcode, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1500
0
        return false;
1501
0
    }
1502
207k
    return true;
1503
207k
}
1504
1505
/* Returning 0 indicates a failure. */
1506
static uint32_t
1507
function_get_version(PyObject *o, int opcode)
1508
207k
{
1509
207k
    assert(Py_IS_TYPE(o, &PyFunction_Type));
1510
207k
    PyFunctionObject *func = (PyFunctionObject *)o;
1511
207k
    uint32_t version = _PyFunction_GetVersionForCurrentState(func);
1512
207k
    if (!_PyFunction_IsVersionValid(version)) {
1513
0
        SPECIALIZATION_FAIL(opcode, SPEC_FAIL_OUT_OF_VERSIONS);
1514
0
        return 0;
1515
0
    }
1516
207k
    return version;
1517
207k
}
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.14k
        if (PyLong_CheckExact(sub)) {
1594
820
            if (_PyLong_IsNonNegativeCompact((PyLongObject *)sub)
1595
250
                && ((PyLongObject *)sub)->long_value.ob_digit[0] < (size_t)PyList_GET_SIZE(container))
1596
250
            {
1597
250
                specialize(instr, STORE_SUBSCR_LIST_INT);
1598
250
                return;
1599
250
            }
1600
570
            else {
1601
570
                SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);
1602
570
                unspecialize(instr);
1603
570
                return;
1604
570
            }
1605
820
        }
1606
323
        else if (PySlice_Check(sub)) {
1607
323
            SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_LIST_SLICE);
1608
323
            unspecialize(instr);
1609
323
            return;
1610
323
        }
1611
0
        else {
1612
0
            SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
1613
0
            unspecialize(instr);
1614
0
            return;
1615
0
        }
1616
1.14k
    }
1617
15.0k
    if (container_type->tp_as_mapping != NULL &&
1618
15.0k
        container_type->tp_as_mapping->mp_ass_subscript == _PyDict_StoreSubscript)
1619
1.88k
    {
1620
1.88k
        specialize(instr, STORE_SUBSCR_DICT);
1621
1.88k
        return;
1622
1.88k
    }
1623
13.1k
    SPECIALIZATION_FAIL(STORE_SUBSCR, store_subscr_fail_kind(container, sub));
1624
13.1k
    unspecialize(instr);
1625
13.1k
}
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.18k
{
1631
1.18k
    assert(tp->tp_new == PyBaseObject_Type.tp_new);
1632
1.18k
    if (tp->tp_alloc != PyType_GenericAlloc) {
1633
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OVERRIDDEN);
1634
0
        return NULL;
1635
0
    }
1636
1.18k
    unsigned long tp_flags = PyType_GetFlags(tp);
1637
1.18k
    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.18k
    PyObject *init = _PyType_LookupRefAndVersion(tp, &_Py_ID(__init__), tp_version);
1643
1.18k
    if (init == NULL || !PyFunction_Check(init)) {
1644
199
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_INIT_NOT_PYTHON);
1645
199
        Py_XDECREF(init);
1646
199
        return NULL;
1647
199
    }
1648
990
    int kind = function_kind((PyCodeObject *)PyFunction_GET_CODE(init));
1649
990
    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
926
    return init;
1655
990
}
1656
1657
static int
1658
specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
1659
4.42k
{
1660
4.42k
    assert(PyType_Check(callable));
1661
4.42k
    PyTypeObject *tp = _PyType_CAST(callable);
1662
4.42k
    if (tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) {
1663
2.75k
        int oparg = instr->op.arg;
1664
2.75k
        if (nargs == 1 && oparg == 1) {
1665
1.87k
            if (tp == &PyUnicode_Type) {
1666
157
                specialize(instr, CALL_STR_1);
1667
157
                return 0;
1668
157
            }
1669
1.71k
            else if (tp == &PyType_Type) {
1670
360
                specialize(instr, CALL_TYPE_1);
1671
360
                return 0;
1672
360
            }
1673
1.35k
            else if (tp == &PyTuple_Type) {
1674
126
                specialize(instr, CALL_TUPLE_1);
1675
126
                return 0;
1676
126
            }
1677
1.87k
        }
1678
2.11k
        if (tp->tp_vectorcall != NULL) {
1679
1.47k
            specialize(instr, CALL_BUILTIN_CLASS);
1680
1.47k
            return 0;
1681
1.47k
        }
1682
638
        goto generic;
1683
2.11k
    }
1684
1.66k
    if (Py_TYPE(tp) != &PyType_Type) {
1685
90
        goto generic;
1686
90
    }
1687
1.57k
    if (tp->tp_new == PyBaseObject_Type.tp_new) {
1688
1.18k
        unsigned int tp_version = 0;
1689
1.18k
        PyObject *init = get_init_for_simple_managed_python_class(tp, &tp_version);
1690
1.18k
        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.18k
        if (init != NULL && _PyType_CacheInitForSpecialization(
1696
926
                                (PyHeapTypeObject *)tp, init, tp_version)) {
1697
926
            _PyCallCache *cache = (_PyCallCache *)(instr + 1);
1698
926
            write_u32(cache->func_version, tp_version);
1699
926
            specialize(instr, CALL_ALLOC_AND_ENTER_INIT);
1700
926
            Py_DECREF(init);
1701
926
            return 0;
1702
926
        }
1703
263
        Py_XDECREF(init);
1704
263
    }
1705
1.38k
generic:
1706
1.38k
    specialize(instr, CALL_NON_PY_GENERAL);
1707
1.38k
    return 0;
1708
1.57k
}
1709
1710
static int
1711
specialize_method_descriptor(PyMethodDescrObject *descr, PyObject *self_or_null,
1712
                             _Py_CODEUNIT *instr, int nargs)
1713
473k
{
1714
473k
    switch (descr->d_method->ml_flags & _Py_METH_CALL_FLAGS) {
1715
29.6k
        case METH_NOARGS: {
1716
29.6k
            if (nargs != 1) {
1717
0
                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1718
0
                return -1;
1719
0
            }
1720
29.6k
            specialize(instr, CALL_METHOD_DESCRIPTOR_NOARGS);
1721
29.6k
            return 0;
1722
29.6k
        }
1723
367k
        case METH_O: {
1724
367k
            if (nargs != 2) {
1725
0
                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1726
0
                return -1;
1727
0
            }
1728
367k
            PyInterpreterState *interp = _PyInterpreterState_GET();
1729
367k
            PyObject *list_append = interp->callable_cache.list_append;
1730
367k
            int oparg = instr->op.arg;
1731
367k
            if ((PyObject *)descr == list_append && oparg == 1) {
1732
359k
                assert(self_or_null != NULL);
1733
359k
                if (PyList_CheckExact(self_or_null)) {
1734
1.07k
                    specialize(instr, CALL_LIST_APPEND);
1735
1.07k
                    return 0;
1736
1.07k
                }
1737
359k
            }
1738
365k
            specialize(instr, CALL_METHOD_DESCRIPTOR_O);
1739
365k
            return 0;
1740
367k
        }
1741
4.66k
        case METH_FASTCALL: {
1742
4.66k
            specialize(instr, CALL_METHOD_DESCRIPTOR_FAST);
1743
4.66k
            return 0;
1744
367k
        }
1745
71.8k
        case METH_FASTCALL | METH_KEYWORDS: {
1746
71.8k
            specialize(instr, CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS);
1747
71.8k
            return 0;
1748
367k
        }
1749
473k
    }
1750
330
    specialize(instr, CALL_NON_PY_GENERAL);
1751
330
    return 0;
1752
473k
}
1753
1754
static int
1755
specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
1756
                   bool bound_method)
1757
48.2k
{
1758
48.2k
    _PyCallCache *cache = (_PyCallCache *)(instr + 1);
1759
48.2k
    PyCodeObject *code = (PyCodeObject *)func->func_code;
1760
48.2k
    int kind = function_kind(code);
1761
    /* Don't specialize if PEP 523 is active */
1762
48.2k
    if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) {
1763
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
1764
0
        return -1;
1765
0
    }
1766
48.2k
    if (func->vectorcall != _PyFunction_Vectorcall) {
1767
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_VECTORCALL);
1768
0
        return -1;
1769
0
    }
1770
48.2k
    int argcount = -1;
1771
48.2k
    if (kind == SPEC_FAIL_CODE_NOT_OPTIMIZED) {
1772
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CODE_NOT_OPTIMIZED);
1773
0
        return -1;
1774
0
    }
1775
48.2k
    if (kind == SIMPLE_FUNCTION) {
1776
46.6k
        argcount = code->co_argcount;
1777
46.6k
    }
1778
48.2k
    int version = _PyFunction_GetVersionForCurrentState(func);
1779
48.2k
    if (!_PyFunction_IsVersionValid(version)) {
1780
59
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
1781
59
        return -1;
1782
59
    }
1783
48.1k
    write_u32(cache->func_version, version);
1784
48.1k
    uint8_t opcode;
1785
48.1k
    if (argcount == nargs + bound_method) {
1786
46.1k
        opcode =
1787
46.1k
            bound_method ? CALL_BOUND_METHOD_EXACT_ARGS : CALL_PY_EXACT_ARGS;
1788
46.1k
    }
1789
2.00k
    else {
1790
2.00k
        opcode = bound_method ? CALL_BOUND_METHOD_GENERAL : CALL_PY_GENERAL;
1791
2.00k
    }
1792
48.1k
    specialize(instr, opcode);
1793
48.1k
    return 0;
1794
48.2k
}
1795
1796
1797
static int
1798
specialize_py_call_kw(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
1799
                   bool bound_method)
1800
2.36k
{
1801
2.36k
    _PyCallCache *cache = (_PyCallCache *)(instr + 1);
1802
2.36k
    PyCodeObject *code = (PyCodeObject *)func->func_code;
1803
2.36k
    int kind = function_kind(code);
1804
    /* Don't specialize if PEP 523 is active */
1805
2.36k
    if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) {
1806
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
1807
0
        return -1;
1808
0
    }
1809
2.36k
    if (func->vectorcall != _PyFunction_Vectorcall) {
1810
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_VECTORCALL);
1811
0
        return -1;
1812
0
    }
1813
2.36k
    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.36k
    int version = _PyFunction_GetVersionForCurrentState(func);
1818
2.36k
    if (!_PyFunction_IsVersionValid(version)) {
1819
64
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
1820
64
        return -1;
1821
64
    }
1822
2.30k
    write_u32(cache->func_version, version);
1823
2.30k
    specialize(instr, bound_method ? CALL_KW_BOUND_METHOD : CALL_KW_PY);
1824
2.30k
    return 0;
1825
2.36k
}
1826
1827
static int
1828
specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
1829
11.4k
{
1830
11.4k
    if (PyCFunction_GET_FUNCTION(callable) == NULL) {
1831
0
        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OTHER);
1832
0
        return 1;
1833
0
    }
1834
11.4k
    switch (PyCFunction_GET_FLAGS(callable) & _Py_METH_CALL_FLAGS) {
1835
3.95k
        case METH_O: {
1836
3.95k
            if (nargs != 1) {
1837
0
                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1838
0
                return 1;
1839
0
            }
1840
            /* len(o) */
1841
3.95k
            PyInterpreterState *interp = _PyInterpreterState_GET();
1842
3.95k
            if (callable == interp->callable_cache.len && instr->op.arg == 1) {
1843
2.12k
                specialize(instr, CALL_LEN);
1844
2.12k
                return 0;
1845
2.12k
            }
1846
1.83k
            specialize(instr, CALL_BUILTIN_O);
1847
1.83k
            return 0;
1848
3.95k
        }
1849
5.59k
        case METH_FASTCALL: {
1850
5.59k
            if (nargs == 2) {
1851
                /* isinstance(o1, o2) */
1852
3.87k
                PyInterpreterState *interp = _PyInterpreterState_GET();
1853
3.87k
                if (callable == interp->callable_cache.isinstance && instr->op.arg == 2) {
1854
2.07k
                    specialize(instr, CALL_ISINSTANCE);
1855
2.07k
                    return 0;
1856
2.07k
                }
1857
3.87k
            }
1858
3.52k
            specialize(instr, CALL_BUILTIN_FAST);
1859
3.52k
            return 0;
1860
5.59k
        }
1861
1.43k
        case METH_FASTCALL | METH_KEYWORDS: {
1862
1.43k
            specialize(instr, CALL_BUILTIN_FAST_WITH_KEYWORDS);
1863
1.43k
            return 0;
1864
5.59k
        }
1865
472
        default:
1866
472
            specialize(instr, CALL_NON_PY_GENERAL);
1867
472
            return 0;
1868
11.4k
    }
1869
11.4k
}
1870
1871
Py_NO_INLINE void
1872
_Py_Specialize_Call(_PyStackRef callable_st, _PyStackRef self_or_null_st, _Py_CODEUNIT *instr, int nargs)
1873
553k
{
1874
553k
    PyObject *callable = PyStackRef_AsPyObjectBorrow(callable_st);
1875
1876
553k
    assert(ENABLE_SPECIALIZATION);
1877
553k
    assert(_PyOpcode_Caches[CALL] == INLINE_CACHE_ENTRIES_CALL);
1878
553k
    assert(_Py_OPCODE(*instr) != INSTRUMENTED_CALL);
1879
553k
    int fail;
1880
553k
    if (PyCFunction_CheckExact(callable)) {
1881
11.4k
        fail = specialize_c_call(callable, instr, nargs);
1882
11.4k
    }
1883
541k
    else if (PyFunction_Check(callable)) {
1884
40.8k
        fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs, false);
1885
40.8k
    }
1886
501k
    else if (PyType_Check(callable)) {
1887
4.42k
        fail = specialize_class_call(callable, instr, nargs);
1888
4.42k
    }
1889
496k
    else if (Py_IS_TYPE(callable, &PyMethodDescr_Type)) {
1890
473k
        PyObject *self_or_null = PyStackRef_AsPyObjectBorrow(self_or_null_st);
1891
473k
        fail = specialize_method_descriptor((PyMethodDescrObject *)callable,
1892
473k
                                            self_or_null, instr, nargs);
1893
473k
    }
1894
23.0k
    else if (PyMethod_Check(callable)) {
1895
7.35k
        PyObject *func = ((PyMethodObject *)callable)->im_func;
1896
7.35k
        if (PyFunction_Check(func)) {
1897
7.34k
            fail = specialize_py_call((PyFunctionObject *)func, instr, nargs, true);
1898
7.34k
        }
1899
8
        else {
1900
8
            SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_BOUND_METHOD);
1901
8
            fail = -1;
1902
8
        }
1903
7.35k
    }
1904
15.7k
    else {
1905
15.7k
        specialize(instr, CALL_NON_PY_GENERAL);
1906
15.7k
        fail = 0;
1907
15.7k
    }
1908
553k
    if (fail) {
1909
67
        unspecialize(instr);
1910
67
    }
1911
553k
}
1912
1913
Py_NO_INLINE void
1914
_Py_Specialize_CallKw(_PyStackRef callable_st, _Py_CODEUNIT *instr, int nargs)
1915
3.07k
{
1916
3.07k
    PyObject *callable = PyStackRef_AsPyObjectBorrow(callable_st);
1917
1918
3.07k
    assert(ENABLE_SPECIALIZATION);
1919
3.07k
    assert(_PyOpcode_Caches[CALL_KW] == INLINE_CACHE_ENTRIES_CALL_KW);
1920
3.07k
    assert(_Py_OPCODE(*instr) != INSTRUMENTED_CALL_KW);
1921
3.07k
    int fail;
1922
3.07k
    if (PyFunction_Check(callable)) {
1923
764
        fail = specialize_py_call_kw((PyFunctionObject *)callable, instr, nargs, false);
1924
764
    }
1925
2.31k
    else if (PyMethod_Check(callable)) {
1926
1.60k
        PyObject *func = ((PyMethodObject *)callable)->im_func;
1927
1.60k
        if (PyFunction_Check(func)) {
1928
1.60k
            fail = specialize_py_call_kw((PyFunctionObject *)func, instr, nargs, true);
1929
1.60k
        }
1930
0
        else {
1931
0
            SPECIALIZATION_FAIL(CALL_KW, SPEC_FAIL_CALL_BOUND_METHOD);
1932
0
            fail = -1;
1933
0
        }
1934
1.60k
    }
1935
710
    else {
1936
710
        specialize(instr, CALL_KW_NON_PY);
1937
710
        fail = 0;
1938
710
    }
1939
3.07k
    if (fail) {
1940
64
        unspecialize(instr);
1941
64
    }
1942
3.07k
}
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
120M
{
2138
120M
    return PyLong_CheckExact(v) &&
2139
120M
           _PyLong_IsCompact((PyLongObject *)v);
2140
120M
}
2141
2142
#define SEQ_INT_MULTIPLY_ACTION(NAME, REPEAT, SEQ, COUNT) \
2143
    static PyObject * \
2144
    (NAME)(PyObject *lhs, PyObject *rhs) \
2145
407k
    { \
2146
407k
        Py_ssize_t count = PyLong_AsSsize_t(COUNT); \
2147
407k
        if (count == -1 && PyErr_Occurred()) { \
2148
0
            return NULL; \
2149
0
        } \
2150
407k
        return REPEAT(SEQ, count); \
2151
407k
    }
2152
279k
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
91.0k
SEQ_INT_MULTIPLY_ACTION(bytes_int_multiply, _PyBytes_Repeat,   lhs, rhs)
2155
36.6k
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
60.2M
{
2163
60.2M
    return (is_compactlong(lhs) && is_compactlong(rhs));
2164
60.2M
}
2165
2166
#define BITWISE_LONGS_ACTION(NAME, OP) \
2167
    static PyObject * \
2168
    (NAME)(PyObject *lhs, PyObject *rhs) \
2169
60.2M
    { \
2170
60.2M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2171
60.2M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2172
60.2M
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2173
60.2M
    }
specialize.c:compactlongs_or
Line
Count
Source
2169
480k
    { \
2170
480k
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2171
480k
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2172
480k
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2173
480k
    }
specialize.c:compactlongs_and
Line
Count
Source
2169
59.8M
    { \
2170
59.8M
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2171
59.8M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2172
59.8M
        return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2173
59.8M
    }
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
1.01M
{
2184
1.01M
    return (
2185
1.01M
        PyFloat_CheckExact(lhs) &&
2186
990k
        !isnan(PyFloat_AS_DOUBLE(lhs)) &&
2187
1.01M
        PyLong_CheckExact(rhs) &&
2188
990k
        _PyLong_IsCompact((PyLongObject *)rhs)
2189
1.01M
    );
2190
1.01M
}
2191
2192
static inline int
2193
nonzero_float_compactlong_guard(PyObject *lhs, PyObject *rhs)
2194
456k
{
2195
456k
    return (
2196
456k
        float_compactlong_guard(lhs, rhs) && !_PyLong_IsZero((PyLongObject*)rhs)
2197
456k
    );
2198
456k
}
2199
2200
#define FLOAT_LONG_ACTION(NAME, OP) \
2201
    static PyObject * \
2202
    (NAME)(PyObject *lhs, PyObject *rhs) \
2203
990k
    { \
2204
990k
        double lhs_val = PyFloat_AS_DOUBLE(lhs); \
2205
990k
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2206
990k
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2207
990k
    }
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
456k
    { \
2204
456k
        double lhs_val = PyFloat_AS_DOUBLE(lhs); \
2205
456k
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2206
456k
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2207
456k
    }
specialize.c:float_compactlong_multiply
Line
Count
Source
2203
533k
    { \
2204
533k
        double lhs_val = PyFloat_AS_DOUBLE(lhs); \
2205
533k
        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2206
533k
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2207
533k
    }
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.22M
{
2219
5.22M
    return (
2220
5.22M
        PyLong_CheckExact(lhs) &&
2221
5.22M
        _PyLong_IsCompact((PyLongObject *)lhs) &&
2222
5.22M
        PyFloat_CheckExact(rhs) &&
2223
5.20M
        !isnan(PyFloat_AS_DOUBLE(rhs))
2224
5.22M
    );
2225
5.22M
}
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.20M
    { \
2239
5.20M
        double rhs_val = PyFloat_AS_DOUBLE(rhs); \
2240
5.20M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2241
5.20M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2242
5.20M
    }
specialize.c:compactlong_float_add
Line
Count
Source
2238
4.11k
    { \
2239
4.11k
        double rhs_val = PyFloat_AS_DOUBLE(rhs); \
2240
4.11k
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2241
4.11k
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2242
4.11k
    }
specialize.c:compactlong_float_subtract
Line
Count
Source
2238
2.59M
    { \
2239
2.59M
        double rhs_val = PyFloat_AS_DOUBLE(rhs); \
2240
2.59M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2241
2.59M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2242
2.59M
    }
Unexecuted instantiation: specialize.c:compactlong_float_true_div
specialize.c:compactlong_float_multiply
Line
Count
Source
2238
2.60M
    { \
2239
2.60M
        double rhs_val = PyFloat_AS_DOUBLE(rhs); \
2240
2.60M
        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2241
2.60M
        return PyFloat_FromDouble(lhs_val OP rhs_val); \
2242
2.60M
    }
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
51.6k
{
2321
51.6k
    size_t n = sizeof(binaryop_extend_descrs)/sizeof(_PyBinaryOpSpecializationDescr);
2322
2.06M
    for (size_t i = 0; i < n; i++) {
2323
2.01M
        _PyBinaryOpSpecializationDescr *d = &binaryop_extend_descrs[i];
2324
2.01M
        if (d->oparg != oparg) {
2325
1.92M
            continue;
2326
1.92M
        }
2327
93.0k
        int match = (d->guard != NULL)
2328
93.0k
            ? d->guard(lhs, rhs)
2329
93.0k
            : (Py_TYPE(lhs) == d->lhs_type && Py_TYPE(rhs) == d->rhs_type);
2330
93.0k
        if (match) {
2331
1.39k
            *descr = d;
2332
1.39k
            return 1;
2333
1.39k
        }
2334
93.0k
    }
2335
50.2k
    return 0;
2336
51.6k
}
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.20M
{
2342
1.20M
    PyObject *lhs = PyStackRef_AsPyObjectBorrow(lhs_st);
2343
1.20M
    PyObject *rhs = PyStackRef_AsPyObjectBorrow(rhs_st);
2344
1.20M
    assert(ENABLE_SPECIALIZATION);
2345
1.20M
    assert(_PyOpcode_Caches[BINARY_OP] == INLINE_CACHE_ENTRIES_BINARY_OP);
2346
2347
1.20M
    _PyBinaryOpCache *cache = (_PyBinaryOpCache *)(instr + 1);
2348
1.20M
    if (instr->op.code == BINARY_OP_EXTEND) {
2349
10
        write_ptr(cache->external_cache, NULL);
2350
10
    }
2351
2352
1.20M
    switch (oparg) {
2353
16.5k
        case NB_ADD:
2354
24.8k
        case NB_INPLACE_ADD:
2355
24.8k
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2356
1.69k
                break;
2357
1.69k
            }
2358
23.1k
            if (PyUnicode_CheckExact(lhs)) {
2359
725
                _Py_CODEUNIT next = instr[INLINE_CACHE_ENTRIES_BINARY_OP + 1];
2360
725
                bool to_store = (next.op.code == STORE_FAST);
2361
725
                if (to_store && PyStackRef_AsPyObjectBorrow(locals[next.op.arg]) == lhs) {
2362
146
                    specialize(instr, BINARY_OP_INPLACE_ADD_UNICODE);
2363
146
                    return;
2364
146
                }
2365
579
                specialize(instr, BINARY_OP_ADD_UNICODE);
2366
579
                return;
2367
725
            }
2368
22.4k
            if (_PyLong_CheckExactAndCompact(lhs) && _PyLong_CheckExactAndCompact(rhs)) {
2369
6.03k
                specialize(instr, BINARY_OP_ADD_INT);
2370
6.03k
                return;
2371
6.03k
            }
2372
16.4k
            if (PyFloat_CheckExact(lhs)) {
2373
7
                specialize(instr, BINARY_OP_ADD_FLOAT);
2374
7
                return;
2375
7
            }
2376
16.4k
            break;
2377
16.4k
        case NB_MULTIPLY:
2378
2.12k
        case NB_INPLACE_MULTIPLY:
2379
2.12k
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2380
204
                break;
2381
204
            }
2382
1.92k
            if (_PyLong_CheckExactAndCompact(lhs) && _PyLong_CheckExactAndCompact(rhs)) {
2383
471
                specialize(instr, BINARY_OP_MULTIPLY_INT);
2384
471
                return;
2385
471
            }
2386
1.45k
            if (PyFloat_CheckExact(lhs)) {
2387
22
                specialize(instr, BINARY_OP_MULTIPLY_FLOAT);
2388
22
                return;
2389
22
            }
2390
1.43k
            break;
2391
1.99k
        case NB_SUBTRACT:
2392
2.07k
        case NB_INPLACE_SUBTRACT:
2393
2.07k
            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2394
22
                break;
2395
22
            }
2396
2.05k
            if (_PyLong_CheckExactAndCompact(lhs) && _PyLong_CheckExactAndCompact(rhs)) {
2397
1.20k
                specialize(instr, BINARY_OP_SUBTRACT_INT);
2398
1.20k
                return;
2399
1.20k
            }
2400
848
            if (PyFloat_CheckExact(lhs)) {
2401
24
                specialize(instr, BINARY_OP_SUBTRACT_FLOAT);
2402
24
                return;
2403
24
            }
2404
824
            break;
2405
1.15M
        case NB_SUBSCR:
2406
1.15M
            if (PyLong_CheckExact(rhs) && _PyLong_IsNonNegativeCompact((PyLongObject *)rhs)) {
2407
1.14M
                if (PyList_CheckExact(lhs)) {
2408
39.7k
                    specialize(instr, BINARY_OP_SUBSCR_LIST_INT);
2409
39.7k
                    return;
2410
39.7k
                }
2411
1.10M
                if (PyTuple_CheckExact(lhs)) {
2412
1.12k
                    specialize(instr, BINARY_OP_SUBSCR_TUPLE_INT);
2413
1.12k
                    return;
2414
1.12k
                }
2415
1.10M
                if (PyUnicode_CheckExact(lhs) && _PyLong_IsNonNegativeCompact((PyLongObject*)rhs)) {
2416
1.09M
                    if (PyUnicode_IS_COMPACT_ASCII(lhs)) {
2417
1.62k
                        specialize(instr, BINARY_OP_SUBSCR_STR_INT);
2418
1.62k
                        return;
2419
1.09M
                    } else {
2420
1.09M
                        specialize(instr, BINARY_OP_SUBSCR_USTR_INT);
2421
1.09M
                        return;
2422
1.09M
                    }
2423
1.09M
                }
2424
1.10M
            }
2425
17.0k
            if (Py_TYPE(lhs)->tp_as_mapping != NULL &&
2426
16.8k
                Py_TYPE(lhs)->tp_as_mapping->mp_subscript == _PyDict_Subscript)
2427
870
            {
2428
870
                specialize(instr, BINARY_OP_SUBSCR_DICT);
2429
870
                return;
2430
870
            }
2431
16.1k
            if (PyList_CheckExact(lhs) && PySlice_Check(rhs)) {
2432
98
                specialize(instr, BINARY_OP_SUBSCR_LIST_SLICE);
2433
98
                return;
2434
98
            }
2435
16.0k
            unsigned int tp_version;
2436
16.0k
            PyTypeObject *container_type = Py_TYPE(lhs);
2437
16.0k
            PyObject *descriptor = _PyType_LookupRefAndVersion(container_type, &_Py_ID(__getitem__), &tp_version);
2438
16.0k
            if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type &&
2439
1.23k
                container_type->tp_flags & Py_TPFLAGS_HEAPTYPE)
2440
1.23k
            {
2441
1.23k
                PyFunctionObject *func = (PyFunctionObject *)descriptor;
2442
1.23k
                PyCodeObject *fcode = (PyCodeObject *)func->func_code;
2443
1.23k
                int kind = function_kind(fcode);
2444
1.23k
                PyHeapTypeObject *ht = (PyHeapTypeObject *)container_type;
2445
1.23k
                if (kind == SIMPLE_FUNCTION &&
2446
1.23k
                    fcode->co_argcount == 2 &&
2447
1.23k
                    _PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET()) && /* Don't specialize if PEP 523 is active */
2448
1.23k
                    _PyType_CacheGetItemForSpecialization(ht, descriptor, (uint32_t)tp_version))
2449
1.23k
                {
2450
1.23k
                    specialize(instr, BINARY_OP_SUBSCR_GETITEM);
2451
1.23k
                    Py_DECREF(descriptor);
2452
1.23k
                    return;
2453
1.23k
                }
2454
1.23k
            }
2455
14.8k
            Py_XDECREF(descriptor);
2456
14.8k
            break;
2457
1.20M
    }
2458
2459
51.6k
    _PyBinaryOpSpecializationDescr *descr;
2460
51.6k
    if (binary_op_extended_specialization(lhs, rhs, oparg, &descr)) {
2461
1.39k
        specialize(instr, BINARY_OP_EXTEND);
2462
1.39k
        write_ptr(cache->external_cache, (void*)descr);
2463
1.39k
        return;
2464
1.39k
    }
2465
2466
50.2k
    SPECIALIZATION_FAIL(BINARY_OP, binary_op_fail_kind(oparg, lhs, rhs));
2467
50.2k
    unspecialize(instr);
2468
50.2k
    return;
2469
51.6k
}
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
20.1k
{
2511
20.1k
    PyObject *lhs = PyStackRef_AsPyObjectBorrow(lhs_st);
2512
20.1k
    PyObject *rhs = PyStackRef_AsPyObjectBorrow(rhs_st);
2513
20.1k
    uint8_t specialized_op;
2514
2515
20.1k
    assert(ENABLE_SPECIALIZATION);
2516
20.1k
    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
20.1k
    if (Py_TYPE(lhs) != Py_TYPE(rhs)) {
2520
4.11k
        SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
2521
4.11k
        goto failure;
2522
4.11k
    }
2523
16.0k
    if (PyFloat_CheckExact(lhs)) {
2524
69
        specialized_op = COMPARE_OP_FLOAT;
2525
69
        goto success;
2526
69
    }
2527
15.9k
    if (PyLong_CheckExact(lhs)) {
2528
8.93k
        if (_PyLong_IsCompact((PyLongObject *)lhs) && _PyLong_IsCompact((PyLongObject *)rhs)) {
2529
5.15k
            specialized_op = COMPARE_OP_INT;
2530
5.15k
            goto success;
2531
5.15k
        }
2532
3.77k
        else {
2533
3.77k
            SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_BIG_INT);
2534
3.77k
            goto failure;
2535
3.77k
        }
2536
8.93k
    }
2537
7.01k
    if (PyUnicode_CheckExact(lhs)) {
2538
4.80k
        int cmp = oparg >> 5;
2539
4.80k
        if (cmp != Py_EQ && cmp != Py_NE) {
2540
2.27k
            SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_STRING);
2541
2.27k
            goto failure;
2542
2.27k
        }
2543
2.52k
        else {
2544
2.52k
            specialized_op = COMPARE_OP_STR;
2545
2.52k
            goto success;
2546
2.52k
        }
2547
4.80k
    }
2548
2.21k
    SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
2549
12.3k
failure:
2550
12.3k
    unspecialize(instr);
2551
12.3k
    return;
2552
7.75k
success:
2553
7.75k
    specialize(instr, specialized_op);
2554
7.75k
}
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
6.82k
{
2573
6.82k
    PyObject *seq = PyStackRef_AsPyObjectBorrow(seq_st);
2574
2575
6.82k
    assert(ENABLE_SPECIALIZATION);
2576
6.82k
    assert(_PyOpcode_Caches[UNPACK_SEQUENCE] ==
2577
6.82k
           INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE);
2578
6.82k
    if (PyTuple_CheckExact(seq)) {
2579
2.43k
        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.43k
        if (PyTuple_GET_SIZE(seq) == 2) {
2585
1.66k
            specialize(instr, UNPACK_SEQUENCE_TWO_TUPLE);
2586
1.66k
            return;
2587
1.66k
        }
2588
768
        specialize(instr, UNPACK_SEQUENCE_TUPLE);
2589
768
        return;
2590
2.43k
    }
2591
4.39k
    if (PyList_CheckExact(seq)) {
2592
4.25k
        if (PyList_GET_SIZE(seq) != oparg) {
2593
2.82k
            SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_EXPECTED_ERROR);
2594
2.82k
            unspecialize(instr);
2595
2.82k
            return;
2596
2.82k
        }
2597
1.42k
        specialize(instr, UNPACK_SEQUENCE_LIST);
2598
1.42k
        return;
2599
4.25k
    }
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
57.3k
{
2680
57.3k
    assert(ENABLE_SPECIALIZATION);
2681
57.3k
    assert(_PyOpcode_Caches[FOR_ITER] == INLINE_CACHE_ENTRIES_FOR_ITER);
2682
57.3k
    PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
2683
57.3k
    PyTypeObject *tp = Py_TYPE(iter_o);
2684
2685
57.3k
    if (PyStackRef_IsNull(null_or_index)) {
2686
51.0k
        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
256
            specialize(instr, FOR_ITER_RANGE);
2698
256
            return;
2699
256
        }
2700
50.8k
        else if (tp == &PyGen_Type && oparg <= SHRT_MAX) {
2701
689
            assert(instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == END_FOR  ||
2702
689
                instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == INSTRUMENTED_END_FOR
2703
689
            );
2704
            /* Don't specialize if PEP 523 is active */
2705
689
            if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) {
2706
0
                goto failure;
2707
0
            }
2708
689
            specialize(instr, FOR_ITER_GEN);
2709
689
            return;
2710
689
        }
2711
51.0k
    }
2712
6.23k
    else {
2713
6.23k
        if (tp->_tp_iteritem != NULL) {
2714
6.23k
            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
4.55k
                specialize(instr, FOR_ITER_LIST);
2722
4.55k
                return;
2723
4.55k
            }
2724
1.67k
            else if (tp == &PyTuple_Type) {
2725
1.51k
                specialize(instr, FOR_ITER_TUPLE);
2726
1.51k
                return;
2727
1.51k
            }
2728
6.23k
        }
2729
161
        specialize(instr, FOR_ITER_VIRTUAL);
2730
161
        return;
2731
6.23k
    }
2732
50.1k
failure:
2733
50.1k
    SPECIALIZATION_FAIL(FOR_ITER,
2734
50.1k
                        _PySpecialization_ClassifyIterator(iter_o));
2735
50.1k
    unspecialize(instr);
2736
50.1k
}
2737
2738
Py_NO_INLINE void
2739
_Py_Specialize_Send(_PyStackRef receiver_st, _Py_CODEUNIT *instr)
2740
613
{
2741
613
    PyObject *receiver = PyStackRef_AsPyObjectBorrow(receiver_st);
2742
2743
613
    assert(ENABLE_SPECIALIZATION);
2744
613
    assert(_PyOpcode_Caches[SEND] == INLINE_CACHE_ENTRIES_SEND);
2745
613
    PyTypeObject *tp = Py_TYPE(receiver);
2746
613
    if (tp == &PyGen_Type || tp == &PyCoro_Type) {
2747
        /* Don't specialize if PEP 523 is active */
2748
295
        if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) {
2749
0
            SPECIALIZATION_FAIL(SEND, SPEC_FAIL_OTHER);
2750
0
            goto failure;
2751
0
        }
2752
295
        specialize(instr, SEND_GEN);
2753
295
        return;
2754
295
    }
2755
318
    if (tp->_tp_iteritem != NULL) {
2756
318
        specialize(instr, SEND_VIRTUAL);
2757
318
        return;
2758
318
    }
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
639
{
2772
639
    PyObject *func = PyStackRef_AsPyObjectBorrow(func_st);
2773
2774
639
    assert(ENABLE_SPECIALIZATION);
2775
639
    assert(_PyOpcode_Caches[CALL_FUNCTION_EX] == INLINE_CACHE_ENTRIES_CALL_FUNCTION_EX);
2776
2777
639
    if (Py_TYPE(func) == &PyFunction_Type &&
2778
183
        ((PyFunctionObject *)func)->vectorcall == _PyFunction_Vectorcall) {
2779
183
        if (!_PyInterpreterState_IsSpecializationEnabled(_PyInterpreterState_GET())) {
2780
0
            goto failure;
2781
0
        }
2782
183
        specialize(instr, CALL_EX_PY);
2783
183
        return;
2784
183
    }
2785
456
    specialize(instr, CALL_EX_NON_PY_GENERAL);
2786
456
    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
60.5k
{
2823
60.5k
    PyNumberMethods *nb = ty->tp_as_number;
2824
60.5k
    if (nb && nb->nb_bool) {
2825
49
        return SPEC_FAIL_TO_BOOL_NUMBER;
2826
49
    }
2827
60.5k
    PyMappingMethods *mp = ty->tp_as_mapping;
2828
60.5k
    if (mp && mp->mp_length) {
2829
3.34k
        return SPEC_FAIL_TO_BOOL_MAPPING;
2830
3.34k
    }
2831
57.1k
    PySequenceMethods *sq = ty->tp_as_sequence;
2832
57.1k
    if (sq && sq->sq_length) {
2833
5.08k
      return SPEC_FAIL_TO_BOOL_SEQUENCE;
2834
5.08k
    }
2835
52.0k
    return 0;
2836
57.1k
}
2837
2838
Py_NO_INLINE void
2839
_Py_Specialize_ToBool(_PyStackRef value_o, _Py_CODEUNIT *instr)
2840
181k
{
2841
181k
    assert(ENABLE_SPECIALIZATION);
2842
181k
    assert(_PyOpcode_Caches[TO_BOOL] == INLINE_CACHE_ENTRIES_TO_BOOL);
2843
181k
    _PyToBoolCache *cache = (_PyToBoolCache *)(instr + 1);
2844
181k
    PyObject *value = PyStackRef_AsPyObjectBorrow(value_o);
2845
181k
    uint8_t specialized_op;
2846
181k
    if (PyBool_Check(value)) {
2847
25.7k
        specialized_op = TO_BOOL_BOOL;
2848
25.7k
        goto success;
2849
25.7k
    }
2850
155k
    if (PyLong_CheckExact(value)) {
2851
6.93k
        specialized_op = TO_BOOL_INT;
2852
6.93k
        goto success;
2853
6.93k
    }
2854
148k
    if (PyList_CheckExact(value)) {
2855
582
        specialized_op = TO_BOOL_LIST;
2856
582
        goto success;
2857
582
    }
2858
148k
    if (Py_IsNone(value)) {
2859
63.0k
        specialized_op = TO_BOOL_NONE;
2860
63.0k
        goto success;
2861
63.0k
    }
2862
85.2k
    if (PyUnicode_CheckExact(value)) {
2863
19.4k
        specialized_op = TO_BOOL_STR;
2864
19.4k
        goto success;
2865
19.4k
    }
2866
65.7k
    if (PyType_HasFeature(Py_TYPE(value), Py_TPFLAGS_HEAPTYPE)) {
2867
60.5k
        unsigned int version = 0;
2868
60.5k
        int err = _PyType_Validate(Py_TYPE(value), check_type_always_true, &version);
2869
60.5k
        if (err < 0) {
2870
0
            SPECIALIZATION_FAIL(TO_BOOL, SPEC_FAIL_OUT_OF_VERSIONS);
2871
0
            goto failure;
2872
0
        }
2873
60.5k
        else if (err > 0) {
2874
8.47k
            SPECIALIZATION_FAIL(TO_BOOL, err);
2875
8.47k
            goto failure;
2876
8.47k
        }
2877
2878
60.5k
        assert(err == 0);
2879
52.0k
        assert(version);
2880
52.0k
        write_u32(cache->version, version);
2881
52.0k
        specialized_op = TO_BOOL_ALWAYS_TRUE;
2882
52.0k
        goto success;
2883
60.5k
    }
2884
2885
5.17k
    SPECIALIZATION_FAIL(TO_BOOL, to_bool_fail_kind(value));
2886
13.6k
failure:
2887
13.6k
    unspecialize(instr);
2888
13.6k
    return;
2889
167k
success:
2890
167k
    specialize(instr, specialized_op);
2891
167k
}
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
35.0k
{
2915
35.0k
    PyObject *value = PyStackRef_AsPyObjectBorrow(value_st);
2916
2917
35.0k
    assert(ENABLE_SPECIALIZATION);
2918
35.0k
    assert(_PyOpcode_Caches[CONTAINS_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP);
2919
35.0k
    if (PyAnyDict_CheckExact(value)) {
2920
709
        specialize(instr, CONTAINS_OP_DICT);
2921
709
        return;
2922
709
    }
2923
34.3k
    if (PySet_CheckExact(value) || PyFrozenSet_CheckExact(value)) {
2924
697
        specialize(instr, CONTAINS_OP_SET);
2925
697
        return;
2926
697
    }
2927
2928
33.6k
    SPECIALIZATION_FAIL(CONTAINS_OP, containsop_fail_kind(value));
2929
33.6k
    unspecialize(instr);
2930
33.6k
    return;
2931
34.3k
}
2932
2933
void
2934
_Py_Specialize_GetIter(_PyStackRef iterable, _Py_CODEUNIT *instr)
2935
9.60k
{
2936
9.60k
    assert(ENABLE_SPECIALIZATION);
2937
9.60k
    PyTypeObject *tp = PyStackRef_TYPE(iterable);
2938
9.60k
    if (tp->_tp_iteritem != NULL) {
2939
2.41k
        specialize(instr, GET_ITER_VIRTUAL);
2940
2.41k
        return;
2941
2.41k
    }
2942
7.19k
    if (tp->tp_iter == PyObject_SelfIter) {
2943
722
        specialize(instr, GET_ITER_SELF);
2944
722
        return;
2945
722
    }
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
2.05M
{
2954
2.05M
    if (tstate->tracing == 0 && instr->op.code == RESUME) {
2955
93.7k
        if (tstate->interp->jit) {
2956
0
            PyCodeObject *co = (PyCodeObject *)PyStackRef_AsPyObjectBorrow(frame->f_executable);
2957
0
            if (co != NULL &&
2958
0
                PyCode_Check(co) &&
2959
0
                (co->co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) == 0) {
2960
0
                specialize(instr, RESUME_CHECK_JIT);
2961
0
                set_counter((_Py_BackoffCounter *)instr + 1, initial_resume_backoff_counter(&tstate->interp->opt_config));
2962
0
                return;
2963
0
            }
2964
0
        }
2965
93.7k
        specialize(instr, RESUME_CHECK);
2966
93.7k
        return;
2967
93.7k
    }
2968
1.96M
    unspecialize(instr);
2969
1.96M
    return;
2970
2.05M
}
2971
2972
#ifdef Py_STATS
2973
void
2974
_Py_GatherStats_GetIter(_PyStackRef iterable)
2975
{
2976
    PyTypeObject *tp = PyStackRef_TYPE(iterable);
2977
    int kind = SPEC_FAIL_OTHER;
2978
    if (tp == &PyTuple_Type) {
2979
        kind = SPEC_FAIL_ITER_TUPLE;
2980
    }
2981
    else if (tp == &PyList_Type) {
2982
        kind = SPEC_FAIL_ITER_LIST;
2983
    }
2984
    else if (tp == &PyDict_Type) {
2985
        kind = SPEC_FAIL_ITER_DICT_KEYS;
2986
    }
2987
    else if (tp == &PySet_Type) {
2988
        kind = SPEC_FAIL_ITER_SET;
2989
    }
2990
    else if (tp == &PyBytes_Type) {
2991
        kind = SPEC_FAIL_ITER_BYTES;
2992
    }
2993
    else if (tp == &PyEnum_Type) {
2994
        kind = SPEC_FAIL_ITER_ENUMERATE;
2995
    }
2996
    else if (tp == &PyUnicode_Type) {
2997
        kind = SPEC_FAIL_ITER_STRING;
2998
    }
2999
    else if (tp == &PyGen_Type) {
3000
        kind = SPEC_FAIL_ITER_GENERATOR;
3001
    }
3002
    else if (tp == &PyCoro_Type) {
3003
        kind = SPEC_FAIL_ITER_COROUTINE;
3004
    }
3005
    else if (tp == &PyAsyncGen_Type) {
3006
        kind = SPEC_FAIL_ITER_ASYNC_GENERATOR;
3007
    }
3008
    else if (tp == &_PyAsyncGenASend_Type) {
3009
        kind = SPEC_FAIL_ITER_ASYNC_GENERATOR_SEND;
3010
    }
3011
    else if (tp->tp_iter == PyObject_SelfIter) {
3012
        kind = SPEC_FAIL_ITER_SELF;
3013
    }
3014
    SPECIALIZATION_FAIL(GET_ITER, kind);
3015
}
3016
#endif
3017
3018
3019
/* Code init cleanup.
3020
 * CALL_ALLOC_AND_ENTER_INIT will set up
3021
 * the frame to execute the EXIT_INIT_CHECK
3022
 * instruction.
3023
 * Ends with a RESUME so that it is not traced.
3024
 * This is used as a plain code object, not a function,
3025
 * so must not access globals or builtins.
3026
 * There are a few other constraints imposed on the code
3027
 * by the free-threaded build:
3028
 *
3029
 * 1. The RESUME instruction must not be executed. Otherwise we may attempt to
3030
 *    free the statically allocated TLBC array.
3031
 * 2. It must contain no specializable instructions. Specializing multiple
3032
 *    copies of the same bytecode is not thread-safe in free-threaded builds.
3033
 *
3034
 * This should be dynamically allocated if either of those restrictions need to
3035
 * be lifted.
3036
 */
3037
3038
#define NO_LOC_4 (128 | (PY_CODE_LOCATION_INFO_NONE << 3) | 3)
3039
3040
static const PyBytesObject no_location = {
3041
    PyVarObject_HEAD_INIT(&PyBytes_Type, 1)
3042
    .ob_sval = { NO_LOC_4 }
3043
};
3044
3045
#ifdef Py_GIL_DISABLED
3046
static _PyCodeArray init_cleanup_tlbc = {
3047
    .size = 1,
3048
    .entries = {(char*) &_Py_InitCleanup.co_code_adaptive},
3049
};
3050
#endif
3051
3052
const struct _PyCode8 _Py_InitCleanup = {
3053
    _PyVarObject_HEAD_INIT(&PyCode_Type, 3),
3054
    .co_consts = (PyObject *)&_Py_SINGLETON(tuple_empty),
3055
    .co_names = (PyObject *)&_Py_SINGLETON(tuple_empty),
3056
    .co_exceptiontable = (PyObject *)&_Py_SINGLETON(bytes_empty),
3057
    .co_flags = CO_OPTIMIZED | CO_NO_MONITORING_EVENTS,
3058
    .co_localsplusnames = (PyObject *)&_Py_SINGLETON(tuple_empty),
3059
    .co_localspluskinds = (PyObject *)&_Py_SINGLETON(bytes_empty),
3060
    .co_filename = &_Py_ID(__init__),
3061
    .co_name = &_Py_ID(__init__),
3062
    .co_qualname = &_Py_ID(__init__),
3063
    .co_linetable = (PyObject *)&no_location,
3064
    ._co_firsttraceable = 4,
3065
    .co_stacksize = 2,
3066
    .co_framesize = 2 + FRAME_SPECIALS_SIZE,
3067
#ifdef Py_GIL_DISABLED
3068
    .co_tlbc = &init_cleanup_tlbc,
3069
#endif
3070
    .co_code_adaptive = {
3071
        EXIT_INIT_CHECK, 0,
3072
        RETURN_VALUE, 0,
3073
        RESUME, RESUME_AT_FUNC_START,
3074
        CACHE, 0, /* RESUME's cache */
3075
    }
3076
};