Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-35230: dict: Remove some macros #10513

Merged
merged 3 commits into from
Nov 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Include/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,6 @@ PyAPI_FUNC(void) _Py_NegativeRefcount(const char *filename, int lineno,
PyAPI_FUNC(Py_ssize_t) _Py_GetRefTotal(void);
#define _Py_INC_REFTOTAL _Py_RefTotal++
#define _Py_DEC_REFTOTAL _Py_RefTotal--
#define _Py_REF_DEBUG_COMMA ,

/* Py_REF_DEBUG also controls the display of refcounts and memory block
* allocations at the interactive prompt and at interpreter shutdown
Expand All @@ -743,7 +742,6 @@ PyAPI_FUNC(void) _PyDebug_PrintTotalRefs(void);
#else
#define _Py_INC_REFTOTAL
#define _Py_DEC_REFTOTAL
#define _Py_REF_DEBUG_COMMA
#endif /* Py_REF_DEBUG */

#ifdef COUNT_ALLOCS
Expand Down
101 changes: 59 additions & 42 deletions Objects/dictobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,17 +302,31 @@ PyDict_Fini(void)
#define DK_ENTRIES(dk) \
((PyDictKeyEntry*)(&((int8_t*)((dk)->dk_indices))[DK_SIZE(dk) * DK_IXSIZE(dk)]))

#define DK_DEBUG_INCREF _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA
#define DK_DEBUG_DECREF _Py_DEC_REFTOTAL _Py_REF_DEBUG_COMMA

#define DK_INCREF(dk) (DK_DEBUG_INCREF ++(dk)->dk_refcnt)
#define DK_DECREF(dk) if (DK_DEBUG_DECREF (--(dk)->dk_refcnt) == 0) free_keys_object(dk)
#define DK_MASK(dk) (((dk)->dk_size)-1)
#define IS_POWER_OF_2(x) (((x) & (x-1)) == 0)

static void free_keys_object(PyDictKeysObject *keys);

static inline void
dictkeys_incref(PyDictKeysObject *dk)
{
_Py_INC_REFTOTAL;
dk->dk_refcnt++;
}

static inline void
dictkeys_decref(PyDictKeysObject *dk)
{
assert(dk->dk_refcnt > 0);
_Py_DEC_REFTOTAL;
if (--dk->dk_refcnt == 0) {
free_keys_object(dk);
}
}

/* lookup indices. returns DKIX_EMPTY, DKIX_DUMMY, or ix >=0 */
static inline Py_ssize_t
dk_get_index(PyDictKeysObject *keys, Py_ssize_t i)
dictkeys_get_index(PyDictKeysObject *keys, Py_ssize_t i)
{
Py_ssize_t s = DK_SIZE(keys);
Py_ssize_t ix;
Expand Down Expand Up @@ -341,7 +355,7 @@ dk_get_index(PyDictKeysObject *keys, Py_ssize_t i)

/* write to indices. */
static inline void
dk_set_index(PyDictKeysObject *keys, Py_ssize_t i, Py_ssize_t ix)
dictkeys_set_index(PyDictKeysObject *keys, Py_ssize_t i, Py_ssize_t ix)
{
Py_ssize_t s = DK_SIZE(keys);

Expand Down Expand Up @@ -464,7 +478,7 @@ _PyDict_CheckConsistency(PyDictObject *mp)

#ifdef DEBUG_PYDICT
for (i=0; i < keys->dk_size; i++) {
Py_ssize_t ix = dk_get_index(keys, i);
Py_ssize_t ix = dictkeys_get_index(keys, i);
ASSERT(DKIX_DUMMY <= ix && ix <= usable);
}

Expand Down Expand Up @@ -543,7 +557,8 @@ static PyDictKeysObject *new_keys_object(Py_ssize_t size)
return NULL;
}
}
DK_DEBUG_INCREF dk->dk_refcnt = 1;
_Py_INC_REFTOTAL;
dk->dk_refcnt = 1;
dk->dk_size = size;
dk->dk_usable = usable;
dk->dk_lookup = lookdict_unicode_nodummy;
Expand Down Expand Up @@ -587,7 +602,7 @@ new_dict(PyDictKeysObject *keys, PyObject **values)
else {
mp = PyObject_GC_New(PyDictObject, &PyDict_Type);
if (mp == NULL) {
DK_DECREF(keys);
dictkeys_decref(keys);
free_values(values);
return NULL;
}
Expand All @@ -610,7 +625,7 @@ new_dict_with_shared_keys(PyDictKeysObject *keys)
size = USABLE_FRACTION(DK_SIZE(keys));
values = new_values(size);
if (values == NULL) {
DK_DECREF(keys);
dictkeys_decref(keys);
return PyErr_NoMemory();
}
for (i = 0; i < size; i++) {
Expand Down Expand Up @@ -665,7 +680,7 @@ clone_combined_dict(PyDictObject *orig)

/* Since we copied the keys table we now have an extra reference
in the system. Manually call _Py_INC_REFTOTAL to signal that
we have it now; calling DK_INCREF would be an error as
we have it now; calling dictkeys_incref would be an error as
keys->dk_refcnt is already set to 1 (after memcpy). */
_Py_INC_REFTOTAL;

Expand All @@ -690,7 +705,7 @@ lookdict_index(PyDictKeysObject *k, Py_hash_t hash, Py_ssize_t index)
size_t i = (size_t)hash & mask;

for (;;) {
Py_ssize_t ix = dk_get_index(k, i);
Py_ssize_t ix = dictkeys_get_index(k, i);
if (ix == index) {
return i;
}
Expand Down Expand Up @@ -743,7 +758,7 @@ lookdict(PyDictObject *mp, PyObject *key,
i = (size_t)hash & mask;

for (;;) {
Py_ssize_t ix = dk_get_index(dk, i);
Py_ssize_t ix = dictkeys_get_index(dk, i);
if (ix == DKIX_EMPTY) {
*value_addr = NULL;
return ix;
Expand Down Expand Up @@ -803,7 +818,7 @@ lookdict_unicode(PyDictObject *mp, PyObject *key,
size_t i = (size_t)hash & mask;

for (;;) {
Py_ssize_t ix = dk_get_index(mp->ma_keys, i);
Py_ssize_t ix = dictkeys_get_index(mp->ma_keys, i);
if (ix == DKIX_EMPTY) {
*value_addr = NULL;
return DKIX_EMPTY;
Expand Down Expand Up @@ -846,7 +861,7 @@ lookdict_unicode_nodummy(PyDictObject *mp, PyObject *key,
size_t i = (size_t)hash & mask;

for (;;) {
Py_ssize_t ix = dk_get_index(mp->ma_keys, i);
Py_ssize_t ix = dictkeys_get_index(mp->ma_keys, i);
assert (ix != DKIX_DUMMY);
if (ix == DKIX_EMPTY) {
*value_addr = NULL;
Expand Down Expand Up @@ -891,7 +906,7 @@ lookdict_split(PyDictObject *mp, PyObject *key,
size_t i = (size_t)hash & mask;

for (;;) {
Py_ssize_t ix = dk_get_index(mp->ma_keys, i);
Py_ssize_t ix = dictkeys_get_index(mp->ma_keys, i);
assert (ix != DKIX_DUMMY);
if (ix == DKIX_EMPTY) {
*value_addr = NULL;
Expand Down Expand Up @@ -983,11 +998,11 @@ find_empty_slot(PyDictKeysObject *keys, Py_hash_t hash)

const size_t mask = DK_MASK(keys);
size_t i = hash & mask;
Py_ssize_t ix = dk_get_index(keys, i);
Py_ssize_t ix = dictkeys_get_index(keys, i);
for (size_t perturb = hash; ix >= 0;) {
perturb >>= PERTURB_SHIFT;
i = (i*5 + perturb + 1) & mask;
ix = dk_get_index(keys, i);
ix = dictkeys_get_index(keys, i);
}
return i;
}
Expand Down Expand Up @@ -1044,7 +1059,7 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
}
Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash);
ep = &DK_ENTRIES(mp->ma_keys)[mp->ma_keys->dk_nentries];
dk_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
dictkeys_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
ep->me_key = key;
ep->me_hash = hash;
if (mp->ma_values) {
Expand Down Expand Up @@ -1098,11 +1113,11 @@ build_indices(PyDictKeysObject *keys, PyDictKeyEntry *ep, Py_ssize_t n)
for (Py_ssize_t ix = 0; ix != n; ix++, ep++) {
Py_hash_t hash = ep->me_hash;
size_t i = hash & mask;
for (size_t perturb = hash; dk_get_index(keys, i) != DKIX_EMPTY;) {
for (size_t perturb = hash; dictkeys_get_index(keys, i) != DKIX_EMPTY;) {
perturb >>= PERTURB_SHIFT;
i = mask & (i*5 + perturb + 1);
}
dk_set_index(keys, i, ix);
dictkeys_set_index(keys, i, ix);
}
}

Expand Down Expand Up @@ -1171,7 +1186,7 @@ dictresize(PyDictObject *mp, Py_ssize_t minsize)
newentries[i].me_value = oldvalues[i];
}

DK_DECREF(oldkeys);
dictkeys_decref(oldkeys);
mp->ma_values = NULL;
if (oldvalues != empty_values) {
free_values(oldvalues);
Expand All @@ -1194,10 +1209,12 @@ dictresize(PyDictObject *mp, Py_ssize_t minsize)
assert(oldkeys->dk_refcnt == 1);
if (oldkeys->dk_size == PyDict_MINSIZE &&
numfreekeys < PyDict_MAXFREELIST) {
DK_DEBUG_DECREF keys_free_list[numfreekeys++] = oldkeys;
_Py_DEC_REFTOTAL;
keys_free_list[numfreekeys++] = oldkeys;
}
else {
DK_DEBUG_DECREF PyObject_FREE(oldkeys);
_Py_DEC_REFTOTAL;
PyObject_FREE(oldkeys);
}
}

Expand Down Expand Up @@ -1247,7 +1264,7 @@ make_keys_shared(PyObject *op)
mp->ma_keys->dk_lookup = lookdict_split;
mp->ma_values = values;
}
DK_INCREF(mp->ma_keys);
dictkeys_incref(mp->ma_keys);
return mp->ma_keys;
}

Expand Down Expand Up @@ -1499,7 +1516,7 @@ delitem_common(PyDictObject *mp, Py_hash_t hash, Py_ssize_t ix,
mp->ma_used--;
mp->ma_version_tag = DICT_NEXT_VERSION();
ep = &DK_ENTRIES(mp->ma_keys)[ix];
dk_set_index(mp->ma_keys, hashpos, DKIX_DUMMY);
dictkeys_set_index(mp->ma_keys, hashpos, DKIX_DUMMY);
ENSURE_ALLOWS_DELETIONS(mp);
old_key = ep->me_key;
ep->me_key = NULL;
Expand Down Expand Up @@ -1630,7 +1647,7 @@ PyDict_Clear(PyObject *op)
if (oldvalues == empty_values)
return;
/* Empty the dict... */
DK_INCREF(Py_EMPTY_KEYS);
dictkeys_incref(Py_EMPTY_KEYS);
mp->ma_keys = Py_EMPTY_KEYS;
mp->ma_values = empty_values;
mp->ma_used = 0;
Expand All @@ -1641,11 +1658,11 @@ PyDict_Clear(PyObject *op)
for (i = 0; i < n; i++)
Py_CLEAR(oldvalues[i]);
free_values(oldvalues);
DK_DECREF(oldkeys);
dictkeys_decref(oldkeys);
}
else {
assert(oldkeys->dk_refcnt == 1);
DK_DECREF(oldkeys);
dictkeys_decref(oldkeys);
}
assert(_PyDict_CheckConsistency(mp));
}
Expand Down Expand Up @@ -1769,7 +1786,7 @@ _PyDict_Pop_KnownHash(PyObject *dict, PyObject *key, Py_hash_t hash, PyObject *d
assert(old_value != NULL);
mp->ma_used--;
mp->ma_version_tag = DICT_NEXT_VERSION();
dk_set_index(mp->ma_keys, hashpos, DKIX_DUMMY);
dictkeys_set_index(mp->ma_keys, hashpos, DKIX_DUMMY);
ep = &DK_ENTRIES(mp->ma_keys)[ix];
ENSURE_ALLOWS_DELETIONS(mp);
old_key = ep->me_key;
Expand Down Expand Up @@ -1910,11 +1927,11 @@ dict_dealloc(PyDictObject *mp)
}
free_values(values);
}
DK_DECREF(keys);
dictkeys_decref(keys);
}
else if (keys != NULL) {
assert(keys->dk_refcnt == 1);
DK_DECREF(keys);
dictkeys_decref(keys);
}
if (numfree < PyDict_MAXFREELIST && Py_TYPE(mp) == &PyDict_Type)
free_list[numfree++] = mp;
Expand Down Expand Up @@ -2563,7 +2580,7 @@ PyDict_Copy(PyObject *o)
split_copy->ma_keys = mp->ma_keys;
split_copy->ma_used = mp->ma_used;
split_copy->ma_version_tag = DICT_NEXT_VERSION();
DK_INCREF(mp->ma_keys);
dictkeys_incref(mp->ma_keys);
for (i = 0, n = size; i < n; i++) {
PyObject *value = mp->ma_values[i];
Py_XINCREF(value);
Expand Down Expand Up @@ -2828,7 +2845,7 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash);
ep0 = DK_ENTRIES(mp->ma_keys);
ep = &ep0[mp->ma_keys->dk_nentries];
dk_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
dictkeys_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
Py_INCREF(key);
Py_INCREF(value);
MAINTAIN_TRACKING(mp, key, value);
Expand Down Expand Up @@ -2949,8 +2966,8 @@ dict_popitem(PyDictObject *mp, PyObject *Py_UNUSED(ignored))
ep = &ep0[i];
j = lookdict_index(mp->ma_keys, ep->me_hash, i);
assert(j >= 0);
assert(dk_get_index(mp->ma_keys, j) == i);
dk_set_index(mp->ma_keys, j, DKIX_DUMMY);
assert(dictkeys_get_index(mp->ma_keys, j) == i);
dictkeys_set_index(mp->ma_keys, j, DKIX_DUMMY);

PyTuple_SET_ITEM(res, 0, ep->me_key);
PyTuple_SET_ITEM(res, 1, ep->me_value);
Expand Down Expand Up @@ -4460,7 +4477,7 @@ PyObject_GenericGetDict(PyObject *obj, void *context)
if (dict == NULL) {
PyTypeObject *tp = Py_TYPE(obj);
if ((tp->tp_flags & Py_TPFLAGS_HEAPTYPE) && CACHED_KEYS(tp)) {
DK_INCREF(CACHED_KEYS(tp));
dictkeys_incref(CACHED_KEYS(tp));
*dictptr = dict = new_dict_with_shared_keys(CACHED_KEYS(tp));
}
else {
Expand All @@ -4484,7 +4501,7 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
assert(dictptr != NULL);
dict = *dictptr;
if (dict == NULL) {
DK_INCREF(cached);
dictkeys_incref(cached);
dict = new_dict_with_shared_keys(cached);
if (dict == NULL)
return -1;
Expand All @@ -4496,7 +4513,7 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
// always converts dict to combined form.
if ((cached = CACHED_KEYS(tp)) != NULL) {
CACHED_KEYS(tp) = NULL;
DK_DECREF(cached);
dictkeys_decref(cached);
}
}
else {
Expand Down Expand Up @@ -4525,7 +4542,7 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
else {
CACHED_KEYS(tp) = NULL;
}
DK_DECREF(cached);
dictkeys_decref(cached);
if (CACHED_KEYS(tp) == NULL && PyErr_Occurred())
return -1;
}
Expand All @@ -4550,5 +4567,5 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
void
_PyDictKeys_DecRef(PyDictKeysObject *keys)
{
DK_DECREF(keys);
dictkeys_decref(keys);
}