bpo-33712: OrderedDict only creates od_fast_nodes cache if needed (GH… · python/cpython@861d34e

@@ -101,10 +101,6 @@ For removing nodes:

101101

* _odict_find_node(od, key)

102102

* _odict_keys_equal(od1, od2)

103103104-

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:

109105110106

============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===

@@ -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

================= ================

383378384379

================= ================

@@ -530,15 +525,6 @@ struct _odictnode {

530525

#define _odict_FOREACH(od, node) \

531526

for (node = _odict_FIRST(od); node != NULL; node = _odictnode_NEXT(node))

532527533-

#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)

559545560546

/* 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

}

586573587574

/* 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;

765755756+

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;

785776786-

_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;

788781789782

node = _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.");

1176116911771170

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

}

156715551568-

/* 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 */

1590155715911558

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

*/

1637160416381605

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

}

1642161016431611

static int