Skip to content

JIT: Assertion failure in _PyOptimizer_Optimize #143123

@devdanzin

Description

@devdanzin

Crash report

What happened?

It's possible to abort a patched debug JIT build by running the code below. The interpreter must be called from a venv in which lafleur is installed as editable, likely due to that priming the GC into a state suitable for the crash.

Sorry about the convoluted reproduction steps.

The necessary patch is:

diff --git a/Include/internal/pycore_backoff.h b/Include/internal/pycore_backoff.h
index 23ca7299e0d..0289b5fee7c 100644
--- a/Include/internal/pycore_backoff.h
+++ b/Include/internal/pycore_backoff.h
@@ -124,7 +124,7 @@ trigger_backoff_counter(void)
 // For example, 4095 does not work for the nqueens benchmark on pyperformance
 // as we always end up tracing the loop iteration's
 // exhaustion iteration. Which aborts our current tracer.
-#define JUMP_BACKWARD_INITIAL_VALUE 4000
+#define JUMP_BACKWARD_INITIAL_VALUE 63
 #define JUMP_BACKWARD_INITIAL_BACKOFF 6
 static inline _Py_BackoffCounter
 initial_jump_backoff_counter(void)
@@ -137,7 +137,7 @@ initial_jump_backoff_counter(void)
  * Must be larger than ADAPTIVE_COOLDOWN_VALUE,
  * otherwise when a side exit warms up we may construct
  * a new trace before the Tier 1 code has properly re-specialized. */
-#define SIDE_EXIT_INITIAL_VALUE 4000
+#define SIDE_EXIT_INITIAL_VALUE 63
 #define SIDE_EXIT_INITIAL_BACKOFF 6

 static inline _Py_BackoffCounter

To install lafleur as editable, first create a venv and activate it, then clone the lafleur repo and run pip install -e /path/to/lafleur/clone.

This MRE must be invoked like this:

/path/to/venv/with/editable/lafleur/install/bin/python mre.py

MRE:

import asyncio
any_v2 = None
tuple_v4 = (1, "")

def f1():
    class A:
        def _():...
        def __(): ...
        def ___():...

    class B: ...
    class C:
        def _(): ...    
    class D:
        def _(): ...    
    class E:
        def _(): ...    
    class F:
        def _(): ...    
    class G:
        def _(): ...    
    class H:
        def _(): ...    
    
    l = []
    for i in range(5):
        def _(): ...
    class I:
        async def _(): ...
        try:
            c = _()
        except Exception: ...

    def __(): ...
    class J:
        def _(): ...

    for _ in range(300):
        try:
            try: ValueError("")
            except E: ...
        except Exception: ...
    (
        any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2,
        any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2,
        any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2,
        any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2,
        any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2,
        any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2,
        any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2, any_v2,
        any_v2, any_v2, 
    )
    class K:
        def _():...
        def __(): ...
        def ___():...
    class AsyncCtx_9078:
        def _(self): ...
        async def __():
            try:
                for _ in K(10): ...
            except Exception: ...
        try:
            c = __()
        except Exception: ...
    x, *y = tuple_v4
    class L:
        def _():...
        def __(): ...
        def ___():...
    class M:
        def _(self): ...
        async def __():
            try:
                for _ in L(10): ...
            except Exception: ...
        try:
            c = __()
        except Exception: ...

    x, *y = x, *y = tuple_v4
    class M:
        def _():...
        def __(): ...
        def ___():...
    class N:
        def _():...
        def __(): ...
        def ___():...
    class O:
        def _(self): ...
        async def __():
            try:
                for _ in N(10): ...
            except Exception: ...
        try:
            c = __()
        except Exception: ...
    class P:
        def _():...
        def __(): ...
        def ___():...
    class Q:
        def _(self): ...
        async def __():
            try:
                with Q(): ...
            except Exception: ...
        try:
            c = __()
        except Exception: ...
    class R:
        def _(self): ...
        async def __():
            try:
                with R(): ...
            except Exception: ...
        try:
            c = __()
        except Exception: ...

    x, *y = x, *y = tuple_v4
    class S:
        def __init__(self, lit):
            selit = self.count = 0
        def __aiter__(self):return self
        async def __anext__(self):
            if self.count: n
            self.count += 1
    class T:
        def _(self): ...
        async def __():
            try:
                async for _ in S(10): ...
            except Exception: ...
        try:
            c = __()
            while True:
                try: c.send(None)
                except Exception: break
        except Exception: ...

for i in range(300):
    print(i)
    f1()

Traceback:

1
[...]
200
201
python: Python/optimizer.c:144: int _PyOptimizer_Optimize(_PyInterpreterFrame *, PyThreadState *): Assertion `_tstate->jit_tracer_state.initial_state.func != NULL' failed.

Program received signal SIGABRT, Aborted.

#0  __pthread_kill_implementation (threadid=<optimized out>, signo=6, no_tid=0) at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (threadid=<optimized out>, signo=6) at ./nptl/pthread_kill.c:89
#2  __GI___pthread_kill (threadid=<optimized out>, signo=signo@entry=6) at ./nptl/pthread_kill.c:100
#3  0x00007ffff7c45e2e in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4  0x00007ffff7c28888 in __GI_abort () at ./stdlib/abort.c:77
#5  0x00007ffff7c287f0 in __assert_fail_base (fmt=<optimized out>, assertion=<optimized out>, file=<optimized out>, line=<optimized out>, function=<optimized out>) at ./assert/assert.c:118
#6  0x00007ffff7c3c19f in __assert_fail (assertion=<optimized out>, file=<optimized out>, line=<optimized out>, function=<optimized out>) at ./assert/assert.c:127
#7  0x00005555563c0bd0 in _PyOptimizer_Optimize (frame=frame@entry=0x7e8ff6de5298, tstate=tstate@entry=0x555556e62830 <_PyRuntime+358864>) at Python/optimizer.c:144
#8  0x0000555555ed2e64 in stop_tracing_and_jit (tstate=0x555556e62830 <_PyRuntime+358864>, frame=frame@entry=0x7e8ff6de5298) at Python/ceval.c:1405
#9  0x0000555555e8eeed in _PyEval_EvalFrameDefault (tstate=<optimized out>, frame=<optimized out>, throwflag=<optimized out>) at Python/generated_cases.c.h:11628
#10 0x0000555555e6bf98 in _PyEval_EvalFrame (tstate=0x555556e62830 <_PyRuntime+358864>, frame=0x7e8ff6de5220, throwflag=0) at ./Include/internal/pycore_ceval.h:119
#11 _PyEval_Vector (tstate=<optimized out>, func=<optimized out>, locals=<optimized out>, args=<optimized out>, argcount=<optimized out>, kwnames=0x0) at Python/ceval.c:2483
#12 0x0000555555e6b9b5 in PyEval_EvalCode (co=<optimized out>, globals=<optimized out>, locals=0x7c7ff6e86440) at Python/ceval.c:1008

Output from running with PYTHON_LLTRACE=4 PYTHON_OPT_DEBUG=4:
830_abort_lltrace_opt_debug.txt

Found using lafleur.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Output from running 'python -VV' on the command line:

Python 3.15.0a3+ (heads/main-dirty:3cc57505e53, Dec 23 2025, 19:04:15) [Clang 21.1.2 (2ubuntu6)]

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)topic-JITtype-crashA hard crash of the interpreter, possibly with a core dump

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions