@@ -619,30 +619,18 @@ int
619619_PyGen_SetStopIterationValue (PyObject * value )
620620{
621621 assert (!PyErr_Occurred ());
622- PyObject * e ;
623-
624- if (value == NULL ||
625- (!PyTuple_Check (value ) && !PyExceptionInstance_Check (value )))
626- {
627- /* Delay exception instantiation if we can */
628- PyErr_SetObject (PyExc_StopIteration , value );
629- return 0 ;
630- }
631- /* Construct an exception instance manually with
632- * PyObject_CallOneArg and pass it to PyErr_SetObject.
633- *
634- * We do this to handle a situation when "value" is a tuple, in which
635- * case PyErr_SetObject would set the value of StopIteration to
636- * the first element of the tuple.
637- *
638- * (See PyErr_SetObject/_PyErr_CreateException code for details.)
639- */
640- e = PyObject_CallOneArg (PyExc_StopIteration , value );
641- if (e == NULL ) {
622+ // Construct an exception instance manually with PyObject_CallOneArg()
623+ // but use PyErr_SetRaisedException() instead of PyErr_SetObject() as
624+ // PyErr_SetObject(exc_type, value) has a fast path when 'value'
625+ // is a tuple, where the value of the StopIteration exception would be
626+ // set to 'value[0]' instead of 'value'.
627+ PyObject * exc = value == NULL
628+ ? PyObject_CallNoArgs (PyExc_StopIteration )
629+ : PyObject_CallOneArg (PyExc_StopIteration , value );
630+ if (exc == NULL ) {
642631 return -1 ;
643632 }
644- PyErr_SetObject (PyExc_StopIteration , e );
645- Py_DECREF (e );
633+ PyErr_SetRaisedException (exc /* stolen */ );
646634 return 0 ;
647635}
648636
0 commit comments