mirror of
https://github.com/python/cpython.git
synced 2025-12-15 21:44:50 +00:00
Implement compact dict
Issue #27350: `dict` implementation is changed like PyPy. It is more compact and preserves insertion order. _PyDict_Dummy() function has been removed. Disable test_gdb: python-gdb.py is not updated yet to the new structure of compact dictionaries (issue #28023). Patch written by INADA Naoki.
This commit is contained in:
parent
d8b7770a0e
commit
742da040db
12 changed files with 793 additions and 569 deletions
|
|
@ -8,15 +8,25 @@ typedef struct {
|
|||
PyObject *me_value; /* This field is only meaningful for combined tables */
|
||||
} PyDictKeyEntry;
|
||||
|
||||
typedef PyDictKeyEntry *(*dict_lookup_func)
|
||||
(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr);
|
||||
/* dict_lookup_func() returns index of entry which can be used like DK_ENTRIES(dk)[index].
|
||||
* -1 when no entry found, -3 when compare raises error.
|
||||
*/
|
||||
typedef Py_ssize_t (*dict_lookup_func)
|
||||
(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr,
|
||||
Py_ssize_t *hashpos);
|
||||
|
||||
#define DKIX_EMPTY (-1)
|
||||
#define DKIX_DUMMY (-2) /* Used internally */
|
||||
#define DKIX_ERROR (-3)
|
||||
|
||||
/* See dictobject.c for actual layout of DictKeysObject */
|
||||
struct _dictkeysobject {
|
||||
Py_ssize_t dk_refcnt;
|
||||
Py_ssize_t dk_size;
|
||||
dict_lookup_func dk_lookup;
|
||||
Py_ssize_t dk_usable;
|
||||
PyDictKeyEntry dk_entries[1];
|
||||
Py_ssize_t dk_nentries; /* How many entries are used. */
|
||||
char dk_indices[8]; /* dynamically sized. 8 is minimum. */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
1259
Objects/dictobject.c
1259
Objects/dictobject.c
File diff suppressed because it is too large
Load diff
|
|
@ -22,12 +22,6 @@ _Py_GetRefTotal(void)
|
|||
{
|
||||
PyObject *o;
|
||||
Py_ssize_t total = _Py_RefTotal;
|
||||
/* ignore the references to the dummy object of the dicts and sets
|
||||
because they are not reliable and not useful (now that the
|
||||
hash table code is well-tested) */
|
||||
o = _PyDict_Dummy();
|
||||
if (o != NULL)
|
||||
total -= o->ob_refcnt;
|
||||
o = _PySet_Dummy;
|
||||
if (o != NULL)
|
||||
total -= o->ob_refcnt;
|
||||
|
|
|
|||
|
|
@ -536,14 +536,17 @@ static Py_ssize_t
|
|||
_odict_get_index_raw(PyODictObject *od, PyObject *key, Py_hash_t hash)
|
||||
{
|
||||
PyObject **value_addr = NULL;
|
||||
PyDictKeyEntry *ep;
|
||||
PyDictKeysObject *keys = ((PyDictObject *)od)->ma_keys;
|
||||
Py_ssize_t ix;
|
||||
|
||||
ep = (keys->dk_lookup)((PyDictObject *)od, key, hash, &value_addr);
|
||||
if (ep == NULL)
|
||||
ix = (keys->dk_lookup)((PyDictObject *)od, key, hash, &value_addr, NULL);
|
||||
if (ix == DKIX_EMPTY) {
|
||||
return keys->dk_nentries; /* index of new entry */
|
||||
}
|
||||
if (ix < 0)
|
||||
return -1;
|
||||
/* We use pointer arithmetic to get the entry's index into the table. */
|
||||
return ep - keys->dk_entries;
|
||||
return ix;
|
||||
}
|
||||
|
||||
/* Replace od->od_fast_nodes with a new table matching the size of dict's. */
|
||||
|
|
@ -565,7 +568,7 @@ _odict_resize(PyODictObject *od) {
|
|||
/* Copy the current nodes into the table. */
|
||||
_odict_FOREACH(od, node) {
|
||||
i = _odict_get_index_raw(od, _odictnode_KEY(node),
|
||||
_odictnode_HASH(node));
|
||||
_odictnode_HASH(node));
|
||||
if (i < 0) {
|
||||
PyMem_FREE(fast_nodes);
|
||||
return -1;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue