Use static inline function Py_EnterRecursiveCall() (#91988)

Currently, calling Py_EnterRecursiveCall() and
Py_LeaveRecursiveCall() may use a function call or a static inline
function call, depending if the internal pycore_ceval.h header file
is included or not. Use a different name for the static inline
function to ensure that the static inline function is always used in
Python internals for best performance. Similar approach than
PyThreadState_GET() (function call) and _PyThreadState_GET() (static
inline function).

* Rename _Py_EnterRecursiveCall() to _Py_EnterRecursiveCallTstate()
* Rename _Py_LeaveRecursiveCall() to _Py_LeaveRecursiveCallTstate()
* pycore_ceval.h: Rename Py_EnterRecursiveCall() to
  _Py_EnterRecursiveCall() and Py_LeaveRecursiveCall() and
  _Py_LeaveRecursiveCall()
This commit is contained in:
Victor Stinner 2022-05-04 13:30:23 +02:00 committed by GitHub
parent 14243369b5
commit d716a0dfe2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 524 additions and 521 deletions

View File

@ -91,7 +91,7 @@ extern void _PyEval_DeactivateOpCache(void);
#ifdef USE_STACKCHECK #ifdef USE_STACKCHECK
/* With USE_STACKCHECK macro defined, trigger stack checks in /* With USE_STACKCHECK macro defined, trigger stack checks in
_Py_CheckRecursiveCall() on every 64th call to Py_EnterRecursiveCall. */ _Py_CheckRecursiveCall() on every 64th call to _Py_EnterRecursiveCall. */
static inline int _Py_MakeRecCheck(PyThreadState *tstate) { static inline int _Py_MakeRecCheck(PyThreadState *tstate) {
return (tstate->recursion_remaining-- <= 0 return (tstate->recursion_remaining-- <= 0
|| (tstate->recursion_remaining & 63) == 0); || (tstate->recursion_remaining & 63) == 0);
@ -106,29 +106,25 @@ PyAPI_FUNC(int) _Py_CheckRecursiveCall(
PyThreadState *tstate, PyThreadState *tstate,
const char *where); const char *where);
static inline int _Py_EnterRecursiveCall(PyThreadState *tstate, static inline int _Py_EnterRecursiveCallTstate(PyThreadState *tstate,
const char *where) { const char *where) {
return (_Py_MakeRecCheck(tstate) && _Py_CheckRecursiveCall(tstate, where)); return (_Py_MakeRecCheck(tstate) && _Py_CheckRecursiveCall(tstate, where));
} }
static inline int _Py_EnterRecursiveCall_inline(const char *where) { static inline int _Py_EnterRecursiveCall(const char *where) {
PyThreadState *tstate = _PyThreadState_GET(); PyThreadState *tstate = _PyThreadState_GET();
return _Py_EnterRecursiveCall(tstate, where); return _Py_EnterRecursiveCallTstate(tstate, where);
} }
#define Py_EnterRecursiveCall(where) _Py_EnterRecursiveCall_inline(where) static inline void _Py_LeaveRecursiveCallTstate(PyThreadState *tstate) {
static inline void _Py_LeaveRecursiveCall(PyThreadState *tstate) {
tstate->recursion_remaining++; tstate->recursion_remaining++;
} }
static inline void _Py_LeaveRecursiveCall_inline(void) { static inline void _Py_LeaveRecursiveCall(void) {
PyThreadState *tstate = _PyThreadState_GET(); PyThreadState *tstate = _PyThreadState_GET();
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
} }
#define Py_LeaveRecursiveCall() _Py_LeaveRecursiveCall_inline()
extern struct _PyInterpreterFrame* _PyEval_GetFrame(void); extern struct _PyInterpreterFrame* _PyEval_GetFrame(void);
extern PyObject* _Py_MakeCoro(PyFunctionObject *func); extern PyObject* _Py_MakeCoro(PyFunctionObject *func);

View File

@ -112,6 +112,7 @@ bytes(cdata)
#endif #endif
#include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_ceval.h" // _Py_EnterRecursiveCall()
#include "structmember.h" // PyMemberDef #include "structmember.h" // PyMemberDef
#include <ffi.h> #include <ffi.h>
@ -2270,12 +2271,12 @@ PyCSimpleType_from_param(PyObject *type, PyObject *value)
return NULL; return NULL;
} }
if (as_parameter) { if (as_parameter) {
if (Py_EnterRecursiveCall("while processing _as_parameter_")) { if (_Py_EnterRecursiveCall("while processing _as_parameter_")) {
Py_DECREF(as_parameter); Py_DECREF(as_parameter);
return NULL; return NULL;
} }
value = PyCSimpleType_from_param(type, as_parameter); value = PyCSimpleType_from_param(type, as_parameter);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
Py_DECREF(as_parameter); Py_DECREF(as_parameter);
return value; return value;
} }

View File

