Coverage Report

Created: 2026-10-31 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Objects/odictobject.c
Line
Count
Source
1
/* Ordered Dictionary object implementation.
2
3
This implementation is necessarily explicitly equivalent to the pure Python
4
OrderedDict class in Lib/collections/__init__.py.  The strategy there
5
involves using a doubly-linked-list to capture the order.  We keep to that
6
strategy, using a lower-level linked-list.
7
8
About the Linked-List
9
=====================
10
11
For the linked list we use a basic doubly-linked-list.  Using a circularly-
12
linked-list does have some benefits, but they don't apply so much here
13
since OrderedDict is focused on the ends of the list (for the most part).
14
Furthermore, there are some features of generic linked-lists that we simply
15
don't need for OrderedDict.  Thus a simple custom implementation meets our
16
needs.  Alternatives to our simple approach include the QCIRCLE_*
17
macros from BSD's queue.h, and the linux's list.h.
18
19
Getting O(1) Node Lookup
20
------------------------
21
22
One invariant of Python's OrderedDict is that it preserves time complexity
23
of dict's methods, particularly the O(1) operations.  Simply adding a
24
linked-list on top of dict is not sufficient here; operations for nodes in
25
the middle of the linked-list implicitly require finding the node first.
26
With a simple linked-list like we're using, that is an O(n) operation.
27
Consequently, methods like __delitem__() would change from O(1) to O(n),
28
which is unacceptable.
29
30
In order to preserve O(1) performance for node removal (finding nodes), we
31
must do better than just looping through the linked-list.  Here are options
32
we've considered:
33
34
1. use a second dict to map keys to nodes (a la the pure Python version).
35
2. keep a simple hash table mirroring the order of dict's, mapping each key
36
   to the corresponding node in the linked-list.
37
3. use a version of shared keys (split dict) that allows non-unicode keys.
38
4. have the value stored for each key be a (value, node) pair, and adjust
39
   __getitem__(), get(), etc. accordingly.
40
41
The approach with the least performance impact (time and space) is #2,
42
mirroring the key order of dict's dk_entries with an array of node pointers.
43
While _Py_dict_lookup() does not give us the index into the array,
44
we make use of pointer arithmetic to get that index.  An alternative would
45
be to refactor _Py_dict_lookup() to provide the index, explicitly exposing
46
the implementation detail.  We could even just use a custom lookup function
47
for OrderedDict that facilitates our need.  However, both approaches are
48
significantly more complicated than just using pointer arithmetic.
49
50
The catch with mirroring the hash table ordering is that we have to keep
51
the ordering in sync through any dict resizes.  However, that order only
52
matters during node lookup.  We can simply defer any potential resizing
53
until we need to do a lookup.
54
55
Linked-List Nodes
56
-----------------
57
58
The current implementation stores a pointer to the associated key only.
59
One alternative would be to store a pointer to the PyDictKeyEntry instead.
60
This would save one pointer de-reference per item, which is nice during
61
calls to values() and items().  However, it adds unnecessary overhead
62
otherwise, so we stick with just the key.
63
64
Linked-List API
65
---------------
66
67
As noted, the linked-list implemented here does not have all the bells and
68
whistles.  However, we recognize that the implementation may need to
69
change to accommodate performance improvements or extra functionality.  To
70
that end, we use a simple API to interact with the linked-list.  Here's a
71
summary of the methods/macros:
72
73
Node info:
74
75
* _odictnode_KEY(node)
76
* _odictnode_VALUE(od, node)
77
* _odictnode_PREV(node)
78
* _odictnode_NEXT(node)
79
80
Linked-List info:
81
82
* _odict_FIRST(od)
83
* _odict_LAST(od)
84
* _odict_EMPTY(od)
85
* _odict_FOREACH(od, node) - used in place of `for (node=...)`
86
87
For adding nodes:
88
89
* _odict_add_head(od, node)
90
* _odict_add_tail(od, node)
91
* _odict_add_new_node(od, key, hash)
92
93
For removing nodes:
94
95
* _odict_clear_node(od, node, key, hash)
96
* _odict_clear_nodes(od, clear_each)
97
98
Others:
99
100
* _odict_find_node_hash(od, key, hash)
101
* _odict_find_node(od, key)
102
* _odict_keys_equal(od1, od2)
103
104
And here's a look at how the linked-list relates to the OrderedDict API:
105
106
============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===
107
method       key val prev next mem  1st last empty iter find add rmv  clr keq
108
============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===
109
__del__                                      ~                        X
110
__delitem__                    free                     ~        node
111
__eq__       ~                                                            X
112
__iter__     X            X
113
__new__                             X   X
114
__reduce__   X   ~                                 X
115
__repr__     X   X                                 X
116
__reversed__ X       X
117
__setitem__                                                  key
118
__sizeof__                     size          X
119
clear                          ~             ~                        X
120
copy         X   X                                 X
121
items        X   X        X
122
keys         X            X
123
move_to_end  X                      X   X               ~    h/t key
124
pop                            free                              key
125
popitem      X   X             free X   X                        node
126
setdefault       ~                                      ?    ~
127
values           X        X
128
============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===
129
130
__delitem__ is the only method that directly relies on finding an arbitrary
131
node in the linked-list.  Everything else is iteration or relates to the
132
ends of the linked-list.
133
134
Situation that Endangers Consistency
135
------------------------------------
136
Using a raw linked-list for OrderedDict exposes a key situation that can
137
cause problems.  If a node is stored in a variable, there is a chance that
138
the node may have been deallocated before the variable gets used, thus
139
potentially leading to a segmentation fault.  A key place where this shows
140
up is during iteration through the linked list (via _odict_FOREACH or
141
otherwise).
142
143
A number of solutions are available to resolve this situation:
144
145
* defer looking up the node until as late as possible and certainly after
146
  any code that could possibly result in a deletion;
147
* if the node is needed both before and after a point where the node might
148
  be removed, do a check before using the node at the "after" location to
149
  see if the node is still valid;
150
* like the last one, but simply pull the node again to ensure it's right;
151
* keep the key in the variable instead of the node and then look up the
152
  node using the key at the point where the node is needed (this is what
153
  we do for the iterators).
154
155
Another related problem, preserving consistent ordering during iteration,
156
is described below.  That one is not exclusive to using linked-lists.
157
158
159
Challenges from Subclassing dict
160
================================
161
162
OrderedDict subclasses dict, which is an unusual relationship between two
163
builtin types (other than the base object type).  Doing so results in
164
some complication and deserves further explanation.  There are two things
165
to consider here.  First, in what circumstances or with what adjustments
166
can OrderedDict be used as a drop-in replacement for dict (at the C level)?
167
Second, how can the OrderedDict implementation leverage the dict
168
implementation effectively without introducing unnecessary coupling or
169
inefficiencies?
170
171
This second point is reflected here and in the implementation, so the
172
further focus is on the first point.  It is worth noting that for
173
overridden methods, the dict implementation is deferred to as much as
174
possible.  Furthermore, coupling is limited to as little as is reasonable.
175
176
Concrete API Compatibility
177
--------------------------
178
179
Use of the concrete C-API for dict (PyDict_*) with OrderedDict is
180
problematic.  (See http://bugs.python.org/issue10977.)  The concrete API
181
has a number of hard-coded assumptions tied to the dict implementation.
182
This is, in part, due to performance reasons, which is understandable
183
given the part dict plays in Python.
184
185
Any attempt to replace dict with OrderedDict for any role in the
186
interpreter (e.g. **kwds) faces a challenge.  Such any effort must
187
recognize that the instances in affected locations currently interact with
188
the concrete API.
189
190
Here are some ways to address this challenge:
191
192
1. Change the relevant usage of the concrete API in CPython and add
193
   PyDict_CheckExact() calls to each of the concrete API functions.
194
2. Adjust the relevant concrete API functions to explicitly accommodate
195
   OrderedDict.
196
3. As with #1, add the checks, but improve the abstract API with smart fast
197
   paths for dict and OrderedDict, and refactor CPython to use the abstract
198
   API.  Improvements to the abstract API would be valuable regardless.
199
200
Adding the checks to the concrete API would help make any interpreter
201
switch to OrderedDict less painful for extension modules.  However, this
202
won't work.  The equivalent C API call to `dict.__setitem__(obj, k, v)`
203
is `PyDict_SetItem(obj, k, v)`.  This illustrates how subclasses in C call
204
the base class's methods, since there is no equivalent of super() in the
205
C API.  Calling into Python for parent class API would work, but some
206
extension modules already rely on this feature of the concrete API.
207
208
For reference, here is a breakdown of some of the dict concrete API:
209
210
========================== ============= =======================
211
concrete API               uses          abstract API
212
========================== ============= =======================
213
PyDict_Check                             PyMapping_Check
214
(PyDict_CheckExact)                      -
215
(PyDict_New)                             -
216
(PyDictProxy_New)                        -
217
PyDict_Clear                             -
218
PyDict_Contains                          PySequence_Contains
219
PyDict_Copy                              -
220
PyDict_SetItem                           PyObject_SetItem
221
PyDict_SetItemString                     PyMapping_SetItemString
222
PyDict_DelItem                           PyMapping_DelItem
223
PyDict_DelItemString                     PyMapping_DelItemString
224
PyDict_GetItem                           -
225
PyDict_GetItemWithError                  PyObject_GetItem
226
PyDict_GetItemString                     PyMapping_GetItemString
227
PyDict_Items                             PyMapping_Items
228
PyDict_Keys                              PyMapping_Keys
229
PyDict_Values                            PyMapping_Values
230
PyDict_Size                              PyMapping_Size
231
                                         PyMapping_Length
232
PyDict_Next                              PyIter_Next
233
_PyDict_Next                             -
234
PyDict_Merge                             -
235
PyDict_Update                            -
236
PyDict_MergeFromSeq2                     -
237
PyDict_ClearFreeList                     -
238
-                                        PyMapping_HasKeyString
239
-                                        PyMapping_HasKey
240
========================== ============= =======================
241
242
243
The dict Interface Relative to OrderedDict
244
==========================================
245
246
Since OrderedDict subclasses dict, understanding the various methods and
247
attributes of dict is important for implementing OrderedDict.
248
249
Relevant Type Slots
250
-------------------
251
252
================= ================ =================== ================
253
slot              attribute        object              dict
254
================= ================ =================== ================
255
tp_dealloc        -                object_dealloc      dict_dealloc
256
tp_repr           __repr__         object_repr         dict_repr
257
sq_contains       __contains__     -                   dict_contains
258
mp_length         __len__          -                   dict_length
259
mp_subscript      __getitem__      -                   dict_subscript
260
mp_ass_subscript  __setitem__      -                   dict_ass_sub
261
                  __delitem__
262
tp_hash           __hash__         Py_HashPointer      ..._HashNotImpl
263
tp_str            __str__          object_str          -
264
tp_getattro       __getattribute__ ..._GenericGetAttr  (repeated)
265
                  __getattr__
266
tp_setattro       __setattr__      ..._GenericSetAttr  (disabled)
267
tp_doc            __doc__          (literal)           dictionary_doc
268
tp_traverse       -                -                   dict_traverse
269
tp_clear          -                -                   dict_tp_clear
270
tp_richcompare    __eq__           object_richcompare  dict_richcompare
271
                  __ne__
272
tp_weaklistoffset (__weakref__)    -                   -
273
tp_iter           __iter__         -                   dict_iter
274
tp_dictoffset     (__dict__)       -                   -
275
tp_init           __init__         object_init         dict_init
276
tp_alloc          -                PyType_GenericAlloc (repeated)
277
tp_new            __new__          object_new          dict_new
278
tp_free           -                PyObject_Free       PyObject_GC_Del
279
================= ================ =================== ================
280
281
Relevant Methods
282
----------------
283
284
================ =================== ===============
285
method           object              dict
286
================ =================== ===============
287
__reduce__       object_reduce       -
288
__sizeof__       object_sizeof       dict_sizeof
289
clear            -                   dict_clear
290
copy             -                   dict_copy
291
fromkeys         -                   dict_fromkeys
292
get              -                   dict_get
293
items            -                   dictitems_new
294
keys             -                   dictkeys_new
295
pop              -                   dict_pop
296
popitem          -                   dict_popitem
297
setdefault       -                   dict_setdefault
298
update           -                   dict_update
299
values           -                   dictvalues_new
300
================ =================== ===============
301
302
303
Pure Python OrderedDict
304
=======================
305
306
As already noted, compatibility with the pure Python OrderedDict
307
implementation is a key goal of this C implementation.  To further that
308
goal, here's a summary of how OrderedDict-specific methods are implemented
309
in collections/__init__.py.  Also provided is an indication of which
310
methods directly mutate or iterate the object, as well as any relationship
311
with the underlying linked-list.
312
313
============= ============== == ================ === === ====
314
method        impl used      ll uses             inq mut iter
315
============= ============== == ================ === === ====
316
__contains__  dict           -  -                X
317
__delitem__   OrderedDict    Y  dict.__delitem__     X
318
__eq__        OrderedDict    N  OrderedDict      ~
319
                                dict.__eq__
320
                                __iter__
321
__getitem__   dict           -  -                X
322
__iter__      OrderedDict    Y  -                        X
323
__init__      OrderedDict    N  update
324
__len__       dict           -  -                X
325
__ne__        MutableMapping -  __eq__           ~
326
__reduce__    OrderedDict    N  OrderedDict      ~
327
                                __iter__
328
                                __getitem__
329
__repr__      OrderedDict    N  __class__        ~
330
                                items
331
__reversed__  OrderedDict    Y  -                        X
332
__setitem__   OrderedDict    Y  __contains__         X
333
                                dict.__setitem__
334
__sizeof__    OrderedDict    Y  __len__          ~
335
                                __dict__
336
clear         OrderedDict    Y  dict.clear           X
337
copy          OrderedDict    N  __class__
338
                                __init__
339
fromkeys      OrderedDict    N  __setitem__
340
get           dict           -  -                ~
341
items         MutableMapping -  ItemsView                X
342
keys          MutableMapping -  KeysView                 X
343
move_to_end   OrderedDict    Y  -                    X
344
pop           OrderedDict    N  __contains__         X
345
                                __getitem__
346
                                __delitem__
347
popitem       OrderedDict    Y  dict.pop             X
348
setdefault    OrderedDict    N  __contains__         ~
349
                                __getitem__
350
                                __setitem__
351
update        MutableMapping -  __setitem__          ~
352
values        MutableMapping -  ValuesView               X
353
============= ============== == ================ === === ====
354
355
__reversed__ and move_to_end are both exclusive to OrderedDict.
356
357
358
C OrderedDict Implementation
359
============================
360
361
================= ================
362
slot              impl
363
================= ================
364
tp_dealloc        odict_dealloc
365
tp_repr           odict_repr
366
mp_ass_subscript  odict_ass_sub
367
tp_doc            odict_doc
368
tp_traverse       odict_traverse
369
tp_clear          odict_tp_clear
370
tp_richcompare    odict_richcompare
371
tp_weaklistoffset (offset)
372
tp_iter           odict_iter
373
tp_dictoffset     (offset)
374
tp_init           odict_init
375
tp_alloc          (repeated)
376
================= ================
377
378
================= ================
379
method            impl
380
================= ================
381
__reduce__        odict_reduce
382
__sizeof__        odict_sizeof
383
clear             odict_clear
384
copy              odict_copy
385
fromkeys          odict_fromkeys
386
items             odictitems_new
387
keys              odictkeys_new
388
pop               odict_pop
389
popitem           odict_popitem
390
setdefault        odict_setdefault
391
update            odict_update
392
values            odictvalues_new
393
================= ================
394
395
Inherited unchanged from object/dict:
396
397
================ ==========================
398
method           type field
399
================ ==========================
400
-                tp_free
401
__contains__     tp_as_sequence.sq_contains
402
__getattr__      tp_getattro
403
__getattribute__ tp_getattro
404
__getitem__      tp_as_mapping.mp_subscript
405
__hash__         tp_hash
406
__len__          tp_as_mapping.mp_length
407
__setattr__      tp_setattro
408
__str__          tp_str
409
get              -
410
================ ==========================
411
412
413
Other Challenges
414
================
415
416
Preserving Ordering During Iteration
417
------------------------------------
418
During iteration through an OrderedDict, it is possible that items could
419
get added, removed, or reordered.  For a linked-list implementation, as
420
with some other implementations, that situation may lead to undefined
421
behavior.  The documentation for dict mentions this in the `iter()` section
422
of http://docs.python.org/3.4/library/stdtypes.html#dictionary-view-objects.
423
In this implementation we follow dict's lead (as does the pure Python
424
implementation) for __iter__(), keys(), values(), and items().
425
426
For internal iteration (using _odict_FOREACH or not), there is still the
427
risk that not all nodes that we expect to be seen in the loop actually get
428
seen.  Thus, we are careful in each of those places to ensure that they
429
are.  This comes, of course, at a small price at each location.  The
430
solutions are much the same as those detailed in the `Situation that
431
Endangers Consistency` section above.
432
433
434
Potential Optimizations
435
=======================
436
437
* Allocate the nodes as a block via od_fast_nodes instead of individually.
438
  - Set node->key to NULL to indicate the node is not-in-use.
439
  - Add _odict_EXISTS()?
440
  - How to maintain consistency across resizes?  Existing node pointers
441
    would be invalidated after a resize, which is particularly problematic
442
    for the iterators.
443
* Use a more stream-lined implementation of update() and, likely indirectly,
444
  __init__().
445
446
*/
447
448
/* TODO
449
450
sooner:
451
- reentrancy (make sure everything is at a thread-safe state when calling
452
  into Python).  I've already checked this multiple times, but want to
453
  make one more pass.
454
- add unit tests for reentrancy?
455
456
later:
457
- make the dict views support the full set API (the pure Python impl does)
458
- implement a fuller MutableMapping API in C?
459
- move the MutableMapping implementation to abstract.c?
460
- optimize mutablemapping_update
461
- use PyObject_Malloc (small object allocator) for odict nodes?
462
- support subclasses better (e.g. in odict_richcompare)
463
464
*/
465
466
#include "Python.h"
467
#include "pycore_call.h"             // _PyObject_CallNoArgs()
468
#include "pycore_ceval.h"            // _PyEval_GetBuiltin()
469
#include "pycore_critical_section.h" //_Py_BEGIN_CRITICAL_SECTION
470
#include "pycore_dict.h"             // _Py_dict_lookup()
471
#include "pycore_object.h"           // _PyObject_GC_UNTRACK()
472
#include "pycore_pyerrors.h"         // _PyErr_ChainExceptions1()
473
#include "pycore_tuple.h"            // _PyTuple_Recycle()
474
#include <stddef.h>                  // offsetof()
475
#include "pycore_weakref.h"          // FT_CLEAR_WEAKREFS()
476
477
#include "clinic/odictobject.c.h"
478
479
/*[clinic input]
480
class OrderedDict "PyODictObject *" "&PyODict_Type"
481
class odictiter "PyObject *" "&PyODictIter_Type"
482
[clinic start generated code]*/
483
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ae5599eeb14d29ae]*/
484
485
486
typedef struct _odictnode _ODictNode;
487
488
/* PyODictObject */
489
struct _odictobject {
490
    PyDictObject od_dict;        /* the underlying dict */
491
    _ODictNode *od_first;        /* first node in the linked list, if any */
492
    _ODictNode *od_last;         /* last node in the linked list, if any */
493
    /* od_fast_nodes, od_fast_nodes_size and od_resize_sentinel are managed
494
     * by _odict_resize().
495
     * Note that we rely on implementation details of dict for both. */
496
    _ODictNode **od_fast_nodes;  /* hash table that mirrors the dict table */
497
    Py_ssize_t od_fast_nodes_size;
498
    void *od_resize_sentinel;    /* changes if odict should be resized */
499
500
    size_t od_state;             /* incremented whenever the LL changes */
501
    PyObject *od_inst_dict;      /* OrderedDict().__dict__ */
502
    PyObject *od_weakreflist;    /* holds weakrefs to the odict */
503
};
504
505
12.5M
#define _PyODictObject_CAST(op) _Py_CAST(PyODictObject*, (op))
506
507
508
/* ----------------------------------------------
509
 * odict keys (a simple doubly-linked list)
510
 */
