Skip to content

Use static inline function Py_EnterRecursiveCall() #91988

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 8 additions & 12 deletions Include/internal/pycore_ceval.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ extern void _PyEval_DeactivateOpCache(void);

#ifdef USE_STACKCHECK
/* 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) {
return (tstate->recursion_remaining-- <= 0
|| (tstate->recursion_remaining & 63) == 0);
Expand All @@ -106,29 +106,25 @@ PyAPI_FUNC(int) _Py_CheckRecursiveCall(
PyThreadState *tstate,
const char *where);

static inline int _Py_EnterRecursiveCall(PyThreadState *tstate,
const char *where) {
static inline int _Py_EnterRecursiveCallTstate(PyThreadState *tstate,
const char *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();
return _Py_EnterRecursiveCall(tstate, where);
return _Py_EnterRecursiveCallTstate(tstate, where);
}

#define Py_EnterRecursiveCall(where) _Py_EnterRecursiveCall_inline(where)

static inline void _Py_LeaveRecursiveCall(PyThreadState *tstate) {
static inline void _Py_LeaveRecursiveCallTstate(PyThreadState *tstate) {
tstate->recursion_remaining++;
}

static inline void _Py_LeaveRecursiveCall_inline(void) {
static inline void _Py_LeaveRecursiveCall(void) {
PyThreadState *tstate = _PyThreadState_GET();
_Py_LeaveRecursiveCall(tstate);
_Py_LeaveRecursiveCallTstate(tstate);
}

#define Py_LeaveRecursiveCall() _Py_LeaveRecursiveCall_inline()

extern struct _PyInterpreterFrame* _PyEval_GetFrame(void);

extern PyObject* _Py_MakeCoro(PyFunctionObject *func);
Expand Down
5 changes: 3 additions & 2 deletions Modules/_ctypes/_ctypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ bytes(cdata)
#endif

#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_ceval.h" // _Py_EnterRecursiveCall()
#include "structmember.h" // PyMemberDef

#include <ffi.h>
Expand Down Expand Up @@ -2270,12 +2271,12 @@ PyCSimpleType_from_param(PyObject *type, PyObject *value)
return NULL;
}
if (as_parameter) {
if (Py_EnterRecursiveCall("while processing _as_parameter_")) {
if (_Py_EnterRecursiveCall("while processing _as_parameter_")) {
Py_DECREF(as_parameter);
return NULL;
}
value = PyCSimpleType_from_param(type, as_parameter);
Py_LeaveRecursiveCall();
_Py_LeaveRecursiveCall();
Py_DECREF(as_parameter);
return value;
}
Expand Down
25 changes: 13 additions & 12 deletions Modules/_json.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define NEEDS_PY_IDENTIFIER

#include "Python.h"
#include "pycore_ceval.h" // _Py_EnterRecursiveCall()
#include "structmember.h" // PyMemberDef
#include "pycore_accu.h"

Expand Down Expand Up @@ -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);
case '{':
/* object */
if (Py_EnterRecursiveCall(" while decoding a JSON object "
"from a unicode string"))
if (_Py_EnterRecursiveCall(" while decoding a JSON object "
"from a unicode string"))
return NULL;
res = _parse_object_unicode(s, pystr, idx + 1, next_idx_ptr);
Py_LeaveRecursiveCall();
_Py_LeaveRecursiveCall();
return res;
case '[':
/* array */
if (Py_EnterRecursiveCall(" while decoding a JSON array "
"from a unicode string"))
if (_Py_EnterRecursiveCall(" while decoding a JSON array "
"from a unicode string"))
return NULL;
res = _parse_array_unicode(s, pystr, idx + 1, next_idx_ptr);
Py_LeaveRecursiveCall();
_Py_LeaveRecursiveCall();
return res;
case 'n':
/* null */
Expand Down Expand Up @@ -1430,17 +1431,17 @@ encoder_listencode_obj(PyEncoderObject *s, _PyAccu *acc,
return _steal_accumulate(acc, encoded);
}
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;
rv = encoder_listencode_list(s, acc, obj, indent_level);
Py_LeaveRecursiveCall();
_Py_LeaveRecursiveCall();
return rv;
}
else if (PyDict_Check(obj)) {
if (Py_EnterRecursiveCall(" while encoding a JSON object"))
if (_Py_EnterRecursiveCall(" while encoding a JSON object"))
return -1;
rv = encoder_listencode_dict(s, acc, obj, indent_level);
Py_LeaveRecursiveCall();
_Py_LeaveRecursiveCall();
return rv;
}
else {
Expand Down Expand Up @@ -1468,13 +1469,13 @@ encoder_listencode_obj(PyEncoderObject *s, _PyAccu *acc,
return -1;
}

if (Py_EnterRecursiveCall(" while encoding a JSON object")) {
if (_Py_EnterRecursiveCall(" while encoding a JSON object")) {
Py_DECREF(newobj);
Py_XDECREF(ident);
return -1;
}
rv = encoder_listencode_obj(s, acc, newobj, indent_level);
Py_LeaveRecursiveCall();
_Py_LeaveRecursiveCall();

Py_DECREF(newobj);
if (rv) {
Expand Down
23 changes: 12 additions & 11 deletions Modules/_pickle.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#endif

#include "Python.h"
#include "pycore_ceval.h" // _Py_EnterRecursiveCall()
#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_runtime.h" // _Py_ID()
#include "pycore_pystate.h" // _PyThreadState_GET()
Expand Down Expand Up @@ -3068,21 +3069,21 @@ save_list(PicklerObject *self, PyObject *obj)
if (len != 0) {
/* Materialize the list elements. */
if (PyList_CheckExact(obj) && self->proto > 0) {
if (Py_EnterRecursiveCall(" while pickling an object"))
if (_Py_EnterRecursiveCall(" while pickling an object"))
goto error;
status = batch_list_exact(self, obj);
Py_LeaveRecursiveCall();
_Py_LeaveRecursiveCall();
} else {
PyObject *iter = PyObject_GetIter(obj);
if (iter == NULL)
goto error;

if (Py_EnterRecursiveCall(" while pickling an object")) {
if (_Py_EnterRecursiveCall(" while pickling an object")) {
Py_DECREF(iter);
goto error;
}
status = batch_list(self, iter);
Py_LeaveRecursiveCall();
_Py_LeaveRecursiveCall();
Py_DECREF(iter);
}
}
Expand Down Expand Up @@ -3327,10 +3328,10 @@ save_dict(PicklerObject *self, PyObject *obj)
if (PyDict_CheckExact(obj) && self->proto > 0) {
/* We can take certain shortcuts if we know this is a dict and
not a dict subclass. */
if (Py_EnterRecursiveCall(" while pickling an object"))
if (_Py_EnterRecursiveCall(" while pickling an object"))
goto error;
status = batch_dict_exact(self, obj);
Py_LeaveRecursiveCall();
_Py_LeaveRecursiveCall();
} else {
items = PyObject_CallMethodNoArgs(obj, &_Py_ID(items));
if (items == NULL)
Expand All @@ -3339,12 +3340,12 @@ save_dict(PicklerObject *self, PyObject *obj)
Py_DECREF(items);
if (iter == NULL)
goto error;
if (Py_EnterRecursiveCall(" while pickling an object")) {
if (_Py_EnterRecursiveCall(" while pickling an object")) {
Py_DECREF(iter);
goto error;
}
status = batch_dict(self, iter);
Py_LeaveRecursiveCall();
_Py_LeaveRecursiveCall();
Py_DECREF(iter);
}
}
Expand Down Expand Up @@ -4300,9 +4301,9 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
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. */
if (Py_EnterRecursiveCall(" while pickling an object")) {
if (_Py_EnterRecursiveCall(" while pickling an object")) {
return -1;
}

Expand Down Expand Up @@ -4460,7 +4461,7 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
}
done:

Py_LeaveRecursiveCall();
_Py_LeaveRecursiveCall();
Py_XDECREF(reduce_func);
Py_XDECREF(reduce_value);

Expand Down
22 changes: 11 additions & 11 deletions Objects/abstract.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#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_pyerrors.h" // _PyErr_Occurred()
#include "pycore_pystate.h" // _PyThreadState_GET()
Expand Down Expand Up @@ -2546,7 +2546,7 @@ abstract_issubclass(PyObject *derived, PyObject *cls)
break;
}
assert(n >= 2);
if (Py_EnterRecursiveCall(" in __issubclass__")) {
if (_Py_EnterRecursiveCall(" in __issubclass__")) {
Py_DECREF(bases);
return -1;
}
Expand All @@ -2556,7 +2556,7 @@ abstract_issubclass(PyObject *derived, PyObject *cls)
break;
}
}
Py_LeaveRecursiveCall();
_Py_LeaveRecursiveCall();
Py_DECREF(bases);
return r;
}
Expand Down Expand Up @@ -2633,7 +2633,7 @@ object_recursive_isinstance(PyThreadState *tstate, PyObject *inst, PyObject *cls
if (PyTuple_Check(cls)) {
/* Not a general sequence -- that opens up the road to
recursion and stack overflow. */
if (_Py_EnterRecursiveCall(tstate, " in __instancecheck__")) {
if (_Py_EnterRecursiveCallTstate(tstate, " in __instancecheck__")) {
return -1;
}
Py_ssize_t n = PyTuple_GET_SIZE(cls);
Expand All @@ -2646,19 +2646,19 @@ object_recursive_isinstance(PyThreadState *tstate, PyObject *inst, PyObject *cls
break;
}
}
_Py_LeaveRecursiveCall(tstate);
_Py_LeaveRecursiveCallTstate(tstate);
return r;
}

PyObject *checker = _PyObject_LookupSpecial(cls, &_Py_ID(__instancecheck__));
if (checker != NULL) {
if (_Py_EnterRecursiveCall(tstate, " in __instancecheck__")) {
if (_Py_EnterRecursiveCallTstate(tstate, " in __instancecheck__")) {
Py_DECREF(checker);
return -1;
}

PyObject *res = PyObject_CallOneArg(checker, inst);
_Py_LeaveRecursiveCall(tstate);
_Py_LeaveRecursiveCallTstate(tstate);
Py_DECREF(checker);

if (res == NULL) {
Expand Down Expand Up @@ -2725,7 +2725,7 @@ object_issubclass(PyThreadState *tstate, PyObject *derived, PyObject *cls)

if (PyTuple_Check(cls)) {

if (_Py_EnterRecursiveCall(tstate, " in __subclasscheck__")) {
if (_Py_EnterRecursiveCallTstate(tstate, " in __subclasscheck__")) {
return -1;
}
Py_ssize_t n = PyTuple_GET_SIZE(cls);
Expand All @@ -2737,19 +2737,19 @@ object_issubclass(PyThreadState *tstate, PyObject *derived, PyObject *cls)
/* either found it, or got an error */
break;
}
_Py_LeaveRecursiveCall(tstate);
_Py_LeaveRecursiveCallTstate(tstate);
return r;
}

checker = _PyObject_LookupSpecial(cls, &_Py_ID(__subclasscheck__));
if (checker != NULL) {
int ok = -1;
if (_Py_EnterRecursiveCall(tstate, " in __subclasscheck__")) {
if (_Py_EnterRecursiveCallTstate(tstate, " in __subclasscheck__")) {
Py_DECREF(checker);
return ok;
}
PyObject *res = PyObject_CallOneArg(checker, derived);
_Py_LeaveRecursiveCall(tstate);
_Py_LeaveRecursiveCallTstate(tstate);
Py_DECREF(checker);
if (res != NULL) {
ok = PyObject_IsTrue(res);
Expand Down
2 changes: 1 addition & 1 deletion Objects/bytesobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -3489,7 +3489,7 @@ _PyBytesWriter_Alloc(_PyBytesWriter *writer, Py_ssize_t size)
Don't modify the _PyBytesWriter structure (use a shorter small buffer)
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),
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. */
writer->allocated = Py_MIN(writer->allocated, 10);
/* _PyBytesWriter_CheckConsistency() requires the last byte to be 0,
Expand Down
8 changes: 4 additions & 4 deletions Objects/call.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,11 +209,11 @@ _PyObject_MakeTpCall(PyThreadState *tstate, PyObject *callable,
}

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(
(PyCFunctionWithKeywords)call, callable, argstuple, kwdict);
_Py_LeaveRecursiveCall(tstate);
_Py_LeaveRecursiveCallTstate(tstate);
}

Py_DECREF(argstuple);
Expand Down Expand Up @@ -336,13 +336,13 @@ _PyObject_Call(PyThreadState *tstate, PyObject *callable,
return NULL;
}

if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) {
if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) {
return NULL;
}

result = (*call)(callable, args, kwargs);

_Py_LeaveRecursiveCall(tstate);
_Py_LeaveRecursiveCallTstate(tstate);

return _Py_CheckFunctionResult(tstate, callable, result, NULL);
}
Expand Down
Loading