Coverage Report

Created: 2026-04-12 06:54

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
251M
#define PyDict_LOG_MINSIZE 3
116
42.7M
#define PyDict_MINSIZE 8
117
118
#include "Python.h"
119
#include "pycore_bitutils.h"      // _Py_bit_length
120
#include "pycore_call.h"          // _PyObject_CallNoArgs()
121
#include "pycore_ceval.h"         // _PyEval_GetBuiltin()
122
#include "pycore_code.h"          // stats
123
#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION, Py_END_CRITICAL_SECTION
124
#include "pycore_dict.h"          // export _PyDict_SizeOf()
125
#include "pycore_freelist.h"      // _PyFreeListState_GET()
126
#include "pycore_gc.h"            // _PyObject_GC_IS_TRACKED()
127
#include "pycore_object.h"        // _PyObject_GC_TRACK(), _PyDebugAllocatorStats()
128
#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_LOAD_SSIZE_RELAXED
129
#include "pycore_pyerrors.h"      // _PyErr_GetRaisedException()
130
#include "pycore_pystate.h"       // _PyThreadState_GET()
131
#include "pycore_setobject.h"     // _PySet_NextEntry()
132
#include "pycore_tuple.h"         // _PyTuple_Recycle()
133
#include "pycore_unicodeobject.h" // _PyUnicode_InternImmortal()
134
135
#include "stringlib/eq.h"                // unicode_eq()
136
#include <stdbool.h>
137
138
// Forward declarations
139
static PyObject* frozendict_new(PyTypeObject *type, PyObject *args,
140
                                PyObject *kwds);
141
static PyObject* dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
142
static int dict_merge(PyObject *a, PyObject *b, int override, PyObject **dupkey);
143
static int dict_contains(PyObject *op, PyObject *key);
144
static int dict_merge_from_seq2(PyObject *d, PyObject *seq2, int override);
145
146
147
/*[clinic input]
148
class dict "PyDictObject *" "&PyDict_Type"
149
class frozendict "PyFrozenDictObject *" "&PyFrozenDict_Type"
150
[clinic start generated code]*/
151
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=5dfa93bac68e7c54]*/
152
153
154
/*
155
To ensure the lookup algorithm terminates, there must be at least one Unused
156
slot (NULL key) in the table.
157
To avoid slowing down lookups on a near-full table, we resize the table when
158
it's USABLE_FRACTION (currently two-thirds) full.
159
*/
160
161
#ifdef Py_GIL_DISABLED
162
163
static inline void
164
ASSERT_DICT_LOCKED(PyObject *op)
165
{
166
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
167
}
168
#define ASSERT_DICT_LOCKED(op) ASSERT_DICT_LOCKED(_Py_CAST(PyObject*, op))
169
#define ASSERT_WORLD_STOPPED_OR_DICT_LOCKED(op)                         \
170
    if (!_PyInterpreterState_GET()->stoptheworld.world_stopped) {       \
171
        ASSERT_DICT_LOCKED(op);                                         \
172
    }
173
#define ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(op)                         \
174
    if (!_PyInterpreterState_GET()->stoptheworld.world_stopped) {      \
175
        _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);                 \
176
    }
177
178
#define IS_DICT_SHARED(mp) _PyObject_GC_IS_SHARED(mp)
179
#define SET_DICT_SHARED(mp) _PyObject_GC_SET_SHARED(mp)
180
#define LOAD_INDEX(keys, size, idx) _Py_atomic_load_int##size##_relaxed(&((const int##size##_t*)keys->dk_indices)[idx]);
181
#define STORE_INDEX(keys, size, idx, value) _Py_atomic_store_int##size##_relaxed(&((int##size##_t*)keys->dk_indices)[idx], (int##size##_t)value);
182
#define ASSERT_OWNED_OR_SHARED(mp) \
183
    assert(_Py_IsOwnedByCurrentThread((PyObject *)mp) || IS_DICT_SHARED(mp));
184
185
#define LOCK_KEYS_IF_SPLIT(keys, kind) \
186
        if (kind == DICT_KEYS_SPLIT) { \
187
            LOCK_KEYS(keys);           \
188
        }
189
190
#define UNLOCK_KEYS_IF_SPLIT(keys, kind) \
191
        if (kind == DICT_KEYS_SPLIT) {   \
192
            UNLOCK_KEYS(keys);           \
193
        }
194
195
static inline Py_ssize_t
196
load_keys_nentries(PyDictObject *mp)
197
{
198
    PyDictKeysObject *keys = _Py_atomic_load_ptr(&mp->ma_keys);
199
    return _Py_atomic_load_ssize(&keys->dk_nentries);
200
}
201
202
static inline void
203
set_keys(PyDictObject *mp, PyDictKeysObject *keys)
204
{
205
    ASSERT_OWNED_OR_SHARED(mp);
206
    _Py_atomic_store_ptr_release(&mp->ma_keys, keys);
207
}
208
209
static inline void
210
set_values(PyDictObject *mp, PyDictValues *values)
211
{
212
    ASSERT_OWNED_OR_SHARED(mp);
213
    _Py_atomic_store_ptr_release(&mp->ma_values, values);
214
}
215
216
#define LOCK_KEYS(keys) PyMutex_LockFlags(&keys->dk_mutex, _Py_LOCK_DONT_DETACH)
217
#define UNLOCK_KEYS(keys) PyMutex_Unlock(&keys->dk_mutex)
218
219
#define ASSERT_KEYS_LOCKED(keys) assert(PyMutex_IsLocked(&keys->dk_mutex))
220
#define LOAD_SHARED_KEY(key) _Py_atomic_load_ptr_acquire(&key)
221
#define STORE_SHARED_KEY(key, value) _Py_atomic_store_ptr_release(&key, value)
222
// Inc refs the keys object, giving the previous value
223
#define INCREF_KEYS(dk)  _Py_atomic_add_ssize(&dk->dk_refcnt, 1)
224
// Dec refs the keys object, giving the previous value
225
#define DECREF_KEYS(dk)  _Py_atomic_add_ssize(&dk->dk_refcnt, -1)
226
#define LOAD_KEYS_NENTRIES(keys) _Py_atomic_load_ssize_relaxed(&keys->dk_nentries)
227
228
#define INCREF_KEYS_FT(dk) dictkeys_incref(dk)
229
#define DECREF_KEYS_FT(dk, shared) dictkeys_decref(dk, shared)
230
231
static inline void split_keys_entry_added(PyDictKeysObject *keys)
232
{
233
    ASSERT_KEYS_LOCKED(keys);
234
235
    // We increase before we decrease so we never get too small of a value
236
    // when we're racing with reads
237
    _Py_atomic_store_ssize_relaxed(&keys->dk_nentries, keys->dk_nentries + 1);
238
    _Py_atomic_store_ssize_release(&keys->dk_usable, keys->dk_usable - 1);
239
}
240
241
#else /* Py_GIL_DISABLED */
242
243
#define ASSERT_DICT_LOCKED(op)
244
#define ASSERT_WORLD_STOPPED_OR_DICT_LOCKED(op)
245
#define ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(op)
246
#define LOCK_KEYS(keys)
247
#define UNLOCK_KEYS(keys)
248
#define ASSERT_KEYS_LOCKED(keys)
249
2
#define LOAD_SHARED_KEY(key) key
250
1.37M
#define STORE_SHARED_KEY(key, value) key = value
251
611k
#define INCREF_KEYS(dk)  dk->dk_refcnt++
252
48.2M
#define DECREF_KEYS(dk)  dk->dk_refcnt--
253
11.5k
#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.82M
#define IS_DICT_SHARED(mp) (false)
259
#define SET_DICT_SHARED(mp)
260
2.91G
#define LOAD_INDEX(keys, size, idx) ((const int##size##_t*)(keys->dk_indices))[idx]
261
222M
#define STORE_INDEX(keys, size, idx, value) ((int##size##_t*)(keys->dk_indices))[idx] = (int##size##_t)value
262
263
static inline void split_keys_entry_added(PyDictKeysObject *keys)
264
1.37M
{
265
1.37M
    keys->dk_usable--;
266
1.37M
    keys->dk_nentries++;
267
1.37M
}
268
269
static inline void
270
set_keys(PyDictObject *mp, PyDictKeysObject *keys)
271
9.26M
{
272
9.26M
    mp->ma_keys = keys;
273
9.26M
}
274
275
static inline void
276
set_values(PyDictObject *mp, PyDictValues *values)
277
604k
{
278
604k
    mp->ma_values = values;
279
604k
}
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
482M
    (assert(PyAnyDict_Check(op)), _Py_CAST(PyDictObject*, op))
312
313
13.5M
#define GET_USED(ep) FT_ATOMIC_LOAD_SSIZE_RELAXED((ep)->ma_used)
314
315
93.7M
#define STORE_KEY(ep, key) FT_ATOMIC_STORE_PTR_RELEASE((ep)->me_key, key)
316
158M
#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
61.3M
#define STORE_HASH(ep, hash) FT_ATOMIC_STORE_SSIZE_RELAXED((ep)->me_hash, hash)
319
95.9M
#define STORE_KEYS_USABLE(keys, usable) FT_ATOMIC_STORE_SSIZE_RELAXED(keys->dk_usable, usable)
320
96.2M
#define STORE_KEYS_NENTRIES(keys, nentries) FT_ATOMIC_STORE_SSIZE_RELAXED(keys->dk_nentries, nentries)
321
140M
#define STORE_USED(mp, used) FT_ATOMIC_STORE_SSIZE_RELAXED(mp->ma_used, used)
322
323
556M
#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
612M
{
437
612M
    return PyUnstable_Unicode_GET_CACHED_HASH(o);
438
612M
}
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.27G
#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
611k
{
468
611k
    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
611k
    INCREF_KEYS(dk);
476
611k
}
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.6M
        assert(FT_ATOMIC_LOAD_SSIZE_RELAXED(dk->dk_refcnt) == _Py_DICT_IMMORTAL_INITIAL_REFCNT);
483
74.6M
        return;
484
74.6M
    }
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.2M
            PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dk);
492
43.2M
            Py_ssize_t i, n;
493
119M
            for (i = 0, n = dk->dk_nentries; i < n; i++) {
494
75.8M
                Py_XDECREF(entries[i].me_key);
495
75.8M
                Py_XDECREF(entries[i].me_value);
496
75.8M
            }
497
43.2M
        }
