612 Commits
Author SHA1 Message Date
Donghee Na aff7a2e23b gh-159111: Update vendored mimalloc to v2.5.2 (gh-159112)
* Update vendored mimalloc to v2.5.2

Upgrade mimalloc from v2.1.2 to v2.5.2 as-is from upstream.

v2.1.2: https://github.com/microsoft/mimalloc/releases/tag/v2.1.2
v2.5.2: https://github.com/microsoft/mimalloc/releases/tag/v2.5.2

* Re-apply CPython-specific changes to mimalloc v2.5.2

Most of the previous downstream changes were upstreamed in mimalloc
v2.1.3 - v2.1.7 (heap tags, _mi_heap_init/_mi_tld_init, MI_PRIM_THREAD_ID,
sub-processes, heap walk optimizations, platform fixes) and are dropped.

Remaining CPython-specific changes, all marked with a "CPython" comment:

- QSBR delayed page freeing for free-threaded builds (gh-115103,
  gh-145615): mi_page_t/mi_heap_t fields and _PyMem_mi_* hooks in
  page.c, heap.c and segment.c.
- debug_offset: preserve the first bytes of a PyObject (ob_tid, refcount
  fields) when filling freed or uninitialized memory in debug builds
  (gh-115491).
- Atomic mi_block_t.next loads/stores to avoid TSAN reports (gh-129748).
- Relax the owning thread assertion in _mi_free_delayed_block for
  free-threaded builds, since the GC traverses heaps of other threads.
- Call _mi_heap_delayed_free_partial() in mi_heap_visit_blocks()
  (gh-112532).
- Only count reclaimed pages up to MI_MEDIUM_OBJ_SIZE_MAX as a
  "right page" in mi_segment_reclaim (gh-115103).
- Rename the weak _ZSt15get_new_handlerv symbol and disable the
  mi_is_in_heap_region debug warning.
- Zero-initialize _mi_page_empty instead of a positional initializer.

* Update the free-threaded build to mimalloc v2.5.2 changes

mimalloc v2.1.4 replaced the list of abandoned segments with per-arena
bitmaps and introduced sub-processes (mi_subproc_t) to keep abandoned
segments of separate interpreters apart. Use them instead of the
CPython-specific mi_abandoned_pool_t:

- Each interpreter owns a mi_subproc_t created in init_interpreter().
- tstate_mimalloc_bind() sets tld->segments.subproc and uses the
  upstream _mi_heap_init() signature.
- The GC and sys.getallocatedblocks() visit abandoned segments with
  _PyMem_mi_visit_abandoned_blocks(), the upstream cursor API without
  the mi_option_visit_abandoned requirement, while STW.

* Update NEWS.d

* fix MSAN

* fix TSAN

* fix test_cext

* Disable THP

* Address code review

* Address code review

* Address code review

* nit

* Address code review

