diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index 0b1df7e68b8dfa..3eb7f33de406fd 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -261,17 +261,53 @@ _Py_DECREF_NO_DEALLOC(PyObject *op) } #else -// TODO: implement Py_DECREF specializations for Py_GIL_DISABLED build + static inline void _Py_DECREF_SPECIALIZED(PyObject *op, const destructor destruct) { - Py_DECREF(op); + if (_Py_IsOwnedByCurrentThread(op) && + _Py_atomic_load_ssize_relaxed(&op->ob_ref_shared) == 0) { + uint32_t local = _Py_atomic_load_uint32_relaxed(&op->ob_ref_local); + if (local == _Py_IMMORTAL_REFCNT_LOCAL) { + _Py_DECREF_IMMORTAL_STAT_INC(); + return; + } + _Py_DECREF_STAT_INC(); +#ifdef Py_REF_DEBUG + _Py_DECREF_DecRefTotal(); +#endif + local--; + _Py_atomic_store_uint32_relaxed(&op->ob_ref_local, local); + if (local == 0) { + destruct(op); + } + } + else { + Py_DECREF(op); + } } static inline void _Py_DECREF_NO_DEALLOC(PyObject *op) { - Py_DECREF(op); + if (_Py_IsOwnedByCurrentThread(op) && + _Py_atomic_load_ssize_relaxed(&op->ob_ref_shared) == 0) { + uint32_t local = _Py_atomic_load_uint32_relaxed(&op->ob_ref_local); + if (local == _Py_IMMORTAL_REFCNT_LOCAL) { + _Py_DECREF_IMMORTAL_STAT_INC(); + return; + } + _Py_DECREF_STAT_INC(); +#ifdef Py_REF_DEBUG + _Py_DECREF_DecRefTotal(); +#endif + local--; + assert(local > 0); + _Py_atomic_store_uint32_relaxed(&op->ob_ref_local, local); + } + else { + Py_DECREF(op); + } } static inline int diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-05-11-11-40.gh-issue-129695.qt2Jsz.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-05-11-11-40.gh-issue-129695.qt2Jsz.rst new file mode 100644 index 00000000000000..55fc7f31d88ead --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-05-11-11-40.gh-issue-129695.qt2Jsz.rst @@ -0,0 +1,2 @@ +Add an optimized version of the ``_PyFloat_FromDouble_ConsumeInputs`` +function for the free-threaded build. diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 7ca43033d722ab..363a7354f80f7f 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -134,27 +134,16 @@ PyFloat_FromDouble(double fval) return (PyObject *) op; } -#ifdef Py_GIL_DISABLED - -PyObject *_PyFloat_FromDouble_ConsumeInputs(_PyStackRef left, _PyStackRef right, double value) -{ - PyStackRef_CLOSE(left); - PyStackRef_CLOSE(right); - return PyFloat_FromDouble(value); -} - -#else // Py_GIL_DISABLED - PyObject *_PyFloat_FromDouble_ConsumeInputs(_PyStackRef left, _PyStackRef right, double value) { PyObject *left_o = PyStackRef_AsPyObjectSteal(left); PyObject *right_o = PyStackRef_AsPyObjectSteal(right); - if (Py_REFCNT(left_o) == 1) { + if (_PyObject_IsUniquelyReferenced(left_o)) { ((PyFloatObject *)left_o)->ob_fval = value; _Py_DECREF_SPECIALIZED(right_o, _PyFloat_ExactDealloc); return left_o; } - else if (Py_REFCNT(right_o) == 1) { + else if (_PyObject_IsUniquelyReferenced(right_o)) { ((PyFloatObject *)right_o)->ob_fval = value; _Py_DECREF_NO_DEALLOC(left_o); return right_o; @@ -167,8 +156,6 @@ PyObject *_PyFloat_FromDouble_ConsumeInputs(_PyStackRef left, _PyStackRef right, } } -#endif // Py_GIL_DISABLED - static PyObject * float_from_string_inner(const char *s, Py_ssize_t len, void *obj) {