498
4.37M
        else {
499
4.37M
            PyDictKeyEntry *entries = DK_ENTRIES(dk);
500
4.37M
            Py_ssize_t i, n;
501
66.1M
            for (i = 0, n = dk->dk_nentries; i < n; i++) {
502
61.7M
                Py_XDECREF(entries[i].me_key);
503
61.7M
                Py_XDECREF(entries[i].me_value);
504
61.7M
            }
505
4.37M
        }
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.91G
{
514
2.91G
    int log2size = DK_LOG_SIZE(keys);
515
2.91G
    Py_ssize_t ix;
516
517
2.91G
    if (log2size < 8) {
518
2.73G
        ix = LOAD_INDEX(keys, 8, i);
519
2.73G
    }
520
173M
    else if (log2size < 16) {
521
158M
        ix = LOAD_INDEX(keys, 16, i);
522
158M
    }
523
15.6M
#if SIZEOF_VOID_P > 4
524
15.6M
    else if (log2size >= 32) {
525
0
        ix = LOAD_INDEX(keys, 64, i);
526
0
    }
527
15.6M
#endif
528
15.6M
    else {
529
15.6M
        ix = LOAD_INDEX(keys, 32, i);
530
15.6M
    }
531
2.91G
    assert(ix >= DKIX_DUMMY);
532
2.91G
    return ix;
533
2.91G
}
534
535
/* write to indices. */
536
static inline void
537
dictkeys_set_index(PyDictKeysObject *keys, Py_ssize_t i, Py_ssize_t ix)
538
222M
{
539
222M
    int log2size = DK_LOG_SIZE(keys);
540
541
222M
    assert(ix >= DKIX_DUMMY);
542
222M
    assert(keys->dk_version == 0);
543
544
222M
    if (log2size < 8) {
545
189M
        assert(ix <= 0x7f);
546
189M
        STORE_INDEX(keys, 8, i, ix);
547
189M
    }
548
32.6M
    else if (log2size < 16) {
549
29.0M
        assert(ix <= 0x7fff);
550
29.0M
        STORE_INDEX(keys, 16, i, ix);
551
29.0M
    }
552
3.51M
#if SIZEOF_VOID_P > 4
553
3.51M
    else if (log2size >= 32) {
554
0
        STORE_INDEX(keys, 64, i, ix);
555
0
    }
556
3.51M
#endif
557
3.51M
    else {
558
3.51M
        assert(ix <= 0x7fffffff);
559
3.51M
        STORE_INDEX(keys, 32, i, ix);
560
3.51M
    }
561
222M
}
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.85M
{
581
5.85M
#if SIZEOF_LONG == SIZEOF_SIZE_T
582
5.85M
    minsize = Py_MAX(minsize, PyDict_MINSIZE);
583
5.85M
    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.85M
}
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
479k
{
608
479k
    return calculate_log2_keysize((n*3 + 1) / 2);
609
479k
}
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.37M
#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
311M
#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
322M
#  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.10M
{
659
1.10M
    assert(mp->ma_used <= SHARED_KEYS_MAX_SIZE);
660
1.10M
    assert(i < mp->ma_values->size);
661
1.10M
    uint8_t *array = get_insertion_order_array(mp->ma_values);
662
1.10M
    return array[i];
663
1.10M
}
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
48.8M
{
790
48.8M
    Py_ssize_t usable;
791
48.8M
    int log2_bytes;
792
48.8M
    size_t entry_size = unicode ? sizeof(PyDictUnicodeEntry) : sizeof(PyDictKeyEntry);
793
794
48.8M
    assert(log2_size >= PyDict_LOG_MINSIZE);
795
796
48.8M
    usable = USABLE_FRACTION((size_t)1<<log2_size);
797
48.8M
    if (log2_size < 8) {
798
48.6M
        log2_bytes = log2_size;
799
48.6M
    }
800
166k
    else if (log2_size < 16) {
801
166k
        log2_bytes = log2_size + 1;
802
166k
    }
803
69
#if SIZEOF_VOID_P > 4
804
69
    else if (log2_size >= 32) {
805
0
        log2_bytes = log2_size + 3;
806
0
    }
807
69
#endif
808
69
    else {
809
69
        log2_bytes = log2_size + 2;
810
69
    }
811
812
48.8M
    PyDictKeysObject *dk = NULL;
813
48.8M
    if (log2_size == PyDict_LOG_MINSIZE && unicode) {
814
39.4M
        dk = _Py_FREELIST_POP_MEM(dictkeys);
815
39.4M
    }
816
48.8M
    if (dk == NULL) {
817
30.2M
        dk = PyMem_Malloc(sizeof(PyDictKeysObject)
818
30.2M
                          + ((size_t)1 << log2_bytes)
819
30.2M
                          + entry_size * usable);
820
30.2M
        if (dk == NULL) {
821
0
            PyErr_NoMemory();
822
0
            return NULL;
823
0
        }
824
30.2M
    }
825
#ifdef Py_REF_DEBUG
826
    _Py_IncRefTotal(_PyThreadState_GET());
827
#endif
828
48.8M
    dk->dk_refcnt = 1;
829
48.8M
    dk->dk_log2_size = log2_size;
830
48.8M
    dk->dk_log2_index_bytes = log2_bytes;
831
48.8M
    dk->dk_kind = unicode ? DICT_KEYS_UNICODE : DICT_KEYS_GENERAL;
832
#ifdef Py_GIL_DISABLED
833
    dk->dk_mutex = (PyMutex){0};
834
#endif
835
48.8M
    dk->dk_nentries = 0;
836
48.8M
    dk->dk_usable = usable;
837
48.8M
    dk->dk_version = 0;
838
48.8M
    memset(&dk->dk_indices[0], 0xff, ((size_t)1 << log2_bytes));
839
48.8M
    memset(&dk->dk_indices[(size_t)1 << log2_bytes], 0, entry_size * usable);
840
48.8M
    return dk;
841
48.8M
}
842
843
static void
844
free_keys_object(PyDictKeysObject *keys, bool use_qsbr)
845
52.3M
{
846
#ifdef Py_GIL_DISABLED
847
    if (use_qsbr) {
848
        _PyMem_FreeDelayed(keys, _PyDict_KeysSize(keys));
849
        return;
850
    }
851
#endif
852
52.3M
    if (DK_LOG_SIZE(keys) == PyDict_LOG_MINSIZE && keys->dk_kind == DICT_KEYS_UNICODE) {
853
42.9M
        _Py_FREELIST_FREE(dictkeys, keys, PyMem_Free);
854
42.9M
    }
855
9.39M
    else {
856
9.39M
        PyMem_Free(keys);
857
9.39M
    }
858
52.3M
}
859
860
static size_t
861
values_size_from_count(size_t count)
862
13.0k
{
863
13.0k
    assert(count >= 1);
864
13.0k
    size_t suffix_size = _Py_SIZE_ROUND_UP(count, sizeof(PyObject *));
865
13.0k
    assert(suffix_size < 128);
866
13.0k
    assert(suffix_size % sizeof(PyObject *) == 0);
867
13.0k
    return (count + 1) * sizeof(PyObject *) + suffix_size;
868
13.0k
}
869
870
134M
#define CACHED_KEYS(tp) (((PyHeapTypeObject*)tp)->ht_cached_keys)
871
872
static inline PyDictValues*
873
new_values(size_t size)
874
13.0k
{
875
13.0k
    size_t n = values_size_from_count(size);
876
13.0k
    PyDictValues *res = (PyDictValues *)PyMem_Malloc(n);
877
13.0k
    if (res == NULL) {
878
0
        return NULL;
879
0
    }
880
13.0k
    res->embedded = 0;
881
13.0k
    res->size = 0;
882
13.0k
    assert(size < 256);
883
13.0k
    res->capacity = (uint8_t)size;
884
13.0k
    return res;
885
13.0k
}
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
117M
{
905
117M
    assert(keys != NULL);
906
117M
    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
117M
    mp->ma_keys = keys;
915
117M
    mp->ma_values = values;
916
117M
    mp->ma_used = used;
917
117M
    mp->_ma_watcher_tag = 0;
918
117M
    ASSERT_CONSISTENT(mp);
919
117M
    _PyObject_GC_TRACK(mp);
920
117M
    return (PyObject *)mp;
921
117M
}
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
117M
{
928
117M
    PyDictObject *mp = _Py_FREELIST_POP(PyDictObject, dicts);
929
117M
    if (mp == NULL) {
930
24.5M
        mp = PyObject_GC_New(PyDictObject, &PyDict_Type);
931
24.5M
    }
932
117M
    assert(mp == NULL || Py_IS_TYPE(mp, &PyDict_Type));
933
934
117M
    return new_dict_impl(mp, keys, values, used, free_values_on_failure);
935
117M
}
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.99k
{
949
6.99k
    size_t size = shared_keys_usable_size(keys);
950
6.99k
    PyDictValues *values = new_values(size);
951
6.99k
    if (values == NULL) {
952
0
        return PyErr_NoMemory();
953
0
    }
954
6.99k
    dictkeys_incref(keys);
955
216k
    for (size_t i = 0; i < size; i++) {
956
209k
        values->values[i] = NULL;
957
209k
    }
958
6.99k
    return new_dict(keys, values, 0, 1);
959
6.99k
}
960
961
962
static PyDictKeysObject *
963
clone_combined_dict_keys(PyDictObject *orig)
964
3.62M
{
965
3.62M
    assert(PyAnyDict_Check(orig));
966
3.62M
    assert(Py_TYPE(orig)->tp_iter == dict_iter);
967
3.62M
    assert(orig->ma_values == NULL);
968
3.62M
    assert(orig->ma_keys != Py_EMPTY_KEYS);
969
3.62M
    assert(orig->ma_keys->dk_refcnt == 1);
970
971
3.62M
    if (!PyFrozenDict_Check(orig)) {
972
3.62M
        ASSERT_DICT_LOCKED(orig);
973
3.62M
    }
974
975
3.62M
    size_t keys_size = _PyDict_KeysSize(orig->ma_keys);
976
3.62M
    PyDictKeysObject *keys = PyMem_Malloc(keys_size);
977
3.62M
    if (keys == NULL) {
978
0
        PyErr_NoMemory();
979
0
        return NULL;
980
0
    }
981
982
3.62M
    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.62M
    PyObject **pkey, **pvalue;
988
3.62M
    size_t offs;
989
3.62M
    if (DK_IS_UNICODE(orig->ma_keys)) {
990
3.61M
        PyDictUnicodeEntry *ep0 = DK_UNICODE_ENTRIES(keys);
991
3.61M
        pkey = &ep0->me_key;
992
3.61M
        pvalue = &ep0->me_value;
993
3.61M
        offs = sizeof(PyDictUnicodeEntry) / sizeof(PyObject*);
994
3.61M
    }
995
7.38k
    else {
996
7.38k
        PyDictKeyEntry *ep0 = DK_ENTRIES(keys);
997
7.38k
        pkey = &ep0->me_key;
998
7.38k
        pvalue = &ep0->me_value;
999
7.38k
        offs = sizeof(PyDictKeyEntry) / sizeof(PyObject*);
1000
7.38k
    }
1001
1002
3.62M
    Py_ssize_t n = keys->dk_nentries;
1003
9.40M
    for (Py_ssize_t i = 0; i < n; i++) {
1004
5.77M
        PyObject *value = *pvalue;
1005
5.77M
        if (value != NULL) {
1006
5.75M
            Py_INCREF(value);
1007
5.75M
            Py_INCREF(*pkey);
1008
5.75M
        }
1009
5.77M
        pvalue += offs;
1010
5.77M
        pkey += offs;
1011
5.77M
    }
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.62M
    return keys;
1021
3.62M
}
1022
1023
PyObject *
1024
PyDict_New(void)
1025
116M
{
1026
    /* We don't incref Py_EMPTY_KEYS here because it is immortal. */
1027
116M
    return new_dict(Py_EMPTY_KEYS, NULL, 0, 0);
1028
116M
}
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.66M
{
1034
3.66M
    size_t mask = DK_MASK(k);
1035
3.66M
    size_t perturb = (size_t)hash;
1036
3.66M
    size_t i = (size_t)hash & mask;
1037
1038
7.53M
    for (;;) {
1039
7.53M
        Py_ssize_t ix = dictkeys_get_index(k, i);
1040
7.53M
        if (ix == index) {
1041
3.66M
            return i;
1042
3.66M
        }
1043
3.87M
        if (ix == DKIX_EMPTY) {
1044
0
            return DKIX_EMPTY;
1045
0
        }
1046
3.87M
        perturb >>= PERTURB_SHIFT;
1047
3.87M
        i = mask & (i*5 + perturb + 1);
1048
3.87M
    }
1049
3.66M
    Py_UNREACHABLE();
1050
3.66M
}
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.17G
{
1056
2.17G
    void *ep0 = _DK_ENTRIES(dk);
1057
2.17G
    size_t mask = DK_MASK(dk);
1058
2.17G
    size_t perturb = hash;
1059
2.17G
    size_t i = (size_t)hash & mask;
1060
2.17G
    Py_ssize_t ix;
1061
2.34G
    for (;;) {
1062
2.34G
        ix = dictkeys_get_index(dk, i);
1063
2.34G
        if (ix >= 0) {
1064
1.87G
            int cmp = check_lookup(mp, dk, ep0, ix, key, hash);
1065
1.87G
            if (cmp < 0) {
1066
0
                return cmp;
1067
1.87G
            } else if (cmp) {
1068
1.55G
                return ix;
1069
1.55G
            }
1070
1.87G
        }
1071
467M
        else if (ix == DKIX_EMPTY) {
1072
434M
            return DKIX_EMPTY;
1073
434M
        }
1074
349M
        perturb >>= PERTURB_SHIFT;
1075
349M
        i = mask & (i*5 + perturb + 1);
1076
1077
        // Manual loop unrolling
1078
349M
        ix = dictkeys_get_index(dk, i);
1079
349M
        if (ix >= 0) {
1080
202M
            int cmp = check_lookup(mp, dk, ep0, ix, key, hash);
1081
202M
            if (cmp < 0) {
1082
0
                return cmp;
1083
202M
            } else if (cmp) {
1084
43.6M
                return ix;
1085
43.6M
            }
1086
202M
        }
1087
147M
        else if (ix == DKIX_EMPTY) {
1088
140M
            return DKIX_EMPTY;
1089
140M
        }
1090
165M
        perturb >>= PERTURB_SHIFT;
1091
165M
        i = mask & (i*5 + perturb + 1);
1092
165M
    }
1093
2.17G
    Py_UNREACHABLE();
1094
2.17G
}
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
1.98k
{
1100
1.98k
    PyDictUnicodeEntry *ep = &((PyDictUnicodeEntry *)ep0)[ix];
1101
1.98k
    assert(ep->me_key != NULL);
1102
1.98k
    assert(PyUnicode_CheckExact(ep->me_key));
1103
1.98k
    assert(!PyUnicode_CheckExact(key));
1104
1105
1.98k
    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
1.98k
    return 0;
1122
1.98k
}
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
31.9M
{
1128
31.9M
    return do_lookup(mp, dk, key, hash, compare_unicode_generic);
1129
31.9M
}
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.79G
{
1135
1.79G
    PyDictUnicodeEntry *ep = &((PyDictUnicodeEntry *)ep0)[ix];
1136
1.79G
    PyObject *ep_key = FT_ATOMIC_LOAD_PTR_CONSUME(ep->me_key);
1137
1.79G
    assert(ep_key != NULL);
1138
1.79G
    assert(PyUnicode_CheckExact(ep_key));
1139
1.79G
    if (ep_key == key ||
1140
1.45G
            (unicode_get_hash(ep_key) == hash && unicode_eq(ep_key, key))) {
1141
1.45G
        return 1;
1142
1.45G
    }
1143
334M
    return 0;
1144
1.79G
}
1145
1146
static Py_ssize_t _Py_HOT_FUNCTION
1147
unicodekeys_lookup_unicode(PyDictKeysObject* dk, PyObject *key, Py_hash_t hash)
1148
1.83G
{
1149
1.83G
    return do_lookup(NULL, dk, key, hash, compare_unicode_unicode);
1150
1.83G
}
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
285M
{
1156
285M
    PyDictKeyEntry *ep = &((PyDictKeyEntry *)ep0)[ix];
1157
285M
    assert(ep->me_key != NULL);
1158
285M
    if (ep->me_key == key) {
1159
56.9M
        return 1;
1160
56.9M
    }
1161
228M
    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
139M
    return 0;
1178
228M
}
1179
1180
static Py_ssize_t
1181
dictkeys_generic_lookup(PyDictObject *mp, PyDictKeysObject* dk, PyObject *key, Py_hash_t hash)
1182
311M
{
1183
311M
    return do_lookup(mp, dk, key, hash, compare_generic);
1184
311M
}
1185
1186
static bool
1187
check_keys_unicode(PyDictKeysObject *dk, PyObject *key)
1188
2.84M
{
1189
2.84M
    return PyUnicode_CheckExact(key) && (dk->dk_kind != DICT_KEYS_GENERAL);
1190
2.84M
}
1191
1192
static Py_ssize_t
1193
hash_unicode_key(PyObject *key)
1194
69.1M
{
1195
69.1M
    assert(PyUnicode_CheckExact(key));
1196
69.1M
    Py_hash_t hash = unicode_get_hash(key);
1197
69.1M
    if (hash == -1) {
1198
0
        hash = PyUnicode_Type.tp_hash(key);
1199
0
        assert(hash != -1);
1200
0
    }
1201
69.1M
    return hash;
1202
69.1M
}
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
74.1M
{
1213
74.1M
    Py_ssize_t ix;
1214
74.1M
    assert(dk->dk_kind == DICT_KEYS_SPLIT);
1215
74.1M
    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
74.1M
    ix = unicodekeys_lookup_unicode(dk, key, hash);
1229
74.1M
#endif
1230
74.1M
    return ix;
1231
74.1M
}
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.1k
{
1242
16.1k
    if (!check_keys_unicode(dk, key)) {
1243
0
        return DKIX_ERROR;
1244
0
    }
1245
16.1k
    Py_hash_t hash = hash_unicode_key(key);
1246
16.1k
    return unicodekeys_lookup_unicode(dk, key, hash);
1247
16.1k
}
1248
1249
Py_ssize_t
1250
_PyDictKeys_StringLookupAndVersion(PyDictKeysObject *dk, PyObject *key, uint32_t *version)
1251
2.82M
{
1252
2.82M
    if (!check_keys_unicode(dk, key)) {
1253
0
        return DKIX_ERROR;
1254
0
    }
1255
2.82M
    Py_ssize_t ix;
1256
2.82M
    Py_hash_t hash = hash_unicode_key(key);
1257
2.82M
    LOCK_KEYS(dk);
1258
2.82M
    ix = unicodekeys_lookup_unicode(dk, key, hash);
1259
2.82M
    *version = _PyDictKeys_GetVersionForCurrentState(_PyInterpreterState_GET(), dk);
1260
2.82M
    UNLOCK_KEYS(dk);
1261
2.82M
    return ix;
1262
2.82M
}
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
74.1M
{
1270
74.1M
    assert(dk->dk_kind == DICT_KEYS_SPLIT);
1271
74.1M
    assert(PyUnicode_CheckExact(key));
1272
74.1M
    Py_hash_t hash = unicode_get_hash(key);
1273
74.1M
    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
74.1M
    return unicodekeys_lookup_split(dk, key, hash);
1281
74.1M
}
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.08G
{
1301
2.08G
    PyDictKeysObject *dk;
1302
2.08G
    DictKeysKind kind;
1303
2.08G
    Py_ssize_t ix;
1304
1305
2.08G
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(mp);
1306
2.08G
start:
1307
2.08G
    dk = mp->ma_keys;
1308
2.08G
    kind = dk->dk_kind;
1309
1310
2.08G
    if (kind != DICT_KEYS_GENERAL) {
1311
1.76G
        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.73G
            ix = unicodekeys_lookup_unicode(dk, key, hash);
1321
1.73G
#endif
1322
1.73G
        }
1323
31.9M
        else {
1324
31.9M
            INCREF_KEYS_FT(dk);
1325
31.9M
            LOCK_KEYS_IF_SPLIT(dk, kind);
1326
1327
31.9M
            ix = unicodekeys_lookup_generic(mp, dk, key, hash);
1328
1329
31.9M
            UNLOCK_KEYS_IF_SPLIT(dk, kind);
1330
31.9M
            DECREF_KEYS_FT(dk, IS_DICT_SHARED(mp));
1331
31.9M
            if (ix == DKIX_KEY_CHANGED) {
1332
0
                goto start;
1333
0
            }
1334
31.9M
        }
1335
1336
1.76G
        if (ix >= 0) {
1337
1.38G
            if (kind == DICT_KEYS_SPLIT) {
1338
7.19M
                *value_addr = mp->ma_values->values[ix];
1339
7.19M
            }
1340
1.38G
            else {
1341
1.38G
                *value_addr = DK_UNICODE_ENTRIES(dk)[ix].me_value;
1342
1.38G
            }
1343
1.38G
        }
1344
380M
        else {
1345
380M
            *value_addr = NULL;
1346
380M
        }
1347
1.76G
    }
1348
311M
    else {
1349
311M
        ix = dictkeys_generic_lookup(mp, dk, key, hash);
1350
311M
        if (ix == DKIX_KEY_CHANGED) {
1351
0
            goto start;
1352
0
        }
1353
311M
        if (ix >= 0) {
1354
145M
            *value_addr = DK_ENTRIES(dk)[ix].me_value;
1355
145M
        }
1356
165M
        else {
1357
165M
            *value_addr = NULL;
1358
165M
        }
1359
311M
    }
1360
1361
2.08G
    return ix;
1362
2.08G
}
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.26M
{
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.26M
}
1407
1408
static inline void
1409
ensure_shared_on_keys_version_assignment(PyDictObject *mp)
1410
61.4k
{
1411
61.4k
    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
61.4k
}
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
188M
{
1707
188M
    PyObject *val;
1708
188M
    Py_ssize_t ix = _Py_dict_lookup(mp, key, hash, &val);
1709
188M
    if (val == NULL) {
1710
153M
        *value_addr = PyStackRef_NULL;
1711
153M
    }
1712
35.8M
    else {
1713
35.8M
        *value_addr = PyStackRef_FromPyObjectNew(val);
1714
35.8M
    }
1715
188M
    return ix;
1716
188M
}
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
66.3M
{
1725
66.3M
    assert(PyUnicode_CheckExact(key));
1726
66.3M
    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
66.3M
    PyObject *obj;
1754
66.3M
    Py_INCREF(mp);
1755
66.3M
    Py_ssize_t ix = _Py_dict_lookup_threadsafe(mp, key, hash, &obj);
1756
66.3M
    Py_DECREF(mp);
1757
66.3M
    if (ix == DKIX_ERROR) {
1758
0
        PyStackRef_CLEAR(*method);
1759
0
        return -1;
1760
0
    }
1761
66.3M
    else if (ix >= 0 && obj != NULL) {
1762
27
        PyStackRef_XSETREF(*method, PyStackRef_FromPyObjectSteal(obj));
1763
27
        return 1;
1764
27
    }
1765
66.3M
    return 0;  // not found
1766
66.3M
}
1767
1768
int
1769
_PyDict_HasOnlyStringKeys(PyObject *dict)
1770
241k
{
1771
241k
    Py_ssize_t pos = 0;
1772
241k
    PyObject *key, *value;
1773
241k
    assert(PyDict_Check(dict));
1774
    /* Shortcut */
1775
241k
    if (((PyDictObject *)dict)->ma_keys->dk_kind != DICT_KEYS_GENERAL)
1776
241k
        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.02k
{
1786
8.02k
    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.02k
}
1802
1803
static inline int
1804
is_unusable_slot(Py_ssize_t ix)
1805
122M
{
1806
#ifdef Py_GIL_DISABLED
1807
    return ix >= 0 || ix == DKIX_DUMMY;
1808
#else
1809
122M
    return ix >= 0;
1810
122M
#endif
1811
122M
}
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
91.4M
{
1819
91.4M
    assert(keys != NULL);
1820
1821
91.4M
    const size_t mask = DK_MASK(keys);
1822
91.4M
    size_t i = hash & mask;
1823
91.4M
    Py_ssize_t ix = dictkeys_get_index(keys, i);
1824
122M
    for (size_t perturb = hash; is_unusable_slot(ix);) {
1825
30.5M
        perturb >>= PERTURB_SHIFT;
1826
30.5M
        i = (i*5 + perturb + 1) & mask;
1827
30.5M
        ix = dictkeys_get_index(keys, i);
1828
30.5M
    }
1829
91.4M
    return i;
1830
91.4M
}
1831
1832
static int
1833
insertion_resize(PyDictObject *mp, int unicode)
1834
5.37M
{
1835
5.37M
    return dictresize(mp, calculate_log2_keysize(GROWTH_RATE(mp)), unicode);
1836
5.37M
}
1837
1838
static inline int
1839
insert_combined_dict(PyDictObject *mp,
1840
                     Py_hash_t hash, PyObject *key, PyObject *value)
1841
90.1M
{
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
90.1M
    if (DK_IS_UNICODE(mp->ma_keys) && !PyUnicode_CheckExact(key)) {
1845
6.88k
        if (insertion_resize(mp, 0) < 0)
1846
0
            return -1;
1847
6.88k
        assert(mp->ma_keys->dk_kind == DICT_KEYS_GENERAL);
1848
6.88k
    }
1849
1850
90.1M
    if (mp->ma_keys->dk_usable <= 0) {
1851
        /* Need to resize. */
1852
5.36M
        if (insertion_resize(mp, 1) < 0) {
1853
0
            return -1;
1854
0
        }
1855
5.36M
    }
1856
1857
90.1M
    _PyDict_NotifyEvent(PyDict_EVENT_ADDED, mp, key, value);
1858
90.1M
    FT_ATOMIC_STORE_UINT32_RELAXED(mp->ma_keys->dk_version, 0);
1859
1860
90.1M
    Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash);
1861
90.1M
    dictkeys_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
1862
1863
90.1M
    if (DK_IS_UNICODE(mp->ma_keys)) {
1864
31.2M
        PyDictUnicodeEntry *ep;
1865
31.2M
        ep = &DK_UNICODE_ENTRIES(mp->ma_keys)[mp->ma_keys->dk_nentries];
1866
31.2M
        STORE_KEY(ep, key);
1867
31.2M
        STORE_VALUE(ep, value);
1868
31.2M
    }
1869
58.8M
    else {
1870
58.8M
        PyDictKeyEntry *ep;
1871
58.8M
        ep = &DK_ENTRIES(mp->ma_keys)[mp->ma_keys->dk_nentries];
1872
58.8M
        STORE_KEY(ep, key);
1873
58.8M
        STORE_VALUE(ep, value);
1874
58.8M
        STORE_HASH(ep, hash);
1875
58.8M
    }
1876
90.1M
    STORE_KEYS_USABLE(mp->ma_keys, mp->ma_keys->dk_usable - 1);
1877
90.1M
    STORE_KEYS_NENTRIES(mp->ma_keys, mp->ma_keys->dk_nentries + 1);
1878
90.1M
    assert(mp->ma_keys->dk_usable >= 0);
1879
90.1M
    return 0;
1880
90.1M
}
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.37M
        FT_ATOMIC_STORE_UINT32_RELAXED(keys->dk_version, 0);
