]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-91079: Implement C stack limits using addresses, not counters. (GH-130007)
authorMark Shannon <mark@hotpy.org>
Wed, 19 Feb 2025 11:44:57 +0000 (11:44 +0000)
committerGitHub <noreply@github.com>
Wed, 19 Feb 2025 11:44:57 +0000 (11:44 +0000)
* Implement C recursion protection with limit pointers

* Remove calls to PyOS_CheckStack

* Add stack protection to parser

* Make tests more robust to low stacks

* Improve error messages for stack overflow

47 files changed:
Doc/c-api/exceptions.rst
Include/cpython/object.h
Include/cpython/pystate.h
Include/internal/pycore_ceval.h
Include/internal/pycore_symtable.h
Include/internal/pycore_tstate.h
Include/pythonrun.h
Lib/test/list_tests.py
Lib/test/mapping_tests.py
Lib/test/pythoninfo.py
Lib/test/support/__init__.py
Lib/test/test_ast/test_ast.py
Lib/test/test_call.py
Lib/test/test_capi/test_misc.py
Lib/test/test_compile.py
Lib/test/test_dict.py
Lib/test/test_dictviews.py
Lib/test/test_exception_group.py
Lib/test/test_exceptions.py
Lib/test/test_fstring.py
Lib/test/test_functools.py
Lib/test/test_isinstance.py
Lib/test/test_json/test_recursion.py
Lib/test/test_marshal.py
Lib/test/test_sys_settrace.py
Lib/test/test_tokenize.py
Lib/test/test_userdict.py
Lib/test/test_userlist.py
Lib/test/test_xml_etree_c.py
Misc/NEWS.d/next/Core_and_Builtins/2025-02-12-12-44-36.gh-issue-91079.8Nq08d.rst [new file with mode: 0644]
Modules/_testcapimodule.c
Modules/_testinternalcapi.c
Objects/object.c
Parser/asdl_c.py
Parser/parser.c
Python/Python-ast.c
Python/ast.c
Python/ast_opt.c
Python/bytecodes.c
Python/ceval.c
Python/executor_cases.c.h
Python/generated_cases.c.h
Python/pystate.c
Python/pythonrun.c
Python/symtable.c
Tools/cases_generator/analyzer.py
Tools/peg_generator/pegen/c_generator.py

index c1f0bd750361d60c6846845e96f67dbaadc9caf8..19f6baf9b3dc90bc7c0bb4f895d839e21ca744cf 100644 (file)
@@ -921,11 +921,7 @@ because the :ref:`call protocol <call>` takes care of recursion handling.
 
    Marks a point where a recursive C-level call is about to be performed.
 
-   If :c:macro:`!USE_STACKCHECK` is defined, this function checks if the OS
-   stack overflowed using :c:func:`PyOS_CheckStack`.  If this is the case, it
-   sets a :exc:`MemoryError` and returns a nonzero value.
-
-   The function then checks if the recursion limit is reached.  If this is the
+   The function then checks if the stack limit is reached.  If this is the
    case, a :exc:`RecursionError` is set and a nonzero value is returned.
    Otherwise, zero is returned.
 
index 71bd01884426ad04d500073331e36a1eb13dd3c7..260b90da24c18b6ebeea93206df168346a9e2ff9 100644 (file)
@@ -487,18 +487,19 @@ PyAPI_FUNC(void) _PyTrash_thread_destroy_chain(PyThreadState *tstate);
  * we have headroom above the trigger limit */
 #define Py_TRASHCAN_HEADROOM 50
 
