@@ -115,19 +115,20 @@ As a consequence of this, split keys have a maximum size of 16.
115115#define PyDict_MINSIZE 8
116116
117117#include "Python.h"
118- #include "pycore_bitutils.h" // _Py_bit_length
119- #include "pycore_call.h" // _PyObject_CallNoArgs()
120- #include "pycore_ceval.h" // _PyEval_GetBuiltin()
121- #include "pycore_code.h" // stats
122- #include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION, Py_END_CRITICAL_SECTION
123- #include "pycore_dict.h" // export _PyDict_SizeOf()
124- #include "pycore_freelist.h" // _PyFreeListState_GET()
125- #include "pycore_gc.h" // _PyObject_GC_IS_TRACKED()
126- #include "pycore_object.h" // _PyObject_GC_TRACK(), _PyDebugAllocatorStats()
127- #include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
128- #include "pycore_pystate.h" // _PyThreadState_GET()
129- #include "pycore_setobject.h" // _PySet_NextEntry()
130- #include "stringlib/eq.h" // unicode_eq()
118+ #include "pycore_bitutils.h" // _Py_bit_length
119+ #include "pycore_call.h" // _PyObject_CallNoArgs()
120+ #include "pycore_ceval.h" // _PyEval_GetBuiltin()
121+ #include "pycore_code.h" // stats
122+ #include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION, Py_END_CRITICAL_SECTION
123+ #include "pycore_dict.h" // export _PyDict_SizeOf()
124+ #include "pycore_freelist.h" // _PyFreeListState_GET()
125+ #include "pycore_gc.h" // _PyObject_GC_IS_TRACKED()
126+ #include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_STORE_PTR_RELAXED
127+ #include "pycore_object.h" // _PyObject_GC_TRACK(), _PyDebugAllocatorStats()
128+ #include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
129+ #include "pycore_pystate.h" // _PyThreadState_GET()
130+ #include "pycore_setobject.h" // _PySet_NextEntry()
131+ #include "stringlib/eq.h" // unicode_eq
131132
132133#include <stdbool.h>
133134
@@ -234,6 +235,14 @@ set_values(PyDictObject *mp, PyDictValues *values)
234235
235236#endif
236237
238+ #define STORE_KEY (ep , key ) FT_ATOMIC_STORE_PTR_RELAXED(ep->me_key, key)
239+ #define STORE_VALUE (ep , value ) FT_ATOMIC_STORE_PTR_RELAXED(ep->me_value, value)
240+ #define STORE_SPLIT_VALUE (mp , idx , value ) FT_ATOMIC_STORE_PTR_RELAXED(mp->ma_values->values[idx], value)
241+ #define STORE_HASH (ep , hash ) FT_ATOMIC_STORE_SSIZE_RELAXED(ep->me_hash, hash)
242+ #define STORE_KEYS_USABLE (keys , usable ) FT_ATOMIC_STORE_SSIZE_RELAXED(keys->dk_usable, usable)
243+ #define STORE_KEYS_NENTRIES (keys , nentries ) FT_ATOMIC_STORE_SSIZE_RELAXED(keys->dk_nentries, nentries)
244+ #define STORE_USED (mp , used ) FT_ATOMIC_STORE_SSIZE_RELAXED(mp->ma_used, used)
245+
237246#define PERTURB_SHIFT 5
238247
239248/*
@@ -1605,7 +1614,6 @@ insert_into_splitdictkeys(PyDictKeysObject *keys, PyObject *name)
16051614 return ix ;
16061615}
16071616
1608-
16091617static inline int
16101618insert_combined_dict (PyInterpreterState * interp , PyDictObject * mp ,
16111619 Py_hash_t hash , PyObject * key , PyObject * value )
@@ -1623,18 +1631,18 @@ insert_combined_dict(PyInterpreterState *interp, PyDictObject *mp,
16231631 if (DK_IS_UNICODE (mp -> ma_keys )) {
16241632 PyDictUnicodeEntry * ep ;
16251633 ep = & DK_UNICODE_ENTRIES (mp -> ma_keys )[mp -> ma_keys -> dk_nentries ];
1626- ep -> me_key = key ;
1627- ep -> me_value = value ;
1634+ STORE_KEY ( ep , key ) ;
1635+ STORE_VALUE ( ep , value ) ;
16281636 }
16291637 else {
16301638 PyDictKeyEntry * ep ;
16311639 ep = & DK_ENTRIES (mp -> ma_keys )[mp -> ma_keys -> dk_nentries ];
1632- ep -> me_key = key ;
1633- ep -> me_hash = hash ;
1634- ep -> me_value = value ;
1640+ STORE_KEY ( ep , key ) ;
1641+ STORE_VALUE ( ep , value ) ;
1642+ STORE_HASH ( ep , hash ) ;
16351643 }
1636- mp -> ma_keys -> dk_usable -- ;
1637- mp -> ma_keys -> dk_nentries ++ ;
1644+ STORE_KEYS_USABLE ( mp -> ma_keys , mp -> ma_keys -> dk_usable - 1 ) ;
1645+ STORE_KEYS_NENTRIES ( mp -> ma_keys , mp -> ma_keys -> dk_nentries + 1 ) ;
16381646 assert (mp -> ma_keys -> dk_usable >= 0 );
16391647 return 0 ;
16401648}
@@ -1666,7 +1674,7 @@ insert_split_dict(PyInterpreterState *interp, PyDictObject *mp,
16661674 Py_ssize_t index = keys -> dk_nentries ;
16671675 _PyDictValues_AddToInsertionOrder (mp -> ma_values , index );
16681676 assert (mp -> ma_values -> values [index ] == NULL );
1669- mp -> ma_values -> values [ index ] = value ;
1677+ STORE_SPLIT_VALUE ( mp , index , value ) ;
16701678
16711679 split_keys_entry_added (keys );
16721680 assert (keys -> dk_usable >= 0 );
@@ -1997,8 +2005,8 @@ dictresize(PyInterpreterState *interp, PyDictObject *mp,
19972005 }
19982006 }
19992007
2000- mp -> ma_keys -> dk_usable -= numentries ;
2001- mp -> ma_keys -> dk_nentries = numentries ;
2008+ STORE_KEYS_USABLE ( mp -> ma_keys , mp -> ma_keys -> dk_usable - numentries ) ;
2009+ STORE_KEYS_NENTRIES ( mp -> ma_keys , numentries ) ;
20022010 ASSERT_CONSISTENT (mp );
20032011 return 0 ;
20042012}
@@ -2491,15 +2499,15 @@ delitem_common(PyDictObject *mp, Py_hash_t hash, Py_ssize_t ix,
24912499 if (DK_IS_UNICODE (mp -> ma_keys )) {
24922500 PyDictUnicodeEntry * ep = & DK_UNICODE_ENTRIES (mp -> ma_keys )[ix ];
24932501 old_key = ep -> me_key ;
2494- ep -> me_key = NULL ;
2495- ep -> me_value = NULL ;
2502+ STORE_KEY ( ep , NULL ) ;
2503+ STORE_VALUE ( ep , NULL ) ;
24962504 }
24972505 else {
24982506 PyDictKeyEntry * ep = & DK_ENTRIES (mp -> ma_keys )[ix ];
24992507 old_key = ep -> me_key ;
2500- ep -> me_key = NULL ;
2501- ep -> me_value = NULL ;
2502- ep -> me_hash = 0 ;
2508+ STORE_KEY ( ep , NULL ) ;
2509+ STORE_VALUE ( ep , NULL ) ;
2510+ STORE_HASH ( ep , 0 ) ;
25032511 }
25042512 Py_DECREF (old_key );
25052513 }
@@ -4377,8 +4385,8 @@ dict_popitem_impl(PyDictObject *self)
43774385 PyTuple_SET_ITEM (res , 0 , key );
43784386 PyTuple_SET_ITEM (res , 1 , value );
43794387 /* We can't dk_usable++ since there is DKIX_DUMMY in indices */
4380- self -> ma_keys -> dk_nentries = i ;
4381- self -> ma_used -- ;
4388+ STORE_KEYS_NENTRIES ( self -> ma_keys , i ) ;
4389+ STORE_USED ( self , self -> ma_used - 1 ) ;
43824390 self -> ma_version_tag = new_version ;
43834391 ASSERT_CONSISTENT (self );
43844392 return res ;
0 commit comments