@ -10,6 +10,7 @@
#define NEEDS_PY_IDENTIFIER #define NEEDS_PY_IDENTIFIER
#include "Python.h" #include "Python.h"
#include "pycore_ceval.h" // _Py_EnterRecursiveCall()
#include "structmember.h" // PyMemberDef #include "structmember.h" // PyMemberDef
#include "pycore_accu.h" #include "pycore_accu.h"
@ -1059,19 +1060,19 @@ scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_
return scanstring_unicode(pystr, idx + 1, s->strict, next_idx_ptr); return scanstring_unicode(pystr, idx + 1, s->strict, next_idx_ptr);
case '{': case '{':
/* object */ /* object */
if (Py_EnterRecursiveCall(" while decoding a JSON object " if (_Py_EnterRecursiveCall(" while decoding a JSON object "
"from a unicode string")) "from a unicode string"))
return NULL; return NULL;
res = _parse_object_unicode(s, pystr, idx + 1, next_idx_ptr); res = _parse_object_unicode(s, pystr, idx + 1, next_idx_ptr);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
return res; return res;
case '[': case '[':
/* array */ /* array */
if (Py_EnterRecursiveCall(" while decoding a JSON array " if (_Py_EnterRecursiveCall(" while decoding a JSON array "
"from a unicode string")) "from a unicode string"))
return NULL; return NULL;
res = _parse_array_unicode(s, pystr, idx + 1, next_idx_ptr); res = _parse_array_unicode(s, pystr, idx + 1, next_idx_ptr);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
return res; return res;
case 'n': case 'n':
/* null */ /* null */
@ -1430,17 +1431,17 @@ encoder_listencode_obj(PyEncoderObject *s, _PyAccu *acc,
return _steal_accumulate(acc, encoded); return _steal_accumulate(acc, encoded);
} }
else if (PyList_Check(obj) || PyTuple_Check(obj)) { else if (PyList_Check(obj) || PyTuple_Check(obj)) {
if (Py_EnterRecursiveCall(" while encoding a JSON object")) if (_Py_EnterRecursiveCall(" while encoding a JSON object"))
return -1; return -1;
rv = encoder_listencode_list(s, acc, obj, indent_level); rv = encoder_listencode_list(s, acc, obj, indent_level);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
return rv; return rv;
} }
else if (PyDict_Check(obj)) { else if (PyDict_Check(obj)) {
if (Py_EnterRecursiveCall(" while encoding a JSON object")) if (_Py_EnterRecursiveCall(" while encoding a JSON object"))
return -1; return -1;
rv = encoder_listencode_dict(s, acc, obj, indent_level); rv = encoder_listencode_dict(s, acc, obj, indent_level);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
return rv; return rv;
} }
else { else {
@ -1468,13 +1469,13 @@ encoder_listencode_obj(PyEncoderObject *s, _PyAccu *acc,
return -1; return -1;
} }
if (Py_EnterRecursiveCall(" while encoding a JSON object")) { if (_Py_EnterRecursiveCall(" while encoding a JSON object")) {
Py_DECREF(newobj); Py_DECREF(newobj);
Py_XDECREF(ident); Py_XDECREF(ident);
return -1; return -1;
} }
rv = encoder_listencode_obj(s, acc, newobj, indent_level); rv = encoder_listencode_obj(s, acc, newobj, indent_level);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
Py_DECREF(newobj); Py_DECREF(newobj);
if (rv) { if (rv) {

View File

@ -9,6 +9,7 @@
#endif #endif
#include "Python.h" #include "Python.h"
#include "pycore_ceval.h" // _Py_EnterRecursiveCall()
#include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_runtime.h" // _Py_ID() #include "pycore_runtime.h" // _Py_ID()
#include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_pystate.h" // _PyThreadState_GET()
@ -3068,21 +3069,21 @@ save_list(PicklerObject *self, PyObject *obj)
if (len != 0) { if (len != 0) {
/* Materialize the list elements. */ /* Materialize the list elements. */
if (PyList_CheckExact(obj) && self->proto > 0) { if (PyList_CheckExact(obj) && self->proto > 0) {
if (Py_EnterRecursiveCall(" while pickling an object")) if (_Py_EnterRecursiveCall(" while pickling an object"))
goto error; goto error;
status = batch_list_exact(self, obj); status = batch_list_exact(self, obj);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
} else { } else {
PyObject *iter = PyObject_GetIter(obj); PyObject *iter = PyObject_GetIter(obj);
if (iter == NULL) if (iter == NULL)
goto error; goto error;
if (Py_EnterRecursiveCall(" while pickling an object")) { if (_Py_EnterRecursiveCall(" while pickling an object")) {
Py_DECREF(iter); Py_DECREF(iter);
goto error; goto error;
} }
status = batch_list(self, iter); status = batch_list(self, iter);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
Py_DECREF(iter); Py_DECREF(iter);
} }
} }
@ -3327,10 +3328,10 @@ save_dict(PicklerObject *self, PyObject *obj)
if (PyDict_CheckExact(obj) && self->proto > 0) { if (PyDict_CheckExact(obj) && self->proto > 0) {
/* We can take certain shortcuts if we know this is a dict and /* We can take certain shortcuts if we know this is a dict and
not a dict subclass. */ not a dict subclass. */
if (Py_EnterRecursiveCall(" while pickling an object")) if (_Py_EnterRecursiveCall(" while pickling an object"))
goto error; goto error;
status = batch_dict_exact(self, obj); status = batch_dict_exact(self, obj);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
} else { } else {
items = PyObject_CallMethodNoArgs(obj, &_Py_ID(items)); items = PyObject_CallMethodNoArgs(obj, &_Py_ID(items));
if (items == NULL) if (items == NULL)
@ -3339,12 +3340,12 @@ save_dict(PicklerObject *self, PyObject *obj)
Py_DECREF(items); Py_DECREF(items);
if (iter == NULL) if (iter == NULL)
goto error; goto error;
if (Py_EnterRecursiveCall(" while pickling an object")) { if (_Py_EnterRecursiveCall(" while pickling an object")) {
Py_DECREF(iter); Py_DECREF(iter);
goto error; goto error;
} }
status = batch_dict(self, iter); status = batch_dict(self, iter);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
Py_DECREF(iter); Py_DECREF(iter);
} }
} }
@ -4300,9 +4301,9 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
return save_unicode(self, obj); return save_unicode(self, obj);
} }
/* We're only calling Py_EnterRecursiveCall here so that atomic /* We're only calling _Py_EnterRecursiveCall here so that atomic
types above are pickled faster. */ types above are pickled faster. */
if (Py_EnterRecursiveCall(" while pickling an object")) { if (_Py_EnterRecursiveCall(" while pickling an object")) {
return -1; return -1;
} }
@ -4460,7 +4461,7 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
} }
done: done:
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
Py_XDECREF(reduce_func); Py_XDECREF(reduce_func);
Py_XDECREF(reduce_value); Py_XDECREF(reduce_value);

