LCOV - code coverage report
Current view: | top level - Python - specialize.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 629 | 725 | 86.8 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 24 | 24 | 100.0 %
|  |  | Branches: | 343 | 438 | 78.3 %

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

Generated by: LCOV version 1.14