9421 Commits
Author SHA1 Message Date
mpage a9049ee4fb gh-160496: Clear inline values with atomic release stores (#160510) 2026-10-26 19:46:46 +05:30
Davi de Jesus 34889af658 gh-160588: Restore the gh-123022 check in the vendored mimalloc (#160589) 2026-10-24 20:49:51 +03:00
Neil Schemenauer 00c54508c6 gh-159564: Make weakref dereference lock-free. (#159578) 2026-10-24 14:56:31 +00:00
Pieter Eendebak 0dd6a4d417 gh-87613: Use AC vectorcall for weakref.ref() (#159470) 2026-10-24 13:31:45 +00:00
Christian Aurich Zanettini Martins eaab974e8a gh-159244: Fix crash in dict() on a concurrently mutated key/value pair (#159245)
In the free-threaded build, dict() and dict.update() checked that a
list key/value pair had two items and then read them with borrowed
references without holding its lock, so another thread could empty
the list in between and the items were read from a freed or NULL
array.
2026-10-24 20:02:10 +09:00
Christian Aurich Zanettini Martins 2507a7fa73 gh-159294: Fix crash when creating an ExceptionGroup fails with MemoryError (#159295) 2026-10-23 20:57:58 +00:00
Kumar Aditya b1e32ff4f3 gh-159580: use _Py_INCREF_TYPE in object.__class__ (#160424) 2026-10-23 08:33:57 +00:00
Cody MaloneyandClaude Opus 5.5 3fc4d1f9b3 gh-87613: Allow Argument Clinic vectorcall on heap types (#160115)
Heap types have no static type object so switch from `Py_Is` to an
assert that the shadowed `tp_new` / `tp_init` function is the expected
one to validate the vectorcall is only used with the right type.

Heap types can have zero-argument `__new__` and `__init__` so add
support  for that producing the same error message via a new helper
`_PyArg_NoPositionalStack()`.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 03:13:30 +00:00
Donghee Na 45538495be gh-114258: Update Argument Clinic for `__str__`. (gh-160402) 2026-10-23 02:31:41 +00:00
Dino Viehland 03cb1adb39 gh-158198: Fix crash when de-inlining dict while freeing owning object (#160114)
* gh-158198: Fix crash when de-inlining dict while freeing owning object
2026-10-22 15:55:35 -07:00
Jelle Zijlstra a076a55ad2 gh-159739: Keep descriptor metadata dictionaries alive during insertion (#160193)
The classmethod and staticmethod metadata setters dropped their reference to the descriptor dictionary before inserting the new value. A key comparison or value finalizer can replace the dictionary during insertion, leaving the operation using released memory. Keep the dictionary alive until insertion finishes. Backport to 3.15 and 3.14.
2026-10-22 15:26:16 -07:00
Jelle Zijlstra d98f2cba61 gh-159739: Protect list storage while reporting its size (#160196)
On free-threaded builds, list.__sizeof__() reads an allocation header through an atomically loaded storage pointer. The list's owner can resize and free that storage between the load and the header read, producing invalid size data or an invalid memory read. Hold the list lock while inspecting the allocation. Backport to 3.15 and 3.14.
2026-10-22 21:50:54 +00:00
Jelle Zijlstra 3e7393bdf5 gh-159739: Propagate float rounding allocation failures (#160195) 2026-10-22 19:35:48 +00:00
Edward Xu 60e956e18b gh-149816: Fix race between setattr and object.__dict__ update (#152296)
Fix race between `setattr` and `object.__dict__` update (#152296)
2026-10-22 10:44:20 -07:00
Jelle Zijlstra e67334ab07 gh-159739: Do not intern complex subclasses in code constants (#159980) 2026-10-22 07:40:51 -07:00
Jelle Zijlstra d36a3f6970 gh-159739: Release replaced type alias values (#160167)
A type alias can be evaluated again before an earlier evaluation finishes, either recursively or in another thread. The later completion overwrites the cached value without releasing it, permanently leaking that value; synchronize cache access and release the replaced value outside the lock. Backport to 3.15 and 3.14.
2026-10-22 14:05:16 +00:00
Shamil ac430e3285 gh-158304: Avoid creating StopIteration for every value yielded by an async generator (#158315) 2026-10-22 14:18:28 +05:30
Donghee Na 3b3c692295 gh-114258: Use Argument Clinic for `__hash__` (gh-160059) 2026-10-22 07:54:04 +00:00
Donghee Na 9f3d5067f3 gh-159111: Add missing downstream changes when upgrade to 2.5.2. (gh-160207) 2026-10-21 23:26:29 -07:00
Gregory P. Smith 5a63d35681 gh-160179: Leave bytearray empty when __init__() fails midway (GH-160180)
The list/tuple fast path and the buffer path resized the object before
filling it and did not undo the resize on error, leaving stale bytes.
2026-10-21 22:20:54 -07:00
Gregory P. Smith d4750a7751 gh-160162: Fix crash in int left shift with huge count on 32-bit (GH-160163)
Bound the shift count by MAX_LONG_DIGITS*PyLong_SHIFT instead of
PY_SSIZE_T_MAX*PyLong_SHIFT, so that the result size computed in
long_lshift1() cannot overflow Py_ssize_t.
2026-10-21 20:50:05 -07:00
Donghee Na c1c4c18dfc gh-114258: Use Argument Clinic for `__getitem__` (gh-160068) 2026-10-22 01:06:48 +00:00
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
Jason G 08500b05e1 gh-154318: Guard C recursion when hashing nested tuples and frozendicts (GH-154362)
* gh-154318: Guard C recursion when hashing nested tuples and frozendicts

tuple_hash() and frozendict_hash() fold each contained object's hash into
an accumulator with PyObject_Hash() inside an unguarded loop. For a deeply
nested tuple or frozendict this recurses back into the same function once
per level and overflows the C stack (SIGSEGV / STATUS_STACK_OVERFLOW)
instead of raising RecursionError.

Wrap both loops in _Py_EnterRecursiveCall() / _Py_LeaveRecursiveCall(), as
the sibling comparison and repr paths already do. The guard is placed after
the cached-hash early return, so repeated hashing of an already-hashed
tuple is unaffected.

This also covers types.GenericAlias, whose ga_hash() hashes its __args__
tuple and so crashed through tuple_hash().
2026-10-21 15:10:17 -07:00
Peter Bierma 5a17b2ecfd gh-114258: Use Argument Clinic for __add__/__iadd__ (GH-160051) 2026-10-21 21:59:07 +00:00
Peter Bierma fe70b06917 gh-114258: Use Argument Clinic for __mul__/__imul__ (GH-160049) 2026-10-21 20:17:22 +00:00
Asish KumarandStan Ulbrych a13d6dbe03 gh-148268: Avoid debug assertion in specialized list compares (#148309)
Co-authored-by: Stan Ulbrych <stan@python.org>
2026-10-21 18:12:42 +00:00
Peter Bierma 65b7e9444a gh-114258: Use Argument Clinic for __repr__ (GH-160011) 2026-10-21 18:06:57 +00:00
Peter Bierma 796b26b360 gh-114258: Use Argument Clinic for __setitem__ (GH-160048) 2026-10-21 17:09:15 +00:00
Jelle Zijlstra 9c649dbaa8 gh-159739: Keep generic alias arguments alive while formatting errors (#159981)
When a generic alias contains a list of parameters and an object claiming to be an unpacked type-variable tuple returns a non-tuple from `__typing_subst__`, the error path frees the temporary argument tuple before reading it to format a `TypeError`. That use-after-free can crash the interpreter instead of reporting the invalid substitution.
2026-10-20 21:33:19 -07:00
Jelle Zijlstra ebce4b70bf gh-159739: Release weak proxy operands on errors (#159968)
Backport to 3.15 and 3.14.
2026-10-20 21:32:50 -07:00
Jelle Zijlstra 4101d59902 gh-159739: Break reference cycles involving property objects (#159978) 2026-10-20 21:31:59 -07:00
Donghee Na f9c0e1ea27 gh-114258: Update AC to support @critical_section for tp_iternext (gh-159962) 2026-10-21 00:25:02 +00:00
Gregory P. Smith c3608845b6 gh-159739: Fix crash in _PyTuple_Resize() with an invalid size (GH-159804)
_PyTuple_Resize() did not validate newsize for non-empty tuples.

Raise SystemError for a negative size and MemoryError for a too-large size,
like PyTuple_New() already does for the empty-tuple path.
2026-10-20 16:00:14 -07:00
Neil Schemenauer 4bb1dadff4 gh-158197: Fix split dict iteration during concurrent deletion (gh-158686)
Read insertion order from the iterator's captured values snapshot instead
of re-reading ma_values and asserting against a concurrently changing
size. Retry under the dictionary lock when a value slot has been cleared.

Make insertion-order writes atomic and publish size changes with release
stores, pairing with the iterator's size load. Keep order-byte accesses
relaxed. Add _Py_atomic_store_uint8_release() and
FT_ATOMIC_STORE_UINT8_RELEASE() for this.
2026-10-20 12:33:27 -07:00
Jelle ZijlstraandJelle Zijlstra c8746492c5 gh-159739: Handle OrderedDict item iterator allocation failures (#159774)
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
2026-10-20 10:26:52 -07:00
Jelle ZijlstraandJelle Zijlstra 07df106f7e gh-159739: [typing] Handle generic alias construction errors (#159772)
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
2026-10-20 10:20:51 -07:00
Jelle ZijlstraandJelle Zijlstra 95f94d04d8 gh-159739: Reject the minimum dynamic formatting width (#159780)
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
2026-10-20 10:20:20 -07:00
Jelle ZijlstraandJelle Zijlstra d51e6e596b gh-159739: Initialize template iterator references before allocating (#159773)
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
2026-10-20 10:19:30 -07:00
Donghee Na 182bf2e72f gh-159462: Relax the thread check in _PyMem_mi_page_reclaimed() (gh-159807) 2026-10-20 09:40:52 -07:00
Kumar Aditya cb12c5e514 gh-157361: Implement aiter() in Python instead of C (#157687)
gh-157361: Implement aiter() in Python instead of C

Move both forms of aiter() into the frozen _pybuiltins module and remove
the C async_callable_iterator types. The callable form now returns an
iterator whose __anext__() is a plain coroutine, so call-graph tools can
see through it into the awaited result of the callable.
2026-10-20 15:33:36 +05:30
Donghee NaandVictor Stinner 4c73f50ca9 gh-159813: Add a fast path for None in PyUnicodeWriter_WriteRepr (gh-159814)
Co-authored-by: Victor Stinner <vstinner@python.org>
2026-10-19 21:00:42 -07:00
Jelle ZijlstraandJelle Zijlstra 9e262af9ae gh-159739: Handle module filename encoding errors (#159749)
Propagate UTF-8 conversion errors before copying the module filename.

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
2026-10-19 19:30:21 -07:00
Jelle Zijlstra 5b0ab21364 gh-159739: Check character formatting allocation failure (#159746)
Propagate the error from PyUnicode_FromOrdinal() before using the
result.
2026-10-19 19:29:25 -07:00
Jelle ZijlstraandJelle Zijlstra 14cd72b0ca gh-159739: Release tuple items if resizing fails (GH-159754)
Release the references still held by the original tuple when
reallocation fails.

Backport to 3.15 and 3.14.

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
2026-10-19 21:20:58 +00:00
Cody MaloneyandClaude Opus 5.5 6576fb46db gh-87613: Use AC vectorcall for bytes and bytearray (#158891)
* gh-87613: Use AC vectorcall for bytes and bytearray

Speeds up common construction of both objects. Enables optimizing
construction off uniquely referenced temporary objects.

Previously the argument tuples / dictionaries required by the call
protocol resulted in arguments never being unique temporaries. With
vectorcall they can be. Avoid copying by adopting the existing
allocation when possible.

Benchmark
Run on my linux dev machine: PGO+LTO, clang 23, --with-tail-call-interp

(note: AI Written, but I think sufficiently representative)
```python
"""bytes() and bytearray() construction.

temp/ passes a unique temporary (adopted, no copy); named/ binds the same
source to a name first so it is always copied.
"""
import pyperf

runner = pyperf.Runner()

runner.timeit('call/bytes()', 'bytes()')
runner.timeit('call/bytes(int)', 'bytes(16)')
runner.timeit('call/bytes(bytes)', "bytes(b'abcdefghabcdefgh')")
runner.timeit("call/bytes(str, 'ascii')", "bytes('abcdefgh', 'ascii')")
runner.timeit('call/bytearray()', 'bytearray()')
runner.timeit('call/bytearray(int)', 'bytearray(16)')
runner.timeit('call/bytearray(bytes)', "bytearray(b'abcdefghabcdefgh')")
runner.timeit("call/bytearray(str, 'ascii')",
              "bytearray('abcdefgh', 'ascii')")

for size_name, size in (('16B', 16), ('4KiB', 4096), ('1MiB', 1 << 20)):
    # Slicing in the statement makes a fresh unique temporary.
    setup = f"b = b'x' * {size}; ba = bytearray(b)"
    runner.timeit(f'temp/bytes(bytearray) {size_name}',
                  'bytes(ba[1:])', setup)
    runner.timeit(f'named/bytes(bytearray) {size_name}',
                  'x = ba[1:]; bytes(x); del x', setup)
    runner.timeit(f'temp/bytearray(bytes) {size_name}',
                  'bytearray(b[1:])', setup)
    runner.timeit(f'named/bytearray(bytes) {size_name}',
                  'x = b[1:]; bytearray(x); del x', setup)
    runner.timeit(f'temp/bytearray(bytearray) {size_name}',
                  'bytearray(ba[1:])', setup)
    runner.timeit(f'named/bytearray(bytearray) {size_name}',
                  'x = ba[1:]; bytearray(x); del x', setup)
```

| Benchmark                       | main    | patch                  |
|---------------------------------|:-------:|:----------------------:|
| temp/bytearray(bytearray) 1MiB  | 515 us  | 14.9 us: 34.53x faster |
| temp/bytearray(bytes) 1MiB      | 508 us  | 14.8 us: 34.27x faster |
| temp/bytes(bytearray) 1MiB      | 507 us  | 14.9 us: 34.05x faster |
| temp/bytearray(bytes) 4KiB      | 144 ns  | 79.5 ns: 1.81x faster  |
| temp/bytearray(bytearray) 4KiB  | 155 ns  | 94.7 ns: 1.63x faster  |
| temp/bytearray(bytes) 16B       | 56.4 ns | 36.1 ns: 1.56x faster  |
| temp/bytes(bytearray) 4KiB      | 150 ns  | 96.4 ns: 1.55x faster  |
| temp/bytearray(bytearray) 16B   | 64.1 ns | 47.3 ns: 1.35x faster  |
| call/bytes()                    | 14.7 ns | 11.1 ns: 1.32x faster  |
| call/bytes(int)                 | 31.5 ns | 24.3 ns: 1.29x faster  |
| call/bytes(str, 'ascii')        | 36.9 ns | 28.7 ns: 1.28x faster  |
| call/bytes(bytes)               | 34.3 ns | 27.3 ns: 1.26x faster  |
| temp/bytes(bytearray) 16B       | 59.4 ns | 49.5 ns: 1.20x faster  |
| call/bytearray(str, 'ascii')    | 45.6 ns | 39.1 ns: 1.17x faster  |
| call/bytearray(bytes)           | 44.3 ns | 38.9 ns: 1.14x faster  |
| call/bytearray(int)             | 41.7 ns | 37.3 ns: 1.12x faster  |
| named/bytearray(bytes) 16B      | 59.6 ns | 54.4 ns: 1.10x faster  |
| named/bytes(bytearray) 16B      | 61.3 ns | 56.2 ns: 1.09x faster  |
| named/bytearray(bytearray) 16B  | 65.3 ns | 60.9 ns: 1.07x faster  |
| named/bytes(bytearray) 4KiB     | 154 ns  | 148 ns: 1.04x faster   |
| call/bytearray()                | 22.1 ns | 21.4 ns: 1.03x faster  |
| named/bytearray(bytearray) 4KiB | 156 ns  | 151 ns: 1.03x faster   |
| named/bytearray(bytes) 4KiB     | 146 ns  | 143 ns: 1.02x faster   |
| Geometric mean                  | (ref)   | 1.77x faster           |

Benchmark hidden because not significant (3): named/bytes(bytearray) 1MiB,
named/bytearray(bytes) 1MiB, named/bytearray(bytearray) 1MiB

* Remove unique temporary adoption optimizations

PyUnstable_Object_IsUniqueReferencedTemporary() can't tell when a C
caller still holds a borrowed reference to the argument (for example
bisect.insort(lst, bytearray(b'abc')[1:], key=bytes)), so adopting the
buffer empties an object still in use. Leave the optimization for a
follow-up and keep this PR to the vectorcall change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 22:39:11 +02:00
he_tao cdf010b10c gh-158816: Skip useless hash table probe when deleting from split dicts (#158819)
delitem_common() unconditionally called lookdict_index() to locate the index slot in dk_indices that points at the entry being removed.

That slot is only used by the combined branch, to overwrite it with DKIX_DUMMY.  In split tables the whole probe sequence was redundant work.

Move the call into the combined branch and drop the now-pointless assert() for split tables.

Microbenchmark (free-threaded build, -Og, no PGO; deleting keys from materialized instance dicts; medians over 12 alternating runs):

    del d[k]           71.2 -> 69.2 ns/op   (-2.8%)
    d.pop(k)           98.9 -> 96.1 ns/op   (-2.8%)
    colliding hashes   78.0 -> 74.4 ns/op   (-4.6%)
2026-10-18 23:36:02 +09:00
Neil Schemenauer 010bebbf9f gh-159136: Avoid stop-the-world when setting function name attributes (gh-159269)
Setting __name__, __qualname__, __doc__ or __module__ on a function
stopped the world in the free-threaded build since gh-154826 and
gh-154851, making functools.wraps() orders of magnitude slower with
multiple threads.

Use the per-object critical section and _PyObject_XSetRefDelayed()
instead, as gen_set_name() already does.  Use acquire loads in the
readers and hold strong references across error reporting, tracing, and
eval-frame recording that may execute Python or detach the thread.  The
__code__, __defaults__, __kwdefaults__ and __closure__ setters still
stop the world to clear func_version.

Document synchronization requirements for direct field access and the
lifetime of borrowed function attributes.
2026-10-16 20:24:12 -07:00
Michael J. Sullivan 3646ea571f gh-159430: Add _PyObject_LookupSpecial error checks in bytes/weakref (GH-159432)
_PyObject_LookupSpecial needs a PyErr_Occurred() check to handle
failures while during the lookup, or else it can fail with a "returned
a result with an exception set" error.

Add some missing ones in bytes and weakref/
2026-10-15 17:14:02 +02:00
Neil Schemenauer b70a5128c4 gh-159431: Handle immortal objects in _PyObject_XDecRefDelayed() (gh-159433)
Skip immortal objects both when queueing and when processing the
queue, and remove the now redundant caller-side checks.
2026-10-14 14:11:48 -07:00