View File

@ -3,7 +3,7 @@
#include "Python.h" #include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check() #include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_ceval.h" // _Py_EnterRecursiveCall() #include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate()
#include "pycore_object.h" // _Py_CheckSlotResult() #include "pycore_object.h" // _Py_CheckSlotResult()
#include "pycore_pyerrors.h" // _PyErr_Occurred() #include "pycore_pyerrors.h" // _PyErr_Occurred()
#include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_pystate.h" // _PyThreadState_GET()
@ -2546,7 +2546,7 @@ abstract_issubclass(PyObject *derived, PyObject *cls)
break; break;
} }
assert(n >= 2); assert(n >= 2);
if (Py_EnterRecursiveCall(" in __issubclass__")) { if (_Py_EnterRecursiveCall(" in __issubclass__")) {
Py_DECREF(bases); Py_DECREF(bases);
return -1; return -1;
} }
@ -2556,7 +2556,7 @@ abstract_issubclass(PyObject *derived, PyObject *cls)
break; break;
} }
} }
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
Py_DECREF(bases); Py_DECREF(bases);
return r; return r;
} }
@ -2633,7 +2633,7 @@ object_recursive_isinstance(PyThreadState *tstate, PyObject *inst, PyObject *cls
if (PyTuple_Check(cls)) { if (PyTuple_Check(cls)) {
/* Not a general sequence -- that opens up the road to /* Not a general sequence -- that opens up the road to
recursion and stack overflow. */ recursion and stack overflow. */
if (_Py_EnterRecursiveCall(tstate, " in __instancecheck__")) { if (_Py_EnterRecursiveCallTstate(tstate, " in __instancecheck__")) {
return -1; return -1;
} }
Py_ssize_t n = PyTuple_GET_SIZE(cls); Py_ssize_t n = PyTuple_GET_SIZE(cls);
@ -2646,19 +2646,19 @@ object_recursive_isinstance(PyThreadState *tstate, PyObject *inst, PyObject *cls
break; break;
} }
} }
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
return r; return r;
} }
PyObject *checker = _PyObject_LookupSpecial(cls, &_Py_ID(__instancecheck__)); PyObject *checker = _PyObject_LookupSpecial(cls, &_Py_ID(__instancecheck__));
if (checker != NULL) { if (checker != NULL) {
if (_Py_EnterRecursiveCall(tstate, " in __instancecheck__")) { if (_Py_EnterRecursiveCallTstate(tstate, " in __instancecheck__")) {
Py_DECREF(checker); Py_DECREF(checker);
return -1; return -1;
} }
PyObject *res = PyObject_CallOneArg(checker, inst); PyObject *res = PyObject_CallOneArg(checker, inst);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
Py_DECREF(checker); Py_DECREF(checker);
if (res == NULL) { if (res == NULL) {
@ -2725,7 +2725,7 @@ object_issubclass(PyThreadState *tstate, PyObject *derived, PyObject *cls)
if (PyTuple_Check(cls)) { if (PyTuple_Check(cls)) {
if (_Py_EnterRecursiveCall(tstate, " in __subclasscheck__")) { if (_Py_EnterRecursiveCallTstate(tstate, " in __subclasscheck__")) {
return -1; return -1;
} }
Py_ssize_t n = PyTuple_GET_SIZE(cls); Py_ssize_t n = PyTuple_GET_SIZE(cls);
@ -2737,19 +2737,19 @@ object_issubclass(PyThreadState *tstate, PyObject *derived, PyObject *cls)
/* either found it, or got an error */ /* either found it, or got an error */
break; break;
} }
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
return r; return r;
} }
checker = _PyObject_LookupSpecial(cls, &_Py_ID(__subclasscheck__)); checker = _PyObject_LookupSpecial(cls, &_Py_ID(__subclasscheck__));
if (checker != NULL) { if (checker != NULL) {
int ok = -1; int ok = -1;
if (_Py_EnterRecursiveCall(tstate, " in __subclasscheck__")) { if (_Py_EnterRecursiveCallTstate(tstate, " in __subclasscheck__")) {
Py_DECREF(checker); Py_DECREF(checker);
return ok; return ok;
} }
PyObject *res = PyObject_CallOneArg(checker, derived); PyObject *res = PyObject_CallOneArg(checker, derived);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
Py_DECREF(checker); Py_DECREF(checker);
if (res != NULL) { if (res != NULL) {
ok = PyObject_IsTrue(res); ok = PyObject_IsTrue(res);

View File

@ -3489,7 +3489,7 @@ _PyBytesWriter_Alloc(_PyBytesWriter *writer, Py_ssize_t size)
Don't modify the _PyBytesWriter structure (use a shorter small buffer) Don't modify the _PyBytesWriter structure (use a shorter small buffer)
in debug mode to also be able to detect stack overflow when running in debug mode to also be able to detect stack overflow when running
tests in debug mode. The _PyBytesWriter is large (more than 512 bytes), tests in debug mode. The _PyBytesWriter is large (more than 512 bytes),
if Py_EnterRecursiveCall() is not used in deep C callback, we may hit a if _Py_EnterRecursiveCall() is not used in deep C callback, we may hit a
stack overflow. */ stack overflow. */
writer->allocated = Py_MIN(writer->allocated, 10); writer->allocated = Py_MIN(writer->allocated, 10);
/* _PyBytesWriter_CheckConsistency() requires the last byte to be 0, /* _PyBytesWriter_CheckConsistency() requires the last byte to be 0,

View File

@ -209,11 +209,11 @@ _PyObject_MakeTpCall(PyThreadState *tstate, PyObject *callable,
} }
PyObject *result = NULL; PyObject *result = NULL;
if (_Py_EnterRecursiveCall(tstate, " while calling a Python object") == 0) if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object") == 0)
{ {
result = _PyCFunctionWithKeywords_TrampolineCall( result = _PyCFunctionWithKeywords_TrampolineCall(
(PyCFunctionWithKeywords)call, callable, argstuple, kwdict); (PyCFunctionWithKeywords)call, callable, argstuple, kwdict);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
} }
Py_DECREF(argstuple); Py_DECREF(argstuple);
@ -336,13 +336,13 @@ _PyObject_Call(PyThreadState *tstate, PyObject *callable,
return NULL; return NULL;
} }
if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) { if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) {
return NULL; return NULL;
} }
result = (*call)(callable, args, kwargs); result = (*call)(callable, args, kwargs);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
return _Py_CheckFunctionResult(tstate, callable, result, NULL); return _Py_CheckFunctionResult(tstate, callable, result, NULL);
} }

View File

@ -1,7 +1,7 @@
/* Descriptors -- a new, flexible way to describe attributes */ /* Descriptors -- a new, flexible way to describe attributes */
#include "Python.h" #include "Python.h"
#include "pycore_ceval.h" // _Py_EnterRecursiveCall() #include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate()
#include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_object.h" // _PyObject_GC_UNTRACK()
#include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_tuple.h" // _PyTuple_ITEMS() #include "pycore_tuple.h" // _PyTuple_ITEMS()
@ -302,7 +302,7 @@ typedef void (*funcptr)(void);
static inline funcptr static inline funcptr
method_enter_call(PyThreadState *tstate, PyObject *func) method_enter_call(PyThreadState *tstate, PyObject *func)
{ {
if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) { if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) {
return NULL; return NULL;
} }
return (funcptr)((PyMethodDescrObject *)func)->d_method->ml_meth; return (funcptr)((PyMethodDescrObject *)func)->d_method->ml_meth;
@ -330,7 +330,7 @@ method_vectorcall_VARARGS(
PyObject *result = _PyCFunction_TrampolineCall( PyObject *result = _PyCFunction_TrampolineCall(
meth, args[0], argstuple); meth, args[0], argstuple);
Py_DECREF(argstuple); Py_DECREF(argstuple);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
return result; return result;
} }
@ -363,7 +363,7 @@ method_vectorcall_VARARGS_KEYWORDS(
} }
result = _PyCFunctionWithKeywords_TrampolineCall( result = _PyCFunctionWithKeywords_TrampolineCall(
meth, args[0], argstuple, kwdict); meth, args[0], argstuple, kwdict);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
exit: exit:
Py_DECREF(argstuple); Py_DECREF(argstuple);
Py_XDECREF(kwdict); Py_XDECREF(kwdict);
@ -386,7 +386,7 @@ method_vectorcall_FASTCALL_KEYWORDS_METHOD(
PyObject *result = meth(args[0], PyObject *result = meth(args[0],
((PyMethodDescrObject *)func)->d_common.d_type, ((PyMethodDescrObject *)func)->d_common.d_type,
args+1, nargs-1, kwnames); args+1, nargs-1, kwnames);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
return result; return result;
} }
@ -405,7 +405,7 @@ method_vectorcall_FASTCALL(
return NULL; return NULL;
} }
PyObject *result = meth(args[0], args+1, nargs-1); PyObject *result = meth(args[0], args+1, nargs-1);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
return result; return result;
} }
@ -424,7 +424,7 @@ method_vectorcall_FASTCALL_KEYWORDS(
return NULL; return NULL;
} }
PyObject *result = meth(args[0], args+1, nargs-1, kwnames); PyObject *result = meth(args[0], args+1, nargs-1, kwnames);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
return result; return result;
} }
@ -451,7 +451,7 @@ method_vectorcall_NOARGS(
return NULL; return NULL;
} }
PyObject *result = _PyCFunction_TrampolineCall(meth, args[0], NULL); PyObject *result = _PyCFunction_TrampolineCall(meth, args[0], NULL);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
return result; return result;
} }
@ -479,7 +479,7 @@ method_vectorcall_O(
return NULL; return NULL;
} }
PyObject *result = _PyCFunction_TrampolineCall(meth, args[0], args[1]); PyObject *result = _PyCFunction_TrampolineCall(meth, args[0], args[1]);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
return result; return result;
} }