+/* Helper function for Py_TRASHCAN_BEGIN */
+PyAPI_FUNC(int) _Py_ReachedRecursionLimitWithMargin(PyThreadState *tstate, int margin_count);
+
 #define Py_TRASHCAN_BEGIN(op, dealloc) \
 do { \
     PyThreadState *tstate = PyThreadState_Get(); \
-    if (tstate->c_recursion_remaining <= Py_TRASHCAN_HEADROOM && Py_TYPE(op)->tp_dealloc == (destructor)dealloc) { \
+    if (_Py_ReachedRecursionLimitWithMargin(tstate, 1) && Py_TYPE(op)->tp_dealloc == (destructor)dealloc) { \
         _PyTrash_thread_deposit_object(tstate, (PyObject *)op); \
         break; \
-    } \
-    tstate->c_recursion_remaining--;
+    }
     /* The body of the deallocator is here. */
 #define Py_TRASHCAN_END \
-    tstate->c_recursion_remaining++; \
-    if (tstate->delete_later && tstate->c_recursion_remaining > (Py_TRASHCAN_HEADROOM*2)) { \
+    if (tstate->delete_later && !_Py_ReachedRecursionLimitWithMargin(tstate, 2)) { \
         _PyTrash_thread_destroy_chain(tstate); \
     } \
 } while (0);
index cd6d95824968502a1589bb6a2eac5f65dc7db3c0..e0d2ac9bf93ad8764678dfef11a8e9580e6630e5 100644 (file)
@@ -112,7 +112,7 @@ struct _ts {
     int py_recursion_remaining;
     int py_recursion_limit;
 
-    int c_recursion_remaining;
+    int c_recursion_remaining; /* Retained for backwards compatibility. Do not use */
     int recursion_headroom; /* Allow 50 more calls to handle any errors. */
 
     /* 'tracing' keeps track of the execution depth when tracing/profiling.
@@ -202,36 +202,7 @@ struct _ts {
     PyObject *threading_local_sentinel;
 };
 
-#ifdef Py_DEBUG
-   // A debug build is likely built with low optimization level which implies
-   // higher stack memory usage than a release build: use a lower limit.
-#  define Py_C_RECURSION_LIMIT 500
-#elif defined(__s390x__)
-#  define Py_C_RECURSION_LIMIT 800
-#elif defined(_WIN32) && defined(_M_ARM64)
-#  define Py_C_RECURSION_LIMIT 1000
-#elif defined(_WIN32)
-#  define Py_C_RECURSION_LIMIT 3000
-#elif defined(__ANDROID__)
-   // On an ARM64 emulator, API level 34 was OK with 10000, but API level 21
-   // crashed in test_compiler_recursion_limit.
-#  define Py_C_RECURSION_LIMIT 3000
-#elif defined(_Py_ADDRESS_SANITIZER)
-#  define Py_C_RECURSION_LIMIT 4000
-#elif defined(__sparc__)
-   // test_descr crashed on sparc64 with >7000 but let's keep a margin of error.
-#  define Py_C_RECURSION_LIMIT 4000
-#elif defined(__wasi__)
-   // Based on wasmtime 16.
-#  define Py_C_RECURSION_LIMIT 5000
-#elif defined(__hppa__) || defined(__powerpc64__)
-   // test_descr crashed with >8000 but let's keep a margin of error.
-#  define Py_C_RECURSION_LIMIT 5000
-#else
-   // This value is duplicated in Lib/test/support/__init__.py
-#  define Py_C_RECURSION_LIMIT 10000
-#endif
-
+# define Py_C_RECURSION_LIMIT 5000
 
 /* other API */
 
@@ -246,7 +217,6 @@ _PyThreadState_UncheckedGet(void)
     return PyThreadState_GetUnchecked();
 }
 
-
 // Disable tracing and profiling.
 PyAPI_FUNC(void) PyThreadState_EnterTracing(PyThreadState *tstate);
 
index 6265afba38be2664908f5e2bdb8c4cb9b70d642c..f9e6a99ce29d2b8a4fd723490d23984e559410c2 100644 (file)
@@ -193,18 +193,12 @@ extern void _PyEval_DeactivateOpCache(void);
 
 /* --- _Py_EnterRecursiveCall() ----------------------------------------- */
 
-#ifdef USE_STACKCHECK
-/* With USE_STACKCHECK macro defined, trigger stack checks in
-   _Py_CheckRecursiveCall() on every 64th call to _Py_EnterRecursiveCall. */
 static inline int _Py_MakeRecCheck(PyThreadState *tstate)  {
-    return (tstate->c_recursion_remaining-- < 0
-            || (tstate->c_recursion_remaining & 63) == 0);
+    char here;
+    uintptr_t here_addr = (uintptr_t)&here;
+    _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
+    return here_addr < _tstate->c_stack_soft_limit;
 }
-#else
-static inline int _Py_MakeRecCheck(PyThreadState *tstate) {
-    return tstate->c_recursion_remaining-- < 0;
-}
-#endif
 
 // Export for '_json' shared extension, used via _Py_EnterRecursiveCall()
 // static inline function.
@@ -220,23 +214,31 @@ static inline int _Py_EnterRecursiveCallTstate(PyThreadState *tstate,
     return (_Py_MakeRecCheck(tstate) && _Py_CheckRecursiveCall(tstate, where));
 }
 
-static inline void _Py_EnterRecursiveCallTstateUnchecked(PyThreadState *tstate)  {
-    assert(tstate->c_recursion_remaining > 0);
-    tstate->c_recursion_remaining--;
-}
-
 static inline int _Py_EnterRecursiveCall(const char *where) {
     PyThreadState *tstate = _PyThreadState_GET();
     return _Py_EnterRecursiveCallTstate(tstate, where);
 }
 
-static inline void _Py_LeaveRecursiveCallTstate(PyThreadState *tstate)  {
-    tstate->c_recursion_remaining++;
+static inline void _Py_LeaveRecursiveCallTstate(PyThreadState *tstate) {
+    (void)tstate;
+}
+
+PyAPI_FUNC(void) _Py_InitializeRecursionLimits(PyThreadState *tstate);
+
+static inline int _Py_ReachedRecursionLimit(PyThreadState *tstate)  {
+    char here;
+    uintptr_t here_addr = (uintptr_t)&here;
+    _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
+    if (here_addr > _tstate->c_stack_soft_limit) {
+        return 0;
+    }
+    if (_tstate->c_stack_hard_limit == 0) {
+        _Py_InitializeRecursionLimits(tstate);
+    }
+    return here_addr <= _tstate->c_stack_soft_limit;
 }
 
 static inline void _Py_LeaveRecursiveCall(void)  {
-    PyThreadState *tstate = _PyThreadState_GET();
-    _Py_LeaveRecursiveCallTstate(tstate);
 }
 
 extern struct _PyInterpreterFrame* _PyEval_GetFrame(void);
@@ -327,7 +329,6 @@ void _Py_unset_eval_breaker_bit_all(PyInterpreterState *interp, uintptr_t bit);
 
 PyAPI_FUNC(PyObject *) _PyFloat_FromDouble_ConsumeInputs(_PyStackRef left, _PyStackRef right, double value);
 
-
 #ifdef __cplusplus
 }
 #endif
index b7e274296112aada2baa2a1566cfc4809f6de2bb..3b87a7f869c4d743f8816b39c80e7923d3764159 100644 (file)
@@ -82,8 +82,6 @@ struct symtable {
     PyObject *st_private;           /* name of current class or NULL */
     _PyFutureFeatures *st_future;   /* module's future features that affect
                                        the symbol table */
-    int recursion_depth;            /* current recursion depth */
-    int recursion_limit;            /* recursion limit */
 };
 
 typedef struct _symtable_entry {
index 932623f54c426071507cbae4f63793770ab8fc43..624b29e32ed463bbf3061a060a57be27f8123cfd 100644 (file)
@@ -21,6 +21,11 @@ typedef struct _PyThreadStateImpl {
     // semi-public fields are in PyThreadState.
     PyThreadState base;
 
+    // These are addresses, but we need to convert to ints to avoid UB.
+    uintptr_t c_stack_top;
+    uintptr_t c_stack_soft_limit;
+    uintptr_t c_stack_hard_limit;
+
     PyObject *asyncio_running_loop; // Strong reference
     PyObject *asyncio_running_task; // Strong reference
 
index 154c7450cb934f9492b1f2957f8a55545d27fdf4..03b713beb8155fe7ac13b96a6a43edb5431ee392 100644 (file)
@@ -21,14 +21,18 @@ PyAPI_FUNC(void) PyErr_DisplayException(PyObject *);
 /* Stuff with no proper home (yet) */
 PyAPI_DATA(int) (*PyOS_InputHook)(void);
 
-/* Stack size, in "pointers" (so we get extra safety margins
-   on 64-bit platforms).  On a 32-bit platform, this translates
-   to an 8k margin. */
-#define PYOS_STACK_MARGIN 2048
-
-#if defined(WIN32) && !defined(MS_WIN64) && !defined(_M_ARM) && defined(_MSC_VER) && _MSC_VER >= 1300
-/* Enable stack checking under Microsoft C */
-// When changing the platforms, ensure PyOS_CheckStack() docs are still correct
+/* Stack size, in "pointers". This must be large enough, so
+ * no two calls to check recursion depth are more than this far
+ * apart. In practice, that means it must be larger than the C
+ * stack consumption of PyEval_EvalDefault */
+#if defined(Py_DEBUG) && defined(WIN32)
+#  define PYOS_STACK_MARGIN 3072
+#else
+#  define PYOS_STACK_MARGIN 2048
+#endif
+#define PYOS_STACK_MARGIN_BYTES (PYOS_STACK_MARGIN * sizeof(void *))
+
+#if defined(WIN32)
 #define USE_STACKCHECK
 #endif
 
index dbd9f27872962d805f16ad8cefe2647117502c25..4e63abfc3ce1b32a4c848fc5a97752a896c12e54 100644 (file)
@@ -6,7 +6,8 @@ import sys
 from functools import cmp_to_key
 
 from test import seq_tests
-from test.support import ALWAYS_EQ, NEVER_EQ, get_c_recursion_limit, skip_emscripten_stack_overflow
+from test.support import ALWAYS_EQ, NEVER_EQ
+from test.support import skip_emscripten_stack_overflow, skip_wasi_stack_overflow
 
 
 class CommonTest(seq_tests.CommonTest):
@@ -59,10 +60,11 @@ class CommonTest(seq_tests.CommonTest):
         self.assertEqual(str(a2), "[0, 1, 2, [...], 3]")
         self.assertEqual(repr(a2), "[0, 1, 2, [...], 3]")
 
+    @skip_wasi_stack_overflow()
     @skip_emscripten_stack_overflow()
     def test_repr_deep(self):
         a = self.type2test([])
-        for i in range(get_c_recursion_limit() + 1):
+        for i in range(100_000):
             a = self.type2test([a])
         self.assertRaises(RecursionError, repr, a)
 
index f249f0021e9c1c3ccb9b53f949831b8ac2337f33..1a0caa00fcd49e0ade9a5fea50fec6a751d39f00 100644 (file)
@@ -1,7 +1,7 @@
 # tests common to dict and UserDict
 import unittest
 import collections
-from test.support import get_c_recursion_limit, skip_emscripten_stack_overflow
+from test import support
 
 
 class BasicTestMappingProtocol(unittest.TestCase):
@@ -622,10 +622,11 @@ class TestHashMappingProtocol(TestMappingProtocol):
         d = self._full_mapping({1: BadRepr()})
         self.assertRaises(Exc, repr, d)
 
-    @skip_emscripten_stack_overflow()
+    @support.skip_wasi_stack_overflow()
+    @support.skip_emscripten_stack_overflow()
     def test_repr_deep(self):
         d = self._empty_mapping()
-        for i in range(get_c_recursion_limit() + 1):
+        for i in range(support.exceeds_recursion_limit()):
             d0 = d
             d = self._empty_mapping()
             d[1] = d0
index 0b2e4b1c1988c41e1d73622d97ed4847d36cb6c0..38236d82376f373ea55885b4d661cdaf3d393c00 100644 (file)
@@ -684,7 +684,6 @@ def collect_testcapi(info_add):
     for name in (
         'LONG_MAX',         # always 32-bit on Windows, 64-bit on 64-bit Unix
         'PY_SSIZE_T_MAX',
-        'Py_C_RECURSION_LIMIT',
         'SIZEOF_TIME_T',    # 32-bit or 64-bit depending on the platform
         'SIZEOF_WCHAR_T',   # 16-bit or 32-bit depending on the platform
     ):
index f31d98bf731d679508d195c57b8082d0a57dee3b..88ac5a56ee928e0b4bc5284b4df5659ac50ae4dd 100644 (file)
@@ -56,8 +56,7 @@ __all__ = [
     "run_with_tz", "PGO", "missing_compiler_executable",
     "ALWAYS_EQ", "NEVER_EQ", "LARGEST", "SMALLEST",
     "LOOPBACK_TIMEOUT", "INTERNET_TIMEOUT", "SHORT_TIMEOUT", "LONG_TIMEOUT",
-    "Py_DEBUG", "exceeds_recursion_limit", "get_c_recursion_limit",
-    "skip_on_s390x",
+    "Py_DEBUG", "exceeds_recursion_limit", "skip_on_s390x",
     "requires_jit_enabled",
     "requires_jit_disabled",
     "force_not_colorized",
@@ -558,6 +557,9 @@ is_wasi = sys.platform == "wasi"
 def skip_emscripten_stack_overflow():
     return unittest.skipIf(is_emscripten, "Exhausts limited stack on Emscripten")
 
+def skip_wasi_stack_overflow():
+    return unittest.skipIf(is_wasi, "Exhausts stack on WASI")
+
 is_apple_mobile = sys.platform in {"ios", "tvos", "watchos"}
 is_apple = is_apple_mobile or sys.platform == "darwin"
 
@@ -2624,17 +2626,9 @@ def adjust_int_max_str_digits(max_digits):
         sys.set_int_max_str_digits(current)
 
 
-def get_c_recursion_limit():
-    try:
-        import _testcapi
-        return _testcapi.Py_C_RECURSION_LIMIT
-    except ImportError:
-        raise unittest.SkipTest('requires _testcapi')
-
-
 def exceeds_recursion_limit():
     """For recursion tests, easily exceeds default recursion limit."""
-    return get_c_recursion_limit() * 3
+    return 100_000
 
 
 # Windows doesn't have os.uname() but it doesn't support s390x.
index 42dbb6e79c33b4ad769da62d4fe0ab80c9c65a5f..07a444856375527c925b5e76085ba27ecb061c30 100644 (file)
@@ -18,7 +18,8 @@ except ImportError:
     _testinternalcapi = None
 
 from test import support
-from test.support import os_helper, script_helper, skip_emscripten_stack_overflow
+from test.support import os_helper, script_helper
+from test.support import skip_emscripten_stack_overflow, skip_wasi_stack_overflow
 from test.support.ast_helper import ASTTestMixin
 from test.test_ast.utils import to_tuple
 from test.test_ast.snippets import (
@@ -751,11 +752,11 @@ class AST_Tests(unittest.TestCase):
         enum._test_simple_enum(_Precedence, ast._Precedence)
 
     @support.cpython_only
+    @skip_wasi_stack_overflow()
     @skip_emscripten_stack_overflow()
     def test_ast_recursion_limit(self):
-        fail_depth = support.exceeds_recursion_limit()
-        crash_depth = 100_000
-        success_depth = int(support.get_c_recursion_limit() * 0.8)
+        crash_depth = 200_000
+        success_depth = 200
         if _testinternalcapi is not None:
             remaining = _testinternalcapi.get_c_recursion_remaining()
             success_depth = min(success_depth, remaining)
@@ -763,13 +764,13 @@ class AST_Tests(unittest.TestCase):
         def check_limit(prefix, repeated):
             expect_ok = prefix + repeated * success_depth
             ast.parse(expect_ok)
-            for depth in (fail_depth, crash_depth):
-                broken = prefix + repeated * depth
-                details = "Compiling ({!r} + {!r} * {})".format(
-                            prefix, repeated, depth)
-                with self.assertRaises(RecursionError, msg=details):
-                    with support.infinite_recursion():
-                        ast.parse(broken)
+
+            broken = prefix + repeated * crash_depth
+            details = "Compiling ({!r} + {!r} * {})".format(
+                        prefix, repeated, crash_depth)
+            with self.assertRaises(RecursionError, msg=details):
+                with support.infinite_recursion():
+                    ast.parse(broken)
 
         check_limit("a", "()")
         check_limit("a", ".b")
index 9d73d0e690ed5810fb2ec6ae8fd952d780b50096..95eaf810eea091a0ddccdf8e7bb24e593d64f419 100644 (file)
@@ -1,6 +1,6 @@
 import unittest
 from test.support import (cpython_only, is_wasi, requires_limited_api, Py_DEBUG,
-                          set_recursion_limit, skip_on_s390x, skip_emscripten_stack_overflow,
+                          set_recursion_limit, skip_on_s390x, exceeds_recursion_limit, skip_emscripten_stack_overflow,
                           skip_if_sanitizer, import_helper)
 try:
     import _testcapi
@@ -1064,10 +1064,10 @@ class TestRecursion(unittest.TestCase):
             recurse(90_000)
             with self.assertRaises(RecursionError):
                 recurse(101_000)
-            c_recurse(100)
+            c_recurse(50)
             with self.assertRaises(RecursionError):
                 c_recurse(90_000)
-            c_py_recurse(90)
+            c_py_recurse(50)
             with self.assertRaises(RecursionError):
                 c_py_recurse(100_000)
 
index b218f72f1bbce048e5961186817edf396b5e6bbd..6c4cf5bd6598bcdba082dedd4e0771c30a7c859e 100644 (file)
@@ -408,7 +408,7 @@ class CAPITest(unittest.TestCase):
         # activated when its tp_dealloc is being called by a subclass
         from _testcapi import MyList
         L = None
-        for i in range(1000):
+        for i in range(100):
             L = MyList((L,))
 
     @support.requires_resource('cpu')
index 8163b483d9603da67c46e391d34a4d5bf064d5ab..e0a33b8141c709f9d8f8243300075f40cda61e18 100644 (file)
@@ -21,7 +21,7 @@ except ImportError:
 
 from test import support
 from test.support import (script_helper, requires_debug_ranges, run_code,
-                          requires_specialization, get_c_recursion_limit)
+                          requires_specialization)
 from test.support.bytecode_helper import instructions_with_positions
 from test.support.os_helper import FakePath
 
@@ -123,7 +123,7 @@ class TestSpecifics(unittest.TestCase):
     @unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI")
     @support.skip_emscripten_stack_overflow()
     def test_extended_arg(self):
-        repeat = int(get_c_recursion_limit() * 0.9)
+        repeat = 100
         longexpr = 'x = x or ' + '-x' * repeat
         g = {}
         code = textwrap.dedent('''
@@ -712,11 +712,11 @@ class TestSpecifics(unittest.TestCase):
     @unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI")
     @support.skip_emscripten_stack_overflow()
     def test_compiler_recursion_limit(self):
-        # Expected limit is Py_C_RECURSION_LIMIT
-        limit = get_c_recursion_limit()
-        fail_depth = limit + 1
-        crash_depth = limit * 100
-        success_depth = int(limit * 0.8)
+        # Compiler frames are small
+        limit = 100
+        fail_depth = limit * 1000
+        crash_depth = limit * 2000
+        success_depth = limit
 
         def check_limit(prefix, repeated, mode="single"):
             expect_ok = prefix + repeated * success_depth
index 86b2f22dee53479fb7d2d25060e12efd12ffff7c..7756c1f995cf2c5fed2a1ba75571073072c7bb87 100644 (file)
@@ -8,7 +8,7 @@ import sys
 import unittest
 import weakref
 from test import support
-from test.support import import_helper, get_c_recursion_limit
+from test.support import import_helper
 
 
 class DictTest(unittest.TestCase):
@@ -594,10 +594,11 @@ class DictTest(unittest.TestCase):
         d = {1: BadRepr()}
         self.assertRaises(Exc, repr, d)
 
+    @support.skip_wasi_stack_overflow()
     @support.skip_emscripten_stack_overflow()
     def test_repr_deep(self):
         d = {}
-        for i in range(get_c_recursion_limit() + 1):
+        for i in range(support.exceeds_recursion_limit()):
             d = {1: d}
         self.assertRaises(RecursionError, repr, d)
 
index d6bf00eeeb00134ae74c3b2882936a8f998238ab..691fc5dfb5e8ab94523e8e8669d325fd270db167 100644 (file)
@@ -2,7 +2,7 @@ import collections.abc
 import copy
 import pickle
 import unittest
-from test.support import get_c_recursion_limit, skip_emscripten_stack_overflow
+from test.support import skip_emscripten_stack_overflow, skip_wasi_stack_overflow, exceeds_recursion_limit
 
 class DictSetTest(unittest.TestCase):
 
@@ -277,10 +277,11 @@ class DictSetTest(unittest.TestCase):
         # Again.
         self.assertIsInstance(r, str)
 
+    @skip_wasi_stack_overflow()
     @skip_emscripten_stack_overflow()
     def test_deeply_nested_repr(self):
         d = {}
-        for i in range(get_c_recursion_limit()//2 + 100):
+        for i in range(exceeds_recursion_limit()):
             d = {42: d.values()}
         self.assertRaises(RecursionError, repr, d)
 
index 53212529c27e286af8caceaf74a33130472c647f..92bbf7917642b0fc6c7fb71639a4e9cb8cf1c1ed 100644 (file)
@@ -1,7 +1,7 @@
 import collections.abc
 import types
 import unittest
-from test.support import get_c_recursion_limit, skip_emscripten_stack_overflow
+from test.support import skip_emscripten_stack_overflow, exceeds_recursion_limit
 
 class TestExceptionGroupTypeHierarchy(unittest.TestCase):
     def test_exception_group_types(self):
@@ -460,7 +460,7 @@ class ExceptionGroupSplitTests(ExceptionGroupTestBase):
 class DeepRecursionInSplitAndSubgroup(unittest.TestCase):
     def make_deep_eg(self):
         e = TypeError(1)
-        for i in range(get_c_recursion_limit() + 1):
+        for i in range(exceeds_recursion_limit()):
             e = ExceptionGroup('eg', [e])
         return e
 
index 7aa200ad8bee6cbf2992d10424a9ecb2903a6b64..bd1053b67fde5834a57ca0aeb201ead3895b870e 100644 (file)
@@ -1479,7 +1479,7 @@ class ExceptionTests(unittest.TestCase):
         """
         rc, out, err = script_helper.assert_python_failure("-c", code)
         self.assertEqual(rc, 1)
-        expected = b'RecursionError: maximum recursion depth exceeded'
+        expected = b'RecursionError'
         self.assertTrue(expected in err, msg=f"{expected!r} not found in {err[:3_000]!r}... (truncated)")
         self.assertIn(b'Done.', out)
 
index f5111b38a457074d200a4116eb570dc71b05de36..5974024c170cef024186e15941634170001c9a81 100644 (file)
@@ -628,13 +628,23 @@ x = (
                             r"does not match opening parenthesis '\('",
                             ["f'{a(4}'",
                             ])
-        self.assertRaises(SyntaxError, eval, "f'{" + "("*500 + "}'")
+        self.assertRaises(SyntaxError, eval, "f'{" + "("*20 + "}'")
 
     @unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI")
     def test_fstring_nested_too_deeply(self):
-        self.assertAllRaise(SyntaxError,
-                            "f-string: expressions nested too deeply",
-                            ['f"{1+2:{1+2:{1+1:{1}}}}"'])
+        def raises_syntax_or_memory_error(txt):
+            try:
+                eval(txt)
+            except SyntaxError:
+                pass
+            except MemoryError:
+                pass
+            except Exception as ex:
+                self.fail(f"Should raise SyntaxError or MemoryError, not {type(ex)}")
+            else:
+                self.fail("No exception raised")
+
+        raises_syntax_or_memory_error('f"{1+2:{1+2:{1+1:{1}}}}"')
 
         def create_nested_fstring(n):
             if n == 0:
@@ -642,9 +652,10 @@ x = (
             prev = create_nested_fstring(n-1)
             return f'f"{{{prev}}}"'
 
-        self.assertAllRaise(SyntaxError,
-                            "too many nested f-strings",
-                            [create_nested_fstring(160)])
+        raises_syntax_or_memory_error(create_nested_fstring(160))
+        raises_syntax_or_memory_error("f'{" + "("*100 + "}'")
+        raises_syntax_or_memory_error("f'{" + "("*1000 + "}'")
+        raises_syntax_or_memory_error("f'{" + "("*10_000 + "}'")
 
     def test_syntax_error_in_nested_fstring(self):
         # See gh-104016 for more information on this crash
index abd330c0de57ac11e849f43f7483a7417edbb929..a67c7b2280df9e8a8ca9419dd60e6f8ab877a415 100644 (file)
@@ -2087,15 +2087,12 @@ class TestLRU:
                 return n
             return fib(n-1) + fib(n-2)
 
-        if not support.Py_DEBUG:
-            depth = support.get_c_recursion_limit()*2//7
-            with support.infinite_recursion():
-                fib(depth)
+        fib(100)
         if self.module == c_functools:
             fib.cache_clear()
             with support.infinite_recursion():
                 with self.assertRaises(RecursionError):
-                    fib(10000)
+                    fib(support.exceeds_recursion_limit())
 
 
 @py_functools.lru_cache()
index abc75c82375d984ff9da458b415183548aa27198..115e26c5541526679d5e2205d9fc52db81cb491f 100644 (file)
@@ -267,15 +267,13 @@ class TestIsInstanceIsSubclass(unittest.TestCase):
     def test_subclass_recursion_limit(self):
         # make sure that issubclass raises RecursionError before the C stack is
         # blown
-        with support.infinite_recursion():
-            self.assertRaises(RecursionError, blowstack, issubclass, str, str)
+        self.assertRaises(RecursionError, blowstack, issubclass, str, str)
 
     @support.skip_emscripten_stack_overflow()
     def test_isinstance_recursion_limit(self):
         # make sure that issubclass raises RecursionError before the C stack is
         # blown
-        with support.infinite_recursion():
-            self.assertRaises(RecursionError, blowstack, isinstance, '', str)
+        self.assertRaises(RecursionError, blowstack, isinstance, '', str)
 
     def test_subclass_with_union(self):
         self.assertTrue(issubclass(int, int | float | int))
@@ -355,8 +353,9 @@ def blowstack(fxn, arg, compare_to):
     # Make sure that calling isinstance with a deeply nested tuple for its
     # argument will raise RecursionError eventually.
     tuple_arg = (compare_to,)
-    for cnt in range(support.exceeds_recursion_limit()):
-        tuple_arg = (tuple_arg,)
+    while True:
+        for _ in range(100):
+            tuple_arg = (tuple_arg,)
         fxn(arg, tuple_arg)
 
 
index 663c0643579ac8a53673b8bb2da25ee12c0a6367..700821f8625834dc0acf4c0748e3d114ec4e8b1e 100644 (file)
@@ -82,6 +82,7 @@ class TestRecursion:
             with support.infinite_recursion():
                 self.loads('[' * 100000 + '1' + ']' * 100000)
 
+    @support.skip_wasi_stack_overflow()
     @support.skip_emscripten_stack_overflow()
     def test_highly_nested_objects_encoding(self):
         # See #12051
index 4ed9f1fc1b8020b6430d6844471362b08ff9a82b..8b1fb0eba1f8b60bd7653c996c0cac1558130bef 100644 (file)
@@ -125,8 +125,7 @@ class CodeTestCase(unittest.TestCase):
     def test_many_codeobjects(self):
         # Issue2957: bad recursion count on code objects
         # more than MAX_MARSHAL_STACK_DEPTH
-        count = support.exceeds_recursion_limit()
-        codes = (ExceptionTestCase.test_exceptions.__code__,) * count
+        codes = (ExceptionTestCase.test_exceptions.__code__,) * 10_000
         marshal.loads(marshal.dumps(codes))
 
     def test_different_filenames(self):
index 28c2c681babe18ea2e9fd3dc72b011bf9c59fb5b..e528c6a9c69d282272c25b76490252406563d7c5 100644 (file)
@@ -3035,18 +3035,18 @@ class TestExtendedArgs(unittest.TestCase):
 
     def test_trace_lots_of_globals(self):
 
-        count = min(1000, int(support.get_c_recursion_limit() * 0.8))
+        count = 1000
 
         code = """if 1:
             def f():
                 return (
                     {}
                 )
-        """.format("\n+\n".join(f"var{i}\n" for i in range(count)))
+        """.format("\n,\n".join(f"var{i}\n" for i in range(count)))
         ns = {f"var{i}": i for i in range(count)}
         exec(code, ns)
         counts = self.count_traces(ns["f"])
-        self.assertEqual(counts, {'call': 1, 'line': count * 2, 'return': 1})
+        self.assertEqual(counts, {'call': 1, 'line': count * 2 + 1, 'return': 1})
 
 
 class TestEdgeCases(unittest.TestCase):
index 52d3341975088b1778ea5ddde10bcf0374213c37..5fa4e0d922ed0805e903e4736b5de6c96c6fa333 100644 (file)
@@ -3040,6 +3040,7 @@ async def f():
             with self.subTest(case=case):
                 self.assertRaises(tokenize.TokenError, get_tokens, case)
 
+    @support.skip_wasi_stack_overflow()
     def test_max_indent(self):
         MAXINDENT = 100
 
index 61e79f553e8ec9178058bd1d74b74642baae8dc2..9bd842eda5b49c17d2454d68e1df3b9267ef5bc3 100644 (file)
@@ -213,11 +213,7 @@ class UserDictTest(mapping_tests.TestHashMappingProtocol):
         else:
             self.fail("g[42] didn't raise KeyError")
 
-    # Decorate existing test with recursion limit, because
-    # the test is for C structure, but `UserDict` is a Python structure.
-    test_repr_deep = support.infinite_recursion(25)(
-        mapping_tests.TestHashMappingProtocol.test_repr_deep,
-    )
+    test_repr_deep = mapping_tests.TestHashMappingProtocol.test_repr_deep
 
 
 if __name__ == "__main__":
index 312702c8e398b9bdb072bf4e60d3aa2f8193868a..e82e88f3f3ed1d6fbe2eb93be4e0b22eb63cf84b 100644 (file)
@@ -69,9 +69,7 @@ class UserListTest(list_tests.CommonTest):
 
     # Decorate existing test with recursion limit, because
     # the test is for C structure, but `UserList` is a Python structure.
-    test_repr_deep = support.infinite_recursion(25)(
-        list_tests.CommonTest.test_repr_deep,
-    )
+    test_repr_deep = list_tests.CommonTest.test_repr_deep
 
 if __name__ == "__main__":
     unittest.main()
index db19af419bdeab357e30a897a2bd8607c7864a09..9ed0f4096a45e3c683a50dd5ae26406fb182d42f 100644 (file)
@@ -57,6 +57,7 @@ class MiscTests(unittest.TestCase):
             del element.attrib
         self.assertEqual(element.attrib, {'A': 'B', 'C': 'D'})
 
+    @support.skip_wasi_stack_overflow()
     @unittest.skipIf(support.is_emscripten, "segfaults")
     def test_trashcan(self):
         # If this test fails, it will most likely die via segfault.
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-12-12-44-36.gh-issue-91079.8Nq08d.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-12-12-44-36.gh-issue-91079.8Nq08d.rst
new file mode 100644 (file)
index 0000000..e592a7d
--- /dev/null
@@ -0,0 +1,3 @@
+Change C stack overflow protection to consider the amount of stack consumed,
+rather than a counter. This allows deeper recursion in many cases, but
+remains safe.
index 3d5fa9006447ded0876287109db90c886f9d89ae..9260c7659440ea78277b4d664d9ed1065ef9ceee 100644 (file)
@@ -3239,7 +3239,6 @@ PyInit__testcapi(void)
     PyModule_AddObject(m, "instancemethod", (PyObject *)&PyInstanceMethod_Type);
 
     PyModule_AddIntConstant(m, "the_number_three", 3);
-    PyModule_AddIntMacro(m, Py_C_RECURSION_LIMIT);
     PyModule_AddObject(m, "INT32_MIN", PyLong_FromInt32(INT32_MIN));
     PyModule_AddObject(m, "INT32_MAX", PyLong_FromInt32(INT32_MAX));
     PyModule_AddObject(m, "UINT32_MAX", PyLong_FromUInt32(UINT32_MAX));
index e44b629897c58abe0b8f5dfe797c8f9ca94e47bb..67cd96ac55e77991ff17abd3d47ada5afc42ddeb 100644 (file)
@@ -115,7 +115,11 @@ static PyObject*
 get_c_recursion_remaining(PyObject *self, PyObject *Py_UNUSED(args))
 {
     PyThreadState *tstate = _PyThreadState_GET();
-    return PyLong_FromLong(tstate->c_recursion_remaining);
+    char here;
+    uintptr_t here_addr = (uintptr_t)&here;
+    _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
+    int remaining = (int)((here_addr - _tstate->c_stack_soft_limit)/PYOS_STACK_MARGIN_BYTES * 50);
+    return PyLong_FromLong(remaining);
 }
 
 
index 16aedac916bf346db0e6bb71d2dc44e953cf90d1..d342549b6ffecc8f70caec0c88a88a90f40b65ed 100644 (file)
@@ -612,12 +612,9 @@ PyObject_Print(PyObject *op, FILE *fp, int flags)
     int write_error = 0;
     if (PyErr_CheckSignals())
         return -1;
-#ifdef USE_STACKCHECK
-    if (PyOS_CheckStack()) {
-        PyErr_SetString(PyExc_MemoryError, "stack overflow");
+    if (_Py_EnterRecursiveCall(" printing an object")) {
         return -1;
     }
-#endif
     clearerr(fp); /* Clear any previous error condition */
     if (op == NULL) {
         Py_BEGIN_ALLOW_THREADS
@@ -738,12 +735,6 @@ PyObject_Repr(PyObject *v)
     PyObject *res;
     if (PyErr_CheckSignals())
         return NULL;
-#ifdef USE_STACKCHECK
-    if (PyOS_CheckStack()) {
-        PyErr_SetString(PyExc_MemoryError, "stack overflow");
-        return NULL;
-    }
-#endif
     if (v == NULL)
         return PyUnicode_FromString("<NULL>");
     if (Py_TYPE(v)->tp_repr == NULL)
@@ -786,12 +777,6 @@ PyObject_Str(PyObject *v)
     PyObject *res;
     if (PyErr_CheckSignals())
         return NULL;
-#ifdef USE_STACKCHECK
-    if (PyOS_CheckStack()) {
-        PyErr_SetString(PyExc_MemoryError, "stack overflow");
-        return NULL;
-    }
-#endif
     if (v == NULL)
         return PyUnicode_FromString("<NULL>");
     if (PyUnicode_CheckExact(v)) {
@@ -2900,19 +2885,6 @@ _PyTrash_thread_deposit_object(PyThreadState *tstate, PyObject *op)
 void
 _PyTrash_thread_destroy_chain(PyThreadState *tstate)
 {
-    /* We need to increase c_recursion_remaining here, otherwise,
-       _PyTrash_thread_destroy_chain will be called recursively
-       and then possibly crash.  An example that may crash without
-       increase:
-           N = 500000  # need to be large enough
-           ob = object()
-           tups = [(ob,) for i in range(N)]
-           for i in range(49):
-               tups = [(tup,) for tup in tups]
-           del tups
-    */
-    assert(tstate->c_recursion_remaining > Py_TRASHCAN_HEADROOM);
-    tstate->c_recursion_remaining--;
     while (tstate->delete_later) {
         PyObject *op = tstate->delete_later;
         destructor dealloc = Py_TYPE(op)->tp_dealloc;
@@ -2934,7 +2906,6 @@ _PyTrash_thread_destroy_chain(PyThreadState *tstate)
         _PyObject_ASSERT(op, Py_REFCNT(op) == 0);
         (*dealloc)(op);
     }
-    tstate->c_recursion_remaining++;
 }
 
 void _Py_NO_RETURN
index b2a5dd6792deadc84a21b467c0eaa80b94142e4a..5c8014a47d5177e181f5d1fdfb4aaa76251f325c 100755 (executable)
@@ -738,7 +738,7 @@ class SequenceConstructorVisitor(EmitVisitor):
 class PyTypesDeclareVisitor(PickleVisitor):
 
     def visitProduct(self, prod, name):
-        self.emit("static PyObject* ast2obj_%s(struct ast_state *state, struct validator *vstate, void*);" % name, 0)
+        self.emit("static PyObject* ast2obj_%s(struct ast_state *state, void*);" % name, 0)
         if prod.attributes:
             self.emit("static const char * const %s_attributes[] = {" % name, 0)
             for a in prod.attributes:
@@ -759,7 +759,7 @@ class PyTypesDeclareVisitor(PickleVisitor):
         ptype = "void*"
         if is_simple(sum):
             ptype = get_c_type(name)
-        self.emit("static PyObject* ast2obj_%s(struct ast_state *state, struct validator *vstate, %s);" % (name, ptype), 0)
+        self.emit("static PyObject* ast2obj_%s(struct ast_state *state, %s);" % (name, ptype), 0)
         for t in sum.types:
             self.visitConstructor(t, name)
 
@@ -1734,8 +1734,8 @@ add_attributes(struct ast_state *state, PyObject *type, const char * const *attr
 
 /* Conversion AST -> Python */
 
-static PyObject* ast2obj_list(struct ast_state *state, struct validator *vstate, asdl_seq *seq,
-                              PyObject* (*func)(struct ast_state *state, struct validator *vstate, void*))
+static PyObject* ast2obj_list(struct ast_state *state, asdl_seq *seq,
+                              PyObject* (*func)(struct ast_state *state, void*))
 {
     Py_ssize_t i, n = asdl_seq_LEN(seq);
     PyObject *result = PyList_New(n);
@@ -1743,7 +1743,7 @@ static PyObject* ast2obj_list(struct ast_state *state, struct validator *vstate,
     if (!result)
         return NULL;
     for (i = 0; i < n; i++) {
-        value = func(state, vstate, asdl_seq_GET_UNTYPED(seq, i));
+        value = func(state, asdl_seq_GET_UNTYPED(seq, i));
         if (!value) {
             Py_DECREF(result);
             return NULL;
@@ -1753,7 +1753,7 @@ static PyObject* ast2obj_list(struct ast_state *state, struct validator *vstate,
     return result;
 }
 
-static PyObject* ast2obj_object(struct ast_state *Py_UNUSED(state), struct validator *Py_UNUSED(vstate), void *o)
+static PyObject* ast2obj_object(struct ast_state *Py_UNUSED(state), void *o)
 {
     PyObject *op = (PyObject*)o;
     if (!op) {
@@ -1765,7 +1765,7 @@ static PyObject* ast2obj_object(struct ast_state *Py_UNUSED(state), struct valid
 #define ast2obj_identifier ast2obj_object
 #define ast2obj_string ast2obj_object
 
-static PyObject* ast2obj_int(struct ast_state *Py_UNUSED(state), struct validator *Py_UNUSED(vstate), long b)
+static PyObject* ast2obj_int(struct ast_state *Py_UNUSED(state), long b)
 {
     return PyLong_FromLong(b);
 }
@@ -2014,7 +2014,7 @@ class ObjVisitor(PickleVisitor):
     def func_begin(self, name):
         ctype = get_c_type(name)
         self.emit("PyObject*", 0)
-        self.emit("ast2obj_%s(struct ast_state *state, struct validator *vstate, void* _o)" % (name), 0)
+        self.emit("ast2obj_%s(struct ast_state *state, void* _o)" % (name), 0)
         self.emit("{", 0)
         self.emit("%s o = (%s)_o;" % (ctype, ctype), 1)
         self.emit("PyObject *result = NULL, *value = NULL;", 1)
@@ -2022,17 +2022,15 @@ class ObjVisitor(PickleVisitor):
         self.emit('if (!o) {', 1)
         self.emit("Py_RETURN_NONE;", 2)
         self.emit("}", 1)
-        self.emit("if (++vstate->recursion_depth > vstate->recursion_limit) {", 1)
-        self.emit("PyErr_SetString(PyExc_RecursionError,", 2)
-        self.emit('"maximum recursion depth exceeded during ast construction");', 3)
+        self.emit('if (Py_EnterRecursiveCall("during  ast construction")) {', 1)
         self.emit("return NULL;", 2)
         self.emit("}", 1)
 
     def func_end(self):
-        self.emit("vstate->recursion_depth--;", 1)
+        self.emit("Py_LeaveRecursiveCall();", 1)
         self.emit("return result;", 1)
         self.emit("failed:", 0)
-        self.emit("vstate->recursion_depth--;", 1)
+        self.emit("Py_LeaveRecursiveCall();", 1)
         self.emit("Py_XDECREF(value);", 1)
         self.emit("Py_XDECREF(result);", 1)
         self.emit("return NULL;", 1)
@@ -2050,7 +2048,7 @@ class ObjVisitor(PickleVisitor):
             self.visitConstructor(t, i + 1, name)
         self.emit("}", 1)
         for a in sum.attributes:
-            self.emit("value = ast2obj_%s(state, vstate, o->%s);" % (a.type, a.name), 1)
+            self.emit("value = ast2obj_%s(state, o->%s);" % (a.type, a.name), 1)
             self.emit("if (!value) goto failed;", 1)
             self.emit('if (PyObject_SetAttr(result, state->%s, value) < 0)' % a.name, 1)
             self.emit('goto failed;', 2)
@@ -2058,7 +2056,7 @@ class ObjVisitor(PickleVisitor):
         self.func_end()
 
     def simpleSum(self, sum, name):
-        self.emit("PyObject* ast2obj_%s(struct ast_state *state, struct validator *vstate, %s_ty o)" % (name, name), 0)
+        self.emit("PyObject* ast2obj_%s(struct ast_state *state, %s_ty o)" % (name, name), 0)
         self.emit("{", 0)
         self.emit("switch(o) {", 1)
         for t in sum.types:
@@ -2076,7 +2074,7 @@ class ObjVisitor(PickleVisitor):
         for field in prod.fields:
             self.visitField(field, name, 1, True)
         for a in prod.attributes:
-            self.emit("value = ast2obj_%s(state, vstate, o->%s);" % (a.type, a.name), 1)
+            self.emit("value = ast2obj_%s(state, o->%s);" % (a.type, a.name), 1)
             self.emit("if (!value) goto failed;", 1)
             self.emit("if (PyObject_SetAttr(result, state->%s, value) < 0)" % a.name, 1)
             self.emit('goto failed;', 2)
@@ -2117,7 +2115,7 @@ class ObjVisitor(PickleVisitor):
                 self.emit("for(i = 0; i < n; i++)", depth+1)
                 # This cannot fail, so no need for error handling
                 self.emit(
-                    "PyList_SET_ITEM(value, i, ast2obj_{0}(state, vstate, ({0}_ty)asdl_seq_GET({1}, i)));".format(
+                    "PyList_SET_ITEM(value, i, ast2obj_{0}(state, ({0}_ty)asdl_seq_GET({1}, i)));".format(
                         field.type,
                         value
                     ),
@@ -2126,9 +2124,9 @@ class ObjVisitor(PickleVisitor):
                 )
                 self.emit("}", depth)
             else:
-                self.emit("value = ast2obj_list(state, vstate, (asdl_seq*)%s, ast2obj_%s);" % (value, field.type), depth)
+                self.emit("value = ast2obj_list(state, (asdl_seq*)%s, ast2obj_%s);" % (value, field.type), depth)
         else:
-            self.emit("value = ast2obj_%s(state, vstate, %s);" % (field.type, value), depth, reflow=False)
+            self.emit("value = ast2obj_%s(state, %s);" % (field.type, value), depth, reflow=False)
 
 
 class PartingShots(StaticVisitor):
@@ -2140,28 +2138,8 @@ PyObject* PyAST_mod2obj(mod_ty t)
     if (state == NULL) {
         return NULL;
     }
+    PyObject *result = ast2obj_mod(state, t);
 
-    int starting_recursion_depth;
-    /* Be careful here to prevent overflow. */
-    PyThreadState *tstate = _PyThreadState_GET();
-    if (!tstate) {
-        return NULL;
-    }
-    struct validator vstate;
-    vstate.recursion_limit = Py_C_RECURSION_LIMIT;
-    int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining;
-    starting_recursion_depth = recursion_depth;
-    vstate.recursion_depth = starting_recursion_depth;
-
-    PyObject *result = ast2obj_mod(state, &vstate, t);
-
-    /* Check that the recursion depth counting balanced correctly */
-    if (result && vstate.recursion_depth != starting_recursion_depth) {
-        PyErr_Format(PyExc_SystemError,
-            "AST constructor recursion depth mismatch (before=%d, after=%d)",
-            starting_recursion_depth, vstate.recursion_depth);
-        return NULL;
-    }
     return result;
 }
 
@@ -2305,11 +2283,6 @@ def generate_module_def(mod, metadata, f, internal_h):
         #include "structmember.h"
         #include <stddef.h>
 
-        struct validator {
-            int recursion_depth;            /* current recursion depth */
-            int recursion_limit;            /* recursion limit */
-        };
-
         // Forward declaration
         static int init_types(void *arg);
 
index 48508b14ee8716945d99d03a12b62dc449ae53c1..edebddc95f968e95b6cdb67ab8d1a63987c3d57e 100644 (file)
@@ -14,7 +14,7 @@
 #    define MAXSTACK 4000
 #  endif
 #else
-#  define MAXSTACK 6000
+#  define MAXSTACK 4000
 #endif
 static const int n_keyword_lists = 9;
 static KeywordToken *reserved_keywords[] = {
@@ -947,7 +947,7 @@ static void *_tmp_172_rule(Parser *p);
 static mod_ty
 file_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -993,7 +993,7 @@ file_rule(Parser *p)
 static mod_ty
 interactive_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -1036,7 +1036,7 @@ interactive_rule(Parser *p)
 static mod_ty
 eval_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -1085,7 +1085,7 @@ eval_rule(Parser *p)
 static mod_ty
 func_type_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -1146,7 +1146,7 @@ func_type_rule(Parser *p)
 static asdl_stmt_seq*
 statements_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -1189,7 +1189,7 @@ statements_rule(Parser *p)
 static asdl_stmt_seq*
 statement_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -1256,7 +1256,7 @@ statement_rule(Parser *p)
 static asdl_stmt_seq*
 statement_newline_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -1387,7 +1387,7 @@ statement_newline_rule(Parser *p)
 static asdl_stmt_seq*
 simple_stmts_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -1480,7 +1480,7 @@ simple_stmts_rule(Parser *p)
 static stmt_ty
 simple_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -1825,7 +1825,7 @@ simple_stmt_rule(Parser *p)
 static stmt_ty
 compound_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -2015,7 +2015,7 @@ compound_stmt_rule(Parser *p)
 static stmt_ty
 assignment_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -2233,7 +2233,7 @@ assignment_rule(Parser *p)
 static expr_ty
 annotated_rhs_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -2303,7 +2303,7 @@ annotated_rhs_rule(Parser *p)
 static AugOperator*
 augassign_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -2634,7 +2634,7 @@ augassign_rule(Parser *p)
 static stmt_ty
 return_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -2698,7 +2698,7 @@ return_stmt_rule(Parser *p)
 static stmt_ty
 raise_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -2798,7 +2798,7 @@ raise_stmt_rule(Parser *p)
 static stmt_ty
 pass_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -2859,7 +2859,7 @@ pass_stmt_rule(Parser *p)
 static stmt_ty
 break_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -2920,7 +2920,7 @@ break_stmt_rule(Parser *p)
 static stmt_ty
 continue_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -2981,7 +2981,7 @@ continue_stmt_rule(Parser *p)
 static stmt_ty
 global_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -3045,7 +3045,7 @@ global_stmt_rule(Parser *p)
 static stmt_ty
 nonlocal_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -3109,7 +3109,7 @@ nonlocal_stmt_rule(Parser *p)
 static stmt_ty
 del_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -3194,7 +3194,7 @@ del_stmt_rule(Parser *p)
 static stmt_ty
 yield_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -3255,7 +3255,7 @@ yield_stmt_rule(Parser *p)
 static stmt_ty
 assert_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -3322,7 +3322,7 @@ assert_stmt_rule(Parser *p)
 static stmt_ty
 import_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -3398,7 +3398,7 @@ import_stmt_rule(Parser *p)
 static stmt_ty
 import_name_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -3464,7 +3464,7 @@ import_name_rule(Parser *p)
 static stmt_ty
 import_from_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -3583,7 +3583,7 @@ import_from_rule(Parser *p)
 static asdl_alias_seq*
 import_from_targets_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -3718,7 +3718,7 @@ import_from_targets_rule(Parser *p)
 static asdl_alias_seq*
 import_from_as_names_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -3761,7 +3761,7 @@ import_from_as_names_rule(Parser *p)
 static alias_ty
 import_from_as_name_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -3825,7 +3825,7 @@ import_from_as_name_rule(Parser *p)
 static asdl_alias_seq*
 dotted_as_names_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -3868,7 +3868,7 @@ dotted_as_names_rule(Parser *p)
 static alias_ty
 dotted_as_name_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -3934,7 +3934,7 @@ static expr_ty dotted_name_raw(Parser *);
 static expr_ty
 dotted_name_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     expr_ty _res = NULL;
@@ -3968,7 +3968,7 @@ dotted_name_rule(Parser *p)
 static expr_ty
 dotted_name_raw(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -4036,7 +4036,7 @@ dotted_name_raw(Parser *p)
 static asdl_stmt_seq*
 block_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -4131,7 +4131,7 @@ block_rule(Parser *p)
 static asdl_expr_seq*
 decorators_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -4174,7 +4174,7 @@ decorators_rule(Parser *p)
 static stmt_ty
 class_def_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -4241,7 +4241,7 @@ class_def_rule(Parser *p)
 static stmt_ty
 class_def_raw_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -4336,7 +4336,7 @@ class_def_raw_rule(Parser *p)
 static stmt_ty
 function_def_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -4404,7 +4404,7 @@ function_def_rule(Parser *p)
 static stmt_ty
 function_def_raw_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -4574,7 +4574,7 @@ function_def_raw_rule(Parser *p)
 static arguments_ty
 params_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -4636,7 +4636,7 @@ params_rule(Parser *p)
 static arguments_ty
 parameters_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -4799,7 +4799,7 @@ parameters_rule(Parser *p)
 static asdl_arg_seq*
 slash_no_default_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -4879,7 +4879,7 @@ slash_no_default_rule(Parser *p)
 static SlashWithDefault*
 slash_with_default_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -4968,7 +4968,7 @@ slash_with_default_rule(Parser *p)
 static StarEtc*
 star_etc_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -5129,7 +5129,7 @@ star_etc_rule(Parser *p)
 static arg_ty
 kwds_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -5194,7 +5194,7 @@ kwds_rule(Parser *p)
 static arg_ty
 param_no_default_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -5274,7 +5274,7 @@ param_no_default_rule(Parser *p)
 static arg_ty
 param_no_default_star_annotation_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -5352,7 +5352,7 @@ param_no_default_star_annotation_rule(Parser *p)
 static NameDefaultPair*
 param_with_default_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -5438,7 +5438,7 @@ param_with_default_rule(Parser *p)
 static NameDefaultPair*
 param_maybe_default_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -5522,7 +5522,7 @@ param_maybe_default_rule(Parser *p)
 static arg_ty
 param_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -5586,7 +5586,7 @@ param_rule(Parser *p)
 static arg_ty
 param_star_annotation_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -5650,7 +5650,7 @@ param_star_annotation_rule(Parser *p)
 static expr_ty
 annotation_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -5696,7 +5696,7 @@ annotation_rule(Parser *p)
 static expr_ty
 star_annotation_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -5742,7 +5742,7 @@ star_annotation_rule(Parser *p)
 static expr_ty
 default_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -5810,7 +5810,7 @@ default_rule(Parser *p)
 static stmt_ty
 if_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -5950,7 +5950,7 @@ if_stmt_rule(Parser *p)
 static stmt_ty
 elif_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -6087,7 +6087,7 @@ elif_stmt_rule(Parser *p)
 static asdl_stmt_seq*
 else_block_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -6155,7 +6155,7 @@ else_block_rule(Parser *p)
 static stmt_ty
 while_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -6251,7 +6251,7 @@ while_stmt_rule(Parser *p)
 static stmt_ty
 for_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -6448,7 +6448,7 @@ for_stmt_rule(Parser *p)
 static stmt_ty
 with_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -6720,7 +6720,7 @@ with_stmt_rule(Parser *p)
 static withitem_ty
 with_item_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -6818,7 +6818,7 @@ with_item_rule(Parser *p)
 static stmt_ty
 try_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -7007,7 +7007,7 @@ try_stmt_rule(Parser *p)
 static excepthandler_ty
 except_block_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -7160,7 +7160,7 @@ except_block_rule(Parser *p)
 static excepthandler_ty
 except_star_block_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -7274,7 +7274,7 @@ except_star_block_rule(Parser *p)
 static asdl_stmt_seq*
 finally_block_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -7344,7 +7344,7 @@ finally_block_rule(Parser *p)
 static stmt_ty
 match_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -7442,7 +7442,7 @@ match_stmt_rule(Parser *p)
 static expr_ty
 subject_expr_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -7528,7 +7528,7 @@ subject_expr_rule(Parser *p)
 static match_case_ty
 case_block_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -7602,7 +7602,7 @@ case_block_rule(Parser *p)
 static expr_ty
 guard_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -7648,7 +7648,7 @@ guard_rule(Parser *p)
 static pattern_ty
 patterns_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -7728,7 +7728,7 @@ patterns_rule(Parser *p)
 static pattern_ty
 pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -7785,7 +7785,7 @@ pattern_rule(Parser *p)
 static pattern_ty
 as_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -7871,7 +7871,7 @@ as_pattern_rule(Parser *p)
 static pattern_ty
 or_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -7940,7 +7940,7 @@ or_pattern_rule(Parser *p)
 static pattern_ty
 closed_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -8122,7 +8122,7 @@ closed_pattern_rule(Parser *p)
 static pattern_ty
 literal_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -8356,7 +8356,7 @@ literal_pattern_rule(Parser *p)
 static expr_ty
 literal_expr_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -8544,7 +8544,7 @@ literal_expr_rule(Parser *p)
 static expr_ty
 complex_number_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -8650,7 +8650,7 @@ complex_number_rule(Parser *p)
 static expr_ty
 signed_number_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -8733,7 +8733,7 @@ signed_number_rule(Parser *p)
 static expr_ty
 signed_real_number_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -8816,7 +8816,7 @@ signed_real_number_rule(Parser *p)
 static expr_ty
 real_number_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -8859,7 +8859,7 @@ real_number_rule(Parser *p)
 static expr_ty
 imaginary_number_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -8902,7 +8902,7 @@ imaginary_number_rule(Parser *p)
 static pattern_ty
 capture_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -8963,7 +8963,7 @@ capture_pattern_rule(Parser *p)
 static expr_ty
 pattern_capture_target_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -9010,7 +9010,7 @@ pattern_capture_target_rule(Parser *p)
 static pattern_ty
 wildcard_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -9071,7 +9071,7 @@ wildcard_pattern_rule(Parser *p)
 static pattern_ty
 value_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -9136,7 +9136,7 @@ static expr_ty attr_raw(Parser *);
 static expr_ty
 attr_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     expr_ty _res = NULL;
@@ -9170,7 +9170,7 @@ attr_rule(Parser *p)
 static expr_ty
 attr_raw(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -9238,7 +9238,7 @@ attr_raw(Parser *p)
 static expr_ty
 name_or_attr_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -9295,7 +9295,7 @@ name_or_attr_rule(Parser *p)
 static pattern_ty
 group_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -9344,7 +9344,7 @@ group_pattern_rule(Parser *p)
 static pattern_ty
 sequence_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -9450,7 +9450,7 @@ sequence_pattern_rule(Parser *p)
 static asdl_seq*
 open_sequence_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -9499,7 +9499,7 @@ open_sequence_pattern_rule(Parser *p)
 static asdl_seq*
 maybe_sequence_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -9546,7 +9546,7 @@ maybe_sequence_pattern_rule(Parser *p)
 static pattern_ty
 maybe_star_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -9603,7 +9603,7 @@ maybe_star_pattern_rule(Parser *p)
 static pattern_ty
 star_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -9712,7 +9712,7 @@ star_pattern_rule(Parser *p)
 static pattern_ty
 mapping_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -9911,7 +9911,7 @@ mapping_pattern_rule(Parser *p)
 static asdl_seq*
 items_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -9949,7 +9949,7 @@ items_pattern_rule(Parser *p)
 static KeyPatternPair*
 key_value_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -9998,7 +9998,7 @@ key_value_pattern_rule(Parser *p)
 static expr_ty
 double_star_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -10049,7 +10049,7 @@ double_star_pattern_rule(Parser *p)
 static pattern_ty
 class_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -10279,7 +10279,7 @@ class_pattern_rule(Parser *p)
 static asdl_pattern_seq*
 positional_patterns_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -10322,7 +10322,7 @@ positional_patterns_rule(Parser *p)
 static asdl_seq*
 keyword_patterns_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -10360,7 +10360,7 @@ keyword_patterns_rule(Parser *p)
 static KeyPatternPair*
 keyword_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -10409,7 +10409,7 @@ keyword_pattern_rule(Parser *p)
 static stmt_ty
 type_alias_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -10482,7 +10482,7 @@ type_alias_rule(Parser *p)
 static asdl_type_param_seq*
 type_params_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -10550,7 +10550,7 @@ type_params_rule(Parser *p)
 static asdl_type_param_seq*
 type_param_seq_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -10601,7 +10601,7 @@ type_param_seq_rule(Parser *p)
 static type_param_ty
 type_param_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -10770,7 +10770,7 @@ type_param_rule(Parser *p)
 static expr_ty
 type_param_bound_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -10816,7 +10816,7 @@ type_param_bound_rule(Parser *p)
 static expr_ty
 type_param_default_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -10862,7 +10862,7 @@ type_param_default_rule(Parser *p)
 static expr_ty
 type_param_starred_default_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -10908,7 +10908,7 @@ type_param_starred_default_rule(Parser *p)
 static expr_ty
 expressions_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -11036,7 +11036,7 @@ expressions_rule(Parser *p)
 static expr_ty
 expression_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -11190,7 +11190,7 @@ expression_rule(Parser *p)
 static expr_ty
 yield_expr_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -11296,7 +11296,7 @@ yield_expr_rule(Parser *p)
 static expr_ty
 star_expressions_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -11419,7 +11419,7 @@ star_expressions_rule(Parser *p)
 static expr_ty
 star_expression_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -11507,7 +11507,7 @@ star_expression_rule(Parser *p)
 static asdl_expr_seq*
 star_named_expressions_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -11554,7 +11554,7 @@ star_named_expressions_rule(Parser *p)
 static expr_ty
 star_named_expression_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -11637,7 +11637,7 @@ star_named_expression_rule(Parser *p)
 static expr_ty
 assignment_expression_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -11711,7 +11711,7 @@ assignment_expression_rule(Parser *p)
 static expr_ty
 named_expression_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -11789,7 +11789,7 @@ named_expression_rule(Parser *p)
 static expr_ty
 disjunction_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -11877,7 +11877,7 @@ disjunction_rule(Parser *p)
 static expr_ty
 conjunction_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -11965,7 +11965,7 @@ conjunction_rule(Parser *p)
 static expr_ty
 inversion_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -12053,7 +12053,7 @@ inversion_rule(Parser *p)
 static expr_ty
 comparison_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -12146,7 +12146,7 @@ comparison_rule(Parser *p)
 static CmpopExprPair*
 compare_op_bitwise_or_pair_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -12355,7 +12355,7 @@ compare_op_bitwise_or_pair_rule(Parser *p)
 static CmpopExprPair*
 eq_bitwise_or_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -12401,7 +12401,7 @@ eq_bitwise_or_rule(Parser *p)
 static CmpopExprPair*
 noteq_bitwise_or_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -12447,7 +12447,7 @@ noteq_bitwise_or_rule(Parser *p)
 static CmpopExprPair*
 lte_bitwise_or_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -12493,7 +12493,7 @@ lte_bitwise_or_rule(Parser *p)
 static CmpopExprPair*
 lt_bitwise_or_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -12539,7 +12539,7 @@ lt_bitwise_or_rule(Parser *p)
 static CmpopExprPair*
 gte_bitwise_or_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -12585,7 +12585,7 @@ gte_bitwise_or_rule(Parser *p)
 static CmpopExprPair*
 gt_bitwise_or_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -12631,7 +12631,7 @@ gt_bitwise_or_rule(Parser *p)
 static CmpopExprPair*
 notin_bitwise_or_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -12680,7 +12680,7 @@ notin_bitwise_or_rule(Parser *p)
 static CmpopExprPair*
 in_bitwise_or_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -12726,7 +12726,7 @@ in_bitwise_or_rule(Parser *p)
 static CmpopExprPair*
 isnot_bitwise_or_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -12775,7 +12775,7 @@ isnot_bitwise_or_rule(Parser *p)
 static CmpopExprPair*
 is_bitwise_or_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -12823,7 +12823,7 @@ static expr_ty bitwise_or_raw(Parser *);
 static expr_ty
 bitwise_or_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     expr_ty _res = NULL;
@@ -12857,7 +12857,7 @@ bitwise_or_rule(Parser *p)
 static expr_ty
 bitwise_or_raw(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -12945,7 +12945,7 @@ static expr_ty bitwise_xor_raw(Parser *);
 static expr_ty
 bitwise_xor_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     expr_ty _res = NULL;
@@ -12979,7 +12979,7 @@ bitwise_xor_rule(Parser *p)
 static expr_ty
 bitwise_xor_raw(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -13067,7 +13067,7 @@ static expr_ty bitwise_and_raw(Parser *);
 static expr_ty
 bitwise_and_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     expr_ty _res = NULL;
@@ -13101,7 +13101,7 @@ bitwise_and_rule(Parser *p)
 static expr_ty
 bitwise_and_raw(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -13189,7 +13189,7 @@ static expr_ty shift_expr_raw(Parser *);
 static expr_ty
 shift_expr_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     expr_ty _res = NULL;
@@ -13223,7 +13223,7 @@ shift_expr_rule(Parser *p)
 static expr_ty
 shift_expr_raw(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -13369,7 +13369,7 @@ static expr_ty sum_raw(Parser *);
 static expr_ty
 sum_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     expr_ty _res = NULL;
@@ -13403,7 +13403,7 @@ sum_rule(Parser *p)
 static expr_ty
 sum_raw(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -13537,7 +13537,7 @@ static expr_ty term_raw(Parser *);
 static expr_ty
 term_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     expr_ty _res = NULL;
@@ -13571,7 +13571,7 @@ term_rule(Parser *p)
 static expr_ty
 term_raw(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -13832,7 +13832,7 @@ term_raw(Parser *p)
 static expr_ty
 factor_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -13992,7 +13992,7 @@ factor_rule(Parser *p)
 static expr_ty
 power_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -14078,7 +14078,7 @@ power_rule(Parser *p)
 static expr_ty
 await_primary_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -14173,7 +14173,7 @@ static expr_ty primary_raw(Parser *);
 static expr_ty
 primary_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     expr_ty _res = NULL;
@@ -14207,7 +14207,7 @@ primary_rule(Parser *p)
 static expr_ty
 primary_raw(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -14413,7 +14413,7 @@ primary_raw(Parser *p)
 static expr_ty
 slices_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -14504,7 +14504,7 @@ slices_rule(Parser *p)
 static expr_ty
 slice_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -14608,7 +14608,7 @@ slice_rule(Parser *p)
 static expr_ty
 atom_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -14890,7 +14890,7 @@ atom_rule(Parser *p)
 static expr_ty
 group_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -14958,7 +14958,7 @@ group_rule(Parser *p)
 static expr_ty
 lambdef_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -15028,7 +15028,7 @@ lambdef_rule(Parser *p)
 static arguments_ty
 lambda_params_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -15090,7 +15090,7 @@ lambda_params_rule(Parser *p)
 static arguments_ty
 lambda_parameters_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -15255,7 +15255,7 @@ lambda_parameters_rule(Parser *p)
 static asdl_arg_seq*
 lambda_slash_no_default_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -15335,7 +15335,7 @@ lambda_slash_no_default_rule(Parser *p)
 static SlashWithDefault*
 lambda_slash_with_default_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -15423,7 +15423,7 @@ lambda_slash_with_default_rule(Parser *p)
 static StarEtc*
 lambda_star_etc_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -15551,7 +15551,7 @@ lambda_star_etc_rule(Parser *p)
 static arg_ty
 lambda_kwds_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -15616,7 +15616,7 @@ lambda_kwds_rule(Parser *p)
 static arg_ty
 lambda_param_no_default_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -15688,7 +15688,7 @@ lambda_param_no_default_rule(Parser *p)
 static NameDefaultPair*
 lambda_param_with_default_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -15766,7 +15766,7 @@ lambda_param_with_default_rule(Parser *p)
 static NameDefaultPair*
 lambda_param_maybe_default_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -15844,7 +15844,7 @@ lambda_param_maybe_default_rule(Parser *p)
 static arg_ty
 lambda_param_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -15905,7 +15905,7 @@ lambda_param_rule(Parser *p)
 static expr_ty
 fstring_middle_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -15969,7 +15969,7 @@ fstring_middle_rule(Parser *p)
 static expr_ty
 fstring_replacement_field_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -16064,7 +16064,7 @@ fstring_replacement_field_rule(Parser *p)
 static ResultTokenWithMetadata*
 fstring_conversion_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -16110,7 +16110,7 @@ fstring_conversion_rule(Parser *p)
 static ResultTokenWithMetadata*
 fstring_full_format_spec_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -16174,7 +16174,7 @@ fstring_full_format_spec_rule(Parser *p)
 static expr_ty
 fstring_format_spec_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -16236,7 +16236,7 @@ fstring_format_spec_rule(Parser *p)
 static expr_ty
 fstring_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -16285,7 +16285,7 @@ fstring_rule(Parser *p)
 static expr_ty
 string_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -16328,7 +16328,7 @@ string_rule(Parser *p)
 static expr_ty
 strings_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -16394,7 +16394,7 @@ strings_rule(Parser *p)
 static expr_ty
 list_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -16461,7 +16461,7 @@ list_rule(Parser *p)
 static expr_ty
 tuple_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -16528,7 +16528,7 @@ tuple_rule(Parser *p)
 static expr_ty
 set_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -16595,7 +16595,7 @@ set_rule(Parser *p)
 static expr_ty
 dict_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -16687,7 +16687,7 @@ dict_rule(Parser *p)
 static asdl_seq*
 double_starred_kvpairs_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -16734,7 +16734,7 @@ double_starred_kvpairs_rule(Parser *p)
 static KeyValuePair*
 double_starred_kvpair_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -16799,7 +16799,7 @@ double_starred_kvpair_rule(Parser *p)
 static KeyValuePair*
 kvpair_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -16848,7 +16848,7 @@ kvpair_rule(Parser *p)
 static asdl_comprehension_seq*
 for_if_clauses_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -16895,7 +16895,7 @@ for_if_clauses_rule(Parser *p)
 static comprehension_ty
 for_if_clause_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -17041,7 +17041,7 @@ for_if_clause_rule(Parser *p)
 static expr_ty
 listcomp_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -17130,7 +17130,7 @@ listcomp_rule(Parser *p)
 static expr_ty
 setcomp_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -17221,7 +17221,7 @@ setcomp_rule(Parser *p)
 static expr_ty
 genexp_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -17310,7 +17310,7 @@ genexp_rule(Parser *p)
 static expr_ty
 dictcomp_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -17399,7 +17399,7 @@ dictcomp_rule(Parser *p)
 static expr_ty
 arguments_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -17474,7 +17474,7 @@ arguments_rule(Parser *p)
 static expr_ty
 args_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -17574,7 +17574,7 @@ args_rule(Parser *p)
 static asdl_seq*
 kwargs_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -17664,7 +17664,7 @@ kwargs_rule(Parser *p)
 static expr_ty
 starred_expression_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -17766,7 +17766,7 @@ starred_expression_rule(Parser *p)
 static KeywordOrStarred*
 kwarg_or_starred_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -17876,7 +17876,7 @@ kwarg_or_starred_rule(Parser *p)
 static KeywordOrStarred*
 kwarg_or_double_starred_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -17998,7 +17998,7 @@ kwarg_or_double_starred_rule(Parser *p)
 static expr_ty
 star_targets_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -18092,7 +18092,7 @@ star_targets_rule(Parser *p)
 static asdl_expr_seq*
 star_targets_list_seq_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -18139,7 +18139,7 @@ star_targets_list_seq_rule(Parser *p)
 static asdl_expr_seq*
 star_targets_tuple_seq_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -18216,7 +18216,7 @@ star_targets_tuple_seq_rule(Parser *p)
 static expr_ty
 star_target_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -18307,7 +18307,7 @@ star_target_rule(Parser *p)
 static expr_ty
 target_with_star_atom_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -18448,7 +18448,7 @@ target_with_star_atom_rule(Parser *p)
 static expr_ty
 star_atom_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -18608,7 +18608,7 @@ star_atom_rule(Parser *p)
 static expr_ty
 single_target_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -18702,7 +18702,7 @@ single_target_rule(Parser *p)
 static expr_ty
 single_subscript_attribute_target_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -18822,7 +18822,7 @@ static expr_ty t_primary_raw(Parser *);
 static expr_ty
 t_primary_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     expr_ty _res = NULL;
@@ -18856,7 +18856,7 @@ t_primary_rule(Parser *p)
 static expr_ty
 t_primary_raw(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -19077,7 +19077,7 @@ t_primary_raw(Parser *p)
 static void *
 t_lookahead_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -19153,7 +19153,7 @@ t_lookahead_rule(Parser *p)
 static asdl_expr_seq*
 del_targets_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -19203,7 +19203,7 @@ del_targets_rule(Parser *p)
 static expr_ty
 del_target_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -19340,7 +19340,7 @@ del_target_rule(Parser *p)
 static expr_ty
 del_t_atom_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -19507,7 +19507,7 @@ del_t_atom_rule(Parser *p)
 static asdl_expr_seq*
 type_expressions_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -19751,7 +19751,7 @@ type_expressions_rule(Parser *p)
 static Token*
 func_type_comment_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -19844,7 +19844,7 @@ func_type_comment_rule(Parser *p)
 static void *
 invalid_arguments_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -20087,7 +20087,7 @@ invalid_arguments_rule(Parser *p)
 static void *
 invalid_kwarg_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -20233,7 +20233,7 @@ expression_without_invalid_rule(Parser *p)
 {
     int _prev_call_invalid = p->call_invalid_rules;
     p->call_invalid_rules = 0;
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -20352,7 +20352,7 @@ expression_without_invalid_rule(Parser *p)
 static void *
 invalid_legacy_expression_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -20400,7 +20400,7 @@ invalid_legacy_expression_rule(Parser *p)
 static void *
 invalid_type_param_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -20491,7 +20491,7 @@ invalid_type_param_rule(Parser *p)
 static void *
 invalid_expression_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -20708,7 +20708,7 @@ invalid_expression_rule(Parser *p)
 static void *
 invalid_named_expression_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -20834,7 +20834,7 @@ invalid_named_expression_rule(Parser *p)
 static void *
 invalid_assignment_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -21039,7 +21039,7 @@ invalid_assignment_rule(Parser *p)
 static expr_ty
 invalid_ann_assign_target_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -21126,7 +21126,7 @@ invalid_ann_assign_target_rule(Parser *p)
 static void *
 invalid_del_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -21172,7 +21172,7 @@ invalid_del_stmt_rule(Parser *p)
 static void *
 invalid_block_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -21220,7 +21220,7 @@ invalid_block_rule(Parser *p)
 static void *
 invalid_comprehension_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -21338,7 +21338,7 @@ invalid_comprehension_rule(Parser *p)
 static void *
 invalid_dict_comprehension_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -21399,7 +21399,7 @@ invalid_dict_comprehension_rule(Parser *p)
 static void *
 invalid_parameters_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -21616,7 +21616,7 @@ invalid_parameters_rule(Parser *p)
 static void *
 invalid_default_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -21665,7 +21665,7 @@ invalid_default_rule(Parser *p)
 static void *
 invalid_star_etc_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -21807,7 +21807,7 @@ invalid_star_etc_rule(Parser *p)
 static void *
 invalid_kwds_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -21922,7 +21922,7 @@ invalid_kwds_rule(Parser *p)
 static void *
 invalid_parameters_helper_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -21990,7 +21990,7 @@ invalid_parameters_helper_rule(Parser *p)
 static void *
 invalid_lambda_parameters_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -22209,7 +22209,7 @@ invalid_lambda_parameters_rule(Parser *p)
 static void *
 invalid_lambda_parameters_helper_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -22274,7 +22274,7 @@ invalid_lambda_parameters_helper_rule(Parser *p)
 static void *
 invalid_lambda_star_etc_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -22389,7 +22389,7 @@ invalid_lambda_star_etc_rule(Parser *p)
 static void *
 invalid_lambda_kwds_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -22504,7 +22504,7 @@ invalid_lambda_kwds_rule(Parser *p)
 static void *
 invalid_double_type_comments_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -22559,7 +22559,7 @@ invalid_double_type_comments_rule(Parser *p)
 static void *
 invalid_with_item_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -22610,7 +22610,7 @@ invalid_with_item_rule(Parser *p)
 static void *
 invalid_for_if_clause_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -22662,7 +22662,7 @@ invalid_for_if_clause_rule(Parser *p)
 static void *
 invalid_for_target_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -22712,7 +22712,7 @@ invalid_for_target_rule(Parser *p)
 static void *
 invalid_group_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -22794,7 +22794,7 @@ invalid_group_rule(Parser *p)
 static void *
 invalid_import_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -22873,7 +22873,7 @@ invalid_import_rule(Parser *p)
 static void *
 invalid_import_from_targets_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -22948,7 +22948,7 @@ invalid_import_from_targets_rule(Parser *p)
 static void *
 invalid_with_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -23047,7 +23047,7 @@ invalid_with_stmt_rule(Parser *p)
 static void *
 invalid_with_stmt_indent_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -23158,7 +23158,7 @@ invalid_with_stmt_indent_rule(Parser *p)
 static void *
 invalid_try_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -23337,7 +23337,7 @@ invalid_try_stmt_rule(Parser *p)
 static void *
 invalid_except_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -23494,7 +23494,7 @@ invalid_except_stmt_rule(Parser *p)
 static void *
 invalid_except_star_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -23659,7 +23659,7 @@ invalid_except_star_stmt_rule(Parser *p)
 static void *
 invalid_finally_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -23712,7 +23712,7 @@ invalid_finally_stmt_rule(Parser *p)
 static void *
 invalid_except_stmt_indent_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -23803,7 +23803,7 @@ invalid_except_stmt_indent_rule(Parser *p)
 static void *
 invalid_except_star_stmt_indent_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -23866,7 +23866,7 @@ invalid_except_star_stmt_indent_rule(Parser *p)
 static void *
 invalid_match_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -23952,7 +23952,7 @@ invalid_match_stmt_rule(Parser *p)
 static void *
 invalid_case_block_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -24044,7 +24044,7 @@ invalid_case_block_rule(Parser *p)
 static void *
 invalid_as_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -24123,7 +24123,7 @@ invalid_as_pattern_rule(Parser *p)
 static void *
 invalid_class_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -24173,7 +24173,7 @@ invalid_class_pattern_rule(Parser *p)
 static asdl_pattern_seq*
 invalid_class_argument_pattern_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -24228,7 +24228,7 @@ invalid_class_argument_pattern_rule(Parser *p)
 static void *
 invalid_if_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -24314,7 +24314,7 @@ invalid_if_stmt_rule(Parser *p)
 static void *
 invalid_elif_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -24398,7 +24398,7 @@ invalid_elif_stmt_rule(Parser *p)
 static void *
 invalid_else_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -24451,7 +24451,7 @@ invalid_else_stmt_rule(Parser *p)
 static void *
 invalid_while_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -24537,7 +24537,7 @@ invalid_while_stmt_rule(Parser *p)
 static void *
 invalid_for_stmt_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -24643,7 +24643,7 @@ invalid_for_stmt_rule(Parser *p)
 static void *
 invalid_def_raw_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -24775,7 +24775,7 @@ invalid_def_raw_rule(Parser *p)
 static void *
 invalid_class_def_raw_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -24878,7 +24878,7 @@ invalid_class_def_raw_rule(Parser *p)
 static void *
 invalid_double_starred_kvpairs_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -24987,7 +24987,7 @@ invalid_double_starred_kvpairs_rule(Parser *p)
 static void *
 invalid_kvpair_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -25094,7 +25094,7 @@ invalid_kvpair_rule(Parser *p)
 static void *
 invalid_starred_expression_unpacking_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -25146,7 +25146,7 @@ invalid_starred_expression_unpacking_rule(Parser *p)
 static void *
 invalid_starred_expression_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -25200,7 +25200,7 @@ invalid_starred_expression_rule(Parser *p)
 static void *
 invalid_replacement_field_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -25560,7 +25560,7 @@ invalid_replacement_field_rule(Parser *p)
 static void *
 invalid_conversion_character_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -25631,7 +25631,7 @@ invalid_conversion_character_rule(Parser *p)
 static void *
 invalid_arithmetic_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -25683,7 +25683,7 @@ invalid_arithmetic_rule(Parser *p)
 static void *
 invalid_factor_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -25732,7 +25732,7 @@ invalid_factor_rule(Parser *p)
 static void *
 invalid_type_params_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -25778,7 +25778,7 @@ invalid_type_params_rule(Parser *p)
 static asdl_seq *
 _loop0_1_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -25845,7 +25845,7 @@ _loop0_1_rule(Parser *p)
 static asdl_seq *
 _loop1_2_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -25917,7 +25917,7 @@ _loop1_2_rule(Parser *p)
 static asdl_seq *
 _loop0_3_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -25993,7 +25993,7 @@ _loop0_3_rule(Parser *p)
 static asdl_seq *
 _gather_4_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -26034,7 +26034,7 @@ _gather_4_rule(Parser *p)
 static void *
 _tmp_5_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -26091,7 +26091,7 @@ _tmp_5_rule(Parser *p)
 static void *
 _tmp_6_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -26167,7 +26167,7 @@ _tmp_6_rule(Parser *p)
 static void *
 _tmp_7_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -26224,7 +26224,7 @@ _tmp_7_rule(Parser *p)
 static void *
 _tmp_8_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -26281,7 +26281,7 @@ _tmp_8_rule(Parser *p)
 static void *
 _tmp_9_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -26338,7 +26338,7 @@ _tmp_9_rule(Parser *p)
 static void *
 _tmp_10_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -26384,7 +26384,7 @@ _tmp_10_rule(Parser *p)
 static void *
 _tmp_11_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -26452,7 +26452,7 @@ _tmp_11_rule(Parser *p)
 static asdl_seq *
 _loop1_12_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -26524,7 +26524,7 @@ _loop1_12_rule(Parser *p)
 static void *
 _tmp_13_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -26570,7 +26570,7 @@ _tmp_13_rule(Parser *p)
 static asdl_seq *
 _loop0_14_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -26646,7 +26646,7 @@ _loop0_14_rule(Parser *p)
 static asdl_seq *
 _gather_15_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -26687,7 +26687,7 @@ _gather_15_rule(Parser *p)
 static void *
 _tmp_16_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -26744,7 +26744,7 @@ _tmp_16_rule(Parser *p)
 static void *
 _tmp_17_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -26790,7 +26790,7 @@ _tmp_17_rule(Parser *p)
 static asdl_seq *
 _loop0_18_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -26857,7 +26857,7 @@ _loop0_18_rule(Parser *p)
 static asdl_seq *
 _loop1_19_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -26929,7 +26929,7 @@ _loop1_19_rule(Parser *p)
 static asdl_seq *
 _loop0_20_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -27005,7 +27005,7 @@ _loop0_20_rule(Parser *p)
 static asdl_seq *
 _gather_21_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -27046,7 +27046,7 @@ _gather_21_rule(Parser *p)
 static void *
 _tmp_22_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -27092,7 +27092,7 @@ _tmp_22_rule(Parser *p)
 static asdl_seq *
 _loop0_23_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -27168,7 +27168,7 @@ _loop0_23_rule(Parser *p)
 static asdl_seq *
 _gather_24_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -27209,7 +27209,7 @@ _gather_24_rule(Parser *p)
 static asdl_seq *
 _loop1_25_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -27281,7 +27281,7 @@ _loop1_25_rule(Parser *p)
 static void *
 _tmp_26_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -27330,7 +27330,7 @@ _tmp_26_rule(Parser *p)
 static void *
 _tmp_27_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -27376,7 +27376,7 @@ _tmp_27_rule(Parser *p)
 static asdl_seq *
 _loop0_28_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -27443,7 +27443,7 @@ _loop0_28_rule(Parser *p)
 static asdl_seq *
 _loop0_29_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -27510,7 +27510,7 @@ _loop0_29_rule(Parser *p)
 static asdl_seq *
 _loop1_30_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -27582,7 +27582,7 @@ _loop1_30_rule(Parser *p)
 static asdl_seq *
 _loop1_31_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -27654,7 +27654,7 @@ _loop1_31_rule(Parser *p)
 static asdl_seq *
 _loop0_32_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -27721,7 +27721,7 @@ _loop0_32_rule(Parser *p)
 static asdl_seq *
 _loop1_33_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -27793,7 +27793,7 @@ _loop1_33_rule(Parser *p)
 static asdl_seq *
 _loop0_34_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -27869,7 +27869,7 @@ _loop0_34_rule(Parser *p)
 static asdl_seq *
 _gather_35_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -27910,7 +27910,7 @@ _gather_35_rule(Parser *p)
 static void *
 _tmp_36_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -27986,7 +27986,7 @@ _tmp_36_rule(Parser *p)
 static asdl_seq *
 _loop1_37_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -28058,7 +28058,7 @@ _loop1_37_rule(Parser *p)
 static asdl_seq *
 _loop1_38_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -28130,7 +28130,7 @@ _loop1_38_rule(Parser *p)
 static asdl_seq *
 _loop1_39_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -28202,7 +28202,7 @@ _loop1_39_rule(Parser *p)
 static asdl_seq *
 _loop0_40_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -28278,7 +28278,7 @@ _loop0_40_rule(Parser *p)
 static asdl_seq *
 _gather_41_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -28319,7 +28319,7 @@ _gather_41_rule(Parser *p)
 static void *
 _tmp_42_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -28376,7 +28376,7 @@ _tmp_42_rule(Parser *p)
 static void *
 _tmp_43_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -28452,7 +28452,7 @@ _tmp_43_rule(Parser *p)
 static asdl_seq *
 _loop0_44_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -28528,7 +28528,7 @@ _loop0_44_rule(Parser *p)
 static asdl_seq *
 _gather_45_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -28569,7 +28569,7 @@ _gather_45_rule(Parser *p)
 static asdl_seq *
 _loop0_46_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -28645,7 +28645,7 @@ _loop0_46_rule(Parser *p)
 static asdl_seq *
 _gather_47_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -28686,7 +28686,7 @@ _gather_47_rule(Parser *p)
 static void *
 _tmp_48_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -28743,7 +28743,7 @@ _tmp_48_rule(Parser *p)
 static asdl_seq *
 _loop0_49_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -28819,7 +28819,7 @@ _loop0_49_rule(Parser *p)
 static asdl_seq *
 _gather_50_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -28860,7 +28860,7 @@ _gather_50_rule(Parser *p)
 static asdl_seq *
 _loop0_51_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -28936,7 +28936,7 @@ _loop0_51_rule(Parser *p)
 static asdl_seq *
 _gather_52_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -28977,7 +28977,7 @@ _gather_52_rule(Parser *p)
 static asdl_seq *
 _loop0_53_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -29053,7 +29053,7 @@ _loop0_53_rule(Parser *p)
 static asdl_seq *
 _gather_54_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -29094,7 +29094,7 @@ _gather_54_rule(Parser *p)
 static asdl_seq *
 _loop1_55_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -29166,7 +29166,7 @@ _loop1_55_rule(Parser *p)
 static asdl_seq *
 _loop1_56_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -29238,7 +29238,7 @@ _loop1_56_rule(Parser *p)
 static asdl_seq *
 _loop0_57_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -29314,7 +29314,7 @@ _loop0_57_rule(Parser *p)
 static asdl_seq *
 _gather_58_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -29355,7 +29355,7 @@ _gather_58_rule(Parser *p)
 static asdl_seq *
 _loop1_59_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -29427,7 +29427,7 @@ _loop1_59_rule(Parser *p)
 static asdl_seq *
 _loop1_60_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -29499,7 +29499,7 @@ _loop1_60_rule(Parser *p)
 static asdl_seq *
 _loop1_61_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -29571,7 +29571,7 @@ _loop1_61_rule(Parser *p)
 static void *
 _tmp_62_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -29614,7 +29614,7 @@ _tmp_62_rule(Parser *p)
 static asdl_seq *
 _loop0_63_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -29690,7 +29690,7 @@ _loop0_63_rule(Parser *p)
 static asdl_seq *
 _gather_64_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -29731,7 +29731,7 @@ _gather_64_rule(Parser *p)
 static void *
 _tmp_65_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -29777,7 +29777,7 @@ _tmp_65_rule(Parser *p)
 static void *
 _tmp_66_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -29834,7 +29834,7 @@ _tmp_66_rule(Parser *p)
 static void *
 _tmp_67_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -29910,7 +29910,7 @@ _tmp_67_rule(Parser *p)
 static void *
 _tmp_68_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -29967,7 +29967,7 @@ _tmp_68_rule(Parser *p)
 static void *
 _tmp_69_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -30062,7 +30062,7 @@ _tmp_69_rule(Parser *p)
 static void *
 _tmp_70_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -30119,7 +30119,7 @@ _tmp_70_rule(Parser *p)
 static asdl_seq *
 _loop0_71_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -30186,7 +30186,7 @@ _loop0_71_rule(Parser *p)
 static asdl_seq *
 _loop0_72_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -30253,7 +30253,7 @@ _loop0_72_rule(Parser *p)
 static asdl_seq *
 _loop1_73_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -30325,7 +30325,7 @@ _loop1_73_rule(Parser *p)
 static asdl_seq *
 _loop1_74_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -30397,7 +30397,7 @@ _loop1_74_rule(Parser *p)
 static asdl_seq *
 _loop0_75_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -30464,7 +30464,7 @@ _loop0_75_rule(Parser *p)
 static asdl_seq *
 _loop1_76_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -30536,7 +30536,7 @@ _loop1_76_rule(Parser *p)
 static asdl_seq *
 _loop0_77_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -30603,7 +30603,7 @@ _loop0_77_rule(Parser *p)
 static asdl_seq *
 _loop0_78_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -30670,7 +30670,7 @@ _loop0_78_rule(Parser *p)
 static asdl_seq *
 _loop1_79_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -30742,7 +30742,7 @@ _loop1_79_rule(Parser *p)
 static void *
 _tmp_80_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -30791,7 +30791,7 @@ _tmp_80_rule(Parser *p)
 static asdl_seq *
 _loop0_81_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -30867,7 +30867,7 @@ _loop0_81_rule(Parser *p)
 static asdl_seq *
 _gather_82_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -30908,7 +30908,7 @@ _gather_82_rule(Parser *p)
 static asdl_seq *
 _loop1_83_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -30980,7 +30980,7 @@ _loop1_83_rule(Parser *p)
 static asdl_seq *
 _loop0_84_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -31047,7 +31047,7 @@ _loop0_84_rule(Parser *p)
 static void *
 _tmp_85_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -31106,7 +31106,7 @@ _tmp_85_rule(Parser *p)
 static asdl_seq *
 _loop0_86_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -31183,7 +31183,7 @@ _loop0_86_rule(Parser *p)
 static asdl_seq *
 _gather_87_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -31224,7 +31224,7 @@ _gather_87_rule(Parser *p)
 static void *
 _tmp_88_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -31270,7 +31270,7 @@ _tmp_88_rule(Parser *p)
 static asdl_seq *
 _loop0_89_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -31346,7 +31346,7 @@ _loop0_89_rule(Parser *p)
 static asdl_seq *
 _gather_90_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -31387,7 +31387,7 @@ _gather_90_rule(Parser *p)
 static asdl_seq *
 _loop0_91_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -31463,7 +31463,7 @@ _loop0_91_rule(Parser *p)
 static asdl_seq *
 _gather_92_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -31504,7 +31504,7 @@ _gather_92_rule(Parser *p)
 static asdl_seq *
 _loop0_93_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -31571,7 +31571,7 @@ _loop0_93_rule(Parser *p)
 static asdl_seq *
 _loop0_94_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -31647,7 +31647,7 @@ _loop0_94_rule(Parser *p)
 static asdl_seq *
 _gather_95_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -31688,7 +31688,7 @@ _gather_95_rule(Parser *p)
 static asdl_seq *
 _loop1_96_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -31760,7 +31760,7 @@ _loop1_96_rule(Parser *p)
 static void *
 _tmp_97_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -31800,7 +31800,7 @@ _tmp_97_rule(Parser *p)
 static asdl_seq *
 _loop0_98_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -31876,7 +31876,7 @@ _loop0_98_rule(Parser *p)
 static asdl_seq *
 _gather_99_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -31917,7 +31917,7 @@ _gather_99_rule(Parser *p)
 static asdl_seq *
 _loop0_100_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -31993,7 +31993,7 @@ _loop0_100_rule(Parser *p)
 static asdl_seq *
 _gather_101_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -32034,7 +32034,7 @@ _gather_101_rule(Parser *p)
 static void *
 _tmp_102_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -32077,7 +32077,7 @@ _tmp_102_rule(Parser *p)
 static void *
 _tmp_103_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -32134,7 +32134,7 @@ _tmp_103_rule(Parser *p)
 static asdl_seq *
 _loop0_104_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -32210,7 +32210,7 @@ _loop0_104_rule(Parser *p)
 static asdl_seq *
 _gather_105_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -32251,7 +32251,7 @@ _gather_105_rule(Parser *p)
 static void *
 _tmp_106_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -32311,7 +32311,7 @@ _tmp_106_rule(Parser *p)
 static void *
 _tmp_107_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -32352,7 +32352,7 @@ _tmp_107_rule(Parser *p)
 static void *
 _tmp_108_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -32409,7 +32409,7 @@ _tmp_108_rule(Parser *p)
 static void *
 _tmp_109_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -32485,7 +32485,7 @@ _tmp_109_rule(Parser *p)
 static void *
 _tmp_110_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -32526,7 +32526,7 @@ _tmp_110_rule(Parser *p)
 static asdl_seq *
 _loop1_111_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -32598,7 +32598,7 @@ _loop1_111_rule(Parser *p)
 static void *
 _tmp_112_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -32658,7 +32658,7 @@ _tmp_112_rule(Parser *p)
 static void *
 _tmp_113_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -32715,7 +32715,7 @@ _tmp_113_rule(Parser *p)
 static void *
 _tmp_114_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -32791,7 +32791,7 @@ _tmp_114_rule(Parser *p)
 static void *
 _tmp_115_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -32848,7 +32848,7 @@ _tmp_115_rule(Parser *p)
 static void *
 _tmp_116_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -32981,7 +32981,7 @@ _tmp_116_rule(Parser *p)
 static asdl_seq *
 _loop0_117_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -33048,7 +33048,7 @@ _loop0_117_rule(Parser *p)
 static asdl_seq *
 _loop0_118_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -33115,7 +33115,7 @@ _loop0_118_rule(Parser *p)
 static void *
 _tmp_119_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -33191,7 +33191,7 @@ _tmp_119_rule(Parser *p)
 static void *
 _tmp_120_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -33248,7 +33248,7 @@ _tmp_120_rule(Parser *p)
 static void *
 _tmp_121_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -33305,7 +33305,7 @@ _tmp_121_rule(Parser *p)
 static void *
 _tmp_122_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -33362,7 +33362,7 @@ _tmp_122_rule(Parser *p)
 static void *
 _tmp_123_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -33419,7 +33419,7 @@ _tmp_123_rule(Parser *p)
 static void *
 _tmp_124_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -33479,7 +33479,7 @@ _tmp_124_rule(Parser *p)
 static void *
 _tmp_125_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -33536,7 +33536,7 @@ _tmp_125_rule(Parser *p)
 static void *
 _tmp_126_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -33612,7 +33612,7 @@ _tmp_126_rule(Parser *p)
 static void *
 _tmp_127_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -33669,7 +33669,7 @@ _tmp_127_rule(Parser *p)
 static asdl_seq *
 _loop0_128_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -33745,7 +33745,7 @@ _loop0_128_rule(Parser *p)
 static asdl_seq *
 _gather_129_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -33786,7 +33786,7 @@ _gather_129_rule(Parser *p)
 static void *
 _tmp_130_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -33843,7 +33843,7 @@ _tmp_130_rule(Parser *p)
 static void *
 _tmp_131_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -33903,7 +33903,7 @@ _tmp_131_rule(Parser *p)
 static void *
 _tmp_132_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -33960,7 +33960,7 @@ _tmp_132_rule(Parser *p)
 static void *
 _tmp_133_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -34005,7 +34005,7 @@ _tmp_133_rule(Parser *p)
 static asdl_seq *
 _loop0_134_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -34081,7 +34081,7 @@ _loop0_134_rule(Parser *p)
 static asdl_seq *
 _gather_135_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -34122,7 +34122,7 @@ _gather_135_rule(Parser *p)
 static asdl_seq *
 _loop0_136_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -34198,7 +34198,7 @@ _loop0_136_rule(Parser *p)
 static asdl_seq *
 _gather_137_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -34239,7 +34239,7 @@ _gather_137_rule(Parser *p)
 static asdl_seq *
 _loop0_138_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -34315,7 +34315,7 @@ _loop0_138_rule(Parser *p)
 static asdl_seq *
 _gather_139_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -34356,7 +34356,7 @@ _gather_139_rule(Parser *p)
 static void *
 _tmp_140_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -34413,7 +34413,7 @@ _tmp_140_rule(Parser *p)
 static asdl_seq *
 _loop0_141_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -34480,7 +34480,7 @@ _loop0_141_rule(Parser *p)
 static void *
 _tmp_142_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -34522,7 +34522,7 @@ _tmp_142_rule(Parser *p)
 static void *
 _tmp_143_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -34579,7 +34579,7 @@ _tmp_143_rule(Parser *p)
 static void *
 _tmp_144_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -34620,7 +34620,7 @@ _tmp_144_rule(Parser *p)
 static void *
 _tmp_145_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -34677,7 +34677,7 @@ _tmp_145_rule(Parser *p)
 static void *
 _tmp_146_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -34772,7 +34772,7 @@ _tmp_146_rule(Parser *p)
 static void *
 _tmp_147_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -34848,7 +34848,7 @@ _tmp_147_rule(Parser *p)
 static void *
 _tmp_148_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -34889,7 +34889,7 @@ _tmp_148_rule(Parser *p)
 static void *
 _tmp_149_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -34946,7 +34946,7 @@ _tmp_149_rule(Parser *p)
 static void *
 _tmp_150_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -35098,7 +35098,7 @@ _tmp_150_rule(Parser *p)
 static void *
 _tmp_151_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -35174,7 +35174,7 @@ _tmp_151_rule(Parser *p)
 static void *
 _tmp_152_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -35220,7 +35220,7 @@ _tmp_152_rule(Parser *p)
 static void *
 _tmp_153_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -35277,7 +35277,7 @@ _tmp_153_rule(Parser *p)
 static void *
 _tmp_154_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -35326,7 +35326,7 @@ _tmp_154_rule(Parser *p)
 static void *
 _tmp_155_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -35372,7 +35372,7 @@ _tmp_155_rule(Parser *p)
 static void *
 _tmp_156_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -35418,7 +35418,7 @@ _tmp_156_rule(Parser *p)
 static void *
 _tmp_157_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -35464,7 +35464,7 @@ _tmp_157_rule(Parser *p)
 static void *
 _tmp_158_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -35521,7 +35521,7 @@ _tmp_158_rule(Parser *p)
 static void *
 _tmp_159_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -35578,7 +35578,7 @@ _tmp_159_rule(Parser *p)
 static void *
 _tmp_160_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -35624,7 +35624,7 @@ _tmp_160_rule(Parser *p)
 static void *
 _tmp_161_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -35683,7 +35683,7 @@ _tmp_161_rule(Parser *p)
 static void *
 _tmp_162_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -35730,7 +35730,7 @@ _tmp_162_rule(Parser *p)
 static void *
 _tmp_163_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -35774,7 +35774,7 @@ _tmp_163_rule(Parser *p)
 static void *
 _tmp_164_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -35814,7 +35814,7 @@ _tmp_164_rule(Parser *p)
 static void *
 _tmp_165_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -35854,7 +35854,7 @@ _tmp_165_rule(Parser *p)
 static void *
 _tmp_166_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -35911,7 +35911,7 @@ _tmp_166_rule(Parser *p)
 static void *
 _tmp_167_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -35968,7 +35968,7 @@ _tmp_167_rule(Parser *p)
 static asdl_seq *
 _loop0_168_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -36035,7 +36035,7 @@ _loop0_168_rule(Parser *p)
 static void *
 _tmp_169_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -36077,7 +36077,7 @@ _tmp_169_rule(Parser *p)
 static void *
 _tmp_170_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -36119,7 +36119,7 @@ _tmp_170_rule(Parser *p)
 static void *
 _tmp_171_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
@@ -36160,7 +36160,7 @@ _tmp_171_rule(Parser *p)
 static void *
 _tmp_172_rule(Parser *p)
 {
-    if (p->level++ == MAXSTACK) {
+    if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {
         _Pypegen_stack_overflow(p);
     }
     if (p->error_indicator) {
index 4adf72a8537a51bd6ac4b1c6b8756949276e8ddd..638e3f67e1cfdda4f64dfa85b7a5135dd981ce30 100644 (file)
 #include "structmember.h"
 #include <stddef.h>
 
-struct validator {
-    int recursion_depth;            /* current recursion depth */
-    int recursion_limit;            /* recursion limit */
-};
-
 // Forward declaration
 static int init_types(void *arg);
 
@@ -392,8 +387,7 @@ GENERATE_ASDL_SEQ_CONSTRUCTOR(pattern, pattern_ty)
 GENERATE_ASDL_SEQ_CONSTRUCTOR(type_ignore, type_ignore_ty)
 GENERATE_ASDL_SEQ_CONSTRUCTOR(type_param, type_param_ty)
 
-static PyObject* ast2obj_mod(struct ast_state *state, struct validator *vstate,
-                             void*);
+static PyObject* ast2obj_mod(struct ast_state *state, void*);
 static const char * const Module_fields[]={
     "body",
     "type_ignores",
@@ -414,8 +408,7 @@ static const char * const stmt_attributes[] = {
     "end_lineno",
     "end_col_offset",
 };
-static PyObject* ast2obj_stmt(struct ast_state *state, struct validator
-                              *vstate, void*);
+static PyObject* ast2obj_stmt(struct ast_state *state, void*);
 static const char * const FunctionDef_fields[]={
     "name",
     "args",
@@ -550,8 +543,7 @@ static const char * const expr_attributes[] = {
     "end_lineno",
     "end_col_offset",
 };
-static PyObject* ast2obj_expr(struct ast_state *state, struct validator
-                              *vstate, void*);
+static PyObject* ast2obj_expr(struct ast_state *state, void*);
 static const char * const BoolOp_fields[]={
     "op",
     "values",
@@ -664,18 +656,12 @@ static const char * const Slice_fields[]={
     "upper",
     "step",
 };
-static PyObject* ast2obj_expr_context(struct ast_state *state, struct validator
-                                      *vstate, expr_context_ty);
-static PyObject* ast2obj_boolop(struct ast_state *state, struct validator
-                                *vstate, boolop_ty);
-static PyObject* ast2obj_operator(struct ast_state *state, struct validator
-                                  *vstate, operator_ty);
-static PyObject* ast2obj_unaryop(struct ast_state *state, struct validator
-                                 *vstate, unaryop_ty);
-static PyObject* ast2obj_cmpop(struct ast_state *state, struct validator
-                               *vstate, cmpop_ty);
-static PyObject* ast2obj_comprehension(struct ast_state *state, struct
-                                       validator *vstate, void*);
+static PyObject* ast2obj_expr_context(struct ast_state *state, expr_context_ty);
+static PyObject* ast2obj_boolop(struct ast_state *state, boolop_ty);
+static PyObject* ast2obj_operator(struct ast_state *state, operator_ty);
+static PyObject* ast2obj_unaryop(struct ast_state *state, unaryop_ty);
+static PyObject* ast2obj_cmpop(struct ast_state *state, cmpop_ty);
+static PyObject* ast2obj_comprehension(struct ast_state *state, void*);
 static const char * const comprehension_fields[]={
     "target",
     "iter",
@@ -688,15 +674,13 @@ static const char * const excepthandler_attributes[] = {
     "end_lineno",
     "end_col_offset",
 };
-static PyObject* ast2obj_excepthandler(struct ast_state *state, struct
-                                       validator *vstate, void*);
+static PyObject* ast2obj_excepthandler(struct ast_state *state, void*);
 static const char * const ExceptHandler_fields[]={
     "type",
     "name",
     "body",
 };
-static PyObject* ast2obj_arguments(struct ast_state *state, struct validator
-                                   *vstate, void*);
+static PyObject* ast2obj_arguments(struct ast_state *state, void*);
 static const char * const arguments_fields[]={
     "posonlyargs",
     "args",
@@ -706,8 +690,7 @@ static const char * const arguments_fields[]={
     "kwarg",
     "defaults",
 };
-static PyObject* ast2obj_arg(struct ast_state *state, struct validator *vstate,
-                             void*);
+static PyObject* ast2obj_arg(struct ast_state *state, void*);
 static const char * const arg_attributes[] = {
     "lineno",
     "col_offset",
@@ -719,8 +702,7 @@ static const char * const arg_fields[]={
     "annotation",
     "type_comment",
 };
-static PyObject* ast2obj_keyword(struct ast_state *state, struct validator
-                                 *vstate, void*);
+static PyObject* ast2obj_keyword(struct ast_state *state, void*);
 static const char * const keyword_attributes[] = {
     "lineno",
     "col_offset",
@@ -731,8 +713,7 @@ static const char * const keyword_fields[]={
     "arg",
     "value",
 };
-static PyObject* ast2obj_alias(struct ast_state *state, struct validator
-                               *vstate, void*);
+static PyObject* ast2obj_alias(struct ast_state *state, void*);
 static const char * const alias_attributes[] = {
     "lineno",
     "col_offset",
@@ -743,14 +724,12 @@ static const char * const alias_fields[]={
     "name",
     "asname",
 };
-static PyObject* ast2obj_withitem(struct ast_state *state, struct validator
-                                  *vstate, void*);
+static PyObject* ast2obj_withitem(struct ast_state *state, void*);
 static const char * const withitem_fields[]={
     "context_expr",
     "optional_vars",
 };
-static PyObject* ast2obj_match_case(struct ast_state *state, struct validator
-                                    *vstate, void*);
+static PyObject* ast2obj_match_case(struct ast_state *state, void*);
 static const char * const match_case_fields[]={
     "pattern",
     "guard",
@@ -762,8 +741,7 @@ static const char * const pattern_attributes[] = {
     "end_lineno",
     "end_col_offset",
 };
-static PyObject* ast2obj_pattern(struct ast_state *state, struct validator
-                                 *vstate, void*);
+static PyObject* ast2obj_pattern(struct ast_state *state, void*);
 static const char * const MatchValue_fields[]={
     "value",
 };
@@ -794,8 +772,7 @@ static const char * const MatchAs_fields[]={
 static const char * const MatchOr_fields[]={
     "patterns",
 };
-static PyObject* ast2obj_type_ignore(struct ast_state *state, struct validator
-                                     *vstate, void*);
+static PyObject* ast2obj_type_ignore(struct ast_state *state, void*);
 static const char * const TypeIgnore_fields[]={
     "lineno",
     "tag",
@@ -806,8 +783,7 @@ static const char * const type_param_attributes[] = {
     "end_lineno",
     "end_col_offset",
 };
-static PyObject* ast2obj_type_param(struct ast_state *state, struct validator
-                                    *vstate, void*);
+static PyObject* ast2obj_type_param(struct ast_state *state, void*);
 static const char * const TypeVar_fields[]={
     "name",
     "bound",
@@ -5933,8 +5909,8 @@ add_attributes(struct ast_state *state, PyObject *type, const char * const *attr
 
 /* Conversion AST -> Python */
 
-static PyObject* ast2obj_list(struct ast_state *state, struct validator *vstate, asdl_seq *seq,
-                              PyObject* (*func)(struct ast_state *state, struct validator *vstate, void*))
+static PyObject* ast2obj_list(struct ast_state *state, asdl_seq *seq,
+                              PyObject* (*func)(struct ast_state *state, void*))
 {
     Py_ssize_t i, n = asdl_seq_LEN(seq);
     PyObject *result = PyList_New(n);
@@ -5942,7 +5918,7 @@ static PyObject* ast2obj_list(struct ast_state *state, struct validator *vstate,
     if (!result)
         return NULL;
     for (i = 0; i < n; i++) {
-        value = func(state, vstate, asdl_seq_GET_UNTYPED(seq, i));
+        value = func(state, asdl_seq_GET_UNTYPED(seq, i));
         if (!value) {
             Py_DECREF(result);
             return NULL;
@@ -5952,7 +5928,7 @@ static PyObject* ast2obj_list(struct ast_state *state, struct validator *vstate,
     return result;
 }
 
-static PyObject* ast2obj_object(struct ast_state *Py_UNUSED(state), struct validator *Py_UNUSED(vstate), void *o)
+static PyObject* ast2obj_object(struct ast_state *Py_UNUSED(state), void *o)
 {
     PyObject *op = (PyObject*)o;
     if (!op) {
@@ -5964,7 +5940,7 @@ static PyObject* ast2obj_object(struct ast_state *Py_UNUSED(state), struct valid
 #define ast2obj_identifier ast2obj_object
 #define ast2obj_string ast2obj_object
 
-static PyObject* ast2obj_int(struct ast_state *Py_UNUSED(state), struct validator *Py_UNUSED(vstate), long b)
+static PyObject* ast2obj_int(struct ast_state *Py_UNUSED(state), long b)
 {
     return PyLong_FromLong(b);
 }
@@ -8712,7 +8688,7 @@ _PyAST_TypeVarTuple(identifier name, expr_ty default_value, int lineno, int
 
 
 PyObject*
-ast2obj_mod(struct ast_state *state, struct validator *vstate, void* _o)
+ast2obj_mod(struct ast_state *state, void* _o)
 {
     mod_ty o = (mod_ty)_o;
     PyObject *result = NULL, *value = NULL;
@@ -8720,9 +8696,7 @@ ast2obj_mod(struct ast_state *state, struct validator *vstate, void* _o)
     if (!o) {
         Py_RETURN_NONE;
     }
-    if (++vstate->recursion_depth > vstate->recursion_limit) {
-        PyErr_SetString(PyExc_RecursionError,
-            "maximum recursion depth exceeded during ast construction");
+    if (Py_EnterRecursiveCall("during  ast construction")) {
         return NULL;
     }
     switch (o->kind) {
@@ -8730,14 +8704,12 @@ ast2obj_mod(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Module_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Module.body,
-                             ast2obj_stmt);
+        value = ast2obj_list(state, (asdl_seq*)o->v.Module.body, ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->body, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate,
-                             (asdl_seq*)o->v.Module.type_ignores,
+        value = ast2obj_list(state, (asdl_seq*)o->v.Module.type_ignores,
                              ast2obj_type_ignore);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->type_ignores, value) == -1)
@@ -8748,7 +8720,7 @@ ast2obj_mod(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Interactive_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Interactive.body,
+        value = ast2obj_list(state, (asdl_seq*)o->v.Interactive.body,
                              ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->body, value) == -1)
@@ -8759,7 +8731,7 @@ ast2obj_mod(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Expression_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.Expression.body);
+        value = ast2obj_expr(state, o->v.Expression.body);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->body, value) == -1)
             goto failed;
@@ -8769,31 +8741,30 @@ ast2obj_mod(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->FunctionType_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate,
-                             (asdl_seq*)o->v.FunctionType.argtypes,
+        value = ast2obj_list(state, (asdl_seq*)o->v.FunctionType.argtypes,
                              ast2obj_expr);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->argtypes, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.FunctionType.returns);
+        value = ast2obj_expr(state, o->v.FunctionType.returns);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->returns, value) == -1)
             goto failed;
         Py_DECREF(value);
         break;
     }
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     return result;
 failed:
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     Py_XDECREF(value);
     Py_XDECREF(result);
     return NULL;
 }
 
 PyObject*
-ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
+ast2obj_stmt(struct ast_state *state, void* _o)
 {
     stmt_ty o = (stmt_ty)_o;
     PyObject *result = NULL, *value = NULL;
@@ -8801,9 +8772,7 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
     if (!o) {
         Py_RETURN_NONE;
     }
-    if (++vstate->recursion_depth > vstate->recursion_limit) {
-        PyErr_SetString(PyExc_RecursionError,
-            "maximum recursion depth exceeded during ast construction");
+    if (Py_EnterRecursiveCall("during  ast construction")) {
         return NULL;
     }
     switch (o->kind) {
@@ -8811,41 +8780,39 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->FunctionDef_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_identifier(state, vstate, o->v.FunctionDef.name);
+        value = ast2obj_identifier(state, o->v.FunctionDef.name);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->name, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_arguments(state, vstate, o->v.FunctionDef.args);
+        value = ast2obj_arguments(state, o->v.FunctionDef.args);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->args, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.FunctionDef.body,
+        value = ast2obj_list(state, (asdl_seq*)o->v.FunctionDef.body,
                              ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->body, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate,
-                             (asdl_seq*)o->v.FunctionDef.decorator_list,
+        value = ast2obj_list(state, (asdl_seq*)o->v.FunctionDef.decorator_list,
                              ast2obj_expr);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->decorator_list, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.FunctionDef.returns);
+        value = ast2obj_expr(state, o->v.FunctionDef.returns);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->returns, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_string(state, vstate, o->v.FunctionDef.type_comment);
+        value = ast2obj_string(state, o->v.FunctionDef.type_comment);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->type_comment, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate,
-                             (asdl_seq*)o->v.FunctionDef.type_params,
+        value = ast2obj_list(state, (asdl_seq*)o->v.FunctionDef.type_params,
                              ast2obj_type_param);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->type_params, value) == -1)
@@ -8856,41 +8823,40 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->AsyncFunctionDef_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_identifier(state, vstate, o->v.AsyncFunctionDef.name);
+        value = ast2obj_identifier(state, o->v.AsyncFunctionDef.name);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->name, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_arguments(state, vstate, o->v.AsyncFunctionDef.args);
+        value = ast2obj_arguments(state, o->v.AsyncFunctionDef.args);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->args, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate,
-                             (asdl_seq*)o->v.AsyncFunctionDef.body,
+        value = ast2obj_list(state, (asdl_seq*)o->v.AsyncFunctionDef.body,
                              ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->body, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate,
+        value = ast2obj_list(state,
                              (asdl_seq*)o->v.AsyncFunctionDef.decorator_list,
                              ast2obj_expr);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->decorator_list, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.AsyncFunctionDef.returns);
+        value = ast2obj_expr(state, o->v.AsyncFunctionDef.returns);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->returns, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_string(state, vstate, o->v.AsyncFunctionDef.type_comment);
+        value = ast2obj_string(state, o->v.AsyncFunctionDef.type_comment);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->type_comment, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate,
+        value = ast2obj_list(state,
                              (asdl_seq*)o->v.AsyncFunctionDef.type_params,
                              ast2obj_type_param);
         if (!value) goto failed;
@@ -8902,38 +8868,36 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->ClassDef_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_identifier(state, vstate, o->v.ClassDef.name);
+        value = ast2obj_identifier(state, o->v.ClassDef.name);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->name, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.ClassDef.bases,
+        value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.bases,
                              ast2obj_expr);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->bases, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.ClassDef.keywords,
+        value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.keywords,
                              ast2obj_keyword);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->keywords, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.ClassDef.body,
+        value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.body,
                              ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->body, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate,
-                             (asdl_seq*)o->v.ClassDef.decorator_list,
+        value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.decorator_list,
                              ast2obj_expr);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->decorator_list, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate,
-                             (asdl_seq*)o->v.ClassDef.type_params,
+        value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.type_params,
                              ast2obj_type_param);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->type_params, value) == -1)
@@ -8944,7 +8908,7 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Return_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.Return.value);
+        value = ast2obj_expr(state, o->v.Return.value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->value, value) == -1)
             goto failed;
@@ -8954,7 +8918,7 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Delete_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Delete.targets,
+        value = ast2obj_list(state, (asdl_seq*)o->v.Delete.targets,
                              ast2obj_expr);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->targets, value) == -1)
@@ -8965,18 +8929,18 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Assign_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Assign.targets,
+        value = ast2obj_list(state, (asdl_seq*)o->v.Assign.targets,
                              ast2obj_expr);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->targets, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.Assign.value);
+        value = ast2obj_expr(state, o->v.Assign.value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->value, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_string(state, vstate, o->v.Assign.type_comment);
+        value = ast2obj_string(state, o->v.Assign.type_comment);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->type_comment, value) == -1)
             goto failed;
@@ -8986,19 +8950,18 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->TypeAlias_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.TypeAlias.name);
+        value = ast2obj_expr(state, o->v.TypeAlias.name);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->name, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate,
-                             (asdl_seq*)o->v.TypeAlias.type_params,
+        value = ast2obj_list(state, (asdl_seq*)o->v.TypeAlias.type_params,
                              ast2obj_type_param);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->type_params, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.TypeAlias.value);
+        value = ast2obj_expr(state, o->v.TypeAlias.value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->value, value) == -1)
             goto failed;
@@ -9008,17 +8971,17 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->AugAssign_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.AugAssign.target);
+        value = ast2obj_expr(state, o->v.AugAssign.target);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->target, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_operator(state, vstate, o->v.AugAssign.op);
+        value = ast2obj_operator(state, o->v.AugAssign.op);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->op, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.AugAssign.value);
+        value = ast2obj_expr(state, o->v.AugAssign.value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->value, value) == -1)
             goto failed;
@@ -9028,22 +8991,22 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->AnnAssign_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.AnnAssign.target);
+        value = ast2obj_expr(state, o->v.AnnAssign.target);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->target, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.AnnAssign.annotation);
+        value = ast2obj_expr(state, o->v.AnnAssign.annotation);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->annotation, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.AnnAssign.value);
+        value = ast2obj_expr(state, o->v.AnnAssign.value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->value, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_int(state, vstate, o->v.AnnAssign.simple);
+        value = ast2obj_int(state, o->v.AnnAssign.simple);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->simple, value) == -1)
             goto failed;
@@ -9053,29 +9016,27 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->For_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.For.target);
+        value = ast2obj_expr(state, o->v.For.target);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->target, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.For.iter);
+        value = ast2obj_expr(state, o->v.For.iter);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->iter, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.For.body,
-                             ast2obj_stmt);
+        value = ast2obj_list(state, (asdl_seq*)o->v.For.body, ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->body, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.For.orelse,
-                             ast2obj_stmt);
+        value = ast2obj_list(state, (asdl_seq*)o->v.For.orelse, ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->orelse, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_string(state, vstate, o->v.For.type_comment);
+        value = ast2obj_string(state, o->v.For.type_comment);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->type_comment, value) == -1)
             goto failed;
@@ -9085,29 +9046,29 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->AsyncFor_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.AsyncFor.target);
+        value = ast2obj_expr(state, o->v.AsyncFor.target);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->target, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.AsyncFor.iter);
+        value = ast2obj_expr(state, o->v.AsyncFor.iter);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->iter, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.AsyncFor.body,
+        value = ast2obj_list(state, (asdl_seq*)o->v.AsyncFor.body,
                              ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->body, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.AsyncFor.orelse,
+        value = ast2obj_list(state, (asdl_seq*)o->v.AsyncFor.orelse,
                              ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->orelse, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_string(state, vstate, o->v.AsyncFor.type_comment);
+        value = ast2obj_string(state, o->v.AsyncFor.type_comment);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->type_comment, value) == -1)
             goto failed;
@@ -9117,19 +9078,17 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->While_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.While.test);
+        value = ast2obj_expr(state, o->v.While.test);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->test, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.While.body,
-                             ast2obj_stmt);
+        value = ast2obj_list(state, (asdl_seq*)o->v.While.body, ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->body, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.While.orelse,
-                             ast2obj_stmt);
+        value = ast2obj_list(state, (asdl_seq*)o->v.While.orelse, ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->orelse, value) == -1)
             goto failed;
@@ -9139,19 +9098,17 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->If_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.If.test);
+        value = ast2obj_expr(state, o->v.If.test);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->test, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.If.body,
-                             ast2obj_stmt);
+        value = ast2obj_list(state, (asdl_seq*)o->v.If.body, ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->body, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.If.orelse,
-                             ast2obj_stmt);
+        value = ast2obj_list(state, (asdl_seq*)o->v.If.orelse, ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->orelse, value) == -1)
             goto failed;
@@ -9161,19 +9118,18 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->With_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.With.items,
+        value = ast2obj_list(state, (asdl_seq*)o->v.With.items,
                              ast2obj_withitem);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->items, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.With.body,
-                             ast2obj_stmt);
+        value = ast2obj_list(state, (asdl_seq*)o->v.With.body, ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->body, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_string(state, vstate, o->v.With.type_comment);
+        value = ast2obj_string(state, o->v.With.type_comment);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->type_comment, value) == -1)
             goto failed;
@@ -9183,19 +9139,19 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->AsyncWith_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.AsyncWith.items,
+        value = ast2obj_list(state, (asdl_seq*)o->v.AsyncWith.items,
                              ast2obj_withitem);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->items, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.AsyncWith.body,
+        value = ast2obj_list(state, (asdl_seq*)o->v.AsyncWith.body,
                              ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->body, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_string(state, vstate, o->v.AsyncWith.type_comment);
+        value = ast2obj_string(state, o->v.AsyncWith.type_comment);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->type_comment, value) == -1)
             goto failed;
@@ -9205,12 +9161,12 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Match_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.Match.subject);
+        value = ast2obj_expr(state, o->v.Match.subject);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->subject, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Match.cases,
+        value = ast2obj_list(state, (asdl_seq*)o->v.Match.cases,
                              ast2obj_match_case);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->cases, value) == -1)
@@ -9221,12 +9177,12 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Raise_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.Raise.exc);
+        value = ast2obj_expr(state, o->v.Raise.exc);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->exc, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.Raise.cause);
+        value = ast2obj_expr(state, o->v.Raise.cause);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->cause, value) == -1)
             goto failed;
@@ -9236,25 +9192,23 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Try_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Try.body,
-                             ast2obj_stmt);
+        value = ast2obj_list(state, (asdl_seq*)o->v.Try.body, ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->body, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Try.handlers,
+        value = ast2obj_list(state, (asdl_seq*)o->v.Try.handlers,
                              ast2obj_excepthandler);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->handlers, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Try.orelse,
-                             ast2obj_stmt);
+        value = ast2obj_list(state, (asdl_seq*)o->v.Try.orelse, ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->orelse, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Try.finalbody,
+        value = ast2obj_list(state, (asdl_seq*)o->v.Try.finalbody,
                              ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->finalbody, value) == -1)
@@ -9265,25 +9219,24 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->TryStar_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.TryStar.body,
-                             ast2obj_stmt);
+        value = ast2obj_list(state, (asdl_seq*)o->v.TryStar.body, ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->body, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.TryStar.handlers,
+        value = ast2obj_list(state, (asdl_seq*)o->v.TryStar.handlers,
                              ast2obj_excepthandler);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->handlers, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.TryStar.orelse,
+        value = ast2obj_list(state, (asdl_seq*)o->v.TryStar.orelse,
                              ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->orelse, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.TryStar.finalbody,
+        value = ast2obj_list(state, (asdl_seq*)o->v.TryStar.finalbody,
                              ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->finalbody, value) == -1)
@@ -9294,12 +9247,12 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Assert_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.Assert.test);
+        value = ast2obj_expr(state, o->v.Assert.test);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->test, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.Assert.msg);
+        value = ast2obj_expr(state, o->v.Assert.msg);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->msg, value) == -1)
             goto failed;
@@ -9309,7 +9262,7 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Import_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Import.names,
+        value = ast2obj_list(state, (asdl_seq*)o->v.Import.names,
                              ast2obj_alias);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->names, value) == -1)
@@ -9320,18 +9273,18 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->ImportFrom_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_identifier(state, vstate, o->v.ImportFrom.module);
+        value = ast2obj_identifier(state, o->v.ImportFrom.module);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->module, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.ImportFrom.names,
+        value = ast2obj_list(state, (asdl_seq*)o->v.ImportFrom.names,
                              ast2obj_alias);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->names, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_int(state, vstate, o->v.ImportFrom.level);
+        value = ast2obj_int(state, o->v.ImportFrom.level);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->level, value) == -1)
             goto failed;
@@ -9341,7 +9294,7 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Global_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Global.names,
+        value = ast2obj_list(state, (asdl_seq*)o->v.Global.names,
                              ast2obj_identifier);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->names, value) == -1)
@@ -9352,7 +9305,7 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Nonlocal_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Nonlocal.names,
+        value = ast2obj_list(state, (asdl_seq*)o->v.Nonlocal.names,
                              ast2obj_identifier);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->names, value) == -1)
@@ -9363,7 +9316,7 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Expr_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.Expr.value);
+        value = ast2obj_expr(state, o->v.Expr.value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->value, value) == -1)
             goto failed;
@@ -9385,37 +9338,37 @@ ast2obj_stmt(struct ast_state *state, struct validator *vstate, void* _o)
         if (!result) goto failed;
         break;
     }
-    value = ast2obj_int(state, vstate, o->lineno);
+    value = ast2obj_int(state, o->lineno);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->lineno, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->col_offset);
+    value = ast2obj_int(state, o->col_offset);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->col_offset, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->end_lineno);
+    value = ast2obj_int(state, o->end_lineno);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->end_lineno, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->end_col_offset);
+    value = ast2obj_int(state, o->end_col_offset);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)
         goto failed;
     Py_DECREF(value);
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     return result;
 failed:
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     Py_XDECREF(value);
     Py_XDECREF(result);
     return NULL;
 }
 
 PyObject*
-ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
+ast2obj_expr(struct ast_state *state, void* _o)
 {
     expr_ty o = (expr_ty)_o;
     PyObject *result = NULL, *value = NULL;
@@ -9423,9 +9376,7 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
     if (!o) {
         Py_RETURN_NONE;
     }
-    if (++vstate->recursion_depth > vstate->recursion_limit) {
-        PyErr_SetString(PyExc_RecursionError,
-            "maximum recursion depth exceeded during ast construction");
+    if (Py_EnterRecursiveCall("during  ast construction")) {
         return NULL;
     }
     switch (o->kind) {
@@ -9433,12 +9384,12 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->BoolOp_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_boolop(state, vstate, o->v.BoolOp.op);
+        value = ast2obj_boolop(state, o->v.BoolOp.op);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->op, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.BoolOp.values,
+        value = ast2obj_list(state, (asdl_seq*)o->v.BoolOp.values,
                              ast2obj_expr);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->values, value) == -1)
@@ -9449,12 +9400,12 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->NamedExpr_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.NamedExpr.target);
+        value = ast2obj_expr(state, o->v.NamedExpr.target);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->target, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.NamedExpr.value);
+        value = ast2obj_expr(state, o->v.NamedExpr.value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->value, value) == -1)
             goto failed;
@@ -9464,17 +9415,17 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->BinOp_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.BinOp.left);
+        value = ast2obj_expr(state, o->v.BinOp.left);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->left, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_operator(state, vstate, o->v.BinOp.op);
+        value = ast2obj_operator(state, o->v.BinOp.op);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->op, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.BinOp.right);
+        value = ast2obj_expr(state, o->v.BinOp.right);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->right, value) == -1)
             goto failed;
@@ -9484,12 +9435,12 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->UnaryOp_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_unaryop(state, vstate, o->v.UnaryOp.op);
+        value = ast2obj_unaryop(state, o->v.UnaryOp.op);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->op, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.UnaryOp.operand);
+        value = ast2obj_expr(state, o->v.UnaryOp.operand);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->operand, value) == -1)
             goto failed;
@@ -9499,12 +9450,12 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Lambda_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_arguments(state, vstate, o->v.Lambda.args);
+        value = ast2obj_arguments(state, o->v.Lambda.args);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->args, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.Lambda.body);
+        value = ast2obj_expr(state, o->v.Lambda.body);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->body, value) == -1)
             goto failed;
@@ -9514,17 +9465,17 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->IfExp_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.IfExp.test);
+        value = ast2obj_expr(state, o->v.IfExp.test);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->test, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.IfExp.body);
+        value = ast2obj_expr(state, o->v.IfExp.body);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->body, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.IfExp.orelse);
+        value = ast2obj_expr(state, o->v.IfExp.orelse);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->orelse, value) == -1)
             goto failed;
@@ -9534,14 +9485,12 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Dict_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Dict.keys,
-                             ast2obj_expr);
+        value = ast2obj_list(state, (asdl_seq*)o->v.Dict.keys, ast2obj_expr);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->keys, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Dict.values,
-                             ast2obj_expr);
+        value = ast2obj_list(state, (asdl_seq*)o->v.Dict.values, ast2obj_expr);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->values, value) == -1)
             goto failed;
@@ -9551,8 +9500,7 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Set_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Set.elts,
-                             ast2obj_expr);
+        value = ast2obj_list(state, (asdl_seq*)o->v.Set.elts, ast2obj_expr);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->elts, value) == -1)
             goto failed;
@@ -9562,13 +9510,12 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->ListComp_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.ListComp.elt);
+        value = ast2obj_expr(state, o->v.ListComp.elt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->elt, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate,
-                             (asdl_seq*)o->v.ListComp.generators,
+        value = ast2obj_list(state, (asdl_seq*)o->v.ListComp.generators,
                              ast2obj_comprehension);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->generators, value) == -1)
@@ -9579,12 +9526,12 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->SetComp_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.SetComp.elt);
+        value = ast2obj_expr(state, o->v.SetComp.elt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->elt, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.SetComp.generators,
+        value = ast2obj_list(state, (asdl_seq*)o->v.SetComp.generators,
                              ast2obj_comprehension);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->generators, value) == -1)
@@ -9595,18 +9542,17 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->DictComp_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.DictComp.key);
+        value = ast2obj_expr(state, o->v.DictComp.key);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->key, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.DictComp.value);
+        value = ast2obj_expr(state, o->v.DictComp.value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->value, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate,
-                             (asdl_seq*)o->v.DictComp.generators,
+        value = ast2obj_list(state, (asdl_seq*)o->v.DictComp.generators,
                              ast2obj_comprehension);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->generators, value) == -1)
@@ -9617,13 +9563,12 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->GeneratorExp_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.GeneratorExp.elt);
+        value = ast2obj_expr(state, o->v.GeneratorExp.elt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->elt, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate,
-                             (asdl_seq*)o->v.GeneratorExp.generators,
+        value = ast2obj_list(state, (asdl_seq*)o->v.GeneratorExp.generators,
                              ast2obj_comprehension);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->generators, value) == -1)
@@ -9634,7 +9579,7 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Await_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.Await.value);
+        value = ast2obj_expr(state, o->v.Await.value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->value, value) == -1)
             goto failed;
@@ -9644,7 +9589,7 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Yield_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.Yield.value);
+        value = ast2obj_expr(state, o->v.Yield.value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->value, value) == -1)
             goto failed;
@@ -9654,7 +9599,7 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->YieldFrom_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.YieldFrom.value);
+        value = ast2obj_expr(state, o->v.YieldFrom.value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->value, value) == -1)
             goto failed;
@@ -9664,7 +9609,7 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Compare_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.Compare.left);
+        value = ast2obj_expr(state, o->v.Compare.left);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->left, value) == -1)
             goto failed;
@@ -9674,14 +9619,14 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
             value = PyList_New(n);
             if (!value) goto failed;
             for(i = 0; i < n; i++)
-                PyList_SET_ITEM(value, i, ast2obj_cmpop(state, vstate, (cmpop_ty)asdl_seq_GET(o->v.Compare.ops, i)));
+                PyList_SET_ITEM(value, i, ast2obj_cmpop(state, (cmpop_ty)asdl_seq_GET(o->v.Compare.ops, i)));
         }
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->ops, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate,
-                             (asdl_seq*)o->v.Compare.comparators, ast2obj_expr);
+        value = ast2obj_list(state, (asdl_seq*)o->v.Compare.comparators,
+                             ast2obj_expr);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->comparators, value) == -1)
             goto failed;
@@ -9691,18 +9636,17 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Call_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.Call.func);
+        value = ast2obj_expr(state, o->v.Call.func);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->func, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Call.args,
-                             ast2obj_expr);
+        value = ast2obj_list(state, (asdl_seq*)o->v.Call.args, ast2obj_expr);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->args, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Call.keywords,
+        value = ast2obj_list(state, (asdl_seq*)o->v.Call.keywords,
                              ast2obj_keyword);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->keywords, value) == -1)
@@ -9713,17 +9657,17 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->FormattedValue_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.FormattedValue.value);
+        value = ast2obj_expr(state, o->v.FormattedValue.value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->value, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_int(state, vstate, o->v.FormattedValue.conversion);
+        value = ast2obj_int(state, o->v.FormattedValue.conversion);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->conversion, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.FormattedValue.format_spec);
+        value = ast2obj_expr(state, o->v.FormattedValue.format_spec);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->format_spec, value) == -1)
             goto failed;
@@ -9733,7 +9677,7 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->JoinedStr_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.JoinedStr.values,
+        value = ast2obj_list(state, (asdl_seq*)o->v.JoinedStr.values,
                              ast2obj_expr);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->values, value) == -1)
@@ -9744,12 +9688,12 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Constant_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_constant(state, vstate, o->v.Constant.value);
+        value = ast2obj_constant(state, o->v.Constant.value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->value, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_string(state, vstate, o->v.Constant.kind);
+        value = ast2obj_string(state, o->v.Constant.kind);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->kind, value) == -1)
             goto failed;
@@ -9759,17 +9703,17 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Attribute_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.Attribute.value);
+        value = ast2obj_expr(state, o->v.Attribute.value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->value, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_identifier(state, vstate, o->v.Attribute.attr);
+        value = ast2obj_identifier(state, o->v.Attribute.attr);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->attr, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr_context(state, vstate, o->v.Attribute.ctx);
+        value = ast2obj_expr_context(state, o->v.Attribute.ctx);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->ctx, value) == -1)
             goto failed;
@@ -9779,17 +9723,17 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Subscript_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.Subscript.value);
+        value = ast2obj_expr(state, o->v.Subscript.value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->value, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.Subscript.slice);
+        value = ast2obj_expr(state, o->v.Subscript.slice);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->slice, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr_context(state, vstate, o->v.Subscript.ctx);
+        value = ast2obj_expr_context(state, o->v.Subscript.ctx);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->ctx, value) == -1)
             goto failed;
@@ -9799,12 +9743,12 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Starred_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.Starred.value);
+        value = ast2obj_expr(state, o->v.Starred.value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->value, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr_context(state, vstate, o->v.Starred.ctx);
+        value = ast2obj_expr_context(state, o->v.Starred.ctx);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->ctx, value) == -1)
             goto failed;
@@ -9814,12 +9758,12 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Name_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_identifier(state, vstate, o->v.Name.id);
+        value = ast2obj_identifier(state, o->v.Name.id);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->id, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr_context(state, vstate, o->v.Name.ctx);
+        value = ast2obj_expr_context(state, o->v.Name.ctx);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->ctx, value) == -1)
             goto failed;
@@ -9829,13 +9773,12 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->List_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.List.elts,
-                             ast2obj_expr);
+        value = ast2obj_list(state, (asdl_seq*)o->v.List.elts, ast2obj_expr);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->elts, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr_context(state, vstate, o->v.List.ctx);
+        value = ast2obj_expr_context(state, o->v.List.ctx);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->ctx, value) == -1)
             goto failed;
@@ -9845,13 +9788,12 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Tuple_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.Tuple.elts,
-                             ast2obj_expr);
+        value = ast2obj_list(state, (asdl_seq*)o->v.Tuple.elts, ast2obj_expr);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->elts, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr_context(state, vstate, o->v.Tuple.ctx);
+        value = ast2obj_expr_context(state, o->v.Tuple.ctx);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->ctx, value) == -1)
             goto failed;
@@ -9861,54 +9803,53 @@ ast2obj_expr(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->Slice_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.Slice.lower);
+        value = ast2obj_expr(state, o->v.Slice.lower);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->lower, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.Slice.upper);
+        value = ast2obj_expr(state, o->v.Slice.upper);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->upper, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.Slice.step);
+        value = ast2obj_expr(state, o->v.Slice.step);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->step, value) == -1)
             goto failed;
         Py_DECREF(value);
         break;
     }
-    value = ast2obj_int(state, vstate, o->lineno);
+    value = ast2obj_int(state, o->lineno);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->lineno, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->col_offset);
+    value = ast2obj_int(state, o->col_offset);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->col_offset, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->end_lineno);
+    value = ast2obj_int(state, o->end_lineno);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->end_lineno, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->end_col_offset);
+    value = ast2obj_int(state, o->end_col_offset);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)
         goto failed;
     Py_DECREF(value);
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     return result;
 failed:
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     Py_XDECREF(value);
     Py_XDECREF(result);
     return NULL;
 }
 
-PyObject* ast2obj_expr_context(struct ast_state *state, struct validator
-                               *vstate, expr_context_ty o)
+PyObject* ast2obj_expr_context(struct ast_state *state, expr_context_ty o)
 {
     switch(o) {
         case Load:
@@ -9920,8 +9861,7 @@ PyObject* ast2obj_expr_context(struct ast_state *state, struct validator
     }
     Py_UNREACHABLE();
 }
-PyObject* ast2obj_boolop(struct ast_state *state, struct validator *vstate,
-                         boolop_ty o)
+PyObject* ast2obj_boolop(struct ast_state *state, boolop_ty o)
 {
     switch(o) {
         case And:
@@ -9931,8 +9871,7 @@ PyObject* ast2obj_boolop(struct ast_state *state, struct validator *vstate,
     }
     Py_UNREACHABLE();
 }
-PyObject* ast2obj_operator(struct ast_state *state, struct validator *vstate,
-                           operator_ty o)
+PyObject* ast2obj_operator(struct ast_state *state, operator_ty o)
 {
     switch(o) {
         case Add:
@@ -9964,8 +9903,7 @@ PyObject* ast2obj_operator(struct ast_state *state, struct validator *vstate,
     }
     Py_UNREACHABLE();
 }
-PyObject* ast2obj_unaryop(struct ast_state *state, struct validator *vstate,
-                          unaryop_ty o)
+PyObject* ast2obj_unaryop(struct ast_state *state, unaryop_ty o)
 {
     switch(o) {
         case Invert:
@@ -9979,8 +9917,7 @@ PyObject* ast2obj_unaryop(struct ast_state *state, struct validator *vstate,
     }
     Py_UNREACHABLE();
 }
-PyObject* ast2obj_cmpop(struct ast_state *state, struct validator *vstate,
-                        cmpop_ty o)
+PyObject* ast2obj_cmpop(struct ast_state *state, cmpop_ty o)
 {
     switch(o) {
         case Eq:
@@ -10007,8 +9944,7 @@ PyObject* ast2obj_cmpop(struct ast_state *state, struct validator *vstate,
     Py_UNREACHABLE();
 }
 PyObject*
-ast2obj_comprehension(struct ast_state *state, struct validator *vstate, void*
-                      _o)
+ast2obj_comprehension(struct ast_state *state, void* _o)
 {
     comprehension_ty o = (comprehension_ty)_o;
     PyObject *result = NULL, *value = NULL;
@@ -10016,46 +9952,43 @@ ast2obj_comprehension(struct ast_state *state, struct validator *vstate, void*
     if (!o) {
         Py_RETURN_NONE;
     }
-    if (++vstate->recursion_depth > vstate->recursion_limit) {
-        PyErr_SetString(PyExc_RecursionError,
-            "maximum recursion depth exceeded during ast construction");
+    if (Py_EnterRecursiveCall("during  ast construction")) {
         return NULL;
     }
     tp = (PyTypeObject *)state->comprehension_type;
     result = PyType_GenericNew(tp, NULL, NULL);
     if (!result) return NULL;
-    value = ast2obj_expr(state, vstate, o->target);
+    value = ast2obj_expr(state, o->target);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->target, value) == -1)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_expr(state, vstate, o->iter);
+    value = ast2obj_expr(state, o->iter);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->iter, value) == -1)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_list(state, vstate, (asdl_seq*)o->ifs, ast2obj_expr);
+    value = ast2obj_list(state, (asdl_seq*)o->ifs, ast2obj_expr);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->ifs, value) == -1)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->is_async);
+    value = ast2obj_int(state, o->is_async);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->is_async, value) == -1)
         goto failed;
     Py_DECREF(value);
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     return result;
 failed:
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     Py_XDECREF(value);
     Py_XDECREF(result);
     return NULL;
 }
 
 PyObject*
-ast2obj_excepthandler(struct ast_state *state, struct validator *vstate, void*
-                      _o)
+ast2obj_excepthandler(struct ast_state *state, void* _o)
 {
     excepthandler_ty o = (excepthandler_ty)_o;
     PyObject *result = NULL, *value = NULL;
@@ -10063,9 +9996,7 @@ ast2obj_excepthandler(struct ast_state *state, struct validator *vstate, void*
     if (!o) {
         Py_RETURN_NONE;
     }
-    if (++vstate->recursion_depth > vstate->recursion_limit) {
-        PyErr_SetString(PyExc_RecursionError,
-            "maximum recursion depth exceeded during ast construction");
+    if (Py_EnterRecursiveCall("during  ast construction")) {
         return NULL;
     }
     switch (o->kind) {
@@ -10073,17 +10004,17 @@ ast2obj_excepthandler(struct ast_state *state, struct validator *vstate, void*
         tp = (PyTypeObject *)state->ExceptHandler_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.ExceptHandler.type);
+        value = ast2obj_expr(state, o->v.ExceptHandler.type);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->type, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_identifier(state, vstate, o->v.ExceptHandler.name);
+        value = ast2obj_identifier(state, o->v.ExceptHandler.name);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->name, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.ExceptHandler.body,
+        value = ast2obj_list(state, (asdl_seq*)o->v.ExceptHandler.body,
                              ast2obj_stmt);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->body, value) == -1)
@@ -10091,37 +10022,37 @@ ast2obj_excepthandler(struct ast_state *state, struct validator *vstate, void*
         Py_DECREF(value);
         break;
     }
-    value = ast2obj_int(state, vstate, o->lineno);
+    value = ast2obj_int(state, o->lineno);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->lineno, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->col_offset);
+    value = ast2obj_int(state, o->col_offset);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->col_offset, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->end_lineno);
+    value = ast2obj_int(state, o->end_lineno);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->end_lineno, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->end_col_offset);
+    value = ast2obj_int(state, o->end_col_offset);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)
         goto failed;
     Py_DECREF(value);
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     return result;
 failed:
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     Py_XDECREF(value);
     Py_XDECREF(result);
     return NULL;
 }
 
 PyObject*
-ast2obj_arguments(struct ast_state *state, struct validator *vstate, void* _o)
+ast2obj_arguments(struct ast_state *state, void* _o)
 {
     arguments_ty o = (arguments_ty)_o;
     PyObject *result = NULL, *value = NULL;
@@ -10129,61 +10060,58 @@ ast2obj_arguments(struct ast_state *state, struct validator *vstate, void* _o)
     if (!o) {
         Py_RETURN_NONE;
     }
-    if (++vstate->recursion_depth > vstate->recursion_limit) {
-        PyErr_SetString(PyExc_RecursionError,
-            "maximum recursion depth exceeded during ast construction");
+    if (Py_EnterRecursiveCall("during  ast construction")) {
         return NULL;
     }
     tp = (PyTypeObject *)state->arguments_type;
     result = PyType_GenericNew(tp, NULL, NULL);
     if (!result) return NULL;
-    value = ast2obj_list(state, vstate, (asdl_seq*)o->posonlyargs, ast2obj_arg);
+    value = ast2obj_list(state, (asdl_seq*)o->posonlyargs, ast2obj_arg);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->posonlyargs, value) == -1)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_list(state, vstate, (asdl_seq*)o->args, ast2obj_arg);
+    value = ast2obj_list(state, (asdl_seq*)o->args, ast2obj_arg);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->args, value) == -1)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_arg(state, vstate, o->vararg);
+    value = ast2obj_arg(state, o->vararg);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->vararg, value) == -1)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_list(state, vstate, (asdl_seq*)o->kwonlyargs, ast2obj_arg);
+    value = ast2obj_list(state, (asdl_seq*)o->kwonlyargs, ast2obj_arg);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->kwonlyargs, value) == -1)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_list(state, vstate, (asdl_seq*)o->kw_defaults,
-                         ast2obj_expr);
+    value = ast2obj_list(state, (asdl_seq*)o->kw_defaults, ast2obj_expr);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->kw_defaults, value) == -1)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_arg(state, vstate, o->kwarg);
+    value = ast2obj_arg(state, o->kwarg);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->kwarg, value) == -1)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_list(state, vstate, (asdl_seq*)o->defaults, ast2obj_expr);
+    value = ast2obj_list(state, (asdl_seq*)o->defaults, ast2obj_expr);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->defaults, value) == -1)
         goto failed;
     Py_DECREF(value);
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     return result;
 failed:
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     Py_XDECREF(value);
     Py_XDECREF(result);
     return NULL;
 }
 
 PyObject*
-ast2obj_arg(struct ast_state *state, struct validator *vstate, void* _o)
+ast2obj_arg(struct ast_state *state, void* _o)
 {
     arg_ty o = (arg_ty)_o;
     PyObject *result = NULL, *value = NULL;
@@ -10191,60 +10119,58 @@ ast2obj_arg(struct ast_state *state, struct validator *vstate, void* _o)
     if (!o) {
         Py_RETURN_NONE;
     }
-    if (++vstate->recursion_depth > vstate->recursion_limit) {
-        PyErr_SetString(PyExc_RecursionError,
-            "maximum recursion depth exceeded during ast construction");
+    if (Py_EnterRecursiveCall("during  ast construction")) {
         return NULL;
     }
     tp = (PyTypeObject *)state->arg_type;
     result = PyType_GenericNew(tp, NULL, NULL);
     if (!result) return NULL;
-    value = ast2obj_identifier(state, vstate, o->arg);
+    value = ast2obj_identifier(state, o->arg);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->arg, value) == -1)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_expr(state, vstate, o->annotation);
+    value = ast2obj_expr(state, o->annotation);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->annotation, value) == -1)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_string(state, vstate, o->type_comment);
+    value = ast2obj_string(state, o->type_comment);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->type_comment, value) == -1)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->lineno);
+    value = ast2obj_int(state, o->lineno);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->lineno, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->col_offset);
+    value = ast2obj_int(state, o->col_offset);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->col_offset, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->end_lineno);
+    value = ast2obj_int(state, o->end_lineno);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->end_lineno, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->end_col_offset);
+    value = ast2obj_int(state, o->end_col_offset);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)
         goto failed;
     Py_DECREF(value);
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     return result;
 failed:
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     Py_XDECREF(value);
     Py_XDECREF(result);
     return NULL;
 }
 
 PyObject*
-ast2obj_keyword(struct ast_state *state, struct validator *vstate, void* _o)
+ast2obj_keyword(struct ast_state *state, void* _o)
 {
     keyword_ty o = (keyword_ty)_o;
     PyObject *result = NULL, *value = NULL;
@@ -10252,55 +10178,53 @@ ast2obj_keyword(struct ast_state *state, struct validator *vstate, void* _o)
     if (!o) {
         Py_RETURN_NONE;
     }
-    if (++vstate->recursion_depth > vstate->recursion_limit) {
-        PyErr_SetString(PyExc_RecursionError,
-            "maximum recursion depth exceeded during ast construction");
+    if (Py_EnterRecursiveCall("during  ast construction")) {
         return NULL;
     }
     tp = (PyTypeObject *)state->keyword_type;
     result = PyType_GenericNew(tp, NULL, NULL);
     if (!result) return NULL;
-    value = ast2obj_identifier(state, vstate, o->arg);
+    value = ast2obj_identifier(state, o->arg);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->arg, value) == -1)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_expr(state, vstate, o->value);
+    value = ast2obj_expr(state, o->value);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->value, value) == -1)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->lineno);
+    value = ast2obj_int(state, o->lineno);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->lineno, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->col_offset);
+    value = ast2obj_int(state, o->col_offset);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->col_offset, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->end_lineno);
+    value = ast2obj_int(state, o->end_lineno);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->end_lineno, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->end_col_offset);
+    value = ast2obj_int(state, o->end_col_offset);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)
         goto failed;
     Py_DECREF(value);
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     return result;
 failed:
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     Py_XDECREF(value);
     Py_XDECREF(result);
     return NULL;
 }
 
 PyObject*
-ast2obj_alias(struct ast_state *state, struct validator *vstate, void* _o)
+ast2obj_alias(struct ast_state *state, void* _o)
 {
     alias_ty o = (alias_ty)_o;
     PyObject *result = NULL, *value = NULL;
@@ -10308,55 +10232,53 @@ ast2obj_alias(struct ast_state *state, struct validator *vstate, void* _o)
     if (!o) {
         Py_RETURN_NONE;
     }
-    if (++vstate->recursion_depth > vstate->recursion_limit) {
-        PyErr_SetString(PyExc_RecursionError,
-            "maximum recursion depth exceeded during ast construction");
+    if (Py_EnterRecursiveCall("during  ast construction")) {
         return NULL;
     }
     tp = (PyTypeObject *)state->alias_type;
     result = PyType_GenericNew(tp, NULL, NULL);
     if (!result) return NULL;
-    value = ast2obj_identifier(state, vstate, o->name);
+    value = ast2obj_identifier(state, o->name);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->name, value) == -1)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_identifier(state, vstate, o->asname);
+    value = ast2obj_identifier(state, o->asname);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->asname, value) == -1)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->lineno);
+    value = ast2obj_int(state, o->lineno);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->lineno, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->col_offset);
+    value = ast2obj_int(state, o->col_offset);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->col_offset, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->end_lineno);
+    value = ast2obj_int(state, o->end_lineno);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->end_lineno, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->end_col_offset);
+    value = ast2obj_int(state, o->end_col_offset);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)
         goto failed;
     Py_DECREF(value);
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     return result;
 failed:
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     Py_XDECREF(value);
     Py_XDECREF(result);
     return NULL;
 }
 
 PyObject*
-ast2obj_withitem(struct ast_state *state, struct validator *vstate, void* _o)
+ast2obj_withitem(struct ast_state *state, void* _o)
 {
     withitem_ty o = (withitem_ty)_o;
     PyObject *result = NULL, *value = NULL;
@@ -10364,35 +10286,33 @@ ast2obj_withitem(struct ast_state *state, struct validator *vstate, void* _o)
     if (!o) {
         Py_RETURN_NONE;
     }
-    if (++vstate->recursion_depth > vstate->recursion_limit) {
-        PyErr_SetString(PyExc_RecursionError,
-            "maximum recursion depth exceeded during ast construction");
+    if (Py_EnterRecursiveCall("during  ast construction")) {
         return NULL;
     }
     tp = (PyTypeObject *)state->withitem_type;
     result = PyType_GenericNew(tp, NULL, NULL);
     if (!result) return NULL;
-    value = ast2obj_expr(state, vstate, o->context_expr);
+    value = ast2obj_expr(state, o->context_expr);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->context_expr, value) == -1)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_expr(state, vstate, o->optional_vars);
+    value = ast2obj_expr(state, o->optional_vars);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->optional_vars, value) == -1)
         goto failed;
     Py_DECREF(value);
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     return result;
 failed:
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     Py_XDECREF(value);
     Py_XDECREF(result);
     return NULL;
 }
 
 PyObject*
-ast2obj_match_case(struct ast_state *state, struct validator *vstate, void* _o)
+ast2obj_match_case(struct ast_state *state, void* _o)
 {
     match_case_ty o = (match_case_ty)_o;
     PyObject *result = NULL, *value = NULL;
@@ -10400,40 +10320,38 @@ ast2obj_match_case(struct ast_state *state, struct validator *vstate, void* _o)
     if (!o) {
         Py_RETURN_NONE;
     }
-    if (++vstate->recursion_depth > vstate->recursion_limit) {
-        PyErr_SetString(PyExc_RecursionError,
-            "maximum recursion depth exceeded during ast construction");
+    if (Py_EnterRecursiveCall("during  ast construction")) {
         return NULL;
     }
     tp = (PyTypeObject *)state->match_case_type;
     result = PyType_GenericNew(tp, NULL, NULL);
     if (!result) return NULL;
-    value = ast2obj_pattern(state, vstate, o->pattern);
+    value = ast2obj_pattern(state, o->pattern);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->pattern, value) == -1)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_expr(state, vstate, o->guard);
+    value = ast2obj_expr(state, o->guard);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->guard, value) == -1)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_list(state, vstate, (asdl_seq*)o->body, ast2obj_stmt);
+    value = ast2obj_list(state, (asdl_seq*)o->body, ast2obj_stmt);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->body, value) == -1)
         goto failed;
     Py_DECREF(value);
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     return result;
 failed:
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     Py_XDECREF(value);
     Py_XDECREF(result);
     return NULL;
 }
 
 PyObject*
-ast2obj_pattern(struct ast_state *state, struct validator *vstate, void* _o)
+ast2obj_pattern(struct ast_state *state, void* _o)
 {
     pattern_ty o = (pattern_ty)_o;
     PyObject *result = NULL, *value = NULL;
@@ -10441,9 +10359,7 @@ ast2obj_pattern(struct ast_state *state, struct validator *vstate, void* _o)
     if (!o) {
         Py_RETURN_NONE;
     }
-    if (++vstate->recursion_depth > vstate->recursion_limit) {
-        PyErr_SetString(PyExc_RecursionError,
-            "maximum recursion depth exceeded during ast construction");
+    if (Py_EnterRecursiveCall("during  ast construction")) {
         return NULL;
     }
     switch (o->kind) {
@@ -10451,7 +10367,7 @@ ast2obj_pattern(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->MatchValue_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.MatchValue.value);
+        value = ast2obj_expr(state, o->v.MatchValue.value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->value, value) == -1)
             goto failed;
@@ -10461,7 +10377,7 @@ ast2obj_pattern(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->MatchSingleton_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_constant(state, vstate, o->v.MatchSingleton.value);
+        value = ast2obj_constant(state, o->v.MatchSingleton.value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->value, value) == -1)
             goto failed;
@@ -10471,8 +10387,7 @@ ast2obj_pattern(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->MatchSequence_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate,
-                             (asdl_seq*)o->v.MatchSequence.patterns,
+        value = ast2obj_list(state, (asdl_seq*)o->v.MatchSequence.patterns,
                              ast2obj_pattern);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->patterns, value) == -1)
@@ -10483,20 +10398,19 @@ ast2obj_pattern(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->MatchMapping_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.MatchMapping.keys,
+        value = ast2obj_list(state, (asdl_seq*)o->v.MatchMapping.keys,
                              ast2obj_expr);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->keys, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate,
-                             (asdl_seq*)o->v.MatchMapping.patterns,
+        value = ast2obj_list(state, (asdl_seq*)o->v.MatchMapping.patterns,
                              ast2obj_pattern);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->patterns, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_identifier(state, vstate, o->v.MatchMapping.rest);
+        value = ast2obj_identifier(state, o->v.MatchMapping.rest);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->rest, value) == -1)
             goto failed;
@@ -10506,27 +10420,24 @@ ast2obj_pattern(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->MatchClass_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_expr(state, vstate, o->v.MatchClass.cls);
+        value = ast2obj_expr(state, o->v.MatchClass.cls);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->cls, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate,
-                             (asdl_seq*)o->v.MatchClass.patterns,
+        value = ast2obj_list(state, (asdl_seq*)o->v.MatchClass.patterns,
                              ast2obj_pattern);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->patterns, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate,
-                             (asdl_seq*)o->v.MatchClass.kwd_attrs,
+        value = ast2obj_list(state, (asdl_seq*)o->v.MatchClass.kwd_attrs,
                              ast2obj_identifier);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->kwd_attrs, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_list(state, vstate,
-                             (asdl_seq*)o->v.MatchClass.kwd_patterns,
+        value = ast2obj_list(state, (asdl_seq*)o->v.MatchClass.kwd_patterns,
                              ast2obj_pattern);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->kwd_patterns, value) == -1)
@@ -10537,7 +10448,7 @@ ast2obj_pattern(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->MatchStar_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_identifier(state, vstate, o->v.MatchStar.name);
+        value = ast2obj_identifier(state, o->v.MatchStar.name);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->name, value) == -1)
             goto failed;
@@ -10547,12 +10458,12 @@ ast2obj_pattern(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->MatchAs_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_pattern(state, vstate, o->v.MatchAs.pattern);
+        value = ast2obj_pattern(state, o->v.MatchAs.pattern);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->pattern, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_identifier(state, vstate, o->v.MatchAs.name);
+        value = ast2obj_identifier(state, o->v.MatchAs.name);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->name, value) == -1)
             goto failed;
@@ -10562,7 +10473,7 @@ ast2obj_pattern(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->MatchOr_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_list(state, vstate, (asdl_seq*)o->v.MatchOr.patterns,
+        value = ast2obj_list(state, (asdl_seq*)o->v.MatchOr.patterns,
                              ast2obj_pattern);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->patterns, value) == -1)
@@ -10570,37 +10481,37 @@ ast2obj_pattern(struct ast_state *state, struct validator *vstate, void* _o)
         Py_DECREF(value);
         break;
     }
-    value = ast2obj_int(state, vstate, o->lineno);
+    value = ast2obj_int(state, o->lineno);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->lineno, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->col_offset);
+    value = ast2obj_int(state, o->col_offset);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->col_offset, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->end_lineno);
+    value = ast2obj_int(state, o->end_lineno);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->end_lineno, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->end_col_offset);
+    value = ast2obj_int(state, o->end_col_offset);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)
         goto failed;
     Py_DECREF(value);
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     return result;
 failed:
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     Py_XDECREF(value);
     Py_XDECREF(result);
     return NULL;
 }
 
 PyObject*
-ast2obj_type_ignore(struct ast_state *state, struct validator *vstate, void* _o)
+ast2obj_type_ignore(struct ast_state *state, void* _o)
 {
     type_ignore_ty o = (type_ignore_ty)_o;
     PyObject *result = NULL, *value = NULL;
@@ -10608,9 +10519,7 @@ ast2obj_type_ignore(struct ast_state *state, struct validator *vstate, void* _o)
     if (!o) {
         Py_RETURN_NONE;
     }
-    if (++vstate->recursion_depth > vstate->recursion_limit) {
-        PyErr_SetString(PyExc_RecursionError,
-            "maximum recursion depth exceeded during ast construction");
+    if (Py_EnterRecursiveCall("during  ast construction")) {
         return NULL;
     }
     switch (o->kind) {
@@ -10618,29 +10527,29 @@ ast2obj_type_ignore(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->TypeIgnore_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_int(state, vstate, o->v.TypeIgnore.lineno);
+        value = ast2obj_int(state, o->v.TypeIgnore.lineno);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->lineno, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_string(state, vstate, o->v.TypeIgnore.tag);
+        value = ast2obj_string(state, o->v.TypeIgnore.tag);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->tag, value) == -1)
             goto failed;
         Py_DECREF(value);
         break;
     }
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     return result;
 failed:
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     Py_XDECREF(value);
     Py_XDECREF(result);
     return NULL;
 }
 
 PyObject*
-ast2obj_type_param(struct ast_state *state, struct validator *vstate, void* _o)
+ast2obj_type_param(struct ast_state *state, void* _o)
 {
     type_param_ty o = (type_param_ty)_o;
     PyObject *result = NULL, *value = NULL;
@@ -10648,9 +10557,7 @@ ast2obj_type_param(struct ast_state *state, struct validator *vstate, void* _o)
     if (!o) {
         Py_RETURN_NONE;
     }
-    if (++vstate->recursion_depth > vstate->recursion_limit) {
-        PyErr_SetString(PyExc_RecursionError,
-            "maximum recursion depth exceeded during ast construction");
+    if (Py_EnterRecursiveCall("during  ast construction")) {
         return NULL;
     }
     switch (o->kind) {
@@ -10658,17 +10565,17 @@ ast2obj_type_param(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->TypeVar_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_identifier(state, vstate, o->v.TypeVar.name);
+        value = ast2obj_identifier(state, o->v.TypeVar.name);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->name, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.TypeVar.bound);
+        value = ast2obj_expr(state, o->v.TypeVar.bound);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->bound, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.TypeVar.default_value);
+        value = ast2obj_expr(state, o->v.TypeVar.default_value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->default_value, value) == -1)
             goto failed;
@@ -10678,12 +10585,12 @@ ast2obj_type_param(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->ParamSpec_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_identifier(state, vstate, o->v.ParamSpec.name);
+        value = ast2obj_identifier(state, o->v.ParamSpec.name);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->name, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.ParamSpec.default_value);
+        value = ast2obj_expr(state, o->v.ParamSpec.default_value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->default_value, value) == -1)
             goto failed;
@@ -10693,42 +10600,42 @@ ast2obj_type_param(struct ast_state *state, struct validator *vstate, void* _o)
         tp = (PyTypeObject *)state->TypeVarTuple_type;
         result = PyType_GenericNew(tp, NULL, NULL);
         if (!result) goto failed;
-        value = ast2obj_identifier(state, vstate, o->v.TypeVarTuple.name);
+        value = ast2obj_identifier(state, o->v.TypeVarTuple.name);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->name, value) == -1)
             goto failed;
         Py_DECREF(value);
-        value = ast2obj_expr(state, vstate, o->v.TypeVarTuple.default_value);
+        value = ast2obj_expr(state, o->v.TypeVarTuple.default_value);
         if (!value) goto failed;
         if (PyObject_SetAttr(result, state->default_value, value) == -1)
             goto failed;
         Py_DECREF(value);
         break;
     }
-    value = ast2obj_int(state, vstate, o->lineno);
+    value = ast2obj_int(state, o->lineno);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->lineno, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->col_offset);
+    value = ast2obj_int(state, o->col_offset);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->col_offset, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->end_lineno);
+    value = ast2obj_int(state, o->end_lineno);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->end_lineno, value) < 0)
         goto failed;
     Py_DECREF(value);
-    value = ast2obj_int(state, vstate, o->end_col_offset);
+    value = ast2obj_int(state, o->end_col_offset);
     if (!value) goto failed;
     if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)
         goto failed;
     Py_DECREF(value);
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     return result;
 failed:
-    vstate->recursion_depth--;
+    Py_LeaveRecursiveCall();
     Py_XDECREF(value);
     Py_XDECREF(result);
     return NULL;
@@ -18135,28 +18042,8 @@ PyObject* PyAST_mod2obj(mod_ty t)
     if (state == NULL) {
         return NULL;
     }
+    PyObject *result = ast2obj_mod(state, t);
 
-    int starting_recursion_depth;
-    /* Be careful here to prevent overflow. */
-    PyThreadState *tstate = _PyThreadState_GET();
-    if (!tstate) {
-        return NULL;
-    }
-    struct validator vstate;
-    vstate.recursion_limit = Py_C_RECURSION_LIMIT;
-    int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining;
-    starting_recursion_depth = recursion_depth;
-    vstate.recursion_depth = starting_recursion_depth;
-
-    PyObject *result = ast2obj_mod(state, &vstate, t);
-
-    /* Check that the recursion depth counting balanced correctly */
-    if (result && vstate.recursion_depth != starting_recursion_depth) {
-        PyErr_Format(PyExc_SystemError,
-            "AST constructor recursion depth mismatch (before=%d, after=%d)",
-            starting_recursion_depth, vstate.recursion_depth);
-        return NULL;
-    }
     return result;
 }
 
index bf1ff5f3ec18baf24d758c33b4881c06781b17d7..597df5b63b5f394abff9aa75049a4754eb592748 100644 (file)
@@ -9,34 +9,22 @@
 #include <assert.h>
 #include <stdbool.h>
 
-struct validator {
-    int recursion_depth;            /* current recursion depth */
-    int recursion_limit;            /* recursion limit */
-};
-
-#define ENTER_RECURSIVE(ST) \
-    do { \
-        if (++(ST)->recursion_depth > (ST)->recursion_limit) { \
-            PyErr_SetString(PyExc_RecursionError, \
-                "maximum recursion depth exceeded during compilation"); \
-            return 0; \
-        } \
-    } while(0)
+#define ENTER_RECURSIVE() \
+if (Py_EnterRecursiveCall(" during compilation")) { \
+    return 0; \
+}
 
-#define LEAVE_RECURSIVE(ST) \
-    do { \
-        --(ST)->recursion_depth; \
-    } while(0)
+#define LEAVE_RECURSIVE() Py_LeaveRecursiveCall();
 
-static int validate_stmts(struct validator *, asdl_stmt_seq *);
-static int validate_exprs(struct validator *, asdl_expr_seq *, expr_context_ty, int);
-static int validate_patterns(struct validator *, asdl_pattern_seq *, int);
-static int validate_type_params(struct validator *, asdl_type_param_seq *);
+static int validate_stmts(asdl_stmt_seq *);
+static int validate_exprs(asdl_expr_seq *, expr_context_ty, int);
+static int validate_patterns(asdl_pattern_seq *, int);
+static int validate_type_params(asdl_type_param_seq *);
 static int _validate_nonempty_seq(asdl_seq *, const char *, const char *);
-static int validate_stmt(struct validator *, stmt_ty);
-static int validate_expr(struct validator *, expr_ty, expr_context_ty);
-static int validate_pattern(struct validator *, pattern_ty, int);
-static int validate_typeparam(struct validator *, type_param_ty);
+static int validate_stmt(stmt_ty);
+static int validate_expr(expr_ty, expr_context_ty);
+static int validate_pattern(pattern_ty, int);
+static int validate_typeparam(type_param_ty);
 
 #define VALIDATE_POSITIONS(node) \
     if (node->lineno > node->end_lineno) { \
@@ -80,7 +68,7 @@ validate_name(PyObject *name)
 }
 
 static int
-validate_comprehension(struct validator *state, asdl_comprehension_seq *gens)
+validate_comprehension(asdl_comprehension_seq *gens)
 {
     assert(!PyErr_Occurred());
     if (!asdl_seq_LEN(gens)) {
@@ -89,32 +77,32 @@ validate_comprehension(struct validator *state, asdl_comprehension_seq *gens)
     }
     for (Py_ssize_t i = 0; i < asdl_seq_LEN(gens); i++) {
         comprehension_ty comp = asdl_seq_GET(gens, i);
-        if (!validate_expr(state, comp->target, Store) ||
-            !validate_expr(state, comp->iter, Load) ||
-            !validate_exprs(state, comp->ifs, Load, 0))
+        if (!validate_expr(comp->target, Store) ||
+            !validate_expr(comp->iter, Load) ||
+            !validate_exprs(comp->ifs, Load, 0))
             return 0;
     }
     return 1;
 }
 
 static int
-validate_keywords(struct validator *state, asdl_keyword_seq *keywords)
+validate_keywords(asdl_keyword_seq *keywords)
 {
     assert(!PyErr_Occurred());
     for (Py_ssize_t i = 0; i < asdl_seq_LEN(keywords); i++)
-        if (!validate_expr(state, (asdl_seq_GET(keywords, i))->value, Load))
+        if (!validate_expr((asdl_seq_GET(keywords, i))->value, Load))
             return 0;
     return 1;
 }
 
 static int
-validate_args(struct validator *state, asdl_arg_seq *args)
+validate_args(asdl_arg_seq *args)
 {
     assert(!PyErr_Occurred());
     for (Py_ssize_t i = 0; i < asdl_seq_LEN(args); i++) {
         arg_ty arg = asdl_seq_GET(args, i);
         VALIDATE_POSITIONS(arg);
-        if (arg->annotation && !validate_expr(state, arg->annotation, Load))
+        if (arg->annotation && !validate_expr(arg->annotation, Load))
             return 0;
     }
     return 1;
@@ -136,20 +124,20 @@ expr_context_name(expr_context_ty ctx)
 }
 
 static int
-validate_arguments(struct validator *state, arguments_ty args)
+validate_arguments(arguments_ty args)
 {
     assert(!PyErr_Occurred());
-    if (!validate_args(state, args->posonlyargs) || !validate_args(state, args->args)) {
+    if (!validate_args(args->posonlyargs) || !validate_args(args->args)) {
         return 0;
     }
     if (args->vararg && args->vararg->annotation
-        && !validate_expr(state, args->vararg->annotation, Load)) {
+        && !validate_expr(args->vararg->annotation, Load)) {
             return 0;
     }
-    if (!validate_args(state, args->kwonlyargs))
+    if (!validate_args(args->kwonlyargs))
         return 0;
     if (args->kwarg && args->kwarg->annotation
-        && !validate_expr(state, args->kwarg->annotation, Load)) {
+        && !validate_expr(args->kwarg->annotation, Load)) {
             return 0;
     }
     if (asdl_seq_LEN(args->defaults) > asdl_seq_LEN(args->posonlyargs) + asdl_seq_LEN(args->args)) {
@@ -161,11 +149,11 @@ validate_arguments(struct validator *state, arguments_ty args)
                         "kw_defaults on arguments");
         return 0;
     }
-    return validate_exprs(state, args->defaults, Load, 0) && validate_exprs(state, args->kw_defaults, Load, 1);
+    return validate_exprs(args->defaults, Load, 0) && validate_exprs(args->kw_defaults, Load, 1);
 }
 
 static int
-validate_constant(struct validator *state, PyObject *value)
+validate_constant(PyObject *value)
 {
     assert(!PyErr_Occurred());
     if (value == Py_None || value == Py_Ellipsis)
@@ -180,7 +168,7 @@ validate_constant(struct validator *state, PyObject *value)
         return 1;
 
     if (PyTuple_CheckExact(value) || PyFrozenSet_CheckExact(value)) {
-        ENTER_RECURSIVE(state);
+        ENTER_RECURSIVE();
 
         PyObject *it = PyObject_GetIter(value);
         if (it == NULL)
@@ -196,7 +184,7 @@ validate_constant(struct validator *state, PyObject *value)
                 break;
             }
 
-            if (!validate_constant(state, item)) {
+            if (!validate_constant(item)) {
                 Py_DECREF(it);
                 Py_DECREF(item);
                 return 0;
@@ -205,7 +193,7 @@ validate_constant(struct validator *state, PyObject *value)
         }
 
         Py_DECREF(it);
-        LEAVE_RECURSIVE(state);
+        LEAVE_RECURSIVE();
         return 1;
     }
 
@@ -218,12 +206,12 @@ validate_constant(struct validator *state, PyObject *value)
 }
 
 static int
-validate_expr(struct validator *state, expr_ty exp, expr_context_ty ctx)
+validate_expr(expr_ty exp, expr_context_ty ctx)
 {
     assert(!PyErr_Occurred());
     VALIDATE_POSITIONS(exp);
     int ret = -1;
-    ENTER_RECURSIVE(state);
+    ENTER_RECURSIVE();
     int check_ctx = 1;
     expr_context_ty actual_ctx;
 
@@ -273,23 +261,23 @@ validate_expr(struct validator *state, expr_ty exp, expr_context_ty ctx)
             PyErr_SetString(PyExc_ValueError, "BoolOp with less than 2 values");
             return 0;
         }
-        ret = validate_exprs(state, exp->v.BoolOp.values, Load, 0);
+        ret = validate_exprs(exp->v.BoolOp.values, Load, 0);
         break;
     case BinOp_kind:
-        ret = validate_expr(state, exp->v.BinOp.left, Load) &&
-            validate_expr(state, exp->v.BinOp.right, Load);
+        ret = validate_expr(exp->v.BinOp.left, Load) &&
+            validate_expr(exp->v.BinOp.right, Load);
         break;
     case UnaryOp_kind:
-        ret = validate_expr(state, exp->v.UnaryOp.operand, Load);
+        ret = validate_expr(exp->v.UnaryOp.operand, Load);
         break;
     case Lambda_kind:
-        ret = validate_arguments(state, exp->v.Lambda.args) &&
-            validate_expr(state, exp->v.Lambda.body, Load);
+        ret = validate_arguments(exp->v.Lambda.args) &&
+            validate_expr(exp->v.Lambda.body, Load);
         break;
     case IfExp_kind:
-        ret = validate_expr(state, exp->v.IfExp.test, Load) &&
-            validate_expr(state, exp->v.IfExp.body, Load) &&
-            validate_expr(state, exp->v.IfExp.orelse, Load);
+        ret = validate_expr(exp->v.IfExp.test, Load) &&
+            validate_expr(exp->v.IfExp.body, Load) &&
+            validate_expr(exp->v.IfExp.orelse, Load);
         break;
     case Dict_kind:
         if (asdl_seq_LEN(exp->v.Dict.keys) != asdl_seq_LEN(exp->v.Dict.values)) {
@@ -299,34 +287,34 @@ validate_expr(struct validator *state, expr_ty exp, expr_context_ty ctx)
         }
         /* null_ok=1 for keys expressions to allow dict unpacking to work in
            dict literals, i.e. ``{**{a:b}}`` */
-        ret = validate_exprs(state, exp->v.Dict.keys, Load, /*null_ok=*/ 1) &&
-            validate_exprs(state, exp->v.Dict.values, Load, /*null_ok=*/ 0);
+        ret = validate_exprs(exp->v.Dict.keys, Load, /*null_ok=*/ 1) &&
+            validate_exprs(exp->v.Dict.values, Load, /*null_ok=*/ 0);
         break;
     case Set_kind:
-        ret = validate_exprs(state, exp->v.Set.elts, Load, 0);
+        ret = validate_exprs(exp->v.Set.elts, Load, 0);
         break;
 #define COMP(NAME) \
         case NAME ## _kind: \
-            ret = validate_comprehension(state, exp->v.NAME.generators) && \
-                validate_expr(state, exp->v.NAME.elt, Load); \
+            ret = validate_comprehension(exp->v.NAME.generators) && \
+                validate_expr(exp->v.NAME.elt, Load); \
             break;
     COMP(ListComp)
     COMP(SetComp)
     COMP(GeneratorExp)
 #undef COMP
     case DictComp_kind:
-        ret = validate_comprehension(state, exp->v.DictComp.generators) &&
-            validate_expr(state, exp->v.DictComp.key, Load) &&
-            validate_expr(state, exp->v.DictComp.value, Load);
+        ret = validate_comprehension(exp->v.DictComp.generators) &&
+            validate_expr(exp->v.DictComp.key, Load) &&
+            validate_expr(exp->v.DictComp.value, Load);
         break;
     case Yield_kind:
-        ret = !exp->v.Yield.value || validate_expr(state, exp->v.Yield.value, Load);
+        ret = !exp->v.Yield.value || validate_expr(exp->v.Yield.value, Load);
         break;
     case YieldFrom_kind:
-        ret = validate_expr(state, exp->v.YieldFrom.value, Load);
+        ret = validate_expr(exp->v.YieldFrom.value, Load);
         break;
     case Await_kind:
-        ret = validate_expr(state, exp->v.Await.value, Load);
+        ret = validate_expr(exp->v.Await.value, Load);
         break;
     case Compare_kind:
         if (!asdl_seq_LEN(exp->v.Compare.comparators)) {
@@ -339,52 +327,52 @@ validate_expr(struct validator *state, expr_ty exp, expr_context_ty ctx)
                             "of comparators and operands");
             return 0;
         }
-        ret = validate_exprs(state, exp->v.Compare.comparators, Load, 0) &&
-            validate_expr(state, exp->v.Compare.left, Load);
+        ret = validate_exprs(exp->v.Compare.comparators, Load, 0) &&
+            validate_expr(exp->v.Compare.left, Load);
         break;
     case Call_kind:
-        ret = validate_expr(state, exp->v.Call.func, Load) &&
-            validate_exprs(state, exp->v.Call.args, Load, 0) &&
-            validate_keywords(state, exp->v.Call.keywords);
+        ret = validate_expr(exp->v.Call.func, Load) &&
+            validate_exprs(exp->v.Call.args, Load, 0) &&
+            validate_keywords(exp->v.Call.keywords);
         break;
     case Constant_kind:
-        if (!validate_constant(state, exp->v.Constant.value)) {
+        if (!validate_constant(exp->v.Constant.value)) {
             return 0;
         }
         ret = 1;
         break;
     case JoinedStr_kind:
-        ret = validate_exprs(state, exp->v.JoinedStr.values, Load, 0);
+        ret = validate_exprs(exp->v.JoinedStr.values, Load, 0);
         break;
     case FormattedValue_kind:
-        if (validate_expr(state, exp->v.FormattedValue.value, Load) == 0)
+        if (validate_expr(exp->v.FormattedValue.value, Load) == 0)
             return 0;
         if (exp->v.FormattedValue.format_spec) {
-            ret = validate_expr(state, exp->v.FormattedValue.format_spec, Load);
+            ret = validate_expr(exp->v.FormattedValue.format_spec, Load);
             break;
         }
         ret = 1;
         break;
     case Attribute_kind:
-        ret = validate_expr(state, exp->v.Attribute.value, Load);
+        ret = validate_expr(exp->v.Attribute.value, Load);
         break;
     case Subscript_kind:
-        ret = validate_expr(state, exp->v.Subscript.slice, Load) &&
-            validate_expr(state, exp->v.Subscript.value, Load);
+        ret = validate_expr(exp->v.Subscript.slice, Load) &&
+            validate_expr(exp->v.Subscript.value, Load);
         break;
     case Starred_kind:
-        ret = validate_expr(state, exp->v.Starred.value, ctx);
+        ret = validate_expr(exp->v.Starred.value, ctx);
         break;
     case Slice_kind:
-        ret = (!exp->v.Slice.lower || validate_expr(state, exp->v.Slice.lower, Load)) &&
-            (!exp->v.Slice.upper || validate_expr(state, exp->v.Slice.upper, Load)) &&
-            (!exp->v.Slice.step || validate_expr(state, exp->v.Slice.step, Load));
+        ret = (!exp->v.Slice.lower || validate_expr(exp->v.Slice.lower, Load)) &&
+            (!exp->v.Slice.upper || validate_expr(exp->v.Slice.upper, Load)) &&
+            (!exp->v.Slice.step || validate_expr(exp->v.Slice.step, Load));
         break;
     case List_kind:
-        ret = validate_exprs(state, exp->v.List.elts, ctx, 0);
+        ret = validate_exprs(exp->v.List.elts, ctx, 0);
         break;
     case Tuple_kind:
-        ret = validate_exprs(state, exp->v.Tuple.elts, ctx, 0);
+        ret = validate_exprs(exp->v.Tuple.elts, ctx, 0);
         break;
     case NamedExpr_kind:
         if (exp->v.NamedExpr.target->kind != Name_kind) {
@@ -392,7 +380,7 @@ validate_expr(struct validator *state, expr_ty exp, expr_context_ty ctx)
                             "NamedExpr target must be a Name");
             return 0;
         }
-        ret = validate_expr(state, exp->v.NamedExpr.value, Load);
+        ret = validate_expr(exp->v.NamedExpr.value, Load);
         break;
     /* This last case doesn't have any checking. */
     case Name_kind:
@@ -404,7 +392,7 @@ validate_expr(struct validator *state, expr_ty exp, expr_context_ty ctx)
         PyErr_SetString(PyExc_SystemError, "unexpected expression");
         ret = 0;
     }
-    LEAVE_RECURSIVE(state);
+    LEAVE_RECURSIVE();
     return ret;
 }
 
@@ -480,10 +468,10 @@ ensure_literal_complex(expr_ty exp)
 }
 
 static int
-validate_pattern_match_value(struct validator *state, expr_ty exp)
+validate_pattern_match_value(expr_ty exp)
 {
     assert(!PyErr_Occurred());
-    if (!validate_expr(state, exp, Load)) {
+    if (!validate_expr(exp, Load)) {
         return 0;
     }
 
@@ -493,7 +481,7 @@ validate_pattern_match_value(struct validator *state, expr_ty exp)
             /* Ellipsis and immutable sequences are not allowed.
                For True, False and None, MatchSingleton() should
                be used */
-            if (!validate_expr(state, exp, Load)) {
+            if (!validate_expr(exp, Load)) {
                 return 0;
             }
             PyObject *literal = exp->v.Constant.value;
@@ -545,15 +533,15 @@ validate_capture(PyObject *name)
 }
 
 static int
-validate_pattern(struct validator *state, pattern_ty p, int star_ok)
+validate_pattern(pattern_ty p, int star_ok)
 {
     assert(!PyErr_Occurred());
     VALIDATE_POSITIONS(p);
     int ret = -1;
-    ENTER_RECURSIVE(state);
+    ENTER_RECURSIVE();
     switch (p->kind) {
         case MatchValue_kind:
-            ret = validate_pattern_match_value(state, p->v.MatchValue.value);
+            ret = validate_pattern_match_value(p->v.MatchValue.value);
             break;
         case MatchSingleton_kind:
             ret = p->v.MatchSingleton.value == Py_None || PyBool_Check(p->v.MatchSingleton.value);
@@ -563,7 +551,7 @@ validate_pattern(struct validator *state, pattern_ty p, int star_ok)
             }
             break;
         case MatchSequence_kind:
-            ret = validate_patterns(state, p->v.MatchSequence.patterns, /*star_ok=*/1);
+            ret = validate_patterns(p->v.MatchSequence.patterns, /*star_ok=*/1);
             break;
         case MatchMapping_kind:
             if (asdl_seq_LEN(p->v.MatchMapping.keys) != asdl_seq_LEN(p->v.MatchMapping.patterns)) {
@@ -591,7 +579,7 @@ validate_pattern(struct validator *state, pattern_ty p, int star_ok)
                         continue;
                     }
                 }
-                if (!validate_pattern_match_value(state, key)) {
+                if (!validate_pattern_match_value(key)) {
                     ret = 0;
                     break;
                 }
@@ -599,7 +587,7 @@ validate_pattern(struct validator *state, pattern_ty p, int star_ok)
             if (ret == 0) {
                 break;
             }
-            ret = validate_patterns(state, p->v.MatchMapping.patterns, /*star_ok=*/0);
+            ret = validate_patterns(p->v.MatchMapping.patterns, /*star_ok=*/0);
             break;
         case MatchClass_kind:
             if (asdl_seq_LEN(p->v.MatchClass.kwd_attrs) != asdl_seq_LEN(p->v.MatchClass.kwd_patterns)) {
@@ -608,7 +596,7 @@ validate_pattern(struct validator *state, pattern_ty p, int star_ok)
                 ret = 0;
                 break;
             }
-            if (!validate_expr(state, p->v.MatchClass.cls, Load)) {
+            if (!validate_expr(p->v.MatchClass.cls, Load)) {
                 ret = 0;
                 break;
             }
@@ -644,12 +632,12 @@ validate_pattern(struct validator *state, pattern_ty p, int star_ok)
                 break;
             }
 
-            if (!validate_patterns(state, p->v.MatchClass.patterns, /*star_ok=*/0)) {
+            if (!validate_patterns(p->v.MatchClass.patterns, /*star_ok=*/0)) {
                 ret = 0;
                 break;
             }
 
-            ret = validate_patterns(state, p->v.MatchClass.kwd_patterns, /*star_ok=*/0);
+            ret = validate_patterns(p->v.MatchClass.kwd_patterns, /*star_ok=*/0);
             break;
         case MatchStar_kind:
             if (!star_ok) {
@@ -673,7 +661,7 @@ validate_pattern(struct validator *state, pattern_ty p, int star_ok)
                 ret = 0;
             }
             else {
-                ret = validate_pattern(state, p->v.MatchAs.pattern, /*star_ok=*/0);
+                ret = validate_pattern(p->v.MatchAs.pattern, /*star_ok=*/0);
             }
             break;
         case MatchOr_kind:
@@ -683,7 +671,7 @@ validate_pattern(struct validator *state, pattern_ty p, int star_ok)
                 ret = 0;
                 break;
             }
-            ret = validate_patterns(state, p->v.MatchOr.patterns, /*star_ok=*/0);
+            ret = validate_patterns(p->v.MatchOr.patterns, /*star_ok=*/0);
             break;
     // No default case, so the compiler will emit a warning if new pattern
     // kinds are added without being handled here
@@ -692,7 +680,7 @@ validate_pattern(struct validator *state, pattern_ty p, int star_ok)
         PyErr_SetString(PyExc_SystemError, "unexpected pattern");
         ret = 0;
     }
-    LEAVE_RECURSIVE(state);
+    LEAVE_RECURSIVE();
     return ret;
 }
 
@@ -707,56 +695,56 @@ _validate_nonempty_seq(asdl_seq *seq, const char *what, const char *owner)
 #define validate_nonempty_seq(seq, what, owner) _validate_nonempty_seq((asdl_seq*)seq, what, owner)
 
 static int
-validate_assignlist(struct validator *state, asdl_expr_seq *targets, expr_context_ty ctx)
+validate_assignlist(asdl_expr_seq *targets, expr_context_ty ctx)
 {
     assert(!PyErr_Occurred());
     return validate_nonempty_seq(targets, "targets", ctx == Del ? "Delete" : "Assign") &&
-        validate_exprs(state, targets, ctx, 0);
+        validate_exprs(targets, ctx, 0);
 }
 
 static int
-validate_body(struct validator *state, asdl_stmt_seq *body, const char *owner)
+validate_body(asdl_stmt_seq *body, const char *owner)
 {
     assert(!PyErr_Occurred());
-    return validate_nonempty_seq(body, "body", owner) && validate_stmts(state, body);
+    return validate_nonempty_seq(body, "body", owner) && validate_stmts(body);
 }
 
 static int
-validate_stmt(struct validator *state, stmt_ty stmt)
+validate_stmt(stmt_ty stmt)
 {
     assert(!PyErr_Occurred());
     VALIDATE_POSITIONS(stmt);
     int ret = -1;
-    ENTER_RECURSIVE(state);
+    ENTER_RECURSIVE();
     switch (stmt->kind) {
     case FunctionDef_kind:
-        ret = validate_body(state, stmt->v.FunctionDef.body, "FunctionDef") &&
-            validate_type_params(state, stmt->v.FunctionDef.type_params) &&
-            validate_arguments(state, stmt->v.FunctionDef.args) &&
-            validate_exprs(state, stmt->v.FunctionDef.decorator_list, Load, 0) &&
+        ret = validate_body(stmt->v.FunctionDef.body, "FunctionDef") &&
+            validate_type_params(stmt->v.FunctionDef.type_params) &&
+            validate_arguments(stmt->v.FunctionDef.args) &&
+            validate_exprs(stmt->v.FunctionDef.decorator_list, Load, 0) &&
             (!stmt->v.FunctionDef.returns ||
-             validate_expr(state, stmt->v.FunctionDef.returns, Load));
+             validate_expr(stmt->v.FunctionDef.returns, Load));
         break;
     case ClassDef_kind:
-        ret = validate_body(state, stmt->v.ClassDef.body, "ClassDef") &&
-            validate_type_params(state, stmt->v.ClassDef.type_params) &&
-            validate_exprs(state, stmt->v.ClassDef.bases, Load, 0) &&
-            validate_keywords(state, stmt->v.ClassDef.keywords) &&
-            validate_exprs(state, stmt->v.ClassDef.decorator_list, Load, 0);
+        ret = validate_body(stmt->v.ClassDef.body, "ClassDef") &&
+            validate_type_params(stmt->v.ClassDef.type_params) &&
+            validate_exprs(stmt->v.ClassDef.bases, Load, 0) &&
+            validate_keywords(stmt->v.ClassDef.keywords) &&
+            validate_exprs(stmt->v.ClassDef.decorator_list, Load, 0);
         break;
     case Return_kind:
-        ret = !stmt->v.Return.value || validate_expr(state, stmt->v.Return.value, Load);
+        ret = !stmt->v.Return.value || validate_expr(stmt->v.Return.value, Load);
         break;
     case Delete_kind:
-        ret = validate_assignlist(state, stmt->v.Delete.targets, Del);
+        ret = validate_assignlist(stmt->v.Delete.targets, Del);
         break;
     case Assign_kind:
-        ret = validate_assignlist(state, stmt->v.Assign.targets, Store) &&
-            validate_expr(state, stmt->v.Assign.value, Load);
+        ret = validate_assignlist(stmt->v.Assign.targets, Store) &&
+            validate_expr(stmt->v.Assign.value, Load);
         break;
     case AugAssign_kind:
-        ret = validate_expr(state, stmt->v.AugAssign.target, Store) &&
-            validate_expr(state, stmt->v.AugAssign.value, Load);
+        ret = validate_expr(stmt->v.AugAssign.target, Store) &&
+            validate_expr(stmt->v.AugAssign.value, Load);
         break;
     case AnnAssign_kind:
         if (stmt->v.AnnAssign.target->kind != Name_kind &&
@@ -765,10 +753,10 @@ validate_stmt(struct validator *state, stmt_ty stmt)
                             "AnnAssign with simple non-Name target");
             return 0;
         }
-        ret = validate_expr(state, stmt->v.AnnAssign.target, Store) &&
+        ret = validate_expr(stmt->v.AnnAssign.target, Store) &&
                (!stmt->v.AnnAssign.value ||
-                validate_expr(state, stmt->v.AnnAssign.value, Load)) &&
-               validate_expr(state, stmt->v.AnnAssign.annotation, Load);
+                validate_expr(stmt->v.AnnAssign.value, Load)) &&
+               validate_expr(stmt->v.AnnAssign.annotation, Load);
         break;
     case TypeAlias_kind:
         if (stmt->v.TypeAlias.name->kind != Name_kind) {
@@ -776,64 +764,64 @@ validate_stmt(struct validator *state, stmt_ty stmt)
                             "TypeAlias with non-Name name");
             return 0;
         }
-        ret = validate_expr(state, stmt->v.TypeAlias.name, Store) &&
-            validate_type_params(state, stmt->v.TypeAlias.type_params) &&
-            validate_expr(state, stmt->v.TypeAlias.value, Load);
+        ret = validate_expr(stmt->v.TypeAlias.name, Store) &&
+            validate_type_params(stmt->v.TypeAlias.type_params) &&
+            validate_expr(stmt->v.TypeAlias.value, Load);
         break;
     case For_kind:
-        ret = validate_expr(state, stmt->v.For.target, Store) &&
-            validate_expr(state, stmt->v.For.iter, Load) &&
-            validate_body(state, stmt->v.For.body, "For") &&
-            validate_stmts(state, stmt->v.For.orelse);
+        ret = validate_expr(stmt->v.For.target, Store) &&
+            validate_expr(stmt->v.For.iter, Load) &&
+            validate_body(stmt->v.For.body, "For") &&
+            validate_stmts(stmt->v.For.orelse);
         break;
     case AsyncFor_kind:
-        ret = validate_expr(state, stmt->v.AsyncFor.target, Store) &&
-            validate_expr(state, stmt->v.AsyncFor.iter, Load) &&
-            validate_body(state, stmt->v.AsyncFor.body, "AsyncFor") &&
-            validate_stmts(state, stmt->v.AsyncFor.orelse);
+        ret = validate_expr(stmt->v.AsyncFor.target, Store) &&
+            validate_expr(stmt->v.AsyncFor.iter, Load) &&
+            validate_body(stmt->v.AsyncFor.body, "AsyncFor") &&
+            validate_stmts(stmt->v.AsyncFor.orelse);
         break;
     case While_kind:
-        ret = validate_expr(state, stmt->v.While.test, Load) &&
-            validate_body(state, stmt->v.While.body, "While") &&
-            validate_stmts(state, stmt->v.While.orelse);
+        ret = validate_expr(stmt->v.While.test, Load) &&
+            validate_body(stmt->v.While.body, "While") &&
+            validate_stmts(stmt->v.While.orelse);
         break;
     case If_kind:
-        ret = validate_expr(state, stmt->v.If.test, Load) &&
-            validate_body(state, stmt->v.If.body, "If") &&
-            validate_stmts(state, stmt->v.If.orelse);
+        ret = validate_expr(stmt->v.If.test, Load) &&
+            validate_body(stmt->v.If.body, "If") &&
+            validate_stmts(stmt->v.If.orelse);
         break;
     case With_kind:
         if (!validate_nonempty_seq(stmt->v.With.items, "items", "With"))
             return 0;
         for (Py_ssize_t i = 0; i < asdl_seq_LEN(stmt->v.With.items); i++) {
             withitem_ty item = asdl_seq_GET(stmt->v.With.items, i);
-            if (!validate_expr(state, item->context_expr, Load) ||
-                (item->optional_vars && !validate_expr(state, item->optional_vars, Store)))
+            if (!validate_expr(item->context_expr, Load) ||
+                (item->optional_vars && !validate_expr(item->optional_vars, Store)))
                 return 0;
         }
-        ret = validate_body(state, stmt->v.With.body, "With");
+        ret = validate_body(stmt->v.With.body, "With");
         break;
     case AsyncWith_kind:
         if (!validate_nonempty_seq(stmt->v.AsyncWith.items, "items", "AsyncWith"))
             return 0;
         for (Py_ssize_t i = 0; i < asdl_seq_LEN(stmt->v.AsyncWith.items); i++) {
             withitem_ty item = asdl_seq_GET(stmt->v.AsyncWith.items, i);
-            if (!validate_expr(state, item->context_expr, Load) ||
-                (item->optional_vars && !validate_expr(state, item->optional_vars, Store)))
+            if (!validate_expr(item->context_expr, Load) ||
+                (item->optional_vars && !validate_expr(item->optional_vars, Store)))
                 return 0;
         }
-        ret = validate_body(state, stmt->v.AsyncWith.body, "AsyncWith");
+        ret = validate_body(stmt->v.AsyncWith.body, "AsyncWith");
         break;
     case Match_kind:
-        if (!validate_expr(state, stmt->v.Match.subject, Load)
+        if (!validate_expr(stmt->v.Match.subject, Load)
             || !validate_nonempty_seq(stmt->v.Match.cases, "cases", "Match")) {
             return 0;
         }
         for (Py_ssize_t i = 0; i < asdl_seq_LEN(stmt->v.Match.cases); i++) {
             match_case_ty m = asdl_seq_GET(stmt->v.Match.cases, i);
-            if (!validate_pattern(state, m->pattern, /*star_ok=*/0)
-                || (m->guard && !validate_expr(state, m->guard, Load))
-                || !validate_body(state, m->body, "match_case")) {
+            if (!validate_pattern(m->pattern, /*star_ok=*/0)
+                || (m->guard && !validate_expr(m->guard, Load))
+                || !validate_body(m->body, "match_case")) {
                 return 0;
             }
         }
@@ -841,8 +829,8 @@ validate_stmt(struct validator *state, stmt_ty stmt)
         break;
     case Raise_kind:
         if (stmt->v.Raise.exc) {
-            ret = validate_expr(state, stmt->v.Raise.exc, Load) &&
-                (!stmt->v.Raise.cause || validate_expr(state, stmt->v.Raise.cause, Load));
+            ret = validate_expr(stmt->v.Raise.exc, Load) &&
+                (!stmt->v.Raise.cause || validate_expr(stmt->v.Raise.cause, Load));
             break;
         }
         if (stmt->v.Raise.cause) {
@@ -852,7 +840,7 @@ validate_stmt(struct validator *state, stmt_ty stmt)
         ret = 1;
         break;
     case Try_kind:
-        if (!validate_body(state, stmt->v.Try.body, "Try"))
+        if (!validate_body(stmt->v.Try.body, "Try"))
             return 0;
         if (!asdl_seq_LEN(stmt->v.Try.handlers) &&
             !asdl_seq_LEN(stmt->v.Try.finalbody)) {
@@ -868,17 +856,17 @@ validate_stmt(struct validator *state, stmt_ty stmt)
             excepthandler_ty handler = asdl_seq_GET(stmt->v.Try.handlers, i);
             VALIDATE_POSITIONS(handler);
             if ((handler->v.ExceptHandler.type &&
-                 !validate_expr(state, handler->v.ExceptHandler.type, Load)) ||
-                !validate_body(state, handler->v.ExceptHandler.body, "ExceptHandler"))
+                 !validate_expr(handler->v.ExceptHandler.type, Load)) ||
+                !validate_body(handler->v.ExceptHandler.body, "ExceptHandler"))
                 return 0;
         }
         ret = (!asdl_seq_LEN(stmt->v.Try.finalbody) ||
-                validate_stmts(state, stmt->v.Try.finalbody)) &&
+                validate_stmts(stmt->v.Try.finalbody)) &&
             (!asdl_seq_LEN(stmt->v.Try.orelse) ||
-             validate_stmts(state, stmt->v.Try.orelse));
+             validate_stmts(stmt->v.Try.orelse));
         break;
     case TryStar_kind:
-        if (!validate_body(state, stmt->v.TryStar.body, "TryStar"))
+        if (!validate_body(stmt->v.TryStar.body, "TryStar"))
             return 0;
         if (!asdl_seq_LEN(stmt->v.TryStar.handlers) &&
             !asdl_seq_LEN(stmt->v.TryStar.finalbody)) {
@@ -893,18 +881,18 @@ validate_stmt(struct validator *state, stmt_ty stmt)
         for (Py_ssize_t i = 0; i < asdl_seq_LEN(stmt->v.TryStar.handlers); i++) {
             excepthandler_ty handler = asdl_seq_GET(stmt->v.TryStar.handlers, i);
             if ((handler->v.ExceptHandler.type &&
-                 !validate_expr(state, handler->v.ExceptHandler.type, Load)) ||
-                !validate_body(state, handler->v.ExceptHandler.body, "ExceptHandler"))
+                 !validate_expr(handler->v.ExceptHandler.type, Load)) ||
+                !validate_body(handler->v.ExceptHandler.body, "ExceptHandler"))
                 return 0;
         }
         ret = (!asdl_seq_LEN(stmt->v.TryStar.finalbody) ||
-                validate_stmts(state, stmt->v.TryStar.finalbody)) &&
+                validate_stmts(stmt->v.TryStar.finalbody)) &&
             (!asdl_seq_LEN(stmt->v.TryStar.orelse) ||
-             validate_stmts(state, stmt->v.TryStar.orelse));
+             validate_stmts(stmt->v.TryStar.orelse));
         break;
     case Assert_kind:
-        ret = validate_expr(state, stmt->v.Assert.test, Load) &&
-            (!stmt->v.Assert.msg || validate_expr(state, stmt->v.Assert.msg, Load));
+        ret = validate_expr(stmt->v.Assert.test, Load) &&
+            (!stmt->v.Assert.msg || validate_expr(stmt->v.Assert.msg, Load));
         break;
     case Import_kind:
         ret = validate_nonempty_seq(stmt->v.Import.names, "names", "Import");
@@ -923,15 +911,15 @@ validate_stmt(struct validator *state, stmt_ty stmt)
         ret = validate_nonempty_seq(stmt->v.Nonlocal.names, "names", "Nonlocal");
         break;
     case Expr_kind:
-        ret = validate_expr(state, stmt->v.Expr.value, Load);
+        ret = validate_expr(stmt->v.Expr.value, Load);
         break;
     case AsyncFunctionDef_kind:
-        ret = validate_body(state, stmt->v.AsyncFunctionDef.body, "AsyncFunctionDef") &&
-            validate_type_params(state, stmt->v.AsyncFunctionDef.type_params) &&
-            validate_arguments(state, stmt->v.AsyncFunctionDef.args) &&
-            validate_exprs(state, stmt->v.AsyncFunctionDef.decorator_list, Load, 0) &&
+        ret = validate_body(stmt->v.AsyncFunctionDef.body, "AsyncFunctionDef") &&
+            validate_type_params(stmt->v.AsyncFunctionDef.type_params) &&
+            validate_arguments(stmt->v.AsyncFunctionDef.args) &&
+            validate_exprs(stmt->v.AsyncFunctionDef.decorator_list, Load, 0) &&
             (!stmt->v.AsyncFunctionDef.returns ||
-             validate_expr(state, stmt->v.AsyncFunctionDef.returns, Load));
+             validate_expr(stmt->v.AsyncFunctionDef.returns, Load));
         break;
     case Pass_kind:
     case Break_kind:
@@ -944,18 +932,18 @@ validate_stmt(struct validator *state, stmt_ty stmt)
         PyErr_SetString(PyExc_SystemError, "unexpected statement");
         ret = 0;
     }
-    LEAVE_RECURSIVE(state);
+    LEAVE_RECURSIVE();
     return ret;
 }
 
 static int
-validate_stmts(struct validator *state, asdl_stmt_seq *seq)
+validate_stmts(asdl_stmt_seq *seq)
 {
     assert(!PyErr_Occurred());
     for (Py_ssize_t i = 0; i < asdl_seq_LEN(seq); i++) {
         stmt_ty stmt = asdl_seq_GET(seq, i);
         if (stmt) {
-            if (!validate_stmt(state, stmt))
+            if (!validate_stmt(stmt))
                 return 0;
         }
         else {
@@ -968,13 +956,13 @@ validate_stmts(struct validator *state, asdl_stmt_seq *seq)
 }
 
 static int
-validate_exprs(struct validator *state, asdl_expr_seq *exprs, expr_context_ty ctx, int null_ok)
+validate_exprs(asdl_expr_seq *exprs, expr_context_ty ctx, int null_ok)
 {
     assert(!PyErr_Occurred());
     for (Py_ssize_t i = 0; i < asdl_seq_LEN(exprs); i++) {
         expr_ty expr = asdl_seq_GET(exprs, i);
         if (expr) {
-            if (!validate_expr(state, expr, ctx))
+            if (!validate_expr(expr, ctx))
                 return 0;
         }
         else if (!null_ok) {
@@ -988,12 +976,12 @@ validate_exprs(struct validator *state, asdl_expr_seq *exprs, expr_context_ty ct
 }
 
 static int
-validate_patterns(struct validator *state, asdl_pattern_seq *patterns, int star_ok)
+validate_patterns(asdl_pattern_seq *patterns, int star_ok)
 {
     assert(!PyErr_Occurred());
     for (Py_ssize_t i = 0; i < asdl_seq_LEN(patterns); i++) {
         pattern_ty pattern = asdl_seq_GET(patterns, i);
-        if (!validate_pattern(state, pattern, star_ok)) {
+        if (!validate_pattern(pattern, star_ok)) {
             return 0;
         }
     }
@@ -1001,7 +989,7 @@ validate_patterns(struct validator *state, asdl_pattern_seq *patterns, int star_
 }
 
 static int
-validate_typeparam(struct validator *state, type_param_ty tp)
+validate_typeparam(type_param_ty tp)
 {
     VALIDATE_POSITIONS(tp);
     int ret = -1;
@@ -1009,32 +997,32 @@ validate_typeparam(struct validator *state, type_param_ty tp)
         case TypeVar_kind:
             ret = validate_name(tp->v.TypeVar.name) &&
                 (!tp->v.TypeVar.bound ||
-                 validate_expr(state, tp->v.TypeVar.bound, Load)) &&
+                 validate_expr(tp->v.TypeVar.bound, Load)) &&
                 (!tp->v.TypeVar.default_value ||
-                 validate_expr(state, tp->v.TypeVar.default_value, Load));
+                 validate_expr(tp->v.TypeVar.default_value, Load));
             break;
         case ParamSpec_kind:
             ret = validate_name(tp->v.ParamSpec.name) &&
                 (!tp->v.ParamSpec.default_value ||
-                 validate_expr(state, tp->v.ParamSpec.default_value, Load));
+                 validate_expr(tp->v.ParamSpec.default_value, Load));
             break;
         case TypeVarTuple_kind:
             ret = validate_name(tp->v.TypeVarTuple.name) &&
                 (!tp->v.TypeVarTuple.default_value ||
-                 validate_expr(state, tp->v.TypeVarTuple.default_value, Load));
+                 validate_expr(tp->v.TypeVarTuple.default_value, Load));
             break;
     }
     return ret;
 }
 
 static int
-validate_type_params(struct validator *state, asdl_type_param_seq *tps)
+validate_type_params(asdl_type_param_seq *tps)
 {
     Py_ssize_t i;
     for (i = 0; i < asdl_seq_LEN(tps); i++) {
         type_param_ty tp = asdl_seq_GET(tps, i);
         if (tp) {
-            if (!validate_typeparam(state, tp))
+            if (!validate_typeparam(tp))
                 return 0;
         }
     }
@@ -1046,34 +1034,20 @@ _PyAST_Validate(mod_ty mod)
 {
     assert(!PyErr_Occurred());
     int res = -1;
-    struct validator state;
-    PyThreadState *tstate;
-    int starting_recursion_depth;
-
-    /* Setup recursion depth check counters */
-    tstate = _PyThreadState_GET();
-    if (!tstate) {
-        return 0;
-    }
-    /* Be careful here to prevent overflow. */
-    int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining;
-    starting_recursion_depth = recursion_depth;
-    state.recursion_depth = starting_recursion_depth;
-    state.recursion_limit = Py_C_RECURSION_LIMIT;
 
     switch (mod->kind) {
     case Module_kind:
-        res = validate_stmts(&state, mod->v.Module.body);
+        res = validate_stmts(mod->v.Module.body);
         break;
     case Interactive_kind:
-        res = validate_stmts(&state, mod->v.Interactive.body);
+        res = validate_stmts(mod->v.Interactive.body);
         break;
     case Expression_kind:
-        res = validate_expr(&state, mod->v.Expression.body, Load);
+        res = validate_expr(mod->v.Expression.body, Load);
         break;
     case FunctionType_kind:
-        res = validate_exprs(&state, mod->v.FunctionType.argtypes, Load, /*null_ok=*/0) &&
-              validate_expr(&state, mod->v.FunctionType.returns, Load);
+        res = validate_exprs(mod->v.FunctionType.argtypes, Load, /*null_ok=*/0) &&
+              validate_expr(mod->v.FunctionType.returns, Load);
         break;
     // No default case so compiler emits warning for unhandled cases
     }
@@ -1082,14 +1056,6 @@ _PyAST_Validate(mod_ty mod)
         PyErr_SetString(PyExc_SystemError, "impossible module node");
         return 0;
     }
-
-    /* Check that the recursion depth counting balanced correctly */
-    if (res && state.recursion_depth != starting_recursion_depth) {
-        PyErr_Format(PyExc_SystemError,
-            "AST validator recursion depth mismatch (before=%d, after=%d)",
-            starting_recursion_depth, state.recursion_depth);
-        return 0;
-    }
     return res;
 }
 
index 0b58e8cd2a2ced336293b9fb753be028157e4ef5..ab1ee96b045362541d0c04151d6a9c272121d660 100644 (file)
 typedef struct {
     int optimize;
     int ff_features;
-
-    int recursion_depth;            /* current recursion depth */
-    int recursion_limit;            /* recursion limit */
 } _PyASTOptimizeState;
 
-#define ENTER_RECURSIVE(ST) \
-    do { \
-        if (++(ST)->recursion_depth > (ST)->recursion_limit) { \
-            PyErr_SetString(PyExc_RecursionError, \
-                "maximum recursion depth exceeded during compilation"); \
-            return 0; \
-        } \
-    } while(0)
+#define ENTER_RECURSIVE() \
+if (Py_EnterRecursiveCall(" during compilation")) { \
+    return 0; \
+}
 
-#define LEAVE_RECURSIVE(ST) \
-    do { \
-        --(ST)->recursion_depth; \
-    } while(0)
+#define LEAVE_RECURSIVE() Py_LeaveRecursiveCall();
 
 static int
 make_const(expr_ty node, PyObject *val, PyArena *arena)
@@ -668,7 +658,7 @@ astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
 static int
 astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
 {
-    ENTER_RECURSIVE(state);
+    ENTER_RECURSIVE();
     switch (node_->kind) {
     case BoolOp_kind:
         CALL_SEQ(astfold_expr, expr, node_->v.BoolOp.values);
@@ -765,7 +755,7 @@ astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
     case Name_kind:
         if (node_->v.Name.ctx == Load &&
                 _PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) {
-            LEAVE_RECURSIVE(state);
+            LEAVE_RECURSIVE();
             return make_const(node_, PyBool_FromLong(!state->optimize), ctx_);
         }
         break;
@@ -778,7 +768,7 @@ astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
     // No default case, so the compiler will emit a warning if new expression
     // kinds are added without being handled here
     }
-    LEAVE_RECURSIVE(state);;
+    LEAVE_RECURSIVE();
     return 1;
 }
 
@@ -823,7 +813,7 @@ astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
 static int
 astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
 {
-    ENTER_RECURSIVE(state);
+    ENTER_RECURSIVE();
     switch (node_->kind) {
     case FunctionDef_kind:
         CALL_SEQ(astfold_type_param, type_param, node_->v.FunctionDef.type_params);
@@ -945,7 +935,7 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
     // No default case, so the compiler will emit a warning if new statement
     // kinds are added without being handled here
     }
-    LEAVE_RECURSIVE(state);
+    LEAVE_RECURSIVE();
     return 1;
 }
 
@@ -977,7 +967,7 @@ astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
     // Currently, this is really only used to form complex/negative numeric
     // constants in MatchValue and MatchMapping nodes
     // We still recurse into all subexpressions and subpatterns anyway
-    ENTER_RECURSIVE(state);
+    ENTER_RECURSIVE();
     switch (node_->kind) {
         case MatchValue_kind:
             CALL(astfold_expr, expr_ty, node_->v.MatchValue.value);
@@ -1009,7 +999,7 @@ astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
     // No default case, so the compiler will emit a warning if new pattern
     // kinds are added without being handled here
     }
-    LEAVE_RECURSIVE(state);
+    LEAVE_RECURSIVE();
     return 1;
 }
 
@@ -1047,34 +1037,12 @@ astfold_type_param(type_param_ty node_, PyArena *ctx_, _PyASTOptimizeState *stat
 int
 _PyAST_Optimize(mod_ty mod, PyArena *arena, int optimize, int ff_features)
 {
-    PyThreadState *tstate;
-    int starting_recursion_depth;
-
     _PyASTOptimizeState state;
     state.optimize = optimize;
     state.ff_features = ff_features;
 
-    /* Setup recursion depth check counters */
-    tstate = _PyThreadState_GET();
-    if (!tstate) {
-        return 0;
-    }
-    /* Be careful here to prevent overflow. */
-    int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining;
-    starting_recursion_depth = recursion_depth;
-    state.recursion_depth = starting_recursion_depth;
-    state.recursion_limit = Py_C_RECURSION_LIMIT;
-
     int ret = astfold_mod(mod, arena, &state);
     assert(ret || PyErr_Occurred());
 
-    /* Check that the recursion depth counting balanced correctly */
-    if (ret && state.recursion_depth != starting_recursion_depth) {
-        PyErr_Format(PyExc_SystemError,
-            "AST optimizer recursion depth mismatch (before=%d, after=%d)",
-            starting_recursion_depth, state.recursion_depth);
-        return 0;
-    }
-
     return ret;
 }
index 1c5fdf847b62c2f3a20bd7941c515389bd30793c..3c5cb07709d66c266daa5514cb34c60706e6ad87 100644 (file)
@@ -1082,7 +1082,6 @@ dummy_func(
             /* Restore previous frame and return. */
             tstate->current_frame = frame->previous;
             assert(!_PyErr_Occurred(tstate));
-            tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS;
             PyObject *result = PyStackRef_AsPyObjectSteal(retval);
             SYNC_SP(); /* Not strictly necessary, but prevents warnings */
             return result;
@@ -3971,11 +3970,10 @@ dummy_func(
             EXIT_IF(!PyCFunction_CheckExact(callable_o));
             EXIT_IF(PyCFunction_GET_FLAGS(callable_o) != METH_O);
             // CPython promises to check all non-vectorcall function calls.
-            EXIT_IF(tstate->c_recursion_remaining <= 0);
+            EXIT_IF(_Py_ReachedRecursionLimit(tstate));
             STAT_INC(CALL, hit);
             PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable_o);
             _PyStackRef arg = args[0];
-            _Py_EnterRecursiveCallTstateUnchecked(tstate);
             PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, PyCFunction_GET_SELF(callable_o), PyStackRef_AsPyObjectBorrow(arg));
             _Py_LeaveRecursiveCallTstate(tstate);
             assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
@@ -4165,14 +4163,13 @@ dummy_func(
             PyMethodDef *meth = method->d_method;
             EXIT_IF(meth->ml_flags != METH_O);
             // CPython promises to check all non-vectorcall function calls.
-            EXIT_IF(tstate->c_recursion_remaining <= 0);
+            EXIT_IF(_Py_ReachedRecursionLimit(tstate));
             _PyStackRef arg_stackref = arguments[1];
             _PyStackRef self_stackref = arguments[0];
             EXIT_IF(!Py_IS_TYPE(PyStackRef_AsPyObjectBorrow(self_stackref),
                                  method->d_common.d_type));
             STAT_INC(CALL, hit);
             PyCFunction cfunc = meth->ml_meth;
-            _Py_EnterRecursiveCallTstateUnchecked(tstate);
             PyObject *res_o = _PyCFunction_TrampolineCall(cfunc,
                                   PyStackRef_AsPyObjectBorrow(self_stackref),
                                   PyStackRef_AsPyObjectBorrow(arg_stackref));
@@ -4247,10 +4244,9 @@ dummy_func(
             EXIT_IF(!Py_IS_TYPE(self, method->d_common.d_type));
             EXIT_IF(meth->ml_flags != METH_NOARGS);
             // CPython promises to check all non-vectorcall function calls.
-            EXIT_IF(tstate->c_recursion_remaining <= 0);
+            EXIT_IF(_Py_ReachedRecursionLimit(tstate));
             STAT_INC(CALL, hit);
             PyCFunction cfunc = meth->ml_meth;
-            _Py_EnterRecursiveCallTstateUnchecked(tstate);
             PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, self, NULL);
             _Py_LeaveRecursiveCallTstate(tstate);
             assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
@@ -5252,7 +5248,6 @@ dummy_func(
             if (frame->owner == FRAME_OWNED_BY_INTERPRETER) {
                 /* Restore previous frame and exit */
                 tstate->current_frame = frame->previous;
-                tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS;
                 return NULL;
             }
             next_instr = frame->instr_ptr;
index cf9a8713ed9803d4d829dcfe58df80405011f042..0459c57c4cbaedeceada8849e4df4064bbf50dc4 100644 (file)
@@ -304,36 +304,106 @@ Py_SetRecursionLimit(int new_limit)
     _PyEval_StartTheWorld(interp);
 }
 
+int
+_Py_ReachedRecursionLimitWithMargin(PyThreadState *tstate, int margin_count)
+{
+    char here;
+    uintptr_t here_addr = (uintptr_t)&here;
+    _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
+    if (here_addr > _tstate->c_stack_soft_limit + margin_count * PYOS_STACK_MARGIN_BYTES) {
+        return 0;
+    }
+    if (_tstate->c_stack_hard_limit == 0) {
+        _Py_InitializeRecursionLimits(tstate);
+    }
+    return here_addr <= _tstate->c_stack_soft_limit + margin_count * PYOS_STACK_MARGIN_BYTES;
+}
+
+void
+_Py_EnterRecursiveCallUnchecked(PyThreadState *tstate)
+{
+    char here;
+    uintptr_t here_addr = (uintptr_t)&here;
+    _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
+    if (here_addr < _tstate->c_stack_hard_limit) {
+        Py_FatalError("Unchecked stack overflow.");
+    }
+}
+
+#if defined(__s390x__)
+#  define Py_C_STACK_SIZE 320000
+#elif defined(_WIN32)
+   // Don't define Py_C_STACK_SIZE, ask the O/S
+#elif defined(__ANDROID__)
+#  define Py_C_STACK_SIZE 1200000
+#elif defined(__sparc__)
+#  define Py_C_STACK_SIZE 1600000
+#elif defined(__wasi__)
+   /* Web assembly has two stacks, so this isn't really the stack depth */
+#  define Py_C_STACK_SIZE 100000
+#elif defined(__hppa__) || defined(__powerpc64__)
+#  define Py_C_STACK_SIZE 2000000
+#else
+#  define Py_C_STACK_SIZE 5000000
+#endif
+
+void
+_Py_InitializeRecursionLimits(PyThreadState *tstate)
+{
+    _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
+#ifdef WIN32
+    ULONG_PTR low, high;
+    GetCurrentThreadStackLimits(&low, &high);
+    _tstate->c_stack_top = (uintptr_t)high;
+    ULONG guarantee = 0;
+    SetThreadStackGuarantee(&guarantee);
+    _tstate->c_stack_hard_limit = ((uintptr_t)low) + guarantee + PYOS_STACK_MARGIN_BYTES;
+    _tstate->c_stack_soft_limit = _tstate->c_stack_hard_limit + PYOS_STACK_MARGIN_BYTES;
+#else
+    char here;
+    uintptr_t here_addr = (uintptr_t)&here;
+    _tstate->c_stack_top = _Py_SIZE_ROUND_UP(here_addr, 4096);
+    _tstate->c_stack_soft_limit = _tstate->c_stack_top - Py_C_STACK_SIZE;
+    _tstate->c_stack_hard_limit = _tstate->c_stack_top - (Py_C_STACK_SIZE + PYOS_STACK_MARGIN_BYTES);
+#endif
+}
+
 /* The function _Py_EnterRecursiveCallTstate() only calls _Py_CheckRecursiveCall()
    if the recursion_depth reaches recursion_limit. */
 int
 _Py_CheckRecursiveCall(PyThreadState *tstate, const char *where)
 {
-#ifdef USE_STACKCHECK
-    if (PyOS_CheckStack()) {
-        ++tstate->c_recursion_remaining;
-        _PyErr_SetString(tstate, PyExc_MemoryError, "Stack overflow");
-        return -1;
+    _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
+    char here;
+    uintptr_t here_addr = (uintptr_t)&here;
+    assert(_tstate->c_stack_soft_limit != 0);
+    if (_tstate->c_stack_hard_limit == 0) {
+        _Py_InitializeRecursionLimits(tstate);
+    }
+    if (here_addr >= _tstate->c_stack_soft_limit) {
+        return 0;
+    }
+    assert(_tstate->c_stack_hard_limit != 0);
+    if (here_addr < _tstate->c_stack_hard_limit) {
+        /* Overflowing while handling an overflow. Give up. */
+        int kbytes_used = (int)(_tstate->c_stack_top - here_addr)/1024;
+        char buffer[80];
+        snprintf(buffer, 80, "Unrecoverable stack overflow (used %d kB)%s", kbytes_used, where);
+        Py_FatalError(buffer);
     }
-#endif
     if (tstate->recursion_headroom) {
-        if (tstate->c_recursion_remaining < -50) {
-            /* Overflowing while handling an overflow. Give up. */
-            Py_FatalError("Cannot recover from stack overflow.");
-        }
+        return 0;
     }
     else {
-        if (tstate->c_recursion_remaining <= 0) {
-            tstate->recursion_headroom++;
-            _PyErr_Format(tstate, PyExc_RecursionError,
-                        "maximum recursion depth exceeded%s",
-                        where);
-            tstate->recursion_headroom--;
-            ++tstate->c_recursion_remaining;
-            return -1;
-        }
+        int kbytes_used = (int)(_tstate->c_stack_top - here_addr)/1024;
+        tstate->recursion_headroom++;
+        _PyErr_Format(tstate, PyExc_RecursionError,
+                    "Stack overflow (used %d kB)%s",
+                    kbytes_used,
+                    where);
+        tstate->recursion_headroom--;
+        return -1;
     }
-    return 0;
 }
 
 
@@ -761,11 +831,6 @@ _PyObjectArray_Free(PyObject **array, PyObject **scratch)
 }
 
 
-/* _PyEval_EvalFrameDefault() is a *big* function,
- * so consume 3 units of C stack */
-#define PY_EVAL_C_STACK_UNITS 2
-
-
 /* _PyEval_EvalFrameDefault is too large to optimize for speed with PGO on MSVC.
  */
 #if (defined(_MSC_VER) && \
@@ -838,8 +903,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
     frame->previous = &entry_frame;
     tstate->current_frame = frame;
 
-    tstate->c_recursion_remaining -= (PY_EVAL_C_STACK_UNITS - 1);
-
     /* support for generator.throw() */
     if (throwflag) {
         if (_Py_EnterRecursivePy(tstate)) {
@@ -998,7 +1061,6 @@ early_exit:
     assert(frame->owner == FRAME_OWNED_BY_INTERPRETER);
     /* Restore previous frame and exit */
     tstate->current_frame = frame->previous;
-    tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS;
     return NULL;
 }
 
@@ -1562,11 +1624,9 @@ clear_thread_frame(PyThreadState *tstate, _PyInterpreterFrame * frame)
     // _PyThreadState_PopFrame, since f_code is already cleared at that point:
     assert((PyObject **)frame + _PyFrame_GetCode(frame)->co_framesize ==
         tstate->datastack_top);
-    tstate->c_recursion_remaining--;
     assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame);
     _PyFrame_ClearExceptCode(frame);
     PyStackRef_CLEAR(frame->f_executable);
-    tstate->c_recursion_remaining++;
     _PyThreadState_PopFrame(tstate, frame);
 }
 
@@ -1579,11 +1639,9 @@ clear_gen_frame(PyThreadState *tstate, _PyInterpreterFrame * frame)
     assert(tstate->exc_info == &gen->gi_exc_state);
     tstate->exc_info = gen->gi_exc_state.previous_item;
     gen->gi_exc_state.previous_item = NULL;
-    tstate->c_recursion_remaining--;
     assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame);
     _PyFrame_ClearExceptCode(frame);
     _PyErr_ClearExcState(&gen->gi_exc_state);
-    tstate->c_recursion_remaining++;
     frame->previous = NULL;
 }
 
index 5962e0ebd4f4931a50ccd80a31e658d71bc9a926..9520bc854dc831fce6026bef736906fc5649cd6b 100644 (file)
                 JUMP_TO_JUMP_TARGET();
             }
             // CPython promises to check all non-vectorcall function calls.
-            if (tstate->c_recursion_remaining <= 0) {
+            if (_Py_ReachedRecursionLimit(tstate)) {
                 UOP_STAT_INC(uopcode, miss);
                 JUMP_TO_JUMP_TARGET();
             }
             STAT_INC(CALL, hit);
             PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable_o);
             _PyStackRef arg = args[0];
-            _Py_EnterRecursiveCallTstateUnchecked(tstate);
             _PyFrame_SetStackPointer(frame, stack_pointer);
             PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, PyCFunction_GET_SELF(callable_o), PyStackRef_AsPyObjectBorrow(arg));
             stack_pointer = _PyFrame_GetStackPointer(frame);
                 JUMP_TO_JUMP_TARGET();
             }
             // CPython promises to check all non-vectorcall function calls.
-            if (tstate->c_recursion_remaining <= 0) {
+            if (_Py_ReachedRecursionLimit(tstate)) {
                 UOP_STAT_INC(uopcode, miss);
                 JUMP_TO_JUMP_TARGET();
             }
             }
             STAT_INC(CALL, hit);
             PyCFunction cfunc = meth->ml_meth;
-            _Py_EnterRecursiveCallTstateUnchecked(tstate);
             _PyFrame_SetStackPointer(frame, stack_pointer);
             PyObject *res_o = _PyCFunction_TrampolineCall(cfunc,
                 PyStackRef_AsPyObjectBorrow(self_stackref),
                 JUMP_TO_JUMP_TARGET();
             }
             // CPython promises to check all non-vectorcall function calls.
-            if (tstate->c_recursion_remaining <= 0) {
+            if (_Py_ReachedRecursionLimit(tstate)) {
                 UOP_STAT_INC(uopcode, miss);
                 JUMP_TO_JUMP_TARGET();
             }
             STAT_INC(CALL, hit);
             PyCFunction cfunc = meth->ml_meth;
-            _Py_EnterRecursiveCallTstateUnchecked(tstate);
             _PyFrame_SetStackPointer(frame, stack_pointer);
             PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, self, NULL);
             stack_pointer = _PyFrame_GetStackPointer(frame);
index 01fa857b96ac3b0a9ebaa8221070fe66e82a61a0..268e8836994bc4e2c9149010eaabed946a9e782c 100644 (file)
                     JUMP_TO_PREDICTED(CALL);
                 }
                 // CPython promises to check all non-vectorcall function calls.
-                if (tstate->c_recursion_remaining <= 0) {
+                if (_Py_ReachedRecursionLimit(tstate)) {
                     UPDATE_MISS_STATS(CALL);
                     assert(_PyOpcode_Deopt[opcode] == (CALL));
                     JUMP_TO_PREDICTED(CALL);
                 STAT_INC(CALL, hit);
                 PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable_o);
                 _PyStackRef arg = args[0];
-                _Py_EnterRecursiveCallTstateUnchecked(tstate);
                 _PyFrame_SetStackPointer(frame, stack_pointer);
                 PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, PyCFunction_GET_SELF(callable_o), PyStackRef_AsPyObjectBorrow(arg));
                 stack_pointer = _PyFrame_GetStackPointer(frame);
                     JUMP_TO_PREDICTED(CALL);
                 }
                 // CPython promises to check all non-vectorcall function calls.
-                if (tstate->c_recursion_remaining <= 0) {
+                if (_Py_ReachedRecursionLimit(tstate)) {
                     UPDATE_MISS_STATS(CALL);
                     assert(_PyOpcode_Deopt[opcode] == (CALL));
                     JUMP_TO_PREDICTED(CALL);
                 }
                 STAT_INC(CALL, hit);
                 PyCFunction cfunc = meth->ml_meth;
-                _Py_EnterRecursiveCallTstateUnchecked(tstate);
                 _PyFrame_SetStackPointer(frame, stack_pointer);
                 PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, self, NULL);
                 stack_pointer = _PyFrame_GetStackPointer(frame);
                     JUMP_TO_PREDICTED(CALL);
                 }
                 // CPython promises to check all non-vectorcall function calls.
-                if (tstate->c_recursion_remaining <= 0) {
+                if (_Py_ReachedRecursionLimit(tstate)) {
                     UPDATE_MISS_STATS(CALL);
                     assert(_PyOpcode_Deopt[opcode] == (CALL));
                     JUMP_TO_PREDICTED(CALL);
                 }
                 STAT_INC(CALL, hit);
                 PyCFunction cfunc = meth->ml_meth;
-                _Py_EnterRecursiveCallTstateUnchecked(tstate);
                 _PyFrame_SetStackPointer(frame, stack_pointer);
                 PyObject *res_o = _PyCFunction_TrampolineCall(cfunc,
                     PyStackRef_AsPyObjectBorrow(self_stackref),
             /* Restore previous frame and return. */
             tstate->current_frame = frame->previous;
             assert(!_PyErr_Occurred(tstate));
-            tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS;
             PyObject *result = PyStackRef_AsPyObjectSteal(retval);
             stack_pointer += -1;
             assert(WITHIN_STACK_BOUNDS());
@@ -12081,7 +12077,6 @@ JUMP_TO_LABEL(error);
             if (frame->owner == FRAME_OWNED_BY_INTERPRETER) {
                 /* Restore previous frame and exit */
                 tstate->current_frame = frame->previous;
-                tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS;
                 return NULL;
             }
             next_instr = frame->instr_ptr;
index 89a652850e936379036289537514c85e26bf093d..4caef2260ae58ebdff46418ec187a221d0f58f40 100644 (file)
@@ -1490,10 +1490,9 @@ init_threadstate(_PyThreadStateImpl *_tstate,
 
     // thread_id and native_thread_id are set in bind_tstate().
 
-    tstate->py_recursion_limit = interp->ceval.recursion_limit,
-    tstate->py_recursion_remaining = interp->ceval.recursion_limit,
-    tstate->c_recursion_remaining = Py_C_RECURSION_LIMIT;
-
+    tstate->py_recursion_limit = interp->ceval.recursion_limit;
+    tstate->py_recursion_remaining = interp->ceval.recursion_limit;
+    tstate->c_recursion_remaining = 2;
     tstate->exc_info = &tstate->exc_state;
 
     // PyGILState_Release must not try to delete this thread state.
@@ -1508,6 +1507,10 @@ init_threadstate(_PyThreadStateImpl *_tstate,
     tstate->previous_executor = NULL;
     tstate->dict_global_version = 0;
 
+    _tstate->c_stack_soft_limit = UINTPTR_MAX;
+    _tstate->c_stack_top = 0;
+    _tstate->c_stack_hard_limit = 0;
+
     _tstate->asyncio_running_loop = NULL;
     _tstate->asyncio_running_task = NULL;
 
index 945e267ef72c6feb6a9dcea144971b89f6e38b6c..36390dac6152f6cef2c1cc095ec8d9681a6aece2 100644 (file)
@@ -1528,12 +1528,8 @@ _Py_SourceAsString(PyObject *cmd, const char *funcname, const char *what, PyComp
 }
 
 #if defined(USE_STACKCHECK)
-#if defined(WIN32) && defined(_MSC_VER)
 
-/* Stack checking for Microsoft C */
-
-#include <malloc.h>
-#include <excpt.h>
+/* Stack checking */
 
 /*
  * Return non-zero when we run out of memory on the stack; zero otherwise.
@@ -1541,27 +1537,10 @@ _Py_SourceAsString(PyObject *cmd, const char *funcname, const char *what, PyComp
 int
 PyOS_CheckStack(void)
 {
-    __try {
-        /* alloca throws a stack overflow exception if there's
-           not enough space left on the stack */
-        alloca(PYOS_STACK_MARGIN * sizeof(void*));
-        return 0;
-    } __except (GetExceptionCode() == STATUS_STACK_OVERFLOW ?
-                    EXCEPTION_EXECUTE_HANDLER :
-            EXCEPTION_CONTINUE_SEARCH) {
-        int errcode = _resetstkoflw();
-        if (errcode == 0)
-        {
-            Py_FatalError("Could not reset the stack!");
-        }
-    }
-    return 1;
+    PyThreadState *tstate = _PyThreadState_GET();
+    return _Py_ReachedRecursionLimit(tstate);
 }
 
-#endif /* WIN32 && _MSC_VER */
-
-/* Alternate implementations can be added here... */
-
 #endif /* USE_STACKCHECK */
 
 /* Deprecated C API functions still provided for binary compatibility */
index 49bd01ba68ac9ea28b51cf75e8d7b14a10b22450..873576183314e649bdd24a445e1e0360af46cb1c 100644 (file)
@@ -406,7 +406,6 @@ _PySymtable_Build(mod_ty mod, PyObject *filename, _PyFutureFeatures *future)
     asdl_stmt_seq *seq;
     Py_ssize_t i;
     PyThreadState *tstate;
-    int starting_recursion_depth;
 
     if (st == NULL)
         return NULL;
@@ -423,11 +422,6 @@ _PySymtable_Build(mod_ty mod, PyObject *filename, _PyFutureFeatures *future)
         _PySymtable_Free(st);
         return NULL;
     }
-    /* Be careful here to prevent overflow. */
-    int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining;
-    starting_recursion_depth = recursion_depth;
-    st->recursion_depth = starting_recursion_depth;
-    st->recursion_limit = Py_C_RECURSION_LIMIT;
 
     /* Make the initial symbol information gathering pass */
 
@@ -469,14 +463,6 @@ _PySymtable_Build(mod_ty mod, PyObject *filename, _PyFutureFeatures *future)
         _PySymtable_Free(st);
         return NULL;
     }
-    /* Check that the recursion depth counting balanced correctly */
-    if (st->recursion_depth != starting_recursion_depth) {
-        PyErr_Format(PyExc_SystemError,
-            "symtable analysis recursion depth mismatch (before=%d, after=%d)",
-            starting_recursion_depth, st->recursion_depth);
-        _PySymtable_Free(st);
-        return NULL;
-    }
     /* Make the second symbol analysis pass */
     if (symtable_analyze(st)) {
 #if _PY_DUMP_SYMTABLE
@@ -1736,19 +1722,12 @@ symtable_enter_type_param_block(struct symtable *st, identifier name,
         } \
     } while(0)
 
-#define ENTER_RECURSIVE(ST) \
-    do { \
-        if (++(ST)->recursion_depth > (ST)->recursion_limit) { \
-            PyErr_SetString(PyExc_RecursionError, \
-                "maximum recursion depth exceeded during compilation"); \
-            return 0; \
-        } \
-    } while(0)
+#define ENTER_RECURSIVE() \
+if (Py_EnterRecursiveCall(" during compilation")) { \
+    return 0; \
+}
 
-#define LEAVE_RECURSIVE(ST) \
-    do { \
-        --(ST)->recursion_depth; \
-    } while(0)
+#define LEAVE_RECURSIVE() Py_LeaveRecursiveCall();
 
 
 static int
@@ -1823,7 +1802,7 @@ maybe_set_ste_coroutine_for_module(struct symtable *st, stmt_ty s)
 static int
 symtable_visit_stmt(struct symtable *st, stmt_ty s)
 {
-    ENTER_RECURSIVE(st);
+    ENTER_RECURSIVE();
     switch (s->kind) {
     case FunctionDef_kind: {
         if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL, LOCATION(s)))
@@ -2235,7 +2214,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
             VISIT_SEQ(st, stmt, s->v.AsyncFor.orelse);
         break;
     }
-    LEAVE_RECURSIVE(st);
+    LEAVE_RECURSIVE();
     return 1;
 }
 
@@ -2358,7 +2337,7 @@ symtable_handle_namedexpr(struct symtable *st, expr_ty e)
 static int
 symtable_visit_expr(struct symtable *st, expr_ty e)
 {
-    ENTER_RECURSIVE(st);
+    ENTER_RECURSIVE();
     switch (e->kind) {
     case NamedExpr_kind:
         if (!symtable_raise_if_annotation_block(st, "named expression", e)) {
@@ -2529,7 +2508,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
         VISIT_SEQ(st, expr, e->v.Tuple.elts);
         break;
     }
-    LEAVE_RECURSIVE(st);
+    LEAVE_RECURSIVE();
     return 1;
 }
 
@@ -2563,7 +2542,7 @@ symtable_visit_type_param_bound_or_default(
 static int
 symtable_visit_type_param(struct symtable *st, type_param_ty tp)
 {
-    ENTER_RECURSIVE(st);
+    ENTER_RECURSIVE();
     switch(tp->kind) {
     case TypeVar_kind:
         if (!symtable_add_def(st, tp->v.TypeVar.name, DEF_TYPE_PARAM | DEF_LOCAL, LOCATION(tp)))
@@ -2612,14 +2591,14 @@ symtable_visit_type_param(struct symtable *st, type_param_ty tp)
         }
         break;
     }
-    LEAVE_RECURSIVE(st);
+    LEAVE_RECURSIVE();
     return 1;
 }
 
 static int
 symtable_visit_pattern(struct symtable *st, pattern_ty p)
 {
-    ENTER_RECURSIVE(st);
+    ENTER_RECURSIVE();
     switch (p->kind) {
     case MatchValue_kind:
         VISIT(st, expr, p->v.MatchValue.value);
@@ -2668,7 +2647,7 @@ symtable_visit_pattern(struct symtable *st, pattern_ty p)
         VISIT_SEQ(st, pattern, p->v.MatchOr.patterns);
         break;
     }
-    LEAVE_RECURSIVE(st);
+    LEAVE_RECURSIVE();
     return 1;
 }
 
index 295bcc87b2cadf4ddfecb89e24256ef0ce8915bc..10db9acbb362c88bdbf2f1b15a55abe8c03fff46 100644 (file)
@@ -653,7 +653,6 @@ NON_ESCAPING_FUNCTIONS = (
     "_PyUnicode_JoinArray",
     "_Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY",
     "_Py_DECREF_NO_DEALLOC",
-    "_Py_EnterRecursiveCallTstateUnchecked",
     "_Py_ID",
     "_Py_IsImmortal",
     "_Py_LeaveRecursiveCallPy",
@@ -673,6 +672,7 @@ NON_ESCAPING_FUNCTIONS = (
     "initial_temperature_backoff_counter",
     "JUMP_TO_LABEL",
     "restart_backoff_counter",
+    "_Py_ReachedRecursionLimit",
 )
 
 def find_stmt_start(node: parser.CodeDef, idx: int) -> lexer.Token:
index a4951d05e80ebdb698cff4a18d4970ee99d2a912..2be85a163b4043e6bc3009e05c76f6ac162872f9 100644 (file)
@@ -44,7 +44,7 @@ EXTENSION_PREFIX = """\
 #    define MAXSTACK 4000
 #  endif
 #else
-#  define MAXSTACK 6000
+#  define MAXSTACK 4000
 #endif
 
 """
@@ -380,7 +380,7 @@ class CParserGenerator(ParserGenerator, GrammarVisitor):
         self.cleanup_statements: List[str] = []
 
     def add_level(self) -> None:
-        self.print("if (p->level++ == MAXSTACK) {")
+        self.print("if (p->level++ == MAXSTACK || _Py_ReachedRecursionLimitWithMargin(PyThreadState_Get(), 1)) {")
         with self.indent():
             self.print("_Pypegen_stack_overflow(p);")
         self.print("}")