#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;
/* 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);
#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);
}
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;
else {
mp = PyObject_GC_New(PyDictObject, &PyDict_Type);
if (mp == NULL) {
- DK_DECREF(keys);
+ dictkeys_decref(keys);
free_values(values);
return NULL;
}
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++) {
/* 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;
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;
}
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;
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;
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;
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;
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;
}
}
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) {
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);
}
}
newentries[i].me_value = oldvalues[i];
}
- DK_DECREF(oldkeys);
+ dictkeys_decref(oldkeys);
mp->ma_values = NULL;
if (oldvalues != empty_values) {
free_values(oldvalues);
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);
}
}
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;
}
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;
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;
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));
}
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;
}
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;
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);
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);
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);
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 {
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;
// always converts dict to combined form.
if ((cached = CACHED_KEYS(tp)) != NULL) {
CACHED_KEYS(tp) = NULL;
- DK_DECREF(cached);
+ dictkeys_decref(cached);
}
}
else {
else {
CACHED_KEYS(tp) = NULL;
}
- DK_DECREF(cached);
+ dictkeys_decref(cached);
if (CACHED_KEYS(tp) == NULL && PyErr_Occurred())
return -1;
}
void
_PyDictKeys_DecRef(PyDictKeysObject *keys)
{
- DK_DECREF(keys);
+ dictkeys_decref(keys);
}