View File

@ -7,6 +7,7 @@
#define PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <stdbool.h> #include <stdbool.h>
#include "pycore_ceval.h" // _Py_EnterRecursiveCall
#include "pycore_exceptions.h" // struct _Py_exc_state #include "pycore_exceptions.h" // struct _Py_exc_state
#include "pycore_initconfig.h" #include "pycore_initconfig.h"
#include "pycore_object.h" #include "pycore_object.h"
@ -1097,7 +1098,7 @@ exceptiongroup_split_recursive(PyObject *exc,
for (Py_ssize_t i = 0; i < num_excs; i++) { for (Py_ssize_t i = 0; i < num_excs; i++) {
PyObject *e = PyTuple_GET_ITEM(eg->excs, i); PyObject *e = PyTuple_GET_ITEM(eg->excs, i);
_exceptiongroup_split_result rec_result; _exceptiongroup_split_result rec_result;
if (Py_EnterRecursiveCall(" in exceptiongroup_split_recursive")) { if (_Py_EnterRecursiveCall(" in exceptiongroup_split_recursive")) {
goto done; goto done;
} }
if (exceptiongroup_split_recursive( if (exceptiongroup_split_recursive(
@ -1105,10 +1106,10 @@ exceptiongroup_split_recursive(PyObject *exc,
construct_rest, &rec_result) < 0) { construct_rest, &rec_result) < 0) {
assert(!rec_result.match); assert(!rec_result.match);
assert(!rec_result.rest); assert(!rec_result.rest);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
goto done; goto done;
} }
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
if (rec_result.match) { if (rec_result.match) {
assert(PyList_CheckExact(match_list)); assert(PyList_CheckExact(match_list));
if (PyList_Append(match_list, rec_result.match) < 0) { if (PyList_Append(match_list, rec_result.match) < 0) {
@ -1234,11 +1235,11 @@ collect_exception_group_leaves(PyObject *exc, PyObject *leaves)
/* recursive calls */ /* recursive calls */
for (Py_ssize_t i = 0; i < num_excs; i++) { for (Py_ssize_t i = 0; i < num_excs; i++) {
PyObject *e = PyTuple_GET_ITEM(eg->excs, i); PyObject *e = PyTuple_GET_ITEM(eg->excs, i);
if (Py_EnterRecursiveCall(" in collect_exception_group_leaves")) { if (_Py_EnterRecursiveCall(" in collect_exception_group_leaves")) {
return -1; return -1;
} }
int res = collect_exception_group_leaves(e, leaves); int res = collect_exception_group_leaves(e, leaves);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
if (res < 0) { if (res < 0) {
return -1; return -1;
} }

View File

@ -2,7 +2,7 @@
/* Method object implementation */ /* Method object implementation */
#include "Python.h" #include "Python.h"
#include "pycore_ceval.h" // _Py_EnterRecursiveCall() #include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate()
#include "pycore_object.h" #include "pycore_object.h"
#include "pycore_pyerrors.h" #include "pycore_pyerrors.h"
#include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_pystate.h" // _PyThreadState_GET()
@ -403,7 +403,7 @@ typedef void (*funcptr)(void);
static inline funcptr static inline funcptr
cfunction_enter_call(PyThreadState *tstate, PyObject *func) cfunction_enter_call(PyThreadState *tstate, PyObject *func)
{ {
if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) { if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) {
return NULL; return NULL;
} }
return (funcptr)PyCFunction_GET_FUNCTION(func); return (funcptr)PyCFunction_GET_FUNCTION(func);
@ -425,7 +425,7 @@ cfunction_vectorcall_FASTCALL(
return NULL; return NULL;
} }
PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs); PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
return result; return result;
} }
@ -441,7 +441,7 @@ cfunction_vectorcall_FASTCALL_KEYWORDS(
return NULL; return NULL;
} }
PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs, kwnames); PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs, kwnames);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
return result; return result;
} }
@ -457,7 +457,7 @@ cfunction_vectorcall_FASTCALL_KEYWORDS_METHOD(
return NULL; return NULL;
} }
PyObject *result = meth(PyCFunction_GET_SELF(func), cls, args, nargs, kwnames); PyObject *result = meth(PyCFunction_GET_SELF(func), cls, args, nargs, kwnames);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
return result; return result;
} }
@ -485,7 +485,7 @@ cfunction_vectorcall_NOARGS(
} }
PyObject *result = _PyCFunction_TrampolineCall( PyObject *result = _PyCFunction_TrampolineCall(
meth, PyCFunction_GET_SELF(func), NULL); meth, PyCFunction_GET_SELF(func), NULL);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
return result; return result;
} }
@ -513,7 +513,7 @@ cfunction_vectorcall_O(
} }
PyObject *result = _PyCFunction_TrampolineCall( PyObject *result = _PyCFunction_TrampolineCall(
meth, PyCFunction_GET_SELF(func), args[0]); meth, PyCFunction_GET_SELF(func), args[0]);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
return result; return result;
} }

