python / python/cpython

Make the JIT thread-safe

Abierto
#133,171 13 comentarios 13 reacciones 4 asignados Ver en GitHub

@Fidget-Spinner ya está trabajando en esto.

Desde el 8/11/2025.

interpreter-core performance topic-free-threading topic-JIT
Lenguaje dominante
Python
Estrellas
77.2k
Forks
35.9k
Métricas de merge de PR
Métricas de PR pendientes

Descripción

Currently, --enable-experimental-jit and --disable-gil can be configured together. However, the behavior in this configuration is probably surprising, and not what the user intends: the JIT is built, but never actually used.

I've been seeing a lot of people configuring these "bleeding edge" experimental builds now, and we even have one in CI (we've been using it to make sure the JIT build step isn't broken). Until the free-threaded build supports the JIT, we should start by erroring during the configure step for these builds in 3.14. I'll open a PR to do this soon.

For 3.15, the JIT should be updated to work on the free-threaded build. This shouldn't be done in a way that pessimizes the JIT in the default build... it will probably start with a bunch of #ifdef Py_GIL_DISABLED/#ifndef Py_GIL_DISABLED blocks, in order to at least get something working.

This isn't something that I am planning on working on personally. This isn't a good beginner issue either. If there is somebody with free-threading experience interested in learning more about the JIT and willing to take on this project, then that would be great. I can't claim deep free-threading knowledge, but I'm willing to walk you through how the JIT works, help identify what the potential thread-safety issues may be, and review/debug any PRs.

In my understanding, here's a very high-level triage of the current situation:

  • (phase1) JUMP_BACKWARD: We need to re-enable specialization for this instruction. This shouldn't be too hard, since we already have idioms for specialization on the free-threaded build.
  • (phase1) bytecodes.c: There are several instructions that are tier-two (JIT) only. These need to be audited for thread-safety.
  • (phase1) _PyOptimizer_Optimize: Finding space for and inserting executors into the code object needs to be done in a thread-safe way, which probably will involve locking the code object such that only one part of it can be compiled at a time.
  • (phase1) _PyExecutorObject: These are objects that manage JIT code. They are joined into a giant doubly-linked list, and are unlinked as they are invalidated or no longer needed. This list needs to be made thread-safe.
  • (phase1)translate_bytecode_to_trace: This shouldn't be too bad, since each thread has its own copy of the bytecode and inline caches (so we don't need to worry about concurrent mutations during tracing). Function inlining and for loop headers may need some attention.
  • (phase1)_PyJIT_Compile: This is probably fine, actually, which is a relief. The entire machine-code backend is stateless and self-contained. As long as mmap/mprotect/munmap/etc. are threadsafe, then we're okay. The generated code is immutable, and can be shared between threads without issue.
  • (phase2) _Py_uop_analyze_and_optimize is going to be where most of our time and ongoing effort is spent. Thankfully it's all optional (in theory), so we may just be able to turn it all off and selectively turn things back on. It consists of three passes:
    • remove_globals: This has the potential to be annoying, but I think it may not be too bad (as long as watchers are already thread-safe?).
    • optimize_uops: This is going to be the long tail, I think. This one is different, since we don't only care if the optimize_uops itself is thread-safe (easy), but also if our optimizations will be thread-safe at runtime (hard). We'll probably just end up #ifdef'ing out many of the bodies in optimizer_bytecodes.c and figuring out how to turn them back on (if at all).
    • remove_unneeded_uops: This already looks fine to me.

If stuff is missing, please add it to the list.

It may even be reasonable to stop the world for JIT compilation initially (just to get something working), then later introduce finer-grained locking as needed.

Linked PRs
  • gh-133179
  • gh-137800
  • gh-140038

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.