@@ -247,58 +247,47 @@ static uint64_t pydict_global_version = 0;
247247
248248#define DICT_NEXT_VERSION () (++pydict_global_version)
249249
250- /* Dictionary reuse scheme to save calls to malloc and free */
251- #ifndef PyDict_MAXFREELIST
252- #define PyDict_MAXFREELIST 80
253- #endif
254-
255- /* bpo-40521: dict free lists are shared by all interpreters. */
256- #ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
257- # undef PyDict_MAXFREELIST
258- # define PyDict_MAXFREELIST 0
259- #endif
260-
261- #if PyDict_MAXFREELIST > 0
262- static PyDictObject * free_list [PyDict_MAXFREELIST ];
263- static int numfree = 0 ;
264- static PyDictKeysObject * keys_free_list [PyDict_MAXFREELIST ];
265- static int numfreekeys = 0 ;
266- #endif
267-
268250#include "clinic/dictobject.c.h"
269251
270252void
271- _PyDict_ClearFreeList (void )
253+ _PyDict_ClearFreeList (PyThreadState * tstate )
272254{
273- #if PyDict_MAXFREELIST > 0
274- while (numfree ) {
275- PyDictObject * op = free_list [-- numfree ];
255+ struct _Py_dict_state * state = & tstate -> interp -> dict_state ;
256+ while (state -> numfree ) {
257+ PyDictObject * op = state -> free_list [-- state -> numfree ];
276258 assert (PyDict_CheckExact (op ));
277259 PyObject_GC_Del (op );
278260 }
279- while (numfreekeys ) {
280- PyObject_FREE (keys_free_list [-- numfreekeys ]);
261+ while (state -> keys_numfree ) {
262+ PyObject_FREE (state -> keys_free_list [-- state -> keys_numfree ]);
281263 }
282- #endif
283264}
284265
285- /* Print summary info about the state of the optimized allocator */
266+
286267void
287- _PyDict_DebugMallocStats ( FILE * out )
268+ _PyDict_Fini ( PyThreadState * tstate )
288269{
289- #if PyDict_MAXFREELIST > 0
290- _PyDebugAllocatorStats (out ,
291- "free PyDictObject" , numfree , sizeof (PyDictObject ));
270+ _PyDict_ClearFreeList (tstate );
271+ #ifdef Py_DEBUG
272+ PyInterpreterState * interp = _PyInterpreterState_GET ();
273+ struct _Py_dict_state * state = & interp -> dict_state ;
274+ state -> numfree = -1 ;
275+ state -> keys_numfree = -1 ;
292276#endif
293277}
294278
295279
280+ /* Print summary info about the state of the optimized allocator */
296281void
297- _PyDict_Fini ( void )
282+ _PyDict_DebugMallocStats ( FILE * out )
298283{
299- _PyDict_ClearFreeList ();
284+ PyInterpreterState * interp = _PyInterpreterState_GET ();
285+ struct _Py_dict_state * state = & interp -> dict_state ;
286+ _PyDebugAllocatorStats (out , "free PyDictObject" ,
287+ state -> numfree , sizeof (PyDictObject ));
300288}
301289
290+
302291#define DK_SIZE (dk ) ((dk)->dk_size)
303292#if SIZEOF_VOID_P > 4
304293#define DK_IXSIZE (dk ) \
@@ -543,7 +532,8 @@ _PyDict_CheckConsistency(PyObject *op, int check_content)
543532}
544533
545534
546- static PyDictKeysObject * new_keys_object (Py_ssize_t size )
535+ static PyDictKeysObject *
536+ new_keys_object (Py_ssize_t size )
547537{
548538 PyDictKeysObject * dk ;
549539 Py_ssize_t es , usable ;
@@ -567,12 +557,16 @@ static PyDictKeysObject *new_keys_object(Py_ssize_t size)
567557 es = sizeof (Py_ssize_t );
568558 }
569559
570- #if PyDict_MAXFREELIST > 0
571- if (size == PyDict_MINSIZE && numfreekeys > 0 ) {
572- dk = keys_free_list [-- numfreekeys ];
560+ PyInterpreterState * interp = _PyInterpreterState_GET ();
561+ struct _Py_dict_state * state = & interp -> dict_state ;
562+ #ifdef Py_DEBUG
563+ // new_keys_object() must not be called after _PyDict_Fini()
564+ assert (state -> keys_numfree != -1 );
565+ #endif
566+ if (size == PyDict_MINSIZE && state -> keys_numfree > 0 ) {
567+ dk = state -> keys_free_list [-- state -> keys_numfree ];
573568 }
574569 else
575- #endif
576570 {
577571 dk = PyObject_MALLOC (sizeof (PyDictKeysObject )
578572 + es * size
@@ -604,12 +598,16 @@ free_keys_object(PyDictKeysObject *keys)
604598 Py_XDECREF (entries [i ].me_key );
605599 Py_XDECREF (entries [i ].me_value );
606600 }
607- #if PyDict_MAXFREELIST > 0
608- if (keys -> dk_size == PyDict_MINSIZE && numfreekeys < PyDict_MAXFREELIST ) {
609- keys_free_list [numfreekeys ++ ] = keys ;
601+ PyInterpreterState * interp = _PyInterpreterState_GET ();
602+ struct _Py_dict_state * state = & interp -> dict_state ;
603+ #ifdef Py_DEBUG
604+ // free_keys_object() must not be called after _PyDict_Fini()
605+ assert (state -> keys_numfree != -1 );
606+ #endif
607+ if (keys -> dk_size == PyDict_MINSIZE && state -> keys_numfree < PyDict_MAXFREELIST ) {
608+ state -> keys_free_list [state -> keys_numfree ++ ] = keys ;
610609 return ;
611610 }
612- #endif
613611 PyObject_FREE (keys );
614612}
615613
@@ -622,16 +620,19 @@ new_dict(PyDictKeysObject *keys, PyObject **values)
622620{
623621 PyDictObject * mp ;
624622 assert (keys != NULL );
625- #if PyDict_MAXFREELIST > 0
626- if (numfree ) {
627- mp = free_list [-- numfree ];
623+ PyInterpreterState * interp = _PyInterpreterState_GET ();
624+ struct _Py_dict_state * state = & interp -> dict_state ;
625+ #ifdef Py_DEBUG
626+ // new_dict() must not be called after _PyDict_Fini()
627+ assert (state -> numfree != -1 );
628+ #endif
629+ if (state -> numfree ) {
630+ mp = state -> free_list [-- state -> numfree ];
628631 assert (mp != NULL );
629632 assert (Py_IS_TYPE (mp , & PyDict_Type ));
630633 _Py_NewReference ((PyObject * )mp );
631634 }
632- else
633- #endif
634- {
635+ else {
635636 mp = PyObject_GC_New (PyDictObject , & PyDict_Type );
636637 if (mp == NULL ) {
637638 dictkeys_decref (keys );
@@ -1280,15 +1281,18 @@ dictresize(PyDictObject *mp, Py_ssize_t minsize)
12801281#ifdef Py_REF_DEBUG
12811282 _Py_RefTotal -- ;
12821283#endif
1283- #if PyDict_MAXFREELIST > 0
1284+ PyInterpreterState * interp = _PyInterpreterState_GET ();
1285+ struct _Py_dict_state * state = & interp -> dict_state ;
1286+ #ifdef Py_DEBUG
1287+ // dictresize() must not be called after _PyDict_Fini()
1288+ assert (state -> keys_numfree != -1 );
1289+ #endif
12841290 if (oldkeys -> dk_size == PyDict_MINSIZE &&
1285- numfreekeys < PyDict_MAXFREELIST )
1291+ state -> keys_numfree < PyDict_MAXFREELIST )
12861292 {
1287- keys_free_list [numfreekeys ++ ] = oldkeys ;
1293+ state -> keys_free_list [state -> keys_numfree ++ ] = oldkeys ;
12881294 }
1289- else
1290- #endif
1291- {
1295+ else {
12921296 PyObject_FREE (oldkeys );
12931297 }
12941298 }
@@ -2028,13 +2032,16 @@ dict_dealloc(PyDictObject *mp)
20282032 assert (keys -> dk_refcnt == 1 );
20292033 dictkeys_decref (keys );
20302034 }
2031- #if PyDict_MAXFREELIST > 0
2032- if ( numfree < PyDict_MAXFREELIST && Py_IS_TYPE ( mp , & PyDict_Type )) {
2033- free_list [ numfree ++ ] = mp ;
2034- }
2035- else
2035+ PyInterpreterState * interp = _PyInterpreterState_GET ();
2036+ struct _Py_dict_state * state = & interp -> dict_state ;
2037+ #ifdef Py_DEBUG
2038+ // new_dict() must not be called after _PyDict_Fini()
2039+ assert ( state -> numfree != -1 );
20362040#endif
2037- {
2041+ if (state -> numfree < PyDict_MAXFREELIST && Py_IS_TYPE (mp , & PyDict_Type )) {
2042+ state -> free_list [state -> numfree ++ ] = mp ;
2043+ }
2044+ else {
20382045 Py_TYPE (mp )-> tp_free ((PyObject * )mp );
20392046 }
20402047 Py_TRASHCAN_END
0 commit comments