@@ -1541,6 +1541,12 @@ _PyEval_FrameFromPyFunctionAndArgs(PyThreadState *tstate, PyObject* const *args,
1541
1541
return _PyEvalFramePushAndInit (tstate , con , locals , args , vector_nargs , NULL , 1 );
1542
1542
}
1543
1543
1544
+ static PyObject *
1545
+ make_coro (PyThreadState * tstate , PyFrameConstructor * con ,
1546
+ PyObject * locals ,
1547
+ PyObject * const * args , size_t argcount ,
1548
+ PyObject * kwnames );
1549
+
1544
1550
PyObject * _Py_HOT_FUNCTION
1545
1551
_PyEval_EvalFrameDefault (PyThreadState * tstate , InterpreterFrame * frame , int throwflag )
1546
1552
{
@@ -4637,40 +4643,44 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
4637
4643
4638
4644
// Check if the call can be inlined or not
4639
4645
PyObject * function = PEEK (oparg + 1 );
4640
- int inline_call = 0 ;
4641
4646
if (Py_TYPE (function ) == & PyFunction_Type ) {
4642
4647
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
+ }
4645
4672
}
4646
-
4647
- if (!inline_call ) {
4673
+ else {
4648
4674
PyObject * * sp = stack_pointer ;
4649
4675
res = call_function (tstate , & sp , oparg , NULL , cframe .use_tracing );
4650
4676
stack_pointer = sp ;
4651
- PUSH (res );
4652
- if (res == NULL ) {
4653
- goto error ;
4654
- }
4655
- CHECK_EVAL_BREAKER ();
4656
- DISPATCH ();
4657
4677
}
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 ) {
4664
4680
goto error ;
4665
4681
}
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 ();
4674
4684
}
4675
4685
4676
4686
TARGET (CALL_FUNCTION_KW ): {
0 commit comments