LCOV - code coverage report
Current view: top level - Objects - dictobject.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 2285 2609 87.6 %
Date: 2022-07-07 18:19:46 Functions: 162 165 98.2 %

          Line data    Source code
       1             : /* Dictionary object implementation using a hash table */
       2             : 
       3             : /* The distribution includes a separate file, Objects/dictnotes.txt,
       4             :    describing explorations into dictionary design and optimization.
       5             :    It covers typical dictionary use patterns, the parameters for
       6             :    tuning dictionaries, and several ideas for possible optimizations.
       7             : */
       8             : 
       9             : /* PyDictKeysObject
      10             : 
      11             : This implements the dictionary's hashtable.
      12             : 
      13             : As of Python 3.6, this is compact and ordered. Basic idea is described here:
      14             : * https://mail.python.org/pipermail/python-dev/2012-December/123028.html
      15             : * https://morepypy.blogspot.com/2015/01/faster-more-memory-efficient-and-more.html
      16             : 
      17             : layout:
      18             : 
      19             : +---------------------+
      20             : | dk_refcnt           |
      21             : | dk_log2_size        |
      22             : | dk_log2_index_bytes |
      23             : | dk_kind             |
      24             : | dk_usable           |
      25             : | dk_nentries         |
      26             : +---------------------+
      27             : | dk_indices[]        |
      28             : |                     |
      29             : +---------------------+
      30             : | dk_entries[]        |
      31             : |                     |
      32             : +---------------------+
      33             : 
      34             : dk_indices is actual hashtable.  It holds index in entries, or DKIX_EMPTY(-1)
      35             : or DKIX_DUMMY(-2).
      36             : Size of indices is dk_size.  Type of each index in indices is vary on dk_size:
      37             : 
      38             : * int8  for          dk_size <= 128
      39             : * int16 for 256   <= dk_size <= 2**15
      40             : * int32 for 2**16 <= dk_size <= 2**31
      41             : * int64 for 2**32 <= dk_size
      42             : 
      43             : dk_entries is array of PyDictKeyEntry when dk_kind == DICT_KEYS_GENERAL or
      44             : PyDictUnicodeEntry otherwise. Its length is USABLE_FRACTION(dk_size).
      45             : 
      46             : NOTE: Since negative value is used for DKIX_EMPTY and DKIX_DUMMY, type of
      47             : dk_indices entry is signed integer and int16 is used for table which
      48             : dk_size == 256.
      49             : */
      50             : 
      51             : 
      52             : /*
      53             : The DictObject can be in one of two forms.
      54             : 
      55             : Either:
      56             :   A combined table:
      57             :     ma_values == NULL, dk_refcnt == 1.
      58             :     Values are stored in the me_value field of the PyDictKeysObject.
      59             : Or:
      60             :   A split table:
      61             :     ma_values != NULL, dk_refcnt >= 1
      62             :     Values are stored in the ma_values array.
      63             :     Only string (unicode) keys are allowed.
      64             : 
      65             : There are four kinds of slots in the table (slot is index, and
      66             : DK_ENTRIES(keys)[index] if index >= 0):
      67             : 
      68             : 1. Unused.  index == DKIX_EMPTY
      69             :    Does not hold an active (key, value) pair now and never did.  Unused can
      70             :    transition to Active upon key insertion.  This is each slot's initial state.
      71             : 
      72             : 2. Active.  index >= 0, me_key != NULL and me_value != NULL
      73             :    Holds an active (key, value) pair.  Active can transition to Dummy or
      74             :    Pending upon key deletion (for combined and split tables respectively).
      75             :    This is the only case in which me_value != NULL.
      76             : 
      77             : 3. Dummy.  index == DKIX_DUMMY  (combined only)
      78             :    Previously held an active (key, value) pair, but that was deleted and an
      79             :    active pair has not yet overwritten the slot.  Dummy can transition to
      80             :    Active upon key insertion.  Dummy slots cannot be made Unused again
      81             :    else the probe sequence in case of collision would have no way to know
      82             :    they were once active.
      83             : 
      84             : 4. Pending. index >= 0, key != NULL, and value == NULL  (split only)
      85             :    Not yet inserted in split-table.
      86             : */
      87             : 
      88             : /*
      89             : Preserving insertion order
      90             : 
      91             : It's simple for combined table.  Since dk_entries is mostly append only, we can
      92             : get insertion order by just iterating dk_entries.
      93             : 
      94             : One exception is .popitem().  It removes last item in dk_entries and decrement
      95             : dk_nentries to achieve amortized O(1).  Since there are DKIX_DUMMY remains in
      96             : dk_indices, we can't increment dk_usable even though dk_nentries is
      97             : decremented.
      98             : 
      99             : To preserve the order in a split table, a bit vector is used  to record the
     100             : insertion order. When a key is inserted the bit vector is shifted up by 4 bits
     101             : and the index of the key is stored in the low 4 bits.
     102             : As a consequence of this, split keys have a maximum size of 16.
     103             : */
     104             : 
     105             : /* PyDict_MINSIZE is the starting size for any new dict.
     106             :  * 8 allows dicts with no more than 5 active entries; experiments suggested
     107             :  * this suffices for the majority of dicts (consisting mostly of usually-small
     108             :  * dicts created to pass keyword arguments).
     109             :  * Making this 8, rather than 4 reduces the number of resizes for most
     110             :  * dictionaries, without any significant extra memory use.
     111             :  */
     112             : #define PyDict_LOG_MINSIZE 3
     113             : #define PyDict_MINSIZE 8
     114             : 
     115             : #include "Python.h"
     116             : #include "pycore_bitutils.h"      // _Py_bit_length
     117             : #include "pycore_call.h"          // _PyObject_CallNoArgs()
     118             : #include "pycore_code.h"          // stats
     119             : #include "pycore_dict.h"          // PyDictKeysObject
     120             : #include "pycore_gc.h"            // _PyObject_GC_IS_TRACKED()
     121             : #include "pycore_object.h"        // _PyObject_GC_TRACK()
     122             : #include "pycore_pyerrors.h"      // _PyErr_Fetch()
     123             : #include "pycore_pystate.h"       // _PyThreadState_GET()
     124             : #include "stringlib/eq.h"         // unicode_eq()
     125             : 
     126             : #include <stdbool.h>
     127             : 
     128             : /*[clinic input]
     129             : class dict "PyDictObject *" "&PyDict_Type"
     130             : [clinic start generated code]*/
     131             : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=f157a5a0ce9589d6]*/
     132             : 
     133             : 
     134             : /*
     135             : To ensure the lookup algorithm terminates, there must be at least one Unused
     136             : slot (NULL key) in the table.
     137             : To avoid slowing down lookups on a near-full table, we resize the table when
     138             : it's USABLE_FRACTION (currently two-thirds) full.
     139             : */
     140             : 
     141             : #define PERTURB_SHIFT 5
     142             : 
     143             : /*
     144             : Major subtleties ahead:  Most hash schemes depend on having a "good" hash
     145             : function, in the sense of simulating randomness.  Python doesn't:  its most
     146             : important hash functions (for ints) are very regular in common
     147             : cases:
     148             : 
     149             :   >>>[hash(i) for i in range(4)]
     150             :   [0, 1, 2, 3]
     151             : 
     152             : This isn't necessarily bad!  To the contrary, in a table of size 2**i, taking
     153             : the low-order i bits as the initial table index is extremely fast, and there
     154             : are no collisions at all for dicts indexed by a contiguous range of ints. So
     155             : this gives better-than-random behavior in common cases, and that's very
     156             : desirable.
     157             : 
     158             : OTOH, when collisions occur, the tendency to fill contiguous slices of the
     159             : hash table makes a good collision resolution strategy crucial.  Taking only
     160             : the last i bits of the hash code is also vulnerable:  for example, consider
     161             : the list [i << 16 for i in range(20000)] as a set of keys.  Since ints are
     162             : their own hash codes, and this fits in a dict of size 2**15, the last 15 bits
     163             :  of every hash code are all 0:  they *all* map to the same table index.
     164             : 
     165             : But catering to unusual cases should not slow the usual ones, so we just take
     166             : the last i bits anyway.  It's up to collision resolution to do the rest.  If
     167             : we *usually* find the key we're looking for on the first try (and, it turns
     168             : out, we usually do -- the table load factor is kept under 2/3, so the odds
     169             : are solidly in our favor), then it makes best sense to keep the initial index
     170             : computation dirt cheap.
     171             : 
     172             : The first half of collision resolution is to visit table indices via this
     173             : recurrence:
     174             : 
     175             :     j = ((5*j) + 1) mod 2**i
     176             : 
     177             : For any initial j in range(2**i), repeating that 2**i times generates each
     178             : int in range(2**i) exactly once (see any text on random-number generation for
     179             : proof).  By itself, this doesn't help much:  like linear probing (setting
     180             : j += 1, or j -= 1, on each loop trip), it scans the table entries in a fixed
     181             : order.  This would be bad, except that's not the only thing we do, and it's
     182             : actually *good* in the common cases where hash keys are consecutive.  In an
     183             : example that's really too small to make this entirely clear, for a table of
     184             : size 2**3 the order of indices is:
     185             : 
     186             :     0 -> 1 -> 6 -> 7 -> 4 -> 5 -> 2 -> 3 -> 0 [and here it's repeating]
     187             : 
     188             : If two things come in at index 5, the first place we look after is index 2,
     189             : not 6, so if another comes in at index 6 the collision at 5 didn't hurt it.
     190             : Linear probing is deadly in this case because there the fixed probe order
     191             : is the *same* as the order consecutive keys are likely to arrive.  But it's
     192             : extremely unlikely hash codes will follow a 5*j+1 recurrence by accident,
     193             : and certain that consecutive hash codes do not.
     194             : 
     195             : The other half of the strategy is to get the other bits of the hash code
     196             : into play.  This is done by initializing a (unsigned) vrbl "perturb" to the
     197             : full hash code, and changing the recurrence to:
     198             : 
     199             :     perturb >>= PERTURB_SHIFT;
     200             :     j = (5*j) + 1 + perturb;
     201             :     use j % 2**i as the next table index;
     202             : 
     203             : Now the probe sequence depends (eventually) on every bit in the hash code,
     204             : and the pseudo-scrambling property of recurring on 5*j+1 is more valuable,
     205             : because it quickly magnifies small differences in the bits that didn't affect
     206             : the initial index.  Note that because perturb is unsigned, if the recurrence
     207             : is executed often enough perturb eventually becomes and remains 0.  At that
     208             : point (very rarely reached) the recurrence is on (just) 5*j+1 again, and
     209             : that's certain to find an empty slot eventually (since it generates every int
     210             : in range(2**i), and we make sure there's always at least one empty slot).
     211             : 
     212             : Selecting a good value for PERTURB_SHIFT is a balancing act.  You want it
     213             : small so that the high bits of the hash code continue to affect the probe
     214             : sequence across iterations; but you want it large so that in really bad cases
     215             : the high-order hash bits have an effect on early iterations.  5 was "the
     216             : best" in minimizing total collisions across experiments Tim Peters ran (on
     217             : both normal and pathological cases), but 4 and 6 weren't significantly worse.
     218             : 
     219             : Historical: Reimer Behrends contributed the idea of using a polynomial-based
     220             : approach, using repeated multiplication by x in GF(2**n) where an irreducible
     221             : polynomial for each table size was chosen such that x was a primitive root.
     222             : Christian Tismer later extended that to use division by x instead, as an
     223             : efficient way to get the high bits of the hash code into play.  This scheme
     224             : also gave excellent collision statistics, but was more expensive:  two
     225             : if-tests were required inside the loop; computing "the next" index took about
     226             : the same number of operations but without as much potential parallelism
     227             : (e.g., computing 5*j can go on at the same time as computing 1+perturb in the
     228             : above, and then shifting perturb can be done while the table index is being
     229             : masked); and the PyDictObject struct required a member to hold the table's
     230             : polynomial.  In Tim's experiments the current scheme ran faster, produced
     231             : equally good collision statistics, needed less code & used less memory.
     232             : 
     233             : */
     234             : 
     235             : static int dictresize(PyDictObject *mp, uint8_t log_newsize, int unicode);
     236             : 
     237             : static PyObject* dict_iter(PyDictObject *dict);
     238             : 
     239             : /*Global counter used to set ma_version_tag field of dictionary.
     240             :  * It is incremented each time that a dictionary is created and each
     241             :  * time that a dictionary is modified. */
     242             : uint64_t _pydict_global_version = 0;
     243             : 
     244             : #include "clinic/dictobject.c.h"
     245             : 
     246             : 
     247             : #if PyDict_MAXFREELIST > 0
     248             : static struct _Py_dict_state *
     249   159510000 : get_dict_state(void)
     250             : {
     251   159510000 :     PyInterpreterState *interp = _PyInterpreterState_GET();
     252   159510000 :     return &interp->dict_state;
     253             : }
     254             : #endif
     255             : 
     256             : 
     257             : void
     258       30840 : _PyDict_ClearFreeList(PyInterpreterState *interp)
     259             : {
     260             : #if PyDict_MAXFREELIST > 0
     261       30840 :     struct _Py_dict_state *state = &interp->dict_state;
     262     1083500 :     while (state->numfree) {
     263     1052660 :         PyDictObject *op = state->free_list[--state->numfree];
     264     1052660 :         assert(PyDict_CheckExact(op));
     265     1052660 :         PyObject_GC_Del(op);
     266             :     }
     267      958320 :     while (state->keys_numfree) {
     268      927480 :         PyObject_Free(state->keys_free_list[--state->keys_numfree]);
     269             :     }
     270             : #endif
     271       30840 : }
     272             : 
     273             : 
     274             : void
     275        3120 : _PyDict_Fini(PyInterpreterState *interp)
     276             : {
     277        3120 :     _PyDict_ClearFreeList(interp);
     278             : #if defined(Py_DEBUG) && PyDict_MAXFREELIST > 0
     279        3120 :     struct _Py_dict_state *state = &interp->dict_state;
     280        3120 :     state->numfree = -1;
     281        3120 :     state->keys_numfree = -1;
     282             : #endif
     283        3120 : }
     284             : 
     285             : static inline Py_hash_t
     286  2498040000 : unicode_get_hash(PyObject *o)
     287             : {
     288  2498040000 :     assert(PyUnicode_CheckExact(o));
     289  2498040000 :     return _PyASCIIObject_CAST(o)->hash;
     290             : }
     291             : 
     292             : /* Print summary info about the state of the optimized allocator */
     293             : void
     294           1 : _PyDict_DebugMallocStats(FILE *out)
     295             : {
     296             : #if PyDict_MAXFREELIST > 0
     297           1 :     struct _Py_dict_state *state = get_dict_state();
     298           1 :     _PyDebugAllocatorStats(out, "free PyDictObject",
     299             :                            state->numfree, sizeof(PyDictObject));
     300             : #endif
     301           1 : }
     302             : 
     303             : #define DK_MASK(dk) (DK_SIZE(dk)-1)
     304             : 
     305             : static void free_keys_object(PyDictKeysObject *keys);
     306             : 
     307             : static inline void
     308    46190500 : dictkeys_incref(PyDictKeysObject *dk)
     309             : {
     310             : #ifdef Py_REF_DEBUG
     311    46190500 :     _Py_RefTotal++;
     312             : #endif
     313    46190500 :     dk->dk_refcnt++;
     314    46190500 : }
     315             : 
     316             : static inline void
     317    69946400 : dictkeys_decref(PyDictKeysObject *dk)
     318             : {
     319    69946400 :     assert(dk->dk_refcnt > 0);
     320             : #ifdef Py_REF_DEBUG
     321    69946400 :     _Py_RefTotal--;
     322             : #endif
     323    69946400 :     if (--dk->dk_refcnt == 0) {
     324    23822900 :         free_keys_object(dk);
     325             :     }
     326    69946400 : }
     327             : 
     328             : /* lookup indices.  returns DKIX_EMPTY, DKIX_DUMMY, or ix >=0 */
     329             : static inline Py_ssize_t
     330  3268330000 : dictkeys_get_index(const PyDictKeysObject *keys, Py_ssize_t i)
     331             : {
     332  3268330000 :     int log2size = DK_LOG_SIZE(keys);
     333             :     Py_ssize_t ix;
     334             : 
     335  3268330000 :     if (log2size < 8) {
     336  2459020000 :         const int8_t *indices = (const int8_t*)(keys->dk_indices);
     337  2459020000 :         ix = indices[i];
     338             :     }
     339   809313000 :     else if (log2size < 16) {
     340   783542000 :         const int16_t *indices = (const int16_t*)(keys->dk_indices);
     341   783542000 :         ix = indices[i];
     342             :     }
     343             : #if SIZEOF_VOID_P > 4
     344    25771500 :     else if (log2size >= 32) {
     345           0 :         const int64_t *indices = (const int64_t*)(keys->dk_indices);
     346           0 :         ix = indices[i];
     347             :     }
     348             : #endif
     349             :     else {
     350    25771500 :         const int32_t *indices = (const int32_t*)(keys->dk_indices);
     351    25771500 :         ix = indices[i];
     352             :     }
     353  3268330000 :     assert(ix >= DKIX_DUMMY);
     354  3268330000 :     return ix;
     355             : }
     356             : 
     357             : /* write to indices. */
     358             : static inline void
     359   320232000 : dictkeys_set_index(PyDictKeysObject *keys, Py_ssize_t i, Py_ssize_t ix)
     360             : {
     361   320232000 :     int log2size = DK_LOG_SIZE(keys);
     362             : 
     363   320232000 :     assert(ix >= DKIX_DUMMY);
     364   320232000 :     assert(keys->dk_version == 0);
     365             : 
     366   320232000 :     if (log2size < 8) {
     367   194945000 :         int8_t *indices = (int8_t*)(keys->dk_indices);
     368   194945000 :         assert(ix <= 0x7f);
     369   194945000 :         indices[i] = (char)ix;
     370             :     }
     371   125287000 :     else if (log2size < 16) {
     372   121721000 :         int16_t *indices = (int16_t*)(keys->dk_indices);
     373   121721000 :         assert(ix <= 0x7fff);
     374   121721000 :         indices[i] = (int16_t)ix;
     375             :     }
     376             : #if SIZEOF_VOID_P > 4
     377     3566260 :     else if (log2size >= 32) {
     378           0 :         int64_t *indices = (int64_t*)(keys->dk_indices);
     379           0 :         indices[i] = ix;
     380             :     }
     381             : #endif
     382             :     else {
     383     3566260 :         int32_t *indices = (int32_t*)(keys->dk_indices);
     384     3566260 :         assert(ix <= 0x7fffffff);
     385     3566260 :         indices[i] = (int32_t)ix;
     386             :     }
     387   320232000 : }
     388             : 
     389             : 
     390             : /* USABLE_FRACTION is the maximum dictionary load.
     391             :  * Increasing this ratio makes dictionaries more dense resulting in more
     392             :  * collisions.  Decreasing it improves sparseness at the expense of spreading
     393             :  * indices over more cache lines and at the cost of total memory consumed.
     394             :  *
     395             :  * USABLE_FRACTION must obey the following:
     396             :  *     (0 < USABLE_FRACTION(n) < n) for all n >= 2
     397             :  *
     398             :  * USABLE_FRACTION should be quick to calculate.
     399             :  * Fractions around 1/2 to 2/3 seem to work well in practice.
     400             :  */
     401             : #define USABLE_FRACTION(n) (((n) << 1)/3)
     402             : 
     403             : /* Find the smallest dk_size >= minsize. */
     404             : static inline uint8_t
     405    10745300 : calculate_log2_keysize(Py_ssize_t minsize)
     406             : {
     407             : #if SIZEOF_LONG == SIZEOF_SIZE_T
     408    10745300 :     minsize = (minsize | PyDict_MINSIZE) - 1;
     409    10745300 :     return _Py_bit_length(minsize | (PyDict_MINSIZE-1));
     410             : #elif defined(_MSC_VER)
     411             :     // On 64bit Windows, sizeof(long) == 4.
     412             :     minsize = (minsize | PyDict_MINSIZE) - 1;
     413             :     unsigned long msb;
     414             :     _BitScanReverse64(&msb, (uint64_t)minsize);
     415             :     return (uint8_t)(msb + 1);
     416             : #else
     417             :     uint8_t log2_size;
     418             :     for (log2_size = PyDict_LOG_MINSIZE;
     419             :             (((Py_ssize_t)1) << log2_size) < minsize;
     420             :             log2_size++)
     421             :         ;
     422             :     return log2_size;
     423             : #endif
     424             : }
     425             : 
     426             : /* estimate_keysize is reverse function of USABLE_FRACTION.
     427             :  *
     428             :  * This can be used to reserve enough size to insert n entries without
     429             :  * resizing.
     430             :  */
     431             : static inline uint8_t
     432      241825 : estimate_log2_keysize(Py_ssize_t n)
     433             : {
     434      241825 :     return calculate_log2_keysize((n*3 + 1) / 2);
     435             : }
     436             : 
     437             : 
     438             : /* GROWTH_RATE. Growth rate upon hitting maximum load.
     439             :  * Currently set to used*3.
     440             :  * This means that dicts double in size when growing without deletions,
     441             :  * but have more head room when the number of deletions is on a par with the
     442             :  * number of insertions.  See also bpo-17563 and bpo-33205.
     443             :  *
     444             :  * GROWTH_RATE was set to used*4 up to version 3.2.
     445             :  * GROWTH_RATE was set to used*2 in version 3.3.0
     446             :  * GROWTH_RATE was set to used*2 + capacity/2 in 3.4.0-3.6.0.
     447             :  */
     448             : #define GROWTH_RATE(d) ((d)->ma_used*3)
     449             : 
     450             : /* This immutable, empty PyDictKeysObject is used for PyDict_Clear()
     451             :  * (which cannot fail and thus can do no allocation).
     452             :  */
     453             : static PyDictKeysObject empty_keys_struct = {
     454             :         1, /* dk_refcnt */
     455             :         0, /* dk_log2_size */
     456             :         0, /* dk_log2_index_bytes */
     457             :         DICT_KEYS_UNICODE, /* dk_kind */
     458             :         1, /* dk_version */
     459             :         0, /* dk_usable (immutable) */
     460             :         0, /* dk_nentries */
     461             :         {DKIX_EMPTY, DKIX_EMPTY, DKIX_EMPTY, DKIX_EMPTY,
     462             :          DKIX_EMPTY, DKIX_EMPTY, DKIX_EMPTY, DKIX_EMPTY}, /* dk_indices */
     463             : };
     464             : 
     465             : #define Py_EMPTY_KEYS &empty_keys_struct
     466             : 
     467             : /* Uncomment to check the dict content in _PyDict_CheckConsistency() */
     468             : // #define DEBUG_PYDICT
     469             : 
     470             : #ifdef DEBUG_PYDICT
     471             : #  define ASSERT_CONSISTENT(op) assert(_PyDict_CheckConsistency((PyObject *)(op), 1))
     472             : #else
     473             : #  define ASSERT_CONSISTENT(op) assert(_PyDict_CheckConsistency((PyObject *)(op), 0))
     474             : #endif
     475             : 
     476             : static inline int
     477      888681 : get_index_from_order(PyDictObject *mp, Py_ssize_t i)
     478             : {
     479      888681 :     assert(mp->ma_used <= SHARED_KEYS_MAX_SIZE);
     480      888681 :     assert(i < (((char *)mp->ma_values)[-2]));
     481      888681 :     return ((char *)mp->ma_values)[-3-i];
     482             : }
     483             : 
     484             : #ifdef DEBUG_PYDICT
     485             : static void
     486             : dump_entries(PyDictKeysObject *dk)
     487             : {
     488             :     for (Py_ssize_t i = 0; i < dk->dk_nentries; i++) {
     489             :         if (DK_IS_UNICODE(dk)) {
     490             :             PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(dk)[i];
     491             :             printf("key=%p value=%p\n", ep->me_key, ep->me_value);
     492             :         }
     493             :         else {
     494             :             PyDictKeyEntry *ep = &DK_ENTRIES(dk)[i];
     495             :             printf("key=%p hash=%lx value=%p\n", ep->me_key, ep->me_hash, ep->me_value);
     496             :         }
     497             :     }
     498             : }
     499             : #endif
     500             : 
     501             : int
     502   401568000 : _PyDict_CheckConsistency(PyObject *op, int check_content)
     503             : {
     504             : #define CHECK(expr) \
     505             :     do { if (!(expr)) { _PyObject_ASSERT_FAILED_MSG(op, Py_STRINGIFY(expr)); } } while (0)
     506             : 
     507   401568000 :     assert(op != NULL);
     508   401568000 :     CHECK(PyDict_Check(op));
     509   401568000 :     PyDictObject *mp = (PyDictObject *)op;
     510             : 
     511   401568000 :     PyDictKeysObject *keys = mp->ma_keys;
     512   401568000 :     int splitted = _PyDict_HasSplitTable(mp);
     513   401568000 :     Py_ssize_t usable = USABLE_FRACTION(DK_SIZE(keys));
     514             : 
     515   401568000 :     CHECK(0 <= mp->ma_used && mp->ma_used <= usable);
     516   401568000 :     CHECK(0 <= keys->dk_usable && keys->dk_usable <= usable);
     517   401568000 :     CHECK(0 <= keys->dk_nentries && keys->dk_nentries <= usable);
     518   401568000 :     CHECK(keys->dk_usable + keys->dk_nentries <= usable);
     519             : 
     520   401568000 :     if (!splitted) {
     521             :         /* combined table */
     522   386571000 :         CHECK(keys->dk_kind != DICT_KEYS_SPLIT);
     523   386571000 :         CHECK(keys->dk_refcnt == 1 || keys == Py_EMPTY_KEYS);
     524             :     }
     525             :     else {
     526    14996700 :         CHECK(keys->dk_kind == DICT_KEYS_SPLIT);
     527    14996700 :         CHECK(mp->ma_used <= SHARED_KEYS_MAX_SIZE);
     528             :     }
     529             : 
     530   401568000 :     if (check_content) {
     531           0 :         for (Py_ssize_t i=0; i < DK_SIZE(keys); i++) {
     532           0 :             Py_ssize_t ix = dictkeys_get_index(keys, i);
     533           0 :             CHECK(DKIX_DUMMY <= ix && ix <= usable);
     534             :         }
     535             : 
     536           0 :         if (keys->dk_kind == DICT_KEYS_GENERAL) {
     537           0 :             PyDictKeyEntry *entries = DK_ENTRIES(keys);
     538           0 :             for (Py_ssize_t i=0; i < usable; i++) {
     539           0 :                 PyDictKeyEntry *entry = &entries[i];
     540           0 :                 PyObject *key = entry->me_key;
     541             : 
     542           0 :                 if (key != NULL) {
     543             :                     /* test_dict fails if PyObject_Hash() is called again */
     544           0 :                     CHECK(entry->me_hash != -1);
     545           0 :                     CHECK(entry->me_value != NULL);
     546             : 
     547           0 :                     if (PyUnicode_CheckExact(key)) {
     548           0 :                         Py_hash_t hash = unicode_get_hash(key);
     549           0 :                         CHECK(entry->me_hash == hash);
     550             :                     }
     551             :                 }
     552             :             }
     553             :         }
     554             :         else {
     555           0 :             PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys);
     556           0 :             for (Py_ssize_t i=0; i < usable; i++) {
     557           0 :                 PyDictUnicodeEntry *entry = &entries[i];
     558           0 :                 PyObject *key = entry->me_key;
     559             : 
     560           0 :                 if (key != NULL) {
     561           0 :                     CHECK(PyUnicode_CheckExact(key));
     562           0 :                     Py_hash_t hash = unicode_get_hash(key);
     563           0 :                     CHECK(hash != -1);
     564           0 :                     if (!splitted) {
     565           0 :                         CHECK(entry->me_value != NULL);
     566             :                     }
     567             :                 }
     568             : 
     569           0 :                 if (splitted) {
     570           0 :                     CHECK(entry->me_value == NULL);
     571             :                 }
     572             :             }
     573             :         }
     574             : 
     575           0 :         if (splitted) {
     576           0 :             CHECK(mp->ma_used <= SHARED_KEYS_MAX_SIZE);
     577             :             /* splitted table */
     578           0 :             int duplicate_check = 0;
     579           0 :             for (Py_ssize_t i=0; i < mp->ma_used; i++) {
     580           0 :                 int index = get_index_from_order(mp, i);
     581           0 :                 CHECK((duplicate_check & (1<<index)) == 0);
     582           0 :                 duplicate_check |= (1<<index);
     583           0 :                 CHECK(mp->ma_values->values[index] != NULL);
     584             :             }
     585             :         }
     586             :     }
     587   401568000 :     return 1;
     588             : 
     589             : #undef CHECK
     590             : }
     591             : 
     592             : 
     593             : static PyDictKeysObject*
     594    31095800 : new_keys_object(uint8_t log2_size, bool unicode)
     595             : {
     596             :     PyDictKeysObject *dk;
     597             :     Py_ssize_t usable;
     598             :     int log2_bytes;
     599    31095800 :     size_t entry_size = unicode ? sizeof(PyDictUnicodeEntry) : sizeof(PyDictKeyEntry);
     600             : 
     601    31095800 :     assert(log2_size >= PyDict_LOG_MINSIZE);
     602             : 
     603    31095800 :     usable = USABLE_FRACTION(1<<log2_size);
     604    31095800 :     if (log2_size < 8) {
     605    30922800 :         log2_bytes = log2_size;
     606             :     }
     607      172932 :     else if (log2_size < 16) {
     608      172872 :         log2_bytes = log2_size + 1;
     609             :     }
     610             : #if SIZEOF_VOID_P > 4
     611          60 :     else if (log2_size >= 32) {
     612           0 :         log2_bytes = log2_size + 3;
     613             :     }
     614             : #endif
     615             :     else {
     616          60 :         log2_bytes = log2_size + 2;
     617             :     }
     618             : 
     619             : #if PyDict_MAXFREELIST > 0
     620    31095800 :     struct _Py_dict_state *state = get_dict_state();
     621             : #ifdef Py_DEBUG
     622             :     // new_keys_object() must not be called after _PyDict_Fini()
     623    31095800 :     assert(state->keys_numfree != -1);
     624             : #endif
     625    31095800 :     if (log2_size == PyDict_LOG_MINSIZE && unicode && state->keys_numfree > 0) {
     626    15776600 :         dk = state->keys_free_list[--state->keys_numfree];
     627    15776600 :         OBJECT_STAT_INC(from_freelist);
     628             :     }
     629             :     else
     630             : #endif
     631             :     {
     632    15319200 :         dk = PyObject_Malloc(sizeof(PyDictKeysObject)
     633    15319200 :                              + ((size_t)1 << log2_bytes)
     634    15319200 :                              + entry_size * usable);
     635    15319200 :         if (dk == NULL) {
     636           0 :             PyErr_NoMemory();
     637           0 :             return NULL;
     638             :         }
     639             :     }
     640             : #ifdef Py_REF_DEBUG
     641    31095800 :     _Py_RefTotal++;
     642             : #endif
     643    31095800 :     dk->dk_refcnt = 1;
     644    31095800 :     dk->dk_log2_size = log2_size;
     645    31095800 :     dk->dk_log2_index_bytes = log2_bytes;
     646    31095800 :     dk->dk_kind = unicode ? DICT_KEYS_UNICODE : DICT_KEYS_GENERAL;
     647    31095800 :     dk->dk_nentries = 0;
     648    31095800 :     dk->dk_usable = usable;
     649    31095800 :     dk->dk_version = 0;
     650    31095800 :     memset(&dk->dk_indices[0], 0xff, ((size_t)1 << log2_bytes));
     651    31095800 :     memset(&dk->dk_indices[(size_t)1 << log2_bytes], 0, entry_size * usable);
     652    31095800 :     return dk;
     653             : }
     654             : 
     655             : static void
     656    23822900 : free_keys_object(PyDictKeysObject *keys)
     657             : {
     658    23822900 :     assert(keys != Py_EMPTY_KEYS);
     659    23822900 :     if (DK_IS_UNICODE(keys)) {
     660    21528600 :         PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys);
     661             :         Py_ssize_t i, n;
     662   183597000 :         for (i = 0, n = keys->dk_nentries; i < n; i++) {
     663   162069000 :             Py_XDECREF(entries[i].me_key);
     664   162069000 :             Py_XDECREF(entries[i].me_value);
     665             :         }
     666             :     }
     667             :     else {
     668     2294310 :         PyDictKeyEntry *entries = DK_ENTRIES(keys);
     669             :         Py_ssize_t i, n;
     670    20866400 :         for (i = 0, n = keys->dk_nentries; i < n; i++) {
     671    18572100 :             Py_XDECREF(entries[i].me_key);
     672    18572100 :             Py_XDECREF(entries[i].me_value);
     673             :         }
     674             :     }
     675             : #if PyDict_MAXFREELIST > 0
     676    23822900 :     struct _Py_dict_state *state = get_dict_state();
     677             : #ifdef Py_DEBUG
     678             :     // free_keys_object() must not be called after _PyDict_Fini()
     679    23822900 :     assert(state->keys_numfree != -1);
     680             : #endif
     681    23822900 :     if (DK_LOG_SIZE(keys) == PyDict_LOG_MINSIZE
     682    13905000 :             && state->keys_numfree < PyDict_MAXFREELIST
     683    10912300 :             && DK_IS_UNICODE(keys)) {
     684     9654400 :         state->keys_free_list[state->keys_numfree++] = keys;
     685             :         OBJECT_STAT_INC(to_freelist);
     686     9654400 :         return;
     687             :     }
     688             : #endif
     689    14168500 :     PyObject_Free(keys);
     690             : }
     691             : 
     692             : static inline PyDictValues*
     693    13062000 : new_values(Py_ssize_t size)
     694             : {
     695    13062000 :     assert(size > 0);
     696    13062000 :     size_t prefix_size = _Py_SIZE_ROUND_UP(size+2, sizeof(PyObject *));
     697    13062000 :     assert(prefix_size < 256);
     698    13062000 :     size_t n = prefix_size + size * sizeof(PyObject *);
     699    13062000 :     uint8_t *mem = PyMem_Malloc(n);
     700    13062000 :     if (mem == NULL) {
     701           0 :         return NULL;
     702             :     }
     703    13062000 :     assert(prefix_size % sizeof(PyObject *) == 0);
     704    13062000 :     mem[prefix_size-1] = (uint8_t)prefix_size;
     705    13062000 :     return (PyDictValues*)(mem + prefix_size);
     706             : }
     707             : 
     708             : static inline void
     709    13056100 : free_values(PyDictValues *values)
     710             : {
     711    13056100 :     int prefix_size = ((uint8_t *)values)[-1];
     712    13056100 :     PyMem_Free(((char *)values)-prefix_size);
     713    13056100 : }
     714             : 
     715             : /* Consumes a reference to the keys object */
     716             : static PyObject *
     717    46984600 : new_dict(PyDictKeysObject *keys, PyDictValues *values, Py_ssize_t used, int free_values_on_failure)
     718             : {
     719             :     PyDictObject *mp;
     720    46984600 :     assert(keys != NULL);
     721             : #if PyDict_MAXFREELIST > 0
     722    46984600 :     struct _Py_dict_state *state = get_dict_state();
     723             : #ifdef Py_DEBUG
     724             :     // new_dict() must not be called after _PyDict_Fini()
     725    46984600 :     assert(state->numfree != -1);
     726             : #endif
     727    46984600 :     if (state->numfree) {
     728    32260600 :         mp = state->free_list[--state->numfree];
     729    32260600 :         assert (mp != NULL);
     730    32260600 :         assert (Py_IS_TYPE(mp, &PyDict_Type));
     731             :         OBJECT_STAT_INC(from_freelist);
     732    32260600 :         _Py_NewReference((PyObject *)mp);
     733             :     }
     734             :     else
     735             : #endif
     736             :     {
     737    14724000 :         mp = PyObject_GC_New(PyDictObject, &PyDict_Type);
     738    14724000 :         if (mp == NULL) {
     739           0 :             dictkeys_decref(keys);
     740           0 :             if (free_values_on_failure) {
     741           0 :                 free_values(values);
     742             :             }
     743           0 :             return NULL;
     744             :         }
     745             :     }
     746    46984600 :     mp->ma_keys = keys;
     747    46984600 :     mp->ma_values = values;
     748    46984600 :     mp->ma_used = used;
     749    46984600 :     mp->ma_version_tag = DICT_NEXT_VERSION();
     750    46984600 :     ASSERT_CONSISTENT(mp);
     751    46984600 :     return (PyObject *)mp;
     752             : }
     753             : 
     754             : static inline Py_ssize_t
     755    15100800 : shared_keys_usable_size(PyDictKeysObject *keys)
     756             : {
     757    15100800 :     return keys->dk_nentries + keys->dk_usable;
     758             : }
     759             : 
     760             : /* Consumes a reference to the keys object */
     761             : static PyObject *
     762     4338660 : new_dict_with_shared_keys(PyDictKeysObject *keys)
     763             : {
     764             :     PyDictValues *values;
     765             :     Py_ssize_t i, size;
     766             : 
     767     4338660 :     size = shared_keys_usable_size(keys);
     768     4338660 :     values = new_values(size);
     769     4338660 :     if (values == NULL) {
     770           0 :         dictkeys_decref(keys);
     771           0 :         return PyErr_NoMemory();
     772             :     }
     773     4338660 :     ((char *)values)[-2] = 0;
     774   134498000 :     for (i = 0; i < size; i++) {
     775   130160000 :         values->values[i] = NULL;
     776             :     }
     777     4338660 :     return new_dict(keys, values, 0, 1);
     778             : }
     779             : 
     780             : 
     781             : static PyDictKeysObject *
     782     3327170 : clone_combined_dict_keys(PyDictObject *orig)
     783             : {
     784     3327170 :     assert(PyDict_Check(orig));
     785     3327170 :     assert(Py_TYPE(orig)->tp_iter == (getiterfunc)dict_iter);
     786     3327170 :     assert(orig->ma_values == NULL);
     787     3327170 :     assert(orig->ma_keys->dk_refcnt == 1);
     788             : 
     789     3327170 :     Py_ssize_t keys_size = _PyDict_KeysSize(orig->ma_keys);
     790     3327170 :     PyDictKeysObject *keys = PyObject_Malloc(keys_size);
     791     3327170 :     if (keys == NULL) {
     792           4 :         PyErr_NoMemory();
     793           4 :         return NULL;
     794             :     }
     795             : 
     796     3327170 :     memcpy(keys, orig->ma_keys, keys_size);
     797             : 
     798             :     /* After copying key/value pairs, we need to incref all
     799             :        keys and values and they are about to be co-owned by a
     800             :        new dict object. */
     801             :     PyObject **pkey, **pvalue;
     802             :     size_t offs;
     803     3327170 :     if (DK_IS_UNICODE(orig->ma_keys)) {
     804     3285660 :         PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(keys);
     805     3285660 :         pkey = &ep0->me_key;
     806     3285660 :         pvalue = &ep0->me_value;
     807     3285660 :         offs = sizeof(PyDictUnicodeEntry) / sizeof(PyObject*);
     808             :     }
     809             :     else {
     810       41507 :         PyDictKeyEntry *ep0 = DK_ENTRIES(keys);
     811       41507 :         pkey = &ep0->me_key;
     812       41507 :         pvalue = &ep0->me_value;
     813       41507 :         offs = sizeof(PyDictKeyEntry) / sizeof(PyObject*);
     814             :     }
     815             : 
     816     3327170 :     Py_ssize_t n = keys->dk_nentries;
     817    35393800 :     for (Py_ssize_t i = 0; i < n; i++) {
     818    32066600 :         PyObject *value = *pvalue;
     819    32066600 :         if (value != NULL) {
     820    31173300 :             Py_INCREF(value);
     821    31173300 :             Py_INCREF(*pkey);
     822             :         }
     823    32066600 :         pvalue += offs;
     824    32066600 :         pkey += offs;
     825             :     }
     826             : 
     827             :     /* Since we copied the keys table we now have an extra reference
     828             :        in the system.  Manually call increment _Py_RefTotal to signal that
     829             :        we have it now; calling dictkeys_incref would be an error as
     830             :        keys->dk_refcnt is already set to 1 (after memcpy). */
     831             : #ifdef Py_REF_DEBUG
     832     3327170 :     _Py_RefTotal++;
     833             : #endif
     834     3327170 :     return keys;
     835             : }
     836             : 
     837             : PyObject *
     838    39665500 : PyDict_New(void)
     839             : {
     840    39665500 :     dictkeys_incref(Py_EMPTY_KEYS);
     841    39665500 :     return new_dict(Py_EMPTY_KEYS, NULL, 0, 0);
     842             : }
     843             : 
     844             : /* Search index of hash table from offset of entry table */
     845             : static Py_ssize_t
     846    26415500 : lookdict_index(PyDictKeysObject *k, Py_hash_t hash, Py_ssize_t index)
     847             : {
     848    26415500 :     size_t mask = DK_MASK(k);
     849    26415500 :     size_t perturb = (size_t)hash;
     850    26415500 :     size_t i = (size_t)hash & mask;
     851             : 
     852    11873400 :     for (;;) {
     853    38288900 :         Py_ssize_t ix = dictkeys_get_index(k, i);
     854    38288900 :         if (ix == index) {
     855    26415500 :             return i;
     856             :         }
     857    11873400 :         if (ix == DKIX_EMPTY) {
     858           0 :             return DKIX_EMPTY;
     859             :         }
     860    11873400 :         perturb >>= PERTURB_SHIFT;
     861    11873400 :         i = mask & (i*5 + perturb + 1);
     862             :     }
     863             :     Py_UNREACHABLE();
     864             : }
     865             : 
     866             : // Search non-Unicode key from Unicode table
     867             : static Py_ssize_t
     868     1365160 : unicodekeys_lookup_generic(PyDictObject *mp, PyDictKeysObject* dk, PyObject *key, Py_hash_t hash)
     869             : {
     870     1365160 :     PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(dk);
     871     1365160 :     size_t mask = DK_MASK(dk);
     872     1365160 :     size_t perturb = hash;
     873     1365160 :     size_t i = (size_t)hash & mask;
     874             :     Py_ssize_t ix;
     875             :     for (;;) {
     876     1408200 :         ix = dictkeys_get_index(dk, i);
     877     1408200 :         if (ix >= 0) {
     878       43021 :             PyDictUnicodeEntry *ep = &ep0[ix];
     879       43021 :             assert(ep->me_key != NULL);
     880       43021 :             assert(PyUnicode_CheckExact(ep->me_key));
     881       43021 :             if (ep->me_key == key) {
     882           0 :                 return ix;
     883             :             }
     884       43021 :             if (unicode_get_hash(ep->me_key) == hash) {
     885         341 :                 PyObject *startkey = ep->me_key;
     886         341 :                 Py_INCREF(startkey);
     887         341 :                 int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
     888         341 :                 Py_DECREF(startkey);
     889         341 :                 if (cmp < 0) {
     890           0 :                     return DKIX_ERROR;
     891             :                 }
     892         341 :                 if (dk == mp->ma_keys && ep->me_key == startkey) {
     893         341 :                     if (cmp > 0) {
     894          13 :                         return ix;
     895             :                     }
     896             :                 }
     897             :                 else {
     898             :                     /* The dict was mutated, restart */
     899           0 :                     return DKIX_KEY_CHANGED;
     900             :                 }
     901             :             }
     902             :         }
     903     1365180 :         else if (ix == DKIX_EMPTY) {
     904     1365150 :             return DKIX_EMPTY;
     905             :         }
     906       43040 :         perturb >>= PERTURB_SHIFT;
     907       43040 :         i = mask & (i*5 + perturb + 1);
     908             :     }
     909             :     Py_UNREACHABLE();
     910             : }
     911             : 
     912             : // Search Unicode key from Unicode table.
     913             : static Py_ssize_t _Py_HOT_FUNCTION
     914  1663050000 : unicodekeys_lookup_unicode(PyDictKeysObject* dk, PyObject *key, Py_hash_t hash)
     915             : {
     916  1663050000 :     PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(dk);
     917  1663050000 :     size_t mask = DK_MASK(dk);
     918  1663050000 :     size_t perturb = hash;
     919  1663050000 :     size_t i = (size_t)hash & mask;
     920             :     Py_ssize_t ix;
     921             :     for (;;) {
     922  1995460000 :         ix = dictkeys_get_index(dk, i);
     923  1995460000 :         if (ix >= 0) {
     924  1111850000 :             PyDictUnicodeEntry *ep = &ep0[ix];
     925  1111850000 :             assert(ep->me_key != NULL);
     926  1111850000 :             assert(PyUnicode_CheckExact(ep->me_key));
     927  1913000000 :             if (ep->me_key == key ||
     928   893655000 :                     (unicode_get_hash(ep->me_key) == hash && unicode_eq(ep->me_key, key))) {
     929   403205000 :                 return ix;
     930             :             }
     931             :         }
     932   883613000 :         else if (ix == DKIX_EMPTY) {
     933   865470000 :             return DKIX_EMPTY;
     934             :         }
     935   726790000 :         perturb >>= PERTURB_SHIFT;
     936   726790000 :         i = mask & (i*5 + perturb + 1);
     937   726790000 :         ix = dictkeys_get_index(dk, i);
     938   726790000 :         if (ix >= 0) {
     939   375793000 :             PyDictUnicodeEntry *ep = &ep0[ix];
     940   375793000 :             assert(ep->me_key != NULL);
     941   375793000 :             assert(PyUnicode_CheckExact(ep->me_key));
     942   711854000 :             if (ep->me_key == key ||
     943   348148000 :                     (unicode_get_hash(ep->me_key) == hash && unicode_eq(ep->me_key, key))) {
     944    51820100 :                 return ix;
     945             :             }
     946             :         }
     947   350996000 :         else if (ix == DKIX_EMPTY) {
     948   342559000 :             return DKIX_EMPTY;
     949             :         }
     950   332411000 :         perturb >>= PERTURB_SHIFT;
     951   332411000 :         i = mask & (i*5 + perturb + 1);
     952             :     }
     953             :     Py_UNREACHABLE();
     954             : }
     955             : 
     956             : // Search key from Generic table.
     957             : static Py_ssize_t
     958    58973800 : dictkeys_generic_lookup(PyDictObject *mp, PyDictKeysObject* dk, PyObject *key, Py_hash_t hash)
     959             : {
     960    58973800 :     PyDictKeyEntry *ep0 = DK_ENTRIES(dk);
     961    58973800 :     size_t mask = DK_MASK(dk);
     962    58973800 :     size_t perturb = hash;
     963    58973800 :     size_t i = (size_t)hash & mask;
     964             :     Py_ssize_t ix;
     965             :     for (;;) {
     966   102418000 :         ix = dictkeys_get_index(dk, i);
     967   102418000 :         if (ix >= 0) {
     968    70640000 :             PyDictKeyEntry *ep = &ep0[ix];
     969    70640000 :             assert(ep->me_key != NULL);
     970    70640000 :             if (ep->me_key == key) {
     971    19200200 :                 return ix;
     972             :             }
     973    51439800 :             if (ep->me_hash == hash) {
     974    10326500 :                 PyObject *startkey = ep->me_key;
     975    10326500 :                 Py_INCREF(startkey);
     976    10326500 :                 int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
     977    10326500 :                 Py_DECREF(startkey);
     978    10326500 :                 if (cmp < 0) {
     979          14 :                     return DKIX_ERROR;
     980             :                 }
     981    10326500 :                 if (dk == mp->ma_keys && ep->me_key == startkey) {
     982    10326500 :                     if (cmp > 0) {
     983     9881820 :                         return ix;
     984             :                     }
     985             :                 }
     986             :                 else {
     987             :                     /* The dict was mutated, restart */
     988          42 :                     return DKIX_KEY_CHANGED;
     989             :                 }
     990             :             }
     991             :         }
     992    31778300 :         else if (ix == DKIX_EMPTY) {
     993    29891800 :             return DKIX_EMPTY;
     994             :         }
     995    43444500 :         perturb >>= PERTURB_SHIFT;
     996    43444500 :         i = mask & (i*5 + perturb + 1);
     997             :     }
     998             :     Py_UNREACHABLE();
     999             : }
    1000             : 
    1001             : /* Lookup a string in a (all unicode) dict keys.
    1002             :  * Returns DKIX_ERROR if key is not a string,
    1003             :  * or if the dict keys is not all strings.
    1004             :  * If the keys is present then return the index of key.
    1005             :  * If the key is not present then return DKIX_EMPTY.
    1006             :  */
    1007             : Py_ssize_t
    1008    66782900 : _PyDictKeys_StringLookup(PyDictKeysObject* dk, PyObject *key)
    1009             : {
    1010    66782900 :     DictKeysKind kind = dk->dk_kind;
    1011    66782900 :     if (!PyUnicode_CheckExact(key) || kind == DICT_KEYS_GENERAL) {
    1012           0 :         return DKIX_ERROR;
    1013             :     }
    1014    66782900 :     Py_hash_t hash = unicode_get_hash(key);
    1015    66782900 :     if (hash == -1) {
    1016           0 :         hash = PyUnicode_Type.tp_hash(key);
    1017           0 :         if (hash == -1) {
    1018           0 :             PyErr_Clear();
    1019           0 :             return DKIX_ERROR;
    1020             :         }
    1021             :     }
    1022    66782900 :     return unicodekeys_lookup_unicode(dk, key, hash);
    1023             : }
    1024             : 
    1025             : /*
    1026             : The basic lookup function used by all operations.
    1027             : This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4.
    1028             : Open addressing is preferred over chaining since the link overhead for
    1029             : chaining would be substantial (100% with typical malloc overhead).
    1030             : 
    1031             : The initial probe index is computed as hash mod the table size. Subsequent
    1032             : probe indices are computed as explained earlier.
    1033             : 
    1034             : All arithmetic on hash should ignore overflow.
    1035             : 
    1036             : _Py_dict_lookup() is general-purpose, and may return DKIX_ERROR if (and only if) a
    1037             : comparison raises an exception.
    1038             : When the key isn't found a DKIX_EMPTY is returned.
    1039             : */
    1040             : Py_ssize_t
    1041  1648910000 : _Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr)
    1042             : {
    1043             :     PyDictKeysObject *dk;
    1044             :     DictKeysKind kind;
    1045             :     Py_ssize_t ix;
    1046             : 
    1047  1648910000 : start:
    1048  1648910000 :     dk = mp->ma_keys;
    1049  1648910000 :     kind = dk->dk_kind;
    1050             : 
    1051  1648910000 :     if (kind != DICT_KEYS_GENERAL) {
    1052  1589940000 :         if (PyUnicode_CheckExact(key)) {
    1053  1588570000 :             ix = unicodekeys_lookup_unicode(dk, key, hash);
    1054             :         }
    1055             :         else {
    1056     1365160 :             ix = unicodekeys_lookup_generic(mp, dk, key, hash);
    1057     1365160 :             if (ix == DKIX_KEY_CHANGED) {
    1058           0 :                 goto start;
    1059             :             }
    1060             :         }
    1061             : 
    1062  1589940000 :         if (ix >= 0) {
    1063   423541000 :             if (kind == DICT_KEYS_SPLIT) {
    1064    12511400 :                 *value_addr = mp->ma_values->values[ix];
    1065             :             }
    1066             :             else {
    1067   411030000 :                 *value_addr = DK_UNICODE_ENTRIES(dk)[ix].me_value;
    1068             :             }
    1069             :         }
    1070             :         else {
    1071  1166390000 :             *value_addr = NULL;
    1072             :         }
    1073             :     }
    1074             :     else {
    1075    58973800 :         ix = dictkeys_generic_lookup(mp, dk, key, hash);
    1076    58973800 :         if (ix == DKIX_KEY_CHANGED) {
    1077          42 :             goto start;
    1078             :         }
    1079    58973800 :         if (ix >= 0) {
    1080    29082000 :             *value_addr = DK_ENTRIES(dk)[ix].me_value;
    1081             :         }
    1082             :         else {
    1083    29891800 :             *value_addr = NULL;
    1084             :         }
    1085             :     }
    1086             : 
    1087  1648910000 :     return ix;
    1088             : }
    1089             : 
    1090             : int
    1091       13577 : _PyDict_HasOnlyStringKeys(PyObject *dict)
    1092             : {
    1093       13577 :     Py_ssize_t pos = 0;
    1094             :     PyObject *key, *value;
    1095       13577 :     assert(PyDict_Check(dict));
    1096             :     /* Shortcut */
    1097       13577 :     if (((PyDictObject *)dict)->ma_keys->dk_kind != DICT_KEYS_GENERAL)
    1098       13574 :         return 1;
    1099           3 :     while (PyDict_Next(dict, &pos, &key, &value))
    1100           3 :         if (!PyUnicode_Check(key))
    1101           3 :             return 0;
    1102           0 :     return 1;
    1103             : }
    1104             : 
    1105             : #define MAINTAIN_TRACKING(mp, key, value) \
    1106             :     do { \
    1107             :         if (!_PyObject_GC_IS_TRACKED(mp)) { \
    1108             :             if (_PyObject_GC_MAY_BE_TRACKED(key) || \
    1109             :                 _PyObject_GC_MAY_BE_TRACKED(value)) { \
    1110             :                 _PyObject_GC_TRACK(mp); \
    1111             :             } \
    1112             :         } \
    1113             :     } while(0)
    1114             : 
    1115             : void
    1116    38168200 : _PyDict_MaybeUntrack(PyObject *op)
    1117             : {
    1118             :     PyDictObject *mp;
    1119             :     PyObject *value;
    1120             :     Py_ssize_t i, numentries;
    1121             : 
    1122    38168200 :     if (!PyDict_CheckExact(op) || !_PyObject_GC_IS_TRACKED(op))
    1123           0 :         return;
    1124             : 
    1125    38168200 :     mp = (PyDictObject *) op;
    1126    38168200 :     numentries = mp->ma_keys->dk_nentries;
    1127    38168200 :     if (_PyDict_HasSplitTable(mp)) {
    1128      934820 :         for (i = 0; i < numentries; i++) {
    1129      933670 :             if ((value = mp->ma_values->values[i]) == NULL)
    1130         648 :                 continue;
    1131      933022 :             if (_PyObject_GC_MAY_BE_TRACKED(value)) {
    1132      302449 :                 return;
    1133             :             }
    1134             :         }
    1135             :     }
    1136             :     else {
    1137    37864600 :         if (DK_IS_UNICODE(mp->ma_keys)) {
    1138    32496900 :             PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(mp->ma_keys);
    1139    93911300 :             for (i = 0; i < numentries; i++) {
    1140    93763700 :                 if ((value = ep0[i].me_value) == NULL)
    1141     7135160 :                     continue;
    1142    86628500 :                 if (_PyObject_GC_MAY_BE_TRACKED(value))
    1143    32349200 :                     return;
    1144             :             }
    1145             :         }
    1146             :         else {
    1147     5367740 :             PyDictKeyEntry *ep0 = DK_ENTRIES(mp->ma_keys);
    1148     6494660 :             for (i = 0; i < numentries; i++) {
    1149     6481220 :                 if ((value = ep0[i].me_value) == NULL)
    1150      236436 :                     continue;
    1151     7295560 :                 if (_PyObject_GC_MAY_BE_TRACKED(value) ||
    1152     1050780 :                     _PyObject_GC_MAY_BE_TRACKED(ep0[i].me_key))
    1153     5354300 :                     return;
    1154             :             }
    1155             :         }
    1156             :     }
    1157      162255 :     _PyObject_GC_UNTRACK(op);
    1158             : }
    1159             : 
    1160             : /* Internal function to find slot for an item from its hash
    1161             :    when it is known that the key is not present in the dict.
    1162             : 
    1163             :    The dict must be combined. */
    1164             : static Py_ssize_t
    1165   134416000 : find_empty_slot(PyDictKeysObject *keys, Py_hash_t hash)
    1166             : {
    1167   134416000 :     assert(keys != NULL);
    1168             : 
    1169   134416000 :     const size_t mask = DK_MASK(keys);
    1170   134416000 :     size_t i = hash & mask;
    1171   134416000 :     Py_ssize_t ix = dictkeys_get_index(keys, i);
    1172   233790000 :     for (size_t perturb = hash; ix >= 0;) {
    1173    99373600 :         perturb >>= PERTURB_SHIFT;
    1174    99373600 :         i = (i*5 + perturb + 1) & mask;
    1175    99373600 :         ix = dictkeys_get_index(keys, i);
    1176             :     }
    1177   134416000 :     return i;
    1178             : }
    1179             : 
    1180             : static int
    1181    10503400 : insertion_resize(PyDictObject *mp, int unicode)
    1182             : {
    1183    10503400 :     return dictresize(mp, calculate_log2_keysize(GROWTH_RATE(mp)), unicode);
    1184             : }
    1185             : 
    1186             : static Py_ssize_t
    1187     7700960 : insert_into_dictkeys(PyDictKeysObject *keys, PyObject *name)
    1188             : {
    1189     7700960 :     assert(PyUnicode_CheckExact(name));
    1190     7700960 :     Py_hash_t hash = unicode_get_hash(name);
    1191     7700960 :     if (hash == -1) {
    1192           0 :         hash = PyUnicode_Type.tp_hash(name);
    1193           0 :         if (hash == -1) {
    1194           0 :             PyErr_Clear();
    1195           0 :             return DKIX_EMPTY;
    1196             :         }
    1197             :     }
    1198     7700960 :     Py_ssize_t ix = unicodekeys_lookup_unicode(keys, name, hash);
    1199     7700960 :     if (ix == DKIX_EMPTY) {
    1200      722919 :         if (keys->dk_usable <= 0) {
    1201      111104 :             return DKIX_EMPTY;
    1202             :         }
    1203      611815 :         Py_INCREF(name);
    1204             :         /* Insert into new slot. */
    1205      611815 :         keys->dk_version = 0;
    1206      611815 :         Py_ssize_t hashpos = find_empty_slot(keys, hash);
    1207      611815 :         ix = keys->dk_nentries;
    1208      611815 :         PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(keys)[ix];
    1209      611815 :         dictkeys_set_index(keys, hashpos, ix);
    1210      611815 :         assert(ep->me_key == NULL);
    1211      611815 :         ep->me_key = name;
    1212      611815 :         keys->dk_usable--;
    1213      611815 :         keys->dk_nentries++;
    1214             :     }
    1215     7589860 :     assert (ix < SHARED_KEYS_MAX_SIZE);
    1216     7589860 :     return ix;
    1217             : }
    1218             : 
    1219             : /*
    1220             : Internal routine to insert a new item into the table.
    1221             : Used both by the internal resize routine and by the public insert routine.
    1222             : Returns -1 if an error occurred, or 0 on success.
    1223             : Consumes key and value references.
    1224             : */
    1225             : static int
    1226   141099000 : insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
    1227             : {
    1228             :     PyObject *old_value;
    1229             : 
    1230   141099000 :     if (DK_IS_UNICODE(mp->ma_keys) && !PyUnicode_CheckExact(key)) {
    1231      105208 :         if (insertion_resize(mp, 0) < 0)
    1232           0 :             goto Fail;
    1233      105208 :         assert(mp->ma_keys->dk_kind == DICT_KEYS_GENERAL);
    1234             :     }
    1235             : 
    1236   141099000 :     Py_ssize_t ix = _Py_dict_lookup(mp, key, hash, &old_value);
    1237   141099000 :     if (ix == DKIX_ERROR)
    1238           3 :         goto Fail;
    1239             : 
    1240   141099000 :     MAINTAIN_TRACKING(mp, key, value);
    1241             : 
    1242   141099000 :     if (ix == DKIX_EMPTY) {
    1243             :         /* Insert into new slot. */
    1244    99409600 :         mp->ma_keys->dk_version = 0;
    1245    99409600 :         assert(old_value == NULL);
    1246    99409600 :         if (mp->ma_keys->dk_usable <= 0) {
    1247             :             /* Need to resize. */
    1248     9516690 :             if (insertion_resize(mp, 1) < 0)
    1249           0 :                 goto Fail;
    1250             :         }
    1251             : 
    1252    99409600 :         Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash);
    1253    99409600 :         dictkeys_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
    1254             : 
    1255    99409600 :         if (DK_IS_UNICODE(mp->ma_keys)) {
    1256             :             PyDictUnicodeEntry *ep;
    1257    86579000 :             ep = &DK_UNICODE_ENTRIES(mp->ma_keys)[mp->ma_keys->dk_nentries];
    1258    86579000 :             ep->me_key = key;
    1259    86579000 :             if (mp->ma_values) {
    1260      305380 :                 Py_ssize_t index = mp->ma_keys->dk_nentries;
    1261      305380 :                 _PyDictValues_AddToInsertionOrder(mp->ma_values, index);
    1262      305380 :                 assert (mp->ma_values->values[index] == NULL);
    1263      305380 :                 mp->ma_values->values[index] = value;
    1264             :             }
    1265             :             else {
    1266    86273700 :                 ep->me_value = value;
    1267             :             }
    1268             :         }
    1269             :         else {
    1270             :             PyDictKeyEntry *ep;
    1271    12830500 :             ep = &DK_ENTRIES(mp->ma_keys)[mp->ma_keys->dk_nentries];
    1272    12830500 :             ep->me_key = key;
    1273    12830500 :             ep->me_hash = hash;
    1274    12830500 :             ep->me_value = value;
    1275             :         }
    1276    99409600 :         mp->ma_used++;
    1277    99409600 :         mp->ma_version_tag = DICT_NEXT_VERSION();
    1278    99409600 :         mp->ma_keys->dk_usable--;
    1279    99409600 :         mp->ma_keys->dk_nentries++;
    1280    99409600 :         assert(mp->ma_keys->dk_usable >= 0);
    1281    99409600 :         ASSERT_CONSISTENT(mp);
    1282    99409600 :         return 0;
    1283             :     }
    1284             : 
    1285    41689400 :     if (old_value != value) {
    1286    36568500 :         if (_PyDict_HasSplitTable(mp)) {
    1287     4978980 :             mp->ma_values->values[ix] = value;
    1288     4978980 :             if (old_value == NULL) {
    1289     4710100 :                 _PyDictValues_AddToInsertionOrder(mp->ma_values, ix);
    1290     4710100 :                 mp->ma_used++;
    1291             :             }
    1292             :         }
    1293             :         else {
    1294    31589500 :             assert(old_value != NULL);
    1295    31589500 :             if (DK_IS_UNICODE(mp->ma_keys)) {
    1296    30040800 :                 DK_UNICODE_ENTRIES(mp->ma_keys)[ix].me_value = value;
    1297             :             }
    1298             :             else {
    1299     1548710 :                 DK_ENTRIES(mp->ma_keys)[ix].me_value = value;
    1300             :             }
    1301             :         }
    1302    36568500 :         mp->ma_version_tag = DICT_NEXT_VERSION();
    1303             :     }
    1304    41689400 :     Py_XDECREF(old_value); /* which **CAN** re-enter (see issue #22653) */
    1305    41689400 :     ASSERT_CONSISTENT(mp);
    1306    41689400 :     Py_DECREF(key);
    1307    41689400 :     return 0;
    1308             : 
    1309           3 : Fail:
    1310           3 :     Py_DECREF(value);
    1311           3 :     Py_DECREF(key);
    1312           3 :     return -1;
    1313             : }
    1314             : 
    1315             : // Same to insertdict but specialized for ma_keys = Py_EMPTY_KEYS.
    1316             : // Consumes key and value references.
    1317             : static int
    1318    19668900 : insert_to_emptydict(PyDictObject *mp, PyObject *key, Py_hash_t hash,
    1319             :                     PyObject *value)
    1320             : {
    1321    19668900 :     assert(mp->ma_keys == Py_EMPTY_KEYS);
    1322             : 
    1323    19668900 :     int unicode = PyUnicode_CheckExact(key);
    1324    19668900 :     PyDictKeysObject *newkeys = new_keys_object(PyDict_LOG_MINSIZE, unicode);
    1325    19668900 :     if (newkeys == NULL) {
    1326           0 :         Py_DECREF(key);
    1327           0 :         Py_DECREF(value);
    1328           0 :         return -1;
    1329             :     }
    1330    19668900 :     dictkeys_decref(Py_EMPTY_KEYS);
    1331    19668900 :     mp->ma_keys = newkeys;
    1332    19668900 :     mp->ma_values = NULL;
    1333             : 
    1334    19668900 :     MAINTAIN_TRACKING(mp, key, value);
    1335             : 
    1336    19668900 :     size_t hashpos = (size_t)hash & (PyDict_MINSIZE-1);
    1337    19668900 :     dictkeys_set_index(mp->ma_keys, hashpos, 0);
    1338    19668900 :     if (unicode) {
    1339    17569700 :         PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(mp->ma_keys);
    1340    17569700 :         ep->me_key = key;
    1341    17569700 :         ep->me_value = value;
    1342             :     }
    1343             :     else {
    1344     2099180 :         PyDictKeyEntry *ep = DK_ENTRIES(mp->ma_keys);
    1345     2099180 :         ep->me_key = key;
    1346     2099180 :         ep->me_hash = hash;
    1347     2099180 :         ep->me_value = value;
    1348             :     }
    1349    19668900 :     mp->ma_used++;
    1350    19668900 :     mp->ma_version_tag = DICT_NEXT_VERSION();
    1351    19668900 :     mp->ma_keys->dk_usable--;
    1352    19668900 :     mp->ma_keys->dk_nentries++;
    1353    19668900 :     return 0;
    1354             : }
    1355             : 
    1356             : /*
    1357             : Internal routine used by dictresize() to build a hashtable of entries.
    1358             : */
    1359             : static void
    1360     1208630 : build_indices_generic(PyDictKeysObject *keys, PyDictKeyEntry *ep, Py_ssize_t n)
    1361             : {
    1362     1208630 :     size_t mask = DK_MASK(keys);
    1363    19886000 :     for (Py_ssize_t ix = 0; ix != n; ix++, ep++) {
    1364    18677400 :         Py_hash_t hash = ep->me_hash;
    1365    18677400 :         size_t i = hash & mask;
    1366    25468600 :         for (size_t perturb = hash; dictkeys_get_index(keys, i) != DKIX_EMPTY;) {
    1367     6791150 :             perturb >>= PERTURB_SHIFT;
    1368     6791150 :             i = mask & (i*5 + perturb + 1);
    1369             :         }
    1370    18677400 :         dictkeys_set_index(keys, i, ix);
    1371             :     }
    1372     1208630 : }
    1373             : 
    1374             : static void
    1375     9388740 : build_indices_unicode(PyDictKeysObject *keys, PyDictUnicodeEntry *ep, Py_ssize_t n)
    1376             : {
    1377     9388740 :     size_t mask = DK_MASK(keys);
    1378   130624000 :     for (Py_ssize_t ix = 0; ix != n; ix++, ep++) {
    1379   121235000 :         Py_hash_t hash = unicode_get_hash(ep->me_key);
    1380   121235000 :         assert(hash != -1);
    1381   121235000 :         size_t i = hash & mask;
    1382   144687000 :         for (size_t perturb = hash; dictkeys_get_index(keys, i) != DKIX_EMPTY;) {
    1383    23452000 :             perturb >>= PERTURB_SHIFT;
    1384    23452000 :             i = mask & (i*5 + perturb + 1);
    1385             :         }
    1386   121235000 :         dictkeys_set_index(keys, i, ix);
    1387             :     }
    1388     9388740 : }
    1389             : 
    1390             : /*
    1391             : Restructure the table by allocating a new table and reinserting all
    1392             : items again.  When entries have been deleted, the new table may
    1393             : actually be smaller than the old one.
    1394             : If a table is split (its keys and hashes are shared, its values are not),
    1395             : then the values are temporarily copied into the table, it is resized as
    1396             : a combined table, then the me_value slots in the old table are NULLed out.
    1397             : After resizing a table is always combined.
    1398             : 
    1399             : This function supports:
    1400             :  - Unicode split -> Unicode combined or Generic
    1401             :  - Unicode combined -> Unicode combined or Generic
    1402             :  - Generic -> Generic
    1403             : */
    1404             : static int
    1405    10597400 : dictresize(PyDictObject *mp, uint8_t log2_newsize, int unicode)
    1406             : {
    1407             :     PyDictKeysObject *oldkeys;
    1408             :     PyDictValues *oldvalues;
    1409             : 
    1410    10597400 :     if (log2_newsize >= SIZEOF_SIZE_T*8) {
    1411           0 :         PyErr_NoMemory();
    1412           0 :         return -1;
    1413             :     }
    1414    10597400 :     assert(log2_newsize >= PyDict_LOG_MINSIZE);
    1415             : 
    1416    10597400 :     oldkeys = mp->ma_keys;
    1417    10597400 :     oldvalues = mp->ma_values;
    1418             : 
    1419    10597400 :     if (!DK_IS_UNICODE(oldkeys)) {
    1420     1048780 :         unicode = 0;
    1421             :     }
    1422             : 
    1423             :     /* NOTE: Current odict checks mp->ma_keys to detect resize happen.
    1424             :      * So we can't reuse oldkeys even if oldkeys->dk_size == newsize.
    1425             :      * TODO: Try reusing oldkeys when reimplement odict.
    1426             :      */
    1427             : 
    1428             :     /* Allocate a new table. */
    1429    10597400 :     mp->ma_keys = new_keys_object(log2_newsize, unicode);
    1430    10597400 :     if (mp->ma_keys == NULL) {
    1431           0 :         mp->ma_keys = oldkeys;
    1432           0 :         return -1;
    1433             :     }
    1434             :     // New table must be large enough.
    1435    10597400 :     assert(mp->ma_keys->dk_usable >= mp->ma_used);
    1436             : 
    1437    10597400 :     Py_ssize_t numentries = mp->ma_used;
    1438             : 
    1439    10597400 :     if (oldvalues != NULL) {
    1440      115971 :          PyDictUnicodeEntry *oldentries = DK_UNICODE_ENTRIES(oldkeys);
    1441             :         /* Convert split table into new combined table.
    1442             :          * We must incref keys; we can transfer values.
    1443             :          */
    1444      115971 :         if (mp->ma_keys->dk_kind == DICT_KEYS_GENERAL) {
    1445             :             // split -> generic
    1446           3 :             PyDictKeyEntry *newentries = DK_ENTRIES(mp->ma_keys);
    1447             : 
    1448           3 :             for (Py_ssize_t i = 0; i < numentries; i++) {
    1449           0 :                 int index = get_index_from_order(mp, i);
    1450           0 :                 PyDictUnicodeEntry *ep = &oldentries[index];
    1451           0 :                 assert(oldvalues->values[index] != NULL);
    1452           0 :                 Py_INCREF(ep->me_key);
    1453           0 :                 newentries[i].me_key = ep->me_key;
    1454           0 :                 newentries[i].me_hash = unicode_get_hash(ep->me_key);
    1455           0 :                 newentries[i].me_value = oldvalues->values[index];
    1456             :             }
    1457           3 :             build_indices_generic(mp->ma_keys, newentries, numentries);
    1458             :         }
    1459             :         else { // split -> combined unicode
    1460      115968 :             PyDictUnicodeEntry *newentries = DK_UNICODE_ENTRIES(mp->ma_keys);
    1461             : 
    1462      730865 :             for (Py_ssize_t i = 0; i < numentries; i++) {
    1463      614897 :                 int index = get_index_from_order(mp, i);
    1464      614897 :                 PyDictUnicodeEntry *ep = &oldentries[index];
    1465      614897 :                 assert(oldvalues->values[index] != NULL);
    1466      614897 :                 Py_INCREF(ep->me_key);
    1467      614897 :                 newentries[i].me_key = ep->me_key;
    1468      614897 :                 newentries[i].me_value = oldvalues->values[index];
    1469             :             }
    1470      115968 :             build_indices_unicode(mp->ma_keys, newentries, numentries);
    1471             :         }
    1472      115971 :         dictkeys_decref(oldkeys);
    1473      115971 :         mp->ma_values = NULL;
    1474      115971 :         free_values(oldvalues);
    1475             :     }
    1476             :     else {  // oldkeys is combined.
    1477    10481400 :         if (oldkeys->dk_kind == DICT_KEYS_GENERAL) {
    1478             :             // generic -> generic
    1479     1048780 :             assert(mp->ma_keys->dk_kind == DICT_KEYS_GENERAL);
    1480     1048780 :             PyDictKeyEntry *oldentries = DK_ENTRIES(oldkeys);
    1481     1048780 :             PyDictKeyEntry *newentries = DK_ENTRIES(mp->ma_keys);
    1482     1048780 :             if (oldkeys->dk_nentries == numentries) {
    1483      921251 :                 memcpy(newentries, oldentries, numentries * sizeof(PyDictKeyEntry));
    1484             :             }
    1485             :             else {
    1486      127530 :                 PyDictKeyEntry *ep = oldentries;
    1487      897193 :                 for (Py_ssize_t i = 0; i < numentries; i++) {
    1488     1049140 :                     while (ep->me_value == NULL)
    1489      279477 :                         ep++;
    1490      769663 :                     newentries[i] = *ep++;
    1491             :                 }
    1492             :             }
    1493     1048780 :             build_indices_generic(mp->ma_keys, newentries, numentries);
    1494             :         }
    1495             :         else {  // oldkeys is combined unicode
    1496     9432620 :             PyDictUnicodeEntry *oldentries = DK_UNICODE_ENTRIES(oldkeys);
    1497     9432620 :             if (unicode) { // combined unicode -> combined unicode
    1498     9272770 :                 PyDictUnicodeEntry *newentries = DK_UNICODE_ENTRIES(mp->ma_keys);
    1499     9272770 :                 if (oldkeys->dk_nentries == numentries && mp->ma_keys->dk_kind == DICT_KEYS_UNICODE) {
    1500     8851020 :                     memcpy(newentries, oldentries, numentries * sizeof(PyDictUnicodeEntry));
    1501             :                 }
    1502             :                 else {
    1503      421753 :                     PyDictUnicodeEntry *ep = oldentries;
    1504    34060300 :                     for (Py_ssize_t i = 0; i < numentries; i++) {
    1505    35160700 :                         while (ep->me_value == NULL)
    1506     1522150 :                             ep++;
    1507    33638600 :                         newentries[i] = *ep++;
    1508             :                     }
    1509             :                 }
    1510     9272770 :                 build_indices_unicode(mp->ma_keys, newentries, numentries);
    1511             :             }
    1512             :             else { // combined unicode -> generic
    1513      159850 :                 PyDictKeyEntry *newentries = DK_ENTRIES(mp->ma_keys);
    1514      159850 :                 PyDictUnicodeEntry *ep = oldentries;
    1515      572409 :                 for (Py_ssize_t i = 0; i < numentries; i++) {
    1516      412559 :                     while (ep->me_value == NULL)
    1517           0 :                         ep++;
    1518      412559 :                     newentries[i].me_key = ep->me_key;
    1519      412559 :                     newentries[i].me_hash = unicode_get_hash(ep->me_key);
    1520      412559 :                     newentries[i].me_value = ep->me_value;
    1521      412559 :                     ep++;
    1522             :                 }
    1523      159850 :                 build_indices_generic(mp->ma_keys, newentries, numentries);
    1524             :             }
    1525             :         }
    1526             : 
    1527             :         // We can not use free_keys_object here because key's reference
    1528             :         // are moved already.
    1529             : #ifdef Py_REF_DEBUG
    1530    10481400 :         _Py_RefTotal--;
    1531             : #endif
    1532    10481400 :         if (oldkeys == Py_EMPTY_KEYS) {
    1533       58723 :             oldkeys->dk_refcnt--;
    1534       58723 :             assert(oldkeys->dk_refcnt > 0);
    1535             :         }
    1536             :         else {
    1537    10422700 :             assert(oldkeys->dk_kind != DICT_KEYS_SPLIT);
    1538    10422700 :             assert(oldkeys->dk_refcnt == 1);
    1539             : #if PyDict_MAXFREELIST > 0
    1540    10422700 :             struct _Py_dict_state *state = get_dict_state();
    1541             : #ifdef Py_DEBUG
    1542             :             // dictresize() must not be called after _PyDict_Fini()
    1543    10422700 :             assert(state->keys_numfree != -1);
    1544             : #endif
    1545    10422700 :             if (DK_LOG_SIZE(oldkeys) == PyDict_LOG_MINSIZE &&
    1546     7735490 :                     DK_IS_UNICODE(oldkeys) &&
    1547     7078300 :                     state->keys_numfree < PyDict_MAXFREELIST)
    1548             :             {
    1549     7049850 :                 state->keys_free_list[state->keys_numfree++] = oldkeys;
    1550     7049850 :                 OBJECT_STAT_INC(to_freelist);
    1551             :             }
    1552             :             else
    1553             : #endif
    1554             :             {
    1555     3372830 :                 PyObject_Free(oldkeys);
    1556             :             }
    1557             :         }
    1558             :     }
    1559             : 
    1560    10597400 :     mp->ma_keys->dk_usable -= numentries;
    1561    10597400 :     mp->ma_keys->dk_nentries = numentries;
    1562    10597400 :     ASSERT_CONSISTENT(mp);
    1563    10597400 :     return 0;
    1564             : }
    1565             : 
    1566             : static PyObject *
    1567    21274500 : dict_new_presized(Py_ssize_t minused, bool unicode)
    1568             : {
    1569    21274500 :     const uint8_t log2_max_presize = 17;
    1570    21274500 :     const Py_ssize_t max_presize = ((Py_ssize_t)1) << log2_max_presize;
    1571             :     uint8_t log2_newsize;
    1572             :     PyDictKeysObject *new_keys;
    1573             : 
    1574    21274500 :     if (minused <= USABLE_FRACTION(PyDict_MINSIZE)) {
    1575    21126600 :         return PyDict_New();
    1576             :     }
    1577             :     /* There are no strict guarantee that returned dict can contain minused
    1578             :      * items without resize.  So we create medium size dict instead of very
    1579             :      * large dict or MemoryError.
    1580             :      */
    1581      147902 :     if (minused > USABLE_FRACTION(max_presize)) {
    1582           0 :         log2_newsize = log2_max_presize;
    1583             :     }
    1584             :     else {
    1585      147902 :         log2_newsize = estimate_log2_keysize(minused);
    1586             :     }
    1587             : 
    1588      147902 :     new_keys = new_keys_object(log2_newsize, unicode);
    1589      147902 :     if (new_keys == NULL)
    1590           0 :         return NULL;
    1591      147902 :     return new_dict(new_keys, NULL, 0, 0);
    1592             : }
    1593             : 
    1594             : PyObject *
    1595           0 : _PyDict_NewPresized(Py_ssize_t minused)
    1596             : {
    1597           0 :     return dict_new_presized(minused, false);
    1598             : }
    1599             : 
    1600             : PyObject *
    1601    21274500 : _PyDict_FromItems(PyObject *const *keys, Py_ssize_t keys_offset,
    1602             :                   PyObject *const *values, Py_ssize_t values_offset,
    1603             :                   Py_ssize_t length)
    1604             : {
    1605    21274500 :     bool unicode = true;
    1606    21274500 :     PyObject *const *ks = keys;
    1607             : 
    1608    29439400 :     for (Py_ssize_t i = 0; i < length; i++) {
    1609     8215680 :         if (!PyUnicode_CheckExact(*ks)) {
    1610       50786 :             unicode = false;
    1611       50786 :             break;
    1612             :         }
    1613     8164890 :         ks += keys_offset;
    1614             :     }
    1615             : 
    1616    21274500 :     PyObject *dict = dict_new_presized(length, unicode);
    1617    21274500 :     if (dict == NULL) {
    1618           0 :         return NULL;
    1619             :     }
    1620             : 
    1621    21274500 :     ks = keys;
    1622    21274500 :     PyObject *const *vs = values;
    1623             : 
    1624    29636000 :     for (Py_ssize_t i = 0; i < length; i++) {
    1625     8361430 :         PyObject *key = *ks;
    1626     8361430 :         PyObject *value = *vs;
    1627     8361430 :         if (PyDict_SetItem(dict, key, value) < 0) {
    1628           1 :             Py_DECREF(dict);
    1629           1 :             return NULL;
    1630             :         }
    1631     8361430 :         ks += keys_offset;
    1632     8361430 :         vs += values_offset;
    1633             :     }
    1634             : 
    1635    21274500 :     return dict;
    1636             : }
    1637             : 
    1638             : /* Note that, for historical reasons, PyDict_GetItem() suppresses all errors
    1639             :  * that may occur (originally dicts supported only string keys, and exceptions
    1640             :  * weren't possible).  So, while the original intent was that a NULL return
    1641             :  * meant the key wasn't present, in reality it can mean that, or that an error
    1642             :  * (suppressed) occurred while computing the key's hash, or that some error
    1643             :  * (suppressed) occurred when comparing keys in the dict's internal probe
    1644             :  * sequence.  A nasty example of the latter is when a Python-coded comparison
    1645             :  * function hits a stack-depth error, which can cause this to return NULL
    1646             :  * even if the key is present.
    1647             :  */
    1648             : PyObject *
    1649     1298190 : PyDict_GetItem(PyObject *op, PyObject *key)
    1650             : {
    1651     1298190 :     if (!PyDict_Check(op)) {
    1652           0 :         return NULL;
    1653             :     }
    1654     1298190 :     PyDictObject *mp = (PyDictObject *)op;
    1655             : 
    1656             :     Py_hash_t hash;
    1657     1298190 :     if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
    1658         235 :         hash = PyObject_Hash(key);
    1659         235 :         if (hash == -1) {
    1660           0 :             PyErr_Clear();
    1661           0 :             return NULL;
    1662             :         }
    1663             :     }
    1664             : 
    1665     1298190 :     PyThreadState *tstate = _PyThreadState_GET();
    1666             : #ifdef Py_DEBUG
    1667             :     // bpo-40839: Before Python 3.10, it was possible to call PyDict_GetItem()
    1668             :     // with the GIL released.
    1669     1298190 :     _Py_EnsureTstateNotNULL(tstate);
    1670             : #endif
    1671             : 
    1672             :     /* Preserve the existing exception */
    1673             :     PyObject *exc_type, *exc_value, *exc_tb;
    1674             :     PyObject *value;
    1675             :     Py_ssize_t ix; (void)ix;
    1676             : 
    1677     1298190 :     _PyErr_Fetch(tstate, &exc_type, &exc_value, &exc_tb);
    1678     1298190 :     ix = _Py_dict_lookup(mp, key, hash, &value);
    1679             : 
    1680             :     /* Ignore any exception raised by the lookup */
    1681     1298190 :     _PyErr_Restore(tstate, exc_type, exc_value, exc_tb);
    1682             : 
    1683             : 
    1684     1298190 :     assert(ix >= 0 || value == NULL);
    1685     1298190 :     return value;
    1686             : }
    1687             : 
    1688             : Py_ssize_t
    1689      907564 : _PyDict_GetItemHint(PyDictObject *mp, PyObject *key,
    1690             :                     Py_ssize_t hint, PyObject **value)
    1691             : {
    1692      907564 :     assert(*value == NULL);
    1693      907564 :     assert(PyDict_CheckExact((PyObject*)mp));
    1694      907564 :     assert(PyUnicode_CheckExact(key));
    1695             : 
    1696      907564 :     if (hint >= 0 && hint < mp->ma_keys->dk_nentries) {
    1697           0 :         PyObject *res = NULL;
    1698             : 
    1699           0 :         if (DK_IS_UNICODE(mp->ma_keys)) {
    1700           0 :             PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(mp->ma_keys) + (size_t)hint;
    1701           0 :             if (ep->me_key == key) {
    1702           0 :                 if (mp->ma_keys->dk_kind == DICT_KEYS_SPLIT) {
    1703           0 :                     assert(mp->ma_values != NULL);
    1704           0 :                     res = mp->ma_values->values[(size_t)hint];
    1705             :                 }
    1706             :                 else {
    1707           0 :                     res = ep->me_value;
    1708             :                 }
    1709           0 :                 if (res != NULL) {
    1710           0 :                     *value = res;
    1711           0 :                     return hint;
    1712             :                 }
    1713             :             }
    1714             :         }
    1715             :         else {
    1716           0 :             PyDictKeyEntry *ep = DK_ENTRIES(mp->ma_keys) + (size_t)hint;
    1717           0 :             if (ep->me_key == key) {
    1718           0 :                 if (mp->ma_keys->dk_kind == DICT_KEYS_SPLIT) {
    1719           0 :                     assert(mp->ma_values != NULL);
    1720           0 :                     res = mp->ma_values->values[(size_t)hint];
    1721             :                 }
    1722             :                 else {
    1723           0 :                     res = ep->me_value;
    1724             :                 }
    1725           0 :                 if (res != NULL) {
    1726           0 :                     *value = res;
    1727           0 :                     return hint;
    1728             :                 }
    1729             :             }
    1730             :         }
    1731             :     }
    1732             : 
    1733      907564 :     Py_hash_t hash = unicode_get_hash(key);
    1734      907564 :     if (hash == -1) {
    1735           0 :         hash = PyObject_Hash(key);
    1736           0 :         if (hash == -1) {
    1737           0 :             return -1;
    1738             :         }
    1739             :     }
    1740             : 
    1741      907564 :     return _Py_dict_lookup(mp, key, hash, value);
    1742             : }
    1743             : 
    1744             : /* Same as PyDict_GetItemWithError() but with hash supplied by caller.
    1745             :    This returns NULL *with* an exception set if an exception occurred.
    1746             :    It returns NULL *without* an exception set if the key wasn't present.
    1747             : */
    1748             : PyObject *
    1749   485606000 : _PyDict_GetItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
    1750             : {
    1751             :     Py_ssize_t ix; (void)ix;
    1752   485606000 :     PyDictObject *mp = (PyDictObject *)op;
    1753             :     PyObject *value;
    1754             : 
    1755   485606000 :     if (!PyDict_Check(op)) {
    1756           1 :         PyErr_BadInternalCall();
    1757           1 :         return NULL;
    1758             :     }
    1759             : 
    1760   485606000 :     ix = _Py_dict_lookup(mp, key, hash, &value);
    1761   485606000 :     assert(ix >= 0 || value == NULL);
    1762   485606000 :     return value;
    1763             : }
    1764             : 
    1765             : /* Variant of PyDict_GetItem() that doesn't suppress exceptions.
    1766             :    This returns NULL *with* an exception set if an exception occurred.
    1767             :    It returns NULL *without* an exception set if the key wasn't present.
    1768             : */
    1769             : PyObject *
    1770   243735000 : PyDict_GetItemWithError(PyObject *op, PyObject *key)
    1771             : {
    1772             :     Py_ssize_t ix; (void)ix;
    1773             :     Py_hash_t hash;
    1774   243735000 :     PyDictObject*mp = (PyDictObject *)op;
    1775             :     PyObject *value;
    1776             : 
    1777   243735000 :     if (!PyDict_Check(op)) {
    1778           0 :         PyErr_BadInternalCall();
    1779           0 :         return NULL;
    1780             :     }
    1781   243735000 :     if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1)
    1782             :     {
    1783    19484700 :         hash = PyObject_Hash(key);
    1784    19484700 :         if (hash == -1) {
    1785          11 :             return NULL;
    1786             :         }
    1787             :     }
    1788             : 
    1789   243735000 :     ix = _Py_dict_lookup(mp, key, hash, &value);
    1790   243735000 :     assert(ix >= 0 || value == NULL);
    1791   243735000 :     return value;
    1792             : }
    1793             : 
    1794             : PyObject *
    1795     2557170 : _PyDict_GetItemWithError(PyObject *dp, PyObject *kv)
    1796             : {
    1797     2557170 :     assert(PyUnicode_CheckExact(kv));
    1798     2557170 :     Py_hash_t hash = kv->ob_type->tp_hash(kv);
    1799     2557170 :     if (hash == -1) {
    1800           0 :         return NULL;
    1801             :     }
    1802     2557170 :     return _PyDict_GetItem_KnownHash(dp, kv, hash);
    1803             : }
    1804             : 
    1805             : PyObject *
    1806        8292 : _PyDict_GetItemIdWithError(PyObject *dp, _Py_Identifier *key)
    1807             : {
    1808             :     PyObject *kv;
    1809        8292 :     kv = _PyUnicode_FromId(key); /* borrowed */
    1810        8292 :     if (kv == NULL)
    1811           0 :         return NULL;
    1812        8292 :     Py_hash_t hash = unicode_get_hash(kv);
    1813        8292 :     assert (hash != -1);  /* interned strings have their hash value initialised */
    1814        8292 :     return _PyDict_GetItem_KnownHash(dp, kv, hash);
    1815             : }
    1816             : 
    1817             : PyObject *
    1818     3624860 : _PyDict_GetItemStringWithError(PyObject *v, const char *key)
    1819             : {
    1820             :     PyObject *kv, *rv;
    1821     3624860 :     kv = PyUnicode_FromString(key);
    1822     3624860 :     if (kv == NULL) {
    1823           6 :         return NULL;
    1824             :     }
    1825     3624860 :     rv = PyDict_GetItemWithError(v, kv);
    1826     3624860 :     Py_DECREF(kv);
    1827     3624860 :     return rv;
    1828             : }
    1829             : 
    1830             : /* Fast version of global value lookup (LOAD_GLOBAL).
    1831             :  * Lookup in globals, then builtins.
    1832             :  *
    1833             :  *
    1834             :  *
    1835             :  *
    1836             :  * Raise an exception and return NULL if an error occurred (ex: computing the
    1837             :  * key hash failed, key comparison failed, ...). Return NULL if the key doesn't
    1838             :  * exist. Return the value if the key exists.
    1839             :  */
    1840             : PyObject *
    1841    34888900 : _PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key)
    1842             : {
    1843             :     Py_ssize_t ix;
    1844             :     Py_hash_t hash;
    1845             :     PyObject *value;
    1846             : 
    1847    34888900 :     if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
    1848           0 :         hash = PyObject_Hash(key);
    1849           0 :         if (hash == -1)
    1850           0 :             return NULL;
    1851             :     }
    1852             : 
    1853             :     /* namespace 1: globals */
    1854    34888900 :     ix = _Py_dict_lookup(globals, key, hash, &value);
    1855    34888900 :     if (ix == DKIX_ERROR)
    1856           0 :         return NULL;
    1857    34888900 :     if (ix != DKIX_EMPTY && value != NULL)
    1858    17430000 :         return value;
    1859             : 
    1860             :     /* namespace 2: builtins */
    1861    17458900 :     ix = _Py_dict_lookup(builtins, key, hash, &value);
    1862    17458900 :     assert(ix >= 0 || value == NULL);
    1863    17458900 :     return value;
    1864             : }
    1865             : 
    1866             : /* Consumes references to key and value */
    1867             : int
    1868   154400000 : _PyDict_SetItem_Take2(PyDictObject *mp, PyObject *key, PyObject *value)
    1869             : {
    1870   154400000 :     assert(key);
    1871   154400000 :     assert(value);
    1872   154400000 :     assert(PyDict_Check(mp));
    1873             :     Py_hash_t hash;
    1874   154400000 :     if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
    1875    17838600 :         hash = PyObject_Hash(key);
    1876    17838600 :         if (hash == -1) {
    1877           5 :             Py_DECREF(key);
    1878           5 :             Py_DECREF(value);
    1879           5 :             return -1;
    1880             :         }
    1881             :     }
    1882   154400000 :     if (mp->ma_keys == Py_EMPTY_KEYS) {
    1883    19456000 :         return insert_to_emptydict(mp, key, hash, value);
    1884             :     }
    1885             :     /* insertdict() handles any resizing that might be necessary */
    1886   134944000 :     return insertdict(mp, key, hash, value);
    1887             : }
    1888             : 
    1889             : /* CAUTION: PyDict_SetItem() must guarantee that it won't resize the
    1890             :  * dictionary if it's merely replacing the value for an existing key.
    1891             :  * This means that it's safe to loop over a dictionary with PyDict_Next()
    1892             :  * and occasionally replace a value -- but you can't insert new keys or
    1893             :  * remove them.
    1894             :  */
    1895             : int
    1896   138051000 : PyDict_SetItem(PyObject *op, PyObject *key, PyObject *value)
    1897             : {
    1898   138051000 :     if (!PyDict_Check(op)) {
    1899           0 :         PyErr_BadInternalCall();
    1900           0 :         return -1;
    1901             :     }
    1902   138051000 :     assert(key);
    1903   138051000 :     assert(value);
    1904   138051000 :     Py_INCREF(key);
    1905   138051000 :     Py_INCREF(value);
    1906   138051000 :     return _PyDict_SetItem_Take2((PyDictObject *)op, key, value);
    1907             : }
    1908             : 
    1909             : int
    1910      117935 : _PyDict_SetItem_KnownHash(PyObject *op, PyObject *key, PyObject *value,
    1911             :                          Py_hash_t hash)
    1912             : {
    1913             :     PyDictObject *mp;
    1914             : 
    1915      117935 :     if (!PyDict_Check(op)) {
    1916           0 :         PyErr_BadInternalCall();
    1917           0 :         return -1;
    1918             :     }
    1919      117935 :     assert(key);
    1920      117935 :     assert(value);
    1921      117935 :     assert(hash != -1);
    1922      117935 :     mp = (PyDictObject *)op;
    1923             : 
    1924      117935 :     Py_INCREF(key);
    1925      117935 :     Py_INCREF(value);
    1926      117935 :     if (mp->ma_keys == Py_EMPTY_KEYS) {
    1927       22297 :         return insert_to_emptydict(mp, key, hash, value);
    1928             :     }
    1929             :     /* insertdict() handles any resizing that might be necessary */
    1930       95638 :     return insertdict(mp, key, hash, value);
    1931             : }
    1932             : 
    1933             : static void
    1934     3377130 : delete_index_from_values(PyDictValues *values, Py_ssize_t ix)
    1935             : {
    1936     3377130 :     uint8_t *size_ptr = ((uint8_t *)values)-2;
    1937     3377130 :     int size = *size_ptr;
    1938             :     int i;
    1939     9050240 :     for (i = 1; size_ptr[-i] != ix; i++) {
    1940     5673110 :         assert(i <= size);
    1941             :     }
    1942     3377130 :     assert(i <= size);
    1943     8079890 :     for (; i < size; i++) {
    1944     4702760 :         size_ptr[-i] = size_ptr[-i-1];
    1945             :     }
    1946     3377130 :     *size_ptr = size -1;
    1947     3377130 : }
    1948             : 
    1949             : static int
    1950    26220400 : delitem_common(PyDictObject *mp, Py_hash_t hash, Py_ssize_t ix,
    1951             :                PyObject *old_value)
    1952             : {
    1953             :     PyObject *old_key;
    1954             : 
    1955    26220400 :     Py_ssize_t hashpos = lookdict_index(mp->ma_keys, hash, ix);
    1956    26220400 :     assert(hashpos >= 0);
    1957             : 
    1958    26220400 :     mp->ma_used--;
    1959    26220400 :     mp->ma_version_tag = DICT_NEXT_VERSION();
    1960    26220400 :     if (mp->ma_values) {
    1961        4145 :         assert(old_value == mp->ma_values->values[ix]);
    1962        4145 :         mp->ma_values->values[ix] = NULL;
    1963        4145 :         assert(ix < SHARED_KEYS_MAX_SIZE);
    1964             :         /* Update order */
    1965        4145 :         delete_index_from_values(mp->ma_values, ix);
    1966        4145 :         ASSERT_CONSISTENT(mp);
    1967             :     }
    1968             :     else {
    1969    26216300 :         mp->ma_keys->dk_version = 0;
    1970    26216300 :         dictkeys_set_index(mp->ma_keys, hashpos, DKIX_DUMMY);
    1971    26216300 :         if (DK_IS_UNICODE(mp->ma_keys)) {
    1972    22930400 :             PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(mp->ma_keys)[ix];
    1973    22930400 :             old_key = ep->me_key;
    1974    22930400 :             ep->me_key = NULL;
    1975    22930400 :             ep->me_value = NULL;
    1976             :         }
    1977             :         else {
    1978     3285850 :             PyDictKeyEntry *ep = &DK_ENTRIES(mp->ma_keys)[ix];
    1979     3285850 :             old_key = ep->me_key;
    1980     3285850 :             ep->me_key = NULL;
    1981     3285850 :             ep->me_value = NULL;
    1982     3285850 :             ep->me_hash = 0;
    1983             :         }
    1984    26216300 :         Py_DECREF(old_key);
    1985             :     }
    1986    26220400 :     Py_DECREF(old_value);
    1987             : 
    1988    26220400 :     ASSERT_CONSISTENT(mp);
    1989    26220400 :     return 0;
    1990             : }
    1991             : 
    1992             : int
    1993    25545700 : PyDict_DelItem(PyObject *op, PyObject *key)
    1994             : {
    1995             :     Py_hash_t hash;
    1996    25545700 :     assert(key);
    1997    25545700 :     if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
    1998     2971210 :         hash = PyObject_Hash(key);
    1999     2971210 :         if (hash == -1)
    2000           0 :             return -1;
    2001             :     }
    2002             : 
    2003    25545700 :     return _PyDict_DelItem_KnownHash(op, key, hash);
    2004             : }
    2005             : 
    2006             : int
    2007    25567800 : _PyDict_DelItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
    2008             : {
    2009             :     Py_ssize_t ix;
    2010             :     PyDictObject *mp;
    2011             :     PyObject *old_value;
    2012             : 
    2013    25567800 :     if (!PyDict_Check(op)) {
    2014           0 :         PyErr_BadInternalCall();
    2015           0 :         return -1;
    2016             :     }
    2017    25567800 :     assert(key);
    2018    25567800 :     assert(hash != -1);
    2019    25567800 :     mp = (PyDictObject *)op;
    2020    25567800 :     ix = _Py_dict_lookup(mp, key, hash, &old_value);
    2021    25567800 :     if (ix == DKIX_ERROR)
    2022           0 :         return -1;
    2023    25567800 :     if (ix == DKIX_EMPTY || old_value == NULL) {
    2024       41139 :         _PyErr_SetKeyError(key);
    2025       41139 :         return -1;
    2026             :     }
    2027             : 
    2028    25526600 :     return delitem_common(mp, hash, ix, old_value);
    2029             : }
    2030             : 
    2031             : /* This function promises that the predicate -> deletion sequence is atomic
    2032             :  * (i.e. protected by the GIL), assuming the predicate itself doesn't
    2033             :  * release the GIL.
    2034             :  */
    2035             : int
    2036      177173 : _PyDict_DelItemIf(PyObject *op, PyObject *key,
    2037             :                   int (*predicate)(PyObject *value))
    2038             : {
    2039             :     Py_ssize_t hashpos, ix;
    2040             :     PyDictObject *mp;
    2041             :     Py_hash_t hash;
    2042             :     PyObject *old_value;
    2043             :     int res;
    2044             : 
    2045      177173 :     if (!PyDict_Check(op)) {
    2046           0 :         PyErr_BadInternalCall();
    2047           0 :         return -1;
    2048             :     }
    2049      177173 :     assert(key);
    2050      177173 :     hash = PyObject_Hash(key);
    2051      177173 :     if (hash == -1)
    2052           0 :         return -1;
    2053      177173 :     mp = (PyDictObject *)op;
    2054      177173 :     ix = _Py_dict_lookup(mp, key, hash, &old_value);
    2055      177173 :     if (ix == DKIX_ERROR)
    2056           0 :         return -1;
    2057      177173 :     if (ix == DKIX_EMPTY || old_value == NULL) {
    2058          44 :         _PyErr_SetKeyError(key);
    2059          44 :         return -1;
    2060             :     }
    2061             : 
    2062      177129 :     res = predicate(old_value);
    2063      177129 :     if (res == -1)
    2064           0 :         return -1;
    2065             : 
    2066      177129 :     hashpos = lookdict_index(mp->ma_keys, hash, ix);
    2067      177129 :     assert(hashpos >= 0);
    2068             : 
    2069      177129 :     if (res > 0)
    2070      176359 :         return delitem_common(mp, hashpos, ix, old_value);
    2071             :     else
    2072         770 :         return 0;
    2073             : }
    2074             : 
    2075             : 
    2076             : void
    2077     1898000 : PyDict_Clear(PyObject *op)
    2078             : {
    2079             :     PyDictObject *mp;
    2080             :     PyDictKeysObject *oldkeys;
    2081             :     PyDictValues *oldvalues;
    2082             :     Py_ssize_t i, n;
    2083             : 
    2084     1898000 :     if (!PyDict_Check(op))
    2085           0 :         return;
    2086     1898000 :     mp = ((PyDictObject *)op);
    2087     1898000 :     oldkeys = mp->ma_keys;
    2088     1898000 :     oldvalues = mp->ma_values;
    2089     1898000 :     if (oldkeys == Py_EMPTY_KEYS) {
    2090      326272 :         return;
    2091             :     }
    2092             :     /* Empty the dict... */
    2093     1571720 :     dictkeys_incref(Py_EMPTY_KEYS);
    2094     1571720 :     mp->ma_keys = Py_EMPTY_KEYS;
    2095     1571720 :     mp->ma_values = NULL;
    2096     1571720 :     mp->ma_used = 0;
    2097     1571720 :     mp->ma_version_tag = DICT_NEXT_VERSION();
    2098             :     /* ...then clear the keys and values */
    2099     1571720 :     if (oldvalues != NULL) {
    2100          60 :         n = oldkeys->dk_nentries;
    2101         558 :         for (i = 0; i < n; i++)
    2102         498 :             Py_CLEAR(oldvalues->values[i]);
    2103          60 :         free_values(oldvalues);
    2104          60 :         dictkeys_decref(oldkeys);
    2105             :     }
    2106             :     else {
    2107     1571660 :        assert(oldkeys->dk_refcnt == 1);
    2108     1571660 :        dictkeys_decref(oldkeys);
    2109             :     }
    2110     1571720 :     ASSERT_CONSISTENT(mp);
    2111             : }
    2112             : 
    2113             : /* Internal version of PyDict_Next that returns a hash value in addition
    2114             :  * to the key and value.
    2115             :  * Return 1 on success, return 0 when the reached the end of the dictionary
    2116             :  * (or if op is not a dictionary)
    2117             :  */
    2118             : int
    2119    77802600 : _PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey,
    2120             :              PyObject **pvalue, Py_hash_t *phash)
    2121             : {
    2122             :     Py_ssize_t i;
    2123             :     PyDictObject *mp;
    2124             :     PyObject *key, *value;
    2125             :     Py_hash_t hash;
    2126             : 
    2127    77802600 :     if (!PyDict_Check(op))
    2128           0 :         return 0;
    2129    77802600 :     mp = (PyDictObject *)op;
    2130    77802600 :     i = *ppos;
    2131    77802600 :     if (mp->ma_values) {
    2132      220438 :         assert(mp->ma_used <= SHARED_KEYS_MAX_SIZE);
    2133      220438 :         if (i < 0 || i >= mp->ma_used)
    2134       13249 :             return 0;
    2135      207189 :         int index = get_index_from_order(mp, i);
    2136      207189 :         value = mp->ma_values->values[index];
    2137             : 
    2138      207189 :         key = DK_UNICODE_ENTRIES(mp->ma_keys)[index].me_key;
    2139      207189 :         hash = unicode_get_hash(key);
    2140      207189 :         assert(value != NULL);
    2141             :     }
    2142             :     else {
    2143    77582200 :         Py_ssize_t n = mp->ma_keys->dk_nentries;
    2144    77582200 :         if (i < 0 || i >= n)
    2145    10489600 :             return 0;
    2146    67092600 :         if (DK_IS_UNICODE(mp->ma_keys)) {
    2147    63046300 :             PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(mp->ma_keys)[i];
    2148    82996800 :             while (i < n && entry_ptr->me_value == NULL) {
    2149    19950500 :                 entry_ptr++;
    2150    19950500 :                 i++;
    2151             :             }
    2152    63046300 :             if (i >= n)
    2153       50955 :                 return 0;
    2154    62995400 :             key = entry_ptr->me_key;
    2155    62995400 :             hash = unicode_get_hash(entry_ptr->me_key);
    2156    62995400 :             value = entry_ptr->me_value;
    2157             :         }
    2158             :         else {
    2159     4046330 :             PyDictKeyEntry *entry_ptr = &DK_ENTRIES(mp->ma_keys)[i];
    2160     4116680 :             while (i < n && entry_ptr->me_value == NULL) {
    2161       70345 :                 entry_ptr++;
    2162       70345 :                 i++;
    2163             :             }
    2164     4046330 :             if (i >= n)
    2165       18255 :                 return 0;
    2166     4028080 :             key = entry_ptr->me_key;
    2167     4028080 :             hash = entry_ptr->me_hash;
    2168     4028080 :             value = entry_ptr->me_value;
    2169             :         }
    2170             :     }
    2171    67230600 :     *ppos = i+1;
    2172    67230600 :     if (pkey)
    2173    66836800 :         *pkey = key;
    2174    67230600 :     if (pvalue)
    2175    57338000 :         *pvalue = value;
    2176    67230600 :     if (phash)
    2177     6121430 :         *phash = hash;
    2178    67230600 :     return 1;
    2179             : }
    2180             : 
    2181             : /*
    2182             :  * Iterate over a dict.  Use like so:
    2183             :  *
    2184             :  *     Py_ssize_t i;
    2185             :  *     PyObject *key, *value;
    2186             :  *     i = 0;   # important!  i should not otherwise be changed by you
    2187             :  *     while (PyDict_Next(yourdict, &i, &key, &value)) {
    2188             :  *         Refer to borrowed references in key and value.
    2189             :  *     }
    2190             :  *
    2191             :  * Return 1 on success, return 0 when the reached the end of the dictionary
    2192             :  * (or if op is not a dictionary)
    2193             :  *
    2194             :  * CAUTION:  In general, it isn't safe to use PyDict_Next in a loop that
    2195             :  * mutates the dict.  One exception:  it is safe if the loop merely changes
    2196             :  * the values associated with the keys (but doesn't insert new keys or
    2197             :  * delete keys), via PyDict_SetItem().
    2198             :  */
    2199             : int
    2200    60364100 : PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue)
    2201             : {
    2202    60364100 :     return _PyDict_Next(op, ppos, pkey, pvalue, NULL);
    2203             : }
    2204             : 
    2205             : /* Internal version of dict.pop(). */
    2206             : PyObject *
    2207      642378 : _PyDict_Pop_KnownHash(PyObject *dict, PyObject *key, Py_hash_t hash, PyObject *deflt)
    2208             : {
    2209             :     Py_ssize_t ix;
    2210             :     PyObject *old_value;
    2211             :     PyDictObject *mp;
    2212             : 
    2213      642378 :     assert(PyDict_Check(dict));
    2214      642378 :     mp = (PyDictObject *)dict;
    2215             : 
    2216      642378 :     if (mp->ma_used == 0) {
    2217           0 :         if (deflt) {
    2218           0 :             Py_INCREF(deflt);
    2219           0 :             return deflt;
    2220             :         }
    2221           0 :         _PyErr_SetKeyError(key);
    2222           0 :         return NULL;
    2223             :     }
    2224      642378 :     ix = _Py_dict_lookup(mp, key, hash, &old_value);
    2225      642378 :     if (ix == DKIX_ERROR)
    2226           1 :         return NULL;
    2227      642377 :     if (ix == DKIX_EMPTY || old_value == NULL) {
    2228      124955 :         if (deflt) {
    2229       85800 :             Py_INCREF(deflt);
    2230       85800 :             return deflt;
    2231             :         }
    2232       39155 :         _PyErr_SetKeyError(key);
    2233       39155 :         return NULL;
    2234             :     }
    2235      517422 :     assert(old_value != NULL);
    2236      517422 :     Py_INCREF(old_value);
    2237      517422 :     delitem_common(mp, hash, ix, old_value);
    2238             : 
    2239      517422 :     ASSERT_CONSISTENT(mp);
    2240      517422 :     return old_value;
    2241             : }
    2242             : 
    2243             : PyObject *
    2244      774244 : _PyDict_Pop(PyObject *dict, PyObject *key, PyObject *deflt)
    2245             : {
    2246             :     Py_hash_t hash;
    2247             : 
    2248      774244 :     if (((PyDictObject *)dict)->ma_used == 0) {
    2249      137995 :         if (deflt) {
    2250       96825 :             Py_INCREF(deflt);
    2251       96825 :             return deflt;
    2252             :         }
    2253       41170 :         _PyErr_SetKeyError(key);
    2254       41170 :         return NULL;
    2255             :     }
    2256      636249 :     if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
    2257      132604 :         hash = PyObject_Hash(key);
    2258      132604 :         if (hash == -1)
    2259           1 :             return NULL;
    2260             :     }
    2261      636248 :     return _PyDict_Pop_KnownHash(dict, key, hash, deflt);
    2262             : }
    2263             : 
    2264             : /* Internal version of dict.from_keys().  It is subclass-friendly. */
    2265             : PyObject *
    2266      107871 : _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
    2267             : {
    2268             :     PyObject *it;       /* iter(iterable) */
    2269             :     PyObject *key;
    2270             :     PyObject *d;
    2271             :     int status;
    2272             : 
    2273      107871 :     d = _PyObject_CallNoArgs(cls);
    2274      107871 :     if (d == NULL)
    2275           1 :         return NULL;
    2276             : 
    2277      107870 :     if (PyDict_CheckExact(d) && ((PyDictObject *)d)->ma_used == 0) {
    2278      107805 :         if (PyDict_CheckExact(iterable)) {
    2279         268 :             PyDictObject *mp = (PyDictObject *)d;
    2280             :             PyObject *oldvalue;
    2281         268 :             Py_ssize_t pos = 0;
    2282             :             PyObject *key;
    2283             :             Py_hash_t hash;
    2284             : 
    2285         268 :             int unicode = DK_IS_UNICODE(((PyDictObject*)iterable)->ma_keys);
    2286         268 :             if (dictresize(mp, estimate_log2_keysize(PyDict_GET_SIZE(iterable)), unicode)) {
    2287           0 :                 Py_DECREF(d);
    2288           0 :                 return NULL;
    2289             :             }
    2290             : 
    2291         845 :             while (_PyDict_Next(iterable, &pos, &key, &oldvalue, &hash)) {
    2292         577 :                 Py_INCREF(key);
    2293         577 :                 Py_INCREF(value);
    2294         577 :                 if (insertdict(mp, key, hash, value)) {
    2295           0 :                     Py_DECREF(d);
    2296           0 :                     return NULL;
    2297             :                 }
    2298             :             }
    2299         268 :             return d;
    2300             :         }
    2301      107537 :         if (PyAnySet_CheckExact(iterable)) {
    2302         313 :             PyDictObject *mp = (PyDictObject *)d;
    2303         313 :             Py_ssize_t pos = 0;
    2304             :             PyObject *key;
    2305             :             Py_hash_t hash;
    2306             : 
    2307         313 :             if (dictresize(mp, estimate_log2_keysize(PySet_GET_SIZE(iterable)), 0)) {
    2308           0 :                 Py_DECREF(d);
    2309           0 :                 return NULL;
    2310             :             }
    2311             : 
    2312        1154 :             while (_PySet_NextEntry(iterable, &pos, &key, &hash)) {
    2313         841 :                 Py_INCREF(key);
    2314         841 :                 Py_INCREF(value);
    2315         841 :                 if (insertdict(mp, key, hash, value)) {
    2316           0 :                     Py_DECREF(d);
    2317           0 :                     return NULL;
    2318             :                 }
    2319             :             }
    2320         313 :             return d;
    2321             :         }
    2322             :     }
    2323             : 
    2324      107289 :     it = PyObject_GetIter(iterable);
    2325      107289 :     if (it == NULL){
    2326           2 :         Py_DECREF(d);
    2327           2 :         return NULL;
    2328             :     }
    2329             : 
    2330      107287 :     if (PyDict_CheckExact(d)) {
    2331      799581 :         while ((key = PyIter_Next(it)) != NULL) {
    2332      692358 :             status = PyDict_SetItem(d, key, value);
    2333      692358 :             Py_DECREF(key);
    2334      692358 :             if (status < 0)
    2335           0 :                 goto Fail;
    2336             :         }
    2337             :     } else {
    2338         449 :         while ((key = PyIter_Next(it)) != NULL) {
    2339         386 :             status = PyObject_SetItem(d, key, value);
    2340         386 :             Py_DECREF(key);
    2341         386 :             if (status < 0)
    2342           1 :                 goto Fail;
    2343             :         }
    2344             :     }
    2345             : 
    2346      107286 :     if (PyErr_Occurred())
    2347           1 :         goto Fail;
    2348      107285 :     Py_DECREF(it);
    2349      107285 :     return d;
    2350             : 
    2351           2 : Fail:
    2352           2 :     Py_DECREF(it);
    2353           2 :     Py_DECREF(d);
    2354           2 :     return NULL;
    2355             : }
    2356             : 
    2357             : /* Methods */
    2358             : 
    2359             : static void
    2360    47273700 : dict_dealloc(PyDictObject *mp)
    2361             : {
    2362    47273700 :     PyDictValues *values = mp->ma_values;
    2363    47273700 :     PyDictKeysObject *keys = mp->ma_keys;
    2364             :     Py_ssize_t i, n;
    2365             : 
    2366             :     /* bpo-31095: UnTrack is needed before calling any callbacks */
    2367    47273700 :     PyObject_GC_UnTrack(mp);
    2368    47273700 :     Py_TRASHCAN_BEGIN(mp, dict_dealloc)
    2369    47183600 :     if (values != NULL) {
    2370     9660310 :         for (i = 0, n = mp->ma_keys->dk_nentries; i < n; i++) {
    2371     5234120 :             Py_XDECREF(values->values[i]);
    2372             :         }
    2373     4426190 :         free_values(values);
    2374     4426190 :         dictkeys_decref(keys);
    2375             :     }
    2376    42757400 :     else if (keys != NULL) {
    2377    42757400 :         assert(keys->dk_refcnt == 1 || keys == Py_EMPTY_KEYS);
    2378    42757400 :         dictkeys_decref(keys);
    2379             :     }
    2380             : #if PyDict_MAXFREELIST > 0
    2381    47183600 :     struct _Py_dict_state *state = get_dict_state();
    2382             : #ifdef Py_DEBUG
    2383             :     // new_dict() must not be called after _PyDict_Fini()
    2384    47183600 :     assert(state->numfree != -1);
    2385             : #endif
    2386    47183600 :     if (state->numfree < PyDict_MAXFREELIST && Py_IS_TYPE(mp, &PyDict_Type)) {
    2387    33313500 :         state->free_list[state->numfree++] = mp;
    2388    33313500 :         OBJECT_STAT_INC(to_freelist);
    2389             :     }
    2390             :     else
    2391             : #endif
    2392             :     {
    2393    13870100 :         Py_TYPE(mp)->tp_free((PyObject *)mp);
    2394             :     }
    2395    47183600 :     Py_TRASHCAN_END
    2396    47273700 : }
    2397             : 
    2398             : 
    2399             : static PyObject *
    2400        5722 : dict_repr(PyDictObject *mp)
    2401             : {
    2402             :     Py_ssize_t i;
    2403        5722 :     PyObject *key = NULL, *value = NULL;
    2404             :     _PyUnicodeWriter writer;
    2405             :     int first;
    2406             : 
    2407        5722 :     i = Py_ReprEnter((PyObject *)mp);
    2408        5722 :     if (i != 0) {
    2409           4 :         return i > 0 ? PyUnicode_FromString("{...}") : NULL;
    2410             :     }
    2411             : 
    2412        5718 :     if (mp->ma_used == 0) {
    2413         286 :         Py_ReprLeave((PyObject *)mp);
    2414         286 :         return PyUnicode_FromString("{}");
    2415             :     }
    2416             : 
    2417        5432 :     _PyUnicodeWriter_Init(&writer);
    2418        5432 :     writer.overallocate = 1;
    2419             :     /* "{" + "1: 2" + ", 3: 4" * (len - 1) + "}" */
    2420        5432 :     writer.min_length = 1 + 4 + (2 + 4) * (mp->ma_used - 1) + 1;
    2421             : 
    2422        5432 :     if (_PyUnicodeWriter_WriteChar(&writer, '{') < 0)
    2423           0 :         goto error;
    2424             : 
    2425             :     /* Do repr() on each key+value pair, and insert ": " between them.
    2426             :        Note that repr may mutate the dict. */
    2427        5432 :     i = 0;
    2428        5432 :     first = 1;
    2429      271812 :     while (PyDict_Next((PyObject *)mp, &i, &key, &value)) {
    2430             :         PyObject *s;
    2431             :         int res;
    2432             : 
    2433             :         /* Prevent repr from deleting key or value during key format. */
    2434      267590 :         Py_INCREF(key);
    2435      267590 :         Py_INCREF(value);
    2436             : 
    2437      267590 :         if (!first) {
    2438      262158 :             if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0)
    2439           0 :                 goto error;
    2440             :         }
    2441      267590 :         first = 0;
    2442             : 
    2443      267590 :         s = PyObject_Repr(key);
    2444      267590 :         if (s == NULL)
    2445           1 :             goto error;
    2446      267589 :         res = _PyUnicodeWriter_WriteStr(&writer, s);
    2447      267589 :         Py_DECREF(s);
    2448      267589 :         if (res < 0)
    2449           0 :             goto error;
    2450             : 
    2451      267589 :         if (_PyUnicodeWriter_WriteASCIIString(&writer, ": ", 2) < 0)
    2452           0 :             goto error;
    2453             : 
    2454      267589 :         s = PyObject_Repr(value);
    2455      267589 :         if (s == NULL)
    2456        1209 :             goto error;
    2457      266380 :         res = _PyUnicodeWriter_WriteStr(&writer, s);
    2458      266380 :         Py_DECREF(s);
    2459      266380 :         if (res < 0)
    2460           0 :             goto error;
    2461             : 
    2462      266380 :         Py_CLEAR(key);
    2463      266380 :         Py_CLEAR(value);
    2464             :     }
    2465             : 
    2466        4222 :     writer.overallocate = 0;
    2467        4222 :     if (_PyUnicodeWriter_WriteChar(&writer, '}') < 0)
    2468           0 :         goto error;
    2469             : 
    2470        4222 :     Py_ReprLeave((PyObject *)mp);
    2471             : 
    2472        4222 :     return _PyUnicodeWriter_Finish(&writer);
    2473             : 
    2474        1210 : error:
    2475        1210 :     Py_ReprLeave((PyObject *)mp);
    2476        1210 :     _PyUnicodeWriter_Dealloc(&writer);
    2477        1210 :     Py_XDECREF(key);
    2478        1210 :     Py_XDECREF(value);
    2479        1210 :     return NULL;
    2480             : }
    2481             : 
    2482             : static Py_ssize_t
    2483     1860810 : dict_length(PyDictObject *mp)
    2484             : {
    2485     1860810 :     return mp->ma_used;
    2486             : }
    2487             : 
    2488             : static PyObject *
    2489     5242500 : dict_subscript(PyDictObject *mp, PyObject *key)
    2490             : {
    2491             :     Py_ssize_t ix;
    2492             :     Py_hash_t hash;
    2493             :     PyObject *value;
    2494             : 
    2495     5242500 :     if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
    2496     1144190 :         hash = PyObject_Hash(key);
    2497     1144190 :         if (hash == -1)
    2498           3 :             return NULL;
    2499             :     }
    2500     5242490 :     ix = _Py_dict_lookup(mp, key, hash, &value);
    2501     5242490 :     if (ix == DKIX_ERROR)
    2502           1 :         return NULL;
    2503     5242490 :     if (ix == DKIX_EMPTY || value == NULL) {
    2504      596442 :         if (!PyDict_CheckExact(mp)) {
    2505             :             /* Look up __missing__ method if we're a subclass. */
    2506             :             PyObject *missing, *res;
    2507      317926 :             missing = _PyObject_LookupSpecial(
    2508             :                     (PyObject *)mp, &_Py_ID(__missing__));
    2509      317926 :             if (missing != NULL) {
    2510      269299 :                 res = PyObject_CallOneArg(missing, key);
    2511      269299 :                 Py_DECREF(missing);
    2512      269299 :                 return res;
    2513             :             }
    2514       48627 :             else if (PyErr_Occurred())
    2515           1 :                 return NULL;
    2516             :         }
    2517      327142 :         _PyErr_SetKeyError(key);
    2518      327142 :         return NULL;
    2519             :     }
    2520     4646050 :     Py_INCREF(value);
    2521     4646050 :     return value;
    2522             : }
    2523             : 
    2524             : static int
    2525     4987780 : dict_ass_sub(PyDictObject *mp, PyObject *v, PyObject *w)
    2526             : {
    2527     4987780 :     if (w == NULL)
    2528     2482090 :         return PyDict_DelItem((PyObject *)mp, v);
    2529             :     else
    2530     2505690 :         return PyDict_SetItem((PyObject *)mp, v, w);
    2531             : }
    2532             : 
    2533             : static PyMappingMethods dict_as_mapping = {
    2534             :     (lenfunc)dict_length, /*mp_length*/
    2535             :     (binaryfunc)dict_subscript, /*mp_subscript*/
    2536             :     (objobjargproc)dict_ass_sub, /*mp_ass_subscript*/
    2537             : };
    2538             : 
    2539             : static PyObject *
    2540      983729 : dict_keys(PyDictObject *mp)
    2541             : {
    2542             :     PyObject *v;
    2543             :     Py_ssize_t n;
    2544             : 
    2545      983729 :   again:
    2546      983729 :     n = mp->ma_used;
    2547      983729 :     v = PyList_New(n);
    2548      983729 :     if (v == NULL)
    2549           0 :         return NULL;
    2550      983729 :     if (n != mp->ma_used) {
    2551             :         /* Durnit.  The allocations caused the dict to resize.
    2552             :          * Just start over, this shouldn't normally happen.
    2553             :          */
    2554           0 :         Py_DECREF(v);
    2555           0 :         goto again;
    2556             :     }
    2557             : 
    2558             :     /* Nothing we do below makes any function calls. */
    2559      983729 :     Py_ssize_t j = 0, pos = 0;
    2560             :     PyObject *key;
    2561    10876300 :     while (_PyDict_Next((PyObject*)mp, &pos, &key, NULL, NULL)) {
    2562     9892600 :         assert(j < n);
    2563     9892600 :         Py_INCREF(key);
    2564     9892600 :         PyList_SET_ITEM(v, j, key);
    2565     9892600 :         j++;
    2566             :     }
    2567      983729 :     assert(j == n);
    2568      983729 :     return v;
    2569             : }
    2570             : 
    2571             : static PyObject *
    2572           7 : dict_values(PyDictObject *mp)
    2573             : {
    2574             :     PyObject *v;
    2575             :     Py_ssize_t n;
    2576             : 
    2577           7 :   again:
    2578           7 :     n = mp->ma_used;
    2579           7 :     v = PyList_New(n);
    2580           7 :     if (v == NULL)
    2581           0 :         return NULL;
    2582           7 :     if (n != mp->ma_used) {
    2583             :         /* Durnit.  The allocations caused the dict to resize.
    2584             :          * Just start over, this shouldn't normally happen.
    2585             :          */
    2586           0 :         Py_DECREF(v);
    2587           0 :         goto again;
    2588             :     }
    2589             : 
    2590             :     /* Nothing we do below makes any function calls. */
    2591           7 :     Py_ssize_t j = 0, pos = 0;
    2592             :     PyObject *value;
    2593         575 :     while (_PyDict_Next((PyObject*)mp, &pos, NULL, &value, NULL)) {
    2594         568 :         assert(j < n);
    2595         568 :         Py_INCREF(value);
    2596         568 :         PyList_SET_ITEM(v, j, value);
    2597         568 :         j++;
    2598             :     }
    2599           7 :     assert(j == n);
    2600           7 :     return v;
    2601             : }
    2602             : 
    2603             : static PyObject *
    2604        1397 : dict_items(PyDictObject *mp)
    2605             : {
    2606             :     PyObject *v;
    2607             :     Py_ssize_t i, n;
    2608             :     PyObject *item;
    2609             : 
    2610             :     /* Preallocate the list of tuples, to avoid allocations during
    2611             :      * the loop over the items, which could trigger GC, which
    2612             :      * could resize the dict. :-(
    2613             :      */
    2614        1397 :   again:
    2615        1397 :     n = mp->ma_used;
    2616        1397 :     v = PyList_New(n);
    2617        1397 :     if (v == NULL)
    2618           0 :         return NULL;
    2619       27390 :     for (i = 0; i < n; i++) {
    2620       25993 :         item = PyTuple_New(2);
    2621       25993 :         if (item == NULL) {
    2622           0 :             Py_DECREF(v);
    2623           0 :             return NULL;
    2624             :         }
    2625       25993 :         PyList_SET_ITEM(v, i, item);
    2626             :     }
    2627        1397 :     if (n != mp->ma_used) {
    2628             :         /* Durnit.  The allocations caused the dict to resize.
    2629             :          * Just start over, this shouldn't normally happen.
    2630             :          */
    2631           0 :         Py_DECREF(v);
    2632           0 :         goto again;
    2633             :     }
    2634             : 
    2635             :     /* Nothing we do below makes any function calls. */
    2636        1397 :     Py_ssize_t j = 0, pos = 0;
    2637             :     PyObject *key, *value;
    2638       27390 :     while (_PyDict_Next((PyObject*)mp, &pos, &key, &value, NULL)) {
    2639       25993 :         assert(j < n);
    2640       25993 :         PyObject *item = PyList_GET_ITEM(v, j);
    2641       25993 :         Py_INCREF(key);
    2642       25993 :         PyTuple_SET_ITEM(item, 0, key);
    2643       25993 :         Py_INCREF(value);
    2644       25993 :         PyTuple_SET_ITEM(item, 1, value);
    2645       25993 :         j++;
    2646             :     }
    2647        1397 :     assert(j == n);
    2648        1397 :     return v;
    2649             : }
    2650             : 
    2651             : /*[clinic input]
    2652             : @classmethod
    2653             : dict.fromkeys
    2654             :     iterable: object
    2655             :     value: object=None
    2656             :     /
    2657             : 
    2658             : Create a new dictionary with keys from iterable and values set to value.
    2659             : [clinic start generated code]*/
    2660             : 
    2661             : static PyObject *
    2662      107821 : dict_fromkeys_impl(PyTypeObject *type, PyObject *iterable, PyObject *value)
    2663             : /*[clinic end generated code: output=8fb98e4b10384999 input=382ba4855d0f74c3]*/
    2664             : {
    2665      107821 :     return _PyDict_FromKeys((PyObject *)type, iterable, value);
    2666             : }
    2667             : 
    2668             : /* Single-arg dict update; used by dict_update_common and operators. */
    2669             : static int
    2670     5555080 : dict_update_arg(PyObject *self, PyObject *arg)
    2671             : {
    2672     5555080 :     if (PyDict_CheckExact(arg)) {
    2673     5437150 :         return PyDict_Merge(self, arg, 1);
    2674             :     }
    2675             :     PyObject *func;
    2676      117930 :     if (_PyObject_LookupAttr(arg, &_Py_ID(keys), &func) < 0) {
    2677           0 :         return -1;
    2678             :     }
    2679      117930 :     if (func != NULL) {
    2680       43455 :         Py_DECREF(func);
    2681       43455 :         return PyDict_Merge(self, arg, 1);
    2682             :     }
    2683       74475 :     return PyDict_MergeFromSeq2(self, arg, 1);
    2684             : }
    2685             : 
    2686             : static int
    2687     5518840 : dict_update_common(PyObject *self, PyObject *args, PyObject *kwds,
    2688             :                    const char *methname)
    2689             : {
    2690     5518840 :     PyObject *arg = NULL;
    2691     5518840 :     int result = 0;
    2692             : 
    2693     5518840 :     if (!PyArg_UnpackTuple(args, methname, 0, 1, &arg)) {
    2694           3 :         result = -1;
    2695             :     }
    2696     5518830 :     else if (arg != NULL) {
    2697     5427850 :         result = dict_update_arg(self, arg);
    2698             :     }
    2699             : 
    2700     5518840 :     if (result == 0 && kwds != NULL) {
    2701        3945 :         if (PyArg_ValidateKeywordArguments(kwds))
    2702        3943 :             result = PyDict_Merge(self, kwds, 1);
    2703             :         else
    2704           2 :             result = -1;
    2705             :     }
    2706     5518840 :     return result;
    2707             : }
    2708             : 
    2709             : /* Note: dict.update() uses the METH_VARARGS|METH_KEYWORDS calling convention.
    2710             :    Using METH_FASTCALL|METH_KEYWORDS would make dict.update(**dict2) calls
    2711             :    slower, see the issue #29312. */
    2712             : static PyObject *
    2713     5430510 : dict_update(PyObject *self, PyObject *args, PyObject *kwds)
    2714             : {
    2715     5430510 :     if (dict_update_common(self, args, kwds, "update") != -1)
    2716     5430480 :         Py_RETURN_NONE;
    2717          27 :     return NULL;
    2718             : }
    2719             : 
    2720             : /* Update unconditionally replaces existing items.
    2721             :    Merge has a 3rd argument 'override'; if set, it acts like Update,
    2722             :    otherwise it leaves existing items unchanged.
    2723             : 
    2724             :    PyDict_{Update,Merge} update/merge from a mapping object.
    2725             : 
    2726             :    PyDict_MergeFromSeq2 updates/merges from any iterable object
    2727             :    producing iterable objects of length 2.
    2728             : */
    2729             : 
    2730             : int
    2731       74475 : PyDict_MergeFromSeq2(PyObject *d, PyObject *seq2, int override)
    2732             : {
    2733             :     PyObject *it;       /* iter(seq2) */
    2734             :     Py_ssize_t i;       /* index into seq2 of current element */
    2735             :     PyObject *item;     /* seq2[i] */
    2736             :     PyObject *fast;     /* item as a 2-tuple or 2-list */
    2737             : 
    2738       74475 :     assert(d != NULL);
    2739       74475 :     assert(PyDict_Check(d));
    2740       74475 :     assert(seq2 != NULL);
    2741             : 
    2742       74475 :     it = PyObject_GetIter(seq2);
    2743       74475 :     if (it == NULL)
    2744          15 :         return -1;
    2745             : 
    2746      853465 :     for (i = 0; ; ++i) {
    2747             :         PyObject *key, *value;
    2748             :         Py_ssize_t n;
    2749             : 
    2750      853465 :         fast = NULL;
    2751      853465 :         item = PyIter_Next(it);
    2752      853465 :         if (item == NULL) {
    2753       74449 :             if (PyErr_Occurred())
    2754           6 :                 goto Fail;
    2755       74443 :             break;
    2756             :         }
    2757             : 
    2758             :         /* Convert item to sequence, and verify length 2. */
    2759      779016 :         fast = PySequence_Fast(item, "");
    2760      779016 :         if (fast == NULL) {
    2761           2 :             if (PyErr_ExceptionMatches(PyExc_TypeError))
    2762           2 :                 PyErr_Format(PyExc_TypeError,
    2763             :                     "cannot convert dictionary update "
    2764             :                     "sequence element #%zd to a sequence",
    2765             :                     i);
    2766           2 :             goto Fail;
    2767             :         }
    2768      779014 :         n = PySequence_Fast_GET_SIZE(fast);
    2769      779014 :         if (n != 2) {
    2770           9 :             PyErr_Format(PyExc_ValueError,
    2771             :                          "dictionary update sequence element #%zd "
    2772             :                          "has length %zd; 2 is required",
    2773             :                          i, n);
    2774           9 :             goto Fail;
    2775             :         }
    2776             : 
    2777             :         /* Update/merge with this (key, value) pair. */
    2778      779005 :         key = PySequence_Fast_GET_ITEM(fast, 0);
    2779      779005 :         value = PySequence_Fast_GET_ITEM(fast, 1);
    2780      779005 :         Py_INCREF(key);
    2781      779005 :         Py_INCREF(value);
    2782      779005 :         if (override) {
    2783      779005 :             if (PyDict_SetItem(d, key, value) < 0) {
    2784           0 :                 Py_DECREF(key);
    2785           0 :                 Py_DECREF(value);
    2786           0 :                 goto Fail;
    2787             :             }
    2788             :         }
    2789             :         else {
    2790           0 :             if (PyDict_SetDefault(d, key, value) == NULL) {
    2791           0 :                 Py_DECREF(key);
    2792           0 :                 Py_DECREF(value);
    2793           0 :                 goto Fail;
    2794             :             }
    2795             :         }
    2796             : 
    2797      779005 :         Py_DECREF(key);
    2798      779005 :         Py_DECREF(value);
    2799      779005 :         Py_DECREF(fast);
    2800      779005 :         Py_DECREF(item);
    2801             :     }
    2802             : 
    2803       74443 :     i = 0;
    2804       74443 :     ASSERT_CONSISTENT(d);
    2805       74443 :     goto Return;
    2806          17 : Fail:
    2807          17 :     Py_XDECREF(item);
    2808          17 :     Py_XDECREF(fast);
    2809          17 :     i = -1;
    2810       74460 : Return:
    2811       74460 :     Py_DECREF(it);
    2812       74460 :     return Py_SAFE_DOWNCAST(i, Py_ssize_t, int);
    2813             : }
    2814             : 
    2815             : static int
    2816     9241220 : dict_merge(PyObject *a, PyObject *b, int override)
    2817             : {
    2818             :     PyDictObject *mp, *other;
    2819             : 
    2820     9241220 :     assert(0 <= override && override <= 2);
    2821             : 
    2822             :     /* We accept for the argument either a concrete dictionary object,
    2823             :      * or an abstract "mapping" object.  For the former, we can do
    2824             :      * things quite efficiently.  For the latter, we only require that
    2825             :      * PyMapping_Keys() and PyObject_GetItem() be supported.
    2826             :      */
    2827     9241220 :     if (a == NULL || !PyDict_Check(a) || b == NULL) {
    2828           0 :         PyErr_BadInternalCall();
    2829           0 :         return -1;
    2830             :     }
    2831     9241220 :     mp = (PyDictObject*)a;
    2832     9626210 :     if (PyDict_Check(b) && (Py_TYPE(b)->tp_iter == (getiterfunc)dict_iter)) {
    2833     9140630 :         other = (PyDictObject*)b;
    2834     9140630 :         if (other == mp || other->ma_used == 0)
    2835             :             /* a.update(a) or a.update({}); nothing to do */
    2836     8755640 :             return 0;
    2837     1126890 :         if (mp->ma_used == 0) {
    2838             :             /* Since the target dict is empty, PyDict_GetItem()
    2839             :              * always returns NULL.  Setting override to 1
    2840             :              * skips the unnecessary test.
    2841             :              */
    2842      805337 :             override = 1;
    2843      805337 :             PyDictKeysObject *okeys = other->ma_keys;
    2844             : 
    2845             :             // If other is clean, combined, and just allocated, just clone it.
    2846      805337 :             if (other->ma_values == NULL &&
    2847      799424 :                     other->ma_used == okeys->dk_nentries &&
    2848      754378 :                     (DK_LOG_SIZE(okeys) == PyDict_LOG_MINSIZE ||
    2849       35960 :                      USABLE_FRACTION(DK_SIZE(okeys)/2) < other->ma_used)) {
    2850      741884 :                 PyDictKeysObject *keys = clone_combined_dict_keys(other);
    2851      741884 :                 if (keys == NULL) {
    2852           2 :                     return -1;
    2853             :                 }
    2854             : 
    2855      741882 :                 dictkeys_decref(mp->ma_keys);
    2856      741882 :                 mp->ma_keys = keys;
    2857      741882 :                 if (mp->ma_values != NULL) {
    2858       45682 :                     free_values(mp->ma_values);
    2859       45682 :                     mp->ma_values = NULL;
    2860             :                 }
    2861             : 
    2862      741882 :                 mp->ma_used = other->ma_used;
    2863      741882 :                 mp->ma_version_tag = DICT_NEXT_VERSION();
    2864      741882 :                 ASSERT_CONSISTENT(mp);
    2865             : 
    2866      741882 :                 if (_PyObject_GC_IS_TRACKED(other) && !_PyObject_GC_IS_TRACKED(mp)) {
    2867             :                     /* Maintain tracking. */
    2868      160362 :                     _PyObject_GC_TRACK(mp);
    2869             :                 }
    2870             : 
    2871      741882 :                 return 0;
    2872             :             }
    2873             :         }
    2874             :         /* Do one big resize at the start, rather than
    2875             :          * incrementally resizing as we insert new items.  Expect
    2876             :          * that there will be no (or few) overlapping keys.
    2877             :          */
    2878      385003 :         if (USABLE_FRACTION(DK_SIZE(mp->ma_keys)) < other->ma_used) {
    2879       93342 :             int unicode = DK_IS_UNICODE(other->ma_keys);
    2880       93342 :             if (dictresize(mp, estimate_log2_keysize(mp->ma_used + other->ma_used), unicode)) {
    2881           0 :                return -1;
    2882             :             }
    2883             :         }
    2884             : 
    2885      385003 :         Py_ssize_t orig_size = other->ma_keys->dk_nentries;
    2886      385003 :         Py_ssize_t pos = 0;
    2887             :         Py_hash_t hash;
    2888             :         PyObject *key, *value;
    2889             : 
    2890     6442520 :         while (_PyDict_Next((PyObject*)other, &pos, &key, &value, &hash)) {
    2891     6057530 :             int err = 0;
    2892     6057530 :             Py_INCREF(key);
    2893     6057530 :             Py_INCREF(value);
    2894     6057530 :             if (override == 1) {
    2895     6019710 :                 Py_INCREF(key);
    2896     6019710 :                 Py_INCREF(value);
    2897     6019710 :                 err = insertdict(mp, key, hash, value);
    2898             :             }
    2899             :             else {
    2900       37821 :                 err = _PyDict_Contains_KnownHash(a, key, hash);
    2901       37821 :                 if (err == 0) {
    2902       37811 :                     Py_INCREF(key);
    2903       37811 :                     Py_INCREF(value);
    2904       37811 :                     err = insertdict(mp, key, hash, value);
    2905             :                 }
    2906          10 :                 else if (err > 0) {
    2907          10 :                     if (override != 0) {
    2908          10 :                         _PyErr_SetKeyError(key);
    2909          10 :                         Py_DECREF(value);
    2910          10 :                         Py_DECREF(key);
    2911          10 :                         return -1;
    2912             :                     }
    2913           0 :                     err = 0;
    2914             :                 }
    2915             :             }
    2916     6057520 :             Py_DECREF(value);
    2917     6057520 :             Py_DECREF(key);
    2918     6057520 :             if (err != 0)
    2919           1 :                 return -1;
    2920             : 
    2921     6057520 :             if (orig_size != other->ma_keys->dk_nentries) {
    2922           1 :                 PyErr_SetString(PyExc_RuntimeError,
    2923             :                         "dict mutated during update");
    2924           1 :                 return -1;
    2925             :             }
    2926             :         }
    2927             :     }
    2928             :     else {
    2929             :         /* Do it the generic, slower way */
    2930      100587 :         PyObject *keys = PyMapping_Keys(b);
    2931             :         PyObject *iter;
    2932             :         PyObject *key, *value;
    2933             :         int status;
    2934             : 
    2935      100587 :         if (keys == NULL)
    2936             :             /* Docstring says this is equivalent to E.keys() so
    2937             :              * if E doesn't have a .keys() method we want
    2938             :              * AttributeError to percolate up.  Might as well
    2939             :              * do the same for any other error.
    2940             :              */
    2941          23 :             return -1;
    2942             : 
    2943      100564 :         iter = PyObject_GetIter(keys);
    2944      100564 :         Py_DECREF(keys);
    2945      100564 :         if (iter == NULL)
    2946           0 :             return -1;
    2947             : 
    2948     2524540 :         for (key = PyIter_Next(iter); key; key = PyIter_Next(iter)) {
    2949     2423980 :             if (override != 1) {
    2950         149 :                 status = PyDict_Contains(a, key);
    2951         149 :                 if (status != 0) {
    2952           3 :                     if (status > 0) {
    2953           3 :                         if (override == 0) {
    2954           0 :                             Py_DECREF(key);
    2955           0 :                             continue;
    2956             :                         }
    2957           3 :                         _PyErr_SetKeyError(key);
    2958             :                     }
    2959           3 :                     Py_DECREF(key);
    2960           3 :                     Py_DECREF(iter);
    2961           3 :                     return -1;
    2962             :                 }
    2963             :             }
    2964     2423980 :             value = PyObject_GetItem(b, key);
    2965     2423980 :             if (value == NULL) {
    2966           5 :                 Py_DECREF(iter);
    2967           5 :                 Py_DECREF(key);
    2968           5 :                 return -1;
    2969             :             }
    2970     2423980 :             status = PyDict_SetItem(a, key, value);
    2971     2423980 :             Py_DECREF(key);
    2972     2423980 :             Py_DECREF(value);
    2973     2423980 :             if (status < 0) {
    2974           0 :                 Py_DECREF(iter);
    2975           0 :                 return -1;
    2976             :             }
    2977             :         }
    2978      100556 :         Py_DECREF(iter);
    2979      100556 :         if (PyErr_Occurred())
    2980             :             /* Iterator completed, via error */
    2981           0 :             return -1;
    2982             :     }
    2983      485547 :     ASSERT_CONSISTENT(a);
    2984      485547 :     return 0;
    2985             : }
    2986             : 
    2987             : int
    2988      342067 : PyDict_Update(PyObject *a, PyObject *b)
    2989             : {
    2990      342067 :     return dict_merge(a, b, 1);
    2991             : }
    2992             : 
    2993             : int
    2994     5484880 : PyDict_Merge(PyObject *a, PyObject *b, int override)
    2995             : {
    2996             :     /* XXX Deprecate override not in (0, 1). */
    2997     5484880 :     return dict_merge(a, b, override != 0);
    2998             : }
    2999             : 
    3000             : int
    3001     3412470 : _PyDict_MergeEx(PyObject *a, PyObject *b, int override)
    3002             : {
    3003     3412470 :     return dict_merge(a, b, override);
    3004             : }
    3005             : 
    3006             : static PyObject *
    3007       80177 : dict_copy(PyDictObject *mp, PyObject *Py_UNUSED(ignored))
    3008             : {
    3009       80177 :     return PyDict_Copy((PyObject*)mp);
    3010             : }
    3011             : 
    3012             : PyObject *
    3013     2617740 : PyDict_Copy(PyObject *o)
    3014             : {
    3015             :     PyObject *copy;
    3016             :     PyDictObject *mp;
    3017             :     Py_ssize_t i, n;
    3018             : 
    3019     2617740 :     if (o == NULL || !PyDict_Check(o)) {
    3020           0 :         PyErr_BadInternalCall();
    3021           0 :         return NULL;
    3022             :     }
    3023             : 
    3024     2617740 :     mp = (PyDictObject *)o;
    3025     2617740 :     if (mp->ma_used == 0) {
    3026             :         /* The dict is empty; just return a new dict. */
    3027       28369 :         return PyDict_New();
    3028             :     }
    3029             : 
    3030     2589370 :     if (_PyDict_HasSplitTable(mp)) {
    3031             :         PyDictObject *split_copy;
    3032        2288 :         Py_ssize_t size = shared_keys_usable_size(mp->ma_keys);
    3033             :         PyDictValues *newvalues;
    3034        2288 :         newvalues = new_values(size);
    3035        2288 :         if (newvalues == NULL)
    3036           0 :             return PyErr_NoMemory();
    3037        2288 :         split_copy = PyObject_GC_New(PyDictObject, &PyDict_Type);
    3038        2288 :         if (split_copy == NULL) {
    3039           0 :             free_values(newvalues);
    3040           0 :             return NULL;
    3041             :         }
    3042        2288 :         size_t prefix_size = ((uint8_t *)newvalues)[-1];
    3043        2288 :         memcpy(((char *)newvalues)-prefix_size, ((char *)mp->ma_values)-prefix_size, prefix_size-1);
    3044        2288 :         split_copy->ma_values = newvalues;
    3045        2288 :         split_copy->ma_keys = mp->ma_keys;
    3046        2288 :         split_copy->ma_used = mp->ma_used;
    3047        2288 :         split_copy->ma_version_tag = DICT_NEXT_VERSION();
    3048        2288 :         dictkeys_incref(mp->ma_keys);
    3049       61208 :         for (i = 0, n = size; i < n; i++) {
    3050       58920 :             PyObject *value = mp->ma_values->values[i];
    3051       58920 :             Py_XINCREF(value);
    3052       58920 :             split_copy->ma_values->values[i] = value;
    3053             :         }
    3054        2288 :         if (_PyObject_GC_IS_TRACKED(mp))
    3055        2006 :             _PyObject_GC_TRACK(split_copy);
    3056        2288 :         return (PyObject *)split_copy;
    3057             :     }
    3058             : 
    3059     2587080 :     if (Py_TYPE(mp)->tp_iter == (getiterfunc)dict_iter &&
    3060     2587080 :             mp->ma_values == NULL &&
    3061     2587080 :             (mp->ma_used >= (mp->ma_keys->dk_nentries * 2) / 3))
    3062             :     {
    3063             :         /* Use fast-copy if:
    3064             : 
    3065             :            (1) type(mp) doesn't override tp_iter; and
    3066             : 
    3067             :            (2) 'mp' is not a split-dict; and
    3068             : 
    3069             :            (3) if 'mp' is non-compact ('del' operation does not resize dicts),
    3070             :                do fast-copy only if it has at most 1/3 non-used keys.
    3071             : 
    3072             :            The last condition (3) is important to guard against a pathological
    3073             :            case when a large dict is almost emptied with multiple del/pop
    3074             :            operations and copied after that.  In cases like this, we defer to
    3075             :            PyDict_Merge, which produces a compacted copy.
    3076             :         */
    3077     2585290 :         PyDictKeysObject *keys = clone_combined_dict_keys(mp);
    3078     2585290 :         if (keys == NULL) {
    3079           2 :             return NULL;
    3080             :         }
    3081     2585290 :         PyDictObject *new = (PyDictObject *)new_dict(keys, NULL, 0, 0);
    3082     2585290 :         if (new == NULL) {
    3083             :             /* In case of an error, `new_dict()` takes care of
    3084             :                cleaning up `keys`. */
    3085           0 :             return NULL;
    3086             :         }
    3087             : 
    3088     2585290 :         new->ma_used = mp->ma_used;
    3089     2585290 :         ASSERT_CONSISTENT(new);
    3090     2585290 :         if (_PyObject_GC_IS_TRACKED(mp)) {
    3091             :             /* Maintain tracking. */
    3092     2168460 :             _PyObject_GC_TRACK(new);
    3093             :         }
    3094             : 
    3095     2585290 :         return (PyObject *)new;
    3096             :     }
    3097             : 
    3098        1794 :     copy = PyDict_New();
    3099        1794 :     if (copy == NULL)
    3100           0 :         return NULL;
    3101        1794 :     if (dict_merge(copy, o, 1) == 0)
    3102        1794 :         return copy;
    3103           0 :     Py_DECREF(copy);
    3104           0 :     return NULL;
    3105             : }
    3106             : 
    3107             : Py_ssize_t
    3108     2039390 : PyDict_Size(PyObject *mp)
    3109             : {
    3110     2039390 :     if (mp == NULL || !PyDict_Check(mp)) {
    3111           0 :         PyErr_BadInternalCall();
    3112           0 :         return -1;
    3113             :     }
    3114     2039390 :     return ((PyDictObject *)mp)->ma_used;
    3115             : }
    3116             : 
    3117             : PyObject *
    3118      983729 : PyDict_Keys(PyObject *mp)
    3119             : {
    3120      983729 :     if (mp == NULL || !PyDict_Check(mp)) {
    3121           0 :         PyErr_BadInternalCall();
    3122           0 :         return NULL;
    3123             :     }
    3124      983729 :     return dict_keys((PyDictObject *)mp);
    3125             : }
    3126             : 
    3127             : PyObject *
    3128           7 : PyDict_Values(PyObject *mp)
    3129             : {
    3130           7 :     if (mp == NULL || !PyDict_Check(mp)) {
    3131           0 :         PyErr_BadInternalCall();
    3132           0 :         return NULL;
    3133             :     }
    3134           7 :     return dict_values((PyDictObject *)mp);
    3135             : }
    3136             : 
    3137             : PyObject *
    3138        1397 : PyDict_Items(PyObject *mp)
    3139             : {
    3140        1397 :     if (mp == NULL || !PyDict_Check(mp)) {
    3141           0 :         PyErr_BadInternalCall();
    3142           0 :         return NULL;
    3143             :     }
    3144        1397 :     return dict_items((PyDictObject *)mp);
    3145             : }
    3146             : 
    3147             : /* Return 1 if dicts equal, 0 if not, -1 if error.
    3148             :  * Gets out as soon as any difference is detected.
    3149             :  * Uses only Py_EQ comparison.
    3150             :  */
    3151             : static int
    3152      122118 : dict_equal(PyDictObject *a, PyDictObject *b)
    3153             : {
    3154             :     Py_ssize_t i;
    3155             : 
    3156      122118 :     if (a->ma_used != b->ma_used)
    3157             :         /* can't be equal if # of entries differ */
    3158       16593 :         return 0;
    3159             :     /* Same # of entries -- check all of 'em.  Exit early on any diff. */
    3160     1603030 :     for (i = 0; i < a->ma_keys->dk_nentries; i++) {
    3161             :         PyObject *key, *aval;
    3162             :         Py_hash_t hash;
    3163     1505050 :         if (DK_IS_UNICODE(a->ma_keys)) {
    3164     1270730 :             PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(a->ma_keys)[i];
    3165     1270730 :             key = ep->me_key;
    3166     1270730 :             if (key == NULL) {
    3167         398 :                 continue;
    3168             :             }
    3169     1270330 :             hash = unicode_get_hash(key);
    3170     1270330 :             if (a->ma_values)
    3171        2972 :                 aval = a->ma_values->values[i];
    3172             :             else
    3173     1267360 :                 aval = ep->me_value;
    3174             :         }
    3175             :         else {
    3176      234324 :             PyDictKeyEntry *ep = &DK_ENTRIES(a->ma_keys)[i];
    3177      234324 :             key = ep->me_key;
    3178      234324 :             aval = ep->me_value;
    3179      234324 :             hash = ep->me_hash;
    3180             :         }
    3181     1504660 :         if (aval != NULL) {
    3182             :             int cmp;
    3183             :             PyObject *bval;
    3184             :             /* temporarily bump aval's refcount to ensure it stays
    3185             :                alive until we're done with it */
    3186     1504160 :             Py_INCREF(aval);
    3187             :             /* ditto for key */
    3188     1504160 :             Py_INCREF(key);
    3189             :             /* reuse the known hash value */
    3190     1504160 :             _Py_dict_lookup(b, key, hash, &bval);
    3191     1504160 :             if (bval == NULL) {
    3192        5551 :                 Py_DECREF(key);
    3193        5551 :                 Py_DECREF(aval);
    3194        5551 :                 if (PyErr_Occurred())
    3195        7545 :                     return -1;
    3196        5549 :                 return 0;
    3197             :             }
    3198     1498610 :             Py_INCREF(bval);
    3199     1498610 :             cmp = PyObject_RichCompareBool(aval, bval, Py_EQ);
    3200     1498610 :             Py_DECREF(key);
    3201     1498610 :             Py_DECREF(aval);
    3202     1498610 :             Py_DECREF(bval);
    3203     1498610 :             if (cmp <= 0)  /* error or not equal */
    3204        1994 :                 return cmp;
    3205             :         }
    3206             :     }
    3207       97980 :     return 1;
    3208             : }
    3209             : 
    3210             : static PyObject *
    3211      122481 : dict_richcompare(PyObject *v, PyObject *w, int op)
    3212             : {
    3213             :     int cmp;
    3214             :     PyObject *res;
    3215             : 
    3216      122481 :     if (!PyDict_Check(v) || !PyDict_Check(w)) {
    3217         331 :         res = Py_NotImplemented;
    3218             :     }
    3219      122150 :     else if (op == Py_EQ || op == Py_NE) {
    3220      122118 :         cmp = dict_equal((PyDictObject *)v, (PyDictObject *)w);
    3221      122118 :         if (cmp < 0)
    3222        1934 :             return NULL;
    3223      120184 :         res = (cmp == (op == Py_EQ)) ? Py_True : Py_False;
    3224             :     }
    3225             :     else
    3226          32 :         res = Py_NotImplemented;
    3227      120547 :     Py_INCREF(res);
    3228      120547 :     return res;
    3229             : }
    3230             : 
    3231             : /*[clinic input]
    3232             : 
    3233             : @coexist
    3234             : dict.__contains__
    3235             : 
    3236             :   key: object
    3237             :   /
    3238             : 
    3239             : True if the dictionary has the specified key, else False.
    3240             : [clinic start generated code]*/
    3241             : 
    3242             : static PyObject *
    3243      175896 : dict___contains__(PyDictObject *self, PyObject *key)
    3244             : /*[clinic end generated code: output=a3d03db709ed6e6b input=fe1cb42ad831e820]*/
    3245             : {
    3246      175896 :     register PyDictObject *mp = self;
    3247             :     Py_hash_t hash;
    3248             :     Py_ssize_t ix;
    3249             :     PyObject *value;
    3250             : 
    3251      175896 :     if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
    3252        3269 :         hash = PyObject_Hash(key);
    3253        3269 :         if (hash == -1)
    3254           0 :             return NULL;
    3255             :     }
    3256      175896 :     ix = _Py_dict_lookup(mp, key, hash, &value);
    3257      175896 :     if (ix == DKIX_ERROR)
    3258           1 :         return NULL;
    3259      175895 :     if (ix == DKIX_EMPTY || value == NULL)
    3260       70840 :         Py_RETURN_FALSE;
    3261      105055 :     Py_RETURN_TRUE;
    3262             : }
    3263             : 
    3264             : /*[clinic input]
    3265             : dict.get
    3266             : 
    3267             :     key: object
    3268             :     default: object = None
    3269             :     /
    3270             : 
    3271             : Return the value for key if key is in the dictionary, else default.
    3272             : [clinic start generated code]*/
    3273             : 
    3274             : static PyObject *
    3275    18825700 : dict_get_impl(PyDictObject *self, PyObject *key, PyObject *default_value)
    3276             : /*[clinic end generated code: output=bba707729dee05bf input=279ddb5790b6b107]*/
    3277             : {
    3278    18825700 :     PyObject *val = NULL;
    3279             :     Py_hash_t hash;
    3280             :     Py_ssize_t ix;
    3281             : 
    3282    18825700 :     if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
    3283    12016000 :         hash = PyObject_Hash(key);
    3284    12016000 :         if (hash == -1)
    3285           3 :             return NULL;
    3286             :     }
    3287    18825700 :     ix = _Py_dict_lookup(self, key, hash, &val);
    3288    18825700 :     if (ix == DKIX_ERROR)
    3289           1 :         return NULL;
    3290    18825700 :     if (ix == DKIX_EMPTY || val == NULL) {
    3291     9524350 :         val = default_value;
    3292             :     }
    3293    18825700 :     Py_INCREF(val);
    3294    18825700 :     return val;
    3295             : }
    3296             : 
    3297             : PyObject *
    3298   112826000 : PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
    3299             : {
    3300   112826000 :     PyDictObject *mp = (PyDictObject *)d;
    3301             :     PyObject *value;
    3302             :     Py_hash_t hash;
    3303             : 
    3304   112826000 :     if (!PyDict_Check(d)) {
    3305           0 :         PyErr_BadInternalCall();
    3306           0 :         return NULL;
    3307             :     }
    3308             : 
    3309   112826000 :     if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
    3310    98811600 :         hash = PyObject_Hash(key);
    3311    98811600 :         if (hash == -1)
    3312           5 :             return NULL;
    3313             :     }
    3314             : 
    3315   112826000 :     if (mp->ma_keys == Py_EMPTY_KEYS) {
    3316      190575 :         Py_INCREF(key);
    3317      190575 :         Py_INCREF(defaultobj);
    3318      190575 :         if (insert_to_emptydict(mp, key, hash, defaultobj) < 0) {
    3319           0 :             return NULL;
    3320             :         }
    3321      190575 :         return defaultobj;
    3322             :     }
    3323             : 
    3324   112635000 :     if (!PyUnicode_CheckExact(key) && DK_IS_UNICODE(mp->ma_keys)) {
    3325       52337 :         if (insertion_resize(mp, 0) < 0) {
    3326           0 :             return NULL;
    3327             :         }
    3328             :     }
    3329             : 
    3330   112635000 :     Py_ssize_t ix = _Py_dict_lookup(mp, key, hash, &value);
    3331   112635000 :     if (ix == DKIX_ERROR)
    3332           1 :         return NULL;
    3333             : 
    3334   112635000 :     if (ix == DKIX_EMPTY) {
    3335    34394900 :         mp->ma_keys->dk_version = 0;
    3336    34394900 :         value = defaultobj;
    3337    34394900 :         if (mp->ma_keys->dk_usable <= 0) {
    3338      829211 :             if (insertion_resize(mp, 1) < 0) {
    3339           0 :                 return NULL;
    3340             :             }
    3341             :         }
    3342    34394900 :         Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash);
    3343    34394900 :         dictkeys_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
    3344    34394900 :         if (DK_IS_UNICODE(mp->ma_keys)) {
    3345    29983800 :             assert(PyUnicode_CheckExact(key));
    3346    29983800 :             PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(mp->ma_keys)[mp->ma_keys->dk_nentries];
    3347    29983800 :             ep->me_key = key;
    3348    29983800 :             if (_PyDict_HasSplitTable(mp)) {
    3349          85 :                 Py_ssize_t index = (int)mp->ma_keys->dk_nentries;
    3350          85 :                 assert(index < SHARED_KEYS_MAX_SIZE);
    3351          85 :                 assert(mp->ma_values->values[index] == NULL);
    3352          85 :                 mp->ma_values->values[index] = value;
    3353          85 :                 _PyDictValues_AddToInsertionOrder(mp->ma_values, index);
    3354             :             }
    3355             :             else {
    3356    29983700 :                 ep->me_value = value;
    3357             :             }
    3358             :         }
    3359             :         else {
    3360     4411080 :             PyDictKeyEntry *ep = &DK_ENTRIES(mp->ma_keys)[mp->ma_keys->dk_nentries];
    3361     4411080 :             ep->me_key = key;
    3362     4411080 :             ep->me_hash = hash;
    3363     4411080 :             ep->me_value = value;
    3364             :         }
    3365    34394900 :         Py_INCREF(key);
    3366    34394900 :         Py_INCREF(value);
    3367    34394900 :         MAINTAIN_TRACKING(mp, key, value);
    3368    34394900 :         mp->ma_used++;
    3369    34394900 :         mp->ma_version_tag = DICT_NEXT_VERSION();
    3370    34394900 :         mp->ma_keys->dk_usable--;
    3371    34394900 :         mp->ma_keys->dk_nentries++;
    3372    34394900 :         assert(mp->ma_keys->dk_usable >= 0);
    3373             :     }
    3374    78240000 :     else if (value == NULL) {
    3375          18 :         value = defaultobj;
    3376          18 :         assert(_PyDict_HasSplitTable(mp));
    3377          18 :         assert(mp->ma_values->values[ix] == NULL);
    3378          18 :         Py_INCREF(value);
    3379          18 :         MAINTAIN_TRACKING(mp, key, value);
    3380          18 :         mp->ma_values->values[ix] = value;
    3381          18 :         _PyDictValues_AddToInsertionOrder(mp->ma_values, ix);
    3382          18 :         mp->ma_used++;
    3383          18 :         mp->ma_version_tag = DICT_NEXT_VERSION();
    3384             :     }
    3385             : 
    3386   112635000 :     ASSERT_CONSISTENT(mp);
    3387   112635000 :     return value;
    3388             : }
    3389             : 
    3390             : /*[clinic input]
    3391             : dict.setdefault
    3392             : 
    3393             :     key: object
    3394             :     default: object = None
    3395             :     /
    3396             : 
    3397             : Insert key with a value of default if key is not in the dictionary.
    3398             : 
    3399             : Return the value for key if key is in the dictionary, else default.
    3400             : [clinic start generated code]*/
    3401             : 
    3402             : static PyObject *
    3403      419018 : dict_setdefault_impl(PyDictObject *self, PyObject *key,
    3404             :                      PyObject *default_value)
    3405             : /*[clinic end generated code: output=f8c1101ebf69e220 input=0f063756e815fd9d]*/
    3406             : {
    3407             :     PyObject *val;
    3408             : 
    3409      419018 :     val = PyDict_SetDefault((PyObject *)self, key, default_value);
    3410      419018 :     Py_XINCREF(val);
    3411      419018 :     return val;
    3412             : }
    3413             : 
    3414             : static PyObject *
    3415      130957 : dict_clear(PyDictObject *mp, PyObject *Py_UNUSED(ignored))
    3416             : {
    3417      130957 :     PyDict_Clear((PyObject *)mp);
    3418      130957 :     Py_RETURN_NONE;
    3419             : }
    3420             : 
    3421             : /*[clinic input]
    3422             : dict.pop
    3423             : 
    3424             :     key: object
    3425             :     default: object = NULL
    3426             :     /
    3427             : 
    3428             : D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
    3429             : 
    3430             : If the key is not found, return the default if given; otherwise,
    3431             : raise a KeyError.
    3432             : [clinic start generated code]*/
    3433             : 
    3434             : static PyObject *
    3435      772820 : dict_pop_impl(PyDictObject *self, PyObject *key, PyObject *default_value)
    3436             : /*[clinic end generated code: output=3abb47b89f24c21c input=e221baa01044c44c]*/
    3437             : {
    3438      772820 :     return _PyDict_Pop((PyObject*)self, key, default_value);
    3439             : }
    3440             : 
    3441             : /*[clinic input]
    3442             : dict.popitem
    3443             : 
    3444             : Remove and return a (key, value) pair as a 2-tuple.
    3445             : 
    3446             : Pairs are returned in LIFO (last-in, first-out) order.
    3447             : Raises KeyError if the dict is empty.
    3448             : [clinic start generated code]*/
    3449             : 
    3450             : static PyObject *
    3451       19389 : dict_popitem_impl(PyDictObject *self)
    3452             : /*[clinic end generated code: output=e65fcb04420d230d input=1c38a49f21f64941]*/
    3453             : {
    3454             :     Py_ssize_t i, j;
    3455             :     PyObject *res;
    3456             : 
    3457             :     /* Allocate the result tuple before checking the size.  Believe it
    3458             :      * or not, this allocation could trigger a garbage collection which
    3459             :      * could empty the dict, so if we checked the size first and that
    3460             :      * happened, the result would be an infinite loop (searching for an
    3461             :      * entry that no longer exists).  Note that the usual popitem()
    3462             :      * idiom is "while d: k, v = d.popitem()". so needing to throw the
    3463             :      * tuple away if the dict *is* empty isn't a significant
    3464             :      * inefficiency -- possible, but unlikely in practice.
    3465             :      */
    3466       19389 :     res = PyTuple_New(2);
    3467       19389 :     if (res == NULL)
    3468           0 :         return NULL;
    3469       19389 :     if (self->ma_used == 0) {
    3470        1391 :         Py_DECREF(res);
    3471        1391 :         PyErr_SetString(PyExc_KeyError, "popitem(): dictionary is empty");
    3472        1391 :         return NULL;
    3473             :     }
    3474             :     /* Convert split table to combined table */
    3475       17998 :     if (self->ma_keys->dk_kind == DICT_KEYS_SPLIT) {
    3476           1 :         if (dictresize(self, DK_LOG_SIZE(self->ma_keys), 1)) {
    3477           0 :             Py_DECREF(res);
    3478           0 :             return NULL;
    3479             :         }
    3480             :     }
    3481       17998 :     self->ma_keys->dk_version = 0;
    3482             : 
    3483             :     /* Pop last item */
    3484             :     PyObject *key, *value;
    3485             :     Py_hash_t hash;
    3486       17998 :     if (DK_IS_UNICODE(self->ma_keys)) {
    3487       17830 :         PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(self->ma_keys);
    3488       17830 :         i = self->ma_keys->dk_nentries - 1;
    3489       17838 :         while (i >= 0 && ep0[i].me_value == NULL) {
    3490           8 :             i--;
    3491             :         }
    3492       17830 :         assert(i >= 0);
    3493             : 
    3494       17830 :         key = ep0[i].me_key;
    3495       17830 :         hash = unicode_get_hash(key);
    3496       17830 :         value = ep0[i].me_value;
    3497       17830 :         ep0[i].me_key = NULL;
    3498       17830 :         ep0[i].me_value = NULL;
    3499             :     }
    3500             :     else {
    3501         168 :         PyDictKeyEntry *ep0 = DK_ENTRIES(self->ma_keys);
    3502         168 :         i = self->ma_keys->dk_nentries - 1;
    3503         182 :         while (i >= 0 && ep0[i].me_value == NULL) {
    3504          14 :             i--;
    3505             :         }
    3506         168 :         assert(i >= 0);
    3507             : 
    3508         168 :         key = ep0[i].me_key;
    3509         168 :         hash = ep0[i].me_hash;
    3510         168 :         value = ep0[i].me_value;
    3511         168 :         ep0[i].me_key = NULL;
    3512         168 :         ep0[i].me_hash = -1;
    3513         168 :         ep0[i].me_value = NULL;
    3514             :     }
    3515             : 
    3516       17998 :     j = lookdict_index(self->ma_keys, hash, i);
    3517       17998 :     assert(j >= 0);
    3518       17998 :     assert(dictkeys_get_index(self->ma_keys, j) == i);
    3519       17998 :     dictkeys_set_index(self->ma_keys, j, DKIX_DUMMY);
    3520             : 
    3521       17998 :     PyTuple_SET_ITEM(res, 0, key);
    3522       17998 :     PyTuple_SET_ITEM(res, 1, value);
    3523             :     /* We can't dk_usable++ since there is DKIX_DUMMY in indices */
    3524       17998 :     self->ma_keys->dk_nentries = i;
    3525       17998 :     self->ma_used--;
    3526       17998 :     self->ma_version_tag = DICT_NEXT_VERSION();
    3527       17998 :     ASSERT_CONSISTENT(self);
    3528       17998 :     return res;
    3529             : }
    3530             : 
    3531             : static int
    3532   105582000 : dict_traverse(PyObject *op, visitproc visit, void *arg)
    3533             : {
    3534   105582000 :     PyDictObject *mp = (PyDictObject *)op;
    3535   105582000 :     PyDictKeysObject *keys = mp->ma_keys;
    3536   105582000 :     Py_ssize_t i, n = keys->dk_nentries;
    3537             : 
    3538   105582000 :     if (DK_IS_UNICODE(keys)) {
    3539    93179300 :         if (mp->ma_values != NULL) {
    3540     6606410 :             for (i = 0; i < n; i++) {
    3541     5805210 :                 Py_VISIT(mp->ma_values->values[i]);
    3542             :             }
    3543             :         }
    3544             :         else {
    3545    92378100 :             PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys);
    3546  1288550000 :             for (i = 0; i < n; i++) {
    3547  1196170000 :                 Py_VISIT(entries[i].me_value);
    3548             :             }
    3549             :         }
    3550             :     }
    3551             :     else {
    3552    12403200 :         PyDictKeyEntry *entries = DK_ENTRIES(keys);
    3553   104032000 :         for (i = 0; i < n; i++) {
    3554    91628900 :             if (entries[i].me_value != NULL) {
    3555    82727800 :                 Py_VISIT(entries[i].me_value);
    3556    82727800 :                 Py_VISIT(entries[i].me_key);
    3557             :             }
    3558             :         }
    3559             :     }
    3560   105582000 :     return 0;
    3561             : }
    3562             : 
    3563             : static int
    3564      368057 : dict_tp_clear(PyObject *op)
    3565             : {
    3566      368057 :     PyDict_Clear(op);
    3567      368057 :     return 0;
    3568             : }
    3569             : 
    3570             : static PyObject *dictiter_new(PyDictObject *, PyTypeObject *);
    3571             : 
    3572             : Py_ssize_t
    3573          46 : _PyDict_SizeOf(PyDictObject *mp)
    3574             : {
    3575             :     Py_ssize_t res;
    3576             : 
    3577          46 :     res = _PyObject_SIZE(Py_TYPE(mp));
    3578          46 :     if (mp->ma_values) {
    3579          15 :         res += shared_keys_usable_size(mp->ma_keys) * sizeof(PyObject*);
    3580             :     }
    3581             :     /* If the dictionary is split, the keys portion is accounted-for
    3582             :        in the type object. */
    3583          46 :     if (mp->ma_keys->dk_refcnt == 1) {
    3584          26 :         res += _PyDict_KeysSize(mp->ma_keys);
    3585             :     }
    3586          46 :     return res;
    3587             : }
    3588             : 
    3589             : Py_ssize_t
    3590     3327200 : _PyDict_KeysSize(PyDictKeysObject *keys)
    3591             : {
    3592     6654400 :     size_t es = keys->dk_kind == DICT_KEYS_GENERAL
    3593     3327200 :         ?  sizeof(PyDictKeyEntry) : sizeof(PyDictUnicodeEntry);
    3594             :     return (sizeof(PyDictKeysObject)
    3595     3327200 :             + ((size_t)1 << keys->dk_log2_index_bytes)
    3596     3327200 :             + USABLE_FRACTION(DK_SIZE(keys)) * es);
    3597             : }
    3598             : 
    3599             : static PyObject *
    3600          34 : dict_sizeof(PyDictObject *mp, PyObject *Py_UNUSED(ignored))
    3601             : {
    3602          34 :     return PyLong_FromSsize_t(_PyDict_SizeOf(mp));
    3603             : }
    3604             : 
    3605             : static PyObject *
    3606         219 : dict_or(PyObject *self, PyObject *other)
    3607             : {
    3608         219 :     if (!PyDict_Check(self) || !PyDict_Check(other)) {
    3609          14 :         Py_RETURN_NOTIMPLEMENTED;
    3610             :     }
    3611         205 :     PyObject *new = PyDict_Copy(self);
    3612         205 :     if (new == NULL) {
    3613           0 :         return NULL;
    3614             :     }
    3615         205 :     if (dict_update_arg(new, other)) {
    3616           0 :         Py_DECREF(new);
    3617           0 :         return NULL;
    3618             :     }
    3619         205 :     return new;
    3620             : }
    3621             : 
    3622             : static PyObject *
    3623        1225 : dict_ior(PyObject *self, PyObject *other)
    3624             : {
    3625        1225 :     if (dict_update_arg(self, other)) {
    3626           3 :         return NULL;
    3627             :     }
    3628        1222 :     Py_INCREF(self);
    3629        1222 :     return self;
    3630             : }
    3631             : 
    3632             : PyDoc_STRVAR(getitem__doc__, "x.__getitem__(y) <==> x[y]");
    3633             : 
    3634             : PyDoc_STRVAR(sizeof__doc__,
    3635             : "D.__sizeof__() -> size of D in memory, in bytes");
    3636             : 
    3637             : PyDoc_STRVAR(update__doc__,
    3638             : "D.update([E, ]**F) -> None.  Update D from dict/iterable E and F.\n\
    3639             : If E is present and has a .keys() method, then does:  for k in E: D[k] = E[k]\n\
    3640             : If E is present and lacks a .keys() method, then does:  for k, v in E: D[k] = v\n\
    3641             : In either case, this is followed by: for k in F:  D[k] = F[k]");
    3642             : 
    3643             : PyDoc_STRVAR(clear__doc__,
    3644             : "D.clear() -> None.  Remove all items from D.");
    3645             : 
    3646             : PyDoc_STRVAR(copy__doc__,
    3647             : "D.copy() -> a shallow copy of D");
    3648             : 
    3649             : /* Forward */
    3650             : static PyObject *dictkeys_new(PyObject *, PyObject *);
    3651             : static PyObject *dictitems_new(PyObject *, PyObject *);
    3652             : static PyObject *dictvalues_new(PyObject *, PyObject *);
    3653             : 
    3654             : PyDoc_STRVAR(keys__doc__,
    3655             :              "D.keys() -> a set-like object providing a view on D's keys");
    3656             : PyDoc_STRVAR(items__doc__,
    3657             :              "D.items() -> a set-like object providing a view on D's items");
    3658             : PyDoc_STRVAR(values__doc__,
    3659             :              "D.values() -> an object providing a view on D's values");
    3660             : 
    3661             : static PyMethodDef mapp_methods[] = {
    3662             :     DICT___CONTAINS___METHODDEF
    3663             :     {"__getitem__", _PyCFunction_CAST(dict_subscript),        METH_O | METH_COEXIST,
    3664             :      getitem__doc__},
    3665             :     {"__sizeof__",      _PyCFunction_CAST(dict_sizeof),       METH_NOARGS,
    3666             :      sizeof__doc__},
    3667             :     DICT_GET_METHODDEF
    3668             :     DICT_SETDEFAULT_METHODDEF
    3669             :     DICT_POP_METHODDEF
    3670             :     DICT_POPITEM_METHODDEF
    3671             :     {"keys",            dictkeys_new,                   METH_NOARGS,
    3672             :     keys__doc__},
    3673             :     {"items",           dictitems_new,                  METH_NOARGS,
    3674             :     items__doc__},
    3675             :     {"values",          dictvalues_new,                 METH_NOARGS,
    3676             :     values__doc__},
    3677             :     {"update",          _PyCFunction_CAST(dict_update), METH_VARARGS | METH_KEYWORDS,
    3678             :      update__doc__},
    3679             :     DICT_FROMKEYS_METHODDEF
    3680             :     {"clear",           (PyCFunction)dict_clear,        METH_NOARGS,
    3681             :      clear__doc__},
    3682             :     {"copy",            (PyCFunction)dict_copy,         METH_NOARGS,
    3683             :      copy__doc__},
    3684             :     DICT___REVERSED___METHODDEF
    3685             :     {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
    3686             :     {NULL,              NULL}   /* sentinel */
    3687             : };
    3688             : 
    3689             : /* Return 1 if `key` is in dict `op`, 0 if not, and -1 on error. */
    3690             : int
    3691   558907000 : PyDict_Contains(PyObject *op, PyObject *key)
    3692             : {
    3693             :     Py_hash_t hash;
    3694             :     Py_ssize_t ix;
    3695   558907000 :     PyDictObject *mp = (PyDictObject *)op;
    3696             :     PyObject *value;
    3697             : 
    3698   558907000 :     if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
    3699     6861680 :         hash = PyObject_Hash(key);
    3700     6861680 :         if (hash == -1)
    3701           4 :             return -1;
    3702             :     }
    3703   558907000 :     ix = _Py_dict_lookup(mp, key, hash, &value);
    3704   558907000 :     if (ix == DKIX_ERROR)
    3705           2 :         return -1;
    3706   558907000 :     return (ix != DKIX_EMPTY && value != NULL);
    3707             : }
    3708             : 
    3709             : /* Internal version of PyDict_Contains used when the hash value is already known */
    3710             : int
    3711       38710 : _PyDict_Contains_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
    3712             : {
    3713       38710 :     PyDictObject *mp = (PyDictObject *)op;
    3714             :     PyObject *value;
    3715             :     Py_ssize_t ix;
    3716             : 
    3717       38710 :     ix = _Py_dict_lookup(mp, key, hash, &value);
    3718       38710 :     if (ix == DKIX_ERROR)
    3719           0 :         return -1;
    3720       38710 :     return (ix != DKIX_EMPTY && value != NULL);
    3721             : }
    3722             : 
    3723             : int
    3724        1268 : _PyDict_ContainsId(PyObject *op, _Py_Identifier *key)
    3725             : {
    3726        1268 :     PyObject *kv = _PyUnicode_FromId(key); /* borrowed */
    3727        1268 :     if (kv == NULL) {
    3728           0 :         return -1;
    3729             :     }
    3730        1268 :     return PyDict_Contains(op, kv);
    3731             : }
    3732             : 
    3733             : /* Hack to implement "key in dict" */
    3734             : static PySequenceMethods dict_as_sequence = {
    3735             :     0,                          /* sq_length */
    3736             :     0,                          /* sq_concat */
    3737             :     0,                          /* sq_repeat */
    3738             :     0,                          /* sq_item */
    3739             :     0,                          /* sq_slice */
    3740             :     0,                          /* sq_ass_item */
    3741             :     0,                          /* sq_ass_slice */
    3742             :     PyDict_Contains,            /* sq_contains */
    3743             :     0,                          /* sq_inplace_concat */
    3744             :     0,                          /* sq_inplace_repeat */
    3745             : };
    3746             : 
    3747             : static PyNumberMethods dict_as_number = {
    3748             :     .nb_or = dict_or,
    3749             :     .nb_inplace_or = dict_ior,
    3750             : };
    3751             : 
    3752             : static PyObject *
    3753      365139 : dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
    3754             : {
    3755      365139 :     assert(type != NULL);
    3756      365139 :     assert(type->tp_alloc != NULL);
    3757             :     // dict subclasses must implement the GC protocol
    3758      365139 :     assert(_PyType_IS_GC(type));
    3759             : 
    3760      365139 :     PyObject *self = type->tp_alloc(type, 0);
    3761      365139 :     if (self == NULL) {
    3762           0 :         return NULL;
    3763             :     }
    3764      365139 :     PyDictObject *d = (PyDictObject *)self;
    3765             : 
    3766      365139 :     d->ma_used = 0;
    3767      365139 :     d->ma_version_tag = DICT_NEXT_VERSION();
    3768      365139 :     dictkeys_incref(Py_EMPTY_KEYS);
    3769      365139 :     d->ma_keys = Py_EMPTY_KEYS;
    3770      365139 :     d->ma_values = NULL;
    3771      365139 :     ASSERT_CONSISTENT(d);
    3772             : 
    3773      365139 :     if (type != &PyDict_Type) {
    3774             :         // Don't track if a subclass tp_alloc is PyType_GenericAlloc()
    3775      102800 :         if (!_PyObject_GC_IS_TRACKED(d)) {
    3776       12663 :             _PyObject_GC_TRACK(d);
    3777             :         }
    3778             :     }
    3779             :     else {
    3780             :         // _PyType_AllocNoTrack() does not track the created object
    3781      262339 :         assert(!_PyObject_GC_IS_TRACKED(d));
    3782             :     }
    3783      365139 :     return self;
    3784             : }
    3785             : 
    3786             : static int
    3787       88330 : dict_init(PyObject *self, PyObject *args, PyObject *kwds)
    3788             : {
    3789       88330 :     return dict_update_common(self, args, kwds, "dict");
    3790             : }
    3791             : 
    3792             : static PyObject *
    3793      262342 : dict_vectorcall(PyObject *type, PyObject * const*args,
    3794             :                 size_t nargsf, PyObject *kwnames)
    3795             : {
    3796      262342 :     Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
    3797      262342 :     if (!_PyArg_CheckPositional("dict", nargs, 0, 1)) {
    3798           3 :         return NULL;
    3799             :     }
    3800             : 
    3801      262339 :     PyObject *self = dict_new(_PyType_CAST(type), NULL, NULL);
    3802      262339 :     if (self == NULL) {
    3803           0 :         return NULL;
    3804             :     }
    3805      262339 :     if (nargs == 1) {
    3806      125804 :         if (dict_update_arg(self, args[0]) < 0) {
    3807          24 :             Py_DECREF(self);
    3808          24 :             return NULL;
    3809             :         }
    3810      125780 :         args++;
    3811             :     }
    3812      262315 :     if (kwnames != NULL) {
    3813      147645 :         for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(kwnames); i++) {
    3814      100493 :             if (PyDict_SetItem(self, PyTuple_GET_ITEM(kwnames, i), args[i]) < 0) {
    3815           0 :                 Py_DECREF(self);
    3816           0 :                 return NULL;
    3817             :             }
    3818             :         }
    3819             :     }
    3820      262315 :     return self;
    3821             : }
    3822             : 
    3823             : static PyObject *
    3824      490586 : dict_iter(PyDictObject *dict)
    3825             : {
    3826      490586 :     return dictiter_new(dict, &PyDictIterKey_Type);
    3827             : }
    3828             : 
    3829             : PyDoc_STRVAR(dictionary_doc,
    3830             : "dict() -> new empty dictionary\n"
    3831             : "dict(mapping) -> new dictionary initialized from a mapping object's\n"
    3832             : "    (key, value) pairs\n"
    3833             : "dict(iterable) -> new dictionary initialized as if via:\n"
    3834             : "    d = {}\n"
    3835             : "    for k, v in iterable:\n"
    3836             : "        d[k] = v\n"
    3837             : "dict(**kwargs) -> new dictionary initialized with the name=value pairs\n"
    3838             : "    in the keyword argument list.  For example:  dict(one=1, two=2)");
    3839             : 
    3840             : PyTypeObject PyDict_Type = {
    3841             :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    3842             :     "dict",
    3843             :     sizeof(PyDictObject),
    3844             :     0,
    3845             :     (destructor)dict_dealloc,                   /* tp_dealloc */
    3846             :     0,                                          /* tp_vectorcall_offset */
    3847             :     0,                                          /* tp_getattr */
    3848             :     0,                                          /* tp_setattr */
    3849             :     0,                                          /* tp_as_async */
    3850             :     (reprfunc)dict_repr,                        /* tp_repr */
    3851             :     &dict_as_number,                            /* tp_as_number */
    3852             :     &dict_as_sequence,                          /* tp_as_sequence */
    3853             :     &dict_as_mapping,                           /* tp_as_mapping */
    3854             :     PyObject_HashNotImplemented,                /* tp_hash */
    3855             :     0,                                          /* tp_call */
    3856             :     0,                                          /* tp_str */
    3857             :     PyObject_GenericGetAttr,                    /* tp_getattro */
    3858             :     0,                                          /* tp_setattro */
    3859             :     0,                                          /* tp_as_buffer */
    3860             :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
    3861             :         Py_TPFLAGS_BASETYPE | Py_TPFLAGS_DICT_SUBCLASS |
    3862             :         _Py_TPFLAGS_MATCH_SELF | Py_TPFLAGS_MAPPING,  /* tp_flags */
    3863             :     dictionary_doc,                             /* tp_doc */
    3864             :     dict_traverse,                              /* tp_traverse */
    3865             :     dict_tp_clear,                              /* tp_clear */
    3866             :     dict_richcompare,                           /* tp_richcompare */
    3867             :     0,                                          /* tp_weaklistoffset */
    3868             :     (getiterfunc)dict_iter,                     /* tp_iter */
    3869             :     0,                                          /* tp_iternext */
    3870             :     mapp_methods,                               /* tp_methods */
    3871             :     0,                                          /* tp_members */
    3872             :     0,                                          /* tp_getset */
    3873             :     0,                                          /* tp_base */
    3874             :     0,                                          /* tp_dict */
    3875             :     0,                                          /* tp_descr_get */
    3876             :     0,                                          /* tp_descr_set */
    3877             :     0,                                          /* tp_dictoffset */
    3878             :     dict_init,                                  /* tp_init */
    3879             :     _PyType_AllocNoTrack,                       /* tp_alloc */
    3880             :     dict_new,                                   /* tp_new */
    3881             :     PyObject_GC_Del,                            /* tp_free */
    3882             :     .tp_vectorcall = dict_vectorcall,
    3883             : };
    3884             : 
    3885             : /* For backward compatibility with old dictionary interface */
    3886             : 
    3887             : PyObject *
    3888           0 : PyDict_GetItemString(PyObject *v, const char *key)
    3889             : {
    3890             :     PyObject *kv, *rv;
    3891           0 :     kv = PyUnicode_FromString(key);
    3892           0 :     if (kv == NULL) {
    3893           0 :         PyErr_Clear();
    3894           0 :         return NULL;
    3895             :     }
    3896           0 :     rv = PyDict_GetItem(v, kv);
    3897           0 :     Py_DECREF(kv);
    3898           0 :     return rv;
    3899             : }
    3900             : 
    3901             : int
    3902       10568 : _PyDict_SetItemId(PyObject *v, _Py_Identifier *key, PyObject *item)
    3903             : {
    3904             :     PyObject *kv;
    3905       10568 :     kv = _PyUnicode_FromId(key); /* borrowed */
    3906       10568 :     if (kv == NULL)
    3907           0 :         return -1;
    3908       10568 :     return PyDict_SetItem(v, kv, item);
    3909             : }
    3910             : 
    3911             : int
    3912     3897750 : PyDict_SetItemString(PyObject *v, const char *key, PyObject *item)
    3913             : {
    3914             :     PyObject *kv;
    3915             :     int err;
    3916     3897750 :     kv = PyUnicode_FromString(key);
    3917     3897750 :     if (kv == NULL)
    3918          49 :         return -1;
    3919     3897700 :     PyUnicode_InternInPlace(&kv); /* XXX Should we really? */
    3920     3897700 :     err = PyDict_SetItem(v, kv, item);
    3921     3897700 :     Py_DECREF(kv);
    3922     3897700 :     return err;
    3923             : }
    3924             : 
    3925             : int
    3926           0 : _PyDict_DelItemId(PyObject *v, _Py_Identifier *key)
    3927             : {
    3928           0 :     PyObject *kv = _PyUnicode_FromId(key); /* borrowed */
    3929           0 :     if (kv == NULL)
    3930           0 :         return -1;
    3931           0 :     return PyDict_DelItem(v, kv);
    3932             : }
    3933             : 
    3934             : int
    3935         612 : PyDict_DelItemString(PyObject *v, const char *key)
    3936             : {
    3937             :     PyObject *kv;
    3938             :     int err;
    3939         612 :     kv = PyUnicode_FromString(key);
    3940         612 :     if (kv == NULL)
    3941           0 :         return -1;
    3942         612 :     err = PyDict_DelItem(v, kv);
    3943         612 :     Py_DECREF(kv);
    3944         612 :     return err;
    3945             : }
    3946             : 
    3947             : /* Dictionary iterator types */
    3948             : 
    3949             : typedef struct {
    3950             :     PyObject_HEAD
    3951             :     PyDictObject *di_dict; /* Set to NULL when iterator is exhausted */
    3952             :     Py_ssize_t di_used;
    3953             :     Py_ssize_t di_pos;
    3954             :     PyObject* di_result; /* reusable result tuple for iteritems */
    3955             :     Py_ssize_t len;
    3956             : } dictiterobject;
    3957             : 
    3958             : static PyObject *
    3959     1590340 : dictiter_new(PyDictObject *dict, PyTypeObject *itertype)
    3960             : {
    3961             :     dictiterobject *di;
    3962     1590340 :     di = PyObject_GC_New(dictiterobject, itertype);
    3963     1590340 :     if (di == NULL) {
    3964           0 :         return NULL;
    3965             :     }
    3966     1590340 :     Py_INCREF(dict);
    3967     1590340 :     di->di_dict = dict;
    3968     1590340 :     di->di_used = dict->ma_used;
    3969     1590340 :     di->len = dict->ma_used;
    3970     1590340 :     if (itertype == &PyDictRevIterKey_Type ||
    3971     1590310 :          itertype == &PyDictRevIterItem_Type ||
    3972             :          itertype == &PyDictRevIterValue_Type) {
    3973          51 :         if (dict->ma_values) {
    3974           3 :             di->di_pos = dict->ma_used - 1;
    3975             :         }
    3976             :         else {
    3977          48 :             di->di_pos = dict->ma_keys->dk_nentries - 1;
    3978             :         }
    3979             :     }
    3980             :     else {
    3981     1590290 :         di->di_pos = 0;
    3982             :     }
    3983     1590340 :     if (itertype == &PyDictIterItem_Type ||
    3984             :         itertype == &PyDictRevIterItem_Type) {
    3985      615184 :         di->di_result = PyTuple_Pack(2, Py_None, Py_None);
    3986      615184 :         if (di->di_result == NULL) {
    3987           0 :             Py_DECREF(di);
    3988           0 :             return NULL;
    3989             :         }
    3990             :     }
    3991             :     else {
    3992      975161 :         di->di_result = NULL;
    3993             :     }
    3994     1590340 :     _PyObject_GC_TRACK(di);
    3995     1590340 :     return (PyObject *)di;
    3996             : }
    3997             : 
    3998             : static void
    3999     1590340 : dictiter_dealloc(dictiterobject *di)
    4000             : {
    4001             :     /* bpo-31095: UnTrack is needed before calling any callbacks */
    4002     1590340 :     _PyObject_GC_UNTRACK(di);
    4003     1590340 :     Py_XDECREF(di->di_dict);
    4004     1590340 :     Py_XDECREF(di->di_result);
    4005     1590340 :     PyObject_GC_Del(di);
    4006     1590340 : }
    4007             : 
    4008             : static int
    4009        3886 : dictiter_traverse(dictiterobject *di, visitproc visit, void *arg)
    4010             : {
    4011        3886 :     Py_VISIT(di->di_dict);
    4012        3886 :     Py_VISIT(di->di_result);
    4013        3886 :     return 0;
    4014             : }
    4015             : 
    4016             : static PyObject *
    4017      274677 : dictiter_len(dictiterobject *di, PyObject *Py_UNUSED(ignored))
    4018             : {
    4019      274677 :     Py_ssize_t len = 0;
    4020      274677 :     if (di->di_dict != NULL && di->di_used == di->di_dict->ma_used)
    4021      274667 :         len = di->len;
    4022      274677 :     return PyLong_FromSize_t(len);
    4023             : }
    4024             : 
    4025             : PyDoc_STRVAR(length_hint_doc,
    4026             :              "Private method returning an estimate of len(list(it)).");
    4027             : 
    4028             : static PyObject *
    4029             : dictiter_reduce(dictiterobject *di, PyObject *Py_UNUSED(ignored));
    4030             : 
    4031             : PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
    4032             : 
    4033             : static PyMethodDef dictiter_methods[] = {
    4034             :     {"__length_hint__", _PyCFunction_CAST(dictiter_len), METH_NOARGS,
    4035             :      length_hint_doc},
    4036             :      {"__reduce__", _PyCFunction_CAST(dictiter_reduce), METH_NOARGS,
    4037             :      reduce_doc},
    4038             :     {NULL,              NULL}           /* sentinel */
    4039             : };
    4040             : 
    4041             : static PyObject*
    4042     6534360 : dictiter_iternextkey(dictiterobject *di)
    4043             : {
    4044             :     PyObject *key;
    4045             :     Py_ssize_t i;
    4046             :     PyDictKeysObject *k;
    4047     6534360 :     PyDictObject *d = di->di_dict;
    4048             : 
    4049     6534360 :     if (d == NULL)
    4050           7 :         return NULL;
    4051     6534350 :     assert (PyDict_Check(d));
    4052             : 
    4053     6534350 :     if (di->di_used != d->ma_used) {
    4054         236 :         PyErr_SetString(PyExc_RuntimeError,
    4055             :                         "dictionary changed size during iteration");
    4056         236 :         di->di_used = -1; /* Make this state sticky */
    4057         236 :         return NULL;
    4058             :     }
    4059             : 
    4060     6534120 :     i = di->di_pos;
    4061     6534120 :     k = d->ma_keys;
    4062     6534120 :     assert(i >= 0);
    4063     6534120 :     if (d->ma_values) {
    4064       13644 :         if (i >= d->ma_used)
    4065        1687 :             goto fail;
    4066       11957 :         int index = get_index_from_order(d, i);
    4067       11957 :         key = DK_UNICODE_ENTRIES(k)[index].me_key;
    4068       11957 :         assert(d->ma_values->values[index] != NULL);
    4069             :     }
    4070             :     else {
    4071     6520470 :         Py_ssize_t n = k->dk_nentries;
    4072     6520470 :         if (DK_IS_UNICODE(k)) {
    4073     3326440 :             PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(k)[i];
    4074    14735200 :             while (i < n && entry_ptr->me_value == NULL) {
    4075    11408800 :                 entry_ptr++;
    4076    11408800 :                 i++;
    4077             :             }
    4078     3326440 :             if (i >= n)
    4079      285584 :                 goto fail;
    4080     3040860 :             key = entry_ptr->me_key;
    4081             :         }
    4082             :         else {
    4083     3194030 :             PyDictKeyEntry *entry_ptr = &DK_ENTRIES(k)[i];
    4084     5463870 :             while (i < n && entry_ptr->me_value == NULL) {
    4085     2269840 :                 entry_ptr++;
    4086     2269840 :                 i++;
    4087             :             }
    4088     3194030 :             if (i >= n)
    4089      268784 :                 goto fail;
    4090     2925250 :             key = entry_ptr->me_key;
    4091             :         }
    4092             :     }
    4093             :     // We found an element (key), but did not expect it
    4094     5978060 :     if (di->len == 0) {
    4095           1 :         PyErr_SetString(PyExc_RuntimeError,
    4096             :                         "dictionary keys changed during iteration");
    4097           1 :         goto fail;
    4098             :     }
    4099     5978060 :     di->di_pos = i+1;
    4100     5978060 :     di->len--;
    4101     5978060 :     Py_INCREF(key);
    4102     5978060 :     return key;
    4103             : 
    4104      556056 : fail:
    4105      556056 :     di->di_dict = NULL;
    4106      556056 :     Py_DECREF(d);
    4107      556056 :     return NULL;
    4108             : }
    4109             : 
    4110             : PyTypeObject PyDictIterKey_Type = {
    4111             :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    4112             :     "dict_keyiterator",                         /* tp_name */
    4113             :     sizeof(dictiterobject),                     /* tp_basicsize */
    4114             :     0,                                          /* tp_itemsize */
    4115             :     /* methods */
    4116             :     (destructor)dictiter_dealloc,               /* tp_dealloc */
    4117             :     0,                                          /* tp_vectorcall_offset */
    4118             :     0,                                          /* tp_getattr */
    4119             :     0,                                          /* tp_setattr */
    4120             :     0,                                          /* tp_as_async */
    4121             :     0,                                          /* tp_repr */
    4122             :     0,                                          /* tp_as_number */
    4123             :     0,                                          /* tp_as_sequence */
    4124             :     0,                                          /* tp_as_mapping */
    4125             :     0,                                          /* tp_hash */
    4126             :     0,                                          /* tp_call */
    4127             :     0,                                          /* tp_str */
    4128             :     PyObject_GenericGetAttr,                    /* tp_getattro */
    4129             :     0,                                          /* tp_setattro */
    4130             :     0,                                          /* tp_as_buffer */
    4131             :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
    4132             :     0,                                          /* tp_doc */
    4133             :     (traverseproc)dictiter_traverse,            /* tp_traverse */
    4134             :     0,                                          /* tp_clear */
    4135             :     0,                                          /* tp_richcompare */
    4136             :     0,                                          /* tp_weaklistoffset */
    4137             :     PyObject_SelfIter,                          /* tp_iter */
    4138             :     (iternextfunc)dictiter_iternextkey,         /* tp_iternext */
    4139             :     dictiter_methods,                           /* tp_methods */
    4140             :     0,
    4141             : };
    4142             : 
    4143             : static PyObject *
    4144     1414760 : dictiter_iternextvalue(dictiterobject *di)
    4145             : {
    4146             :     PyObject *value;
    4147             :     Py_ssize_t i;
    4148     1414760 :     PyDictObject *d = di->di_dict;
    4149             : 
    4150     1414760 :     if (d == NULL)
    4151           1 :         return NULL;
    4152     1414760 :     assert (PyDict_Check(d));
    4153             : 
    4154     1414760 :     if (di->di_used != d->ma_used) {
    4155           1 :         PyErr_SetString(PyExc_RuntimeError,
    4156             :                         "dictionary changed size during iteration");
    4157           1 :         di->di_used = -1; /* Make this state sticky */
    4158           1 :         return NULL;
    4159             :     }
    4160             : 
    4161     1414760 :     i = di->di_pos;
    4162     1414760 :     assert(i >= 0);
    4163     1414760 :     if (d->ma_values) {
    4164           0 :         if (i >= d->ma_used)
    4165           0 :             goto fail;
    4166           0 :         int index = get_index_from_order(d, i);
    4167           0 :         value = d->ma_values->values[index];
    4168           0 :         assert(value != NULL);
    4169             :     }
    4170             :     else {
    4171     1414760 :         Py_ssize_t n = d->ma_keys->dk_nentries;
    4172     1414760 :         if (DK_IS_UNICODE(d->ma_keys)) {
    4173     1279550 :             PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(d->ma_keys)[i];
    4174     1447020 :             while (i < n && entry_ptr->me_value == NULL) {
    4175      167467 :                 entry_ptr++;
    4176      167467 :                 i++;
    4177             :             }
    4178     1279550 :             if (i >= n)
    4179      350584 :                 goto fail;
    4180      928970 :             value = entry_ptr->me_value;
    4181             :         }
    4182             :         else {
    4183      135207 :             PyDictKeyEntry *entry_ptr = &DK_ENTRIES(d->ma_keys)[i];
    4184      367598 :             while (i < n && entry_ptr->me_value == NULL) {
    4185      232391 :                 entry_ptr++;
    4186      232391 :                 i++;
    4187             :             }
    4188      135207 :             if (i >= n)
    4189       10414 :                 goto fail;
    4190      124793 :             value = entry_ptr->me_value;
    4191             :         }
    4192             :     }
    4193             :     // We found an element, but did not expect it
    4194     1053760 :     if (di->len == 0) {
    4195           1 :         PyErr_SetString(PyExc_RuntimeError,
    4196             :                         "dictionary keys changed during iteration");
    4197           1 :         goto fail;
    4198             :     }
    4199     1053760 :     di->di_pos = i+1;
    4200     1053760 :     di->len--;
    4201     1053760 :     Py_INCREF(value);
    4202     1053760 :     return value;
    4203             : 
    4204      360999 : fail:
    4205      360999 :     di->di_dict = NULL;
    4206      360999 :     Py_DECREF(d);
    4207      360999 :     return NULL;
    4208             : }
    4209             : 
    4210             : PyTypeObject PyDictIterValue_Type = {
    4211             :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    4212             :     "dict_valueiterator",                       /* tp_name */
    4213             :     sizeof(dictiterobject),                     /* tp_basicsize */
    4214             :     0,                                          /* tp_itemsize */
    4215             :     /* methods */
    4216             :     (destructor)dictiter_dealloc,               /* tp_dealloc */
    4217             :     0,                                          /* tp_vectorcall_offset */
    4218             :     0,                                          /* tp_getattr */
    4219             :     0,                                          /* tp_setattr */
    4220             :     0,                                          /* tp_as_async */
    4221             :     0,                                          /* tp_repr */
    4222             :     0,                                          /* tp_as_number */
    4223             :     0,                                          /* tp_as_sequence */
    4224             :     0,                                          /* tp_as_mapping */
    4225             :     0,                                          /* tp_hash */
    4226             :     0,                                          /* tp_call */
    4227             :     0,                                          /* tp_str */
    4228             :     PyObject_GenericGetAttr,                    /* tp_getattro */
    4229             :     0,                                          /* tp_setattro */
    4230             :     0,                                          /* tp_as_buffer */
    4231             :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
    4232             :     0,                                          /* tp_doc */
    4233             :     (traverseproc)dictiter_traverse,            /* tp_traverse */
    4234             :     0,                                          /* tp_clear */
    4235             :     0,                                          /* tp_richcompare */
    4236             :     0,                                          /* tp_weaklistoffset */
    4237             :     PyObject_SelfIter,                          /* tp_iter */
    4238             :     (iternextfunc)dictiter_iternextvalue,       /* tp_iternext */
    4239             :     dictiter_methods,                           /* tp_methods */
    4240             :     0,
    4241             : };
    4242             : 
    4243             : static PyObject *
    4244     7322090 : dictiter_iternextitem(dictiterobject *di)
    4245             : {
    4246             :     PyObject *key, *value, *result;
    4247             :     Py_ssize_t i;
    4248     7322090 :     PyDictObject *d = di->di_dict;
    4249             : 
    4250     7322090 :     if (d == NULL)
    4251           1 :         return NULL;
    4252     7322090 :     assert (PyDict_Check(d));
    4253             : 
    4254     7322090 :     if (di->di_used != d->ma_used) {
    4255          72 :         PyErr_SetString(PyExc_RuntimeError,
    4256             :                         "dictionary changed size during iteration");
    4257          72 :         di->di_used = -1; /* Make this state sticky */
    4258          72 :         return NULL;
    4259             :     }
    4260             : 
    4261     7322020 :     i = di->di_pos;
    4262     7322020 :     assert(i >= 0);
    4263     7322020 :     if (d->ma_values) {
    4264      101978 :         if (i >= d->ma_used)
    4265       47344 :             goto fail;
    4266       54634 :         int index = get_index_from_order(d, i);
    4267       54634 :         key = DK_UNICODE_ENTRIES(d->ma_keys)[index].me_key;
    4268       54634 :         value = d->ma_values->values[index];
    4269       54634 :         assert(value != NULL);
    4270             :     }
    4271             :     else {
    4272     7220040 :         Py_ssize_t n = d->ma_keys->dk_nentries;
    4273     7220040 :         if (DK_IS_UNICODE(d->ma_keys)) {
    4274     6480470 :             PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(d->ma_keys)[i];
    4275     6684800 :             while (i < n && entry_ptr->me_value == NULL) {
    4276      204339 :                 entry_ptr++;
    4277      204339 :                 i++;
    4278             :             }
    4279     6480470 :             if (i >= n)
    4280      523017 :                 goto fail;
    4281     5957450 :             key = entry_ptr->me_key;
    4282     5957450 :             value = entry_ptr->me_value;
    4283             :         }
    4284             :         else {
    4285      739572 :             PyDictKeyEntry *entry_ptr = &DK_ENTRIES(d->ma_keys)[i];
    4286      749962 :             while (i < n && entry_ptr->me_value == NULL) {
    4287       10390 :                 entry_ptr++;
    4288       10390 :                 i++;
    4289             :             }
    4290      739572 :             if (i >= n)
    4291       30358 :                 goto fail;
    4292      709214 :             key = entry_ptr->me_key;
    4293      709214 :             value = entry_ptr->me_value;
    4294             :         }
    4295             :     }
    4296             :     // We found an element, but did not expect it
    4297     6721300 :     if (di->len == 0) {
    4298           1 :         PyErr_SetString(PyExc_RuntimeError,
    4299             :                         "dictionary keys changed during iteration");
    4300           1 :         goto fail;
    4301             :     }
    4302     6721300 :     di->di_pos = i+1;
    4303     6721300 :     di->len--;
    4304     6721300 :     Py_INCREF(key);
    4305     6721300 :     Py_INCREF(value);
    4306     6721300 :     result = di->di_result;
    4307     6721300 :     if (Py_REFCNT(result) == 1) {
    4308     4946340 :         PyObject *oldkey = PyTuple_GET_ITEM(result, 0);
    4309     4946340 :         PyObject *oldvalue = PyTuple_GET_ITEM(result, 1);
    4310     4946340 :         PyTuple_SET_ITEM(result, 0, key);  /* steals reference */
    4311     4946340 :         PyTuple_SET_ITEM(result, 1, value);  /* steals reference */
    4312     4946340 :         Py_INCREF(result);
    4313     4946340 :         Py_DECREF(oldkey);
    4314     4946340 :         Py_DECREF(oldvalue);
    4315             :         // bpo-42536: The GC may have untracked this result tuple. Since we're
    4316             :         // recycling it, make sure it's tracked again:
    4317     4946340 :         if (!_PyObject_GC_IS_TRACKED(result)) {
    4318         571 :             _PyObject_GC_TRACK(result);
    4319             :         }
    4320             :     }
    4321             :     else {
    4322     1774960 :         result = PyTuple_New(2);
    4323     1774960 :         if (result == NULL)
    4324           0 :             return NULL;
    4325     1774960 :         PyTuple_SET_ITEM(result, 0, key);  /* steals reference */
    4326     1774960 :         PyTuple_SET_ITEM(result, 1, value);  /* steals reference */
    4327             :     }
    4328     6721300 :     return result;
    4329             : 
    4330      600720 : fail:
    4331      600720 :     di->di_dict = NULL;
    4332      600720 :     Py_DECREF(d);
    4333      600720 :     return NULL;
    4334             : }
    4335             : 
    4336             : PyTypeObject PyDictIterItem_Type = {
    4337             :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    4338             :     "dict_itemiterator",                        /* tp_name */
    4339             :     sizeof(dictiterobject),                     /* tp_basicsize */
    4340             :     0,                                          /* tp_itemsize */
    4341             :     /* methods */
    4342             :     (destructor)dictiter_dealloc,               /* tp_dealloc */
    4343             :     0,                                          /* tp_vectorcall_offset */
    4344             :     0,                                          /* tp_getattr */
    4345             :     0,                                          /* tp_setattr */
    4346             :     0,                                          /* tp_as_async */
    4347             :     0,                                          /* tp_repr */
    4348             :     0,                                          /* tp_as_number */
    4349             :     0,                                          /* tp_as_sequence */
    4350             :     0,                                          /* tp_as_mapping */
    4351             :     0,                                          /* tp_hash */
    4352             :     0,                                          /* tp_call */
    4353             :     0,                                          /* tp_str */
    4354             :     PyObject_GenericGetAttr,                    /* tp_getattro */
    4355             :     0,                                          /* tp_setattro */
    4356             :     0,                                          /* tp_as_buffer */
    4357             :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
    4358             :     0,                                          /* tp_doc */
    4359             :     (traverseproc)dictiter_traverse,            /* tp_traverse */
    4360             :     0,                                          /* tp_clear */
    4361             :     0,                                          /* tp_richcompare */
    4362             :     0,                                          /* tp_weaklistoffset */
    4363             :     PyObject_SelfIter,                          /* tp_iter */
    4364             :     (iternextfunc)dictiter_iternextitem,        /* tp_iternext */
    4365             :     dictiter_methods,                           /* tp_methods */
    4366             :     0,
    4367             : };
    4368             : 
    4369             : 
    4370             : /* dictreviter */
    4371             : 
    4372             : static PyObject *
    4373         172 : dictreviter_iternext(dictiterobject *di)
    4374             : {
    4375         172 :     PyDictObject *d = di->di_dict;
    4376             : 
    4377         172 :     if (d == NULL) {
    4378           2 :         return NULL;
    4379             :     }
    4380         170 :     assert (PyDict_Check(d));
    4381             : 
    4382         170 :     if (di->di_used != d->ma_used) {
    4383           0 :         PyErr_SetString(PyExc_RuntimeError,
    4384             :                          "dictionary changed size during iteration");
    4385           0 :         di->di_used = -1; /* Make this state sticky */
    4386           0 :         return NULL;
    4387             :     }
    4388             : 
    4389         170 :     Py_ssize_t i = di->di_pos;
    4390         170 :     PyDictKeysObject *k = d->ma_keys;
    4391             :     PyObject *key, *value, *result;
    4392             : 
    4393         170 :     if (i < 0) {
    4394          50 :         goto fail;
    4395             :     }
    4396         120 :     if (d->ma_values) {
    4397           4 :         int index = get_index_from_order(d, i);
    4398           4 :         key = DK_UNICODE_ENTRIES(k)[index].me_key;
    4399           4 :         value = d->ma_values->values[index];
    4400           4 :         assert (value != NULL);
    4401             :     }
    4402             :     else {
    4403         116 :         if (DK_IS_UNICODE(k)) {
    4404          13 :             PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(k)[i];
    4405          15 :             while (entry_ptr->me_value == NULL) {
    4406           2 :                 if (--i < 0) {
    4407           0 :                     goto fail;
    4408             :                 }
    4409           2 :                 entry_ptr--;
    4410             :             }
    4411          13 :             key = entry_ptr->me_key;
    4412          13 :             value = entry_ptr->me_value;
    4413             :         }
    4414             :         else {
    4415         103 :             PyDictKeyEntry *entry_ptr = &DK_ENTRIES(k)[i];
    4416         109 :             while (entry_ptr->me_value == NULL) {
    4417           6 :                 if (--i < 0) {
    4418           0 :                     goto fail;
    4419             :                 }
    4420           6 :                 entry_ptr--;
    4421             :             }
    4422         103 :             key = entry_ptr->me_key;
    4423         103 :             value = entry_ptr->me_value;
    4424             :         }
    4425             :     }
    4426         120 :     di->di_pos = i-1;
    4427         120 :     di->len--;
    4428             : 
    4429         120 :     if (Py_IS_TYPE(di, &PyDictRevIterKey_Type)) {
    4430          65 :         Py_INCREF(key);
    4431          65 :         return key;
    4432             :     }
    4433          55 :     else if (Py_IS_TYPE(di, &PyDictRevIterValue_Type)) {
    4434          36 :         Py_INCREF(value);
    4435          36 :         return value;
    4436             :     }
    4437          19 :     else if (Py_IS_TYPE(di, &PyDictRevIterItem_Type)) {
    4438          19 :         Py_INCREF(key);
    4439          19 :         Py_INCREF(value);
    4440          19 :         result = di->di_result;
    4441          19 :         if (Py_REFCNT(result) == 1) {
    4442           7 :             PyObject *oldkey = PyTuple_GET_ITEM(result, 0);
    4443           7 :             PyObject *oldvalue = PyTuple_GET_ITEM(result, 1);
    4444           7 :             PyTuple_SET_ITEM(result, 0, key);  /* steals reference */
    4445           7 :             PyTuple_SET_ITEM(result, 1, value);  /* steals reference */
    4446           7 :             Py_INCREF(result);
    4447           7 :             Py_DECREF(oldkey);
    4448           7 :             Py_DECREF(oldvalue);
    4449             :             // bpo-42536: The GC may have untracked this result tuple. Since
    4450             :             // we're recycling it, make sure it's tracked again:
    4451           7 :             if (!_PyObject_GC_IS_TRACKED(result)) {
    4452           1 :                 _PyObject_GC_TRACK(result);
    4453             :             }
    4454             :         }
    4455             :         else {
    4456          12 :             result = PyTuple_New(2);
    4457          12 :             if (result == NULL) {
    4458           0 :                 return NULL;
    4459             :             }
    4460          12 :             PyTuple_SET_ITEM(result, 0, key); /* steals reference */
    4461          12 :             PyTuple_SET_ITEM(result, 1, value); /* steals reference */
    4462             :         }
    4463          19 :         return result;
    4464             :     }
    4465             :     else {
    4466           0 :         Py_UNREACHABLE();
    4467             :     }
    4468             : 
    4469          50 : fail:
    4470          50 :     di->di_dict = NULL;
    4471          50 :     Py_DECREF(d);
    4472          50 :     return NULL;
    4473             : }
    4474             : 
    4475             : PyTypeObject PyDictRevIterKey_Type = {
    4476             :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    4477             :     "dict_reversekeyiterator",
    4478             :     sizeof(dictiterobject),
    4479             :     .tp_dealloc = (destructor)dictiter_dealloc,
    4480             :     .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
    4481             :     .tp_traverse = (traverseproc)dictiter_traverse,
    4482             :     .tp_iter = PyObject_SelfIter,
    4483             :     .tp_iternext = (iternextfunc)dictreviter_iternext,
    4484             :     .tp_methods = dictiter_methods
    4485             : };
    4486             : 
    4487             : 
    4488             : /*[clinic input]
    4489             : dict.__reversed__
    4490             : 
    4491             : Return a reverse iterator over the dict keys.
    4492             : [clinic start generated code]*/
    4493             : 
    4494             : static PyObject *
    4495          26 : dict___reversed___impl(PyDictObject *self)
    4496             : /*[clinic end generated code: output=e674483336d1ed51 input=23210ef3477d8c4d]*/
    4497             : {
    4498          26 :     assert (PyDict_Check(self));
    4499          26 :     return dictiter_new(self, &PyDictRevIterKey_Type);
    4500             : }
    4501             : 
    4502             : static PyObject *
    4503          42 : dictiter_reduce(dictiterobject *di, PyObject *Py_UNUSED(ignored))
    4504             : {
    4505             :     /* copy the iterator state */
    4506          42 :     dictiterobject tmp = *di;
    4507          42 :     Py_XINCREF(tmp.di_dict);
    4508             : 
    4509          42 :     PyObject *list = PySequence_List((PyObject*)&tmp);
    4510          42 :     Py_XDECREF(tmp.di_dict);
    4511          42 :     if (list == NULL) {
    4512           0 :         return NULL;
    4513             :     }
    4514          42 :     return Py_BuildValue("N(N)", _PyEval_GetBuiltin(&_Py_ID(iter)), list);
    4515             : }
    4516             : 
    4517             : PyTypeObject PyDictRevIterItem_Type = {
    4518             :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    4519             :     "dict_reverseitemiterator",
    4520             :     sizeof(dictiterobject),
    4521             :     .tp_dealloc = (destructor)dictiter_dealloc,
    4522             :     .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
    4523             :     .tp_traverse = (traverseproc)dictiter_traverse,
    4524             :     .tp_iter = PyObject_SelfIter,
    4525             :     .tp_iternext = (iternextfunc)dictreviter_iternext,
    4526             :     .tp_methods = dictiter_methods
    4527             : };
    4528             : 
    4529             : PyTypeObject PyDictRevIterValue_Type = {
    4530             :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    4531             :     "dict_reversevalueiterator",
    4532             :     sizeof(dictiterobject),
    4533             :     .tp_dealloc = (destructor)dictiter_dealloc,
    4534             :     .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
    4535             :     .tp_traverse = (traverseproc)dictiter_traverse,
    4536             :     .tp_iter = PyObject_SelfIter,
    4537             :     .tp_iternext = (iternextfunc)dictreviter_iternext,
    4538             :     .tp_methods = dictiter_methods
    4539             : };
    4540             : 
    4541             : /***********************************************/
    4542             : /* View objects for keys(), items(), values(). */
    4543             : /***********************************************/
    4544             : 
    4545             : /* The instance lay-out is the same for all three; but the type differs. */
    4546             : 
    4547             : static void
    4548     1133520 : dictview_dealloc(_PyDictViewObject *dv)
    4549             : {
    4550             :     /* bpo-31095: UnTrack is needed before calling any callbacks */
    4551     1133520 :     _PyObject_GC_UNTRACK(dv);
    4552     1133520 :     Py_XDECREF(dv->dv_dict);
    4553     1133520 :     PyObject_GC_Del(dv);
    4554     1133520 : }
    4555             : 
    4556             : static int
    4557        5802 : dictview_traverse(_PyDictViewObject *dv, visitproc visit, void *arg)
    4558             : {
    4559        5802 :     Py_VISIT(dv->dv_dict);
    4560        5802 :     return 0;
    4561             : }
    4562             : 
    4563             : static Py_ssize_t
    4564       39500 : dictview_len(_PyDictViewObject *dv)
    4565             : {
    4566       39500 :     Py_ssize_t len = 0;
    4567       39500 :     if (dv->dv_dict != NULL)
    4568       39500 :         len = dv->dv_dict->ma_used;
    4569       39500 :     return len;
    4570             : }
    4571             : 
    4572             : PyObject *
    4573     1133520 : _PyDictView_New(PyObject *dict, PyTypeObject *type)
    4574             : {
    4575             :     _PyDictViewObject *dv;
    4576     1133520 :     if (dict == NULL) {
    4577           0 :         PyErr_BadInternalCall();
    4578           0 :         return NULL;
    4579             :     }
    4580     1133520 :     if (!PyDict_Check(dict)) {
    4581             :         /* XXX Get rid of this restriction later */
    4582           0 :         PyErr_Format(PyExc_TypeError,
    4583             :                      "%s() requires a dict argument, not '%s'",
    4584           0 :                      type->tp_name, Py_TYPE(dict)->tp_name);
    4585           0 :         return NULL;
    4586             :     }
    4587     1133520 :     dv = PyObject_GC_New(_PyDictViewObject, type);
    4588     1133520 :     if (dv == NULL)
    4589           0 :         return NULL;
    4590     1133520 :     Py_INCREF(dict);
    4591     1133520 :     dv->dv_dict = (PyDictObject *)dict;
    4592     1133520 :     _PyObject_GC_TRACK(dv);
    4593     1133520 :     return (PyObject *)dv;
    4594             : }
    4595             : 
    4596             : static PyObject *
    4597           6 : dictview_mapping(PyObject *view, void *Py_UNUSED(ignored)) {
    4598           6 :     assert(view != NULL);
    4599           6 :     assert(PyDictKeys_Check(view)
    4600             :            || PyDictValues_Check(view)
    4601             :            || PyDictItems_Check(view));
    4602           6 :     PyObject *mapping = (PyObject *)((_PyDictViewObject *)view)->dv_dict;
    4603           6 :     return PyDictProxy_New(mapping);
    4604             : }
    4605             : 
    4606             : static PyGetSetDef dictview_getset[] = {
    4607             :     {"mapping", dictview_mapping, (setter)NULL,
    4608             :      "dictionary that this view refers to", NULL},
    4609             :     {0}
    4610             : };
    4611             : 
    4612             : /* TODO(guido): The views objects are not complete:
    4613             : 
    4614             :  * support more set operations
    4615             :  * support arbitrary mappings?
    4616             :    - either these should be static or exported in dictobject.h
    4617             :    - if public then they should probably be in builtins
    4618             : */
    4619             : 
    4620             : /* Return 1 if self is a subset of other, iterating over self;
    4621             :    0 if not; -1 if an error occurred. */
    4622             : static int
    4623          93 : all_contained_in(PyObject *self, PyObject *other)
    4624             : {
    4625          93 :     PyObject *iter = PyObject_GetIter(self);
    4626          93 :     int ok = 1;
    4627             : 
    4628          93 :     if (iter == NULL)
    4629           0 :         return -1;
    4630         196 :     for (;;) {
    4631         289 :         PyObject *next = PyIter_Next(iter);
    4632         289 :         if (next == NULL) {
    4633          71 :             if (PyErr_Occurred())
    4634           0 :                 ok = -1;
    4635          71 :             break;
    4636             :         }
    4637         218 :         ok = PySequence_Contains(other, next);
    4638         218 :         Py_DECREF(next);
    4639         218 :         if (ok <= 0)
    4640          22 :             break;
    4641             :     }
    4642          93 :     Py_DECREF(iter);
    4643          93 :     return ok;
    4644             : }
    4645             : 
    4646             : static PyObject *
    4647         118 : dictview_richcompare(PyObject *self, PyObject *other, int op)
    4648             : {
    4649             :     Py_ssize_t len_self, len_other;
    4650             :     int ok;
    4651             :     PyObject *result;
    4652             : 
    4653         118 :     assert(self != NULL);
    4654         118 :     assert(PyDictViewSet_Check(self));
    4655         118 :     assert(other != NULL);
    4656             : 
    4657         118 :     if (!PyAnySet_Check(other) && !PyDictViewSet_Check(other))
    4658           2 :         Py_RETURN_NOTIMPLEMENTED;
    4659             : 
    4660         116 :     len_self = PyObject_Size(self);
    4661         116 :     if (len_self < 0)
    4662           0 :         return NULL;
    4663         116 :     len_other = PyObject_Size(other);
    4664         116 :     if (len_other < 0)
    4665           0 :         return NULL;
    4666             : 
    4667         116 :     ok = 0;
    4668         116 :     switch(op) {
    4669             : 
    4670          59 :     case Py_NE:
    4671             :     case Py_EQ:
    4672          59 :         if (len_self == len_other)
    4673          48 :             ok = all_contained_in(self, other);
    4674          59 :         if (op == Py_NE && ok >= 0)
    4675          17 :             ok = !ok;
    4676          59 :         break;
    4677             : 
    4678           9 :     case Py_LT:
    4679           9 :         if (len_self < len_other)
    4680           5 :             ok = all_contained_in(self, other);
    4681           9 :         break;
    4682             : 
    4683           9 :       case Py_LE:
    4684           9 :           if (len_self <= len_other)
    4685           7 :               ok = all_contained_in(self, other);
    4686           9 :           break;
    4687             : 
    4688           9 :     case Py_GT:
    4689           9 :         if (len_self > len_other)
    4690           5 :             ok = all_contained_in(other, self);
    4691           9 :         break;
    4692             : 
    4693          30 :     case Py_GE:
    4694          30 :         if (len_self >= len_other)
    4695          28 :             ok = all_contained_in(other, self);
    4696          30 :         break;
    4697             : 
    4698             :     }
    4699         116 :     if (ok < 0)
    4700           6 :         return NULL;
    4701         110 :     result = ok ? Py_True : Py_False;
    4702         110 :     Py_INCREF(result);
    4703         110 :     return result;
    4704             : }
    4705             : 
    4706             : static PyObject *
    4707         501 : dictview_repr(_PyDictViewObject *dv)
    4708             : {
    4709             :     PyObject *seq;
    4710         501 :     PyObject *result = NULL;
    4711             :     Py_ssize_t rc;
    4712             : 
    4713         501 :     rc = Py_ReprEnter((PyObject *)dv);
    4714         501 :     if (rc != 0) {
    4715           6 :         return rc > 0 ? PyUnicode_FromString("...") : NULL;
    4716             :     }
    4717         495 :     seq = PySequence_List((PyObject *)dv);
    4718         495 :     if (seq == NULL) {
    4719           0 :         goto Done;
    4720             :     }
    4721         495 :     result = PyUnicode_FromFormat("%s(%R)", Py_TYPE(dv)->tp_name, seq);
    4722         495 :     Py_DECREF(seq);
    4723             : 
    4724         495 : Done:
    4725         495 :     Py_ReprLeave((PyObject *)dv);
    4726         495 :     return result;
    4727             : }
    4728             : 
    4729             : /*** dict_keys ***/
    4730             : 
    4731             : static PyObject *
    4732      112503 : dictkeys_iter(_PyDictViewObject *dv)
    4733             : {
    4734      112503 :     if (dv->dv_dict == NULL) {
    4735           0 :         Py_RETURN_NONE;
    4736             :     }
    4737      112503 :     return dictiter_new(dv->dv_dict, &PyDictIterKey_Type);
    4738             : }
    4739             : 
    4740             : static int
    4741      284201 : dictkeys_contains(_PyDictViewObject *dv, PyObject *obj)
    4742             : {
    4743      284201 :     if (dv->dv_dict == NULL)
    4744           0 :         return 0;
    4745      284201 :     return PyDict_Contains((PyObject *)dv->dv_dict, obj);
    4746             : }
    4747             : 
    4748             : static PySequenceMethods dictkeys_as_sequence = {
    4749             :     (lenfunc)dictview_len,              /* sq_length */
    4750             :     0,                                  /* sq_concat */
    4751             :     0,                                  /* sq_repeat */
    4752             :     0,                                  /* sq_item */
    4753             :     0,                                  /* sq_slice */
    4754             :     0,                                  /* sq_ass_item */
    4755             :     0,                                  /* sq_ass_slice */
    4756             :     (objobjproc)dictkeys_contains,      /* sq_contains */
    4757             : };
    4758             : 
    4759             : // Create an set object from dictviews object.
    4760             : // Returns a new reference.
    4761             : // This utility function is used by set operations.
    4762             : static PyObject*
    4763         191 : dictviews_to_set(PyObject *self)
    4764             : {
    4765         191 :     PyObject *left = self;
    4766         191 :     if (PyDictKeys_Check(self)) {
    4767             :         // PySet_New() has fast path for the dict object.
    4768         165 :         PyObject *dict = (PyObject *)((_PyDictViewObject *)self)->dv_dict;
    4769         165 :         if (PyDict_CheckExact(dict)) {
    4770         165 :             left = dict;
    4771             :         }
    4772             :     }
    4773         191 :     return PySet_New(left);
    4774             : }
    4775             : 
    4776             : static PyObject*
    4777         153 : dictviews_sub(PyObject *self, PyObject *other)
    4778             : {
    4779         153 :     PyObject *result = dictviews_to_set(self);
    4780         153 :     if (result == NULL) {
    4781           0 :         return NULL;
    4782             :     }
    4783             : 
    4784         153 :     PyObject *tmp = PyObject_CallMethodOneArg(
    4785             :             result, &_Py_ID(difference_update), other);
    4786         153 :     if (tmp == NULL) {
    4787           2 :         Py_DECREF(result);
    4788           2 :         return NULL;
    4789             :     }
    4790             : 
    4791         151 :     Py_DECREF(tmp);
    4792         151 :     return result;
    4793             : }
    4794             : 
    4795             : static int
    4796             : dictitems_contains(_PyDictViewObject *dv, PyObject *obj);
    4797             : 
    4798             : PyObject *
    4799          29 : _PyDictView_Intersect(PyObject* self, PyObject *other)
    4800             : {
    4801             :     PyObject *result;
    4802             :     PyObject *it;
    4803             :     PyObject *key;
    4804             :     Py_ssize_t len_self;
    4805             :     int rv;
    4806             :     int (*dict_contains)(_PyDictViewObject *, PyObject *);
    4807             : 
    4808             :     /* Python interpreter swaps parameters when dict view
    4809             :        is on right side of & */
    4810          29 :     if (!PyDictViewSet_Check(self)) {
    4811           2 :         PyObject *tmp = other;
    4812           2 :         other = self;
    4813           2 :         self = tmp;
    4814             :     }
    4815             : 
    4816          29 :     len_self = dictview_len((_PyDictViewObject *)self);
    4817             : 
    4818             :     /* if other is a set and self is smaller than other,
    4819             :        reuse set intersection logic */
    4820          29 :     if (PySet_CheckExact(other) && len_self <= PyObject_Size(other)) {
    4821           7 :         return PyObject_CallMethodObjArgs(
    4822             :                 other, &_Py_ID(intersection), self, NULL);
    4823             :     }
    4824             : 
    4825             :     /* if other is another dict view, and it is bigger than self,
    4826             :        swap them */
    4827          22 :     if (PyDictViewSet_Check(other)) {
    4828          12 :         Py_ssize_t len_other = dictview_len((_PyDictViewObject *)other);
    4829          12 :         if (len_other > len_self) {
    4830           3 :             PyObject *tmp = other;
    4831           3 :             other = self;
    4832           3 :             self = tmp;
    4833             :         }
    4834             :     }
    4835             : 
    4836             :     /* at this point, two things should be true
    4837             :        1. self is a dictview
    4838             :        2. if other is a dictview then it is smaller than self */
    4839          22 :     result = PySet_New(NULL);
    4840          22 :     if (result == NULL)
    4841           0 :         return NULL;
    4842             : 
    4843          22 :     it = PyObject_GetIter(other);
    4844          22 :     if (it == NULL) {
    4845           2 :         Py_DECREF(result);
    4846           2 :         return NULL;
    4847             :     }
    4848             : 
    4849          20 :     if (PyDictKeys_Check(self)) {
    4850          14 :         dict_contains = dictkeys_contains;
    4851             :     }
    4852             :     /* else PyDictItems_Check(self) */
    4853             :     else {
    4854           6 :         dict_contains = dictitems_contains;
    4855             :     }
    4856             : 
    4857          51 :     while ((key = PyIter_Next(it)) != NULL) {
    4858          31 :         rv = dict_contains((_PyDictViewObject *)self, key);
    4859          31 :         if (rv < 0) {
    4860           0 :             goto error;
    4861             :         }
    4862          31 :         if (rv) {
    4863          19 :             if (PySet_Add(result, key)) {
    4864           0 :                 goto error;
    4865             :             }
    4866             :         }
    4867          31 :         Py_DECREF(key);
    4868             :     }
    4869          20 :     Py_DECREF(it);
    4870          20 :     if (PyErr_Occurred()) {
    4871           0 :         Py_DECREF(result);
    4872           0 :         return NULL;
    4873             :     }
    4874          20 :     return result;
    4875             : 
    4876           0 : error:
    4877           0 :     Py_DECREF(it);
    4878           0 :     Py_DECREF(result);
    4879           0 :     Py_DECREF(key);
    4880           0 :     return NULL;
    4881             : }
    4882             : 
    4883             : static PyObject*
    4884          25 : dictviews_or(PyObject* self, PyObject *other)
    4885             : {
    4886          25 :     PyObject *result = dictviews_to_set(self);
    4887          25 :     if (result == NULL) {
    4888           0 :         return NULL;
    4889             :     }
    4890             : 
    4891          25 :     if (_PySet_Update(result, other) < 0) {
    4892           2 :         Py_DECREF(result);
    4893           2 :         return NULL;
    4894             :     }
    4895          23 :     return result;
    4896             : }
    4897             : 
    4898             : static PyObject *
    4899         105 : dictitems_xor(PyObject *self, PyObject *other)
    4900             : {
    4901         105 :     assert(PyDictItems_Check(self));
    4902         105 :     assert(PyDictItems_Check(other));
    4903         105 :     PyObject *d1 = (PyObject *)((_PyDictViewObject *)self)->dv_dict;
    4904         105 :     PyObject *d2 = (PyObject *)((_PyDictViewObject *)other)->dv_dict;
    4905             : 
    4906         105 :     PyObject *temp_dict = PyDict_Copy(d1);
    4907         105 :     if (temp_dict == NULL) {
    4908           0 :         return NULL;
    4909             :     }
    4910         105 :     PyObject *result_set = PySet_New(NULL);
    4911         105 :     if (result_set == NULL) {
    4912           0 :         Py_CLEAR(temp_dict);
    4913           0 :         return NULL;
    4914             :     }
    4915             : 
    4916         105 :     PyObject *key = NULL, *val1 = NULL, *val2 = NULL;
    4917         105 :     Py_ssize_t pos = 0;
    4918             :     Py_hash_t hash;
    4919             : 
    4920        1102 :     while (_PyDict_Next(d2, &pos, &key, &val2, &hash)) {
    4921         997 :         Py_INCREF(key);
    4922         997 :         Py_INCREF(val2);
    4923         997 :         val1 = _PyDict_GetItem_KnownHash(temp_dict, key, hash);
    4924             : 
    4925             :         int to_delete;
    4926         997 :         if (val1 == NULL) {
    4927         510 :             if (PyErr_Occurred()) {
    4928           0 :                 goto error;
    4929             :             }
    4930         510 :             to_delete = 0;
    4931             :         }
    4932             :         else {
    4933         487 :             Py_INCREF(val1);
    4934         487 :             to_delete = PyObject_RichCompareBool(val1, val2, Py_EQ);
    4935         487 :             if (to_delete < 0) {
    4936           0 :                 goto error;
    4937             :             }
    4938             :         }
    4939             : 
    4940         997 :         if (to_delete) {
    4941         166 :             if (_PyDict_DelItem_KnownHash(temp_dict, key, hash) < 0) {
    4942           0 :                 goto error;
    4943             :             }
    4944             :         }
    4945             :         else {
    4946         831 :             PyObject *pair = PyTuple_Pack(2, key, val2);
    4947         831 :             if (pair == NULL) {
    4948           0 :                 goto error;
    4949             :             }
    4950         831 :             if (PySet_Add(result_set, pair) < 0) {
    4951           0 :                 Py_DECREF(pair);
    4952           0 :                 goto error;
    4953             :             }
    4954         831 :             Py_DECREF(pair);
    4955             :         }
    4956         997 :         Py_DECREF(key);
    4957         997 :         Py_XDECREF(val1);
    4958         997 :         Py_DECREF(val2);
    4959             :     }
    4960         105 :     key = val1 = val2 = NULL;
    4961             : 
    4962         105 :     PyObject *remaining_pairs = PyObject_CallMethodNoArgs(
    4963             :             temp_dict, &_Py_ID(items));
    4964         105 :     if (remaining_pairs == NULL) {
    4965           0 :         goto error;
    4966             :     }
    4967         105 :     if (_PySet_Update(result_set, remaining_pairs) < 0) {
    4968           0 :         Py_DECREF(remaining_pairs);
    4969           0 :         goto error;
    4970             :     }
    4971         105 :     Py_DECREF(temp_dict);
    4972         105 :     Py_DECREF(remaining_pairs);
    4973         105 :     return result_set;
    4974             : 
    4975           0 : error:
    4976           0 :     Py_XDECREF(temp_dict);
    4977           0 :     Py_XDECREF(result_set);
    4978           0 :     Py_XDECREF(key);
    4979           0 :     Py_XDECREF(val1);
    4980           0 :     Py_XDECREF(val2);
    4981           0 :     return NULL;
    4982             : }
    4983             : 
    4984             : static PyObject*
    4985         118 : dictviews_xor(PyObject* self, PyObject *other)
    4986             : {
    4987         118 :     if (PyDictItems_Check(self) && PyDictItems_Check(other)) {
    4988         105 :         return dictitems_xor(self, other);
    4989             :     }
    4990          13 :     PyObject *result = dictviews_to_set(self);
    4991          13 :     if (result == NULL) {
    4992           0 :         return NULL;
    4993             :     }
    4994             : 
    4995          13 :     PyObject *tmp = PyObject_CallMethodOneArg(
    4996             :             result, &_Py_ID(symmetric_difference_update), other);
    4997          13 :     if (tmp == NULL) {
    4998           2 :         Py_DECREF(result);
    4999           2 :         return NULL;
    5000             :     }
    5001             : 
    5002          11 :     Py_DECREF(tmp);
    5003          11 :     return result;
    5004             : }
    5005             : 
    5006             : static PyNumberMethods dictviews_as_number = {
    5007             :     0,                                  /*nb_add*/
    5008             :     (binaryfunc)dictviews_sub,          /*nb_subtract*/
    5009             :     0,                                  /*nb_multiply*/
    5010             :     0,                                  /*nb_remainder*/
    5011             :     0,                                  /*nb_divmod*/
    5012             :     0,                                  /*nb_power*/
    5013             :     0,                                  /*nb_negative*/
    5014             :     0,                                  /*nb_positive*/
    5015             :     0,                                  /*nb_absolute*/
    5016             :     0,                                  /*nb_bool*/
    5017             :     0,                                  /*nb_invert*/
    5018             :     0,                                  /*nb_lshift*/
    5019             :     0,                                  /*nb_rshift*/
    5020             :     (binaryfunc)_PyDictView_Intersect,  /*nb_and*/
    5021             :     (binaryfunc)dictviews_xor,          /*nb_xor*/
    5022             :     (binaryfunc)dictviews_or,           /*nb_or*/
    5023             : };
    5024             : 
    5025             : static PyObject*
    5026          29 : dictviews_isdisjoint(PyObject *self, PyObject *other)
    5027             : {
    5028             :     PyObject *it;
    5029          29 :     PyObject *item = NULL;
    5030             : 
    5031          29 :     if (self == other) {
    5032           0 :         if (dictview_len((_PyDictViewObject *)self) == 0)
    5033           0 :             Py_RETURN_TRUE;
    5034             :         else
    5035           0 :             Py_RETURN_FALSE;
    5036             :     }
    5037             : 
    5038             :     /* Iterate over the shorter object (only if other is a set,
    5039             :      * because PySequence_Contains may be expensive otherwise): */
    5040          29 :     if (PyAnySet_Check(other) || PyDictViewSet_Check(other)) {
    5041          18 :         Py_ssize_t len_self = dictview_len((_PyDictViewObject *)self);
    5042          18 :         Py_ssize_t len_other = PyObject_Size(other);
    5043          18 :         if (len_other == -1)
    5044           0 :             return NULL;
    5045             : 
    5046          18 :         if ((len_other > len_self)) {
    5047           4 :             PyObject *tmp = other;
    5048           4 :             other = self;
    5049           4 :             self = tmp;
    5050             :         }
    5051             :     }
    5052             : 
    5053          29 :     it = PyObject_GetIter(other);
    5054          29 :     if (it == NULL)
    5055           0 :         return NULL;
    5056             : 
    5057          58 :     while ((item = PyIter_Next(it)) != NULL) {
    5058          37 :         int contains = PySequence_Contains(self, item);
    5059          37 :         Py_DECREF(item);
    5060          37 :         if (contains == -1) {
    5061           0 :             Py_DECREF(it);
    5062           0 :             return NULL;
    5063             :         }
    5064             : 
    5065          37 :         if (contains) {
    5066           8 :             Py_DECREF(it);
    5067           8 :             Py_RETURN_FALSE;
    5068             :         }
    5069             :     }
    5070          21 :     Py_DECREF(it);
    5071          21 :     if (PyErr_Occurred())
    5072           0 :         return NULL; /* PyIter_Next raised an exception. */
    5073          21 :     Py_RETURN_TRUE;
    5074             : }
    5075             : 
    5076             : PyDoc_STRVAR(isdisjoint_doc,
    5077             : "Return True if the view and the given iterable have a null intersection.");
    5078             : 
    5079             : static PyObject* dictkeys_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored));
    5080             : 
    5081             : PyDoc_STRVAR(reversed_keys_doc,
    5082             : "Return a reverse iterator over the dict keys.");
    5083             : 
    5084             : static PyMethodDef dictkeys_methods[] = {
    5085             :     {"isdisjoint",      (PyCFunction)dictviews_isdisjoint,  METH_O,
    5086             :      isdisjoint_doc},
    5087             :     {"__reversed__",    _PyCFunction_CAST(dictkeys_reversed),    METH_NOARGS,
    5088             :      reversed_keys_doc},
    5089             :     {NULL,              NULL}           /* sentinel */
    5090             : };
    5091             : 
    5092             : PyTypeObject PyDictKeys_Type = {
    5093             :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    5094             :     "dict_keys",                                /* tp_name */
    5095             :     sizeof(_PyDictViewObject),                  /* tp_basicsize */
    5096             :     0,                                          /* tp_itemsize */
    5097             :     /* methods */
    5098             :     (destructor)dictview_dealloc,               /* tp_dealloc */
    5099             :     0,                                          /* tp_vectorcall_offset */
    5100             :     0,                                          /* tp_getattr */
    5101             :     0,                                          /* tp_setattr */
    5102             :     0,                                          /* tp_as_async */
    5103             :     (reprfunc)dictview_repr,                    /* tp_repr */
    5104             :     &dictviews_as_number,                       /* tp_as_number */
    5105             :     &dictkeys_as_sequence,                      /* tp_as_sequence */
    5106             :     0,                                          /* tp_as_mapping */
    5107             :     0,                                          /* tp_hash */
    5108             :     0,                                          /* tp_call */
    5109             :     0,                                          /* tp_str */
    5110             :     PyObject_GenericGetAttr,                    /* tp_getattro */
    5111             :     0,                                          /* tp_setattro */
    5112             :     0,                                          /* tp_as_buffer */
    5113             :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
    5114             :     0,                                          /* tp_doc */
    5115             :     (traverseproc)dictview_traverse,            /* tp_traverse */
    5116             :     0,                                          /* tp_clear */
    5117             :     dictview_richcompare,                       /* tp_richcompare */
    5118             :     0,                                          /* tp_weaklistoffset */
    5119             :     (getiterfunc)dictkeys_iter,                 /* tp_iter */
    5120             :     0,                                          /* tp_iternext */
    5121             :     dictkeys_methods,                           /* tp_methods */
    5122             :     .tp_getset = dictview_getset,
    5123             : };
    5124             : 
    5125             : static PyObject *
    5126      117082 : dictkeys_new(PyObject *dict, PyObject *Py_UNUSED(ignored))
    5127             : {
    5128      117082 :     return _PyDictView_New(dict, &PyDictKeys_Type);
    5129             : }
    5130             : 
    5131             : static PyObject *
    5132           2 : dictkeys_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
    5133             : {
    5134           2 :     if (dv->dv_dict == NULL) {
    5135           0 :         Py_RETURN_NONE;
    5136             :     }
    5137           2 :     return dictiter_new(dv->dv_dict, &PyDictRevIterKey_Type);
    5138             : }
    5139             : 
    5140             : /*** dict_items ***/
    5141             : 
    5142             : static PyObject *
    5143      615175 : dictitems_iter(_PyDictViewObject *dv)
    5144             : {
    5145      615175 :     if (dv->dv_dict == NULL) {
    5146           0 :         Py_RETURN_NONE;
    5147             :     }
    5148      615175 :     return dictiter_new(dv->dv_dict, &PyDictIterItem_Type);
    5149             : }
    5150             : 
    5151             : static int
    5152         135 : dictitems_contains(_PyDictViewObject *dv, PyObject *obj)
    5153             : {
    5154             :     int result;
    5155             :     PyObject *key, *value, *found;
    5156         135 :     if (dv->dv_dict == NULL)
    5157           0 :         return 0;
    5158         135 :     if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 2)
    5159          10 :         return 0;
    5160         125 :     key = PyTuple_GET_ITEM(obj, 0);
    5161         125 :     value = PyTuple_GET_ITEM(obj, 1);
    5162         125 :     found = PyDict_GetItemWithError((PyObject *)dv->dv_dict, key);
    5163         125 :     if (found == NULL) {
    5164          16 :         if (PyErr_Occurred())
    5165           1 :             return -1;
    5166          15 :         return 0;
    5167             :     }
    5168         109 :     Py_INCREF(found);
    5169         109 :     result = PyObject_RichCompareBool(found, value, Py_EQ);
    5170         109 :     Py_DECREF(found);
    5171         109 :     return result;
    5172             : }
    5173             : 
    5174             : static PySequenceMethods dictitems_as_sequence = {
    5175             :     (lenfunc)dictview_len,              /* sq_length */
    5176             :     0,                                  /* sq_concat */
    5177             :     0,                                  /* sq_repeat */
    5178             :     0,                                  /* sq_item */
    5179             :     0,                                  /* sq_slice */
    5180             :     0,                                  /* sq_ass_item */
    5181             :     0,                                  /* sq_ass_slice */
    5182             :     (objobjproc)dictitems_contains,     /* sq_contains */
    5183             : };
    5184             : 
    5185             : static PyObject* dictitems_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored));
    5186             : 
    5187             : PyDoc_STRVAR(reversed_items_doc,
    5188             : "Return a reverse iterator over the dict items.");
    5189             : 
    5190             : static PyMethodDef dictitems_methods[] = {
    5191             :     {"isdisjoint",      (PyCFunction)dictviews_isdisjoint,  METH_O,
    5192             :      isdisjoint_doc},
    5193             :     {"__reversed__",    (PyCFunction)dictitems_reversed,    METH_NOARGS,
    5194             :      reversed_items_doc},
    5195             :     {NULL,              NULL}           /* sentinel */
    5196             : };
    5197             : 
    5198             : PyTypeObject PyDictItems_Type = {
    5199             :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    5200             :     "dict_items",                               /* tp_name */
    5201             :     sizeof(_PyDictViewObject),                  /* tp_basicsize */
    5202             :     0,                                          /* tp_itemsize */
    5203             :     /* methods */
    5204             :     (destructor)dictview_dealloc,               /* tp_dealloc */
    5205             :     0,                                          /* tp_vectorcall_offset */
    5206             :     0,                                          /* tp_getattr */
    5207             :     0,                                          /* tp_setattr */
    5208             :     0,                                          /* tp_as_async */
    5209             :     (reprfunc)dictview_repr,                    /* tp_repr */
    5210             :     &dictviews_as_number,                       /* tp_as_number */
    5211             :     &dictitems_as_sequence,                     /* tp_as_sequence */
    5212             :     0,                                          /* tp_as_mapping */
    5213             :     0,                                          /* tp_hash */
    5214             :     0,                                          /* tp_call */
    5215             :     0,                                          /* tp_str */
    5216             :     PyObject_GenericGetAttr,                    /* tp_getattro */
    5217             :     0,                                          /* tp_setattro */
    5218             :     0,                                          /* tp_as_buffer */
    5219             :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
    5220             :     0,                                          /* tp_doc */
    5221             :     (traverseproc)dictview_traverse,            /* tp_traverse */
    5222             :     0,                                          /* tp_clear */
    5223             :     dictview_richcompare,                       /* tp_richcompare */
    5224             :     0,                                          /* tp_weaklistoffset */
    5225             :     (getiterfunc)dictitems_iter,                /* tp_iter */
    5226             :     0,                                          /* tp_iternext */
    5227             :     dictitems_methods,                          /* tp_methods */
    5228             :     .tp_getset = dictview_getset,
    5229             : };
    5230             : 
    5231             : static PyObject *
    5232      618264 : dictitems_new(PyObject *dict, PyObject *Py_UNUSED(ignored))
    5233             : {
    5234      618264 :     return _PyDictView_New(dict, &PyDictItems_Type);
    5235             : }
    5236             : 
    5237             : static PyObject *
    5238           9 : dictitems_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
    5239             : {
    5240           9 :     if (dv->dv_dict == NULL) {
    5241           0 :         Py_RETURN_NONE;
    5242             :     }
    5243           9 :     return dictiter_new(dv->dv_dict, &PyDictRevIterItem_Type);
    5244             : }
    5245             : 
    5246             : /*** dict_values ***/
    5247             : 
    5248             : static PyObject *
    5249      372030 : dictvalues_iter(_PyDictViewObject *dv)
    5250             : {
    5251      372030 :     if (dv->dv_dict == NULL) {
    5252           0 :         Py_RETURN_NONE;
    5253             :     }
    5254      372030 :     return dictiter_new(dv->dv_dict, &PyDictIterValue_Type);
    5255             : }
    5256             : 
    5257             : static PySequenceMethods dictvalues_as_sequence = {
    5258             :     (lenfunc)dictview_len,              /* sq_length */
    5259             :     0,                                  /* sq_concat */
    5260             :     0,                                  /* sq_repeat */
    5261             :     0,                                  /* sq_item */
    5262             :     0,                                  /* sq_slice */
    5263             :     0,                                  /* sq_ass_item */
    5264             :     0,                                  /* sq_ass_slice */
    5265             :     (objobjproc)0,                      /* sq_contains */
    5266             : };
    5267             : 
    5268             : static PyObject* dictvalues_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored));
    5269             : 
    5270             : PyDoc_STRVAR(reversed_values_doc,
    5271             : "Return a reverse iterator over the dict values.");
    5272             : 
    5273             : static PyMethodDef dictvalues_methods[] = {
    5274             :     {"__reversed__",    (PyCFunction)dictvalues_reversed,    METH_NOARGS,
    5275             :      reversed_values_doc},
    5276             :     {NULL,              NULL}           /* sentinel */
    5277             : };
    5278             : 
    5279             : PyTypeObject PyDictValues_Type = {
    5280             :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    5281             :     "dict_values",                              /* tp_name */
    5282             :     sizeof(_PyDictViewObject),                  /* tp_basicsize */
    5283             :     0,                                          /* tp_itemsize */
    5284             :     /* methods */
    5285             :     (destructor)dictview_dealloc,               /* tp_dealloc */
    5286             :     0,                                          /* tp_vectorcall_offset */
    5287             :     0,                                          /* tp_getattr */
    5288             :     0,                                          /* tp_setattr */
    5289             :     0,                                          /* tp_as_async */
    5290             :     (reprfunc)dictview_repr,                    /* tp_repr */
    5291             :     0,                                          /* tp_as_number */
    5292             :     &dictvalues_as_sequence,                    /* tp_as_sequence */
    5293             :     0,                                          /* tp_as_mapping */
    5294             :     0,                                          /* tp_hash */
    5295             :     0,                                          /* tp_call */
    5296             :     0,                                          /* tp_str */
    5297             :     PyObject_GenericGetAttr,                    /* tp_getattro */
    5298             :     0,                                          /* tp_setattro */
    5299             :     0,                                          /* tp_as_buffer */
    5300             :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
    5301             :     0,                                          /* tp_doc */
    5302             :     (traverseproc)dictview_traverse,            /* tp_traverse */
    5303             :     0,                                          /* tp_clear */
    5304             :     0,                                          /* tp_richcompare */
    5305             :     0,                                          /* tp_weaklistoffset */
    5306             :     (getiterfunc)dictvalues_iter,               /* tp_iter */
    5307             :     0,                                          /* tp_iternext */
    5308             :     dictvalues_methods,                         /* tp_methods */
    5309             :     .tp_getset = dictview_getset,
    5310             : };
    5311             : 
    5312             : static PyObject *
    5313      376154 : dictvalues_new(PyObject *dict, PyObject *Py_UNUSED(ignored))
    5314             : {
    5315      376154 :     return _PyDictView_New(dict, &PyDictValues_Type);
    5316             : }
    5317             : 
    5318             : static PyObject *
    5319          14 : dictvalues_reversed(_PyDictViewObject *dv, PyObject *Py_UNUSED(ignored))
    5320             : {
    5321          14 :     if (dv->dv_dict == NULL) {
    5322           0 :         Py_RETURN_NONE;
    5323             :     }
    5324          14 :     return dictiter_new(dv->dv_dict, &PyDictRevIterValue_Type);
    5325             : }
    5326             : 
    5327             : 
    5328             : /* Returns NULL if cannot allocate a new PyDictKeysObject,
    5329             :    but does not set an error */
    5330             : PyDictKeysObject *
    5331      681619 : _PyDict_NewKeysForClass(void)
    5332             : {
    5333      681619 :     PyDictKeysObject *keys = new_keys_object(NEXT_LOG2_SHARED_KEYS_MAX_SIZE, 1);
    5334      681619 :     if (keys == NULL) {
    5335           0 :         PyErr_Clear();
    5336             :     }
    5337             :     else {
    5338      681619 :         assert(keys->dk_nentries == 0);
    5339             :         /* Set to max size+1 as it will shrink by one before each new object */
    5340      681619 :         keys->dk_usable = SHARED_KEYS_MAX_SIZE;
    5341      681619 :         keys->dk_kind = DICT_KEYS_SPLIT;
    5342             :     }
    5343      681619 :     return keys;
    5344             : }
    5345             : 
    5346             : #define CACHED_KEYS(tp) (((PyHeapTypeObject*)tp)->ht_cached_keys)
    5347             : 
    5348             : static int
    5349     8721090 : init_inline_values(PyObject *obj, PyTypeObject *tp)
    5350             : {
    5351     8721090 :     assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE);
    5352             :     // assert(type->tp_dictoffset > 0);  -- TO DO Update this assert.
    5353     8721090 :     assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
    5354     8721090 :     PyDictKeysObject *keys = CACHED_KEYS(tp);
    5355     8721090 :     assert(keys != NULL);
    5356     8721090 :     if (keys->dk_usable > 1) {
    5357     1402130 :         keys->dk_usable--;
    5358             :     }
    5359     8721090 :     Py_ssize_t size = shared_keys_usable_size(keys);
    5360     8721090 :     assert(size > 0);
    5361     8721090 :     PyDictValues *values = new_values(size);
    5362     8721090 :     if (values == NULL) {
    5363           0 :         PyErr_NoMemory();
    5364           0 :         return -1;
    5365             :     }
    5366     8721090 :     assert(((uint8_t *)values)[-1] >= size+2);
    5367     8721090 :     ((uint8_t *)values)[-2] = 0;
    5368    69413500 :     for (int i = 0; i < size; i++) {
    5369    60692400 :         values->values[i] = NULL;
    5370             :     }
    5371     8721090 :     *_PyObject_ValuesPointer(obj) = values;
    5372     8721090 :     return 0;
    5373             : }
    5374             : 
    5375             : int
    5376    10529000 : _PyObject_InitializeDict(PyObject *obj)
    5377             : {
    5378    10529000 :     PyTypeObject *tp = Py_TYPE(obj);
    5379    10529000 :     if (tp->tp_dictoffset == 0) {
    5380     1807940 :         return 0;
    5381             :     }
    5382     8721090 :     if (tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) {
    5383             :         OBJECT_STAT_INC(new_values);
    5384     8721090 :         return init_inline_values(obj, tp);
    5385             :     }
    5386             :     PyObject *dict;
    5387           4 :     if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE) && CACHED_KEYS(tp)) {
    5388           0 :         dictkeys_incref(CACHED_KEYS(tp));
    5389           0 :         dict = new_dict_with_shared_keys(CACHED_KEYS(tp));
    5390             :     }
    5391             :     else {
    5392           4 :         dict = PyDict_New();
    5393             :     }
    5394           4 :     if (dict == NULL) {
    5395           0 :         return -1;
    5396             :     }
    5397           4 :     PyObject **dictptr = _PyObject_DictPointer(obj);
    5398           4 :     *dictptr = dict;
    5399           4 :     return 0;
    5400             : }
    5401             : 
    5402             : static PyObject *
    5403      247233 : make_dict_from_instance_attributes(PyDictKeysObject *keys, PyDictValues *values)
    5404             : {
    5405      247233 :     dictkeys_incref(keys);
    5406      247233 :     Py_ssize_t used = 0;
    5407      247233 :     Py_ssize_t track = 0;
    5408     2038720 :     for (Py_ssize_t i = 0; i < shared_keys_usable_size(keys); i++) {
    5409     1791480 :         PyObject *val = values->values[i];
    5410     1791480 :         if (val != NULL) {
    5411      778114 :             used += 1;
    5412      778114 :             track += _PyObject_GC_MAY_BE_TRACKED(val);
    5413             :         }
    5414             :     }
    5415      247233 :     PyObject *res = new_dict(keys, values, used, 0);
    5416      247233 :     if (track && res) {
    5417      125924 :         _PyObject_GC_TRACK(res);
    5418             :     }
    5419      247233 :     return res;
    5420             : }
    5421             : 
    5422             : PyObject *
    5423         576 : _PyObject_MakeDictFromInstanceAttributes(PyObject *obj, PyDictValues *values)
    5424             : {
    5425         576 :     assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
    5426         576 :     PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
    5427             :     OBJECT_STAT_INC(dict_materialized_on_request);
    5428         576 :     return make_dict_from_instance_attributes(keys, values);
    5429             : }
    5430             : 
    5431             : int
    5432     7700960 : _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
    5433             :                               PyObject *name, PyObject *value)
    5434             : {
    5435     7700960 :     PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
    5436     7700960 :     assert(keys != NULL);
    5437     7700960 :     assert(values != NULL);
    5438     7700960 :     assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
    5439     7700960 :     Py_ssize_t ix = DKIX_EMPTY;
    5440     7700960 :     if (PyUnicode_CheckExact(name)) {
    5441     7700960 :         ix = insert_into_dictkeys(keys, name);
    5442             :     }
    5443     7700960 :     if (ix == DKIX_EMPTY) {
    5444             : #ifdef Py_STATS
    5445             :         if (PyUnicode_CheckExact(name)) {
    5446             :             if (shared_keys_usable_size(keys) == SHARED_KEYS_MAX_SIZE) {
    5447             :                 OBJECT_STAT_INC(dict_materialized_too_big);
    5448             :             }
    5449             :             else {
    5450             :                 OBJECT_STAT_INC(dict_materialized_new_key);
    5451             :             }
    5452             :         }
    5453             :         else {
    5454             :             OBJECT_STAT_INC(dict_materialized_str_subclass);
    5455             :         }
    5456             : #endif
    5457      111105 :         PyObject *dict = make_dict_from_instance_attributes(keys, values);
    5458      111105 :         if (dict == NULL) {
    5459           0 :             return -1;
    5460             :         }
    5461      111105 :         *_PyObject_ValuesPointer(obj) = NULL;
    5462      111105 :         *_PyObject_ManagedDictPointer(obj) = dict;
    5463      111105 :         if (value == NULL) {
    5464           1 :             return PyDict_DelItem(dict, name);
    5465             :         }
    5466             :         else {
    5467      111104 :             return PyDict_SetItem(dict, name, value);
    5468             :         }
    5469             :     }
    5470     7589860 :     PyObject *old_value = values->values[ix];
    5471     7589860 :     Py_XINCREF(value);
    5472     7589860 :     values->values[ix] = value;
    5473     7589860 :     if (old_value == NULL) {
    5474     3465220 :         if (value == NULL) {
    5475          75 :             PyErr_Format(PyExc_AttributeError,
    5476             :                          "'%.100s' object has no attribute '%U'",
    5477          75 :                          Py_TYPE(obj)->tp_name, name);
    5478          75 :             return -1;
    5479             :         }
    5480     3465150 :         _PyDictValues_AddToInsertionOrder(values, ix);
    5481             :     }
    5482             :     else {
    5483     4124640 :         if (value == NULL) {
    5484     3372990 :             delete_index_from_values(values, ix);
    5485             :         }
    5486     4124640 :         Py_DECREF(old_value);
    5487             :     }
    5488     7589780 :     return 0;
    5489             : }
    5490             : 
    5491             : PyObject *
    5492    63073600 : _PyObject_GetInstanceAttribute(PyObject *obj, PyDictValues *values,
    5493             :                               PyObject *name)
    5494             : {
    5495    63073600 :     assert(PyUnicode_CheckExact(name));
    5496    63073600 :     PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
    5497    63073600 :     assert(keys != NULL);
    5498    63073600 :     Py_ssize_t ix = _PyDictKeys_StringLookup(keys, name);
    5499    63073600 :     if (ix == DKIX_EMPTY) {
    5500    41229200 :         return NULL;
    5501             :     }
    5502    21844500 :     PyObject *value = values->values[ix];
    5503    21844500 :     Py_XINCREF(value);
    5504    21844500 :     return value;
    5505             : }
    5506             : 
    5507             : int
    5508       63142 : _PyObject_IsInstanceDictEmpty(PyObject *obj)
    5509             : {
    5510       63142 :     PyTypeObject *tp = Py_TYPE(obj);
    5511       63142 :     if (tp->tp_dictoffset == 0) {
    5512        1623 :         return 1;
    5513             :     }
    5514             :     PyObject **dictptr;
    5515       61519 :     if (tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) {
    5516       60805 :         PyDictValues *values = *_PyObject_ValuesPointer(obj);
    5517       60805 :         if (values) {
    5518       51408 :             PyDictKeysObject *keys = CACHED_KEYS(tp);
    5519       51471 :             for (Py_ssize_t i = 0; i < keys->dk_nentries; i++) {
    5520       50944 :                 if (values->values[i] != NULL) {
    5521       50881 :                     return 0;
    5522             :                 }
    5523             :             }
    5524         527 :             return 1;
    5525             :         }
    5526        9397 :         dictptr = _PyObject_ManagedDictPointer(obj);
    5527             :     }
    5528             :     else {
    5529         714 :        dictptr = _PyObject_DictPointer(obj);
    5530             :     }
    5531       10111 :     PyObject *dict = *dictptr;
    5532       10111 :     if (dict == NULL) {
    5533         960 :         return 1;
    5534             :     }
    5535        9151 :     return ((PyDictObject *)dict)->ma_used == 0;
    5536             : }
    5537             : 
    5538             : 
    5539             : int
    5540   105863000 : _PyObject_VisitInstanceAttributes(PyObject *self, visitproc visit, void *arg)
    5541             : {
    5542   105863000 :     PyTypeObject *tp = Py_TYPE(self);
    5543   105863000 :     assert(Py_TYPE(self)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
    5544   105863000 :     PyDictValues **values_ptr = _PyObject_ValuesPointer(self);
    5545   105863000 :     if (*values_ptr == NULL) {
    5546    49690500 :         return 0;
    5547             :     }
    5548    56172000 :     PyDictKeysObject *keys = CACHED_KEYS(tp);
    5549   343088000 :     for (Py_ssize_t i = 0; i < keys->dk_nentries; i++) {
    5550   286916000 :         Py_VISIT((*values_ptr)->values[i]);
    5551             :     }
    5552    56172000 :     return 0;
    5553             : }
    5554             : 
    5555             : void
    5556      851210 : _PyObject_ClearInstanceAttributes(PyObject *self)
    5557             : {
    5558      851210 :     PyTypeObject *tp = Py_TYPE(self);
    5559      851210 :     assert(Py_TYPE(self)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
    5560      851210 :     PyDictValues **values_ptr = _PyObject_ValuesPointer(self);
    5561      851210 :     if (*values_ptr == NULL) {
    5562      111643 :         return;
    5563             :     }
    5564      739567 :     PyDictKeysObject *keys = CACHED_KEYS(tp);
    5565     2909310 :     for (Py_ssize_t i = 0; i < keys->dk_nentries; i++) {
    5566     2169750 :         Py_CLEAR((*values_ptr)->values[i]);
    5567             :     }
    5568             : }
    5569             : 
    5570             : void
    5571     8878440 : _PyObject_FreeInstanceAttributes(PyObject *self)
    5572             : {
    5573     8878440 :     PyTypeObject *tp = Py_TYPE(self);
    5574     8878440 :     assert(Py_TYPE(self)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
    5575     8878440 :     PyDictValues **values_ptr = _PyObject_ValuesPointer(self);
    5576     8878440 :     if (*values_ptr == NULL) {
    5577      410285 :         return;
    5578             :     }
    5579     8468160 :     PyDictKeysObject *keys = CACHED_KEYS(tp);
    5580    39131100 :     for (Py_ssize_t i = 0; i < keys->dk_nentries; i++) {
    5581    30663000 :         Py_XDECREF((*values_ptr)->values[i]);
    5582             :     }
    5583     8468160 :     free_values(*values_ptr);
    5584             : }
    5585             : 
    5586             : PyObject *
    5587      497358 : PyObject_GenericGetDict(PyObject *obj, void *context)
    5588             : {
    5589             :     PyObject *dict;
    5590      497358 :     PyTypeObject *tp = Py_TYPE(obj);
    5591      497358 :     if (_PyType_HasFeature(tp, Py_TPFLAGS_MANAGED_DICT)) {
    5592      299752 :         PyDictValues **values_ptr = _PyObject_ValuesPointer(obj);
    5593      299752 :         PyObject **dictptr = _PyObject_ManagedDictPointer(obj);
    5594      299752 :         if (*values_ptr) {
    5595      135552 :             assert(*dictptr == NULL);
    5596             :             OBJECT_STAT_INC(dict_materialized_on_request);
    5597      135552 :             *dictptr = dict = make_dict_from_instance_attributes(CACHED_KEYS(tp), *values_ptr);
    5598      135552 :             if (dict != NULL) {
    5599      135552 :                 *values_ptr = NULL;
    5600             :             }
    5601             :         }
    5602      164200 :         else if (*dictptr == NULL) {
    5603        1949 :             *dictptr = dict = PyDict_New();
    5604             :         }
    5605             :         else {
    5606      162251 :             dict = *dictptr;
    5607             :         }
    5608             :     }
    5609             :     else {
    5610      197606 :         PyObject **dictptr = _PyObject_DictPointer(obj);
    5611      197606 :         if (dictptr == NULL) {
    5612           0 :             PyErr_SetString(PyExc_AttributeError,
    5613             :                             "This object has no __dict__");
    5614           0 :             return NULL;
    5615             :         }
    5616      197606 :         dict = *dictptr;
    5617      197606 :         if (dict == NULL) {
    5618      168130 :             PyTypeObject *tp = Py_TYPE(obj);
    5619      168130 :             if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE) && CACHED_KEYS(tp)) {
    5620           0 :                 dictkeys_incref(CACHED_KEYS(tp));
    5621           0 :                 *dictptr = dict = new_dict_with_shared_keys(CACHED_KEYS(tp));
    5622             :             }
    5623             :             else {
    5624      168130 :                 *dictptr = dict = PyDict_New();
    5625             :             }
    5626             :         }
    5627             :     }
    5628      497358 :     Py_XINCREF(dict);
    5629      497358 :     return dict;
    5630             : }
    5631             : 
    5632             : int
    5633    57668300 : _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
    5634             :                       PyObject *key, PyObject *value)
    5635             : {
    5636             :     PyObject *dict;
    5637             :     int res;
    5638             :     PyDictKeysObject *cached;
    5639             : 
    5640    57668300 :     assert(dictptr != NULL);
    5641    57668300 :     if ((tp->tp_flags & Py_TPFLAGS_HEAPTYPE) && (cached = CACHED_KEYS(tp))) {
    5642     5179820 :         assert(dictptr != NULL);
    5643     5179820 :         dict = *dictptr;
    5644     5179820 :         if (dict == NULL) {
    5645     4338660 :             dictkeys_incref(cached);
    5646     4338660 :             dict = new_dict_with_shared_keys(cached);
    5647     4338660 :             if (dict == NULL)
    5648           0 :                 return -1;
    5649     4338660 :             *dictptr = dict;
    5650             :         }
    5651     5179820 :         if (value == NULL) {
    5652        6493 :             res = PyDict_DelItem(dict, key);
    5653             :         }
    5654             :         else {
    5655     5173320 :             res = PyDict_SetItem(dict, key, value);
    5656             :         }
    5657             :     } else {
    5658    52488500 :         dict = *dictptr;
    5659    52488500 :         if (dict == NULL) {
    5660     6280370 :             dict = PyDict_New();
    5661     6280370 :             if (dict == NULL)
    5662           0 :                 return -1;
    5663     6280370 :             *dictptr = dict;
    5664             :         }
    5665    52488500 :         if (value == NULL) {
    5666      158522 :             res = PyDict_DelItem(dict, key);
    5667             :         } else {
    5668    52330000 :             res = PyDict_SetItem(dict, key, value);
    5669             :         }
    5670             :     }
    5671    57668300 :     ASSERT_CONSISTENT(dict);
    5672    57668300 :     return res;
    5673             : }
    5674             : 
    5675             : void
    5676      664372 : _PyDictKeys_DecRef(PyDictKeysObject *keys)
    5677             : {
    5678      664372 :     dictkeys_decref(keys);
    5679      664372 : }
    5680             : 
    5681             : static uint32_t next_dict_keys_version = 2;
    5682             : 
    5683     3275510 : uint32_t _PyDictKeys_GetVersionForCurrentState(PyDictKeysObject *dictkeys)
    5684             : {
    5685     3275510 :     if (dictkeys->dk_version != 0) {
    5686     3070360 :         return dictkeys->dk_version;
    5687             :     }
    5688      205146 :     if (next_dict_keys_version == 0) {
    5689           0 :         return 0;
    5690             :     }
    5691      205146 :     uint32_t v = next_dict_keys_version++;
    5692      205146 :     dictkeys->dk_version = v;
    5693      205146 :     return v;
    5694             : }

Generated by: LCOV version 1.14