Commit 0ce7a3a3 authored by Serhiy Storchaka's avatar Serhiy Storchaka

Issue #25914: Fixed and simplified OrderedDict.__sizeof__.

parent 5af85640
...@@ -98,7 +98,7 @@ PyAPI_FUNC(PyObject *) _PyDict_NewPresized(Py_ssize_t minused); ...@@ -98,7 +98,7 @@ PyAPI_FUNC(PyObject *) _PyDict_NewPresized(Py_ssize_t minused);
PyAPI_FUNC(void) _PyDict_MaybeUntrack(PyObject *mp); PyAPI_FUNC(void) _PyDict_MaybeUntrack(PyObject *mp);
PyAPI_FUNC(int) _PyDict_HasOnlyStringKeys(PyObject *mp); PyAPI_FUNC(int) _PyDict_HasOnlyStringKeys(PyObject *mp);
Py_ssize_t _PyDict_KeysSize(PyDictKeysObject *keys); Py_ssize_t _PyDict_KeysSize(PyDictKeysObject *keys);
PyObject *_PyDict_SizeOf(PyDictObject *); Py_ssize_t _PyDict_SizeOf(PyDictObject *);
PyObject *_PyDict_Pop(PyDictObject *, PyObject *, PyObject *); PyObject *_PyDict_Pop(PyDictObject *, PyObject *, PyObject *);
PyObject *_PyDict_FromKeys(PyObject *, PyObject *, PyObject *); PyObject *_PyDict_FromKeys(PyObject *, PyObject *, PyObject *);
#define _PyDict_HasSplitTable(d) ((d)->ma_values != NULL) #define _PyDict_HasSplitTable(d) ((d)->ma_values != NULL)
......
...@@ -2,6 +2,7 @@ import contextlib ...@@ -2,6 +2,7 @@ import contextlib
import copy import copy
import pickle import pickle
from random import randrange, shuffle from random import randrange, shuffle
import struct
import sys import sys
import unittest import unittest
from collections.abc import MutableMapping from collections.abc import MutableMapping
...@@ -596,6 +597,37 @@ class CPythonOrderedDictTests(OrderedDictTests, unittest.TestCase): ...@@ -596,6 +597,37 @@ class CPythonOrderedDictTests(OrderedDictTests, unittest.TestCase):
module = c_coll module = c_coll
OrderedDict = c_coll.OrderedDict OrderedDict = c_coll.OrderedDict
check_sizeof = support.check_sizeof
@support.cpython_only
def test_sizeof_exact(self):
OrderedDict = self.OrderedDict
calcsize = struct.calcsize
size = support.calcobjsize
check = self.check_sizeof
basicsize = size('n2P' + '3PnPn2P') + calcsize('2nPn')
entrysize = calcsize('n2P') + calcsize('P')
nodesize = calcsize('Pn2P')
od = OrderedDict()
check(od, basicsize + 8*entrysize)
od.x = 1
check(od, basicsize + 8*entrysize)
od.update([(i, i) for i in range(3)])
check(od, basicsize + 8*entrysize + 3*nodesize)
od.update([(i, i) for i in range(3, 10)])
check(od, basicsize + 16*entrysize + 10*nodesize)
check(od.keys(), size('P'))
check(od.items(), size('P'))
check(od.values(), size('P'))
itersize = size('iP2n2P')
check(iter(od), itersize)
check(iter(od.keys()), itersize)
check(iter(od.items()), itersize)
check(iter(od.values()), itersize)
def test_key_change_during_iteration(self): def test_key_change_during_iteration(self):
OrderedDict = self.OrderedDict OrderedDict = self.OrderedDict
......
...@@ -28,6 +28,8 @@ Core and Builtins ...@@ -28,6 +28,8 @@ Core and Builtins
Library Library
------- -------
- Issue #25914: Fixed and simplified OrderedDict.__sizeof__.
- Issue #25902: Fixed various refcount issues in ElementTree iteration. - Issue #25902: Fixed various refcount issues in ElementTree iteration.
- Issue #25717: Restore the previous behaviour of tolerating most fstat() - Issue #25717: Restore the previous behaviour of tolerating most fstat()
......
...@@ -2554,7 +2554,7 @@ dict_tp_clear(PyObject *op) ...@@ -2554,7 +2554,7 @@ dict_tp_clear(PyObject *op)
static PyObject *dictiter_new(PyDictObject *, PyTypeObject *); static PyObject *dictiter_new(PyDictObject *, PyTypeObject *);
PyObject * Py_ssize_t
_PyDict_SizeOf(PyDictObject *mp) _PyDict_SizeOf(PyDictObject *mp)
{ {
Py_ssize_t size, res; Py_ssize_t size, res;
...@@ -2567,7 +2567,7 @@ _PyDict_SizeOf(PyDictObject *mp) ...@@ -2567,7 +2567,7 @@ _PyDict_SizeOf(PyDictObject *mp)
in the type object. */ in the type object. */
if (mp->ma_keys->dk_refcnt == 1) if (mp->ma_keys->dk_refcnt == 1)
res += sizeof(PyDictKeysObject) + (size-1) * sizeof(PyDictKeyEntry); res += sizeof(PyDictKeysObject) + (size-1) * sizeof(PyDictKeyEntry);
return PyLong_FromSsize_t(res); return res;
} }
Py_ssize_t Py_ssize_t
...@@ -2576,6 +2576,12 @@ _PyDict_KeysSize(PyDictKeysObject *keys) ...@@ -2576,6 +2576,12 @@ _PyDict_KeysSize(PyDictKeysObject *keys)
return sizeof(PyDictKeysObject) + (DK_SIZE(keys)-1) * sizeof(PyDictKeyEntry); return sizeof(PyDictKeysObject) + (DK_SIZE(keys)-1) * sizeof(PyDictKeyEntry);
} }
PyObject *
dict_sizeof(PyDictObject *mp)
{
return PyLong_FromSsize_t(_PyDict_SizeOf(mp));
}
PyDoc_STRVAR(getitem__doc__, "x.__getitem__(y) <==> x[y]"); PyDoc_STRVAR(getitem__doc__, "x.__getitem__(y) <==> x[y]");
PyDoc_STRVAR(sizeof__doc__, PyDoc_STRVAR(sizeof__doc__,
...@@ -2623,7 +2629,7 @@ static PyMethodDef mapp_methods[] = { ...@@ -2623,7 +2629,7 @@ static PyMethodDef mapp_methods[] = {
DICT___CONTAINS___METHODDEF DICT___CONTAINS___METHODDEF
{"__getitem__", (PyCFunction)dict_subscript, METH_O | METH_COEXIST, {"__getitem__", (PyCFunction)dict_subscript, METH_O | METH_COEXIST,
getitem__doc__}, getitem__doc__},
{"__sizeof__", (PyCFunction)_PyDict_SizeOf, METH_NOARGS, {"__sizeof__", (PyCFunction)dict_sizeof, METH_NOARGS,
sizeof__doc__}, sizeof__doc__},
{"get", (PyCFunction)dict_get, METH_VARARGS, {"get", (PyCFunction)dict_get, METH_VARARGS,
get__doc__}, get__doc__},
......
...@@ -940,27 +940,7 @@ PyDoc_STRVAR(odict_sizeof__doc__, ""); ...@@ -940,27 +940,7 @@ PyDoc_STRVAR(odict_sizeof__doc__, "");
static PyObject * static PyObject *
odict_sizeof(PyODictObject *od) odict_sizeof(PyODictObject *od)
{ {
PyObject *pylong; Py_ssize_t res = _PyDict_SizeOf((PyDictObject *)od);
Py_ssize_t res, temp;
pylong = _PyDict_SizeOf((PyDictObject *)od);
if (pylong == NULL)
return NULL;
res = PyLong_AsSsize_t(pylong);
Py_DECREF(pylong);
if (res == -1 && PyErr_Occurred())
return NULL;
/* instance dict */
pylong = _PyDict_SizeOf((PyDictObject *)od->od_inst_dict);
if (pylong == NULL)
return NULL;
temp = PyLong_AsSsize_t(pylong);
Py_DECREF(pylong);
if (temp == -1 && PyErr_Occurred())
return NULL;
res += temp;
res += sizeof(_ODictNode *) * _odict_FAST_SIZE(od); /* od_fast_nodes */ res += sizeof(_ODictNode *) * _odict_FAST_SIZE(od); /* od_fast_nodes */
if (!_odict_EMPTY(od)) { if (!_odict_EMPTY(od)) {
res += sizeof(_ODictNode) * PyODict_SIZE(od); /* linked-list */ res += sizeof(_ODictNode) * PyODict_SIZE(od); /* linked-list */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment