@@ -7159,70 +7159,47 @@ _PyDict_DetachFromObject(PyDictObject *mp, PyObject *obj)
7159
7159
return 0 ;
7160
7160
}
7161
7161
7162
- PyObject *
7163
- PyObject_GenericGetDict (PyObject * obj , void * context )
7162
+ static inline PyObject *
7163
+ ensure_managed_dict (PyObject * obj )
7164
7164
{
7165
- PyInterpreterState * interp = _PyInterpreterState_GET ();
7166
- PyTypeObject * tp = Py_TYPE (obj );
7167
- PyDictObject * dict ;
7168
- if (_PyType_HasFeature (tp , Py_TPFLAGS_MANAGED_DICT )) {
7169
- dict = _PyObject_GetManagedDict (obj );
7170
- if (dict == NULL &&
7171
- (tp -> tp_flags & Py_TPFLAGS_INLINE_VALUES ) &&
7165
+ PyDictObject * dict = _PyObject_GetManagedDict (obj );
7166
+ if (dict == NULL ) {
7167
+ PyTypeObject * tp = Py_TYPE (obj );
7168
+ if ((tp -> tp_flags & Py_TPFLAGS_INLINE_VALUES ) &&
7172
7169
FT_ATOMIC_LOAD_UINT8 (_PyObject_InlineValues (obj )-> valid )) {
7173
7170
dict = _PyObject_MaterializeManagedDict (obj );
7174
7171
}
7175
- else if (dict == NULL ) {
7176
- Py_BEGIN_CRITICAL_SECTION (obj );
7177
-
7172
+ else {
7173
+ #ifdef Py_GIL_DISABLED
7178
7174
// Check again that we're not racing with someone else creating the dict
7175
+ Py_BEGIN_CRITICAL_SECTION (obj );
7179
7176
dict = _PyObject_GetManagedDict (obj );
7180
- if (dict == NULL ) {
7181
- OBJECT_STAT_INC (dict_materialized_on_request );
7182
- dictkeys_incref (CACHED_KEYS (tp ));
7183
- dict = (PyDictObject * )new_dict_with_shared_keys (interp , CACHED_KEYS (tp ));
7184
- FT_ATOMIC_STORE_PTR_RELEASE (_PyObject_ManagedDictPointer (obj )-> dict ,
7185
- (PyDictObject * )dict );
7177
+ if (dict != NULL ) {
7178
+ goto done ;
7186
7179
}
7180
+ #endif
7181
+ OBJECT_STAT_INC (dict_materialized_on_request );
7182
+ dictkeys_incref (CACHED_KEYS (tp ));
7183
+ dict = (PyDictObject * )new_dict_with_shared_keys (_PyInterpreterState_GET (),
7184
+ CACHED_KEYS (tp ));
7185
+ FT_ATOMIC_STORE_PTR_RELEASE (_PyObject_ManagedDictPointer (obj )-> dict ,
7186
+ (PyDictObject * )dict );
7187
7187
7188
+ #ifdef Py_GIL_DISABLED
7189
+ done :
7188
7190
Py_END_CRITICAL_SECTION ();
7191
+ #endif
7189
7192
}
7190
- return Py_XNewRef ((PyObject * )dict );
7191
- }
7192
- else {
7193
- PyObject * * dictptr = _PyObject_ComputedDictPointer (obj );
7194
- if (dictptr == NULL ) {
7195
- PyErr_SetString (PyExc_AttributeError ,
7196
- "This object has no __dict__" );
7197
- return NULL ;
7198
- }
7199
- PyObject * dict = * dictptr ;
7200
- if (dict == NULL ) {
7201
- PyTypeObject * tp = Py_TYPE (obj );
7202
- if (_PyType_HasFeature (tp , Py_TPFLAGS_HEAPTYPE ) && CACHED_KEYS (tp )) {
7203
- dictkeys_incref (CACHED_KEYS (tp ));
7204
- * dictptr = dict = new_dict_with_shared_keys (
7205
- interp , CACHED_KEYS (tp ));
7206
- }
7207
- else {
7208
- * dictptr = dict = PyDict_New ();
7209
- }
7210
- }
7211
- return Py_XNewRef (dict );
7212
7193
}
7194
+ return (PyObject * )dict ;
7213
7195
}
7214
7196
7215
- int
7216
- _PyObjectDict_SetItem (PyTypeObject * tp , PyObject * obj , PyObject * * dictptr ,
7217
- PyObject * key , PyObject * value )
7197
+ static inline PyObject *
7198
+ ensure_nonmanaged_dict (PyObject * obj , PyObject * * dictptr )
7218
7199
{
7219
- PyObject * dict ;
7220
- int res ;
7221
7200
PyDictKeysObject * cached ;
7222
- PyInterpreterState * interp = _PyInterpreterState_GET ();
7223
7201
7224
- assert (dictptr != NULL );
7225
- dict = * dictptr ;
7202
+ PyObject * dict = FT_ATOMIC_LOAD_PTR_RELAXED (* dictptr );
7226
7203
if (dict == NULL ) {
7227
7204
#ifdef Py_GIL_DISABLED
7228
7205
Py_BEGIN_CRITICAL_SECTION (obj );
@@ -7231,7 +7208,9 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject *obj, PyObject **dictptr,
7231
7208
goto done ;
7232
7209
}
7233
7210
#endif
7211
+ PyTypeObject * tp = Py_TYPE (obj );
7234
7212
if ((tp -> tp_flags & Py_TPFLAGS_HEAPTYPE ) && (cached = CACHED_KEYS (tp ))) {
7213
+ PyInterpreterState * interp = _PyInterpreterState_GET ();
7235
7214
assert (!_PyType_HasFeature (tp , Py_TPFLAGS_INLINE_VALUES ));
7236
7215
dictkeys_incref (cached );
7237
7216
dict = new_dict_with_shared_keys (interp , cached );
@@ -7242,14 +7221,45 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject *obj, PyObject **dictptr,
7242
7221
else {
7243
7222
dict = PyDict_New ();
7244
7223
}
7245
- * dictptr = dict ;
7224
+ FT_ATOMIC_STORE_PTR_RELAXED ( * dictptr , dict ) ;
7246
7225
#ifdef Py_GIL_DISABLED
7247
7226
done :
7248
7227
Py_END_CRITICAL_SECTION ();
7249
7228
#endif
7250
- if (dict == NULL ) {
7251
- return -1 ;
7229
+ }
7230
+ return dict ;
7231
+ }
7232
+
7233
+ PyObject *
7234
+ PyObject_GenericGetDict (PyObject * obj , void * context )
7235
+ {
7236
+ PyTypeObject * tp = Py_TYPE (obj );
7237
+ if (_PyType_HasFeature (tp , Py_TPFLAGS_MANAGED_DICT )) {
7238
+ return Py_XNewRef (ensure_managed_dict (obj ));
7239
+ }
7240
+ else {
7241
+ PyObject * * dictptr = _PyObject_ComputedDictPointer (obj );
7242
+ if (dictptr == NULL ) {
7243
+ PyErr_SetString (PyExc_AttributeError ,
7244
+ "This object has no __dict__" );
7245
+ return NULL ;
7252
7246
}
7247
+
7248
+ return Py_XNewRef (ensure_nonmanaged_dict (obj , dictptr ));
7249
+ }
7250
+ }
7251
+
7252
+ int
7253
+ _PyObjectDict_SetItem (PyTypeObject * tp , PyObject * obj , PyObject * * dictptr ,
7254
+ PyObject * key , PyObject * value )
7255
+ {
7256
+ PyObject * dict ;
7257
+ int res ;
7258
+
7259
+ assert (dictptr != NULL );
7260
+ dict = ensure_nonmanaged_dict (obj , dictptr );
7261
+ if (dict == NULL ) {
7262
+ return -1 ;
7253
7263
}
7254
7264
7255
7265
Py_BEGIN_CRITICAL_SECTION (dict );
0 commit comments