Skip to content

Commit

Permalink
gh-112075: Use PyMem_* for allocating dict keys objects (#114543)
Browse files Browse the repository at this point in the history
Use PyMem_* for keys allocation
  • Loading branch information
DinoV authored Jan 29, 2024
1 parent 2c089b0 commit 3d71665
Showing 1 changed file with 23 additions and 43 deletions.
66 changes: 23 additions & 43 deletions Objects/dictobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ _PyDict_ClearFreeList(PyInterpreterState *interp)
PyObject_GC_Del(op);
}
while (state->keys_numfree) {
PyObject_Free(state->keys_free_list[--state->keys_numfree]);
PyMem_Free(state->keys_free_list[--state->keys_numfree]);
}
#endif
}
Expand Down Expand Up @@ -332,6 +332,22 @@ dictkeys_decref(PyInterpreterState *interp, PyDictKeysObject *dk)
_Py_DecRefTotal(_PyInterpreterState_GET());
#endif
if (--dk->dk_refcnt == 0) {
if (DK_IS_UNICODE(dk)) {
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dk);
Py_ssize_t i, n;
for (i = 0, n = dk->dk_nentries; i < n; i++) {
Py_XDECREF(entries[i].me_key);
Py_XDECREF(entries[i].me_value);
}
}
else {
PyDictKeyEntry *entries = DK_ENTRIES(dk);
Py_ssize_t i, n;
for (i = 0, n = dk->dk_nentries; i < n; i++) {
Py_XDECREF(entries[i].me_key);
Py_XDECREF(entries[i].me_value);
}
}
free_keys_object(interp, dk);
}
}
Expand Down Expand Up @@ -640,9 +656,9 @@ new_keys_object(PyInterpreterState *interp, uint8_t log2_size, bool unicode)
else
#endif
{
dk = PyObject_Malloc(sizeof(PyDictKeysObject)
+ ((size_t)1 << log2_bytes)
+ entry_size * usable);
dk = PyMem_Malloc(sizeof(PyDictKeysObject)
+ ((size_t)1 << log2_bytes)
+ entry_size * usable);
if (dk == NULL) {
PyErr_NoMemory();
return NULL;
Expand All @@ -666,23 +682,6 @@ new_keys_object(PyInterpreterState *interp, uint8_t log2_size, bool unicode)
static void
free_keys_object(PyInterpreterState *interp, PyDictKeysObject *keys)
{
assert(keys != Py_EMPTY_KEYS);
if (DK_IS_UNICODE(keys)) {
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys);
Py_ssize_t i, n;
for (i = 0, n = keys->dk_nentries; i < n; i++) {
Py_XDECREF(entries[i].me_key);
Py_XDECREF(entries[i].me_value);
}
}
else {
PyDictKeyEntry *entries = DK_ENTRIES(keys);
Py_ssize_t i, n;
for (i = 0, n = keys->dk_nentries; i < n; i++) {
Py_XDECREF(entries[i].me_key);
Py_XDECREF(entries[i].me_value);
}
}
#if PyDict_MAXFREELIST > 0
struct _Py_dict_state *state = get_dict_state(interp);
#ifdef Py_DEBUG
Expand All @@ -697,7 +696,7 @@ free_keys_object(PyInterpreterState *interp, PyDictKeysObject *keys)
return;
}
#endif
PyObject_Free(keys);
PyMem_Free(keys);
}

static inline PyDictValues*
Expand Down Expand Up @@ -798,7 +797,7 @@ clone_combined_dict_keys(PyDictObject *orig)
assert(orig->ma_keys->dk_refcnt == 1);

size_t keys_size = _PyDict_KeysSize(orig->ma_keys);
PyDictKeysObject *keys = PyObject_Malloc(keys_size);
PyDictKeysObject *keys = PyMem_Malloc(keys_size);
if (keys == NULL) {
PyErr_NoMemory();
return NULL;
Expand Down Expand Up @@ -1544,32 +1543,13 @@ dictresize(PyInterpreterState *interp, PyDictObject *mp,
}
}

// We can not use free_keys_object here because key's reference
// are moved already.
if (oldkeys != Py_EMPTY_KEYS) {
#ifdef Py_REF_DEBUG
_Py_DecRefTotal(_PyInterpreterState_GET());
#endif
assert(oldkeys->dk_kind != DICT_KEYS_SPLIT);
assert(oldkeys->dk_refcnt == 1);
#if PyDict_MAXFREELIST > 0
struct _Py_dict_state *state = get_dict_state(interp);
#ifdef Py_DEBUG
// dictresize() must not be called after _PyDict_Fini()
assert(state->keys_numfree != -1);
#endif
if (DK_LOG_SIZE(oldkeys) == PyDict_LOG_MINSIZE &&
DK_IS_UNICODE(oldkeys) &&
state->keys_numfree < PyDict_MAXFREELIST)
{
state->keys_free_list[state->keys_numfree++] = oldkeys;
OBJECT_STAT_INC(to_freelist);
}
else
#endif
{
PyObject_Free(oldkeys);
}
free_keys_object(interp, oldkeys);
}
}

Expand Down

0 comments on commit 3d71665

Please sign in to comment.