bpo-39984: Add PyInterpreterState.ceval (GH-19047)

subinterpreters: Move _PyRuntimeState.ceval.tracing_possible to
PyInterpreterState.ceval.tracing_possible: each interpreter now has
its own variable.

Changes:

* Add _ceval_state structure.
* Add PyInterpreterState.ceval field.
* _PyEval_EvalFrameDefault(): add ceval2 variable (struct _ceval_state*).
* Rename _PyEval_Initialize() to _PyEval_InitRuntimeState().
* Add _PyEval_InitState().
* Don't export internal _Py_FinishPendingCalls() and
  _PyEval_FiniThreads() functions anymore.
This commit is contained in:
Victor Stinner 2020-03-17 18:56:44 +01:00 committed by GitHub
parent 514c469719
commit dab8423d22
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 35 additions and 19 deletions

View File

@ -15,9 +15,10 @@ struct _frame;
#include "pycore_pystate.h" /* PyInterpreterState.eval_frame */ #include "pycore_pystate.h" /* PyInterpreterState.eval_frame */
PyAPI_FUNC(void) _Py_FinishPendingCalls(PyThreadState *tstate); extern void _Py_FinishPendingCalls(PyThreadState *tstate);
PyAPI_FUNC(void) _PyEval_Initialize(struct _ceval_runtime_state *); extern void _PyEval_InitRuntimeState(struct _ceval_runtime_state *);
PyAPI_FUNC(void) _PyEval_FiniThreads( extern void _PyEval_InitState(struct _ceval_state *);
extern void _PyEval_FiniThreads(
struct _ceval_runtime_state *ceval); struct _ceval_runtime_state *ceval);
PyAPI_FUNC(void) _PyEval_SignalReceived( PyAPI_FUNC(void) _PyEval_SignalReceived(
struct _ceval_runtime_state *ceval); struct _ceval_runtime_state *ceval);

View File

