mirror of
https://github.com/python/cpython.git
synced 2025-07-24 03:35:53 +00:00
bpo-38500: Add _PyInterpreterState_SetEvalFrameFunc() (GH-17340)
PyInterpreterState.eval_frame function now requires a tstate (Python thread state) parameter. Add private functions to the C API to get and set the frame evaluation function: * Add tstate parameter to _PyFrameEvalFunction function type. * Add _PyInterpreterState_GetEvalFrameFunc() and _PyInterpreterState_SetEvalFrameFunc() functions. * Add tstate parameter to _PyEval_EvalFrameDefault().
This commit is contained in:
parent
c846ef004d
commit
0b72b23fb0
9 changed files with 67 additions and 13 deletions
|
@ -1091,6 +1091,32 @@ All of the following functions must be called after :c:func:`Py_Initialize`.
|
||||||
|
|
||||||
.. versionadded:: 3.8
|
.. versionadded:: 3.8
|
||||||
|
|
||||||
|
.. c:type:: PyObject* (*_PyFrameEvalFunction)(PyThreadState *tstate, PyFrameObject *frame, int throwflag)
|
||||||
|
|
||||||
|
Type of a frame evaluation function.
|
||||||
|
|
||||||
|
The *throwflag* parameter is used by the ``throw()`` method of generators:
|
||||||
|
if non-zero, handle the current exception.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.9
|
||||||
|
The function now takes a *tstate* parameter.
|
||||||
|
|
||||||
|
.. c:function:: _PyFrameEvalFunction _PyInterpreterState_GetEvalFrameFunc(PyInterpreterState *interp)
|
||||||
|
|
||||||
|
Get the frame evaluation function.
|
||||||
|
|
||||||
|
See the :pep:`523` "Adding a frame evaluation API to CPython".
|
||||||
|
|
||||||
|
.. versionadded:: 3.9
|
||||||
|
|
||||||
|
.. c:function:: void _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState *interp, _PyFrameEvalFunction eval_frame);
|
||||||
|
|
||||||
|
Set the frame evaluation function.
|
||||||
|
|
||||||
|
See the :pep:`523` "Adding a frame evaluation API to CPython".
|
||||||
|
|
||||||
|
.. versionadded:: 3.9
|
||||||
|
|
||||||
|
|
||||||
.. c:function:: PyObject* PyThreadState_GetDict()
|
.. c:function:: PyObject* PyThreadState_GetDict()
|
||||||
|
|
||||||
|
|
|
@ -487,6 +487,10 @@ Build and C API Changes
|
||||||
|
|
||||||
(Contributed by Victor Stinner in :issue:`38644` and :issue:`39542`.)
|
(Contributed by Victor Stinner in :issue:`38644` and :issue:`39542`.)
|
||||||
|
|
||||||
|
* ``PyInterpreterState.eval_frame`` (:pep:`523`) now requires a new mandatory
|
||||||
|
*tstate* parameter (``PyThreadState*``).
|
||||||
|
(Contributed by Victor Stinner in :issue:`38500`.)
|
||||||
|
|
||||||
|
|
||||||
Deprecated
|
Deprecated
|
||||||
==========
|
==========
|
||||||
|
|
|
@ -21,7 +21,7 @@ PyAPI_FUNC(PyObject *) _PyEval_GetBuiltinId(_Py_Identifier *);
|
||||||
flag was set, else return 0. */
|
flag was set, else return 0. */
|
||||||
PyAPI_FUNC(int) PyEval_MergeCompilerFlags(PyCompilerFlags *cf);
|
PyAPI_FUNC(int) PyEval_MergeCompilerFlags(PyCompilerFlags *cf);
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject *) _PyEval_EvalFrameDefault(struct _frame *f, int exc);
|
PyAPI_FUNC(PyObject *) _PyEval_EvalFrameDefault(PyThreadState *tstate, struct _frame *f, int exc);
|
||||||
|
|
||||||
PyAPI_FUNC(void) _PyEval_SetSwitchInterval(unsigned long microseconds);
|
PyAPI_FUNC(void) _PyEval_SetSwitchInterval(unsigned long microseconds);
|
||||||
PyAPI_FUNC(unsigned long) _PyEval_GetSwitchInterval(void);
|
PyAPI_FUNC(unsigned long) _PyEval_GetSwitchInterval(void);
|
||||||
|
|
|
@ -186,6 +186,16 @@ PyAPI_FUNC(void) PyThreadState_DeleteCurrent(void);
|
||||||
|
|
||||||
typedef struct _frame *(*PyThreadFrameGetter)(PyThreadState *self_);
|
typedef struct _frame *(*PyThreadFrameGetter)(PyThreadState *self_);
|
||||||
|
|
||||||
|
/* Frame evaluation API */
|
||||||
|
|
||||||
|
typedef PyObject* (*_PyFrameEvalFunction)(PyThreadState *tstate, struct _frame *, int);
|
||||||
|
|
||||||
|
PyAPI_FUNC(_PyFrameEvalFunction) _PyInterpreterState_GetEvalFrameFunc(
|
||||||
|
PyInterpreterState *interp);
|
||||||
|
PyAPI_FUNC(void) _PyInterpreterState_SetEvalFrameFunc(
|
||||||
|
PyInterpreterState *interp,
|
||||||
|
_PyFrameEvalFunction eval_frame);
|
||||||
|
|
||||||
/* cross-interpreter data */
|
/* cross-interpreter data */
|
||||||
|
|
||||||
struct _xid;
|
struct _xid;
|
||||||
|
|
|
@ -40,7 +40,7 @@ void _PyEval_Fini(void);
|
||||||
static inline PyObject*
|
static inline PyObject*
|
||||||
_PyEval_EvalFrame(PyThreadState *tstate, struct _frame *f, int throwflag)
|
_PyEval_EvalFrame(PyThreadState *tstate, struct _frame *f, int throwflag)
|
||||||
{
|
{
|
||||||
return tstate->interp->eval_frame(f, throwflag);
|
return tstate->interp->eval_frame(tstate, f, throwflag);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern PyObject *_PyEval_EvalCode(
|
extern PyObject *_PyEval_EvalCode(
|
||||||
|
|
|
@ -54,8 +54,6 @@ struct _ceval_runtime_state {
|
||||||
|
|
||||||
/* interpreter state */
|
/* interpreter state */
|
||||||
|
|
||||||
typedef PyObject* (*_PyFrameEvalFunction)(struct _frame *, int);
|
|
||||||
|
|
||||||
#define _PY_NSMALLPOSINTS 257
|
#define _PY_NSMALLPOSINTS 257
|
||||||
#define _PY_NSMALLNEGINTS 5
|
#define _PY_NSMALLNEGINTS 5
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
Add a private API to get and set the frame evaluation function: add
|
||||||
|
:c:func:`_PyInterpreterState_GetEvalFrameFunc` and
|
||||||
|
:c:func:`_PyInterpreterState_SetEvalFrameFunc` C functions.
|
||||||
|
The :c:type:`_PyFrameEvalFunction` function type now takes a *tstate*
|
||||||
|
parameter.
|
|
@ -725,9 +725,7 @@ PyEval_EvalCode(PyObject *co, PyObject *globals, PyObject *locals)
|
||||||
PyObject *
|
PyObject *
|
||||||
PyEval_EvalFrame(PyFrameObject *f)
|
PyEval_EvalFrame(PyFrameObject *f)
|
||||||
{
|
{
|
||||||
/* This is for backward compatibility with extension modules that
|
/* Function kept for backward compatibility */
|
||||||
used this API; core interpreter code should call
|
|
||||||
PyEval_EvalFrameEx() */
|
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
return _PyEval_EvalFrame(tstate, f, 0);
|
return _PyEval_EvalFrame(tstate, f, 0);
|
||||||
}
|
}
|
||||||
|
@ -740,8 +738,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* _Py_HOT_FUNCTION
|
PyObject* _Py_HOT_FUNCTION
|
||||||
_PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
|
_PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
|
||||||
{
|
{
|
||||||
|
ensure_tstate_not_null(__func__, tstate);
|
||||||
|
|
||||||
#ifdef DXPAIRS
|
#ifdef DXPAIRS
|
||||||
int lastopcode = 0;
|
int lastopcode = 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -756,9 +756,6 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
|
||||||
_Py_atomic_int * const eval_breaker = &ceval->eval_breaker;
|
_Py_atomic_int * const eval_breaker = &ceval->eval_breaker;
|
||||||
PyCodeObject *co;
|
PyCodeObject *co;
|
||||||
|
|
||||||
PyThreadState * const tstate = _PyRuntimeState_GetThreadState(runtime);
|
|
||||||
ensure_tstate_not_null(__func__, tstate);
|
|
||||||
|
|
||||||
/* when tracing we set things up so that
|
/* when tracing we set things up so that
|
||||||
|
|
||||||
not (instr_lb <= current_bytecode_offset < instr_ub)
|
not (instr_lb <= current_bytecode_offset < instr_ub)
|
||||||
|
@ -1181,7 +1178,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
#ifdef Py_DEBUG
|
#ifdef Py_DEBUG
|
||||||
/* PyEval_EvalFrameEx() must not be called with an exception set,
|
/* _PyEval_EvalFrameDefault() must not be called with an exception set,
|
||||||
because it can clear it (directly or indirectly) and so the
|
because it can clear it (directly or indirectly) and so the
|
||||||
caller loses its exception */
|
caller loses its exception */
|
||||||
assert(!_PyErr_Occurred(tstate));
|
assert(!_PyErr_Occurred(tstate));
|
||||||
|
@ -3702,7 +3699,7 @@ exit_eval_frame:
|
||||||
f->f_executing = 0;
|
f->f_executing = 0;
|
||||||
tstate->frame = f->f_back;
|
tstate->frame = f->f_back;
|
||||||
|
|
||||||
return _Py_CheckFunctionResult(tstate, NULL, retval, "PyEval_EvalFrameEx");
|
return _Py_CheckFunctionResult(tstate, NULL, retval, __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -1722,6 +1722,20 @@ _register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_PyFrameEvalFunction
|
||||||
|
_PyInterpreterState_GetEvalFrameFunc(PyInterpreterState *interp)
|
||||||
|
{
|
||||||
|
return interp->eval_frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_PyInterpreterState_SetEvalFrameFunc(PyInterpreterState *interp,
|
||||||
|
_PyFrameEvalFunction eval_frame)
|
||||||
|
{
|
||||||
|
interp->eval_frame = eval_frame;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue