From 28d630d90ded85c6f8d4027319bbbf584a44fbb4 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Sun, 21 Dec 2025 21:54:01 +0100 Subject: [PATCH 1/2] Avoid incref/decref pair in long_bitwise --- Objects/longobject.c | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index 8ba1fd65078f48..0f929b73fcc58a 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -5589,46 +5589,45 @@ long_bitwise(PyLongObject *a, Py_ssize_t size_a, size_b, size_z, i; PyLongObject *z; + PyLongObject *new_a = NULL; + PyLongObject *new_b = NULL; + /* Bitwise operations for negative numbers operate as though on a two's complement representation. So convert arguments from sign-magnitude to two's complement, and convert the result back to sign-magnitude at the end. */ - /* If a is negative, replace it by its two's complement. */ size_a = _PyLong_DigitCount(a); + size_b = _PyLong_DigitCount(b); + /* Swap a and b if necessary to ensure size_a >= size_b. */ + if (size_a < size_b) { + z = a; a = b; b = z; + size_z = size_a; size_a = size_b; size_b = size_z; + } + + /* If a is negative, replace it by its two's complement. */ nega = _PyLong_IsNegative(a); if (nega) { z = long_alloc(size_a); if (z == NULL) return NULL; v_complement(z->long_value.ob_digit, a->long_value.ob_digit, size_a); + new_a = z; // reference to decrement instead of a itself a = z; } - else - /* Keep reference count consistent. */ - Py_INCREF(a); /* Same for b. */ - size_b = _PyLong_DigitCount(b); negb = _PyLong_IsNegative(b); if (negb) { z = long_alloc(size_b); if (z == NULL) { - Py_DECREF(a); + Py_XDECREF(new_a); return NULL; } v_complement(z->long_value.ob_digit, b->long_value.ob_digit, size_b); + new_b = z; // reference to decrement instead of b itself b = z; } - else - Py_INCREF(b); - - /* Swap a and b if necessary to ensure size_a >= size_b. */ - if (size_a < size_b) { - z = a; a = b; b = z; - size_z = size_a; size_a = size_b; size_b = size_z; - negz = nega; nega = negb; negb = negz; - } /* JRH: The original logic here was to allocate the result value (z) as the longer of the two operands. However, there are some cases @@ -5658,8 +5657,8 @@ long_bitwise(PyLongObject *a, the final two's complement of z doesn't overflow. */ z = long_alloc(size_z + negz); if (z == NULL) { - Py_DECREF(a); - Py_DECREF(b); + Py_XDECREF(new_a); + Py_XDECREF(new_a); return NULL; } @@ -5696,8 +5695,8 @@ long_bitwise(PyLongObject *a, v_complement(z->long_value.ob_digit, z->long_value.ob_digit, size_z+1); } - Py_DECREF(a); - Py_DECREF(b); + Py_XDECREF(new_a); + Py_XDECREF(new_b); return (PyObject *)maybe_small_long(long_normalize(z)); } From 6a6428eeb3556f27397c6e8895568e5b24f41f4d Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Mon, 29 Dec 2025 19:31:50 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2025-12-29-19-31-46.gh-issue-143192.JxGAyl.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-12-29-19-31-46.gh-issue-143192.JxGAyl.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-29-19-31-46.gh-issue-143192.JxGAyl.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-29-19-31-46.gh-issue-143192.JxGAyl.rst new file mode 100644 index 00000000000000..3a99b3d9e6a1c2 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-29-19-31-46.gh-issue-143192.JxGAyl.rst @@ -0,0 +1 @@ +Improve performance of bitwise operations on multi-digit ints.