@@ -1102,6 +1102,41 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
11021102 return -1 ;
11031103}
11041104
1105+ // Same to insertdict but specialized for ma_keys = Py_EMPTY_KEYS.
1106+ static int
1107+ insert_to_emptydict (PyDictObject * mp , PyObject * key , Py_hash_t hash ,
1108+ PyObject * value )
1109+ {
1110+ assert (mp -> ma_keys == Py_EMPTY_KEYS );
1111+
1112+ PyDictKeysObject * newkeys = new_keys_object (PyDict_MINSIZE );
1113+ if (newkeys == NULL ) {
1114+ return -1 ;
1115+ }
1116+ if (!PyUnicode_CheckExact (key )) {
1117+ newkeys -> dk_lookup = lookdict ;
1118+ }
1119+ dictkeys_decref (Py_EMPTY_KEYS );
1120+ mp -> ma_keys = newkeys ;
1121+ mp -> ma_values = NULL ;
1122+
1123+ Py_INCREF (key );
1124+ Py_INCREF (value );
1125+ MAINTAIN_TRACKING (mp , key , value );
1126+
1127+ size_t hashpos = (size_t )hash & (PyDict_MINSIZE - 1 );
1128+ PyDictKeyEntry * ep = & DK_ENTRIES (mp -> ma_keys )[0 ];
1129+ dictkeys_set_index (mp -> ma_keys , hashpos , 0 );
1130+ ep -> me_key = key ;
1131+ ep -> me_hash = hash ;
1132+ ep -> me_value = value ;
1133+ mp -> ma_used ++ ;
1134+ mp -> ma_version_tag = DICT_NEXT_VERSION ();
1135+ mp -> ma_keys -> dk_usable -- ;
1136+ mp -> ma_keys -> dk_nentries ++ ;
1137+ return 0 ;
1138+ }
1139+
11051140/*
11061141Internal routine used by dictresize() to build a hashtable of entries.
11071142*/
@@ -1274,7 +1309,7 @@ _PyDict_NewPresized(Py_ssize_t minused)
12741309 Py_ssize_t newsize ;
12751310 PyDictKeysObject * new_keys ;
12761311
1277- if (minused == 0 ) {
1312+ if (minused <= USABLE_FRACTION ( PyDict_MINSIZE ) ) {
12781313 return PyDict_New ();
12791314 }
12801315 /* There are no strict guarantee that returned dict can contain minused
@@ -1286,7 +1321,7 @@ _PyDict_NewPresized(Py_ssize_t minused)
12861321 }
12871322 else {
12881323 Py_ssize_t minsize = ESTIMATE_SIZE (minused );
1289- newsize = PyDict_MINSIZE ;
1324+ newsize = PyDict_MINSIZE * 2 ;
12901325 while (newsize < minsize ) {
12911326 newsize <<= 1 ;
12921327 }
@@ -1495,6 +1530,9 @@ PyDict_SetItem(PyObject *op, PyObject *key, PyObject *value)
14951530 return -1 ;
14961531 }
14971532
1533+ if (mp -> ma_keys == Py_EMPTY_KEYS ) {
1534+ return insert_to_emptydict (mp , key , hash , value );
1535+ }
14981536 /* insertdict() handles any resizing that might be necessary */
14991537 return insertdict (mp , key , hash , value );
15001538}
@@ -1514,6 +1552,9 @@ _PyDict_SetItem_KnownHash(PyObject *op, PyObject *key, PyObject *value,
15141552 assert (hash != -1 );
15151553 mp = (PyDictObject * )op ;
15161554
1555+ if (mp -> ma_keys == Py_EMPTY_KEYS ) {
1556+ return insert_to_emptydict (mp , key , hash , value );
1557+ }
15171558 /* insertdict() handles any resizing that might be necessary */
15181559 return insertdict (mp , key , hash , value );
15191560}
@@ -2844,6 +2885,12 @@ PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
28442885 if (hash == -1 )
28452886 return NULL ;
28462887 }
2888+ if (mp -> ma_keys == Py_EMPTY_KEYS ) {
2889+ if (insert_to_emptydict (mp , key , hash , defaultobj ) < 0 ) {
2890+ return NULL ;
2891+ }
2892+ return defaultobj ;
2893+ }
28472894
28482895 if (mp -> ma_values != NULL && !PyUnicode_CheckExact (key )) {
28492896 if (insertion_resize (mp ) < 0 )
0 commit comments