Skip to content

Commit 919b741

Browse files
authored
Merge pull request #16 from markshannon/simple_cframe
Drop test for tracing and inline coroutine creation
2 parents 832bccf + 9a63ee1 commit 919b741

File tree

1 file changed

+35
-25
lines changed

1 file changed

+35
-25
lines changed

Python/ceval.c

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
15441550
PyObject* _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

Comments
 (0)