LCOV - code coverage report
Current view: top level - Objects - genobject.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 734 854 85.9 %
Date: 2022-07-07 18:19:46 Functions: 71 78 91.0 %

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

Generated by: LCOV version 1.14