View File

@ -3,7 +3,7 @@
#include "Python.h" #include "Python.h"
#include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_ceval.h" // _Py_EnterRecursiveCall() #include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate()
#include "pycore_context.h" // _PyContextTokenMissing_Type #include "pycore_context.h" // _PyContextTokenMissing_Type
#include "pycore_dict.h" // _PyObject_MakeDictFromInstanceAttributes() #include "pycore_dict.h" // _PyObject_MakeDictFromInstanceAttributes()
#include "pycore_floatobject.h" // _PyFloat_DebugMallocStats() #include "pycore_floatobject.h" // _PyFloat_DebugMallocStats()
@ -427,12 +427,12 @@ PyObject_Repr(PyObject *v)
/* It is possible for a type to have a tp_repr representation that loops /* It is possible for a type to have a tp_repr representation that loops
infinitely. */ infinitely. */
if (_Py_EnterRecursiveCall(tstate, if (_Py_EnterRecursiveCallTstate(tstate,
" while getting the repr of an object")) { " while getting the repr of an object")) {
return NULL; return NULL;
} }
res = (*Py_TYPE(v)->tp_repr)(v); res = (*Py_TYPE(v)->tp_repr)(v);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
if (res == NULL) { if (res == NULL) {
return NULL; return NULL;
@ -487,11 +487,11 @@ PyObject_Str(PyObject *v)
/* It is possible for a type to have a tp_str representation that loops /* It is possible for a type to have a tp_str representation that loops
infinitely. */ infinitely. */
if (_Py_EnterRecursiveCall(tstate, " while getting the str of an object")) { if (_Py_EnterRecursiveCallTstate(tstate, " while getting the str of an object")) {
return NULL; return NULL;
} }
res = (*Py_TYPE(v)->tp_str)(v); res = (*Py_TYPE(v)->tp_str)(v);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
if (res == NULL) { if (res == NULL) {
return NULL; return NULL;
@ -724,11 +724,11 @@ PyObject_RichCompare(PyObject *v, PyObject *w, int op)
} }
return NULL; return NULL;
} }
if (_Py_EnterRecursiveCall(tstate, " in comparison")) { if (_Py_EnterRecursiveCallTstate(tstate, " in comparison")) {
return NULL; return NULL;
} }
PyObject *res = do_richcompare(tstate, v, w, op); PyObject *res = do_richcompare(tstate, v, w, op);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
return res; return res;
} }

