@@ -605,30 +605,18 @@ int
605605_PyGen_SetStopIterationValue (PyObject * value )
606606{
607607 assert (!PyErr_Occurred ());
608- PyObject * e ;
609-
610- if (value == NULL ||
611- (!PyTuple_Check (value ) && !PyExceptionInstance_Check (value )))
612- {
613- /* Delay exception instantiation if we can */
614- PyErr_SetObject (PyExc_StopIteration , value );
615- return 0 ;
616- }
617- /* Construct an exception instance manually with
618- * PyObject_CallOneArg and pass it to PyErr_SetObject.
619- *
620- * We do this to handle a situation when "value" is a tuple, in which
621- * case PyErr_SetObject would set the value of StopIteration to
622- * the first element of the tuple.
623- *
624- * (See PyErr_SetObject/_PyErr_CreateException code for details.)
625- */
626- e = PyObject_CallOneArg (PyExc_StopIteration , value );
627- if (e == NULL ) {
608+ // Construct an exception instance manually with PyObject_CallOneArg()
609+ // but use PyErr_SetRaisedException() instead of PyErr_SetObject() as
610+ // PyErr_SetObject(exc_type, value) has a fast path when 'value'
611+ // is a tuple, where the value of the StopIteration exception would be
612+ // set to 'value[0]' instead of 'value'.
613+ PyObject * exc = value == NULL
614+ ? PyObject_CallNoArgs (PyExc_StopIteration )
615+ : PyObject_CallOneArg (PyExc_StopIteration , value );
616+ if (exc == NULL ) {
628617 return -1 ;
629618 }
630- PyErr_SetObject (PyExc_StopIteration , e );
631- Py_DECREF (e );
619+ PyErr_SetRaisedException (exc /* stolen */ );
632620 return 0 ;
633621}
634622
0 commit comments