* Address code review
2026-10-21 17:41:07 -07:00
Nathan Goldbaum 999855b07f gh-159041: Fix use-after-free in asyncio task tracking during thread state cleanup (#159073) 2026-10-19 10:16:36 +05:30
a6a63b6f5b gh-142349: Simplify lazy import resolution (#158282)
Co-authored-by: Petr Viktorin <encukou@gmail.com>
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
2026-10-01 16:20:45 +00:00
Himesh Rupchandani c3cb46870b gh-158364: Don't report other interpreters' threads in sys._current_frames (GH-158369) 2026-09-29 22:24:24 -04:00
Trent Nelson f156510960 gh-151518: Avoid STW starvation of attaching threads (#152826)
* gh-151518: Avoid STW starvation of attaching threads

Free-threaded stop-the-world pauses can otherwise starve a thread trying to reattach after it was suspended while detached.  A tight manual gc.collect() loop can release and immediately request the next stop-the-world pause, repeatedly parking the detached thread before it can attach and make progress.

Add a distinct _Py_THREAD_SUSPENDED_DETACHED state for tstates parked from DETACHED.  tstate_wait_attach() marks an attach waiter only after observing that detached-origin suspended state, and park_detached_threads() skips only those active waiters on later stop-the-world passes.  The ordinary successful tstate_try_attach() path remains the baseline CAS-only path.

Teach the related stop-the-world paths about both suspended states, including start_the_world() and tstate_delete_common().  Keep the new wait flag after the existing hot free-threaded _PyThreadStateImpl fields so their offsets do not move.

Add a free-threaded GC regression test that runs a subprocess with a tight gc.collect() worker and verifies the main thread can reattach after sleeping and stop the worker.

* gh-151518: Track attach waiters in the thread state

Represent active attach waiters with suspended-waiting and
detached-waiting states. Preserve waiter registration when the
world resumes, and keep passive detached threads immediately parkable.

Restore the thread-state padding and retain the single-CAS
uncontended attach path.

* gh-151518: Simplify the GC fairness regression

Use explicit warmup imports and a joined non-daemon collector.
Run the child through script_helper with a faulthandler watchdog
so a stalled attachment still fails with a traceback.

Describe the bug as a fairness issue in the NEWS entry.

* gh-151518: Exercise STW fairness directly

* gh-151518: Preserve attach waiters when resuming BRC suspensions

Share the waiter-aware resume transition between stop-the-world pauses
and biased reference count merging so a concurrently registering waiter
keeps its opportunity to attach.

Restore the support import needed by the new upstream GC regression and
align the thread-state constants.

* gh-151518: Strengthen the STW attach fairness regression

Hold each test pause for 10 ms and repeat pauses in C to reduce the
opportunities for a waiting thread to run between pause requests.

Clarify that parking rechecks the thread state before sleeping.

* gh-151518: Restrict STW test pauses to free-threaded builds

STW is a no-op in GIL builds. Avoid waiting in the helper there,
since WASI cannot perform the blocking futex operation.

* gh-151518: Wake only registered attach waiters

Avoid a parking-lot lookup when resuming a suspended thread that
has not tried to reattach. Use the old state from the successful CAS
so concurrent waiter registration still receives a wakeup.
2026-09-25 11:24:14 -07:00
Kumar Aditya 030e913a74 gh-157838: Merge biased refcounts on behalf of detached threads (#157839) 2026-09-23 22:08:56 +05:30
Kumar Aditya 6b1b90f7c4 gh-155725: Remove PyGILState_Ensure usage from tracemalloc (#156409) 2026-08-30 13:04:55 +05:30
Abdul Mohammad 94a75f74a1 gh-155504: Set the interpreter before fallible thread state initialization (#155590) 2026-08-16 08:42:24 +05:30
Neil Schemenauer 44e92d4a59 gh-155363: Fix QSBR slot leak on thread state creation failure (gh-155365)
In the free-threaded build, new_threadstate() reserves a QSBR thread-state
slot before it can still fail for other reasons, but the failure paths only
called free_threadstate(), which does not know about the reservation.
Restructure code so failure path doesn't leak.
2026-08-11 09:48:19 -07:00
Petr Viktorin c7b9a13a75 gh-154431: Revert "gh-154431: Fix data race in sys.audithook (#154462)" (GH-154769)
This commit caused a refleak.

This reverts commit 596cd5c5d7.
2026-07-27 16:00:20 +02:00
sobolevn 596cd5c5d7 gh-154431: Fix data race in sys.audithook (#154462) 2026-07-22 14:09:20 +02:00
Kumar Aditya daf09e17bf gh-145685: per-type method cache implementation (#150160) 2026-07-21 14:11:22 +05:30
sobolevn ecdef17730 gh-151126: Fix a possible crash during the startup with no memory under Py_STACKREF_DEBUG (#152478) 2026-06-30 14:28:17 +03:00
Pablo Galindo Salgado 8cda6ae2f1 gh-151613: Fix remote debugging frame cache ABA (#151614)
The remote debugging frame cache previously used only the last_profiled_frame address as its cache anchor. If a frame returned and a later frame reused the same _PyInterpreterFrame address, the profiler could accept a stale cache entry and splice parent frames from a different call chain into the current stack.

This adds a last_profiled_frame_seq counter next to last_profiled_frame, increments it when the anchor advances, stores it in frame cache entries, and validates cache hits against both the frame address and the sequence. Cache miss walks now copy stack chunks before storing new cache entries so stored continuations come from a stable snapshot. The new regression test exercises alternating call chains and checks that cached stacks never contain frames from both branches.
2026-06-27 16:56:31 +00:00
Neko Asakura 39bd44fc70 gh-148871: make LOAD_COMMON_CONSTANT use immortal stackref borrows (GH-149625) 2026-05-28 12:27:37 +01:00
Hai Zhu 441af3a934 gh-149335: Avoid JIT trace buffer asserts with overhead above FITNESS_INITIAL (GH-149633) 2026-05-21 15:57:31 +01:00
Alper 8a4895985f gh-145235: Make dict watcher API thread-safe for free-threaded builds (gh-145233)
In free-threaded builds, concurrent calls to PyDict_AddWatcher, PyDict_ClearWatcher, PyDict_Watch, and PyDict_Unwatch can race on the shared callback array and the per-dict watcher tags. This change adds a mutex to serialize watcher registration and removal, atomic operations for tag updates, and atomic acquire/release synchronization for callback dispatch in _PyDict_SendEvent.
2026-05-11 11:39:55 -04:00
2b7c28a440 gh-149101: Implement PEP 788 (GH-149116)
Co-authored-by: Petr Viktorin <encukou@gmail.com>
Co-authored-by: Sam Gross <colesbury@gmail.com>
2026-05-06 17:39:30 -04:00
Hai Zhu 618b726d68 gh-146073: Add fitness/exit quality mechanism for JIT trace frontend (GH-148089)
* Replaces ad-hoc logic for ending traces with a simple inequality: `fitness < exit_quality`
* Fitness starts high and is reduced for branches, backward edges, calls and trace length
* Exit quality reflect how good a spot that instruction is to end a trace. Closing a loop is very, specializable instructions are very low and the others in between.
2026-04-24 10:37:01 +01:00
Diego Russo 9633c5239d GH-126910: Build/link the JIT shim in the Python interpreter (#148872) 2026-04-23 12:23:18 +01:00
Dino Viehland c0af5c024b gh-146031: Allow keeping specialization enabled when specifying eval frame function (#146032)
Allow keeping specialization enabled when specifying eval frame function
2026-04-16 09:44:26 -07:00
Gregory P. SmithandClaude Opus 4.6 64afa947f4 gh-146302: make Py_IsInitialized() thread-safe and reflect true init completion (GH-146303)
## Summary

- Move the `runtime->initialized = 1` store from before `site.py` import to the end of `init_interp_main()`, so `Py_IsInitialized()` only returns true after initialization has fully completed
- Access `initialized` and `core_initialized` through new inline accessors using acquire/release atomics, to also protect from data race undefined behavior
- `PySys_AddAuditHook()` now uses the accessor, so with the flag move it correctly skips audit hook invocation during all init phases (matching the documented "after runtime initialization" behavior) ... We could argue that running these earlier would be good even if the intent was never explicitly expressed, but that'd be its own issue.

## Motivation

`Py_IsInitialized()` returned 1 while `Py_InitializeEx()` was still running — specifically, before `site.py` had been imported. See https://github.com/PyO3/pyo3/issues/5900 where a second thread could acquire the GIL and start executing Python with an incomplete `sys.path` because `site.py` hadn't finished.

The flag was also a plain `int` with no atomic operations, making concurrent reads a C-standard data race, though unlikely to manifest.

## Regression test:

The added test properly fails on `main` with `ERROR: Py_IsInitialized() was true during site import`.

---

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 21:54:23 +00:00
Ken Jin 328da67b2c gh-146073: Revert "gh-146073: Add fitness/exit quality mechanism for JIT trace frontend (GH-147966)" (#148082)
This reverts commit 198b04b75f.
2026-04-04 11:56:40 +00:00
Hai Zhu 198b04b75f gh-146073: Add fitness/exit quality mechanism for JIT trace frontend (GH-147966) 2026-04-03 23:54:30 +08:00
Ken Jin 1384f025f5 gh-126910: Verify that JIT stencils preserve frame pointer (GH-146524) 2026-03-28 03:38:54 +08:00
Diego Russo b60b9261b5 GH-126910: avoid reading the FP for getting the SP (GH-146521) 2026-03-28 01:52:48 +08:00
Ken Jin 3d0824aef2 gh-127958: Trace from RESUME in the JIT (GH-145905) 2026-03-17 00:18:59 +08:00
Hai Zhu 81ef1b7317 gh-144888: Replace bloom filter linked lists with continuous arrays to optimize executor invalidating performance (GH-145873) 2026-03-16 15:58:18 +00:00
T. Woutersandblurb-it[bot] 706fd4ec08 gh-142183: Cache one datachunk per tstate to prevent alloc/dealloc thrashing (#145789)
Cache one datachunk per tstate to prevent alloc/dealloc thrashing when repeatedly hitting the same call depth at exactly the wrong boundary.

---------

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
2026-03-11 15:46:16 +01:00
Hai Zhu 29840247ff gh-144068: fix JIT tracer memory leak when daemon thread exits (GH-144077) 2026-01-24 09:43:01 +00:00
Mark Shannon d77aaa7311 GH-139109: Partial reworking of JIT data structures (GH-144105)
* Halve size of buffers by reusing combined trace + optimizer buffers for TOS caching
* Add simple buffer struct for more maintainable handling of buffers
* Decouple JIT structs from thread state struct
* Ensure terminator is added to trace, when optimizer gives up
2026-01-22 10:55:49 +00:00
Donghee Na 27a7160b8b gh-141504: Move PYTHON_UOPS_OPTIMIZE to policy object (GH-144082) 2026-01-20 18:47:38 +00:00
Donghee Na 794f758cd8 gh-141504: Refactor policy object into a single opt_config (gh-143644) 2026-01-15 09:53:00 +09:00
Hai Zhu 94dbce1397 gh-138050: Use cold flag instead of warm flag in MAKE_WARM (GH-143827) 2026-01-14 10:27:33 +00:00
Ken Jin e0fb278064 gh-143421: Allocate all JIT state in one go (GH-143626) 2026-01-09 19:00:49 +00:00
Ken Jin b852236b26 gh-143421: Lazily allocate tracer code and opt buffers (GH-143597) 2026-01-09 16:56:19 +00:00
Hai ZhuandKumar Aditya aeb3403563 gh-143421: Move JitOptContext from stack allocation to per-thread heap allocation (GH-143536)
* move JitOptContext to _PyThreadStateImpl
* make _PyUOpInstruction buffer a part of _PyThreadStateImpl

Co-authored-by: Kumar Aditya <kumaraditya@python.org>
2026-01-08 19:38:21 +00:00
Sam Gross f11f5ebfe6 gh-129824: Fix data race on runtime->gilstate.check_enabled (gh-143530) 2026-01-07 17:56:14 -05:00
Donghee Na 12283f6373 gh-141504: Factor out tracing and optimization heuristics into a single object (gh-143381) 2026-01-03 15:22:14 +00:00
Diego Russo 685272eb8a JIT: Rename trampoline.c to shim.c (#142974) 2025-12-19 14:39:41 +00:00
Mark Shannon e4058d7cb1 GH-142513: Reimplement executor management (GH-142931)
* Invalidating an executor does not cause arbitrary code to run
* Executors are only freed at safe points
2025-12-18 16:43:44 +00:00
Kevin Wang 49b1fb43f6 gh-142048: Fix lost gc allocations count on thread cleanup (#142233) 2025-12-10 07:29:40 +00:00
Pablo Galindo Salgado d6d850df89 gh-138122: Don't sample partial frame chains (#141912) 2025-12-07 15:53:48 +00:00
Ken Jin 4fa80ce74c gh-139109: A new tracing JIT compiler frontend for CPython (GH-140310)
This PR changes the current JIT model from trace projection to trace recording. Benchmarking: better pyperformance (about 1.7% overall) geomean versus current https://raw.githubusercontent.com/facebookexperimental/free-threading-benchmarking/refs/heads/main/results/bm-20251108-3.15.0a1%2B-7e2bc1d-JIT/bm-20251108-vultr-x86_64-Fidget%252dSpinner-tracing_jit-3.15.0a1%2B-7e2bc1d-vs-base.svg, 100% faster Richards on the most improved benchmark versus the current JIT. Slowdown of about 10-15% on the worst benchmark versus the current JIT. **Note: the fastest version isn't the one merged, as it relies on fixing bugs in the specializing interpreter, which is left to another PR**. The speedup in the merged version is about 1.1%. https://raw.githubusercontent.com/facebookexperimental/free-threading-benchmarking/refs/heads/main/results/bm-20251112-3.15.0a1%2B-f8a764a-JIT/bm-20251112-vultr-x86_64-Fidget%252dSpinner-tracing_jit-3.15.0a1%2B-f8a764a-vs-base.svg

Stats: 50% more uops executed, 30% more traces entered the last time we ran them. It also suggests our trace lengths for a real trace recording JIT are too short, as a lot of trace too long aborts https://github.com/facebookexperimental/free-threading-benchmarking/blob/main/results/bm-20251023-3.15.0a1%2B-eb73378-CLANG%2CJIT/bm-20251023-vultr-x86_64-Fidget%252dSpinner-tracing_jit-3.15.0a1%2B-eb73378-pystats-vs-base.md .

This new JIT frontend is already able to record/execute significantly more instructions than the previous JIT frontend. In this PR, we are now able to record through custom dunders, simple object creation, generators, etc. None of these were done by the old JIT frontend. Some custom dunders uops were discovered to be broken as part of this work gh-140277

The optimizer stack space check is disabled, as it's no longer valid to deal with underflow.

Pros:
* Ignoring the generated tracer code as it's automatically created, this is only additional 1k lines of code. The maintenance burden is handled by the DSL and code generator.
* `optimizer.c` is now significantly simpler, as we don't have to do strange things to recover the bytecode from a trace.
* The new JIT frontend is able to handle a lot more control-flow than the old one.
* Tracing is very low overhead. We use the tail calling interpreter/computed goto interpreter to switch between tracing mode and non-tracing mode. I call this mechanism dual dispatch, as we have two dispatch tables dispatching to each other. Specialization is still enabled while tracing.
* Better handling of polymorphism. We leverage the specializing interpreter for this.

Cons:
* (For now) requires tail calling interpreter or computed gotos. This means no Windows JIT for now :(. Not to fret, tail calling is coming soon to Windows though https://github.com/python/cpython/pull/139962

Design:
* After each instruction, the `record_previous_inst` function/label is executed. This does as the name suggests.
* The tracing interpreter lowers bytecode to uops directly so that it can obtain "fresh" values at the point of lowering.
* The tracing version behaves nearly identical to the normal interpreter, in fact it even has specialization! This allows it to run without much of a slowdown when tracing. The actual cost of tracing is only a function call and writes to memory.
* The tracing interpreter uses the specializing interpreter's deopt to naturally form the side exit chains. This allows it to side exit chain effectively, without repeating much code. We force a re-specializing when tracing a deopt.
* The tracing interpreter can even handle goto errors/exceptions, but I chose to disable them for now as it's not tested.
* Because we do not share interpreter dispatch, there is should be no significant slowdown to the original specializing interpreter on tailcall and computed got with JIT disabled. With JIT enabled, there might be a slowdown in the form of the JIT trying to trace.
* Things that could have dynamic instruction pointer effects are guarded on. The guard deopts to a new instruction --- `_DYNAMIC_EXIT`.
2025-11-13 18:08:32 +00:00
Victor StinnerandPetr Viktorin b99db92dde gh-139653: Add PyUnstable_ThreadState_SetStackProtection() (#139668)
Add PyUnstable_ThreadState_SetStackProtection() and
PyUnstable_ThreadState_ResetStackProtection() functions
to set the stack base address and stack size of a Python
thread state.

Co-authored-by: Petr Viktorin <encukou@gmail.com>
2025-11-13 17:30:50 +01:00
Neil Schemenauer c98c5b3449 gh-131253: free-threaded build support for pystats (gh-137189)
Allow the --enable-pystats build option to be used with free-threading.  The
stats are now stored on a per-interpreter basis, rather than process global.
For free-threaded builds, the stats structure is allocated per-thread and
then periodically merged into the per-interpreter stats structure (on thread
exit or when the reporting function is called). Most of the pystats related
code has be moved into the file Python/pystats.c.
2025-11-03 11:36:37 -08:00
Peter Bierma 2cefa70eb9 gh-140544: Always assume that thread locals are available (GH-140690)
Python has required thread local support since 3.12 (see GH-103324). By assuming that thread locals are always supported, we can improve the performance of third-party extensions by allowing them to access the attached thread and interpreter states directly.
2025-10-28 09:07:19 -04:00
alm 1753ccb432 gh-138050: [WIP] JIT - Streamline MAKE_WARM - move coldness check to executor creation (GH-138240) 2025-10-27 16:37:37 +00:00
Kumar Aditya ef4665f918 gh-140544: store pointer to interpreter state as a thread local for fast access (#140573) 2025-10-25 19:56:07 +05:30
Kumar Aditya ebf9938496 gh-140544: cleanup HAVE_THREAD_LOCAL checks in pystate.c (#140547) 2025-10-24 14:23:06 +00:00