@@ -883,6 +883,7 @@ new_dict(PyInterpreterState *interp,
883883 mp -> ma_used = used ;
884884 mp -> _ma_watcher_tag = 0 ;
885885 ASSERT_CONSISTENT (mp );
886+ _PyObject_GC_TRACK (mp );
886887 return (PyObject * )mp ;
887888}
888889
@@ -1578,64 +1579,6 @@ _PyDict_HasOnlyStringKeys(PyObject *dict)
15781579 return 1 ;
15791580}
15801581
1581- #define MAINTAIN_TRACKING (mp , key , value ) \
1582- do { \
1583- if (!_PyObject_GC_IS_TRACKED(mp)) { \
1584- if (_PyObject_GC_MAY_BE_TRACKED(key) || \
1585- _PyObject_GC_MAY_BE_TRACKED(value)) { \
1586- _PyObject_GC_TRACK(mp); \
1587- } \
1588- } \
1589- } while(0)
1590-
1591- void
1592- _PyDict_MaybeUntrack (PyObject * op )
1593- {
1594- PyDictObject * mp ;
1595- PyObject * value ;
1596- Py_ssize_t i , numentries ;
1597-
1598- ASSERT_WORLD_STOPPED_OR_DICT_LOCKED (op );
1599-
1600- if (!PyDict_CheckExact (op ) || !_PyObject_GC_IS_TRACKED (op ))
1601- return ;
1602-
1603- mp = (PyDictObject * ) op ;
1604- ASSERT_CONSISTENT (mp );
1605- numentries = mp -> ma_keys -> dk_nentries ;
1606- if (_PyDict_HasSplitTable (mp )) {
1607- for (i = 0 ; i < numentries ; i ++ ) {
1608- if ((value = mp -> ma_values -> values [i ]) == NULL )
1609- continue ;
1610- if (_PyObject_GC_MAY_BE_TRACKED (value )) {
1611- return ;
1612- }
1613- }
1614- }
1615- else {
1616- if (DK_IS_UNICODE (mp -> ma_keys )) {
1617- PyDictUnicodeEntry * ep0 = DK_UNICODE_ENTRIES (mp -> ma_keys );
1618- for (i = 0 ; i < numentries ; i ++ ) {
1619- if ((value = ep0 [i ].me_value ) == NULL )
1620- continue ;
1621- if (_PyObject_GC_MAY_BE_TRACKED (value ))
1622- return ;
1623- }
1624- }
1625- else {
1626- PyDictKeyEntry * ep0 = DK_ENTRIES (mp -> ma_keys );
1627- for (i = 0 ; i < numentries ; i ++ ) {
1628- if ((value = ep0 [i ].me_value ) == NULL )
1629- continue ;
1630- if (_PyObject_GC_MAY_BE_TRACKED (value ) ||
1631- _PyObject_GC_MAY_BE_TRACKED (ep0 [i ].me_key ))
1632- return ;
1633- }
1634- }
1635- }
1636- _PyObject_GC_UNTRACK (op );
1637- }
1638-
16391582void
16401583_PyDict_EnablePerThreadRefcounting (PyObject * op )
16411584{
@@ -1761,7 +1704,6 @@ insert_split_value(PyInterpreterState *interp, PyDictObject *mp, PyObject *key,
17611704{
17621705 assert (PyUnicode_CheckExact (key ));
17631706 ASSERT_DICT_LOCKED (mp );
1764- MAINTAIN_TRACKING (mp , key , value );
17651707 PyObject * old_value = mp -> ma_values -> values [ix ];
17661708 if (old_value == NULL ) {
17671709 _PyDict_NotifyEvent (interp , PyDict_EVENT_ADDED , mp , key , value );
@@ -1818,8 +1760,6 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp,
18181760 if (ix == DKIX_ERROR )
18191761 goto Fail ;
18201762
1821- MAINTAIN_TRACKING (mp , key , value );
1822-
18231763 if (ix == DKIX_EMPTY ) {
18241764 assert (!_PyDict_HasSplitTable (mp ));
18251765 /* Insert into new slot. */
@@ -1878,8 +1818,6 @@ insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp,
18781818 /* We don't decref Py_EMPTY_KEYS here because it is immortal. */
18791819 assert (mp -> ma_values == NULL );
18801820
1881- MAINTAIN_TRACKING (mp , key , value );
1882-
18831821 size_t hashpos = (size_t )hash & (PyDict_MINSIZE - 1 );
18841822 dictkeys_set_index (newkeys , hashpos , 0 );
18851823 if (unicode ) {
@@ -4024,8 +3962,7 @@ copy_lock_held(PyObject *o)
40243962 split_copy -> ma_used = mp -> ma_used ;
40253963 split_copy -> _ma_watcher_tag = 0 ;
40263964 dictkeys_incref (mp -> ma_keys );
4027- if (_PyObject_GC_IS_TRACKED (mp ))
4028- _PyObject_GC_TRACK (split_copy );
3965+ _PyObject_GC_TRACK (split_copy );
40293966 return (PyObject * )split_copy ;
40303967 }
40313968
@@ -4060,11 +3997,6 @@ copy_lock_held(PyObject *o)
40603997
40613998 new -> ma_used = mp -> ma_used ;
40623999 ASSERT_CONSISTENT (new );
4063- if (_PyObject_GC_IS_TRACKED (mp )) {
4064- /* Maintain tracking. */
4065- _PyObject_GC_TRACK (new );
4066- }
4067-
40684000 return (PyObject * )new ;
40694001 }
40704002
@@ -4351,7 +4283,6 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
43514283 }
43524284 }
43534285
4354- MAINTAIN_TRACKING (mp , key , value );
43554286 STORE_USED (mp , mp -> ma_used + 1 );
43564287 assert (mp -> ma_keys -> dk_usable >= 0 );
43574288 ASSERT_CONSISTENT (mp );
@@ -4800,16 +4731,8 @@ dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
48004731 d -> ma_keys = Py_EMPTY_KEYS ;
48014732 d -> ma_values = NULL ;
48024733 ASSERT_CONSISTENT (d );
4803-
4804- if (type != & PyDict_Type ) {
4805- // Don't track if a subclass tp_alloc is PyType_GenericAlloc()
4806- if (!_PyObject_GC_IS_TRACKED (d )) {
4807- _PyObject_GC_TRACK (d );
4808- }
4809- }
4810- else {
4811- // _PyType_AllocNoTrack() does not track the created object
4812- assert (!_PyObject_GC_IS_TRACKED (d ));
4734+ if (!_PyObject_GC_IS_TRACKED (d )) {
4735+ _PyObject_GC_TRACK (d );
48134736 }
48144737 return self ;
48154738}
@@ -6746,19 +6669,14 @@ make_dict_from_instance_attributes(PyInterpreterState *interp,
67466669{
67476670 dictkeys_incref (keys );
67486671 Py_ssize_t used = 0 ;
6749- Py_ssize_t track = 0 ;
67506672 size_t size = shared_keys_usable_size (keys );
67516673 for (size_t i = 0 ; i < size ; i ++ ) {
67526674 PyObject * val = values -> values [i ];
67536675 if (val != NULL ) {
67546676 used += 1 ;
6755- track += _PyObject_GC_MAY_BE_TRACKED (val );
67566677 }
67576678 }
67586679 PyDictObject * res = (PyDictObject * )new_dict (interp , keys , values , used , 0 );
6759- if (track && res ) {
6760- _PyObject_GC_TRACK (res );
6761- }
67626680 return res ;
67636681}
67646682
@@ -7204,6 +7122,7 @@ _PyObject_SetManagedDict(PyObject *obj, PyObject *new_dict)
72047122 // since we locked it.
72057123 dict = _PyObject_ManagedDictPointer (obj )-> dict ;
72067124 err = _PyDict_DetachFromObject (dict , obj );
7125+ assert (err == 0 || new_dict == NULL );
72077126 if (err == 0 ) {
72087127 FT_ATOMIC_STORE_PTR (_PyObject_ManagedDictPointer (obj )-> dict ,
72097128 (PyDictObject * )Py_XNewRef (new_dict ));
@@ -7236,7 +7155,21 @@ void
72367155PyObject_ClearManagedDict (PyObject * obj )
72377156{
72387157 if (_PyObject_SetManagedDict (obj , NULL ) < 0 ) {
7158+ /* Must be out of memory */
7159+ assert (PyErr_Occurred () == PyExc_MemoryError );
72397160 PyErr_WriteUnraisable (NULL );
7161+ /* Clear the dict */
7162+ PyDictObject * dict = _PyObject_GetManagedDict (obj );
7163+ Py_BEGIN_CRITICAL_SECTION2 (dict , obj );
7164+ dict = _PyObject_ManagedDictPointer (obj )-> dict ;
7165+ PyInterpreterState * interp = _PyInterpreterState_GET ();
7166+ PyDictKeysObject * oldkeys = dict -> ma_keys ;
7167+ set_keys (dict , Py_EMPTY_KEYS );
7168+ dict -> ma_values = NULL ;
7169+ dictkeys_decref (interp , oldkeys , IS_DICT_SHARED (dict ));
7170+ STORE_USED (dict , 0 );
7171+ set_dict_inline_values (obj , NULL );
7172+ Py_END_CRITICAL_SECTION2 ();
72407173 }
72417174}
72427175
@@ -7261,12 +7194,6 @@ _PyDict_DetachFromObject(PyDictObject *mp, PyObject *obj)
72617194 PyDictValues * values = copy_values (mp -> ma_values );
72627195
72637196 if (values == NULL ) {
7264- /* Out of memory. Clear the dict */
7265- PyInterpreterState * interp = _PyInterpreterState_GET ();
7266- PyDictKeysObject * oldkeys = mp -> ma_keys ;
7267- set_keys (mp , Py_EMPTY_KEYS );
7268- dictkeys_decref (interp , oldkeys , IS_DICT_SHARED (mp ));
7269- STORE_USED (mp , 0 );
72707197 PyErr_NoMemory ();
72717198 return -1 ;
72727199 }
0 commit comments