Coverage Report

Created: 2026-10-31 06:21

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