1901
1.37M
        Py_ssize_t hashpos = find_empty_slot(keys, hash);
1902
1.37M
        ix = keys->dk_nentries;
1903
1.37M
        dictkeys_set_index(keys, hashpos, ix);
1904
1.37M
        PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(keys)[ix];
1905
1.37M
        STORE_SHARED_KEY(ep->me_key, Py_NewRef(key));
1906
1.37M
        split_keys_entry_added(keys);
1907
1.37M
    }
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
static void
1914
insert_split_value(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
132M
{
1946
132M
    assert(can_modify_dict(mp));
1947
1948
132M
    PyObject *old_value = NULL;
1949
132M
    Py_ssize_t ix;
1950
1951
132M
    if (_PyDict_HasSplitTable(mp) && PyUnicode_CheckExact(key)) {
1952
813k
        ix = insert_split_key(mp->ma_keys, key, hash);
1953
813k
        if (ix != DKIX_EMPTY) {
1954
208k
            insert_split_value(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
813k
    }
1961
131M
    else {
1962
131M
        ix = _Py_dict_lookup(mp, key, hash, &old_value);
1963
131M
        if (ix == DKIX_ERROR)
1964
0
            goto Fail;
1965
131M
    }
1966
1967
131M
    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
88.7M
        if (insert_combined_dict(mp, hash, key, value) < 0) {
1976
0
            goto Fail;
1977
0
        }
1978
88.7M
        STORE_USED(mp, mp->ma_used + 1);
1979
88.7M
        ASSERT_CONSISTENT(mp);
1980
88.7M
        return 0;
1981
88.7M
    }
1982
1983
43.1M
    if (old_value != value) {
1984
21.8M
        _PyDict_NotifyEvent(PyDict_EVENT_MODIFIED, mp, key, value);
1985
21.8M
        assert(old_value != NULL);
1986
21.8M
        if (DK_IS_UNICODE(mp->ma_keys)) {
1987
21.1M
            if (_PyDict_HasSplitTable(mp)) {
1988
0
                STORE_SPLIT_VALUE(mp, ix, value);
1989
0
            }
1990
21.1M
            else {
1991
21.1M
                PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(mp->ma_keys)[ix];
1992
21.1M
                STORE_VALUE(ep, value);
1993
21.1M
            }
1994
21.1M
        }
1995
751k
        else {
1996
751k
            PyDictKeyEntry *ep = &DK_ENTRIES(mp->ma_keys)[ix];
1997
751k
            STORE_VALUE(ep, value);
1998
751k
        }
1999
21.8M
    }
2000
43.1M
    Py_XDECREF(old_value); /* which **CAN** re-enter (see issue #22653) */
2001
43.1M
    ASSERT_CONSISTENT(mp);
2002
43.1M
    Py_DECREF(key);
2003
43.1M
    return 0;
2004
2005
0
Fail:
2006
0
    Py_DECREF(value);
2007
0
    Py_DECREF(key);
2008
0
    return -1;
2009
131M
}
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.7M
{
2017
42.7M
    assert(can_modify_dict(mp));
2018
42.7M
    assert(mp->ma_keys == Py_EMPTY_KEYS);
2019
2020
42.7M
    int unicode = PyUnicode_CheckExact(key);
2021
42.7M
    PyDictKeysObject *newkeys = new_keys_object(PyDict_LOG_MINSIZE, unicode);
2022
42.7M
    if (newkeys == NULL) {
2023
0
        Py_DECREF(key);
2024
0
        Py_DECREF(value);
2025
0
        return -1;
2026
0
    }
2027
42.7M
    _PyDict_NotifyEvent(PyDict_EVENT_ADDED, mp, key, value);
2028
2029
    /* We don't decref Py_EMPTY_KEYS here because it is immortal. */
2030
42.7M
    assert(mp->ma_values == NULL);
2031
2032
42.7M
    size_t hashpos = (size_t)hash & (PyDict_MINSIZE-1);
2033
42.7M
    dictkeys_set_index(newkeys, hashpos, 0);
2034
42.7M
    if (unicode) {
2035
38.3M
        PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(newkeys);
2036
38.3M
        ep->me_key = key;
2037
38.3M
        STORE_VALUE(ep, value);
2038
38.3M
    }
2039
4.36M
    else {
2040
4.36M
        PyDictKeyEntry *ep = DK_ENTRIES(newkeys);
2041
4.36M
        ep->me_key = key;
2042
4.36M
        ep->me_hash = hash;
2043
4.36M
        STORE_VALUE(ep, value);
2044
4.36M
    }
2045
42.7M
    STORE_USED(mp, mp->ma_used + 1);
2046
42.7M
    newkeys->dk_usable--;
2047
42.7M
    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.7M
    FT_ATOMIC_STORE_PTR_RELEASE(mp->ma_keys, newkeys);
2054
42.7M
    return 0;
2055
42.7M
}
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
3.86M
{
2063
3.86M
    size_t mask = DK_MASK(keys);
2064
76.8M
    for (Py_ssize_t ix = 0; ix != n; ix++, ep++) {
2065
73.0M
        Py_hash_t hash = ep->me_hash;
2066
73.0M
        size_t i = hash & mask;
2067
78.1M
        for (size_t perturb = hash; dictkeys_get_index(keys, i) != DKIX_EMPTY;) {
2068
5.17M
            perturb >>= PERTURB_SHIFT;
2069
5.17M
            i = mask & (i*5 + perturb + 1);
2070
5.17M
        }
2071
73.0M
        dictkeys_set_index(keys, i, ix);
2072
73.0M
    }
2073
3.86M
}
2074
2075
static void
2076
build_indices_unicode(PyDictKeysObject *keys, PyDictUnicodeEntry *ep, Py_ssize_t n)
2077
1.96M
{
2078
1.96M
    size_t mask = DK_MASK(keys);
2079
13.4M
    for (Py_ssize_t ix = 0; ix != n; ix++, ep++) {
2080
11.4M
        Py_hash_t hash = unicode_get_hash(ep->me_key);
2081
11.4M
        assert(hash != -1);
2082
11.4M
        size_t i = hash & mask;
2083
13.4M
        for (size_t perturb = hash; dictkeys_get_index(keys, i) != DKIX_EMPTY;) {
2084
1.96M
            perturb >>= PERTURB_SHIFT;
2085
1.96M
            i = mask & (i*5 + perturb + 1);
2086
1.96M
        }
2087
11.4M
        dictkeys_set_index(keys, i, ix);
2088
11.4M
    }
2089
1.96M
}
2090
2091
static void
2092
invalidate_and_clear_inline_values(PyDictValues *values)
2093
598k
{
2094
598k
    assert(values->embedded);
2095
598k
    FT_ATOMIC_STORE_UINT8(values->valid, 0);
2096
2.18M
    for (int i = 0; i < values->capacity; i++) {
2097
1.58M
        FT_ATOMIC_STORE_PTR_RELEASE(values->values[i], NULL);
2098
1.58M
    }
2099
598k
}
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.82M
{
2119
5.82M
    assert(can_modify_dict(mp));
2120
2121
5.82M
    PyDictKeysObject *oldkeys, *newkeys;
2122
5.82M
    PyDictValues *oldvalues;
2123
2124
5.82M
    if (log2_newsize >= SIZEOF_SIZE_T*8) {
2125
0
        PyErr_NoMemory();
2126
0
        return -1;
2127
0
    }
2128
5.82M
    assert(log2_newsize >= PyDict_LOG_MINSIZE);
2129
2130
5.82M
    oldkeys = mp->ma_keys;
2131
5.82M
    oldvalues = mp->ma_values;
2132
2133
5.82M
    if (!DK_IS_UNICODE(oldkeys)) {
2134
3.85M
        unicode = 0;
2135
3.85M
    }
2136
2137
5.82M
    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.82M
    newkeys = new_keys_object(log2_newsize, unicode);
2145
5.82M
    if (newkeys == NULL) {
2146
0
        return -1;
2147
0
    }
2148
    // New table must be large enough.
2149
5.82M
    assert(newkeys->dk_usable >= mp->ma_used);
2150
2151
5.82M
    Py_ssize_t numentries = mp->ma_used;
2152
2153
5.82M
    if (oldvalues != NULL) {
2154
604k
        LOCK_KEYS(oldkeys);
2155
604k
        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
604k
        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
604k
        else { // split -> combined unicode
2174
604k
            PyDictUnicodeEntry *newentries = DK_UNICODE_ENTRIES(newkeys);
2175
2176
1.70M
            for (Py_ssize_t i = 0; i < numentries; i++) {
2177
1.10M
                int index = get_index_from_order(mp, i);
2178
1.10M
                PyDictUnicodeEntry *ep = &oldentries[index];
2179
1.10M
                assert(oldvalues->values[index] != NULL);
2180
1.10M
                newentries[i].me_key = Py_NewRef(ep->me_key);
2181
1.10M
                newentries[i].me_value = oldvalues->values[index];
2182
1.10M
            }
2183
604k
            build_indices_unicode(newkeys, newentries, numentries);
2184
604k
        }
2185
604k
        UNLOCK_KEYS(oldkeys);
2186
604k
        set_keys(mp, newkeys);
2187
604k
        dictkeys_decref(oldkeys, IS_DICT_SHARED(mp));
2188
604k
        set_values(mp, NULL);
2189
604k
        if (oldvalues->embedded) {
2190
598k
            assert(oldvalues->embedded == 1);
2191
598k
            assert(oldvalues->valid == 1);
2192
598k
            invalidate_and_clear_inline_values(oldvalues);
2193
598k
        }
2194
6.03k
        else {
2195
6.03k
            free_values(oldvalues, IS_DICT_SHARED(mp));
2196
6.03k
        }
2197
604k
    }
2198
5.21M
    else {  // oldkeys is combined.
2199
5.21M
        if (oldkeys->dk_kind == DICT_KEYS_GENERAL) {
2200
            // generic -> generic
2201
3.85M
            assert(newkeys->dk_kind == DICT_KEYS_GENERAL);
2202
3.85M
            PyDictKeyEntry *oldentries = DK_ENTRIES(oldkeys);
2203
3.85M
            PyDictKeyEntry *newentries = DK_ENTRIES(newkeys);
2204
3.85M
            if (oldkeys->dk_nentries == numentries) {
2205
3.82M
                memcpy(newentries, oldentries, numentries * sizeof(PyDictKeyEntry));
2206
3.82M
            }
2207
26.7k
            else {
2208
26.7k
                PyDictKeyEntry *ep = oldentries;
2209
706k
                for (Py_ssize_t i = 0; i < numentries; i++) {
2210
1.39M
                    while (ep->me_value == NULL)
2211
712k
                        ep++;
2212
679k
                    newentries[i] = *ep++;
2213
679k
                }
2214
26.7k
            }
2215
3.85M
            build_indices_generic(newkeys, newentries, numentries);
2216
3.85M
        }
2217
1.36M
        else {  // oldkeys is combined unicode
2218
1.36M
            PyDictUnicodeEntry *oldentries = DK_UNICODE_ENTRIES(oldkeys);
2219
1.36M
            if (unicode) { // combined unicode -> combined unicode
2220
1.35M
                PyDictUnicodeEntry *newentries = DK_UNICODE_ENTRIES(newkeys);
2221
1.35M
                if (oldkeys->dk_nentries == numentries && mp->ma_keys->dk_kind == DICT_KEYS_UNICODE) {
2222
1.34M
                    memcpy(newentries, oldentries, numentries * sizeof(PyDictUnicodeEntry));
2223
1.34M
                }
2224
11.1k
                else {
2225
11.1k
                    PyDictUnicodeEntry *ep = oldentries;
2226
758k
                    for (Py_ssize_t i = 0; i < numentries; i++) {
2227
781k
                        while (ep->me_value == NULL)
2228
33.6k
                            ep++;
2229
747k
                        newentries[i] = *ep++;
2230
747k
                    }
2231
11.1k
                }
2232
1.35M
                build_indices_unicode(newkeys, newentries, numentries);
2233
1.35M
            }
2234
6.88k
            else { // combined unicode -> generic
2235
6.88k
                PyDictKeyEntry *newentries = DK_ENTRIES(newkeys);
2236
6.88k
                PyDictUnicodeEntry *ep = oldentries;
2237
20.3k
                for (Py_ssize_t i = 0; i < numentries; i++) {
2238
13.4k
                    while (ep->me_value == NULL)
2239
0
                        ep++;
2240
13.4k
                    newentries[i].me_key = ep->me_key;
2241
13.4k
                    newentries[i].me_hash = unicode_get_hash(ep->me_key);
2242
13.4k
                    newentries[i].me_value = ep->me_value;
2243
13.4k
                    ep++;
2244
13.4k
                }
2245
6.88k
                build_indices_generic(newkeys, newentries, numentries);
2246
6.88k
            }
2247
1.36M
        }
2248
2249
5.21M
        set_keys(mp, newkeys);
2250
2251
5.21M
        if (oldkeys != Py_EMPTY_KEYS) {
2252
#ifdef Py_REF_DEBUG
2253
            _Py_DecRefTotal(_PyThreadState_GET());
2254
#endif
2255
4.76M
            assert(oldkeys->dk_kind != DICT_KEYS_SPLIT);
2256
4.76M
            assert(oldkeys->dk_refcnt == 1);
2257
4.76M
            free_keys_object(oldkeys, IS_DICT_SHARED(mp));
2258
4.76M
        }
2259
5.21M
    }
2260
2261
5.82M
    STORE_KEYS_USABLE(mp->ma_keys, mp->ma_keys->dk_usable - numentries);
2262
5.82M
    STORE_KEYS_NENTRIES(mp->ma_keys, numentries);
2263
5.82M
    ASSERT_CONSISTENT(mp);
2264
5.82M
    return 0;
2265
5.82M
}
2266
2267
static PyObject *
2268
dict_new_presized(Py_ssize_t minused, bool unicode)
2269
68.0M
{
2270
68.0M
    const uint8_t log2_max_presize = 17;
2271
68.0M
    const Py_ssize_t max_presize = ((Py_ssize_t)1) << log2_max_presize;
2272
68.0M
    uint8_t log2_newsize;
2273
68.0M
    PyDictKeysObject *new_keys;
2274
2275
68.0M
    if (minused <= USABLE_FRACTION(PyDict_MINSIZE)) {
2276
67.9M
        return PyDict_New();
2277
67.9M
    }
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
27.8k
    if (minused > USABLE_FRACTION(max_presize)) {
2283
0
        log2_newsize = log2_max_presize;
2284
0
    }
2285
27.8k
    else {
2286
27.8k
        log2_newsize = estimate_log2_keysize(minused);
2287
27.8k
    }
2288
2289
27.8k
    new_keys = new_keys_object(log2_newsize, unicode);
2290
27.8k
    if (new_keys == NULL)
2291
0
        return NULL;
2292
27.8k
    return new_dict(new_keys, NULL, 0, 0);
2293
27.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
68.0M
{
2306
68.0M
    bool unicode = true;
2307
68.0M
    PyObject *const *ks = keys;
2308
2309
86.6M
    for (Py_ssize_t i = 0; i < length; i++) {
2310
18.7M
        if (!PyUnicode_CheckExact(*ks)) {
2311
78.3k
            unicode = false;
2312
78.3k
            break;
2313
78.3k
        }
2314
18.6M
        ks += keys_offset;
2315
18.6M
    }
2316
2317
68.0M
    PyObject *dict = dict_new_presized(length, unicode);
2318
68.0M
    if (dict == NULL) {
2319
0
        return NULL;
2320
0
    }
2321
2322
68.0M
    ks = keys;
2323
68.0M
    PyObject *const *vs = values;
2324
2325
86.9M
    for (Py_ssize_t i = 0; i < length; i++) {
2326
18.9M
        PyObject *key = *ks;
2327
18.9M
        PyObject *value = *vs;
2328
18.9M
        if (setitem_lock_held((PyDictObject *)dict, key, value) < 0) {
2329
0
            Py_DECREF(dict);
2330
0
            return NULL;
2331
0
        }
2332
18.9M
        ks += keys_offset;
2333
18.9M
        vs += values_offset;
2334
18.9M
    }
2335
2336
68.0M
    return dict;
2337
68.0M
}
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
235k
{
2352
235k
    if (!PyAnyDict_Check(op)) {
2353
0
        return NULL;
2354
0
    }
2355
235k
    PyDictObject *mp = (PyDictObject *)op;
2356
2357
235k
    Py_hash_t hash = _PyObject_HashFast(key);
2358
235k
    if (hash == -1) {
2359
0
        PyErr_FormatUnraisable(warnmsg);
2360
0
        return NULL;
2361
0
    }
2362
2363
235k
    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
235k
    PyObject *value;
2372
235k
    Py_ssize_t ix; (void)ix;
2373
2374
235k
    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
235k
    ix = _Py_dict_lookup(mp, key, hash, &value);
2380
235k
#endif
2381
2382
    /* Ignore any exception raised by the lookup */
2383
235k
    PyObject *exc2 = _PyErr_Occurred(tstate);
2384
235k
    if (exc2 && !PyErr_GivenExceptionMatches(exc2, PyExc_KeyError)) {
2385
0
        PyErr_FormatUnraisable(warnmsg);
2386
0
    }
2387
235k
    _PyErr_SetRaisedException(tstate, exc);
2388
2389
235k
    assert(ix >= 0 || value == NULL);
2390
235k
    return value;  // borrowed reference
2391
235k
}
2392
2393
PyObject *
2394
PyDict_GetItem(PyObject *op, PyObject *key)
2395
235k
{
2396
235k
    return dict_getitem(op, key,
2397
235k
            "Exception ignored in PyDict_GetItem(); consider using "
2398
235k
            "PyDict_GetItemRef() or PyDict_GetItemWithError()");
2399
235k
}
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
59.3k
{
2425
    // TODO: Thread safety
2426
59.3k
    assert(PyDict_CheckExact((PyObject*)mp));
2427
59.3k
    assert(PyUnicode_CheckExact(key));
2428
2429
59.3k
    Py_hash_t hash = _PyObject_HashFast(key);
2430
59.3k
    if (hash == -1) {
2431
0
        dict_unhashable_type((PyObject*)mp, key);
2432
0
        return -1;
2433
0
    }
2434
2435
59.3k
    return _Py_dict_lookup(mp, key, hash, value);
2436
59.3k
}
2437
2438
Py_ssize_t
2439
_PyDict_LookupIndex(PyDictObject *mp, PyObject *key)
2440
13.8k
{
2441
13.8k
    PyObject *value; // discarded
2442
13.8k
    return _PyDict_LookupIndexAndValue(mp, key, &value);
2443
13.8k
}
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
69.0k
{
2479
69.0k
    PyObject *value;
2480
69.0k
    Py_ssize_t ix = _Py_dict_lookup(op, key, hash, &value);
2481
69.0k
    assert(ix >= 0 || value == NULL);
2482
69.0k
    if (ix == DKIX_ERROR) {
2483
0
        *result = NULL;
2484
0
        return -1;
2485
0
    }
2486
69.0k
    if (value == NULL) {
2487
802
        *result = NULL;
2488
802
        return 0;  // missing key
2489
802
    }
2490
68.2k
    *result = Py_NewRef(value);
2491
68.2k
    return 1;  // key is present
2492
69.0k
}
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.05G
{
2501
1.05G
    PyObject *value;
2502
#ifdef Py_GIL_DISABLED
2503
    Py_ssize_t ix = _Py_dict_lookup_threadsafe(op, key, hash, &value);
2504
#else
2505
1.05G
    Py_ssize_t ix = _Py_dict_lookup(op, key, hash, &value);
2506
1.05G
#endif
2507
1.05G
    assert(ix >= 0 || value == NULL);
2508
1.05G
    if (ix == DKIX_ERROR) {
2509
0
        *result = NULL;
2510
0
        return -1;
2511
0
    }
2512
1.05G
    if (value == NULL) {
2513
58.3M
        *result = NULL;
2514
58.3M
        return 0;  // missing key
2515
58.3M
    }
2516
#ifdef Py_GIL_DISABLED
2517
    *result = value;
2518
#else
2519
993M
    *result = Py_NewRef(value);
2520
993M
#endif
2521
993M
    return 1;  // key is present
2522
1.05G
}
2523
2524
int
2525
PyDict_GetItemRef(PyObject *op, PyObject *key, PyObject **result)
2526
1.05G
{
2527
1.05G
    if (!PyAnyDict_Check(op)) {
2528
0
        PyErr_BadInternalCall();
2529
0
        *result = NULL;
2530
0
        return -1;
2531
0
    }
2532
2533
1.05G
    Py_hash_t hash = _PyObject_HashFast(key);
2534
1.05G
    if (hash == -1) {
2535
0
        dict_unhashable_type(op, key);
2536
0
        *result = NULL;
2537
0
        return -1;
2538
0
    }
2539
2540
1.05G
    return _PyDict_GetItemRef_KnownHash((PyDictObject *)op, key, hash, result);
2541
1.05G
}
2542
2543
int
2544
_PyDict_GetItemRef_Unicode_LockHeld(PyDictObject *op, PyObject *key, PyObject **result)
2545
37.2k
{
2546
37.2k
    ASSERT_DICT_LOCKED(op);
2547
37.2k
    assert(PyUnicode_CheckExact(key));
2548
2549
37.2k
    Py_hash_t hash = _PyObject_HashFast(key);
2550
37.2k
    if (hash == -1) {
2551
0
        dict_unhashable_type((PyObject*)op, key);
2552
0
        *result = NULL;
2553
0
        return -1;
2554
0
    }
2555
2556
37.2k
    PyObject *value;
2557
37.2k
    Py_ssize_t ix = _Py_dict_lookup(op, key, hash, &value);
2558
37.2k
    assert(ix >= 0 || value == NULL);
2559
37.2k
    if (ix == DKIX_ERROR) {
2560
0
        *result = NULL;
2561
0
        return -1;
2562
0
    }
2563
37.2k
    if (value == NULL) {
2564
12.4k
        *result = NULL;
2565
12.4k
        return 0;  // missing key
2566
12.4k
    }
2567
24.7k
    *result = Py_NewRef(value);
2568
24.7k
    return 1;  // key is present
2569
37.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
61.2M
{
2578
61.2M
    Py_ssize_t ix; (void)ix;
2579
61.2M
    Py_hash_t hash;
2580
61.2M
    PyDictObject*mp = (PyDictObject *)op;
2581
61.2M
    PyObject *value;
2582
2583
61.2M
    if (!PyAnyDict_Check(op)) {
2584
0
        PyErr_BadInternalCall();
2585
0
        return NULL;
2586
0
    }
2587
61.2M
    hash = _PyObject_HashFast(key);
2588
61.2M
    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
61.2M
    ix = _Py_dict_lookup(mp, key, hash, &value);
2598
61.2M
#endif
2599
61.2M
    assert(ix >= 0 || value == NULL);
2600
61.2M
    return value;  // borrowed reference
2601
61.2M
}
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.31k
{
2642
1.31k
    Py_ssize_t ix;
2643
1.31k
    Py_hash_t hash;
2644
1.31k
    PyObject *value;
2645
2646
1.31k
    hash = _PyObject_HashFast(key);
2647
1.31k
    if (hash == -1) {
2648
0
        return NULL;
2649
0
    }
2650
2651
    /* namespace 1: globals */
2652
1.31k
    ix = _Py_dict_lookup_threadsafe(globals, key, hash, &value);
2653
1.31k
    if (ix == DKIX_ERROR)
2654
0
        return NULL;
2655
1.31k
    if (ix != DKIX_EMPTY && value != NULL)
2656
270
        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.31k
}
2663
2664
void
2665
_PyDict_LoadGlobalStackRef(PyDictObject *globals, PyDictObject *builtins, PyObject *key, _PyStackRef *res)
2666
255k
{
2667
255k
    Py_ssize_t ix;
2668
255k
    Py_hash_t hash;
2669
2670
255k
    hash = _PyObject_HashFast(key);
2671
255k
    if (hash == -1) {
2672
0
        *res = PyStackRef_NULL;
2673
0
        return;
2674
0
    }
2675
2676
    /* namespace 1: globals */
2677
255k
    ix = _Py_dict_lookup_threadsafe_stackref(globals, key, hash, res);
2678
255k
    if (ix == DKIX_ERROR) {
2679
0
        return;
2680
0
    }
2681
255k
    if (ix != DKIX_EMPTY && !PyStackRef_IsNull(*res)) {
2682
111k
        return;
2683
111k
    }
2684
2685
    /* namespace 2: builtins */
2686
143k
    ix = _Py_dict_lookup_threadsafe_stackref(builtins, key, hash, res);
2687
143k
    assert(ix >= 0 || PyStackRef_IsNull(*res));
2688
143k
}
2689
2690
PyObject *
2691
_PyDict_LoadBuiltinsFromGlobals(PyObject *globals)
2692
18.6M
{
2693
18.6M
    if (!PyAnyDict_Check(globals)) {
2694
0
        PyErr_BadInternalCall();
2695
0
        return NULL;
2696
0
    }
2697
2698
18.6M
    PyDictObject *mp = (PyDictObject *)globals;
2699
18.6M
    PyObject *key = &_Py_ID(__builtins__);
2700
18.6M
    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.6M
    _PyStackRef ref;
2707
18.6M
    Py_ssize_t ix = _Py_dict_lookup_threadsafe_stackref(mp, key, hash, &ref);
2708
18.6M
    if (ix == DKIX_ERROR) {
2709
0
        return NULL;
2710
0
    }
2711
18.6M
    if (PyStackRef_IsNull(ref)) {
2712
183
        return Py_NewRef(PyEval_GetBuiltins());
2713
183
    }
2714
18.6M
    PyObject *builtins = PyStackRef_AsPyObjectBorrow(ref);
2715
18.6M
    if (PyModule_Check(builtins)) {
2716
72
        builtins = _PyModule_GetDict(builtins);
2717
72
        assert(builtins != NULL);
2718
72
    }
2719
18.6M
    _Py_INCREF_BUILTINS(builtins);
2720
18.6M
    PyStackRef_CLOSE(ref);
2721
18.6M
    return builtins;
2722
18.6M
}
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
173M
{
2732
173M
    assert(PyAnyDict_Check(mp));
2733
173M
    assert(can_modify_dict(mp));
2734
173M
    assert(key);
2735
173M
    assert(value);
2736
2737
173M
    if (mp->ma_keys == Py_EMPTY_KEYS) {
2738
42.3M
        return insert_to_emptydict(mp, key, hash, value);
2739
42.3M
    }
2740
    /* insertdict() handles any resizing that might be necessary */
2741
130M
    return insertdict(mp, key, hash, value);
2742
173M
}
2743
2744
static int
2745
setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value)
2746
173M
{
2747
173M
    Py_hash_t hash = _PyObject_HashFast(key);
2748
173M
    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
173M
    return setitem_take2_lock_held_known_hash(mp, key, value, hash);
2756
173M
}
2757
2758
int
2759
_PyDict_SetItem_Take2(PyDictObject *mp, PyObject *key, PyObject *value)
2760
96.4M
{
2761
96.4M
    int res;
2762
96.4M
    Py_BEGIN_CRITICAL_SECTION(mp);
2763
96.4M
    res = setitem_take2_lock_held(mp, key, value);
2764
96.4M
    Py_END_CRITICAL_SECTION();
2765
96.4M
    return res;
2766
96.4M
}
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.8M
{
2787
23.8M
    assert(key);
2788
23.8M
    assert(value);
2789
2790
23.8M
    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.8M
    return _PyDict_SetItem_Take2((PyDictObject *)op,
2801
23.8M
                                 Py_NewRef(key), Py_NewRef(value));
2802
23.8M
}
2803
2804
static int
2805
_PyAnyDict_SetItem(PyObject *op, PyObject *key, PyObject *value)
2806
2.50k
{
2807
2.50k
    assert(PyAnyDict_Check(op));
2808
2.50k
    assert(key);
2809
2.50k
    assert(value);
2810
2.50k
    return _PyDict_SetItem_Take2((PyDictObject *)op,
2811
2.50k
                                 Py_NewRef(key), Py_NewRef(value));
2812
2.50k
}
2813
2814
static int
2815
setitem_lock_held(PyDictObject *mp, PyObject *key, PyObject *value)
2816
76.8M
{
2817
76.8M
    assert(key);
2818
76.8M
    assert(value);
2819
76.8M
    return setitem_take2_lock_held(mp,
2820
76.8M
                                   Py_NewRef(key), Py_NewRef(value));
2821
76.8M
}
2822
2823
2824
int
2825
_PyDict_SetItem_KnownHash_LockHeld(PyDictObject *mp, PyObject *key, PyObject *value,
2826
                                   Py_hash_t hash)
2827
33.9k
{
2828
33.9k
    if (mp->ma_keys == Py_EMPTY_KEYS) {
2829
23.2k
        return insert_to_emptydict(mp, Py_NewRef(key), hash, Py_NewRef(value));
2830
23.2k
    }
2831
    /* insertdict() handles any resizing that might be necessary */
2832
10.7k
    return insertdict(mp, Py_NewRef(key), hash, Py_NewRef(value));
2833
33.9k
}
2834
2835
int
2836
_PyDict_SetItem_KnownHash(PyObject *op, PyObject *key, PyObject *value,
2837
                          Py_hash_t hash)
2838
254
{
2839
254
    assert(key);
2840
254
    assert(value);
2841
254
    assert(hash != -1);
2842
2843
254
    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
254
    int res;
2854
254
    Py_BEGIN_CRITICAL_SECTION(op);
2855
254
    res = _PyDict_SetItem_KnownHash_LockHeld((PyDictObject *)op, key, value, hash);
2856
254
    Py_END_CRITICAL_SECTION();
2857
254
    return res;
2858
254
}
2859
2860
static void
2861
delete_index_from_values(PyDictValues *values, Py_ssize_t ix)
2862
366k
{
2863
366k
    uint8_t *array = get_insertion_order_array(values);
2864
366k
    int size = values->size;
2865
366k
    assert(size <= values->capacity);
2866
366k
    int i;
2867
978k
    for (i = 0; array[i] != ix; i++) {
2868
611k
        assert(i < size);
2869
611k
    }
2870
366k
    assert(i < size);
2871
366k
    size--;
2872
855k
    for (; i < size; i++) {
2873
489k
        array[i] = array[i+1];
2874
489k
    }
2875
366k
    values->size = size;
2876
366k
}
2877
2878
static void
2879
delitem_common(PyDictObject *mp, Py_hash_t hash, Py_ssize_t ix,
2880
               PyObject *old_value)
2881
3.34M
{
2882
3.34M
    assert(can_modify_dict(mp));
2883
2884
3.34M
    PyObject *old_key;
2885
2886
3.34M
    Py_ssize_t hashpos = lookdict_index(mp->ma_keys, hash, ix);
2887
3.34M
    assert(hashpos >= 0);
2888
2889
3.34M
    STORE_USED(mp, mp->ma_used - 1);
2890
3.34M
    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
3.34M
    else {
2899
3.34M
        FT_ATOMIC_STORE_UINT32_RELAXED(mp->ma_keys->dk_version, 0);
2900
3.34M
        dictkeys_set_index(mp->ma_keys, hashpos, DKIX_DUMMY);
2901
3.34M
        if (DK_IS_UNICODE(mp->ma_keys)) {
2902
1.13M
            PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(mp->ma_keys)[ix];
2903
1.13M
            old_key = ep->me_key;
2904
1.13M
            STORE_KEY(ep, NULL);
2905
1.13M
            STORE_VALUE(ep, NULL);
2906
1.13M
        }
2907
2.21M
        else {
2908
2.21M
            PyDictKeyEntry *ep = &DK_ENTRIES(mp->ma_keys)[ix];
2909
2.21M
            old_key = ep->me_key;
2910
2.21M
            STORE_KEY(ep, NULL);
2911
2.21M
            STORE_VALUE(ep, NULL);
2912
2.21M
            STORE_HASH(ep, 0);
2913
2.21M
        }
2914
3.34M
        Py_DECREF(old_key);
2915
3.34M
    }
2916
3.34M
    Py_DECREF(old_value);
2917
2918
3.34M
    ASSERT_CONSISTENT(mp);
2919
3.34M
}
2920
2921
int
2922
PyDict_DelItem(PyObject *op, PyObject *key)
2923
2.48M
{
2924
2.48M
    assert(key);
2925
2.48M
    Py_hash_t hash = _PyObject_HashFast(key);
2926
2.48M
    if (hash == -1) {
2927
0
        dict_unhashable_type(op, key);
2928
0
        return -1;
2929
0
    }
2930
2931
2.48M
    return _PyDict_DelItem_KnownHash(op, key, hash);
2932
2.48M
}
2933
2934
int
2935
_PyDict_DelItem_KnownHash_LockHeld(PyObject *op, PyObject *key, Py_hash_t hash)
2936
2.50M
{
2937
2.50M
    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.50M
    Py_ssize_t ix;
2948
2.50M
    PyObject *old_value;
2949
2.50M
    PyDictObject *mp = (PyDictObject *)op;
2950
2.50M
    assert(can_modify_dict(mp));
2951
2952
2.50M
    assert(key);
2953
2.50M
    assert(hash != -1);
2954
2.50M
    ix = _Py_dict_lookup(mp, key, hash, &old_value);
2955
2.50M
    if (ix == DKIX_ERROR)
2956
0
        return -1;
2957
2.50M
    if (ix == DKIX_EMPTY || old_value == NULL) {
2958
0
        _PyErr_SetKeyError(key);
2959
0
        return -1;
2960
0
    }
2961
2962
2.50M
    _PyDict_NotifyEvent(PyDict_EVENT_DELETED, mp, key, NULL);
2963
2.50M
    delitem_common(mp, hash, ix, old_value);
2964
2.50M
    return 0;
2965
2.50M
}
2966
2967
int
2968
_PyDict_DelItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
2969
2.48M
{
2970
2.48M
    int res;
2971
2.48M
    Py_BEGIN_CRITICAL_SECTION(op);
2972
2.48M
    res = _PyDict_DelItem_KnownHash_LockHeld(op, key, hash);
2973
2.48M
    Py_END_CRITICAL_SECTION();
2974
2.48M
    return res;
2975
2.48M
}
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
483k
{
3050
483k
    if (!PyDict_Check(op)) {
3051
0
        return;
3052
0
    }
3053
483k
    PyDictObject *mp = (PyDictObject *)op;
3054
483k
    assert(can_modify_dict(mp));
3055
3056
483k
    PyDictKeysObject *oldkeys;
3057
483k
    PyDictValues *oldvalues;
3058
483k
    Py_ssize_t i, n;
3059
3060
483k
    oldkeys = mp->ma_keys;
3061
483k
    oldvalues = mp->ma_values;
3062
483k
    if (oldkeys == Py_EMPTY_KEYS) {
3063
238k
        return;
3064
238k
    }
3065
    /* Empty the dict... */
3066
244k
    _PyDict_NotifyEvent(PyDict_EVENT_CLEARED, mp, NULL, NULL);
3067
    // We don't inc ref empty keys because they're immortal
3068
244k
    ensure_shared_on_resize(mp);
3069
244k
    STORE_USED(mp, 0);
3070
244k
    if (oldvalues == NULL) {
3071
244k
        set_keys(mp, Py_EMPTY_KEYS);
3072
244k
        assert(oldkeys->dk_refcnt == 1);
3073
244k
        dictkeys_decref(oldkeys, IS_DICT_SHARED(mp));
3074
244k
    }
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
244k
    ASSERT_CONSISTENT(mp);
3089
244k
}
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
477k
{
3099
477k
    Py_BEGIN_CRITICAL_SECTION(op);
3100
477k
    clear_lock_held(op);
3101
477k
    Py_END_CRITICAL_SECTION();
3102
477k
}
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.6M
{
3113
42.6M
    Py_ssize_t i;
3114
42.6M
    PyDictObject *mp;
3115
42.6M
    PyObject *key, *value;
3116
42.6M
    Py_hash_t hash;
3117
3118
42.6M
    if (!PyAnyDict_Check(op))
3119
0
        return 0;
3120
3121
42.6M
    mp = (PyDictObject *)op;
3122
42.6M
    i = *ppos;
3123
42.6M
    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.6M
    else {
3134
42.6M
        Py_ssize_t n = mp->ma_keys->dk_nentries;
3135
42.6M
        if (i < 0 || i >= n)
3136
17.4M
            return 0;
3137
25.1M
        if (DK_IS_UNICODE(mp->ma_keys)) {
3138
22.2M
            PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(mp->ma_keys)[i];
3139
22.6M
            while (i < n && entry_ptr->me_value == NULL) {
3140
469k
                entry_ptr++;
3141
469k
                i++;
3142
469k
            }
3143
22.2M
            if (i >= n)
3144
227k
                return 0;
3145
21.9M
            key = entry_ptr->me_key;
3146
21.9M
            hash = unicode_get_hash(entry_ptr->me_key);
3147
21.9M
            value = entry_ptr->me_value;
3148
21.9M
        }
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
25.1M
    }
3162
24.9M
    *ppos = i+1;
3163
24.9M
    if (pkey)
3164
24.9M
        *pkey = key;
3165
24.9M
    if (pvalue)
3166
24.2M
        *pvalue = value;
3167
24.9M
    if (phash)
3168
1.19M
        *phash = hash;
3169
24.9M
    return 1;
3170
42.6M
}
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.3M
{
3193
30.3M
    return _PyDict_Next(op, ppos, pkey, pvalue, NULL);
3194
30.3M
}
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
838k
{
3202
838k
    assert(PyDict_Check(mp));
3203
838k
    assert(can_modify_dict(mp));
3204
3205
838k
    if (mp->ma_used == 0) {
3206
0
        if (result) {
3207
0
            *result = NULL;
3208
0
        }
3209
0
        return 0;
3210
0
    }
3211
3212
838k
    PyObject *old_value;
3213
838k
    Py_ssize_t ix = _Py_dict_lookup(mp, key, hash, &old_value);
3214
838k
    if (ix == DKIX_ERROR) {
3215
0
        if (result) {
3216
0
            *result = NULL;
3217
0
        }
3218
0
        return -1;
3219
0
    }
3220
3221
838k
    if (ix == DKIX_EMPTY || old_value == NULL) {
3222
8.23k
        if (result) {
3223
4.31k
            *result = NULL;
3224
4.31k
        }
3225
8.23k
        return 0;
3226
8.23k
    }
3227
3228
838k
    assert(old_value != NULL);
3229
829k
    _PyDict_NotifyEvent(PyDict_EVENT_DELETED, mp, key, NULL);
3230
829k
    delitem_common(mp, hash, ix, Py_NewRef(old_value));
3231
3232
829k
    ASSERT_CONSISTENT(mp);
3233
829k
    if (result) {
3234
829k
        *result = old_value;
3235
829k
    }
3236
2
    else {
3237
2
        Py_DECREF(old_value);
3238
2
    }
3239
829k
    return 1;
3240
838k
}
3241
3242
static int
3243
pop_lock_held(PyObject *op, PyObject *key, PyObject **result)
3244
1.08M
{
3245
1.08M
    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
1.08M
    PyDictObject *dict = (PyDictObject *)op;
3258
1.08M
    assert(can_modify_dict(dict));
3259
3260
1.08M
    if (dict->ma_used == 0) {
3261
249k
        if (result) {
3262
249k
            *result = NULL;
3263
249k
        }
3264
249k
        return 0;
3265
249k
    }
3266
3267
838k
    Py_hash_t hash = _PyObject_HashFast(key);
3268
838k
    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
838k
    return _PyDict_Pop_KnownHash(dict, key, hash, result);
3276
838k
}
3277
3278
int
3279
PyDict_Pop(PyObject *op, PyObject *key, PyObject **result)
3280
1.08M
{
3281
1.08M
    int err;
3282
1.08M
    Py_BEGIN_CRITICAL_SECTION(op);
3283
1.08M
    err = pop_lock_held(op, key, result);
3284
1.08M
    Py_END_CRITICAL_SECTION();
3285
3286
1.08M
    return err;
3287
1.08M
}
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
506k
{
3310
506k
    PyObject *result;
3311
506k
    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
255k
    return result;
3319
506k
}
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
303
        if (values->embedded == 0) {
3538
9.33k
            for (i = 0, n = values->capacity; i < n; i++) {
3539
9.02k
                Py_XDECREF(values->values[i]);
3540
9.02k
            }
3541
303
            free_values(values, false);
3542
303
        }
3543
303
        dictkeys_decref(keys, false);
3544
303
    }
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
118M
        _Py_FREELIST_FREE(dicts, mp, Py_TYPE(mp)->tp_free);
3551
118M
    }
3552
45.3k
    else {
3553
45.3k
        Py_TYPE(mp)->tp_free((PyObject *)mp);
3554
45.3k
    }
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.2M
{
3663
10.2M
    return GET_USED(_PyAnyDict_CAST(self));
3664
10.2M
}
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.99M
{
3675
5.99M
    PyDictObject *mp = (PyDictObject *)self;
3676
5.99M
    Py_ssize_t ix;
3677
5.99M
    Py_hash_t hash;
3678
5.99M
    PyObject *value;
3679
3680
5.99M
    hash = _PyObject_HashFast(key);
3681
5.99M
    if (hash == -1) {
3682
0
        dict_unhashable_type(self, key);
3683
0
        return NULL;
3684
0
    }
3685
5.99M
    ix = _Py_dict_lookup_threadsafe(mp, key, hash, &value);
3686
5.99M
    if (ix == DKIX_ERROR)
3687
0
        return NULL;
3688
5.99M
    if (ix == DKIX_EMPTY || value == NULL) {
3689
12.2k
        if (!PyAnyDict_CheckExact(mp)) {
3690
            /* Look up __missing__ method if we're a subclass. */
3691
11.7k
            PyObject *missing, *res;
3692
11.7k
            missing = _PyObject_LookupSpecial(
3693
11.7k
                    (PyObject *)mp, &_Py_ID(__missing__));
3694
11.7k
            if (missing != NULL) {
3695
10.9k
                res = PyObject_CallOneArg(missing, key);
3696
10.9k
                Py_DECREF(missing);
3697
10.9k
                return res;
3698
10.9k
            }
3699
819
            else if (PyErr_Occurred())
3700
0
                return NULL;
3701
11.7k
        }
3702
1.31k
        _PyErr_SetKeyError(key);
3703
1.31k
        return NULL;
3704
12.2k
    }
3705
5.98M
    return value;
3706
5.99M
}
3707
3708
static int
3709
dict_ass_sub(PyObject *mp, PyObject *v, PyObject *w)
3710
320k
{
3711
320k
    if (w == NULL)
3712
311k
        return PyDict_DelItem(mp, v);
3713
8.85k
    else
3714
8.85k
        return PyDict_SetItem(mp, v, w);
3715
320k
}
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.8k
{
3726
17.8k
    ASSERT_DICT_LOCKED(dict);
3727
3728
17.8k
    if (dict == NULL || !PyAnyDict_Check(dict)) {
3729
0
        PyErr_BadInternalCall();
3730
0
        return NULL;
3731
0
    }
3732
17.8k
    PyDictObject *mp = (PyDictObject *)dict;
3733
17.8k
    PyObject *v;
3734
17.8k
    Py_ssize_t n;
3735
3736
17.8k
  again:
3737
17.8k
    n = mp->ma_used;
3738
17.8k
    v = PyList_New(n);
3739
17.8k
    if (v == NULL)
3740
0
        return NULL;
3741
17.8k
    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.8k
    Py_ssize_t j = 0, pos = 0;
3751
17.8k
    PyObject *key;
3752
705k
    while (_PyDict_Next((PyObject*)mp, &pos, &key, NULL, NULL)) {
3753
688k
        assert(j < n);
3754
688k
        PyList_SET_ITEM(v, j, Py_NewRef(key));
3755
688k
        j++;
3756
688k
    }
3757
17.8k
    assert(j == n);
3758
17.8k
    return v;
3759
17.8k
}
3760
3761
PyObject *
3762
PyDict_Keys(PyObject *dict)
3763
17.8k
{
3764
17.8k
    PyObject *res;
3765
17.8k
    Py_BEGIN_CRITICAL_SECTION(dict);
3766
17.8k
    res = keys_lock_held(dict);
3767
17.8k
    Py_END_CRITICAL_SECTION();
3768
3769
17.8k
    return res;
3770
17.8k
}
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
27.1k
{
3905
27.1k
    if (PyAnyDict_CheckExact(arg)) {
3906
26.1k
        return dict_merge(self, arg, 1, NULL);
3907
26.1k
    }
3908
943
    int has_keys = PyObject_HasAttrWithError(arg, &_Py_ID(keys));
3909
943
    if (has_keys < 0) {
3910
0
        return -1;
3911
0
    }
3912
943
    if (has_keys) {
3913
519
        return dict_merge(self, arg, 1, NULL);
3914
519
    }
3915
424
    return dict_merge_from_seq2(self, arg, 1);
3916
943
}
3917
3918
static int
3919
dict_update_common(PyObject *self, PyObject *args, PyObject *kwds,
3920
                   const char *methname)
3921
33.2k
{
3922
33.2k
    PyObject *arg = NULL;
3923
33.2k
    int result = 0;
3924
3925
33.2k
    if (!PyArg_UnpackTuple(args, methname, 0, 1, &arg)) {
3926
0
        result = -1;
3927
0
    }
3928
33.2k
    else if (arg != NULL) {
3929
10.5k
        result = dict_update_arg(self, arg);
3930
10.5k
    }
3931
3932
33.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
33.2k
    return result;
3939
33.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.5k
{
3947
10.5k
    if (dict_update_common(self, args, kwds, "update") != -1)
3948
10.5k
        Py_RETURN_NONE;
3949
0
    return NULL;
3950
10.5k
}
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
424
{
3965
424
    PyObject *it;       /* iter(seq2) */
3966
424
    Py_ssize_t i;       /* index into seq2 of current element */
3967
424
    PyObject *item;     /* seq2[i] */
3968
424
    PyObject *fast;     /* item as a 2-tuple or 2-list */
3969
3970
424
    assert(d != NULL);
3971
424
    assert(PyAnyDict_Check(d));
3972
424
    assert(seq2 != NULL);
3973
3974
424
    it = PyObject_GetIter(seq2);
3975
424
    if (it == NULL)
3976
0
        return -1;
3977
3978
5.13k
    for (i = 0; ; ++i) {
3979
5.13k
        PyObject *key, *value;
3980
5.13k
        Py_ssize_t n;
3981
3982
5.13k
        fast = NULL;
3983
5.13k
        item = PyIter_Next(it);
3984
5.13k
        if (item == NULL) {
3985
424
            if (PyErr_Occurred())
3986
0
                goto Fail;
3987
424
            break;
3988
424
        }
3989
3990
        /* Convert item to sequence, and verify length 2. */
3991
4.70k
        fast = PySequence_Fast(item, "object is not iterable");
3992
4.70k
        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.70k
        n = PySequence_Fast_GET_SIZE(fast);
4002
4.70k
        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.70k
        key = PySequence_Fast_GET_ITEM(fast, 0);
4012
4.70k
        value = PySequence_Fast_GET_ITEM(fast, 1);
4013
4.70k
        Py_INCREF(key);
4014
4.70k
        Py_INCREF(value);
4015
4.70k
        if (override) {
4016
4.70k
            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.70k
        }
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.70k
        Py_DECREF(key);
4031
4.70k
        Py_DECREF(value);
4032
4.70k
        Py_DECREF(fast);
4033
4.70k
        Py_DECREF(item);
4034
4.70k
    }
4035
4036
424
    i = 0;
4037
424
    ASSERT_CONSISTENT(d);
4038
424
    goto Return;
4039
0
Fail:
4040
0
    Py_XDECREF(item);
4041
0
    Py_XDECREF(fast);
4042
0
    i = -1;
4043
424
Return:
4044
424
    Py_DECREF(it);
4045
424
    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
424
{
4051
424
    int res;
4052
424
    Py_BEGIN_CRITICAL_SECTION(d);
4053
424
    res = merge_from_seq2_lock_held(d, seq2, override);
4054
424
    Py_END_CRITICAL_SECTION();
4055
4056
424
    return res;
4057
424
}
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.8M
{
4080
19.8M
    assert(can_modify_dict(mp));
4081
19.8M
    ASSERT_DICT_LOCKED(other);
4082
4083
19.8M
    if (other == mp || other->ma_used == 0)
4084
        /* a.update(a) or a.update({}); nothing to do */
4085
16.1M
        return 0;
4086
3.65M
    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.65M
        override = 1;
4092
3.65M
        PyDictKeysObject *okeys = other->ma_keys;
4093
4094
        // If other is clean, combined, and just allocated, just clone it.
4095
3.65M
        if (mp->ma_values == NULL &&
4096
3.65M
            other->ma_values == NULL &&
4097
3.65M
            other->ma_used == okeys->dk_nentries &&
4098
3.19M
            (DK_LOG_SIZE(okeys) == PyDict_LOG_MINSIZE ||
4099
900
             USABLE_FRACTION(DK_SIZE(okeys)/2) < other->ma_used)
4100
3.65M
        ) {
4101
3.19M
            _PyDict_NotifyEvent(PyDict_EVENT_CLONED, mp, (PyObject *)other, NULL);
4102
3.19M
            PyDictKeysObject *keys = clone_combined_dict_keys(other);
4103
3.19M
            if (keys == NULL)
4104
0
                return -1;
4105
4106
3.19M
            ensure_shared_on_resize(mp);
4107
3.19M
            dictkeys_decref(mp->ma_keys, IS_DICT_SHARED(mp));
4108
3.19M
            set_keys(mp, keys);
4109
3.19M
            STORE_USED(mp, other->ma_used);
4110
3.19M
            ASSERT_CONSISTENT(mp);
4111
4112
3.19M
            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.19M
            return 0;
4118
3.19M
        }
4119
3.65M
    }
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
455k
    if (USABLE_FRACTION(DK_SIZE(mp->ma_keys)) < other->ma_used) {
4125
451k
        int unicode = DK_IS_UNICODE(other->ma_keys);
4126
451k
        if (dictresize(mp, estimate_log2_keysize(mp->ma_used + other->ma_used),
4127
451k
                        unicode)) {
4128
0
            return -1;
4129
0
        }
4130
451k
    }
4131
4132
455k
    Py_ssize_t orig_size = other->ma_used;
4133
455k
    Py_ssize_t pos = 0;
4134
455k
    Py_hash_t hash;
4135
455k
    PyObject *key, *value;
4136
4137
1.64M
    while (_PyDict_Next((PyObject*)other, &pos, &key, &value, &hash)) {
4138
1.19M
        int err = 0;
4139
1.19M
        Py_INCREF(key);
4140
1.19M
        Py_INCREF(value);
4141
1.19M
        if (override == 1) {
4142
1.19M
            err = insertdict(mp, Py_NewRef(key), hash, Py_NewRef(value));
4143
1.19M
        }
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.19M
        Py_DECREF(value);
4159
1.19M
        Py_DECREF(key);
4160
1.19M
        if (err != 0)
4161
0
            return -1;
4162
4163
1.19M
        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.19M
    }
4169
455k
    return 0;
4170
455k
}
4171
4172
static int
4173
dict_merge(PyObject *a, PyObject *b, int override, PyObject **dupkey)
4174
19.8M
{
4175
19.8M
    assert(a != NULL);
4176
19.8M
    assert(b != NULL);
4177
19.8M
    assert(0 <= override && override <= 2);
4178
4179
19.8M
    PyDictObject *mp = _PyAnyDict_CAST(a);
4180
19.8M
    int res = 0;
4181
19.8M
    if (PyAnyDict_Check(b) && (Py_TYPE(b)->tp_iter == dict_iter)) {
4182
19.8M
        PyDictObject *other = (PyDictObject*)b;
4183
19.8M
        int res;
4184
19.8M
        Py_BEGIN_CRITICAL_SECTION2(a, b);
4185
19.8M
        res = dict_dict_merge((PyDictObject *)a, other, override, dupkey);
4186
19.8M
        ASSERT_CONSISTENT(a);
4187
19.8M
        Py_END_CRITICAL_SECTION2();
4188
19.8M
        return res;
4189
19.8M
    }
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.8M
}
4265
4266
static int
4267
dict_merge_api(PyObject *a, PyObject *b, int override, PyObject **dupkey)
4268
19.8M
{
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.8M
    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.8M
    return dict_merge(a, b, override, dupkey);
4284
19.8M
}
4285
4286
int
4287
PyDict_Update(PyObject *a, PyObject *b)
4288
70.3k
{
4289
70.3k
    return dict_merge_api(a, b, 1, NULL);
4290
70.3k
}
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.7M
{
4302
19.7M
    return dict_merge_api(a, b, 2, dupkey);
4303
19.7M
}
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.16M
{
4315
1.16M
    return PyDict_Copy((PyObject *)self);
4316
1.16M
}
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.65M
{
4342
1.65M
    PyObject *copy;
4343
1.65M
    PyDictObject *mp;
4344
4345
    // frozendict is immutable and so doesn't need critical section
4346
1.65M
    if (!PyFrozenDict_Check(o)) {
4347
1.65M
        ASSERT_DICT_LOCKED(o);
4348
1.65M
    }
4349
4350
1.65M
    mp = (PyDictObject *)o;
4351
1.65M
    if (mp->ma_used == 0) {
4352
        /* The dict is empty; just return a new dict. */
4353
1.21M
        if (as_frozendict) {
4354
0
            return PyFrozenDict_New(NULL);
4355
0
        }
4356
1.21M
        else {
4357
1.21M
            return PyDict_New();
4358
1.21M
        }
4359
1.21M
    }
4360
4361
432k
    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
426k
    if (Py_TYPE(mp)->tp_iter == dict_iter &&
4395
426k
            mp->ma_values == NULL &&
4396
426k
            (mp->ma_used >= (mp->ma_keys->dk_nentries * 2) / 3))
4397
426k
    {
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
426k
        PyDictKeysObject *keys = clone_combined_dict_keys(mp);
4413
426k
        if (keys == NULL) {
4414
0
            return NULL;
4415
0
        }
4416
426k
        PyDictObject *new;
4417
426k
        if (as_frozendict) {
4418
0
            new = (PyDictObject *)new_frozendict(keys, NULL, 0, 0);
4419
0
        }
4420
426k
        else {
4421
426k
            new = (PyDictObject *)new_dict(keys, NULL, 0, 0);
4422
426k
        }
4423
426k
        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
426k
        new->ma_used = mp->ma_used;
4430
426k
        ASSERT_CONSISTENT(new);
4431
426k
        return (PyObject *)new;
4432
426k
    }
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.41M
{
4451
1.41M
    if (o == NULL || !PyDict_Check(o)) {
4452
0
        PyErr_BadInternalCall();
4453
0
        return NULL;
4454
0
    }
4455
4456
1.41M
    PyObject *res;
4457
1.41M
    Py_BEGIN_CRITICAL_SECTION(o);
4458
1.41M
    res = copy_lock_held(o, 0);
4459
1.41M
    Py_END_CRITICAL_SECTION();
4460
1.41M
    return res;
4461
1.41M
}
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
241k
{
4487
241k
    assert(PyAnyDict_Check(o));
4488
4489
241k
    PyObject *res;
4490
241k
    if (PyFrozenDict_Check(o)) {
4491
0
        res = copy_lock_held(o, 0);
4492
0
    }
4493
241k
    else {
4494
241k
        Py_BEGIN_CRITICAL_SECTION(o);
4495
241k
        res = copy_lock_held(o, 0);
4496
241k
        Py_END_CRITICAL_SECTION();
4497
241k
    }
4498
241k
    return res;
4499
241k
}
4500
4501
Py_ssize_t
4502
PyDict_Size(PyObject *mp)
4503
454k
{
4504
454k
    if (mp == NULL || !PyAnyDict_Check(mp)) {
4505
0
        PyErr_BadInternalCall();
4506
0
        return -1;
4507
0
    }
4508
454k
    return GET_USED((PyDictObject *)mp);
4509
454k
}
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.3k
{
4518
11.3k
    Py_ssize_t i;
4519
4520
11.3k
    ASSERT_DICT_LOCKED(a);
4521
11.3k
    ASSERT_DICT_LOCKED(b);
4522
4523
11.3k
    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.5k
    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.3k
    return 1;
4575
11.3k
}
4576
4577
static int
4578
dict_equal(PyDictObject *a, PyDictObject *b)
4579
11.3k
{
4580
11.3k
    int res;
4581
11.3k
    Py_BEGIN_CRITICAL_SECTION2(a, b);
4582
11.3k
    res = dict_equal_lock_held(a, b);
4583
11.3k
    Py_END_CRITICAL_SECTION2();
4584
4585
11.3k
    return res;
4586
11.3k
}
4587
4588
static PyObject *
4589
dict_richcompare(PyObject *v, PyObject *w, int op)
4590
11.3k
{
4591
11.3k
    int cmp;
4592
11.3k
    PyObject *res;
4593
4594
11.3k
    if (!PyAnyDict_Check(v) || !PyAnyDict_Check(w)) {
4595
0
        res = Py_NotImplemented;
4596
0
    }
4597
11.3k
    else if (op == Py_EQ || op == Py_NE) {
4598
11.3k
        cmp = dict_equal((PyDictObject *)v, (PyDictObject *)w);
4599
11.3k
        if (cmp < 0)
4600
0
            return NULL;
4601
11.3k
        res = (cmp == (op == Py_EQ)) ? Py_True : Py_False;
4602
11.3k
    }
4603
0
    else
4604
0
        res = Py_NotImplemented;
4605
11.3k
    return Py_NewRef(res);
4606
11.3k
}
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
91.9M
{
4647
91.9M
    PyObject *val = NULL;
4648
91.9M
    Py_hash_t hash;
4649
91.9M
    Py_ssize_t ix;
4650
4651
91.9M
    hash = _PyObject_HashFast(key);
4652
91.9M
    if (hash == -1) {
4653
0
        dict_unhashable_type((PyObject*)self, key);
4654
0
        return NULL;
4655
0
    }
4656
91.9M
    ix = _Py_dict_lookup_threadsafe(self, key, hash, &val);
4657
91.9M
    if (ix == DKIX_ERROR)
4658
0
        return NULL;
4659
91.9M
    if (ix == DKIX_EMPTY || val == NULL) {
4660
71.3M
        val = Py_NewRef(default_value);
4661
71.3M
    }
4662
91.9M
    return val;
4663
91.9M
}
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
351k
        if (insert_to_emptydict(mp, Py_NewRef(key), hash,
4699
351k
                                Py_NewRef(default_value)) < 0) {
4700
0
            if (result) {
4701
0
                *result = NULL;
4702
0
            }
4703
0
            return -1;
4704
0
        }
4705
351k
        if (result) {
4706
351k
            *result = incref_result ? Py_NewRef(default_value) : default_value;
4707
351k
        }
4708
351k
        return 0;
4709
351k
    }
4710
4711
14.1M
    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
                insert_split_value(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.1M
    else {
4728
14.1M
        ix = _Py_dict_lookup(mp, key, hash, &value);
4729
14.1M
        if (ix == DKIX_ERROR) {
4730
0
            if (result) {
4731
0
                *result = NULL;
4732
0
            }
4733
0
            return -1;
4734
0
        }
4735
14.1M
    }
4736
4737
14.1M
    if (ix == DKIX_EMPTY) {
4738
1.34M
        value = default_value;
4739
4740
        // See comment to this function in insertdict.
4741
1.34M
        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.34M
        STORE_USED(mp, mp->ma_used + 1);
4751
1.34M
        assert(mp->ma_keys->dk_usable >= 0);
4752
1.34M
        ASSERT_CONSISTENT(mp);
4753
1.34M
        if (result) {
4754
1.27M
            *result = incref_result ? Py_NewRef(value) : value;
4755
1.27M
        }
4756
1.34M
        return 0;
4757
1.34M
    }
4758
4759
14.1M
    assert(value != NULL);
4760
12.7M
    ASSERT_CONSISTENT(mp);
4761
12.7M
    if (result) {
4762
12.7M
        *result = incref_result ? Py_NewRef(value) : value;
4763
12.7M
    }
4764
12.7M
    return 1;
4765
14.1M
}
4766
4767
int
4768
PyDict_SetDefaultRef(PyObject *d, PyObject *key, PyObject *default_value,
4769
                     PyObject **result)
4770
7.07M
{
4771
7.07M
    int res;
4772
7.07M
    Py_BEGIN_CRITICAL_SECTION(d);
4773
7.07M
    res = dict_setdefault_ref_lock_held(d, key, default_value, result, 1);
4774
7.07M
    Py_END_CRITICAL_SECTION();
4775
7.07M
    return res;
4776
7.07M
}
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
7.39M
{
4806
7.39M
    PyObject *val;
4807
7.39M
    dict_setdefault_ref_lock_held((PyObject *)self, key, default_value, &val, 1);
4808
7.39M
    return val;
4809
7.39M
}
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
506k
{
4844
506k
    return dict_pop_default((PyObject*)self, key, default_value);
4845
506k
}
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
634k
{
4861
634k
    assert(can_modify_dict(self));
4862
4863
634k
    Py_ssize_t i, j;
4864
634k
    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
634k
    res = PyTuple_New(2);
4876
634k
    if (res == NULL)
4877
0
        return NULL;
4878
634k
    if (self->ma_used == 0) {
4879
317k
        Py_DECREF(res);
4880
317k
        PyErr_SetString(PyExc_KeyError, "popitem(): dictionary is empty");
4881
317k
        return NULL;
4882
317k
    }
4883
    /* Convert split table to combined table */
4884
317k
    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
317k
    FT_ATOMIC_STORE_UINT32_RELAXED(self->ma_keys->dk_version, 0);
4891
4892
    /* Pop last item */
4893
317k
    PyObject *key, *value;
4894
317k
    Py_hash_t hash;
4895
317k
    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
317k
    else {
4911
317k
        PyDictKeyEntry *ep0 = DK_ENTRIES(self->ma_keys);
4912
317k
        i = self->ma_keys->dk_nentries - 1;
4913
317k
        while (i >= 0 && ep0[i].me_value == NULL) {
4914
0
            i--;
4915
0
        }
4916
317k
        assert(i >= 0);
4917
4918
317k
        key = ep0[i].me_key;
4919
317k
        _PyDict_NotifyEvent(PyDict_EVENT_DELETED, self, key, NULL);
4920
317k
        hash = ep0[i].me_hash;
4921
317k
        value = ep0[i].me_value;
4922
317k
        STORE_KEY(&ep0[i], NULL);
4923
317k
        STORE_HASH(&ep0[i], -1);
4924
317k
        STORE_VALUE(&ep0[i], NULL);
4925
317k
    }
4926
4927
317k
    j = lookdict_index(self->ma_keys, hash, i);
4928
317k
    assert(j >= 0);
4929
317k
    assert(dictkeys_get_index(self->ma_keys, j) == i);
4930
317k
    dictkeys_set_index(self->ma_keys, j, DKIX_DUMMY);
4931
4932
317k
    PyTuple_SET_ITEM(res, 0, key);
4933
317k
    PyTuple_SET_ITEM(res, 1, value);
4934
    /* We can't dk_usable++ since there is DKIX_DUMMY in indices */
4935
317k
    STORE_KEYS_NENTRIES(self->ma_keys, i);
4936
317k
    STORE_USED(self, self->ma_used - 1);
4937
317k
    ASSERT_CONSISTENT(self);
4938
317k
    return res;
4939
317k
}
4940
4941
static int
4942
dict_traverse(PyObject *op, visitproc visit, void *arg)
4943
30.8M
{
4944
30.8M
    PyDictObject *mp = (PyDictObject *)op;
4945
30.8M
    PyDictKeysObject *keys = mp->ma_keys;
4946
30.8M
    Py_ssize_t i, n = keys->dk_nentries;
4947
4948
30.8M
    if (DK_IS_UNICODE(keys)) {
4949
29.3M
        if (_PyDict_HasSplitTable(mp)) {
4950
6.70M
            for (i = 0; i < n; i++) {
4951
5.85M
                Py_VISIT(mp->ma_values->values[i]);
4952
5.85M
            }
4953
845k
        }
4954
28.5M
        else {
4955
28.5M
            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.5M
        }
4960
29.3M
    }
4961
1.51M
    else {
4962
1.51M
        PyDictKeyEntry *entries = DK_ENTRIES(keys);
4963
62.7M
        for (i = 0; i < n; i++) {
4964
61.2M
            if (entries[i].me_value != NULL) {
4965
59.8M
                Py_VISIT(entries[i].me_value);
4966
59.8M
                Py_VISIT(entries[i].me_key);
4967
59.8M
            }
4968
61.2M
        }
4969
1.51M
    }
4970
30.8M
    return 0;
4971
30.8M
}
4972
4973
static int
4974
dict_tp_clear(PyObject *op)
4975
220k
{
4976
220k
    PyDict_Clear(op);
4977
220k
    return 0;
4978
220k
}
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.62M
{
5023
3.62M
    size_t es = (keys->dk_kind == DICT_KEYS_GENERAL
5024
3.62M
                 ? sizeof(PyDictKeyEntry) : sizeof(PyDictUnicodeEntry));
5025
3.62M
    size_t size = sizeof(PyDictKeysObject);
5026
3.62M
    size += (size_t)1 << keys->dk_log2_index_bytes;
5027
3.62M
    size += USABLE_FRACTION((size_t)DK_SIZE(keys)) * es;
5028
3.62M
    return size;
5029
3.62M
}
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
static PyObject *
5045
dict_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 dict_or(self, other);
5081
0
}
5082
5083
5084
static PyObject *
5085
dict_ior(PyObject *self, PyObject *other)
5086
132
{
5087
132
    if (dict_update_arg(self, other)) {
5088
0
        return NULL;
5089
0
    }
5090
132
    return Py_NewRef(self);
5091
132
}
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
462M
{
5129
462M
    Py_hash_t hash = _PyObject_HashFast(key);
5130
462M
    if (hash == -1) {
5131
0
        dict_unhashable_type(op, key);
5132
0
        return -1;
5133
0
    }
5134
5135
462M
    return _PyDict_Contains_KnownHash(op, key, hash);
5136
462M
}
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
462M
{
5142
462M
    if (!PyAnyDict_Check(op)) {
5143
0
        PyErr_BadInternalCall();
5144
0
        return -1;
5145
0
    }
5146
5147
462M
    return dict_contains(op, key);
5148
462M
}
5149
5150
int
5151
PyDict_ContainsString(PyObject *op, const char *key)
5152
2.50k
{
5153
2.50k
    PyObject *key_obj = PyUnicode_FromString(key);
5154
2.50k
    if (key_obj == NULL) {
5155
0
        return -1;
5156
0
    }
5157
2.50k
    int res = PyDict_Contains(op, key_obj);
5158
2.50k
    Py_DECREF(key_obj);
5159
2.50k
    return res;
5160
2.50k
}
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
462M
{
5166
462M
    PyDictObject *mp = _PyAnyDict_CAST(op);
5167
462M
    PyObject *value;
5168
462M
    Py_ssize_t ix;
5169
5170
#ifdef Py_GIL_DISABLED
5171
    ix = _Py_dict_lookup_threadsafe(mp, key, hash, &value);
5172
#else
5173
462M
    ix = _Py_dict_lookup(mp, key, hash, &value);
5174
462M
#endif
5175
462M
    if (ix == DKIX_ERROR)
5176
0
        return -1;
5177
462M
    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
462M
}
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 = dict_or,
5202
    .nb_inplace_or = dict_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
22.7k
{
5235
22.7k
    return dict_update_common(self, args, kwds, "dict");
5236
22.7k
}
5237
5238
static PyObject *
5239
dict_vectorcall(PyObject *type, PyObject * const*args,
5240
                size_t nargsf, PyObject *kwnames)
5241
1.50M
{
5242
1.50M
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
5243
1.50M
    if (!_PyArg_CheckPositional("dict", nargs, 0, 1)) {
5244
0
        return NULL;
5245
0
    }
5246
5247
1.50M
    PyObject *self = dict_new(_PyType_CAST(type), NULL, NULL);
5248
1.50M
    if (self == NULL) {
5249
0
        return NULL;
5250
0
    }
5251
1.50M
    if (nargs == 1) {
5252
16.2k
        if (dict_update_arg(self, args[0]) < 0) {
5253
0
            Py_DECREF(self);
5254
0
            return NULL;
5255
0
        }
5256
16.2k
        args++;
5257
16.2k
    }
5258
1.50M
    if (kwnames != NULL) {
5259
113k
        for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(kwnames); i++) {
5260
89.2k
            PyObject *key = PyTuple_GET_ITEM(kwnames, i);  // borrowed
5261
89.2k
            if (PyDict_SetItem(self, key, args[i]) < 0) {
5262
0
                Py_DECREF(self);
5263
0
                return NULL;
5264
0
            }
5265
89.2k
        }
5266
24.3k
    }
5267
1.50M
    return self;
5268
1.50M
}
5269
5270
static PyObject *
5271
frozendict_vectorcall(PyObject *type, PyObject * const*args,
5272
                      size_t nargsf, PyObject *kwnames)