511
512
struct _odictnode {
513
    PyObject *key;
514
    Py_hash_t hash;
515
    _ODictNode *next;
516
    _ODictNode *prev;
517
};
518
519
#define _odictnode_KEY(node) \
520
2.90M
    (node->key)
521
#define _odictnode_HASH(node) \
522
2.66k
    (node->hash)
523
/* borrowed reference */
524
#define _odictnode_VALUE(node, od) \
525
    PyODict_GetItemWithError((PyObject *)od, _odictnode_KEY(node))
526
949k
#define _odictnode_PREV(node) (node->prev)
527
1.15M
#define _odictnode_NEXT(node) (node->next)
528
529
8.91M
#define _odict_FIRST(od) (_PyODictObject_CAST(od)->od_first)
530
6.57M
#define _odict_LAST(od) (_PyODictObject_CAST(od)->od_last)
531
5.81M
#define _odict_EMPTY(od) (_odict_FIRST(od) == NULL)
532
#define _odict_FOREACH(od, node) \
533
2.67k
    for (node = _odict_FIRST(od); node != NULL; node = _odictnode_NEXT(node))
534
535
/* Return the index into the hash table, regardless of a valid node. */
536
static Py_ssize_t
537
_odict_get_index_raw(PyODictObject *od, PyObject *key, Py_hash_t hash)
538
2.91M
{
539
2.91M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
540
2.91M
    PyObject *value = NULL;
541
2.91M
    PyDictKeysObject *keys = ((PyDictObject *)od)->ma_keys;
542
2.91M
    Py_ssize_t ix;
543
#ifdef Py_GIL_DISABLED
544
    ix = _Py_dict_lookup_threadsafe((PyDictObject *)od, key, hash, &value);
545
    Py_XDECREF(value);
546
#else
547
2.91M
    ix = _Py_dict_lookup((PyDictObject *)od, key, hash, &value);
548
2.91M
#endif
549
2.91M
    if (ix == DKIX_EMPTY) {
550
0
        return keys->dk_nentries;  /* index of new entry */
551
0
    }
552
2.91M
    if (ix < 0)
553
0
        return -1;
554
    /* We use pointer arithmetic to get the entry's index into the table. */
555
2.91M
    return ix;
556
2.91M
}
557
558
2.91M
#define ONE ((Py_ssize_t)1)
559
560
/* Replace od->od_fast_nodes with a new table matching the size of dict's. */
561
static int
562
_odict_resize(PyODictObject *od)
563
854
{
564
854
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
565
854
    Py_ssize_t size, i;
566
854
    _ODictNode **fast_nodes, *node;
567
568
    /* Initialize a new "fast nodes" table. */
569
854
    size = ONE << (((PyDictObject *)od)->ma_keys->dk_log2_size);
570
854
    fast_nodes = PyMem_NEW(_ODictNode *, size);
571
854
    if (fast_nodes == NULL) {
572
0
        PyErr_NoMemory();
573
0
        return -1;
574
0
    }
575
8.78k
    for (i = 0; i < size; i++)
576
7.92k
        fast_nodes[i] = NULL;
577
578
    /* Copy the current nodes into the table. */
579
854
    _odict_FOREACH(od, node) {
580
560
        i = _odict_get_index_raw(od, _odictnode_KEY(node),
581
560
                                 _odictnode_HASH(node));
582
560
        if (i < 0) {
583
0
            PyMem_Free(fast_nodes);
584
0
            return -1;
585
0
        }
586
560
        fast_nodes[i] = node;
587
560
    }
588
589
    /* Replace the old fast nodes table. */
590
854
    PyMem_Free(od->od_fast_nodes);
591
854
    od->od_fast_nodes = fast_nodes;
592
854
    od->od_fast_nodes_size = size;
593
854
    od->od_resize_sentinel = ((PyDictObject *)od)->ma_keys;
594
854
    return 0;
595
854
}
596
597
/* Return the index into the hash table, regardless of a valid node. */
598
static Py_ssize_t
599
_odict_get_index(PyODictObject *od, PyObject *key, Py_hash_t hash)
600
2.91M
{
601
2.91M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
602
2.91M
    PyDictKeysObject *keys;
603
604
2.91M
    assert(key != NULL);
605
2.91M
    keys = ((PyDictObject *)od)->ma_keys;
606
607
    /* Ensure od_fast_nodes and dk_entries are in sync. */
608
2.91M
    if (od->od_resize_sentinel != keys ||
609
2.91M
        od->od_fast_nodes_size != (ONE << (keys->dk_log2_size))) {
610
854
        int resize_res = _odict_resize(od);
611
854
        if (resize_res < 0)
612
0
            return -1;
613
854
    }
614
615
2.91M
    return _odict_get_index_raw(od, key, hash);
616
2.91M
}
617
618
/* Returns NULL if there was some error or the key was not found. */
619
static _ODictNode *
620
_odict_find_node_hash(PyODictObject *od, PyObject *key, Py_hash_t hash)
621
0
{
622
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
623
0
    Py_ssize_t index;
624
625
0
    if (_odict_EMPTY(od))
626
0
        return NULL;
627
0
    index = _odict_get_index(od, key, hash);
628
0
    if (index < 0)
629
0
        return NULL;
630
0
    assert(od->od_fast_nodes != NULL);
631
0
    return od->od_fast_nodes[index];
632
0
}
633
634
static _ODictNode *
635
_odict_find_node(PyODictObject *od, PyObject *key)
636
2.91M
{
637
2.91M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
638
2.91M
    Py_ssize_t index;
639
2.91M
    Py_hash_t hash;
640
641
2.91M
    if (_odict_EMPTY(od))
642
0
        return NULL;
643
2.91M
    hash = PyObject_Hash(key);
644
2.91M
    if (hash == -1)
645
0
        return NULL;
646
2.91M
    index = _odict_get_index(od, key, hash);
647
2.91M
    if (index < 0)
648
0
        return NULL;
649
2.91M
    assert(od->od_fast_nodes != NULL);
650
2.91M
    return od->od_fast_nodes[index];
651
2.91M
}
652
653
static void
654
_odict_add_head(PyODictObject *od, _ODictNode *node)
655
0
{
656
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
657
0
    _odictnode_PREV(node) = NULL;
658
0
    _odictnode_NEXT(node) = _odict_FIRST(od);
659
0
    if (_odict_FIRST(od) == NULL)
660
0
        _odict_LAST(od) = node;
661
0
    else
662
0
        _odictnode_PREV(_odict_FIRST(od)) = node;
663
0
    _odict_FIRST(od) = node;
664
0
    od->od_state++;
665
0
}
666
667
static void
668
_odict_add_tail(PyODictObject *od, _ODictNode *node)
669
191k
{
670
191k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
671
191k
    _odictnode_PREV(node) = _odict_LAST(od);
672
191k
    _odictnode_NEXT(node) = NULL;
673
191k
    if (_odict_LAST(od) == NULL)
674
767
        _odict_FIRST(od) = node;
675
190k
    else
676
190k
        _odictnode_NEXT(_odict_LAST(od)) = node;
677
191k
    _odict_LAST(od) = node;
678
191k
    od->od_state++;
679
191k
}
680
681
/* adds the node to the end of the list */
682
static int
683
_odict_add_new_node(PyODictObject *od, PyObject *key, Py_hash_t hash)
684
2.10k
{
685
2.10k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
686
2.10k
    Py_ssize_t i;
687
2.10k
    _ODictNode *node;
688
689
2.10k
    Py_INCREF(key);
690
2.10k
    i = _odict_get_index(od, key, hash);
691
2.10k
    if (i < 0) {
692
0
        if (!PyErr_Occurred())
693
0
            PyErr_SetObject(PyExc_KeyError, key);
694
0
        Py_DECREF(key);
695
0
        return -1;
696
0
    }
697
2.10k
    assert(od->od_fast_nodes != NULL);
698
2.10k
    if (od->od_fast_nodes[i] != NULL) {
699
        /* We already have a node for the key so there's no need to add one. */
700
0
        Py_DECREF(key);
701
0
        return 0;
702
0
    }
703
704
    /* must not be added yet */
705
2.10k
    node = (_ODictNode *)PyMem_Malloc(sizeof(_ODictNode));
706
2.10k
    if (node == NULL) {
707
0
        Py_DECREF(key);
708
0
        PyErr_NoMemory();
709
0
        return -1;
710
0
    }
711
712
2.10k
    _odictnode_KEY(node) = key;
713
2.10k
    _odictnode_HASH(node) = hash;
714
2.10k
    _odict_add_tail(od, node);
715
2.10k
    od->od_fast_nodes[i] = node;
716
2.10k
    return 0;
717
2.10k
}
718
719
/* Putting the decref after the free causes problems. */
720
#define _odictnode_DEALLOC(node) \
721
1.98k
    do { \
722
1.98k
        Py_DECREF(_odictnode_KEY(node)); \
723
1.98k
        PyMem_Free((void *)node); \
724
1.98k
    } while (0)
