@@ -517,27 +517,16 @@ _PyDict_MaybeUntrack(PyObject *op)
517517 _PyObject_GC_UNTRACK (op );
518518}
519519
520-
521520/*
522- Internal routine to insert a new item into the table.
523- Used both by the internal resize routine and by the public insert routine.
524- Eats a reference to key and one to value.
525- Returns -1 if an error occurred, or 0 on success.
521+ Internal routine to insert a new item into the table when you have entry object.
522+ Used by insertdict.
526523*/
527524static int
528- insertdict (register PyDictObject * mp , PyObject * key , Py_hash_t hash , PyObject * value )
525+ insertdict_by_entry (register PyDictObject * mp , PyObject * key , Py_hash_t hash ,
526+ PyDictEntry * ep , PyObject * value )
529527{
530528 PyObject * old_value ;
531- register PyDictEntry * ep ;
532- typedef PyDictEntry * (* lookupfunc )(PyDictObject * , PyObject * , Py_hash_t );
533529
534- assert (mp -> ma_lookup != NULL );
535- ep = mp -> ma_lookup (mp , key , hash );
536- if (ep == NULL ) {
537- Py_DECREF (key );
538- Py_DECREF (value );
539- return -1 ;
540- }
541530 MAINTAIN_TRACKING (mp , key , value );
542531 if (ep -> me_value != NULL ) {
543532 old_value = ep -> me_value ;
@@ -560,6 +549,28 @@ insertdict(register PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *v
560549 return 0 ;
561550}
562551
552+
553+ /*
554+ Internal routine to insert a new item into the table.
555+ Used both by the internal resize routine and by the public insert routine.
556+ Eats a reference to key and one to value.
557+ Returns -1 if an error occurred, or 0 on success.
558+ */
559+ static int
560+ insertdict (register PyDictObject * mp , PyObject * key , Py_hash_t hash , PyObject * value )
561+ {
562+ register PyDictEntry * ep ;
563+
564+ assert (mp -> ma_lookup != NULL );
565+ ep = mp -> ma_lookup (mp , key , hash );
566+ if (ep == NULL ) {
567+ Py_DECREF (key );
568+ Py_DECREF (value );
569+ return -1 ;
570+ }
571+ return insertdict_by_entry (mp , key , hash , ep , value );
572+ }
573+
563574/*
564575Internal routine used by dictresize() to insert an item which is
565576known to be absent from the dict. This routine also assumes that
@@ -783,39 +794,26 @@ PyDict_GetItemWithError(PyObject *op, PyObject *key)
783794 return ep -> me_value ;
784795}
785796
786- /* CAUTION: PyDict_SetItem() must guarantee that it won't resize the
787- * dictionary if it's merely replacing the value for an existing key.
788- * This means that it's safe to loop over a dictionary with PyDict_Next()
789- * and occasionally replace a value -- but you can't insert new keys or
790- * remove them.
791- */
792- int
793- PyDict_SetItem (register PyObject * op , PyObject * key , PyObject * value )
797+ static int
798+ dict_set_item_by_hash_or_entry (register PyObject * op , PyObject * key ,
799+ Py_hash_t hash , PyDictEntry * ep , PyObject * value )
794800{
795801 register PyDictObject * mp ;
796- register Py_hash_t hash ;
797802 register Py_ssize_t n_used ;
798803
799- if (!PyDict_Check (op )) {
800- PyErr_BadInternalCall ();
801- return -1 ;
802- }
803- assert (key );
804- assert (value );
805804 mp = (PyDictObject * )op ;
806- if (!PyUnicode_CheckExact (key ) ||
807- (hash = ((PyASCIIObject * ) key )-> hash ) == -1 )
808- {
809- hash = PyObject_Hash (key );
810- if (hash == -1 )
811- return -1 ;
812- }
813805 assert (mp -> ma_fill <= mp -> ma_mask ); /* at least one empty slot */
814806 n_used = mp -> ma_used ;
815807 Py_INCREF (value );
816808 Py_INCREF (key );
817- if (insertdict (mp , key , hash , value ) != 0 )
818- return -1 ;
809+ if (ep == NULL ) {
810+ if (insertdict (mp , key , hash , value ) != 0 )
811+ return -1 ;
812+ }
813+ else {
814+ if (insertdict_by_entry (mp , key , hash , ep , value ) != 0 )
815+ return -1 ;
816+ }
819817 /* If we added a key, we can safely resize. Otherwise just return!
820818 * If fill >= 2/3 size, adjust size. Normally, this doubles or
821819 * quaduples the size, but it's also possible for the dict to shrink
@@ -835,6 +833,36 @@ PyDict_SetItem(register PyObject *op, PyObject *key, PyObject *value)
835833 return dictresize (mp , (mp -> ma_used > 50000 ? 2 : 4 ) * mp -> ma_used );
836834}
837835
836+ /* CAUTION: PyDict_SetItem() must guarantee that it won't resize the
837+ * dictionary if it's merely replacing the value for an existing key.
838+ * This means that it's safe to loop over a dictionary with PyDict_Next()
839+ * and occasionally replace a value -- but you can't insert new keys or
840+ * remove them.
841+ */
842+ int
843+ PyDict_SetItem (register PyObject * op , PyObject * key , PyObject * value )
844+ {
845+ register Py_hash_t hash ;
846+
847+ if (!PyDict_Check (op )) {
848+ PyErr_BadInternalCall ();
849+ return -1 ;
850+ }
851+ assert (key );
852+ assert (value );
853+ if (PyUnicode_CheckExact (key )) {
854+ hash = ((PyASCIIObject * ) key )-> hash ;
855+ if (hash == -1 )
856+ hash = PyObject_Hash (key );
857+ }
858+ else {
859+ hash = PyObject_Hash (key );
860+ if (hash == -1 )
861+ return -1 ;
862+ }
863+ return dict_set_item_by_hash_or_entry (op , key , hash , NULL , value );
864+ }
865+
838866int
839867PyDict_DelItem (PyObject * op , PyObject * key )
840868{
@@ -1803,9 +1831,9 @@ dict_setdefault(register PyDictObject *mp, PyObject *args)
18031831 return NULL ;
18041832 val = ep -> me_value ;
18051833 if (val == NULL ) {
1806- val = failobj ;
1807- if ( PyDict_SetItem (( PyObject * ) mp , key , failobj ))
1808- val = NULL ;
1834+ if ( dict_set_item_by_hash_or_entry (( PyObject * ) mp , key , hash , ep ,
1835+ failobj ) == 0 )
1836+ val = failobj ;
18091837 }
18101838 Py_XINCREF (val );
18111839 return val ;
0 commit comments