5273
285
{
5274
285
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
5275
285
    if (!_PyArg_CheckPositional("frozendict", nargs, 0, 1)) {
5276
0
        return NULL;
5277
0
    }
5278
5279
285
    if (nargs == 1 && kwnames == NULL
5280
285
        && 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
285
    PyObject *self = frozendict_new(_PyType_CAST(type), NULL, NULL);
5288
285
    if (self == NULL) {
5289
0
        return NULL;
5290
0
    }
5291
285
    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
285
    if (kwnames != NULL) {
5299
2.70k
        for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(kwnames); i++) {
5300
2.50k
            PyObject *key = PyTuple_GET_ITEM(kwnames, i);  // borrowed
5301
2.50k
            if (_PyAnyDict_SetItem(self, key, args[i]) < 0) {
5302
0
                Py_DECREF(self);
5303
0
                return NULL;
5304
0
            }
5305
2.50k
        }
5306
204
    }
5307
285
    return self;
5308
285
}
5309
5310
static PyObject *
5311
dict_iter(PyObject *self)
5312
243k
{
5313
243k
    PyDictObject *dict = (PyDictObject *)self;
5314
243k
    return dictiter_new(dict, &PyDictIterKey_Type);
5315
243k
}
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.70M
{
5398
2.70M
    PyObject *key_obj = PyUnicode_FromString(key);
5399
2.70M
    if (key_obj == NULL) {
5400
0
        *result = NULL;
5401
0
        return -1;
5402
0
    }
5403
2.70M
    int res = PyDict_GetItemRef(v, key_obj, result);
5404
2.70M
    Py_DECREF(key_obj);
5405
2.70M
    return res;
5406
2.70M
}
5407
5408
int
5409
PyDict_SetItemString(PyObject *v, const char *key, PyObject *item)
5410
45.1k
{
5411
45.1k
    PyObject *kv;
5412
45.1k
    int err;
5413
45.1k
    kv = PyUnicode_FromString(key);
5414
45.1k
    if (kv == NULL)
5415
0
        return -1;
5416
45.1k
    PyInterpreterState *interp = _PyInterpreterState_GET();
5417
45.1k
    _PyUnicode_InternImmortal(interp, &kv); /* XXX Should we really? */
5418
45.1k
    err = PyDict_SetItem(v, kv, item);
5419
45.1k
    Py_DECREF(kv);
5420
45.1k
    return err;
5421
45.1k
}
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.85M
{
5450
2.85M
    Py_ssize_t used;
5451
2.85M
    dictiterobject *di;
5452
2.85M
    di = PyObject_GC_New(dictiterobject, itertype);
5453
2.85M
    if (di == NULL) {
5454
0
        return NULL;
5455
0
    }
5456
2.85M
    di->di_dict = (PyDictObject*)Py_NewRef(dict);
5457
2.85M
    used = GET_USED(dict);
5458
2.85M
    di->di_used = used;
5459
2.85M
    di->len = used;
5460
2.85M
    if (itertype == &PyDictRevIterKey_Type ||
5461
2.85M
         itertype == &PyDictRevIterItem_Type ||
5462
2.85M
         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.85M
    else {
5471
2.85M
        di->di_pos = 0;
5472
2.85M
    }
5473
2.85M
    if (itertype == &PyDictIterItem_Type ||
5474
2.33M
        itertype == &PyDictRevIterItem_Type) {
5475
2.33M
        di->di_result = _PyTuple_FromPairSteal(Py_None, Py_None);
5476
2.33M
        if (di->di_result == NULL) {
5477
0
            Py_DECREF(di);
5478
0
            return NULL;
5479
0
        }
5480
2.33M
    }
5481
524k
    else {
5482
524k
        di->di_result = NULL;
5483
524k
    }
5484
2.85M
    _PyObject_GC_TRACK(di);
5485
2.85M
    return (PyObject *)di;
5486
2.85M
}
5487
5488
static void
5489
dictiter_dealloc(PyObject *self)
5490
2.85M
{
5491
2.85M
    dictiterobject *di = (dictiterobject *)self;
5492
    /* bpo-31095: UnTrack is needed before calling any callbacks */
5493
2.85M
    _PyObject_GC_UNTRACK(di);
5494
2.85M
    Py_XDECREF(di->di_dict);
5495
2.85M
    Py_XDECREF(di->di_result);
5496
2.85M
    PyObject_GC_Del(di);
5497
2.85M
}
5498
5499
static int
5500
dictiter_traverse(PyObject *self, visitproc visit, void *arg)
5501
1.73k
{
5502
1.73k
    dictiterobject *di = (dictiterobject *)self;
5503
1.73k
    Py_VISIT(di->di_dict);
5504
1.73k
    Py_VISIT(di->di_result);
5505
1.73k
    return 0;
5506
1.73k
}
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.30M
{
5545
2.30M
    dictiterobject *di = (dictiterobject *)self;
5546
2.30M
    PyObject *key;
5547
2.30M
    Py_ssize_t i;
5548
2.30M
    PyDictKeysObject *k;
5549
5550
2.30M
    assert (PyAnyDict_Check(d));
5551
2.30M
    ASSERT_DICT_LOCKED(d);
5552
5553
2.30M
    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.30M
    i = di->di_pos;
5561
2.30M
    k = d->ma_keys;
5562
2.30M
    assert(i >= 0);
5563
2.30M
    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.30M
    else {
5571
2.30M
        Py_ssize_t n = k->dk_nentries;
5572
2.30M
        if (DK_IS_UNICODE(k)) {
5573
1.92M
            PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(k)[i];
5574
2.00M
            while (i < n && entry_ptr->me_value == NULL) {
5575
79.8k
                entry_ptr++;
5576
79.8k
                i++;
5577
79.8k
            }
5578
1.92M
            if (i >= n)
5579
287k
                goto fail;
5580
1.64M
            key = entry_ptr->me_key;
5581
1.64M
        }
5582
377k
        else {
5583
377k
            PyDictKeyEntry *entry_ptr = &DK_ENTRIES(k)[i];
5584
377k
            while (i < n && entry_ptr->me_value == NULL) {
5585
0
                entry_ptr++;
5586
0
                i++;
5587
0
            }
5588
377k
            if (i >= n)
5589
75.4k
                goto fail;
5590
301k
            key = entry_ptr->me_key;
5591
301k
        }
5592
2.30M
    }
5593
    // We found an element (key), but did not expect it
5594
1.94M
    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.94M
    di->di_pos = i+1;
5600
1.94M
    di->len--;
5601
1.94M
    return Py_NewRef(key);
5602
5603
363k
fail:
5604
363k
    di->di_dict = NULL;
5605
363k
    Py_DECREF(d);
5606
363k
    return NULL;
5607
1.94M
}
5608
5609
#endif  /* Py_GIL_DISABLED */
5610
5611
static PyObject*
5612
dictiter_iternextkey(PyObject *self)
5613
2.30M
{
5614
2.30M
    dictiterobject *di = (dictiterobject *)self;
5615
2.30M
    PyDictObject *d = di->di_dict;
5616
5617
2.30M
    if (d == NULL)
5618
0
        return NULL;
5619
5620
2.30M
    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.30M
    value = dictiter_iternextkey_lock_held(d, self);
5627
2.30M
#endif
5628
5629
2.30M
    return value;
5630
2.30M
}
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
780k
{
5670
780k
    dictiterobject *di = (dictiterobject *)self;
5671
780k
    PyObject *value;
5672
780k
    Py_ssize_t i;
5673
5674
780k
    assert (PyAnyDict_Check(d));
5675
780k
    ASSERT_DICT_LOCKED(d);
5676
5677
780k
    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
780k
    i = di->di_pos;
5685
780k
    assert(i >= 0);
5686
780k
    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
780k
    else {
5694
780k
        Py_ssize_t n = d->ma_keys->dk_nentries;
5695
780k
        if (DK_IS_UNICODE(d->ma_keys)) {
5696
16.9k
            PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(d->ma_keys)[i];
5697
17.0k
            while (i < n && entry_ptr->me_value == NULL) {
5698
88
                entry_ptr++;
5699
88
                i++;
5700
88
            }
5701
16.9k
            if (i >= n)
5702
973
                goto fail;
5703
16.0k
            value = entry_ptr->me_value;
5704
16.0k
        }
5705
763k
        else {
5706
763k
            PyDictKeyEntry *entry_ptr = &DK_ENTRIES(d->ma_keys)[i];
5707
763k
            while (i < n && entry_ptr->me_value == NULL) {
5708
0
                entry_ptr++;
5709
0
                i++;
5710
0
            }
5711
763k
            if (i >= n)
5712
150k
                goto fail;
5713
613k
            value = entry_ptr->me_value;
5714
613k
        }
5715
780k
    }
5716
    // We found an element, but did not expect it
5717
629k
    if (di->len == 0) {
5718
0
        PyErr_SetString(PyExc_RuntimeError,
5719
0
                        "dictionary keys changed during iteration");
5720
0
        goto fail;
5721
0
    }
5722
629k
    di->di_pos = i+1;
5723
629k
    di->len--;
5724
629k
    return Py_NewRef(value);
5725
5726
151k
fail:
5727
151k
    di->di_dict = NULL;
5728
151k
    Py_DECREF(d);
5729
151k
    return NULL;
5730
629k
}
5731
5732
#endif  /* Py_GIL_DISABLED */
5733
5734
static PyObject *
5735
dictiter_iternextvalue(PyObject *self)
5736
780k
{
5737
780k
    dictiterobject *di = (dictiterobject *)self;
5738
780k
    PyDictObject *d = di->di_dict;
5739
5740
780k
    if (d == NULL)
5741
0
        return NULL;
5742
5743
780k
    PyObject *value;
5744
#ifdef Py_GIL_DISABLED
5745
    if (dictiter_iternext_threadsafe(d, self, NULL, &value) < 0) {
5746
        value = NULL;
5747
    }
5748
#else
5749
780k
    value = dictiter_iternextvalue_lock_held(d, self);
5750
780k
#endif
5751
5752
780k
    return value;
5753
780k
}
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.58M
{
5792
5.58M
    dictiterobject *di = (dictiterobject *)self;
5793
5.58M
    PyObject *key, *value;
5794
5.58M
    Py_ssize_t i;
5795
5796
5.58M
    assert (PyAnyDict_Check(d));
5797
5.58M
    ASSERT_DICT_LOCKED(d);
5798
5799
5.58M
    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.58M
    i = FT_ATOMIC_LOAD_SSIZE_RELAXED(di->di_pos);
5807
5808
5.58M
    assert(i >= 0);
5809
5.58M
    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.58M
    else {
5818
5.58M
        Py_ssize_t n = d->ma_keys->dk_nentries;
5819
5.58M
        if (DK_IS_UNICODE(d->ma_keys)) {
5820
4.82M
            PyDictUnicodeEntry *entry_ptr = &DK_UNICODE_ENTRIES(d->ma_keys)[i];
5821
4.82M
            while (i < n && entry_ptr->me_value == NULL) {
5822
5.97k
                entry_ptr++;
5823
5.97k
                i++;
5824
5.97k
            }
5825
4.82M
            if (i >= n)
5826
1.94M
                goto fail;
5827
2.87M
            key = entry_ptr->me_key;
5828
2.87M
            value = entry_ptr->me_value;
5829
2.87M
        }
5830
760k
        else {
5831
760k
            PyDictKeyEntry *entry_ptr = &DK_ENTRIES(d->ma_keys)[i];
5832
760k
            while (i < n && entry_ptr->me_value == NULL) {
5833
0
                entry_ptr++;
5834
0
                i++;
5835
0
            }
5836
760k
            if (i >= n)
5837
380k
                goto fail;
5838
380k
            key = entry_ptr->me_key;
5839
380k
            value = entry_ptr->me_value;
5840
380k
        }
5841
5.58M
    }
5842
    // We found an element, but did not expect it
5843
3.25M
    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.25M
    di->di_pos = i+1;
5849
3.25M
    di->len--;
5850
3.25M
    if (out_key != NULL) {
5851
3.25M
        *out_key = Py_NewRef(key);
5852
3.25M
    }
5853
3.25M
    if (out_value != NULL) {
5854
3.25M
        *out_value = Py_NewRef(value);
5855
3.25M
    }
5856
3.25M
    return 0;
5857
5858
2.32M
fail:
5859
2.32M
    di->di_dict = NULL;
5860
2.32M
    Py_DECREF(d);
5861
2.32M
    return -1;
5862
3.25M
}
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.25M
{
6005
3.25M
    if (_PyObject_IsUniquelyReferenced(result)) {
6006
3.23M
        Py_INCREF(result);
6007
3.23M
        return true;
6008
3.23M
    }
6009
24.1k
    return false;
6010
3.25M
}
6011
6012
static PyObject *
6013
dictiter_iternextitem(PyObject *self)
6014
5.58M
{
6015
5.58M
    dictiterobject *di = (dictiterobject *)self;
6016
5.58M
    PyDictObject *d = di->di_dict;
6017
6018
5.58M
    if (d == NULL)
6019
0
        return NULL;
6020
6021
5.58M
    PyObject *key, *value;
6022
#ifdef Py_GIL_DISABLED
6023
    if (dictiter_iternext_threadsafe(d, self, &key, &value) == 0) {
6024
#else
6025
5.58M
    if (dictiter_iternextitem_lock_held(d, self, &key, &value) == 0) {
6026
6027
3.25M
#endif
6028
3.25M
        PyObject *result = di->di_result;
6029
3.25M
        if (acquire_iter_result(result)) {
6030
3.23M
            PyObject *oldkey = PyTuple_GET_ITEM(result, 0);
6031
3.23M
            PyObject *oldvalue = PyTuple_GET_ITEM(result, 1);
6032
3.23M
            PyTuple_SET_ITEM(result, 0, key);
6033
3.23M
            PyTuple_SET_ITEM(result, 1, value);
6034
3.23M
            Py_DECREF(oldkey);
6035
3.23M
            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.23M
            _PyTuple_Recycle(result);
6039
3.23M
        }
6040
24.1k
        else {
6041
24.1k
            result = _PyTuple_FromPairSteal(key, value);
6042
24.1k
        }
6043
3.25M
        return result;
6044
3.25M
    }
6045
2.32M
    return NULL;
6046
5.58M
}
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.70M
{
6266
2.70M
    _PyDictViewObject *dv = (_PyDictViewObject *)self;
6267
    /* bpo-31095: UnTrack is needed before calling any callbacks */
6268
2.70M
    _PyObject_GC_UNTRACK(dv);
6269
2.70M
    Py_XDECREF(dv->dv_dict);
6270
2.70M
    PyObject_GC_Del(dv);
6271
2.70M
}
6272
6273
static int
6274
dictview_traverse(PyObject *self, visitproc visit, void *arg)
6275
19
{
6276
19
    _PyDictViewObject *dv = (_PyDictViewObject *)self;
6277
19
    Py_VISIT(dv->dv_dict);
6278
19
    return 0;
6279
19
}
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.70M
{
6294
2.70M
    _PyDictViewObject *dv;
6295
2.70M
    if (dict == NULL) {
6296
0
        PyErr_BadInternalCall();
6297
0
        return NULL;
6298
0
    }
6299
2.70M
    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.70M
    dv = PyObject_GC_New(_PyDictViewObject, type);
6307
2.70M
    if (dv == NULL)
6308
0
        return NULL;
6309
2.70M
    dv->dv_dict = (PyDictObject *)Py_NewRef(dict);
6310
2.70M
    _PyObject_GC_TRACK(dv);
6311
2.70M
    return (PyObject *)dv;
6312
2.70M
}
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
120k
{
6452
120k
    _PyDictViewObject *dv = (_PyDictViewObject *)self;
6453
120k
    if (dv->dv_dict == NULL) {
6454
0
        Py_RETURN_NONE;
6455
0
    }
6456
120k
    return dictiter_new(dv->dv_dict, &PyDictIterKey_Type);
6457
120k
}
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
120k
{
6869
120k
    return _PyDictView_New((PyObject *)self, &PyDictKeys_Type);
6870
120k
}
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.33M
{
6887
2.33M
    _PyDictViewObject *dv = (_PyDictViewObject *)self;
6888
2.33M
    if (dv->dv_dict == NULL) {
6889
0
        Py_RETURN_NONE;
6890
0
    }
6891
2.33M
    return dictiter_new(dv->dv_dict, &PyDictIterItem_Type);
6892
2.33M
}
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.33M
{
6981
2.33M
    return _PyDictView_New((PyObject *)self, &PyDictItems_Type);
6982
2.33M
}
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
161k
{
6999
161k
    _PyDictViewObject *dv = (_PyDictViewObject *)self;
7000
161k
    if (dv->dv_dict == NULL) {
7001
0
        Py_RETURN_NONE;
7002
0
    }
7003
161k
    return dictiter_new(dv->dv_dict, &PyDictIterValue_Type);
7004
161k
}
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
161k
{
7071
161k
    return _PyDictView_New((PyObject *)self, &PyDictValues_Type);
7072
161k
}
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
235k
{
7090
235k
    PyDictKeysObject *keys = new_keys_object(NEXT_LOG2_SHARED_KEYS_MAX_SIZE, 1);
7091
235k
    if (keys == NULL) {
7092
0
        PyErr_Clear();
7093
0
    }
7094
235k
    else {
7095
235k
        assert(keys->dk_nentries == 0);
7096
        /* Set to max size+1 as it will shrink by one before each new object */
7097
235k
        keys->dk_usable = SHARED_KEYS_MAX_SIZE;
7098
235k
        keys->dk_kind = DICT_KEYS_SPLIT;
7099
235k
    }
7100
235k
    if (cls->ht_type.tp_dict) {
7101
235k
        PyObject *attrs = PyDict_GetItem(cls->ht_type.tp_dict, &_Py_ID(__static_attributes__));
7102
235k
        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
235k
    }
7114
235k
    return keys;
7115
235k
}
7116
7117
void
7118
_PyObject_InitInlineValues(PyObject *obj, PyTypeObject *tp)
7119
33.3M
{
7120
33.3M
    assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE);
7121
33.3M
    assert(tp->tp_flags & Py_TPFLAGS_INLINE_VALUES);
7122
33.3M
    assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
7123
33.3M
    PyDictKeysObject *keys = CACHED_KEYS(tp);
7124
33.3M
    assert(keys != NULL);
7125
33.3M
    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.3M
    if (keys->dk_usable > 1) {
7137
241k
        keys->dk_usable--;
7138
241k
    }
7139
33.3M
#endif
7140
33.3M
    size_t size = shared_keys_usable_size(keys);
7141
33.3M
    PyDictValues *values = _PyObject_InlineValues(obj);
7142
33.3M
    assert(size < 256);
7143
33.3M
    values->capacity = (uint8_t)size;
7144
33.3M
    values->size = 0;
7145
33.3M
    values->embedded = 1;
7146
33.3M
    values->valid = 1;
7147
211M
    for (size_t i = 0; i < size; i++) {
7148
178M
        values->values[i] = NULL;
7149
178M
    }
7150
33.3M
    _PyObject_ManagedDictPointer(obj)->dict = NULL;
7151
33.3M
}
7152
7153
static PyDictObject *
7154
make_dict_from_instance_attributes(PyDictKeysObject *keys, PyDictValues *values)
7155
598k
{
7156
598k
    dictkeys_incref(keys);
7157
598k
    Py_ssize_t used = 0;
7158
598k
    size_t size = shared_keys_usable_size(keys);
7159
2.18M
    for (size_t i = 0; i < size; i++) {
7160
1.58M
        PyObject *val = values->values[i];
7161
1.58M
        if (val != NULL) {
7162
934k
            used += 1;
7163
934k
        }
7164
1.58M
    }
7165
598k
    PyDictObject *res = (PyDictObject *)new_dict(keys, values, used, 0);
7166
598k
    return res;
7167
598k
}
7168
7169
PyDictObject *
7170
_PyObject_MaterializeManagedDict_LockHeld(PyObject *obj)
7171
6.20k
{
7172
6.20k
    ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(obj);
7173
7174
6.20k
    OBJECT_STAT_INC(dict_materialized_on_request);
7175
7176
6.20k
    PyDictValues *values = _PyObject_InlineValues(obj);
7177
6.20k
    PyDictObject *dict;
7178
6.20k
    if (values->valid) {
7179
6.20k
        PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
7180
6.20k
        dict = make_dict_from_instance_attributes(keys, values);
7181
6.20k
    }
7182
0
    else {
7183
0
        dict = (PyDictObject *)PyDict_New();
7184
0
    }
7185
6.20k
    FT_ATOMIC_STORE_PTR_RELEASE(_PyObject_ManagedDictPointer(obj)->dict,
7186
6.20k
                                dict);
7187
6.20k
    return dict;
7188
6.20k
}
7189
7190
PyDictObject *
7191
_PyObject_MaterializeManagedDict(PyObject *obj)
7192
80.0M
{
7193
80.0M
    PyDictObject *dict = _PyObject_GetManagedDict(obj);
7194
80.0M
    if (dict != NULL) {
7195
80.0M
        return dict;
7196
80.0M
    }
7197
7198
6.20k
    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.20k
    dict = _PyObject_MaterializeManagedDict_LockHeld(obj);
7208
7209
#ifdef Py_GIL_DISABLED
7210
exit:
7211
#endif
7212
6.20k
    Py_END_CRITICAL_SECTION();
7213
6.20k
    return dict;
7214
80.0M
}
7215
7216
int
7217
_PyDict_SetItem_LockHeld(PyDictObject *dict, PyObject *name, PyObject *value)
7218
46.7M
{
7219
46.7M
    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
46.7M
    if (value == NULL) {
7235
12.5k
        Py_hash_t hash = _PyObject_HashFast(name);
7236
12.5k
        if (hash == -1) {
7237
0
            dict_unhashable_type((PyObject*)dict, name);
7238
0
            return -1;
7239
0
        }
7240
12.5k
        return _PyDict_DelItem_KnownHash_LockHeld((PyObject *)dict, name, hash);
7241
46.7M
    } else {
7242
46.7M
        return setitem_lock_held(dict, name, value);
7243
46.7M
    }
7244
46.7M
}
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
598k
        int res;
7288
598k
        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
592k
            dict = make_dict_from_instance_attributes(keys, values);
7292
592k
            if (dict == NULL ||
7293
592k
                _PyDict_SetItem_LockHeld(dict, name, value) < 0) {
7294
0
                Py_XDECREF(dict);
7295
0
                return -1;
7296
0
            }
7297
7298
592k
            FT_ATOMIC_STORE_PTR_RELEASE(_PyObject_ManagedDictPointer(obj)->dict,
7299
592k
                                        (PyDictObject *)dict);
7300
592k
            return 0;
7301
592k
        }
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
598k
    }
