From 28d630d90ded85c6f8d4027319bbbf584a44fbb4 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Sun, 21 Dec 2025 21:54:01 +0100 Subject: [PATCH] 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)); }