The main branch's JIT doesn't seem to want to compile the example due to trace stack underflow. So I reduced the side exit count on my tracing JIT example and tried. Seems like LLVM 21 doesn't fix the problem :(
PYTHON_JIT=0
-----------
Testing various unwinding methods on the same deep call stack...
[GNU backtrace]
Total frames: 27
Showing first 10 frames:
# 0 /home/ken/Documents/GitHub/cpython-unwind/stackunwind.cpython-315-x86_64-linux-gnu.so(+0x280a) [0x78674f7a580a]
# 1 ../cpython/python(PyObject_Vectorcall+0x33) [0x58c0e08d2303]
# 2 ../cpython/python(_PyEval_EvalFrameDefault+0xf7a1) [0x58c0e086b141]
# 3 ../cpython/python(+0x2860aa) [0x58c0e0a430aa]
# 4 ../cpython/python(PyObject_Vectorcall+0x33) [0x58c0e08d2303]
# 5 ../cpython/python(_PyEval_EvalFrameDefault+0x3fb3) [0x58c0e085f953]
# 6 ../cpython/python(+0x2860aa) [0x58c0e0a430aa]
# 7 ../cpython/python(PyObject_Vectorcall+0x33) [0x58c0e08d2303]
# 8 ../cpython/python(_PyEval_EvalFrameDefault+0x3fb3) [0x58c0e085f953]
# 9 ../cpython/python(+0x2860aa) [0x58c0e0a430aa]
... (17 more frames)
[libunwind]
Total frames: 26
Showing first 10 frames:
# 0 PyObject_Vectorcall+0x33
# 1 _PyEval_EvalFrameDefault+0xf7a1
# 2 _PyEval_Vector+0x21a
# 3 PyObject_Vectorcall+0x33
# 4 _PyEval_EvalFrameDefault+0x3fb3
# 5 _PyEval_Vector+0x21a
# 6 PyObject_Vectorcall+0x33
# 7 _PyEval_EvalFrameDefault+0x3fb3
# 8 _PyEval_Vector+0x21a
# 9 PyObject_Vectorcall+0x33
... (16 more frames)
[libdw (DWARF)]
Total frames: 26
Showing first 10 frames:
# 0 PyObject_Vectorcall
# 1 _PyEval_EvalFrameDefault
# 2 _PyEval_Vector
# 3 PyObject_Vectorcall
# 4 _PyEval_EvalFrameDefault
# 5 _PyEval_Vector
# 6 PyObject_Vectorcall
# 7 _PyEval_EvalFrameDefault
# 8 _PyEval_Vector
# 9 PyObject_Vectorcall
... (16 more frames)
[Manual frame pointers]
Total frames: 4
Showing first 4 frames:
# 0 0x58c0e08d2303
# 1 0x2
# 2 0x58c0e0dbb7e0
# 3 0x2
PYTHON_JIT=1
------------
[GNU backtrace]
Total frames: 6
Showing first 6 frames:
# 0 /home/ken/Documents/GitHub/cpython-unwind/stackunwind.cpython-315-x86_64-linux-gnu.so(+0x280a) [0x7a0a357d080a]
# 1 ../cpython/python(PyObject_Vectorcall+0x33) [0x57385e3d3303]
# 2 ../cpython/python(_PyEval_EvalFrameDefault+0xf7a1) [0x57385e36c141]
# 3 ../cpython/python(+0x2860aa) [0x57385e5440aa]
# 4 ../cpython/python(PyObject_Vectorcall+0x33) [0x57385e3d3303]
# 5 [0x7a0a3398d4fb]
[libunwind]
Total frames: 5
Showing first 5 frames:
# 0 PyObject_Vectorcall+0x33
# 1 _PyEval_EvalFrameDefault+0xf7a1
# 2 _PyEval_Vector+0x21a
# 3 PyObject_Vectorcall+0x33
# 4 <unknown>
[libdw (DWARF)]
Total frames: 5
Showing first 5 frames:
# 0 PyObject_Vectorcall
# 1 _PyEval_EvalFrameDefault
# 2 _PyEval_Vector
# 3 PyObject_Vectorcall
# 4 <unknown>
[Manual frame pointers]
Total frames: 4
Showing first 4 frames:
# 0 0x57385e3d3303
# 1 0x(nil)
# 2 0x57385e8bc7e0
# 3 0x(nil)
Notice the missing frames!
However, I have made a very interesting discovery --- compiling the interpreter with a recent enough clang version (tested with clang-20/21) to the JIT restores the frames!!!
[GNU backtrace]
Total frames: 29
Showing first 10 frames:
# 0 /home/ken/Documents/GitHub/cpython-unwind/stackunwind.cpython-315-x86_64-linux-gnu.so(+0x280a) [0x797cf3f7c80a]
# 1 ../cpython/python(PyObject_Vectorcall+0x43) [0x64be6334e693]
# 2 ../cpython/python(_PyEval_EvalFrameDefault+0x5d3e) [0x64be6347f63e]
# 3 ../cpython/python(+0x217706) [0x64be63479706]
# 4 ../cpython/python(PyObject_Vectorcall+0x43) [0x64be6334e693]
# 5 ../cpython/python(_PyEval_EvalFrameDefault+0x3768) [0x64be6347d068]
# 6 ../cpython/python(+0x217706) [0x64be63479706]
# 7 ../cpython/python(PyObject_Vectorcall+0x43) [0x64be6334e693]
# 8 ../cpython/python(_PyEval_EvalFrameDefault+0x3768) [0x64be6347d068]
# 9 ../cpython/python(+0x217706) [0x64be63479706]
... (19 more frames)
[libunwind]
Total frames: 28
Showing first 10 frames:
# 0 PyObject_Vectorcall+0x43
# 1 _PyEval_EvalFrameDefault+0x5d3e
# 2 _PyEval_Vector+0x266
# 3 PyObject_Vectorcall+0x43
# 4 _PyEval_EvalFrameDefault+0x3768
# 5 _PyEval_Vector+0x266
# 6 PyObject_Vectorcall+0x43
# 7 _PyEval_EvalFrameDefault+0x3768
# 8 _PyEval_Vector+0x266
# 9 PyObject_Vectorcall+0x43
... (18 more frames)
[libdw (DWARF)]
Total frames: 28
Showing first 10 frames:
# 0 PyObject_Vectorcall
# 1 _PyEval_EvalFrameDefault
# 2 _PyEval_Vector
# 3 PyObject_Vectorcall
# 4 _PyEval_EvalFrameDefault
# 5 _PyEval_Vector
# 6 PyObject_Vectorcall
# 7 _PyEval_EvalFrameDefault
# 8 _PyEval_Vector
# 9 PyObject_Vectorcall
... (18 more frames)
[Manual frame pointers]
Total frames: 16
Showing first 10 frames:
# 0 0x64be6334e693
# 1 0x2
# 2 0x64be63479706
# 3 0x2
# 4 0x64be63479706
# 5 0x2
# 6 0x64be63479706
# 7 0x(nil)
# 8 0x64be63479706
# 9 0x(nil)
... (6 more frames)
So the solution to the stack unwinding seems to be to mandate compiilng CPython with the same clang as the JIT!