7308
7309
17.2M
    PyObject *old_value = values->values[ix];
7310
17.2M
    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.2M
    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.2M
    FT_ATOMIC_STORE_PTR_RELEASE(values->values[ix], Py_XNewRef(value));
7326
7327
17.2M
    if (old_value == NULL) {
7328
12.3M
        _PyDictValues_AddToInsertionOrder(values, ix);
7329
12.3M
        if (dict) {
7330
60
            assert(dict->ma_values == values);
7331
60
            STORE_USED(dict, dict->ma_used + 1);
7332
60
        }
7333
12.3M
    }
7334
4.90M
    else {
7335
4.90M
        if (value == NULL) {
7336
366k
            delete_index_from_values(values, ix);
7337
366k
            if (dict) {
7338
0
                assert(dict->ma_values == values);
7339
0
                STORE_USED(dict, dict->ma_used - 1);
7340
0
            }
7341
366k
        }
7342
4.90M
        Py_DECREF(old_value);
7343
4.90M
    }
7344
17.2M
    return 0;
7345
17.2M
}
7346
7347
static inline int
7348
store_instance_attr_dict(PyObject *obj, PyDictObject *dict, PyObject *name, PyObject *value)
7349
22.8M
{
7350
22.8M
    PyDictValues *values = _PyObject_InlineValues(obj);
7351
22.8M
    int res;
7352
22.8M
    Py_BEGIN_CRITICAL_SECTION(dict);
7353
22.8M
    if (dict->ma_values == values) {
7354
0
        res = store_instance_attr_lock_held(obj, values, name, value);
7355
0
    }
7356
22.8M
    else {
7357
22.8M
        res = _PyDict_SetItem_LockHeld(dict, name, value);
7358
22.8M
    }
7359
22.8M
    Py_END_CRITICAL_SECTION();
7360
22.8M
    return res;
7361
22.8M
}
7362
7363
int
7364
_PyObject_StoreInstanceAttribute(PyObject *obj, PyObject *name, PyObject *value)
7365
40.6M
{
7366
40.6M
    PyDictValues *values = _PyObject_InlineValues(obj);
7367
40.6M
    if (!FT_ATOMIC_LOAD_UINT8(values->valid)) {
7368
22.8M
        PyDictObject *dict = _PyObject_GetManagedDict(obj);
7369
22.8M
        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.8M
        return store_instance_attr_dict(obj, dict, name, value);
7379
22.8M
    }
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.6M
#endif
7411
40.6M
}
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
180M
{
7449
180M
    assert(PyUnicode_CheckExact(name));
7450
180M
    PyDictValues *values = _PyObject_InlineValues(obj);
7451
180M
    if (!FT_ATOMIC_LOAD_UINT8(values->valid)) {
7452
107M
        return false;
7453
107M
    }
7454
7455
73.4M
    PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj));
