LCOV - code coverage report
Current view: top level - Python - specialize.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 651 689 94.5 %
Date: 2022-07-20 13:12:14 Functions: 22 22 100.0 %
Branches: 367 412 89.1 %

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

Generated by: LCOV version 1.14