Coverage Report

Created: 2026-03-23 06:45

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