7456
73.4M
    assert(keys != NULL);
7457
73.4M
    Py_ssize_t ix = _PyDictKeys_StringLookupSplit(keys, name);
7458
73.4M
    if (ix == DKIX_EMPTY) {
7459
24.3M
        *attr = NULL;
7460
24.3M
        return true;
7461
24.3M
    }
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
49.0M
    PyObject *value = values->values[ix];
7520
49.0M
    *attr = Py_XNewRef(value);
7521
49.0M
    return true;
7522
73.4M
#endif
7523
73.4M
}
7524
7525
int
7526
_PyObject_IsInstanceDictEmpty(PyObject *obj)
7527
8.98k
{
7528
8.98k
    PyTypeObject *tp = Py_TYPE(obj);
7529
8.98k
    if (tp->tp_dictoffset == 0) {
7530
8.98k
        return 1;
7531
8.98k
    }
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
27.4M
{
7562
27.4M
    PyTypeObject *tp = Py_TYPE(obj);
7563
27.4M
    if((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {
7564
0
        return 0;
7565
0
    }
7566
27.4M
    PyDictObject *dict = _PyObject_ManagedDictPointer(obj)->dict;
7567
27.4M
    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
26.3M
    else if (tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) {
7574
26.3M
        PyDictValues *values = _PyObject_InlineValues(obj);
7575
26.3M
        if (values->valid) {
7576
198M
            for (Py_ssize_t i = 0; i < values->capacity; i++) {
7577
172M
                Py_VISIT(values->values[i]);
7578
172M
            }
7579
26.3M
        }
7580
26.3M
    }
7581
27.4M
    return 0;
7582
27.4M
}
7583
7584
static void
7585
clear_inline_values(PyDictValues *values)
7586
33.0M
{
7587
33.0M
    if (values->valid) {
7588
32.7M
        FT_ATOMIC_STORE_UINT8(values->valid, 0);
7589
209M
        for (Py_ssize_t i = 0; i < values->capacity; i++) {
7590
176M
            Py_CLEAR(values->values[i]);
7591
176M
        }
7592
32.7M
    }
7593
33.0M
}
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
22
{
7768
22
    assert(_PyObject_ManagedDictPointer(obj)->dict == mp);
7769
22
    assert(_PyObject_InlineValuesConsistencyCheck(obj));
7770
7771
22
    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
22
    ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(mp);
7778
22
    assert(mp->ma_values->embedded == 1);
7779
22
    assert(mp->ma_values->valid == 1);
7780
22
    assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_INLINE_VALUES);
7781
7782
22
    PyDictValues *values = copy_values(mp->ma_values);
7783
7784
22
    if (values == NULL) {
7785
0
        PyErr_NoMemory();
7786
0
        return -1;
7787
0
    }
7788
22
    mp->ma_values = values;
7789
7790
22
    invalidate_and_clear_inline_values(_PyObject_InlineValues(obj));
7791
7792
22
    assert(_PyObject_InlineValuesConsistencyCheck(obj));
7793
22
    ASSERT_CONSISTENT(mp);
7794
22
    return 0;
7795
22
}
7796
7797
7798
void
7799
PyObject_ClearManagedDict(PyObject *obj)
7800
33.6M
{
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.6M
    if (Py_TYPE(obj)->tp_flags & Py_TPFLAGS_INLINE_VALUES) {
7804
33.6M
        PyDictObject *dict = _PyObject_GetManagedDict(obj);
7805
33.6M
        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
33.0M
            clear_inline_values(_PyObject_InlineValues(obj));
7810
33.0M
            return;
7811
33.0M
        }
7812
598k
        else if (FT_ATOMIC_LOAD_PTR_RELAXED(dict->ma_values) ==
7813
598k
                    _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
22
            int err;
7818
22
            Py_BEGIN_CRITICAL_SECTION(dict);
7819
22
            err = detach_dict_from_object(dict, obj);
7820
22
            Py_END_CRITICAL_SECTION();
7821
7822
22
            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
22
        }
7838
33.6M
    }
7839
600k
    Py_CLEAR(_PyObject_ManagedDictPointer(obj)->dict);
7840
600k
}
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
648k
{
7853
648k
    PyDictObject *dict = _PyObject_GetManagedDict(obj);
7854
648k
    if (dict == NULL) {
7855
6.20k
        PyTypeObject *tp = Py_TYPE(obj);
7856
6.20k
        if ((tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) &&
7857
6.20k
            FT_ATOMIC_LOAD_UINT8(_PyObject_InlineValues(obj)->valid)) {
7858
6.20k
            dict = _PyObject_MaterializeManagedDict(obj);
7859
6.20k
        }
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.20k
    }
7879
648k
    return (PyObject *)dict;
7880
648k
}
7881
7882
static inline PyObject *
7883
ensure_nonmanaged_dict(PyObject *obj, PyObject **dictptr)
7884
23.3M
{
7885
23.3M
    PyDictKeysObject *cached;
7886
7887
23.3M
    PyObject *dict = FT_ATOMIC_LOAD_PTR_ACQUIRE(*dictptr);
7888
23.3M
    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.99k
            assert(!_PyType_HasFeature(tp, Py_TPFLAGS_INLINE_VALUES));
7899
6.99k
            dict = new_dict_with_shared_keys(cached);
7900
6.99k
        }
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
23.3M
    return dict;
7911
23.3M
}
7912
7913
PyObject *
7914
PyObject_GenericGetDict(PyObject *obj, void *context)
7915
665k
{
7916
665k
    PyTypeObject *tp = Py_TYPE(obj);
7917
665k
    if (_PyType_HasFeature(tp, Py_TPFLAGS_MANAGED_DICT)) {
7918
648k
        return Py_XNewRef(ensure_managed_dict(obj));
7919
648k
    }
7920
16.9k
    else {
7921
16.9k
        PyObject **dictptr = _PyObject_ComputedDictPointer(obj);
7922
16.9k
        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.9k
        return Py_XNewRef(ensure_nonmanaged_dict(obj, dictptr));
7929
16.9k
    }
7930
665k
}
7931
7932
int
7933
_PyObjectDict_SetItem(PyTypeObject *tp, PyObject *obj, PyObject **dictptr,
7934
                      PyObject *key, PyObject *value)
