Skip to content

Commit dab8423

Browse files
authored
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.
1 parent 514c469 commit dab8423

File tree

5 files changed

+35
-19
lines changed

5 files changed

+35
-19
lines changed

Include/internal/pycore_ceval.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ struct _frame;
1515

1616
#include "pycore_pystate.h" /* PyInterpreterState.eval_frame */
1717

18-
PyAPI_FUNC(void) _Py_FinishPendingCalls(PyThreadState *tstate);
19-
PyAPI_FUNC(void) _PyEval_Initialize(struct _ceval_runtime_state *);
20-
PyAPI_FUNC(void) _PyEval_FiniThreads(
18+
extern void _Py_FinishPendingCalls(PyThreadState *tstate);
19+
extern void _PyEval_InitRuntimeState(struct _ceval_runtime_state *);
20+
extern void _PyEval_InitState(struct _ceval_state *);
21+
extern void _PyEval_FiniThreads(
2122
struct _ceval_runtime_state *ceval);
2223
PyAPI_FUNC(void) _PyEval_SignalReceived(
2324
struct _ceval_runtime_state *ceval);

Include/internal/pycore_pystate.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,6 @@ struct _pending_calls {
3535

3636
struct _ceval_runtime_state {
3737
int recursion_limit;
38-
/* Records whether tracing is on for any thread. Counts the number
39-
of threads for which tstate->c_tracefunc is non-NULL, so if the
40-
value is 0, we know we don't have to check this thread's
41-
c_tracefunc. This speeds up the if statement in
42-
PyEval_EvalFrameEx() after fast_next_opcode. */
43-
int tracing_possible;
4438
/* This single variable consolidates all requests to break out of
4539
the fast path in the eval loop. */
4640
_Py_atomic_int eval_breaker;
@@ -52,6 +46,15 @@ struct _ceval_runtime_state {
5246
struct _gil_runtime_state gil;
5347
};
5448

49+
struct _ceval_state {
50+
/* Records whether tracing is on for any thread. Counts the number
51+
of threads for which tstate->c_tracefunc is non-NULL, so if the
52+
value is 0, we know we don't have to check this thread's
53+
c_tracefunc. This speeds up the if statement in
54+
_PyEval_EvalFrameDefault() after fast_next_opcode. */
55+
int tracing_possible;
56+
};
57+
5558
/* interpreter state */
5659

5760
#define _PY_NSMALLPOSINTS 257
@@ -75,6 +78,7 @@ struct _is {
7578

7679
int finalizing;
7780

81+
struct _ceval_state ceval;
7882
struct _gc_runtime_state gc;
7983

8084
PyObject *modules;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
subinterpreters: Move ``_PyRuntimeState.ceval.tracing_possible`` to
2+
``PyInterpreterState.ceval.tracing_possible``: each interpreter now has its own
3+
variable.

Python/ceval.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -638,11 +638,17 @@ Py_MakePendingCalls(void)
638638
int _Py_CheckRecursionLimit = Py_DEFAULT_RECURSION_LIMIT;
639639

640640
void
641-
_PyEval_Initialize(struct _ceval_runtime_state *state)
641+
_PyEval_InitRuntimeState(struct _ceval_runtime_state *ceval)
642642
{
643-
state->recursion_limit = Py_DEFAULT_RECURSION_LIMIT;
643+
ceval->recursion_limit = Py_DEFAULT_RECURSION_LIMIT;
644644
_Py_CheckRecursionLimit = Py_DEFAULT_RECURSION_LIMIT;
645-
_gil_initialize(&state->gil);
645+
_gil_initialize(&ceval->gil);
646+
}
647+
648+
void
649+
_PyEval_InitState(struct _ceval_state *ceval)
650+
{
651+
/* PyInterpreterState_New() initializes ceval to zero */
646652
}
647653

648654
int
@@ -657,7 +663,7 @@ Py_SetRecursionLimit(int new_limit)
657663
{
658664
struct _ceval_runtime_state *ceval = &_PyRuntime.ceval;
659665
ceval->recursion_limit = new_limit;
660-
_Py_CheckRecursionLimit = ceval->recursion_limit;
666+
_Py_CheckRecursionLimit = new_limit;
661667
}
662668

663669
/* The function _Py_EnterRecursiveCall() only calls _Py_CheckRecursiveCall()
@@ -753,6 +759,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
753759
PyObject *retval = NULL; /* Return value */
754760
_PyRuntimeState * const runtime = &_PyRuntime;
755761
struct _ceval_runtime_state * const ceval = &runtime->ceval;
762+
struct _ceval_state * const ceval2 = &tstate->interp->ceval;
756763
_Py_atomic_int * const eval_breaker = &ceval->eval_breaker;
757764
PyCodeObject *co;
758765

@@ -841,7 +848,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
841848
#ifdef LLTRACE
842849
#define FAST_DISPATCH() \
843850
{ \
844-
if (!lltrace && !_Py_TracingPossible(ceval) && !PyDTrace_LINE_ENABLED()) { \
851+
if (!lltrace && !_Py_TracingPossible(ceval2) && !PyDTrace_LINE_ENABLED()) { \
845852
f->f_lasti = INSTR_OFFSET(); \
846853
NEXTOPARG(); \
847854
goto *opcode_targets[opcode]; \
@@ -851,7 +858,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
851858
#else
852859
#define FAST_DISPATCH() \
853860
{ \
854-
if (!_Py_TracingPossible(ceval) && !PyDTrace_LINE_ENABLED()) { \
861+
if (!_Py_TracingPossible(ceval2) && !PyDTrace_LINE_ENABLED()) { \
855862
f->f_lasti = INSTR_OFFSET(); \
856863
NEXTOPARG(); \
857864
goto *opcode_targets[opcode]; \
@@ -1268,7 +1275,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
12681275

12691276
/* line-by-line tracing support */
12701277

1271-
if (_Py_TracingPossible(ceval) &&
1278+
if (_Py_TracingPossible(ceval2) &&
12721279
tstate->c_tracefunc != NULL && !tstate->tracing) {
12731280
int err;
12741281
/* see maybe_call_line_trace
@@ -3647,7 +3654,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
36473654
PUSH(val);
36483655
PUSH(exc);
36493656
JUMPTO(handler);
3650-
if (_Py_TracingPossible(ceval)) {
3657+
if (_Py_TracingPossible(ceval2)) {
36513658
int needs_new_execution_window = (f->f_lasti < instr_lb || f->f_lasti >= instr_ub);
36523659
int needs_line_update = (f->f_lasti == instr_lb || f->f_lasti < instr_prev);
36533660
/* 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)
46394646
return -1;
46404647
}
46414648

4642-
struct _ceval_runtime_state *ceval = &tstate->interp->runtime->ceval;
4649+
struct _ceval_state *ceval = &tstate->interp->ceval;
46434650
PyObject *traceobj = tstate->c_traceobj;
46444651
ceval->tracing_possible += (func != NULL) - (tstate->c_tracefunc != NULL);
46454652

Python/pystate.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ _PyRuntimeState_Init_impl(_PyRuntimeState *runtime)
5858
runtime->open_code_userdata = open_code_userdata;
5959
runtime->audit_hook_head = audit_hook_head;
6060

61-
_PyEval_Initialize(&runtime->ceval);
61+
_PyEval_InitRuntimeState(&runtime->ceval);
6262

6363
PyPreConfig_InitPythonConfig(&runtime->preconfig);
6464

@@ -213,6 +213,7 @@ PyInterpreterState_New(void)
213213
_PyRuntimeState *runtime = &_PyRuntime;
214214
interp->runtime = runtime;
215215

216+
_PyEval_InitState(&interp->ceval);
216217
_PyGC_InitState(&interp->gc);
217218
PyConfig_InitPythonConfig(&interp->config);
218219

0 commit comments

Comments
 (0)