725
726
/* Repeated calls on the same node are no-ops. */
727
static void
728
_odict_remove_node(PyODictObject *od, _ODictNode *node)
729
189k
{
730
189k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
731
189k
    if (_odict_FIRST(od) == node)
732
68
        _odict_FIRST(od) = _odictnode_NEXT(node);
733
189k
    else if (_odictnode_PREV(node) != NULL)
734
189k
        _odictnode_NEXT(_odictnode_PREV(node)) = _odictnode_NEXT(node);
735
736
189k
    if (_odict_LAST(od) == node)
737
0
        _odict_LAST(od) = _odictnode_PREV(node);
738
189k
    else if (_odictnode_NEXT(node) != NULL)
739
189k
        _odictnode_PREV(_odictnode_NEXT(node)) = _odictnode_PREV(node);
740
741
189k
    _odictnode_PREV(node) = NULL;
742
189k
    _odictnode_NEXT(node) = NULL;
743
189k
    od->od_state++;
744
189k
}
745
746
/* If someone calls PyDict_DelItem() directly on an OrderedDict, we'll
747
   get all sorts of problems here.  In PyODict_DelItem we make sure to
748
   call _odict_clear_node first.
749
750
   This matters in the case of colliding keys.  Suppose we add 3 keys:
751
   [A, B, C], where the hash of C collides with A and the next possible
752
   index in the hash table is occupied by B.  If we remove B then for C
753
   the dict's looknode func will give us the old index of B instead of
754
   the index we got before deleting B.  However, the node for C in
755
   od_fast_nodes is still at the old dict index of C.  Thus to be sure
756
   things don't get out of sync, we clear the node in od_fast_nodes
757
   *before* calling PyDict_DelItem.
758
759
   The same must be done for any other OrderedDict operations where
760
   we modify od_fast_nodes.
761
*/
762
static int
763
_odict_clear_node(PyODictObject *od, _ODictNode *node, PyObject *key,
764
                  Py_hash_t hash)
765
0
{
766
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
767
0
    Py_ssize_t i;
768
769
0
    assert(key != NULL);
770
0
    if (_odict_EMPTY(od)) {
771
        /* Let later code decide if this is a KeyError. */
772
0
        return 0;
773
0
    }
774
775
0
    i = _odict_get_index(od, key, hash);
776
0
    if (i < 0)
777
0
        return PyErr_Occurred() ? -1 : 0;
778
779
0
    assert(od->od_fast_nodes != NULL);
780
0
    if (node == NULL)
781
0
        node = od->od_fast_nodes[i];
782
0
    assert(node == od->od_fast_nodes[i]);
783
0
    if (node == NULL) {
784
        /* Let later code decide if this is a KeyError. */
785
0
        return 0;
786
0
    }
787
788
    // Now clear the node.
789
0
    od->od_fast_nodes[i] = NULL;
790
0
    _odict_remove_node(od, node);
791
0
    _odictnode_DEALLOC(node);
792
0
    return 0;
793
0
}
794
795
static void
796
_odict_clear_nodes(PyODictObject *od)
797
824
{
798
824
    _ODictNode *node, *next;
799
800
824
    PyMem_Free(od->od_fast_nodes);
801
824
    od->od_fast_nodes = NULL;
802
824
    od->od_fast_nodes_size = 0;
803
824
    od->od_resize_sentinel = NULL;
804
805
824
    node = _odict_FIRST(od);
806
824
    _odict_FIRST(od) = NULL;
807
824
    _odict_LAST(od) = NULL;
808
2.81k
    while (node != NULL) {
809
1.98k
        next = _odictnode_NEXT(node);
810
1.98k
        _odictnode_DEALLOC(node);
811
1.98k
        node = next;
812
1.98k
    }
813
824
    od->od_state++;
814
824
}
815
816
/* There isn't any memory management of nodes past this point. */
817
#undef _odictnode_DEALLOC
818
819
static int
820
_odict_keys_equal(PyODictObject *a, PyODictObject *b)
821
0
{
822
0
    _ODictNode *node_a, *node_b;
823
824
    // keep operands' state to detect undesired mutations
825
0
    const size_t state_a = a->od_state;
826
0
    const size_t state_b = b->od_state;
827
828
0
    node_a = _odict_FIRST(a);
829
0
    node_b = _odict_FIRST(b);
830
0
    while (1) {
831
0
        if (node_a == NULL && node_b == NULL) {
832
            /* success: hit the end of each at the same time */
833
0
            return 1;
834
0
        }
835
0
        else if (node_a == NULL || node_b == NULL) {
836
            /* unequal length */
837
0
            return 0;
838
0
        }
839
0
        else {
840
0
            PyObject *key_a = Py_NewRef(_odictnode_KEY(node_a));
841
0
            PyObject *key_b = Py_NewRef(_odictnode_KEY(node_b));
842
0
            int res = PyObject_RichCompareBool(key_a, key_b, Py_EQ);
843
0
            Py_DECREF(key_a);
844
0
            Py_DECREF(key_b);
845
0
            if (res < 0) {
846
0
                return res;
847
0
            }
848
0
            else if (a->od_state != state_a || b->od_state != state_b) {
849
0
                PyErr_SetString(PyExc_RuntimeError,
850
0
                                "OrderedDict mutated during iteration");
851
0
                return -1;
852
0
            }
853
0
            else if (res == 0) {
854
                // This check comes after the check on the state
855
                // in order for the exception to be set correctly.
856
0
                return 0;
857
0
            }
858
859
            /* otherwise it must match, so move on to the next one */
860
0
            node_a = _odictnode_NEXT(node_a);
861
0
            node_b = _odictnode_NEXT(node_b);
862
0
        }
863
0
    }
864
0
}
865
866
867
/* ----------------------------------------------
868
 * OrderedDict mapping methods
869
 */
