From dab8423d220243efabbbcafafc12d90145539b50 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 17 Mar 2020 18:56:44 +0100 Subject: 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. --- Include/internal/pycore_ceval.h | 7 +++--- Include/internal/pycore_pystate.h | 16 ++++++++------ .../2020-03-17-01-55-33.bpo-39984.y5Chgb.rst | 3 +++ Python/ceval.c | 25 ++++++++++++++-------- Python/pystate.c | 3 ++- 5 files changed, 35 insertions(+), 19 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-03-17-01-55-33.bpo-39984.y5Chgb.rst diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index ae6ef9a..ec00d18 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -15,9 +15,10 @@ struct _frame; #include "pycore_pystate.h" /* PyInterpreterState.eval_frame */ -PyAPI_FUNC(void) _Py_FinishPendingCalls(PyThreadState *tstate); -PyAPI_FUNC(void) _PyEval_Initialize(struct _ceval_runtime_state *); -PyAPI_FUNC(void) _PyEval_FiniThreads( +extern void _Py_FinishPendingCalls(PyThreadState *tstate); +extern void _PyEval_InitRuntimeState(struct _ceval_runtime_state *); +extern void _PyEval_InitState(struct _ceval_state *); +extern void _PyEval_FiniThreads( struct _ceval_runtime_state *ceval); PyAPI_FUNC(void) _PyEval_SignalReceived( struct _ceval_runtime_state *ceval); diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index 0a83546..0e3a9e6 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -35,12 +35,6 @@ struct _pending_calls { struct _ceval_runtime_state { 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 the fast path in the eval loop. */ _Py_atomic_int eval_breaker; @@ -52,6 +46,15 @@ struct _ceval_runtime_state { 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 */ #define _PY_NSMALLPOSINTS 257 @@ -75,6 +78,7 @@ struct _is { int finalizing; + struct _ceval_state ceval; struct _gc_runtime_state gc; PyObject *modules; diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-03-17-01-55-33.bpo-39984.y5Chgb.rst b/Misc/NEWS.d/next/Core and Builtins/2020-03-17-01-55-33.bpo-39984.y5Chgb.rst new file mode 100644 index 0000000..5f4b25c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-03-17-01-55-33.bpo-39984.y5Chgb.rst @@ -0,0 +1,3 @@ +subinterpreters: Move ``_PyRuntimeState.ceval.tracing_possible`` to +``PyInterpreterState.ceval.tracing_possible``: each interpreter now has its own +variable. diff --git a/Python/ceval.c b/Python/ceval.c index b359fb0..8835c3e 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -638,11 +638,17 @@ Py_MakePendingCalls(void) int _Py_CheckRecursionLimit = Py_DEFAULT_RECURSION_LIMIT; 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; - _gil_initialize(&state->gil); + _gil_initialize(&ceval->gil); +} + +void +_PyEval_InitState(struct _ceval_state *ceval) +{ + /* PyInterpreterState_New() initializes ceval to zero */ } int @@ -657,7 +663,7 @@ Py_SetRecursionLimit(int new_limit) { struct _ceval_runtime_state *ceval = &_PyRuntime.ceval; ceval->recursion_limit = new_limit; - _Py_CheckRecursionLimit = ceval->recursion_limit; + _Py_CheckRecursionLimit = new_limit; } /* 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 */ _PyRuntimeState * const runtime = &_PyRuntime; 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; PyCodeObject *co; @@ -841,7 +848,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) #ifdef LLTRACE #define FAST_DISPATCH() \ { \ - if (!lltrace && !_Py_TracingPossible(ceval) && !PyDTrace_LINE_ENABLED()) { \ + if (!lltrace && !_Py_TracingPossible(ceval2) && !PyDTrace_LINE_ENABLED()) { \ f->f_lasti = INSTR_OFFSET(); \ NEXTOPARG(); \ goto *opcode_targets[opcode]; \ @@ -851,7 +858,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) #else #define FAST_DISPATCH() \ { \ - if (!_Py_TracingPossible(ceval) && !PyDTrace_LINE_ENABLED()) { \ + if (!_Py_TracingPossible(ceval2) && !PyDTrace_LINE_ENABLED()) { \ f->f_lasti = INSTR_OFFSET(); \ NEXTOPARG(); \ goto *opcode_targets[opcode]; \ @@ -1268,7 +1275,7 @@ main_loop: /* line-by-line tracing support */ - if (_Py_TracingPossible(ceval) && + if (_Py_TracingPossible(ceval2) && tstate->c_tracefunc != NULL && !tstate->tracing) { int err; /* see maybe_call_line_trace @@ -3647,7 +3654,7 @@ exception_unwind: PUSH(val); PUSH(exc); 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_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 @@ -4639,7 +4646,7 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg) return -1; } - struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval; + struct _ceval_state *ceval = &tstate->interp->ceval; PyObject *traceobj = tstate->c_traceobj; ceval->tracing_possible += (func != NULL) - (tstate->c_tracefunc != NULL); diff --git a/Python/pystate.c b/Python/pystate.c index f92c2b4..77d4cc7 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -58,7 +58,7 @@ _PyRuntimeState_Init_impl(_PyRuntimeState *runtime) runtime->open_code_userdata = open_code_userdata; runtime->audit_hook_head = audit_hook_head; - _PyEval_Initialize(&runtime->ceval); + _PyEval_InitRuntimeState(&runtime->ceval); PyPreConfig_InitPythonConfig(&runtime->preconfig); @@ -213,6 +213,7 @@ PyInterpreterState_New(void) _PyRuntimeState *runtime = &_PyRuntime; interp->runtime = runtime; + _PyEval_InitState(&interp->ceval); _PyGC_InitState(&interp->gc); PyConfig_InitPythonConfig(&interp->config); -- cgit v0.12