LCOV - code coverage report
Current view: top level - Objects - genobject.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit 5e6661bce9] Lines: 184 792 23.2 %
Date: 2023-03-20 08:15:36 Functions: 17 85 20.0 %
Branches: 87 460 18.9 %

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

Generated by: LCOV version 1.14