diff --git a/.github/workflows/jit.yml b/.github/workflows/jit.yml
index 52f7d0d2b3df95..80e4ae603a2614 100644
--- a/.github/workflows/jit.yml
+++ b/.github/workflows/jit.yml
@@ -134,6 +134,34 @@ jobs:
make all --jobs 4
./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
+ jit-with-disabled-gil:
+ name: Free-Threaded (Debug)
+ needs: interpreter
+ runs-on: ubuntu-24.04
+ timeout-minutes: 90
+ strategy:
+ fail-fast: false
+ matrix:
+ llvm:
+ - 19
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ persist-credentials: false
+ - uses: actions/setup-python@v5
+ with:
+ python-version: '3.11'
+ - name: Build with JIT enabled and GIL disabled
+ run: |
+ sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }}
+ export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH"
+ ./configure --enable-experimental-jit --with-pydebug --disable-gil
+ make all --jobs 4
+ - name: Run tests
+ run: |
+ ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
+ continue-on-error: true
+
no-opt-jit:
name: JIT without optimizations (Debug)
needs: interpreter
@@ -160,31 +188,3 @@ jobs:
- name: Run tests without optimizations
run: |
PYTHON_UOPS_OPTIMIZE=0 ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
-
- # XXX: GH-133171
- # jit-with-disabled-gil:
- # name: Free-Threaded (Debug)
- # needs: interpreter
- # runs-on: ubuntu-24.04
- # timeout-minutes: 90
- # strategy:
- # fail-fast: false
- # matrix:
- # llvm:
- # - 19
- # steps:
- # - uses: actions/checkout@v4
- # with:
- # persist-credentials: false
- # - uses: actions/setup-python@v5
- # with:
- # python-version: '3.11'
- # - name: Build with JIT enabled and GIL disabled
- # run: |
- # sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }}
- # export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH"
- # ./configure --enable-experimental-jit --with-pydebug --disable-gil
- # make all --jobs 4
- # - name: Run tests
- # run: |
- # ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3
diff --git a/Doc/c-api/weakref.rst b/Doc/c-api/weakref.rst
index c3c6cf413dcef5..14ec9d951c4a5f 100644
--- a/Doc/c-api/weakref.rst
+++ b/Doc/c-api/weakref.rst
@@ -64,30 +64,6 @@ as much as it can.
.. versionadded:: 3.13
-.. c:function:: PyObject* PyWeakref_GetObject(PyObject *ref)
-
- Return a :term:`borrowed reference` to the referenced object from a weak
- reference, *ref*. If the referent is no longer live, returns ``Py_None``.
-
- .. note::
-
- This function returns a :term:`borrowed reference` to the referenced object.
- This means that you should always call :c:func:`Py_INCREF` on the object
- except when it cannot be destroyed before the last usage of the borrowed
- reference.
-
- .. deprecated-removed:: 3.13 3.15
- Use :c:func:`PyWeakref_GetRef` instead.
-
-
-.. c:function:: PyObject* PyWeakref_GET_OBJECT(PyObject *ref)
-
- Similar to :c:func:`PyWeakref_GetObject`, but does no error checking.
-
- .. deprecated-removed:: 3.13 3.15
- Use :c:func:`PyWeakref_GetRef` instead.
-
-
.. c:function:: int PyWeakref_IsDead(PyObject *ref)
Test if the weak reference *ref* is dead. Returns 1 if the reference is
diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat
index 144c5608e07426..44ee2586301259 100644
--- a/Doc/data/refcounts.dat
+++ b/Doc/data/refcounts.dat
@@ -2947,12 +2947,6 @@ PyWeakref_CheckProxy:PyObject*:ob:0:
PyWeakref_CheckRef:int:::
PyWeakref_CheckRef:PyObject*:ob:0:
-PyWeakref_GET_OBJECT:PyObject*::0:
-PyWeakref_GET_OBJECT:PyObject*:ref:0:
-
-PyWeakref_GetObject:PyObject*::0:
-PyWeakref_GetObject:PyObject*:ref:0:
-
PyWeakref_GetRef:int:::
PyWeakref_GetRef:PyObject*:ref:0:
PyWeakref_GetRef:PyObject**:pobj:+1:
diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat
index 3f51254494c654..7ad5f3ecfab5b4 100644
--- a/Doc/data/stable_abi.dat
+++ b/Doc/data/stable_abi.dat
@@ -830,7 +830,6 @@ member,PyVarObject.ob_size,3.2,,
func,PyVectorcall_Call,3.12,,
func,PyVectorcall_NARGS,3.12,,
type,PyWeakReference,3.2,,opaque
-func,PyWeakref_GetObject,3.2,,
func,PyWeakref_GetRef,3.13,,
func,PyWeakref_NewProxy,3.2,,
func,PyWeakref_NewRef,3.2,,
diff --git a/Doc/deprecations/c-api-pending-removal-in-3.15.rst b/Doc/deprecations/c-api-pending-removal-in-3.15.rst
index 8db3631cab31f1..9927b876760d34 100644
--- a/Doc/deprecations/c-api-pending-removal-in-3.15.rst
+++ b/Doc/deprecations/c-api-pending-removal-in-3.15.rst
@@ -3,7 +3,7 @@ Pending removal in Python 3.15
* The :c:func:`!PyImport_ImportModuleNoBlock`:
Use :c:func:`PyImport_ImportModule` instead.
-* :c:func:`PyWeakref_GetObject` and :c:func:`PyWeakref_GET_OBJECT`:
+* :c:func:`!PyWeakref_GetObject` and :c:func:`!PyWeakref_GET_OBJECT`:
Use :c:func:`PyWeakref_GetRef` instead. The `pythoncapi-compat project
`__ can be used to get
:c:func:`PyWeakref_GetRef` on Python 3.12 and older.
diff --git a/Doc/howto/free-threading-extensions.rst b/Doc/howto/free-threading-extensions.rst
index 577e283bb9cb4c..3776132c685414 100644
--- a/Doc/howto/free-threading-extensions.rst
+++ b/Doc/howto/free-threading-extensions.rst
@@ -173,9 +173,9 @@ that return :term:`strong references `.
+-----------------------------------+-----------------------------------+
| :c:func:`PyDict_Next` | none (see :ref:`PyDict_Next`) |
+-----------------------------------+-----------------------------------+
-| :c:func:`PyWeakref_GetObject` | :c:func:`PyWeakref_GetRef` |
+| :c:func:`!PyWeakref_GetObject` | :c:func:`PyWeakref_GetRef` |
+-----------------------------------+-----------------------------------+
-| :c:func:`PyWeakref_GET_OBJECT` | :c:func:`PyWeakref_GetRef` |
+| :c:func:`!PyWeakref_GET_OBJECT` | :c:func:`PyWeakref_GetRef` |
+-----------------------------------+-----------------------------------+
| :c:func:`PyImport_AddModule` | :c:func:`PyImport_AddModuleRef` |
+-----------------------------------+-----------------------------------+
diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst
index 90a695ef937f75..8c5c87a7ef16e4 100644
--- a/Doc/library/codecs.rst
+++ b/Doc/library/codecs.rst
@@ -1339,7 +1339,7 @@ particular, the following variants typically exist:
+-----------------+--------------------------------+--------------------------------+
| utf_8 | U8, UTF, utf8, cp65001 | all languages |
+-----------------+--------------------------------+--------------------------------+
-| utf_8_sig | | all languages |
+| utf_8_sig | utf8-sig | all languages |
+-----------------+--------------------------------+--------------------------------+
.. versionchanged:: 3.4
diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst
index 2dd205dd2b8831..a095d887352127 100644
--- a/Doc/whatsnew/3.11.rst
+++ b/Doc/whatsnew/3.11.rst
@@ -2673,7 +2673,7 @@ Removed
(Contributed by Victor Stinner in :issue:`45474`.)
-* Exclude :c:func:`PyWeakref_GET_OBJECT` from the limited C API. It never
+* Exclude :c:func:`!PyWeakref_GET_OBJECT` from the limited C API. It never
worked since the :c:type:`!PyWeakReference` structure is opaque in the
limited C API.
(Contributed by Victor Stinner in :issue:`35134`.)
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index 67fec4ebc4a234..fbb27adbf9969c 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -2246,7 +2246,7 @@ New Features
(Contributed by Serhiy Storchaka in :gh:`110289`.)
* Add the :c:func:`PyWeakref_GetRef` function
- as an alternative to :c:func:`PyWeakref_GetObject`
+ as an alternative to :c:func:`!PyWeakref_GetObject`
that returns a :term:`strong reference`
or ``NULL`` if the referent is no longer live.
(Contributed by Victor Stinner in :gh:`105927`.)
@@ -2531,8 +2531,8 @@ Deprecated C APIs
are just aliases to :c:type:`!wchar_t`.
(Contributed by Victor Stinner in :gh:`105156`.)
-* Deprecate the :c:func:`PyWeakref_GetObject` and
- :c:func:`PyWeakref_GET_OBJECT` functions,
+* Deprecate the :c:func:`!PyWeakref_GetObject` and
+ :c:func:`!PyWeakref_GET_OBJECT` functions,
which return a :term:`borrowed reference`.
Replace them with the new :c:func:`PyWeakref_GetRef` function,
which returns a :term:`strong reference`.
diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst
index 7b146621dddcfa..d5d387d9a0aaa7 100644
--- a/Doc/whatsnew/3.15.rst
+++ b/Doc/whatsnew/3.15.rst
@@ -869,6 +869,11 @@ Removed C APIs
of :c:func:`PyImport_ImportModule`.
(Contributed by Bénédikt Tran in :gh:`133644`.)
+* :c:func:`!PyWeakref_GetObject` and :c:macro:`!PyWeakref_GET_OBJECT`:
+ use :c:func:`PyWeakref_GetRef` instead. The |pythoncapi_compat_project|
+ can be used to get :c:func:`!PyWeakref_GetRef` on Python 3.12 and older.
+ (Contributed by Bénédikt Tran in :gh:`133644`.)
+
* Remove deprecated :c:func:`!PySys_ResetWarnOptions`.
Clear :data:`sys.warnoptions` and :data:`!warnings.filters` instead.
diff --git a/Include/cpython/weakrefobject.h b/Include/cpython/weakrefobject.h
index da8e77cddaca63..e0711407cee470 100644
--- a/Include/cpython/weakrefobject.h
+++ b/Include/cpython/weakrefobject.h
@@ -47,20 +47,3 @@ PyAPI_FUNC(void) _PyWeakref_ClearRef(PyWeakReference *self);
// Test if a weak reference is dead.
PyAPI_FUNC(int) PyWeakref_IsDead(PyObject *ref);
-
-Py_DEPRECATED(3.13) static inline PyObject* PyWeakref_GET_OBJECT(PyObject *ref_obj)
-{
- PyWeakReference *ref = _PyWeakref_CAST(ref_obj);
- PyObject *obj = ref->wr_object;
- // Explanation for the Py_REFCNT() check: when a weakref's target is part
- // of a long chain of deallocations which triggers the trashcan mechanism,
- // clearing the weakrefs can be delayed long after the target's refcount
- // has dropped to zero. In the meantime, code accessing the weakref will
- // be able to "see" the target object even though it is supposed to be
- // unreachable. See issue gh-60806.
- if (Py_REFCNT(obj) > 0) {
- return obj;
- }
- return Py_None;
-}
-#define PyWeakref_GET_OBJECT(ref) PyWeakref_GET_OBJECT(_PyObject_CAST(ref))
diff --git a/Include/internal/pycore_stackref.h b/Include/internal/pycore_stackref.h
index c4e8f10fe05276..062834368bcd29 100644
--- a/Include/internal/pycore_stackref.h
+++ b/Include/internal/pycore_stackref.h
@@ -464,6 +464,12 @@ PyStackRef_CLOSE_SPECIALIZED(_PyStackRef ref, destructor destruct)
PyStackRef_CLOSE(ref);
}
+static inline int
+PyStackRef_RefcountOnObject(_PyStackRef ref)
+{
+ return (ref.bits & Py_TAG_REFCNT) == 0;
+}
+
static inline _PyStackRef
PyStackRef_DUP(_PyStackRef stackref)
{
diff --git a/Include/weakrefobject.h b/Include/weakrefobject.h
index a6e71eb178b124..17fac62961c0fb 100644
--- a/Include/weakrefobject.h
+++ b/Include/weakrefobject.h
@@ -27,7 +27,6 @@ PyAPI_FUNC(PyObject *) PyWeakref_NewRef(PyObject *ob,
PyObject *callback);
PyAPI_FUNC(PyObject *) PyWeakref_NewProxy(PyObject *ob,
PyObject *callback);
-Py_DEPRECATED(3.13) PyAPI_FUNC(PyObject *) PyWeakref_GetObject(PyObject *ref);
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030D0000
PyAPI_FUNC(int) PyWeakref_GetRef(PyObject *ref, PyObject **pobj);
diff --git a/Lib/encodings/aliases.py b/Lib/encodings/aliases.py
index 474d74ea3dc191..f4b1b8dd43f920 100644
--- a/Lib/encodings/aliases.py
+++ b/Lib/encodings/aliases.py
@@ -17,7 +17,7 @@
"""
aliases = {
- # Please keep this list sorted alphabetically by value !
+ # Please keep this list sorted alphabetically by value!
# ascii codec
'646' : 'ascii',
@@ -554,6 +554,9 @@
'utf8_ucs4' : 'utf_8',
'cp65001' : 'utf_8',
+ # utf_8_sig codec
+ 'utf8_sig' : 'utf_8_sig',
+
# uu_codec codec
'uu' : 'uu_codec',
diff --git a/Lib/pdb.py b/Lib/pdb.py
index a783583a2b1c38..fd48882e28fe7c 100644
--- a/Lib/pdb.py
+++ b/Lib/pdb.py
@@ -100,7 +100,6 @@
import _pyrepl.utils
from contextlib import ExitStack, closing, contextmanager
-from rlcompleter import Completer
from types import CodeType
from warnings import deprecated
@@ -364,6 +363,15 @@ def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None,
readline.set_completer_delims(' \t\n`@#%^&*()=+[{]}\\|;:\'",<>?')
except ImportError:
pass
+
+ # GH-138860
+ # We need to lazy-import rlcompleter to avoid deadlock
+ # We cannot import it during self.complete* methods because importing
+ # rlcompleter for the first time will overwrite readline's completer
+ # So we import it here and save the Completer class
+ from rlcompleter import Completer
+ self.RlCompleter = Completer
+
self.allow_kbdint = False
self.nosigint = nosigint
# Consider these characters as part of the command so when the users type
@@ -1186,10 +1194,9 @@ def completedefault(self, text, line, begidx, endidx):
conv_vars = self.curframe.f_globals.get('__pdb_convenience_variables', {})
return [f"${name}" for name in conv_vars if name.startswith(text[1:])]
- # Use rlcompleter to do the completion
state = 0
matches = []
- completer = Completer(self.curframe.f_globals | self.curframe.f_locals)
+ completer = self.RlCompleter(self.curframe.f_globals | self.curframe.f_locals)
while (match := completer.complete(text, state)) is not None:
matches.append(match)
state += 1
@@ -1204,8 +1211,8 @@ def _enable_rlcompleter(self, ns):
return
try:
+ completer = self.RlCompleter(ns)
old_completer = readline.get_completer()
- completer = Completer(ns)
readline.set_completer(completer.complete)
yield
finally:
diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py
index 6b74e21ad73d1a..9a7d855003551a 100644
--- a/Lib/test/test_pdb.py
+++ b/Lib/test/test_pdb.py
@@ -4688,6 +4688,28 @@ def foo():
stdout, _ = self._run_script(script, commands)
self.assertIn("42", stdout)
+ def test_readline_not_imported(self):
+ """GH-138860
+ Directly or indirectly importing readline might deadlock a subprocess
+ if it's launched with process_group=0 or preexec_fn=setpgrp
+
+ It's also a pattern that readline is never imported with just import pdb.
+
+ This test is to ensure that readline is not imported for import pdb.
+ It's possible that we have a good reason to do that in the future.
+ """
+
+ script = textwrap.dedent("""
+ import sys
+ import pdb
+ if "readline" in sys.modules:
+ print("readline imported")
+ """)
+ commands = ""
+ stdout, stderr = self._run_script(script, commands)
+ self.assertNotIn("readline imported", stdout)
+ self.assertEqual(stderr, "")
+
@support.force_colorized_test_class
class PdbTestColorize(unittest.TestCase):
diff --git a/Misc/NEWS.d/3.11.0a2.rst b/Misc/NEWS.d/3.11.0a2.rst
index 48cf2c1e428d87..12e03b46db0b3f 100644
--- a/Misc/NEWS.d/3.11.0a2.rst
+++ b/Misc/NEWS.d/3.11.0a2.rst
@@ -1188,7 +1188,7 @@ context objects can now be disabled.
.. nonce: Z0Zk_m
.. section: C API
-Exclude :c:func:`PyWeakref_GET_OBJECT` from the limited C API. It never
+Exclude :c:func:`!PyWeakref_GET_OBJECT` from the limited C API. It never
worked since the :c:type:`!PyWeakReference` structure is opaque in the
limited C API.
diff --git a/Misc/NEWS.d/3.13.0a1.rst b/Misc/NEWS.d/3.13.0a1.rst
index a3aa7353a1bba1..a5f0161e8f591e 100644
--- a/Misc/NEWS.d/3.13.0a1.rst
+++ b/Misc/NEWS.d/3.13.0a1.rst
@@ -6458,8 +6458,8 @@ Victor Stinner.
.. nonce: GRxZtI
.. section: C API
-Deprecate the :c:func:`PyWeakref_GetObject` and
-:c:func:`PyWeakref_GET_OBJECT` functions: use the new
+Deprecate the :c:func:`!PyWeakref_GetObject` and
+:c:func:`!PyWeakref_GET_OBJECT` functions: use the new
:c:func:`PyWeakref_GetRef` function instead. Patch by Victor Stinner.
..
@@ -6470,7 +6470,7 @@ Deprecate the :c:func:`PyWeakref_GetObject` and
.. section: C API
Add :c:func:`PyWeakref_GetRef` function: similar to
-:c:func:`PyWeakref_GetObject` but returns a :term:`strong reference`, or
+:c:func:`!PyWeakref_GetObject` but returns a :term:`strong reference`, or
``NULL`` if the referent is no longer live. Patch by Victor Stinner.
..
diff --git a/Misc/NEWS.d/next/C_API/2025-05-08-12-40-59.gh-issue-133644.FNexLJ.rst b/Misc/NEWS.d/next/C_API/2025-05-08-12-40-59.gh-issue-133644.FNexLJ.rst
new file mode 100644
index 00000000000000..71f1eaa5290d46
--- /dev/null
+++ b/Misc/NEWS.d/next/C_API/2025-05-08-12-40-59.gh-issue-133644.FNexLJ.rst
@@ -0,0 +1,3 @@
+Remove deprecated function :c:func:`!PyWeakref_GetObject` and macro
+:c:macro:`!PyWeakref_GET_OBJECT`. Use :c:func:`PyWeakref_GetRef` instead.
+Patch by Bénédikt Tran.
diff --git a/Misc/NEWS.d/next/Library/2025-07-11-08-15-17.gh-issue-83336.ptpmq7.rst b/Misc/NEWS.d/next/Library/2025-07-11-08-15-17.gh-issue-83336.ptpmq7.rst
new file mode 100644
index 00000000000000..022ff664ed94df
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-07-11-08-15-17.gh-issue-83336.ptpmq7.rst
@@ -0,0 +1 @@
+``utf8_sig`` is now aliased to :mod:`encodings.utf_8_sig`
diff --git a/Misc/NEWS.d/next/Library/2025-09-20-17-50-31.gh-issue-138860.Y9JXap.rst b/Misc/NEWS.d/next/Library/2025-09-20-17-50-31.gh-issue-138860.Y9JXap.rst
new file mode 100644
index 00000000000000..0903eb71ae4346
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-09-20-17-50-31.gh-issue-138860.Y9JXap.rst
@@ -0,0 +1 @@
+Lazy import :mod:`rlcompleter` in :mod:`pdb` to avoid deadlock in subprocess.
diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml
index d651e0fac111b1..4a03cc76f5e1e9 100644
--- a/Misc/stable_abi.toml
+++ b/Misc/stable_abi.toml
@@ -1600,6 +1600,7 @@
added = '3.2'
[function.PyWeakref_GetObject]
added = '3.2'
+ abi_only = true
[function.PyWeakref_NewProxy]
added = '3.2'
[function.PyWeakref_NewRef]
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index a5c4604056ab4e..508ef55511e49d 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -2206,9 +2206,8 @@ test_macros(PyObject *self, PyObject *Py_UNUSED(args))
static PyObject *
test_weakref_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
- // Ignore PyWeakref_GetObject() deprecation, we test it on purpose
- _Py_COMP_DIAG_PUSH
- _Py_COMP_DIAG_IGNORE_DEPR_DECLS
+ // Get the function (removed in 3.15) from the stable ABI.
+ PyAPI_FUNC(PyObject *) PyWeakref_GetObject(PyObject *);
// Create a new heap type, create an instance of this type, and delete the
// type. This object supports weak references.
@@ -2249,19 +2248,12 @@ test_weakref_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
ref = PyWeakref_GetObject(weakref); // borrowed ref
assert(ref == obj);
- // test PyWeakref_GET_OBJECT(), reference is alive
- ref = PyWeakref_GET_OBJECT(weakref); // borrowed ref
- assert(ref == obj);
-
// delete the referenced object: clear the weakref
assert(Py_REFCNT(obj) == 1);
Py_DECREF(obj);
assert(PyWeakref_IsDead(weakref));
- // test PyWeakref_GET_OBJECT(), reference is dead
- assert(PyWeakref_GET_OBJECT(weakref) == Py_None);
-
// test PyWeakref_GetRef(), reference is dead
ref = UNINITIALIZED_PTR;
assert(PyWeakref_GetRef(weakref, &ref) == 0);
@@ -2312,8 +2304,6 @@ test_weakref_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
Py_DECREF(weakref);
Py_RETURN_NONE;
-
- _Py_COMP_DIAG_POP
}
struct simpletracer_data {
diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c
index bd4c4ac9b3475a..61fa3ddad0bfd8 100644
--- a/Objects/weakrefobject.c
+++ b/Objects/weakrefobject.c
@@ -964,7 +964,8 @@ PyWeakref_GetRef(PyObject *ref, PyObject **pobj)
}
-PyObject *
+/* removed in 3.15, but kept for stable ABI compatibility */
+PyAPI_FUNC(PyObject *)
PyWeakref_GetObject(PyObject *ref)
{
if (ref == NULL || !PyWeakref_Check(ref)) {
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 9b993188fb73c7..f9f14322df0a5e 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -2940,9 +2940,10 @@ dummy_func(
};
tier1 op(_SPECIALIZE_JUMP_BACKWARD, (--)) {
- #if ENABLE_SPECIALIZATION
+ #if ENABLE_SPECIALIZATION_FT
if (this_instr->op.code == JUMP_BACKWARD) {
- this_instr->op.code = tstate->interp->jit ? JUMP_BACKWARD_JIT : JUMP_BACKWARD_NO_JIT;
+ uint8_t desired = tstate->interp->jit ? JUMP_BACKWARD_JIT : JUMP_BACKWARD_NO_JIT;
+ FT_ATOMIC_STORE_UINT8_RELAXED(this_instr->op.code, desired);
// Need to re-dispatch so the warmup counter isn't off by one:
next_instr = this_instr;
DISPATCH_SAME_OPARG();
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index e33d15f2e51e16..79328a7b725613 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -7589,9 +7589,10 @@
/* Skip 1 cache entry */
// _SPECIALIZE_JUMP_BACKWARD
{
- #if ENABLE_SPECIALIZATION
+ #if ENABLE_SPECIALIZATION_FT
if (this_instr->op.code == JUMP_BACKWARD) {
- this_instr->op.code = tstate->interp->jit ? JUMP_BACKWARD_JIT : JUMP_BACKWARD_NO_JIT;
+ uint8_t desired = tstate->interp->jit ? JUMP_BACKWARD_JIT : JUMP_BACKWARD_NO_JIT;
+ FT_ATOMIC_STORE_UINT8_RELAXED(this_instr->op.code, desired);
next_instr = this_instr;
DISPATCH_SAME_OPARG();
}
diff --git a/Python/optimizer.c b/Python/optimizer.c
index 53f1500f3989a4..7b76cddeabff44 100644
--- a/Python/optimizer.c
+++ b/Python/optimizer.c
@@ -119,6 +119,7 @@ _PyOptimizer_Optimize(
PyInterpreterState *interp = _PyInterpreterState_GET();
assert(interp->jit);
assert(!interp->compiling);
+#ifndef Py_GIL_DISABLED
interp->compiling = true;
// The first executor in a chain and the MAX_CHAIN_DEPTH'th executor *must*
// make progress in order to avoid infinite loops or excessively-long
@@ -160,6 +161,9 @@ _PyOptimizer_Optimize(
assert((*executor_ptr)->vm_data.valid);
interp->compiling = false;
return 1;
+#else
+ return 0;
+#endif
}
static _PyExecutorObject *
diff --git a/configure b/configure
index cd8f2f19c0b92c..7624cbf0d2ae3d 100755
--- a/configure
+++ b/configure
@@ -10891,7 +10891,8 @@ printf "%s\n" "$tier2_flags $jit_flags" >&6; }
if test "$disable_gil" = "yes" -a "$enable_experimental_jit" != "no"; then
# GH-133171: This configuration builds the JIT but never actually uses it,
# which is surprising (and strictly worse than not building it at all):
- as_fn_error $? "--enable-experimental-jit cannot be used with --disable-gil." "$LINENO" 5
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: --enable-experimental-jit does not work correctly with --disable-gil." >&5
+printf "%s\n" "$as_me: WARNING: --enable-experimental-jit does not work correctly with --disable-gil." >&2;}
fi
case "$ac_cv_cc_name" in
diff --git a/configure.ac b/configure.ac
index 8312dc55084333..7a7e32d42945b9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2799,7 +2799,7 @@ AC_MSG_RESULT([$tier2_flags $jit_flags])
if test "$disable_gil" = "yes" -a "$enable_experimental_jit" != "no"; then
# GH-133171: This configuration builds the JIT but never actually uses it,
# which is surprising (and strictly worse than not building it at all):
- AC_MSG_ERROR([--enable-experimental-jit cannot be used with --disable-gil.])
+ AC_MSG_WARN([--enable-experimental-jit does not work correctly with --disable-gil.])
fi
case "$ac_cv_cc_name" in