@@ -985,8 +985,10 @@ make_keys_shared(PyObject *op)
985985 return NULL ;
986986 }
987987 else if (mp -> ma_keys -> dk_lookup == lookdict_unicode ) {
988- /* Remove dummy keys */
989- if (dictresize (mp , DK_SIZE (mp -> ma_keys )))
988+ /* Remove dummy keys
989+ * -1 is required since dictresize() uses key size > minused
990+ */
991+ if (dictresize (mp , DK_SIZE (mp -> ma_keys ) - 1 ))
990992 return NULL ;
991993 }
992994 assert (mp -> ma_keys -> dk_lookup == lookdict_unicode_nodummy );
@@ -2473,7 +2475,8 @@ dict_popitem(PyDictObject *mp)
24732475 }
24742476 /* Convert split table to combined table */
24752477 if (mp -> ma_keys -> dk_lookup == lookdict_split ) {
2476- if (dictresize (mp , DK_SIZE (mp -> ma_keys ))) {
2478+ /* -1 is required since dictresize() uses key size > minused */
2479+ if (dictresize (mp , DK_SIZE (mp -> ma_keys ) - 1 )) {
24772480 Py_DECREF (res );
24782481 return NULL ;
24792482 }
@@ -3848,10 +3851,16 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
38483851 CACHED_KEYS (tp ) = NULL ;
38493852 DK_DECREF (cached );
38503853 }
3851- } else {
3854+ }
3855+ else {
3856+ int was_shared = cached == ((PyDictObject * )dict )-> ma_keys ;
38523857 res = PyDict_SetItem (dict , key , value );
3853- if (cached != ((PyDictObject * )dict )-> ma_keys ) {
3854- /* Either update tp->ht_cached_keys or delete it */
3858+ /* PyDict_SetItem() may call dictresize() and convert split table
3859+ * into combined table. In such case, convert it to split
3860+ * table again and update type's shared key only when this is
3861+ * the only dict sharing key with the type.
3862+ */
3863+ if (was_shared && cached != ((PyDictObject * )dict )-> ma_keys ) {
38553864 if (cached -> dk_refcnt == 1 ) {
38563865 CACHED_KEYS (tp ) = make_keys_shared (dict );
38573866 } else {
0 commit comments