870
871
/* mp_ass_subscript: __setitem__() and __delitem__() */
872
873
static int
874
odict_mp_ass_sub(PyObject *od, PyObject *v, PyObject *w)
875
2.10k
{
876
2.10k
    if (w == NULL)
877
0
        return PyODict_DelItem(od, v);
878
2.10k
    else
879
2.10k
        return PyODict_SetItem(od, v, w);
880
2.10k
}
881
882
/* tp_as_mapping */
883
884
static PyMappingMethods odict_as_mapping = {
885
    0,                                  /*mp_length*/
886
    0,                                  /*mp_subscript*/
887
    odict_mp_ass_sub,                   /*mp_ass_subscript*/
888
};
889
890
891
/* ----------------------------------------------
892
 * OrderedDict number methods
893
 */
894
895
static int mutablemapping_update_arg(PyObject*, PyObject*);
896
897
static PyObject *
898
odict_or(PyObject *left, PyObject *right)
899
0
{
900
0
    PyTypeObject *type;
901
0
    PyObject *other;
902
0
    if (PyODict_Check(left)) {
903
0
        type = Py_TYPE(left);
904
0
        other = right;
905
0
    }
906
0
    else {
907
0
        type = Py_TYPE(right);
908
0
        other = left;
909
0
    }
910
0
    if (!PyAnyDict_Check(other)) {
911
0
        Py_RETURN_NOTIMPLEMENTED;
912
0
    }
913
0
    PyObject *new = PyObject_CallOneArg((PyObject*)type, left);
914
0
    if (!new) {
915
0
        return NULL;
916
0
    }
917
0
    if (mutablemapping_update_arg(new, right) < 0) {
918
0
        Py_DECREF(new);
919
0
        return NULL;
920
0
    }
921
0
    return new;
922
0
}
923
924
static PyObject *
925
odict_inplace_or(PyObject *self, PyObject *other)
926
0
{
927
0
    if (mutablemapping_update_arg(self, other) < 0) {
928
0
        return NULL;
929
0
    }
930
0
    return Py_NewRef(self);
931
0
}
932
933
/* tp_as_number */
934
935
static PyNumberMethods odict_as_number = {
936
    .nb_or = odict_or,
937
    .nb_inplace_or = odict_inplace_or,
938
};
939
940
941
/* ----------------------------------------------
942
 * OrderedDict methods
943
 */
944
945
/* fromkeys() */
946
947
/*[clinic input]
948
@permit_long_summary
949
@classmethod
950
OrderedDict.fromkeys
951
952
    iterable as seq: object
953
    value: object = None
954
955
Create a new ordered dictionary with keys from iterable and values set to value.
956
[clinic start generated code]*/
957
958
static PyObject *
959
OrderedDict_fromkeys_impl(PyTypeObject *type, PyObject *seq, PyObject *value)
960
/*[clinic end generated code: output=c10390d452d78d6d input=1277ae0769083848]*/
961
0
{
962
0
    return _PyDict_FromKeys((PyObject *)type, seq, value);
963
0
}
964
965
/*[clinic input]
966
@critical_section
967
OrderedDict.__sizeof__ -> Py_ssize_t
968
[clinic start generated code]*/
969
970
static Py_ssize_t
971
OrderedDict___sizeof___impl(PyODictObject *self)
972
/*[clinic end generated code: output=1a8560db8cf83ac5 input=655e989ae24daa6a]*/
973
0
{
974
0
    Py_ssize_t res = _PyDict_SizeOf_LockHeld((PyDictObject *)self);
975
0
    res += sizeof(_ODictNode *) * self->od_fast_nodes_size;  /* od_fast_nodes */
976
0
    if (!_odict_EMPTY(self)) {
977
0
        res += sizeof(_ODictNode) * PyODict_SIZE(self);  /* linked-list */
978
0
    }
979
0
    return res;
980
0
}
981
982
/*[clinic input]
983
OrderedDict.__reduce__
984
    self as od: self(type="PyODictObject *")
985
986
Return state information for pickling
987
[clinic start generated code]*/
988
989
static PyObject *
990
OrderedDict___reduce___impl(PyODictObject *od)
991
/*[clinic end generated code: output=71eeb81f760a6a8e input=b0467c7ec400fe5e]*/
992
0
{
993
0
    PyObject *state, *result = NULL;
994
0
    PyObject *items_iter, *items, *args = NULL;
995
996
    /* capture any instance state */
997
0
    state = _PyObject_GetState((PyObject *)od);
998
0
    if (state == NULL)
999
0
        goto Done;
1000
1001
    /* build the result */
1002
0
    args = PyTuple_New(0);
1003
0
    if (args == NULL)
1004
0
        goto Done;
1005
1006
0
    items = PyObject_CallMethodNoArgs((PyObject *)od, &_Py_ID(items));
1007
0
    if (items == NULL)
1008
0
        goto Done;
1009
1010
0
    items_iter = PyObject_GetIter(items);
1011
0
    Py_DECREF(items);
1012
0
    if (items_iter == NULL)
1013
0
        goto Done;
1014
1015
0
    result = PyTuple_Pack(5, Py_TYPE(od), args, state, Py_None, items_iter);
1016
0
    Py_DECREF(items_iter);
1017
1018
0
Done:
1019
0
    Py_XDECREF(state);
1020
0
    Py_XDECREF(args);
1021
1022
0
    return result;
1023
0
}
1024
1025
/* setdefault(): Skips __missing__() calls. */
1026
1027
static int PyODict_SetItem_LockHeld(PyObject *self, PyObject *key, PyObject *value);
1028
1029
/*[clinic input]
1030
@critical_section
1031
OrderedDict.setdefault
1032
1033
    key: object
1034
    default: object = None
1035
1036
Insert key with a value of default if key is not in the dictionary.
1037
1038
Return the value for key if key is in the dictionary, else default.
1039
[clinic start generated code]*/
1040
1041
static PyObject *
1042
OrderedDict_setdefault_impl(PyODictObject *self, PyObject *key,
1043
                            PyObject *default_value)
1044
/*[clinic end generated code: output=97537cb7c28464b6 input=d7b93e92734f99b5]*/
1045
0
{
1046
0
    PyObject *result = NULL;
1047
1048
0
    if (PyODict_CheckExact(self)) {
1049
0
        result = PyODict_GetItemWithError(self, key);  /* borrowed */
1050
0
        if (result == NULL) {
1051
0
            if (PyErr_Occurred())
1052
0
                return NULL;
1053
0
            assert(_odict_find_node(self, key) == NULL);
1054
0
            if (PyODict_SetItem_LockHeld((PyObject *)self, key, default_value) >= 0) {
1055
0
                result = Py_NewRef(default_value);
1056
0
            }
1057
0
        }
1058
0
        else {
1059
0
            Py_INCREF(result);
1060
0
        }
1061
0
    }
1062
0
    else {
1063
0
        int exists = PySequence_Contains((PyObject *)self, key);
1064
0
        if (exists < 0) {
1065
0
            return NULL;
1066
0
        }
1067
0
        else if (exists) {
1068
0
            result = PyObject_GetItem((PyObject *)self, key);
1069
0
        }
1070
0
        else if (PyObject_SetItem((PyObject *)self, key, default_value) >= 0) {
1071
0
            result = Py_NewRef(default_value);
1072
0
        }
1073
0
    }
1074
1075
0
    return result;
1076
0
}
1077
1078
/* pop() */
1079
1080
static PyObject *
1081
_odict_popkey_hash(PyObject *od, PyObject *key, PyObject *failobj,
1082
                   Py_hash_t hash)
1083
0
{
1084
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
1085
1086
0
    PyObject *value = NULL;
1087
0
    _ODictNode *node = _odict_find_node_hash(_PyODictObject_CAST(od), key, hash);
1088
0
    if (node != NULL) {
1089
        /* Pop the node first to avoid a possible dict resize (due to
1090
           eval loop reentrancy) and complications due to hash collision
1091
           resolution. */
1092
0
        int res = _odict_clear_node(_PyODictObject_CAST(od), node, key, hash);
1093
0
        if (res < 0) {
1094
0
            goto done;
1095
0
        }
1096
        /* Now delete the value from the dict. */
1097
0
        if (_PyDict_Pop_KnownHash((PyDictObject *)od, key, hash,
1098
0
                                  &value) == 0) {
1099
0
            value = Py_NewRef(failobj);
1100
0
        }
1101
0
    }
1102
0
    else if (value == NULL && !PyErr_Occurred()) {
1103
        /* Apply the fallback value, if necessary. */
1104
0
        if (failobj) {
1105
0
            value = Py_NewRef(failobj);
1106
0
        }
1107
0
        else {
1108
0
            PyErr_SetObject(PyExc_KeyError, key);
1109
0
        }
1110
0
    }
1111
0
done:
1112
1113
0
    return value;
1114
0
}
1115
1116
/* Skips __missing__() calls. */
1117
/*[clinic input]
1118
@critical_section
1119
@permit_long_summary
1120
OrderedDict.pop
1121
1122
    key: object
1123
    default: object = NULL
1124
1125
od.pop(key[,default]) -> v, remove specified key and return the corresponding value.
1126
1127
If the key is not found, return the default if given; otherwise,
1128
raise a KeyError.
1129
[clinic start generated code]*/
1130
1131
static PyObject *
1132
OrderedDict_pop_impl(PyODictObject *self, PyObject *key,
1133
                     PyObject *default_value)
1134
/*[clinic end generated code: output=7a6447d104e7494b input=0742e3c9bf076a72]*/
1135
0
{
1136
0
    Py_hash_t hash = PyObject_Hash(key);
1137
0
    if (hash == -1)
1138
0
        return NULL;
1139
0
    return _odict_popkey_hash((PyObject *)self, key, default_value, hash);
1140
0
}
1141
1142
1143
/* popitem() */
1144
1145
/*[clinic input]
1146
@critical_section
1147
OrderedDict.popitem
1148
1149
    last: bool = True
1150
1151
Remove and return a (key, value) pair from the dictionary.
1152
1153
Pairs are returned in LIFO order if last is true or FIFO order if
1154
false.
1155
[clinic start generated code]*/
1156
1157
static PyObject *
1158
OrderedDict_popitem_impl(PyODictObject *self, int last)
1159
/*[clinic end generated code: output=98e7d986690d49eb input=ebf1cc91579c9e54]*/
1160
0
{
1161
0
    PyObject *key, *value;
1162
0
    _ODictNode *node;
1163
1164
    /* pull the item */
1165
1166
0
    if (_odict_EMPTY(self)) {
1167
0
        PyErr_SetString(PyExc_KeyError, "dictionary is empty");
1168
0
        return NULL;
1169
0
    }
1170
1171
0
    node = last ? _odict_LAST(self) : _odict_FIRST(self);
1172
0
    key = Py_NewRef(_odictnode_KEY(node));
1173
0
    value = _odict_popkey_hash((PyObject *)self, key, NULL, _odictnode_HASH(node));
1174
0
    if (value == NULL) {
1175
0
        Py_DECREF(key);
1176
0
        return NULL;
1177
0
    }
1178
0
    return _PyTuple_FromPairSteal(key, value);
1179
0
}
1180
1181
/* keys() */
1182
1183
/* MutableMapping.keys() does not have a docstring. */
1184
PyDoc_STRVAR(odict_keys__doc__, "");
1185
1186
static PyObject * odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored));  /* forward */
1187
static int
1188
_PyODict_SetItem_KnownHash_LockHeld(PyObject *od, PyObject *key, PyObject *value,
1189
                                    Py_hash_t hash); /* forward */
