@@ -7048,17 +7048,9 @@ _PyObject_SetManagedDict(PyObject *obj, PyObject *new_dict)
70487048
70497049 Py_BEGIN_CRITICAL_SECTION2 (dict , obj );
70507050
7051- #ifdef Py_DEBUG
7052- // If the dict in the object has been replaced between when we got
7053- // the dict and unlocked the objects then it's definitely no longer
7054- // inline and there's no need to detach it, we can just replace it.
7055- // The call to _PyDict_DetachFromObject will be a nop.
7056- PyDictObject * cur_dict = _PyObject_ManagedDictPointer (obj )-> dict ;
7057- assert (cur_dict == dict ||
7058- (cur_dict -> ma_values != _PyObject_InlineValues (obj ) &&
7059- dict -> ma_values != _PyObject_InlineValues (obj ) &&
7060- !_PyObject_InlineValues (obj )-> valid ));
7061- #endif
7051+ // We've locked dict, but the actual dict could have changed
7052+ // since we locked it.
7053+ dict = _PyObject_ManagedDictPointer (obj )-> dict ;
70627054
70637055 FT_ATOMIC_STORE_PTR (_PyObject_ManagedDictPointer (obj )-> dict ,
70647056 (PyDictObject * )Py_XNewRef (new_dict ));
@@ -7067,7 +7059,7 @@ _PyObject_SetManagedDict(PyObject *obj, PyObject *new_dict)
70677059
70687060 Py_END_CRITICAL_SECTION2 ();
70697061
7070- Py_DECREF (dict );
7062+ Py_XDECREF (dict );
70717063 }
70727064 else {
70737065 PyDictObject * dict ;
@@ -7095,21 +7087,25 @@ PyObject_ClearManagedDict(PyObject *obj)
70957087int
70967088_PyDict_DetachFromObject (PyDictObject * mp , PyObject * obj )
70977089{
7098- _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED (mp );
70997090 _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED (obj );
71007091
7101- if (mp -> ma_values == NULL || mp -> ma_values != _PyObject_InlineValues (obj )) {
7092+ if (FT_ATOMIC_LOAD_PTR_RELAXED ( mp -> ma_values ) != _PyObject_InlineValues (obj )) {
71027093 return 0 ;
71037094 }
7095+
7096+ // We could be called with an unlocked dict when the caller knows the
7097+ // values are already detached, so we assert after inline values check.
7098+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED (mp );
71047099 assert (mp -> ma_values -> embedded == 1 );
71057100 assert (mp -> ma_values -> valid == 1 );
71067101 assert (Py_TYPE (obj )-> tp_flags & Py_TPFLAGS_INLINE_VALUES );
71077102
7108- mp -> ma_values = copy_values (mp -> ma_values );
7103+ PyDictValues * values = copy_values (mp -> ma_values );
71097104
7110- if (mp -> ma_values == NULL ) {
7105+ if (values == NULL ) {
71117106 return -1 ;
71127107 }
7108+ mp -> ma_values = values ;
71137109
71147110 FT_ATOMIC_STORE_UINT8 (_PyObject_InlineValues (obj )-> valid , 0 );
71157111
0 commit comments