diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 66ddc991a9b..f2acf10df8c 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -43,6 +43,9 @@ extern PyObject *_PyEval_BuiltinsFromGlobals( static inline PyObject* _PyEval_EvalFrame(PyThreadState *tstate, struct _interpreter_frame *frame, int throwflag) { + if (tstate->interp->eval_frame == NULL) { + return _PyEval_EvalFrameDefault(tstate, frame, throwflag); + } return tstate->interp->eval_frame(tstate, frame, throwflag); } diff --git a/Python/ceval.c b/Python/ceval.c index df435bf3d76..a63b80395dc 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4612,7 +4612,7 @@ check_eval_breaker: // Check if the call can be inlined or not PyObject *function = PEEK(oparg + 1); - if (Py_TYPE(function) == &PyFunction_Type) { + if (Py_TYPE(function) == &PyFunction_Type && tstate->interp->eval_frame == NULL) { int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(function))->co_flags; PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : PyFunction_GET_GLOBALS(function); int is_generator = code_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR); @@ -4630,7 +4630,6 @@ check_eval_breaker: } STACK_SHRINK(oparg + 1); - assert(tstate->interp->eval_frame != NULL); // The frame has stolen all the arguments from the stack, // so there is no need to clean them up. Py_DECREF(function); @@ -5687,7 +5686,7 @@ _PyEvalFramePushAndInit(PyThreadState *tstate, PyFrameConstructor *con, if (steal_args) { // If we failed to initialize locals, make sure the caller still own all the // arguments. Notice that we only need to increase the reference count of the - // *valid* arguments (i.e. the ones that fit into the frame). + // *valid* arguments (i.e. the ones that fit into the frame). PyCodeObject *co = (PyCodeObject*)con->fc_code; const size_t total_args = co->co_argcount + co->co_kwonlyargcount; for (size_t i = 0; i < Py_MIN(argcount, total_args); i++) { @@ -5734,7 +5733,6 @@ _PyEval_Vector(PyThreadState *tstate, PyFrameConstructor *con, if (frame == NULL) { return NULL; } - assert (tstate->interp->eval_frame != NULL); PyObject *retval = _PyEval_EvalFrame(tstate, frame, 0); assert(_PyFrame_GetStackPointer(frame) == _PyFrame_Stackbase(frame)); if (_PyEvalFrameClearAndPop(tstate, frame)) { diff --git a/Python/pystate.c b/Python/pystate.c index 45272142e41..f02de926c6f 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -230,7 +230,7 @@ PyInterpreterState_New(void) PyConfig_InitPythonConfig(&interp->config); _PyType_InitCache(interp); - interp->eval_frame = _PyEval_EvalFrameDefault; + interp->eval_frame = NULL; #ifdef HAVE_DLOPEN #if HAVE_DECL_RTLD_NOW interp->dlopenflags = RTLD_NOW; @@ -1973,6 +1973,9 @@ _register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry) _PyFrameEvalFunction _PyInterpreterState_GetEvalFrameFunc(PyInterpreterState *interp) { + if (interp->eval_frame == NULL) { + return _PyEval_EvalFrameDefault; + } return interp->eval_frame; } @@ -1981,7 +1984,12 @@ void _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState *interp, _PyFrameEvalFunction eval_frame) { - interp->eval_frame = eval_frame; + if (eval_frame == _PyEval_EvalFrameDefault) { + interp->eval_frame = NULL; + } + else { + interp->eval_frame = eval_frame; + } }