Coverage Report

Created: 2026-05-16 06:46

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