gh-112075: Avoid locking shared keys on every assignment (#116087) · python/cpython@556749c

@@ -1597,19 +1597,11 @@ insertion_resize(PyInterpreterState *interp, PyDictObject *mp, int unicode)

15971597

}

1598159815991599

static Py_ssize_t

1600-

insert_into_splitdictkeys(PyDictKeysObject *keys, PyObject *name)

1600+

insert_into_splitdictkeys(PyDictKeysObject *keys, PyObject *name, Py_hash_t hash)

16011601

{

16021602

assert(PyUnicode_CheckExact(name));

16031603

ASSERT_KEYS_LOCKED(keys);

160416041605-

Py_hash_t hash = unicode_get_hash(name);

1606-

if (hash == -1) {

1607-

hash = PyUnicode_Type.tp_hash(name);

1608-

if (hash == -1) {

1609-

PyErr_Clear();

1610-

return DKIX_EMPTY;

1611-

}

1612-

}

16131605

Py_ssize_t ix = unicodekeys_lookup_unicode(keys, name, hash);

16141606

if (ix == DKIX_EMPTY) {

16151607

if (keys->dk_usable <= 0) {

@@ -6692,8 +6684,25 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,

66926684

assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT);

66936685

Py_ssize_t ix = DKIX_EMPTY;

66946686

if (PyUnicode_CheckExact(name)) {

6695-

LOCK_KEYS(keys);

6696-

ix = insert_into_splitdictkeys(keys, name);

6687+

Py_hash_t hash = unicode_get_hash(name);

6688+

if (hash == -1) {

6689+

hash = PyUnicode_Type.tp_hash(name);

6690+

assert(hash != -1);

6691+

}

6692+6693+

#ifdef Py_GIL_DISABLED

6694+

// Try a thread-safe lookup to see if the index is already allocated

6695+

ix = unicodekeys_lookup_unicode_threadsafe(keys, name, hash);

6696+

if (ix == DKIX_EMPTY) {

6697+

// Lock keys and do insert

6698+

LOCK_KEYS(keys);

6699+

ix = insert_into_splitdictkeys(keys, name, hash);

6700+

UNLOCK_KEYS(keys);

6701+

}

6702+

#else

6703+

ix = insert_into_splitdictkeys(keys, name, hash);

6704+

#endif

6705+66976706

#ifdef Py_STATS

66986707

if (ix == DKIX_EMPTY) {

66996708

if (PyUnicode_CheckExact(name)) {

@@ -6709,7 +6718,6 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,

67096718

}

67106719

}

67116720

#endif

6712-

UNLOCK_KEYS(keys);

67136721

}

67146722

if (ix == DKIX_EMPTY) {

67156723

PyObject *dict = make_dict_from_instance_attributes(