@@ -139,6 +139,10 @@ lookdict(dictobject *mp, PyObject *key, register long hash)
139139 register unsigned int mask = mp -> ma_size - 1 ;
140140 dictentry * ep0 = mp -> ma_table ;
141141 register dictentry * ep ;
142+ register int restore_error = 0 ;
143+ register int checked_error = 0 ;
144+ register int cmp ;
145+ PyObject * err_type , * err_value , * err_tb ;
142146 /* We must come up with (i, incr) such that 0 <= i < ma_size
143147 and 0 < incr < ma_size and both are a function of hash */
144148 i = (~hash ) & mask ;
@@ -151,14 +155,25 @@ lookdict(dictobject *mp, PyObject *key, register long hash)
151155 if (ep -> me_key == dummy )
152156 freeslot = ep ;
153157 else {
154- if (ep -> me_hash == hash &&
155- PyObject_Compare (ep -> me_key , key ) == 0 )
156- {
157- return ep ;
158+ if (ep -> me_hash == hash ) {
159+ /* error can't have been checked yet */
160+ checked_error = 1 ;
161+ if (PyErr_Occurred ()) {
162+ restore_error = 1 ;
163+ PyErr_Fetch (& err_type , & err_value , & err_tb );
164+ }
165+ cmp = PyObject_Compare (ep -> me_key , key );
166+ if (PyErr_Occurred ())
167+ PyErr_Clear ();
168+ else if (cmp == 0 ) {
169+ if (restore_error )
170+ PyErr_Restore (err_type , err_value ,
171+ err_tb );
172+ return ep ;
173+ }
158174 }
159175 freeslot = NULL ;
160176 }
161- /* XXX What if PyObject_Compare returned an exception? */
162177 /* Derive incr from hash, just to make it more arbitrary. Note that
163178 incr must not be 0, or we will get into an infinite loop.*/
164179 incr = (hash ^ ((unsigned long )hash >> 3 )) & mask ;
@@ -167,6 +182,8 @@ lookdict(dictobject *mp, PyObject *key, register long hash)
167182 for (;;) {
168183 ep = & ep0 [(i + incr )& mask ];
169184 if (ep -> me_key == NULL ) {
185+ if (restore_error )
186+ PyErr_Restore (err_type , err_value , err_tb );
170187 if (freeslot != NULL )
171188 return freeslot ;
172189 else
@@ -176,12 +193,30 @@ lookdict(dictobject *mp, PyObject *key, register long hash)
176193 if (freeslot == NULL )
177194 freeslot = ep ;
178195 }
179- else if (ep -> me_key == key ||
180- ( ep -> me_hash == hash &&
181- PyObject_Compare ( ep -> me_key , key ) == 0 )) {
196+ else if (ep -> me_key == key ) {
197+ if ( restore_error )
198+ PyErr_Restore ( err_type , err_value , err_tb );
182199 return ep ;
200+ }
201+ else if (ep -> me_hash == hash ) {
202+ if (!checked_error ) {
203+ checked_error = 1 ;
204+ if (PyErr_Occurred ()) {
205+ restore_error = 1 ;
206+ PyErr_Fetch (& err_type , & err_value ,
207+ & err_tb );
208+ }
209+ }
210+ cmp = PyObject_Compare (ep -> me_key , key );
211+ if (PyErr_Occurred ())
212+ PyErr_Clear ();
213+ else if (cmp == 0 ) {
214+ if (restore_error )
215+ PyErr_Restore (err_type , err_value ,
216+ err_tb );
217+ return ep ;
218+ }
183219 }
184- /* XXX What if PyObject_Compare returned an exception? */
185220 /* Cycle through GF(2^n)-{0} */
186221 incr = incr << 1 ;
187222 if (incr > mask )
0 commit comments