Coverage Report

Created: 2026-04-20 06:11

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