@@ -300,9 +300,19 @@ _PyDict_DebugMallocStats(FILE *out)
300
300
301
301
static void free_keys_object (PyInterpreterState * interp , PyDictKeysObject * keys );
302
302
303
+ /* PyDictKeysObject has refcounts like PyObject does, so we have the
304
+ following two functions to mirror what Py_INCREF() and Py_DECREF() do.
305
+ (Keep in mind that PyDictKeysObject isn't actually a PyObject.)
306
+ Likewise a PyDictKeysObject can be immortal (e.g. Py_EMPTY_KEYS),
307
+ so we apply a naive version of what Py_INCREF() and Py_DECREF() do
308
+ for immortal objects. */
309
+
303
310
static inline void
304
311
dictkeys_incref (PyDictKeysObject * dk )
305
312
{
313
+ if (dk -> dk_refcnt == _Py_IMMORTAL_REFCNT ) {
314
+ return ;
315
+ }
306
316
#ifdef Py_REF_DEBUG
307
317
_Py_IncRefTotal (_PyInterpreterState_GET ());
308
318
#endif
@@ -312,6 +322,9 @@ dictkeys_incref(PyDictKeysObject *dk)
312
322
static inline void
313
323
dictkeys_decref (PyInterpreterState * interp , PyDictKeysObject * dk )
314
324
{
325
+ if (dk -> dk_refcnt == _Py_IMMORTAL_REFCNT ) {
326
+ return ;
327
+ }
315
328
assert (dk -> dk_refcnt > 0 );
316
329
#ifdef Py_REF_DEBUG
317
330
_Py_DecRefTotal (_PyInterpreterState_GET ());
@@ -447,7 +460,7 @@ estimate_log2_keysize(Py_ssize_t n)
447
460
* (which cannot fail and thus can do no allocation).
448
461
*/
449
462
static PyDictKeysObject empty_keys_struct = {
450
- 1 , /* dk_refcnt */
463
+ _Py_IMMORTAL_REFCNT , /* dk_refcnt */
451
464
0 , /* dk_log2_size */
452
465
0 , /* dk_log2_index_bytes */
453
466
DICT_KEYS_UNICODE , /* dk_kind */
@@ -779,6 +792,7 @@ clone_combined_dict_keys(PyDictObject *orig)
779
792
assert (PyDict_Check (orig ));
780
793
assert (Py_TYPE (orig )-> tp_iter == (getiterfunc )dict_iter );
781
794
assert (orig -> ma_values == NULL );
795
+ assert (orig -> ma_keys != Py_EMPTY_KEYS );
782
796
assert (orig -> ma_keys -> dk_refcnt == 1 );
783
797
784
798
size_t keys_size = _PyDict_KeysSize (orig -> ma_keys );
@@ -833,7 +847,7 @@ PyObject *
833
847
PyDict_New (void )
834
848
{
835
849
PyInterpreterState * interp = _PyInterpreterState_GET ();
836
- dictkeys_incref ( Py_EMPTY_KEYS );
850
+ /* We don't incref Py_EMPTY_KEYS here because it is immortal. */
837
851
return new_dict (interp , Py_EMPTY_KEYS , NULL , 0 , 0 );
838
852
}
839
853
@@ -1331,7 +1345,7 @@ insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp,
1331
1345
Py_DECREF (value );
1332
1346
return -1 ;
1333
1347
}
1334
- dictkeys_decref ( interp , Py_EMPTY_KEYS );
1348
+ /* We don't decref Py_EMPTY_KEYS here because it is immortal. */
1335
1349
mp -> ma_keys = newkeys ;
1336
1350
mp -> ma_values = NULL ;
1337
1351
@@ -1529,14 +1543,10 @@ dictresize(PyInterpreterState *interp, PyDictObject *mp,
1529
1543
1530
1544
// We can not use free_keys_object here because key's reference
1531
1545
// are moved already.
1546
+ if (oldkeys != Py_EMPTY_KEYS ) {
1532
1547
#ifdef Py_REF_DEBUG
1533
- _Py_DecRefTotal (_PyInterpreterState_GET ());
1548
+ _Py_DecRefTotal (_PyInterpreterState_GET ());
1534
1549
#endif
1535
- if (oldkeys == Py_EMPTY_KEYS ) {
1536
- oldkeys -> dk_refcnt -- ;
1537
- assert (oldkeys -> dk_refcnt > 0 );
1538
- }
1539
- else {
1540
1550
assert (oldkeys -> dk_kind != DICT_KEYS_SPLIT );
1541
1551
assert (oldkeys -> dk_refcnt == 1 );
1542
1552
#if PyDict_MAXFREELIST > 0
@@ -2080,8 +2090,8 @@ PyDict_Clear(PyObject *op)
2080
2090
dictkeys_decref (interp , oldkeys );
2081
2091
}
2082
2092
else {
2083
- assert (oldkeys -> dk_refcnt == 1 );
2084
- dictkeys_decref (interp , oldkeys );
2093
+ assert (oldkeys -> dk_refcnt == 1 );
2094
+ dictkeys_decref (interp , oldkeys );
2085
2095
}
2086
2096
ASSERT_CONSISTENT (mp );
2087
2097
}
0 commit comments