1190
1191
/* values() */
1192
1193
/* MutableMapping.values() does not have a docstring. */
1194
PyDoc_STRVAR(odict_values__doc__, "");
1195
1196
static PyObject * odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored));  /* forward */
1197
1198
/* items() */
1199
1200
/* MutableMapping.items() does not have a docstring. */
1201
PyDoc_STRVAR(odict_items__doc__, "");
1202
1203
static PyObject * odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored));  /* forward */
1204
1205
/* update() */
1206
1207
/* MutableMapping.update() does not have a docstring. */
1208
PyDoc_STRVAR(odict_update__doc__, "");
1209
1210
/* forward */
1211
static PyObject * mutablemapping_update(PyObject *, PyObject *, PyObject *);
1212
1213
871
#define odict_update mutablemapping_update
1214
1215
/*[clinic input]
1216
@critical_section
1217
OrderedDict.clear
1218
1219
Remove all items from ordered dict.
1220
[clinic start generated code]*/
1221
1222
static PyObject *
1223
OrderedDict_clear_impl(PyODictObject *self)
1224
/*[clinic end generated code: output=a1a76d1322f556c5 input=08b12322e74c535c]*/
1225
0
{
1226
0
    _PyDict_Clear_LockHeld((PyObject *)self);
1227
0
    _odict_clear_nodes(self);
1228
0
    Py_RETURN_NONE;
1229
0
}
1230
1231
/* copy() */
1232
1233
/*[clinic input]
1234
@critical_section
1235
OrderedDict.copy
1236
    self as od: self
1237
1238
A shallow copy of ordered dict.
1239
[clinic start generated code]*/
1240
1241
static PyObject *
1242
OrderedDict_copy_impl(PyObject *od)
1243
/*[clinic end generated code: output=9cdbe7394aecc576 input=e329951ae617ed48]*/
1244
0
{
1245
0
    _ODictNode *node;
1246
0
    PyObject *od_copy;
1247
1248
0
    if (PyODict_CheckExact(od))
1249
0
        od_copy = PyODict_New();
1250
0
    else
1251
0
        od_copy = _PyObject_CallNoArgs((PyObject *)Py_TYPE(od));
1252
0
    if (od_copy == NULL)
1253
0
        return NULL;
1254
1255
    /* The loop body may run arbitrary Python code which could mutate od and
1256
       free its nodes (gh-148660); detect that the same way __eq__ does. */
1257
0
    size_t state = _PyODictObject_CAST(od)->od_state;
1258
1259
0
    if (PyODict_CheckExact(od)) {
1260
0
        _odict_FOREACH(od, node) {
1261
0
            PyObject *key = Py_NewRef(_odictnode_KEY(node));
1262
0
            Py_hash_t hash = _odictnode_HASH(node);
1263
0
            PyObject *value = PyODict_GetItemWithError(od, key);
1264
0
            if (value == NULL) {
1265
0
                if (!PyErr_Occurred())
1266
0
                    PyErr_SetObject(PyExc_KeyError, key);
1267
0
                Py_DECREF(key);
1268
0
                goto fail;
1269
0
            }
1270
0
            int res = _PyODict_SetItem_KnownHash_LockHeld((PyObject *)od_copy,
1271
0
                                                          key, value, hash);
1272
0
            Py_DECREF(key);
1273
0
            if (res != 0)
1274
0
                goto fail;
1275
0
            if (_PyODictObject_CAST(od)->od_state != state)
1276
0
                goto mutated;
1277
0
        }
1278
0
    }
1279
0
    else {
1280
0
        _odict_FOREACH(od, node) {
1281
0
            PyObject *key = Py_NewRef(_odictnode_KEY(node));
1282
0
            PyObject *value = PyObject_GetItem(od, key);
1283
0
            if (value == NULL) {
1284
0
                Py_DECREF(key);
1285
0
                goto fail;
1286
0
            }
1287
0
            int res = PyObject_SetItem((PyObject *)od_copy, key, value);
1288
0
            Py_DECREF(value);
1289
0
            Py_DECREF(key);
1290
0
            if (res != 0)
1291
0
                goto fail;
1292
0
            if (_PyODictObject_CAST(od)->od_state != state)
1293
0
                goto mutated;
1294
0
        }
1295
0
    }
1296
0
    return od_copy;
1297
1298
0
mutated:
1299
0
    PyErr_SetString(PyExc_RuntimeError,
1300
0
                    "OrderedDict mutated during iteration");
1301
0
fail:
1302
0
    Py_DECREF(od_copy);
1303
0
    return NULL;
1304
0
}
1305
1306
/* __reversed__() */
1307
1308
PyDoc_STRVAR(odict_reversed__doc__, "od.__reversed__() <==> reversed(od)");
1309
1310
14.1k
#define _odict_ITER_REVERSED 1
1311
20.0k
#define _odict_ITER_KEYS 2
1312
23.5k
#define _odict_ITER_VALUES 4
1313
12.9k
#define _odict_ITER_ITEMS (_odict_ITER_KEYS|_odict_ITER_VALUES)
1314
1315
/* forward */
1316
static PyObject * odictiter_new(PyODictObject *, int);
1317
1318
static PyObject *
1319
odict_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
1320
0
{
1321
0
    PyODictObject *od = _PyODictObject_CAST(op);
1322
0
    return odictiter_new(od, _odict_ITER_KEYS|_odict_ITER_REVERSED);
1323
0
}
1324
1325
1326
/* move_to_end() */
1327
1328
/*[clinic input]
1329
@critical_section
1330
OrderedDict.move_to_end
1331
1332
    key: object
1333
    last: bool = True
1334
1335
Move an existing element to the end (or beginning if last is false).
1336
1337
Raise KeyError if the element does not exist.
1338
[clinic start generated code]*/
1339
1340
static PyObject *
1341
OrderedDict_move_to_end_impl(PyODictObject *self, PyObject *key, int last)
1342
/*[clinic end generated code: output=fafa4c5cc9b92f20 input=09f8bc7053c0f6d4]*/
1343
2.90M
{
1344
2.90M
    _ODictNode *node;
1345
1346
2.90M
    if (_odict_EMPTY(self)) {
1347
0
        PyErr_SetObject(PyExc_KeyError, key);
1348
0
        return NULL;
1349
0
    }
1350
2.90M
    node = last ? _odict_LAST(self) : _odict_FIRST(self);
1351
2.90M
    if (key != _odictnode_KEY(node)) {
1352
2.90M
        node = _odict_find_node(self, key);
1353
2.90M
        if (node == NULL) {
1354
0
            if (!PyErr_Occurred())
1355
0
                PyErr_SetObject(PyExc_KeyError, key);
1356
0
            return NULL;
1357
0
        }
1358
2.90M
        if (last) {
1359
            /* Only move if not already the last one. */
1360
2.90M
            if (node != _odict_LAST(self)) {
1361
189k
                _odict_remove_node(self, node);
1362
189k
                _odict_add_tail(self, node);
1363
189k
            }
1364
2.90M
        }
1365
0
        else {
1366
            /* Only move if not already the first one. */
1367
0
            if (node != _odict_FIRST(self)) {
1368
0
                _odict_remove_node(self, node);
1369
0
                _odict_add_head(self, node);
1370
0
            }
1371
0
        }
1372
2.90M
    }
1373
2.90M
    Py_RETURN_NONE;
1374
2.90M
}
1375
1376
1377
/* tp_methods */
1378
1379
static PyMethodDef odict_methods[] = {
1380
1381
    /* overridden dict methods */
1382
    ORDEREDDICT_FROMKEYS_METHODDEF
1383
    ORDEREDDICT___SIZEOF___METHODDEF
1384
    ORDEREDDICT___REDUCE___METHODDEF
1385
    ORDEREDDICT_SETDEFAULT_METHODDEF
1386
    ORDEREDDICT_POP_METHODDEF
1387
    ORDEREDDICT_POPITEM_METHODDEF
1388
    {"keys",            odictkeys_new,                  METH_NOARGS,
1389
     odict_keys__doc__},
1390
    {"values",          odictvalues_new,                METH_NOARGS,
1391
     odict_values__doc__},
1392
    {"items",           odictitems_new,                 METH_NOARGS,
1393
     odict_items__doc__},
1394
    {"update",          _PyCFunction_CAST(odict_update), METH_VARARGS | METH_KEYWORDS,
1395
     odict_update__doc__},
1396
     ORDEREDDICT_CLEAR_METHODDEF
1397
     ORDEREDDICT_COPY_METHODDEF
1398
    /* new methods */
1399
    {"__reversed__",    odict_reversed,    METH_NOARGS,
1400
     odict_reversed__doc__},
1401
    ORDEREDDICT_MOVE_TO_END_METHODDEF
1402
1403
    {NULL,              NULL}   /* sentinel */
1404
};
1405
1406
1407
/* ----------------------------------------------
1408
 * OrderedDict members
1409
 */
