@@ -118,6 +118,7 @@ As a consequence of this, split keys have a maximum size of 16.
118
118
#include "pycore_ceval.h" // _PyEval_GetBuiltin()
119
119
#include "pycore_code.h" // stats
120
120
#include "pycore_dict.h" // export _PyDict_SizeOf()
121
+ #include "pycore_freelist.h" // _PyFreeListState_GET()
121
122
#include "pycore_gc.h" // _PyObject_GC_IS_TRACKED()
122
123
#include "pycore_object.h" // _PyObject_GC_TRACK(), _PyDebugAllocatorStats()
123
124
#include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
@@ -242,40 +243,44 @@ static PyObject* dict_iter(PyObject *dict);
242
243
#include "clinic/dictobject.c.h"
243
244
244
245
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 )
248
249
{
249
- return & interp -> dict_state ;
250
+ _PyFreeListState * state = _PyFreeListState_GET ();
251
+ return & state -> dicts ;
250
252
}
251
253
#endif
252
254
253
255
254
256
void
255
- _PyDict_ClearFreeList (PyInterpreterState * interp )
257
+ _PyDict_ClearFreeList (_PyFreeListState * freelist_state , int is_finalization )
256
258
{
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 ) {
260
262
PyDictObject * op = state -> free_list [-- state -> numfree ];
261
263
assert (PyDict_CheckExact (op ));
262
264
PyObject_GC_Del (op );
263
265
}
264
- while (state -> keys_numfree ) {
266
+ while (state -> keys_numfree > 0 ) {
265
267
PyMem_Free (state -> keys_free_list [-- state -> keys_numfree ]);
266
268
}
269
+ if (is_finalization ) {
270
+ state -> numfree = -1 ;
271
+ state -> keys_numfree = -1 ;
272
+ }
267
273
#endif
268
274
}
269
275
270
-
271
276
void
272
- _PyDict_Fini (PyInterpreterState * interp )
277
+ _PyDict_Fini (PyInterpreterState * Py_UNUSED ( interp ) )
273
278
{
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 ) ;
279
284
#endif
280
285
}
281
286
@@ -290,17 +295,16 @@ unicode_get_hash(PyObject *o)
290
295
void
291
296
_PyDict_DebugMallocStats (FILE * out )
292
297
{
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 ();
296
300
_PyDebugAllocatorStats (out , "free PyDictObject" ,
297
301
state -> numfree , sizeof (PyDictObject ));
298
302
#endif
299
303
}
300
304
301
305
#define DK_MASK (dk ) (DK_SIZE(dk)-1)
302
306
303
- static void free_keys_object (PyInterpreterState * interp , PyDictKeysObject * keys );
307
+ static void free_keys_object (PyDictKeysObject * keys );
304
308
305
309
/* PyDictKeysObject has refcounts like PyObject does, so we have the
306
310
following two functions to mirror what Py_INCREF() and Py_DECREF() do.
@@ -348,7 +352,7 @@ dictkeys_decref(PyInterpreterState *interp, PyDictKeysObject *dk)
348
352
Py_XDECREF (entries [i ].me_value );
349
353
}
350
354
}
351
- free_keys_object (interp , dk );
355
+ free_keys_object (dk );
352
356
}
353
357
}
354
358
@@ -643,12 +647,8 @@ new_keys_object(PyInterpreterState *interp, uint8_t log2_size, bool unicode)
643
647
log2_bytes = log2_size + 2 ;
644
648
}
645
649
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 ();
652
652
if (log2_size == PyDict_LOG_MINSIZE && unicode && state -> keys_numfree > 0 ) {
653
653
dk = state -> keys_free_list [-- state -> keys_numfree ];
654
654
OBJECT_STAT_INC (from_freelist );
@@ -680,16 +680,13 @@ new_keys_object(PyInterpreterState *interp, uint8_t log2_size, bool unicode)
680
680
}
681
681
682
682
static void
683
- free_keys_object (PyInterpreterState * interp , PyDictKeysObject * keys )
683
+ free_keys_object (PyDictKeysObject * keys )
684
684
{
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 ();
691
687
if (DK_LOG_SIZE (keys ) == PyDict_LOG_MINSIZE
692
688
&& state -> keys_numfree < PyDict_MAXFREELIST
689
+ && state -> keys_numfree >= 0
693
690
&& DK_IS_UNICODE (keys )) {
694
691
state -> keys_free_list [state -> keys_numfree ++ ] = keys ;
695
692
OBJECT_STAT_INC (to_freelist );
@@ -730,13 +727,9 @@ new_dict(PyInterpreterState *interp,
730
727
{
731
728
PyDictObject * mp ;
732
729
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 ) {
740
733
mp = state -> free_list [-- state -> numfree ];
741
734
assert (mp != NULL );
742
735
assert (Py_IS_TYPE (mp , & PyDict_Type ));
@@ -1547,7 +1540,7 @@ dictresize(PyInterpreterState *interp, PyDictObject *mp,
1547
1540
#endif
1548
1541
assert (oldkeys -> dk_kind != DICT_KEYS_SPLIT );
1549
1542
assert (oldkeys -> dk_refcnt == 1 );
1550
- free_keys_object (interp , oldkeys );
1543
+ free_keys_object (oldkeys );
1551
1544
}
1552
1545
}
1553
1546
@@ -2458,13 +2451,10 @@ dict_dealloc(PyObject *self)
2458
2451
assert (keys -> dk_refcnt == 1 || keys == Py_EMPTY_KEYS );
2459
2452
dictkeys_decref (interp , keys );
2460
2453
}
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 )) {
2468
2458
state -> free_list [state -> numfree ++ ] = mp ;
2469
2459
OBJECT_STAT_INC (to_freelist );
2470
2460
}
0 commit comments