7935
23.3M
{
7936
23.3M
    PyObject *dict;
7937
23.3M
    int res;
7938
7939
23.3M
    assert(dictptr != NULL);
7940
23.3M
    dict = ensure_nonmanaged_dict(obj, dictptr);
7941
23.3M
    if (dict == NULL) {
7942
0
        return -1;
7943
0
    }
7944
7945
23.3M
    Py_BEGIN_CRITICAL_SECTION(dict);
7946
23.3M
    res = _PyDict_SetItem_LockHeld((PyDictObject *)dict, key, value);
7947
23.3M
    ASSERT_CONSISTENT(dict);
7948
23.3M
    Py_END_CRITICAL_SECTION();
7949
23.3M
    return res;
7950
23.3M
}
7951
7952
void
7953
_PyDictKeys_DecRef(PyDictKeysObject *keys)
7954
227k
{
7955
227k
    dictkeys_decref(keys, false);
7956
227k
}
7957
7958
static inline uint32_t
7959
get_next_dict_keys_version(PyInterpreterState *interp)
7960
12.9k
{
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.9k
    if (interp->dict_state.next_keys_version == 0) {
7973
0
        return 0;
7974
0
    }
7975
12.9k
    uint32_t v = interp->dict_state.next_keys_version++;
7976
12.9k
#endif
7977
12.9k
    return v;
7978
12.9k
}
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.88M
{
7986
2.88M
    uint32_t dk_version = FT_ATOMIC_LOAD_UINT32_RELAXED(dictkeys->dk_version);
7987
2.88M
    if (dk_version != 0) {
7988
2.87M
        return dk_version;
7989
2.87M
    }
7990
12.9k
    dk_version = get_next_dict_keys_version(interp);
7991
12.9k
    FT_ATOMIC_STORE_UINT32_RELAXED(dictkeys->dk_version, dk_version);
7992
12.9k
    return dk_version;
7993
2.88M
}
7994
7995
uint32_t
7996
_PyDict_GetKeysVersionForCurrentState(PyInterpreterState *interp,
7997
                                      PyDictObject *dict)
