@@ -193,18 +193,28 @@ extern void _PyEval_DeactivateOpCache(void);
193193
194194/* --- _Py_EnterRecursiveCall() ----------------------------------------- */
195195
196- #ifdef USE_STACKCHECK
197- /* With USE_STACKCHECK macro defined, trigger stack checks in
198- _Py_CheckRecursiveCall() on every 64th call to _Py_EnterRecursiveCall. */
199- static inline int _Py_MakeRecCheck (PyThreadState * tstate ) {
200- return (tstate -> c_recursion_remaining -- < 0
201- || (tstate -> c_recursion_remaining & 63 ) == 0 );
196+ #if !_Py__has_builtin (__builtin_frame_address )
197+ static uintptr_t return_pointer_as_int (char * p ) {
198+ return (uintptr_t )p ;
202199}
200+ #endif
201+
202+ static inline uintptr_t
203+ _Py_get_machine_stack_pointer (void ) {
204+ #if _Py__has_builtin (__builtin_frame_address )
205+ return (uintptr_t )__builtin_frame_address (0 );
203206#else
204- static inline int _Py_MakeRecCheck ( PyThreadState * tstate ) {
205- return tstate -> c_recursion_remaining -- < 0 ;
206- }
207+ char here ;
208+ /* Avoid compiler warning about returning stack address */
209+ return return_pointer_as_int ( & here );
207210#endif
211+ }
212+
213+ static inline int _Py_MakeRecCheck (PyThreadState * tstate ) {
214+ uintptr_t here_addr = _Py_get_machine_stack_pointer ();
215+ _PyThreadStateImpl * _tstate = (_PyThreadStateImpl * )tstate ;
216+ return here_addr < _tstate -> c_stack_soft_limit ;
217+ }
208218
209219// Export for '_json' shared extension, used via _Py_EnterRecursiveCall()
210220// static inline function.
@@ -220,23 +230,30 @@ static inline int _Py_EnterRecursiveCallTstate(PyThreadState *tstate,
220230 return (_Py_MakeRecCheck (tstate ) && _Py_CheckRecursiveCall (tstate , where ));
221231}
222232
223- static inline void _Py_EnterRecursiveCallTstateUnchecked (PyThreadState * tstate ) {
224- assert (tstate -> c_recursion_remaining > 0 );
225- tstate -> c_recursion_remaining -- ;
226- }
227-
228233static inline int _Py_EnterRecursiveCall (const char * where ) {
229234 PyThreadState * tstate = _PyThreadState_GET ();
230235 return _Py_EnterRecursiveCallTstate (tstate , where );
231236}
232237
233- static inline void _Py_LeaveRecursiveCallTstate (PyThreadState * tstate ) {
234- tstate -> c_recursion_remaining ++ ;
238+ static inline void _Py_LeaveRecursiveCallTstate (PyThreadState * tstate ) {
239+ (void )tstate ;
240+ }
241+
242+ PyAPI_FUNC (void ) _Py_InitializeRecursionLimits (PyThreadState * tstate );
243+
244+ static inline int _Py_ReachedRecursionLimit (PyThreadState * tstate ) {
245+ uintptr_t here_addr = _Py_get_machine_stack_pointer ();
246+ _PyThreadStateImpl * _tstate = (_PyThreadStateImpl * )tstate ;
247+ if (here_addr > _tstate -> c_stack_soft_limit ) {
248+ return 0 ;
249+ }
250+ if (_tstate -> c_stack_hard_limit == 0 ) {
251+ _Py_InitializeRecursionLimits (tstate );
252+ }
253+ return here_addr <= _tstate -> c_stack_soft_limit ;
235254}
236255
237256static inline void _Py_LeaveRecursiveCall (void ) {
238- PyThreadState * tstate = _PyThreadState_GET ();
239- _Py_LeaveRecursiveCallTstate (tstate );
240257}
241258
242259extern struct _PyInterpreterFrame * _PyEval_GetFrame (void );
@@ -327,7 +344,6 @@ void _Py_unset_eval_breaker_bit_all(PyInterpreterState *interp, uintptr_t bit);
327344
328345PyAPI_FUNC (PyObject * ) _PyFloat_FromDouble_ConsumeInputs (_PyStackRef left , _PyStackRef right , double value );
329346
330-
331347#ifdef __cplusplus
332348}
333349#endif
0 commit comments