@ -35,12 +35,6 @@ struct _pending_calls {
struct _ceval_runtime_state { struct _ceval_runtime_state {
int recursion_limit; int recursion_limit;
/* Records whether tracing is on for any thread. Counts the number
of threads for which tstate->c_tracefunc is non-NULL, so if the
value is 0, we know we don't have to check this thread's
c_tracefunc. This speeds up the if statement in
PyEval_EvalFrameEx() after fast_next_opcode. */
int tracing_possible;
/* This single variable consolidates all requests to break out of /* This single variable consolidates all requests to break out of
the fast path in the eval loop. */ the fast path in the eval loop. */
_Py_atomic_int eval_breaker; _Py_atomic_int eval_breaker;
@ -52,6 +46,15 @@ struct _ceval_runtime_state {
struct _gil_runtime_state gil; struct _gil_runtime_state gil;
}; };
struct _ceval_state {
/* Records whether tracing is on for any thread. Counts the number
of threads for which tstate->c_tracefunc is non-NULL, so if the
value is 0, we know we don't have to check this thread's
c_tracefunc. This speeds up the if statement in
_PyEval_EvalFrameDefault() after fast_next_opcode. */
int tracing_possible;
};
/* interpreter state */ /* interpreter state */
#define _PY_NSMALLPOSINTS 257 #define _PY_NSMALLPOSINTS 257
@ -75,6 +78,7 @@ struct _is {
int finalizing; int finalizing;
struct _ceval_state ceval;
struct _gc_runtime_state gc; struct _gc_runtime_state gc;
PyObject *modules; PyObject *modules;

View File

@ -0,0 +1,3 @@
subinterpreters: Move ``_PyRuntimeState.ceval.tracing_possible`` to
``PyInterpreterState.ceval.tracing_possible``: each interpreter now has its own
variable.

View File

@ -638,11 +638,17 @@ Py_MakePendingCalls(void)
int _Py_CheckRecursionLimit = Py_DEFAULT_RECURSION_LIMIT; int _Py_CheckRecursionLimit = Py_DEFAULT_RECURSION_LIMIT;
void void
_PyEval_Initialize(struct _ceval_runtime_state *state) _PyEval_InitRuntimeState(struct _ceval_runtime_state *ceval)
{ {
state->recursion_limit = Py_DEFAULT_RECURSION_LIMIT; ceval->recursion_limit = Py_DEFAULT_RECURSION_LIMIT;
_Py_CheckRecursionLimit = Py_DEFAULT_RECURSION_LIMIT; _Py_CheckRecursionLimit = Py_DEFAULT_RECURSION_LIMIT;
_gil_initialize(&state->gil); _gil_initialize(&ceval->gil);
}
void
_PyEval_InitState(struct _ceval_state *ceval)
{
/* PyInterpreterState_New() initializes ceval to zero */
} }
int int
@ -657,7 +663,7 @@ Py_SetRecursionLimit(int new_limit)
{ {
struct _ceval_runtime_state *ceval = &_PyRuntime.ceval; struct _ceval_runtime_state *ceval = &_PyRuntime.ceval;
ceval->recursion_limit = new_limit; ceval->recursion_limit = new_limit;
_Py_CheckRecursionLimit = ceval->recursion_limit; _Py_CheckRecursionLimit = new_limit;
} }
/* The function _Py_EnterRecursiveCall() only calls _Py_CheckRecursiveCall() /* The function _Py_EnterRecursiveCall() only calls _Py_CheckRecursiveCall()
@ -753,6 +759,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
PyObject *retval = NULL; /* Return value */ PyObject *retval = NULL; /* Return value */
_PyRuntimeState * const runtime = &_PyRuntime; _PyRuntimeState * const runtime = &_PyRuntime;
struct _ceval_runtime_state * const ceval = &runtime->ceval; struct _ceval_runtime_state * const ceval = &runtime->ceval;
struct _ceval_state * const ceval2 = &tstate->interp->ceval;
_Py_atomic_int * const eval_breaker = &ceval->eval_breaker; _Py_atomic_int * const eval_breaker = &ceval->eval_breaker;
PyCodeObject *co; PyCodeObject *co;
@ -841,7 +848,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
#ifdef LLTRACE #ifdef LLTRACE
#define FAST_DISPATCH() \ #define FAST_DISPATCH() \
{ \ { \
if (!lltrace && !_Py_TracingPossible(ceval) && !PyDTrace_LINE_ENABLED()) { \ if (!lltrace && !_Py_TracingPossible(ceval2) && !PyDTrace_LINE_ENABLED()) { \
f->f_lasti = INSTR_OFFSET(); \ f->f_lasti = INSTR_OFFSET(); \
NEXTOPARG(); \ NEXTOPARG(); \
goto *opcode_targets[opcode]; \ goto *opcode_targets[opcode]; \
@ -851,7 +858,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
#else #else
#define FAST_DISPATCH() \ #define FAST_DISPATCH() \
{ \ { \
if (!_Py_TracingPossible(ceval) && !PyDTrace_LINE_ENABLED()) { \ if (!_Py_TracingPossible(ceval2) && !PyDTrace_LINE_ENABLED()) { \
f->f_lasti = INSTR_OFFSET(); \ f->f_lasti = INSTR_OFFSET(); \
NEXTOPARG(); \ NEXTOPARG(); \
goto *opcode_targets[opcode]; \ goto *opcode_targets[opcode]; \
@ -1268,7 +1275,7 @@ main_loop:
/* line-by-line tracing support */ /* line-by-line tracing support */
if (_Py_TracingPossible(ceval) && if (_Py_TracingPossible(ceval2) &&
tstate->c_tracefunc != NULL && !tstate->tracing) { tstate->c_tracefunc != NULL && !tstate->tracing) {
int err; int err;
/* see maybe_call_line_trace /* see maybe_call_line_trace
@ -3647,7 +3654,7 @@ exception_unwind:
PUSH(val); PUSH(val);
PUSH(exc); PUSH(exc);
JUMPTO(handler); JUMPTO(handler);
if (_Py_TracingPossible(ceval)) { if (_Py_TracingPossible(ceval2)) {
int needs_new_execution_window = (f->f_lasti < instr_lb || f->f_lasti >= instr_ub); int needs_new_execution_window = (f->f_lasti < instr_lb || f->f_lasti >= instr_ub);
int needs_line_update = (f->f_lasti == instr_lb || f->f_lasti < instr_prev); int needs_line_update = (f->f_lasti == instr_lb || f->f_lasti < instr_prev);
/* Make sure that we trace line after exception if we are in a new execution /* Make sure that we trace line after exception if we are in a new execution
@ -4639,7 +4646,7 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
return -1; return -1;
} }
struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval; struct _ceval_state *ceval = &tstate->interp->ceval;
PyObject *traceobj = tstate->c_traceobj; PyObject *traceobj = tstate->c_traceobj;
ceval->tracing_possible += (func != NULL) - (tstate->c_tracefunc != NULL); ceval->tracing_possible += (func != NULL) - (tstate->c_tracefunc != NULL);

View File

@ -58,7 +58,7 @@ _PyRuntimeState_Init_impl(_PyRuntimeState *runtime)
runtime->open_code_userdata = open_code_userdata; runtime->open_code_userdata = open_code_userdata;
runtime->audit_hook_head = audit_hook_head; runtime->audit_hook_head = audit_hook_head;
_PyEval_Initialize(&runtime->ceval); _PyEval_InitRuntimeState(&runtime->ceval);
PyPreConfig_InitPythonConfig(&runtime->preconfig); PyPreConfig_InitPythonConfig(&runtime->preconfig);
@ -213,6 +213,7 @@ PyInterpreterState_New(void)
_PyRuntimeState *runtime = &_PyRuntime; _PyRuntimeState *runtime = &_PyRuntime;
interp->runtime = runtime; interp->runtime = runtime;
_PyEval_InitState(&interp->ceval);
_PyGC_InitState(&interp->gc); _PyGC_InitState(&interp->gc);
PyConfig_InitPythonConfig(&interp->config); PyConfig_InitPythonConfig(&interp->config);