1410
1411
/* tp_getset */
1412
1413
static PyGetSetDef odict_getset[] = {
1414
    {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1415
    {NULL}
1416
};
1417
1418
/* ----------------------------------------------
1419
 * OrderedDict type slot methods
1420
 */
1421
1422
/* tp_dealloc */
1423
1424
static void
1425
odict_dealloc(PyObject *op)
1426
824
{
1427
824
    PyODictObject *self = _PyODictObject_CAST(op);
1428
824
    PyObject_GC_UnTrack(self);
1429
1430
824
    Py_XDECREF(self->od_inst_dict);
1431
824
    FT_CLEAR_WEAKREFS(op, self->od_weakreflist);
1432
1433
824
    _odict_clear_nodes(self);
1434
824
    PyDict_Type.tp_dealloc((PyObject *)self);
1435
824
}
1436
1437
/* tp_repr */
1438
1439
static PyObject *
1440
odict_repr(PyObject *op)
1441
0
{
1442
0
    PyODictObject *self = _PyODictObject_CAST(op);
1443
0
    int i;
1444
0
    PyObject *result = NULL, *dcopy = NULL;
1445
1446
0
    if (PyODict_SIZE(self) == 0)
1447
0
        return PyUnicode_FromFormat("%s()", _PyType_Name(Py_TYPE(self)));
1448
1449
0
    i = Py_ReprEnter((PyObject *)self);
1450
0
    if (i != 0) {
1451
0
        return i > 0 ? PyUnicode_FromString("...") : NULL;
1452
0
    }
1453
1454
0
    dcopy = PyDict_Copy((PyObject *)self);
1455
0
    if (dcopy == NULL) {
1456
0
        goto Done;
1457
0
    }
1458
1459
0
    result = PyUnicode_FromFormat("%s(%R)",
1460
0
                                  _PyType_Name(Py_TYPE(self)),
1461
0
                                  dcopy);
1462
0
    Py_DECREF(dcopy);
1463
1464
0
Done:
1465
0
    Py_ReprLeave((PyObject *)self);
1466
0
    return result;
1467
0
}
1468
1469
/* tp_doc */
1470
1471
PyDoc_STRVAR(odict_doc,
1472
        "Dictionary that remembers insertion order");
1473
1474
/* tp_traverse */
1475
1476
static int
1477
odict_traverse(PyObject *op, visitproc visit, void *arg)
1478
354
{
1479
354
    PyODictObject *od = _PyODictObject_CAST(op);
1480
354
    _ODictNode *node;
1481
1482
354
    Py_VISIT(od->od_inst_dict);
1483
906
    _odict_FOREACH(od, node) {
1484
906
        Py_VISIT(_odictnode_KEY(node));
1485
906
    }
1486
354
    return PyDict_Type.tp_traverse((PyObject *)od, visit, arg);
1487
354
}
1488
1489
/* tp_clear */
1490
1491
static int
1492
odict_tp_clear(PyObject *op)
1493
0
{
1494
0
    PyODictObject *od = _PyODictObject_CAST(op);
1495
0
    Py_CLEAR(od->od_inst_dict);
1496
    // cannot use lock held variant as critical section is not held here
1497
0
    PyDict_Clear(op);
1498
0
    _odict_clear_nodes(od);
1499
0
    return 0;
1500
0
}
1501
1502
/* tp_richcompare */
1503
1504
static PyObject *
1505
odict_richcompare_lock_held(PyObject *v, PyObject *w, int op)
1506
0
{
1507
0
    if (!PyODict_Check(v) || !PyAnyDict_Check(w)) {
1508
0
        Py_RETURN_NOTIMPLEMENTED;
1509
0
    }
1510
1511
0
    if (op == Py_EQ || op == Py_NE) {
1512
0
        PyObject *res, *cmp;
1513
0
        int eq;
1514
1515
0
        cmp = PyDict_Type.tp_richcompare(v, w, op);
1516
0
        if (cmp == NULL)
1517
0
            return NULL;
1518
0
        if (!PyODict_Check(w))
1519
0
            return cmp;
1520
0
        if (op == Py_EQ && cmp == Py_False)
1521
0
            return cmp;
1522
0
        if (op == Py_NE && cmp == Py_True)
1523
0
            return cmp;
1524
0
        Py_DECREF(cmp);
1525
1526
        /* Try comparing odict keys. */
1527
0
        eq = _odict_keys_equal(_PyODictObject_CAST(v), _PyODictObject_CAST(w));
1528
0
        if (eq < 0)
1529
0
            return NULL;
1530
1531
0
        res = (eq == (op == Py_EQ)) ? Py_True : Py_False;
1532
0
        return Py_NewRef(res);
1533
0
    } else {
1534
0
        Py_RETURN_NOTIMPLEMENTED;
1535
0
    }
1536
0
}
1537
1538
static PyObject *
1539
odict_richcompare(PyObject *v, PyObject *w, int op)
1540
0
{
1541
0
    PyObject *res;
1542
0
    Py_BEGIN_CRITICAL_SECTION2(v, w);
1543
0
    res = odict_richcompare_lock_held(v, w, op);
1544
0
    Py_END_CRITICAL_SECTION2();
1545
0
    return res;
1546
0
}
1547
1548
/* tp_iter */
1549
1550
static PyObject *
1551
odict_iter(PyObject *op)
1552
540
{
1553
540
    return odictiter_new(_PyODictObject_CAST(op), _odict_ITER_KEYS);
1554
540
}
1555
1556
/* tp_init */
1557
1558
static int
1559
odict_init(PyObject *self, PyObject *args, PyObject *kwds)
1560
871
{
1561
871
    PyObject *res;
1562
871
    Py_ssize_t len = PyObject_Length(args);
1563
1564
871
    if (len == -1)
1565
0
        return -1;
1566
871
    if (len > 1) {
1567
0
        const char *msg = "expected at most 1 argument, got %zd";
1568
0
        PyErr_Format(PyExc_TypeError, msg, len);
1569
0
        return -1;
1570
0
    }
1571
1572
    /* __init__() triggering update() is just the way things are! */
1573
871
    res = odict_update(self, args, kwds);
1574
871
    if (res == NULL) {
1575
0
        return -1;
1576
871
    } else {
1577
871
        Py_DECREF(res);
1578
871
        return 0;
1579
871
    }
1580
871
}
1581
1582
/* PyODict_Type */
1583
1584
PyTypeObject PyODict_Type = {
1585
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
1586
    "collections.OrderedDict",                  /* tp_name */
1587
    sizeof(PyODictObject),                      /* tp_basicsize */
1588
    0,                                          /* tp_itemsize */
1589
    odict_dealloc,                              /* tp_dealloc */
1590
    0,                                          /* tp_vectorcall_offset */
1591
    0,                                          /* tp_getattr */
1592
    0,                                          /* tp_setattr */
1593
    0,                                          /* tp_as_async */
1594
    odict_repr,                                 /* tp_repr */
1595
    &odict_as_number,                           /* tp_as_number */
1596
    0,                                          /* tp_as_sequence */
1597
    &odict_as_mapping,                          /* tp_as_mapping */
1598
    0,                                          /* tp_hash */
1599
    0,                                          /* tp_call */
1600
    0,                                          /* tp_str */
1601
    0,                                          /* tp_getattro */
1602
    0,                                          /* tp_setattro */
1603
    0,                                          /* tp_as_buffer */
1604
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,/* tp_flags */
1605
    odict_doc,                                  /* tp_doc */
1606
    odict_traverse,                             /* tp_traverse */
1607
    odict_tp_clear,                             /* tp_clear */
1608
    odict_richcompare,                          /* tp_richcompare */
1609
    offsetof(PyODictObject, od_weakreflist),    /* tp_weaklistoffset */
1610
    odict_iter,                                 /* tp_iter */
1611
    0,                                          /* tp_iternext */
1612
    odict_methods,                              /* tp_methods */
1613
    0,                                          /* tp_members */
1614
    odict_getset,                               /* tp_getset */
1615
    &PyDict_Type,                               /* tp_base */
1616
    0,                                          /* tp_dict */
1617
    0,                                          /* tp_descr_get */
1618
    0,                                          /* tp_descr_set */
1619
    offsetof(PyODictObject, od_inst_dict),      /* tp_dictoffset */
1620
    odict_init,                                 /* tp_init */
1621
    PyType_GenericAlloc,                        /* tp_alloc */
1622
    0,                                          /* tp_new */
1623
    0,                                          /* tp_free */
1624
};
1625
1626
1627
/* ----------------------------------------------
1628
 * the public OrderedDict API
1629
 */
1630
1631
PyObject *
1632
PyODict_New(void)
1633
0
{
1634
0
    return PyDict_Type.tp_new(&PyODict_Type, NULL, NULL);
1635
0
}
1636
1637
static int
1638
_PyODict_SetItem_KnownHash_LockHeld(PyObject *od, PyObject *key, PyObject *value,
1639
                                    Py_hash_t hash)
1640
2.10k
{
1641
2.10k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
1642
2.10k
    int res = _PyDict_SetItem_KnownHash_LockHeld((PyDictObject *)od, key, value, hash);
1643
2.10k
    if (res == 0) {
1644
2.10k
        res = _odict_add_new_node(_PyODictObject_CAST(od), key, hash);
1645
2.10k
        if (res < 0) {
1646
            /* Revert setting the value on the dict */
1647
0
            PyObject *exc = PyErr_GetRaisedException();
1648
0
            (void) _PyDict_DelItem_KnownHash(od, key, hash);
1649
0
            _PyErr_ChainExceptions1(exc);
1650
0
        }
1651
2.10k
    }
1652
2.10k
    return res;
1653
2.10k
}
1654
1655
1656
static int
1657
PyODict_SetItem_LockHeld(PyObject *od, PyObject *key, PyObject *value)
1658
2.10k
{
1659
2.10k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
1660
2.10k
    Py_hash_t hash = PyObject_Hash(key);
1661
2.10k
    if (hash == -1) {
1662
0
        return -1;
1663
0
    }
1664
2.10k
    return _PyODict_SetItem_KnownHash_LockHeld(od, key, value, hash);
1665
2.10k
}
1666
1667
int
1668
PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)
1669
2.10k
{
1670
2.10k
    int res;
1671
2.10k
    Py_BEGIN_CRITICAL_SECTION(od);
1672
2.10k
    res = PyODict_SetItem_LockHeld(od, key, value);
1673
2.10k
    Py_END_CRITICAL_SECTION();
1674
2.10k
    return res;
1675
2.10k
}
1676
1677
int
1678
PyODict_DelItem_LockHeld(PyObject *od, PyObject *key)
1679
0
{
1680
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
1681
0
    int res;
1682
0
    Py_hash_t hash = PyObject_Hash(key);
1683
0
    if (hash == -1)
1684
0
        return -1;
1685
0
    res = _odict_clear_node(_PyODictObject_CAST(od), NULL, key, hash);
1686
0
    if (res < 0)
1687
0
        return -1;
1688
0
    return _PyDict_DelItem_KnownHash_LockHeld(od, key, hash);
1689
0
}
1690
1691
int
1692
PyODict_DelItem(PyObject *od, PyObject *key)
1693
0
{
1694
0
    int res;
1695
0
    Py_BEGIN_CRITICAL_SECTION(od);
1696
0
    res = PyODict_DelItem_LockHeld(od, key);
1697
0
    Py_END_CRITICAL_SECTION();
1698
0
    return res;
1699
0
}
1700
1701
/* -------------------------------------------
1702
 * The OrderedDict views (keys/values/items)
1703
 */
