Coverage Report

Created: 2026-07-14 06:16

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