7998
61.4k
{
7999
61.4k
    ASSERT_DICT_LOCKED((PyObject *) dict);
8000
61.4k
    uint32_t dk_version =
8001
61.4k
        _PyDictKeys_GetVersionForCurrentState(interp, dict->ma_keys);
8002
61.4k
    ensure_shared_on_keys_version_assignment(dict);
8003
61.4k
    return dk_version;
8004
61.4k
}
8005
8006
static inline int
8007
validate_watcher_id(PyInterpreterState *interp, int watcher_id)
8008
8.06k
{
8009
8.06k
    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.06k
    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.06k
    return 0;
8018
8.06k
}
8019
8020
int
8021
PyDict_Watch(int watcher_id, PyObject* dict)
8022
8.06k
{
8023
8.06k
    if (!PyDict_Check(dict)) {
8024
0
        PyErr_SetString(PyExc_ValueError, "Cannot watch non-dictionary");
8025
0
        return -1;
8026
0
    }
8027
8.06k
    PyInterpreterState *interp = _PyInterpreterState_GET();
8028
8.06k
    if (validate_watcher_id(interp, watcher_id)) {
8029
0
        return -1;
8030
0
    }
8031
8.06k
    ((PyDictObject*)dict)->_ma_watcher_tag |= (1LL << watcher_id);
8032
8.06k
    return 0;
8033
8.06k
}
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
    ((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
319k
{
8097
319k
    PyInterpreterState *interp = _PyInterpreterState_GET();
8098
2.87M
    for (int i = 0; i < DICT_MAX_WATCHERS; i++) {
8099
2.55M
        if (watcher_bits & 1) {
8100
319k
            PyDict_WatchCallback cb = interp->dict_state.watchers[i];
8101
319k
            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
319k
        }
8111
2.55M
        watcher_bits >>= 1;
8112
2.55M
    }
8113
319k
}
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
285
{
8252
285
    PyObject *d = dict_new(type, args, kwds);
8253
285
    if (d == NULL) {
8254
0
        return NULL;
8255
0
    }
8256
285
    assert(can_modify_dict(_PyAnyDict_CAST(d)));
8257
8258
285
    PyFrozenDictObject *self = _PyFrozenDictObject_CAST(d);
8259
285
    self->ma_hash = -1;
8260
8261
285
    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
285
    else {
8268
285
        assert(kwds == NULL);
8269
285
    }
8270
8271
285
    return d;
8272
285
}
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
};