Branch data Line data Source code
1 : : #include "Python.h"
2 : : #include "pycore_code.h"
3 : : #include "pycore_dict.h"
4 : : #include "pycore_function.h" // _PyFunction_GetVersionForCurrentState()
5 : : #include "pycore_global_strings.h" // _Py_ID()
6 : : #include "pycore_long.h"
7 : : #include "pycore_moduleobject.h"
8 : : #include "pycore_object.h"
9 : : #include "pycore_opcode.h" // _PyOpcode_Caches
10 : : #include "structmember.h" // struct PyMemberDef, T_OFFSET_EX
11 : : #include "pycore_descrobject.h"
12 : :
13 : : #include <stdlib.h> // rand()
14 : :
15 : : /* For guidance on adding or extending families of instructions see
16 : : * ./adaptive.md
17 : : */
18 : :
19 : : /* Map from opcode to adaptive opcode.
20 : : Values of zero are ignored. */
21 : : uint8_t _PyOpcode_Adaptive[256] = {
22 : : [LOAD_ATTR] = LOAD_ATTR_ADAPTIVE,
23 : : [LOAD_GLOBAL] = LOAD_GLOBAL_ADAPTIVE,
24 : : [BINARY_SUBSCR] = BINARY_SUBSCR_ADAPTIVE,
25 : : [STORE_SUBSCR] = STORE_SUBSCR_ADAPTIVE,
26 : : [CALL] = CALL_ADAPTIVE,
27 : : [STORE_ATTR] = STORE_ATTR_ADAPTIVE,
28 : : [BINARY_OP] = BINARY_OP_ADAPTIVE,
29 : : [COMPARE_OP] = COMPARE_OP_ADAPTIVE,
30 : : [UNPACK_SEQUENCE] = UNPACK_SEQUENCE_ADAPTIVE,
31 : : [FOR_ITER] = FOR_ITER_ADAPTIVE,
32 : : };
33 : :
34 : : Py_ssize_t _Py_QuickenedCount = 0;
35 : : #ifdef Py_STATS
36 : : PyStats _py_stats_struct = { 0 };
37 : : PyStats *_py_stats = &_py_stats_struct;
38 : :
39 : : #define ADD_STAT_TO_DICT(res, field) \
40 : : do { \
41 : : PyObject *val = PyLong_FromUnsignedLongLong(stats->field); \
42 : : if (val == NULL) { \
43 : : Py_DECREF(res); \
44 : : return NULL; \
45 : : } \
46 : : if (PyDict_SetItemString(res, #field, val) == -1) { \
47 : : Py_DECREF(res); \
48 : : Py_DECREF(val); \
49 : : return NULL; \
50 : : } \
51 : : Py_DECREF(val); \
52 : : } while(0);
53 : :
54 : : static PyObject*
55 : : stats_to_dict(SpecializationStats *stats)
56 : : {
57 : : PyObject *res = PyDict_New();
58 : : if (res == NULL) {
59 : : return NULL;
60 : : }
61 : : ADD_STAT_TO_DICT(res, success);
62 : : ADD_STAT_TO_DICT(res, failure);
63 : : ADD_STAT_TO_DICT(res, hit);
64 : : ADD_STAT_TO_DICT(res, deferred);
65 : : ADD_STAT_TO_DICT(res, miss);
66 : : ADD_STAT_TO_DICT(res, deopt);
67 : : PyObject *failure_kinds = PyTuple_New(SPECIALIZATION_FAILURE_KINDS);
68 : : if (failure_kinds == NULL) {
69 : : Py_DECREF(res);
70 : : return NULL;
71 : : }
72 : : for (int i = 0; i < SPECIALIZATION_FAILURE_KINDS; i++) {
73 : : PyObject *stat = PyLong_FromUnsignedLongLong(stats->failure_kinds[i]);
74 : : if (stat == NULL) {
75 : : Py_DECREF(res);
76 : : Py_DECREF(failure_kinds);
77 : : return NULL;
78 : : }
79 : : PyTuple_SET_ITEM(failure_kinds, i, stat);
80 : : }
81 : : if (PyDict_SetItemString(res, "failure_kinds", failure_kinds)) {
82 : : Py_DECREF(res);
83 : : Py_DECREF(failure_kinds);
84 : : return NULL;
85 : : }
86 : : Py_DECREF(failure_kinds);
87 : : return res;
88 : : }
89 : : #undef ADD_STAT_TO_DICT
90 : :
91 : : static int
92 : : add_stat_dict(
93 : : PyObject *res,
94 : : int opcode,
95 : : const char *name) {
96 : :
97 : : SpecializationStats *stats = &_py_stats_struct.opcode_stats[opcode].specialization;
98 : : PyObject *d = stats_to_dict(stats);
99 : : if (d == NULL) {
100 : : return -1;
101 : : }
102 : : int err = PyDict_SetItemString(res, name, d);
103 : : Py_DECREF(d);
104 : : return err;
105 : : }
106 : :
107 : : #ifdef Py_STATS
108 : : PyObject*
109 : : _Py_GetSpecializationStats(void) {
110 : : PyObject *stats = PyDict_New();
111 : : if (stats == NULL) {
112 : : return NULL;
113 : : }
114 : : int err = 0;
115 : : err += add_stat_dict(stats, LOAD_ATTR, "load_attr");
116 : : err += add_stat_dict(stats, LOAD_GLOBAL, "load_global");
117 : : err += add_stat_dict(stats, BINARY_SUBSCR, "binary_subscr");
118 : : err += add_stat_dict(stats, STORE_SUBSCR, "store_subscr");
119 : : err += add_stat_dict(stats, STORE_ATTR, "store_attr");
120 : : err += add_stat_dict(stats, CALL, "call");
121 : : err += add_stat_dict(stats, BINARY_OP, "binary_op");
122 : : err += add_stat_dict(stats, COMPARE_OP, "compare_op");
123 : : err += add_stat_dict(stats, UNPACK_SEQUENCE, "unpack_sequence");
124 : : if (err < 0) {
125 : : Py_DECREF(stats);
126 : : return NULL;
127 : : }
128 : : return stats;
129 : : }
130 : : #endif
131 : :
132 : :
133 : : #define PRINT_STAT(i, field) \
134 : : if (stats[i].field) { \
135 : : fprintf(out, " opcode[%d]." #field " : %" PRIu64 "\n", i, stats[i].field); \
136 : : }
137 : :
138 : : static void
139 : : print_spec_stats(FILE *out, OpcodeStats *stats)
140 : : {
141 : : /* Mark some opcodes as specializable for stats,
142 : : * even though we don't specialize them yet. */
143 : : fprintf(out, "opcode[%d].specializable : 1\n", BINARY_SLICE);
144 : : fprintf(out, "opcode[%d].specializable : 1\n", STORE_SLICE);
145 : : for (int i = 0; i < 256; i++) {
146 : : if (_PyOpcode_Adaptive[i]) {
147 : : fprintf(out, "opcode[%d].specializable : 1\n", i);
148 : : }
149 : : PRINT_STAT(i, specialization.success);
150 : : PRINT_STAT(i, specialization.failure);
151 : : PRINT_STAT(i, specialization.hit);
152 : : PRINT_STAT(i, specialization.deferred);
153 : : PRINT_STAT(i, specialization.miss);
154 : : PRINT_STAT(i, specialization.deopt);
155 : : PRINT_STAT(i, execution_count);
156 : : for (int j = 0; j < SPECIALIZATION_FAILURE_KINDS; j++) {
157 : : uint64_t val = stats[i].specialization.failure_kinds[j];
158 : : if (val) {
159 : : fprintf(out, " opcode[%d].specialization.failure_kinds[%d] : %"
160 : : PRIu64 "\n", i, j, val);
161 : : }
162 : : }
163 : : for(int j = 0; j < 256; j++) {
164 : : if (stats[i].pair_count[j]) {
165 : : fprintf(out, "opcode[%d].pair_count[%d] : %" PRIu64 "\n",
166 : : i, j, stats[i].pair_count[j]);
167 : : }
168 : : }
169 : : }
170 : : }
171 : : #undef PRINT_STAT
172 : :
173 : :
174 : : static void
175 : : print_call_stats(FILE *out, CallStats *stats)
176 : : {
177 : : fprintf(out, "Calls to PyEval_EvalDefault: %" PRIu64 "\n", stats->pyeval_calls);
178 : : fprintf(out, "Calls to Python functions inlined: %" PRIu64 "\n", stats->inlined_py_calls);
179 : : fprintf(out, "Frames pushed: %" PRIu64 "\n", stats->frames_pushed);
180 : : fprintf(out, "Frame objects created: %" PRIu64 "\n", stats->frame_objects_created);
181 : : for (int i = 0; i < EVAL_CALL_KINDS; i++) {
182 : : fprintf(out, "Calls via PyEval_EvalFrame[%d] : %" PRIu64 "\n", i, stats->eval_calls[i]);
183 : : }
184 : : }
185 : :
186 : : static void
187 : : print_object_stats(FILE *out, ObjectStats *stats)
188 : : {
189 : : fprintf(out, "Object allocations from freelist: %" PRIu64 "\n", stats->from_freelist);
190 : : fprintf(out, "Object frees to freelist: %" PRIu64 "\n", stats->to_freelist);
191 : : fprintf(out, "Object allocations: %" PRIu64 "\n", stats->allocations);
192 : : fprintf(out, "Object allocations to 512 bytes: %" PRIu64 "\n", stats->allocations512);
193 : : fprintf(out, "Object allocations to 4 kbytes: %" PRIu64 "\n", stats->allocations4k);
194 : : fprintf(out, "Object allocations over 4 kbytes: %" PRIu64 "\n", stats->allocations_big);
195 : : fprintf(out, "Object frees: %" PRIu64 "\n", stats->frees);
196 : : fprintf(out, "Object new values: %" PRIu64 "\n", stats->new_values);
197 : : fprintf(out, "Object interpreter increfs: %" PRIu64 "\n", stats->interpreter_increfs);
198 : : fprintf(out, "Object interpreter decrefs: %" PRIu64 "\n", stats->interpreter_decrefs);
199 : : fprintf(out, "Object increfs: %" PRIu64 "\n", stats->increfs);
200 : : fprintf(out, "Object decrefs: %" PRIu64 "\n", stats->decrefs);
201 : : fprintf(out, "Object materialize dict (on request): %" PRIu64 "\n", stats->dict_materialized_on_request);
202 : : fprintf(out, "Object materialize dict (new key): %" PRIu64 "\n", stats->dict_materialized_new_key);
203 : : fprintf(out, "Object materialize dict (too big): %" PRIu64 "\n", stats->dict_materialized_too_big);
204 : : fprintf(out, "Object materialize dict (str subclass): %" PRIu64 "\n", stats->dict_materialized_str_subclass);
205 : : }
206 : :
207 : : static void
208 : : print_stats(FILE *out, PyStats *stats) {
209 : : print_spec_stats(out, stats->opcode_stats);
210 : : print_call_stats(out, &stats->call_stats);
211 : : print_object_stats(out, &stats->object_stats);
212 : : }
213 : :
214 : : void
215 : : _Py_StatsClear(void)
216 : : {
217 : : _py_stats_struct = (PyStats) { 0 };
218 : : }
219 : :
220 : : void
221 : : _Py_PrintSpecializationStats(int to_file)
222 : : {
223 : : if (_py_stats == NULL) {
224 : : return;
225 : : }
226 : : FILE *out = stderr;
227 : : if (to_file) {
228 : : /* Write to a file instead of stderr. */
229 : : # ifdef MS_WINDOWS
230 : : const char *dirname = "c:\\temp\\py_stats\\";
231 : : # else
232 : : const char *dirname = "/tmp/py_stats/";
233 : : # endif
234 : : /* Use random 160 bit number as file name,
235 : : * to avoid both accidental collisions and
236 : : * symlink attacks. */
237 : : unsigned char rand[20];
238 : : char hex_name[41];
239 : : _PyOS_URandomNonblock(rand, 20);
240 : : for (int i = 0; i < 20; i++) {
241 : : hex_name[2*i] = "0123456789abcdef"[rand[i]&15];
242 : : hex_name[2*i+1] = "0123456789abcdef"[(rand[i]>>4)&15];
243 : : }
244 : : hex_name[40] = '\0';
245 : : char buf[64];
246 : : assert(strlen(dirname) + 40 + strlen(".txt") < 64);
247 : : sprintf(buf, "%s%s.txt", dirname, hex_name);
248 : : FILE *fout = fopen(buf, "w");
249 : : if (fout) {
250 : : out = fout;
251 : : }
252 : : }
253 : : else {
254 : : fprintf(out, "Specialization stats:\n");
255 : : }
256 : : print_stats(out, _py_stats);
257 : : if (out != stderr) {
258 : : fclose(out);
259 : : }
260 : : }
261 : :
262 : : #ifdef Py_STATS
263 : :
264 : : #define SPECIALIZATION_FAIL(opcode, kind) \
265 : : do { \
266 : : if (_py_stats) { \
267 : : _py_stats->opcode_stats[opcode].specialization.failure_kinds[kind]++; \
268 : : } \
269 : : } while (0)
270 : :
271 : : #endif
272 : : #endif
273 : :
274 : : #ifndef SPECIALIZATION_FAIL
275 : : #define SPECIALIZATION_FAIL(opcode, kind) ((void)0)
276 : : #endif
277 : :
278 : : // Insert adaptive instructions and superinstructions. This cannot fail.
279 : : void
280 : 602238 : _PyCode_Quicken(PyCodeObject *code)
281 : : {
282 : 602238 : _Py_QuickenedCount++;
283 : 602238 : int previous_opcode = -1;
284 : 602238 : _Py_CODEUNIT *instructions = _PyCode_CODE(code);
285 [ + + ]: 48093508 : for (int i = 0; i < Py_SIZE(code); i++) {
286 : 47491270 : int opcode = _Py_OPCODE(instructions[i]);
287 : 47491270 : uint8_t adaptive_opcode = _PyOpcode_Adaptive[opcode];
288 [ + + ]: 47491270 : if (adaptive_opcode) {
289 : 11528854 : _Py_SET_OPCODE(instructions[i], adaptive_opcode);
290 : : // Make sure the adaptive counter is zero:
291 : : assert(instructions[i + 1] == 0);
292 : 11528854 : previous_opcode = -1;
293 : 11528854 : i += _PyOpcode_Caches[opcode];
294 : : }
295 : : else {
296 : : assert(!_PyOpcode_Caches[opcode]);
297 [ + + + + : 35962416 : switch (opcode) {
+ + ]
298 : 553918 : case JUMP_BACKWARD:
299 : 553918 : _Py_SET_OPCODE(instructions[i], JUMP_BACKWARD_QUICK);
300 : 553918 : break;
301 : 633328 : case RESUME:
302 : 633328 : _Py_SET_OPCODE(instructions[i], RESUME_QUICK);
303 : 633328 : break;
304 [ + + + + ]: 7855162 : case LOAD_FAST:
305 : : switch(previous_opcode) {
306 : 1435759 : case LOAD_FAST:
307 : 1435759 : _Py_SET_OPCODE(instructions[i - 1],
308 : : LOAD_FAST__LOAD_FAST);
309 : 1435759 : break;
310 : 924143 : case STORE_FAST:
311 : 924143 : _Py_SET_OPCODE(instructions[i - 1],
312 : : STORE_FAST__LOAD_FAST);
313 : 924143 : break;
314 : 435166 : case LOAD_CONST:
315 : 435166 : _Py_SET_OPCODE(instructions[i - 1],
316 : : LOAD_CONST__LOAD_FAST);
317 : 435166 : break;
318 : : }
319 : 7855162 : break;
320 : 2076545 : case STORE_FAST:
321 [ + + ]: 2076545 : if (previous_opcode == STORE_FAST) {
322 : 178162 : _Py_SET_OPCODE(instructions[i - 1],
323 : : STORE_FAST__STORE_FAST);
324 : : }
325 : 2076545 : break;
326 : 7400840 : case LOAD_CONST:
327 [ + + ]: 7400840 : if (previous_opcode == LOAD_FAST) {
328 : 757412 : _Py_SET_OPCODE(instructions[i - 1],
329 : : LOAD_FAST__LOAD_CONST);
330 : : }
331 : 7400840 : break;
332 : : }
333 : 35962416 : previous_opcode = opcode;
334 : : }
335 : : }
336 : 602238 : }
337 : :
338 : : static inline int
339 : 6742333 : miss_counter_start(void) {
340 : : /* Starting value for the counter.
341 : : * This value needs to be not too low, otherwise
342 : : * it would cause excessive de-optimization.
343 : : * Neither should it be too high, or that would delay
344 : : * de-optimization excessively when it is needed.
345 : : * A value around 50 seems to work, and we choose a
346 : : * prime number to avoid artifacts.
347 : : */
348 : 6742333 : return 53;
349 : : }
350 : :
351 : : #define SIMPLE_FUNCTION 0
352 : :
353 : : /* Common */
354 : :
355 : : #define SPEC_FAIL_OTHER 0
356 : : #define SPEC_FAIL_NO_DICT 1
357 : : #define SPEC_FAIL_OVERRIDDEN 2
358 : : #define SPEC_FAIL_OUT_OF_VERSIONS 3
359 : : #define SPEC_FAIL_OUT_OF_RANGE 4
360 : : #define SPEC_FAIL_EXPECTED_ERROR 5
361 : : #define SPEC_FAIL_WRONG_NUMBER_ARGUMENTS 6
362 : :
363 : : #define SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT 18
364 : :
365 : : /* Attributes */
366 : :
367 : : #define SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR 8
368 : : #define SPEC_FAIL_ATTR_NON_OVERRIDING_DESCRIPTOR 9
369 : : #define SPEC_FAIL_ATTR_NOT_DESCRIPTOR 10
370 : : #define SPEC_FAIL_ATTR_METHOD 11
371 : : #define SPEC_FAIL_ATTR_MUTABLE_CLASS 12
372 : : #define SPEC_FAIL_ATTR_PROPERTY 13
373 : : #define SPEC_FAIL_ATTR_NON_OBJECT_SLOT 14
374 : : #define SPEC_FAIL_ATTR_READ_ONLY 15
375 : : #define SPEC_FAIL_ATTR_AUDITED_SLOT 16
376 : : #define SPEC_FAIL_ATTR_NOT_MANAGED_DICT 17
377 : : #define SPEC_FAIL_ATTR_NON_STRING_OR_SPLIT 18
378 : : #define SPEC_FAIL_ATTR_MODULE_ATTR_NOT_FOUND 19
379 : :
380 : : #define SPEC_FAIL_ATTR_SHADOWED 21
381 : : #define SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD 22
382 : : #define SPEC_FAIL_ATTR_CLASS_METHOD_OBJ 23
383 : : #define SPEC_FAIL_ATTR_OBJECT_SLOT 24
384 : : #define SPEC_FAIL_ATTR_HAS_MANAGED_DICT 25
385 : : #define SPEC_FAIL_ATTR_INSTANCE_ATTRIBUTE 26
386 : : #define SPEC_FAIL_ATTR_METACLASS_ATTRIBUTE 27
387 : :
388 : : /* Binary subscr and store subscr */
389 : :
390 : : #define SPEC_FAIL_SUBSCR_ARRAY_INT 8
391 : : #define SPEC_FAIL_SUBSCR_ARRAY_SLICE 9
392 : : #define SPEC_FAIL_SUBSCR_LIST_SLICE 10
393 : : #define SPEC_FAIL_SUBSCR_TUPLE_SLICE 11
394 : : #define SPEC_FAIL_SUBSCR_STRING_INT 12
395 : : #define SPEC_FAIL_SUBSCR_STRING_SLICE 13
396 : : #define SPEC_FAIL_SUBSCR_BUFFER_INT 15
397 : : #define SPEC_FAIL_SUBSCR_BUFFER_SLICE 16
398 : : #define SPEC_FAIL_SUBSCR_SEQUENCE_INT 17
399 : :
400 : : /* Store subscr */
401 : : #define SPEC_FAIL_SUBSCR_BYTEARRAY_INT 18
402 : : #define SPEC_FAIL_SUBSCR_BYTEARRAY_SLICE 19
403 : : #define SPEC_FAIL_SUBSCR_PY_SIMPLE 20
404 : : #define SPEC_FAIL_SUBSCR_PY_OTHER 21
405 : : #define SPEC_FAIL_SUBSCR_DICT_SUBCLASS_NO_OVERRIDE 22
406 : : #define SPEC_FAIL_SUBSCR_NOT_HEAP_TYPE 23
407 : :
408 : : /* Binary op */
409 : :
410 : : #define SPEC_FAIL_BINARY_OP_ADD_DIFFERENT_TYPES 8
411 : : #define SPEC_FAIL_BINARY_OP_ADD_OTHER 9
412 : : #define SPEC_FAIL_BINARY_OP_AND_DIFFERENT_TYPES 10
413 : : #define SPEC_FAIL_BINARY_OP_AND_INT 11
414 : : #define SPEC_FAIL_BINARY_OP_AND_OTHER 12
415 : : #define SPEC_FAIL_BINARY_OP_FLOOR_DIVIDE 13
416 : : #define SPEC_FAIL_BINARY_OP_LSHIFT 14
417 : : #define SPEC_FAIL_BINARY_OP_MATRIX_MULTIPLY 15
418 : : #define SPEC_FAIL_BINARY_OP_MULTIPLY_DIFFERENT_TYPES 16
419 : : #define SPEC_FAIL_BINARY_OP_MULTIPLY_OTHER 17
420 : : #define SPEC_FAIL_BINARY_OP_OR 18
421 : : #define SPEC_FAIL_BINARY_OP_POWER 19
422 : : #define SPEC_FAIL_BINARY_OP_REMAINDER 20
423 : : #define SPEC_FAIL_BINARY_OP_RSHIFT 21
424 : : #define SPEC_FAIL_BINARY_OP_SUBTRACT_DIFFERENT_TYPES 22
425 : : #define SPEC_FAIL_BINARY_OP_SUBTRACT_OTHER 23
426 : : #define SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_DIFFERENT_TYPES 24
427 : : #define SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_FLOAT 25
428 : : #define SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_OTHER 26
429 : : #define SPEC_FAIL_BINARY_OP_XOR 27
430 : :
431 : : /* Calls */
432 : : #define SPEC_FAIL_CALL_COMPLEX_PARAMETERS 9
433 : : #define SPEC_FAIL_CALL_CO_NOT_OPTIMIZED 10
434 : : /* SPEC_FAIL_METHOD defined as 11 above */
435 : :
436 : : #define SPEC_FAIL_CALL_INSTANCE_METHOD 11
437 : : #define SPEC_FAIL_CALL_CMETHOD 12
438 : : #define SPEC_FAIL_CALL_PYCFUNCTION 13
439 : : #define SPEC_FAIL_CALL_PYCFUNCTION_WITH_KEYWORDS 14
440 : : #define SPEC_FAIL_CALL_PYCFUNCTION_FAST_WITH_KEYWORDS 15
441 : : #define SPEC_FAIL_CALL_PYCFUNCTION_NOARGS 16
442 : : #define SPEC_FAIL_CALL_BAD_CALL_FLAGS 17
443 : : #define SPEC_FAIL_CALL_CLASS 18
444 : : #define SPEC_FAIL_CALL_PYTHON_CLASS 19
445 : : #define SPEC_FAIL_CALL_METHOD_DESCRIPTOR 20
446 : : #define SPEC_FAIL_CALL_BOUND_METHOD 21
447 : : #define SPEC_FAIL_CALL_STR 22
448 : : #define SPEC_FAIL_CALL_CLASS_NO_VECTORCALL 23
449 : : #define SPEC_FAIL_CALL_CLASS_MUTABLE 24
450 : : #define SPEC_FAIL_CALL_KWNAMES 25
451 : : #define SPEC_FAIL_CALL_METHOD_WRAPPER 26
452 : : #define SPEC_FAIL_CALL_OPERATOR_WRAPPER 27
453 : : #define SPEC_FAIL_CALL_PYFUNCTION 28
454 : : #define SPEC_FAIL_CALL_PEP_523 29
455 : :
456 : : /* COMPARE_OP */
457 : : #define SPEC_FAIL_COMPARE_OP_DIFFERENT_TYPES 12
458 : : #define SPEC_FAIL_COMPARE_OP_STRING 13
459 : : #define SPEC_FAIL_COMPARE_OP_NOT_FOLLOWED_BY_COND_JUMP 14
460 : : #define SPEC_FAIL_COMPARE_OP_BIG_INT 15
461 : : #define SPEC_FAIL_COMPARE_OP_BYTES 16
462 : : #define SPEC_FAIL_COMPARE_OP_TUPLE 17
463 : : #define SPEC_FAIL_COMPARE_OP_LIST 18
464 : : #define SPEC_FAIL_COMPARE_OP_SET 19
465 : : #define SPEC_FAIL_COMPARE_OP_BOOL 20
466 : : #define SPEC_FAIL_COMPARE_OP_BASEOBJECT 21
467 : : #define SPEC_FAIL_COMPARE_OP_FLOAT_LONG 22
468 : : #define SPEC_FAIL_COMPARE_OP_LONG_FLOAT 23
469 : : #define SPEC_FAIL_COMPARE_OP_EXTENDED_ARG 24
470 : :
471 : : /* FOR_ITER */
472 : : #define SPEC_FAIL_FOR_ITER_GENERATOR 10
473 : : #define SPEC_FAIL_FOR_ITER_COROUTINE 11
474 : : #define SPEC_FAIL_FOR_ITER_ASYNC_GENERATOR 12
475 : : #define SPEC_FAIL_FOR_ITER_LIST 13
476 : : #define SPEC_FAIL_FOR_ITER_TUPLE 14
477 : : #define SPEC_FAIL_FOR_ITER_SET 15
478 : : #define SPEC_FAIL_FOR_ITER_STRING 16
479 : : #define SPEC_FAIL_FOR_ITER_BYTES 17
480 : : #define SPEC_FAIL_FOR_ITER_RANGE 18
481 : : #define SPEC_FAIL_FOR_ITER_ITERTOOLS 19
482 : : #define SPEC_FAIL_FOR_ITER_DICT_KEYS 20
483 : : #define SPEC_FAIL_FOR_ITER_DICT_ITEMS 21
484 : : #define SPEC_FAIL_FOR_ITER_DICT_VALUES 22
485 : : #define SPEC_FAIL_FOR_ITER_ENUMERATE 23
486 : : #define SPEC_FAIL_FOR_ITER_MAP 24
487 : : #define SPEC_FAIL_FOR_ITER_ZIP 25
488 : : #define SPEC_FAIL_FOR_ITER_SEQ_ITER 26
489 : : #define SPEC_FAIL_FOR_ITER_REVERSED_LIST 27
490 : : #define SPEC_FAIL_FOR_ITER_CALLABLE 28
491 : : #define SPEC_FAIL_FOR_ITER_ASCII_STRING 29
492 : :
493 : : // UNPACK_SEQUENCE
494 : :
495 : : #define SPEC_FAIL_UNPACK_SEQUENCE_ITERATOR 8
496 : : #define SPEC_FAIL_UNPACK_SEQUENCE_SEQUENCE 9
497 : :
498 : :
499 : : static int
500 : 376938 : specialize_module_load_attr(PyObject *owner, _Py_CODEUNIT *instr,
501 : : PyObject *name, int opcode, int opcode_module)
502 : : {
503 : 376938 : _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
504 : 376938 : PyModuleObject *m = (PyModuleObject *)owner;
505 : 376938 : PyObject *value = NULL;
506 : : assert((owner->ob_type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0);
507 : 376938 : PyDictObject *dict = (PyDictObject *)m->md_dict;
508 [ - + ]: 376938 : if (dict == NULL) {
509 : : SPECIALIZATION_FAIL(opcode, SPEC_FAIL_NO_DICT);
510 : 0 : return -1;
511 : : }
512 [ - + ]: 376938 : if (dict->ma_keys->dk_kind != DICT_KEYS_UNICODE) {
513 : : SPECIALIZATION_FAIL(opcode, SPEC_FAIL_ATTR_NON_STRING_OR_SPLIT);
514 : 0 : return -1;
515 : : }
516 : 376938 : Py_ssize_t index = _PyDict_GetItemHint(dict, &_Py_ID(__getattr__), -1,
517 : : &value);
518 : : assert(index != DKIX_ERROR);
519 [ + + ]: 376938 : if (index != DKIX_EMPTY) {
520 : : SPECIALIZATION_FAIL(opcode, SPEC_FAIL_ATTR_MODULE_ATTR_NOT_FOUND);
521 : 5349 : return -1;
522 : : }
523 : 371589 : index = _PyDict_GetItemHint(dict, name, -1, &value);
524 : : assert (index != DKIX_ERROR);
525 [ + + ]: 371589 : if (index != (uint16_t)index) {
526 : : SPECIALIZATION_FAIL(opcode, SPEC_FAIL_OUT_OF_RANGE);
527 : 41806 : return -1;
528 : : }
529 : 329783 : uint32_t keys_version = _PyDictKeys_GetVersionForCurrentState(dict->ma_keys);
530 [ - + ]: 329783 : if (keys_version == 0) {
531 : : SPECIALIZATION_FAIL(opcode, SPEC_FAIL_OUT_OF_VERSIONS);
532 : 0 : return -1;
533 : : }
534 : 329783 : write_u32(cache->version, keys_version);
535 : 329783 : cache->index = (uint16_t)index;
536 : 329783 : _Py_SET_OPCODE(*instr, opcode_module);
537 : 329783 : return 0;
538 : : }
539 : :
540 : :
541 : :
542 : : /* Attribute specialization */
543 : :
544 : : typedef enum {
545 : : OVERRIDING, /* Is an overriding descriptor, and will remain so. */
546 : : METHOD, /* Attribute has Py_TPFLAGS_METHOD_DESCRIPTOR set */
547 : : PROPERTY, /* Is a property */
548 : : OBJECT_SLOT, /* Is an object slot descriptor */
549 : : OTHER_SLOT, /* Is a slot descriptor of another type */
550 : : NON_OVERRIDING, /* Is another non-overriding descriptor, and is an instance of an immutable class*/
551 : : BUILTIN_CLASSMETHOD, /* Builtin methods with METH_CLASS */
552 : : PYTHON_CLASSMETHOD, /* Python classmethod(func) object */
553 : : NON_DESCRIPTOR, /* Is not a descriptor, and is an instance of an immutable class */
554 : : MUTABLE, /* Instance of a mutable class; might, or might not, be a descriptor */
555 : : ABSENT, /* Attribute is not present on the class */
556 : : DUNDER_CLASS, /* __class__ attribute */
557 : : GETSET_OVERRIDDEN /* __getattribute__ or __setattr__ has been overridden */
558 : : } DescriptorClassification;
559 : :
560 : :
561 : : static DescriptorClassification
562 : 2827970 : analyze_descriptor(PyTypeObject *type, PyObject *name, PyObject **descr, int store)
563 : : {
564 [ + + ]: 2827970 : if (store) {
565 [ + + ]: 602851 : if (type->tp_setattro != PyObject_GenericSetAttr) {
566 : 100033 : *descr = NULL;
567 : 100033 : return GETSET_OVERRIDDEN;
568 : : }
569 : : }
570 : : else {
571 [ + + ]: 2225119 : if (type->tp_getattro != PyObject_GenericGetAttr) {
572 : 184111 : *descr = NULL;
573 : 184111 : return GETSET_OVERRIDDEN;
574 : : }
575 : : }
576 : 2543826 : PyObject *descriptor = _PyType_Lookup(type, name);
577 : 2543826 : *descr = descriptor;
578 [ + + ]: 2543826 : if (descriptor == NULL) {
579 : 949875 : return ABSENT;
580 : : }
581 : 1593951 : PyTypeObject *desc_cls = Py_TYPE(descriptor);
582 [ + + ]: 1593951 : if (!(desc_cls->tp_flags & Py_TPFLAGS_IMMUTABLETYPE)) {
583 : 37274 : return MUTABLE;
584 : : }
585 [ + + ]: 1556677 : if (desc_cls->tp_descr_set) {
586 [ + + ]: 381273 : if (desc_cls == &PyMemberDescr_Type) {
587 : 184528 : PyMemberDescrObject *member = (PyMemberDescrObject *)descriptor;
588 : 184528 : struct PyMemberDef *dmem = member->d_member;
589 [ + + ]: 184528 : if (dmem->type == T_OBJECT_EX) {
590 : 23111 : return OBJECT_SLOT;
591 : : }
592 : 161417 : return OTHER_SLOT;
593 : : }
594 [ + + ]: 196745 : if (desc_cls == &PyProperty_Type) {
595 : 34343 : return PROPERTY;
596 : : }
597 [ + + ]: 162402 : if (PyUnicode_CompareWithASCIIString(name, "__class__") == 0) {
598 [ + - ]: 52053 : if (descriptor == _PyType_Lookup(&PyBaseObject_Type, name)) {
599 : 52053 : return DUNDER_CLASS;
600 : : }
601 : : }
602 [ + + ]: 110349 : if (store) {
603 : 23497 : return OVERRIDING;
604 : : }
605 : : }
606 [ + + ]: 1262256 : if (desc_cls->tp_descr_get) {
607 [ + + ]: 984635 : if (desc_cls->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR) {
608 : 768043 : return METHOD;
609 : : }
610 [ + + ]: 216592 : if (Py_IS_TYPE(descriptor, &PyClassMethodDescr_Type)) {
611 : 25515 : return BUILTIN_CLASSMETHOD;
612 : : }
613 [ + + ]: 191077 : if (Py_IS_TYPE(descriptor, &PyClassMethod_Type)) {
614 : 71236 : return PYTHON_CLASSMETHOD;
615 : : }
616 : 119841 : return NON_OVERRIDING;
617 : : }
618 : 277621 : return NON_DESCRIPTOR;
619 : : }
620 : :
621 : : static int
622 : 1190006 : specialize_dict_access(
623 : : PyObject *owner, _Py_CODEUNIT *instr, PyTypeObject *type,
624 : : DescriptorClassification kind, PyObject *name,
625 : : int base_op, int values_op, int hint_op)
626 : : {
627 : : assert(kind == NON_OVERRIDING || kind == NON_DESCRIPTOR || kind == ABSENT ||
628 : : kind == BUILTIN_CLASSMETHOD || kind == PYTHON_CLASSMETHOD);
629 : : // No descriptor, or non overriding.
630 [ + + ]: 1190006 : if ((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {
631 : : SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);
632 : 278816 : return 0;
633 : : }
634 : 911190 : _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
635 : 911190 : PyObject **dictptr = _PyObject_ManagedDictPointer(owner);
636 : 911190 : PyDictObject *dict = (PyDictObject *)*dictptr;
637 [ + + ]: 911190 : if (dict == NULL) {
638 : : // Virtual dictionary
639 : 767739 : PyDictKeysObject *keys = ((PyHeapTypeObject *)type)->ht_cached_keys;
640 : : assert(PyUnicode_CheckExact(name));
641 : 767739 : Py_ssize_t index = _PyDictKeys_StringLookup(keys, name);
642 : : assert (index != DKIX_ERROR);
643 [ + + ]: 767739 : if (index != (uint16_t)index) {
644 : : SPECIALIZATION_FAIL(base_op, SPEC_FAIL_OUT_OF_RANGE);
645 : 52834 : return 0;
646 : : }
647 : 714905 : write_u32(cache->version, type->tp_version_tag);
648 : 714905 : cache->index = (uint16_t)index;
649 : 714905 : _Py_SET_OPCODE(*instr, values_op);
650 : : }
651 : : else {
652 [ - + ]: 143451 : if (!PyDict_CheckExact(dict)) {
653 : : SPECIALIZATION_FAIL(base_op, SPEC_FAIL_NO_DICT);
654 : 12107 : return 0;
655 : : }
656 : : // We found an instance with a __dict__.
657 : 143451 : PyObject *value = NULL;
658 : : Py_ssize_t hint =
659 : 143451 : _PyDict_GetItemHint(dict, name, -1, &value);
660 [ + + ]: 143451 : if (hint != (uint16_t)hint) {
661 : : SPECIALIZATION_FAIL(base_op, SPEC_FAIL_OUT_OF_RANGE);
662 : 12107 : return 0;
663 : : }
664 : 131344 : cache->index = (uint16_t)hint;
665 : 131344 : write_u32(cache->version, type->tp_version_tag);
666 : 131344 : _Py_SET_OPCODE(*instr, hint_op);
667 : : }
668 : 846249 : return 1;
669 : : }
670 : :
671 : : static int specialize_attr_loadmethod(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name,
672 : : PyObject* descr, DescriptorClassification kind);
673 : : static int specialize_class_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name);
674 : : static int function_kind(PyCodeObject *code);
675 : :
676 : : int
677 : 3030859 : _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
678 : : {
679 : : assert(_PyOpcode_Caches[LOAD_ATTR] == INLINE_CACHE_ENTRIES_LOAD_ATTR);
680 : 3030859 : _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
681 [ + + ]: 3030859 : if (PyModule_CheckExact(owner)) {
682 : 376938 : int err = specialize_module_load_attr(owner, instr, name, LOAD_ATTR,
683 : : LOAD_ATTR_MODULE);
684 [ + + ]: 376938 : if (err) {
685 : 47155 : goto fail;
686 : : }
687 : 329783 : goto success;
688 : : }
689 [ + + ]: 2653921 : if (PyType_Check(owner)) {
690 : 717575 : int err = specialize_class_load_attr(owner, instr, name);
691 [ + + ]: 717575 : if (err) {
692 : 595802 : goto fail;
693 : : }
694 : 121773 : goto success;
695 : : }
696 : 1936346 : PyTypeObject *type = Py_TYPE(owner);
697 [ - + ]: 1936346 : if (type->tp_dict == NULL) {
698 [ # # ]: 0 : if (PyType_Ready(type) < 0) {
699 : 0 : return -1;
700 : : }
701 : : }
702 : 1936346 : PyObject *descr = NULL;
703 : 1936346 : DescriptorClassification kind = analyze_descriptor(type, name, &descr, 0);
704 : : assert(descr != NULL || kind == ABSENT || kind == GETSET_OVERRIDDEN);
705 [ - + + + : 1936346 : switch(kind) {
+ + + + +
- ]
706 : 0 : case OVERRIDING:
707 : : SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
708 : 0 : goto fail;
709 : 761628 : case METHOD:
710 : : {
711 : 761628 : int oparg = _Py_OPARG(*instr);
712 [ + + ]: 761628 : if (oparg & 1) {
713 [ + + ]: 614113 : if (specialize_attr_loadmethod(owner, instr, name, descr, kind)) {
714 : 554898 : goto success;
715 : : }
716 : : }
717 : : SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
718 : 206730 : goto fail;
719 : : }
720 : 27141 : case PROPERTY:
721 : : {
722 : 27141 : _PyLoadMethodCache *lm_cache = (_PyLoadMethodCache *)(instr + 1);
723 : : assert(Py_TYPE(descr) == &PyProperty_Type);
724 : 27141 : PyObject *fget = ((_PyPropertyObject *)descr)->prop_get;
725 [ - + ]: 27141 : if (fget == NULL) {
726 : : SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
727 : 0 : goto fail;
728 : : }
729 [ + + ]: 27141 : if (Py_TYPE(fget) != &PyFunction_Type) {
730 : : SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_PROPERTY);
731 : 20 : goto fail;
732 : : }
733 : 27121 : PyFunctionObject *func = (PyFunctionObject *)fget;
734 : 27121 : PyCodeObject *fcode = (PyCodeObject *)func->func_code;
735 : 27121 : int kind = function_kind(fcode);
736 [ - + ]: 27121 : if (kind != SIMPLE_FUNCTION) {
737 : : SPECIALIZATION_FAIL(LOAD_ATTR, kind);
738 : 0 : goto fail;
739 : : }
740 [ - + ]: 27121 : if (fcode->co_argcount != 1) {
741 : : SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
742 : 0 : goto fail;
743 : : }
744 : 27121 : int version = _PyFunction_GetVersionForCurrentState(func);
745 [ - + ]: 27121 : if (version == 0) {
746 : : SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
747 : 0 : goto fail;
748 : : }
749 : 27121 : write_u32(lm_cache->keys_version, version);
750 : : assert(type->tp_version_tag != 0);
751 : 27121 : write_u32(lm_cache->type_version, type->tp_version_tag);
752 : : /* borrowed */
753 : 27121 : write_obj(lm_cache->descr, fget);
754 : 27121 : _Py_SET_OPCODE(*instr, LOAD_ATTR_PROPERTY);
755 : 27121 : goto success;
756 : : }
757 : 11588 : case OBJECT_SLOT:
758 : : {
759 : 11588 : PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
760 : 11588 : struct PyMemberDef *dmem = member->d_member;
761 : 11588 : Py_ssize_t offset = dmem->offset;
762 [ - + ]: 11588 : if (dmem->flags & PY_AUDIT_READ) {
763 : : SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_AUDITED_SLOT);
764 : 0 : goto fail;
765 : : }
766 [ - + ]: 11588 : if (offset != (uint16_t)offset) {
767 : : SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE);
768 : 0 : goto fail;
769 : : }
770 : : assert(dmem->type == T_OBJECT_EX);
771 : : assert(offset > 0);
772 : 11588 : cache->index = (uint16_t)offset;
773 : 11588 : write_u32(cache->version, type->tp_version_tag);
774 : 11588 : _Py_SET_OPCODE(*instr, LOAD_ATTR_SLOT);
775 : 11588 : goto success;
776 : : }
777 : 51964 : case DUNDER_CLASS:
778 : : {
779 : 51964 : Py_ssize_t offset = offsetof(PyObject, ob_type);
780 : : assert(offset == (uint16_t)offset);
781 : 51964 : cache->index = (uint16_t)offset;
782 : 51964 : write_u32(cache->version, type->tp_version_tag);
783 : 51964 : _Py_SET_OPCODE(*instr, LOAD_ATTR_SLOT);
784 : 51964 : goto success;
785 : : }
786 : 129828 : case OTHER_SLOT:
787 : : SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT);
788 : 129828 : goto fail;
789 : 26428 : case MUTABLE:
790 : : SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
791 : 26428 : goto fail;
792 : 156304 : case GETSET_OVERRIDDEN:
793 : : SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OVERRIDDEN);
794 : 156304 : goto fail;
795 : 771465 : case BUILTIN_CLASSMETHOD:
796 : : case PYTHON_CLASSMETHOD:
797 : : case NON_OVERRIDING:
798 : : case NON_DESCRIPTOR:
799 : : case ABSENT:
800 : 771465 : break;
801 : : }
802 : 771465 : int err = specialize_dict_access(
803 : : owner, instr, type, kind, name,
804 : : LOAD_ATTR, LOAD_ATTR_INSTANCE_VALUE, LOAD_ATTR_WITH_HINT
805 : : );
806 [ - + ]: 771465 : if (err < 0) {
807 : 0 : return -1;
808 : : }
809 [ + + ]: 771465 : if (err) {
810 : 534618 : goto success;
811 : : }
812 : 236847 : fail:
813 : : STAT_INC(LOAD_ATTR, failure);
814 : : assert(!PyErr_Occurred());
815 : 1399114 : cache->counter = adaptive_counter_backoff(cache->counter);
816 : 1399114 : return 0;
817 : 1631745 : success:
818 : : STAT_INC(LOAD_ATTR, success);
819 : : assert(!PyErr_Occurred());
820 : 1631745 : cache->counter = miss_counter_start();
821 : 1631745 : return 0;
822 : : }
823 : :
824 : : int
825 : 702398 : _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
826 : : {
827 : : assert(_PyOpcode_Caches[STORE_ATTR] == INLINE_CACHE_ENTRIES_STORE_ATTR);
828 : 702398 : _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
829 : 702398 : PyTypeObject *type = Py_TYPE(owner);
830 [ + + ]: 702398 : if (PyModule_CheckExact(owner)) {
831 : : SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OVERRIDDEN);
832 : 99547 : goto fail;
833 : : }
834 : : PyObject *descr;
835 : 602851 : DescriptorClassification kind = analyze_descriptor(type, name, &descr, 1);
836 [ + + + + : 602851 : switch(kind) {
+ + + +
- ]
837 : 23497 : case OVERRIDING:
838 : : SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);
839 : 23497 : goto fail;
840 : 837 : case METHOD:
841 : : SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_METHOD);
842 : 837 : goto fail;
843 : 7202 : case PROPERTY:
844 : : SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_PROPERTY);
845 : 7202 : goto fail;
846 : 11523 : case OBJECT_SLOT:
847 : : {
848 : 11523 : PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
849 : 11523 : struct PyMemberDef *dmem = member->d_member;
850 : 11523 : Py_ssize_t offset = dmem->offset;
851 [ + + ]: 11523 : if (dmem->flags & READONLY) {
852 : : SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_READ_ONLY);
853 : 12 : goto fail;
854 : : }
855 [ - + ]: 11511 : if (offset != (uint16_t)offset) {
856 : : SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OUT_OF_RANGE);
857 : 0 : goto fail;
858 : : }
859 : : assert(dmem->type == T_OBJECT_EX);
860 : : assert(offset > 0);
861 : 11511 : cache->index = (uint16_t)offset;
862 : 11511 : write_u32(cache->version, type->tp_version_tag);
863 : 11511 : _Py_SET_OPCODE(*instr, STORE_ATTR_SLOT);
864 : 11511 : goto success;
865 : : }
866 : 31674 : case DUNDER_CLASS:
867 : : case OTHER_SLOT:
868 : : SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT);
869 : 31674 : goto fail;
870 : 9544 : case MUTABLE:
871 : : SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
872 : 9544 : goto fail;
873 : 100033 : case GETSET_OVERRIDDEN:
874 : : SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OVERRIDDEN);
875 : 100033 : goto fail;
876 : 418541 : case BUILTIN_CLASSMETHOD:
877 : : case PYTHON_CLASSMETHOD:
878 : : case NON_OVERRIDING:
879 : : case NON_DESCRIPTOR:
880 : : case ABSENT:
881 : 418541 : break;
882 : : }
883 : :
884 : 418541 : int err = specialize_dict_access(
885 : : owner, instr, type, kind, name,
886 : : STORE_ATTR, STORE_ATTR_INSTANCE_VALUE, STORE_ATTR_WITH_HINT
887 : : );
888 [ - + ]: 418541 : if (err < 0) {
889 : 0 : return -1;
890 : : }
891 [ + + ]: 418541 : if (err) {
892 : 311631 : goto success;
893 : : }
894 : 106910 : fail:
895 : : STAT_INC(STORE_ATTR, failure);
896 : : assert(!PyErr_Occurred());
897 : 379256 : cache->counter = adaptive_counter_backoff(cache->counter);
898 : 379256 : return 0;
899 : 323142 : success:
900 : : STAT_INC(STORE_ATTR, success);
901 : : assert(!PyErr_Occurred());
902 : 323142 : cache->counter = miss_counter_start();
903 : 323142 : return 0;
904 : : }
905 : :
906 : :
907 : : #ifdef Py_STATS
908 : : static int
909 : : load_attr_fail_kind(DescriptorClassification kind)
910 : : {
911 : : switch (kind) {
912 : : case OVERRIDING:
913 : : return SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR;
914 : : case METHOD:
915 : : return SPEC_FAIL_ATTR_METHOD;
916 : : case PROPERTY:
917 : : return SPEC_FAIL_ATTR_PROPERTY;
918 : : case OBJECT_SLOT:
919 : : return SPEC_FAIL_ATTR_OBJECT_SLOT;
920 : : case OTHER_SLOT:
921 : : return SPEC_FAIL_ATTR_NON_OBJECT_SLOT;
922 : : case DUNDER_CLASS:
923 : : return SPEC_FAIL_OTHER;
924 : : case MUTABLE:
925 : : return SPEC_FAIL_ATTR_MUTABLE_CLASS;
926 : : case GETSET_OVERRIDDEN:
927 : : return SPEC_FAIL_OVERRIDDEN;
928 : : case BUILTIN_CLASSMETHOD:
929 : : return SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD;
930 : : case PYTHON_CLASSMETHOD:
931 : : return SPEC_FAIL_ATTR_CLASS_METHOD_OBJ;
932 : : case NON_OVERRIDING:
933 : : return SPEC_FAIL_ATTR_NON_OVERRIDING_DESCRIPTOR;
934 : : case NON_DESCRIPTOR:
935 : : return SPEC_FAIL_ATTR_NOT_DESCRIPTOR;
936 : : case ABSENT:
937 : : return SPEC_FAIL_ATTR_INSTANCE_ATTRIBUTE;
938 : : }
939 : : Py_UNREACHABLE();
940 : : }
941 : : #endif
942 : :
943 : : static int
944 : 717575 : specialize_class_load_attr(PyObject *owner, _Py_CODEUNIT *instr,
945 : : PyObject *name)
946 : : {
947 : 717575 : _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1);
948 [ + + + + ]: 717575 : if (!PyType_CheckExact(owner) || _PyType_Lookup(Py_TYPE(owner), name)) {
949 : : SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METACLASS_ATTRIBUTE);
950 : 428802 : return -1;
951 : : }
952 : 288773 : PyObject *descr = NULL;
953 : 288773 : DescriptorClassification kind = 0;
954 : 288773 : kind = analyze_descriptor((PyTypeObject *)owner, name, &descr, 0);
955 [ + + ]: 288773 : switch (kind) {
956 : 121773 : case METHOD:
957 : : case NON_DESCRIPTOR:
958 : 121773 : write_u32(cache->type_version, ((PyTypeObject *)owner)->tp_version_tag);
959 : 121773 : write_obj(cache->descr, descr);
960 : 121773 : _Py_SET_OPCODE(*instr, LOAD_ATTR_CLASS);
961 : 121773 : return 0;
962 : : #ifdef Py_STATS
963 : : case ABSENT:
964 : : SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
965 : : return -1;
966 : : #endif
967 : 167000 : default:
968 : : SPECIALIZATION_FAIL(LOAD_ATTR, load_attr_fail_kind(kind));
969 : 167000 : return -1;
970 : : }
971 : : }
972 : :
973 : : typedef enum {
974 : : MANAGED_VALUES = 1,
975 : : MANAGED_DICT = 2,
976 : : OFFSET_DICT = 3,
977 : : NO_DICT = 4,
978 : : LAZY_DICT = 5,
979 : : } ObjectDictKind;
980 : :
981 : : // Please collect stats carefully before and after modifying. A subtle change
982 : : // can cause a significant drop in cache hits. A possible test is
983 : : // python.exe -m test_typing test_re test_dis test_zlib.
984 : : static int
985 : 614113 : specialize_attr_loadmethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name,
986 : : PyObject *descr, DescriptorClassification kind)
987 : : {
988 : 614113 : _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1);
989 : 614113 : PyTypeObject *owner_cls = Py_TYPE(owner);
990 : :
991 : : assert(kind == METHOD && descr != NULL);
992 : : ObjectDictKind dictkind;
993 : : PyDictKeysObject *keys;
994 [ + + ]: 614113 : if (owner_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT) {
995 : 265697 : PyObject *dict = *_PyObject_ManagedDictPointer(owner);
996 : 265697 : keys = ((PyHeapTypeObject *)owner_cls)->ht_cached_keys;
997 [ + + ]: 265697 : if (dict == NULL) {
998 : 220969 : dictkind = MANAGED_VALUES;
999 : : }
1000 : : else {
1001 : 44728 : dictkind = MANAGED_DICT;
1002 : : }
1003 : : }
1004 : : else {
1005 : 348416 : Py_ssize_t dictoffset = owner_cls->tp_dictoffset;
1006 [ + + - + ]: 348416 : if (dictoffset < 0 || dictoffset > INT16_MAX) {
1007 : : SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE);
1008 : 13559 : goto fail;
1009 : : }
1010 [ + + ]: 334857 : if (dictoffset == 0) {
1011 : 323752 : dictkind = NO_DICT;
1012 : 323752 : keys = NULL;
1013 : : }
1014 : : else {
1015 : 11105 : PyObject *dict = *(PyObject **) ((char *)owner + dictoffset);
1016 [ + + ]: 11105 : if (dict == NULL) {
1017 : : // This object will have a dict if user access __dict__
1018 : 7088 : dictkind = LAZY_DICT;
1019 : 7088 : keys = NULL;
1020 : : }
1021 : : else {
1022 : 4017 : keys = ((PyDictObject *)dict)->ma_keys;
1023 : 4017 : dictkind = OFFSET_DICT;
1024 : : }
1025 : : }
1026 : : }
1027 [ + + + + ]: 600554 : if (dictkind == MANAGED_VALUES || dictkind == OFFSET_DICT) {
1028 : 224986 : Py_ssize_t index = _PyDictKeys_StringLookup(keys, name);
1029 [ + + ]: 224986 : if (index != DKIX_EMPTY) {
1030 : : SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_SHADOWED);
1031 : 928 : goto fail;
1032 : : }
1033 : 224058 : uint32_t keys_version = _PyDictKeys_GetVersionForCurrentState(keys);
1034 [ - + ]: 224058 : if (keys_version == 0) {
1035 : : SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
1036 : 0 : goto fail;
1037 : : }
1038 : 224058 : write_u32(cache->keys_version, keys_version);
1039 : : }
1040 [ + + + + : 599626 : switch(dictkind) {
+ - ]
1041 : 323752 : case NO_DICT:
1042 : 323752 : _Py_SET_OPCODE(*instr, LOAD_ATTR_METHOD_NO_DICT);
1043 : 323752 : break;
1044 : 220052 : case MANAGED_VALUES:
1045 : 220052 : _Py_SET_OPCODE(*instr, LOAD_ATTR_METHOD_WITH_VALUES);
1046 : 220052 : break;
1047 : 44728 : case MANAGED_DICT:
1048 : : SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_HAS_MANAGED_DICT);
1049 : 44728 : goto fail;
1050 : 4006 : case OFFSET_DICT:
1051 : : assert(owner_cls->tp_dictoffset > 0 && owner_cls->tp_dictoffset <= INT16_MAX);
1052 : 4006 : _Py_SET_OPCODE(*instr, LOAD_ATTR_METHOD_WITH_DICT);
1053 : 4006 : break;
1054 : 7088 : case LAZY_DICT:
1055 : : assert(owner_cls->tp_dictoffset > 0 && owner_cls->tp_dictoffset <= INT16_MAX);
1056 : 7088 : _Py_SET_OPCODE(*instr, LOAD_ATTR_METHOD_LAZY_DICT);
1057 : 7088 : break;
1058 : : }
1059 : : /* `descr` is borrowed. This is safe for methods (even inherited ones from
1060 : : * super classes!) as long as tp_version_tag is validated for two main reasons:
1061 : : *
1062 : : * 1. The class will always hold a reference to the method so it will
1063 : : * usually not be GC-ed. Should it be deleted in Python, e.g.
1064 : : * `del obj.meth`, tp_version_tag will be invalidated, because of reason 2.
1065 : : *
1066 : : * 2. The pre-existing type method cache (MCACHE) uses the same principles
1067 : : * of caching a borrowed descriptor. The MCACHE infrastructure does all the
1068 : : * heavy lifting for us. E.g. it invalidates tp_version_tag on any MRO
1069 : : * modification, on any type object change along said MRO, etc. (see
1070 : : * PyType_Modified usages in typeobject.c). The MCACHE has been
1071 : : * working since Python 2.6 and it's battle-tested.
1072 : : */
1073 : 554898 : write_u32(cache->type_version, owner_cls->tp_version_tag);
1074 : 554898 : write_obj(cache->descr, descr);
1075 : : // Fall through.
1076 : 554898 : return 1;
1077 : 59215 : fail:
1078 : 59215 : return 0;
1079 : : }
1080 : :
1081 : : int
1082 : 1910482 : _Py_Specialize_LoadGlobal(
1083 : : PyObject *globals, PyObject *builtins,
1084 : : _Py_CODEUNIT *instr, PyObject *name)
1085 : : {
1086 : : assert(_PyOpcode_Caches[LOAD_GLOBAL] == INLINE_CACHE_ENTRIES_LOAD_GLOBAL);
1087 : : /* Use inline cache */
1088 : 1910482 : _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)(instr + 1);
1089 : : assert(PyUnicode_CheckExact(name));
1090 [ + + ]: 1910482 : if (!PyDict_CheckExact(globals)) {
1091 : 4021 : goto fail;
1092 : : }
1093 : 1906461 : PyDictKeysObject * globals_keys = ((PyDictObject *)globals)->ma_keys;
1094 [ - + ]: 1906461 : if (!DK_IS_UNICODE(globals_keys)) {
1095 : : SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT);
1096 : 0 : goto fail;
1097 : : }
1098 : 1906461 : Py_ssize_t index = _PyDictKeys_StringLookup(globals_keys, name);
1099 [ - + ]: 1906461 : if (index == DKIX_ERROR) {
1100 : : SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT);
1101 : 0 : goto fail;
1102 : : }
1103 [ + + ]: 1906461 : if (index != DKIX_EMPTY) {
1104 [ - + ]: 1148895 : if (index != (uint16_t)index) {
1105 : 0 : goto fail;
1106 : : }
1107 : 1148895 : uint32_t keys_version = _PyDictKeys_GetVersionForCurrentState(globals_keys);
1108 [ - + ]: 1148895 : if (keys_version == 0) {
1109 : 0 : goto fail;
1110 : : }
1111 : 1148895 : cache->index = (uint16_t)index;
1112 : 1148895 : write_u32(cache->module_keys_version, keys_version);
1113 : 1148895 : _Py_SET_OPCODE(*instr, LOAD_GLOBAL_MODULE);
1114 : 1148895 : goto success;
1115 : : }
1116 [ - + ]: 757566 : if (!PyDict_CheckExact(builtins)) {
1117 : 0 : goto fail;
1118 : : }
1119 : 757566 : PyDictKeysObject * builtin_keys = ((PyDictObject *)builtins)->ma_keys;
1120 [ - + ]: 757566 : if (!DK_IS_UNICODE(builtin_keys)) {
1121 : : SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT);
1122 : 0 : goto fail;
1123 : : }
1124 : 757566 : index = _PyDictKeys_StringLookup(builtin_keys, name);
1125 [ - + ]: 757566 : if (index == DKIX_ERROR) {
1126 : : SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT);
1127 : 0 : goto fail;
1128 : : }
1129 [ + + ]: 757566 : if (index != (uint16_t)index) {
1130 : 3 : goto fail;
1131 : : }
1132 : 757563 : uint32_t globals_version = _PyDictKeys_GetVersionForCurrentState(globals_keys);
1133 [ - + ]: 757563 : if (globals_version == 0) {
1134 : : SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
1135 : 0 : goto fail;
1136 : : }
1137 : 757563 : uint32_t builtins_version = _PyDictKeys_GetVersionForCurrentState(builtin_keys);
1138 [ - + ]: 757563 : if (builtins_version == 0) {
1139 : : SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
1140 : 0 : goto fail;
1141 : : }
1142 [ - + ]: 757563 : if (builtins_version > UINT16_MAX) {
1143 : : SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
1144 : 0 : goto fail;
1145 : : }
1146 : 757563 : cache->index = (uint16_t)index;
1147 : 757563 : write_u32(cache->module_keys_version, globals_version);
1148 : 757563 : cache->builtin_keys_version = (uint16_t)builtins_version;
1149 : 757563 : _Py_SET_OPCODE(*instr, LOAD_GLOBAL_BUILTIN);
1150 : 757563 : goto success;
1151 : 4024 : fail:
1152 : : STAT_INC(LOAD_GLOBAL, failure);
1153 : : assert(!PyErr_Occurred());
1154 : 4024 : cache->counter = adaptive_counter_backoff(cache->counter);
1155 : 4024 : return 0;
1156 : 1906458 : success:
1157 : : STAT_INC(LOAD_GLOBAL, success);
1158 : : assert(!PyErr_Occurred());
1159 : 1906458 : cache->counter = miss_counter_start();
1160 : 1906458 : return 0;
1161 : : }
1162 : :
1163 : : #ifdef Py_STATS
1164 : : static int
1165 : : binary_subscr_fail_kind(PyTypeObject *container_type, PyObject *sub)
1166 : : {
1167 : : if (container_type == &PyUnicode_Type) {
1168 : : if (PyLong_CheckExact(sub)) {
1169 : : return SPEC_FAIL_SUBSCR_STRING_INT;
1170 : : }
1171 : : if (PySlice_Check(sub)) {
1172 : : return SPEC_FAIL_SUBSCR_STRING_SLICE;
1173 : : }
1174 : : return SPEC_FAIL_OTHER;
1175 : : }
1176 : : else if (strcmp(container_type->tp_name, "array.array") == 0) {
1177 : : if (PyLong_CheckExact(sub)) {
1178 : : return SPEC_FAIL_SUBSCR_ARRAY_INT;
1179 : : }
1180 : : if (PySlice_Check(sub)) {
1181 : : return SPEC_FAIL_SUBSCR_ARRAY_SLICE;
1182 : : }
1183 : : return SPEC_FAIL_OTHER;
1184 : : }
1185 : : else if (container_type->tp_as_buffer) {
1186 : : if (PyLong_CheckExact(sub)) {
1187 : : return SPEC_FAIL_SUBSCR_BUFFER_INT;
1188 : : }
1189 : : if (PySlice_Check(sub)) {
1190 : : return SPEC_FAIL_SUBSCR_BUFFER_SLICE;
1191 : : }
1192 : : return SPEC_FAIL_OTHER;
1193 : : }
1194 : : else if (container_type->tp_as_sequence) {
1195 : : if (PyLong_CheckExact(sub) && container_type->tp_as_sequence->sq_item) {
1196 : : return SPEC_FAIL_SUBSCR_SEQUENCE_INT;
1197 : : }
1198 : : }
1199 : : return SPEC_FAIL_OTHER;
1200 : : }
1201 : : #endif
1202 : :
1203 : : static int
1204 : 1182865 : function_kind(PyCodeObject *code) {
1205 : 1182865 : int flags = code->co_flags;
1206 [ + + + + ]: 1182865 : if ((flags & (CO_VARKEYWORDS | CO_VARARGS)) || code->co_kwonlyargcount) {
1207 : 402932 : return SPEC_FAIL_CALL_COMPLEX_PARAMETERS;
1208 : : }
1209 [ + + ]: 779933 : if ((flags & CO_OPTIMIZED) == 0) {
1210 : 9 : return SPEC_FAIL_CALL_CO_NOT_OPTIMIZED;
1211 : : }
1212 : 779924 : return SIMPLE_FUNCTION;
1213 : : }
1214 : :
1215 : : int
1216 : 591643 : _Py_Specialize_BinarySubscr(
1217 : : PyObject *container, PyObject *sub, _Py_CODEUNIT *instr)
1218 : : {
1219 : : assert(_PyOpcode_Caches[BINARY_SUBSCR] ==
1220 : : INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
1221 : 591643 : _PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)(instr + 1);
1222 : 591643 : PyTypeObject *container_type = Py_TYPE(container);
1223 [ + + ]: 591643 : if (container_type == &PyList_Type) {
1224 [ + + ]: 155117 : if (PyLong_CheckExact(sub)) {
1225 : 145132 : _Py_SET_OPCODE(*instr, BINARY_SUBSCR_LIST_INT);
1226 : 145132 : goto success;
1227 : : }
1228 : : SPECIALIZATION_FAIL(BINARY_SUBSCR,
1229 : : PySlice_Check(sub) ? SPEC_FAIL_SUBSCR_LIST_SLICE : SPEC_FAIL_OTHER);
1230 : 9985 : goto fail;
1231 : : }
1232 [ + + ]: 436526 : if (container_type == &PyTuple_Type) {
1233 [ + + ]: 130487 : if (PyLong_CheckExact(sub)) {
1234 : 130087 : _Py_SET_OPCODE(*instr, BINARY_SUBSCR_TUPLE_INT);
1235 : 130087 : goto success;
1236 : : }
1237 : : SPECIALIZATION_FAIL(BINARY_SUBSCR,
1238 : : PySlice_Check(sub) ? SPEC_FAIL_SUBSCR_TUPLE_SLICE : SPEC_FAIL_OTHER);
1239 : 400 : goto fail;
1240 : : }
1241 [ + + ]: 306039 : if (container_type == &PyDict_Type) {
1242 : 59662 : _Py_SET_OPCODE(*instr, BINARY_SUBSCR_DICT);
1243 : 59662 : goto success;
1244 : : }
1245 : 246377 : PyTypeObject *cls = Py_TYPE(container);
1246 : 246377 : PyObject *descriptor = _PyType_Lookup(cls, &_Py_ID(__getitem__));
1247 [ + + + + ]: 246377 : if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {
1248 [ - + ]: 20116 : if (!(container_type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
1249 : : SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_SUBSCR_NOT_HEAP_TYPE);
1250 : 0 : goto fail;
1251 : : }
1252 : 20116 : PyFunctionObject *func = (PyFunctionObject *)descriptor;
1253 : 20116 : PyCodeObject *fcode = (PyCodeObject *)func->func_code;
1254 : 20116 : int kind = function_kind(fcode);
1255 [ + + ]: 20116 : if (kind != SIMPLE_FUNCTION) {
1256 : : SPECIALIZATION_FAIL(BINARY_SUBSCR, kind);
1257 : 681 : goto fail;
1258 : : }
1259 [ - + ]: 19435 : if (fcode->co_argcount != 2) {
1260 : : SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1261 : 0 : goto fail;
1262 : : }
1263 : : assert(cls->tp_version_tag != 0);
1264 : 19435 : write_u32(cache->type_version, cls->tp_version_tag);
1265 : 19435 : int version = _PyFunction_GetVersionForCurrentState(func);
1266 [ + - - + ]: 19435 : if (version == 0 || version != (uint16_t)version) {
1267 : : SPECIALIZATION_FAIL(BINARY_SUBSCR, version == 0 ?
1268 : : SPEC_FAIL_OUT_OF_VERSIONS : SPEC_FAIL_OUT_OF_RANGE);
1269 : 0 : goto fail;
1270 : : }
1271 : 19435 : cache->func_version = version;
1272 : 19435 : ((PyHeapTypeObject *)container_type)->_spec_cache.getitem = descriptor;
1273 : 19435 : _Py_SET_OPCODE(*instr, BINARY_SUBSCR_GETITEM);
1274 : 19435 : goto success;
1275 : : }
1276 : : SPECIALIZATION_FAIL(BINARY_SUBSCR,
1277 : : binary_subscr_fail_kind(container_type, sub));
1278 : 226261 : fail:
1279 : : STAT_INC(BINARY_SUBSCR, failure);
1280 : : assert(!PyErr_Occurred());
1281 : 237327 : cache->counter = adaptive_counter_backoff(cache->counter);
1282 : 237327 : return 0;
1283 : 354316 : success:
1284 : : STAT_INC(BINARY_SUBSCR, success);
1285 : : assert(!PyErr_Occurred());
1286 : 354316 : cache->counter = miss_counter_start();
1287 : 354316 : return 0;
1288 : : }
1289 : :
1290 : : int
1291 : 275035 : _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *instr)
1292 : : {
1293 : 275035 : _PyStoreSubscrCache *cache = (_PyStoreSubscrCache *)(instr + 1);
1294 : 275035 : PyTypeObject *container_type = Py_TYPE(container);
1295 [ + + ]: 275035 : if (container_type == &PyList_Type) {
1296 [ + + ]: 30551 : if (PyLong_CheckExact(sub)) {
1297 [ + + + + ]: 29806 : if ((Py_SIZE(sub) == 0 || Py_SIZE(sub) == 1)
1298 [ + + ]: 20715 : && ((PyLongObject *)sub)->ob_digit[0] < (size_t)PyList_GET_SIZE(container))
1299 : : {
1300 : 20712 : _Py_SET_OPCODE(*instr, STORE_SUBSCR_LIST_INT);
1301 : 20712 : goto success;
1302 : : }
1303 : : else {
1304 : : SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);
1305 : 9094 : goto fail;
1306 : : }
1307 : : }
1308 [ + - ]: 745 : else if (PySlice_Check(sub)) {
1309 : : SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_LIST_SLICE);
1310 : 745 : goto fail;
1311 : : }
1312 : : else {
1313 : : SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
1314 : 0 : goto fail;
1315 : : }
1316 : : }
1317 [ + + ]: 244484 : if (container_type == &PyDict_Type) {
1318 : 167556 : _Py_SET_OPCODE(*instr, STORE_SUBSCR_DICT);
1319 : 167556 : goto success;
1320 : : }
1321 : : #ifdef Py_STATS
1322 : : PyMappingMethods *as_mapping = container_type->tp_as_mapping;
1323 : : if (as_mapping && (as_mapping->mp_ass_subscript
1324 : : == PyDict_Type.tp_as_mapping->mp_ass_subscript)) {
1325 : : SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_DICT_SUBCLASS_NO_OVERRIDE);
1326 : : goto fail;
1327 : : }
1328 : : if (PyObject_CheckBuffer(container)) {
1329 : : if (PyLong_CheckExact(sub) && (((size_t)Py_SIZE(sub)) > 1)) {
1330 : : SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);
1331 : : }
1332 : : else if (strcmp(container_type->tp_name, "array.array") == 0) {
1333 : : if (PyLong_CheckExact(sub)) {
1334 : : SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_ARRAY_INT);
1335 : : }
1336 : : else if (PySlice_Check(sub)) {
1337 : : SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_ARRAY_SLICE);
1338 : : }
1339 : : else {
1340 : : SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
1341 : : }
1342 : : }
1343 : : else if (PyByteArray_CheckExact(container)) {
1344 : : if (PyLong_CheckExact(sub)) {
1345 : : SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_BYTEARRAY_INT);
1346 : : }
1347 : : else if (PySlice_Check(sub)) {
1348 : : SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_BYTEARRAY_SLICE);
1349 : : }
1350 : : else {
1351 : : SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
1352 : : }
1353 : : }
1354 : : else {
1355 : : if (PyLong_CheckExact(sub)) {
1356 : : SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_BUFFER_INT);
1357 : : }
1358 : : else if (PySlice_Check(sub)) {
1359 : : SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_BUFFER_SLICE);
1360 : : }
1361 : : else {
1362 : : SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
1363 : : }
1364 : : }
1365 : : goto fail;
1366 : : }
1367 : : PyObject *descriptor = _PyType_Lookup(container_type, &_Py_ID(__setitem__));
1368 : : if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {
1369 : : PyFunctionObject *func = (PyFunctionObject *)descriptor;
1370 : : PyCodeObject *code = (PyCodeObject *)func->func_code;
1371 : : int kind = function_kind(code);
1372 : : if (kind == SIMPLE_FUNCTION) {
1373 : : SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_PY_SIMPLE);
1374 : : }
1375 : : else {
1376 : : SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_PY_OTHER);
1377 : : }
1378 : : goto fail;
1379 : : }
1380 : : #endif
1381 : : SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);
1382 : 76928 : fail:
1383 : : STAT_INC(STORE_SUBSCR, failure);
1384 : : assert(!PyErr_Occurred());
1385 : 86767 : cache->counter = adaptive_counter_backoff(cache->counter);
1386 : 86767 : return 0;
1387 : 188268 : success:
1388 : : STAT_INC(STORE_SUBSCR, success);
1389 : : assert(!PyErr_Occurred());
1390 : 188268 : cache->counter = miss_counter_start();
1391 : 188268 : return 0;
1392 : : }
1393 : :
1394 : : static int
1395 : 600454 : specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
1396 : : PyObject *kwnames)
1397 : : {
1398 : : assert(_Py_OPCODE(*instr) == CALL_ADAPTIVE);
1399 : 600454 : PyTypeObject *tp = _PyType_CAST(callable);
1400 [ + + ]: 600454 : if (tp->tp_new == PyBaseObject_Type.tp_new) {
1401 : : SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PYTHON_CLASS);
1402 : 212288 : return -1;
1403 : : }
1404 [ + + ]: 388166 : if (tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) {
1405 : 337590 : int oparg = _Py_OPARG(*instr);
1406 [ + + + + : 337590 : if (nargs == 1 && kwnames == NULL && oparg == 1) {
+ + ]
1407 [ + + ]: 176462 : if (tp == &PyUnicode_Type) {
1408 : 7403 : _Py_SET_OPCODE(*instr, CALL_NO_KW_STR_1);
1409 : 7403 : return 0;
1410 : : }
1411 [ + + ]: 169059 : else if (tp == &PyType_Type) {
1412 : 22401 : _Py_SET_OPCODE(*instr, CALL_NO_KW_TYPE_1);
1413 : 22401 : return 0;
1414 : : }
1415 [ + + ]: 146658 : else if (tp == &PyTuple_Type) {
1416 : 14525 : _Py_SET_OPCODE(*instr, CALL_NO_KW_TUPLE_1);
1417 : 14525 : return 0;
1418 : : }
1419 : : }
1420 [ + + ]: 293261 : if (tp->tp_vectorcall != NULL) {
1421 : 104638 : _Py_SET_OPCODE(*instr, CALL_BUILTIN_CLASS);
1422 : 104638 : return 0;
1423 : : }
1424 : : SPECIALIZATION_FAIL(CALL, tp == &PyUnicode_Type ?
1425 : : SPEC_FAIL_CALL_STR : SPEC_FAIL_CALL_CLASS_NO_VECTORCALL);
1426 : 188623 : return -1;
1427 : : }
1428 : : SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_CLASS_MUTABLE);
1429 : 50576 : return -1;
1430 : : }
1431 : :
1432 : : #ifdef Py_STATS
1433 : : static int
1434 : : builtin_call_fail_kind(int ml_flags)
1435 : : {
1436 : : switch (ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
1437 : : METH_KEYWORDS | METH_METHOD)) {
1438 : : case METH_VARARGS:
1439 : : return SPEC_FAIL_CALL_PYCFUNCTION;
1440 : : case METH_VARARGS | METH_KEYWORDS:
1441 : : return SPEC_FAIL_CALL_PYCFUNCTION_WITH_KEYWORDS;
1442 : : case METH_FASTCALL | METH_KEYWORDS:
1443 : : return SPEC_FAIL_CALL_PYCFUNCTION_FAST_WITH_KEYWORDS;
1444 : : case METH_NOARGS:
1445 : : return SPEC_FAIL_CALL_PYCFUNCTION_NOARGS;
1446 : : /* This case should never happen with PyCFunctionObject -- only
1447 : : PyMethodObject. See zlib.compressobj()'s methods for an example.
1448 : : */
1449 : : case METH_METHOD | METH_FASTCALL | METH_KEYWORDS:
1450 : : default:
1451 : : return SPEC_FAIL_CALL_BAD_CALL_FLAGS;
1452 : : }
1453 : : }
1454 : : #endif
1455 : :
1456 : : static int
1457 : 616905 : specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr,
1458 : : int nargs, PyObject *kwnames)
1459 : : {
1460 : : assert(_Py_OPCODE(*instr) == CALL_ADAPTIVE);
1461 [ + + ]: 616905 : if (kwnames) {
1462 : : SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES);
1463 : 3935 : return -1;
1464 : : }
1465 : :
1466 [ + + + + : 612970 : switch (descr->d_method->ml_flags &
+ ]
1467 : : (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
1468 : : METH_KEYWORDS | METH_METHOD)) {
1469 : 51348 : case METH_NOARGS: {
1470 [ - + ]: 51348 : if (nargs != 1) {
1471 : : SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1472 : 0 : return -1;
1473 : : }
1474 : 51348 : _Py_SET_OPCODE(*instr, CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS);
1475 : 51348 : return 0;
1476 : : }
1477 : 128035 : case METH_O: {
1478 [ - + ]: 128035 : if (nargs != 2) {
1479 : : SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1480 : 0 : return -1;
1481 : : }
1482 : 128035 : PyInterpreterState *interp = _PyInterpreterState_GET();
1483 : 128035 : PyObject *list_append = interp->callable_cache.list_append;
1484 : 128035 : _Py_CODEUNIT next = instr[INLINE_CACHE_ENTRIES_CALL + 1];
1485 : 128035 : bool pop = (_Py_OPCODE(next) == POP_TOP);
1486 : 128035 : int oparg = _Py_OPARG(*instr);
1487 [ + + + + : 128035 : if ((PyObject *)descr == list_append && oparg == 1 && pop) {
+ + ]
1488 : 57850 : _Py_SET_OPCODE(*instr, CALL_NO_KW_LIST_APPEND);
1489 : 57850 : return 0;
1490 : : }
1491 : 70185 : _Py_SET_OPCODE(*instr, CALL_NO_KW_METHOD_DESCRIPTOR_O);
1492 : 70185 : return 0;
1493 : : }
1494 : 80226 : case METH_FASTCALL: {
1495 : 80226 : _Py_SET_OPCODE(*instr, CALL_NO_KW_METHOD_DESCRIPTOR_FAST);
1496 : 80226 : return 0;
1497 : : }
1498 : 13404 : case METH_FASTCALL|METH_KEYWORDS: {
1499 : 13404 : _Py_SET_OPCODE(*instr, CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS);
1500 : 13404 : return 0;
1501 : : }
1502 : : }
1503 : : SPECIALIZATION_FAIL(CALL, builtin_call_fail_kind(descr->d_method->ml_flags));
1504 : 339957 : return -1;
1505 : : }
1506 : :
1507 : : static int
1508 : 1135628 : specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
1509 : : PyObject *kwnames, bool bound_method)
1510 : : {
1511 : 1135628 : _PyCallCache *cache = (_PyCallCache *)(instr + 1);
1512 : : assert(_Py_OPCODE(*instr) == CALL_ADAPTIVE);
1513 : 1135628 : PyCodeObject *code = (PyCodeObject *)func->func_code;
1514 : 1135628 : int kind = function_kind(code);
1515 : : /* Don't specialize if PEP 523 is active */
1516 [ + + ]: 1135628 : if (_PyInterpreterState_GET()->eval_frame) {
1517 : : SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
1518 : 2 : return -1;
1519 : : }
1520 [ + + ]: 1135626 : if (kwnames) {
1521 : : SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES);
1522 : 107328 : return -1;
1523 : : }
1524 [ + + ]: 1028298 : if (kind != SIMPLE_FUNCTION) {
1525 : : SPECIALIZATION_FAIL(CALL, kind);
1526 : 327483 : return -1;
1527 : : }
1528 : 700815 : int argcount = code->co_argcount;
1529 [ + + ]: 700815 : int defcount = func->func_defaults == NULL ? 0 : (int)PyTuple_GET_SIZE(func->func_defaults);
1530 : : assert(defcount <= argcount);
1531 : 700815 : int min_args = argcount-defcount;
1532 [ + + + + ]: 700815 : if (nargs > argcount || nargs < min_args) {
1533 : : SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1534 : 26 : return -1;
1535 : : }
1536 : : assert(nargs <= argcount && nargs >= min_args);
1537 : : assert(min_args >= 0 && defcount >= 0);
1538 : : assert(defcount == 0 || func->func_defaults != NULL);
1539 [ - + ]: 700789 : if (min_args > 0xffff) {
1540 : : SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_RANGE);
1541 : 0 : return -1;
1542 : : }
1543 : 700789 : int version = _PyFunction_GetVersionForCurrentState(func);
1544 [ - + ]: 700789 : if (version == 0) {
1545 : : SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
1546 : 0 : return -1;
1547 : : }
1548 : 700789 : write_u32(cache->func_version, version);
1549 : 700789 : cache->min_args = min_args;
1550 [ + + ]: 700789 : if (argcount == nargs) {
1551 [ + + ]: 654757 : _Py_SET_OPCODE(*instr, bound_method ? CALL_BOUND_METHOD_EXACT_ARGS : CALL_PY_EXACT_ARGS);
1552 : : }
1553 [ + + ]: 46032 : else if (bound_method) {
1554 : : SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_BOUND_METHOD);
1555 : 6828 : return -1;
1556 : : }
1557 : : else {
1558 : 39204 : _Py_SET_OPCODE(*instr, CALL_PY_WITH_DEFAULTS);
1559 : : }
1560 : 693961 : return 0;
1561 : : }
1562 : :
1563 : : static int
1564 : 961502 : specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
1565 : : PyObject *kwnames)
1566 : : {
1567 : : assert(_Py_OPCODE(*instr) == CALL_ADAPTIVE);
1568 [ - + ]: 961502 : if (PyCFunction_GET_FUNCTION(callable) == NULL) {
1569 : 0 : return 1;
1570 : : }
1571 [ + + + + ]: 961502 : switch (PyCFunction_GET_FLAGS(callable) &
1572 : : (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
1573 : : METH_KEYWORDS | METH_METHOD)) {
1574 : 258718 : case METH_O: {
1575 [ - + ]: 258718 : if (kwnames) {
1576 : : SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES);
1577 : 0 : return -1;
1578 : : }
1579 [ - + ]: 258718 : if (nargs != 1) {
1580 : : SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
1581 : 0 : return 1;
1582 : : }
1583 : : /* len(o) */
1584 : 258718 : PyInterpreterState *interp = _PyInterpreterState_GET();
1585 [ + + ]: 258718 : if (callable == interp->callable_cache.len) {
1586 : 104138 : _Py_SET_OPCODE(*instr, CALL_NO_KW_LEN);
1587 : 104138 : return 0;
1588 : : }
1589 : 154580 : _Py_SET_OPCODE(*instr, CALL_NO_KW_BUILTIN_O);
1590 : 154580 : return 0;
1591 : : }
1592 : 278051 : case METH_FASTCALL: {
1593 [ + + ]: 278051 : if (kwnames) {
1594 : : SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES);
1595 : 1 : return -1;
1596 : : }
1597 [ + + ]: 278050 : if (nargs == 2) {
1598 : : /* isinstance(o1, o2) */
1599 : 194368 : PyInterpreterState *interp = _PyInterpreterState_GET();
1600 [ + + ]: 194368 : if (callable == interp->callable_cache.isinstance) {
1601 : 81299 : _Py_SET_OPCODE(*instr, CALL_NO_KW_ISINSTANCE);
1602 : 81299 : return 0;
1603 : : }
1604 : : }
1605 : 196751 : _Py_SET_OPCODE(*instr, CALL_NO_KW_BUILTIN_FAST);
1606 : 196751 : return 0;
1607 : : }
1608 : 75834 : case METH_FASTCALL | METH_KEYWORDS: {
1609 : 75834 : _Py_SET_OPCODE(*instr, CALL_BUILTIN_FAST_WITH_KEYWORDS);
1610 : 75834 : return 0;
1611 : : }
1612 : 348899 : default:
1613 : : SPECIALIZATION_FAIL(CALL,
1614 : : builtin_call_fail_kind(PyCFunction_GET_FLAGS(callable)));
1615 : 348899 : return 1;
1616 : : }
1617 : : }
1618 : :
1619 : : #ifdef Py_STATS
1620 : : static int
1621 : : call_fail_kind(PyObject *callable)
1622 : : {
1623 : : if (PyCFunction_CheckExact(callable)) {
1624 : : return SPEC_FAIL_CALL_PYCFUNCTION;
1625 : : }
1626 : : else if (PyFunction_Check(callable)) {
1627 : : return SPEC_FAIL_CALL_PYFUNCTION;
1628 : : }
1629 : : else if (PyInstanceMethod_Check(callable)) {
1630 : : return SPEC_FAIL_CALL_INSTANCE_METHOD;
1631 : : }
1632 : : else if (PyMethod_Check(callable)) {
1633 : : return SPEC_FAIL_CALL_BOUND_METHOD;
1634 : : }
1635 : : // builtin method
1636 : : else if (PyCMethod_Check(callable)) {
1637 : : return SPEC_FAIL_CALL_CMETHOD;
1638 : : }
1639 : : else if (PyType_Check(callable)) {
1640 : : if (((PyTypeObject *)callable)->tp_new == PyBaseObject_Type.tp_new) {
1641 : : return SPEC_FAIL_CALL_PYTHON_CLASS;
1642 : : }
1643 : : else {
1644 : : return SPEC_FAIL_CALL_CLASS;
1645 : : }
1646 : : }
1647 : : else if (Py_IS_TYPE(callable, &PyMethodDescr_Type)) {
1648 : : return SPEC_FAIL_CALL_METHOD_DESCRIPTOR;
1649 : : }
1650 : : else if (Py_TYPE(callable) == &PyWrapperDescr_Type) {
1651 : : return SPEC_FAIL_CALL_OPERATOR_WRAPPER;
1652 : : }
1653 : : else if (Py_TYPE(callable) == &_PyMethodWrapper_Type) {
1654 : : return SPEC_FAIL_CALL_METHOD_WRAPPER;
1655 : : }
1656 : : return SPEC_FAIL_OTHER;
1657 : : }
1658 : : #endif
1659 : :
1660 : :
1661 : : /* TODO:
1662 : : - Specialize calling classes.
1663 : : */
1664 : : int
1665 : 3390618 : _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
1666 : : PyObject *kwnames)
1667 : : {
1668 : : assert(_PyOpcode_Caches[CALL] == INLINE_CACHE_ENTRIES_CALL);
1669 : 3390618 : _PyCallCache *cache = (_PyCallCache *)(instr + 1);
1670 : : int fail;
1671 [ + + ]: 3390618 : if (PyCFunction_CheckExact(callable)) {
1672 : 961502 : fail = specialize_c_call(callable, instr, nargs, kwnames);
1673 : : }
1674 [ + + ]: 2429116 : else if (PyFunction_Check(callable)) {
1675 : 954939 : fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs,
1676 : : kwnames, false);
1677 : : }
1678 [ + + ]: 1474177 : else if (PyType_Check(callable)) {
1679 : 600454 : fail = specialize_class_call(callable, instr, nargs, kwnames);
1680 : : }
1681 [ + + ]: 873723 : else if (Py_IS_TYPE(callable, &PyMethodDescr_Type)) {
1682 : 616905 : fail = specialize_method_descriptor((PyMethodDescrObject *)callable,
1683 : : instr, nargs, kwnames);
1684 : : }
1685 [ + + ]: 256818 : else if (Py_TYPE(callable) == &PyMethod_Type) {
1686 : 180745 : PyObject *func = ((PyMethodObject *)callable)->im_func;
1687 [ + + ]: 180745 : if (PyFunction_Check(func)) {
1688 : 180689 : fail = specialize_py_call((PyFunctionObject *)func,
1689 : : instr, nargs+1, kwnames, true);
1690 : : } else {
1691 : : SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_BOUND_METHOD);
1692 : 56 : fail = -1;
1693 : : }
1694 : : }
1695 : : else {
1696 : : SPECIALIZATION_FAIL(CALL, call_fail_kind(callable));
1697 : 76073 : fail = -1;
1698 : : }
1699 [ + + ]: 3390618 : if (fail) {
1700 : : STAT_INC(CALL, failure);
1701 : : assert(!PyErr_Occurred());
1702 : 1662075 : cache->counter = adaptive_counter_backoff(cache->counter);
1703 : : }
1704 : : else {
1705 : : STAT_INC(CALL, success);
1706 : : assert(!PyErr_Occurred());
1707 : 1728543 : cache->counter = miss_counter_start();
1708 : : }
1709 : 3390618 : return 0;
1710 : : }
1711 : :
1712 : : #ifdef Py_STATS
1713 : : static int
1714 : : binary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs)
1715 : : {
1716 : : switch (oparg) {
1717 : : case NB_ADD:
1718 : : case NB_INPLACE_ADD:
1719 : : if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1720 : : return SPEC_FAIL_BINARY_OP_ADD_DIFFERENT_TYPES;
1721 : : }
1722 : : return SPEC_FAIL_BINARY_OP_ADD_OTHER;
1723 : : case NB_AND:
1724 : : case NB_INPLACE_AND:
1725 : : if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1726 : : return SPEC_FAIL_BINARY_OP_AND_DIFFERENT_TYPES;
1727 : : }
1728 : : if (PyLong_CheckExact(lhs)) {
1729 : : return SPEC_FAIL_BINARY_OP_AND_INT;
1730 : : }
1731 : : return SPEC_FAIL_BINARY_OP_AND_OTHER;
1732 : : case NB_FLOOR_DIVIDE:
1733 : : case NB_INPLACE_FLOOR_DIVIDE:
1734 : : return SPEC_FAIL_BINARY_OP_FLOOR_DIVIDE;
1735 : : case NB_LSHIFT:
1736 : : case NB_INPLACE_LSHIFT:
1737 : : return SPEC_FAIL_BINARY_OP_LSHIFT;
1738 : : case NB_MATRIX_MULTIPLY:
1739 : : case NB_INPLACE_MATRIX_MULTIPLY:
1740 : : return SPEC_FAIL_BINARY_OP_MATRIX_MULTIPLY;
1741 : : case NB_MULTIPLY:
1742 : : case NB_INPLACE_MULTIPLY:
1743 : : if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1744 : : return SPEC_FAIL_BINARY_OP_MULTIPLY_DIFFERENT_TYPES;
1745 : : }
1746 : : return SPEC_FAIL_BINARY_OP_MULTIPLY_OTHER;
1747 : : case NB_OR:
1748 : : case NB_INPLACE_OR:
1749 : : return SPEC_FAIL_BINARY_OP_OR;
1750 : : case NB_POWER:
1751 : : case NB_INPLACE_POWER:
1752 : : return SPEC_FAIL_BINARY_OP_POWER;
1753 : : case NB_REMAINDER:
1754 : : case NB_INPLACE_REMAINDER:
1755 : : return SPEC_FAIL_BINARY_OP_REMAINDER;
1756 : : case NB_RSHIFT:
1757 : : case NB_INPLACE_RSHIFT:
1758 : : return SPEC_FAIL_BINARY_OP_RSHIFT;
1759 : : case NB_SUBTRACT:
1760 : : case NB_INPLACE_SUBTRACT:
1761 : : if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1762 : : return SPEC_FAIL_BINARY_OP_SUBTRACT_DIFFERENT_TYPES;
1763 : : }
1764 : : return SPEC_FAIL_BINARY_OP_SUBTRACT_OTHER;
1765 : : case NB_TRUE_DIVIDE:
1766 : : case NB_INPLACE_TRUE_DIVIDE:
1767 : : if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1768 : : return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_DIFFERENT_TYPES;
1769 : : }
1770 : : if (PyFloat_CheckExact(lhs)) {
1771 : : return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_FLOAT;
1772 : : }
1773 : : return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_OTHER;
1774 : : case NB_XOR:
1775 : : case NB_INPLACE_XOR:
1776 : : return SPEC_FAIL_BINARY_OP_XOR;
1777 : : }
1778 : : Py_UNREACHABLE();
1779 : : }
1780 : : #endif
1781 : :
1782 : : void
1783 : 379943 : _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
1784 : : int oparg, PyObject **locals)
1785 : : {
1786 : : assert(_PyOpcode_Caches[BINARY_OP] == INLINE_CACHE_ENTRIES_BINARY_OP);
1787 : 379943 : _PyBinaryOpCache *cache = (_PyBinaryOpCache *)(instr + 1);
1788 [ + + + + ]: 379943 : switch (oparg) {
1789 : 164463 : case NB_ADD:
1790 : : case NB_INPLACE_ADD:
1791 [ + + ]: 164463 : if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1792 : 8547 : break;
1793 : : }
1794 [ + + ]: 155916 : if (PyUnicode_CheckExact(lhs)) {
1795 : 56454 : _Py_CODEUNIT next = instr[INLINE_CACHE_ENTRIES_BINARY_OP + 1];
1796 [ + + ]: 101251 : bool to_store = (_Py_OPCODE(next) == STORE_FAST ||
1797 [ + + ]: 44797 : _Py_OPCODE(next) == STORE_FAST__LOAD_FAST);
1798 [ + + + + ]: 56454 : if (to_store && locals[_Py_OPARG(next)] == lhs) {
1799 : 12918 : _Py_SET_OPCODE(*instr, BINARY_OP_INPLACE_ADD_UNICODE);
1800 : 12918 : goto success;
1801 : : }
1802 : 43536 : _Py_SET_OPCODE(*instr, BINARY_OP_ADD_UNICODE);
1803 : 43536 : goto success;
1804 : : }
1805 [ + + ]: 99462 : if (PyLong_CheckExact(lhs)) {
1806 : 54274 : _Py_SET_OPCODE(*instr, BINARY_OP_ADD_INT);
1807 : 54274 : goto success;
1808 : : }
1809 [ + + ]: 45188 : if (PyFloat_CheckExact(lhs)) {
1810 : 356 : _Py_SET_OPCODE(*instr, BINARY_OP_ADD_FLOAT);
1811 : 356 : goto success;
1812 : : }
1813 : 44832 : break;
1814 : 34718 : case NB_MULTIPLY:
1815 : : case NB_INPLACE_MULTIPLY:
1816 [ + + ]: 34718 : if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1817 : 24518 : break;
1818 : : }
1819 [ + + ]: 10200 : if (PyLong_CheckExact(lhs)) {
1820 : 9243 : _Py_SET_OPCODE(*instr, BINARY_OP_MULTIPLY_INT);
1821 : 9243 : goto success;
1822 : : }
1823 [ + + ]: 957 : if (PyFloat_CheckExact(lhs)) {
1824 : 924 : _Py_SET_OPCODE(*instr, BINARY_OP_MULTIPLY_FLOAT);
1825 : 924 : goto success;
1826 : : }
1827 : 33 : break;
1828 : 65244 : case NB_SUBTRACT:
1829 : : case NB_INPLACE_SUBTRACT:
1830 [ + + ]: 65244 : if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
1831 : 18057 : break;
1832 : : }
1833 [ + + ]: 47187 : if (PyLong_CheckExact(lhs)) {
1834 : 44485 : _Py_SET_OPCODE(*instr, BINARY_OP_SUBTRACT_INT);
1835 : 44485 : goto success;
1836 : : }
1837 [ + + ]: 2702 : if (PyFloat_CheckExact(lhs)) {
1838 : 367 : _Py_SET_OPCODE(*instr, BINARY_OP_SUBTRACT_FLOAT);
1839 : 367 : goto success;
1840 : : }
1841 : 2335 : break;
1842 : : #ifndef Py_STATS
1843 : 115518 : default:
1844 : : // These operators don't have any available specializations. Rather
1845 : : // than repeatedly attempting to specialize them, just convert them
1846 : : // back to BINARY_OP (unless we're collecting stats, where it's more
1847 : : // important to get accurate hit counts for the unadaptive version
1848 : : // and each of the different failure types):
1849 : 115518 : _Py_SET_OPCODE(*instr, BINARY_OP);
1850 : 115518 : return;
1851 : : #endif
1852 : : }
1853 : : SPECIALIZATION_FAIL(BINARY_OP, binary_op_fail_kind(oparg, lhs, rhs));
1854 : : STAT_INC(BINARY_OP, failure);
1855 : 98322 : cache->counter = adaptive_counter_backoff(cache->counter);
1856 : 98322 : return;
1857 : 166103 : success:
1858 : : STAT_INC(BINARY_OP, success);
1859 : 166103 : cache->counter = miss_counter_start();
1860 : : }
1861 : :
1862 : :
1863 : : #ifdef Py_STATS
1864 : : static int
1865 : : compare_op_fail_kind(PyObject *lhs, PyObject *rhs)
1866 : : {
1867 : : if (Py_TYPE(lhs) != Py_TYPE(rhs)) {
1868 : : if (PyFloat_CheckExact(lhs) && PyLong_CheckExact(rhs)) {
1869 : : return SPEC_FAIL_COMPARE_OP_FLOAT_LONG;
1870 : : }
1871 : : if (PyLong_CheckExact(lhs) && PyFloat_CheckExact(rhs)) {
1872 : : return SPEC_FAIL_COMPARE_OP_LONG_FLOAT;
1873 : : }
1874 : : return SPEC_FAIL_COMPARE_OP_DIFFERENT_TYPES;
1875 : : }
1876 : : if (PyBytes_CheckExact(lhs)) {
1877 : : return SPEC_FAIL_COMPARE_OP_BYTES;
1878 : : }
1879 : : if (PyTuple_CheckExact(lhs)) {
1880 : : return SPEC_FAIL_COMPARE_OP_TUPLE;
1881 : : }
1882 : : if (PyList_CheckExact(lhs)) {
1883 : : return SPEC_FAIL_COMPARE_OP_LIST;
1884 : : }
1885 : : if (PySet_CheckExact(lhs) || PyFrozenSet_CheckExact(lhs)) {
1886 : : return SPEC_FAIL_COMPARE_OP_SET;
1887 : : }
1888 : : if (PyBool_Check(lhs)) {
1889 : : return SPEC_FAIL_COMPARE_OP_BOOL;
1890 : : }
1891 : : if (Py_TYPE(lhs)->tp_richcompare == PyBaseObject_Type.tp_richcompare) {
1892 : : return SPEC_FAIL_COMPARE_OP_BASEOBJECT;
1893 : : }
1894 : : return SPEC_FAIL_OTHER;
1895 : : }
1896 : : #endif
1897 : :
1898 : :
1899 : : static int compare_masks[] = {
1900 : : // 1-bit: jump if less than
1901 : : // 2-bit: jump if equal
1902 : : // 4-bit: jump if greater
1903 : : [Py_LT] = 1 | 0 | 0,
1904 : : [Py_LE] = 1 | 2 | 0,
1905 : : [Py_EQ] = 0 | 2 | 0,
1906 : : [Py_NE] = 1 | 0 | 4,
1907 : : [Py_GT] = 0 | 0 | 4,
1908 : : [Py_GE] = 0 | 2 | 4,
1909 : : };
1910 : :
1911 : : void
1912 : 409664 : _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
1913 : : int oparg)
1914 : : {
1915 : : assert(_PyOpcode_Caches[COMPARE_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP);
1916 : 409664 : _PyCompareOpCache *cache = (_PyCompareOpCache *)(instr + 1);
1917 : 409664 : int next_opcode = _Py_OPCODE(instr[INLINE_CACHE_ENTRIES_COMPARE_OP + 1]);
1918 [ + + + + ]: 409664 : if (next_opcode != POP_JUMP_FORWARD_IF_FALSE &&
1919 [ + + ]: 81161 : next_opcode != POP_JUMP_BACKWARD_IF_FALSE &&
1920 [ + + ]: 46065 : next_opcode != POP_JUMP_FORWARD_IF_TRUE &&
1921 : : next_opcode != POP_JUMP_BACKWARD_IF_TRUE) {
1922 : : // Can't ever combine, so don't don't bother being adaptive (unless
1923 : : // we're collecting stats, where it's more important to get accurate hit
1924 : : // counts for the unadaptive version and each of the different failure
1925 : : // types):
1926 : : #ifndef Py_STATS
1927 : 43343 : _Py_SET_OPCODE(*instr, COMPARE_OP);
1928 : 43343 : return;
1929 : : #else
1930 : : if (next_opcode == EXTENDED_ARG) {
1931 : : SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_EXTENDED_ARG);
1932 : : goto failure;
1933 : : }
1934 : : SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_NOT_FOLLOWED_BY_COND_JUMP);
1935 : : goto failure;
1936 : : #endif
1937 : : }
1938 : : assert(oparg <= Py_GE);
1939 : 366321 : int when_to_jump_mask = compare_masks[oparg];
1940 [ + + + + ]: 366321 : if (next_opcode == POP_JUMP_FORWARD_IF_FALSE ||
1941 : : next_opcode == POP_JUMP_BACKWARD_IF_FALSE) {
1942 : 328503 : when_to_jump_mask = (1 | 2 | 4) & ~when_to_jump_mask;
1943 : : }
1944 [ + + + + ]: 366321 : if (next_opcode == POP_JUMP_BACKWARD_IF_TRUE ||
1945 : : next_opcode == POP_JUMP_BACKWARD_IF_FALSE) {
1946 : 18992 : when_to_jump_mask <<= 3;
1947 : : }
1948 [ + + ]: 366321 : if (Py_TYPE(lhs) != Py_TYPE(rhs)) {
1949 : : SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
1950 : 26110 : goto failure;
1951 : : }
1952 [ + + ]: 340211 : if (PyFloat_CheckExact(lhs)) {
1953 : 3556 : _Py_SET_OPCODE(*instr, COMPARE_OP_FLOAT_JUMP);
1954 : 3556 : cache->mask = when_to_jump_mask;
1955 : 3556 : goto success;
1956 : : }
1957 [ + + ]: 336655 : if (PyLong_CheckExact(lhs)) {
1958 [ + + + + : 177563 : if (Py_ABS(Py_SIZE(lhs)) <= 1 && Py_ABS(Py_SIZE(rhs)) <= 1) {
+ + + + +
+ + + ]
1959 : 115422 : _Py_SET_OPCODE(*instr, COMPARE_OP_INT_JUMP);
1960 : 115422 : cache->mask = when_to_jump_mask;
1961 : 115422 : goto success;
1962 : : }
1963 : : else {
1964 : : SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_BIG_INT);
1965 : 62141 : goto failure;
1966 : : }
1967 : : }
1968 [ + + ]: 159092 : if (PyUnicode_CheckExact(lhs)) {
1969 [ + + + + ]: 101031 : if (oparg != Py_EQ && oparg != Py_NE) {
1970 : : SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_STRING);
1971 : 333 : goto failure;
1972 : : }
1973 : : else {
1974 : 100698 : _Py_SET_OPCODE(*instr, COMPARE_OP_STR_JUMP);
1975 : 100698 : cache->mask = when_to_jump_mask;
1976 : 100698 : goto success;
1977 : : }
1978 : : }
1979 : : SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
1980 : 58061 : failure:
1981 : : STAT_INC(COMPARE_OP, failure);
1982 : 146645 : cache->counter = adaptive_counter_backoff(cache->counter);
1983 : 146645 : return;
1984 : 219676 : success:
1985 : : STAT_INC(COMPARE_OP, success);
1986 : 219676 : cache->counter = miss_counter_start();
1987 : : }
1988 : :
1989 : : #ifdef Py_STATS
1990 : : static int
1991 : : unpack_sequence_fail_kind(PyObject *seq)
1992 : : {
1993 : : if (PySequence_Check(seq)) {
1994 : : return SPEC_FAIL_UNPACK_SEQUENCE_SEQUENCE;
1995 : : }
1996 : : if (PyIter_Check(seq)) {
1997 : : return SPEC_FAIL_UNPACK_SEQUENCE_ITERATOR;
1998 : : }
1999 : : return SPEC_FAIL_OTHER;
2000 : : }
2001 : : #endif
2002 : :
2003 : : void
2004 : 113891 : _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr, int oparg)
2005 : : {
2006 : : assert(_PyOpcode_Caches[UNPACK_SEQUENCE] ==
2007 : : INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE);
2008 : 113891 : _PyUnpackSequenceCache *cache = (_PyUnpackSequenceCache *)(instr + 1);
2009 [ + + ]: 113891 : if (PyTuple_CheckExact(seq)) {
2010 [ + + ]: 111567 : if (PyTuple_GET_SIZE(seq) != oparg) {
2011 : : SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_EXPECTED_ERROR);
2012 : 2 : goto failure;
2013 : : }
2014 [ + + ]: 111565 : if (PyTuple_GET_SIZE(seq) == 2) {
2015 : 87793 : _Py_SET_OPCODE(*instr, UNPACK_SEQUENCE_TWO_TUPLE);
2016 : 87793 : goto success;
2017 : : }
2018 : 23772 : _Py_SET_OPCODE(*instr, UNPACK_SEQUENCE_TUPLE);
2019 : 23772 : goto success;
2020 : : }
2021 [ + + ]: 2324 : if (PyList_CheckExact(seq)) {
2022 [ + + ]: 485 : if (PyList_GET_SIZE(seq) != oparg) {
2023 : : SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_EXPECTED_ERROR);
2024 : 14 : goto failure;
2025 : : }
2026 : 471 : _Py_SET_OPCODE(*instr, UNPACK_SEQUENCE_LIST);
2027 : 471 : goto success;
2028 : : }
2029 : : SPECIALIZATION_FAIL(UNPACK_SEQUENCE, unpack_sequence_fail_kind(seq));
2030 : 1839 : failure:
2031 : : STAT_INC(UNPACK_SEQUENCE, failure);
2032 : 1855 : cache->counter = adaptive_counter_backoff(cache->counter);
2033 : 1855 : return;
2034 : 112036 : success:
2035 : : STAT_INC(UNPACK_SEQUENCE, success);
2036 : 112036 : cache->counter = miss_counter_start();
2037 : : }
2038 : :
2039 : : #ifdef Py_STATS
2040 : :
2041 : : int
2042 : : _PySpecialization_ClassifyIterator(PyObject *iter)
2043 : : {
2044 : : if (PyGen_CheckExact(iter)) {
2045 : : return SPEC_FAIL_FOR_ITER_GENERATOR;
2046 : : }
2047 : : if (PyCoro_CheckExact(iter)) {
2048 : : return SPEC_FAIL_FOR_ITER_COROUTINE;
2049 : : }
2050 : : if (PyAsyncGen_CheckExact(iter)) {
2051 : : return SPEC_FAIL_FOR_ITER_ASYNC_GENERATOR;
2052 : : }
2053 : : PyTypeObject *t = Py_TYPE(iter);
2054 : : if (t == &PyListIter_Type) {
2055 : : return SPEC_FAIL_FOR_ITER_LIST;
2056 : : }
2057 : : if (t == &PyTupleIter_Type) {
2058 : : return SPEC_FAIL_FOR_ITER_TUPLE;
2059 : : }
2060 : : if (t == &PyDictIterKey_Type) {
2061 : : return SPEC_FAIL_FOR_ITER_DICT_KEYS;
2062 : : }
2063 : : if (t == &PyDictIterValue_Type) {
2064 : : return SPEC_FAIL_FOR_ITER_DICT_VALUES;
2065 : : }
2066 : : if (t == &PyDictIterItem_Type) {
2067 : : return SPEC_FAIL_FOR_ITER_DICT_ITEMS;
2068 : : }
2069 : : if (t == &PySetIter_Type) {
2070 : : return SPEC_FAIL_FOR_ITER_SET;
2071 : : }
2072 : : if (t == &PyUnicodeIter_Type) {
2073 : : return SPEC_FAIL_FOR_ITER_STRING;
2074 : : }
2075 : : if (t == &PyBytesIter_Type) {
2076 : : return SPEC_FAIL_FOR_ITER_BYTES;
2077 : : }
2078 : : if (t == &PyRangeIter_Type) {
2079 : : return SPEC_FAIL_FOR_ITER_RANGE;
2080 : : }
2081 : : if (t == &PyEnum_Type) {
2082 : : return SPEC_FAIL_FOR_ITER_ENUMERATE;
2083 : : }
2084 : : if (t == &PyMap_Type) {
2085 : : return SPEC_FAIL_FOR_ITER_MAP;
2086 : : }
2087 : : if (t == &PyZip_Type) {
2088 : : return SPEC_FAIL_FOR_ITER_ZIP;
2089 : : }
2090 : : if (t == &PySeqIter_Type) {
2091 : : return SPEC_FAIL_FOR_ITER_SEQ_ITER;
2092 : : }
2093 : : if (t == &PyListRevIter_Type) {
2094 : : return SPEC_FAIL_FOR_ITER_REVERSED_LIST;
2095 : : }
2096 : : if (t == &_PyUnicodeASCIIIter_Type) {
2097 : : return SPEC_FAIL_FOR_ITER_ASCII_STRING;
2098 : : }
2099 : : const char *name = t->tp_name;
2100 : : if (strncmp(name, "itertools", 9) == 0) {
2101 : : return SPEC_FAIL_FOR_ITER_ITERTOOLS;
2102 : : }
2103 : : if (strncmp(name, "callable_iterator", 17) == 0) {
2104 : : return SPEC_FAIL_FOR_ITER_CALLABLE;
2105 : : }
2106 : : return SPEC_FAIL_OTHER;
2107 : : }
2108 : :
2109 : : #endif
2110 : :
2111 : : void
2112 : 797526 : _Py_Specialize_ForIter(PyObject *iter, _Py_CODEUNIT *instr)
2113 : : {
2114 : : assert(_PyOpcode_Caches[FOR_ITER] == INLINE_CACHE_ENTRIES_FOR_ITER);
2115 : 797526 : _PyForIterCache *cache = (_PyForIterCache *)(instr + 1);
2116 : 797526 : PyTypeObject *tp = Py_TYPE(iter);
2117 : 797526 : _Py_CODEUNIT next = instr[1+INLINE_CACHE_ENTRIES_FOR_ITER];
2118 : 797526 : int next_op = _PyOpcode_Deopt[_Py_OPCODE(next)];
2119 [ + + ]: 797526 : if (tp == &PyListIter_Type) {
2120 : 96357 : _Py_SET_OPCODE(*instr, FOR_ITER_LIST);
2121 : 96357 : goto success;
2122 : : }
2123 [ + + + + ]: 701169 : else if (tp == &PyRangeIter_Type && next_op == STORE_FAST) {
2124 : 15689 : _Py_SET_OPCODE(*instr, FOR_ITER_RANGE);
2125 : 15689 : goto success;
2126 : : }
2127 : : else {
2128 : : SPECIALIZATION_FAIL(FOR_ITER,
2129 : : _PySpecialization_ClassifyIterator(iter));
2130 : 685480 : goto failure;
2131 : : }
2132 : 685480 : failure:
2133 : : STAT_INC(FOR_ITER, failure);
2134 : 685480 : cache->counter = adaptive_counter_backoff(cache->counter);
2135 : 685480 : return;
2136 : 112046 : success:
2137 : : STAT_INC(FOR_ITER, success);
2138 : 112046 : cache->counter = miss_counter_start();
2139 : : }
|