View File

@ -490,11 +490,11 @@ class Obj2ModPrototypeVisitor(PickleVisitor):
class Obj2ModVisitor(PickleVisitor): class Obj2ModVisitor(PickleVisitor):
@contextmanager @contextmanager
def recursive_call(self, node, level): def recursive_call(self, node, level):
self.emit('if (Py_EnterRecursiveCall(" while traversing \'%s\' node")) {' % node, level, reflow=False) self.emit('if (_Py_EnterRecursiveCall(" while traversing \'%s\' node")) {' % node, level, reflow=False)
self.emit('goto failed;', level + 1) self.emit('goto failed;', level + 1)
self.emit('}', level) self.emit('}', level)
yield yield
self.emit('Py_LeaveRecursiveCall();', level) self.emit('_Py_LeaveRecursiveCall();', level)
def funcHeader(self, name): def funcHeader(self, name):
ctype = get_c_type(name) ctype = get_c_type(name)
@ -1482,9 +1482,10 @@ def generate_module_def(mod, metadata, f, internal_h):
print(textwrap.dedent(""" print(textwrap.dedent("""
#include "Python.h" #include "Python.h"
#include "pycore_ast.h" #include "pycore_ast.h"
#include "pycore_ast_state.h" // struct ast_state #include "pycore_ast_state.h" // struct ast_state
#include "pycore_interp.h" // _PyInterpreterState.ast #include "pycore_ceval.h" // _Py_EnterRecursiveCall
#include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_interp.h" // _PyInterpreterState.ast
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "structmember.h" #include "structmember.h"
#include <stddef.h> #include <stddef.h>

831
Python/Python-ast.c generated

File diff suppressed because it is too large Load Diff

View File

@ -880,7 +880,7 @@ Py_SetRecursionLimit(int new_limit)
} }
} }
/* The function _Py_EnterRecursiveCall() only calls _Py_CheckRecursiveCall() /* The function _Py_EnterRecursiveCallTstate() only calls _Py_CheckRecursiveCall()
if the recursion_depth reaches recursion_limit. */ if the recursion_depth reaches recursion_limit. */
int int
_Py_CheckRecursiveCall(PyThreadState *tstate, const char *where) _Py_CheckRecursiveCall(PyThreadState *tstate, const char *where)
@ -1736,7 +1736,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
/* support for generator.throw() */ /* support for generator.throw() */
if (throwflag) { if (throwflag) {
if (_Py_EnterRecursiveCall(tstate, "")) { if (_Py_EnterRecursiveCallTstate(tstate, "")) {
tstate->recursion_remaining--; tstate->recursion_remaining--;
goto exit_unwind; goto exit_unwind;
} }
@ -1776,7 +1776,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
start_frame: start_frame:
if (_Py_EnterRecursiveCall(tstate, "")) { if (_Py_EnterRecursiveCallTstate(tstate, "")) {
tstate->recursion_remaining--; tstate->recursion_remaining--;
goto exit_unwind; goto exit_unwind;
} }
@ -2492,7 +2492,7 @@ handle_eval_breaker:
_PyFrame_SetStackPointer(frame, stack_pointer); _PyFrame_SetStackPointer(frame, stack_pointer);
TRACE_FUNCTION_EXIT(); TRACE_FUNCTION_EXIT();
DTRACE_FUNCTION_EXIT(); DTRACE_FUNCTION_EXIT();
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
if (!frame->is_entry) { if (!frame->is_entry) {
frame = cframe.current_frame = pop_frame(tstate, frame); frame = cframe.current_frame = pop_frame(tstate, frame);
_PyFrame_StackPush(frame, retval); _PyFrame_StackPush(frame, retval);
@ -2704,7 +2704,7 @@ handle_eval_breaker:
_PyFrame_SetStackPointer(frame, stack_pointer); _PyFrame_SetStackPointer(frame, stack_pointer);
TRACE_FUNCTION_EXIT(); TRACE_FUNCTION_EXIT();
DTRACE_FUNCTION_EXIT(); DTRACE_FUNCTION_EXIT();
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
/* Restore previous cframe and return. */ /* Restore previous cframe and return. */
tstate->cframe = cframe.previous; tstate->cframe = cframe.previous;
tstate->cframe->use_tracing = cframe.use_tracing; tstate->cframe->use_tracing = cframe.use_tracing;
@ -5066,12 +5066,12 @@ handle_eval_breaker:
PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable);
// This is slower but CPython promises to check all non-vectorcall // This is slower but CPython promises to check all non-vectorcall
// function calls. // function calls.
if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) { if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) {
goto error; goto error;
} }
PyObject *arg = TOP(); PyObject *arg = TOP();
PyObject *res = cfunc(PyCFunction_GET_SELF(callable), arg); PyObject *res = cfunc(PyCFunction_GET_SELF(callable), arg);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
Py_DECREF(arg); Py_DECREF(arg);
@ -5268,11 +5268,11 @@ handle_eval_breaker:
PyCFunction cfunc = meth->ml_meth; PyCFunction cfunc = meth->ml_meth;
// This is slower but CPython promises to check all non-vectorcall // This is slower but CPython promises to check all non-vectorcall
// function calls. // function calls.
if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) { if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) {
goto error; goto error;
} }
PyObject *res = cfunc(self, arg); PyObject *res = cfunc(self, arg);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
Py_DECREF(self); Py_DECREF(self);
Py_DECREF(arg); Py_DECREF(arg);
@ -5340,11 +5340,11 @@ handle_eval_breaker:
PyCFunction cfunc = meth->ml_meth; PyCFunction cfunc = meth->ml_meth;
// This is slower but CPython promises to check all non-vectorcall // This is slower but CPython promises to check all non-vectorcall
// function calls. // function calls.
if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) { if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) {
goto error; goto error;
} }
PyObject *res = cfunc(self, NULL); PyObject *res = cfunc(self, NULL);
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
Py_DECREF(self); Py_DECREF(self);
STACK_SHRINK(oparg + 1); STACK_SHRINK(oparg + 1);
@ -5484,7 +5484,7 @@ handle_eval_breaker:
assert(frame->frame_obj == NULL); assert(frame->frame_obj == NULL);
gen->gi_frame_state = FRAME_CREATED; gen->gi_frame_state = FRAME_CREATED;
gen_frame->owner = FRAME_OWNED_BY_GENERATOR; gen_frame->owner = FRAME_OWNED_BY_GENERATOR;
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
if (!frame->is_entry) { if (!frame->is_entry) {
_PyInterpreterFrame *prev = frame->previous; _PyInterpreterFrame *prev = frame->previous;
_PyThreadState_PopFrame(tstate, frame); _PyThreadState_PopFrame(tstate, frame);
@ -5850,7 +5850,7 @@ exception_unwind:
exit_unwind: exit_unwind:
assert(_PyErr_Occurred(tstate)); assert(_PyErr_Occurred(tstate));
_Py_LeaveRecursiveCall(tstate); _Py_LeaveRecursiveCallTstate(tstate);
if (frame->is_entry) { if (frame->is_entry) {
/* Restore previous cframe and exit */ /* Restore previous cframe and exit */
tstate->cframe = cframe.previous; tstate->cframe = cframe.previous;
@ -7955,12 +7955,12 @@ maybe_dtrace_line(_PyInterpreterFrame *frame,
int Py_EnterRecursiveCall(const char *where) int Py_EnterRecursiveCall(const char *where)
{ {
return _Py_EnterRecursiveCall_inline(where); return _Py_EnterRecursiveCall(where);
} }
#undef Py_LeaveRecursiveCall #undef Py_LeaveRecursiveCall
void Py_LeaveRecursiveCall(void) void Py_LeaveRecursiveCall(void)
{ {
_Py_LeaveRecursiveCall_inline(); _Py_LeaveRecursiveCall();
} }

View File

@ -13,6 +13,7 @@
#include "Python.h" #include "Python.h"
#include "pycore_ast.h" // PyAST_mod2obj #include "pycore_ast.h" // PyAST_mod2obj
#include "pycore_ceval.h" // _Py_EnterRecursiveCall
#include "pycore_compile.h" // _PyAST_Compile() #include "pycore_compile.h" // _PyAST_Compile()
#include "pycore_interp.h" // PyInterpreterState.importlib #include "pycore_interp.h" // PyInterpreterState.importlib
#include "pycore_object.h" // _PyDebug_PrintTotalRefs() #include "pycore_object.h" // _PyDebug_PrintTotalRefs()
@ -1268,13 +1269,13 @@ print_chained(struct exception_print_context* ctx, PyObject *value,
{ {
PyObject *f = ctx->file; PyObject *f = ctx->file;
if (Py_EnterRecursiveCall(" in print_chained") < 0) { if (_Py_EnterRecursiveCall(" in print_chained") < 0) {
return -1; return -1;
} }
bool need_close = ctx->need_close; bool need_close = ctx->need_close;
int res = print_exception_recursive(ctx, value); int res = print_exception_recursive(ctx, value);
ctx->need_close = need_close; ctx->need_close = need_close;
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
if (res < 0) { if (res < 0) {
return -1; return -1;
} }
@ -1445,11 +1446,11 @@ print_exception_group(struct exception_print_context *ctx, PyObject *value)
PyObject *exc = PyTuple_GET_ITEM(excs, i); PyObject *exc = PyTuple_GET_ITEM(excs, i);
if (!truncated) { if (!truncated) {
if (Py_EnterRecursiveCall(" in print_exception_group") != 0) { if (_Py_EnterRecursiveCall(" in print_exception_group") != 0) {
return -1; return -1;
} }
int res = print_exception_recursive(ctx, exc); int res = print_exception_recursive(ctx, exc);
Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
if (res < 0) { if (res < 0) {
return -1; return -1;
} }