1704
1705
typedef struct {
1706
    PyObject_HEAD
1707
    int kind;
1708
    PyODictObject *di_odict;
1709
    Py_ssize_t di_size;
1710
    size_t di_state;
1711
    PyObject *di_current;
1712
    PyObject *di_result; /* reusable result tuple for iteritems */
1713
} odictiterobject;
1714
1715
static void
1716
odictiter_dealloc(PyObject *op)
1717
3.23k
{
1718
3.23k
    odictiterobject *di = (odictiterobject*)op;
1719
3.23k
    _PyObject_GC_UNTRACK(di);
1720
3.23k
    Py_XDECREF(di->di_odict);
1721
3.23k
    Py_XDECREF(di->di_current);
1722
3.23k
    if ((di->kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) {
1723
0
        Py_DECREF(di->di_result);
1724
0
    }
1725
3.23k
    PyObject_GC_Del(di);
1726
3.23k
}
1727
1728
static int
1729
odictiter_traverse(PyObject *op, visitproc visit, void *arg)
1730
0
{
1731
0
    odictiterobject *di = (odictiterobject*)op;
1732
0
    Py_VISIT(di->di_odict);
1733
0
    Py_VISIT(di->di_current);  /* A key could be any type, not just str. */
1734
0
    Py_VISIT(di->di_result);
1735
0
    return 0;
1736
0
}
1737
1738
/* In order to protect against modifications during iteration, we track
1739
 * the current key instead of the current node. */
1740
static PyObject *
1741
odictiter_nextkey_lock_held(odictiterobject *di)
1742
10.8k
{
1743
10.8k
    assert(di->di_odict != NULL);
1744
10.8k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(di->di_odict);
1745
10.8k
    PyObject *key = NULL;
1746
10.8k
    _ODictNode *node;
1747
10.8k
    int reversed = di->kind & _odict_ITER_REVERSED;
1748
1749
10.8k
    if (di->di_current == NULL)
1750
2.98k
        goto done;  /* We're already done. */
1751
1752
    /* Check for unsupported changes. */
1753
7.88k
    if (di->di_odict->od_state != di->di_state) {
1754
0
        PyErr_SetString(PyExc_RuntimeError,
1755
0
                        "OrderedDict mutated during iteration");
1756
0
        goto done;
1757
0
    }
1758
7.88k
    if (di->di_size != PyODict_SIZE(di->di_odict)) {
1759
0
        PyErr_SetString(PyExc_RuntimeError,
1760
0
                        "OrderedDict changed size during iteration");
1761
0
        di->di_size = -1; /* Make this state sticky */
1762
0
        return NULL;
1763
0
    }
1764
1765
    /* Get the key. */
1766
7.88k
    node = _odict_find_node(di->di_odict, di->di_current);
1767
7.88k
    if (node == NULL) {
1768
0
        if (!PyErr_Occurred())
1769
0
            PyErr_SetObject(PyExc_KeyError, di->di_current);
1770
        /* Must have been deleted. */
1771
0
        Py_CLEAR(di->di_current);
1772
0
        return NULL;
1773
0
    }
1774
7.88k
    key = di->di_current;
1775
1776
    /* Advance to the next key. */
1777
7.88k
    node = reversed ? _odictnode_PREV(node) : _odictnode_NEXT(node);
1778
7.88k
    if (node == NULL) {
1779
        /* Reached the end. */
1780
2.50k
        di->di_current = NULL;
1781
2.50k
    }
1782
5.38k
    else {
1783
5.38k
        di->di_current = Py_NewRef(_odictnode_KEY(node));
1784
5.38k
    }
1785
1786
7.88k
    return key;
1787
1788
2.98k
done:
1789
2.98k
    Py_CLEAR(di->di_odict);
1790
2.98k
    return key;
1791
7.88k
}
1792
1793
1794
static PyObject *
1795
odictiter_nextkey(odictiterobject *di)
1796
10.8k
{
1797
10.8k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(di);
1798
10.8k
    if (di->di_odict == NULL) {
1799
8
        return NULL;
1800
8
    }
1801
10.8k
    PyObject *res;
1802
10.8k
    Py_BEGIN_CRITICAL_SECTION(di->di_odict);
1803
10.8k
    res = odictiter_nextkey_lock_held(di);
1804
10.8k
    Py_END_CRITICAL_SECTION();
1805
10.8k
    return res;
1806
10.8k
}
1807
1808
/*[clinic input]
1809
@critical_section
1810
odictiter.__next__ as odictiter_iternext
1811
[clinic start generated code]*/
1812
1813
static PyObject *
1814
odictiter_iternext_impl(PyObject *self)
1815
/*[clinic end generated code: output=71aef8eec9e1a133 input=bc8bec6c85481b93]*/
1816
10.8k
{
1817
10.8k
    odictiterobject *di = (odictiterobject*)self;
1818
10.8k
    PyObject *result, *value;
1819
10.8k
    PyObject *key = odictiter_nextkey(di);  /* new reference */
1820
1821
10.8k
    if (key == NULL)
1822
2.99k
        return NULL;
1823
1824
    /* Handle the keys case. */
1825
7.88k
    if (! (di->kind & _odict_ITER_VALUES)) {
1826
1.37k
        return key;
1827
1.37k
    }
1828
1829
6.51k
    if (PyDict_GetItemRef((PyObject *)di->di_odict, key, &value) != 1) {
1830
0
        if (!PyErr_Occurred())
1831
0
            PyErr_SetObject(PyExc_KeyError, key);
1832
0
        Py_DECREF(key);
1833
0
        goto error;
1834
0
    }
1835
1836
    /* Handle the values case. */
1837
6.51k
    if (!(di->kind & _odict_ITER_KEYS)) {
1838
6.51k
        Py_DECREF(key);
1839
6.51k
        return value;
1840
6.51k
    }
1841
1842
    /* Handle the items case. */
1843
0
    result = di->di_result;
1844
1845
0
    if (_PyObject_IsUniquelyReferenced(result)) {
1846
        /* not in use so we can reuse it
1847
         * (the common case during iteration) */
1848
0
        Py_INCREF(result);
1849
0
        Py_DECREF(PyTuple_GET_ITEM(result, 0));  /* borrowed */
1850
0
        Py_DECREF(PyTuple_GET_ITEM(result, 1));  /* borrowed */
1851
        // bpo-42536: The GC may have untracked this result tuple. Since we're
1852
        // recycling it, make sure it's tracked again:
1853
0
        _PyTuple_Recycle(result);
1854
0
        PyTuple_SET_ITEM(result, 0, key);  /* steals reference */
1855
0
        PyTuple_SET_ITEM(result, 1, value);  /* steals reference */
1856
0
    }
1857
0
    else {
1858
0
        result = _PyTuple_FromPairSteal(key, value);
1859
0
        if (result == NULL) {
1860
0
            goto error;
1861
0
        }
1862
0
    }
1863
1864
0
    return result;
1865
1866
0
error:
1867
0
    Py_CLEAR(di->di_current);
1868
0
    Py_CLEAR(di->di_odict);
1869
0
    return NULL;
1870
0
}
1871
1872
1873
/* No need for tp_clear because odictiterobject is not mutable. */
1874
1875
PyDoc_STRVAR(reduce_doc, "Return state information for pickling");
1876
1877
static PyObject *
1878
odictiter_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
1879
0
{
1880
0
    odictiterobject *di = (odictiterobject*)op;
1881
1882
    /* copy the iterator state */
1883
0
    odictiterobject tmp = *di;
1884
0
    Py_XINCREF(tmp.di_odict);
1885
0
    Py_XINCREF(tmp.di_current);
1886
1887
    /* iterate the temporary into a list */
1888
0
    PyObject *list = PySequence_List((PyObject*)&tmp);
1889
0
    Py_XDECREF(tmp.di_odict);
1890
0
    Py_XDECREF(tmp.di_current);
1891
0
    if (list == NULL) {
1892
0
        return NULL;
1893
0
    }
1894
0
    return Py_BuildValue("N(N)", _PyEval_GetBuiltin(&_Py_ID(iter)), list);
1895
0
}
1896
1897
static PyMethodDef odictiter_methods[] = {
1898
    {"__reduce__", odictiter_reduce, METH_NOARGS, reduce_doc},
1899
    {NULL,              NULL}           /* sentinel */
1900
};
1901
1902
PyTypeObject PyODictIter_Type = {
1903
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
1904
    "odict_iterator",                         /* tp_name */
1905
    sizeof(odictiterobject),                  /* tp_basicsize */
1906
    0,                                        /* tp_itemsize */
1907
    /* methods */
1908
    odictiter_dealloc,                        /* tp_dealloc */
1909
    0,                                        /* tp_vectorcall_offset */
1910
    0,                                        /* tp_getattr */
1911
    0,                                        /* tp_setattr */
1912
    0,                                        /* tp_as_async */
1913
    0,                                        /* tp_repr */
1914
    0,                                        /* tp_as_number */
1915
    0,                                        /* tp_as_sequence */
1916
    0,                                        /* tp_as_mapping */
1917
    0,                                        /* tp_hash */
1918
    0,                                        /* tp_call */
1919
    0,                                        /* tp_str */
1920
    PyObject_GenericGetAttr,                  /* tp_getattro */
1921
    0,                                        /* tp_setattro */
1922
    0,                                        /* tp_as_buffer */
1923
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,  /* tp_flags */
1924
    0,                                        /* tp_doc */
1925
    odictiter_traverse,                       /* tp_traverse */
1926
    0,                                        /* tp_clear */
1927
    0,                                        /* tp_richcompare */
1928
    0,                                        /* tp_weaklistoffset */
1929
    PyObject_SelfIter,                        /* tp_iter */
1930
    odictiter_iternext,                       /* tp_iternext */
1931
    odictiter_methods,                        /* tp_methods */
1932
    0,
1933
};
1934
1935
static PyObject *
1936
odictiter_new(PyODictObject *od, int kind)
1937
3.23k
{
1938
3.23k
    odictiterobject *di;
1939
3.23k
    _ODictNode *node;
1940
3.23k
    int reversed = kind & _odict_ITER_REVERSED;
1941
3.23k
    PyObject *result = NULL;
1942
1943
3.23k
    if ((kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) {
1944
0
        result = _PyTuple_FromPairSteal(Py_None, Py_None);
1945
0
        if (result == NULL) {
1946
0
            return NULL;
1947
0
        }
1948
0
    }
1949
3.23k
    di = PyObject_GC_New(odictiterobject, &PyODictIter_Type);
1950
3.23k
    if (di == NULL) {
1951
0
        Py_XDECREF(result);
1952
0
        return NULL;
1953
0
    }
1954
1955
3.23k
    di->di_result = result;
1956
3.23k
    di->kind = kind;
1957
3.23k
    Py_BEGIN_CRITICAL_SECTION(od);
1958
3.23k
    node = reversed ? _odict_LAST(od) : _odict_FIRST(od);
1959
3.23k
    di->di_current = node ? Py_NewRef(_odictnode_KEY(node)) : NULL;
1960
3.23k
    di->di_size = PyODict_SIZE(od);
1961
3.23k
    di->di_state = od->od_state;
1962
3.23k
    di->di_odict = (PyODictObject*)Py_NewRef(od);
1963
3.23k
    Py_END_CRITICAL_SECTION();
1964
1965
3.23k
    _PyObject_GC_TRACK(di);
1966
3.23k
    return (PyObject *)di;
1967
3.23k
}
1968
1969
/* keys() */
1970
1971
static PyObject *
1972
odictkeys_iter(PyObject *op)
1973
0
{
1974
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
1975
0
    if (dv->dv_dict == NULL) {
1976
0
        Py_RETURN_NONE;
1977
0
    }
1978
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
1979
0
            _odict_ITER_KEYS);
1980
0
}
1981
1982
static PyObject *
1983
odictkeys_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
1984
0
{
1985
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
1986
0
    if (dv->dv_dict == NULL) {
1987
0
        Py_RETURN_NONE;
1988
0
    }
1989
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
1990
0
            _odict_ITER_KEYS|_odict_ITER_REVERSED);
1991
0
}
1992
1993
static PyMethodDef odictkeys_methods[] = {
1994
    {"__reversed__", odictkeys_reversed, METH_NOARGS, NULL},
1995
    {NULL,          NULL}           /* sentinel */
1996
};
1997
1998
PyTypeObject PyODictKeys_Type = {
1999
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2000
    "odict_keys",                             /* tp_name */
2001
    0,                                        /* tp_basicsize */
2002
    0,                                        /* tp_itemsize */
2003
    0,                                        /* tp_dealloc */
2004
    0,                                        /* tp_vectorcall_offset */
2005
    0,                                        /* tp_getattr */
2006
    0,                                        /* tp_setattr */
2007
    0,                                        /* tp_as_async */
2008
    0,                                        /* tp_repr */
2009
    0,                                        /* tp_as_number */
2010
    0,                                        /* tp_as_sequence */
2011
    0,                                        /* tp_as_mapping */
2012
    0,                                        /* tp_hash */
2013
    0,                                        /* tp_call */
2014
    0,                                        /* tp_str */
2015
    0,                                        /* tp_getattro */
2016
    0,                                        /* tp_setattro */
2017
    0,                                        /* tp_as_buffer */
2018
    0,                                        /* tp_flags */
2019
    0,                                        /* tp_doc */
2020
    0,                                        /* tp_traverse */
2021
    0,                                        /* tp_clear */
2022
    0,                                        /* tp_richcompare */
2023
    0,                                        /* tp_weaklistoffset */
2024
    odictkeys_iter,                           /* tp_iter */
2025
    0,                                        /* tp_iternext */
2026
    odictkeys_methods,                        /* tp_methods */
2027
    0,                                        /* tp_members */
2028
    0,                                        /* tp_getset */
2029
    &PyDictKeys_Type,                         /* tp_base */
2030
};
2031
2032
static PyObject *
2033
odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored))
2034
0
{
2035
0
    return _PyDictView_New(od, &PyODictKeys_Type);
2036
0
}
2037
2038
/* items() */
2039
2040
static PyObject *
2041
odictitems_iter(PyObject *op)
2042
0
{
2043
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2044
0
    if (dv->dv_dict == NULL) {
2045
0
        Py_RETURN_NONE;
2046
0
    }
2047
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2048
0
            _odict_ITER_KEYS|_odict_ITER_VALUES);
2049
0
}
2050
2051
static PyObject *
2052
odictitems_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
2053
0
{
2054
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2055
0
    if (dv->dv_dict == NULL) {
2056
0
        Py_RETURN_NONE;
2057
0
    }
2058
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2059
0
            _odict_ITER_KEYS|_odict_ITER_VALUES|_odict_ITER_REVERSED);
