Coverage Report

Created: 2026-02-26 06:53

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