@@ -152,6 +152,11 @@ show_counts(void)
152152 INIT_NONZERO_DICT_SLOTS(mp); \
153153 } while(0)
154154
155+ /* Dictionary reuse scheme to save calls to malloc, free, and memset */
156+ #define MAXFREEDICTS 80
157+ static PyDictObject * free_dicts [MAXFREEDICTS ];
158+ static int num_free_dicts = 0 ;
159+
155160PyObject *
156161PyDict_New (void )
157162{
@@ -164,10 +169,23 @@ PyDict_New(void)
164169 Py_AtExit (show_counts );
165170#endif
166171 }
167- mp = PyObject_GC_New (dictobject , & PyDict_Type );
168- if (mp == NULL )
169- return NULL ;
170- EMPTY_TO_MINSIZE (mp );
172+ if (num_free_dicts ) {
173+ mp = free_dicts [-- num_free_dicts ];
174+ assert (mp != NULL );
175+ assert (mp -> ob_type == & PyDict_Type );
176+ _Py_NewReference ((PyObject * )mp );
177+ if (mp -> ma_fill ) {
178+ EMPTY_TO_MINSIZE (mp );
179+ }
180+ assert (mp -> ma_used == 0 );
181+ assert (mp -> ma_table == mp -> ma_smalltable );
182+ assert (mp -> ma_mask == PyDict_MINSIZE - 1 );
183+ } else {
184+ mp = PyObject_GC_New (dictobject , & PyDict_Type );
185+ if (mp == NULL )
186+ return NULL ;
187+ EMPTY_TO_MINSIZE (mp );
188+ }
171189 mp -> ma_lookup = lookdict_string ;
172190#ifdef SHOW_CONVERSION_COUNTS
173191 ++ created ;
@@ -672,23 +690,25 @@ PyDict_Clear(PyObject *op)
672690int
673691PyDict_Next (PyObject * op , int * ppos , PyObject * * pkey , PyObject * * pvalue )
674692{
675- int i ;
676- register dictobject * mp ;
693+ register int i , mask ;
694+ register dictentry * ep ;
695+
677696 if (!PyDict_Check (op ))
678697 return 0 ;
679- mp = (dictobject * )op ;
680698 i = * ppos ;
681699 if (i < 0 )
682700 return 0 ;
683- while (i <= mp -> ma_mask && mp -> ma_table [i ].me_value == NULL )
701+ ep = ((dictobject * )op )-> ma_table ;
702+ mask = ((dictobject * )op )-> ma_mask ;
703+ while (i <= mask && ep [i ].me_value == NULL )
684704 i ++ ;
685705 * ppos = i + 1 ;
686- if (i > mp -> ma_mask )
706+ if (i > mask )
687707 return 0 ;
688708 if (pkey )
689- * pkey = mp -> ma_table [i ].me_key ;
709+ * pkey = ep [i ].me_key ;
690710 if (pvalue )
691- * pvalue = mp -> ma_table [i ].me_value ;
711+ * pvalue = ep [i ].me_value ;
692712 return 1 ;
693713}
694714
@@ -710,7 +730,10 @@ dict_dealloc(register dictobject *mp)
710730 }
711731 if (mp -> ma_table != mp -> ma_smalltable )
712732 PyMem_DEL (mp -> ma_table );
713- mp -> ob_type -> tp_free ((PyObject * )mp );
733+ if (num_free_dicts < MAXFREEDICTS && mp -> ob_type == & PyDict_Type )
734+ free_dicts [num_free_dicts ++ ] = mp ;
735+ else
736+ mp -> ob_type -> tp_free ((PyObject * )mp );
714737 Py_TRASHCAN_SAFE_END (mp )
715738}
716739
@@ -882,7 +905,9 @@ static PyObject *
882905dict_keys (register dictobject * mp )
883906{
884907 register PyObject * v ;
885- register int i , j , n ;
908+ register int i , j ;
909+ dictentry * ep ;
910+ int mask , n ;
886911
887912 again :
888913 n = mp -> ma_used ;
@@ -896,22 +921,27 @@ dict_keys(register dictobject *mp)
896921 Py_DECREF (v );
897922 goto again ;
898923 }
899- for (i = 0 , j = 0 ; i <= mp -> ma_mask ; i ++ ) {
900- if (mp -> ma_table [i ].me_value != NULL ) {
901- PyObject * key = mp -> ma_table [i ].me_key ;
924+ ep = mp -> ma_table ;
925+ mask = mp -> ma_mask ;
926+ for (i = 0 , j = 0 ; i <= mask ; i ++ ) {
927+ if (ep [i ].me_value != NULL ) {
928+ PyObject * key = ep [i ].me_key ;
902929 Py_INCREF (key );
903930 PyList_SET_ITEM (v , j , key );
904931 j ++ ;
905932 }
906933 }
934+ assert (j == n );
907935 return v ;
908936}
909937
910938static PyObject *
911939dict_values (register dictobject * mp )
912940{
913941 register PyObject * v ;
914- register int i , j , n ;
942+ register int i , j ;
943+ dictentry * ep ;
944+ int mask , n ;
915945
916946 again :
917947 n = mp -> ma_used ;
@@ -925,14 +955,17 @@ dict_values(register dictobject *mp)
925955 Py_DECREF (v );
926956 goto again ;
927957 }
928- for (i = 0 , j = 0 ; i <= mp -> ma_mask ; i ++ ) {
929- if (mp -> ma_table [i ].me_value != NULL ) {
930- PyObject * value = mp -> ma_table [i ].me_value ;
958+ ep = mp -> ma_table ;
959+ mask = mp -> ma_mask ;
960+ for (i = 0 , j = 0 ; i <= mask ; i ++ ) {
961+ if (ep [i ].me_value != NULL ) {
962+ PyObject * value = ep [i ].me_value ;
931963 Py_INCREF (value );
932964 PyList_SET_ITEM (v , j , value );
933965 j ++ ;
934966 }
935967 }
968+ assert (j == n );
936969 return v ;
937970}
938971
@@ -941,7 +974,9 @@ dict_items(register dictobject *mp)
941974{
942975 register PyObject * v ;
943976 register int i , j , n ;
977+ int mask ;
944978 PyObject * item , * key , * value ;
979+ dictentry * ep ;
945980
946981 /* Preallocate the list of tuples, to avoid allocations during
947982 * the loop over the items, which could trigger GC, which
@@ -968,10 +1003,12 @@ dict_items(register dictobject *mp)
9681003 goto again ;
9691004 }
9701005 /* Nothing we do below makes any function calls. */
971- for (i = 0 , j = 0 ; i <= mp -> ma_mask ; i ++ ) {
972- if (mp -> ma_table [i ].me_value != NULL ) {
973- key = mp -> ma_table [i ].me_key ;
974- value = mp -> ma_table [i ].me_value ;
1006+ ep = mp -> ma_table ;
1007+ mask = mp -> ma_mask ;
1008+ for (i = 0 , j = 0 ; i <= mask ; i ++ ) {
1009+ if (ep [i ].me_value != NULL ) {
1010+ key = ep [i ].me_key ;
1011+ value = ep [i ].me_value ;
9751012 item = PyList_GET_ITEM (v , j );
9761013 Py_INCREF (key );
9771014 PyTuple_SET_ITEM (item , 0 , key );
0 commit comments