2060
0
}
2061
2062
static PyMethodDef odictitems_methods[] = {
2063
    {"__reversed__", odictitems_reversed, METH_NOARGS, NULL},
2064
    {NULL,          NULL}           /* sentinel */
2065
};
2066
2067
PyTypeObject PyODictItems_Type = {
2068
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2069
    "odict_items",                            /* tp_name */
2070
    0,                                        /* tp_basicsize */
2071
    0,                                        /* tp_itemsize */
2072
    0,                                        /* tp_dealloc */
2073
    0,                                        /* tp_vectorcall_offset */
2074
    0,                                        /* tp_getattr */
2075
    0,                                        /* tp_setattr */
2076
    0,                                        /* tp_as_async */
2077
    0,                                        /* tp_repr */
2078
    0,                                        /* tp_as_number */
2079
    0,                                        /* tp_as_sequence */
2080
    0,                                        /* tp_as_mapping */
2081
    0,                                        /* tp_hash */
2082
    0,                                        /* tp_call */
2083
    0,                                        /* tp_str */
2084
    0,                                        /* tp_getattro */
2085
    0,                                        /* tp_setattro */
2086
    0,                                        /* tp_as_buffer */
2087
    0,                                        /* tp_flags */
2088
    0,                                        /* tp_doc */
2089
    0,                                        /* tp_traverse */
2090
    0,                                        /* tp_clear */
2091
    0,                                        /* tp_richcompare */
2092
    0,                                        /* tp_weaklistoffset */
2093
    odictitems_iter,                          /* tp_iter */
2094
    0,                                        /* tp_iternext */
2095
    odictitems_methods,                       /* tp_methods */
2096
    0,                                        /* tp_members */
2097
    0,                                        /* tp_getset */
2098
    &PyDictItems_Type,                        /* tp_base */
2099
};
2100
2101
static PyObject *
2102
odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored))
2103
0
{
2104
0
    return _PyDictView_New(od, &PyODictItems_Type);
2105
0
}
2106
2107
/* values() */
2108
2109
static PyObject *
2110
odictvalues_iter(PyObject *op)
2111
2.69k
{
2112
2.69k
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2113
2.69k
    if (dv->dv_dict == NULL) {
2114
0
        Py_RETURN_NONE;
2115
0
    }
2116
2.69k
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2117
2.69k
            _odict_ITER_VALUES);
2118
2.69k
}
2119
2120
static PyObject *
2121
odictvalues_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
2122
0
{
2123
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2124
0
    if (dv->dv_dict == NULL) {
2125
0
        Py_RETURN_NONE;
2126
0
    }
2127
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2128
0
            _odict_ITER_VALUES|_odict_ITER_REVERSED);
2129
0
}
2130
2131
static PyMethodDef odictvalues_methods[] = {
2132
    {"__reversed__", odictvalues_reversed, METH_NOARGS, NULL},
2133
    {NULL,          NULL}           /* sentinel */
2134
};
2135
2136
PyTypeObject PyODictValues_Type = {
2137
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2138
    "odict_values",                           /* tp_name */
2139
    0,                                        /* tp_basicsize */
2140
    0,                                        /* tp_itemsize */
2141
    0,                                        /* tp_dealloc */
2142
    0,                                        /* tp_vectorcall_offset */
2143
    0,                                        /* tp_getattr */
2144
    0,                                        /* tp_setattr */
2145
    0,                                        /* tp_as_async */
2146
    0,                                        /* tp_repr */
2147
    0,                                        /* tp_as_number */
2148
    0,                                        /* tp_as_sequence */
2149
    0,                                        /* tp_as_mapping */
2150
    0,                                        /* tp_hash */
2151
    0,                                        /* tp_call */
2152
    0,                                        /* tp_str */
2153
    0,                                        /* tp_getattro */
2154
    0,                                        /* tp_setattro */
2155
    0,                                        /* tp_as_buffer */
2156
    0,                                        /* tp_flags */
2157
    0,                                        /* tp_doc */
2158
    0,                                        /* tp_traverse */
2159
    0,                                        /* tp_clear */
2160
    0,                                        /* tp_richcompare */
2161
    0,                                        /* tp_weaklistoffset */
2162
    odictvalues_iter,                         /* tp_iter */
2163
    0,                                        /* tp_iternext */
2164
    odictvalues_methods,                      /* tp_methods */
2165
    0,                                        /* tp_members */
2166
    0,                                        /* tp_getset */
2167
    &PyDictValues_Type,                       /* tp_base */
2168
};
2169
2170
static PyObject *
2171
odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored))
2172
2.69k
{
2173
2.69k
    return _PyDictView_New(od, &PyODictValues_Type);
2174
2.69k
}
2175
2176
2177
/* ----------------------------------------------
2178
   MutableMapping implementations
2179
2180
Mapping:
2181
2182
============ ===========
2183
method       uses
2184
============ ===========
2185
__contains__ __getitem__
2186
__eq__       items
2187
__getitem__  +
2188
__iter__     +
2189
__len__      +
2190
__ne__       __eq__
2191
get          __getitem__
2192
items        ItemsView
2193
keys         KeysView
2194
values       ValuesView
2195
============ ===========
2196
2197
ItemsView uses __len__, __iter__, and __getitem__.
2198
KeysView uses __len__, __iter__, and __contains__.
2199
ValuesView uses __len__, __iter__, and __getitem__.
2200
2201
MutableMapping:
2202
2203
============ ===========
2204
method       uses
2205
============ ===========
2206
__delitem__  +
2207
__setitem__  +
2208
clear        popitem
2209
pop          __getitem__
2210
             __delitem__
2211
popitem      __iter__
2212
             _getitem__
2213
             __delitem__
2214
setdefault   __getitem__
2215
             __setitem__
2216
update       __setitem__
2217
============ ===========
2218
*/
2219
2220
static int
2221
mutablemapping_add_pairs(PyObject *self, PyObject *pairs)
2222
566
{
2223
566
    assert(!PyErr_Occurred());
2224
2225
566
    PyObject *pair, *iterator, *unexpected;
2226
566
    int res = 0;
2227
2228
566
    iterator = PyObject_GetIter(pairs);
2229
566
    if (iterator == NULL)
2230
0
        return -1;
2231
2232
1.92k
    while ((pair = PyIter_Next(iterator)) != NULL) {
2233
        /* could be more efficient (see UNPACK_SEQUENCE in ceval.c) */
2234
1.35k
        PyObject *key = NULL, *value = NULL;
2235
1.35k
        PyObject *pair_iterator = PyObject_GetIter(pair);
2236
1.35k
        if (pair_iterator == NULL)
2237
0
            goto Done;
2238
2239
1.35k
        key = PyIter_Next(pair_iterator);
2240
1.35k
        if (key == NULL) {
2241
0
            if (!PyErr_Occurred())
2242
0
                PyErr_SetString(PyExc_ValueError,
2243
0
                                "need more than 0 values to unpack");
2244
0
            goto Done;
2245
0
        }
2246
2247
1.35k
        value = PyIter_Next(pair_iterator);
2248
1.35k
        if (value == NULL) {
2249
0
            if (!PyErr_Occurred())
2250
0
                PyErr_SetString(PyExc_ValueError,
2251
0
                                "need more than 1 value to unpack");
2252
0
            goto Done;
2253
0
        }
2254
2255
1.35k
        unexpected = PyIter_Next(pair_iterator);
2256
1.35k
        if (unexpected != NULL) {
2257
0
            Py_DECREF(unexpected);
2258
0
            PyErr_SetString(PyExc_ValueError,
2259
0
                            "too many values to unpack (expected 2)");
2260
0
            goto Done;
2261
0
        }
2262
1.35k
        else if (PyErr_Occurred())
2263
0
            goto Done;
2264
2265
1.35k
        res = PyObject_SetItem(self, key, value);
2266
2267
1.35k
Done:
2268
1.35k
        Py_DECREF(pair);
2269
1.35k
        Py_XDECREF(pair_iterator);
2270
1.35k
        Py_XDECREF(key);
2271
1.35k
        Py_XDECREF(value);
2272
1.35k
        if (PyErr_Occurred())
2273
0
            break;
2274
1.35k
    }
2275
566
    Py_DECREF(iterator);
2276
2277
566
    if (res < 0 || PyErr_Occurred() != NULL)
2278
0
        return -1;
2279
566
    else
2280
566
        return 0;
2281
566
}
2282
2283
static int
2284
mutablemapping_update_arg(PyObject *self, PyObject *arg)
2285
566
{
2286
566
    int res = 0;
2287
566
    if (PyAnyDict_CheckExact(arg)) {
2288
0
        PyObject *items = PyDict_Items(arg);
2289
0
        if (items == NULL) {
2290
0
            return -1;
2291
0
        }
2292
0
        res = mutablemapping_add_pairs(self, items);
2293
0
        Py_DECREF(items);
2294
0
        return res;
2295
0
    }
2296
566
    PyObject *func;
2297
566
    if (PyObject_GetOptionalAttr(arg, &_Py_ID(keys), &func) < 0) {
2298
0
        return -1;
2299
0
    }
2300
566
    if (func != NULL) {
2301
0
        PyObject *keys = _PyObject_CallNoArgs(func);
2302
0
        Py_DECREF(func);
2303
0
        if (keys == NULL) {
2304
0
            return -1;
2305
0
        }
2306
0
        PyObject *iterator = PyObject_GetIter(keys);
2307
0
        Py_DECREF(keys);
2308
0
        if (iterator == NULL) {
2309
0
            return -1;
2310
0
        }
2311
0
        PyObject *key;
2312
0
        while (res == 0 && (key = PyIter_Next(iterator))) {
2313
0
            PyObject *value = PyObject_GetItem(arg, key);
2314
0
            if (value != NULL) {
2315
0
                res = PyObject_SetItem(self, key, value);
2316
0
                Py_DECREF(value);
2317
0
            }
2318
0
            else {
2319
0
                res = -1;
2320
0
            }
2321
0
            Py_DECREF(key);
2322
0
        }
2323
0
        Py_DECREF(iterator);
2324
0
        if (res != 0 || PyErr_Occurred()) {
2325
0
            return -1;
2326
0
        }
2327
0
        return 0;
2328
0
    }
2329
566
    if (PyObject_GetOptionalAttr(arg, &_Py_ID(items), &func) < 0) {
2330
0
        return -1;
2331
0
    }
2332
566
    if (func != NULL) {
2333
0
        PyObject *items = _PyObject_CallNoArgs(func);
2334
0
        Py_DECREF(func);
2335
0
        if (items == NULL) {
2336
0
            return -1;
2337
0
        }
2338
0
        res = mutablemapping_add_pairs(self, items);
2339
0
        Py_DECREF(items);
2340
0
        return res;
2341
0
    }
2342
566
    res = mutablemapping_add_pairs(self, arg);
2343
566
    return res;
2344
566
}
2345
2346
static PyObject *
2347
mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
2348
871
{
2349
871
    int res;
2350
    /* first handle args, if any */
2351
871
    assert(args == NULL || PyTuple_Check(args));
2352
871
    Py_ssize_t len = (args != NULL) ? PyTuple_GET_SIZE(args) : 0;
2353
871
    if (len > 1) {
2354
0
        const char *msg = "update() takes at most 1 positional argument (%zd given)";
2355
0
        PyErr_Format(PyExc_TypeError, msg, len);
2356
0
        return NULL;
2357
0
    }
2358
2359
871
    if (len) {
2360
566
        PyObject *other = PyTuple_GET_ITEM(args, 0);  /* borrowed reference */
2361
566
        assert(other != NULL);
2362
566
        Py_INCREF(other);
2363
566
        res = mutablemapping_update_arg(self, other);
2364
566
        Py_DECREF(other);
2365
566
        if (res < 0) {
2366
0
            return NULL;
2367
0
        }
2368
566
    }
2369
2370
    /* now handle kwargs */
2371
871
    assert(kwargs == NULL || PyAnyDict_Check(kwargs));
2372
871
    if (kwargs != NULL && PyDict_GET_SIZE(kwargs)) {
2373
0
        PyObject *items = PyDict_Items(kwargs);
2374
0
        if (items == NULL)
2375
0
            return NULL;
2376
0
        res = mutablemapping_add_pairs(self, items);
2377
0
        Py_DECREF(items);
2378
0
        if (res == -1)
2379
0
            return NULL;
2380
0
    }
2381
2382
871
    Py_RETURN_NONE;
2383
871
}