@@ -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,39 +4643,48 @@ _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 ;
4648
+ STACK_SHRINK (oparg + 1 );
4649
+ if (code -> co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR )) {
4650
+ PyObject * locals = code -> co_flags & CO_OPTIMIZED ? NULL : PyFunction_GET_GLOBALS (function );
4651
+ res = make_coro (
4652
+ tstate , PyFunction_AS_FRAME_CONSTRUCTOR (function ), locals , stack_pointer + 1 , oparg , NULL );
4653
+ for (int i = 0 ; i < oparg + 1 ; i ++ ) {
4654
+ Py_DECREF (stack_pointer [i ]);
4655
+ }
4656
+ PUSH (res );
4657
+ if (res == NULL ) {
4658
+ goto error ;
4659
+ }
4660
+ }
4661
+ else {
4662
+ InterpreterFrame * new_frame = _PyEval_FrameFromPyFunctionAndArgs (tstate , stack_pointer + 1 , oparg , function );
4663
+ if (new_frame == NULL ) {
4664
+ // When we exit here, we own all variables in the stack (the frame creation has not stolen
4665
+ // any variable) so we need to clean the whole stack (done in the "error" label).
4666
+ goto error ;
4667
+ }
4668
+ assert (tstate -> interp -> eval_frame != NULL );
4669
+ // The frame has stolen all the arguments from the stack, so there is no need to clean up them
4670
+ Py_DECREF (function );
4671
+ _PyFrame_SetStackPointer (frame , stack_pointer );
4672
+ new_frame -> depth = frame -> depth + 1 ;
4673
+ tstate -> frame = frame = new_frame ;
4674
+ goto start_frame ;
4675
+ }
4645
4676
}
4646
-
4647
- if (!inline_call ) {
4677
+ else {
4648
4678
PyObject * * sp = stack_pointer ;
4649
4679
res = call_function (tstate , & sp , oparg , NULL , cframe .use_tracing );
4650
4680
stack_pointer = sp ;
4651
4681
PUSH (res );
4652
4682
if (res == NULL ) {
4653
4683
goto error ;
4654
4684
}
4655
- CHECK_EVAL_BREAKER ();
4656
- DISPATCH ();
4657
4685
}
4658
-
4659
- InterpreterFrame * new_frame = _PyEval_FrameFromPyFunctionAndArgs (tstate , stack_pointer - oparg , oparg , function );
4660
- if (new_frame == NULL ) {
4661
- // When we exit here, we own all variables in the stack (the frame creation has not stolen
4662
- // any variable) so we need to clean the whole stack (done in the "error" label).
4663
- goto error ;
4664
- }
4665
- assert (tstate -> interp -> eval_frame != NULL );
4666
- // The frame has stolen all the arguments from the stack, so there is no need to clean up them
4667
- STACK_SHRINK (oparg + 1 );
4668
- Py_DECREF (function );
4669
- _PyFrame_SetStackPointer (frame , stack_pointer );
4670
- new_frame -> depth = frame -> depth + 1 ;
4671
- tstate -> frame = frame = new_frame ;
4672
- goto start_frame ;
4686
+ CHECK_EVAL_BREAKER ();
4687
+ DISPATCH ();
4673
4688
}
4674
4689
4675
4690
TARGET (CALL_FUNCTION_KW ): {
0 commit comments