@@ -924,16 +924,15 @@ new_dict(PyInterpreterState *interp,
924
924
return (PyObject * )mp ;
925
925
}
926
926
927
- /* Consumes a reference to the keys object */
928
927
static PyObject *
929
928
new_dict_with_shared_keys (PyInterpreterState * interp , PyDictKeysObject * keys )
930
929
{
931
930
size_t size = shared_keys_usable_size (keys );
932
931
PyDictValues * values = new_values (size );
933
932
if (values == NULL ) {
934
- dictkeys_decref (interp , keys , false);
935
933
return PyErr_NoMemory ();
936
934
}
935
+ dictkeys_incref (keys );
937
936
for (size_t i = 0 ; i < size ; i ++ ) {
938
937
values -> values [i ] = NULL ;
939
938
}
@@ -6693,8 +6692,6 @@ materialize_managed_dict_lock_held(PyObject *obj)
6693
6692
{
6694
6693
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED (obj );
6695
6694
6696
- OBJECT_STAT_INC (dict_materialized_on_request );
6697
-
6698
6695
PyDictValues * values = _PyObject_InlineValues (obj );
6699
6696
PyInterpreterState * interp = _PyInterpreterState_GET ();
6700
6697
PyDictKeysObject * keys = CACHED_KEYS (Py_TYPE (obj ));
@@ -7186,35 +7183,77 @@ _PyDict_DetachFromObject(PyDictObject *mp, PyObject *obj)
7186
7183
return 0 ;
7187
7184
}
7188
7185
7189
- PyObject *
7190
- PyObject_GenericGetDict (PyObject * obj , void * context )
7186
+ static inline PyObject *
7187
+ ensure_managed_dict (PyObject * obj )
7191
7188
{
7192
- PyInterpreterState * interp = _PyInterpreterState_GET ();
7193
- PyTypeObject * tp = Py_TYPE (obj );
7194
- PyDictObject * dict ;
7195
- if (_PyType_HasFeature (tp , Py_TPFLAGS_MANAGED_DICT )) {
7196
- dict = _PyObject_GetManagedDict (obj );
7197
- if (dict == NULL &&
7198
- (tp -> tp_flags & Py_TPFLAGS_INLINE_VALUES ) &&
7189
+ PyDictObject * dict = _PyObject_GetManagedDict (obj );
7190
+ if (dict == NULL ) {
7191
+ PyTypeObject * tp = Py_TYPE (obj );
7192
+ if ((tp -> tp_flags & Py_TPFLAGS_INLINE_VALUES ) &&
7199
7193
FT_ATOMIC_LOAD_UINT8 (_PyObject_InlineValues (obj )-> valid )) {
7200
7194
dict = _PyObject_MaterializeManagedDict (obj );
7201
7195
}
7202
- else if (dict == NULL ) {
7203
- Py_BEGIN_CRITICAL_SECTION (obj );
7204
-
7196
+ else {
7197
+ #ifdef Py_GIL_DISABLED
7205
7198
// Check again that we're not racing with someone else creating the dict
7199
+ Py_BEGIN_CRITICAL_SECTION (obj );
7206
7200
dict = _PyObject_GetManagedDict (obj );
7207
- if (dict == NULL ) {
7208
- OBJECT_STAT_INC (dict_materialized_on_request );
7209
- dictkeys_incref (CACHED_KEYS (tp ));
7210
- dict = (PyDictObject * )new_dict_with_shared_keys (interp , CACHED_KEYS (tp ));
7211
- FT_ATOMIC_STORE_PTR_RELEASE (_PyObject_ManagedDictPointer (obj )-> dict ,
7212
- (PyDictObject * )dict );
7201
+ if (dict != NULL ) {
7202
+ goto done ;
7213
7203
}
7204
+ #endif
7205
+ dict = (PyDictObject * )new_dict_with_shared_keys (_PyInterpreterState_GET (),
7206
+ CACHED_KEYS (tp ));
7207
+ FT_ATOMIC_STORE_PTR_RELEASE (_PyObject_ManagedDictPointer (obj )-> dict ,
7208
+ (PyDictObject * )dict );
7214
7209
7210
+ #ifdef Py_GIL_DISABLED
7211
+ done :
7215
7212
Py_END_CRITICAL_SECTION ();
7213
+ #endif
7216
7214
}
7217
- return Py_XNewRef ((PyObject * )dict );
7215
+ }
7216
+ return (PyObject * )dict ;
7217
+ }
7218
+
7219
+ static inline PyObject *
7220
+ ensure_nonmanaged_dict (PyObject * obj , PyObject * * dictptr )
7221
+ {
7222
+ PyDictKeysObject * cached ;
7223
+
7224
+ PyObject * dict = FT_ATOMIC_LOAD_PTR_ACQUIRE (* dictptr );
7225
+ if (dict == NULL ) {
7226
+ #ifdef Py_GIL_DISABLED
7227
+ Py_BEGIN_CRITICAL_SECTION (obj );
7228
+ dict = * dictptr ;
7229
+ if (dict != NULL ) {
7230
+ goto done ;
7231
+ }
7232
+ #endif
7233
+ PyTypeObject * tp = Py_TYPE (obj );
7234
+ if (_PyType_HasFeature (tp , Py_TPFLAGS_HEAPTYPE ) && (cached = CACHED_KEYS (tp ))) {
7235
+ PyInterpreterState * interp = _PyInterpreterState_GET ();
7236
+ assert (!_PyType_HasFeature (tp , Py_TPFLAGS_INLINE_VALUES ));
7237
+ dict = new_dict_with_shared_keys (interp , cached );
7238
+ }
7239
+ else {
7240
+ dict = PyDict_New ();
7241
+ }
7242
+ FT_ATOMIC_STORE_PTR_RELEASE (* dictptr , dict );
7243
+ #ifdef Py_GIL_DISABLED
7244
+ done :
7245
+ Py_END_CRITICAL_SECTION ();
7246
+ #endif
7247
+ }
7248
+ return dict ;
7249
+ }
7250
+
7251
+ PyObject *
7252
+ PyObject_GenericGetDict (PyObject * obj , void * context )
7253
+ {
7254
+ PyTypeObject * tp = Py_TYPE (obj );
7255
+ if (_PyType_HasFeature (tp , Py_TPFLAGS_MANAGED_DICT )) {
7256
+ return Py_XNewRef (ensure_managed_dict (obj ));
7218
7257
}
7219
7258
else {
7220
7259
PyObject * * dictptr = _PyObject_ComputedDictPointer (obj );
@@ -7223,65 +7262,28 @@ PyObject_GenericGetDict(PyObject *obj, void *context)
7223
7262
"This object has no __dict__" );
7224
7263
return NULL ;
7225
7264
}
7226
- PyObject * dict = * dictptr ;
7227
- if (dict == NULL ) {
7228
- PyTypeObject * tp = Py_TYPE (obj );
7229
- if (_PyType_HasFeature (tp , Py_TPFLAGS_HEAPTYPE ) && CACHED_KEYS (tp )) {
7230
- dictkeys_incref (CACHED_KEYS (tp ));
7231
- * dictptr = dict = new_dict_with_shared_keys (
7232
- interp , CACHED_KEYS (tp ));
7233
- }
7234
- else {
7235
- * dictptr = dict = PyDict_New ();
7236
- }
7237
- }
7238
- return Py_XNewRef (dict );
7265
+
7266
+ return Py_XNewRef (ensure_nonmanaged_dict (obj , dictptr ));
7239
7267
}
7240
7268
}
7241
7269
7242
7270
int
7243
- _PyObjectDict_SetItem (PyTypeObject * tp , PyObject * * dictptr ,
7271
+ _PyObjectDict_SetItem (PyTypeObject * tp , PyObject * obj , PyObject * * dictptr ,
7244
7272
PyObject * key , PyObject * value )
7245
7273
{
7246
7274
PyObject * dict ;
7247
7275
int res ;
7248
- PyDictKeysObject * cached ;
7249
- PyInterpreterState * interp = _PyInterpreterState_GET ();
7250
7276
7251
7277
assert (dictptr != NULL );
7252
- if ((tp -> tp_flags & Py_TPFLAGS_HEAPTYPE ) && (cached = CACHED_KEYS (tp ))) {
7253
- assert (dictptr != NULL );
7254
- dict = * dictptr ;
7255
- if (dict == NULL ) {
7256
- assert (!_PyType_HasFeature (tp , Py_TPFLAGS_INLINE_VALUES ));
7257
- dictkeys_incref (cached );
7258
- dict = new_dict_with_shared_keys (interp , cached );
7259
- if (dict == NULL )
7260
- return -1 ;
7261
- * dictptr = dict ;
7262
- }
7263
- if (value == NULL ) {
7264
- res = PyDict_DelItem (dict , key );
7265
- }
7266
- else {
7267
- res = PyDict_SetItem (dict , key , value );
7268
- }
7269
- } else {
7270
- dict = * dictptr ;
7271
- if (dict == NULL ) {
7272
- dict = PyDict_New ();
7273
- if (dict == NULL )
7274
- return -1 ;
7275
- * dictptr = dict ;
7276
- }
7277
- if (value == NULL ) {
7278
- res = PyDict_DelItem (dict , key );
7279
- } else {
7280
- res = PyDict_SetItem (dict , key , value );
7281
- }
7278
+ dict = ensure_nonmanaged_dict (obj , dictptr );
7279
+ if (dict == NULL ) {
7280
+ return -1 ;
7282
7281
}
7283
7282
7283
+ Py_BEGIN_CRITICAL_SECTION (dict );
7284
+ res = _PyDict_SetItem_LockHeld ((PyDictObject * )dict , key , value );
7284
7285
ASSERT_CONSISTENT (dict );
7286
+ Py_END_CRITICAL_SECTION ();
7285
7287
return res ;
7286
7288
}
7287
7289
0 commit comments