Coverage Report

Created: 2026-02-09 07:07

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