Coverage Report

Created: 2025-12-07 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Objects/dictobject.c
Line
Count
Source
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_version          |
25
| dk_usable           |
26
| dk_nentries         |
27
+---------------------+
28
| dk_indices[]        |
29
|                     |
30
+---------------------+
31
| dk_entries[]        |
32
|                     |
33
+---------------------+
34
35
dk_indices is actual hashtable.  It holds index in entries, or DKIX_EMPTY(-1)
36
or DKIX_DUMMY(-2).
37
Size of indices is dk_size.  Type of each index in indices varies with dk_size:
38
39
* int8  for          dk_size <= 128
40
* int16 for 256   <= dk_size <= 2**15
41
* int32 for 2**16 <= dk_size <= 2**31
42
* int64 for 2**32 <= dk_size
43
44
dk_entries is array of PyDictKeyEntry when dk_kind == DICT_KEYS_GENERAL or
45
PyDictUnicodeEntry otherwise. Its length is USABLE_FRACTION(dk_size).
46
47
NOTE: Since negative value is used for DKIX_EMPTY and DKIX_DUMMY, type of
48
dk_indices entry is signed integer and int16 is used for table which
49
dk_size == 256.
50
*/
51
52
53
/*
54
The DictObject can be in one of two forms.
55
56
Either:
57
  A combined table:
58
    ma_values == NULL, dk_refcnt == 1.
59
    Values are stored in the me_value field of the PyDictKeyEntry.
60
Or:
61
  A split table:
62
    ma_values != NULL, dk_refcnt >= 1
63
    Values are stored in the ma_values array.
64
    Only string (unicode) keys are allowed.
65
66
There are four kinds of slots in the table (slot is index, and
67
DK_ENTRIES(keys)[index] if index >= 0):
68
69
1. Unused.  index == DKIX_EMPTY
70
   Does not hold an active (key, value) pair now and never did.  Unused can
71
   transition to Active upon key insertion.  This is each slot's initial state.
72
73
2. Active.  index >= 0, me_key != NULL and me_value != NULL
74
   Holds an active (key, value) pair.  Active can transition to Dummy or
75
   Pending upon key deletion (for combined and split tables respectively).
76
   This is the only case in which me_value != NULL.
77
78
3. Dummy.  index == DKIX_DUMMY  (combined only)
79
   Previously held an active (key, value) pair, but that was deleted and an
80
   active pair has not yet overwritten the slot.  Dummy can transition to
81
   Active upon key insertion.  Dummy slots cannot be made Unused again
82
   else the probe sequence in case of collision would have no way to know
83
   they were once active.
84
   In free-threaded builds dummy slots are not re-used to allow lock-free
85
   lookups to proceed safely.
86
87
4. Pending. index >= 0, key != NULL, and value == NULL  (split only)
88
   Not yet inserted in split-table.
89
*/
90
91
/*
92
Preserving insertion order
93
94
It's simple for combined table.  Since dk_entries is mostly append only, we can
95
get insertion order by just iterating dk_entries.
96
97
One exception is .popitem().  It removes last item in dk_entries and decrement
98
dk_nentries to achieve amortized O(1).  Since there are DKIX_DUMMY remains in
99
dk_indices, we can't increment dk_usable even though dk_nentries is
100
decremented.
101
102
To preserve the order in a split table, a bit vector is used  to record the
103
insertion order. When a key is inserted the bit vector is shifted up by 4 bits
104
and the index of the key is stored in the low 4 bits.
105
As a consequence of this, split keys have a maximum size of 16.
106
*/
107
108
/* PyDict_MINSIZE is the starting size for any new dict.
109
 * 8 allows dicts with no more than 5 active entries; experiments suggested
110
 * this suffices for the majority of dicts (consisting mostly of usually-small
111
 * dicts created to pass keyword arguments).
112
 * Making this 8, rather than 4 reduces the number of resizes for most
113
 * dictionaries, without any significant extra memory use.
114
 */
115
241M
#define PyDict_LOG_MINSIZE 3
116
38.0M
#define PyDict_MINSIZE 8
117
118
#include "Python.h"
119
#include "pycore_bitutils.h"      // _Py_bit_length
120
#include "pycore_call.h"          // _PyObject_CallNoArgs()
121
#include "pycore_ceval.h"         // _PyEval_GetBuiltin()
122
#include "pycore_code.h"          // stats
123
#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION, Py_END_CRITICAL_SECTION
124
#include "pycore_dict.h"          // export _PyDict_SizeOf()
125
#include "pycore_freelist.h"      // _PyFreeListState_GET()
126
#include "pycore_gc.h"            // _PyObject_GC_IS_TRACKED()
127
#include "pycore_object.h"        // _PyObject_GC_TRACK(), _PyDebugAllocatorStats()
128
#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_LOAD_SSIZE_RELAXED
129
#include "pycore_pyerrors.h"      // _PyErr_GetRaisedException()
130
#include "pycore_pystate.h"       // _PyThreadState_GET()
131
#include "pycore_setobject.h"     // _PySet_NextEntry()
132
#include "pycore_tuple.h"         // _PyTuple_Recycle()
133
#include "pycore_unicodeobject.h" // _PyUnicode_InternImmortal()
134
135
#include "stringlib/eq.h"                // unicode_eq()
136
#include <stdbool.h>
137
138
139
/*[clinic input]
140
class dict "PyDictObject *" "&PyDict_Type"
141
[clinic start generated code]*/
142
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f157a5a0ce9589d6]*/
143
144
145
/*
146
To ensure the lookup algorithm terminates, there must be at least one Unused
147
slot (NULL key) in the table.
148
To avoid slowing down lookups on a near-full table, we resize the table when
149
it's USABLE_FRACTION (currently two-thirds) full.
150
*/
151
152
#ifdef Py_GIL_DISABLED
153
154
static inline void
155
ASSERT_DICT_LOCKED(PyObject *op)
156
{
157
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
158
}
159
#define ASSERT_DICT_LOCKED(op) ASSERT_DICT_LOCKED(_Py_CAST(PyObject*, op))
160
#define ASSERT_WORLD_STOPPED_OR_DICT_LOCKED(op)                         \
161
    if (!_PyInterpreterState_GET()->stoptheworld.world_stopped) {       \
162
        ASSERT_DICT_LOCKED(op);                                         \
163
    }
164
#define ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(op)                         \
165
    if (!_PyInterpreterState_GET()->stoptheworld.world_stopped) {      \
166
        _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);                 \
167
    }
168
169
#define IS_DICT_SHARED(mp) _PyObject_GC_IS_SHARED(mp)
170
#define SET_DICT_SHARED(mp) _PyObject_GC_SET_SHARED(mp)
171
#define LOAD_INDEX(keys, size, idx) _Py_atomic_load_int##size##_relaxed(&((const int##size##_t*)keys->dk_indices)[idx]);
172
#define STORE_INDEX(keys, size, idx, value) _Py_atomic_store_int##size##_relaxed(&((int##size##_t*)keys->dk_indices)[idx], (int##size##_t)value);
173
#define ASSERT_OWNED_OR_SHARED(mp) \
174
    assert(_Py_IsOwnedByCurrentThread((PyObject *)mp) || IS_DICT_SHARED(mp));
175
176
#define LOCK_KEYS_IF_SPLIT(keys, kind) \
177
        if (kind == DICT_KEYS_SPLIT) { \
178
            LOCK_KEYS(keys);           \
179
        }
180
181
#define UNLOCK_KEYS_IF_SPLIT(keys, kind) \
182
        if (kind == DICT_KEYS_SPLIT) {   \
183
            UNLOCK_KEYS(keys);           \
184
        }
185
186
static inline Py_ssize_t
187
load_keys_nentries(PyDictObject *mp)
188
{
189
    PyDictKeysObject *keys = _Py_atomic_load_ptr(&mp->ma_keys);
190
    return _Py_atomic_load_ssize(&keys->dk_nentries);
191
}
192
193
static inline void
194
set_keys(PyDictObject *mp, PyDictKeysObject *keys)
195
{
196
    ASSERT_OWNED_OR_SHARED(mp);
197
    _Py_atomic_store_ptr_release(&mp->ma_keys, keys);
198
}
199
200
static inline void
201
set_values(PyDictObject *mp, PyDictValues *values)
202
{
203
    ASSERT_OWNED_OR_SHARED(mp);
204
    _Py_atomic_store_ptr_release(&mp->ma_values, values);
205
}
206
207
#define LOCK_KEYS(keys) PyMutex_LockFlags(&keys->dk_mutex, _Py_LOCK_DONT_DETACH)
208
#define UNLOCK_KEYS(keys) PyMutex_Unlock(&keys->dk_mutex)
209
210
#define ASSERT_KEYS_LOCKED(keys) assert(PyMutex_IsLocked(&keys->dk_mutex))
211
#define LOAD_SHARED_KEY(key) _Py_atomic_load_ptr_acquire(&key)
212
#define STORE_SHARED_KEY(key, value) _Py_atomic_store_ptr_release(&key, value)
213
// Inc refs the keys object, giving the previous value
214
#define INCREF_KEYS(dk)  _Py_atomic_add_ssize(&dk->dk_refcnt, 1)
215
// Dec refs the keys object, giving the previous value
216
#define DECREF_KEYS(dk)  _Py_atomic_add_ssize(&dk->dk_refcnt, -1)
217
#define LOAD_KEYS_NENTRIES(keys) _Py_atomic_load_ssize_relaxed(&keys->dk_nentries)
218
219
#define INCREF_KEYS_FT(dk) dictkeys_incref(dk)
220
#define DECREF_KEYS_FT(dk, shared) dictkeys_decref(dk, shared)
221
222
static inline void split_keys_entry_added(PyDictKeysObject *keys)
223
{
224
    ASSERT_KEYS_LOCKED(keys);
225
226
    // We increase before we decrease so we never get too small of a value
227
    // when we're racing with reads
228
    _Py_atomic_store_ssize_relaxed(&keys->dk_nentries, keys->dk_nentries + 1);
229
    _Py_atomic_store_ssize_release(&keys->dk_usable, keys->dk_usable - 1);
230
}
231
232
#else /* Py_GIL_DISABLED */
233
234
#define ASSERT_DICT_LOCKED(op)
235
#define ASSERT_WORLD_STOPPED_OR_DICT_LOCKED(op)
236
#define ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(op)
237
#define LOCK_KEYS(keys)
238
#define UNLOCK_KEYS(keys)
239
#define ASSERT_KEYS_LOCKED(keys)
240
2
#define LOAD_SHARED_KEY(key) key
241
1.69M
#define STORE_SHARED_KEY(key, value) key = value
242
709k
#define INCREF_KEYS(dk)  dk->dk_refcnt++
243
40.9M
#define DECREF_KEYS(dk)  dk->dk_refcnt--
244
0
#define LOAD_KEYS_NENTRIES(keys) keys->dk_nentries
245
#define INCREF_KEYS_FT(dk)
246
#define DECREF_KEYS_FT(dk, shared)
247
#define LOCK_KEYS_IF_SPLIT(keys, kind)
248
#define UNLOCK_KEYS_IF_SPLIT(keys, kind)
249
12.0M
#define IS_DICT_SHARED(mp) (false)
250
#define SET_DICT_SHARED(mp)
251
5.06G
#define LOAD_INDEX(keys, size, idx) ((const int##size##_t*)(keys->dk_indices))[idx]
252
778M
#define STORE_INDEX(keys, size, idx, value) ((int##size##_t*)(keys->dk_indices))[idx] = (int##size##_t)value
253
254
static inline void split_keys_entry_added(PyDictKeysObject *keys)
255
1.69M
{
256
1.69M
    keys->dk_usable--;
257
1.69M
    keys->dk_nentries++;
258
1.69M
}
259
260
static inline void
261
set_keys(PyDictObject *mp, PyDictKeysObject *keys)
262
12.6M
{
263
12.6M
    mp->ma_keys = keys;
264
12.6M
}
265
266
static inline void
267
set_values(PyDictObject *mp, PyDictValues *values)
268
700k
{
269
700k
    mp->ma_values = values;
270
700k
}
271
272
static inline Py_ssize_t
273
load_keys_nentries(PyDictObject *mp)
274
0
{
275
0
    return mp->ma_keys->dk_nentries;
276
0
}
277
278
279
#endif
280
281
328M
#define STORE_KEY(ep, key) FT_ATOMIC_STORE_PTR_RELEASE((ep)->me_key, key)
282
465M
#define STORE_VALUE(ep, value) FT_ATOMIC_STORE_PTR_RELEASE((ep)->me_value, value)
283
215k
#define STORE_SPLIT_VALUE(mp, idx, value) FT_ATOMIC_STORE_PTR_RELEASE(mp->ma_values->values[idx], value)
284
299M
#define STORE_HASH(ep, hash) FT_ATOMIC_STORE_SSIZE_RELAXED((ep)->me_hash, hash)
285
337M
#define STORE_KEYS_USABLE(keys, usable) FT_ATOMIC_STORE_SSIZE_RELAXED(keys->dk_usable, usable)
286
337M
#define STORE_KEYS_NENTRIES(keys, nentries) FT_ATOMIC_STORE_SSIZE_RELAXED(keys->dk_nentries, nentries)
287
367M
#define STORE_USED(mp, used) FT_ATOMIC_STORE_SSIZE_RELAXED(mp->ma_used, used)
288
289
1.57G
#define PERTURB_SHIFT 5
290
291
/*
292
Major subtleties ahead:  Most hash schemes depend on having a "good" hash
293
function, in the sense of simulating randomness.  Python doesn't:  its most
294
important hash functions (for ints) are very regular in common
295
cases:
296
297
  >>>[hash(i) for i in range(4)]
298
  [0, 1, 2, 3]
299
300
This isn't necessarily bad!  To the contrary, in a table of size 2**i, taking
301
the low-order i bits as the initial table index is extremely fast, and there
302
are no collisions at all for dicts indexed by a contiguous range of ints. So
303
this gives better-than-random behavior in common cases, and that's very
304
desirable.
305
306
OTOH, when collisions occur, the tendency to fill contiguous slices of the
307
hash table makes a good collision resolution strategy crucial.  Taking only
308
the last i bits of the hash code is also vulnerable:  for example, consider
309
the list [i << 16 for i in range(20000)] as a set of keys.  Since ints are
310
their own hash codes, and this fits in a dict of size 2**15, the last 15 bits
311
 of every hash code are all 0:  they *all* map to the same table index.
312
313
But catering to unusual cases should not slow the usual ones, so we just take
314
the last i bits anyway.  It's up to collision resolution to do the rest.  If
315
we *usually* find the key we're looking for on the first try (and, it turns
316
out, we usually do -- the table load factor is kept under 2/3, so the odds
317
are solidly in our favor), then it makes best sense to keep the initial index
318
computation dirt cheap.
319
320
The first half of collision resolution is to visit table indices via this
321
recurrence:
322
323
    j = ((5*j) + 1) mod 2**i
324
325
For any initial j in range(2**i), repeating that 2**i times generates each
326
int in range(2**i) exactly once (see any text on random-number generation for
327
proof).  By itself, this doesn't help much:  like linear probing (setting
328
j += 1, or j -= 1, on each loop trip), it scans the table entries in a fixed
329
order.  This would be bad, except that's not the only thing we do, and it's
330
actually *good* in the common cases where hash keys are consecutive.  In an
331
example that's really too small to make this entirely clear, for a table of
332
size 2**3 the order of indices is:
333
334
    0 -> 1 -> 6 -> 7 -> 4 -> 5 -> 2 -> 3 -> 0 [and here it's repeating]
335
336
If two things come in at index 5, the first place we look after is index 2,
337
not 6, so if another comes in at index 6 the collision at 5 didn't hurt it.
338
Linear probing is deadly in this case because there the fixed probe order
339
is the *same* as the order consecutive keys are likely to arrive.  But it's
340
extremely unlikely hash codes will follow a 5*j+1 recurrence by accident,
341
and certain that consecutive hash codes do not.
342
343
The other half of the strategy is to get the other bits of the hash code
344
into play.  This is done by initializing a (unsigned) vrbl "perturb" to the
345
full hash code, and changing the recurrence to:
346
347
    perturb >>= PERTURB_SHIFT;
348
    j = (5*j) + 1 + perturb;
349
    use j % 2**i as the next table index;
350
351
Now the probe sequence depends (eventually) on every bit in the hash code,
352
and the pseudo-scrambling property of recurring on 5*j+1 is more valuable,
353
because it quickly magnifies small differences in the bits that didn't affect
354
the initial index.  Note that because perturb is unsigned, if the recurrence
355
is executed often enough perturb eventually becomes and remains 0.  At that
356
point (very rarely reached) the recurrence is on (just) 5*j+1 again, and
357
that's certain to find an empty slot eventually (since it generates every int
358
in range(2**i), and we make sure there's always at least one empty slot).
359
360
Selecting a good value for PERTURB_SHIFT is a balancing act.  You want it
361
small so that the high bits of the hash code continue to affect the probe
362
sequence across iterations; but you want it large so that in really bad cases
363
the high-order hash bits have an effect on early iterations.  5 was "the
364
best" in minimizing total collisions across experiments Tim Peters ran (on
365
both normal and pathological cases), but 4 and 6 weren't significantly worse.
366
367
Historical: Reimer Behrends contributed the idea of using a polynomial-based
368
approach, using repeated multiplication by x in GF(2**n) where an irreducible
369
polynomial for each table size was chosen such that x was a primitive root.
370
Christian Tismer later extended that to use division by x instead, as an
371
efficient way to get the high bits of the hash code into play.  This scheme
372
also gave excellent collision statistics, but was more expensive:  two
373
if-tests were required inside the loop; computing "the next" index took about
374
the same number of operations but without as much potential parallelism
375
(e.g., computing 5*j can go on at the same time as computing 1+perturb in the
376
above, and then shifting perturb can be done while the table index is being
377
masked); and the PyDictObject struct required a member to hold the table's
378
polynomial.  In Tim's experiments the current scheme ran faster, produced
379
equally good collision statistics, needed less code & used less memory.
380
381
*/
382
383
static int dictresize(PyDictObject *mp, uint8_t log_newsize, int unicode);
384
385
static PyObject* dict_iter(PyObject *dict);
386
387
static int
388
setitem_lock_held(PyDictObject *mp, PyObject *key, PyObject *value);
389
static int
390
dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_value,
391
                    PyObject **result, int incref_result);
392
393
#ifndef NDEBUG
394
static int _PyObject_InlineValuesConsistencyCheck(PyObject *obj);
395
#endif
396
397
#include "clinic/dictobject.c.h"
398
399
400
static inline Py_hash_t
401
unicode_get_hash(PyObject *o)
402
725M
{
403
725M
    return PyUnstable_Unicode_GET_CACHED_HASH(o);
404
725M
}
405
406
/* Print summary info about the state of the optimized allocator */
407
void
408
_PyDict_DebugMallocStats(FILE *out)
409
0
{
410
0
    _PyDebugAllocatorStats(out, "free PyDictObject",
411
0
                           _Py_FREELIST_SIZE(dicts),
412
0
                           sizeof(PyDictObject));
413
0
    _PyDebugAllocatorStats(out, "free PyDictKeysObject",
414
0
                           _Py_FREELIST_SIZE(dictkeys),
415
0
                           sizeof(PyDictKeysObject));
416
0
}
417
418
3.09G
#define DK_MASK(dk) (DK_SIZE(dk)-1)
419
420
#define _Py_DICT_IMMORTAL_INITIAL_REFCNT PY_SSIZE_T_MIN
421
422
static void free_keys_object(PyDictKeysObject *keys, bool use_qsbr);
423
424
/* PyDictKeysObject has refcounts like PyObject does, so we have the
425
   following two functions to mirror what Py_INCREF() and Py_DECREF() do.
426
   (Keep in mind that PyDictKeysObject isn't actually a PyObject.)
427
   Likewise a PyDictKeysObject can be immortal (e.g. Py_EMPTY_KEYS),
428
   so we apply a naive version of what Py_INCREF() and Py_DECREF() do
429
   for immortal objects. */
430
431
static inline void
432
dictkeys_incref(PyDictKeysObject *dk)
433
709k
{
434
709k
    if (FT_ATOMIC_LOAD_SSIZE_RELAXED(dk->dk_refcnt) < 0) {
435
0
        assert(FT_ATOMIC_LOAD_SSIZE_RELAXED(dk->dk_refcnt) == _Py_DICT_IMMORTAL_INITIAL_REFCNT);
436
0
        return;
437
0
    }
438
#ifdef Py_REF_DEBUG
439
    _Py_IncRefTotal(_PyThreadState_GET());
440
#endif
441
709k
    INCREF_KEYS(dk);
442
709k
}
443
444
static inline void
445
dictkeys_decref(PyDictKeysObject *dk, bool use_qsbr)
446
318M
{
447
318M
    if (FT_ATOMIC_LOAD_SSIZE_RELAXED(dk->dk_refcnt) < 0) {
448
277M
        assert(FT_ATOMIC_LOAD_SSIZE_RELAXED(dk->dk_refcnt) == _Py_DICT_IMMORTAL_INITIAL_REFCNT);
449
277M
        return;
450
277M
    }
451
318M
    assert(FT_ATOMIC_LOAD_SSIZE(dk->dk_refcnt) > 0);
452
#ifdef Py_REF_DEBUG
453
    _Py_DecRefTotal(_PyThreadState_GET());
454
#endif
455
40.9M
    if (DECREF_KEYS(dk) == 1) {
456
40.2M
        if (DK_IS_UNICODE(dk)) {
457
27.7M
            PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dk);
458
27.7M
            Py_ssize_t i, n;
459
84.9M
            for (i = 0, n = dk->dk_nentries; i < n; i++) {
460
57.2M
                Py_XDECREF(entries[i].me_key);
461
57.2M
                Py_XDECREF(entries[i].me_value);
462
57.2M
            }
463
27.7M
        }
464
12.4M
        else {
465
12.4M
            PyDictKeyEntry *entries = DK_ENTRIES(dk);
466
12.4M
            Py_ssize_t i, n;
467
321M
            for (i = 0, n = dk->dk_nentries; i < n; i++) {
468
308M
                Py_XDECREF(entries[i].me_key);
469
308M
                Py_XDECREF(entries[i].me_value);
470
308M
            }
471
12.4M
        }
472
40.2M
        free_keys_object(dk, use_qsbr);
473
40.2M
    }
474
40.9M
}
475
476
/* lookup indices.  returns DKIX_EMPTY, DKIX_DUMMY, or ix >=0 */
477
static inline Py_ssize_t
478
dictkeys_get_index(const PyDictKeysObject *keys, Py_ssize_t i)
479
5.06G
{
480
5.06G
    int log2size = DK_LOG_SIZE(keys);
481
5.06G
    Py_ssize_t ix;
482
483
5.06G
    if (log2size < 8) {
484
3.56G
        ix = LOAD_INDEX(keys, 8, i);
485
3.56G
    }
486
1.50G
    else if (log2size < 16) {
487
1.49G
        ix = LOAD_INDEX(keys, 16, i);
488
1.49G
    }
489
8.47M
#if SIZEOF_VOID_P > 4
490
8.47M
    else if (log2size >= 32) {
491
0
        ix = LOAD_INDEX(keys, 64, i);
492
0
    }
493
8.47M
#endif
494
8.47M
    else {
495
8.47M
        ix = LOAD_INDEX(keys, 32, i);
496
8.47M
    }
497
5.06G
    assert(ix >= DKIX_DUMMY);
498
5.06G
    return ix;
499
5.06G
}
500
501
/* write to indices. */
502
static inline void
503
dictkeys_set_index(PyDictKeysObject *keys, Py_ssize_t i, Py_ssize_t ix)
504
778M
{
505
778M
    int log2size = DK_LOG_SIZE(keys);
506
507
778M
    assert(ix >= DKIX_DUMMY);
508
778M
    assert(keys->dk_version == 0);
509
510
778M
    if (log2size < 8) {
511
304M
        assert(ix <= 0x7f);
512
304M
        STORE_INDEX(keys, 8, i, ix);
513
304M
    }
514
474M
    else if (log2size < 16) {
515
472M
        assert(ix <= 0x7fff);
516
472M
        STORE_INDEX(keys, 16, i, ix);
517
472M
    }
518
1.82M
#if SIZEOF_VOID_P > 4
519
1.82M
    else if (log2size >= 32) {
520
0
        STORE_INDEX(keys, 64, i, ix);
521
0
    }
522
1.82M
#endif
523
1.82M
    else {
524
1.82M
        assert(ix <= 0x7fffffff);
525
1.82M
        STORE_INDEX(keys, 32, i, ix);
526
1.82M
    }
527
778M
}
528
529
530
/* USABLE_FRACTION is the maximum dictionary load.
531
 * Increasing this ratio makes dictionaries more dense resulting in more
532
 * collisions.  Decreasing it improves sparseness at the expense of spreading
533
 * indices over more cache lines and at the cost of total memory consumed.
534
 *
535
 * USABLE_FRACTION must obey the following:
536
 *     (0 < USABLE_FRACTION(n) < n) for all n >= 2
537
 *
538
 * USABLE_FRACTION should be quick to calculate.
539
 * Fractions around 1/2 to 2/3 seem to work well in practice.
540
 */
541
324M
#define USABLE_FRACTION(n) (((n) << 1)/3)
542
543
/* Find the smallest dk_size >= minsize. */
544
static inline uint8_t
545
calculate_log2_keysize(Py_ssize_t minsize)
546
12.0M
{
547
12.0M
#if SIZEOF_LONG == SIZEOF_SIZE_T
548
12.0M
    minsize = Py_MAX(minsize, PyDict_MINSIZE);
549
12.0M
    return _Py_bit_length(minsize - 1);
550
#elif defined(_MSC_VER)
551
    // On 64bit Windows, sizeof(long) == 4. We cannot use _Py_bit_length.
552
    minsize = Py_MAX(minsize, PyDict_MINSIZE);
553
    unsigned long msb;
554
    _BitScanReverse64(&msb, (uint64_t)minsize - 1);
555
    return (uint8_t)(msb + 1);
556
#else
557
    uint8_t log2_size;
558
    for (log2_size = PyDict_LOG_MINSIZE;
559
            (((Py_ssize_t)1) << log2_size) < minsize;
560
            log2_size++)
561
        ;
562
    return log2_size;
563
#endif
564
12.0M
}
565
566
/* estimate_keysize is reverse function of USABLE_FRACTION.
567
 *
568
 * This can be used to reserve enough size to insert n entries without
569
 * resizing.
570
 */
571
static inline uint8_t
572
estimate_log2_keysize(Py_ssize_t n)
573
568k
{
574
568k
    return calculate_log2_keysize((n*3 + 1) / 2);
575
568k
}
576
577
578
/* GROWTH_RATE. Growth rate upon hitting maximum load.
579
 * Currently set to used*3.
580
 * This means that dicts double in size when growing without deletions,
581
 * but have more head room when the number of deletions is on a par with the
582
 * number of insertions.  See also bpo-17563 and bpo-33205.
583
 *
584
 * GROWTH_RATE was set to used*4 up to version 3.2.
585
 * GROWTH_RATE was set to used*2 in version 3.3.0
586
 * GROWTH_RATE was set to used*2 + capacity/2 in 3.4.0-3.6.0.
587
 */
588
11.4M
#define GROWTH_RATE(d) ((d)->ma_used*3)
589
590
/* This immutable, empty PyDictKeysObject is used for PyDict_Clear()
591
 * (which cannot fail and thus can do no allocation).
592
 *
593
 * See https://github.com/python/cpython/pull/127568#discussion_r1868070614
594
 * for the rationale of using dk_log2_index_bytes=3 instead of 0.
595
 */
596
static PyDictKeysObject empty_keys_struct = {
597
        _Py_DICT_IMMORTAL_INITIAL_REFCNT, /* dk_refcnt */
598
        0, /* dk_log2_size */
599
        3, /* dk_log2_index_bytes */
600
        DICT_KEYS_UNICODE, /* dk_kind */
601
#ifdef Py_GIL_DISABLED
602
        {0}, /* dk_mutex */
603
#endif
604
        1, /* dk_version */
605
        0, /* dk_usable (immutable) */
606
        0, /* dk_nentries */
607
        {DKIX_EMPTY, DKIX_EMPTY, DKIX_EMPTY, DKIX_EMPTY,
608
         DKIX_EMPTY, DKIX_EMPTY, DKIX_EMPTY, DKIX_EMPTY}, /* dk_indices */
609
};
610
611
902M
#define Py_EMPTY_KEYS &empty_keys_struct
612
613
/* Uncomment to check the dict content in _PyDict_CheckConsistency() */
614
// #define DEBUG_PYDICT
615
616
#ifdef DEBUG_PYDICT
617
#  define ASSERT_CONSISTENT(op) assert(_PyDict_CheckConsistency((PyObject *)(op), 1))
618
#else
619
918M
#  define ASSERT_CONSISTENT(op) assert(_PyDict_CheckConsistency((PyObject *)(op), 0))
620
#endif
621
622
static inline int
623
get_index_from_order(PyDictObject *mp, Py_ssize_t i)
624
1.25M
{
625
1.25M
    assert(mp->ma_used <= SHARED_KEYS_MAX_SIZE);
626
1.25M
    assert(i < mp->ma_values->size);
627
1.25M
    uint8_t *array = get_insertion_order_array(mp->ma_values);
628
1.25M
    return array[i];
629
1.25M
}
630
631
#ifdef DEBUG_PYDICT
632
static void
633
dump_entries(PyDictKeysObject *dk)
634
{
635
    for (Py_ssize_t i = 0; i < dk->dk_nentries; i++) {
636
        if (DK_IS_UNICODE(dk)) {
637
            PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(dk)[i];
638
            printf("key=%p value=%p\n", ep->me_key, ep->me_value);
639
        }
640
        else {
641
            PyDictKeyEntry *ep = &DK_ENTRIES(dk)[i];
642
            printf("key=%p hash=%lx value=%p\n", ep->me_key, ep->me_hash, ep->me_value);
643
        }
644
    }
645
}
646
#endif
647
648
int
649
_PyDict_CheckConsistency(PyObject *op, int check_content)
650
0
{
651
0
    ASSERT_WORLD_STOPPED_OR_DICT_LOCKED(op);
652
653
0
#define CHECK(expr) \
654
0
    do { if (!(expr)) { _PyObject_ASSERT_FAILED_MSG(op, Py_STRINGIFY(expr)); } } while (0)
655
656
0
    assert(op != NULL);
657
0
    CHECK(PyDict_Check(op));
658
0
    PyDictObject *mp = (PyDictObject *)op;
659
660
0
    PyDictKeysObject *keys = mp->ma_keys;
661
0
    int splitted = _PyDict_HasSplitTable(mp);
662
0
    Py_ssize_t usable = USABLE_FRACTION(DK_SIZE(keys));
663
664
    // In the free-threaded build, shared keys may be concurrently modified,
665
    // so use atomic loads.
666
0
    Py_ssize_t dk_usable = FT_ATOMIC_LOAD_SSIZE_ACQUIRE(keys->dk_usable);
667
0
    Py_ssize_t dk_nentries = FT_ATOMIC_LOAD_SSIZE_ACQUIRE(keys->dk_nentries);
668
669
0
    CHECK(0 <= mp->ma_used && mp->ma_used <= usable);
670
0
    CHECK(0 <= dk_usable && dk_usable <= usable);
671
0
    CHECK(0 <= dk_nentries && dk_nentries <= usable);
672
0
    CHECK(dk_usable + dk_nentries <= usable);
673
674
0
    if (!splitted) {
675
        /* combined table */
676
0
        CHECK(keys->dk_kind != DICT_KEYS_SPLIT);
677
0
        CHECK(keys->dk_refcnt == 1 || keys == Py_EMPTY_KEYS);
678
0
    }
679
0
    else {
680
0
        CHECK(keys->dk_kind == DICT_KEYS_SPLIT);
681
0
        CHECK(mp->ma_used <= SHARED_KEYS_MAX_SIZE);
682
0
        if (mp->ma_values->embedded) {
683
0
            CHECK(mp->ma_values->embedded == 1);
684
0
            CHECK(mp->ma_values->valid == 1);
685
0
        }
686
0
    }
687
688
0
    if (check_content) {
689
0
        LOCK_KEYS_IF_SPLIT(keys, keys->dk_kind);
690
0
        for (Py_ssize_t i=0; i < DK_SIZE(keys); i++) {
691
0
            Py_ssize_t ix = dictkeys_get_index(keys, i);
692
0
            CHECK(DKIX_DUMMY <= ix && ix <= usable);
693
0
        }
694
695
0
        if (keys->dk_kind == DICT_KEYS_GENERAL) {
696
0
            PyDictKeyEntry *entries = DK_ENTRIES(keys);
697
0
            for (Py_ssize_t i=0; i < usable; i++) {
698
0
                PyDictKeyEntry *entry = &entries[i];
699
0
                PyObject *key = entry->me_key;
700
701
0
                if (key != NULL) {
702
                    /* test_dict fails if PyObject_Hash() is called again */
703
0
                    CHECK(entry->me_hash != -1);
704
0
                    CHECK(entry->me_value != NULL);
705
706
0
                    if (PyUnicode_CheckExact(key)) {
707
0
                        Py_hash_t hash = unicode_get_hash(key);
708
0
                        CHECK(entry->me_hash == hash);
709
0
                    }
710
0
                }
711
0
            }
712
0
        }
713
0
        else {
714
0
            PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys);
715
0
            for (Py_ssize_t i=0; i < usable; i++) {
716
0
                PyDictUnicodeEntry *entry = &entries[i];
717
0
                PyObject *key = entry->me_key;
718
719
0
                if (key != NULL) {
720
0
                    CHECK(PyUnicode_CheckExact(key));
721
0
                    Py_hash_t hash = unicode_get_hash(key);
722
0
                    CHECK(hash != -1);
723
0
                    if (!splitted) {
724
0
                        CHECK(entry->me_value != NULL);
725
0
                    }
726
0
                }
727
728
0
                if (splitted) {
729
0
                    CHECK(entry->me_value == NULL);
730
0
                }
731
0
            }
732
0
        }
733
734
0
        if (splitted) {
735
0
            CHECK(mp->ma_used <= SHARED_KEYS_MAX_SIZE);
736
            /* splitted table */
737
0
            int duplicate_check = 0;
738
0
            for (Py_ssize_t i=0; i < mp->ma_used; i++) {
739
0
                int index = get_index_from_order(mp, i);
740
0
                CHECK((duplicate_check & (1<<index)) == 0);
741
0
                duplicate_check |= (1<<index);
742
0
                CHECK(mp->ma_values->values[index] != NULL);
743
0
            }
744
0
        }
745
0
        UNLOCK_KEYS_IF_SPLIT(keys, keys->dk_kind);
746
0
    }
747
0
    return 1;
748
749
0
#undef CHECK
750
0
}
751
752
753
static PyDictKeysObject*
754
new_keys_object(uint8_t log2_size, bool unicode)
755
50.3M
{
756
50.3M
    Py_ssize_t usable;
757
50.3M
    int log2_bytes;
758
50.3M
    size_t entry_size = unicode ? sizeof(PyDictUnicodeEntry) : sizeof(PyDictKeyEntry);
759
760
50.3M
    assert(log2_size >= PyDict_LOG_MINSIZE);
761
762
50.3M
    usable = USABLE_FRACTION((size_t)1<<log2_size);
763
50.3M
    if (log2_size < 8) {
764
49.5M
        log2_bytes = log2_size;
765
49.5M
    }
766
881k
    else if (log2_size < 16) {
767
881k
        log2_bytes = log2_size + 1;
768
881k
    }
769
27
#if SIZEOF_VOID_P > 4
770
27
    else if (log2_size >= 32) {
771
0
        log2_bytes = log2_size + 3;
772
0
    }
773
27
#endif
774
27
    else {
775
27
        log2_bytes = log2_size + 2;
776
27
    }
777
778
50.3M
    PyDictKeysObject *dk = NULL;
779
50.3M
    if (log2_size == PyDict_LOG_MINSIZE && unicode) {
780
26.8M
        dk = _Py_FREELIST_POP_MEM(dictkeys);
781
26.8M
    }
782
50.3M
    if (dk == NULL) {
783
35.0M
        dk = PyMem_Malloc(sizeof(PyDictKeysObject)
784
35.0M
                          + ((size_t)1 << log2_bytes)
785
35.0M
                          + entry_size * usable);
786
35.0M
        if (dk == NULL) {
787
0
            PyErr_NoMemory();
788
0
            return NULL;
789
0
        }
790
35.0M
    }
791
#ifdef Py_REF_DEBUG
792
    _Py_IncRefTotal(_PyThreadState_GET());
793
#endif
794
50.3M
    dk->dk_refcnt = 1;
795
50.3M
    dk->dk_log2_size = log2_size;
796
50.3M
    dk->dk_log2_index_bytes = log2_bytes;
797
50.3M
    dk->dk_kind = unicode ? DICT_KEYS_UNICODE : DICT_KEYS_GENERAL;
798
#ifdef Py_GIL_DISABLED
799
    dk->dk_mutex = (PyMutex){0};
800
#endif
801
50.3M
    dk->dk_nentries = 0;
802
50.3M
    dk->dk_usable = usable;
803
50.3M
    dk->dk_version = 0;
804
50.3M
    memset(&dk->dk_indices[0], 0xff, ((size_t)1 << log2_bytes));
805
50.3M
    memset(&dk->dk_indices[(size_t)1 << log2_bytes], 0, entry_size * usable);
806
50.3M
    return dk;
807
50.3M
}
808
809
static void
810
free_keys_object(PyDictKeysObject *keys, bool use_qsbr)
811
50.9M
{
812
#ifdef Py_GIL_DISABLED
813
    if (use_qsbr) {
814
        _PyMem_FreeDelayed(keys, _PyDict_KeysSize(keys));
815
        return;
816
    }
817
#endif
818
50.9M
    if (DK_LOG_SIZE(keys) == PyDict_LOG_MINSIZE && keys->dk_kind == DICT_KEYS_UNICODE) {
819
27.4M
        _Py_FREELIST_FREE(dictkeys, keys, PyMem_Free);
820
27.4M
    }
821
23.5M
    else {
822
23.5M
        PyMem_Free(keys);
823
23.5M
    }
824
50.9M
}
825
826
static size_t
827
values_size_from_count(size_t count)
828
14.6k
{
829
14.6k
    assert(count >= 1);
830
14.6k
    size_t suffix_size = _Py_SIZE_ROUND_UP(count, sizeof(PyObject *));
831
14.6k
    assert(suffix_size < 128);
832
14.6k
    assert(suffix_size % sizeof(PyObject *) == 0);
833
14.6k
    return (count + 1) * sizeof(PyObject *) + suffix_size;
834
14.6k
}
835
836
127M
#define CACHED_KEYS(tp) (((PyHeapTypeObject*)tp)->ht_cached_keys)
837
838
static inline PyDictValues*
839
new_values(size_t size)
840
14.6k
{
841
14.6k
    size_t n = values_size_from_count(size);
842
14.6k
    PyDictValues *res = (PyDictValues *)PyMem_Malloc(n);
843
14.6k
    if (res == NULL) {
844
0
        return NULL;
845
0
    }
846
14.6k
    res->embedded = 0;
847
14.6k
    res->size = 0;
848
14.6k
    assert(size < 256);
849
14.6k
    res->capacity = (uint8_t)size;
850
14.6k
    return res;
851
14.6k
}
852
853
static inline void
854
free_values(PyDictValues *values, bool use_qsbr)
855
5.78k
{
856
5.78k
    assert(values->embedded == 0);
857
#ifdef Py_GIL_DISABLED
858
    if (use_qsbr) {
859
        _PyMem_FreeDelayed(values, values_size_from_count(values->capacity));
860
        return;
861
    }
862
#endif
863
5.78k
    PyMem_Free(values);
864
5.78k
}
865
866
/* Consumes a reference to the keys object */
867
static PyObject *
868
new_dict(PyDictKeysObject *keys, PyDictValues *values,
869
         Py_ssize_t used, int free_values_on_failure)
870
316M
{
871
316M
    assert(keys != NULL);
872
316M
    PyDictObject *mp = _Py_FREELIST_POP(PyDictObject, dicts);
873
316M
    if (mp == NULL) {
874
13.8M
        mp = PyObject_GC_New(PyDictObject, &PyDict_Type);
875
13.8M
        if (mp == NULL) {
876
0
            dictkeys_decref(keys, false);
877
0
            if (free_values_on_failure) {
878
0
                free_values(values, false);
879
0
            }
880
0
            return NULL;
881
0
        }
882
13.8M
    }
883
316M
    assert(Py_IS_TYPE(mp, &PyDict_Type));
884
316M
    mp->ma_keys = keys;
885
316M
    mp->ma_values = values;
886
316M
    mp->ma_used = used;
887
316M
    mp->_ma_watcher_tag = 0;
888
316M
    ASSERT_CONSISTENT(mp);
889
316M
    _PyObject_GC_TRACK(mp);
890
316M
    return (PyObject *)mp;
891
316M
}
892
893
static PyObject *
894
new_dict_with_shared_keys(PyDictKeysObject *keys)
895
9.07k
{
896
9.07k
    size_t size = shared_keys_usable_size(keys);
897
9.07k
    PyDictValues *values = new_values(size);
898
9.07k
    if (values == NULL) {
899
0
        return PyErr_NoMemory();
900
0
    }
901
9.07k
    dictkeys_incref(keys);
902
281k
    for (size_t i = 0; i < size; i++) {
903
272k
        values->values[i] = NULL;
904
272k
    }
905
9.07k
    return new_dict(keys, values, 0, 1);
906
9.07k
}
907
908
909
static PyDictKeysObject *
910
clone_combined_dict_keys(PyDictObject *orig)
911
636k
{
912
636k
    assert(PyDict_Check(orig));
913
636k
    assert(Py_TYPE(orig)->tp_iter == dict_iter);
914
636k
    assert(orig->ma_values == NULL);
915
636k
    assert(orig->ma_keys != Py_EMPTY_KEYS);
916
636k
    assert(orig->ma_keys->dk_refcnt == 1);
917
918
636k
    ASSERT_DICT_LOCKED(orig);
919
920
636k
    size_t keys_size = _PyDict_KeysSize(orig->ma_keys);
921
636k
    PyDictKeysObject *keys = PyMem_Malloc(keys_size);
922
636k
    if (keys == NULL) {
923
0
        PyErr_NoMemory();
924
0
        return NULL;
925
0
    }
926
927
636k
    memcpy(keys, orig->ma_keys, keys_size);
928
929
    /* After copying key/value pairs, we need to incref all
930
       keys and values and they are about to be co-owned by a
931
       new dict object. */
932
636k
    PyObject **pkey, **pvalue;
933
636k
    size_t offs;
934
636k
    if (DK_IS_UNICODE(orig->ma_keys)) {
935
636k
        PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(keys);
936
636k
        pkey = &ep0->me_key;
937
636k
        pvalue = &ep0->me_value;
938
636k
        offs = sizeof(PyDictUnicodeEntry) / sizeof(PyObject*);
939
636k
    }
940
0
    else {
941
0
        PyDictKeyEntry *ep0 = DK_ENTRIES(keys);
942
0
        pkey = &ep0->me_key;
943
0
        pvalue = &ep0->me_value;
944
0
        offs = sizeof(PyDictKeyEntry) / sizeof(PyObject*);
945
0
    }
946
947
636k
    Py_ssize_t n = keys->dk_nentries;
948
2.32M
    for (Py_ssize_t i = 0; i < n; i++) {
949
1.69M
        PyObject *value = *pvalue;
950
1.69M
        if (value != NULL) {
951
1.68M
            Py_INCREF(value);
952
1.68M
            Py_INCREF(*pkey);
953
1.68M
        }
954
1.69M
        pvalue += offs;
955
1.69M
        pkey += offs;
956
1.69M
    }
957
958
    /* Since we copied the keys table we now have an extra reference
959
       in the system.  Manually call increment _Py_RefTotal to signal that
960
       we have it now; calling dictkeys_incref would be an error as
961
       keys->dk_refcnt is already set to 1 (after memcpy). */
962
#ifdef Py_REF_DEBUG
963
    _Py_IncRefTotal(_PyThreadState_GET());
964
#endif
965
636k
    return keys;
966
636k
}
967
968
PyObject *
969
PyDict_New(void)
970
315M
{
971
    /* We don't incref Py_EMPTY_KEYS here because it is immortal. */
972
315M
    return new_dict(Py_EMPTY_KEYS, NULL, 0, 0);
973
315M
}
974
975
/* Search index of hash table from offset of entry table */
976
static Py_ssize_t
977
lookdict_index(PyDictKeysObject *k, Py_hash_t hash, Py_ssize_t index)
978
3.16M
{
979
3.16M
    size_t mask = DK_MASK(k);
980
3.16M
    size_t perturb = (size_t)hash;
981
3.16M
    size_t i = (size_t)hash & mask;
982
983
6.83M
    for (;;) {
984
6.83M
        Py_ssize_t ix = dictkeys_get_index(k, i);
985
6.83M
        if (ix == index) {
986
3.16M
            return i;
987
3.16M
        }
988
3.66M
        if (ix == DKIX_EMPTY) {
989
0
            return DKIX_EMPTY;
990
0
        }
991
3.66M
        perturb >>= PERTURB_SHIFT;
992
3.66M
        i = mask & (i*5 + perturb + 1);
993
3.66M
    }
994
3.16M
    Py_UNREACHABLE();
995
3.16M
}
996
997
static inline Py_ALWAYS_INLINE Py_ssize_t
998
do_lookup(PyDictObject *mp, PyDictKeysObject *dk, PyObject *key, Py_hash_t hash,
999
          int (*check_lookup)(PyDictObject *, PyDictKeysObject *, void *, Py_ssize_t ix, PyObject *key, Py_hash_t))
1000
2.75G
{
1001
2.75G
    void *ep0 = _DK_ENTRIES(dk);
1002
2.75G
    size_t mask = DK_MASK(dk);
1003
2.75G
    size_t perturb = hash;
1004
2.75G
    size_t i = (size_t)hash & mask;
1005
2.75G
    Py_ssize_t ix;
1006
3.15G
    for (;;) {
1007
3.15G
        ix = dictkeys_get_index(dk, i);
1008
3.15G
        if (ix >= 0) {
1009
2.10G
            int cmp = check_lookup(mp, dk, ep0, ix, key, hash);
1010
2.10G
            if (cmp < 0) {
1011
0
                return cmp;
1012
2.10G
            } else if (cmp) {
1013
1.51G
                return ix;
1014
1.51G
            }
1015
2.10G
        }
1016
1.04G
        else if (ix == DKIX_EMPTY) {
1017
786M
            return DKIX_EMPTY;
1018
786M
        }
1019
844M
        perturb >>= PERTURB_SHIFT;
1020
844M
        i = mask & (i*5 + perturb + 1);
1021
1022
        // Manual loop unrolling
1023
844M
        ix = dictkeys_get_index(dk, i);
1024
844M
        if (ix >= 0) {
1025
426M
            int cmp = check_lookup(mp, dk, ep0, ix, key, hash);
1026
426M
            if (cmp < 0) {
1027
0
                return cmp;
1028
426M
            } else if (cmp) {
1029
110M
                return ix;
1030
110M
            }
1031
426M
        }
1032
417M
        else if (ix == DKIX_EMPTY) {
1033
337M
            return DKIX_EMPTY;
1034
337M
        }
1035
395M
        perturb >>= PERTURB_SHIFT;
1036
395M
        i = mask & (i*5 + perturb + 1);
1037
395M
    }
1038
2.75G
    Py_UNREACHABLE();
1039
2.75G
}
1040
1041
static inline int
1042
compare_unicode_generic(PyDictObject *mp, PyDictKeysObject *dk,
1043
                        void *ep0, Py_ssize_t ix, PyObject *key, Py_hash_t hash)
1044
4.68k
{
1045
4.68k
    PyDictUnicodeEntry *ep = &((PyDictUnicodeEntry *)ep0)[ix];
1046
4.68k
    assert(ep->me_key != NULL);
1047
4.68k
    assert(PyUnicode_CheckExact(ep->me_key));
1048
4.68k
    assert(!PyUnicode_CheckExact(key));
1049
1050
4.68k
    if (unicode_get_hash(ep->me_key) == hash) {
1051
22
        PyObject *startkey = ep->me_key;
1052
22
        Py_INCREF(startkey);
1053
22
        int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
1054
22
        Py_DECREF(startkey);
1055
22
        if (cmp < 0) {
1056
0
            return DKIX_ERROR;
1057
0
        }
1058
22
        if (dk == mp->ma_keys && ep->me_key == startkey) {
1059
22
            return cmp;
1060
22
        }
1061
0
        else {
1062
            /* The dict was mutated, restart */
1063
0
            return DKIX_KEY_CHANGED;
1064
0
        }
1065
22
    }
1066
4.66k
    return 0;
1067
4.68k
}
1068
1069
// Search non-Unicode key from Unicode table
1070
static Py_ssize_t
1071
unicodekeys_lookup_generic(PyDictObject *mp, PyDictKeysObject* dk, PyObject *key, Py_hash_t hash)
1072
103M
{
1073
103M
    return do_lookup(mp, dk, key, hash, compare_unicode_generic);
1074
103M
}
1075
1076
static inline int
1077
compare_unicode_unicode(PyDictObject *mp, PyDictKeysObject *dk,
1078
                        void *ep0, Py_ssize_t ix, PyObject *key, Py_hash_t hash)
1079
1.91G
{
1080
1.91G
    PyDictUnicodeEntry *ep = &((PyDictUnicodeEntry *)ep0)[ix];
1081
1.91G
    PyObject *ep_key = FT_ATOMIC_LOAD_PTR_RELAXED(ep->me_key);
1082
1.91G
    assert(ep_key != NULL);
1083
1.91G
    assert(PyUnicode_CheckExact(ep_key));
1084
1.91G
    if (ep_key == key ||
1085
1.43G
            (unicode_get_hash(ep_key) == hash && unicode_eq(ep_key, key))) {
1086
1.43G
        return 1;
1087
1.43G
    }
1088
479M
    return 0;
1089
1.91G
}
1090
1091
static Py_ssize_t _Py_HOT_FUNCTION
1092
unicodekeys_lookup_unicode(PyDictKeysObject* dk, PyObject *key, Py_hash_t hash)
1093
2.01G
{
1094
2.01G
    return do_lookup(NULL, dk, key, hash, compare_unicode_unicode);
1095
2.01G
}
1096
1097
static inline int
1098
compare_generic(PyDictObject *mp, PyDictKeysObject *dk,
1099
                void *ep0, Py_ssize_t ix, PyObject *key, Py_hash_t hash)
1100
614M
{
1101
614M
    PyDictKeyEntry *ep = &((PyDictKeyEntry *)ep0)[ix];
1102
614M
    assert(ep->me_key != NULL);
1103
614M
    if (ep->me_key == key) {
1104
35.0M
        return 1;
1105
35.0M
    }
1106
579M
    if (ep->me_hash == hash) {
1107
155M
        PyObject *startkey = ep->me_key;
1108
155M
        Py_INCREF(startkey);
1109
155M
        int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
1110
155M
        Py_DECREF(startkey);
1111
155M
        if (cmp < 0) {
1112
0
            return DKIX_ERROR;
1113
0
        }
1114
155M
        if (dk == mp->ma_keys && ep->me_key == startkey) {
1115
155M
            return cmp;
1116
155M
        }
1117
0
        else {
1118
            /* The dict was mutated, restart */
1119
0
            return DKIX_KEY_CHANGED;
1120
0
        }
1121
155M
    }
1122
424M
    return 0;
1123
579M
}
1124
1125
static Py_ssize_t
1126
dictkeys_generic_lookup(PyDictObject *mp, PyDictKeysObject* dk, PyObject *key, Py_hash_t hash)
1127
639M
{
1128
639M
    return do_lookup(mp, dk, key, hash, compare_generic);
1129
639M
}
1130
1131
static bool
1132
check_keys_unicode(PyDictKeysObject *dk, PyObject *key)
1133
2.40M
{
1134
2.40M
    return PyUnicode_CheckExact(key) && (dk->dk_kind != DICT_KEYS_GENERAL);
1135
2.40M
}
1136
1137
static Py_ssize_t
1138
hash_unicode_key(PyObject *key)
1139
36.5M
{
1140
36.5M
    assert(PyUnicode_CheckExact(key));
1141
36.5M
    Py_hash_t hash = unicode_get_hash(key);
1142
36.5M
    if (hash == -1) {
1143
0
        hash = PyUnicode_Type.tp_hash(key);
1144
0
        assert(hash != -1);
1145
0
    }
1146
36.5M
    return hash;
1147
36.5M
}
1148
1149
#ifdef Py_GIL_DISABLED
1150
static Py_ssize_t
1151
unicodekeys_lookup_unicode_threadsafe(PyDictKeysObject* dk, PyObject *key,
1152
                                      Py_hash_t hash);
1153
#endif
1154
1155
static Py_ssize_t
1156
unicodekeys_lookup_split(PyDictKeysObject* dk, PyObject *key, Py_hash_t hash)
1157
64.1M
{
1158
64.1M
    Py_ssize_t ix;
1159
64.1M
    assert(dk->dk_kind == DICT_KEYS_SPLIT);
1160
64.1M
    assert(PyUnicode_CheckExact(key));
1161
1162
#ifdef Py_GIL_DISABLED
1163
    // A split dictionaries keys can be mutated by other dictionaries
1164
    // but if we have a unicode key we can avoid locking the shared
1165
    // keys.
1166
    ix = unicodekeys_lookup_unicode_threadsafe(dk, key, hash);
1167
    if (ix == DKIX_KEY_CHANGED) {
1168
        LOCK_KEYS(dk);
1169
        ix = unicodekeys_lookup_unicode(dk, key, hash);
1170
        UNLOCK_KEYS(dk);
1171
    }
1172
#else
1173
64.1M
    ix = unicodekeys_lookup_unicode(dk, key, hash);
1174
64.1M
#endif
1175
64.1M
    return ix;
1176
64.1M
}
1177
1178
/* Lookup a string in a (all unicode) dict keys.
1179
 * Returns DKIX_ERROR if key is not a string,
1180
 * or if the dict keys is not all strings.
1181
 * If the keys is present then return the index of key.
1182
 * If the key is not present then return DKIX_EMPTY.
1183
 */
1184
Py_ssize_t
1185
_PyDictKeys_StringLookup(PyDictKeysObject* dk, PyObject *key)
1186
33.8k
{
1187
33.8k
    if (!check_keys_unicode(dk, key)) {
1188
0
        return DKIX_ERROR;
1189
0
    }
1190
33.8k
    Py_hash_t hash = hash_unicode_key(key);
1191
33.8k
    return unicodekeys_lookup_unicode(dk, key, hash);
1192
33.8k
}
1193
1194
Py_ssize_t
1195
_PyDictKeys_StringLookupAndVersion(PyDictKeysObject *dk, PyObject *key, uint32_t *version)
1196
2.36M
{
1197
2.36M
    if (!check_keys_unicode(dk, key)) {
1198
0
        return DKIX_ERROR;
1199
0
    }
1200
2.36M
    Py_ssize_t ix;
1201
2.36M
    Py_hash_t hash = hash_unicode_key(key);
1202
2.36M
    LOCK_KEYS(dk);
1203
2.36M
    ix = unicodekeys_lookup_unicode(dk, key, hash);
1204
2.36M
    *version = _PyDictKeys_GetVersionForCurrentState(_PyInterpreterState_GET(), dk);
1205
2.36M
    UNLOCK_KEYS(dk);
1206
2.36M
    return ix;
1207
2.36M
}
1208
1209
/* Like _PyDictKeys_StringLookup() but only works on split keys.  Note
1210
 * that in free-threaded builds this locks the keys object as required.
1211
 */
1212
Py_ssize_t
1213
_PyDictKeys_StringLookupSplit(PyDictKeysObject* dk, PyObject *key)
1214
64.1M
{
1215
64.1M
    assert(dk->dk_kind == DICT_KEYS_SPLIT);
1216
64.1M
    assert(PyUnicode_CheckExact(key));
1217
64.1M
    Py_hash_t hash = unicode_get_hash(key);
1218
64.1M
    if (hash == -1) {
1219
0
        hash = PyUnicode_Type.tp_hash(key);
1220
0
        if (hash == -1) {
1221
0
            PyErr_Clear();
1222
0
            return DKIX_ERROR;
1223
0
        }
1224
0
    }
1225
64.1M
    return unicodekeys_lookup_split(dk, key, hash);
1226
64.1M
}
1227
1228
/*
1229
The basic lookup function used by all operations.
1230
This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4.
1231
Open addressing is preferred over chaining since the link overhead for
1232
chaining would be substantial (100% with typical malloc overhead).
1233
1234
The initial probe index is computed as hash mod the table size. Subsequent
1235
probe indices are computed as explained earlier.
1236
1237
All arithmetic on hash should ignore overflow.
1238
1239
_Py_dict_lookup() is general-purpose, and may return DKIX_ERROR if (and only if) a
1240
comparison raises an exception.
1241
When the key isn't found a DKIX_EMPTY is returned.
1242
*/
1243
Py_ssize_t
1244
_Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr)
1245
2.66G
{
1246
2.66G
    PyDictKeysObject *dk;
1247
2.66G
    DictKeysKind kind;
1248
2.66G
    Py_ssize_t ix;
1249
1250
2.66G
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(mp);
1251
2.66G
start:
1252
2.66G
    dk = mp->ma_keys;
1253
2.66G
    kind = dk->dk_kind;
1254
1255
2.66G
    if (kind != DICT_KEYS_GENERAL) {
1256
2.02G
        if (PyUnicode_CheckExact(key)) {
1257
#ifdef Py_GIL_DISABLED
1258
            if (kind == DICT_KEYS_SPLIT) {
1259
                ix = unicodekeys_lookup_split(dk, key, hash);
1260
            }
1261
            else {
1262
                ix = unicodekeys_lookup_unicode(dk, key, hash);
1263
            }
1264
#else
1265
1.92G
            ix = unicodekeys_lookup_unicode(dk, key, hash);
1266
1.92G
#endif
1267
1.92G
        }
1268
103M
        else {
1269
103M
            INCREF_KEYS_FT(dk);
1270
103M
            LOCK_KEYS_IF_SPLIT(dk, kind);
1271
1272
103M
            ix = unicodekeys_lookup_generic(mp, dk, key, hash);
1273
1274
103M
            UNLOCK_KEYS_IF_SPLIT(dk, kind);
1275
103M
            DECREF_KEYS_FT(dk, IS_DICT_SHARED(mp));
1276
103M
            if (ix == DKIX_KEY_CHANGED) {
1277
0
                goto start;
1278
0
            }
1279
103M
        }
1280
1281
2.02G
        if (ix >= 0) {
1282
1.38G
            if (kind == DICT_KEYS_SPLIT) {
1283
4.39M
                *value_addr = mp->ma_values->values[ix];
1284
4.39M
            }
1285
1.37G
            else {
1286
1.37G
                *value_addr = DK_UNICODE_ENTRIES(dk)[ix].me_value;
1287
1.37G
            }
1288
1.38G
        }
1289
646M
        else {
1290
646M
            *value_addr = NULL;
1291
646M
        }
1292
2.02G
    }
1293
639M
    else {
1294
639M
        ix = dictkeys_generic_lookup(mp, dk, key, hash);
1295
639M
        if (ix == DKIX_KEY_CHANGED) {
1296
0
            goto start;
1297
0
        }
1298
639M
        if (ix >= 0) {
1299
190M
            *value_addr = DK_ENTRIES(dk)[ix].me_value;
1300
190M
        }
1301
448M
        else {
1302
448M
            *value_addr = NULL;
1303
448M
        }
1304
639M
    }
1305
1306
2.66G
    return ix;
1307
2.66G
}
1308
1309
#ifdef Py_GIL_DISABLED
1310
static inline void
1311
ensure_shared_on_read(PyDictObject *mp)
1312
{
1313
    if (!_Py_IsOwnedByCurrentThread((PyObject *)mp) && !IS_DICT_SHARED(mp)) {
1314
        // The first time we access a dict from a non-owning thread we mark it
1315
        // as shared. This ensures that a concurrent resize operation will
1316
        // delay freeing the old keys or values using QSBR, which is necessary
1317
        // to safely allow concurrent reads without locking...
1318
        Py_BEGIN_CRITICAL_SECTION(mp);
1319
        if (!IS_DICT_SHARED(mp)) {
1320
            SET_DICT_SHARED(mp);
1321
        }
1322
        Py_END_CRITICAL_SECTION();
1323
    }
1324
}
1325
1326
void
1327
_PyDict_EnsureSharedOnRead(PyDictObject *mp)
1328
{
1329
    ensure_shared_on_read(mp);
1330
}
1331
#endif
1332
1333
static inline void
1334
ensure_shared_on_resize(PyDictObject *mp)
1335
12.6M
{
1336
#ifdef Py_GIL_DISABLED
1337
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(mp);
1338
1339
    if (!_Py_IsOwnedByCurrentThread((PyObject *)mp) && !IS_DICT_SHARED(mp)) {
1340
        // We are writing to the dict from another thread that owns
1341
        // it and we haven't marked it as shared which will ensure
1342
        // that when we re-size ma_keys or ma_values that we will
1343
        // free using QSBR.  We need to lock the dictionary to
1344
        // contend with writes from the owning thread, mark it as
1345
        // shared, and then we can continue with lock-free reads.
1346
        // Technically this is a little heavy handed, we could just
1347
        // free the individual old keys / old-values using qsbr
1348
        SET_DICT_SHARED(mp);
1349
    }
1350
#endif
1351
12.6M
}
1352
1353
static inline void
1354
ensure_shared_on_keys_version_assignment(PyDictObject *mp)
1355
38.0k
{
1356
38.0k
    ASSERT_DICT_LOCKED((PyObject *) mp);
1357
    #ifdef Py_GIL_DISABLED
1358
    if (!IS_DICT_SHARED(mp)) {
1359
        // This ensures that a concurrent resize operation will delay
1360
        // freeing the old keys or values using QSBR, which is necessary to
1361
        // safely allow concurrent reads without locking.
1362
        SET_DICT_SHARED(mp);
1363
    }
1364
    #endif
1365
38.0k
}
1366
1367
#ifdef Py_GIL_DISABLED
1368
1369
static inline Py_ALWAYS_INLINE int
1370
compare_unicode_generic_threadsafe(PyDictObject *mp, PyDictKeysObject *dk,
1371
                                   void *ep0, Py_ssize_t ix, PyObject *key, Py_hash_t hash)
1372
{
1373
    PyDictUnicodeEntry *ep = &((PyDictUnicodeEntry *)ep0)[ix];
1374
    PyObject *startkey = _Py_atomic_load_ptr_relaxed(&ep->me_key);
1375
    assert(startkey == NULL || PyUnicode_CheckExact(ep->me_key));
1376
    assert(!PyUnicode_CheckExact(key));
1377
1378
    if (startkey != NULL) {
1379
        if (!_Py_TryIncrefCompare(&ep->me_key, startkey)) {
1380
            return DKIX_KEY_CHANGED;
1381
        }
1382
1383
        if (unicode_get_hash(startkey) == hash) {
1384
            int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
1385
            Py_DECREF(startkey);
1386
            if (cmp < 0) {
1387
                return DKIX_ERROR;
1388
            }
1389
            if (dk == _Py_atomic_load_ptr_relaxed(&mp->ma_keys) &&
1390
                startkey == _Py_atomic_load_ptr_relaxed(&ep->me_key)) {
1391
                return cmp;
1392
            }
1393
            else {
1394
                /* The dict was mutated, restart */
1395
                return DKIX_KEY_CHANGED;
1396
            }
1397
        }
1398
        else {
1399
            Py_DECREF(startkey);
1400
        }
1401
    }
1402
    return 0;
1403
}
1404
1405
// Search non-Unicode key from Unicode table
1406
static Py_ssize_t
1407
unicodekeys_lookup_generic_threadsafe(PyDictObject *mp, PyDictKeysObject* dk, PyObject *key, Py_hash_t hash)
1408
{
1409
    return do_lookup(mp, dk, key, hash, compare_unicode_generic_threadsafe);
1410
}
1411
1412
static inline Py_ALWAYS_INLINE int
1413
compare_unicode_unicode_threadsafe(PyDictObject *mp, PyDictKeysObject *dk,
1414
                                   void *ep0, Py_ssize_t ix, PyObject *key, Py_hash_t hash)
1415
{
1416
    PyDictUnicodeEntry *ep = &((PyDictUnicodeEntry *)ep0)[ix];
1417
    PyObject *startkey = _Py_atomic_load_ptr_relaxed(&ep->me_key);
1418
    if (startkey == key) {
1419
        assert(PyUnicode_CheckExact(startkey));
1420
        return 1;
1421
    }
1422
    if (startkey != NULL) {
1423
        if (_Py_IsImmortal(startkey)) {
1424
            assert(PyUnicode_CheckExact(startkey));
1425
            return unicode_get_hash(startkey) == hash && unicode_eq(startkey, key);
1426
        }
1427
        else {
1428
            if (!_Py_TryIncrefCompare(&ep->me_key, startkey)) {
1429
                return DKIX_KEY_CHANGED;
1430
            }
1431
            assert(PyUnicode_CheckExact(startkey));
1432
            if (unicode_get_hash(startkey) == hash && unicode_eq(startkey, key)) {
1433
                Py_DECREF(startkey);
1434
                return 1;
1435
            }
1436
            Py_DECREF(startkey);
1437
        }
1438
    }
1439
    return 0;
1440
}
1441
1442
static Py_ssize_t _Py_HOT_FUNCTION
1443
unicodekeys_lookup_unicode_threadsafe(PyDictKeysObject* dk, PyObject *key, Py_hash_t hash)
1444
{
1445
    return do_lookup(NULL, dk, key, hash, compare_unicode_unicode_threadsafe);
1446
}
1447
1448
static inline Py_ALWAYS_INLINE int
1449
compare_generic_threadsafe(PyDictObject *mp, PyDictKeysObject *dk,
1450
                           void *ep0, Py_ssize_t ix, PyObject *key, Py_hash_t hash)
1451
{
1452
    PyDictKeyEntry *ep = &((PyDictKeyEntry *)ep0)[ix];
1453
    PyObject *startkey = _Py_atomic_load_ptr_relaxed(&ep->me_key);
1454
    if (startkey == key) {
1455
        return 1;
1456
    }
1457
    Py_ssize_t ep_hash = _Py_atomic_load_ssize_relaxed(&ep->me_hash);
1458
    if (ep_hash == hash) {
1459
        if (startkey == NULL || !_Py_TryIncrefCompare(&ep->me_key, startkey)) {
1460
            return DKIX_KEY_CHANGED;
1461
        }
1462
        int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
1463
        Py_DECREF(startkey);
1464
        if (cmp < 0) {
1465
            return DKIX_ERROR;
1466
        }
1467
        if (dk == _Py_atomic_load_ptr_relaxed(&mp->ma_keys) &&
1468
            startkey == _Py_atomic_load_ptr_relaxed(&ep->me_key)) {
1469
            return cmp;
1470
        }
1471
        else {
1472
            /* The dict was mutated, restart */
1473
            return DKIX_KEY_CHANGED;
1474
        }
1475
    }
1476
    return 0;
1477
}
1478
1479
static Py_ssize_t
1480
dictkeys_generic_lookup_threadsafe(PyDictObject *mp, PyDictKeysObject* dk, PyObject *key, Py_hash_t hash)
1481
{
1482
    return do_lookup(mp, dk, key, hash, compare_generic_threadsafe);
1483
}
1484
1485
Py_ssize_t
1486
_Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr)
1487
{
1488
    PyDictKeysObject *dk;
1489
    DictKeysKind kind;
1490
    Py_ssize_t ix;
1491
    PyObject *value;
1492
1493
    ensure_shared_on_read(mp);
1494
1495
    dk = _Py_atomic_load_ptr(&mp->ma_keys);
1496
    kind = dk->dk_kind;
1497
1498
    if (kind != DICT_KEYS_GENERAL) {
1499
        if (PyUnicode_CheckExact(key)) {
1500
            ix = unicodekeys_lookup_unicode_threadsafe(dk, key, hash);
1501
        }
1502
        else {
1503
            ix = unicodekeys_lookup_generic_threadsafe(mp, dk, key, hash);
1504
        }
1505
        if (ix == DKIX_KEY_CHANGED) {
1506
            goto read_failed;
1507
        }
1508
1509
        if (ix >= 0) {
1510
            if (kind == DICT_KEYS_SPLIT) {
1511
                PyDictValues *values = _Py_atomic_load_ptr(&mp->ma_values);
1512
                if (values == NULL)
1513
                    goto read_failed;
1514
1515
                uint8_t capacity = _Py_atomic_load_uint8_relaxed(&values->capacity);
1516
                if (ix >= (Py_ssize_t)capacity)
1517
                    goto read_failed;
1518
1519
                value = _Py_TryXGetRef(&values->values[ix]);
1520
                if (value == NULL)
1521
                    goto read_failed;
1522
1523
                if (values != _Py_atomic_load_ptr(&mp->ma_values)) {
1524
                    Py_DECREF(value);
1525
                    goto read_failed;
1526
                }
1527
            }
1528
            else {
1529
                value = _Py_TryXGetRef(&DK_UNICODE_ENTRIES(dk)[ix].me_value);
1530
                if (value == NULL) {
1531
                    goto read_failed;
1532
                }
1533
1534
                if (dk != _Py_atomic_load_ptr(&mp->ma_keys)) {
1535
                    Py_DECREF(value);
1536
                    goto read_failed;
1537
                }
1538
            }
1539
        }
1540
        else {
1541
            value = NULL;
1542
        }
1543
    }
1544
    else {
1545
        ix = dictkeys_generic_lookup_threadsafe(mp, dk, key, hash);
1546
        if (ix == DKIX_KEY_CHANGED) {
1547
            goto read_failed;
1548
        }
1549
        if (ix >= 0) {
1550
            value = _Py_TryXGetRef(&DK_ENTRIES(dk)[ix].me_value);
1551
            if (value == NULL)
1552
                goto read_failed;
1553
1554
            if (dk != _Py_atomic_load_ptr(&mp->ma_keys)) {
1555
                Py_DECREF(value);
1556
                goto read_failed;
1557
            }
1558
        }
1559
        else {
1560
            value = NULL;
1561
        }
1562
    }
1563
1564
    *value_addr = value;
1565
    return ix;
1566
1567
read_failed:
1568
    // In addition to the normal races of the dict being modified the _Py_TryXGetRef
1569
    // can all fail if they don't yet have a shared ref count.  That can happen here
1570
    // or in the *_lookup_* helper.  In that case we need to take the lock to avoid
1571
    // mutation and do a normal incref which will make them shared.
1572
    Py_BEGIN_CRITICAL_SECTION(mp);
1573
    ix = _Py_dict_lookup(mp, key, hash, &value);
1574
    *value_addr = value;
1575
    if (value != NULL) {
1576
        assert(ix >= 0);
1577
        _Py_NewRefWithLock(value);
1578
    }
1579
    Py_END_CRITICAL_SECTION();
1580
    return ix;
1581
}
1582
1583
static Py_ssize_t
1584
lookup_threadsafe_unicode(PyDictKeysObject *dk, PyObject *key, Py_hash_t hash, _PyStackRef *value_addr)
1585
{
1586
    assert(dk->dk_kind == DICT_KEYS_UNICODE);
1587
    assert(PyUnicode_CheckExact(key));
1588
1589
    Py_ssize_t ix = unicodekeys_lookup_unicode_threadsafe(dk, key, hash);
1590
    if (ix == DKIX_EMPTY) {
1591
        *value_addr = PyStackRef_NULL;
1592
        return ix;
1593
    }
1594
    else if (ix >= 0) {
1595
        PyObject **addr_of_value = &DK_UNICODE_ENTRIES(dk)[ix].me_value;
1596
        PyObject *value = _Py_atomic_load_ptr(addr_of_value);
1597
        if (value == NULL) {
1598
            *value_addr = PyStackRef_NULL;
1599
            return DKIX_EMPTY;
1600
        }
1601
        if (_PyObject_HasDeferredRefcount(value)) {
1602
            *value_addr =  (_PyStackRef){ .bits = (uintptr_t)value | Py_TAG_DEFERRED };
1603
            return ix;
1604
        }
1605
        if (_Py_TryIncrefCompare(addr_of_value, value)) {
1606
            *value_addr = PyStackRef_FromPyObjectSteal(value);
1607
            return ix;
1608
        }
1609
        return DKIX_KEY_CHANGED;
1610
    }
1611
    assert(ix == DKIX_KEY_CHANGED);
1612
    return ix;
1613
}
1614
1615
Py_ssize_t
1616
_Py_dict_lookup_threadsafe_stackref(PyDictObject *mp, PyObject *key, Py_hash_t hash, _PyStackRef *value_addr)
1617
{
1618
    PyDictKeysObject *dk = _Py_atomic_load_ptr(&mp->ma_keys);
1619
    if (dk->dk_kind == DICT_KEYS_UNICODE && PyUnicode_CheckExact(key)) {
1620
        Py_ssize_t ix = lookup_threadsafe_unicode(dk, key, hash, value_addr);
1621
        if (ix != DKIX_KEY_CHANGED) {
1622
            return ix;
1623
        }
1624
    }
1625
1626
    PyObject *obj;
1627
    Py_ssize_t ix = _Py_dict_lookup_threadsafe(mp, key, hash, &obj);
1628
    if (ix >= 0 && obj != NULL) {
1629
        *value_addr = PyStackRef_FromPyObjectSteal(obj);
1630
    }
1631
    else {
1632
        *value_addr = PyStackRef_NULL;
1633
    }
1634
    return ix;
1635
}
1636
1637
#else   // Py_GIL_DISABLED
1638
1639
Py_ssize_t
1640
_Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr)
1641
628M
{
1642
628M
    Py_ssize_t ix = _Py_dict_lookup(mp, key, hash, value_addr);
1643
628M
    Py_XNewRef(*value_addr);
1644
628M
    return ix;
1645
628M
}
1646
1647
Py_ssize_t
1648
_Py_dict_lookup_threadsafe_stackref(PyDictObject *mp, PyObject *key, Py_hash_t hash, _PyStackRef *value_addr)
1649
14.4M
{
1650
14.4M
    PyObject *val;
1651
14.4M
    Py_ssize_t ix = _Py_dict_lookup(mp, key, hash, &val);
1652
14.4M
    if (val == NULL) {
1653
97.6k
        *value_addr = PyStackRef_NULL;
1654
97.6k
    }
1655
14.3M
    else {
1656
14.3M
        *value_addr = PyStackRef_FromPyObjectNew(val);
1657
14.3M
    }
1658
14.4M
    return ix;
1659
14.4M
}
1660
1661
#endif
1662
1663
// Looks up the unicode key `key` in the dictionary. Note that `*method` may
1664
// already contain a valid value! See _PyObject_GetMethodStackRef().
1665
int
1666
_PyDict_GetMethodStackRef(PyDictObject *mp, PyObject *key, _PyStackRef *method)
1667
34.1M
{
1668
34.1M
    assert(PyUnicode_CheckExact(key));
1669
34.1M
    Py_hash_t hash = hash_unicode_key(key);
1670
1671
#ifdef Py_GIL_DISABLED
1672
    PyDictKeysObject *dk = _Py_atomic_load_ptr_acquire(&mp->ma_keys);
1673
    if (dk->dk_kind == DICT_KEYS_UNICODE) {
1674
        _PyStackRef ref;
1675
        Py_ssize_t ix = lookup_threadsafe_unicode(dk, key, hash, &ref);
1676
        if (ix >= 0) {
1677
            assert(!PyStackRef_IsNull(ref));
1678
            PyStackRef_XSETREF(*method, ref);
1679
            return 1;
1680
        }
1681
        else if (ix == DKIX_EMPTY) {
1682
            return 0;
1683
        }
1684
        assert(ix == DKIX_KEY_CHANGED);
1685
    }
1686
#endif
1687
1688
34.1M
    PyObject *obj;
1689
34.1M
    Py_INCREF(mp);
1690
34.1M
    Py_ssize_t ix = _Py_dict_lookup_threadsafe(mp, key, hash, &obj);
1691
34.1M
    Py_DECREF(mp);
1692
34.1M
    if (ix == DKIX_ERROR) {
1693
0
        PyStackRef_CLEAR(*method);
1694
0
        return -1;
1695
0
    }
1696
34.1M
    else if (ix >= 0 && obj != NULL) {
1697
2
        PyStackRef_XSETREF(*method, PyStackRef_FromPyObjectSteal(obj));
1698
2
        return 1;
1699
2
    }
1700
34.1M
    return 0;  // not found
1701
34.1M
}
1702
1703
int
1704
_PyDict_HasOnlyStringKeys(PyObject *dict)
1705
292k
{
1706
292k
    Py_ssize_t pos = 0;
1707
292k
    PyObject *key, *value;
1708
292k
    assert(PyDict_Check(dict));
1709
    /* Shortcut */
1710
292k
    if (((PyDictObject *)dict)->ma_keys->dk_kind != DICT_KEYS_GENERAL)
1711
292k
        return 1;
1712
0
    while (PyDict_Next(dict, &pos, &key, &value))
1713
0
        if (!PyUnicode_Check(key))
1714
0
            return 0;
1715
0
    return 1;
1716
0
}
1717
1718
void
1719
_PyDict_EnablePerThreadRefcounting(PyObject *op)
1720
7.45k
{
1721
7.45k
    assert(PyDict_Check(op));
1722
#ifdef Py_GIL_DISABLED
1723
    Py_ssize_t id = _PyObject_AssignUniqueId(op);
1724
    if (id == _Py_INVALID_UNIQUE_ID) {
1725
        return;
1726
    }
1727
    if ((uint64_t)id >= (uint64_t)DICT_UNIQUE_ID_MAX) {
1728
        _PyObject_ReleaseUniqueId(id);
1729
        return;
1730
    }
1731
1732
    PyDictObject *mp = (PyDictObject *)op;
1733
    assert((mp->_ma_watcher_tag >> DICT_UNIQUE_ID_SHIFT) == 0);
1734
    mp->_ma_watcher_tag += (uint64_t)id << DICT_UNIQUE_ID_SHIFT;
1735
#endif
1736
7.45k
}
1737
1738
static inline int
1739
is_unusable_slot(Py_ssize_t ix)
1740
583M
{
1741
#ifdef Py_GIL_DISABLED
1742
    return ix >= 0 || ix == DKIX_DUMMY;
1743
#else
1744
583M
    return ix >= 0;
1745
583M
#endif
1746
583M
}
1747
1748
/* Internal function to find slot for an item from its hash
1749
   when it is known that the key is not present in the dict.
1750
 */
1751
static Py_ssize_t
1752
find_empty_slot(PyDictKeysObject *keys, Py_hash_t hash)
1753
327M
{
1754
327M
    assert(keys != NULL);
1755
1756
327M
    const size_t mask = DK_MASK(keys);
1757
327M
    size_t i = hash & mask;
1758
327M
    Py_ssize_t ix = dictkeys_get_index(keys, i);
1759
583M
    for (size_t perturb = hash; is_unusable_slot(ix);) {
1760
256M
        perturb >>= PERTURB_SHIFT;
1761
256M
        i = (i*5 + perturb + 1) & mask;
1762
256M
        ix = dictkeys_get_index(keys, i);
1763
256M
    }
1764
327M
    return i;
1765
327M
}
1766
1767
static int
1768
insertion_resize(PyDictObject *mp, int unicode)
1769
11.4M
{
1770
11.4M
    return dictresize(mp, calculate_log2_keysize(GROWTH_RATE(mp)), unicode);
1771
11.4M
}
1772
1773
static inline int
1774
insert_combined_dict(PyInterpreterState *interp, PyDictObject *mp,
1775
                     Py_hash_t hash, PyObject *key, PyObject *value)
1776
325M
{
1777
    // gh-140551: If dict was cleared in _Py_dict_lookup,
1778
    // we have to resize one more time to force general key kind.
1779
325M
    if (DK_IS_UNICODE(mp->ma_keys) && !PyUnicode_CheckExact(key)) {
1780
5.24k
        if (insertion_resize(mp, 0) < 0)
1781
0
            return -1;
1782
5.24k
        assert(mp->ma_keys->dk_kind == DICT_KEYS_GENERAL);
1783
5.24k
    }
1784
1785
325M
    if (mp->ma_keys->dk_usable <= 0) {
1786
        /* Need to resize. */
1787
11.4M
        if (insertion_resize(mp, 1) < 0) {
1788
0
            return -1;
1789
0
        }
1790
11.4M
    }
1791
1792
325M
    _PyDict_NotifyEvent(interp, PyDict_EVENT_ADDED, mp, key, value);
1793
325M
    FT_ATOMIC_STORE_UINT32_RELAXED(mp->ma_keys->dk_version, 0);
1794
1795
325M
    Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash);
1796
325M
    dictkeys_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
1797
1798
325M
    if (DK_IS_UNICODE(mp->ma_keys)) {
1799
28.2M
        PyDictUnicodeEntry *ep;
1800
28.2M
        ep = &DK_UNICODE_ENTRIES(mp->ma_keys)[mp->ma_keys->dk_nentries];
1801
28.2M
        STORE_KEY(ep, key);
1802
28.2M
        STORE_VALUE(ep, value);
1803
28.2M
    }
1804
297M
    else {
1805
297M
        PyDictKeyEntry *ep;
1806
297M
        ep = &DK_ENTRIES(mp->ma_keys)[mp->ma_keys->dk_nentries];
1807
297M
        STORE_KEY(ep, key);
1808
297M
        STORE_VALUE(ep, value);
1809
297M
        STORE_HASH(ep, hash);
1810
297M
    }
1811
325M
    STORE_KEYS_USABLE(mp->ma_keys, mp->ma_keys->dk_usable - 1);
1812
325M
    STORE_KEYS_NENTRIES(mp->ma_keys, mp->ma_keys->dk_nentries + 1);
1813
325M
    assert(mp->ma_keys->dk_usable >= 0);
1814
325M
    return 0;
1815
325M
}
1816
1817
static Py_ssize_t
1818
insert_split_key(PyDictKeysObject *keys, PyObject *key, Py_hash_t hash)
1819
19.7M
{
1820
19.7M
    assert(PyUnicode_CheckExact(key));
1821
19.7M
    Py_ssize_t ix;
1822
1823
1824
#ifdef Py_GIL_DISABLED
1825
    ix = unicodekeys_lookup_unicode_threadsafe(keys, key, hash);
1826
    if (ix >= 0) {
1827
        return ix;
1828
    }
1829
#endif
1830
1831
19.7M
    LOCK_KEYS(keys);
1832
19.7M
    ix = unicodekeys_lookup_unicode(keys, key, hash);
1833
19.7M
    if (ix == DKIX_EMPTY && keys->dk_usable > 0) {
1834
        // Insert into new slot
1835
1.69M
        FT_ATOMIC_STORE_UINT32_RELAXED(keys->dk_version, 0);
1836
1.69M
        Py_ssize_t hashpos = find_empty_slot(keys, hash);
1837
1.69M
        ix = keys->dk_nentries;
1838
1.69M
        dictkeys_set_index(keys, hashpos, ix);
1839
1.69M
        PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(keys)[ix];
1840
1.69M
        STORE_SHARED_KEY(ep->me_key, Py_NewRef(key));
1841
1.69M
        split_keys_entry_added(keys);
1842
1.69M
    }
1843
19.7M
    assert (ix < SHARED_KEYS_MAX_SIZE);
1844
19.7M
    UNLOCK_KEYS(keys);
1845
19.7M
    return ix;
1846
19.7M
}
1847
1848
static void
1849
insert_split_value(PyInterpreterState *interp, PyDictObject *mp, PyObject *key, PyObject *value, Py_ssize_t ix)
1850
215k
{
1851
215k
    assert(PyUnicode_CheckExact(key));
1852
215k
    ASSERT_DICT_LOCKED(mp);
1853
215k
    PyObject *old_value = mp->ma_values->values[ix];
1854
215k
    if (old_value == NULL) {
1855
187k
        _PyDict_NotifyEvent(interp, PyDict_EVENT_ADDED, mp, key, value);
1856
187k
        STORE_SPLIT_VALUE(mp, ix, Py_NewRef(value));
1857
187k
        _PyDictValues_AddToInsertionOrder(mp->ma_values, ix);
1858
187k
        STORE_USED(mp, mp->ma_used + 1);
1859
187k
    }
1860
27.9k
    else {
1861
27.9k
        _PyDict_NotifyEvent(interp, PyDict_EVENT_MODIFIED, mp, key, value);
1862
27.9k
        STORE_SPLIT_VALUE(mp, ix, Py_NewRef(value));
1863
        // old_value should be DECREFed after GC track checking is done, if not, it could raise a segmentation fault,
1864
        // when dict only holds the strong reference to value in ep->me_value.
1865
27.9k
        Py_DECREF(old_value);
1866
27.9k
    }
1867
215k
    ASSERT_CONSISTENT(mp);
1868
215k
}
1869
1870
/*
1871
Internal routine to insert a new item into the table.
1872
Used both by the internal resize routine and by the public insert routine.
1873
Returns -1 if an error occurred, or 0 on success.
1874
Consumes key and value references.
1875
*/
1876
static int
1877
insertdict(PyInterpreterState *interp, PyDictObject *mp,
1878
           PyObject *key, Py_hash_t hash, PyObject *value)
1879
445M
{
1880
445M
    PyObject *old_value;
1881
445M
    Py_ssize_t ix;
1882
1883
445M
    ASSERT_DICT_LOCKED(mp);
1884
1885
445M
    if (_PyDict_HasSplitTable(mp) && PyUnicode_CheckExact(key)) {
1886
915k
        ix = insert_split_key(mp->ma_keys, key, hash);
1887
915k
        if (ix != DKIX_EMPTY) {
1888
215k
            insert_split_value(interp, mp, key, value, ix);
1889
215k
            Py_DECREF(key);
1890
215k
            Py_DECREF(value);
1891
215k
            return 0;
1892
215k
        }
1893
        // No space in shared keys. Go to insert_combined_dict() below.
1894
915k
    }
1895
444M
    else {
1896
444M
        ix = _Py_dict_lookup(mp, key, hash, &old_value);
1897
444M
        if (ix == DKIX_ERROR)
1898
0
            goto Fail;
1899
444M
    }
1900
1901
445M
    if (ix == DKIX_EMPTY) {
1902
        // insert_combined_dict() will convert from non DICT_KEYS_GENERAL table
1903
        // into DICT_KEYS_GENERAL table if key is not Unicode.
1904
        // We don't convert it before _Py_dict_lookup because non-Unicode key
1905
        // may change generic table into Unicode table.
1906
321M
        if (insert_combined_dict(interp, mp, hash, key, value) < 0) {
1907
0
            goto Fail;
1908
0
        }
1909
321M
        STORE_USED(mp, mp->ma_used + 1);
1910
321M
        ASSERT_CONSISTENT(mp);
1911
321M
        return 0;
1912
321M
    }
1913
1914
124M
    if (old_value != value) {
1915
98.7M
        _PyDict_NotifyEvent(interp, PyDict_EVENT_MODIFIED, mp, key, value);
1916
98.7M
        assert(old_value != NULL);
1917
98.7M
        if (DK_IS_UNICODE(mp->ma_keys)) {
1918
98.7M
            if (_PyDict_HasSplitTable(mp)) {
1919
0
                STORE_SPLIT_VALUE(mp, ix, value);
1920
0
            }
1921
98.7M
            else {
1922
98.7M
                PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(mp->ma_keys)[ix];
1923
98.7M
                STORE_VALUE(ep, value);
1924
98.7M
            }
1925
98.7M
        }
1926
7.40k
        else {
1927
7.40k
            PyDictKeyEntry *ep = &DK_ENTRIES(mp->ma_keys)[ix];
1928
7.40k
            STORE_VALUE(ep, value);
1929
7.40k
        }
1930
98.7M
    }
1931
124M
    Py_XDECREF(old_value); /* which **CAN** re-enter (see issue #22653) */
1932
124M
    ASSERT_CONSISTENT(mp);
1933
124M
    Py_DECREF(key);
1934
124M
    return 0;
1935
1936
0
Fail:
1937
0
    Py_DECREF(value);
1938
0
    Py_DECREF(key);
1939
0
    return -1;
1940
445M
}
1941
1942
// Same as insertdict but specialized for ma_keys == Py_EMPTY_KEYS.
1943
// Consumes key and value references.
1944
static int
1945
insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp,
1946
                    PyObject *key, Py_hash_t hash, PyObject *value)
1947
38.0M
{
1948
38.0M
    assert(mp->ma_keys == Py_EMPTY_KEYS);
1949
38.0M
    ASSERT_DICT_LOCKED(mp);
1950
1951
38.0M
    int unicode = PyUnicode_CheckExact(key);
1952
38.0M
    PyDictKeysObject *newkeys = new_keys_object(PyDict_LOG_MINSIZE, unicode);
1953
38.0M
    if (newkeys == NULL) {
1954
0
        Py_DECREF(key);
1955
0
        Py_DECREF(value);
1956
0
        return -1;
1957
0
    }
1958
38.0M
    _PyDict_NotifyEvent(interp, PyDict_EVENT_ADDED, mp, key, value);
1959
1960
    /* We don't decref Py_EMPTY_KEYS here because it is immortal. */
1961
38.0M
    assert(mp->ma_values == NULL);
1962
1963
38.0M
    size_t hashpos = (size_t)hash & (PyDict_MINSIZE-1);
1964
38.0M
    dictkeys_set_index(newkeys, hashpos, 0);
1965
38.0M
    if (unicode) {
1966
25.6M
        PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(newkeys);
1967
25.6M
        ep->me_key = key;
1968
25.6M
        STORE_VALUE(ep, value);
1969
25.6M
    }
1970
12.4M
    else {
1971
12.4M
        PyDictKeyEntry *ep = DK_ENTRIES(newkeys);
1972
12.4M
        ep->me_key = key;
1973
12.4M
        ep->me_hash = hash;
1974
12.4M
        STORE_VALUE(ep, value);
1975
12.4M
    }
1976
38.0M
    STORE_USED(mp, mp->ma_used + 1);
1977
38.0M
    newkeys->dk_usable--;
1978
38.0M
    newkeys->dk_nentries++;
1979
    // We store the keys last so no one can see them in a partially inconsistent
1980
    // state so that we don't need to switch the keys to being shared yet for
1981
    // the case where we're inserting from the non-owner thread.  We don't use
1982
    // set_keys here because the transition from empty to non-empty is safe
1983
    // as the empty keys will never be freed.
1984
38.0M
    FT_ATOMIC_STORE_PTR_RELEASE(mp->ma_keys, newkeys);
1985
38.0M
    return 0;
1986
38.0M
}
1987
1988
/*
1989
Internal routine used by dictresize() to build a hashtable of entries.
1990
*/
1991
static void
1992
build_indices_generic(PyDictKeysObject *keys, PyDictKeyEntry *ep, Py_ssize_t n)
1993
9.37M
{
1994
9.37M
    size_t mask = DK_MASK(keys);
1995
402M
    for (Py_ssize_t ix = 0; ix != n; ix++, ep++) {
1996
393M
        Py_hash_t hash = ep->me_hash;
1997
393M
        size_t i = hash & mask;
1998
460M
        for (size_t perturb = hash; dictkeys_get_index(keys, i) != DKIX_EMPTY;) {
1999
67.0M
            perturb >>= PERTURB_SHIFT;
2000
67.0M
            i = mask & (i*5 + perturb + 1);
2001
67.0M
        }
2002
393M
        dictkeys_set_index(keys, i, ix);
2003
393M
    }
2004
9.37M
}
2005
2006
static void
2007
build_indices_unicode(PyDictKeysObject *keys, PyDictUnicodeEntry *ep, Py_ssize_t n)
2008
2.65M
{
2009
2.65M
    size_t mask = DK_MASK(keys);
2010
19.5M
    for (Py_ssize_t ix = 0; ix != n; ix++, ep++) {
2011
16.8M
        Py_hash_t hash = unicode_get_hash(ep->me_key);
2012
16.8M
        assert(hash != -1);
2013
16.8M
        size_t i = hash & mask;
2014
19.8M
        for (size_t perturb = hash; dictkeys_get_index(keys, i) != DKIX_EMPTY;) {
2015
3.02M
            perturb >>= PERTURB_SHIFT;
2016
3.02M
            i = mask & (i*5 + perturb + 1);
2017
3.02M
        }
2018
16.8M
        dictkeys_set_index(keys, i, ix);
2019
16.8M
    }
2020
2.65M
}
2021
2022
static void
2023
invalidate_and_clear_inline_values(PyDictValues *values)
2024
694k
{
2025
694k
    assert(values->embedded);
2026
694k
    FT_ATOMIC_STORE_UINT8(values->valid, 0);
2027
2.24M
    for (int i = 0; i < values->capacity; i++) {
2028
1.55M
        FT_ATOMIC_STORE_PTR_RELEASE(values->values[i], NULL);
2029
1.55M
    }
2030
694k
}
2031
2032
/*
2033
Restructure the table by allocating a new table and reinserting all
2034
items again.  When entries have been deleted, the new table may
2035
actually be smaller than the old one.
2036
If a table is split (its keys and hashes are shared, its values are not),
2037
then the values are temporarily copied into the table, it is resized as
2038
a combined table, then the me_value slots in the old table are NULLed out.
2039
After resizing, a table is always combined.
2040
2041
This function supports:
2042
 - Unicode split -> Unicode combined or Generic
2043
 - Unicode combined -> Unicode combined or Generic
2044
 - Generic -> Generic
2045
*/
2046
static int
2047
dictresize(PyDictObject *mp,
2048
           uint8_t log2_newsize, int unicode)
2049
12.0M
{
2050
12.0M
    PyDictKeysObject *oldkeys, *newkeys;
2051
12.0M
    PyDictValues *oldvalues;
2052
2053
12.0M
    ASSERT_DICT_LOCKED(mp);
2054
2055
12.0M
    if (log2_newsize >= SIZEOF_SIZE_T*8) {
2056
0
        PyErr_NoMemory();
2057
0
        return -1;
2058
0
    }
2059
12.0M
    assert(log2_newsize >= PyDict_LOG_MINSIZE);
2060
2061
12.0M
    oldkeys = mp->ma_keys;
2062
12.0M
    oldvalues = mp->ma_values;
2063
2064
12.0M
    if (!DK_IS_UNICODE(oldkeys)) {
2065
9.37M
        unicode = 0;
2066
9.37M
    }
2067
2068
12.0M
    ensure_shared_on_resize(mp);
2069
    /* NOTE: Current odict checks mp->ma_keys to detect resize happen.
2070
     * So we can't reuse oldkeys even if oldkeys->dk_size == newsize.
2071
     * TODO: Try reusing oldkeys when reimplement odict.
2072
     */
2073
2074
    /* Allocate a new table. */
2075
12.0M
    newkeys = new_keys_object(log2_newsize, unicode);
2076
12.0M
    if (newkeys == NULL) {
2077
0
        return -1;
2078
0
    }
2079
    // New table must be large enough.
2080
12.0M
    assert(newkeys->dk_usable >= mp->ma_used);
2081
2082
12.0M
    Py_ssize_t numentries = mp->ma_used;
2083
2084
12.0M
    if (oldvalues != NULL) {
2085
700k
        LOCK_KEYS(oldkeys);
2086
700k
        PyDictUnicodeEntry *oldentries = DK_UNICODE_ENTRIES(oldkeys);
2087
        /* Convert split table into new combined table.
2088
         * We must incref keys; we can transfer values.
2089
         */
2090
700k
        if (newkeys->dk_kind == DICT_KEYS_GENERAL) {
2091
            // split -> generic
2092
0
            PyDictKeyEntry *newentries = DK_ENTRIES(newkeys);
2093
2094
0
            for (Py_ssize_t i = 0; i < numentries; i++) {
2095
0
                int index = get_index_from_order(mp, i);
2096
0
                PyDictUnicodeEntry *ep = &oldentries[index];
2097
0
                assert(oldvalues->values[index] != NULL);
2098
0
                newentries[i].me_key = Py_NewRef(ep->me_key);
2099
0
                newentries[i].me_hash = unicode_get_hash(ep->me_key);
2100
0
                newentries[i].me_value = oldvalues->values[index];
2101
0
            }
2102
0
            build_indices_generic(newkeys, newentries, numentries);
2103
0
        }
2104
700k
        else { // split -> combined unicode
2105
700k
            PyDictUnicodeEntry *newentries = DK_UNICODE_ENTRIES(newkeys);
2106
2107
1.95M
            for (Py_ssize_t i = 0; i < numentries; i++) {
2108
1.25M
                int index = get_index_from_order(mp, i);
2109
1.25M
                PyDictUnicodeEntry *ep = &oldentries[index];
2110
1.25M
                assert(oldvalues->values[index] != NULL);
2111
1.25M
                newentries[i].me_key = Py_NewRef(ep->me_key);
2112
1.25M
                newentries[i].me_value = oldvalues->values[index];
2113
1.25M
            }
2114
700k
            build_indices_unicode(newkeys, newentries, numentries);
2115
700k
        }
2116
700k
        UNLOCK_KEYS(oldkeys);
2117
700k
        set_keys(mp, newkeys);
2118
700k
        dictkeys_decref(oldkeys, IS_DICT_SHARED(mp));
2119
700k
        set_values(mp, NULL);
2120
700k
        if (oldvalues->embedded) {
2121
694k
            assert(oldvalues->embedded == 1);
2122
694k
            assert(oldvalues->valid == 1);
2123
694k
            invalidate_and_clear_inline_values(oldvalues);
2124
694k
        }
2125
5.58k
        else {
2126
5.58k
            free_values(oldvalues, IS_DICT_SHARED(mp));
2127
5.58k
        }
2128
700k
    }
2129
11.3M
    else {  // oldkeys is combined.
2130
11.3M
        if (oldkeys->dk_kind == DICT_KEYS_GENERAL) {
2131
            // generic -> generic
2132
9.37M
            assert(newkeys->dk_kind == DICT_KEYS_GENERAL);
2133
9.37M
            PyDictKeyEntry *oldentries = DK_ENTRIES(oldkeys);
2134
9.37M
            PyDictKeyEntry *newentries = DK_ENTRIES(newkeys);
2135
9.37M
            if (oldkeys->dk_nentries == numentries) {
2136
9.33M
                memcpy(newentries, oldentries, numentries * sizeof(PyDictKeyEntry));
2137
9.33M
            }
2138
41.3k
            else {
2139
41.3k
                PyDictKeyEntry *ep = oldentries;
2140
507k
                for (Py_ssize_t i = 0; i < numentries; i++) {
2141
1.24M
                    while (ep->me_value == NULL)
2142
782k
                        ep++;
2143
465k
                    newentries[i] = *ep++;
2144
465k
                }
2145
41.3k
            }
2146
9.37M
            build_indices_generic(newkeys, newentries, numentries);
2147
9.37M
        }
2148
1.95M
        else {  // oldkeys is combined unicode
2149
1.95M
            PyDictUnicodeEntry *oldentries = DK_UNICODE_ENTRIES(oldkeys);
2150
1.95M
            if (unicode) { // combined unicode -> combined unicode
2151
1.95M
                PyDictUnicodeEntry *newentries = DK_UNICODE_ENTRIES(newkeys);
2152
1.95M
                if (oldkeys->dk_nentries == numentries && mp->ma_keys->dk_kind == DICT_KEYS_UNICODE) {
2153
1.94M
                    memcpy(newentries, oldentries, numentries * sizeof(PyDictUnicodeEntry));
2154
1.94M
                }
2155
5.74k
                else {
2156
5.74k
                    PyDictUnicodeEntry *ep = oldentries;
2157
627k
                    for (Py_ssize_t i = 0; i < numentries; i++) {
2158
642k
                        while (ep->me_value == NULL)
2159
20.8k
                            ep++;
2160
621k
                        newentries[i] = *ep++;
2161
621k
                    }
2162
5.74k
                }
2163
1.95M
                build_indices_unicode(newkeys, newentries, numentries);
2164
1.95M
            }
2165
5.24k
            else { // combined unicode -> generic
2166
5.24k
                PyDictKeyEntry *newentries = DK_ENTRIES(newkeys);
2167
5.24k
                PyDictUnicodeEntry *ep = oldentries;
2168
18.0k
                for (Py_ssize_t i = 0; i < numentries; i++) {
2169
12.8k
                    while (ep->me_value == NULL)
2170
0
                        ep++;
2171
12.8k
                    newentries[i].me_key = ep->me_key;
2172
12.8k
                    newentries[i].me_hash = unicode_get_hash(ep->me_key);
2173
12.8k
                    newentries[i].me_value = ep->me_value;
2174
12.8k
                    ep++;
2175
12.8k
                }
2176
5.24k
                build_indices_generic(newkeys, newentries, numentries);
2177
5.24k
            }
2178
1.95M
        }
2179
2180
11.3M
        set_keys(mp, newkeys);
2181
2182
11.3M
        if (oldkeys != Py_EMPTY_KEYS) {
2183
#ifdef Py_REF_DEBUG
2184
            _Py_DecRefTotal(_PyThreadState_GET());
2185
#endif
2186
10.7M
            assert(oldkeys->dk_kind != DICT_KEYS_SPLIT);
2187
10.7M
            assert(oldkeys->dk_refcnt == 1);
2188
10.7M
            free_keys_object(oldkeys, IS_DICT_SHARED(mp));
2189
10.7M
        }
2190
11.3M
    }
2191
2192
12.0M
    STORE_KEYS_USABLE(mp->ma_keys, mp->ma_keys->dk_usable - numentries);
2193
12.0M
    STORE_KEYS_NENTRIES(mp->ma_keys, numentries);
2194
12.0M
    ASSERT_CONSISTENT(mp);
2195
12.0M
    return 0;
2196
12.0M
}
2197
2198
static PyObject *
2199
dict_new_presized(Py_ssize_t minused, bool unicode)
2200
272M
{
2201
272M
    const uint8_t log2_max_presize = 17;
2202
272M
    const Py_ssize_t max_presize = ((Py_ssize_t)1) << log2_max_presize;
2203
272M
    uint8_t log2_newsize;
2204
272M
    PyDictKeysObject *new_keys;
2205
2206
272M
    if (minused <= USABLE_FRACTION(PyDict_MINSIZE)) {
2207
272M
        return PyDict_New();
2208
272M
    }
2209
    /* There are no strict guarantee that returned dict can contain minused
2210
     * items without resize.  So we create medium size dict instead of very
2211
     * large dict or MemoryError.
2212
     */
2213
6.17k
    if (minused > USABLE_FRACTION(max_presize)) {
2214
0
        log2_newsize = log2_max_presize;
2215
0
    }
2216
6.17k
    else {
2217
6.17k
        log2_newsize = estimate_log2_keysize(minused);
2218
6.17k
    }
2219
2220
6.17k
    new_keys = new_keys_object(log2_newsize, unicode);
2221
6.17k
    if (new_keys == NULL)
2222
0
        return NULL;
2223
6.17k
    return new_dict(new_keys, NULL, 0, 0);
2224
6.17k
}
2225
2226
PyObject *
2227
_PyDict_NewPresized(Py_ssize_t minused)
2228
0
{
2229
0
    return dict_new_presized(minused, false);
2230
0
}
2231
2232
PyObject *
2233
_PyDict_FromItems(PyObject *const *keys, Py_ssize_t keys_offset,
2234
                  PyObject *const *values, Py_ssize_t values_offset,
2235
                  Py_ssize_t length)
2236
272M
{
2237
272M
    bool unicode = true;
2238
272M
    PyObject *const *ks = keys;
2239
2240
282M
    for (Py_ssize_t i = 0; i < length; i++) {
2241
9.99M
        if (!PyUnicode_CheckExact(*ks)) {
2242
379
            unicode = false;
2243
379
            break;
2244
379
        }
2245
9.99M
        ks += keys_offset;
2246
9.99M
    }
2247
2248
272M
    PyObject *dict = dict_new_presized(length, unicode);
2249
272M
    if (dict == NULL) {
2250
0
        return NULL;
2251
0
    }
2252
2253
272M
    ks = keys;
2254
272M
    PyObject *const *vs = values;
2255
2256
282M
    for (Py_ssize_t i = 0; i < length; i++) {
2257
9.99M
        PyObject *key = *ks;
2258
9.99M
        PyObject *value = *vs;
2259
9.99M
        if (setitem_lock_held((PyDictObject *)dict, key, value) < 0) {
2260
0
            Py_DECREF(dict);
2261
0
            return NULL;
2262
0
        }
2263
9.99M
        ks += keys_offset;
2264
9.99M
        vs += values_offset;
2265
9.99M
    }
2266
2267
272M
    return dict;
2268
272M
}
2269
2270
/* Note that, for historical reasons, PyDict_GetItem() suppresses all errors
2271
 * that may occur (originally dicts supported only string keys, and exceptions
2272
 * weren't possible).  So, while the original intent was that a NULL return
2273
 * meant the key wasn't present, in reality it can mean that, or that an error
2274
 * (suppressed) occurred while computing the key's hash, or that some error
2275
 * (suppressed) occurred when comparing keys in the dict's internal probe
2276
 * sequence.  A nasty example of the latter is when a Python-coded comparison
2277
 * function hits a stack-depth error, which can cause this to return NULL
2278
 * even if the key is present.
2279
 */
2280
static PyObject *
2281
dict_getitem(PyObject *op, PyObject *key, const char *warnmsg)
2282
287k
{
2283
287k
    if (!PyDict_Check(op)) {
2284
0
        return NULL;
2285
0
    }
2286
287k
    PyDictObject *mp = (PyDictObject *)op;
2287
2288
287k
    Py_hash_t hash = _PyObject_HashFast(key);
2289
287k
    if (hash == -1) {
2290
0
        PyErr_FormatUnraisable(warnmsg);
2291
0
        return NULL;
2292
0
    }
2293
2294
287k
    PyThreadState *tstate = _PyThreadState_GET();
2295
#ifdef Py_DEBUG
2296
    // bpo-40839: Before Python 3.10, it was possible to call PyDict_GetItem()
2297
    // with the GIL released.
2298
    _Py_EnsureTstateNotNULL(tstate);
2299
#endif
2300
2301
    /* Preserve the existing exception */
2302
287k
    PyObject *value;
2303
287k
    Py_ssize_t ix; (void)ix;
2304
2305
287k
    PyObject *exc = _PyErr_GetRaisedException(tstate);
2306
#ifdef Py_GIL_DISABLED
2307
    ix = _Py_dict_lookup_threadsafe(mp, key, hash, &value);
2308
    Py_XDECREF(value);
2309
#else
2310
287k
    ix = _Py_dict_lookup(mp, key, hash, &value);
2311
287k
#endif
2312
2313
    /* Ignore any exception raised by the lookup */
2314
287k
    PyObject *exc2 = _PyErr_Occurred(tstate);
2315
287k
    if (exc2 && !PyErr_GivenExceptionMatches(exc2, PyExc_KeyError)) {
2316
0
        PyErr_FormatUnraisable(warnmsg);
2317
0
    }
2318
287k
    _PyErr_SetRaisedException(tstate, exc);
2319
2320
287k
    assert(ix >= 0 || value == NULL);
2321
287k
    return value;  // borrowed reference
2322
287k
}
2323
2324
PyObject *
2325
PyDict_GetItem(PyObject *op, PyObject *key)
2326
287k
{
2327
287k
    return dict_getitem(op, key,
2328
287k
            "Exception ignored in PyDict_GetItem(); consider using "
2329
287k
            "PyDict_GetItemRef() or PyDict_GetItemWithError()");
2330
287k
}
2331
2332
static void
2333
dict_unhashable_type(PyObject *key)
2334
0
{
2335
0
    PyObject *exc = PyErr_GetRaisedException();
2336
0
    assert(exc != NULL);
2337
0
    if (!Py_IS_TYPE(exc, (PyTypeObject*)PyExc_TypeError)) {
2338
0
        PyErr_SetRaisedException(exc);
2339
0
        return;
2340
0
    }
2341
2342
0
    PyErr_Format(PyExc_TypeError,
2343
0
                 "cannot use '%T' as a dict key (%S)",
2344
0
                 key, exc);
2345
0
    Py_DECREF(exc);
2346
0
}
2347
2348
Py_ssize_t
2349
_PyDict_LookupIndex(PyDictObject *mp, PyObject *key)
2350
23.0k
{
2351
    // TODO: Thread safety
2352
23.0k
    PyObject *value;
2353
23.0k
    assert(PyDict_CheckExact((PyObject*)mp));
2354
23.0k
    assert(PyUnicode_CheckExact(key));
2355
2356
23.0k
    Py_hash_t hash = _PyObject_HashFast(key);
2357
23.0k
    if (hash == -1) {
2358
0
        dict_unhashable_type(key);
2359
0
        return -1;
2360
0
    }
2361
2362
23.0k
    return _Py_dict_lookup(mp, key, hash, &value);
2363
23.0k
}
2364
2365
/* Same as PyDict_GetItemWithError() but with hash supplied by caller.
2366
   This returns NULL *with* an exception set if an exception occurred.
2367
   It returns NULL *without* an exception set if the key wasn't present.
2368
*/
2369
PyObject *
2370
_PyDict_GetItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
2371
0
{
2372
0
    Py_ssize_t ix; (void)ix;
2373
0
    PyDictObject *mp = (PyDictObject *)op;
2374
0
    PyObject *value;
2375
2376
0
    if (!PyDict_Check(op)) {
2377
0
        PyErr_BadInternalCall();
2378
0
        return NULL;
2379
0
    }
2380
2381
#ifdef Py_GIL_DISABLED
2382
    ix = _Py_dict_lookup_threadsafe(mp, key, hash, &value);
2383
    Py_XDECREF(value);
2384
#else
2385
0
    ix = _Py_dict_lookup(mp, key, hash, &value);
2386
0
#endif
2387
0
    assert(ix >= 0 || value == NULL);
2388
0
    return value;  // borrowed reference
2389
0
}
2390
2391
/* Gets an item and provides a new reference if the value is present.
2392
 * Returns 1 if the key is present, 0 if the key is missing, and -1 if an
2393
 * exception occurred.
2394
*/
2395
int
2396
_PyDict_GetItemRef_KnownHash_LockHeld(PyDictObject *op, PyObject *key,
2397
                                      Py_hash_t hash, PyObject **result)
2398
52
{
2399
52
    PyObject *value;
2400
52
    Py_ssize_t ix = _Py_dict_lookup(op, key, hash, &value);
2401
52
    assert(ix >= 0 || value == NULL);
2402
52
    if (ix == DKIX_ERROR) {
2403
0
        *result = NULL;
2404
0
        return -1;
2405
0
    }
2406
52
    if (value == NULL) {
2407
32
        *result = NULL;
2408
32
        return 0;  // missing key
2409
32
    }
2410
20
    *result = Py_NewRef(value);
2411
20
    return 1;  // key is present
2412
52
}
2413
2414
/* Gets an item and provides a new reference if the value is present.
2415
 * Returns 1 if the key is present, 0 if the key is missing, and -1 if an
2416
 * exception occurred.
2417
*/
2418
int
2419
_PyDict_GetItemRef_KnownHash(PyDictObject *op, PyObject *key, Py_hash_t hash, PyObject **result)
2420
1.04G
{
2421
1.04G
    PyObject *value;
2422
#ifdef Py_GIL_DISABLED
2423
    Py_ssize_t ix = _Py_dict_lookup_threadsafe(op, key, hash, &value);
2424
#else
2425
1.04G
    Py_ssize_t ix = _Py_dict_lookup(op, key, hash, &value);
2426
1.04G
#endif
2427
1.04G
    assert(ix >= 0 || value == NULL);
2428
1.04G
    if (ix == DKIX_ERROR) {
2429
0
        *result = NULL;
2430
0
        return -1;
2431
0
    }
2432
1.04G
    if (value == NULL) {
2433
235M
        *result = NULL;
2434
235M
        return 0;  // missing key
2435
235M
    }
2436
#ifdef Py_GIL_DISABLED
2437
    *result = value;
2438
#else
2439
810M
    *result = Py_NewRef(value);
2440
810M
#endif
2441
810M
    return 1;  // key is present
2442
1.04G
}
2443
2444
int
2445
PyDict_GetItemRef(PyObject *op, PyObject *key, PyObject **result)
2446
825M
{
2447
825M
    if (!PyDict_Check(op)) {
2448
0
        PyErr_BadInternalCall();
2449
0
        *result = NULL;
2450
0
        return -1;
2451
0
    }
2452
2453
825M
    Py_hash_t hash = _PyObject_HashFast(key);
2454
825M
    if (hash == -1) {
2455
0
        dict_unhashable_type(key);
2456
0
        *result = NULL;
2457
0
        return -1;
2458
0
    }
2459
2460
825M
    return _PyDict_GetItemRef_KnownHash((PyDictObject *)op, key, hash, result);
2461
825M
}
2462
2463
int
2464
_PyDict_GetItemRef_Unicode_LockHeld(PyDictObject *op, PyObject *key, PyObject **result)
2465
26.4k
{
2466
26.4k
    ASSERT_DICT_LOCKED(op);
2467
26.4k
    assert(PyUnicode_CheckExact(key));
2468
2469
26.4k
    Py_hash_t hash = _PyObject_HashFast(key);
2470
26.4k
    if (hash == -1) {
2471
0
        dict_unhashable_type(key);
2472
0
        *result = NULL;
2473
0
        return -1;
2474
0
    }
2475
2476
26.4k
    PyObject *value;
2477
26.4k
    Py_ssize_t ix = _Py_dict_lookup(op, key, hash, &value);
2478
26.4k
    assert(ix >= 0 || value == NULL);
2479
26.4k
    if (ix == DKIX_ERROR) {
2480
0
        *result = NULL;
2481
0
        return -1;
2482
0
    }
2483
26.4k
    if (value == NULL) {
2484
7.88k
        *result = NULL;
2485
7.88k
        return 0;  // missing key
2486
7.88k
    }
2487
18.6k
    *result = Py_NewRef(value);
2488
18.6k
    return 1;  // key is present
2489
26.4k
}
2490
2491
/* Variant of PyDict_GetItem() that doesn't suppress exceptions.
2492
   This returns NULL *with* an exception set if an exception occurred.
2493
   It returns NULL *without* an exception set if the key wasn't present.
2494
*/
2495
PyObject *
2496
PyDict_GetItemWithError(PyObject *op, PyObject *key)
2497
31.3M
{
2498
31.3M
    Py_ssize_t ix; (void)ix;
2499
31.3M
    Py_hash_t hash;
2500
31.3M
    PyDictObject*mp = (PyDictObject *)op;
2501
31.3M
    PyObject *value;
2502
2503
31.3M
    if (!PyDict_Check(op)) {
2504
0
        PyErr_BadInternalCall();
2505
0
        return NULL;
2506
0
    }
2507
31.3M
    hash = _PyObject_HashFast(key);
2508
31.3M
    if (hash == -1) {
2509
0
        dict_unhashable_type(key);
2510
0
        return NULL;
2511
0
    }
2512
2513
#ifdef Py_GIL_DISABLED
2514
    ix = _Py_dict_lookup_threadsafe(mp, key, hash, &value);
2515
    Py_XDECREF(value);
2516
#else
2517
31.3M
    ix = _Py_dict_lookup(mp, key, hash, &value);
2518
31.3M
#endif
2519
31.3M
    assert(ix >= 0 || value == NULL);
2520
31.3M
    return value;  // borrowed reference
2521
31.3M
}
2522
2523
PyObject *
2524
_PyDict_GetItemWithError(PyObject *dp, PyObject *kv)
2525
0
{
2526
0
    assert(PyUnicode_CheckExact(kv));
2527
0
    Py_hash_t hash = Py_TYPE(kv)->tp_hash(kv);
2528
0
    if (hash == -1) {
2529
0
        return NULL;
2530
0
    }
2531
0
    return _PyDict_GetItem_KnownHash(dp, kv, hash);  // borrowed reference
2532
0
}
2533
2534
PyObject *
2535
_PyDict_GetItemStringWithError(PyObject *v, const char *key)
2536
0
{
2537
0
    PyObject *kv, *rv;
2538
0
    kv = PyUnicode_FromString(key);
2539
0
    if (kv == NULL) {
2540
0
        return NULL;
2541
0
    }
2542
0
    rv = PyDict_GetItemWithError(v, kv);
2543
0
    Py_DECREF(kv);
2544
0
    return rv;
2545
0
}
2546
2547
/* Fast version of global value lookup (LOAD_GLOBAL).
2548
 * Lookup in globals, then builtins.
2549
 *
2550
 *
2551
 *
2552
 *
2553
 * Raise an exception and return NULL if an error occurred (ex: computing the
2554
 * key hash failed, key comparison failed, ...). Return NULL if the key doesn't
2555
 * exist. Return the value if the key exists.
2556
 *
2557
 * Returns a new reference.
2558
 */
2559
PyObject *
2560
_PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key)
2561
122
{
2562
122
    Py_ssize_t ix;
2563
122
    Py_hash_t hash;
2564
122
    PyObject *value;
2565
2566
122
    hash = _PyObject_HashFast(key);
2567
122
    if (hash == -1) {
2568
0
        return NULL;
2569
0
    }
2570
2571
    /* namespace 1: globals */
2572
122
    ix = _Py_dict_lookup_threadsafe(globals, key, hash, &value);
2573
122
    if (ix == DKIX_ERROR)
2574
0
        return NULL;
2575
122
    if (ix != DKIX_EMPTY && value != NULL)
2576
10
        return value;
2577
2578
    /* namespace 2: builtins */
2579
112
    ix = _Py_dict_lookup_threadsafe(builtins, key, hash, &value);
2580
112
    assert(ix >= 0 || value == NULL);
2581
112
    return value;
2582
122
}
2583
2584
void
2585
_PyDict_LoadGlobalStackRef(PyDictObject *globals, PyDictObject *builtins, PyObject *key, _PyStackRef *res)
2586
158k
{
2587
158k
    Py_ssize_t ix;
2588
158k
    Py_hash_t hash;
2589
2590
158k
    hash = _PyObject_HashFast(key);
2591
158k
    if (hash == -1) {
2592
0
        *res = PyStackRef_NULL;
2593
0
        return;
2594
0
    }
2595
2596
    /* namespace 1: globals */
2597
158k
    ix = _Py_dict_lookup_threadsafe_stackref(globals, key, hash, res);
2598
158k
    if (ix == DKIX_ERROR) {
2599
0
        return;
2600
0
    }
2601
158k
    if (ix != DKIX_EMPTY && !PyStackRef_IsNull(*res)) {
2602
60.8k
        return;
2603
60.8k
    }
2604
2605
    /* namespace 2: builtins */
2606
97.6k
    ix = _Py_dict_lookup_threadsafe_stackref(builtins, key, hash, res);
2607
97.6k
    assert(ix >= 0 || PyStackRef_IsNull(*res));
2608
97.6k
}
2609
2610
PyObject *
2611
_PyDict_LoadBuiltinsFromGlobals(PyObject *globals)
2612
14.1M
{
2613
14.1M
    if (!PyDict_Check(globals)) {
2614
0
        PyErr_BadInternalCall();
2615
0
        return NULL;
2616
0
    }
2617
2618
14.1M
    PyDictObject *mp = (PyDictObject *)globals;
2619
14.1M
    PyObject *key = &_Py_ID(__builtins__);
2620
14.1M
    Py_hash_t hash = unicode_get_hash(key);
2621
2622
    // Use the stackref variant to avoid reference count contention on the
2623
    // builtins module in the free threading build. It's important not to
2624
    // make any escaping calls between the lookup and the `PyStackRef_CLOSE()`
2625
    // because the `ref` is not visible to the GC.
2626
14.1M
    _PyStackRef ref;
2627
14.1M
    Py_ssize_t ix = _Py_dict_lookup_threadsafe_stackref(mp, key, hash, &ref);
2628
14.1M
    if (ix == DKIX_ERROR) {
2629
0
        return NULL;
2630
0
    }
2631
14.1M
    if (PyStackRef_IsNull(ref)) {
2632
42
        return Py_NewRef(PyEval_GetBuiltins());
2633
42
    }
2634
14.1M
    PyObject *builtins = PyStackRef_AsPyObjectBorrow(ref);
2635
14.1M
    if (PyModule_Check(builtins)) {
2636
56
        builtins = _PyModule_GetDict(builtins);
2637
56
        assert(builtins != NULL);
2638
56
    }
2639
14.1M
    _Py_INCREF_BUILTINS(builtins);
2640
14.1M
    PyStackRef_CLOSE(ref);
2641
14.1M
    return builtins;
2642
14.1M
}
2643
2644
/* Consumes references to key and value */
2645
static int
2646
setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value)
2647
481M
{
2648
481M
    ASSERT_DICT_LOCKED(mp);
2649
2650
481M
    assert(key);
2651
481M
    assert(value);
2652
481M
    assert(PyDict_Check(mp));
2653
481M
    Py_hash_t hash = _PyObject_HashFast(key);
2654
481M
    if (hash == -1) {
2655
0
        dict_unhashable_type(key);
2656
0
        Py_DECREF(key);
2657
0
        Py_DECREF(value);
2658
0
        return -1;
2659
0
    }
2660
2661
481M
    PyInterpreterState *interp = _PyInterpreterState_GET();
2662
2663
481M
    if (mp->ma_keys == Py_EMPTY_KEYS) {
2664
37.5M
        return insert_to_emptydict(interp, mp, key, hash, value);
2665
37.5M
    }
2666
    /* insertdict() handles any resizing that might be necessary */
2667
444M
    return insertdict(interp, mp, key, hash, value);
2668
481M
}
2669
2670
int
2671
_PyDict_SetItem_Take2(PyDictObject *mp, PyObject *key, PyObject *value)
2672
407M
{
2673
407M
    int res;
2674
407M
    Py_BEGIN_CRITICAL_SECTION(mp);
2675
407M
    res = setitem_take2_lock_held(mp, key, value);
2676
407M
    Py_END_CRITICAL_SECTION();
2677
407M
    return res;
2678
407M
}
2679
2680
/* CAUTION: PyDict_SetItem() must guarantee that it won't resize the
2681
 * dictionary if it's merely replacing the value for an existing key.
2682
 * This means that it's safe to loop over a dictionary with PyDict_Next()
2683
 * and occasionally replace a value -- but you can't insert new keys or
2684
 * remove them.
2685
 */
2686
int
2687
PyDict_SetItem(PyObject *op, PyObject *key, PyObject *value)
2688
7.39M
{
2689
7.39M
    if (!PyDict_Check(op)) {
2690
0
        PyErr_BadInternalCall();
2691
0
        return -1;
2692
0
    }
2693
7.39M
    assert(key);
2694
7.39M
    assert(value);
2695
7.39M
    return _PyDict_SetItem_Take2((PyDictObject *)op,
2696
7.39M
                                 Py_NewRef(key), Py_NewRef(value));
2697
7.39M
}
2698
2699
static int
2700
setitem_lock_held(PyDictObject *mp, PyObject *key, PyObject *value)
2701
74.8M
{
2702
74.8M
    assert(key);
2703
74.8M
    assert(value);
2704
74.8M
    return setitem_take2_lock_held(mp,
2705
74.8M
                                   Py_NewRef(key), Py_NewRef(value));
2706
74.8M
}
2707
2708
2709
int
2710
_PyDict_SetItem_KnownHash_LockHeld(PyDictObject *mp, PyObject *key, PyObject *value,
2711
                                   Py_hash_t hash)
2712
234
{
2713
234
    PyInterpreterState *interp = _PyInterpreterState_GET();
2714
234
    if (mp->ma_keys == Py_EMPTY_KEYS) {
2715
29
        return insert_to_emptydict(interp, mp, Py_NewRef(key), hash, Py_NewRef(value));
2716
29
    }
2717
    /* insertdict() handles any resizing that might be necessary */
2718
205
    return insertdict(interp, mp, Py_NewRef(key), hash, Py_NewRef(value));
2719
234
}
2720
2721
int
2722
_PyDict_SetItem_KnownHash(PyObject *op, PyObject *key, PyObject *value,
2723
                          Py_hash_t hash)
2724
42
{
2725
42
    if (!PyDict_Check(op)) {
2726
0
        PyErr_BadInternalCall();
2727
0
        return -1;
2728
0
    }
2729
42
    assert(key);
2730
42
    assert(value);
2731
42
    assert(hash != -1);
2732
2733
42
    int res;
2734
42
    Py_BEGIN_CRITICAL_SECTION(op);
2735
42
    res = _PyDict_SetItem_KnownHash_LockHeld((PyDictObject *)op, key, value, hash);
2736
42
    Py_END_CRITICAL_SECTION();
2737
42
    return res;
2738
42
}
2739
2740
static void
2741
delete_index_from_values(PyDictValues *values, Py_ssize_t ix)
2742
205k
{
2743
205k
    uint8_t *array = get_insertion_order_array(values);
2744
205k
    int size = values->size;
2745
205k
    assert(size <= values->capacity);
2746
205k
    int i;
2747
547k
    for (i = 0; array[i] != ix; i++) {
2748
341k
        assert(i < size);
2749
341k
    }
2750
205k
    assert(i < size);
2751
205k
    size--;
2752
478k
    for (; i < size; i++) {
2753
273k
        array[i] = array[i+1];
2754
273k
    }
2755
205k
    values->size = size;
2756
205k
}
2757
2758
static void
2759
delitem_common(PyDictObject *mp, Py_hash_t hash, Py_ssize_t ix,
2760
               PyObject *old_value)
2761
3.16M
{
2762
3.16M
    PyObject *old_key;
2763
2764
3.16M
    ASSERT_DICT_LOCKED(mp);
2765
2766
3.16M
    Py_ssize_t hashpos = lookdict_index(mp->ma_keys, hash, ix);
2767
3.16M
    assert(hashpos >= 0);
2768
2769
3.16M
    STORE_USED(mp, mp->ma_used - 1);
2770
3.16M
    if (_PyDict_HasSplitTable(mp)) {
2771
0
        assert(old_value == mp->ma_values->values[ix]);
2772
0
        STORE_SPLIT_VALUE(mp, ix, NULL);
2773
0
        assert(ix < SHARED_KEYS_MAX_SIZE);
2774
        /* Update order */
2775
0
        delete_index_from_values(mp->ma_values, ix);
2776
0
        ASSERT_CONSISTENT(mp);
2777
0
    }
2778
3.16M
    else {
2779
3.16M
        FT_ATOMIC_STORE_UINT32_RELAXED(mp->ma_keys->dk_version, 0);
2780
3.16M
        dictkeys_set_index(mp->ma_keys, hashpos, DKIX_DUMMY);
2781
3.16M
        if (DK_IS_UNICODE(mp->ma_keys)) {
2782
1.38M
            PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(mp->ma_keys)[ix];
2783
1.38M
            old_key = ep->me_key;
2784
1.38M
            STORE_KEY(ep, NULL);
2785
1.38M
            STORE_VALUE(ep, NULL);
2786
1.38M
        }
2787
1.78M
        else {
2788
1.78M
            PyDictKeyEntry *ep = &DK_ENTRIES(mp->ma_keys)[ix];
2789
1.78M
            old_key = ep->me_key;
2790
1.78M
            STORE_KEY(ep, NULL);
2791
1.78M
            STORE_VALUE(ep, NULL);
2792
1.78M
            STORE_HASH(ep, 0);
2793
1.78M
        }
2794
3.16M
        Py_DECREF(old_key);
2795
3.16M
    }
2796
3.16M
    Py_DECREF(old_value);
2797
2798
3.16M
    ASSERT_CONSISTENT(mp);
2799
3.16M
}
2800
2801
int
2802
PyDict_DelItem(PyObject *op, PyObject *key)
2803
2.24M
{
2804
2.24M
    assert(key);
2805
2.24M
    Py_hash_t hash = _PyObject_HashFast(key);
2806
2.24M
    if (hash == -1) {
2807
0
        dict_unhashable_type(key);
2808
0
        return -1;
2809
0
    }
2810
2811
2.24M
    return _PyDict_DelItem_KnownHash(op, key, hash);
2812
2.24M
}
2813
2814
int
2815
_PyDict_DelItem_KnownHash_LockHeld(PyObject *op, PyObject *key, Py_hash_t hash)
2816
2.25M
{
2817
2.25M
    Py_ssize_t ix;
2818
2.25M
    PyDictObject *mp;
2819
2.25M
    PyObject *old_value;
2820
2821
2.25M
    if (!PyDict_Check(op)) {
2822
0
        PyErr_BadInternalCall();
2823
0
        return -1;
2824
0
    }
2825
2826
2.25M
    ASSERT_DICT_LOCKED(op);
2827
2828
2.25M
    assert(key);
2829
2.25M
    assert(hash != -1);
2830
2.25M
    mp = (PyDictObject *)op;
2831
2.25M
    ix = _Py_dict_lookup(mp, key, hash, &old_value);
2832
2.25M
    if (ix == DKIX_ERROR)
2833
0
        return -1;
2834
2.25M
    if (ix == DKIX_EMPTY || old_value == NULL) {
2835
0
        _PyErr_SetKeyError(key);
2836
0
        return -1;
2837
0
    }
2838
2839
2.25M
    PyInterpreterState *interp = _PyInterpreterState_GET();
2840
2.25M
    _PyDict_NotifyEvent(interp, PyDict_EVENT_DELETED, mp, key, NULL);
2841
2.25M
    delitem_common(mp, hash, ix, old_value);
2842
2.25M
    return 0;
2843
2.25M
}
2844
2845
int
2846
_PyDict_DelItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
2847
2.24M
{
2848
2.24M
    int res;
2849
2.24M
    Py_BEGIN_CRITICAL_SECTION(op);
2850
2.24M
    res = _PyDict_DelItem_KnownHash_LockHeld(op, key, hash);
2851
2.24M
    Py_END_CRITICAL_SECTION();
2852
2.24M
    return res;
2853
2.24M
}
2854
2855
static int
2856
delitemif_lock_held(PyObject *op, PyObject *key,
2857
                    int (*predicate)(PyObject *value, void *arg),
2858
                    void *arg)
2859
14.1k
{
2860
14.1k
    Py_ssize_t ix;
2861
14.1k
    PyDictObject *mp;
2862
14.1k
    Py_hash_t hash;
2863
14.1k
    PyObject *old_value;
2864
14.1k
    int res;
2865
2866
14.1k
    ASSERT_DICT_LOCKED(op);
2867
2868
14.1k
    assert(key);
2869
14.1k
    hash = PyObject_Hash(key);
2870
14.1k
    if (hash == -1)
2871
0
        return -1;
2872
14.1k
    mp = (PyDictObject *)op;
2873
14.1k
    ix = _Py_dict_lookup(mp, key, hash, &old_value);
2874
14.1k
    if (ix == DKIX_ERROR) {
2875
0
        return -1;
2876
0
    }
2877
14.1k
    if (ix == DKIX_EMPTY || old_value == NULL) {
2878
0
        return 0;
2879
0
    }
2880
2881
14.1k
    res = predicate(old_value, arg);
2882
14.1k
    if (res == -1)
2883
0
        return -1;
2884
2885
14.1k
    if (res > 0) {
2886
14.1k
        PyInterpreterState *interp = _PyInterpreterState_GET();
2887
14.1k
        _PyDict_NotifyEvent(interp, PyDict_EVENT_DELETED, mp, key, NULL);
2888
14.1k
        delitem_common(mp, hash, ix, old_value);
2889
14.1k
        return 1;
2890
14.1k
    } else {
2891
0
        return 0;
2892
0
    }
2893
14.1k
}
2894
/* This function promises that the predicate -> deletion sequence is atomic
2895
 * (i.e. protected by the GIL or the per-dict mutex in free threaded builds),
2896
 * assuming the predicate itself doesn't release the GIL (or cause re-entrancy
2897
 * which would release the per-dict mutex)
2898
 */
2899
int
2900
_PyDict_DelItemIf(PyObject *op, PyObject *key,
2901
                  int (*predicate)(PyObject *value, void *arg),
2902
                  void *arg)
2903
14.1k
{
2904
14.1k
    assert(PyDict_Check(op));
2905
14.1k
    int res;
2906
14.1k
    Py_BEGIN_CRITICAL_SECTION(op);
2907
14.1k
    res = delitemif_lock_held(op, key, predicate, arg);
2908
14.1k
    Py_END_CRITICAL_SECTION();
2909
14.1k
    return res;
2910
14.1k
}
2911
2912
static void
2913
clear_lock_held(PyObject *op)
2914
577k
{
2915
577k
    PyDictObject *mp;
2916
577k
    PyDictKeysObject *oldkeys;
2917
577k
    PyDictValues *oldvalues;
2918
577k
    Py_ssize_t i, n;
2919
2920
577k
    ASSERT_DICT_LOCKED(op);
2921
2922
577k
    if (!PyDict_Check(op))
2923
0
        return;
2924
577k
    mp = ((PyDictObject *)op);
2925
577k
    oldkeys = mp->ma_keys;
2926
577k
    oldvalues = mp->ma_values;
2927
577k
    if (oldkeys == Py_EMPTY_KEYS) {
2928
290k
        return;
2929
290k
    }
2930
    /* Empty the dict... */
2931
287k
    PyInterpreterState *interp = _PyInterpreterState_GET();
2932
287k
    _PyDict_NotifyEvent(interp, PyDict_EVENT_CLEARED, mp, NULL, NULL);
2933
    // We don't inc ref empty keys because they're immortal
2934
287k
    ensure_shared_on_resize(mp);
2935
287k
    STORE_USED(mp, 0);
2936
287k
    if (oldvalues == NULL) {
2937
287k
        set_keys(mp, Py_EMPTY_KEYS);
2938
287k
        assert(oldkeys->dk_refcnt == 1);
2939
287k
        dictkeys_decref(oldkeys, IS_DICT_SHARED(mp));
2940
287k
    }
2941
0
    else {
2942
0
        n = oldkeys->dk_nentries;
2943
0
        for (i = 0; i < n; i++) {
2944
0
            Py_CLEAR(oldvalues->values[i]);
2945
0
        }
2946
0
        if (oldvalues->embedded) {
2947
0
            oldvalues->size = 0;
2948
0
        }
2949
0
        else {
2950
0
            set_values(mp, NULL);
2951
0
            set_keys(mp, Py_EMPTY_KEYS);
2952
0
            free_values(oldvalues, IS_DICT_SHARED(mp));
2953
0
            dictkeys_decref(oldkeys, false);
2954
0
        }
2955
0
    }
2956
287k
    ASSERT_CONSISTENT(mp);
2957
287k
}
2958
2959
void
2960
4.19k
_PyDict_Clear_LockHeld(PyObject *op) {
2961
4.19k
    clear_lock_held(op);
2962
4.19k
}
2963
2964
void
2965
PyDict_Clear(PyObject *op)
2966
573k
{
2967
573k
    Py_BEGIN_CRITICAL_SECTION(op);
2968
573k
    clear_lock_held(op);
2969
573k
    Py_END_CRITICAL_SECTION();
2970
573k
}
2971
2972
/* Internal version of PyDict_Next that returns a hash value in addition
2973
 * to the key and value.
2974
 * Return 1 on success, return 0 when the reached the end of the dictionary
2975
 * (or if op is not a dictionary)
2976
 */
2977
int
2978
_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey,
2979
             PyObject **pvalue, Py_hash_t *phash)
2980
26.3M
{
2981
26.3M
    Py_ssize_t i;
2982
26.3M
    PyDictObject *mp;
2983
26.3M
    PyObject *key, *value;
2984
26.3M
    Py_hash_t hash;
2985
2986
26.3M
    if (!PyDict_Check(op))
2987
0
        return 0;
2988
2989
26.3M
    mp = (PyDictObject *)op;
2990
26.3M
    i = *ppos;
2991
26.3M
    if (_PyDict_HasSplitTable(mp)) {
2992
0
        assert(mp->ma_used <= SHARED_KEYS_MAX_SIZE);
2993
0
        if (i < 0 || i >= mp->ma_used)
2994
0
            return 0;
2995
0
        int index = get_index_from_order(mp, i);
2996
0
        value = mp->ma_values->values[index];
2997
0
        key = LOAD_SHARED_KEY(DK_UNICODE_ENTRIES(mp->ma_keys)[index].me_key);
2998
0
        hash = unicode_get_hash(key);
2999
0
        assert(value != NULL);
3000
0
    }
3001
26.3M
    else {
3002
26.3M
        Py_ssize_t n = mp->ma_keys->dk_nentries;
3003
26.3M
        if (i < 0 || i >= n)
3004
10.4M
            return 0;
3005
15.8M
        if (DK_IS_UNICODE(mp->ma_keys)) {
3006
14.5M
            PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(mp->ma_keys)[i];
3007
15.1M
            while (i < n && entry_ptr->me_value == NULL) {
3008
573k
                entry_ptr++;
3009
573k
                i++;
3010
573k
            }
3011
14.5M
            if (i >= n)
3012
282k
                return 0;
3013
14.3M
            key = entry_ptr->me_key;
3014
14.3M
            hash = unicode_get_hash(entry_ptr->me_key);
3015
14.3M
            value = entry_ptr->me_value;
3016
14.3M
        }
3017
1.26M
        else {
3018
1.26M
            PyDictKeyEntry *entry_ptr = &DK_ENTRIES(mp->ma_keys)[i];
3019
1.26M
            while (i < n && entry_ptr->me_value == NULL) {
3020
0
                entry_ptr++;
3021
0
                i++;
3022
0
            }
3023
1.26M
            if (i >= n)
3024
0
                return 0;
3025
1.26M
            key = entry_ptr->me_key;
3026
1.26M
            hash = entry_ptr->me_hash;
3027
1.26M
            value = entry_ptr->me_value;
3028
1.26M
        }
3029
15.8M
    }
3030
15.5M
    *ppos = i+1;
3031
15.5M
    if (pkey)
3032
15.5M
        *pkey = key;
3033
15.5M
    if (pvalue)
3034
14.8M
        *pvalue = value;
3035
15.5M
    if (phash)
3036
1.45M
        *phash = hash;
3037
15.5M
    return 1;
3038
26.3M
}
3039
3040
/*
3041
 * Iterate over a dict.  Use like so:
3042
 *
3043
 *     Py_ssize_t i;
3044
 *     PyObject *key, *value;
3045
 *     i = 0;   # important!  i should not otherwise be changed by you
3046
 *     while (PyDict_Next(yourdict, &i, &key, &value)) {
3047
 *         Refer to borrowed references in key and value.
3048
 *     }
3049
 *
3050
 * Return 1 on success, return 0 when the reached the end of the dictionary
3051
 * (or if op is not a dictionary)
3052
 *
3053
 * CAUTION:  In general, it isn't safe to use PyDict_Next in a loop that
3054
 * mutates the dict.  One exception:  it is safe if the loop merely changes
3055
 * the values associated with the keys (but doesn't insert new keys or
3056
 * delete keys), via PyDict_SetItem().
3057
 */
3058
int
3059
PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue)
3060
22.0M
{
3061
22.0M
    return _PyDict_Next(op, ppos, pkey, pvalue, NULL);
3062
22.0M
}
3063
3064
3065
/* Internal version of dict.pop(). */
3066
int
3067
_PyDict_Pop_KnownHash(PyDictObject *mp, PyObject *key, Py_hash_t hash,
3068
                      PyObject **result)
3069
901k
{
3070
901k
    assert(PyDict_Check(mp));
3071
3072
901k
    ASSERT_DICT_LOCKED(mp);
3073
3074
901k
    if (mp->ma_used == 0) {
3075
0
        if (result) {
3076
0
            *result = NULL;
3077
0
        }
3078
0
        return 0;
3079
0
    }
3080
3081
901k
    PyObject *old_value;
3082
901k
    Py_ssize_t ix = _Py_dict_lookup(mp, key, hash, &old_value);
3083
901k
    if (ix == DKIX_ERROR) {
3084
0
        if (result) {
3085
0
            *result = NULL;
3086
0
        }
3087
0
        return -1;
3088
0
    }
3089
3090
901k
    if (ix == DKIX_EMPTY || old_value == NULL) {
3091
6.22k
        if (result) {
3092
2.03k
            *result = NULL;
3093
2.03k
        }
3094
6.22k
        return 0;
3095
6.22k
    }
3096
3097
901k
    assert(old_value != NULL);
3098
895k
    PyInterpreterState *interp = _PyInterpreterState_GET();
3099
895k
    _PyDict_NotifyEvent(interp, PyDict_EVENT_DELETED, mp, key, NULL);
3100
895k
    delitem_common(mp, hash, ix, Py_NewRef(old_value));
3101
3102
895k
    ASSERT_CONSISTENT(mp);
3103
895k
    if (result) {
3104
895k
        *result = old_value;
3105
895k
    }
3106
2
    else {
3107
2
        Py_DECREF(old_value);
3108
2
    }
3109
895k
    return 1;
3110
901k
}
3111
3112
static int
3113
pop_lock_held(PyObject *op, PyObject *key, PyObject **result)
3114
1.08M
{
3115
1.08M
    ASSERT_DICT_LOCKED(op);
3116
3117
1.08M
    if (!PyDict_Check(op)) {
3118
0
        if (result) {
3119
0
            *result = NULL;
3120
0
        }
3121
0
        PyErr_BadInternalCall();
3122
0
        return -1;
3123
0
    }
3124
1.08M
    PyDictObject *dict = (PyDictObject *)op;
3125
3126
1.08M
    if (dict->ma_used == 0) {
3127
181k
        if (result) {
3128
181k
            *result = NULL;
3129
181k
        }
3130
181k
        return 0;
3131
181k
    }
3132
3133
901k
    Py_hash_t hash = _PyObject_HashFast(key);
3134
901k
    if (hash == -1) {
3135
0
        dict_unhashable_type(key);
3136
0
        if (result) {
3137
0
            *result = NULL;
3138
0
        }
3139
0
        return -1;
3140
0
    }
3141
901k
    return _PyDict_Pop_KnownHash(dict, key, hash, result);
3142
901k
}
3143
3144
int
3145
PyDict_Pop(PyObject *op, PyObject *key, PyObject **result)
3146
1.08M
{
3147
1.08M
    int err;
3148
1.08M
    Py_BEGIN_CRITICAL_SECTION(op);
3149
1.08M
    err = pop_lock_held(op, key, result);
3150
1.08M
    Py_END_CRITICAL_SECTION();
3151
3152
1.08M
    return err;
3153
1.08M
}
3154
3155
3156
int
3157
PyDict_PopString(PyObject *op, const char *key, PyObject **result)
3158
0
{
3159
0
    PyObject *key_obj = PyUnicode_FromString(key);
3160
0
    if (key_obj == NULL) {
3161
0
        if (result != NULL) {
3162
0
            *result = NULL;
3163
0
        }
3164
0
        return -1;
3165
0
    }
3166
3167
0
    int res = PyDict_Pop(op, key_obj, result);
3168
0
    Py_DECREF(key_obj);
3169
0
    return res;
3170
0
}
3171
3172
3173
static PyObject *
3174
dict_pop_default(PyObject *dict, PyObject *key, PyObject *default_value)
3175
469k
{
3176
469k
    PyObject *result;
3177
469k
    if (PyDict_Pop(dict, key, &result) == 0) {
3178
182k
        if (default_value != NULL) {
3179
182k
            return Py_NewRef(default_value);
3180
182k
        }
3181
0
        _PyErr_SetKeyError(key);
3182
0
        return NULL;
3183
182k
    }
3184
286k
    return result;
3185
469k
}
3186
3187
PyObject *
3188
_PyDict_Pop(PyObject *dict, PyObject *key, PyObject *default_value)
3189
0
{
3190
0
    return dict_pop_default(dict, key, default_value);
3191
0
}
3192
3193
static PyDictObject *
3194
dict_dict_fromkeys(PyInterpreterState *interp, PyDictObject *mp,
3195
                   PyObject *iterable, PyObject *value)
3196
0
{
3197
0
    PyObject *oldvalue;
3198
0
    Py_ssize_t pos = 0;
3199
0
    PyObject *key;
3200
0
    Py_hash_t hash;
3201
0
    int unicode = DK_IS_UNICODE(((PyDictObject*)iterable)->ma_keys);
3202
0
    uint8_t new_size = Py_MAX(
3203
0
        estimate_log2_keysize(PyDict_GET_SIZE(iterable)),
3204
0
        DK_LOG_SIZE(mp->ma_keys));
3205
0
    if (dictresize(mp, new_size, unicode)) {
3206
0
        Py_DECREF(mp);
3207
0
        return NULL;
3208
0
    }
3209
3210
0
    while (_PyDict_Next(iterable, &pos, &key, &oldvalue, &hash)) {
3211
0
        if (insertdict(interp, mp,
3212
0
                        Py_NewRef(key), hash, Py_NewRef(value))) {
3213
0
            Py_DECREF(mp);
3214
0
            return NULL;
3215
0
        }
3216
0
    }
3217
0
    return mp;
3218
0
}
3219
3220
static PyDictObject *
3221
dict_set_fromkeys(PyInterpreterState *interp, PyDictObject *mp,
3222
                  PyObject *iterable, PyObject *value)
3223
0
{
3224
0
    Py_ssize_t pos = 0;
3225
0
    PyObject *key;
3226
0
    Py_hash_t hash;
3227
0
    uint8_t new_size = Py_MAX(
3228
0
        estimate_log2_keysize(PySet_GET_SIZE(iterable)),
3229
0
        DK_LOG_SIZE(mp->ma_keys));
3230
0
    if (dictresize(mp, new_size, 0)) {
3231
0
        Py_DECREF(mp);
3232
0
        return NULL;
3233
0
    }
3234
3235
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(iterable);
3236
0
    while (_PySet_NextEntryRef(iterable, &pos, &key, &hash)) {
3237
0
        if (insertdict(interp, mp, key, hash, Py_NewRef(value))) {
3238
0
            Py_DECREF(mp);
3239
0
            return NULL;
3240
0
        }
3241
0
    }
3242
0
    return mp;
3243
0
}
3244
3245
/* Internal version of dict.from_keys().  It is subclass-friendly. */
3246
PyObject *
3247
_PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
3248
418k
{
3249
418k
    PyObject *it;       /* iter(iterable) */
3250
418k
    PyObject *key;
3251
418k
    PyObject *d;
3252
418k
    int status;
3253
418k
    PyInterpreterState *interp = _PyInterpreterState_GET();
3254
3255
418k
    d = _PyObject_CallNoArgs(cls);
3256
418k
    if (d == NULL)
3257
0
        return NULL;
3258
3259
3260
418k
    if (PyDict_CheckExact(d)) {
3261
418k
        if (PyDict_CheckExact(iterable)) {
3262
0
            PyDictObject *mp = (PyDictObject *)d;
3263
3264
0
            Py_BEGIN_CRITICAL_SECTION2(d, iterable);
3265
0
            d = (PyObject *)dict_dict_fromkeys(interp, mp, iterable, value);
3266
0
            Py_END_CRITICAL_SECTION2();
3267
0
            return d;
3268
0
        }
3269
418k
        else if (PyAnySet_CheckExact(iterable)) {
3270
0
            PyDictObject *mp = (PyDictObject *)d;
3271
3272
0
            Py_BEGIN_CRITICAL_SECTION2(d, iterable);
3273
0
            d = (PyObject *)dict_set_fromkeys(interp, mp, iterable, value);
3274
0
            Py_END_CRITICAL_SECTION2();
3275
0
            return d;
3276
0
        }
3277
418k
    }
3278
3279
418k
    it = PyObject_GetIter(iterable);
3280
418k
    if (it == NULL){
3281
0
        Py_DECREF(d);
3282
0
        return NULL;
3283
0
    }
3284
3285
418k
    if (PyDict_CheckExact(d)) {
3286
418k
        Py_BEGIN_CRITICAL_SECTION(d);
3287
10.8M
        while ((key = PyIter_Next(it)) != NULL) {
3288
10.4M
            status = setitem_lock_held((PyDictObject *)d, key, value);
3289
10.4M
            Py_DECREF(key);
3290
10.4M
            if (status < 0) {
3291
0
                assert(PyErr_Occurred());
3292
0
                goto dict_iter_exit;
3293
0
            }
3294
10.4M
        }
3295
418k
dict_iter_exit:;
3296
418k
        Py_END_CRITICAL_SECTION();
3297
418k
    } else {
3298
0
        while ((key = PyIter_Next(it)) != NULL) {
3299
0
            status = PyObject_SetItem(d, key, value);
3300
0
            Py_DECREF(key);
3301
0
            if (status < 0)
3302
0
                goto Fail;
3303
0
        }
3304
0
    }
3305
3306
418k
    if (PyErr_Occurred())
3307
0
        goto Fail;
3308
418k
    Py_DECREF(it);
3309
418k
    return d;
3310
3311
0
Fail:
3312
0
    Py_DECREF(it);
3313
0
    Py_DECREF(d);
3314
0
    return NULL;
3315
418k
}
3316
3317
/* Methods */
3318
3319
static void
3320
dict_dealloc(PyObject *self)
3321
317M
{
3322
317M
    PyDictObject *mp = (PyDictObject *)self;
3323
317M
    PyInterpreterState *interp = _PyInterpreterState_GET();
3324
317M
    _PyObject_ResurrectStart(self);
3325
317M
    _PyDict_NotifyEvent(interp, PyDict_EVENT_DEALLOCATED, mp, NULL, NULL);
3326
317M
    if (_PyObject_ResurrectEnd(self)) {
3327
0
        return;
3328
0
    }
3329
317M
    PyDictValues *values = mp->ma_values;
3330
317M
    PyDictKeysObject *keys = mp->ma_keys;
3331
317M
    Py_ssize_t i, n;
3332
3333
    /* bpo-31095: UnTrack is needed before calling any callbacks */
3334
317M
    PyObject_GC_UnTrack(mp);
3335
317M
    if (values != NULL) {
3336
201
        if (values->embedded == 0) {
3337
6.23k
            for (i = 0, n = values->capacity; i < n; i++) {
3338
6.03k
                Py_XDECREF(values->values[i]);
3339
6.03k
            }
3340
201
            free_values(values, false);
3341
201
        }
3342
201
        dictkeys_decref(keys, false);
3343
201
    }
3344
317M
    else if (keys != NULL) {
3345
317M
        assert(keys->dk_refcnt == 1 || keys == Py_EMPTY_KEYS);
3346
317M
        dictkeys_decref(keys, false);
3347
317M
    }
3348
317M
    if (Py_IS_TYPE(mp, &PyDict_Type)) {
3349
317M
        _Py_FREELIST_FREE(dicts, mp, Py_TYPE(mp)->tp_free);
3350
317M
    }
3351
204
    else {
3352
204
        Py_TYPE(mp)->tp_free((PyObject *)mp);
3353
204
    }
3354
317M
}
3355
3356
3357
static PyObject *
3358
dict_repr_lock_held(PyObject *self)
3359
0
{
3360
0
    PyDictObject *mp = (PyDictObject *)self;
3361
0
    PyObject *key = NULL, *value = NULL;
3362
0
    ASSERT_DICT_LOCKED(mp);
3363
3364
0
    int res = Py_ReprEnter((PyObject *)mp);
3365
0
    if (res != 0) {
3366
0
        return (res > 0 ? PyUnicode_FromString("{...}") : NULL);
3367
0
    }
3368
3369
0
    if (mp->ma_used == 0) {
3370
0
        Py_ReprLeave((PyObject *)mp);
3371
0
        return PyUnicode_FromString("{}");
3372
0
    }
3373
3374
    // "{" + "1: 2" + ", 3: 4" * (len - 1) + "}"
3375
0
    Py_ssize_t prealloc = 1 + 4 + 6 * (mp->ma_used - 1) + 1;
3376
0
    PyUnicodeWriter *writer = PyUnicodeWriter_Create(prealloc);
3377
0
    if (writer == NULL) {
3378
0
        goto error;
3379
0
    }
3380
3381
0
    if (PyUnicodeWriter_WriteChar(writer, '{') < 0) {
3382
0
        goto error;
3383
0
    }
3384
3385
    /* Do repr() on each key+value pair, and insert ": " between them.
3386
       Note that repr may mutate the dict. */
3387
0
    Py_ssize_t i = 0;
3388
0
    int first = 1;
3389
0
    while (_PyDict_Next((PyObject *)mp, &i, &key, &value, NULL)) {
3390
        // Prevent repr from deleting key or value during key format.
3391
0
        Py_INCREF(key);
3392
0
        Py_INCREF(value);
3393
3394
0
        if (!first) {
3395
            // Write ", "
3396
0
            if (PyUnicodeWriter_WriteChar(writer, ',') < 0) {
3397
0
                goto error;
3398
0
            }
3399
0
            if (PyUnicodeWriter_WriteChar(writer, ' ') < 0) {
3400
0
                goto error;
3401
0
            }
3402
0
        }
3403
0
        first = 0;
3404
3405
        // Write repr(key)
3406
0
        if (PyUnicodeWriter_WriteRepr(writer, key) < 0) {
3407
0
            goto error;
3408
0
        }
3409
3410
        // Write ": "
3411
0
        if (PyUnicodeWriter_WriteChar(writer, ':') < 0) {
3412
0
            goto error;
3413
0
        }
3414
0
        if (PyUnicodeWriter_WriteChar(writer, ' ') < 0) {
3415
0
            goto error;
3416
0
        }
3417
3418
        // Write repr(value)
3419
0
        if (PyUnicodeWriter_WriteRepr(writer, value) < 0) {
3420
0
            goto error;
3421
0
        }
3422
3423
0
        Py_CLEAR(key);
3424
0
        Py_CLEAR(value);
3425
0
    }
3426
3427
0
    if (PyUnicodeWriter_WriteChar(writer, '}') < 0) {
3428
0
        goto error;
3429
0
    }
3430
3431
0
    Py_ReprLeave((PyObject *)mp);
3432
3433
0
    return PyUnicodeWriter_Finish(writer);
3434
3435
0
error:
3436
0
    Py_ReprLeave((PyObject *)mp);
3437
0
    PyUnicodeWriter_Discard(writer);
3438
0
    Py_XDECREF(key);
3439
0
    Py_XDECREF(value);
3440
0
    return NULL;
3441
0
}
3442
3443
static PyObject *
3444
dict_repr(PyObject *self)
3445
0
{
3446
0
    PyObject *res;
3447
0
    Py_BEGIN_CRITICAL_SECTION(self);
3448
0
    res = dict_repr_lock_held(self);
3449
0
    Py_END_CRITICAL_SECTION();
3450
0
    return res;
3451
0
}
3452
3453
static Py_ssize_t
3454
dict_length(PyObject *self)
3455
13.0M
{
3456
13.0M
    return FT_ATOMIC_LOAD_SSIZE_RELAXED(((PyDictObject *)self)->ma_used);
3457
13.0M
}
3458
3459
static PyObject *
3460
dict_subscript(PyObject *self, PyObject *key)
3461
2.65M
{
3462
2.65M
    PyDictObject *mp = (PyDictObject *)self;
3463
2.65M
    Py_ssize_t ix;
3464
2.65M
    Py_hash_t hash;
3465
2.65M
    PyObject *value;
3466
3467
2.65M
    hash = _PyObject_HashFast(key);
3468
2.65M
    if (hash == -1) {
3469
0
        dict_unhashable_type(key);
3470
0
        return NULL;
3471
0
    }
3472
2.65M
    ix = _Py_dict_lookup_threadsafe(mp, key, hash, &value);
3473
2.65M
    if (ix == DKIX_ERROR)
3474
0
        return NULL;
3475
2.65M
    if (ix == DKIX_EMPTY || value == NULL) {
3476
925
        if (!PyDict_CheckExact(mp)) {
3477
            /* Look up __missing__ method if we're a subclass. */
3478
522
            PyObject *missing, *res;
3479
522
            missing = _PyObject_LookupSpecial(
3480
522
                    (PyObject *)mp, &_Py_ID(__missing__));
3481
522
            if (missing != NULL) {
3482
8
                res = PyObject_CallOneArg(missing, key);
3483
8
                Py_DECREF(missing);
3484
8
                return res;
3485
8
            }
3486
514
            else if (PyErr_Occurred())
3487
0
                return NULL;
3488
522
        }
3489
917
        _PyErr_SetKeyError(key);
3490
917
        return NULL;
3491
925
    }
3492
2.65M
    return value;
3493
2.65M
}
3494
3495
static int
3496
dict_ass_sub(PyObject *mp, PyObject *v, PyObject *w)
3497
474k
{
3498
474k
    if (w == NULL)
3499
470k
        return PyDict_DelItem(mp, v);
3500
4.60k
    else
3501
4.60k
        return PyDict_SetItem(mp, v, w);
3502
474k
}
3503
3504
static PyMappingMethods dict_as_mapping = {
3505
    dict_length, /*mp_length*/
3506
    dict_subscript, /*mp_subscript*/
3507
    dict_ass_sub, /*mp_ass_subscript*/
3508
};
3509
3510
static PyObject *
3511
keys_lock_held(PyObject *dict)
3512
22.9k
{
3513
22.9k
    ASSERT_DICT_LOCKED(dict);
3514
3515
22.9k
    if (dict == NULL || !PyDict_Check(dict)) {
3516
0
        PyErr_BadInternalCall();
3517
0
        return NULL;
3518
0
    }
3519
22.9k
    PyDictObject *mp = (PyDictObject *)dict;
3520
22.9k
    PyObject *v;
3521
22.9k
    Py_ssize_t n;
3522
3523
22.9k
  again:
3524
22.9k
    n = mp->ma_used;
3525
22.9k
    v = PyList_New(n);
3526
22.9k
    if (v == NULL)
3527
0
        return NULL;
3528
22.9k
    if (n != mp->ma_used) {
3529
        /* Durnit.  The allocations caused the dict to resize.
3530
         * Just start over, this shouldn't normally happen.
3531
         */
3532
0
        Py_DECREF(v);
3533
0
        goto again;
3534
0
    }
3535
3536
    /* Nothing we do below makes any function calls. */
3537
22.9k
    Py_ssize_t j = 0, pos = 0;
3538
22.9k
    PyObject *key;
3539
705k
    while (_PyDict_Next((PyObject*)mp, &pos, &key, NULL, NULL)) {
3540
682k
        assert(j < n);
3541
682k
        PyList_SET_ITEM(v, j, Py_NewRef(key));
3542
682k
        j++;
3543
682k
    }
3544
22.9k
    assert(j == n);
3545
22.9k
    return v;
3546
22.9k
}
3547
3548
PyObject *
3549
PyDict_Keys(PyObject *dict)
3550
22.9k
{
3551
22.9k
    PyObject *res;
3552
22.9k
    Py_BEGIN_CRITICAL_SECTION(dict);
3553
22.9k
    res = keys_lock_held(dict);
3554
22.9k
    Py_END_CRITICAL_SECTION();
3555
3556
22.9k
    return res;
3557
22.9k
}
3558
3559
static PyObject *
3560
values_lock_held(PyObject *dict)
3561
0
{
3562
0
    ASSERT_DICT_LOCKED(dict);
3563
3564
0
    if (dict == NULL || !PyDict_Check(dict)) {
3565
0
        PyErr_BadInternalCall();
3566
0
        return NULL;
3567
0
    }
3568
0
    PyDictObject *mp = (PyDictObject *)dict;
3569
0
    PyObject *v;
3570
0
    Py_ssize_t n;
3571
3572
0
  again:
3573
0
    n = mp->ma_used;
3574
0
    v = PyList_New(n);
3575
0
    if (v == NULL)
3576
0
        return NULL;
3577
0
    if (n != mp->ma_used) {
3578
        /* Durnit.  The allocations caused the dict to resize.
3579
         * Just start over, this shouldn't normally happen.
3580
         */
3581
0
        Py_DECREF(v);
3582
0
        goto again;
3583
0
    }
3584
3585
    /* Nothing we do below makes any function calls. */
3586
0
    Py_ssize_t j = 0, pos = 0;
3587
0
    PyObject *value;
3588
0
    while (_PyDict_Next((PyObject*)mp, &pos, NULL, &value, NULL)) {
3589
0
        assert(j < n);
3590
0
        PyList_SET_ITEM(v, j, Py_NewRef(value));
3591
0
        j++;
3592
0
    }
3593
0
    assert(j == n);
3594
0
    return v;
3595
0
}
3596
3597
PyObject *
3598
PyDict_Values(PyObject *dict)
3599
0
{
3600
0
    PyObject *res;
3601
0
    Py_BEGIN_CRITICAL_SECTION(dict);
3602
0
    res = values_lock_held(dict);
3603
0
    Py_END_CRITICAL_SECTION();
3604
0
    return res;
3605
0
}
3606
3607
static PyObject *
3608
items_lock_held(PyObject *dict)
3609
0
{
3610
0
    ASSERT_DICT_LOCKED(dict);
3611
3612
0
    if (dict == NULL || !PyDict_Check(dict)) {
3613
0
        PyErr_BadInternalCall();
3614
0
        return NULL;
3615
0
    }
3616
0
    PyDictObject *mp = (PyDictObject *)dict;
3617
0
    PyObject *v;
3618
0
    Py_ssize_t i, n;
3619
0
    PyObject *item;
3620
3621
    /* Preallocate the list of tuples, to avoid allocations during
3622
     * the loop over the items, which could trigger GC, which
3623
     * could resize the dict. :-(
3624
     */
3625
0
  again:
3626
0
    n = mp->ma_used;
3627
0
    v = PyList_New(n);
3628
0
    if (v == NULL)
3629
0
        return NULL;
3630
0
    for (i = 0; i < n; i++) {
3631
0
        item = PyTuple_New(2);
3632
0
        if (item == NULL) {
3633
0
            Py_DECREF(v);
3634
0
            return NULL;
3635
0
        }
3636
0
        PyList_SET_ITEM(v, i, item);
3637
0
    }
3638
0
    if (n != mp->ma_used) {
3639
        /* Durnit.  The allocations caused the dict to resize.
3640
         * Just start over, this shouldn't normally happen.
3641
         */
3642
0
        Py_DECREF(v);
3643
0
        goto again;
3644
0
    }
3645
3646
    /* Nothing we do below makes any function calls. */
3647
0
    Py_ssize_t j = 0, pos = 0;
3648
0
    PyObject *key, *value;
3649
0
    while (_PyDict_Next((PyObject*)mp, &pos, &key, &value, NULL)) {
3650
0
        assert(j < n);
3651
0
        PyObject *item = PyList_GET_ITEM(v, j);
3652
0
        PyTuple_SET_ITEM(item, 0, Py_NewRef(key));
3653
0
        PyTuple_SET_ITEM(item, 1, Py_NewRef(value));
3654
0
        j++;
3655
0
    }
3656
0
    assert(j == n);
3657
0
    return v;
3658
0
}
3659
3660
PyObject *
3661
PyDict_Items(PyObject *dict)
3662
0
{
3663
0
    PyObject *res;
3664
0
    Py_BEGIN_CRITICAL_SECTION(dict);
3665
0
    res = items_lock_held(dict);
3666
0
    Py_END_CRITICAL_SECTION();
3667
3668
0
    return res;
3669
0
}
3670
3671
/*[clinic input]
3672
@classmethod
3673
dict.fromkeys
3674
    iterable: object
3675
    value: object=None
3676
    /
3677
3678
Create a new dictionary with keys from iterable and values set to value.
3679
[clinic start generated code]*/
3680
3681
static PyObject *
3682
dict_fromkeys_impl(PyTypeObject *type, PyObject *iterable, PyObject *value)
3683
/*[clinic end generated code: output=8fb98e4b10384999 input=382ba4855d0f74c3]*/
3684
418k
{
3685
418k
    return _PyDict_FromKeys((PyObject *)type, iterable, value);
3686
418k
}
3687
3688
/* Single-arg dict update; used by dict_update_common and operators. */
3689
static int
3690
dict_update_arg(PyObject *self, PyObject *arg)
3691
1.30k
{
3692
1.30k
    if (PyDict_CheckExact(arg)) {
3693
848
        return PyDict_Merge(self, arg, 1);
3694
848
    }
3695
458
    int has_keys = PyObject_HasAttrWithError(arg, &_Py_ID(keys));
3696
458
    if (has_keys < 0) {
3697
0
        return -1;
3698
0
    }
3699
458
    if (has_keys) {
3700
250
        return PyDict_Merge(self, arg, 1);
3701
250
    }
3702
208
    return PyDict_MergeFromSeq2(self, arg, 1);
3703
458
}
3704
3705
static int
3706
dict_update_common(PyObject *self, PyObject *args, PyObject *kwds,
3707
                   const char *methname)
3708
1.21k
{
3709
1.21k
    PyObject *arg = NULL;
3710
1.21k
    int result = 0;
3711
3712
1.21k
    if (!PyArg_UnpackTuple(args, methname, 0, 1, &arg)) {
3713
0
        result = -1;
3714
0
    }
3715
1.21k
    else if (arg != NULL) {
3716
1.02k
        result = dict_update_arg(self, arg);
3717
1.02k
    }
3718
3719
1.21k
    if (result == 0 && kwds != NULL) {
3720
0
        if (PyArg_ValidateKeywordArguments(kwds))
3721
0
            result = PyDict_Merge(self, kwds, 1);
3722
0
        else
3723
0
            result = -1;
3724
0
    }
3725
1.21k
    return result;
3726
1.21k
}
3727
3728
/* Note: dict.update() uses the METH_VARARGS|METH_KEYWORDS calling convention.
3729
   Using METH_FASTCALL|METH_KEYWORDS would make dict.update(**dict2) calls
3730
   slower, see the issue #29312. */
3731
static PyObject *
3732
dict_update(PyObject *self, PyObject *args, PyObject *kwds)
3733
1.01k
{
3734
1.01k
    if (dict_update_common(self, args, kwds, "update") != -1)
3735
1.01k
        Py_RETURN_NONE;
3736
0
    return NULL;
3737
1.01k
}
3738
3739
/* Update unconditionally replaces existing items.
3740
   Merge has a 3rd argument 'override'; if set, it acts like Update,
3741
   otherwise it leaves existing items unchanged.
3742
3743
   PyDict_{Update,Merge} update/merge from a mapping object.
3744
3745
   PyDict_MergeFromSeq2 updates/merges from any iterable object
3746
   producing iterable objects of length 2.
3747
*/
3748
3749
static int
3750
merge_from_seq2_lock_held(PyObject *d, PyObject *seq2, int override)
3751
208
{
3752
208
    PyObject *it;       /* iter(seq2) */
3753
208
    Py_ssize_t i;       /* index into seq2 of current element */
3754
208
    PyObject *item;     /* seq2[i] */
3755
208
    PyObject *fast;     /* item as a 2-tuple or 2-list */
3756
3757
208
    assert(d != NULL);
3758
208
    assert(PyDict_Check(d));
3759
208
    assert(seq2 != NULL);
3760
3761
208
    it = PyObject_GetIter(seq2);
3762
208
    if (it == NULL)
3763
0
        return -1;
3764
3765
2.77k
    for (i = 0; ; ++i) {
3766
2.77k
        PyObject *key, *value;
3767
2.77k
        Py_ssize_t n;
3768
3769
2.77k
        fast = NULL;
3770
2.77k
        item = PyIter_Next(it);
3771
2.77k
        if (item == NULL) {
3772
208
            if (PyErr_Occurred())
3773
0
                goto Fail;
3774
208
            break;
3775
208
        }
3776
3777
        /* Convert item to sequence, and verify length 2. */
3778
2.57k
        fast = PySequence_Fast(item, "object is not iterable");
3779
2.57k
        if (fast == NULL) {
3780
0
            if (PyErr_ExceptionMatches(PyExc_TypeError)) {
3781
0
                _PyErr_FormatNote(
3782
0
                    "Cannot convert dictionary update "
3783
0
                    "sequence element #%zd to a sequence",
3784
0
                    i);
3785
0
            }
3786
0
            goto Fail;
3787
0
        }
3788
2.57k
        n = PySequence_Fast_GET_SIZE(fast);
3789
2.57k
        if (n != 2) {
3790
0
            PyErr_Format(PyExc_ValueError,
3791
0
                         "dictionary update sequence element #%zd "
3792
0
                         "has length %zd; 2 is required",
3793
0
                         i, n);
3794
0
            goto Fail;
3795
0
        }
3796
3797
        /* Update/merge with this (key, value) pair. */
3798
2.57k
        key = PySequence_Fast_GET_ITEM(fast, 0);
3799
2.57k
        value = PySequence_Fast_GET_ITEM(fast, 1);
3800
2.57k
        Py_INCREF(key);
3801
2.57k
        Py_INCREF(value);
3802
2.57k
        if (override) {
3803
2.57k
            if (setitem_lock_held((PyDictObject *)d, key, value) < 0) {
3804
0
                Py_DECREF(key);
3805
0
                Py_DECREF(value);
3806
0
                goto Fail;
3807
0
            }
3808
2.57k
        }
3809
0
        else {
3810
0
            if (dict_setdefault_ref_lock_held(d, key, value, NULL, 0) < 0) {
3811
0
                Py_DECREF(key);
3812
0
                Py_DECREF(value);
3813
0
                goto Fail;
3814
0
            }
3815
0
        }
3816
3817
2.57k
        Py_DECREF(key);
3818
2.57k
        Py_DECREF(value);
3819
2.57k
        Py_DECREF(fast);
3820
2.57k
        Py_DECREF(item);
3821
2.57k
    }
3822
3823
208
    i = 0;
3824
208
    ASSERT_CONSISTENT(d);
3825
208
    goto Return;
3826
0
Fail:
3827
0
    Py_XDECREF(item);
3828
0
    Py_XDECREF(fast);
3829
0
    i = -1;
3830
208
Return:
3831
208
    Py_DECREF(it);
3832
208
    return Py_SAFE_DOWNCAST(i, Py_ssize_t, int);
3833
0
}
3834
3835
int
3836
PyDict_MergeFromSeq2(PyObject *d, PyObject *seq2, int override)
3837
208
{
3838
208
    int res;
3839
208
    Py_BEGIN_CRITICAL_SECTION(d);
3840
208
    res = merge_from_seq2_lock_held(d, seq2, override);
3841
208
    Py_END_CRITICAL_SECTION();
3842
3843
208
    return res;
3844
208
}
3845
3846
static int
3847
dict_dict_merge(PyInterpreterState *interp, PyDictObject *mp, PyDictObject *other, int override)
3848
19.3M
{
3849
19.3M
    ASSERT_DICT_LOCKED(mp);
3850
19.3M
    ASSERT_DICT_LOCKED(other);
3851
3852
19.3M
    if (other == mp || other->ma_used == 0)
3853
        /* a.update(a) or a.update({}); nothing to do */
3854
18.4M
        return 0;
3855
897k
    if (mp->ma_used == 0) {
3856
        /* Since the target dict is empty, PyDict_GetItem()
3857
            * always returns NULL.  Setting override to 1
3858
            * skips the unnecessary test.
3859
            */
3860
894k
        override = 1;
3861
894k
        PyDictKeysObject *okeys = other->ma_keys;
3862
3863
        // If other is clean, combined, and just allocated, just clone it.
3864
894k
        if (mp->ma_values == NULL &&
3865
894k
            other->ma_values == NULL &&
3866
894k
            other->ma_used == okeys->dk_nentries &&
3867
332k
            (DK_LOG_SIZE(okeys) == PyDict_LOG_MINSIZE ||
3868
104
             USABLE_FRACTION(DK_SIZE(okeys)/2) < other->ma_used)
3869
894k
        ) {
3870
332k
            _PyDict_NotifyEvent(interp, PyDict_EVENT_CLONED, mp, (PyObject *)other, NULL);
3871
332k
            PyDictKeysObject *keys = clone_combined_dict_keys(other);
3872
332k
            if (keys == NULL)
3873
0
                return -1;
3874
3875
332k
            ensure_shared_on_resize(mp);
3876
332k
            dictkeys_decref(mp->ma_keys, IS_DICT_SHARED(mp));
3877
332k
            set_keys(mp, keys);
3878
332k
            STORE_USED(mp, other->ma_used);
3879
332k
            ASSERT_CONSISTENT(mp);
3880
3881
332k
            if (_PyObject_GC_IS_TRACKED(other) && !_PyObject_GC_IS_TRACKED(mp)) {
3882
                /* Maintain tracking. */
3883
0
                _PyObject_GC_TRACK(mp);
3884
0
            }
3885
3886
332k
            return 0;
3887
332k
        }
3888
894k
    }
3889
    /* Do one big resize at the start, rather than
3890
        * incrementally resizing as we insert new items.  Expect
3891
        * that there will be no (or few) overlapping keys.
3892
        */
3893
565k
    if (USABLE_FRACTION(DK_SIZE(mp->ma_keys)) < other->ma_used) {
3894
562k
        int unicode = DK_IS_UNICODE(other->ma_keys);
3895
562k
        if (dictresize(mp, estimate_log2_keysize(mp->ma_used + other->ma_used),
3896
562k
                        unicode)) {
3897
0
            return -1;
3898
0
        }
3899
562k
    }
3900
3901
565k
    Py_ssize_t orig_size = other->ma_used;
3902
565k
    Py_ssize_t pos = 0;
3903
565k
    Py_hash_t hash;
3904
565k
    PyObject *key, *value;
3905
3906
2.01M
    while (_PyDict_Next((PyObject*)other, &pos, &key, &value, &hash)) {
3907
1.45M
        int err = 0;
3908
1.45M
        Py_INCREF(key);
3909
1.45M
        Py_INCREF(value);
3910
1.45M
        if (override == 1) {
3911
1.45M
            err = insertdict(interp, mp,
3912
1.45M
                                Py_NewRef(key), hash, Py_NewRef(value));
3913
1.45M
        }
3914
0
        else {
3915
0
            err = _PyDict_Contains_KnownHash((PyObject *)mp, key, hash);
3916
0
            if (err == 0) {
3917
0
                err = insertdict(interp, mp,
3918
0
                                    Py_NewRef(key), hash, Py_NewRef(value));
3919
0
            }
3920
0
            else if (err > 0) {
3921
0
                if (override != 0) {
3922
0
                    _PyErr_SetKeyError(key);
3923
0
                    Py_DECREF(value);
3924
0
                    Py_DECREF(key);
3925
0
                    return -1;
3926
0
                }
3927
0
                err = 0;
3928
0
            }
3929
0
        }
3930
1.45M
        Py_DECREF(value);
3931
1.45M
        Py_DECREF(key);
3932
1.45M
        if (err != 0)
3933
0
            return -1;
3934
3935
1.45M
        if (orig_size != other->ma_used) {
3936
0
            PyErr_SetString(PyExc_RuntimeError,
3937
0
                    "dict mutated during update");
3938
0
            return -1;
3939
0
        }
3940
1.45M
    }
3941
565k
    return 0;
3942
565k
}
3943
3944
static int
3945
dict_merge(PyInterpreterState *interp, PyObject *a, PyObject *b, int override)
3946
19.3M
{
3947
19.3M
    PyDictObject *mp, *other;
3948
3949
19.3M
    assert(0 <= override && override <= 2);
3950
3951
    /* We accept for the argument either a concrete dictionary object,
3952
     * or an abstract "mapping" object.  For the former, we can do
3953
     * things quite efficiently.  For the latter, we only require that
3954
     * PyMapping_Keys() and PyObject_GetItem() be supported.
3955
     */
3956
19.3M
    if (a == NULL || !PyDict_Check(a) || b == NULL) {
3957
0
        PyErr_BadInternalCall();
3958
0
        return -1;
3959
0
    }
3960
19.3M
    mp = (PyDictObject*)a;
3961
19.3M
    int res = 0;
3962
19.3M
    if (PyDict_Check(b) && (Py_TYPE(b)->tp_iter == dict_iter)) {
3963
19.3M
        other = (PyDictObject*)b;
3964
19.3M
        int res;
3965
19.3M
        Py_BEGIN_CRITICAL_SECTION2(a, b);
3966
19.3M
        res = dict_dict_merge(interp, (PyDictObject *)a, other, override);
3967
19.3M
        ASSERT_CONSISTENT(a);
3968
19.3M
        Py_END_CRITICAL_SECTION2();
3969
19.3M
        return res;
3970
19.3M
    }
3971
61.6k
    else {
3972
        /* Do it the generic, slower way */
3973
61.6k
        Py_BEGIN_CRITICAL_SECTION(a);
3974
61.6k
        PyObject *keys = PyMapping_Keys(b);
3975
61.6k
        PyObject *iter;
3976
61.6k
        PyObject *key, *value;
3977
61.6k
        int status;
3978
3979
61.6k
        if (keys == NULL) {
3980
            /* Docstring says this is equivalent to E.keys() so
3981
             * if E doesn't have a .keys() method we want
3982
             * AttributeError to percolate up.  Might as well
3983
             * do the same for any other error.
3984
             */
3985
0
            res = -1;
3986
0
            goto slow_exit;
3987
0
        }
3988
3989
61.6k
        iter = PyObject_GetIter(keys);
3990
61.6k
        Py_DECREF(keys);
3991
61.6k
        if (iter == NULL) {
3992
0
            res = -1;
3993
0
            goto slow_exit;
3994
0
        }
3995
3996
1.24M
        for (key = PyIter_Next(iter); key; key = PyIter_Next(iter)) {
3997
1.18M
            if (override != 1) {
3998
0
                status = PyDict_Contains(a, key);
3999
0
                if (status != 0) {
4000
0
                    if (status > 0) {
4001
0
                        if (override == 0) {
4002
0
                            Py_DECREF(key);
4003
0
                            continue;
4004
0
                        }
4005
0
                        _PyErr_SetKeyError(key);
4006
0
                    }
4007
0
                    Py_DECREF(key);
4008
0
                    Py_DECREF(iter);
4009
0
                    res = -1;
4010
0
                    goto slow_exit;
4011
0
                }
4012
0
            }
4013
1.18M
            value = PyObject_GetItem(b, key);
4014
1.18M
            if (value == NULL) {
4015
0
                Py_DECREF(iter);
4016
0
                Py_DECREF(key);
4017
0
                res = -1;
4018
0
                goto slow_exit;
4019
0
            }
4020
1.18M
            status = setitem_lock_held(mp, key, value);
4021
1.18M
            Py_DECREF(key);
4022
1.18M
            Py_DECREF(value);
4023
1.18M
            if (status < 0) {
4024
0
                Py_DECREF(iter);
4025
0
                res = -1;
4026
0
                goto slow_exit;
4027
0
                return -1;
4028
0
            }
4029
1.18M
        }
4030
61.6k
        Py_DECREF(iter);
4031
61.6k
        if (PyErr_Occurred()) {
4032
            /* Iterator completed, via error */
4033
0
            res = -1;
4034
0
            goto slow_exit;
4035
0
        }
4036
4037
61.6k
slow_exit:
4038
61.6k
        ASSERT_CONSISTENT(a);
4039
61.6k
        Py_END_CRITICAL_SECTION();
4040
61.6k
        return res;
4041
61.6k
    }
4042
19.3M
}
4043
4044
int
4045
PyDict_Update(PyObject *a, PyObject *b)
4046
64.0k
{
4047
64.0k
    PyInterpreterState *interp = _PyInterpreterState_GET();
4048
64.0k
    return dict_merge(interp, a, b, 1);
4049
64.0k
}
4050
4051
int
4052
PyDict_Merge(PyObject *a, PyObject *b, int override)
4053
1.09k
{
4054
1.09k
    PyInterpreterState *interp = _PyInterpreterState_GET();
4055
    /* XXX Deprecate override not in (0, 1). */
4056
1.09k
    return dict_merge(interp, a, b, override != 0);
4057
1.09k
}
4058
4059
int
4060
_PyDict_MergeEx(PyObject *a, PyObject *b, int override)
4061
19.3M
{
4062
19.3M
    PyInterpreterState *interp = _PyInterpreterState_GET();
4063
19.3M
    return dict_merge(interp, a, b, override);
4064
19.3M
}
4065
4066
/*[clinic input]
4067
dict.copy
4068
4069
Return a shallow copy of the dict.
4070
[clinic start generated code]*/
4071
4072
static PyObject *
4073
dict_copy_impl(PyDictObject *self)
4074
/*[clinic end generated code: output=ffb782cf970a5c39 input=73935f042b639de4]*/
4075
14.7k
{
4076
14.7k
    return PyDict_Copy((PyObject *)self);
4077
14.7k
}
4078
4079
/* Copies the values, but does not change the reference
4080
 * counts of the objects in the array.
4081
 * Return NULL, but does *not* set an exception on failure  */
4082
static PyDictValues *
4083
copy_values(PyDictValues *values)
4084
5.58k
{
4085
5.58k
    PyDictValues *newvalues = new_values(values->capacity);
4086
5.58k
    if (newvalues == NULL) {
4087
0
        return NULL;
4088
0
    }
4089
5.58k
    newvalues->size = values->size;
4090
5.58k
    uint8_t *values_order = get_insertion_order_array(values);
4091
5.58k
    uint8_t *new_values_order = get_insertion_order_array(newvalues);
4092
5.58k
    memcpy(new_values_order, values_order, values->capacity);
4093
167k
    for (int i = 0; i < values->capacity; i++) {
4094
161k
        newvalues->values[i] = values->values[i];
4095
161k
    }
4096
5.58k
    assert(newvalues->embedded == 0);
4097
5.58k
    return newvalues;
4098
5.58k
}
4099
4100
static PyObject *
4101
copy_lock_held(PyObject *o)
4102
604k
{
4103
604k
    PyObject *copy;
4104
604k
    PyDictObject *mp;
4105
604k
    PyInterpreterState *interp = _PyInterpreterState_GET();
4106
4107
604k
    ASSERT_DICT_LOCKED(o);
4108
4109
604k
    mp = (PyDictObject *)o;
4110
604k
    if (mp->ma_used == 0) {
4111
        /* The dict is empty; just return a new dict. */
4112
294k
        return PyDict_New();
4113
294k
    }
4114
4115
310k
    if (_PyDict_HasSplitTable(mp)) {
4116
5.58k
        PyDictObject *split_copy;
4117
5.58k
        PyDictValues *newvalues = copy_values(mp->ma_values);
4118
5.58k
        if (newvalues == NULL) {
4119
0
            return PyErr_NoMemory();
4120
0
        }
4121
5.58k
        split_copy = PyObject_GC_New(PyDictObject, &PyDict_Type);
4122
5.58k
        if (split_copy == NULL) {
4123
0
            free_values(newvalues, false);
4124
0
            return NULL;
4125
0
        }
4126
167k
        for (size_t i = 0; i < newvalues->capacity; i++) {
4127
161k
            Py_XINCREF(newvalues->values[i]);
4128
161k
        }
4129
5.58k
        split_copy->ma_values = newvalues;
4130
5.58k
        split_copy->ma_keys = mp->ma_keys;
4131
5.58k
        split_copy->ma_used = mp->ma_used;
4132
5.58k
        split_copy->_ma_watcher_tag = 0;
4133
5.58k
        dictkeys_incref(mp->ma_keys);
4134
5.58k
        _PyObject_GC_TRACK(split_copy);
4135
5.58k
        return (PyObject *)split_copy;
4136
5.58k
    }
4137
4138
304k
    if (Py_TYPE(mp)->tp_iter == dict_iter &&
4139
304k
            mp->ma_values == NULL &&
4140
304k
            (mp->ma_used >= (mp->ma_keys->dk_nentries * 2) / 3))
4141
304k
    {
4142
        /* Use fast-copy if:
4143
4144
           (1) type(mp) doesn't override tp_iter; and
4145
4146
           (2) 'mp' is not a split-dict; and
4147
4148
           (3) if 'mp' is non-compact ('del' operation does not resize dicts),
4149
               do fast-copy only if it has at most 1/3 non-used keys.
4150
4151
           The last condition (3) is important to guard against a pathological
4152
           case when a large dict is almost emptied with multiple del/pop
4153
           operations and copied after that.  In cases like this, we defer to
4154
           PyDict_Merge, which produces a compacted copy.
4155
        */
4156
304k
        PyDictKeysObject *keys = clone_combined_dict_keys(mp);
4157
304k
        if (keys == NULL) {
4158
0
            return NULL;
4159
0
        }
4160
304k
        PyDictObject *new = (PyDictObject *)new_dict(keys, NULL, 0, 0);
4161
304k
        if (new == NULL) {
4162
            /* In case of an error, `new_dict()` takes care of
4163
               cleaning up `keys`. */
4164
0
            return NULL;
4165
0
        }
4166
4167
304k
        new->ma_used = mp->ma_used;
4168
304k
        ASSERT_CONSISTENT(new);
4169
304k
        return (PyObject *)new;
4170
304k
    }
4171
4172
0
    copy = PyDict_New();
4173
0
    if (copy == NULL)
4174
0
        return NULL;
4175
0
    if (dict_merge(interp, copy, o, 1) == 0)
4176
0
        return copy;
4177
0
    Py_DECREF(copy);
4178
0
    return NULL;
4179
0
}
4180
4181
PyObject *
4182
PyDict_Copy(PyObject *o)
4183
604k
{
4184
604k
    if (o == NULL || !PyDict_Check(o)) {
4185
0
        PyErr_BadInternalCall();
4186
0
        return NULL;
4187
0
    }
4188
4189
604k
    PyObject *res;
4190
604k
    Py_BEGIN_CRITICAL_SECTION(o);
4191
4192
604k
    res = copy_lock_held(o);
4193
4194
604k
    Py_END_CRITICAL_SECTION();
4195
604k
    return res;
4196
604k
}
4197
4198
Py_ssize_t
4199
PyDict_Size(PyObject *mp)
4200
565k
{
4201
565k
    if (mp == NULL || !PyDict_Check(mp)) {
4202
0
        PyErr_BadInternalCall();
4203
0
        return -1;
4204
0
    }
4205
565k
    return FT_ATOMIC_LOAD_SSIZE_RELAXED(((PyDictObject *)mp)->ma_used);
4206
565k
}
4207
4208
/* Return 1 if dicts equal, 0 if not, -1 if error.
4209
 * Gets out as soon as any difference is detected.
4210
 * Uses only Py_EQ comparison.
4211
 */
4212
static int
4213
dict_equal_lock_held(PyDictObject *a, PyDictObject *b)
4214
0
{
4215
0
    Py_ssize_t i;
4216
4217
0
    ASSERT_DICT_LOCKED(a);
4218
0
    ASSERT_DICT_LOCKED(b);
4219
4220
0
    if (a->ma_used != b->ma_used)
4221
        /* can't be equal if # of entries differ */
4222
0
        return 0;
4223
    /* Same # of entries -- check all of 'em.  Exit early on any diff. */
4224
0
    for (i = 0; i < LOAD_KEYS_NENTRIES(a->ma_keys); i++) {
4225
0
        PyObject *key, *aval;
4226
0
        Py_hash_t hash;
4227
0
        if (DK_IS_UNICODE(a->ma_keys)) {
4228
0
            PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(a->ma_keys)[i];
4229
0
            key = ep->me_key;
4230
0
            if (key == NULL) {
4231
0
                continue;
4232
0
            }
4233
0
            hash = unicode_get_hash(key);
4234
0
            if (_PyDict_HasSplitTable(a))
4235
0
                aval = a->ma_values->values[i];
4236
0
            else
4237
0
                aval = ep->me_value;
4238
0
        }
4239
0
        else {
4240
0
            PyDictKeyEntry *ep = &DK_ENTRIES(a->ma_keys)[i];
4241
0
            key = ep->me_key;
4242
0
            aval = ep->me_value;
4243
0
            hash = ep->me_hash;
4244
0
        }
4245
0
        if (aval != NULL) {
4246
0
            int cmp;
4247
0
            PyObject *bval;
4248
            /* temporarily bump aval's refcount to ensure it stays
4249
               alive until we're done with it */
4250
0
            Py_INCREF(aval);
4251
            /* ditto for key */
4252
0
            Py_INCREF(key);
4253
            /* reuse the known hash value */
4254
0
            _Py_dict_lookup(b, key, hash, &bval);
4255
0
            if (bval == NULL) {
4256
0
                Py_DECREF(key);
4257
0
                Py_DECREF(aval);
4258
0
                if (PyErr_Occurred())
4259
0
                    return -1;
4260
0
                return 0;
4261
0
            }
4262
0
            Py_INCREF(bval);
4263
0
            cmp = PyObject_RichCompareBool(aval, bval, Py_EQ);
4264
0
            Py_DECREF(key);
4265
0
            Py_DECREF(aval);
4266
0
            Py_DECREF(bval);
4267
0
            if (cmp <= 0)  /* error or not equal */
4268
0
                return cmp;
4269
0
        }
4270
0
    }
4271
0
    return 1;
4272
0
}
4273
4274
static int
4275
dict_equal(PyDictObject *a, PyDictObject *b)
4276
0
{
4277
0
    int res;
4278
0
    Py_BEGIN_CRITICAL_SECTION2(a, b);
4279
0
    res = dict_equal_lock_held(a, b);
4280
0
    Py_END_CRITICAL_SECTION2();
4281
4282
0
    return res;
4283
0
}
4284
4285
static PyObject *
4286
dict_richcompare(PyObject *v, PyObject *w, int op)
4287
0
{
4288
0
    int cmp;
4289
0
    PyObject *res;
4290
4291
0
    if (!PyDict_Check(v) || !PyDict_Check(w)) {
4292
0
        res = Py_NotImplemented;
4293
0
    }
4294
0
    else if (op == Py_EQ || op == Py_NE) {
4295
0
        cmp = dict_equal((PyDictObject *)v, (PyDictObject *)w);
4296
0
        if (cmp < 0)
4297
0
            return NULL;
4298
0
        res = (cmp == (op == Py_EQ)) ? Py_True : Py_False;
4299
0
    }
4300
0
    else
4301
0
        res = Py_NotImplemented;
4302
0
    return Py_NewRef(res);
4303
0
}
4304
4305
/*[clinic input]
4306
4307
@coexist
4308
dict.__contains__
4309
4310
  key: object
4311
  /
4312
4313
True if the dictionary has the specified key, else False.
4314
[clinic start generated code]*/
4315
4316
static PyObject *
4317
dict___contains___impl(PyDictObject *self, PyObject *key)
4318
/*[clinic end generated code: output=1b314e6da7687dae input=fe1cb42ad831e820]*/
4319
47.6M
{
4320
47.6M
    int contains = PyDict_Contains((PyObject *)self, key);
4321
47.6M
    if (contains < 0) {
4322
0
        return NULL;
4323
0
    }
4324
47.6M
    if (contains) {
4325
42.9M
        Py_RETURN_TRUE;
4326
42.9M
    }
4327
47.6M
    Py_RETURN_FALSE;
4328
47.6M
}
4329
4330
/*[clinic input]
4331
dict.get
4332
4333
    key: object
4334
    default: object = None
4335
    /
4336
4337
Return the value for key if key is in the dictionary, else default.
4338
[clinic start generated code]*/
4339
4340
static PyObject *
4341
dict_get_impl(PyDictObject *self, PyObject *key, PyObject *default_value)
4342
/*[clinic end generated code: output=bba707729dee05bf input=279ddb5790b6b107]*/
4343
591M
{
4344
591M
    PyObject *val = NULL;
4345
591M
    Py_hash_t hash;
4346
591M
    Py_ssize_t ix;
4347
4348
591M
    hash = _PyObject_HashFast(key);
4349
591M
    if (hash == -1) {
4350
0
        dict_unhashable_type(key);
4351
0
        return NULL;
4352
0
    }
4353
591M
    ix = _Py_dict_lookup_threadsafe(self, key, hash, &val);
4354
591M
    if (ix == DKIX_ERROR)
4355
0
        return NULL;
4356
591M
    if (ix == DKIX_EMPTY || val == NULL) {
4357
408M
        val = Py_NewRef(default_value);
4358
408M
    }
4359
591M
    return val;
4360
591M
}
4361
4362
static int
4363
dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_value,
4364
                    PyObject **result, int incref_result)
4365
92.4M
{
4366
92.4M
    PyDictObject *mp = (PyDictObject *)d;
4367
92.4M
    PyObject *value;
4368
92.4M
    Py_hash_t hash;
4369
92.4M
    Py_ssize_t ix;
4370
92.4M
    PyInterpreterState *interp = _PyInterpreterState_GET();
4371
4372
92.4M
    ASSERT_DICT_LOCKED(d);
4373
4374
92.4M
    if (!PyDict_Check(d)) {
4375
0
        PyErr_BadInternalCall();
4376
0
        if (result) {
4377
0
            *result = NULL;
4378
0
        }
4379
0
        return -1;
4380
0
    }
4381
4382
92.4M
    hash = _PyObject_HashFast(key);
4383
92.4M
    if (hash == -1) {
4384
0
        dict_unhashable_type(key);
4385
0
        if (result) {
4386
0
            *result = NULL;
4387
0
        }
4388
0
        return -1;
4389
0
    }
4390
4391
92.4M
    if (mp->ma_keys == Py_EMPTY_KEYS) {
4392
496k
        if (insert_to_emptydict(interp, mp, Py_NewRef(key), hash,
4393
496k
                                Py_NewRef(default_value)) < 0) {
4394
0
            if (result) {
4395
0
                *result = NULL;
4396
0
            }
4397
0
            return -1;
4398
0
        }
4399
496k
        if (result) {
4400
496k
            *result = incref_result ? Py_NewRef(default_value) : default_value;
4401
496k
        }
4402
496k
        return 0;
4403
496k
    }
4404
4405
91.9M
    if (_PyDict_HasSplitTable(mp) && PyUnicode_CheckExact(key)) {
4406
0
        ix = insert_split_key(mp->ma_keys, key, hash);
4407
0
        if (ix != DKIX_EMPTY) {
4408
0
            PyObject *value = mp->ma_values->values[ix];
4409
0
            int already_present = value != NULL;
4410
0
            if (!already_present) {
4411
0
                insert_split_value(interp, mp, key, default_value, ix);
4412
0
                value = default_value;
4413
0
            }
4414
0
            if (result) {
4415
0
                *result = incref_result ? Py_NewRef(value) : value;
4416
0
            }
4417
0
            return already_present;
4418
0
        }
4419
        // No space in shared keys. Go to insert_combined_dict() below.
4420
0
    }
4421
91.9M
    else {
4422
91.9M
        ix = _Py_dict_lookup(mp, key, hash, &value);
4423
91.9M
        if (ix == DKIX_ERROR) {
4424
0
            if (result) {
4425
0
                *result = NULL;
4426
0
            }
4427
0
            return -1;
4428
0
        }
4429
91.9M
    }
4430
4431
91.9M
    if (ix == DKIX_EMPTY) {
4432
4.41M
        value = default_value;
4433
4434
        // See comment to this function in insertdict.
4435
4.41M
        if (insert_combined_dict(interp, mp, hash, Py_NewRef(key), Py_NewRef(value)) < 0) {
4436
0
            Py_DECREF(key);
4437
0
            Py_DECREF(value);
4438
0
            if (result) {
4439
0
                *result = NULL;
4440
0
            }
4441
0
            return -1;
4442
0
        }
4443
4444
4.41M
        STORE_USED(mp, mp->ma_used + 1);
4445
4.41M
        assert(mp->ma_keys->dk_usable >= 0);
4446
4.41M
        ASSERT_CONSISTENT(mp);
4447
4.41M
        if (result) {
4448
4.36M
            *result = incref_result ? Py_NewRef(value) : value;
4449
4.36M
        }
4450
4.41M
        return 0;
4451
4.41M
    }
4452
4453
91.9M
    assert(value != NULL);
4454
87.5M
    ASSERT_CONSISTENT(mp);
4455
87.5M
    if (result) {
4456
87.5M
        *result = incref_result ? Py_NewRef(value) : value;
4457
87.5M
    }
4458
87.5M
    return 1;
4459
91.9M
}
4460
4461
int
4462
PyDict_SetDefaultRef(PyObject *d, PyObject *key, PyObject *default_value,
4463
                     PyObject **result)
4464
5.98M
{
4465
5.98M
    int res;
4466
5.98M
    Py_BEGIN_CRITICAL_SECTION(d);
4467
5.98M
    res = dict_setdefault_ref_lock_held(d, key, default_value, result, 1);
4468
5.98M
    Py_END_CRITICAL_SECTION();
4469
5.98M
    return res;
4470
5.98M
}
4471
4472
PyObject *
4473
PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
4474
0
{
4475
0
    PyObject *result;
4476
0
    Py_BEGIN_CRITICAL_SECTION(d);
4477
0
    dict_setdefault_ref_lock_held(d, key, defaultobj, &result, 0);
4478
0
    Py_END_CRITICAL_SECTION();
4479
0
    return result;
4480
0
}
4481
4482
/*[clinic input]
4483
@critical_section
4484
dict.setdefault
4485
4486
    key: object
4487
    default: object = None
4488
    /
4489
4490
Insert key with a value of default if key is not in the dictionary.
4491
4492
Return the value for key if key is in the dictionary, else default.
4493
[clinic start generated code]*/
4494
4495
static PyObject *
4496
dict_setdefault_impl(PyDictObject *self, PyObject *key,
4497
                     PyObject *default_value)
4498
/*[clinic end generated code: output=f8c1101ebf69e220 input=9237af9a0a224302]*/
4499
86.4M
{
4500
86.4M
    PyObject *val;
4501
86.4M
    dict_setdefault_ref_lock_held((PyObject *)self, key, default_value, &val, 1);
4502
86.4M
    return val;
4503
86.4M
}
4504
4505
4506
/*[clinic input]
4507
dict.clear
4508
4509
Remove all items from the dict.
4510
[clinic start generated code]*/
4511
4512
static PyObject *
4513
dict_clear_impl(PyDictObject *self)
4514
/*[clinic end generated code: output=5139a830df00830a input=0bf729baba97a4c2]*/
4515
14.4k
{
4516
14.4k
    PyDict_Clear((PyObject *)self);
4517
14.4k
    Py_RETURN_NONE;
4518
14.4k
}
4519
4520
/*[clinic input]
4521
@permit_long_summary
4522
dict.pop
4523
4524
    key: object
4525
    default: object = NULL
4526
    /
4527
4528
D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
4529
4530
If the key is not found, return the default if given; otherwise,
4531
raise a KeyError.
4532
[clinic start generated code]*/
4533
4534
static PyObject *
4535
dict_pop_impl(PyDictObject *self, PyObject *key, PyObject *default_value)
4536
/*[clinic end generated code: output=3abb47b89f24c21c input=d409c7eb2de67e38]*/
4537
469k
{
4538
469k
    return dict_pop_default((PyObject*)self, key, default_value);
4539
469k
}
4540
4541
/*[clinic input]
4542
@critical_section
4543
dict.popitem
4544
4545
Remove and return a (key, value) pair as a 2-tuple.
4546
4547
Pairs are returned in LIFO (last-in, first-out) order.
4548
Raises KeyError if the dict is empty.
4549
[clinic start generated code]*/
4550
4551
static PyObject *
4552
dict_popitem_impl(PyDictObject *self)
4553
/*[clinic end generated code: output=e65fcb04420d230d input=ef28b4da5f0f762e]*/
4554
0
{
4555
0
    Py_ssize_t i, j;
4556
0
    PyObject *res;
4557
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
4558
4559
0
    ASSERT_DICT_LOCKED(self);
4560
4561
    /* Allocate the result tuple before checking the size.  Believe it
4562
     * or not, this allocation could trigger a garbage collection which
4563
     * could empty the dict, so if we checked the size first and that
4564
     * happened, the result would be an infinite loop (searching for an
4565
     * entry that no longer exists).  Note that the usual popitem()
4566
     * idiom is "while d: k, v = d.popitem()". so needing to throw the
4567
     * tuple away if the dict *is* empty isn't a significant
4568
     * inefficiency -- possible, but unlikely in practice.
4569
     */
4570
0
    res = PyTuple_New(2);
4571
0
    if (res == NULL)
4572
0
        return NULL;
4573
0
    if (self->ma_used == 0) {
4574
0
        Py_DECREF(res);
4575
0
        PyErr_SetString(PyExc_KeyError, "popitem(): dictionary is empty");
4576
0
        return NULL;
4577
0
    }
4578
    /* Convert split table to combined table */
4579
0
    if (_PyDict_HasSplitTable(self)) {
4580
0
        if (dictresize(self, DK_LOG_SIZE(self->ma_keys), 1) < 0) {
4581
0
            Py_DECREF(res);
4582
0
            return NULL;
4583
0
        }
4584
0
    }
4585
0
    FT_ATOMIC_STORE_UINT32_RELAXED(self->ma_keys->dk_version, 0);
4586
4587
    /* Pop last item */
4588
0
    PyObject *key, *value;
4589
0
    Py_hash_t hash;
4590
0
    if (DK_IS_UNICODE(self->ma_keys)) {
4591
0
        PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(self->ma_keys);
4592
0
        i = self->ma_keys->dk_nentries - 1;
4593
0
        while (i >= 0 && ep0[i].me_value == NULL) {
4594
0
            i--;
4595
0
        }
4596
0
        assert(i >= 0);
4597
4598
0
        key = ep0[i].me_key;
4599
0
        _PyDict_NotifyEvent(interp, PyDict_EVENT_DELETED, self, key, NULL);
4600
0
        hash = unicode_get_hash(key);
4601
0
        value = ep0[i].me_value;
4602
0
        STORE_KEY(&ep0[i], NULL);
4603
0
        STORE_VALUE(&ep0[i], NULL);
4604
0
    }
4605
0
    else {
4606
0
        PyDictKeyEntry *ep0 = DK_ENTRIES(self->ma_keys);
4607
0
        i = self->ma_keys->dk_nentries - 1;
4608
0
        while (i >= 0 && ep0[i].me_value == NULL) {
4609
0
            i--;
4610
0
        }
4611
0
        assert(i >= 0);
4612
4613
0
        key = ep0[i].me_key;
4614
0
        _PyDict_NotifyEvent(interp, PyDict_EVENT_DELETED, self, key, NULL);
4615
0
        hash = ep0[i].me_hash;
4616
0
        value = ep0[i].me_value;
4617
0
        STORE_KEY(&ep0[i], NULL);
4618
0
        STORE_HASH(&ep0[i], -1);
4619
0
        STORE_VALUE(&ep0[i], NULL);
4620
0
    }
4621
4622
0
    j = lookdict_index(self->ma_keys, hash, i);
4623
0
    assert(j >= 0);
4624
0
    assert(dictkeys_get_index(self->ma_keys, j) == i);
4625
0
    dictkeys_set_index(self->ma_keys, j, DKIX_DUMMY);
4626
4627
0
    PyTuple_SET_ITEM(res, 0, key);
4628
0
    PyTuple_SET_ITEM(res, 1, value);
4629
    /* We can't dk_usable++ since there is DKIX_DUMMY in indices */
4630
0
    STORE_KEYS_NENTRIES(self->ma_keys, i);
4631
0
    STORE_USED(self, self->ma_used - 1);
4632
0
    ASSERT_CONSISTENT(self);
4633
0
    return res;
4634
0
}
4635
4636
static int
4637
dict_traverse(PyObject *op, visitproc visit, void *arg)
4638
18.7M
{
4639
18.7M
    PyDictObject *mp = (PyDictObject *)op;
4640
18.7M
    PyDictKeysObject *keys = mp->ma_keys;
4641
18.7M
    Py_ssize_t i, n = keys->dk_nentries;
4642
4643
18.7M
    if (DK_IS_UNICODE(keys)) {
4644
18.3M
        if (_PyDict_HasSplitTable(mp)) {
4645
465k
            if (!mp->ma_values->embedded) {
4646
3.22M
                for (i = 0; i < n; i++) {
4647
2.76M
                    Py_VISIT(mp->ma_values->values[i]);
4648
2.76M
                }
4649
462k
            }
4650
465k
        }
4651
17.8M
        else {
4652
17.8M
            PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys);
4653
95.9M
            for (i = 0; i < n; i++) {
4654
78.0M
                Py_VISIT(entries[i].me_value);
4655
78.0M
            }
4656
17.8M
        }
4657
18.3M
    }
4658
426k
    else {
4659
426k
        PyDictKeyEntry *entries = DK_ENTRIES(keys);
4660
43.4M
        for (i = 0; i < n; i++) {
4661
43.0M
            if (entries[i].me_value != NULL) {
4662
40.0M
                Py_VISIT(entries[i].me_value);
4663
40.0M
                Py_VISIT(entries[i].me_key);
4664
40.0M
            }
4665
43.0M
        }
4666
426k
    }
4667
18.7M
    return 0;
4668
18.7M
}
4669
4670
static int
4671
dict_tp_clear(PyObject *op)
4672
276k
{
4673
276k
    PyDict_Clear(op);
4674
276k
    return 0;
4675
276k
}
4676
4677
static PyObject *dictiter_new(PyDictObject *, PyTypeObject *);
4678
4679
Py_ssize_t
4680
_PyDict_SizeOf_LockHeld(PyDictObject *mp)
4681
0
{
4682
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(mp);
4683
4684
0
    size_t res = _PyObject_SIZE(Py_TYPE(mp));
4685
0
    if (_PyDict_HasSplitTable(mp)) {
4686
0
        res += shared_keys_usable_size(mp->ma_keys) * sizeof(PyObject*);
4687
0
    }
4688
    /* If the dictionary is split, the keys portion is accounted-for
4689
       in the type object. */
4690
0
    if (mp->ma_keys->dk_refcnt == 1) {
4691
0
        res += _PyDict_KeysSize(mp->ma_keys);
4692
0
    }
4693
0
    assert(res <= (size_t)PY_SSIZE_T_MAX);
4694
0
    return (Py_ssize_t)res;
4695
0
}
4696
4697
Py_ssize_t
4698
_PyDict_SizeOf(PyDictObject *mp)
4699
0
{
4700
0
    Py_ssize_t res;
4701
0
    Py_BEGIN_CRITICAL_SECTION(mp);
4702
0
    res = _PyDict_SizeOf_LockHeld(mp);
4703
0
    Py_END_CRITICAL_SECTION();
4704
4705
0
    return res;
4706
0
}
4707
4708
size_t
4709
_PyDict_KeysSize(PyDictKeysObject *keys)
4710
636k
{
4711
636k
    size_t es = (keys->dk_kind == DICT_KEYS_GENERAL
4712
636k
                 ? sizeof(PyDictKeyEntry) : sizeof(PyDictUnicodeEntry));
4713
636k
    size_t size = sizeof(PyDictKeysObject);
4714
636k
    size += (size_t)1 << keys->dk_log2_index_bytes;
4715
636k
    size += USABLE_FRACTION((size_t)DK_SIZE(keys)) * es;
4716
636k
    return size;
4717
636k
}
4718
4719
/*[clinic input]
4720
dict.__sizeof__
4721
4722
Return the size of the dict in memory, in bytes.
4723
[clinic start generated code]*/
4724
4725
static PyObject *
4726
dict___sizeof___impl(PyDictObject *self)
4727
/*[clinic end generated code: output=44279379b3824bda input=4fec4ddfc44a4d1a]*/
4728
0
{
4729
0
    return PyLong_FromSsize_t(_PyDict_SizeOf(self));
4730
0
}
4731
4732
static PyObject *
4733
dict_or(PyObject *self, PyObject *other)
4734
0
{
4735
0
    if (!PyDict_Check(self) || !PyDict_Check(other)) {
4736
0
        Py_RETURN_NOTIMPLEMENTED;
4737
0
    }
4738
0
    PyObject *new = PyDict_Copy(self);
4739
0
    if (new == NULL) {
4740
0
        return NULL;
4741
0
    }
4742
0
    if (dict_update_arg(new, other)) {
4743
0
        Py_DECREF(new);
4744
0
        return NULL;
4745
0
    }
4746
0
    return new;
4747
0
}
4748
4749
static PyObject *
4750
dict_ior(PyObject *self, PyObject *other)
4751
0
{
4752
0
    if (dict_update_arg(self, other)) {
4753
0
        return NULL;
4754
0
    }
4755
0
    return Py_NewRef(self);
4756
0
}
4757
4758
PyDoc_STRVAR(getitem__doc__,
4759
"__getitem__($self, key, /)\n--\n\nReturn self[key].");
4760
4761
PyDoc_STRVAR(update__doc__,
4762
"D.update([E, ]**F) -> None.  Update D from mapping/iterable E and F.\n\
4763
If E is present and has a .keys() method, then does:  for k in E.keys(): D[k] = E[k]\n\
4764
If E is present and lacks a .keys() method, then does:  for k, v in E: D[k] = v\n\
4765
In either case, this is followed by: for k in F:  D[k] = F[k]");
4766
4767
/* Forward */
4768
4769
static PyMethodDef mapp_methods[] = {
4770
    DICT___CONTAINS___METHODDEF
4771
    {"__getitem__",     dict_subscript,                 METH_O | METH_COEXIST,
4772
     getitem__doc__},
4773
    DICT___SIZEOF___METHODDEF
4774
    DICT_GET_METHODDEF
4775
    DICT_SETDEFAULT_METHODDEF
4776
    DICT_POP_METHODDEF
4777
    DICT_POPITEM_METHODDEF
4778
    DICT_KEYS_METHODDEF
4779
    DICT_ITEMS_METHODDEF
4780
    DICT_VALUES_METHODDEF
4781
    {"update",          _PyCFunction_CAST(dict_update), METH_VARARGS | METH_KEYWORDS,
4782
     update__doc__},
4783
    DICT_FROMKEYS_METHODDEF
4784
    DICT_CLEAR_METHODDEF
4785
    DICT_COPY_METHODDEF
4786
    DICT___REVERSED___METHODDEF
4787
    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
4788
    {NULL,              NULL}   /* sentinel */
4789
};
4790
4791
/* Return 1 if `key` is in dict `op`, 0 if not, and -1 on error. */
4792
int
4793
PyDict_Contains(PyObject *op, PyObject *key)
4794
408M
{
4795
408M
    Py_hash_t hash = _PyObject_HashFast(key);
4796
408M
    if (hash == -1) {
4797
0
        dict_unhashable_type(key);
4798
0
        return -1;
4799
0
    }
4800
4801
408M
    return _PyDict_Contains_KnownHash(op, key, hash);
4802
408M
}
4803
4804
int
4805
PyDict_ContainsString(PyObject *op, const char *key)
4806
2.24k
{
4807
2.24k
    PyObject *key_obj = PyUnicode_FromString(key);
4808
2.24k
    if (key_obj == NULL) {
4809
0
        return -1;
4810
0
    }
4811
2.24k
    int res = PyDict_Contains(op, key_obj);
4812
2.24k
    Py_DECREF(key_obj);
4813
2.24k
    return res;
4814
2.24k
}
4815
4816
/* Internal version of PyDict_Contains used when the hash value is already known */
4817
int
4818
_PyDict_Contains_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
4819
408M
{
4820
408M
    PyDictObject *mp = (PyDictObject *)op;
4821
408M
    PyObject *value;
4822
408M
    Py_ssize_t ix;
4823
4824
#ifdef Py_GIL_DISABLED
4825
    ix = _Py_dict_lookup_threadsafe(mp, key, hash, &value);
4826
#else
4827
408M
    ix = _Py_dict_lookup(mp, key, hash, &value);
4828
408M
#endif
4829
408M
    if (ix == DKIX_ERROR)
4830
0
        return -1;
4831
408M
    if (ix != DKIX_EMPTY && value != NULL) {
4832
#ifdef Py_GIL_DISABLED
4833
        Py_DECREF(value);
4834
#endif
4835
317M
        return 1;
4836
317M
    }
4837
90.4M
    return 0;
4838
408M
}
4839
4840
/* Hack to implement "key in dict" */
4841
static PySequenceMethods dict_as_sequence = {
4842
    0,                          /* sq_length */
4843
    0,                          /* sq_concat */
4844
    0,                          /* sq_repeat */
4845
    0,                          /* sq_item */
4846
    0,                          /* sq_slice */
4847
    0,                          /* sq_ass_item */
4848
    0,                          /* sq_ass_slice */
4849
    PyDict_Contains,            /* sq_contains */
4850
    0,                          /* sq_inplace_concat */
4851
    0,                          /* sq_inplace_repeat */
4852
};
4853
4854
static PyNumberMethods dict_as_number = {
4855
    .nb_or = dict_or,
4856
    .nb_inplace_or = dict_ior,
4857
};
4858
4859
static PyObject *
4860
dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
4861
491k
{
4862
491k
    assert(type != NULL);
4863
491k
    assert(type->tp_alloc != NULL);
4864
    // dict subclasses must implement the GC protocol
4865
491k
    assert(_PyType_IS_GC(type));
4866
4867
491k
    PyObject *self = type->tp_alloc(type, 0);
4868
491k
    if (self == NULL) {
4869
0
        return NULL;
4870
0
    }
4871
491k
    PyDictObject *d = (PyDictObject *)self;
4872
4873
491k
    d->ma_used = 0;
4874
491k
    d->_ma_watcher_tag = 0;
4875
    // We don't inc ref empty keys because they're immortal
4876
491k
    assert((Py_EMPTY_KEYS)->dk_refcnt == _Py_DICT_IMMORTAL_INITIAL_REFCNT);
4877
491k
    d->ma_keys = Py_EMPTY_KEYS;
4878
491k
    d->ma_values = NULL;
4879
491k
    ASSERT_CONSISTENT(d);
4880
491k
    if (!_PyObject_GC_IS_TRACKED(d)) {
4881
490k
        _PyObject_GC_TRACK(d);
4882
490k
    }
4883
491k
    return self;
4884
491k
}
4885
4886
static int
4887
dict_init(PyObject *self, PyObject *args, PyObject *kwds)
4888
198
{
4889
198
    return dict_update_common(self, args, kwds, "dict");
4890
198
}
4891
4892
static PyObject *
4893
dict_vectorcall(PyObject *type, PyObject * const*args,
4894
                size_t nargsf, PyObject *kwnames)
4895
490k
{
4896
490k
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
4897
490k
    if (!_PyArg_CheckPositional("dict", nargs, 0, 1)) {
4898
0
        return NULL;
4899
0
    }
4900
4901
490k
    PyObject *self = dict_new(_PyType_CAST(type), NULL, NULL);
4902
490k
    if (self == NULL) {
4903
0
        return NULL;
4904
0
    }
4905
490k
    if (nargs == 1) {
4906
286
        if (dict_update_arg(self, args[0]) < 0) {
4907
0
            Py_DECREF(self);
4908
0
            return NULL;
4909
0
        }
4910
286
        args++;
4911
286
    }
4912
490k
    if (kwnames != NULL) {
4913
74.4k
        for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(kwnames); i++) {
4914
58.4k
            if (PyDict_SetItem(self, PyTuple_GET_ITEM(kwnames, i), args[i]) < 0) {
4915
0
                Py_DECREF(self);
4916
0
                return NULL;
4917
0
            }
4918
58.4k
        }
4919
15.9k
    }
4920
490k
    return self;
4921
490k
}
4922
4923
static PyObject *
4924
dict_iter(PyObject *self)
4925
184k
{
4926
184k
    PyDictObject *dict = (PyDictObject *)self;
4927
184k
    return dictiter_new(dict, &PyDictIterKey_Type);
4928
184k
}
4929
4930
PyDoc_STRVAR(dictionary_doc,
4931
"dict() -> new empty dictionary\n"
4932
"dict(mapping) -> new dictionary initialized from a mapping object's\n"
4933
"    (key, value) pairs\n"
4934
"dict(iterable) -> new dictionary initialized as if via:\n"
4935
"    d = {}\n"
4936
"    for k, v in iterable:\n"
4937
"        d[k] = v\n"
4938
"dict(**kwargs) -> new dictionary initialized with the name=value pairs\n"
4939
"    in the keyword argument list.  For example:  dict(one=1, two=2)");
4940
4941
PyTypeObject PyDict_Type = {
4942
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
4943
    "dict",
4944
    sizeof(PyDictObject),
4945
    0,
4946
    dict_dealloc,                               /* tp_dealloc */
4947
    0,                                          /* tp_vectorcall_offset */
4948
    0,                                          /* tp_getattr */
4949
    0,                                          /* tp_setattr */
4950
    0,                                          /* tp_as_async */
4951
    dict_repr,                                  /* tp_repr */
4952
    &dict_as_number,                            /* tp_as_number */
4953
    &dict_as_sequence,                          /* tp_as_sequence */
4954
    &dict_as_mapping,                           /* tp_as_mapping */
4955
    PyObject_HashNotImplemented,                /* tp_hash */
4956
    0,                                          /* tp_call */
4957
    0,                                          /* tp_str */
4958
    PyObject_GenericGetAttr,                    /* tp_getattro */
4959
    0,                                          /* tp_setattro */
4960
    0,                                          /* tp_as_buffer */
4961
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
4962
        Py_TPFLAGS_BASETYPE | Py_TPFLAGS_DICT_SUBCLASS |
4963
        _Py_TPFLAGS_MATCH_SELF | Py_TPFLAGS_MAPPING,  /* tp_flags */
4964
    dictionary_doc,                             /* tp_doc */
4965
    dict_traverse,                              /* tp_traverse */
4966
    dict_tp_clear,                              /* tp_clear */
4967
    dict_richcompare,                           /* tp_richcompare */
4968
    0,                                          /* tp_weaklistoffset */
4969
    dict_iter,                                  /* tp_iter */
4970
    0,                                          /* tp_iternext */
4971
    mapp_methods,                               /* tp_methods */
4972
    0,                                          /* tp_members */
4973
    0,                                          /* tp_getset */
4974
    0,                                          /* tp_base */
4975
    0,                                          /* tp_dict */
4976
    0,                                          /* tp_descr_get */
4977
    0,                                          /* tp_descr_set */
4978
    0,                                          /* tp_dictoffset */
4979
    dict_init,                                  /* tp_init */
4980
    _PyType_AllocNoTrack,                       /* tp_alloc */
4981
    dict_new,                                   /* tp_new */
4982
    PyObject_GC_Del,                            /* tp_free */
4983
    .tp_vectorcall = dict_vectorcall,
4984
    .tp_version_tag = _Py_TYPE_VERSION_DICT,
4985
};
4986
4987
/* For backward compatibility with old dictionary interface */
4988
4989
PyObject *
4990
PyDict_GetItemString(PyObject *v, const char *key)
4991
0
{
4992
0
    PyObject *kv, *rv;
4993
0
    kv = PyUnicode_FromString(key);
4994
0
    if (kv == NULL) {
4995
0
        PyErr_FormatUnraisable(
4996
0
            "Exception ignored in PyDict_GetItemString(); consider using "
4997
0
            "PyDict_GetItemStringRef()");
4998
0
        return NULL;
4999
0
    }
5000
0
    rv = dict_getitem(v, kv,
5001
0
            "Exception ignored in PyDict_GetItemString(); consider using "
5002
0
            "PyDict_GetItemStringRef()");
5003
0
    Py_DECREF(kv);
5004
0
    return rv;  // borrowed reference
5005
0
}
5006
5007
int
5008
PyDict_GetItemStringRef(PyObject *v, const char *key, PyObject **result)
5009
1.18M
{
5010
1.18M
    PyObject *key_obj = PyUnicode_FromString(key);
5011
1.18M
    if (key_obj == NULL) {
5012
0
        *result = NULL;
5013
0
        return -1;
5014
0
    }
5015
1.18M
    int res = PyDict_GetItemRef(v, key_obj, result);
5016
1.18M
    Py_DECREF(key_obj);
5017
1.18M
    return res;
5018
1.18M
}
5019
5020
int
5021
PyDict_SetItemString(PyObject *v, const char *key, PyObject *item)
5022
34.1k
{
5023
34.1k
    PyObject *kv;
5024
34.1k
    int err;
5025
34.1k
    kv = PyUnicode_FromString(key);
5026
34.1k
    if (kv == NULL)
5027
0
        return -1;
5028
34.1k
    PyInterpreterState *interp = _PyInterpreterState_GET();
5029
34.1k
    _PyUnicode_InternImmortal(interp, &kv); /* XXX Should we really? */
5030
34.1k
    err = PyDict_SetItem(v, kv, item);
5031
34.1k
    Py_DECREF(kv);
5032
34.1k
    return err;
5033
34.1k
}
5034
5035
int
5036
PyDict_DelItemString(PyObject *v, const char *key)
5037
0
{
5038
0
    PyObject *kv;
5039
0
    int err;
5040
0
    kv = PyUnicode_FromString(key);
5041
0
    if (kv == NULL)
5042
0
        return -1;
5043
0
    err = PyDict_DelItem(v, kv);
5044
0
    Py_DECREF(kv);
5045
0
    return err;
5046
0
}
5047
5048
/* Dictionary iterator types */
5049
5050
typedef struct {
5051
    PyObject_HEAD
5052
    PyDictObject *di_dict; /* Set to NULL when iterator is exhausted */
5053
    Py_ssize_t di_used;
5054
    Py_ssize_t di_pos;
5055
    PyObject* di_result; /* reusable result tuple for iteritems */
5056
    Py_ssize_t len;
5057
} dictiterobject;
5058
5059
static PyObject *
5060
dictiter_new(PyDictObject *dict, PyTypeObject *itertype)
5061
1.12M
{
5062
1.12M
    Py_ssize_t used;
5063
1.12M
    dictiterobject *di;
5064
1.12M
    di = PyObject_GC_New(dictiterobject, itertype);
5065
1.12M
    if (di == NULL) {
5066
0
        return NULL;
5067
0
    }
5068
1.12M
    di->di_dict = (PyDictObject*)Py_NewRef(dict);
5069
1.12M
    used = FT_ATOMIC_LOAD_SSIZE_RELAXED(dict->ma_used);
5070
1.12M
    di->di_used = used;
5071
1.12M
    di->len = used;
5072
1.12M
    if (itertype == &PyDictRevIterKey_Type ||
5073
1.12M
         itertype == &PyDictRevIterItem_Type ||
5074
1.12M
         itertype == &PyDictRevIterValue_Type) {
5075
0
        if (_PyDict_HasSplitTable(dict)) {
5076
0
            di->di_pos = used - 1;
5077
0
        }
5078
0
        else {
5079
0
            di->di_pos = load_keys_nentries(dict) - 1;
5080
0
        }
5081
0
    }
5082
1.12M
    else {
5083
1.12M
        di->di_pos = 0;
5084
1.12M
    }
5085
1.12M
    if (itertype == &PyDictIterItem_Type ||
5086
629k
        itertype == &PyDictRevIterItem_Type) {
5087
629k
        di->di_result = PyTuple_Pack(2, Py_None, Py_None);
5088
629k
        if (di->di_result == NULL) {
5089
0
            Py_DECREF(di);
5090
0
            return NULL;
5091
0
        }
5092
629k
    }
5093
498k
    else {
5094
498k
        di->di_result = NULL;
5095
498k
    }
5096
1.12M
    _PyObject_GC_TRACK(di);
5097
1.12M
    return (PyObject *)di;
5098
1.12M
}
5099
5100
static void
5101
dictiter_dealloc(PyObject *self)
5102
1.12M
{
5103
1.12M
    dictiterobject *di = (dictiterobject *)self;
5104
    /* bpo-31095: UnTrack is needed before calling any callbacks */
5105
1.12M
    _PyObject_GC_UNTRACK(di);
5106
1.12M
    Py_XDECREF(di->di_dict);
5107
1.12M
    Py_XDECREF(di->di_result);
5108
1.12M
    PyObject_GC_Del(di);
5109
1.12M
}
5110
5111
static int
5112
dictiter_traverse(PyObject *self, visitproc visit, void *arg)
5113
810
{
5114
810
    dictiterobject *di = (dictiterobject *)self;
5115
810
    Py_VISIT(di->di_dict);
5116
810
    Py_VISIT(di->di_result);
5117
810
    return 0;
5118
810
}
5119
5120
static PyObject *
5121
dictiter_len(PyObject *self, PyObject *Py_UNUSED(ignored))
5122
63.0k
{
5123
63.0k
    dictiterobject *di = (dictiterobject *)self;
5124
63.0k
    Py_ssize_t len = 0;
5125
63.0k
    if (di->di_dict != NULL && di->di_used == FT_ATOMIC_LOAD_SSIZE_RELAXED(di->di_dict->ma_used))
5126
63.0k
        len = FT_ATOMIC_LOAD_SSIZE_RELAXED(di->len);
5127
63.0k
    return PyLong_FromSize_t(len);
5128
63.0k
}
5129
5130
PyDoc_STRVAR(length_hint_doc,
5131
             "Private method returning an estimate of len(list(it)).");
5132
5133
static PyObject *
5134
dictiter_reduce(PyObject *di, PyObject *Py_UNUSED(ignored));
5135
5136
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
5137
5138
static PyMethodDef dictiter_methods[] = {
5139
    {"__length_hint__", dictiter_len,                   METH_NOARGS,
5140
     length_hint_doc},
5141
     {"__reduce__",     dictiter_reduce,                METH_NOARGS,
5142
     reduce_doc},
5143
    {NULL,              NULL}           /* sentinel */
5144
};
5145
5146
#ifdef Py_GIL_DISABLED
5147
5148
static int
5149
dictiter_iternext_threadsafe(PyDictObject *d, PyObject *self,
5150
                             PyObject **out_key, PyObject **out_value);
5151
5152
#else /* Py_GIL_DISABLED */
5153
5154
static PyObject*
5155
dictiter_iternextkey_lock_held(PyDictObject *d, PyObject *self)
5156
3.81M
{
5157
3.81M
    dictiterobject *di = (dictiterobject *)self;
5158
3.81M
    PyObject *key;
5159
3.81M
    Py_ssize_t i;
5160
3.81M
    PyDictKeysObject *k;
5161
5162
3.81M
    assert (PyDict_Check(d));
5163
3.81M
    ASSERT_DICT_LOCKED(d);
5164
5165
3.81M
    if (di->di_used != d->ma_used) {
5166
0
        PyErr_SetString(PyExc_RuntimeError,
5167
0
                        "dictionary changed size during iteration");
5168
0
        di->di_used = -1; /* Make this state sticky */
5169
0
        return NULL;
5170
0
    }
5171
5172
3.81M
    i = di->di_pos;
5173
3.81M
    k = d->ma_keys;
5174
3.81M
    assert(i >= 0);
5175
3.81M
    if (_PyDict_HasSplitTable(d)) {
5176
0
        if (i >= d->ma_used)
5177
0
            goto fail;
5178
0
        int index = get_index_from_order(d, i);
5179
0
        key = LOAD_SHARED_KEY(DK_UNICODE_ENTRIES(k)[index].me_key);
5180
0
        assert(d->ma_values->values[index] != NULL);
5181
0
    }
5182
3.81M
    else {
5183
3.81M
        Py_ssize_t n = k->dk_nentries;
5184
3.81M
        if (DK_IS_UNICODE(k)) {
5185
3.81M
            PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(k)[i];
5186
3.88M
            while (i < n && entry_ptr->me_value == NULL) {
5187
73.1k
                entry_ptr++;
5188
73.1k
                i++;
5189
73.1k
            }
5190
3.81M
            if (i >= n)
5191
492k
                goto fail;
5192
3.32M
            key = entry_ptr->me_key;
5193
3.32M
        }
5194
4
        else {
5195
4
            PyDictKeyEntry *entry_ptr = &DK_ENTRIES(k)[i];
5196
4
            while (i < n && entry_ptr->me_value == NULL) {
5197
0
                entry_ptr++;
5198
0
                i++;
5199
0
            }
5200
4
            if (i >= n)
5201
0
                goto fail;
5202
4
            key = entry_ptr->me_key;
5203
4
        }
5204
3.81M
    }
5205
    // We found an element (key), but did not expect it
5206
3.32M
    if (di->len == 0) {
5207
0
        PyErr_SetString(PyExc_RuntimeError,
5208
0
                        "dictionary keys changed during iteration");
5209
0
        goto fail;
5210
0
    }
5211
3.32M
    di->di_pos = i+1;
5212
3.32M
    di->len--;
5213
3.32M
    return Py_NewRef(key);
5214
5215
492k
fail:
5216
492k
    di->di_dict = NULL;
5217
492k
    Py_DECREF(d);
5218
492k
    return NULL;
5219
3.32M
}
5220
5221
#endif  /* Py_GIL_DISABLED */
5222
5223
static PyObject*
5224
dictiter_iternextkey(PyObject *self)
5225
3.81M
{
5226
3.81M
    dictiterobject *di = (dictiterobject *)self;
5227
3.81M
    PyDictObject *d = di->di_dict;
5228
5229
3.81M
    if (d == NULL)
5230
0
        return NULL;
5231
5232
3.81M
    PyObject *value;
5233
#ifdef Py_GIL_DISABLED
5234
    if (dictiter_iternext_threadsafe(d, self, &value, NULL) < 0) {
5235
        value = NULL;
5236
    }
5237
#else
5238
3.81M
    value = dictiter_iternextkey_lock_held(d, self);
5239
3.81M
#endif
5240
5241
3.81M
    return value;
5242
3.81M
}
5243
5244
PyTypeObject PyDictIterKey_Type = {
5245
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
5246
    "dict_keyiterator",                         /* tp_name */
5247
    sizeof(dictiterobject),                     /* tp_basicsize */
5248
    0,                                          /* tp_itemsize */
5249
    /* methods */
5250
    dictiter_dealloc,                           /* tp_dealloc */
5251
    0,                                          /* tp_vectorcall_offset */
5252
    0,                                          /* tp_getattr */
5253
    0,                                          /* tp_setattr */
5254
    0,                                          /* tp_as_async */
5255
    0,                                          /* tp_repr */
5256
    0,                                          /* tp_as_number */
5257
    0,                                          /* tp_as_sequence */
5258
    0,                                          /* tp_as_mapping */
5259
    0,                                          /* tp_hash */
5260
    0,                                          /* tp_call */
5261
    0,                                          /* tp_str */
5262
    PyObject_GenericGetAttr,                    /* tp_getattro */
5263
    0,                                          /* tp_setattro */
5264
    0,                                          /* tp_as_buffer */
5265
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
5266
    0,                                          /* tp_doc */
5267
    dictiter_traverse,                          /* tp_traverse */
5268
    0,                                          /* tp_clear */
5269
    0,                                          /* tp_richcompare */
5270
    0,                                          /* tp_weaklistoffset */
5271
    PyObject_SelfIter,                          /* tp_iter */
5272
    dictiter_iternextkey,                       /* tp_iternext */
5273
    dictiter_methods,                           /* tp_methods */
5274
    0,
5275
};
5276
5277
#ifndef Py_GIL_DISABLED
5278
5279
static PyObject *
5280
dictiter_iternextvalue_lock_held(PyDictObject *d, PyObject *self)
5281
10.1k
{
5282
10.1k
    dictiterobject *di = (dictiterobject *)self;
5283
10.1k
    PyObject *value;
5284
10.1k
    Py_ssize_t i;
5285
5286
10.1k
    assert (PyDict_Check(d));
5287
10.1k
    ASSERT_DICT_LOCKED(d);
5288
5289
10.1k
    if (di->di_used != d->ma_used) {
5290
0
        PyErr_SetString(PyExc_RuntimeError,
5291
0
                        "dictionary changed size during iteration");
5292
0
        di->di_used = -1; /* Make this state sticky */
5293
0
        return NULL;
5294
0
    }
5295
5296
10.1k
    i = di->di_pos;
5297
10.1k
    assert(i >= 0);
5298
10.1k
    if (_PyDict_HasSplitTable(d)) {
5299
0
        if (i >= d->ma_used)
5300
0
            goto fail;
5301
0
        int index = get_index_from_order(d, i);
5302
0
        value = d->ma_values->values[index];
5303
0
        assert(value != NULL);
5304
0
    }
5305
10.1k
    else {
5306
10.1k
        Py_ssize_t n = d->ma_keys->dk_nentries;
5307
10.1k
        if (DK_IS_UNICODE(d->ma_keys)) {
5308
3.10k
            PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(d->ma_keys)[i];
5309
3.10k
            while (i < n && entry_ptr->me_value == NULL) {
5310
0
                entry_ptr++;
5311
0
                i++;
5312
0
            }
5313
3.10k
            if (i >= n)
5314
82
                goto fail;
5315
3.01k
            value = entry_ptr->me_value;
5316
3.01k
        }
5317
7.04k
        else {
5318
7.04k
            PyDictKeyEntry *entry_ptr = &DK_ENTRIES(d->ma_keys)[i];
5319
7.04k
            while (i < n && entry_ptr->me_value == NULL) {
5320
0
                entry_ptr++;
5321
0
                i++;
5322
0
            }
5323
7.04k
            if (i >= n)
5324
152
                goto fail;
5325
6.89k
            value = entry_ptr->me_value;
5326
6.89k
        }
5327
10.1k
    }
5328
    // We found an element, but did not expect it
5329
9.90k
    if (di->len == 0) {
5330
0
        PyErr_SetString(PyExc_RuntimeError,
5331
0
                        "dictionary keys changed during iteration");
5332
0
        goto fail;
5333
0
    }
5334
9.90k
    di->di_pos = i+1;
5335
9.90k
    di->len--;
5336
9.90k
    return Py_NewRef(value);
5337
5338
234
fail:
5339
234
    di->di_dict = NULL;
5340
234
    Py_DECREF(d);
5341
234
    return NULL;
5342
9.90k
}
5343
5344
#endif  /* Py_GIL_DISABLED */
5345
5346
static PyObject *
5347
dictiter_iternextvalue(PyObject *self)
5348
10.1k
{
5349
10.1k
    dictiterobject *di = (dictiterobject *)self;
5350
10.1k
    PyDictObject *d = di->di_dict;
5351
5352
10.1k
    if (d == NULL)
5353
0
        return NULL;
5354
5355
10.1k
    PyObject *value;
5356
#ifdef Py_GIL_DISABLED
5357
    if (dictiter_iternext_threadsafe(d, self, NULL, &value) < 0) {
5358
        value = NULL;
5359
    }
5360
#else
5361
10.1k
    value = dictiter_iternextvalue_lock_held(d, self);
5362
10.1k
#endif
5363
5364
10.1k
    return value;
5365
10.1k
}
5366
5367
PyTypeObject PyDictIterValue_Type = {
5368
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
5369
    "dict_valueiterator",                       /* tp_name */
5370
    sizeof(dictiterobject),                     /* tp_basicsize */
5371
    0,                                          /* tp_itemsize */
5372
    /* methods */
5373
    dictiter_dealloc,                           /* tp_dealloc */
5374
    0,                                          /* tp_vectorcall_offset */
5375
    0,                                          /* tp_getattr */
5376
    0,                                          /* tp_setattr */
5377
    0,                                          /* tp_as_async */
5378
    0,                                          /* tp_repr */
5379
    0,                                          /* tp_as_number */
5380
    0,                                          /* tp_as_sequence */
5381
    0,                                          /* tp_as_mapping */
5382
    0,                                          /* tp_hash */
5383
    0,                                          /* tp_call */
5384
    0,                                          /* tp_str */
5385
    PyObject_GenericGetAttr,                    /* tp_getattro */
5386
    0,                                          /* tp_setattro */
5387
    0,                                          /* tp_as_buffer */
5388
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
5389
    0,                                          /* tp_doc */
5390
    dictiter_traverse,                          /* tp_traverse */
5391
    0,                                          /* tp_clear */
5392
    0,                                          /* tp_richcompare */
5393
    0,                                          /* tp_weaklistoffset */
5394
    PyObject_SelfIter,                          /* tp_iter */
5395
    dictiter_iternextvalue,                     /* tp_iternext */
5396
    dictiter_methods,                           /* tp_methods */
5397
    0,
5398
};
5399
5400
static int
5401
dictiter_iternextitem_lock_held(PyDictObject *d, PyObject *self,
5402
                                PyObject **out_key, PyObject **out_value)
5403
3.44M
{
5404
3.44M
    dictiterobject *di = (dictiterobject *)self;
5405
3.44M
    PyObject *key, *value;
5406
3.44M
    Py_ssize_t i;
5407
5408
3.44M
    assert (PyDict_Check(d));
5409
3.44M
    ASSERT_DICT_LOCKED(d);
5410
5411
3.44M
    if (di->di_used != d->ma_used) {
5412
0
        PyErr_SetString(PyExc_RuntimeError,
5413
0
                        "dictionary changed size during iteration");
5414
0
        di->di_used = -1; /* Make this state sticky */
5415
0
        return -1;
5416
0
    }
5417
5418
3.44M
    i = FT_ATOMIC_LOAD_SSIZE_RELAXED(di->di_pos);
5419
5420
3.44M
    assert(i >= 0);
5421
3.44M
    if (_PyDict_HasSplitTable(d)) {
5422
10
        if (i >= d->ma_used)
5423
8
            goto fail;
5424
2
        int index = get_index_from_order(d, i);
5425
2
        key = LOAD_SHARED_KEY(DK_UNICODE_ENTRIES(d->ma_keys)[index].me_key);
5426
2
        value = d->ma_values->values[index];
5427
2
        assert(value != NULL);
5428
2
    }
5429
3.44M
    else {
5430
3.44M
        Py_ssize_t n = d->ma_keys->dk_nentries;
5431
3.44M
        if (DK_IS_UNICODE(d->ma_keys)) {
5432
3.44M
            PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(d->ma_keys)[i];
5433
3.45M
            while (i < n && entry_ptr->me_value == NULL) {
5434
10.7k
                entry_ptr++;
5435
10.7k
                i++;
5436
10.7k
            }
5437
3.44M
            if (i >= n)
5438
629k
                goto fail;
5439
2.81M
            key = entry_ptr->me_key;
5440
2.81M
            value = entry_ptr->me_value;
5441
2.81M
        }
5442
26
        else {
5443
26
            PyDictKeyEntry *entry_ptr = &DK_ENTRIES(d->ma_keys)[i];
5444
26
            while (i < n && entry_ptr->me_value == NULL) {
5445
0
                entry_ptr++;
5446
0
                i++;
5447
0
            }
5448
26
            if (i >= n)
5449
2
                goto fail;
5450
24
            key = entry_ptr->me_key;
5451
24
            value = entry_ptr->me_value;
5452
24
        }
5453
3.44M
    }
5454
    // We found an element, but did not expect it
5455
2.81M
    if (di->len == 0) {
5456
0
        PyErr_SetString(PyExc_RuntimeError,
5457
0
                        "dictionary keys changed during iteration");
5458
0
        goto fail;
5459
0
    }
5460
2.81M
    di->di_pos = i+1;
5461
2.81M
    di->len--;
5462
2.81M
    if (out_key != NULL) {
5463
2.81M
        *out_key = Py_NewRef(key);
5464
2.81M
    }
5465
2.81M
    if (out_value != NULL) {
5466
2.81M
        *out_value = Py_NewRef(value);
5467
2.81M
    }
5468
2.81M
    return 0;
5469
5470
629k
fail:
5471
629k
    di->di_dict = NULL;
5472
629k
    Py_DECREF(d);
5473
629k
    return -1;
5474
2.81M
}
5475
5476
#ifdef Py_GIL_DISABLED
5477
5478
// Grabs the key and/or value from the provided locations and if successful
5479
// returns them with an increased reference count.  If either one is unsuccessful
5480
// nothing is incref'd and returns -1.
5481
static int
5482
acquire_key_value(PyObject **key_loc, PyObject *value, PyObject **value_loc,
5483
                  PyObject **out_key, PyObject **out_value)
5484
{
5485
    if (out_key) {
5486
        *out_key = _Py_TryXGetRef(key_loc);
5487
        if (*out_key == NULL) {
5488
            return -1;
5489
        }
5490
    }
5491
5492
    if (out_value) {
5493
        if (!_Py_TryIncrefCompare(value_loc, value)) {
5494
            if (out_key) {
5495
                Py_DECREF(*out_key);
5496
            }
5497
            return -1;
5498
        }
5499
        *out_value = value;
5500
    }
5501
5502
    return 0;
5503
}
5504
5505
static int
5506
dictiter_iternext_threadsafe(PyDictObject *d, PyObject *self,
5507
                             PyObject **out_key, PyObject **out_value)
5508
{
5509
    int res;
5510
    dictiterobject *di = (dictiterobject *)self;
5511
    Py_ssize_t i;
5512
    PyDictKeysObject *k;
5513
5514
    assert (PyDict_Check(d));
5515
5516
    if (di->di_used != _Py_atomic_load_ssize_relaxed(&d->ma_used)) {
5517
        PyErr_SetString(PyExc_RuntimeError,
5518
                        "dictionary changed size during iteration");
5519
        di->di_used = -1; /* Make this state sticky */
5520
        return -1;
5521
    }
5522
5523
    ensure_shared_on_read(d);
5524
5525
    i = _Py_atomic_load_ssize_relaxed(&di->di_pos);
5526
    k = _Py_atomic_load_ptr_acquire(&d->ma_keys);
5527
    assert(i >= 0);
5528
    if (_PyDict_HasSplitTable(d)) {
5529
        PyDictValues *values = _Py_atomic_load_ptr_relaxed(&d->ma_values);
5530
        if (values == NULL) {
5531
            goto concurrent_modification;
5532
        }
5533
5534
        Py_ssize_t used = (Py_ssize_t)_Py_atomic_load_uint8(&values->size);
5535
        if (i >= used) {
5536
            goto fail;
5537
        }
5538
5539
        // We're racing against writes to the order from delete_index_from_values, but
5540
        // single threaded can suffer from concurrent modification to those as well and
5541
        // can have either duplicated or skipped attributes, so we strive to do no better
5542
        // here.
5543
        int index = get_index_from_order(d, i);
5544
        PyObject *value = _Py_atomic_load_ptr(&values->values[index]);
5545
        if (acquire_key_value(&DK_UNICODE_ENTRIES(k)[index].me_key, value,
5546
                               &values->values[index], out_key, out_value) < 0) {
5547
            goto try_locked;
5548
        }
5549
    }
5550
    else {
5551
        Py_ssize_t n = _Py_atomic_load_ssize_relaxed(&k->dk_nentries);
5552
        if (DK_IS_UNICODE(k)) {
5553
            PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(k)[i];
5554
            PyObject *value;
5555
            while (i < n &&
5556
                  (value = _Py_atomic_load_ptr(&entry_ptr->me_value)) == NULL) {
5557
                entry_ptr++;
5558
                i++;
5559
            }
5560
            if (i >= n)
5561
                goto fail;
5562
5563
            if (acquire_key_value(&entry_ptr->me_key, value,
5564
                                   &entry_ptr->me_value, out_key, out_value) < 0) {
5565
                goto try_locked;
5566
            }
5567
        }
5568
        else {
5569
            PyDictKeyEntry *entry_ptr = &DK_ENTRIES(k)[i];
5570
            PyObject *value;
5571
            while (i < n &&
5572
                  (value = _Py_atomic_load_ptr(&entry_ptr->me_value)) == NULL) {
5573
                entry_ptr++;
5574
                i++;
5575
            }
5576
5577
            if (i >= n)
5578
                goto fail;
5579
5580
            if (acquire_key_value(&entry_ptr->me_key, value,
5581
                                   &entry_ptr->me_value, out_key, out_value) < 0) {
5582
                goto try_locked;
5583
            }
5584
        }
5585
    }
5586
    // We found an element (key), but did not expect it
5587
    Py_ssize_t len;
5588
    if ((len = _Py_atomic_load_ssize_relaxed(&di->len)) == 0) {
5589
        goto concurrent_modification;
5590
    }
5591
5592
    _Py_atomic_store_ssize_relaxed(&di->di_pos, i + 1);
5593
    _Py_atomic_store_ssize_relaxed(&di->len, len - 1);
5594
    return 0;
5595
5596
concurrent_modification:
5597
    PyErr_SetString(PyExc_RuntimeError,
5598
                    "dictionary keys changed during iteration");
5599
5600
fail:
5601
    di->di_dict = NULL;
5602
    Py_DECREF(d);
5603
    return -1;
5604
5605
try_locked:
5606
    Py_BEGIN_CRITICAL_SECTION(d);
5607
    res = dictiter_iternextitem_lock_held(d, self, out_key, out_value);
5608
    Py_END_CRITICAL_SECTION();
5609
    return res;
5610
}
5611
5612
#endif
5613
5614
static bool
5615
acquire_iter_result(PyObject *result)
5616
2.81M
{
5617
2.81M
    if (_PyObject_IsUniquelyReferenced(result)) {
5618
2.80M
        Py_INCREF(result);
5619
2.80M
        return true;
5620
2.80M
    }
5621
15.0k
    return false;
5622
2.81M
}
5623
5624
static PyObject *
5625
dictiter_iternextitem(PyObject *self)
5626
3.44M
{
5627
3.44M
    dictiterobject *di = (dictiterobject *)self;
5628
3.44M
    PyDictObject *d = di->di_dict;
5629
5630
3.44M
    if (d == NULL)
5631
0
        return NULL;
5632
5633
3.44M
    PyObject *key, *value;
5634
#ifdef Py_GIL_DISABLED
5635
    if (dictiter_iternext_threadsafe(d, self, &key, &value) == 0) {
5636
#else
5637
3.44M
    if (dictiter_iternextitem_lock_held(d, self, &key, &value) == 0) {
5638
5639
2.81M
#endif
5640
2.81M
        PyObject *result = di->di_result;
5641
2.81M
        if (acquire_iter_result(result)) {
5642
2.80M
            PyObject *oldkey = PyTuple_GET_ITEM(result, 0);
5643
2.80M
            PyObject *oldvalue = PyTuple_GET_ITEM(result, 1);
5644
2.80M
            PyTuple_SET_ITEM(result, 0, key);
5645
2.80M
            PyTuple_SET_ITEM(result, 1, value);
5646
2.80M
            Py_DECREF(oldkey);
5647
2.80M
            Py_DECREF(oldvalue);
5648
            // bpo-42536: The GC may have untracked this result tuple. Since we're
5649
            // recycling it, make sure it's tracked again:
5650
2.80M
            _PyTuple_Recycle(result);
5651
2.80M
        }
5652
15.0k
        else {
5653
15.0k
            result = PyTuple_New(2);
5654
15.0k
            if (result == NULL) {
5655
0
                Py_DECREF(key);
5656
0
                Py_DECREF(value);
5657
0
                return NULL;
5658
0
            }
5659
15.0k
            PyTuple_SET_ITEM(result, 0, key);
5660
15.0k
            PyTuple_SET_ITEM(result, 1, value);
5661
15.0k
        }
5662
2.81M
        return result;
5663
2.81M
    }
5664
629k
    return NULL;
5665
3.44M
}
5666
5667
PyTypeObject PyDictIterItem_Type = {
5668
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
5669
    "dict_itemiterator",                        /* tp_name */
5670
    sizeof(dictiterobject),                     /* tp_basicsize */
5671
    0,                                          /* tp_itemsize */
5672
    /* methods */
5673
    dictiter_dealloc,                           /* tp_dealloc */
5674
    0,                                          /* tp_vectorcall_offset */
5675
    0,                                          /* tp_getattr */
5676
    0,                                          /* tp_setattr */
5677
    0,                                          /* tp_as_async */
5678
    0,                                          /* tp_repr */
5679
    0,                                          /* tp_as_number */
5680
    0,                                          /* tp_as_sequence */
5681
    0,                                          /* tp_as_mapping */
5682
    0,                                          /* tp_hash */
5683
    0,                                          /* tp_call */
5684
    0,                                          /* tp_str */
5685
    PyObject_GenericGetAttr,                    /* tp_getattro */
5686
    0,                                          /* tp_setattro */
5687
    0,                                          /* tp_as_buffer */
5688
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
5689
    0,                                          /* tp_doc */
5690
    dictiter_traverse,                          /* tp_traverse */
5691
    0,                                          /* tp_clear */
5692
    0,                                          /* tp_richcompare */
5693
    0,                                          /* tp_weaklistoffset */
5694
    PyObject_SelfIter,                          /* tp_iter */
5695
    dictiter_iternextitem,                      /* tp_iternext */
5696
    dictiter_methods,                           /* tp_methods */
5697
    0,
5698
};
5699
5700
5701
/* dictreviter */
5702
5703
static PyObject *
5704
dictreviter_iter_lock_held(PyDictObject *d, PyObject *self)
5705
0
{
5706
0
    dictiterobject *di = (dictiterobject *)self;
5707
5708
0
    assert (PyDict_Check(d));
5709
0
    ASSERT_DICT_LOCKED(d);
5710
5711
0
    if (di->di_used != d->ma_used) {
5712
0
        PyErr_SetString(PyExc_RuntimeError,
5713
0
                         "dictionary changed size during iteration");
5714
0
        di->di_used = -1; /* Make this state sticky */
5715
0
        return NULL;
5716
0
    }
5717
5718
0
    Py_ssize_t i = di->di_pos;
5719
0
    PyDictKeysObject *k = d->ma_keys;
5720
0
    PyObject *key, *value, *result;
5721
5722
0
    if (i < 0) {
5723
0
        goto fail;
5724
0
    }
5725
0
    if (_PyDict_HasSplitTable(d)) {
5726
0
        int index = get_index_from_order(d, i);
5727
0
        key = LOAD_SHARED_KEY(DK_UNICODE_ENTRIES(k)[index].me_key);
5728
0
        value = d->ma_values->values[index];
5729
0
        assert (value != NULL);
5730
0
    }
5731
0
    else {
5732
0
        if (DK_IS_UNICODE(k)) {
5733
0
            PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(k)[i];
5734
0
            while (entry_ptr->me_value == NULL) {
5735
0
                if (--i < 0) {
5736
0
                    goto fail;
5737
0
                }
5738
0
                entry_ptr--;
5739
0
            }
5740
0
            key = entry_ptr->me_key;
5741
0
            value = entry_ptr->me_value;
5742
0
        }
5743
0
        else {
5744
0
            PyDictKeyEntry *entry_ptr = &DK_ENTRIES(k)[i];
5745
0
            while (entry_ptr->me_value == NULL) {
5746
0
                if (--i < 0) {
5747
0
                    goto fail;
5748
0
                }
5749
0
                entry_ptr--;
5750
0
            }
5751
0
            key = entry_ptr->me_key;
5752
0
            value = entry_ptr->me_value;
5753
0
        }
5754
0
    }
5755
0
    di->di_pos = i-1;
5756
0
    di->len--;
5757
5758
0
    if (Py_IS_TYPE(di, &PyDictRevIterKey_Type)) {
5759
0
        return Py_NewRef(key);
5760
0
    }
5761
0
    else if (Py_IS_TYPE(di, &PyDictRevIterValue_Type)) {
5762
0
        return Py_NewRef(value);
5763
0
    }
5764
0
    else if (Py_IS_TYPE(di, &PyDictRevIterItem_Type)) {
5765
0
        result = di->di_result;
5766
0
        if (_PyObject_IsUniquelyReferenced(result)) {
5767
0
            PyObject *oldkey = PyTuple_GET_ITEM(result, 0);
5768
0
            PyObject *oldvalue = PyTuple_GET_ITEM(result, 1);
5769
0
            PyTuple_SET_ITEM(result, 0, Py_NewRef(key));
5770
0
            PyTuple_SET_ITEM(result, 1, Py_NewRef(value));
5771
0
            Py_INCREF(result);
5772
0
            Py_DECREF(oldkey);
5773
0
            Py_DECREF(oldvalue);
5774
            // bpo-42536: The GC may have untracked this result tuple. Since
5775
            // we're recycling it, make sure it's tracked again:
5776
0
            _PyTuple_Recycle(result);
5777
0
        }
5778
0
        else {
5779
0
            result = PyTuple_New(2);
5780
0
            if (result == NULL) {
5781
0
                return NULL;
5782
0
            }
5783
0
            PyTuple_SET_ITEM(result, 0, Py_NewRef(key));
5784
0
            PyTuple_SET_ITEM(result, 1, Py_NewRef(value));
5785
0
        }
5786
0
        return result;
5787
0
    }
5788
0
    else {
5789
0
        Py_UNREACHABLE();
5790
0
    }
5791
5792
0
fail:
5793
0
    di->di_dict = NULL;
5794
0
    Py_DECREF(d);
5795
0
    return NULL;
5796
0
}
5797
5798
static PyObject *
5799
dictreviter_iternext(PyObject *self)
5800
0
{
5801
0
    dictiterobject *di = (dictiterobject *)self;
5802
0
    PyDictObject *d = di->di_dict;
5803
5804
0
    if (d == NULL)
5805
0
        return NULL;
5806
5807
0
    PyObject *value;
5808
0
    Py_BEGIN_CRITICAL_SECTION(d);
5809
0
    value = dictreviter_iter_lock_held(d, self);
5810
0
    Py_END_CRITICAL_SECTION();
5811
5812
0
    return value;
5813
0
}
5814
5815
PyTypeObject PyDictRevIterKey_Type = {
5816
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
5817
    "dict_reversekeyiterator",
5818
    sizeof(dictiterobject),
5819
    .tp_dealloc = dictiter_dealloc,
5820
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
5821
    .tp_traverse = dictiter_traverse,
5822
    .tp_iter = PyObject_SelfIter,
5823
    .tp_iternext = dictreviter_iternext,
5824
    .tp_methods = dictiter_methods
5825
};
5826
5827
5828
/*[clinic input]
5829
dict.__reversed__
5830
5831
Return a reverse iterator over the dict keys.
5832
[clinic start generated code]*/
5833
5834
static PyObject *
5835
dict___reversed___impl(PyDictObject *self)
5836
/*[clinic end generated code: output=e674483336d1ed51 input=23210ef3477d8c4d]*/
5837
0
{
5838
0
    assert (PyDict_Check(self));
5839
0
    return dictiter_new(self, &PyDictRevIterKey_Type);
5840
0
}
5841
5842
static PyObject *
5843
dictiter_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
5844
0
{
5845
0
    dictiterobject *di = (dictiterobject *)self;
5846
    /* copy the iterator state */
5847
0
    dictiterobject tmp = *di;
5848
0
    Py_XINCREF(tmp.di_dict);
5849
0
    PyObject *list = PySequence_List((PyObject*)&tmp);
5850
0
    Py_XDECREF(tmp.di_dict);
5851
0
    if (list == NULL) {
5852
0
        return NULL;
5853
0
    }
5854
0
    return Py_BuildValue("N(N)", _PyEval_GetBuiltin(&_Py_ID(iter)), list);
5855
0
}
5856
5857
PyTypeObject PyDictRevIterItem_Type = {
5858
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
5859
    "dict_reverseitemiterator",
5860
    sizeof(dictiterobject),
5861
    .tp_dealloc = dictiter_dealloc,
5862
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
5863
    .tp_traverse = dictiter_traverse,
5864
    .tp_iter = PyObject_SelfIter,
5865
    .tp_iternext = dictreviter_iternext,
5866
    .tp_methods = dictiter_methods
5867
};
5868
5869
PyTypeObject PyDictRevIterValue_Type = {
5870
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
5871
    "dict_reversevalueiterator",
5872
    sizeof(dictiterobject),
5873
    .tp_dealloc = dictiter_dealloc,
5874
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
5875
    .tp_traverse = dictiter_traverse,
5876
    .tp_iter = PyObject_SelfIter,
5877
    .tp_iternext = dictreviter_iternext,
5878
    .tp_methods = dictiter_methods
5879
};
5880
5881
/***********************************************/
5882
/* View objects for keys(), items(), values(). */
5883
/***********************************************/
5884
5885
/* The instance lay-out is the same for all three; but the type differs. */
5886
5887
static void
5888
dictview_dealloc(PyObject *self)
5889
943k
{
5890
943k
    _PyDictViewObject *dv = (_PyDictViewObject *)self;
5891
    /* bpo-31095: UnTrack is needed before calling any callbacks */
5892
943k
    _PyObject_GC_UNTRACK(dv);
5893
943k
    Py_XDECREF(dv->dv_dict);
5894
943k
    PyObject_GC_Del(dv);
5895
943k
}
5896
5897
static int
5898
dictview_traverse(PyObject *self, visitproc visit, void *arg)
5899
7
{
5900
7
    _PyDictViewObject *dv = (_PyDictViewObject *)self;
5901
7
    Py_VISIT(dv->dv_dict);
5902
7
    return 0;
5903
7
}
5904
5905
static Py_ssize_t
5906
dictview_len(PyObject *self)
5907
0
{
5908
0
    _PyDictViewObject *dv = (_PyDictViewObject *)self;
5909
0
    Py_ssize_t len = 0;
5910
0
    if (dv->dv_dict != NULL)
5911
0
        len = FT_ATOMIC_LOAD_SSIZE_RELAXED(dv->dv_dict->ma_used);
5912
0
    return len;
5913
0
}
5914
5915
PyObject *
5916
_PyDictView_New(PyObject *dict, PyTypeObject *type)
5917
943k
{
5918
943k
    _PyDictViewObject *dv;
5919
943k
    if (dict == NULL) {
5920
0
        PyErr_BadInternalCall();
5921
0
        return NULL;
5922
0
    }
5923
943k
    if (!PyDict_Check(dict)) {
5924
        /* XXX Get rid of this restriction later */
5925
0
        PyErr_Format(PyExc_TypeError,
5926
0
                     "%s() requires a dict argument, not '%s'",
5927
0
                     type->tp_name, Py_TYPE(dict)->tp_name);
5928
0
        return NULL;
5929
0
    }
5930
943k
    dv = PyObject_GC_New(_PyDictViewObject, type);
5931
943k
    if (dv == NULL)
5932
0
        return NULL;
5933
943k
    dv->dv_dict = (PyDictObject *)Py_NewRef(dict);
5934
943k
    _PyObject_GC_TRACK(dv);
5935
943k
    return (PyObject *)dv;
5936
943k
}
5937
5938
static PyObject *
5939
0
dictview_mapping(PyObject *view, void *Py_UNUSED(ignored)) {
5940
0
    assert(view != NULL);
5941
0
    assert(PyDictKeys_Check(view)
5942
0
           || PyDictValues_Check(view)
5943
0
           || PyDictItems_Check(view));
5944
0
    PyObject *mapping = (PyObject *)((_PyDictViewObject *)view)->dv_dict;
5945
0
    return PyDictProxy_New(mapping);
5946
0
}
5947
5948
static PyGetSetDef dictview_getset[] = {
5949
    {"mapping", dictview_mapping, NULL,
5950
     PyDoc_STR("dictionary that this view refers to"), NULL},
5951
    {0}
5952
};
5953
5954
/* TODO(guido): The views objects are not complete:
5955
5956
 * support more set operations
5957
 * support arbitrary mappings?
5958
   - either these should be static or exported in dictobject.h
5959
   - if public then they should probably be in builtins
5960
*/
5961
5962
/* Return 1 if self is a subset of other, iterating over self;
5963
   0 if not; -1 if an error occurred. */
5964
static int
5965
all_contained_in(PyObject *self, PyObject *other)
5966
0
{
5967
0
    PyObject *iter = PyObject_GetIter(self);
5968
0
    int ok = 1;
5969
5970
0
    if (iter == NULL)
5971
0
        return -1;
5972
0
    for (;;) {
5973
0
        PyObject *next = PyIter_Next(iter);
5974
0
        if (next == NULL) {
5975
0
            if (PyErr_Occurred())
5976
0
                ok = -1;
5977
0
            break;
5978
0
        }
5979
0
        ok = PySequence_Contains(other, next);
5980
0
        Py_DECREF(next);
5981
0
        if (ok <= 0)
5982
0
            break;
5983
0
    }
5984
0
    Py_DECREF(iter);
5985
0
    return ok;
5986
0
}
5987
5988
static PyObject *
5989
dictview_richcompare(PyObject *self, PyObject *other, int op)
5990
0
{
5991
0
    Py_ssize_t len_self, len_other;
5992
0
    int ok;
5993
0
    PyObject *result;
5994
5995
0
    assert(self != NULL);
5996
0
    assert(PyDictViewSet_Check(self));
5997
0
    assert(other != NULL);
5998
5999
0
    if (!PyAnySet_Check(other) && !PyDictViewSet_Check(other))
6000
0
        Py_RETURN_NOTIMPLEMENTED;
6001
6002
0
    len_self = PyObject_Size(self);
6003
0
    if (len_self < 0)
6004
0
        return NULL;
6005
0
    len_other = PyObject_Size(other);
6006
0
    if (len_other < 0)
6007
0
        return NULL;
6008
6009
0
    ok = 0;
6010
0
    switch(op) {
6011
6012
0
    case Py_NE:
6013
0
    case Py_EQ:
6014
0
        if (len_self == len_other)
6015
0
            ok = all_contained_in(self, other);
6016
0
        if (op == Py_NE && ok >= 0)
6017
0
            ok = !ok;
6018
0
        break;
6019
6020
0
    case Py_LT:
6021
0
        if (len_self < len_other)
6022
0
            ok = all_contained_in(self, other);
6023
0
        break;
6024
6025
0
      case Py_LE:
6026
0
          if (len_self <= len_other)
6027
0
              ok = all_contained_in(self, other);
6028
0
          break;
6029
6030
0
    case Py_GT:
6031
0
        if (len_self > len_other)
6032
0
            ok = all_contained_in(other, self);
6033
0
        break;
6034
6035
0
    case Py_GE:
6036
0
        if (len_self >= len_other)
6037
0
            ok = all_contained_in(other, self);
6038
0
        break;
6039
6040
0
    }
6041
0
    if (ok < 0)
6042
0
        return NULL;
6043
0
    result = ok ? Py_True : Py_False;
6044
0
    return Py_NewRef(result);
6045
0
}
6046
6047
static PyObject *
6048
dictview_repr(PyObject *self)
6049
0
{
6050
0
    _PyDictViewObject *dv = (_PyDictViewObject *)self;
6051
0
    PyObject *seq;
6052
0
    PyObject *result = NULL;
6053
0
    Py_ssize_t rc;
6054
6055
0
    rc = Py_ReprEnter((PyObject *)dv);
6056
0
    if (rc != 0) {
6057
0
        return rc > 0 ? PyUnicode_FromString("...") : NULL;
6058
0
    }
6059
0
    seq = PySequence_List((PyObject *)dv);
6060
0
    if (seq == NULL) {
6061
0
        goto Done;
6062
0
    }
6063
0
    result = PyUnicode_FromFormat("%s(%R)", Py_TYPE(dv)->tp_name, seq);
6064
0
    Py_DECREF(seq);
6065
6066
0
Done:
6067
0
    Py_ReprLeave((PyObject *)dv);
6068
0
    return result;
6069
0
}
6070
6071
/*** dict_keys ***/
6072
6073
static PyObject *
6074
dictkeys_iter(PyObject *self)
6075
307k
{
6076
307k
    _PyDictViewObject *dv = (_PyDictViewObject *)self;
6077
307k
    if (dv->dv_dict == NULL) {
6078
0
        Py_RETURN_NONE;
6079
0
    }
6080
307k
    return dictiter_new(dv->dv_dict, &PyDictIterKey_Type);
6081
307k
}
6082
6083
static int
6084
dictkeys_contains(PyObject *self, PyObject *obj)
6085
0
{
6086
0
    _PyDictViewObject *dv = (_PyDictViewObject *)self;
6087
0
    if (dv->dv_dict == NULL)
6088
0
        return 0;
6089
0
    return PyDict_Contains((PyObject *)dv->dv_dict, obj);
6090
0
}
6091
6092
static PySequenceMethods dictkeys_as_sequence = {
6093
    dictview_len,                       /* sq_length */
6094
    0,                                  /* sq_concat */
6095
    0,                                  /* sq_repeat */
6096
    0,                                  /* sq_item */
6097
    0,                                  /* sq_slice */
6098
    0,                                  /* sq_ass_item */
6099
    0,                                  /* sq_ass_slice */
6100
    dictkeys_contains,                  /* sq_contains */
6101
};
6102
6103
// Create a set object from dictviews object.
6104
// Returns a new reference.
6105
// This utility function is used by set operations.
6106
static PyObject*
6107
dictviews_to_set(PyObject *self)
6108
0
{
6109
0
    PyObject *left = self;
6110
0
    if (PyDictKeys_Check(self)) {
6111
        // PySet_New() has fast path for the dict object.
6112
0
        PyObject *dict = (PyObject *)((_PyDictViewObject *)self)->dv_dict;
6113
0
        if (PyDict_CheckExact(dict)) {
6114
0
            left = dict;
6115
0
        }
6116
0
    }
6117
0
    return PySet_New(left);
6118
0
}
6119
6120
static PyObject*
6121
dictviews_sub(PyObject *self, PyObject *other)
6122
0
{
6123
0
    PyObject *result = dictviews_to_set(self);
6124
0
    if (result == NULL) {
6125
0
        return NULL;
6126
0
    }
6127
6128
0
    PyObject *tmp = PyObject_CallMethodOneArg(
6129
0
            result, &_Py_ID(difference_update), other);
6130
0
    if (tmp == NULL) {
6131
0
        Py_DECREF(result);
6132
0
        return NULL;
6133
0
    }
6134
6135
0
    Py_DECREF(tmp);
6136
0
    return result;
6137
0
}
6138
6139
static int
6140
dictitems_contains(PyObject *dv, PyObject *obj);
6141
6142
PyObject *
6143
_PyDictView_Intersect(PyObject* self, PyObject *other)
6144
0
{
6145
0
    PyObject *result;
6146
0
    PyObject *it;
6147
0
    PyObject *key;
6148
0
    Py_ssize_t len_self;
6149
0
    int rv;
6150
0
    objobjproc dict_contains;
6151
6152
    /* Python interpreter swaps parameters when dict view
6153
       is on right side of & */
6154
0
    if (!PyDictViewSet_Check(self)) {
6155
0
        PyObject *tmp = other;
6156
0
        other = self;
6157
0
        self = tmp;
6158
0
    }
6159
6160
0
    len_self = dictview_len(self);
6161
6162
    /* if other is a set and self is smaller than other,
6163
       reuse set intersection logic */
6164
0
    if (PySet_CheckExact(other) && len_self <= PyObject_Size(other)) {
6165
0
        return PyObject_CallMethodObjArgs(
6166
0
                other, &_Py_ID(intersection), self, NULL);
6167
0
    }
6168
6169
    /* if other is another dict view, and it is bigger than self,
6170
       swap them */
6171
0
    if (PyDictViewSet_Check(other)) {
6172
0
        Py_ssize_t len_other = dictview_len(other);
6173
0
        if (len_other > len_self) {
6174
0
            PyObject *tmp = other;
6175
0
            other = self;
6176
0
            self = tmp;
6177
0
        }
6178
0
    }
6179
6180
    /* at this point, two things should be true
6181
       1. self is a dictview
6182
       2. if other is a dictview then it is smaller than self */
6183
0
    result = PySet_New(NULL);
6184
0
    if (result == NULL)
6185
0
        return NULL;
6186
6187
0
    it = PyObject_GetIter(other);
6188
0
    if (it == NULL) {
6189
0
        Py_DECREF(result);
6190
0
        return NULL;
6191
0
    }
6192
6193
0
    if (PyDictKeys_Check(self)) {
6194
0
        dict_contains = dictkeys_contains;
6195
0
    }
6196
    /* else PyDictItems_Check(self) */
6197
0
    else {
6198
0
        dict_contains = dictitems_contains;
6199
0
    }
6200
6201
0
    while ((key = PyIter_Next(it)) != NULL) {
6202
0
        rv = dict_contains(self, key);
6203
0
        if (rv < 0) {
6204
0
            goto error;
6205
0
        }
6206
0
        if (rv) {
6207
0
            if (PySet_Add(result, key)) {
6208
0
                goto error;
6209
0
            }
6210
0
        }
6211
0
        Py_DECREF(key);
6212
0
    }
6213
0
    Py_DECREF(it);
6214
0
    if (PyErr_Occurred()) {
6215
0
        Py_DECREF(result);
6216
0
        return NULL;
6217
0
    }
6218
0
    return result;
6219
6220
0
error:
6221
0
    Py_DECREF(it);
6222
0
    Py_DECREF(result);
6223
0
    Py_DECREF(key);
6224
0
    return NULL;
6225
0
}
6226
6227
static PyObject*
6228
dictviews_or(PyObject* self, PyObject *other)
6229
0
{
6230
0
    PyObject *result = dictviews_to_set(self);
6231
0
    if (result == NULL) {
6232
0
        return NULL;
6233
0
    }
6234
6235
0
    if (_PySet_Update(result, other) < 0) {
6236
0
        Py_DECREF(result);
6237
0
        return NULL;
6238
0
    }
6239
0
    return result;
6240
0
}
6241
6242
static PyObject *
6243
dictitems_xor_lock_held(PyObject *d1, PyObject *d2)
6244
0
{
6245
0
    ASSERT_DICT_LOCKED(d1);
6246
0
    ASSERT_DICT_LOCKED(d2);
6247
6248
0
    PyObject *temp_dict = copy_lock_held(d1);
6249
0
    if (temp_dict == NULL) {
6250
0
        return NULL;
6251
0
    }
6252
0
    PyObject *result_set = PySet_New(NULL);
6253
0
    if (result_set == NULL) {
6254
0
        Py_CLEAR(temp_dict);
6255
0
        return NULL;
6256
0
    }
6257
6258
0
    PyObject *key = NULL, *val1 = NULL, *val2 = NULL;
6259
0
    Py_ssize_t pos = 0;
6260
0
    Py_hash_t hash;
6261
6262
0
    while (_PyDict_Next(d2, &pos, &key, &val2, &hash)) {
6263
0
        Py_INCREF(key);
6264
0
        Py_INCREF(val2);
6265
0
        val1 = _PyDict_GetItem_KnownHash(temp_dict, key, hash);
6266
6267
0
        int to_delete;
6268
0
        if (val1 == NULL) {
6269
0
            if (PyErr_Occurred()) {
6270
0
                goto error;
6271
0
            }
6272
0
            to_delete = 0;
6273
0
        }
6274
0
        else {
6275
0
            Py_INCREF(val1);
6276
0
            to_delete = PyObject_RichCompareBool(val1, val2, Py_EQ);
6277
0
            if (to_delete < 0) {
6278
0
                goto error;
6279
0
            }
6280
0
        }
6281
6282
0
        if (to_delete) {
6283
0
            if (_PyDict_DelItem_KnownHash(temp_dict, key, hash) < 0) {
6284
0
                goto error;
6285
0
            }
6286
0
        }
6287
0
        else {
6288
0
            PyObject *pair = PyTuple_Pack(2, key, val2);
6289
0
            if (pair == NULL) {
6290
0
                goto error;
6291
0
            }
6292
0
            if (PySet_Add(result_set, pair) < 0) {
6293
0
                Py_DECREF(pair);
6294
0
                goto error;
6295
0
            }
6296
0
            Py_DECREF(pair);
6297
0
        }
6298
0
        Py_DECREF(key);
6299
0
        Py_XDECREF(val1);
6300
0
        Py_DECREF(val2);
6301
0
    }
6302
0
    key = val1 = val2 = NULL;
6303
6304
0
    PyObject *remaining_pairs = PyObject_CallMethodNoArgs(
6305
0
            temp_dict, &_Py_ID(items));
6306
0
    if (remaining_pairs == NULL) {
6307
0
        goto error;
6308
0
    }
6309
0
    if (_PySet_Update(result_set, remaining_pairs) < 0) {
6310
0
        Py_DECREF(remaining_pairs);
6311
0
        goto error;
6312
0
    }
6313
0
    Py_DECREF(temp_dict);
6314
0
    Py_DECREF(remaining_pairs);
6315
0
    return result_set;
6316
6317
0
error:
6318
0
    Py_XDECREF(temp_dict);
6319
0
    Py_XDECREF(result_set);
6320
0
    Py_XDECREF(key);
6321
0
    Py_XDECREF(val1);
6322
0
    Py_XDECREF(val2);
6323
0
    return NULL;
6324
0
}
6325
6326
static PyObject *
6327
dictitems_xor(PyObject *self, PyObject *other)
6328
0
{
6329
0
    assert(PyDictItems_Check(self));
6330
0
    assert(PyDictItems_Check(other));
6331
0
    PyObject *d1 = (PyObject *)((_PyDictViewObject *)self)->dv_dict;
6332
0
    PyObject *d2 = (PyObject *)((_PyDictViewObject *)other)->dv_dict;
6333
6334
0
    PyObject *res;
6335
0
    Py_BEGIN_CRITICAL_SECTION2(d1, d2);
6336
0
    res = dictitems_xor_lock_held(d1, d2);
6337
0
    Py_END_CRITICAL_SECTION2();
6338
6339
0
    return res;
6340
0
}
6341
6342
static PyObject*
6343
dictviews_xor(PyObject* self, PyObject *other)
6344
0
{
6345
0
    if (PyDictItems_Check(self) && PyDictItems_Check(other)) {
6346
0
        return dictitems_xor(self, other);
6347
0
    }
6348
0
    PyObject *result = dictviews_to_set(self);
6349
0
    if (result == NULL) {
6350
0
        return NULL;
6351
0
    }
6352
6353
0
    PyObject *tmp = PyObject_CallMethodOneArg(
6354
0
            result, &_Py_ID(symmetric_difference_update), other);
6355
0
    if (tmp == NULL) {
6356
0
        Py_DECREF(result);
6357
0
        return NULL;
6358
0
    }
6359
6360
0
    Py_DECREF(tmp);
6361
0
    return result;
6362
0
}
6363
6364
static PyNumberMethods dictviews_as_number = {
6365
    0,                                  /*nb_add*/
6366
    dictviews_sub,                      /*nb_subtract*/
6367
    0,                                  /*nb_multiply*/
6368
    0,                                  /*nb_remainder*/
6369
    0,                                  /*nb_divmod*/
6370
    0,                                  /*nb_power*/
6371
    0,                                  /*nb_negative*/
6372
    0,                                  /*nb_positive*/
6373
    0,                                  /*nb_absolute*/
6374
    0,                                  /*nb_bool*/
6375
    0,                                  /*nb_invert*/
6376
    0,                                  /*nb_lshift*/
6377
    0,                                  /*nb_rshift*/
6378
    _PyDictView_Intersect,              /*nb_and*/
6379
    dictviews_xor,                      /*nb_xor*/
6380
    dictviews_or,                       /*nb_or*/
6381
};
6382
6383
static PyObject*
6384
dictviews_isdisjoint(PyObject *self, PyObject *other)
6385
0
{
6386
0
    PyObject *it;
6387
0
    PyObject *item = NULL;
6388
6389
0
    if (self == other) {
6390
0
        if (dictview_len(self) == 0)
6391
0
            Py_RETURN_TRUE;
6392
0
        else
6393
0
            Py_RETURN_FALSE;
6394
0
    }
6395
6396
    /* Iterate over the shorter object (only if other is a set,
6397
     * because PySequence_Contains may be expensive otherwise): */
6398
0
    if (PyAnySet_Check(other) || PyDictViewSet_Check(other)) {
6399
0
        Py_ssize_t len_self = dictview_len(self);
6400
0
        Py_ssize_t len_other = PyObject_Size(other);
6401
0
        if (len_other == -1)
6402
0
            return NULL;
6403
6404
0
        if ((len_other > len_self)) {
6405
0
            PyObject *tmp = other;
6406
0
            other = self;
6407
0
            self = tmp;
6408
0
        }
6409
0
    }
6410
6411
0
    it = PyObject_GetIter(other);
6412
0
    if (it == NULL)
6413
0
        return NULL;
6414
6415
0
    while ((item = PyIter_Next(it)) != NULL) {
6416
0
        int contains = PySequence_Contains(self, item);
6417
0
        Py_DECREF(item);
6418
0
        if (contains == -1) {
6419
0
            Py_DECREF(it);
6420
0
            return NULL;
6421
0
        }
6422
6423
0
        if (contains) {
6424
0
            Py_DECREF(it);
6425
0
            Py_RETURN_FALSE;
6426
0
        }
6427
0
    }
6428
0
    Py_DECREF(it);
6429
0
    if (PyErr_Occurred())
6430
0
        return NULL; /* PyIter_Next raised an exception. */
6431
0
    Py_RETURN_TRUE;
6432
0
}
6433
6434
PyDoc_STRVAR(isdisjoint_doc,
6435
"Return True if the view and the given iterable have a null intersection.");
6436
6437
static PyObject* dictkeys_reversed(PyObject *dv, PyObject *Py_UNUSED(ignored));
6438
6439
PyDoc_STRVAR(reversed_keys_doc,
6440
"Return a reverse iterator over the dict keys.");
6441
6442
static PyMethodDef dictkeys_methods[] = {
6443
    {"isdisjoint",      dictviews_isdisjoint,           METH_O,
6444
     isdisjoint_doc},
6445
    {"__reversed__",    dictkeys_reversed,              METH_NOARGS,
6446
     reversed_keys_doc},
6447
    {NULL,              NULL}           /* sentinel */
6448
};
6449
6450
PyTypeObject PyDictKeys_Type = {
6451
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
6452
    "dict_keys",                                /* tp_name */
6453
    sizeof(_PyDictViewObject),                  /* tp_basicsize */
6454
    0,                                          /* tp_itemsize */
6455
    /* methods */
6456
    dictview_dealloc,                           /* tp_dealloc */
6457
    0,                                          /* tp_vectorcall_offset */
6458
    0,                                          /* tp_getattr */
6459
    0,                                          /* tp_setattr */
6460
    0,                                          /* tp_as_async */
6461
    dictview_repr,                              /* tp_repr */
6462
    &dictviews_as_number,                       /* tp_as_number */
6463
    &dictkeys_as_sequence,                      /* tp_as_sequence */
6464
    0,                                          /* tp_as_mapping */
6465
    0,                                          /* tp_hash */
6466
    0,                                          /* tp_call */
6467
    0,                                          /* tp_str */
6468
    PyObject_GenericGetAttr,                    /* tp_getattro */
6469
    0,                                          /* tp_setattro */
6470
    0,                                          /* tp_as_buffer */
6471
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
6472
    0,                                          /* tp_doc */
6473
    dictview_traverse,                          /* tp_traverse */
6474
    0,                                          /* tp_clear */
6475
    dictview_richcompare,                       /* tp_richcompare */
6476
    0,                                          /* tp_weaklistoffset */
6477
    dictkeys_iter,                              /* tp_iter */
6478
    0,                                          /* tp_iternext */
6479
    dictkeys_methods,                           /* tp_methods */
6480
    .tp_getset = dictview_getset,
6481
};
6482
6483
/*[clinic input]
6484
dict.keys
6485
6486
Return a set-like object providing a view on the dict's keys.
6487
[clinic start generated code]*/
6488
6489
static PyObject *
6490
dict_keys_impl(PyDictObject *self)
6491
/*[clinic end generated code: output=aac2830c62990358 input=42f48a7a771212a7]*/
6492
307k
{
6493
307k
    return _PyDictView_New((PyObject *)self, &PyDictKeys_Type);
6494
307k
}
6495
6496
static PyObject *
6497
dictkeys_reversed(PyObject *self, PyObject *Py_UNUSED(ignored))
6498
0
{
6499
0
    _PyDictViewObject *dv = (_PyDictViewObject *)self;
6500
0
    if (dv->dv_dict == NULL) {
6501
0
        Py_RETURN_NONE;
6502
0
    }
6503
0
    return dictiter_new(dv->dv_dict, &PyDictRevIterKey_Type);
6504
0
}
6505
6506
/*** dict_items ***/
6507
6508
static PyObject *
6509
dictitems_iter(PyObject *self)
6510
629k
{
6511
629k
    _PyDictViewObject *dv = (_PyDictViewObject *)self;
6512
629k
    if (dv->dv_dict == NULL) {
6513
0
        Py_RETURN_NONE;
6514
0
    }
6515
629k
    return dictiter_new(dv->dv_dict, &PyDictIterItem_Type);
6516
629k
}
6517
6518
static int
6519
dictitems_contains(PyObject *self, PyObject *obj)
6520
0
{
6521
0
    _PyDictViewObject *dv = (_PyDictViewObject *)self;
6522
0
    int result;
6523
0
    PyObject *key, *value, *found;
6524
0
    if (dv->dv_dict == NULL)
6525
0
        return 0;
6526
0
    if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 2)
6527
0
        return 0;
6528
0
    key = PyTuple_GET_ITEM(obj, 0);
6529
0
    value = PyTuple_GET_ITEM(obj, 1);
6530
0
    result = PyDict_GetItemRef((PyObject *)dv->dv_dict, key, &found);
6531
0
    if (result == 1) {
6532
0
        result = PyObject_RichCompareBool(found, value, Py_EQ);
6533
0
        Py_DECREF(found);
6534
0
    }
6535
0
    return result;
6536
0
}
6537
6538
static PySequenceMethods dictitems_as_sequence = {
6539
    dictview_len,                       /* sq_length */
6540
    0,                                  /* sq_concat */
6541
    0,                                  /* sq_repeat */
6542
    0,                                  /* sq_item */
6543
    0,                                  /* sq_slice */
6544
    0,                                  /* sq_ass_item */
6545
    0,                                  /* sq_ass_slice */
6546
    dictitems_contains,                 /* sq_contains */
6547
};
6548
6549
static PyObject* dictitems_reversed(PyObject *dv, PyObject *Py_UNUSED(ignored));
6550
6551
PyDoc_STRVAR(reversed_items_doc,
6552
"Return a reverse iterator over the dict items.");
6553
6554
static PyMethodDef dictitems_methods[] = {
6555
    {"isdisjoint",      dictviews_isdisjoint,           METH_O,
6556
     isdisjoint_doc},
6557
    {"__reversed__",    dictitems_reversed,             METH_NOARGS,
6558
     reversed_items_doc},
6559
    {NULL,              NULL}           /* sentinel */
6560
};
6561
6562
PyTypeObject PyDictItems_Type = {
6563
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
6564
    "dict_items",                               /* tp_name */
6565
    sizeof(_PyDictViewObject),                  /* tp_basicsize */
6566
    0,                                          /* tp_itemsize */
6567
    /* methods */
6568
    dictview_dealloc,                           /* tp_dealloc */
6569
    0,                                          /* tp_vectorcall_offset */
6570
    0,                                          /* tp_getattr */
6571
    0,                                          /* tp_setattr */
6572
    0,                                          /* tp_as_async */
6573
    dictview_repr,                              /* tp_repr */
6574
    &dictviews_as_number,                       /* tp_as_number */
6575
    &dictitems_as_sequence,                     /* tp_as_sequence */
6576
    0,                                          /* tp_as_mapping */
6577
    0,                                          /* tp_hash */
6578
    0,                                          /* tp_call */
6579
    0,                                          /* tp_str */
6580
    PyObject_GenericGetAttr,                    /* tp_getattro */
6581
    0,                                          /* tp_setattro */
6582
    0,                                          /* tp_as_buffer */
6583
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
6584
    0,                                          /* tp_doc */
6585
    dictview_traverse,                          /* tp_traverse */
6586
    0,                                          /* tp_clear */
6587
    dictview_richcompare,                       /* tp_richcompare */
6588
    0,                                          /* tp_weaklistoffset */
6589
    dictitems_iter,                             /* tp_iter */
6590
    0,                                          /* tp_iternext */
6591
    dictitems_methods,                          /* tp_methods */
6592
    .tp_getset = dictview_getset,
6593
};
6594
6595
/*[clinic input]
6596
dict.items
6597
6598
Return a set-like object providing a view on the dict's items.
6599
[clinic start generated code]*/
6600
6601
static PyObject *
6602
dict_items_impl(PyDictObject *self)
6603
/*[clinic end generated code: output=88c7db7150c7909a input=87c822872eb71f5a]*/
6604
629k
{
6605
629k
    return _PyDictView_New((PyObject *)self, &PyDictItems_Type);
6606
629k
}
6607
6608
static PyObject *
6609
dictitems_reversed(PyObject *self, PyObject *Py_UNUSED(ignored))
6610
0
{
6611
0
    _PyDictViewObject *dv = (_PyDictViewObject *)self;
6612
0
    if (dv->dv_dict == NULL) {
6613
0
        Py_RETURN_NONE;
6614
0
    }
6615
0
    return dictiter_new(dv->dv_dict, &PyDictRevIterItem_Type);
6616
0
}
6617
6618
/*** dict_values ***/
6619
6620
static PyObject *
6621
dictvalues_iter(PyObject *self)
6622
6.24k
{
6623
6.24k
    _PyDictViewObject *dv = (_PyDictViewObject *)self;
6624
6.24k
    if (dv->dv_dict == NULL) {
6625
0
        Py_RETURN_NONE;
6626
0
    }
6627
6.24k
    return dictiter_new(dv->dv_dict, &PyDictIterValue_Type);
6628
6.24k
}
6629
6630
static PySequenceMethods dictvalues_as_sequence = {
6631
    dictview_len,                       /* sq_length */
6632
    0,                                  /* sq_concat */
6633
    0,                                  /* sq_repeat */
6634
    0,                                  /* sq_item */
6635
    0,                                  /* sq_slice */
6636
    0,                                  /* sq_ass_item */
6637
    0,                                  /* sq_ass_slice */
6638
    0,                                  /* sq_contains */
6639
};
6640
6641
static PyObject* dictvalues_reversed(PyObject *dv, PyObject *Py_UNUSED(ignored));
6642
6643
PyDoc_STRVAR(reversed_values_doc,
6644
"Return a reverse iterator over the dict values.");
6645
6646
static PyMethodDef dictvalues_methods[] = {
6647
    {"__reversed__",    dictvalues_reversed,            METH_NOARGS,
6648
     reversed_values_doc},
6649
    {NULL,              NULL}           /* sentinel */
6650
};
6651
6652
PyTypeObject PyDictValues_Type = {
6653
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
6654
    "dict_values",                              /* tp_name */
6655
    sizeof(_PyDictViewObject),                  /* tp_basicsize */
6656
    0,                                          /* tp_itemsize */
6657
    /* methods */
6658
    dictview_dealloc,                           /* tp_dealloc */
6659
    0,                                          /* tp_vectorcall_offset */
6660
    0,                                          /* tp_getattr */
6661
    0,                                          /* tp_setattr */
6662
    0,                                          /* tp_as_async */
6663
    dictview_repr,                              /* tp_repr */
6664
    0,                                          /* tp_as_number */
6665
    &dictvalues_as_sequence,                    /* tp_as_sequence */
6666
    0,                                          /* tp_as_mapping */
6667
    0,                                          /* tp_hash */
6668
    0,                                          /* tp_call */
6669
    0,                                          /* tp_str */
6670
    PyObject_GenericGetAttr,                    /* tp_getattro */
6671
    0,                                          /* tp_setattro */
6672
    0,                                          /* tp_as_buffer */
6673
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
6674
    0,                                          /* tp_doc */
6675
    dictview_traverse,                          /* tp_traverse */
6676
    0,                                          /* tp_clear */
6677
    0,                                          /* tp_richcompare */
6678
    0,                                          /* tp_weaklistoffset */
6679
    dictvalues_iter,                            /* tp_iter */
6680
    0,                                          /* tp_iternext */
6681
    dictvalues_methods,                         /* tp_methods */
6682
    .tp_getset = dictview_getset,
6683
};
6684
6685
/*[clinic input]
6686
dict.values
6687
6688
Return an object providing a view on the dict's values.
6689
[clinic start generated code]*/
6690
6691
static PyObject *
6692
dict_values_impl(PyDictObject *self)
6693
/*[clinic end generated code: output=ce9f2e9e8a959dd4 input=b46944f85493b230]*/
6694
6.27k
{
6695
6.27k
    return _PyDictView_New((PyObject *)self, &PyDictValues_Type);
6696
6.27k
}
6697
6698
static PyObject *
6699
dictvalues_reversed(PyObject *self, PyObject *Py_UNUSED(ignored))
6700
0
{
6701
0
    _PyDictViewObject *dv = (_PyDictViewObject *)self;
6702
0
    if (dv->dv_dict == NULL) {
6703
0
        Py_RETURN_NONE;
6704
0
    }
6705
0
    return dictiter_new(dv->dv_dict, &PyDictRevIterValue_Type);
6706
0
}
6707
6708
6709
/* Returns NULL if cannot allocate a new PyDictKeysObject,
6710
   but does not set an error */
6711
PyDictKeysObject *
6712
_PyDict_NewKeysForClass(PyHeapTypeObject *cls)
6713
287k
{
6714
287k
    PyDictKeysObject *keys = new_keys_object(NEXT_LOG2_SHARED_KEYS_MAX_SIZE, 1);
6715
287k
    if (keys == NULL) {
6716
0
        PyErr_Clear();
6717
0
    }
6718
287k
    else {
6719
287k
        assert(keys->dk_nentries == 0);
6720
        /* Set to max size+1 as it will shrink by one before each new object */
6721
287k
        keys->dk_usable = SHARED_KEYS_MAX_SIZE;
6722
287k
        keys->dk_kind = DICT_KEYS_SPLIT;
6723
287k
    }
6724
287k
    if (cls->ht_type.tp_dict) {
6725
287k
        PyObject *attrs = PyDict_GetItem(cls->ht_type.tp_dict, &_Py_ID(__static_attributes__));
6726
287k
        if (attrs != NULL && PyTuple_Check(attrs)) {
6727
11.1k
            for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(attrs); i++) {
6728
6.43k
                PyObject *key = PyTuple_GET_ITEM(attrs, i);
6729
6.43k
                Py_hash_t hash;
6730
6.43k
                if (PyUnicode_CheckExact(key) && (hash = unicode_get_hash(key)) != -1) {
6731
6.43k
                    if (insert_split_key(keys, key, hash) == DKIX_EMPTY) {
6732
0
                        break;
6733
0
                    }
6734
6.43k
                }
6735
6.43k
            }
6736
4.71k
        }
6737
287k
    }
6738
287k
    return keys;
6739
287k
}
6740
6741
void
6742
_PyObject_InitInlineValues(PyObject *obj, PyTypeObject *tp)
6743
33.5M
{
6744
33.5M
    assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE);
6745
33.5M
    assert(tp->tp_flags & Py_TPFLAGS_INLINE_VALUES);
6746
33.5M
    assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
6747
33.5M
    PyDictKeysObject *keys = CACHED_KEYS(tp);
6748
33.5M
    assert(keys != NULL);
6749
33.5M
    OBJECT_STAT_INC(inline_values);
6750
#ifdef Py_GIL_DISABLED
6751
    Py_ssize_t usable = _Py_atomic_load_ssize_relaxed(&keys->dk_usable);
6752
    if (usable > 1) {
6753
        LOCK_KEYS(keys);
6754
        if (keys->dk_usable > 1) {
6755
            _Py_atomic_store_ssize(&keys->dk_usable, keys->dk_usable - 1);
6756
        }
6757
        UNLOCK_KEYS(keys);
6758
    }
6759
#else
6760
33.5M
    if (keys->dk_usable > 1) {
6761
292k
        keys->dk_usable--;
6762
292k
    }
6763
33.5M
#endif
6764
33.5M
    size_t size = shared_keys_usable_size(keys);
6765
33.5M
    PyDictValues *values = _PyObject_InlineValues(obj);
6766
33.5M
    assert(size < 256);
6767
33.5M
    values->capacity = (uint8_t)size;
6768
33.5M
    values->size = 0;
6769
33.5M
    values->embedded = 1;
6770
33.5M
    values->valid = 1;
6771
207M
    for (size_t i = 0; i < size; i++) {
6772
174M
        values->values[i] = NULL;
6773
174M
    }
6774
33.5M
    _PyObject_ManagedDictPointer(obj)->dict = NULL;
6775
33.5M
}
6776
6777
static PyDictObject *
6778
make_dict_from_instance_attributes(PyDictKeysObject *keys, PyDictValues *values)
6779
694k
{
6780
694k
    dictkeys_incref(keys);
6781
694k
    Py_ssize_t used = 0;
6782
694k
    size_t size = shared_keys_usable_size(keys);
6783
2.24M
    for (size_t i = 0; i < size; i++) {
6784
1.55M
        PyObject *val = values->values[i];
6785
1.55M
        if (val != NULL) {
6786
1.10M
            used += 1;
6787
1.10M
        }
6788
1.55M
    }
6789
694k
    PyDictObject *res = (PyDictObject *)new_dict(keys, values, used, 0);
6790
694k
    return res;
6791
694k
}
6792
6793
PyDictObject *
6794
_PyObject_MaterializeManagedDict_LockHeld(PyObject *obj)
6795
5.60k
{
6796
5.60k
    ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(obj);
6797
6798
5.60k
    OBJECT_STAT_INC(dict_materialized_on_request);
6799
6800
5.60k
    PyDictValues *values = _PyObject_InlineValues(obj);
6801
5.60k
    PyDictObject *dict;
6802
5.60k
    if (values->valid) {
6803
5.60k
        PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
6804
5.60k
        dict = make_dict_from_instance_attributes(keys, values);
6805
5.60k
    }
6806
0
    else {
6807
0
        dict = (PyDictObject *)PyDict_New();
6808
0
    }
6809
5.60k
    FT_ATOMIC_STORE_PTR_RELEASE(_PyObject_ManagedDictPointer(obj)->dict,
6810
5.60k
                                dict);
6811
5.60k
    return dict;
6812
5.60k
}
6813
6814
PyDictObject *
6815
_PyObject_MaterializeManagedDict(PyObject *obj)
6816
74.0M
{
6817
74.0M
    PyDictObject *dict = _PyObject_GetManagedDict(obj);
6818
74.0M
    if (dict != NULL) {
6819
74.0M
        return dict;
6820
74.0M
    }
6821
6822
5.60k
    Py_BEGIN_CRITICAL_SECTION(obj);
6823
6824
#ifdef Py_GIL_DISABLED
6825
    dict = _PyObject_GetManagedDict(obj);
6826
    if (dict != NULL) {
6827
        // We raced with another thread creating the dict
6828
        goto exit;
6829
    }
6830
#endif
6831
5.60k
    dict = _PyObject_MaterializeManagedDict_LockHeld(obj);
6832
6833
#ifdef Py_GIL_DISABLED
6834
exit:
6835
#endif
6836
5.60k
    Py_END_CRITICAL_SECTION();
6837
5.60k
    return dict;
6838
74.0M
}
6839
6840
int
6841
_PyDict_SetItem_LockHeld(PyDictObject *dict, PyObject *name, PyObject *value)
6842
53.2M
{
6843
53.2M
    if (value == NULL) {
6844
9.90k
        Py_hash_t hash = _PyObject_HashFast(name);
6845
9.90k
        if (hash == -1) {
6846
0
            dict_unhashable_type(name);
6847
0
            return -1;
6848
0
        }
6849
9.90k
        return _PyDict_DelItem_KnownHash_LockHeld((PyObject *)dict, name, hash);
6850
53.2M
    } else {
6851
53.2M
        return setitem_lock_held(dict, name, value);
6852
53.2M
    }
6853
53.2M
}
6854
6855
// Called with either the object's lock or the dict's lock held
6856
// depending on whether or not a dict has been materialized for
6857
// the object.
6858
static int
6859
store_instance_attr_lock_held(PyObject *obj, PyDictValues *values,
6860
                              PyObject *name, PyObject *value)
6861
18.8M
{
6862
18.8M
    PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
6863
18.8M
    assert(keys != NULL);
6864
18.8M
    assert(values != NULL);
6865
18.8M
    assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_INLINE_VALUES);
6866
18.8M
    Py_ssize_t ix = DKIX_EMPTY;
6867
18.8M
    PyDictObject *dict = _PyObject_GetManagedDict(obj);
6868
18.8M
    assert(dict == NULL || ((PyDictObject *)dict)->ma_values == values);
6869
18.8M
    if (PyUnicode_CheckExact(name)) {
6870
18.8M
        Py_hash_t hash = unicode_get_hash(name);
6871
18.8M
        if (hash == -1) {
6872
0
            hash = PyUnicode_Type.tp_hash(name);
6873
0
            assert(hash != -1);
6874
0
        }
6875
6876
18.8M
        ix = insert_split_key(keys, name, hash);
6877
6878
#ifdef Py_STATS
6879
        if (ix == DKIX_EMPTY) {
6880
            if (PyUnicode_CheckExact(name)) {
6881
                if (shared_keys_usable_size(keys) == SHARED_KEYS_MAX_SIZE) {
6882
                    OBJECT_STAT_INC(dict_materialized_too_big);
6883
                }
6884
                else {
6885
                    OBJECT_STAT_INC(dict_materialized_new_key);
6886
                }
6887
            }
6888
            else {
6889
                OBJECT_STAT_INC(dict_materialized_str_subclass);
6890
            }
6891
        }
6892
#endif
6893
18.8M
    }
6894
6895
18.8M
    if (ix == DKIX_EMPTY) {
6896
694k
        int res;
6897
694k
        if (dict == NULL) {
6898
            // Make the dict but don't publish it in the object
6899
            // so that no one else will see it.
6900
688k
            dict = make_dict_from_instance_attributes(keys, values);
6901
688k
            if (dict == NULL ||
6902
688k
                _PyDict_SetItem_LockHeld(dict, name, value) < 0) {
6903
0
                Py_XDECREF(dict);
6904
0
                return -1;
6905
0
            }
6906
6907
688k
            FT_ATOMIC_STORE_PTR_RELEASE(_PyObject_ManagedDictPointer(obj)->dict,
6908
688k
                                        (PyDictObject *)dict);
6909
688k
            return 0;
6910
688k
        }
6911
6912
5.58k
        _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(dict);
6913
6914
5.58k
        res = _PyDict_SetItem_LockHeld(dict, name, value);
6915
5.58k
        return res;
6916
694k
    }
6917
6918
18.1M
    PyObject *old_value = values->values[ix];
6919
18.1M
    if (old_value == NULL && value == NULL) {
6920
0
        PyErr_Format(PyExc_AttributeError,
6921
0
                        "'%.100s' object has no attribute '%U'",
6922
0
                        Py_TYPE(obj)->tp_name, name);
6923
0
        (void)_PyObject_SetAttributeErrorContext(obj, name);
6924
0
        return -1;
6925
0
    }
6926
6927
18.1M
    if (dict) {
6928
0
        PyInterpreterState *interp = _PyInterpreterState_GET();
6929
0
        PyDict_WatchEvent event = (old_value == NULL ? PyDict_EVENT_ADDED :
6930
0
                                   value == NULL ? PyDict_EVENT_DELETED :
6931
0
                                   PyDict_EVENT_MODIFIED);
6932
0
        _PyDict_NotifyEvent(interp, event, dict, name, value);
6933
0
    }
6934
6935
18.1M
    FT_ATOMIC_STORE_PTR_RELEASE(values->values[ix], Py_XNewRef(value));
6936
6937
18.1M
    if (old_value == NULL) {
6938
13.4M
        _PyDictValues_AddToInsertionOrder(values, ix);
6939
13.4M
        if (dict) {
6940
0
            assert(dict->ma_values == values);
6941
0
            STORE_USED(dict, dict->ma_used + 1);
6942
0
        }
6943
13.4M
    }
6944
4.63M
    else {
6945
4.63M
        if (value == NULL) {
6946
205k
            delete_index_from_values(values, ix);
6947
205k
            if (dict) {
6948
0
                assert(dict->ma_values == values);
6949
0
                STORE_USED(dict, dict->ma_used - 1);
6950
0
            }
6951
205k
        }
6952
4.63M
        Py_DECREF(old_value);
6953
4.63M
    }
6954
18.1M
    return 0;
6955
18.1M
}
6956
6957
static inline int
6958
store_instance_attr_dict(PyObject *obj, PyDictObject *dict, PyObject *name, PyObject *value)
6959
25.6M
{
6960
25.6M
    PyDictValues *values = _PyObject_InlineValues(obj);
6961
25.6M
    int res;
6962
25.6M
    Py_BEGIN_CRITICAL_SECTION(dict);
6963
25.6M
    if (dict->ma_values == values) {
6964
0
        res = store_instance_attr_lock_held(obj, values, name, value);
6965
0
    }
6966
25.6M
    else {
6967
25.6M
        res = _PyDict_SetItem_LockHeld(dict, name, value);
6968
25.6M
    }
6969
25.6M
    Py_END_CRITICAL_SECTION();
6970
25.6M
    return res;
6971
25.6M
}
6972
6973
int
6974
_PyObject_StoreInstanceAttribute(PyObject *obj, PyObject *name, PyObject *value)
6975
44.4M
{
6976
44.4M
    PyDictValues *values = _PyObject_InlineValues(obj);
6977
44.4M
    if (!FT_ATOMIC_LOAD_UINT8(values->valid)) {
6978
25.6M
        PyDictObject *dict = _PyObject_GetManagedDict(obj);
6979
25.6M
        if (dict == NULL) {
6980
0
            dict = (PyDictObject *)PyObject_GenericGetDict(obj, NULL);
6981
0
            if (dict == NULL) {
6982
0
                return -1;
6983
0
            }
6984
0
            int res = store_instance_attr_dict(obj, dict, name, value);
6985
0
            Py_DECREF(dict);
6986
0
            return res;
6987
0
        }
6988
25.6M
        return store_instance_attr_dict(obj, dict, name, value);
6989
25.6M
    }
6990
6991
#ifdef Py_GIL_DISABLED
6992
    // We have a valid inline values, at least for now...  There are two potential
6993
    // races with having the values become invalid.  One is the dictionary
6994
    // being detached from the object.  The other is if someone is inserting
6995
    // into the dictionary directly and therefore causing it to resize.
6996
    //
6997
    // If we haven't materialized the dictionary yet we lock on the object, which
6998
    // will also be used to prevent the dictionary from being materialized while
6999
    // we're doing the insertion.  If we race and the dictionary gets created
7000
    // then we'll need to release the object lock and lock the dictionary to
7001
    // prevent resizing.
7002
    PyDictObject *dict = _PyObject_GetManagedDict(obj);
7003
    if (dict == NULL) {
7004
        int res;
7005
        Py_BEGIN_CRITICAL_SECTION(obj);
7006
        dict = _PyObject_GetManagedDict(obj);
7007
7008
        if (dict == NULL) {
7009
            res = store_instance_attr_lock_held(obj, values, name, value);
7010
        }
7011
        Py_END_CRITICAL_SECTION();
7012
7013
        if (dict == NULL) {
7014
            return res;
7015
        }
7016
    }
7017
    return store_instance_attr_dict(obj, dict, name, value);
7018
#else
7019
18.8M
    return store_instance_attr_lock_held(obj, values, name, value);
7020
44.4M
#endif
7021
44.4M
}
7022
7023
/* Sanity check for managed dicts */
7024
#if 0
7025
#define CHECK(val) assert(val); if (!(val)) { return 0; }
7026
7027
int
7028
_PyObject_ManagedDictValidityCheck(PyObject *obj)
7029
{
7030
    PyTypeObject *tp = Py_TYPE(obj);
7031
    CHECK(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
7032
    PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(obj);
7033
    if (_PyManagedDictPointer_IsValues(*managed_dict)) {
7034
        PyDictValues *values = _PyManagedDictPointer_GetValues(*managed_dict);
7035
        int size = ((uint8_t *)values)[-2];
7036
        int count = 0;
7037
        PyDictKeysObject *keys = CACHED_KEYS(tp);
7038
        for (Py_ssize_t i = 0; i < keys->dk_nentries; i++) {
7039
            if (values->values[i] != NULL) {
7040
                count++;
7041
            }
7042
        }
7043
        CHECK(size == count);
7044
    }
7045
    else {
7046
        if (managed_dict->dict != NULL) {
7047
            CHECK(PyDict_Check(managed_dict->dict));
7048
        }
7049
    }
7050
    return 1;
7051
}
7052
#endif
7053
7054
// Attempts to get an instance attribute from the inline values. Returns true
7055
// if successful, or false if the caller needs to lookup in the dictionary.
7056
bool
7057
_PyObject_TryGetInstanceAttribute(PyObject *obj, PyObject *name, PyObject **attr)
7058
157M
{
7059
157M
    assert(PyUnicode_CheckExact(name));
7060
157M
    PyDictValues *values = _PyObject_InlineValues(obj);
7061
157M
    if (!FT_ATOMIC_LOAD_UINT8(values->valid)) {
7062
93.7M
        return false;
7063
93.7M
    }
7064
7065
63.5M
    PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
7066
63.5M
    assert(keys != NULL);
7067
63.5M
    Py_ssize_t ix = _PyDictKeys_StringLookupSplit(keys, name);
7068
63.5M
    if (ix == DKIX_EMPTY) {
7069
23.9M
        *attr = NULL;
7070
23.9M
        return true;
7071
23.9M
    }
7072
7073
#ifdef Py_GIL_DISABLED
7074
    PyObject *value = _Py_atomic_load_ptr_acquire(&values->values[ix]);
7075
    if (value == NULL) {
7076
        if (FT_ATOMIC_LOAD_UINT8(values->valid)) {
7077
            *attr = NULL;
7078
            return true;
7079
        }
7080
    }
7081
    else if (_Py_TryIncrefCompare(&values->values[ix], value)) {
7082
        *attr = value;
7083
        return true;
7084
    }
7085
7086
    PyDictObject *dict = _PyObject_GetManagedDict(obj);
7087
    if (dict == NULL) {
7088
        // No dict, lock the object to prevent one from being
7089
        // materialized...
7090
        bool success = false;
7091
        Py_BEGIN_CRITICAL_SECTION(obj);
7092
7093
        dict = _PyObject_GetManagedDict(obj);
7094
        if (dict == NULL) {
7095
            // Still no dict, we can read from the values
7096
            assert(values->valid);
7097
            value = values->values[ix];
7098
            *attr = _Py_XNewRefWithLock(value);
7099
            success = true;
7100
        }
7101
7102
        Py_END_CRITICAL_SECTION();
7103
7104
        if (success) {
7105
            return true;
7106
        }
7107
    }
7108
7109
    // We have a dictionary, we'll need to lock it to prevent
7110
    // the values from being resized.
7111
    assert(dict != NULL);
7112
7113
    bool success;
7114
    Py_BEGIN_CRITICAL_SECTION(dict);
7115
7116
    if (dict->ma_values == values && FT_ATOMIC_LOAD_UINT8(values->valid)) {
7117
        value = _Py_atomic_load_ptr_relaxed(&values->values[ix]);
7118
        *attr = _Py_XNewRefWithLock(value);
7119
        success = true;
7120
    } else {
7121
        // Caller needs to lookup from the dictionary
7122
        success = false;
7123
    }
7124
7125
    Py_END_CRITICAL_SECTION();
7126
7127
    return success;
7128
#else
7129
39.5M
    PyObject *value = values->values[ix];
7130
39.5M
    *attr = Py_XNewRef(value);
7131
39.5M
    return true;
7132
63.5M
#endif
7133
63.5M
}
7134
7135
int
7136
_PyObject_IsInstanceDictEmpty(PyObject *obj)
7137
0
{
7138
0
    PyTypeObject *tp = Py_TYPE(obj);
7139
0
    if (tp->tp_dictoffset == 0) {
7140
0
        return 1;
7141
0
    }
7142
0
    PyDictObject *dict;
7143
0
    if (tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) {
7144
0
        PyDictValues *values = _PyObject_InlineValues(obj);
7145
0
        if (FT_ATOMIC_LOAD_UINT8(values->valid)) {
7146
0
            PyDictKeysObject *keys = CACHED_KEYS(tp);
7147
0
            for (Py_ssize_t i = 0; i < keys->dk_nentries; i++) {
7148
0
                if (FT_ATOMIC_LOAD_PTR_RELAXED(values->values[i]) != NULL) {
7149
0
                    return 0;
7150
0
                }
7151
0
            }
7152
0
            return 1;
7153
0
        }
7154
0
        dict = _PyObject_GetManagedDict(obj);
7155
0
    }
7156
0
    else if (tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) {
7157
0
        dict = _PyObject_GetManagedDict(obj);
7158
0
    }
7159
0
    else {
7160
0
        PyObject **dictptr = _PyObject_ComputedDictPointer(obj);
7161
0
        dict = (PyDictObject *)*dictptr;
7162
0
    }
7163
0
    if (dict == NULL) {
7164
0
        return 1;
7165
0
    }
7166
0
    return FT_ATOMIC_LOAD_SSIZE_RELAXED(((PyDictObject *)dict)->ma_used) == 0;
7167
0
}
7168
7169
int
7170
PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg)
7171
25.5M
{
7172
25.5M
    PyTypeObject *tp = Py_TYPE(obj);
7173
25.5M
    if((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {
7174
0
        return 0;
7175
0
    }
7176
25.5M
    if (tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) {
7177
25.0M
        PyDictValues *values = _PyObject_InlineValues(obj);
7178
25.0M
        if (values->valid) {
7179
183M
            for (Py_ssize_t i = 0; i < values->capacity; i++) {
7180
158M
                Py_VISIT(values->values[i]);
7181
158M
            }
7182
24.8M
            return 0;
7183
24.8M
        }
7184
25.0M
    }
7185
665k
    Py_VISIT(_PyObject_ManagedDictPointer(obj)->dict);
7186
665k
    return 0;
7187
665k
}
7188
7189
static void
7190
clear_inline_values(PyDictValues *values)
7191
32.9M
{
7192
32.9M
    if (values->valid) {
7193
32.8M
        FT_ATOMIC_STORE_UINT8(values->valid, 0);
7194
205M
        for (Py_ssize_t i = 0; i < values->capacity; i++) {
7195
172M
            Py_CLEAR(values->values[i]);
7196
172M
        }
7197
32.8M
    }
7198
32.9M
}
7199
7200
static void
7201
set_dict_inline_values(PyObject *obj, PyDictObject *new_dict)
7202
0
{
7203
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(obj);
7204
7205
0
    PyDictValues *values = _PyObject_InlineValues(obj);
7206
7207
0
    Py_XINCREF(new_dict);
7208
0
    FT_ATOMIC_STORE_PTR(_PyObject_ManagedDictPointer(obj)->dict, new_dict);
7209
7210
0
    clear_inline_values(values);
7211
0
}
7212
7213
#ifdef Py_GIL_DISABLED
7214
7215
// Trys and sets the dictionary for an object in the easy case when our current
7216
// dictionary is either completely not materialized or is a dictionary which
7217
// does not point at the inline values.
7218
static bool
7219
try_set_dict_inline_only_or_other_dict(PyObject *obj, PyObject *new_dict, PyDictObject **cur_dict)
7220
{
7221
    bool replaced = false;
7222
    Py_BEGIN_CRITICAL_SECTION(obj);
7223
7224
    PyDictObject *dict = *cur_dict = _PyObject_GetManagedDict(obj);
7225
    if (dict == NULL) {
7226
        // We only have inline values, we can just completely replace them.
7227
        set_dict_inline_values(obj, (PyDictObject *)new_dict);
7228
        replaced = true;
7229
        goto exit_lock;
7230
    }
7231
7232
    if (FT_ATOMIC_LOAD_PTR_RELAXED(dict->ma_values) != _PyObject_InlineValues(obj)) {
7233
        // We have a materialized dict which doesn't point at the inline values,
7234
        // We get to simply swap dictionaries and free the old dictionary.
7235
        FT_ATOMIC_STORE_PTR(_PyObject_ManagedDictPointer(obj)->dict,
7236
                            (PyDictObject *)Py_XNewRef(new_dict));
7237
        replaced = true;
7238
        goto exit_lock;
7239
    }
7240
    else {
7241
        // We have inline values, we need to lock the dict and the object
7242
        // at the same time to safely dematerialize them. To do that while releasing
7243
        // the object lock we need a strong reference to the current dictionary.
7244
        Py_INCREF(dict);
7245
    }
7246
exit_lock:
7247
    Py_END_CRITICAL_SECTION();
7248
    return replaced;
7249
}
7250
7251
// Replaces a dictionary that is probably the dictionary which has been
7252
// materialized and points at the inline values. We could have raced
7253
// and replaced it with another dictionary though.
7254
static int
7255
replace_dict_probably_inline_materialized(PyObject *obj, PyDictObject *inline_dict,
7256
                                          PyDictObject *cur_dict, PyObject *new_dict)
7257
{
7258
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(obj);
7259
7260
    if (cur_dict == inline_dict) {
7261
        assert(FT_ATOMIC_LOAD_PTR_RELAXED(inline_dict->ma_values) == _PyObject_InlineValues(obj));
7262
7263
        int err = _PyDict_DetachFromObject(inline_dict, obj);
7264
        if (err != 0) {
7265
            assert(new_dict == NULL);
7266
            return err;
7267
        }
7268
    }
7269
7270
    FT_ATOMIC_STORE_PTR(_PyObject_ManagedDictPointer(obj)->dict,
7271
                        (PyDictObject *)Py_XNewRef(new_dict));
7272
    return 0;
7273
}
7274
7275
#endif
7276
7277
static void
7278
decref_maybe_delay(PyObject *obj, bool delay)
7279
0
{
7280
0
    if (delay) {
7281
0
        _PyObject_XDecRefDelayed(obj);
7282
0
    }
7283
0
    else {
7284
0
        Py_XDECREF(obj);
7285
0
    }
7286
0
}
7287
7288
int
7289
_PyObject_SetManagedDict(PyObject *obj, PyObject *new_dict)
7290
0
{
7291
0
    assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
7292
#ifndef NDEBUG
7293
    Py_BEGIN_CRITICAL_SECTION(obj);
7294
    assert(_PyObject_InlineValuesConsistencyCheck(obj));
7295
    Py_END_CRITICAL_SECTION();
7296
#endif
7297
0
    int err = 0;
7298
0
    PyTypeObject *tp = Py_TYPE(obj);
7299
0
    if (tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) {
7300
#ifdef Py_GIL_DISABLED
7301
        PyDictObject *prev_dict;
7302
        if (!try_set_dict_inline_only_or_other_dict(obj, new_dict, &prev_dict)) {
7303
            // We had a materialized dictionary which pointed at the inline
7304
            // values. We need to lock both the object and the dict at the
7305
            // same time to safely replace it. We can't merely lock the dictionary
7306
            // while the object is locked because it could suspend the object lock.
7307
            PyDictObject *cur_dict;
7308
7309
            assert(prev_dict != NULL);
7310
            Py_BEGIN_CRITICAL_SECTION2(obj, prev_dict);
7311
7312
            // We could have had another thread race in between the call to
7313
            // try_set_dict_inline_only_or_other_dict where we locked the object
7314
            // and when we unlocked and re-locked the dictionary.
7315
            cur_dict = _PyObject_GetManagedDict(obj);
7316
7317
            err = replace_dict_probably_inline_materialized(obj, prev_dict,
7318
                                                            cur_dict, new_dict);
7319
7320
            Py_END_CRITICAL_SECTION2();
7321
7322
            // Decref for the dictionary we incref'd in try_set_dict_inline_only_or_other_dict
7323
            // while the object was locked
7324
            decref_maybe_delay((PyObject *)prev_dict, prev_dict != cur_dict);
7325
            if (err != 0) {
7326
                return err;
7327
            }
7328
7329
            prev_dict = cur_dict;
7330
        }
7331
7332
        if (prev_dict != NULL) {
7333
            // decref for the dictionary that we replaced
7334
            decref_maybe_delay((PyObject *)prev_dict, true);
7335
        }
7336
7337
        return 0;
7338
#else
7339
0
        PyDictObject *dict = _PyObject_GetManagedDict(obj);
7340
0
        if (dict == NULL) {
7341
0
            set_dict_inline_values(obj, (PyDictObject *)new_dict);
7342
0
            return 0;
7343
0
        }
7344
0
        if (_PyDict_DetachFromObject(dict, obj) == 0) {
7345
0
            _PyObject_ManagedDictPointer(obj)->dict = (PyDictObject *)Py_XNewRef(new_dict);
7346
0
            Py_DECREF(dict);
7347
0
            return 0;
7348
0
        }
7349
0
        assert(new_dict == NULL);
7350
0
        return -1;
7351
0
#endif
7352
0
    }
7353
0
    else {
7354
0
        PyDictObject *dict;
7355
7356
0
        Py_BEGIN_CRITICAL_SECTION(obj);
7357
7358
0
        dict = _PyObject_ManagedDictPointer(obj)->dict;
7359
7360
0
        FT_ATOMIC_STORE_PTR(_PyObject_ManagedDictPointer(obj)->dict,
7361
0
                            (PyDictObject *)Py_XNewRef(new_dict));
7362
7363
0
        Py_END_CRITICAL_SECTION();
7364
0
        decref_maybe_delay((PyObject *)dict, true);
7365
0
    }
7366
0
    assert(_PyObject_InlineValuesConsistencyCheck(obj));
7367
0
    return err;
7368
0
}
7369
7370
static int
7371
detach_dict_from_object(PyDictObject *mp, PyObject *obj)
7372
0
{
7373
0
    assert(_PyObject_ManagedDictPointer(obj)->dict == mp);
7374
0
    assert(_PyObject_InlineValuesConsistencyCheck(obj));
7375
7376
0
    if (FT_ATOMIC_LOAD_PTR_RELAXED(mp->ma_values) != _PyObject_InlineValues(obj)) {
7377
0
        return 0;
7378
0
    }
7379
7380
    // We could be called with an unlocked dict when the caller knows the
7381
    // values are already detached, so we assert after inline values check.
7382
0
    ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(mp);
7383
0
    assert(mp->ma_values->embedded == 1);
7384
0
    assert(mp->ma_values->valid == 1);
7385
0
    assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_INLINE_VALUES);
7386
7387
0
    PyDictValues *values = copy_values(mp->ma_values);
7388
7389
0
    if (values == NULL) {
7390
0
        PyErr_NoMemory();
7391
0
        return -1;
7392
0
    }
7393
0
    mp->ma_values = values;
7394
7395
0
    invalidate_and_clear_inline_values(_PyObject_InlineValues(obj));
7396
7397
0
    assert(_PyObject_InlineValuesConsistencyCheck(obj));
7398
0
    ASSERT_CONSISTENT(mp);
7399
0
    return 0;
7400
0
}
7401
7402
7403
void
7404
PyObject_ClearManagedDict(PyObject *obj)
7405
33.6M
{
7406
    // This is called when the object is being freed or cleared
7407
    // by the GC and therefore known to have no references.
7408
33.6M
    if (Py_TYPE(obj)->tp_flags & Py_TPFLAGS_INLINE_VALUES) {
7409
33.6M
        PyDictObject *dict = _PyObject_GetManagedDict(obj);
7410
33.6M
        if (dict == NULL) {
7411
            // We have no materialized dictionary and inline values
7412
            // that just need to be cleared.
7413
            // No dict to clear, we're done
7414
32.9M
            clear_inline_values(_PyObject_InlineValues(obj));
7415
32.9M
            return;
7416
32.9M
        }
7417
694k
        else if (FT_ATOMIC_LOAD_PTR_RELAXED(dict->ma_values) ==
7418
694k
                    _PyObject_InlineValues(obj)) {
7419
            // We have a materialized object which points at the inline
7420
            // values. We need to materialize the keys. Nothing can modify
7421
            // this object, but we need to lock the dictionary.
7422
0
            int err;
7423
0
            Py_BEGIN_CRITICAL_SECTION(dict);
7424
0
            err = detach_dict_from_object(dict, obj);
7425
0
            Py_END_CRITICAL_SECTION();
7426
7427
0
            if (err) {
7428
                /* Must be out of memory */
7429
0
                assert(PyErr_Occurred() == PyExc_MemoryError);
7430
0
                PyErr_FormatUnraisable("Exception ignored while "
7431
0
                                       "clearing an object managed dict");
7432
                /* Clear the dict */
7433
0
                Py_BEGIN_CRITICAL_SECTION(dict);
7434
0
                PyDictKeysObject *oldkeys = dict->ma_keys;
7435
0
                set_keys(dict, Py_EMPTY_KEYS);
7436
0
                dict->ma_values = NULL;
7437
0
                dictkeys_decref(oldkeys, IS_DICT_SHARED(dict));
7438
0
                STORE_USED(dict, 0);
7439
0
                clear_inline_values(_PyObject_InlineValues(obj));
7440
0
                Py_END_CRITICAL_SECTION();
7441
0
            }
7442
0
        }
7443
33.6M
    }
7444
694k
    Py_CLEAR(_PyObject_ManagedDictPointer(obj)->dict);
7445
694k
}
7446
7447
int
7448
_PyDict_DetachFromObject(PyDictObject *mp, PyObject *obj)
7449
0
{
7450
0
    ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(obj);
7451
7452
0
    return detach_dict_from_object(mp, obj);
7453
0
}
7454
7455
static inline PyObject *
7456
ensure_managed_dict(PyObject *obj)
7457
5.62k
{
7458
5.62k
    PyDictObject *dict = _PyObject_GetManagedDict(obj);
7459
5.62k
    if (dict == NULL) {
7460
5.60k
        PyTypeObject *tp = Py_TYPE(obj);
7461
5.60k
        if ((tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) &&
7462
5.60k
            FT_ATOMIC_LOAD_UINT8(_PyObject_InlineValues(obj)->valid)) {
7463
5.60k
            dict = _PyObject_MaterializeManagedDict(obj);
7464
5.60k
        }
7465
0
        else {
7466
#ifdef Py_GIL_DISABLED
7467
            // Check again that we're not racing with someone else creating the dict
7468
            Py_BEGIN_CRITICAL_SECTION(obj);
7469
            dict = _PyObject_GetManagedDict(obj);
7470
            if (dict != NULL) {
7471
                goto done;
7472
            }
7473
#endif
7474
0
            dict = (PyDictObject *)new_dict_with_shared_keys(CACHED_KEYS(tp));
7475
0
            FT_ATOMIC_STORE_PTR_RELEASE(_PyObject_ManagedDictPointer(obj)->dict,
7476
0
                                        (PyDictObject *)dict);
7477
7478
#ifdef Py_GIL_DISABLED
7479
done:
7480
            Py_END_CRITICAL_SECTION();
7481
#endif
7482
0
        }
7483
5.60k
    }
7484
5.62k
    return (PyObject *)dict;
7485
5.62k
}
7486
7487
static inline PyObject *
7488
ensure_nonmanaged_dict(PyObject *obj, PyObject **dictptr)
7489
26.9M
{
7490
26.9M
    PyDictKeysObject *cached;
7491
7492
26.9M
    PyObject *dict = FT_ATOMIC_LOAD_PTR_ACQUIRE(*dictptr);
7493
26.9M
    if (dict == NULL) {
7494
#ifdef Py_GIL_DISABLED
7495
        Py_BEGIN_CRITICAL_SECTION(obj);
7496
        dict = *dictptr;
7497
        if (dict != NULL) {
7498
            goto done;
7499
        }
7500
#endif
7501
12.1M
        PyTypeObject *tp = Py_TYPE(obj);
7502
12.1M
        if (_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE) && (cached = CACHED_KEYS(tp))) {
7503
9.07k
            assert(!_PyType_HasFeature(tp, Py_TPFLAGS_INLINE_VALUES));
7504
9.07k
            dict = new_dict_with_shared_keys(cached);
7505
9.07k
        }
7506
12.0M
        else {
7507
12.0M
            dict = PyDict_New();
7508
12.0M
        }
7509
12.1M
        FT_ATOMIC_STORE_PTR_RELEASE(*dictptr, dict);
7510
#ifdef Py_GIL_DISABLED
7511
done:
7512
        Py_END_CRITICAL_SECTION();
7513
#endif
7514
12.1M
    }
7515
26.9M
    return dict;
7516
26.9M
}
7517
7518
PyObject *
7519
PyObject_GenericGetDict(PyObject *obj, void *context)
7520
6.55k
{
7521
6.55k
    PyTypeObject *tp = Py_TYPE(obj);
7522
6.55k
    if (_PyType_HasFeature(tp, Py_TPFLAGS_MANAGED_DICT)) {
7523
5.62k
        return Py_XNewRef(ensure_managed_dict(obj));
7524
5.62k
    }
7525
922
    else {
7526
922
        PyObject **dictptr = _PyObject_ComputedDictPointer(obj);
7527
922
        if (dictptr == NULL) {
7528
0
            PyErr_SetString(PyExc_AttributeError,
7529
0
                            "This object has no __dict__");
7530
0
            return NULL;
7531
0
        }
7532
7533
922
        return Py_XNewRef(ensure_nonmanaged_dict(obj, dictptr));
7534
922
    }
7535
6.55k
}
7536
7537
int
7538
_PyObjectDict_SetItem(PyTypeObject *tp, PyObject *obj, PyObject **dictptr,
7539
                      PyObject *key, PyObject *value)
7540
26.9M
{
7541
26.9M
    PyObject *dict;
7542
26.9M
    int res;
7543
7544
26.9M
    assert(dictptr != NULL);
7545
26.9M
    dict = ensure_nonmanaged_dict(obj, dictptr);
7546
26.9M
    if (dict == NULL) {
7547
0
        return -1;
7548
0
    }
7549
7550
26.9M
    Py_BEGIN_CRITICAL_SECTION(dict);
7551
26.9M
    res = _PyDict_SetItem_LockHeld((PyDictObject *)dict, key, value);
7552
26.9M
    ASSERT_CONSISTENT(dict);
7553
26.9M
    Py_END_CRITICAL_SECTION();
7554
26.9M
    return res;
7555
26.9M
}
7556
7557
void
7558
_PyDictKeys_DecRef(PyDictKeysObject *keys)
7559
282k
{
7560
282k
    dictkeys_decref(keys, false);
7561
282k
}
7562
7563
static inline uint32_t
7564
get_next_dict_keys_version(PyInterpreterState *interp)
7565
13.4k
{
7566
#ifdef Py_GIL_DISABLED
7567
    uint32_t v;
7568
    do {
7569
        v = _Py_atomic_load_uint32_relaxed(
7570
            &interp->dict_state.next_keys_version);
7571
        if (v == 0) {
7572
            return 0;
7573
        }
7574
    } while (!_Py_atomic_compare_exchange_uint32(
7575
        &interp->dict_state.next_keys_version, &v, v + 1));
7576
#else
7577
13.4k
    if (interp->dict_state.next_keys_version == 0) {
7578
0
        return 0;
7579
0
    }
7580
13.4k
    uint32_t v = interp->dict_state.next_keys_version++;
7581
13.4k
#endif
7582
13.4k
    return v;
7583
13.4k
}
7584
7585
// In free-threaded builds the caller must ensure that the keys object is not
7586
// being mutated concurrently by another thread.
7587
uint32_t
7588
_PyDictKeys_GetVersionForCurrentState(PyInterpreterState *interp,
7589
                                      PyDictKeysObject *dictkeys)
7590
2.40M
{
7591
2.40M
    uint32_t dk_version = FT_ATOMIC_LOAD_UINT32_RELAXED(dictkeys->dk_version);
7592
2.40M
    if (dk_version != 0) {
7593
2.39M
        return dk_version;
7594
2.39M
    }
7595
13.4k
    dk_version = get_next_dict_keys_version(interp);
7596
13.4k
    FT_ATOMIC_STORE_UINT32_RELAXED(dictkeys->dk_version, dk_version);
7597
13.4k
    return dk_version;
7598
2.40M
}
7599
7600
uint32_t
7601
_PyDict_GetKeysVersionForCurrentState(PyInterpreterState *interp,
7602
                                      PyDictObject *dict)
7603
38.0k
{
7604
38.0k
    ASSERT_DICT_LOCKED((PyObject *) dict);
7605
38.0k
    uint32_t dk_version =
7606
38.0k
        _PyDictKeys_GetVersionForCurrentState(interp, dict->ma_keys);
7607
38.0k
    ensure_shared_on_keys_version_assignment(dict);
7608
38.0k
    return dk_version;
7609
38.0k
}
7610
7611
static inline int
7612
validate_watcher_id(PyInterpreterState *interp, int watcher_id)
7613
28
{
7614
28
    if (watcher_id < 0 || watcher_id >= DICT_MAX_WATCHERS) {
7615
0
        PyErr_Format(PyExc_ValueError, "Invalid dict watcher ID %d", watcher_id);
7616
0
        return -1;
7617
0
    }
7618
28
    if (!interp->dict_state.watchers[watcher_id]) {
7619
0
        PyErr_Format(PyExc_ValueError, "No dict watcher set for ID %d", watcher_id);
7620
0
        return -1;
7621
0
    }
7622
28
    return 0;
7623
28
}
7624
7625
int
7626
PyDict_Watch(int watcher_id, PyObject* dict)
7627
28
{
7628
28
    if (!PyDict_Check(dict)) {
7629
0
        PyErr_SetString(PyExc_ValueError, "Cannot watch non-dictionary");
7630
0
        return -1;
7631
0
    }
7632
28
    PyInterpreterState *interp = _PyInterpreterState_GET();
7633
28
    if (validate_watcher_id(interp, watcher_id)) {
7634
0
        return -1;
7635
0
    }
7636
28
    ((PyDictObject*)dict)->_ma_watcher_tag |= (1LL << watcher_id);
7637
28
    return 0;
7638
28
}
7639
7640
int
7641
PyDict_Unwatch(int watcher_id, PyObject* dict)
7642
0
{
7643
0
    if (!PyDict_Check(dict)) {
7644
0
        PyErr_SetString(PyExc_ValueError, "Cannot watch non-dictionary");
7645
0
        return -1;
7646
0
    }
7647
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7648
0
    if (validate_watcher_id(interp, watcher_id)) {
7649
0
        return -1;
7650
0
    }
7651
0
    ((PyDictObject*)dict)->_ma_watcher_tag &= ~(1LL << watcher_id);
7652
0
    return 0;
7653
0
}
7654
7655
int
7656
PyDict_AddWatcher(PyDict_WatchCallback callback)
7657
0
{
7658
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7659
7660
    /* Start at 2, as 0 and 1 are reserved for CPython */
7661
0
    for (int i = 2; i < DICT_MAX_WATCHERS; i++) {
7662
0
        if (!interp->dict_state.watchers[i]) {
7663
0
            interp->dict_state.watchers[i] = callback;
7664
0
            return i;
7665
0
        }
7666
0
    }
7667
7668
0
    PyErr_SetString(PyExc_RuntimeError, "no more dict watcher IDs available");
7669
0
    return -1;
7670
0
}
7671
7672
int
7673
PyDict_ClearWatcher(int watcher_id)
7674
0
{
7675
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7676
0
    if (validate_watcher_id(interp, watcher_id)) {
7677
0
        return -1;
7678
0
    }
7679
0
    interp->dict_state.watchers[watcher_id] = NULL;
7680
0
    return 0;
7681
0
}
7682
7683
static const char *
7684
0
dict_event_name(PyDict_WatchEvent event) {
7685
0
    switch (event) {
7686
0
        #define CASE(op)                \
7687
0
        case PyDict_EVENT_##op:         \
7688
0
            return "PyDict_EVENT_" #op;
7689
0
        PY_FOREACH_DICT_EVENT(CASE)
7690
0
        #undef CASE
7691
0
    }
7692
0
    Py_UNREACHABLE();
7693
0
}
7694
7695
void
7696
_PyDict_SendEvent(int watcher_bits,
7697
                  PyDict_WatchEvent event,
7698
                  PyDictObject *mp,
7699
                  PyObject *key,
7700
                  PyObject *value)
7701
0
{
7702
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
7703
0
    for (int i = 0; i < DICT_MAX_WATCHERS; i++) {
7704
0
        if (watcher_bits & 1) {
7705
0
            PyDict_WatchCallback cb = interp->dict_state.watchers[i];
7706
0
            if (cb && (cb(event, (PyObject*)mp, key, value) < 0)) {
7707
                // We don't want to resurrect the dict by potentially having an
7708
                // unraisablehook keep a reference to it, so we don't pass the
7709
                // dict as context, just an informative string message.  Dict
7710
                // repr can call arbitrary code, so we invent a simpler version.
7711
0
                PyErr_FormatUnraisable(
7712
0
                    "Exception ignored in %s watcher callback for <dict at %p>",
7713
0
                    dict_event_name(event), mp);
7714
0
            }
7715
0
        }
7716
0
        watcher_bits >>= 1;
7717
0
    }
7718
0
}
7719
7720
#ifndef NDEBUG
7721
static int
7722
_PyObject_InlineValuesConsistencyCheck(PyObject *obj)
7723
{
7724
    if ((Py_TYPE(obj)->tp_flags & Py_TPFLAGS_INLINE_VALUES) == 0) {
7725
        return 1;
7726
    }
7727
    assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
7728
    PyDictObject *dict = _PyObject_GetManagedDict(obj);
7729
    if (dict == NULL) {
7730
        return 1;
7731
    }
7732
    if (dict->ma_values == _PyObject_InlineValues(obj) ||
7733
        _PyObject_InlineValues(obj)->valid == 0) {
7734
        return 1;
7735
    }
7736
    assert(0);
7737
    return 0;
7738
}
7739
#endif