-
-
Notifications
You must be signed in to change notification settings - Fork 32k
gh-90667: Add specializations of Py_DECREF when types are known #30872
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
ffe7d7b
d2d7b6f
5cb77fd
f58ebcf
0046cd7
8edfa4d
d095c43
fa6a26a
35c0d25
feebdb3
05b050b
0d6a598
731f79d
d5f49b2
b331bf8
ad146ef
ec763e6
3dd308a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Add type-specialized versions of the ``Py_DECREF()``, and use them for ``float``, ``int``, ``str``, ``bool``, and ``None`` to avoid pointer-chasing at runtime where types are known at C compile time. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,7 +39,16 @@ medium_value(PyLongObject *x) | |
#define IS_SMALL_INT(ival) (-_PY_NSMALLNEGINTS <= (ival) && (ival) < _PY_NSMALLPOSINTS) | ||
#define IS_SMALL_UINT(ival) ((ival) < _PY_NSMALLPOSINTS) | ||
|
||
static inline int is_medium_int(stwodigits x) | ||
static inline void | ||
_Py_DECREF_INT(PyLongObject *op) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this ultimately equivalent to #define _Py_DECREF_INT(op) _Py_DECREF_SPECIALIZED(op, PyObject_Free) ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I removed |
||
{ | ||
assert(PyLong_CheckExact(op)); | ||
_Py_DECREF_SPECIALIZED((PyObject *)op, | ||
(destructor)_PyLong_ExactDealloc); | ||
} | ||
|
||
static inline int | ||
is_medium_int(stwodigits x) | ||
{ | ||
/* Take care that we are comparing unsigned values. */ | ||
twodigits x_plus_mask = ((twodigits)x) + PyLong_MASK; | ||
|
@@ -61,7 +70,7 @@ maybe_small_long(PyLongObject *v) | |
if (v && IS_MEDIUM_VALUE(v)) { | ||
stwodigits ival = medium_value(v); | ||
if (IS_SMALL_INT(ival)) { | ||
Py_DECREF(v); | ||
_Py_DECREF_INT(v); | ||
return (PyLongObject *)get_small_int((sdigit)ival); | ||
} | ||
} | ||
|
@@ -1824,7 +1833,7 @@ long_to_decimal_string_internal(PyObject *aa, | |
#undef WRITE_DIGITS | ||
#undef WRITE_UNICODE_DIGITS | ||
|
||
Py_DECREF(scratch); | ||
_Py_DECREF_INT(scratch); | ||
if (writer) { | ||
writer->pos += strlen; | ||
} | ||
|
@@ -3479,15 +3488,15 @@ k_mul(PyLongObject *a, PyLongObject *b) | |
*/ | ||
i = Py_SIZE(ret) - shift; /* # digits after shift */ | ||
(void)v_isub(ret->ob_digit + shift, i, t2->ob_digit, Py_SIZE(t2)); | ||
Py_DECREF(t2); | ||
_Py_DECREF_INT(t2); | ||
|
||
(void)v_isub(ret->ob_digit + shift, i, t1->ob_digit, Py_SIZE(t1)); | ||
Py_DECREF(t1); | ||
_Py_DECREF_INT(t1); | ||
|
||
/* 6. t3 <- (ah+al)(bh+bl), and add into result. */ | ||
if ((t1 = x_add(ah, al)) == NULL) goto fail; | ||
Py_DECREF(ah); | ||
Py_DECREF(al); | ||
_Py_DECREF_INT(ah); | ||
_Py_DECREF_INT(al); | ||
ah = al = NULL; | ||
|
||
if (a == b) { | ||
|
@@ -3498,21 +3507,21 @@ k_mul(PyLongObject *a, PyLongObject *b) | |
Py_DECREF(t1); | ||
goto fail; | ||
} | ||
Py_DECREF(bh); | ||
Py_DECREF(bl); | ||
_Py_DECREF_INT(bh); | ||
_Py_DECREF_INT(bl); | ||
bh = bl = NULL; | ||
|
||
t3 = k_mul(t1, t2); | ||
Py_DECREF(t1); | ||
Py_DECREF(t2); | ||
_Py_DECREF_INT(t1); | ||
_Py_DECREF_INT(t2); | ||
if (t3 == NULL) goto fail; | ||
assert(Py_SIZE(t3) >= 0); | ||
|
||
/* Add t3. It's not obvious why we can't run out of room here. | ||
* See the (*) comment after this function. | ||
*/ | ||
(void)v_iadd(ret->ob_digit + shift, i, t3->ob_digit, Py_SIZE(t3)); | ||
Py_DECREF(t3); | ||
_Py_DECREF_INT(t3); | ||
|
||
return long_normalize(ret); | ||
|
||
|
@@ -3617,13 +3626,13 @@ k_lopsided_mul(PyLongObject *a, PyLongObject *b) | |
/* Add into result. */ | ||
(void)v_iadd(ret->ob_digit + nbdone, Py_SIZE(ret) - nbdone, | ||
product->ob_digit, Py_SIZE(product)); | ||
Py_DECREF(product); | ||
_Py_DECREF_INT(product); | ||
|
||
bsize -= nbtouse; | ||
nbdone += nbtouse; | ||
} | ||
|
||
Py_DECREF(bslice); | ||
_Py_DECREF_INT(bslice); | ||
return long_normalize(ret); | ||
|
||
fail: | ||
|
@@ -5743,6 +5752,13 @@ int_from_bytes_impl(PyTypeObject *type, PyObject *bytes_obj, | |
return long_obj; | ||
} | ||
|
||
void | ||
_PyLong_ExactDealloc(PyObject *op) | ||
sweeneyde marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
assert(PyLong_CheckExact(op)); | ||
PyObject_Del(op); | ||
} | ||
|
||
static PyObject * | ||
long_long_meth(PyObject *self, PyObject *Py_UNUSED(ignored)) | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you change this to call
_Py_FatalRefcountError
directly?We might want to use
_Py_DECREF_IMMORTAL
for other "immortal" objects like0
or()
and there is no guarantee that their de-allocation functions will call_Py_FatalRefcountError
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. I moved
_Py_FatalRefcountError
frompycore_pyerrors
topycore_object
as well, rather than having an#include
-dependence between the pycore_files.