@@ -7048,17 +7048,9 @@ _PyObject_SetManagedDict(PyObject *obj, PyObject *new_dict)
7048
7048
7049
7049
Py_BEGIN_CRITICAL_SECTION2 (dict , obj );
7050
7050
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 ;
7062
7054
7063
7055
FT_ATOMIC_STORE_PTR (_PyObject_ManagedDictPointer (obj )-> dict ,
7064
7056
(PyDictObject * )Py_XNewRef (new_dict ));
@@ -7067,7 +7059,7 @@ _PyObject_SetManagedDict(PyObject *obj, PyObject *new_dict)
7067
7059
7068
7060
Py_END_CRITICAL_SECTION2 ();
7069
7061
7070
- Py_DECREF (dict );
7062
+ Py_XDECREF (dict );
7071
7063
}
7072
7064
else {
7073
7065
PyDictObject * dict ;
@@ -7095,21 +7087,25 @@ PyObject_ClearManagedDict(PyObject *obj)
7095
7087
int
7096
7088
_PyDict_DetachFromObject (PyDictObject * mp , PyObject * obj )
7097
7089
{
7098
- _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED (mp );
7099
7090
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED (obj );
7100
7091
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 )) {
7102
7093
return 0 ;
7103
7094
}
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 );
7104
7099
assert (mp -> ma_values -> embedded == 1 );
7105
7100
assert (mp -> ma_values -> valid == 1 );
7106
7101
assert (Py_TYPE (obj )-> tp_flags & Py_TPFLAGS_INLINE_VALUES );
7107
7102
7108
- mp -> ma_values = copy_values (mp -> ma_values );
7103
+ PyDictValues * values = copy_values (mp -> ma_values );
7109
7104
7110
- if (mp -> ma_values == NULL ) {
7105
+ if (values == NULL ) {
7111
7106
return -1 ;
7112
7107
}
7108
+ mp -> ma_values = values ;
7113
7109
7114
7110
FT_ATOMIC_STORE_UINT8 (_PyObject_InlineValues (obj )-> valid , 0 );
7115
7111
0 commit comments