@@ -56,6 +56,66 @@ extern PyObject *_PyEval_EvalCode(
5656extern int _PyEval_ThreadsInitialized (_PyRuntimeState * runtime );
5757extern PyStatus _PyEval_InitThreads (PyThreadState * tstate );
5858
59+
60+ /* --- _Py_EnterRecursiveCall() ----------------------------------------- */
61+
62+ PyAPI_DATA (int ) _Py_CheckRecursionLimit ;
63+
64+ #ifdef USE_STACKCHECK
65+ /* With USE_STACKCHECK macro defined, trigger stack checks in
66+ _Py_CheckRecursiveCall() on every 64th call to Py_EnterRecursiveCall. */
67+ static inline int _Py_MakeRecCheck (PyThreadState * tstate ) {
68+ return (++ tstate -> recursion_depth > _Py_CheckRecursionLimit
69+ || ++ tstate -> stackcheck_counter > 64 );
70+ }
71+ #else
72+ static inline int _Py_MakeRecCheck (PyThreadState * tstate ) {
73+ return (++ tstate -> recursion_depth > _Py_CheckRecursionLimit );
74+ }
75+ #endif
76+
77+ PyAPI_FUNC (int ) _Py_CheckRecursiveCall (
78+ PyThreadState * tstate ,
79+ const char * where );
80+
81+ static inline int _Py_EnterRecursiveCall (PyThreadState * tstate ,
82+ const char * where ) {
83+ return (_Py_MakeRecCheck (tstate ) && _Py_CheckRecursiveCall (tstate , where ));
84+ }
85+
86+ static inline int _Py_EnterRecursiveCall_inline (const char * where ) {
87+ PyThreadState * tstate = PyThreadState_GET ();
88+ return _Py_EnterRecursiveCall (tstate , where );
89+ }
90+
91+ #define Py_EnterRecursiveCall (where ) _Py_EnterRecursiveCall_inline(where)
92+
93+
94+ /* Compute the "lower-water mark" for a recursion limit. When
95+ * Py_LeaveRecursiveCall() is called with a recursion depth below this mark,
96+ * the overflowed flag is reset to 0. */
97+ #define _Py_RecursionLimitLowerWaterMark (limit ) \
98+ (((limit) > 200) \
99+ ? ((limit) - 50) \
100+ : (3 * ((limit) >> 2)))
101+
102+ #define _Py_MakeEndRecCheck (x ) \
103+ (--(x) < _Py_RecursionLimitLowerWaterMark(_Py_CheckRecursionLimit))
104+
105+ static inline void _Py_LeaveRecursiveCall (PyThreadState * tstate ) {
106+ if (_Py_MakeEndRecCheck (tstate -> recursion_depth )) {
107+ tstate -> overflowed = 0 ;
108+ }
109+ }
110+
111+ static inline void _Py_LeaveRecursiveCall_inline (void ) {
112+ PyThreadState * tstate = PyThreadState_GET ();
113+ _Py_LeaveRecursiveCall (tstate );
114+ }
115+
116+ #define Py_LeaveRecursiveCall () _Py_LeaveRecursiveCall_inline()
117+
118+
59119#ifdef __cplusplus
60120}
61121#endif
0 commit comments