@@ -193,18 +193,28 @@ extern void _PyEval_DeactivateOpCache(void);
193
193
194
194
/* --- _Py_EnterRecursiveCall() ----------------------------------------- */
195
195
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 ;
202
199
}
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 );
203
206
#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 );
207
210
#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
+ }
208
218
209
219
// Export for '_json' shared extension, used via _Py_EnterRecursiveCall()
210
220
// static inline function.
@@ -220,23 +230,30 @@ static inline int _Py_EnterRecursiveCallTstate(PyThreadState *tstate,
220
230
return (_Py_MakeRecCheck (tstate ) && _Py_CheckRecursiveCall (tstate , where ));
221
231
}
222
232
223
- static inline void _Py_EnterRecursiveCallTstateUnchecked (PyThreadState * tstate ) {
224
- assert (tstate -> c_recursion_remaining > 0 );
225
- tstate -> c_recursion_remaining -- ;
226
- }
227
-
228
233
static inline int _Py_EnterRecursiveCall (const char * where ) {
229
234
PyThreadState * tstate = _PyThreadState_GET ();
230
235
return _Py_EnterRecursiveCallTstate (tstate , where );
231
236
}
232
237
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 ;
235
254
}
236
255
237
256
static inline void _Py_LeaveRecursiveCall (void ) {
238
- PyThreadState * tstate = _PyThreadState_GET ();
239
- _Py_LeaveRecursiveCallTstate (tstate );
240
257
}
241
258
242
259
extern struct _PyInterpreterFrame * _PyEval_GetFrame (void );
@@ -327,7 +344,6 @@ void _Py_unset_eval_breaker_bit_all(PyInterpreterState *interp, uintptr_t bit);
327
344
328
345
PyAPI_FUNC (PyObject * ) _PyFloat_FromDouble_ConsumeInputs (_PyStackRef left , _PyStackRef right , double value );
329
346
330
-
331
347
#ifdef __cplusplus
332
348
}
333
349
#endif
0 commit comments