8000 bpo-33712: OrderedDict only creates od_fast_nodes cache if needed (GH… · python/cpython@861d34e · GitHub
[go: up one dir, main page]

Skip to content

Commit 861d34e

Browse files
bpo-33712: OrderedDict only creates od_fast_nodes cache if needed (GH-7349). (GH-10000)
(cherry picked from commit 6f17e51)
1 parent dcd56f6 commit 861d34e

File tree

2 files changed

+21
-53
lines changed

2 files changed

+21
-53
lines changed

Lib/test/test_ordered_dict.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -697,9 +697,9 @@ def test_sizeof_exact(self):
697697
nodesize = calcsize('Pn2P')
698698

699699
od = OrderedDict()
700-
check(od, basicsize + 8*p + 8 + 5*entrysize) # 8byte indices + 8*2//3 * entry table
700+
check(od, basicsize + 8 + 5*entrysize) # 8byte indices + 8*2//3 * entry table
701701
od.x = 1
702-
check(od, basicsize + 8*p + 8 + 5*entrysize)
702+
check(od, basicsize + 8 + 5*entrysize)
703703
od.update([(i, i) for i in range(3)])
704704
check(od, basicsize + 8*p + 8 + 5*entrysize + 3*nodesize)
705705
od.update([(i, i) for i in range(3, 10)])

Objects/odictobject.c

Lines changed: 19 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,6 @@ For removing nodes:
101101
* _odict_find_node(od, key)
102102
* _odict_keys_equal(od1, od2)
103103
104-
Used, but specific to the linked-list implementation:
105-
106-
* _odict_free_fast_nodes(od)
107-
108104
And here's a look at how the linked-list relates to the OrderedDict API:
109105
110106
============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===
@@ -378,7 +374,6 @@ tp_iter odict_iter
378374
tp_dictoffset (offset)
379375
tp_init odict_init
380376
tp_alloc (repeated)
381-
tp_new odict_new
382377
================= ================
383378
384379
================= ================
@@ -530,15 +525,6 @@ struct _odictnode {
530525
#define _odict_FOREACH(od, node) \
531526
for (node = _odict_FIRST(od); node != NULL; node = _odictnode_NEXT(node))
532527

533-
#define _odict_FAST_SIZE(od) ((PyDictObject *)od)->ma_keys->dk_size
534-
535-
static void
536-
_odict_free_fast_nodes(PyODictObject *od) {
537-
if (od->od_fast_nodes) {
538-
PyMem_FREE(od->od_fast_nodes);
539-
}
540-
}
541-
542528
/* Return the index into the hash table, regardless of a valid node. */
543529
static Py_ssize_t
544530
_odict_get_index_raw(PyODictObject *od, PyObject *key, Py_hash_t hash)
@@ -559,7 +545,8 @@ _odict_get_index_raw(PyODictObject *od, PyObject *key, Py_hash_t hash)
559545

560546
/* Replace od->od_fast_nodes with a new table matching the size of dict's. */
561547
static int
562-
_odict_resize(PyODictObject *od) {
548+
_odict_resize(PyODictObject *od)
549+
{
563550
Py_ssize_t size, i;
564551
_ODictNode **fast_nodes, *node;
565552

@@ -585,7 +572,7 @@ _odict_resize(PyODictObject *od) {
585572
}
586573

587574
/* Replace the old fast nodes table. */
588-
_odict_free_fast_nodes(od);
575+
PyMem_FREE(od->od_fast_nodes);
589576
od->od_fast_nodes = fast_nodes;
590577
od->od_fast_nodes_size = size;
591578
od->od_resize_sentinel = ((PyDictObject *)od)->ma_keys;
@@ -623,6 +610,7 @@ _odict_find_node_hash(PyODictObject *od, PyObject *key, Py_hash_t hash)
623610
index = _odict_get_index(od, key, hash);
624611
if (index < 0)
625612
return NULL;
613+
assert(od->od_fast_nodes != NULL);
626614
return od->od_fast_nodes[index];
627615
}
628616

@@ -640,6 +628,7 @@ _odict_find_node(PyODictObject *od, PyObject *key)
640628
index = _odict_get_index(od, key, hash);
641629
if (index < 0)
642630
return NULL;
631+
assert(od->od_fast_nodes != NULL);
643632
return od->od_fast_nodes[index];
644633
}
645634

@@ -684,7 +673,8 @@ _odict_add_new_node(PyODictObject *od, PyObject *key, Py_hash_t hash)
684673
Py_DECREF(key);
685674
return -1;
686675
}
687-
else if (od->od_fast_nodes[i] != NULL) {
676+
assert(od->od_fast_nodes != NULL);
677+
if (od->od_fast_nodes[i] != NULL) {
688678
/* We already have a node for the key so there's no need to add one. */
689679
Py_DECREF(key);
690680
return 0;
@@ -763,6 +753,7 @@ _odict_clear_node(PyODictObject *od, _ODictNode *node, PyObject *key,
763753
if (i < 0)
764754
return PyErr_Occurred() ? -1 : 0;
765755

756+
assert(od->od_fast_nodes != NULL);
766757
if (node == NULL)
767758
node = od->od_fast_nodes[i];
768759
assert(node == od->od_fast_nodes[i]);
@@ -783,8 +774,10 @@ _odict_clear_nodes(PyODictObject *od)
783774
{
784775
_ODictNode *node, *next;
785776

786-
_odict_free_fast_nodes(od);
777+
PyMem_FREE(od->od_fast_nodes);
787778
od->od_fast_nodes = NULL;
779+
od->od_fast_nodes_size = 0;
780+
od->od_resize_sentinel = NULL;
788781

789782
no F438 de = _odict_FIRST(od);
790783
_odict_FIRST(od) = NULL;
@@ -887,7 +880,7 @@ static PyObject *
887880
odict_sizeof(PyODictObject *od)
888881
{
889882
Py_ssize_t res = _PyDict_SizeOf((PyDictObject *)od);
890-
res += sizeof(_ODictNode *) * _odict_FAST_SIZE(od); /* od_fast_nodes */
883+
res += sizeof(_ODictNode *) * od->od_fast_nodes_size; /* od_fast_nodes */
891884
if (!_odict_EMPTY(od)) {
892885
res += sizeof(_ODictNode) * PyODict_SIZE(od); /* linked-list */
893886
}
@@ -1175,12 +1168,10 @@ PyDoc_STRVAR(odict_clear__doc__,
11751168
"od.clear() -> None. Remove all items from od.");
11761169

11771170
static PyObject *
1178-
odict_clear(register PyODictObject *od)
1171+
odict_clear(register PyODictObject *od, PyObject *Py_UNUSED(ignored))
11791172
{
11801173
PyDict_Clear((PyObject *)od);
11811174
_odict_clear_nodes(od);
1182-
if (_odict_resize(od) < 0)
1183-
return NULL;
11841175
Py_RETURN_NONE;
11851176
}
11861177

@@ -1484,13 +1475,10 @@ odict_traverse(PyODictObject *od, visitproc visit, void *arg)
14841475
static int
14851476
odict_tp_clear(PyODictObject *od)
14861477
{
1487-
PyObject *res;
14881478
Py_CLEAR(od->od_inst_dict);
14891479
Py_CLEAR(od->od_weakreflist);
1490-
res = odict_clear(od);
1491-
if (res == NULL)
1492-
return -1;
1493-
Py_DECREF(res);
1480+
PyDict_Clear((PyObject *)od);
1481+
_odict_clear_nodes(od);
14941482
return 0;
14951483
}
14961484

@@ -1565,27 +1553,6 @@ odict_init(PyObject *self, PyObject *args, PyObject *kwds)
15651553
}
15661554
}
15671555

1568-
/* tp_new */
1569-
1570-
static PyObject *
1571-
odict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1572-
{
1573-
PyODictObject *od;
1574-
1575-
od = (PyODictObject *)PyDict_Type.tp_new(type, args, kwds);
1576-
if (od == NULL)
1577-
return NULL;
1578-
1579-
/* type constructor fills the memory with zeros (see
1580-
PyType_GenericAlloc()), there is no need to set them to zero again */
1581-
if (_odict_resize(od) < 0) {
1582-
Py_DECREF(od);
1583-
return NULL;
1584-
}
1585-
1586-
return (PyObject*)od;
1587-
}
1588-
15891556
/* PyODict_Type */
15901557

15911558
PyTypeObject PyODict_Type = {
@@ -1626,7 +1593,7 @@ PyTypeObject PyODict_Type = {
16261593
offsetof(PyODictObject, od_inst_dict), /* tp_dictoffset */
16271594
(initproc)odict_init, /* tp_init */
16281595
PyType_GenericAlloc, /* tp_alloc */
1629-
(newfunc)odict_new, /* tp_new */
1596+
0, /* tp_new */
16301597
0, /* tp_free */
16311598
};
16321599

@@ -1636,8 +1603,9 @@ PyTypeObject PyODict_Type = {
16361603
*/
16371604

16381605
PyObject *
1639-
PyODict_New(void) {
1640-
return odict_new(&PyODict_Type, NULL, NULL);
1606+
PyODict_New(void)
1607+
{
1608+
return PyDict_Type.tp_new(&PyODict_Type, NULL, NULL);
16411609
}
16421610

16431611
static int

0 commit comments

Comments
 (0)
0