LCOV - code coverage report
Current view: top level - Objects - genobject.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 703 819 85.8 %
Date: 2022-07-20 13:12:14 Functions: 71 78 91.0 %
Branches: 370 470 78.7 %

           Branch data     Line data    Source code
       1                 :            : /* Generator object implementation */
       2                 :            : 
       3                 :            : #define _PY_INTERPRETER
       4                 :            : 
       5                 :            : #include "Python.h"
       6                 :            : #include "pycore_call.h"          // _PyObject_CallNoArgs()
       7                 :            : #include "pycore_ceval.h"         // _PyEval_EvalFrame()
       8                 :            : #include "pycore_frame.h"         // _PyInterpreterFrame
       9                 :            : #include "pycore_genobject.h"     // struct _Py_async_gen_state
      10                 :            : #include "pycore_object.h"        // _PyObject_GC_UNTRACK()
      11                 :            : #include "pycore_opcode.h"        // _PyOpcode_Deopt
      12                 :            : #include "pycore_pyerrors.h"      // _PyErr_ClearExcState()
      13                 :            : #include "pycore_pystate.h"       // _PyThreadState_GET()
      14                 :            : #include "structmember.h"         // PyMemberDef
      15                 :            : #include "opcode.h"               // SEND
      16                 :            : #include "pystats.h"
      17                 :            : 
      18                 :            : static PyObject *gen_close(PyGenObject *, PyObject *);
      19                 :            : static PyObject *async_gen_asend_new(PyAsyncGenObject *, PyObject *);
      20                 :            : static PyObject *async_gen_athrow_new(PyAsyncGenObject *, PyObject *);
      21                 :            : 
      22                 :            : static const char *NON_INIT_CORO_MSG = "can't send non-None value to a "
      23                 :            :                                  "just-started coroutine";
      24                 :            : 
      25                 :            : static const char *ASYNC_GEN_IGNORED_EXIT_MSG =
      26                 :            :                                  "async generator ignored GeneratorExit";
      27                 :            : 
      28                 :            : static inline int
      29                 :     354063 : exc_state_traverse(_PyErr_StackItem *exc_state, visitproc visit, void *arg)
      30                 :            : {
      31   [ +  +  -  + ]:     354063 :     Py_VISIT(exc_state->exc_value);
      32                 :     354063 :     return 0;
      33                 :            : }
      34                 :            : 
      35                 :            : static int
      36                 :     354065 : gen_traverse(PyGenObject *gen, visitproc visit, void *arg)
      37                 :            : {
      38   [ +  -  +  + ]:     354065 :     Py_VISIT(gen->gi_code);
      39   [ +  -  -  + ]:     354064 :     Py_VISIT(gen->gi_name);
      40   [ +  -  -  + ]:     354064 :     Py_VISIT(gen->gi_qualname);
      41         [ +  + ]:     354064 :     if (gen->gi_frame_state < FRAME_CLEARED) {
      42                 :     350708 :         _PyInterpreterFrame *frame = (_PyInterpreterFrame *)(gen->gi_iframe);
      43                 :            :         assert(frame->frame_obj == NULL ||
      44                 :            :                frame->frame_obj->f_frame->owner == FRAME_OWNED_BY_GENERATOR);
      45                 :     350708 :         int err = _PyFrame_Traverse(frame, visit, arg);
      46         [ +  + ]:     350708 :         if (err) {
      47                 :          1 :             return err;
      48                 :            :         }
      49                 :            :     }
      50                 :            :     /* No need to visit cr_origin, because it's just tuples/str/int, so can't
      51                 :            :        participate in a reference cycle. */
      52                 :     354063 :     return exc_state_traverse(&gen->gi_exc_state, visit, arg);
      53                 :            : }
      54                 :            : 
      55                 :            : void
      56                 :   17063261 : _PyGen_Finalize(PyObject *self)
      57                 :            : {
      58                 :   17063261 :     PyGenObject *gen = (PyGenObject *)self;
      59                 :   17063261 :     PyObject *res = NULL;
      60                 :            :     PyObject *error_type, *error_value, *error_traceback;
      61                 :            : 
      62         [ +  + ]:   17063261 :     if (gen->gi_frame_state >= FRAME_COMPLETED) {
      63                 :            :         /* Generator isn't paused, so no need to close */
      64                 :   16468602 :         return;
      65                 :            :     }
      66                 :            : 
      67         [ +  + ]:     594669 :     if (PyAsyncGen_CheckExact(self)) {
      68                 :       5154 :         PyAsyncGenObject *agen = (PyAsyncGenObject*)self;
      69                 :       5154 :         PyObject *finalizer = agen->ag_origin_or_finalizer;
      70   [ +  +  +  + ]:       5154 :         if (finalizer && !agen->ag_closed) {
      71                 :            :             /* Save the current exception, if any. */
      72                 :         10 :             PyErr_Fetch(&error_type, &error_value, &error_traceback);
      73                 :            : 
      74                 :         10 :             res = PyObject_CallOneArg(finalizer, self);
      75                 :            : 
      76         [ -  + ]:         10 :             if (res == NULL) {
      77                 :          0 :                 PyErr_WriteUnraisable(self);
      78                 :            :             } else {
      79                 :         10 :                 Py_DECREF(res);
      80                 :            :             }
      81                 :            :             /* Restore the saved exception. */
      82                 :         10 :             PyErr_Restore(error_type, error_value, error_traceback);
      83                 :         10 :             return;
      84                 :            :         }
      85                 :            :     }
      86                 :            : 
      87                 :            :     /* Save the current exception, if any. */
      88                 :     594659 :     PyErr_Fetch(&error_type, &error_value, &error_traceback);
      89                 :            : 
      90                 :            :     /* If `gen` is a coroutine, and if it was never awaited on,
      91                 :            :        issue a RuntimeWarning. */
      92         [ +  - ]:     594659 :     if (gen->gi_code != NULL &&
      93         [ +  + ]:     594659 :         ((PyCodeObject *)gen->gi_code)->co_flags & CO_COROUTINE &&
      94         [ +  + ]:         60 :         gen->gi_frame_state == FRAME_CREATED)
      95                 :            :     {
      96                 :         40 :         _PyErr_WarnUnawaitedCoroutine((PyObject *)gen);
      97                 :            :     }
      98                 :            :     else {
      99                 :     594619 :         res = gen_close(gen, NULL);
     100                 :            :     }
     101                 :            : 
     102         [ +  + ]:     594659 :     if (res == NULL) {
     103         [ +  + ]:         41 :         if (PyErr_Occurred()) {
     104                 :          1 :             PyErr_WriteUnraisable(self);
     105                 :            :         }
     106                 :            :     }
     107                 :            :     else {
     108                 :     594618 :         Py_DECREF(res);
     109                 :            :     }
     110                 :            : 
     111                 :            :     /* Restore the saved exception. */
     112                 :     594659 :     PyErr_Restore(error_type, error_value, error_traceback);
     113                 :            : }
     114                 :            : 
     115                 :            : static void
     116                 :   17063301 : gen_dealloc(PyGenObject *gen)
     117                 :            : {
     118                 :   17063301 :     PyObject *self = (PyObject *) gen;
     119                 :            : 
     120                 :   17063301 :     _PyObject_GC_UNTRACK(gen);
     121                 :            : 
     122         [ +  + ]:   17063301 :     if (gen->gi_weakreflist != NULL)
     123                 :        138 :         PyObject_ClearWeakRefs(self);
     124                 :            : 
     125                 :   17063301 :     _PyObject_GC_TRACK(self);
     126                 :            : 
     127         [ +  + ]:   17063301 :     if (PyObject_CallFinalizerFromDealloc(self))
     128                 :         43 :         return;                     /* resurrected.  :( */
     129                 :            : 
     130                 :   17063258 :     _PyObject_GC_UNTRACK(self);
     131         [ +  + ]:   17063258 :     if (PyAsyncGen_CheckExact(gen)) {
     132                 :            :         /* We have to handle this case for asynchronous generators
     133                 :            :            right here, because this code has to be between UNTRACK
     134                 :            :            and GC_Del. */
     135         [ +  + ]:       5354 :         Py_CLEAR(((PyAsyncGenObject*)gen)->ag_origin_or_finalizer);
     136                 :            :     }
     137         [ +  + ]:   17063258 :     if (gen->gi_frame_state < FRAME_CLEARED) {
     138                 :         40 :         _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe;
     139                 :         40 :         gen->gi_frame_state = FRAME_CLEARED;
     140                 :         40 :         frame->previous = NULL;
     141                 :         40 :         _PyFrame_Clear(frame);
     142                 :            :     }
     143         [ +  + ]:   17063258 :     if (((PyCodeObject *)gen->gi_code)->co_flags & CO_COROUTINE) {
     144         [ +  + ]:      31557 :         Py_CLEAR(((PyCoroObject *)gen)->cr_origin_or_finalizer);
     145                 :            :     }
     146         [ +  - ]:   17063258 :     Py_CLEAR(gen->gi_code);
     147         [ +  - ]:   17063258 :     Py_CLEAR(gen->gi_name);
     148         [ +  - ]:   17063258 :     Py_CLEAR(gen->gi_qualname);
     149                 :   17063258 :     _PyErr_ClearExcState(&gen->gi_exc_state);
     150                 :   17063258 :     PyObject_GC_Del(gen);
     151                 :            : }
     152                 :            : 
     153                 :            : static PySendResult
     154                 :   62143406 : gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult,
     155                 :            :              int exc, int closing)
     156                 :            : {
     157                 :   62143406 :     PyThreadState *tstate = _PyThreadState_GET();
     158                 :   62143406 :     _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe;
     159                 :            :     PyObject *result;
     160                 :            : 
     161                 :   62143406 :     *presult = NULL;
     162   [ +  +  +  +  :   62143406 :     if (gen->gi_frame_state == FRAME_CREATED && arg && arg != Py_None) {
                   +  + ]
     163                 :          4 :         const char *msg = "can't send non-None value to a "
     164                 :            :                             "just-started generator";
     165         [ +  + ]:          4 :         if (PyCoro_CheckExact(gen)) {
     166                 :          1 :             msg = NON_INIT_CORO_MSG;
     167                 :            :         }
     168         [ +  + ]:          3 :         else if (PyAsyncGen_CheckExact(gen)) {
     169                 :          1 :             msg = "can't send non-None value to a "
     170                 :            :                     "just-started async generator";
     171                 :            :         }
     172                 :          4 :         PyErr_SetString(PyExc_TypeError, msg);
     173                 :          4 :         return PYGEN_ERROR;
     174                 :            :     }
     175         [ +  + ]:   62143402 :     if (gen->gi_frame_state == FRAME_EXECUTING) {
     176                 :          9 :         const char *msg = "generator already executing";
     177         [ +  + ]:          9 :         if (PyCoro_CheckExact(gen)) {
     178                 :          1 :             msg = "coroutine already executing";
     179                 :            :         }
     180         [ -  + ]:          8 :         else if (PyAsyncGen_CheckExact(gen)) {
     181                 :          0 :             msg = "async generator already executing";
     182                 :            :         }
     183                 :          9 :         PyErr_SetString(PyExc_ValueError, msg);
     184                 :          9 :         return PYGEN_ERROR;
     185                 :            :     }
     186         [ +  + ]:   62143393 :     if (gen->gi_frame_state >= FRAME_COMPLETED) {
     187   [ +  +  +  + ]:       9704 :         if (PyCoro_CheckExact(gen) && !closing) {
     188                 :            :             /* `gen` is an exhausted coroutine: raise an error,
     189                 :            :                except when called from gen_close(), which should
     190                 :            :                always be a silent method. */
     191                 :         11 :             PyErr_SetString(
     192                 :            :                 PyExc_RuntimeError,
     193                 :            :                 "cannot reuse already awaited coroutine");
     194                 :            :         }
     195   [ +  +  +  + ]:       9693 :         else if (arg && !exc) {
     196                 :            :             /* `gen` is an exhausted generator:
     197                 :            :                only return value if called from send(). */
     198                 :          1 :             *presult = Py_None;
     199                 :          1 :             Py_INCREF(*presult);
     200                 :          1 :             return PYGEN_RETURN;
     201                 :            :         }
     202                 :       9703 :         return PYGEN_ERROR;
     203                 :            :     }
     204                 :            : 
     205                 :            :     assert(gen->gi_frame_state < FRAME_EXECUTING);
     206                 :            :     /* Push arg onto the frame's value stack */
     207         [ +  + ]:   62133689 :     result = arg ? arg : Py_None;
     208                 :   62133689 :     Py_INCREF(result);
     209                 :   62133689 :     _PyFrame_StackPush(frame, result);
     210                 :            : 
     211                 :   62133689 :     frame->previous = tstate->cframe->current_frame;
     212                 :            : 
     213                 :   62133689 :     gen->gi_exc_state.previous_item = tstate->exc_info;
     214                 :   62133689 :     tstate->exc_info = &gen->gi_exc_state;
     215                 :            : 
     216         [ +  + ]:   62133689 :     if (exc) {
     217                 :            :         assert(_PyErr_Occurred(tstate));
     218                 :     616940 :         _PyErr_ChainStackItem(NULL);
     219                 :            :     }
     220                 :            : 
     221                 :   62133689 :     gen->gi_frame_state = FRAME_EXECUTING;
     222                 :            :     EVAL_CALL_STAT_INC(EVAL_CALL_GENERATOR);
     223                 :   62133689 :     result = _PyEval_EvalFrame(tstate, frame, exc);
     224         [ +  + ]:   62133688 :     if (gen->gi_frame_state == FRAME_EXECUTING) {
     225                 :   17063226 :         gen->gi_frame_state = FRAME_COMPLETED;
     226                 :            :     }
     227                 :   62133688 :     tstate->exc_info = gen->gi_exc_state.previous_item;
     228                 :   62133688 :     gen->gi_exc_state.previous_item = NULL;
     229                 :            : 
     230                 :            :     assert(tstate->cframe->current_frame == frame->previous);
     231                 :            :     /* Don't keep the reference to previous any longer than necessary.  It
     232                 :            :      * may keep a chain of frames alive or it could create a reference
     233                 :            :      * cycle. */
     234                 :   62133688 :     frame->previous = NULL;
     235                 :            : 
     236                 :            :     /* If the generator just returned (as opposed to yielding), signal
     237                 :            :      * that the generator is exhausted. */
     238         [ +  + ]:   62133688 :     if (result) {
     239         [ +  + ]:   61515266 :         if (gen->gi_frame_state == FRAME_SUSPENDED) {
     240                 :   45070462 :             *presult = result;
     241                 :   45070462 :             return PYGEN_NEXT;
     242                 :            :         }
     243                 :            :         assert(result == Py_None || !PyAsyncGen_CheckExact(gen));
     244   [ +  +  +  +  :   16444804 :         if (result == Py_None && !PyAsyncGen_CheckExact(gen) && !arg) {
                   +  + ]
     245                 :            :             /* Return NULL if called by gen_iternext() */
     246         [ +  - ]:   15670851 :             Py_CLEAR(result);
     247                 :            :         }
     248                 :            :     }
     249                 :            :     else {
     250         [ +  + ]:     618422 :         if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
     251                 :         20 :             const char *msg = "generator raised StopIteration";
     252         [ +  + ]:         20 :             if (PyCoro_CheckExact(gen)) {
     253                 :          1 :                 msg = "coroutine raised StopIteration";
     254                 :            :             }
     255         [ +  + ]:         19 :             else if (PyAsyncGen_CheckExact(gen)) {
     256                 :          3 :                 msg = "async generator raised StopIteration";
     257                 :            :             }
     258                 :         20 :             _PyErr_FormatFromCause(PyExc_RuntimeError, "%s", msg);
     259                 :            :         }
     260   [ +  +  +  + ]:     623602 :         else if (PyAsyncGen_CheckExact(gen) &&
     261                 :       5200 :                 PyErr_ExceptionMatches(PyExc_StopAsyncIteration))
     262                 :            :         {
     263                 :            :             /* code in `gen` raised a StopAsyncIteration error:
     264                 :            :                raise a RuntimeError.
     265                 :            :             */
     266                 :          5 :             const char *msg = "async generator raised StopAsyncIteration";
     267                 :          5 :             _PyErr_FormatFromCause(PyExc_RuntimeError, "%s", msg);
     268                 :            :         }
     269                 :            :     }
     270                 :            : 
     271                 :            :     /* generator can't be rerun, so release the frame */
     272                 :            :     /* first clean reference cycle through stored exception traceback */
     273                 :   17063226 :     _PyErr_ClearExcState(&gen->gi_exc_state);
     274                 :            : 
     275                 :   17063226 :     gen->gi_frame_state = FRAME_CLEARED;
     276                 :   17063226 :     _PyFrame_Clear(frame);
     277                 :   17063226 :     *presult = result;
     278         [ +  + ]:   17063226 :     return result ? PYGEN_RETURN : PYGEN_ERROR;
     279                 :            : }
     280                 :            : 
     281                 :            : static PySendResult
     282                 :    5666018 : PyGen_am_send(PyGenObject *gen, PyObject *arg, PyObject **result)
     283                 :            : {
     284                 :    5666018 :     return gen_send_ex2(gen, arg, result, 0, 0);
     285                 :            : }
     286                 :            : 
     287                 :            : static PyObject *
     288                 :     629549 : gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
     289                 :            : {
     290                 :            :     PyObject *result;
     291         [ +  + ]:     629549 :     if (gen_send_ex2(gen, arg, &result, exc, closing) == PYGEN_RETURN) {
     292         [ +  + ]:       2509 :         if (PyAsyncGen_CheckExact(gen)) {
     293                 :            :             assert(result == Py_None);
     294                 :        151 :             PyErr_SetNone(PyExc_StopAsyncIteration);
     295                 :            :         }
     296         [ +  + ]:       2358 :         else if (result == Py_None) {
     297                 :       1670 :             PyErr_SetNone(PyExc_StopIteration);
     298                 :            :         }
     299                 :            :         else {
     300                 :        688 :             _PyGen_SetStopIterationValue(result);
     301                 :            :         }
     302         [ +  - ]:       2509 :         Py_CLEAR(result);
     303                 :            :     }
     304                 :     629549 :     return result;
     305                 :            : }
     306                 :            : 
     307                 :            : PyDoc_STRVAR(send_doc,
     308                 :            : "send(arg) -> send 'arg' into generator,\n\
     309                 :            : return next yielded value or raise StopIteration.");
     310                 :            : 
     311                 :            : static PyObject *
     312                 :       3157 : gen_send(PyGenObject *gen, PyObject *arg)
     313                 :            : {
     314                 :       3157 :     return gen_send_ex(gen, arg, 0, 0);
     315                 :            : }
     316                 :            : 
     317                 :            : PyDoc_STRVAR(close_doc,
     318                 :            : "close() -> raise GeneratorExit inside generator.");
     319                 :            : 
     320                 :            : /*
     321                 :            :  *   This helper function is used by gen_close and gen_throw to
     322                 :            :  *   close a subiterator being delegated to by yield-from.
     323                 :            :  */
     324                 :            : 
     325                 :            : static int
     326                 :      13606 : gen_close_iter(PyObject *yf)
     327                 :            : {
     328                 :      13606 :     PyObject *retval = NULL;
     329                 :            : 
     330   [ +  +  +  + ]:      13606 :     if (PyGen_CheckExact(yf) || PyCoro_CheckExact(yf)) {
     331                 :      12965 :         retval = gen_close((PyGenObject *)yf, NULL);
     332         [ +  + ]:      12965 :         if (retval == NULL)
     333                 :         11 :             return -1;
     334                 :            :     }
     335                 :            :     else {
     336                 :            :         PyObject *meth;
     337         [ +  + ]:        641 :         if (_PyObject_LookupAttr(yf, &_Py_ID(close), &meth) < 0) {
     338                 :          2 :             PyErr_WriteUnraisable(yf);
     339                 :            :         }
     340         [ +  + ]:        641 :         if (meth) {
     341                 :         13 :             retval = _PyObject_CallNoArgs(meth);
     342                 :         13 :             Py_DECREF(meth);
     343         [ -  + ]:         13 :             if (retval == NULL)
     344                 :          0 :                 return -1;
     345                 :            :         }
     346                 :            :     }
     347                 :      13595 :     Py_XDECREF(retval);
     348                 :      13595 :     return 0;
     349                 :            : }
     350                 :            : 
     351                 :            : PyObject *
     352                 :     644065 : _PyGen_yf(PyGenObject *gen)
     353                 :            : {
     354                 :     644065 :     PyObject *yf = NULL;
     355                 :            : 
     356         [ +  + ]:     644065 :     if (gen->gi_frame_state < FRAME_CLEARED) {
     357                 :     634608 :         _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe;
     358                 :            : 
     359         [ +  + ]:     634608 :         if (gen->gi_frame_state == FRAME_CREATED) {
     360                 :            :             /* Return immediately if the frame didn't start yet. SEND
     361                 :            :                always come after LOAD_CONST: a code object should not start
     362                 :            :                with SEND */
     363                 :            :             assert(_Py_OPCODE(_PyCode_CODE(gen->gi_code)[0]) != SEND);
     364                 :      46523 :             return NULL;
     365                 :            :         }
     366                 :     588085 :         _Py_CODEUNIT next = frame->prev_instr[1];
     367   [ +  +  +  + ]:     588085 :         if (_PyOpcode_Deopt[_Py_OPCODE(next)] != RESUME || _Py_OPARG(next) < 2)
     368                 :            :         {
     369                 :            :             /* Not in a yield from */
     370                 :     573203 :             return NULL;
     371                 :            :         }
     372                 :      14882 :         yf = _PyFrame_StackPeek(frame);
     373                 :      14882 :         Py_INCREF(yf);
     374                 :            :     }
     375                 :            : 
     376                 :      24339 :     return yf;
     377                 :            : }
     378                 :            : 
     379                 :            : static PyObject *
     380                 :     622270 : gen_close(PyGenObject *gen, PyObject *args)
     381                 :            : {
     382                 :            :     PyObject *retval;
     383                 :     622270 :     PyObject *yf = _PyGen_yf(gen);
     384                 :     622270 :     int err = 0;
     385                 :            : 
     386         [ +  + ]:     622270 :     if (yf) {
     387                 :      13596 :         PyFrameState state = gen->gi_frame_state;
     388                 :      13596 :         gen->gi_frame_state = FRAME_EXECUTING;
     389                 :      13596 :         err = gen_close_iter(yf);
     390                 :      13596 :         gen->gi_frame_state = state;
     391                 :      13596 :         Py_DECREF(yf);
     392                 :            :     }
     393         [ +  + ]:     622270 :     if (err == 0)
     394                 :     622265 :         PyErr_SetNone(PyExc_GeneratorExit);
     395                 :     622270 :     retval = gen_send_ex(gen, Py_None, 1, 1);
     396         [ +  + ]:     622270 :     if (retval) {
     397                 :          7 :         const char *msg = "generator ignored GeneratorExit";
     398         [ +  + ]:          7 :         if (PyCoro_CheckExact(gen)) {
     399                 :          1 :             msg = "coroutine ignored GeneratorExit";
     400         [ -  + ]:          6 :         } else if (PyAsyncGen_CheckExact(gen)) {
     401                 :          0 :             msg = ASYNC_GEN_IGNORED_EXIT_MSG;
     402                 :            :         }
     403                 :          7 :         Py_DECREF(retval);
     404                 :          7 :         PyErr_SetString(PyExc_RuntimeError, msg);
     405                 :          7 :         return NULL;
     406                 :            :     }
     407         [ +  + ]:     622263 :     if (PyErr_ExceptionMatches(PyExc_StopIteration)
     408         [ +  + ]:     622257 :         || PyErr_ExceptionMatches(PyExc_GeneratorExit)) {
     409                 :     622249 :         PyErr_Clear();          /* ignore these errors */
     410                 :     622249 :         Py_RETURN_NONE;
     411                 :            :     }
     412                 :         14 :     return NULL;
     413                 :            : }
     414                 :            : 
     415                 :            : 
     416                 :            : PyDoc_STRVAR(throw_doc,
     417                 :            : "throw(value)\n\
     418                 :            : throw(type[,value[,tb]])\n\
     419                 :            : \n\
     420                 :            : Raise exception in generator, return next yielded value or raise\n\
     421                 :            : StopIteration.");
     422                 :            : 
     423                 :            : static PyObject *
     424                 :       4217 : _gen_throw(PyGenObject *gen, int close_on_genexit,
     425                 :            :            PyObject *typ, PyObject *val, PyObject *tb)
     426                 :            : {
     427                 :       4217 :     PyObject *yf = _PyGen_yf(gen);
     428                 :            : 
     429         [ +  + ]:       4217 :     if (yf) {
     430                 :       1281 :         _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe;
     431                 :            :         PyObject *ret;
     432                 :            :         int err;
     433   [ +  +  +  - ]:       1281 :         if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit) &&
     434                 :            :             close_on_genexit
     435                 :            :         ) {
     436                 :            :             /* Asynchronous generators *should not* be closed right away.
     437                 :            :                We have to allow some awaits to work it through, hence the
     438                 :            :                `close_on_genexit` parameter here.
     439                 :            :             */
     440                 :         10 :             PyFrameState state = gen->gi_frame_state;
     441                 :         10 :             gen->gi_frame_state = FRAME_EXECUTING;
     442                 :         10 :             err = gen_close_iter(yf);
     443                 :         10 :             gen->gi_frame_state = state;
     444                 :         10 :             Py_DECREF(yf);
     445         [ +  + ]:         10 :             if (err < 0)
     446                 :          6 :                 return gen_send_ex(gen, Py_None, 1, 0);
     447                 :          4 :             goto throw_here;
     448                 :            :         }
     449   [ +  +  +  + ]:       1271 :         if (PyGen_CheckExact(yf) || PyCoro_CheckExact(yf)) {
     450                 :            :             /* `yf` is a generator or a coroutine. */
     451                 :        629 :             PyThreadState *tstate = _PyThreadState_GET();
     452                 :            :             /* Since we are fast-tracking things by skipping the eval loop,
     453                 :            :                we need to update the current frame so the stack trace
     454                 :            :                will be reported correctly to the user. */
     455                 :            :             /* XXX We should probably be updating the current frame
     456                 :            :                somewhere in ceval.c. */
     457                 :        629 :             _PyInterpreterFrame *prev = tstate->cframe->current_frame;
     458                 :        629 :             frame->previous = prev;
     459                 :        629 :             tstate->cframe->current_frame = frame;
     460                 :            :             /* Close the generator that we are currently iterating with
     461                 :            :                'yield from' or awaiting on with 'await'. */
     462                 :        629 :             PyFrameState state = gen->gi_frame_state;
     463                 :        629 :             gen->gi_frame_state = FRAME_EXECUTING;
     464                 :        629 :             ret = _gen_throw((PyGenObject *)yf, close_on_genexit,
     465                 :            :                              typ, val, tb);
     466                 :        629 :             gen->gi_frame_state = state;
     467                 :        629 :             tstate->cframe->current_frame = prev;
     468                 :        629 :             frame->previous = NULL;
     469                 :            :         } else {
     470                 :            :             /* `yf` is an iterator or a coroutine-like object. */
     471                 :            :             PyObject *meth;
     472         [ +  + ]:        642 :             if (_PyObject_LookupAttr(yf, &_Py_ID(throw), &meth) < 0) {
     473                 :          1 :                 Py_DECREF(yf);
     474                 :          1 :                 return NULL;
     475                 :            :             }
     476         [ +  + ]:        641 :             if (meth == NULL) {
     477                 :          1 :                 Py_DECREF(yf);
     478                 :          1 :                 goto throw_here;
     479                 :            :             }
     480                 :        640 :             PyFrameState state = gen->gi_frame_state;
     481                 :        640 :             gen->gi_frame_state = FRAME_EXECUTING;
     482                 :        640 :             ret = PyObject_CallFunctionObjArgs(meth, typ, val, tb, NULL);
     483                 :        640 :             gen->gi_frame_state = state;
     484                 :        640 :             Py_DECREF(meth);
     485                 :            :         }
     486                 :       1269 :         Py_DECREF(yf);
     487         [ +  + ]:       1269 :         if (!ret) {
     488                 :            :             PyObject *val;
     489                 :            :             /* Pop subiterator from stack */
     490                 :            :             assert(gen->gi_frame_state < FRAME_CLEARED);
     491                 :       1237 :             ret = _PyFrame_StackPop((_PyInterpreterFrame *)gen->gi_iframe);
     492                 :            :             assert(ret == yf);
     493                 :       1237 :             Py_DECREF(ret);
     494                 :            :             // XXX: Performing this jump ourselves is awkward and problematic.
     495                 :            :             // See https://github.com/python/cpython/pull/31968.
     496                 :            :             /* Termination repetition of SEND loop */
     497                 :            :             assert(_PyInterpreterFrame_LASTI(frame) >= 0);
     498                 :            :             /* Backup to SEND */
     499                 :            :             assert(_Py_OPCODE(frame->prev_instr[-1]) == SEND);
     500                 :       1237 :             int jump = _Py_OPARG(frame->prev_instr[-1]);
     501                 :       1237 :             frame->prev_instr += jump - 1;
     502         [ +  + ]:       1237 :             if (_PyGen_FetchStopIterationValue(&val) == 0) {
     503                 :         54 :                 ret = gen_send(gen, val);
     504                 :         54 :                 Py_DECREF(val);
     505                 :            :             } else {
     506                 :       1183 :                 ret = gen_send_ex(gen, Py_None, 1, 0);
     507                 :            :             }
     508                 :            :         }
     509                 :       1269 :         return ret;
     510                 :            :     }
     511                 :            : 
     512                 :       2936 : throw_here:
     513                 :            :     /* First, check the traceback argument, replacing None with
     514                 :            :        NULL. */
     515         [ +  + ]:       2941 :     if (tb == Py_None) {
     516                 :         21 :         tb = NULL;
     517                 :            :     }
     518   [ +  +  +  + ]:       2920 :     else if (tb != NULL && !PyTraceBack_Check(tb)) {
     519                 :          2 :         PyErr_SetString(PyExc_TypeError,
     520                 :            :             "throw() third argument must be a traceback object");
     521                 :          2 :         return NULL;
     522                 :            :     }
     523                 :            : 
     524                 :       2939 :     Py_INCREF(typ);
     525                 :       2939 :     Py_XINCREF(val);
     526                 :       2939 :     Py_XINCREF(tb);
     527                 :            : 
     528   [ +  +  +  + ]:       2939 :     if (PyExceptionClass_Check(typ))
     529                 :       2746 :         PyErr_NormalizeException(&typ, &val, &tb);
     530                 :            : 
     531         [ +  + ]:        193 :     else if (PyExceptionInstance_Check(typ)) {
     532                 :            :         /* Raising an instance.  The value should be a dummy. */
     533   [ +  +  +  - ]:        189 :         if (val && val != Py_None) {
     534                 :          2 :             PyErr_SetString(PyExc_TypeError,
     535                 :            :               "instance exception may not have a separate value");
     536                 :          2 :             goto failed_throw;
     537                 :            :         }
     538                 :            :         else {
     539                 :            :             /* Normalize to raise <class>, <instance> */
     540                 :        187 :             Py_XDECREF(val);
     541                 :        187 :             val = typ;
     542                 :        187 :             typ = PyExceptionInstance_Class(typ);
     543                 :        187 :             Py_INCREF(typ);
     544                 :            : 
     545         [ +  - ]:        187 :             if (tb == NULL)
     546                 :            :                 /* Returns NULL if there's no traceback */
     547                 :        187 :                 tb = PyException_GetTraceback(val);
     548                 :            :         }
     549                 :            :     }
     550                 :            :     else {
     551                 :            :         /* Not something you can raise.  throw() fails. */
     552                 :          4 :         PyErr_Format(PyExc_TypeError,
     553                 :            :                      "exceptions must be classes or instances "
     554                 :            :                      "deriving from BaseException, not %s",
     555                 :          4 :                      Py_TYPE(typ)->tp_name);
     556                 :          4 :             goto failed_throw;
     557                 :            :     }
     558                 :            : 
     559                 :       2933 :     PyErr_Restore(typ, val, tb);
     560                 :       2933 :     return gen_send_ex(gen, Py_None, 1, 0);
     561                 :            : 
     562                 :          6 : failed_throw:
     563                 :            :     /* Didn't use our arguments, so restore their original refcounts */
     564                 :          6 :     Py_DECREF(typ);
     565                 :          6 :     Py_XDECREF(val);
     566                 :          6 :     Py_XDECREF(tb);
     567                 :          6 :     return NULL;
     568                 :            : }
     569                 :            : 
     570                 :            : 
     571                 :            : static PyObject *
     572                 :       3549 : gen_throw(PyGenObject *gen, PyObject *const *args, Py_ssize_t nargs)
     573                 :            : {
     574                 :            :     PyObject *typ;
     575                 :       3549 :     PyObject *tb = NULL;
     576                 :       3549 :     PyObject *val = NULL;
     577                 :            : 
     578   [ +  -  -  +  :       3549 :     if (!_PyArg_CheckPositional("throw", nargs, 1, 3)) {
                   -  - ]
     579                 :          0 :         return NULL;
     580                 :            :     }
     581                 :       3549 :     typ = args[0];
     582         [ +  + ]:       3549 :     if (nargs == 3) {
     583                 :       2680 :         val = args[1];
     584                 :       2680 :         tb = args[2];
     585                 :            :     }
     586         [ +  + ]:        869 :     else if (nargs == 2) {
     587                 :          7 :         val = args[1];
     588                 :            :     }
     589                 :       3549 :     return _gen_throw(gen, 1, typ, val, tb);
     590                 :            : }
     591                 :            : 
     592                 :            : 
     593                 :            : static PyObject *
     594                 :   55847839 : gen_iternext(PyGenObject *gen)
     595                 :            : {
     596                 :            :     PyObject *result;
     597                 :            :     assert(PyGen_CheckExact(gen) || PyCoro_CheckExact(gen));
     598         [ +  + ]:   55847839 :     if (gen_send_ex2(gen, NULL, &result, 0, 0) == PYGEN_RETURN) {
     599         [ +  - ]:         49 :         if (result != Py_None) {
     600                 :         49 :             _PyGen_SetStopIterationValue(result);
     601                 :            :         }
     602         [ +  - ]:         49 :         Py_CLEAR(result);
     603                 :            :     }
     604                 :   55847838 :     return result;
     605                 :            : }
     606                 :            : 
     607                 :            : /*
     608                 :            :  * Set StopIteration with specified value.  Value can be arbitrary object
     609                 :            :  * or NULL.
     610                 :            :  *
     611                 :            :  * Returns 0 if StopIteration is set and -1 if any other exception is set.
     612                 :            :  */
     613                 :            : int
     614                 :       1182 : _PyGen_SetStopIterationValue(PyObject *value)
     615                 :            : {
     616                 :            :     PyObject *e;
     617                 :            : 
     618   [ +  -  +  + ]:       2364 :     if (value == NULL ||
     619         [ +  + ]:       2324 :         (!PyTuple_Check(value) && !PyExceptionInstance_Check(value)))
     620                 :            :     {
     621                 :            :         /* Delay exception instantiation if we can */
     622                 :       1133 :         PyErr_SetObject(PyExc_StopIteration, value);
     623                 :       1133 :         return 0;
     624                 :            :     }
     625                 :            :     /* Construct an exception instance manually with
     626                 :            :      * PyObject_CallOneArg and pass it to PyErr_SetObject.
     627                 :            :      *
     628                 :            :      * We do this to handle a situation when "value" is a tuple, in which
     629                 :            :      * case PyErr_SetObject would set the value of StopIteration to
     630                 :            :      * the first element of the tuple.
     631                 :            :      *
     632                 :            :      * (See PyErr_SetObject/_PyErr_CreateException code for details.)
     633                 :            :      */
     634                 :         49 :     e = PyObject_CallOneArg(PyExc_StopIteration, value);
     635         [ -  + ]:         49 :     if (e == NULL) {
     636                 :          0 :         return -1;
     637                 :            :     }
     638                 :         49 :     PyErr_SetObject(PyExc_StopIteration, e);
     639                 :         49 :     Py_DECREF(e);
     640                 :         49 :     return 0;
     641                 :            : }
     642                 :            : 
     643                 :            : /*
     644                 :            :  *   If StopIteration exception is set, fetches its 'value'
     645                 :            :  *   attribute if any, otherwise sets pvalue to None.
     646                 :            :  *
     647                 :            :  *   Returns 0 if no exception or StopIteration is set.
     648                 :            :  *   If any other exception is set, returns -1 and leaves
     649                 :            :  *   pvalue unchanged.
     650                 :            :  */
     651                 :            : 
     652                 :            : int
     653                 :      11497 : _PyGen_FetchStopIterationValue(PyObject **pvalue)
     654                 :            : {
     655                 :            :     PyObject *et, *ev, *tb;
     656                 :      11497 :     PyObject *value = NULL;
     657                 :            : 
     658         [ +  + ]:      11497 :     if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
     659                 :        696 :         PyErr_Fetch(&et, &ev, &tb);
     660         [ +  + ]:        696 :         if (ev) {
     661                 :            :             /* exception will usually be normalised already */
     662         [ +  + ]:        510 :             if (PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
     663                 :        101 :                 value = ((PyStopIterationObject *)ev)->value;
     664                 :        101 :                 Py_INCREF(value);
     665                 :        101 :                 Py_DECREF(ev);
     666   [ +  -  +  - ]:        409 :             } else if (et == PyExc_StopIteration && !PyTuple_Check(ev)) {
     667                 :            :                 /* Avoid normalisation and take ev as value.
     668                 :            :                  *
     669                 :            :                  * Normalization is required if the value is a tuple, in
     670                 :            :                  * that case the value of StopIteration would be set to
     671                 :            :                  * the first element of the tuple.
     672                 :            :                  *
     673                 :            :                  * (See _PyErr_CreateException code for details.)
     674                 :            :                  */
     675                 :        409 :                 value = ev;
     676                 :            :             } else {
     677                 :            :                 /* normalisation required */
     678                 :          0 :                 PyErr_NormalizeException(&et, &ev, &tb);
     679         [ #  # ]:          0 :                 if (!PyObject_TypeCheck(ev, (PyTypeObject *)PyExc_StopIteration)) {
     680                 :          0 :                     PyErr_Restore(et, ev, tb);
     681                 :          0 :                     return -1;
     682                 :            :                 }
     683                 :          0 :                 value = ((PyStopIterationObject *)ev)->value;
     684                 :          0 :                 Py_INCREF(value);
     685                 :          0 :                 Py_DECREF(ev);
     686                 :            :             }
     687                 :            :         }
     688                 :        696 :         Py_XDECREF(et);
     689                 :        696 :         Py_XDECREF(tb);
     690         [ +  + ]:      10801 :     } else if (PyErr_Occurred()) {
     691                 :       1772 :         return -1;
     692                 :            :     }
     693         [ +  + ]:       9725 :     if (value == NULL) {
     694                 :       9215 :         value = Py_None;
     695                 :       9215 :         Py_INCREF(value);
     696                 :            :     }
     697                 :       9725 :     *pvalue = value;
     698                 :       9725 :     return 0;
     699                 :            : }
     700                 :            : 
     701                 :            : static PyObject *
     702                 :          2 : gen_repr(PyGenObject *gen)
     703                 :            : {
     704                 :          2 :     return PyUnicode_FromFormat("<generator object %S at %p>",
     705                 :            :                                 gen->gi_qualname, gen);
     706                 :            : }
     707                 :            : 
     708                 :            : static PyObject *
     709                 :         27 : gen_get_name(PyGenObject *op, void *Py_UNUSED(ignored))
     710                 :            : {
     711                 :         27 :     Py_INCREF(op->gi_name);
     712                 :         27 :     return op->gi_name;
     713                 :            : }
     714                 :            : 
     715                 :            : static int
     716                 :          4 : gen_set_name(PyGenObject *op, PyObject *value, void *Py_UNUSED(ignored))
     717                 :            : {
     718                 :            :     /* Not legal to del gen.gi_name or to set it to anything
     719                 :            :      * other than a string object. */
     720   [ +  +  +  + ]:          4 :     if (value == NULL || !PyUnicode_Check(value)) {
     721                 :          2 :         PyErr_SetString(PyExc_TypeError,
     722                 :            :                         "__name__ must be set to a string object");
     723                 :          2 :         return -1;
     724                 :            :     }
     725                 :          2 :     Py_INCREF(value);
     726                 :          2 :     Py_XSETREF(op->gi_name, value);
     727                 :          2 :     return 0;
     728                 :            : }
     729                 :            : 
     730                 :            : static PyObject *
     731                 :       5548 : gen_get_qualname(PyGenObject *op, void *Py_UNUSED(ignored))
     732                 :            : {
     733                 :       5548 :     Py_INCREF(op->gi_qualname);
     734                 :       5548 :     return op->gi_qualname;
     735                 :            : }
     736                 :            : 
     737                 :            : static int
     738                 :          4 : gen_set_qualname(PyGenObject *op, PyObject *value, void *Py_UNUSED(ignored))
     739                 :            : {
     740                 :            :     /* Not legal to del gen.__qualname__ or to set it to anything
     741                 :            :      * other than a string object. */
     742   [ +  +  +  + ]:          4 :     if (value == NULL || !PyUnicode_Check(value)) {
     743                 :          2 :         PyErr_SetString(PyExc_TypeError,
     744                 :            :                         "__qualname__ must be set to a string object");
     745                 :          2 :         return -1;
     746                 :            :     }
     747                 :          2 :     Py_INCREF(value);
     748                 :          2 :     Py_XSETREF(op->gi_qualname, value);
     749                 :          2 :     return 0;
     750                 :            : }
     751                 :            : 
     752                 :            : static PyObject *
     753                 :          9 : gen_getyieldfrom(PyGenObject *gen, void *Py_UNUSED(ignored))
     754                 :            : {
     755                 :          9 :     PyObject *yf = _PyGen_yf(gen);
     756         [ +  + ]:          9 :     if (yf == NULL)
     757                 :          8 :         Py_RETURN_NONE;
     758                 :          1 :     return yf;
     759                 :            : }
     760                 :            : 
     761                 :            : 
     762                 :            : static PyObject *
     763                 :         23 : gen_getrunning(PyGenObject *gen, void *Py_UNUSED(ignored))
     764                 :            : {
     765         [ +  + ]:         23 :     if (gen->gi_frame_state == FRAME_EXECUTING) {
     766                 :          8 :         Py_RETURN_TRUE;
     767                 :            :     }
     768                 :         15 :     Py_RETURN_FALSE;
     769                 :            : }
     770                 :            : 
     771                 :            : static PyObject *
     772                 :          8 : gen_getsuspended(PyGenObject *gen, void *Py_UNUSED(ignored))
     773                 :            : {
     774                 :          8 :     return PyBool_FromLong(gen->gi_frame_state == FRAME_SUSPENDED);
     775                 :            : }
     776                 :            : 
     777                 :            : static PyObject *
     778                 :       3846 : _gen_getframe(PyGenObject *gen, const char *const name)
     779                 :            : {
     780         [ -  + ]:       3846 :     if (PySys_Audit("object.__getattr__", "Os", gen, name) < 0) {
     781                 :          0 :         return NULL;
     782                 :            :     }
     783         [ +  + ]:       3846 :     if (gen->gi_frame_state == FRAME_CLEARED) {
     784                 :       3431 :         Py_RETURN_NONE;
     785                 :            :     }
     786                 :        415 :     return _Py_XNewRef((PyObject *)_PyFrame_GetFrameObject((_PyInterpreterFrame *)gen->gi_iframe));
     787                 :            : }
     788                 :            : 
     789                 :            : static PyObject *
     790                 :         23 : gen_getframe(PyGenObject *gen, void *Py_UNUSED(ignored))
     791                 :            : {
     792                 :         23 :     return _gen_getframe(gen, "gi_frame");
     793                 :            : }
     794                 :            : 
     795                 :            : static PyGetSetDef gen_getsetlist[] = {
     796                 :            :     {"__name__", (getter)gen_get_name, (setter)gen_set_name,
     797                 :            :      PyDoc_STR("name of the generator")},
     798                 :            :     {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname,
     799                 :            :      PyDoc_STR("qualified name of the generator")},
     800                 :            :     {"gi_yieldfrom", (getter)gen_getyieldfrom, NULL,
     801                 :            :      PyDoc_STR("object being iterated by yield from, or None")},
     802                 :            :     {"gi_running", (getter)gen_getrunning, NULL, NULL},
     803                 :            :     {"gi_frame", (getter)gen_getframe,  NULL, NULL},
     804                 :            :     {"gi_suspended", (getter)gen_getsuspended,  NULL, NULL},
     805                 :            :     {NULL} /* Sentinel */
     806                 :            : };
     807                 :            : 
     808                 :            : static PyMemberDef gen_memberlist[] = {
     809                 :            :     {"gi_code",      T_OBJECT, offsetof(PyGenObject, gi_code),     READONLY|PY_AUDIT_READ},
     810                 :            :     {NULL}      /* Sentinel */
     811                 :            : };
     812                 :            : 
     813                 :            : static PyObject *
     814                 :          1 : gen_sizeof(PyGenObject *gen, PyObject *Py_UNUSED(ignored))
     815                 :            : {
     816                 :            :     Py_ssize_t res;
     817                 :          1 :     res = offsetof(PyGenObject, gi_iframe) + offsetof(_PyInterpreterFrame, localsplus);
     818                 :          1 :     PyCodeObject *code = gen->gi_code;
     819                 :          1 :     res += (code->co_nlocalsplus+code->co_stacksize) * sizeof(PyObject *);
     820                 :          1 :     return PyLong_FromSsize_t(res);
     821                 :            : }
     822                 :            : 
     823                 :            : PyDoc_STRVAR(sizeof__doc__,
     824                 :            : "gen.__sizeof__() -> size of gen in memory, in bytes");
     825                 :            : 
     826                 :            : static PyMethodDef gen_methods[] = {
     827                 :            :     {"send",(PyCFunction)gen_send, METH_O, send_doc},
     828                 :            :     {"throw",_PyCFunction_CAST(gen_throw), METH_FASTCALL, throw_doc},
     829                 :            :     {"close",(PyCFunction)gen_close, METH_NOARGS, close_doc},
     830                 :            :     {"__sizeof__", (PyCFunction)gen_sizeof, METH_NOARGS, sizeof__doc__},
     831                 :            :     {NULL, NULL}        /* Sentinel */
     832                 :            : };
     833                 :            : 
     834                 :            : static PyAsyncMethods gen_as_async = {
     835                 :            :     0,                                          /* am_await */
     836                 :            :     0,                                          /* am_aiter */
     837                 :            :     0,                                          /* am_anext */
     838                 :            :     (sendfunc)PyGen_am_send,                    /* am_send  */
     839                 :            : };
     840                 :            : 
     841                 :            : 
     842                 :            : PyTypeObject PyGen_Type = {
     843                 :            :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
     844                 :            :     "generator",                                /* tp_name */
     845                 :            :     offsetof(PyGenObject, gi_iframe) +
     846                 :            :     offsetof(_PyInterpreterFrame, localsplus),       /* tp_basicsize */
     847                 :            :     sizeof(PyObject *),                         /* tp_itemsize */
     848                 :            :     /* methods */
     849                 :            :     (destructor)gen_dealloc,                    /* tp_dealloc */
     850                 :            :     0,                                          /* tp_vectorcall_offset */
     851                 :            :     0,                                          /* tp_getattr */
     852                 :            :     0,                                          /* tp_setattr */
     853                 :            :     &gen_as_async,                              /* tp_as_async */
     854                 :            :     (reprfunc)gen_repr,                         /* tp_repr */
     855                 :            :     0,                                          /* tp_as_number */
     856                 :            :     0,                                          /* tp_as_sequence */
     857                 :            :     0,                                          /* tp_as_mapping */
     858                 :            :     0,                                          /* tp_hash */
     859                 :            :     0,                                          /* tp_call */
     860                 :            :     0,                                          /* tp_str */
     861                 :            :     PyObject_GenericGetAttr,                    /* tp_getattro */
     862                 :            :     0,                                          /* tp_setattro */
     863                 :            :     0,                                          /* tp_as_buffer */
     864                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
     865                 :            :     0,                                          /* tp_doc */
     866                 :            :     (traverseproc)gen_traverse,                 /* tp_traverse */
     867                 :            :     0,                                          /* tp_clear */
     868                 :            :     0,                                          /* tp_richcompare */
     869                 :            :     offsetof(PyGenObject, gi_weakreflist),      /* tp_weaklistoffset */
     870                 :            :     PyObject_SelfIter,                          /* tp_iter */
     871                 :            :     (iternextfunc)gen_iternext,                 /* tp_iternext */
     872                 :            :     gen_methods,                                /* tp_methods */
     873                 :            :     gen_memberlist,                             /* tp_members */
     874                 :            :     gen_getsetlist,                             /* tp_getset */
     875                 :            :     0,                                          /* tp_base */
     876                 :            :     0,                                          /* tp_dict */
     877                 :            : 
     878                 :            :     0,                                          /* tp_descr_get */
     879                 :            :     0,                                          /* tp_descr_set */
     880                 :            :     0,                                          /* tp_dictoffset */
     881                 :            :     0,                                          /* tp_init */
     882                 :            :     0,                                          /* tp_alloc */
     883                 :            :     0,                                          /* tp_new */
     884                 :            :     0,                                          /* tp_free */
     885                 :            :     0,                                          /* tp_is_gc */
     886                 :            :     0,                                          /* tp_bases */
     887                 :            :     0,                                          /* tp_mro */
     888                 :            :     0,                                          /* tp_cache */
     889                 :            :     0,                                          /* tp_subclasses */
     890                 :            :     0,                                          /* tp_weaklist */
     891                 :            :     0,                                          /* tp_del */
     892                 :            :     0,                                          /* tp_version_tag */
     893                 :            :     _PyGen_Finalize,                            /* tp_finalize */
     894                 :            : };
     895                 :            : 
     896                 :            : static PyObject *
     897                 :   17063267 : make_gen(PyTypeObject *type, PyFunctionObject *func)
     898                 :            : {
     899                 :   17063267 :     PyCodeObject *code = (PyCodeObject *)func->func_code;
     900                 :   17063267 :     int slots = code->co_nlocalsplus + code->co_stacksize;
     901                 :   17063267 :     PyGenObject *gen = PyObject_GC_NewVar(PyGenObject, type, slots);
     902         [ -  + ]:   17063267 :     if (gen == NULL) {
     903                 :          0 :         return NULL;
     904                 :            :     }
     905                 :   17063267 :     gen->gi_frame_state = FRAME_CLEARED;
     906                 :   17063267 :     gen->gi_code = (PyCodeObject *)func->func_code;
     907                 :   17063267 :     Py_INCREF(gen->gi_code);
     908                 :   17063267 :     gen->gi_weakreflist = NULL;
     909                 :   17063267 :     gen->gi_exc_state.exc_value = NULL;
     910                 :   17063267 :     gen->gi_exc_state.previous_item = NULL;
     911                 :            :     assert(func->func_name != NULL);
     912                 :   17063267 :     gen->gi_name = Py_NewRef(func->func_name);
     913                 :            :     assert(func->func_qualname != NULL);
     914                 :   17063267 :     gen->gi_qualname = Py_NewRef(func->func_qualname);
     915                 :   17063267 :     _PyObject_GC_TRACK(gen);
     916                 :   17063267 :     return (PyObject *)gen;
     917                 :            : }
     918                 :            : 
     919                 :            : static PyObject *
     920                 :            : compute_cr_origin(int origin_depth, _PyInterpreterFrame *current_frame);
     921                 :            : 
     922                 :            : PyObject *
     923                 :   17063267 : _Py_MakeCoro(PyFunctionObject *func)
     924                 :            : {
     925                 :   17063267 :     int coro_flags = ((PyCodeObject *)func->func_code)->co_flags &
     926                 :            :         (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR);
     927                 :            :     assert(coro_flags);
     928         [ +  + ]:   17063267 :     if (coro_flags == CO_GENERATOR) {
     929                 :   17026356 :         return make_gen(&PyGen_Type, func);
     930                 :            :     }
     931         [ +  + ]:      36911 :     if (coro_flags == CO_ASYNC_GENERATOR) {
     932                 :            :         PyAsyncGenObject *o;
     933                 :       5354 :         o = (PyAsyncGenObject *)make_gen(&PyAsyncGen_Type, func);
     934         [ -  + ]:       5354 :         if (o == NULL) {
     935                 :          0 :             return NULL;
     936                 :            :         }
     937                 :       5354 :         o->ag_origin_or_finalizer = NULL;
     938                 :       5354 :         o->ag_closed = 0;
     939                 :       5354 :         o->ag_hooks_inited = 0;
     940                 :       5354 :         o->ag_running_async = 0;
     941                 :       5354 :         return (PyObject*)o;
     942                 :            :     }
     943                 :            :     assert (coro_flags == CO_COROUTINE);
     944                 :      31557 :     PyObject *coro = make_gen(&PyCoro_Type, func);
     945         [ -  + ]:      31557 :     if (!coro) {
     946                 :          0 :         return NULL;
     947                 :            :     }
     948                 :      31557 :     PyThreadState *tstate = _PyThreadState_GET();
     949                 :      31557 :     int origin_depth = tstate->coroutine_origin_tracking_depth;
     950                 :            : 
     951         [ +  + ]:      31557 :     if (origin_depth == 0) {
     952                 :      28387 :         ((PyCoroObject *)coro)->cr_origin_or_finalizer = NULL;
     953                 :            :     } else {
     954                 :            :         assert(_PyEval_GetFrame());
     955                 :       3170 :         PyObject *cr_origin = compute_cr_origin(origin_depth, _PyEval_GetFrame()->previous);
     956                 :       3170 :         ((PyCoroObject *)coro)->cr_origin_or_finalizer = cr_origin;
     957         [ -  + ]:       3170 :         if (!cr_origin) {
     958                 :          0 :             Py_DECREF(coro);
     959                 :          0 :             return NULL;
     960                 :            :         }
     961                 :            :     }
     962                 :      31557 :     return coro;
     963                 :            : }
     964                 :            : 
     965                 :            : static PyObject *
     966                 :          0 : gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f,
     967                 :            :                       PyObject *name, PyObject *qualname)
     968                 :            : {
     969                 :          0 :     PyCodeObject *code = f->f_frame->f_code;
     970                 :          0 :     int size = code->co_nlocalsplus + code->co_stacksize;
     971                 :          0 :     PyGenObject *gen = PyObject_GC_NewVar(PyGenObject, type, size);
     972         [ #  # ]:          0 :     if (gen == NULL) {
     973                 :          0 :         Py_DECREF(f);
     974                 :          0 :         return NULL;
     975                 :            :     }
     976                 :            :     /* Copy the frame */
     977                 :            :     assert(f->f_frame->frame_obj == NULL);
     978                 :            :     assert(f->f_frame->owner == FRAME_OWNED_BY_FRAME_OBJECT);
     979                 :          0 :     _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe;
     980                 :          0 :     _PyFrame_Copy((_PyInterpreterFrame *)f->_f_frame_data, frame);
     981                 :          0 :     gen->gi_frame_state = FRAME_CREATED;
     982                 :            :     assert(frame->frame_obj == f);
     983                 :          0 :     f->f_frame = frame;
     984                 :          0 :     frame->owner = FRAME_OWNED_BY_GENERATOR;
     985                 :            :     assert(PyObject_GC_IsTracked((PyObject *)f));
     986                 :          0 :     gen->gi_code = PyFrame_GetCode(f);
     987                 :          0 :     Py_INCREF(gen->gi_code);
     988                 :          0 :     Py_DECREF(f);
     989                 :          0 :     gen->gi_weakreflist = NULL;
     990                 :          0 :     gen->gi_exc_state.exc_value = NULL;
     991                 :          0 :     gen->gi_exc_state.previous_item = NULL;
     992         [ #  # ]:          0 :     if (name != NULL)
     993                 :          0 :         gen->gi_name = name;
     994                 :            :     else
     995                 :          0 :         gen->gi_name = gen->gi_code->co_name;
     996                 :          0 :     Py_INCREF(gen->gi_name);
     997         [ #  # ]:          0 :     if (qualname != NULL)
     998                 :          0 :         gen->gi_qualname = qualname;
     999                 :            :     else
    1000                 :          0 :         gen->gi_qualname = gen->gi_code->co_qualname;
    1001                 :          0 :     Py_INCREF(gen->gi_qualname);
    1002                 :          0 :     _PyObject_GC_TRACK(gen);
    1003                 :          0 :     return (PyObject *)gen;
    1004                 :            : }
    1005                 :            : 
    1006                 :            : PyObject *
    1007                 :          0 : PyGen_NewWithQualName(PyFrameObject *f, PyObject *name, PyObject *qualname)
    1008                 :            : {
    1009                 :          0 :     return gen_new_with_qualname(&PyGen_Type, f, name, qualname);
    1010                 :            : }
    1011                 :            : 
    1012                 :            : PyObject *
    1013                 :          0 : PyGen_New(PyFrameObject *f)
    1014                 :            : {
    1015                 :          0 :     return gen_new_with_qualname(&PyGen_Type, f, NULL, NULL);
    1016                 :            : }
    1017                 :            : 
    1018                 :            : /* Coroutine Object */
    1019                 :            : 
    1020                 :            : typedef struct {
    1021                 :            :     PyObject_HEAD
    1022                 :            :     PyCoroObject *cw_coroutine;
    1023                 :            : } PyCoroWrapper;
    1024                 :            : 
    1025                 :            : static int
    1026                 :      27416 : gen_is_coroutine(PyObject *o)
    1027                 :            : {
    1028         [ +  + ]:      27416 :     if (PyGen_CheckExact(o)) {
    1029                 :        862 :         PyCodeObject *code = (PyCodeObject *)((PyGenObject*)o)->gi_code;
    1030         [ +  + ]:        862 :         if (code->co_flags & CO_ITERABLE_COROUTINE) {
    1031                 :        644 :             return 1;
    1032                 :            :         }
    1033                 :            :     }
    1034                 :      26772 :     return 0;
    1035                 :            : }
    1036                 :            : 
    1037                 :            : /*
    1038                 :            :  *   This helper function returns an awaitable for `o`:
    1039                 :            :  *     - `o` if `o` is a coroutine-object;
    1040                 :            :  *     - `type(o)->tp_as_async->am_await(o)`
    1041                 :            :  *
    1042                 :            :  *   Raises a TypeError if it's not possible to return
    1043                 :            :  *   an awaitable and returns NULL.
    1044                 :            :  */
    1045                 :            : PyObject *
    1046                 :      31939 : _PyCoro_GetAwaitableIter(PyObject *o)
    1047                 :            : {
    1048                 :      31939 :     unaryfunc getter = NULL;
    1049                 :            :     PyTypeObject *ot;
    1050                 :            : 
    1051   [ +  +  +  + ]:      31939 :     if (PyCoro_CheckExact(o) || gen_is_coroutine(o)) {
    1052                 :            :         /* 'o' is a coroutine. */
    1053                 :      18539 :         Py_INCREF(o);
    1054                 :      18539 :         return o;
    1055                 :            :     }
    1056                 :            : 
    1057                 :      13400 :     ot = Py_TYPE(o);
    1058         [ +  + ]:      13400 :     if (ot->tp_as_async != NULL) {
    1059                 :      13389 :         getter = ot->tp_as_async->am_await;
    1060                 :            :     }
    1061         [ +  + ]:      13400 :     if (getter != NULL) {
    1062                 :      13374 :         PyObject *res = (*getter)(o);
    1063         [ +  + ]:      13374 :         if (res != NULL) {
    1064   [ +  +  -  + ]:      13373 :             if (PyCoro_CheckExact(res) || gen_is_coroutine(res)) {
    1065                 :            :                 /* __await__ must return an *iterator*, not
    1066                 :            :                    a coroutine or another awaitable (see PEP 492) */
    1067                 :          1 :                 PyErr_SetString(PyExc_TypeError,
    1068                 :            :                                 "__await__() returned a coroutine");
    1069         [ +  - ]:          1 :                 Py_CLEAR(res);
    1070         [ +  + ]:      13372 :             } else if (!PyIter_Check(res)) {
    1071                 :          5 :                 PyErr_Format(PyExc_TypeError,
    1072                 :            :                              "__await__() returned non-iterator "
    1073                 :            :                              "of type '%.100s'",
    1074                 :          5 :                              Py_TYPE(res)->tp_name);
    1075         [ +  - ]:          5 :                 Py_CLEAR(res);
    1076                 :            :             }
    1077                 :            :         }
    1078                 :      13374 :         return res;
    1079                 :            :     }
    1080                 :            : 
    1081                 :         26 :     PyErr_Format(PyExc_TypeError,
    1082                 :            :                  "object %.100s can't be used in 'await' expression",
    1083                 :            :                  ot->tp_name);
    1084                 :         26 :     return NULL;
    1085                 :            : }
    1086                 :            : 
    1087                 :            : static PyObject *
    1088                 :          6 : coro_repr(PyCoroObject *coro)
    1089                 :            : {
    1090                 :          6 :     return PyUnicode_FromFormat("<coroutine object %S at %p>",
    1091                 :            :                                 coro->cr_qualname, coro);
    1092                 :            : }
    1093                 :            : 
    1094                 :            : static PyObject *
    1095                 :         38 : coro_await(PyCoroObject *coro)
    1096                 :            : {
    1097                 :         38 :     PyCoroWrapper *cw = PyObject_GC_New(PyCoroWrapper, &_PyCoroWrapper_Type);
    1098         [ -  + ]:         38 :     if (cw == NULL) {
    1099                 :          0 :         return NULL;
    1100                 :            :     }
    1101                 :         38 :     Py_INCREF(coro);
    1102                 :         38 :     cw->cw_coroutine = coro;
    1103                 :         38 :     _PyObject_GC_TRACK(cw);
    1104                 :         38 :     return (PyObject *)cw;
    1105                 :            : }
    1106                 :            : 
    1107                 :            : static PyObject *
    1108                 :          9 : coro_get_cr_await(PyCoroObject *coro, void *Py_UNUSED(ignored))
    1109                 :            : {
    1110                 :          9 :     PyObject *yf = _PyGen_yf((PyGenObject *) coro);
    1111         [ +  + ]:          9 :     if (yf == NULL)
    1112                 :          7 :         Py_RETURN_NONE;
    1113                 :          2 :     return yf;
    1114                 :            : }
    1115                 :            : 
    1116                 :            : static PyObject *
    1117                 :          7 : cr_getsuspended(PyCoroObject *coro, void *Py_UNUSED(ignored))
    1118                 :            : {
    1119         [ +  + ]:          7 :     if (coro->cr_frame_state == FRAME_SUSPENDED) {
    1120                 :          2 :         Py_RETURN_TRUE;
    1121                 :            :     }
    1122                 :          5 :     Py_RETURN_FALSE;
    1123                 :            : }
    1124                 :            : 
    1125                 :            : static PyObject *
    1126                 :          9 : cr_getrunning(PyCoroObject *coro, void *Py_UNUSED(ignored))
    1127                 :            : {
    1128         [ +  + ]:          9 :     if (coro->cr_frame_state == FRAME_EXECUTING) {
    1129                 :          2 :         Py_RETURN_TRUE;
    1130                 :            :     }
    1131                 :          7 :     Py_RETURN_FALSE;
    1132                 :            : }
    1133                 :            : 
    1134                 :            : static PyObject *
    1135                 :       3821 : cr_getframe(PyCoroObject *coro, void *Py_UNUSED(ignored))
    1136                 :            : {
    1137                 :       3821 :     return _gen_getframe((PyGenObject *)coro, "cr_frame");
    1138                 :            : }
    1139                 :            : 
    1140                 :            : 
    1141                 :            : static PyGetSetDef coro_getsetlist[] = {
    1142                 :            :     {"__name__", (getter)gen_get_name, (setter)gen_set_name,
    1143                 :            :      PyDoc_STR("name of the coroutine")},
    1144                 :            :     {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname,
    1145                 :            :      PyDoc_STR("qualified name of the coroutine")},
    1146                 :            :     {"cr_await", (getter)coro_get_cr_await, NULL,
    1147                 :            :      PyDoc_STR("object being awaited on, or None")},
    1148                 :            :     {"cr_running", (getter)cr_getrunning, NULL, NULL},
    1149                 :            :     {"cr_frame", (getter)cr_getframe, NULL, NULL},
    1150                 :            :     {"cr_suspended", (getter)cr_getsuspended, NULL, NULL},
    1151                 :            :     {NULL} /* Sentinel */
    1152                 :            : };
    1153                 :            : 
    1154                 :            : static PyMemberDef coro_memberlist[] = {
    1155                 :            :     {"cr_code",      T_OBJECT, offsetof(PyCoroObject, cr_code),     READONLY|PY_AUDIT_READ},
    1156                 :            :     {"cr_origin",    T_OBJECT, offsetof(PyCoroObject, cr_origin_or_finalizer),   READONLY},
    1157                 :            :     {NULL}      /* Sentinel */
    1158                 :            : };
    1159                 :            : 
    1160                 :            : PyDoc_STRVAR(coro_send_doc,
    1161                 :            : "send(arg) -> send 'arg' into coroutine,\n\
    1162                 :            : return next iterated value or raise StopIteration.");
    1163                 :            : 
    1164                 :            : PyDoc_STRVAR(coro_throw_doc,
    1165                 :            : "throw(value)\n\
    1166                 :            : throw(type[,value[,traceback]])\n\
    1167                 :            : \n\
    1168                 :            : Raise exception in coroutine, return next iterated value or raise\n\
    1169                 :            : StopIteration.");
    1170                 :            : 
    1171                 :            : PyDoc_STRVAR(coro_close_doc,
    1172                 :            : "close() -> raise GeneratorExit inside coroutine.");
    1173                 :            : 
    1174                 :            : static PyMethodDef coro_methods[] = {
    1175                 :            :     {"send",(PyCFunction)gen_send, METH_O, coro_send_doc},
    1176                 :            :     {"throw",_PyCFunction_CAST(gen_throw), METH_FASTCALL, coro_throw_doc},
    1177                 :            :     {"close",(PyCFunction)gen_close, METH_NOARGS, coro_close_doc},
    1178                 :            :     {"__sizeof__", (PyCFunction)gen_sizeof, METH_NOARGS, sizeof__doc__},
    1179                 :            :     {NULL, NULL}        /* Sentinel */
    1180                 :            : };
    1181                 :            : 
    1182                 :            : static PyAsyncMethods coro_as_async = {
    1183                 :            :     (unaryfunc)coro_await,                      /* am_await */
    1184                 :            :     0,                                          /* am_aiter */
    1185                 :            :     0,                                          /* am_anext */
    1186                 :            :     (sendfunc)PyGen_am_send,                    /* am_send  */
    1187                 :            : };
    1188                 :            : 
    1189                 :            : PyTypeObject PyCoro_Type = {
    1190                 :            :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    1191                 :            :     "coroutine",                                /* tp_name */
    1192                 :            :     offsetof(PyCoroObject, cr_iframe) +
    1193                 :            :     offsetof(_PyInterpreterFrame, localsplus),       /* tp_basicsize */
    1194                 :            :     sizeof(PyObject *),                         /* tp_itemsize */
    1195                 :            :     /* methods */
    1196                 :            :     (destructor)gen_dealloc,                    /* tp_dealloc */
    1197                 :            :     0,                                          /* tp_vectorcall_offset */
    1198                 :            :     0,                                          /* tp_getattr */
    1199                 :            :     0,                                          /* tp_setattr */
    1200                 :            :     &coro_as_async,                             /* tp_as_async */
    1201                 :            :     (reprfunc)coro_repr,                        /* tp_repr */
    1202                 :            :     0,                                          /* tp_as_number */
    1203                 :            :     0,                                          /* tp_as_sequence */
    1204                 :            :     0,                                          /* tp_as_mapping */
    1205                 :            :     0,                                          /* tp_hash */
    1206                 :            :     0,                                          /* tp_call */
    1207                 :            :     0,                                          /* tp_str */
    1208                 :            :     PyObject_GenericGetAttr,                    /* tp_getattro */
    1209                 :            :     0,                                          /* tp_setattro */
    1210                 :            :     0,                                          /* tp_as_buffer */
    1211                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
    1212                 :            :     0,                                          /* tp_doc */
    1213                 :            :     (traverseproc)gen_traverse,                 /* tp_traverse */
    1214                 :            :     0,                                          /* tp_clear */
    1215                 :            :     0,                                          /* tp_richcompare */
    1216                 :            :     offsetof(PyCoroObject, cr_weakreflist),     /* tp_weaklistoffset */
    1217                 :            :     0,                                          /* tp_iter */
    1218                 :            :     0,                                          /* tp_iternext */
    1219                 :            :     coro_methods,                               /* tp_methods */
    1220                 :            :     coro_memberlist,                            /* tp_members */
    1221                 :            :     coro_getsetlist,                            /* tp_getset */
    1222                 :            :     0,                                          /* tp_base */
    1223                 :            :     0,                                          /* tp_dict */
    1224                 :            :     0,                                          /* tp_descr_get */
    1225                 :            :     0,                                          /* tp_descr_set */
    1226                 :            :     0,                                          /* tp_dictoffset */
    1227                 :            :     0,                                          /* tp_init */
    1228                 :            :     0,                                          /* tp_alloc */
    1229                 :            :     0,                                          /* tp_new */
    1230                 :            :     0,                                          /* tp_free */
    1231                 :            :     0,                                          /* tp_is_gc */
    1232                 :            :     0,                                          /* tp_bases */
    1233                 :            :     0,                                          /* tp_mro */
    1234                 :            :     0,                                          /* tp_cache */
    1235                 :            :     0,                                          /* tp_subclasses */
    1236                 :            :     0,                                          /* tp_weaklist */
    1237                 :            :     0,                                          /* tp_del */
    1238                 :            :     0,                                          /* tp_version_tag */
    1239                 :            :     _PyGen_Finalize,                            /* tp_finalize */
    1240                 :            : };
    1241                 :            : 
    1242                 :            : static void
    1243                 :         38 : coro_wrapper_dealloc(PyCoroWrapper *cw)
    1244                 :            : {
    1245                 :         38 :     _PyObject_GC_UNTRACK((PyObject *)cw);
    1246         [ +  - ]:         38 :     Py_CLEAR(cw->cw_coroutine);
    1247                 :         38 :     PyObject_GC_Del(cw);
    1248                 :         38 : }
    1249                 :            : 
    1250                 :            : static PyObject *
    1251                 :         20 : coro_wrapper_iternext(PyCoroWrapper *cw)
    1252                 :            : {
    1253                 :         20 :     return gen_iternext((PyGenObject *)cw->cw_coroutine);
    1254                 :            : }
    1255                 :            : 
    1256                 :            : static PyObject *
    1257                 :         20 : coro_wrapper_send(PyCoroWrapper *cw, PyObject *arg)
    1258                 :            : {
    1259                 :         20 :     return gen_send((PyGenObject *)cw->cw_coroutine, arg);
    1260                 :            : }
    1261                 :            : 
    1262                 :            : static PyObject *
    1263                 :         12 : coro_wrapper_throw(PyCoroWrapper *cw, PyObject *const *args, Py_ssize_t nargs)
    1264                 :            : {
    1265                 :         12 :     return gen_throw((PyGenObject *)cw->cw_coroutine, args, nargs);
    1266                 :            : }
    1267                 :            : 
    1268                 :            : static PyObject *
    1269                 :         16 : coro_wrapper_close(PyCoroWrapper *cw, PyObject *args)
    1270                 :            : {
    1271                 :         16 :     return gen_close((PyGenObject *)cw->cw_coroutine, args);
    1272                 :            : }
    1273                 :            : 
    1274                 :            : static int
    1275                 :          2 : coro_wrapper_traverse(PyCoroWrapper *cw, visitproc visit, void *arg)
    1276                 :            : {
    1277   [ +  -  -  + ]:          2 :     Py_VISIT((PyObject *)cw->cw_coroutine);
    1278                 :          2 :     return 0;
    1279                 :            : }
    1280                 :            : 
    1281                 :            : static PyMethodDef coro_wrapper_methods[] = {
    1282                 :            :     {"send",(PyCFunction)coro_wrapper_send, METH_O, coro_send_doc},
    1283                 :            :     {"throw",_PyCFunction_CAST(coro_wrapper_throw),
    1284                 :            :     METH_FASTCALL, coro_throw_doc},
    1285                 :            :     {"close",(PyCFunction)coro_wrapper_close, METH_NOARGS, coro_close_doc},
    1286                 :            :     {NULL, NULL}        /* Sentinel */
    1287                 :            : };
    1288                 :            : 
    1289                 :            : PyTypeObject _PyCoroWrapper_Type = {
    1290                 :            :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    1291                 :            :     "coroutine_wrapper",
    1292                 :            :     sizeof(PyCoroWrapper),                      /* tp_basicsize */
    1293                 :            :     0,                                          /* tp_itemsize */
    1294                 :            :     (destructor)coro_wrapper_dealloc,           /* destructor tp_dealloc */
    1295                 :            :     0,                                          /* tp_vectorcall_offset */
    1296                 :            :     0,                                          /* tp_getattr */
    1297                 :            :     0,                                          /* tp_setattr */
    1298                 :            :     0,                                          /* tp_as_async */
    1299                 :            :     0,                                          /* tp_repr */
    1300                 :            :     0,                                          /* tp_as_number */
    1301                 :            :     0,                                          /* tp_as_sequence */
    1302                 :            :     0,                                          /* tp_as_mapping */
    1303                 :            :     0,                                          /* tp_hash */
    1304                 :            :     0,                                          /* tp_call */
    1305                 :            :     0,                                          /* tp_str */
    1306                 :            :     PyObject_GenericGetAttr,                    /* tp_getattro */
    1307                 :            :     0,                                          /* tp_setattro */
    1308                 :            :     0,                                          /* tp_as_buffer */
    1309                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
    1310                 :            :     "A wrapper object implementing __await__ for coroutines.",
    1311                 :            :     (traverseproc)coro_wrapper_traverse,        /* tp_traverse */
    1312                 :            :     0,                                          /* tp_clear */
    1313                 :            :     0,                                          /* tp_richcompare */
    1314                 :            :     0,                                          /* tp_weaklistoffset */
    1315                 :            :     PyObject_SelfIter,                          /* tp_iter */
    1316                 :            :     (iternextfunc)coro_wrapper_iternext,        /* tp_iternext */
    1317                 :            :     coro_wrapper_methods,                       /* tp_methods */
    1318                 :            :     0,                                          /* tp_members */
    1319                 :            :     0,                                          /* tp_getset */
    1320                 :            :     0,                                          /* tp_base */
    1321                 :            :     0,                                          /* tp_dict */
    1322                 :            :     0,                                          /* tp_descr_get */
    1323                 :            :     0,                                          /* tp_descr_set */
    1324                 :            :     0,                                          /* tp_dictoffset */
    1325                 :            :     0,                                          /* tp_init */
    1326                 :            :     0,                                          /* tp_alloc */
    1327                 :            :     0,                                          /* tp_new */
    1328                 :            :     0,                                          /* tp_free */
    1329                 :            : };
    1330                 :            : 
    1331                 :            : static PyObject *
    1332                 :       3170 : compute_cr_origin(int origin_depth, _PyInterpreterFrame *current_frame)
    1333                 :            : {
    1334                 :       3170 :     _PyInterpreterFrame *frame = current_frame;
    1335                 :            :     /* First count how many frames we have */
    1336                 :       3170 :     int frame_count = 0;
    1337   [ +  +  +  + ]:      34852 :     for (; frame && frame_count < origin_depth; ++frame_count) {
    1338                 :      31682 :         frame = frame->previous;
    1339                 :            :     }
    1340                 :            : 
    1341                 :            :     /* Now collect them */
    1342                 :       3170 :     PyObject *cr_origin = PyTuple_New(frame_count);
    1343         [ -  + ]:       3170 :     if (cr_origin == NULL) {
    1344                 :          0 :         return NULL;
    1345                 :            :     }
    1346                 :       3170 :     frame = current_frame;
    1347         [ +  + ]:      34852 :     for (int i = 0; i < frame_count; ++i) {
    1348                 :      31682 :         PyCodeObject *code = frame->f_code;
    1349                 :      31682 :         int line = _PyInterpreterFrame_GetLine(frame);
    1350                 :      31682 :         PyObject *frameinfo = Py_BuildValue("OiO", code->co_filename, line,
    1351                 :            :                                             code->co_name);
    1352         [ -  + ]:      31682 :         if (!frameinfo) {
    1353                 :          0 :             Py_DECREF(cr_origin);
    1354                 :          0 :             return NULL;
    1355                 :            :         }
    1356                 :      31682 :         PyTuple_SET_ITEM(cr_origin, i, frameinfo);
    1357                 :      31682 :         frame = frame->previous;
    1358                 :            :     }
    1359                 :            : 
    1360                 :       3170 :     return cr_origin;
    1361                 :            : }
    1362                 :            : 
    1363                 :            : PyObject *
    1364                 :          0 : PyCoro_New(PyFrameObject *f, PyObject *name, PyObject *qualname)
    1365                 :            : {
    1366                 :          0 :     PyObject *coro = gen_new_with_qualname(&PyCoro_Type, f, name, qualname);
    1367         [ #  # ]:          0 :     if (!coro) {
    1368                 :          0 :         return NULL;
    1369                 :            :     }
    1370                 :            : 
    1371                 :          0 :     PyThreadState *tstate = _PyThreadState_GET();
    1372                 :          0 :     int origin_depth = tstate->coroutine_origin_tracking_depth;
    1373                 :            : 
    1374         [ #  # ]:          0 :     if (origin_depth == 0) {
    1375                 :          0 :         ((PyCoroObject *)coro)->cr_origin_or_finalizer = NULL;
    1376                 :            :     } else {
    1377                 :          0 :         PyObject *cr_origin = compute_cr_origin(origin_depth, _PyEval_GetFrame());
    1378                 :          0 :         ((PyCoroObject *)coro)->cr_origin_or_finalizer = cr_origin;
    1379         [ #  # ]:          0 :         if (!cr_origin) {
    1380                 :          0 :             Py_DECREF(coro);
    1381                 :          0 :             return NULL;
    1382                 :            :         }
    1383                 :            :     }
    1384                 :            : 
    1385                 :          0 :     return coro;
    1386                 :            : }
    1387                 :            : 
    1388                 :            : 
    1389                 :            : /* ========= Asynchronous Generators ========= */
    1390                 :            : 
    1391                 :            : 
    1392                 :            : typedef enum {
    1393                 :            :     AWAITABLE_STATE_INIT,   /* new awaitable, has not yet been iterated */
    1394                 :            :     AWAITABLE_STATE_ITER,   /* being iterated */
    1395                 :            :     AWAITABLE_STATE_CLOSED, /* closed */
    1396                 :            : } AwaitableState;
    1397                 :            : 
    1398                 :            : 
    1399                 :            : typedef struct PyAsyncGenASend {
    1400                 :            :     PyObject_HEAD
    1401                 :            :     PyAsyncGenObject *ags_gen;
    1402                 :            : 
    1403                 :            :     /* Can be NULL, when in the __anext__() mode
    1404                 :            :        (equivalent of "asend(None)") */
    1405                 :            :     PyObject *ags_sendval;
    1406                 :            : 
    1407                 :            :     AwaitableState ags_state;
    1408                 :            : } PyAsyncGenASend;
    1409                 :            : 
    1410                 :            : 
    1411                 :            : typedef struct PyAsyncGenAThrow {
    1412                 :            :     PyObject_HEAD
    1413                 :            :     PyAsyncGenObject *agt_gen;
    1414                 :            : 
    1415                 :            :     /* Can be NULL, when in the "aclose()" mode
    1416                 :            :        (equivalent of "athrow(GeneratorExit)") */
    1417                 :            :     PyObject *agt_args;
    1418                 :            : 
    1419                 :            :     AwaitableState agt_state;
    1420                 :            : } PyAsyncGenAThrow;
    1421                 :            : 
    1422                 :            : 
    1423                 :            : typedef struct _PyAsyncGenWrappedValue {
    1424                 :            :     PyObject_HEAD
    1425                 :            :     PyObject *agw_val;
    1426                 :            : } _PyAsyncGenWrappedValue;
    1427                 :            : 
    1428                 :            : 
    1429                 :            : #define _PyAsyncGenWrappedValue_CheckExact(o) \
    1430                 :            :                     Py_IS_TYPE(o, &_PyAsyncGenWrappedValue_Type)
    1431                 :            : 
    1432                 :            : #define PyAsyncGenASend_CheckExact(o) \
    1433                 :            :                     Py_IS_TYPE(o, &_PyAsyncGenASend_Type)
    1434                 :            : 
    1435                 :            : 
    1436                 :            : static int
    1437                 :         54 : async_gen_traverse(PyAsyncGenObject *gen, visitproc visit, void *arg)
    1438                 :            : {
    1439   [ +  +  -  + ]:         54 :     Py_VISIT(gen->ag_origin_or_finalizer);
    1440                 :         54 :     return gen_traverse((PyGenObject*)gen, visit, arg);
    1441                 :            : }
    1442                 :            : 
    1443                 :            : 
    1444                 :            : static PyObject *
    1445                 :          1 : async_gen_repr(PyAsyncGenObject *o)
    1446                 :            : {
    1447                 :          1 :     return PyUnicode_FromFormat("<async_generator object %S at %p>",
    1448                 :            :                                 o->ag_qualname, o);
    1449                 :            : }
    1450                 :            : 
    1451                 :            : 
    1452                 :            : static int
    1453                 :        665 : async_gen_init_hooks(PyAsyncGenObject *o)
    1454                 :            : {
    1455                 :            :     PyThreadState *tstate;
    1456                 :            :     PyObject *finalizer;
    1457                 :            :     PyObject *firstiter;
    1458                 :            : 
    1459         [ +  + ]:        665 :     if (o->ag_hooks_inited) {
    1460                 :        441 :         return 0;
    1461                 :            :     }
    1462                 :            : 
    1463                 :        224 :     o->ag_hooks_inited = 1;
    1464                 :            : 
    1465                 :        224 :     tstate = _PyThreadState_GET();
    1466                 :            : 
    1467                 :        224 :     finalizer = tstate->async_gen_finalizer;
    1468         [ +  + ]:        224 :     if (finalizer) {
    1469                 :        145 :         Py_INCREF(finalizer);
    1470                 :        145 :         o->ag_origin_or_finalizer = finalizer;
    1471                 :            :     }
    1472                 :            : 
    1473                 :        224 :     firstiter = tstate->async_gen_firstiter;
    1474         [ +  + ]:        224 :     if (firstiter) {
    1475                 :            :         PyObject *res;
    1476                 :            : 
    1477                 :        145 :         Py_INCREF(firstiter);
    1478                 :        145 :         res = PyObject_CallOneArg(firstiter, (PyObject *)o);
    1479                 :        145 :         Py_DECREF(firstiter);
    1480         [ -  + ]:        145 :         if (res == NULL) {
    1481                 :          0 :             return 1;
    1482                 :            :         }
    1483                 :        145 :         Py_DECREF(res);
    1484                 :            :     }
    1485                 :            : 
    1486                 :        224 :     return 0;
    1487                 :            : }
    1488                 :            : 
    1489                 :            : 
    1490                 :            : static PyObject *
    1491                 :        589 : async_gen_anext(PyAsyncGenObject *o)
    1492                 :            : {
    1493         [ -  + ]:        589 :     if (async_gen_init_hooks(o)) {
    1494                 :          0 :         return NULL;
    1495                 :            :     }
    1496                 :        589 :     return async_gen_asend_new(o, NULL);
    1497                 :            : }
    1498                 :            : 
    1499                 :            : 
    1500                 :            : static PyObject *
    1501                 :         22 : async_gen_asend(PyAsyncGenObject *o, PyObject *arg)
    1502                 :            : {
    1503         [ -  + ]:         22 :     if (async_gen_init_hooks(o)) {
    1504                 :          0 :         return NULL;
    1505                 :            :     }
    1506                 :         22 :     return async_gen_asend_new(o, arg);
    1507                 :            : }
    1508                 :            : 
    1509                 :            : 
    1510                 :            : static PyObject *
    1511                 :         31 : async_gen_aclose(PyAsyncGenObject *o, PyObject *arg)
    1512                 :            : {
    1513         [ -  + ]:         31 :     if (async_gen_init_hooks(o)) {
    1514                 :          0 :         return NULL;
    1515                 :            :     }
    1516                 :         31 :     return async_gen_athrow_new(o, NULL);
    1517                 :            : }
    1518                 :            : 
    1519                 :            : static PyObject *
    1520                 :         23 : async_gen_athrow(PyAsyncGenObject *o, PyObject *args)
    1521                 :            : {
    1522         [ -  + ]:         23 :     if (async_gen_init_hooks(o)) {
    1523                 :          0 :         return NULL;
    1524                 :            :     }
    1525                 :         23 :     return async_gen_athrow_new(o, args);
    1526                 :            : }
    1527                 :            : 
    1528                 :            : static PyObject *
    1529                 :          2 : ag_getframe(PyAsyncGenObject *ag, void *Py_UNUSED(ignored))
    1530                 :            : {
    1531                 :          2 :     return _gen_getframe((PyGenObject *)ag, "ag_frame");
    1532                 :            : }
    1533                 :            : 
    1534                 :            : static PyGetSetDef async_gen_getsetlist[] = {
    1535                 :            :     {"__name__", (getter)gen_get_name, (setter)gen_set_name,
    1536                 :            :      PyDoc_STR("name of the async generator")},
    1537                 :            :     {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname,
    1538                 :            :      PyDoc_STR("qualified name of the async generator")},
    1539                 :            :     {"ag_await", (getter)coro_get_cr_await, NULL,
    1540                 :            :      PyDoc_STR("object being awaited on, or None")},
    1541                 :            :      {"ag_frame",  (getter)ag_getframe, NULL, NULL},
    1542                 :            :     {NULL} /* Sentinel */
    1543                 :            : };
    1544                 :            : 
    1545                 :            : static PyMemberDef async_gen_memberlist[] = {
    1546                 :            :     {"ag_running", T_BOOL,   offsetof(PyAsyncGenObject, ag_running_async),
    1547                 :            :         READONLY},
    1548                 :            :     {"ag_code",    T_OBJECT, offsetof(PyAsyncGenObject, ag_code),    READONLY|PY_AUDIT_READ},
    1549                 :            :     {NULL}      /* Sentinel */
    1550                 :            : };
    1551                 :            : 
    1552                 :            : PyDoc_STRVAR(async_aclose_doc,
    1553                 :            : "aclose() -> raise GeneratorExit inside generator.");
    1554                 :            : 
    1555                 :            : PyDoc_STRVAR(async_asend_doc,
    1556                 :            : "asend(v) -> send 'v' in generator.");
    1557                 :            : 
    1558                 :            : PyDoc_STRVAR(async_athrow_doc,
    1559                 :            : "athrow(typ[,val[,tb]]) -> raise exception in generator.");
    1560                 :            : 
    1561                 :            : static PyMethodDef async_gen_methods[] = {
    1562                 :            :     {"asend", (PyCFunction)async_gen_asend, METH_O, async_asend_doc},
    1563                 :            :     {"athrow",(PyCFunction)async_gen_athrow, METH_VARARGS, async_athrow_doc},
    1564                 :            :     {"aclose", (PyCFunction)async_gen_aclose, METH_NOARGS, async_aclose_doc},
    1565                 :            :     {"__sizeof__", (PyCFunction)gen_sizeof, METH_NOARGS, sizeof__doc__},
    1566                 :            :     {"__class_getitem__",    Py_GenericAlias,
    1567                 :            :     METH_O|METH_CLASS,       PyDoc_STR("See PEP 585")},
    1568                 :            :     {NULL, NULL}        /* Sentinel */
    1569                 :            : };
    1570                 :            : 
    1571                 :            : 
    1572                 :            : static PyAsyncMethods async_gen_as_async = {
    1573                 :            :     0,                                          /* am_await */
    1574                 :            :     PyObject_SelfIter,                          /* am_aiter */
    1575                 :            :     (unaryfunc)async_gen_anext,                 /* am_anext */
    1576                 :            :     (sendfunc)PyGen_am_send,                    /* am_send  */
    1577                 :            : };
    1578                 :            : 
    1579                 :            : 
    1580                 :            : PyTypeObject PyAsyncGen_Type = {
    1581                 :            :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    1582                 :            :     "async_generator",                          /* tp_name */
    1583                 :            :     offsetof(PyAsyncGenObject, ag_iframe) +
    1584                 :            :     offsetof(_PyInterpreterFrame, localsplus),       /* tp_basicsize */
    1585                 :            :     sizeof(PyObject *),                         /* tp_itemsize */
    1586                 :            :     /* methods */
    1587                 :            :     (destructor)gen_dealloc,                    /* tp_dealloc */
    1588                 :            :     0,                                          /* tp_vectorcall_offset */
    1589                 :            :     0,                                          /* tp_getattr */
    1590                 :            :     0,                                          /* tp_setattr */
    1591                 :            :     &async_gen_as_async,                        /* tp_as_async */
    1592                 :            :     (reprfunc)async_gen_repr,                   /* tp_repr */
    1593                 :            :     0,                                          /* tp_as_number */
    1594                 :            :     0,                                          /* tp_as_sequence */
    1595                 :            :     0,                                          /* tp_as_mapping */
    1596                 :            :     0,                                          /* tp_hash */
    1597                 :            :     0,                                          /* tp_call */
    1598                 :            :     0,                                          /* tp_str */
    1599                 :            :     PyObject_GenericGetAttr,                    /* tp_getattro */
    1600                 :            :     0,                                          /* tp_setattro */
    1601                 :            :     0,                                          /* tp_as_buffer */
    1602                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
    1603                 :            :     0,                                          /* tp_doc */
    1604                 :            :     (traverseproc)async_gen_traverse,           /* tp_traverse */
    1605                 :            :     0,                                          /* tp_clear */
    1606                 :            :     0,                                          /* tp_richcompare */
    1607                 :            :     offsetof(PyAsyncGenObject, ag_weakreflist), /* tp_weaklistoffset */
    1608                 :            :     0,                                          /* tp_iter */
    1609                 :            :     0,                                          /* tp_iternext */
    1610                 :            :     async_gen_methods,                          /* tp_methods */
    1611                 :            :     async_gen_memberlist,                       /* tp_members */
    1612                 :            :     async_gen_getsetlist,                       /* tp_getset */
    1613                 :            :     0,                                          /* tp_base */
    1614                 :            :     0,                                          /* tp_dict */
    1615                 :            :     0,                                          /* tp_descr_get */
    1616                 :            :     0,                                          /* tp_descr_set */
    1617                 :            :     0,                                          /* tp_dictoffset */
    1618                 :            :     0,                                          /* tp_init */
    1619                 :            :     0,                                          /* tp_alloc */
    1620                 :            :     0,                                          /* tp_new */
    1621                 :            :     0,                                          /* tp_free */
    1622                 :            :     0,                                          /* tp_is_gc */
    1623                 :            :     0,                                          /* tp_bases */
    1624                 :            :     0,                                          /* tp_mro */
    1625                 :            :     0,                                          /* tp_cache */
    1626                 :            :     0,                                          /* tp_subclasses */
    1627                 :            :     0,                                          /* tp_weaklist */
    1628                 :            :     0,                                          /* tp_del */
    1629                 :            :     0,                                          /* tp_version_tag */
    1630                 :            :     _PyGen_Finalize,                            /* tp_finalize */
    1631                 :            : };
    1632                 :            : 
    1633                 :            : 
    1634                 :            : #if _PyAsyncGen_MAXFREELIST > 0
    1635                 :            : static struct _Py_async_gen_state *
    1636                 :       2090 : get_async_gen_state(void)
    1637                 :            : {
    1638                 :       2090 :     PyInterpreterState *interp = _PyInterpreterState_GET();
    1639                 :       2090 :     return &interp->async_gen;
    1640                 :            : }
    1641                 :            : #endif
    1642                 :            : 
    1643                 :            : 
    1644                 :            : PyObject *
    1645                 :          0 : PyAsyncGen_New(PyFrameObject *f, PyObject *name, PyObject *qualname)
    1646                 :            : {
    1647                 :            :     PyAsyncGenObject *o;
    1648                 :          0 :     o = (PyAsyncGenObject *)gen_new_with_qualname(
    1649                 :            :         &PyAsyncGen_Type, f, name, qualname);
    1650         [ #  # ]:          0 :     if (o == NULL) {
    1651                 :          0 :         return NULL;
    1652                 :            :     }
    1653                 :          0 :     o->ag_origin_or_finalizer = NULL;
    1654                 :          0 :     o->ag_closed = 0;
    1655                 :          0 :     o->ag_hooks_inited = 0;
    1656                 :          0 :     o->ag_running_async = 0;
    1657                 :          0 :     return (PyObject*)o;
    1658                 :            : }
    1659                 :            : 
    1660                 :            : 
    1661                 :            : void
    1662                 :      29824 : _PyAsyncGen_ClearFreeLists(PyInterpreterState *interp)
    1663                 :            : {
    1664                 :            : #if _PyAsyncGen_MAXFREELIST > 0
    1665                 :      29824 :     struct _Py_async_gen_state *state = &interp->async_gen;
    1666                 :            : 
    1667         [ +  + ]:      29839 :     while (state->value_numfree) {
    1668                 :            :         _PyAsyncGenWrappedValue *o;
    1669                 :         15 :         o = state->value_freelist[--state->value_numfree];
    1670                 :            :         assert(_PyAsyncGenWrappedValue_CheckExact(o));
    1671                 :         15 :         PyObject_GC_Del(o);
    1672                 :            :     }
    1673                 :            : 
    1674         [ +  + ]:      29847 :     while (state->asend_numfree) {
    1675                 :            :         PyAsyncGenASend *o;
    1676                 :         23 :         o = state->asend_freelist[--state->asend_numfree];
    1677                 :            :         assert(Py_IS_TYPE(o, &_PyAsyncGenASend_Type));
    1678                 :         23 :         PyObject_GC_Del(o);
    1679                 :            :     }
    1680                 :            : #endif
    1681                 :      29824 : }
    1682                 :            : 
    1683                 :            : void
    1684                 :       3125 : _PyAsyncGen_Fini(PyInterpreterState *interp)
    1685                 :            : {
    1686                 :       3125 :     _PyAsyncGen_ClearFreeLists(interp);
    1687                 :            : #if defined(Py_DEBUG) && _PyAsyncGen_MAXFREELIST > 0
    1688                 :            :     struct _Py_async_gen_state *state = &interp->async_gen;
    1689                 :            :     state->value_numfree = -1;
    1690                 :            :     state->asend_numfree = -1;
    1691                 :            : #endif
    1692                 :       3125 : }
    1693                 :            : 
    1694                 :            : 
    1695                 :            : static PyObject *
    1696                 :        769 : async_gen_unwrap_value(PyAsyncGenObject *gen, PyObject *result)
    1697                 :            : {
    1698         [ +  + ]:        769 :     if (result == NULL) {
    1699         [ +  + ]:        200 :         if (!PyErr_Occurred()) {
    1700                 :         10 :             PyErr_SetNone(PyExc_StopAsyncIteration);
    1701                 :            :         }
    1702                 :            : 
    1703         [ +  + ]:        200 :         if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration)
    1704         [ +  + ]:         40 :             || PyErr_ExceptionMatches(PyExc_GeneratorExit)
    1705                 :            :         ) {
    1706                 :        161 :             gen->ag_closed = 1;
    1707                 :            :         }
    1708                 :            : 
    1709                 :        200 :         gen->ag_running_async = 0;
    1710                 :        200 :         return NULL;
    1711                 :            :     }
    1712                 :            : 
    1713         [ +  + ]:        569 :     if (_PyAsyncGenWrappedValue_CheckExact(result)) {
    1714                 :            :         /* async yield */
    1715                 :        432 :         _PyGen_SetStopIterationValue(((_PyAsyncGenWrappedValue*)result)->agw_val);
    1716                 :        432 :         Py_DECREF(result);
    1717                 :        432 :         gen->ag_running_async = 0;
    1718                 :        432 :         return NULL;
    1719                 :            :     }
    1720                 :            : 
    1721                 :        137 :     return result;
    1722                 :            : }
    1723                 :            : 
    1724                 :            : 
    1725                 :            : /* ---------- Async Generator ASend Awaitable ------------ */
    1726                 :            : 
    1727                 :            : 
    1728                 :            : static void
    1729                 :        611 : async_gen_asend_dealloc(PyAsyncGenASend *o)
    1730                 :            : {
    1731                 :        611 :     _PyObject_GC_UNTRACK((PyObject *)o);
    1732         [ +  - ]:        611 :     Py_CLEAR(o->ags_gen);
    1733         [ +  + ]:        611 :     Py_CLEAR(o->ags_sendval);
    1734                 :            : #if _PyAsyncGen_MAXFREELIST > 0
    1735                 :        611 :     struct _Py_async_gen_state *state = get_async_gen_state();
    1736                 :            : #ifdef Py_DEBUG
    1737                 :            :     // async_gen_asend_dealloc() must not be called after _PyAsyncGen_Fini()
    1738                 :            :     assert(state->asend_numfree != -1);
    1739                 :            : #endif
    1740         [ +  - ]:        611 :     if (state->asend_numfree < _PyAsyncGen_MAXFREELIST) {
    1741                 :            :         assert(PyAsyncGenASend_CheckExact(o));
    1742                 :        611 :         state->asend_freelist[state->asend_numfree++] = o;
    1743                 :            :     }
    1744                 :            :     else
    1745                 :            : #endif
    1746                 :            :     {
    1747                 :          0 :         PyObject_GC_Del(o);
    1748                 :            :     }
    1749                 :        611 : }
    1750                 :            : 
    1751                 :            : static int
    1752                 :          6 : async_gen_asend_traverse(PyAsyncGenASend *o, visitproc visit, void *arg)
    1753                 :            : {
    1754   [ +  -  -  + ]:          6 :     Py_VISIT(o->ags_gen);
    1755   [ -  +  -  - ]:          6 :     Py_VISIT(o->ags_sendval);
    1756                 :          6 :     return 0;
    1757                 :            : }
    1758                 :            : 
    1759                 :            : 
    1760                 :            : static PyObject *
    1761                 :        722 : async_gen_asend_send(PyAsyncGenASend *o, PyObject *arg)
    1762                 :            : {
    1763                 :            :     PyObject *result;
    1764                 :            : 
    1765         [ +  + ]:        722 :     if (o->ags_state == AWAITABLE_STATE_CLOSED) {
    1766                 :          2 :         PyErr_SetString(
    1767                 :            :             PyExc_RuntimeError,
    1768                 :            :             "cannot reuse already awaited __anext__()/asend()");
    1769                 :          2 :         return NULL;
    1770                 :            :     }
    1771                 :            : 
    1772         [ +  + ]:        720 :     if (o->ags_state == AWAITABLE_STATE_INIT) {
    1773         [ -  + ]:        606 :         if (o->ags_gen->ag_running_async) {
    1774                 :          0 :             PyErr_SetString(
    1775                 :            :                 PyExc_RuntimeError,
    1776                 :            :                 "anext(): asynchronous generator is already running");
    1777                 :          0 :             return NULL;
    1778                 :            :         }
    1779                 :            : 
    1780   [ +  +  +  + ]:        606 :         if (arg == NULL || arg == Py_None) {
    1781                 :        603 :             arg = o->ags_sendval;
    1782                 :            :         }
    1783                 :        606 :         o->ags_state = AWAITABLE_STATE_ITER;
    1784                 :            :     }
    1785                 :            : 
    1786                 :        720 :     o->ags_gen->ag_running_async = 1;
    1787                 :        720 :     result = gen_send((PyGenObject*)o->ags_gen, arg);
    1788                 :        720 :     result = async_gen_unwrap_value(o->ags_gen, result);
    1789                 :            : 
    1790         [ +  + ]:        720 :     if (result == NULL) {
    1791                 :        596 :         o->ags_state = AWAITABLE_STATE_CLOSED;
    1792                 :            :     }
    1793                 :            : 
    1794                 :        720 :     return result;
    1795                 :            : }
    1796                 :            : 
    1797                 :            : 
    1798                 :            : static PyObject *
    1799                 :        710 : async_gen_asend_iternext(PyAsyncGenASend *o)
    1800                 :            : {
    1801                 :        710 :     return async_gen_asend_send(o, NULL);
    1802                 :            : }
    1803                 :            : 
    1804                 :            : 
    1805                 :            : static PyObject *
    1806                 :         22 : async_gen_asend_throw(PyAsyncGenASend *o, PyObject *const *args, Py_ssize_t nargs)
    1807                 :            : {
    1808                 :            :     PyObject *result;
    1809                 :            : 
    1810         [ -  + ]:         22 :     if (o->ags_state == AWAITABLE_STATE_CLOSED) {
    1811                 :          0 :         PyErr_SetString(
    1812                 :            :             PyExc_RuntimeError,
    1813                 :            :             "cannot reuse already awaited __anext__()/asend()");
    1814                 :          0 :         return NULL;
    1815                 :            :     }
    1816                 :            : 
    1817                 :         22 :     result = gen_throw((PyGenObject*)o->ags_gen, args, nargs);
    1818                 :         22 :     result = async_gen_unwrap_value(o->ags_gen, result);
    1819                 :            : 
    1820         [ +  + ]:         22 :     if (result == NULL) {
    1821                 :         13 :         o->ags_state = AWAITABLE_STATE_CLOSED;
    1822                 :            :     }
    1823                 :            : 
    1824                 :         22 :     return result;
    1825                 :            : }
    1826                 :            : 
    1827                 :            : 
    1828                 :            : static PyObject *
    1829                 :          9 : async_gen_asend_close(PyAsyncGenASend *o, PyObject *args)
    1830                 :            : {
    1831                 :          9 :     o->ags_state = AWAITABLE_STATE_CLOSED;
    1832                 :          9 :     Py_RETURN_NONE;
    1833                 :            : }
    1834                 :            : 
    1835                 :            : 
    1836                 :            : static PyMethodDef async_gen_asend_methods[] = {
    1837                 :            :     {"send", (PyCFunction)async_gen_asend_send, METH_O, send_doc},
    1838                 :            :     {"throw", _PyCFunction_CAST(async_gen_asend_throw), METH_FASTCALL, throw_doc},
    1839                 :            :     {"close", (PyCFunction)async_gen_asend_close, METH_NOARGS, close_doc},
    1840                 :            :     {NULL, NULL}        /* Sentinel */
    1841                 :            : };
    1842                 :            : 
    1843                 :            : 
    1844                 :            : static PyAsyncMethods async_gen_asend_as_async = {
    1845                 :            :     PyObject_SelfIter,                          /* am_await */
    1846                 :            :     0,                                          /* am_aiter */
    1847                 :            :     0,                                          /* am_anext */
    1848                 :            :     0,                                          /* am_send  */
    1849                 :            : };
    1850                 :            : 
    1851                 :            : 
    1852                 :            : PyTypeObject _PyAsyncGenASend_Type = {
    1853                 :            :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    1854                 :            :     "async_generator_asend",                    /* tp_name */
    1855                 :            :     sizeof(PyAsyncGenASend),                    /* tp_basicsize */
    1856                 :            :     0,                                          /* tp_itemsize */
    1857                 :            :     /* methods */
    1858                 :            :     (destructor)async_gen_asend_dealloc,        /* tp_dealloc */
    1859                 :            :     0,                                          /* tp_vectorcall_offset */
    1860                 :            :     0,                                          /* tp_getattr */
    1861                 :            :     0,                                          /* tp_setattr */
    1862                 :            :     &async_gen_asend_as_async,                  /* tp_as_async */
    1863                 :            :     0,                                          /* tp_repr */
    1864                 :            :     0,                                          /* tp_as_number */
    1865                 :            :     0,                                          /* tp_as_sequence */
    1866                 :            :     0,                                          /* tp_as_mapping */
    1867                 :            :     0,                                          /* tp_hash */
    1868                 :            :     0,                                          /* tp_call */
    1869                 :            :     0,                                          /* tp_str */
    1870                 :            :     PyObject_GenericGetAttr,                    /* tp_getattro */
    1871                 :            :     0,                                          /* tp_setattro */
    1872                 :            :     0,                                          /* tp_as_buffer */
    1873                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
    1874                 :            :     0,                                          /* tp_doc */
    1875                 :            :     (traverseproc)async_gen_asend_traverse,     /* tp_traverse */
    1876                 :            :     0,                                          /* tp_clear */
    1877                 :            :     0,                                          /* tp_richcompare */
    1878                 :            :     0,                                          /* tp_weaklistoffset */
    1879                 :            :     PyObject_SelfIter,                          /* tp_iter */
    1880                 :            :     (iternextfunc)async_gen_asend_iternext,     /* tp_iternext */
    1881                 :            :     async_gen_asend_methods,                    /* tp_methods */
    1882                 :            :     0,                                          /* tp_members */
    1883                 :            :     0,                                          /* tp_getset */
    1884                 :            :     0,                                          /* tp_base */
    1885                 :            :     0,                                          /* tp_dict */
    1886                 :            :     0,                                          /* tp_descr_get */
    1887                 :            :     0,                                          /* tp_descr_set */
    1888                 :            :     0,                                          /* tp_dictoffset */
    1889                 :            :     0,                                          /* tp_init */
    1890                 :            :     0,                                          /* tp_alloc */
    1891                 :            :     0,                                          /* tp_new */
    1892                 :            : };
    1893                 :            : 
    1894                 :            : 
    1895                 :            : static PyObject *
    1896                 :        611 : async_gen_asend_new(PyAsyncGenObject *gen, PyObject *sendval)
    1897                 :            : {
    1898                 :            :     PyAsyncGenASend *o;
    1899                 :            : #if _PyAsyncGen_MAXFREELIST > 0
    1900                 :        611 :     struct _Py_async_gen_state *state = get_async_gen_state();
    1901                 :            : #ifdef Py_DEBUG
    1902                 :            :     // async_gen_asend_new() must not be called after _PyAsyncGen_Fini()
    1903                 :            :     assert(state->asend_numfree != -1);
    1904                 :            : #endif
    1905         [ +  + ]:        611 :     if (state->asend_numfree) {
    1906                 :        588 :         state->asend_numfree--;
    1907                 :        588 :         o = state->asend_freelist[state->asend_numfree];
    1908                 :        588 :         _Py_NewReference((PyObject *)o);
    1909                 :            :     }
    1910                 :            :     else
    1911                 :            : #endif
    1912                 :            :     {
    1913                 :         23 :         o = PyObject_GC_New(PyAsyncGenASend, &_PyAsyncGenASend_Type);
    1914         [ -  + ]:         23 :         if (o == NULL) {
    1915                 :          0 :             return NULL;
    1916                 :            :         }
    1917                 :            :     }
    1918                 :            : 
    1919                 :        611 :     Py_INCREF(gen);
    1920                 :        611 :     o->ags_gen = gen;
    1921                 :            : 
    1922                 :        611 :     Py_XINCREF(sendval);
    1923                 :        611 :     o->ags_sendval = sendval;
    1924                 :            : 
    1925                 :        611 :     o->ags_state = AWAITABLE_STATE_INIT;
    1926                 :            : 
    1927                 :        611 :     _PyObject_GC_TRACK((PyObject*)o);
    1928                 :        611 :     return (PyObject*)o;
    1929                 :            : }
    1930                 :            : 
    1931                 :            : 
    1932                 :            : /* ---------- Async Generator Value Wrapper ------------ */
    1933                 :            : 
    1934                 :            : 
    1935                 :            : static void
    1936                 :        434 : async_gen_wrapped_val_dealloc(_PyAsyncGenWrappedValue *o)
    1937                 :            : {
    1938                 :        434 :     _PyObject_GC_UNTRACK((PyObject *)o);
    1939         [ +  - ]:        434 :     Py_CLEAR(o->agw_val);
    1940                 :            : #if _PyAsyncGen_MAXFREELIST > 0
    1941                 :        434 :     struct _Py_async_gen_state *state = get_async_gen_state();
    1942                 :            : #ifdef Py_DEBUG
    1943                 :            :     // async_gen_wrapped_val_dealloc() must not be called after _PyAsyncGen_Fini()
    1944                 :            :     assert(state->value_numfree != -1);
    1945                 :            : #endif
    1946         [ +  - ]:        434 :     if (state->value_numfree < _PyAsyncGen_MAXFREELIST) {
    1947                 :            :         assert(_PyAsyncGenWrappedValue_CheckExact(o));
    1948                 :        434 :         state->value_freelist[state->value_numfree++] = o;
    1949                 :            :         OBJECT_STAT_INC(to_freelist);
    1950                 :            :     }
    1951                 :            :     else
    1952                 :            : #endif
    1953                 :            :     {
    1954                 :          0 :         PyObject_GC_Del(o);
    1955                 :            :     }
    1956                 :        434 : }
    1957                 :            : 
    1958                 :            : 
    1959                 :            : static int
    1960                 :          0 : async_gen_wrapped_val_traverse(_PyAsyncGenWrappedValue *o,
    1961                 :            :                                visitproc visit, void *arg)
    1962                 :            : {
    1963   [ #  #  #  # ]:          0 :     Py_VISIT(o->agw_val);
    1964                 :          0 :     return 0;
    1965                 :            : }
    1966                 :            : 
    1967                 :            : 
    1968                 :            : PyTypeObject _PyAsyncGenWrappedValue_Type = {
    1969                 :            :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    1970                 :            :     "async_generator_wrapped_value",            /* tp_name */
    1971                 :            :     sizeof(_PyAsyncGenWrappedValue),            /* tp_basicsize */
    1972                 :            :     0,                                          /* tp_itemsize */
    1973                 :            :     /* methods */
    1974                 :            :     (destructor)async_gen_wrapped_val_dealloc,  /* tp_dealloc */
    1975                 :            :     0,                                          /* tp_vectorcall_offset */
    1976                 :            :     0,                                          /* tp_getattr */
    1977                 :            :     0,                                          /* tp_setattr */
    1978                 :            :     0,                                          /* tp_as_async */
    1979                 :            :     0,                                          /* tp_repr */
    1980                 :            :     0,                                          /* tp_as_number */
    1981                 :            :     0,                                          /* tp_as_sequence */
    1982                 :            :     0,                                          /* tp_as_mapping */
    1983                 :            :     0,                                          /* tp_hash */
    1984                 :            :     0,                                          /* tp_call */
    1985                 :            :     0,                                          /* tp_str */
    1986                 :            :     PyObject_GenericGetAttr,                    /* tp_getattro */
    1987                 :            :     0,                                          /* tp_setattro */
    1988                 :            :     0,                                          /* tp_as_buffer */
    1989                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
    1990                 :            :     0,                                          /* tp_doc */
    1991                 :            :     (traverseproc)async_gen_wrapped_val_traverse, /* tp_traverse */
    1992                 :            :     0,                                          /* tp_clear */
    1993                 :            :     0,                                          /* tp_richcompare */
    1994                 :            :     0,                                          /* tp_weaklistoffset */
    1995                 :            :     0,                                          /* tp_iter */
    1996                 :            :     0,                                          /* tp_iternext */
    1997                 :            :     0,                                          /* tp_methods */
    1998                 :            :     0,                                          /* tp_members */
    1999                 :            :     0,                                          /* tp_getset */
    2000                 :            :     0,                                          /* tp_base */
    2001                 :            :     0,                                          /* tp_dict */
    2002                 :            :     0,                                          /* tp_descr_get */
    2003                 :            :     0,                                          /* tp_descr_set */
    2004                 :            :     0,                                          /* tp_dictoffset */
    2005                 :            :     0,                                          /* tp_init */
    2006                 :            :     0,                                          /* tp_alloc */
    2007                 :            :     0,                                          /* tp_new */
    2008                 :            : };
    2009                 :            : 
    2010                 :            : 
    2011                 :            : PyObject *
    2012                 :        434 : _PyAsyncGenValueWrapperNew(PyObject *val)
    2013                 :            : {
    2014                 :            :     _PyAsyncGenWrappedValue *o;
    2015                 :            :     assert(val);
    2016                 :            : 
    2017                 :            : #if _PyAsyncGen_MAXFREELIST > 0
    2018                 :        434 :     struct _Py_async_gen_state *state = get_async_gen_state();
    2019                 :            : #ifdef Py_DEBUG
    2020                 :            :     // _PyAsyncGenValueWrapperNew() must not be called after _PyAsyncGen_Fini()
    2021                 :            :     assert(state->value_numfree != -1);
    2022                 :            : #endif
    2023         [ +  + ]:        434 :     if (state->value_numfree) {
    2024                 :        419 :         state->value_numfree--;
    2025                 :        419 :         o = state->value_freelist[state->value_numfree];
    2026                 :            :         OBJECT_STAT_INC(from_freelist);
    2027                 :            :         assert(_PyAsyncGenWrappedValue_CheckExact(o));
    2028                 :        419 :         _Py_NewReference((PyObject*)o);
    2029                 :            :     }
    2030                 :            :     else
    2031                 :            : #endif
    2032                 :            :     {
    2033                 :         15 :         o = PyObject_GC_New(_PyAsyncGenWrappedValue,
    2034                 :            :                             &_PyAsyncGenWrappedValue_Type);
    2035         [ -  + ]:         15 :         if (o == NULL) {
    2036                 :          0 :             return NULL;
    2037                 :            :         }
    2038                 :            :     }
    2039                 :        434 :     o->agw_val = val;
    2040                 :        434 :     Py_INCREF(val);
    2041                 :        434 :     _PyObject_GC_TRACK((PyObject*)o);
    2042                 :        434 :     return (PyObject*)o;
    2043                 :            : }
    2044                 :            : 
    2045                 :            : 
    2046                 :            : /* ---------- Async Generator AThrow awaitable ------------ */
    2047                 :            : 
    2048                 :            : 
    2049                 :            : static void
    2050                 :         54 : async_gen_athrow_dealloc(PyAsyncGenAThrow *o)
    2051                 :            : {
    2052                 :         54 :     _PyObject_GC_UNTRACK((PyObject *)o);
    2053         [ +  - ]:         54 :     Py_CLEAR(o->agt_gen);
    2054         [ +  + ]:         54 :     Py_CLEAR(o->agt_args);
    2055                 :         54 :     PyObject_GC_Del(o);
    2056                 :         54 : }
    2057                 :            : 
    2058                 :            : 
    2059                 :            : static int
    2060                 :         20 : async_gen_athrow_traverse(PyAsyncGenAThrow *o, visitproc visit, void *arg)
    2061                 :            : {
    2062   [ +  -  -  + ]:         20 :     Py_VISIT(o->agt_gen);
    2063   [ -  +  -  - ]:         20 :     Py_VISIT(o->agt_args);
    2064                 :         20 :     return 0;
    2065                 :            : }
    2066                 :            : 
    2067                 :            : 
    2068                 :            : static PyObject *
    2069                 :         57 : async_gen_athrow_send(PyAsyncGenAThrow *o, PyObject *arg)
    2070                 :            : {
    2071                 :         57 :     PyGenObject *gen = (PyGenObject*)o->agt_gen;
    2072                 :            :     PyObject *retval;
    2073                 :            : 
    2074         [ +  + ]:         57 :     if (o->agt_state == AWAITABLE_STATE_CLOSED) {
    2075                 :          1 :         PyErr_SetString(
    2076                 :            :             PyExc_RuntimeError,
    2077                 :            :             "cannot reuse already awaited aclose()/athrow()");
    2078                 :          1 :         return NULL;
    2079                 :            :     }
    2080                 :            : 
    2081         [ +  + ]:         56 :     if (gen->gi_frame_state >= FRAME_COMPLETED) {
    2082                 :          7 :         o->agt_state = AWAITABLE_STATE_CLOSED;
    2083                 :          7 :         PyErr_SetNone(PyExc_StopIteration);
    2084                 :          7 :         return NULL;
    2085                 :            :     }
    2086                 :            : 
    2087         [ +  + ]:         49 :     if (o->agt_state == AWAITABLE_STATE_INIT) {
    2088         [ -  + ]:         39 :         if (o->agt_gen->ag_running_async) {
    2089                 :          0 :             o->agt_state = AWAITABLE_STATE_CLOSED;
    2090         [ #  # ]:          0 :             if (o->agt_args == NULL) {
    2091                 :          0 :                 PyErr_SetString(
    2092                 :            :                     PyExc_RuntimeError,
    2093                 :            :                     "aclose(): asynchronous generator is already running");
    2094                 :            :             }
    2095                 :            :             else {
    2096                 :          0 :                 PyErr_SetString(
    2097                 :            :                     PyExc_RuntimeError,
    2098                 :            :                     "athrow(): asynchronous generator is already running");
    2099                 :            :             }
    2100                 :          0 :             return NULL;
    2101                 :            :         }
    2102                 :            : 
    2103         [ -  + ]:         39 :         if (o->agt_gen->ag_closed) {
    2104                 :          0 :             o->agt_state = AWAITABLE_STATE_CLOSED;
    2105                 :          0 :             PyErr_SetNone(PyExc_StopAsyncIteration);
    2106                 :          0 :             return NULL;
    2107                 :            :         }
    2108                 :            : 
    2109         [ -  + ]:         39 :         if (arg != Py_None) {
    2110                 :          0 :             PyErr_SetString(PyExc_RuntimeError, NON_INIT_CORO_MSG);
    2111                 :          0 :             return NULL;
    2112                 :            :         }
    2113                 :            : 
    2114                 :         39 :         o->agt_state = AWAITABLE_STATE_ITER;
    2115                 :         39 :         o->agt_gen->ag_running_async = 1;
    2116                 :            : 
    2117         [ +  + ]:         39 :         if (o->agt_args == NULL) {
    2118                 :            :             /* aclose() mode */
    2119                 :         16 :             o->agt_gen->ag_closed = 1;
    2120                 :            : 
    2121                 :         16 :             retval = _gen_throw((PyGenObject *)gen,
    2122                 :            :                                 0,  /* Do not close generator when
    2123                 :            :                                        PyExc_GeneratorExit is passed */
    2124                 :            :                                 PyExc_GeneratorExit, NULL, NULL);
    2125                 :            : 
    2126   [ +  +  +  + ]:         16 :             if (retval && _PyAsyncGenWrappedValue_CheckExact(retval)) {
    2127                 :          1 :                 Py_DECREF(retval);
    2128                 :          1 :                 goto yield_close;
    2129                 :            :             }
    2130                 :            :         } else {
    2131                 :            :             PyObject *typ;
    2132                 :         23 :             PyObject *tb = NULL;
    2133                 :         23 :             PyObject *val = NULL;
    2134                 :            : 
    2135         [ -  + ]:         23 :             if (!PyArg_UnpackTuple(o->agt_args, "athrow", 1, 3,
    2136                 :            :                                    &typ, &val, &tb)) {
    2137                 :          0 :                 return NULL;
    2138                 :            :             }
    2139                 :            : 
    2140                 :         23 :             retval = _gen_throw((PyGenObject *)gen,
    2141                 :            :                                 0,  /* Do not close generator when
    2142                 :            :                                        PyExc_GeneratorExit is passed */
    2143                 :            :                                 typ, val, tb);
    2144                 :         23 :             retval = async_gen_unwrap_value(o->agt_gen, retval);
    2145                 :            :         }
    2146         [ +  + ]:         38 :         if (retval == NULL) {
    2147                 :         31 :             goto check_error;
    2148                 :            :         }
    2149                 :          7 :         return retval;
    2150                 :            :     }
    2151                 :            : 
    2152                 :            :     assert(o->agt_state == AWAITABLE_STATE_ITER);
    2153                 :            : 
    2154                 :         10 :     retval = gen_send((PyGenObject *)gen, arg);
    2155         [ +  + ]:         10 :     if (o->agt_args) {
    2156                 :          3 :         return async_gen_unwrap_value(o->agt_gen, retval);
    2157                 :            :     } else {
    2158                 :            :         /* aclose() mode */
    2159         [ +  + ]:          7 :         if (retval) {
    2160         [ +  + ]:          4 :             if (_PyAsyncGenWrappedValue_CheckExact(retval)) {
    2161                 :          1 :                 Py_DECREF(retval);
    2162                 :          1 :                 goto yield_close;
    2163                 :            :             }
    2164                 :            :             else {
    2165                 :          3 :                 return retval;
    2166                 :            :             }
    2167                 :            :         }
    2168                 :            :         else {
    2169                 :          3 :             goto check_error;
    2170                 :            :         }
    2171                 :            :     }
    2172                 :            : 
    2173                 :          2 : yield_close:
    2174                 :          2 :     o->agt_gen->ag_running_async = 0;
    2175                 :          2 :     o->agt_state = AWAITABLE_STATE_CLOSED;
    2176                 :          2 :     PyErr_SetString(
    2177                 :            :         PyExc_RuntimeError, ASYNC_GEN_IGNORED_EXIT_MSG);
    2178                 :          2 :     return NULL;
    2179                 :            : 
    2180                 :         34 : check_error:
    2181                 :         34 :     o->agt_gen->ag_running_async = 0;
    2182                 :         34 :     o->agt_state = AWAITABLE_STATE_CLOSED;
    2183   [ +  +  +  + ]:         65 :     if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration) ||
    2184                 :         31 :             PyErr_ExceptionMatches(PyExc_GeneratorExit))
    2185                 :            :     {
    2186         [ +  + ]:         15 :         if (o->agt_args == NULL) {
    2187                 :            :             /* when aclose() is called we don't want to propagate
    2188                 :            :                StopAsyncIteration or GeneratorExit; just raise
    2189                 :            :                StopIteration, signalling that this 'aclose()' await
    2190                 :            :                is done.
    2191                 :            :             */
    2192                 :         12 :             PyErr_Clear();
    2193                 :         12 :             PyErr_SetNone(PyExc_StopIteration);
    2194                 :            :         }
    2195                 :            :     }
    2196                 :         34 :     return NULL;
    2197                 :            : }
    2198                 :            : 
    2199                 :            : 
    2200                 :            : static PyObject *
    2201                 :          9 : async_gen_athrow_throw(PyAsyncGenAThrow *o, PyObject *const *args, Py_ssize_t nargs)
    2202                 :            : {
    2203                 :            :     PyObject *retval;
    2204                 :            : 
    2205         [ -  + ]:          9 :     if (o->agt_state == AWAITABLE_STATE_CLOSED) {
    2206                 :          0 :         PyErr_SetString(
    2207                 :            :             PyExc_RuntimeError,
    2208                 :            :             "cannot reuse already awaited aclose()/athrow()");
    2209                 :          0 :         return NULL;
    2210                 :            :     }
    2211                 :            : 
    2212                 :          9 :     retval = gen_throw((PyGenObject*)o->agt_gen, args, nargs);
    2213         [ +  + ]:          9 :     if (o->agt_args) {
    2214                 :          1 :         return async_gen_unwrap_value(o->agt_gen, retval);
    2215                 :            :     } else {
    2216                 :            :         /* aclose() mode */
    2217   [ -  +  -  - ]:          8 :         if (retval && _PyAsyncGenWrappedValue_CheckExact(retval)) {
    2218                 :          0 :             o->agt_gen->ag_running_async = 0;
    2219                 :          0 :             o->agt_state = AWAITABLE_STATE_CLOSED;
    2220                 :          0 :             Py_DECREF(retval);
    2221                 :          0 :             PyErr_SetString(PyExc_RuntimeError, ASYNC_GEN_IGNORED_EXIT_MSG);
    2222                 :          0 :             return NULL;
    2223                 :            :         }
    2224   [ +  -  +  + ]:         16 :         if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration) ||
    2225                 :          8 :             PyErr_ExceptionMatches(PyExc_GeneratorExit))
    2226                 :            :         {
    2227                 :            :             /* when aclose() is called we don't want to propagate
    2228                 :            :                StopAsyncIteration or GeneratorExit; just raise
    2229                 :            :                StopIteration, signalling that this 'aclose()' await
    2230                 :            :                is done.
    2231                 :            :             */
    2232                 :          1 :             PyErr_Clear();
    2233                 :          1 :             PyErr_SetNone(PyExc_StopIteration);
    2234                 :            :         }
    2235                 :          8 :         return retval;
    2236                 :            :     }
    2237                 :            : }
    2238                 :            : 
    2239                 :            : 
    2240                 :            : static PyObject *
    2241                 :         57 : async_gen_athrow_iternext(PyAsyncGenAThrow *o)
    2242                 :            : {
    2243                 :         57 :     return async_gen_athrow_send(o, Py_None);
    2244                 :            : }
    2245                 :            : 
    2246                 :            : 
    2247                 :            : static PyObject *
    2248                 :          0 : async_gen_athrow_close(PyAsyncGenAThrow *o, PyObject *args)
    2249                 :            : {
    2250                 :          0 :     o->agt_state = AWAITABLE_STATE_CLOSED;
    2251                 :          0 :     Py_RETURN_NONE;
    2252                 :            : }
    2253                 :            : 
    2254                 :            : 
    2255                 :            : static PyMethodDef async_gen_athrow_methods[] = {
    2256                 :            :     {"send", (PyCFunction)async_gen_athrow_send, METH_O, send_doc},
    2257                 :            :     {"throw", _PyCFunction_CAST(async_gen_athrow_throw),
    2258                 :            :     METH_FASTCALL, throw_doc},
    2259                 :            :     {"close", (PyCFunction)async_gen_athrow_close, METH_NOARGS, close_doc},
    2260                 :            :     {NULL, NULL}        /* Sentinel */
    2261                 :            : };
    2262                 :            : 
    2263                 :            : 
    2264                 :            : static PyAsyncMethods async_gen_athrow_as_async = {
    2265                 :            :     PyObject_SelfIter,                          /* am_await */
    2266                 :            :     0,                                          /* am_aiter */
    2267                 :            :     0,                                          /* am_anext */
    2268                 :            :     0,                                          /* am_send  */
    2269                 :            : };
    2270                 :            : 
    2271                 :            : 
    2272                 :            : PyTypeObject _PyAsyncGenAThrow_Type = {
    2273                 :            :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    2274                 :            :     "async_generator_athrow",                   /* tp_name */
    2275                 :            :     sizeof(PyAsyncGenAThrow),                   /* tp_basicsize */
    2276                 :            :     0,                                          /* tp_itemsize */
    2277                 :            :     /* methods */
    2278                 :            :     (destructor)async_gen_athrow_dealloc,       /* tp_dealloc */
    2279                 :            :     0,                                          /* tp_vectorcall_offset */
    2280                 :            :     0,                                          /* tp_getattr */
    2281                 :            :     0,                                          /* tp_setattr */
    2282                 :            :     &async_gen_athrow_as_async,                 /* tp_as_async */
    2283                 :            :     0,                                          /* tp_repr */
    2284                 :            :     0,                                          /* tp_as_number */
    2285                 :            :     0,                                          /* tp_as_sequence */
    2286                 :            :     0,                                          /* tp_as_mapping */
    2287                 :            :     0,                                          /* tp_hash */
    2288                 :            :     0,                                          /* tp_call */
    2289                 :            :     0,                                          /* tp_str */
    2290                 :            :     PyObject_GenericGetAttr,                    /* tp_getattro */
    2291                 :            :     0,                                          /* tp_setattro */
    2292                 :            :     0,                                          /* tp_as_buffer */
    2293                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
    2294                 :            :     0,                                          /* tp_doc */
    2295                 :            :     (traverseproc)async_gen_athrow_traverse,    /* tp_traverse */
    2296                 :            :     0,                                          /* tp_clear */
    2297                 :            :     0,                                          /* tp_richcompare */
    2298                 :            :     0,                                          /* tp_weaklistoffset */
    2299                 :            :     PyObject_SelfIter,                          /* tp_iter */
    2300                 :            :     (iternextfunc)async_gen_athrow_iternext,    /* tp_iternext */
    2301                 :            :     async_gen_athrow_methods,                   /* tp_methods */
    2302                 :            :     0,                                          /* tp_members */
    2303                 :            :     0,                                          /* tp_getset */
    2304                 :            :     0,                                          /* tp_base */
    2305                 :            :     0,                                          /* tp_dict */
    2306                 :            :     0,                                          /* tp_descr_get */
    2307                 :            :     0,                                          /* tp_descr_set */
    2308                 :            :     0,                                          /* tp_dictoffset */
    2309                 :            :     0,                                          /* tp_init */
    2310                 :            :     0,                                          /* tp_alloc */
    2311                 :            :     0,                                          /* tp_new */
    2312                 :            : };
    2313                 :            : 
    2314                 :            : 
    2315                 :            : static PyObject *
    2316                 :         54 : async_gen_athrow_new(PyAsyncGenObject *gen, PyObject *args)
    2317                 :            : {
    2318                 :            :     PyAsyncGenAThrow *o;
    2319                 :         54 :     o = PyObject_GC_New(PyAsyncGenAThrow, &_PyAsyncGenAThrow_Type);
    2320         [ -  + ]:         54 :     if (o == NULL) {
    2321                 :          0 :         return NULL;
    2322                 :            :     }
    2323                 :         54 :     o->agt_gen = gen;
    2324                 :         54 :     o->agt_args = args;
    2325                 :         54 :     o->agt_state = AWAITABLE_STATE_INIT;
    2326                 :         54 :     Py_INCREF(gen);
    2327                 :         54 :     Py_XINCREF(args);
    2328                 :         54 :     _PyObject_GC_TRACK((PyObject*)o);
    2329                 :         54 :     return (PyObject*)o;
    2330                 :            : }

Generated by: LCOV version 1.14