@@ -118,6 +118,7 @@ As a consequence of this, split keys have a maximum size of 16.
118118#include "pycore_ceval.h" // _PyEval_GetBuiltin()
119119#include "pycore_code.h" // stats
120120#include "pycore_dict.h" // export _PyDict_SizeOf()
121+ #include "pycore_freelist.h" // _PyFreeListState_GET()
121122#include "pycore_gc.h" // _PyObject_GC_IS_TRACKED()
122123#include "pycore_object.h" // _PyObject_GC_TRACK(), _PyDebugAllocatorStats()
123124#include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
@@ -242,40 +243,44 @@ static PyObject* dict_iter(PyObject *dict);
242243#include "clinic/dictobject.c.h"
243244
244245
245- #if PyDict_MAXFREELIST > 0
246- static struct _Py_dict_state *
247- get_dict_state (PyInterpreterState * interp )
246+ #ifdef WITH_FREELISTS
247+ static struct _Py_dict_freelist *
248+ get_dict_state (void )
248249{
249- return & interp -> dict_state ;
250+ _PyFreeListState * state = _PyFreeListState_GET ();
251+ return & state -> dicts ;
250252}
251253#endif
252254
253255
254256void
255- _PyDict_ClearFreeList (PyInterpreterState * interp )
257+ _PyDict_ClearFreeList (_PyFreeListState * freelist_state , int is_finalization )
256258{
257- #if PyDict_MAXFREELIST > 0
258- struct _Py_dict_state * state = & interp -> dict_state ;
259- while (state -> numfree ) {
259+ #ifdef WITH_FREELISTS
260+ struct _Py_dict_freelist * state = & freelist_state -> dicts ;
261+ while (state -> numfree > 0 ) {
260262 PyDictObject * op = state -> free_list [-- state -> numfree ];
261263 assert (PyDict_CheckExact (op ));
262264 PyObject_GC_Del (op );
263265 }
264- while (state -> keys_numfree ) {
266+ while (state -> keys_numfree > 0 ) {
265267 PyMem_Free (state -> keys_free_list [-- state -> keys_numfree ]);
266268 }
269+ if (is_finalization ) {
270+ state -> numfree = -1 ;
271+ state -> keys_numfree = -1 ;
272+ }
267273#endif
268274}
269275
270-
271276void
272- _PyDict_Fini (PyInterpreterState * interp )
277+ _PyDict_Fini (PyInterpreterState * Py_UNUSED ( interp ) )
273278{
274- _PyDict_ClearFreeList ( interp );
275- #if defined( Py_DEBUG ) && PyDict_MAXFREELIST > 0
276- struct _Py_dict_state * state = & interp -> dict_state ;
277- state -> numfree = -1 ;
278- state -> keys_numfree = -1 ;
279+ // With Py_GIL_DISABLED:
280+ // the freelists for the current thread state have already been cleared.
281+ #ifndef Py_GIL_DISABLED
282+ _PyFreeListState * state = _PyFreeListState_GET () ;
283+ _PyDict_ClearFreeList ( state , 1 ) ;
279284#endif
280285}
281286
@@ -290,17 +295,16 @@ unicode_get_hash(PyObject *o)
290295void
291296_PyDict_DebugMallocStats (FILE * out )
292297{
293- #if PyDict_MAXFREELIST > 0
294- PyInterpreterState * interp = _PyInterpreterState_GET ();
295- struct _Py_dict_state * state = get_dict_state (interp );
298+ #ifdef WITH_FREELISTS
299+ struct _Py_dict_freelist * state = get_dict_state ();
296300 _PyDebugAllocatorStats (out , "free PyDictObject" ,
297301 state -> numfree , sizeof (PyDictObject ));
298302#endif
299303}
300304
301305#define DK_MASK (dk ) (DK_SIZE(dk)-1)
302306
303- static void free_keys_object (PyInterpreterState * interp , PyDictKeysObject * keys );
307+ static void free_keys_object (PyDictKeysObject * keys );
304308
305309/* PyDictKeysObject has refcounts like PyObject does, so we have the
306310 following two functions to mirror what Py_INCREF() and Py_DECREF() do.
@@ -348,7 +352,7 @@ dictkeys_decref(PyInterpreterState *interp, PyDictKeysObject *dk)
348352 Py_XDECREF (entries [i ].me_value );
349353 }
350354 }
351- free_keys_object (interp , dk );
355+ free_keys_object (dk );
352356 }
353357}
354358
@@ -643,12 +647,8 @@ new_keys_object(PyInterpreterState *interp, uint8_t log2_size, bool unicode)
643647 log2_bytes = log2_size + 2 ;
644648 }
645649
646- #if PyDict_MAXFREELIST > 0
647- struct _Py_dict_state * state = get_dict_state (interp );
648- #ifdef Py_DEBUG
649- // new_keys_object() must not be called after _PyDict_Fini()
650- assert (state -> keys_numfree != -1 );
651- #endif
650+ #ifdef WITH_FREELISTS
651+ struct _Py_dict_freelist * state = get_dict_state ();
652652 if (log2_size == PyDict_LOG_MINSIZE && unicode && state -> keys_numfree > 0 ) {
653653 dk = state -> keys_free_list [-- state -> keys_numfree ];
654654 OBJECT_STAT_INC (from_freelist );
@@ -680,16 +680,13 @@ new_keys_object(PyInterpreterState *interp, uint8_t log2_size, bool unicode)
680680}
681681
682682static void
683- free_keys_object (PyInterpreterState * interp , PyDictKeysObject * keys )
683+ free_keys_object (PyDictKeysObject * keys )
684684{
685- #if PyDict_MAXFREELIST > 0
686- struct _Py_dict_state * state = get_dict_state (interp );
687- #ifdef Py_DEBUG
688- // free_keys_object() must not be called after _PyDict_Fini()
689- assert (state -> keys_numfree != -1 );
690- #endif
685+ #ifdef WITH_FREELISTS
686+ struct _Py_dict_freelist * state = get_dict_state ();
691687 if (DK_LOG_SIZE (keys ) == PyDict_LOG_MINSIZE
692688 && state -> keys_numfree < PyDict_MAXFREELIST
689+ && state -> keys_numfree >= 0
693690 && DK_IS_UNICODE (keys )) {
694691 state -> keys_free_list [state -> keys_numfree ++ ] = keys ;
695692 OBJECT_STAT_INC (to_freelist );
@@ -730,13 +727,9 @@ new_dict(PyInterpreterState *interp,
730727{
731728 PyDictObject * mp ;
732729 assert (keys != NULL );
733- #if PyDict_MAXFREELIST > 0
734- struct _Py_dict_state * state = get_dict_state (interp );
735- #ifdef Py_DEBUG
736- // new_dict() must not be called after _PyDict_Fini()
737- assert (state -> numfree != -1 );
738- #endif
739- if (state -> numfree ) {
730+ #ifdef WITH_FREELISTS
731+ struct _Py_dict_freelist * state = get_dict_state ();
732+ if (state -> numfree > 0 ) {
740733 mp = state -> free_list [-- state -> numfree ];
741734 assert (mp != NULL );
742735 assert (Py_IS_TYPE (mp , & PyDict_Type ));
@@ -1547,7 +1540,7 @@ dictresize(PyInterpreterState *interp, PyDictObject *mp,
15471540#endif
15481541 assert (oldkeys -> dk_kind != DICT_KEYS_SPLIT );
15491542 assert (oldkeys -> dk_refcnt == 1 );
1550- free_keys_object (interp , oldkeys );
1543+ free_keys_object (oldkeys );
15511544 }
15521545 }
15531546
@@ -2458,13 +2451,10 @@ dict_dealloc(PyObject *self)
24582451 assert (keys -> dk_refcnt == 1 || keys == Py_EMPTY_KEYS );
24592452 dictkeys_decref (interp , keys );
24602453 }
2461- #if PyDict_MAXFREELIST > 0
2462- struct _Py_dict_state * state = get_dict_state (interp );
2463- #ifdef Py_DEBUG
2464- // new_dict() must not be called after _PyDict_Fini()
2465- assert (state -> numfree != -1 );
2466- #endif
2467- if (state -> numfree < PyDict_MAXFREELIST && Py_IS_TYPE (mp , & PyDict_Type )) {
2454+ #ifdef WITH_FREELISTS
2455+ struct _Py_dict_freelist * state = get_dict_state ();
2456+ if (state -> numfree < PyDict_MAXFREELIST && state -> numfree >=0 &&
2457+ Py_IS_TYPE (mp , & PyDict_Type )) {
24682458 state -> free_list [state -> numfree ++ ] = mp ;
24692459 OBJECT_STAT_INC (to_freelist );
24702460 }
0 commit comments