@@ -1541,6 +1541,12 @@ _PyEval_FrameFromPyFunctionAndArgs(PyThreadState *tstate, PyObject* const *args,
15411541 return _PyEvalFramePushAndInit (tstate , con , locals , args , vector_nargs , NULL , 1 );
15421542}
15431543
1544+ static PyObject *
1545+ make_coro (PyThreadState * tstate , PyFrameConstructor * con ,
1546+ PyObject * locals ,
1547+ PyObject * const * args , size_t argcount ,
1548+ PyObject * kwnames );
1549+
15441550PyObject * _Py_HOT_FUNCTION
15451551_PyEval_EvalFrameDefault (PyThreadState * tstate , InterpreterFrame * frame , int throwflag )
15461552{
@@ -4637,40 +4643,44 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
46374643
46384644 // Check if the call can be inlined or not
46394645 PyObject * function = PEEK (oparg + 1 );
4640- int inline_call = 0 ;
46414646 if (Py_TYPE (function ) == & PyFunction_Type ) {
46424647 PyCodeObject * code = (PyCodeObject * )PyFunction_GET_CODE (function );
4643- int is_coro = code -> co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR );
4644- inline_call = (is_coro || cframe .use_tracing ) ? 0 : 1 ;
4648+ STACK_SHRINK (oparg + 1 );
4649+ if ((code -> co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR )) == 0 ) {
4650+ InterpreterFrame * new_frame = _PyEval_FrameFromPyFunctionAndArgs (tstate , stack_pointer + 1 , oparg , function );
4651+ if (new_frame == NULL ) {
4652+ // When we exit here, we own all variables in the stack (the frame creation has not stolen
4653+ // any variable) so we need to clean the whole stack (done in the "error" label).
4654+ goto error ;
4655+ }
4656+ assert (tstate -> interp -> eval_frame != NULL );
4657+ // The frame has stolen all the arguments from the stack, so there is no need to clean up them
4658+ Py_DECREF (function );
4659+ _PyFrame_SetStackPointer (frame , stack_pointer );
4660+ new_frame -> depth = frame -> depth + 1 ;
4661+ tstate -> frame = frame = new_frame ;
4662+ goto start_frame ;
4663+ }
4664+ else {
4665+ /* Callable is a generator or coroutine function: create coroutine or generator. */
4666+ PyObject * locals = code -> co_flags & CO_OPTIMIZED ? NULL : PyFunction_GET_GLOBALS (function );
4667+ res = make_coro (tstate , PyFunction_AS_FRAME_CONSTRUCTOR (function ), locals , stack_pointer + 1 , oparg , NULL );
4668+ for (int i = 0 ; i < oparg + 1 ; i ++ ) {
4669+ Py_DECREF (stack_pointer [i ]);
4670+ }
4671+ }
46454672 }
4646-
4647- if (!inline_call ) {
4673+ else {
46484674 PyObject * * sp = stack_pointer ;
46494675 res = call_function (tstate , & sp , oparg , NULL , cframe .use_tracing );
46504676 stack_pointer = sp ;
4651- PUSH (res );
4652- if (res == NULL ) {
4653- goto error ;
4654- }
4655- CHECK_EVAL_BREAKER ();
4656- DISPATCH ();
46574677 }
4658-
4659- assert (!cframe .use_tracing );
4660- InterpreterFrame * new_frame = _PyEval_FrameFromPyFunctionAndArgs (tstate , stack_pointer - oparg , oparg , function );
4661- if (new_frame == NULL ) {
4662- // When we exit here, we own all variables in the stack (the frame creation has not stolen
4663- // any variable) so we need to clean the whole stack (done in the "error" label).
4678+ PUSH (res );
4679+ if (res == NULL ) {
46644680 goto error ;
46654681 }
4666- assert (tstate -> interp -> eval_frame != NULL );
4667- // The frame has stolen all the arguments from the stack, so there is no need to clean up them
4668- STACK_SHRINK (oparg + 1 );
4669- Py_DECREF (function );
4670- _PyFrame_SetStackPointer (frame , stack_pointer );
4671- new_frame -> depth = frame -> depth + 1 ;
4672- tstate -> frame = frame = new_frame ;
4673- goto start_frame ;
4682+ CHECK_EVAL_BREAKER ();
4683+ DISPATCH ();
46744684 }
46754685
46764686 TARGET (CALL_FUNCTION_KW ): {
0 commit comments