-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
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 all 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 |
---|---|---|
|
@@ -36,7 +36,15 @@ 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, PyObject_Free); | ||
} | ||
|
||
static inline int | ||
is_medium_int(stwodigits x) | ||
{ | ||
/* Take care that we are comparing unsigned values. */ | ||
twodigits x_plus_mask = ((twodigits)x) + PyLong_MASK; | ||
|
@@ -58,7 +66,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); | ||
} | ||
} | ||
|
@@ -1856,7 +1864,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; | ||
} | ||
|
@@ -3561,15 +3569,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) { | ||
|
@@ -3580,21 +3588,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); | ||
|
||
|
@@ -3699,13 +3707,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: | ||
|
@@ -5993,7 +6001,7 @@ PyTypeObject PyLong_Type = { | |
0, /* tp_init */ | ||
0, /* tp_alloc */ | ||
long_new, /* tp_new */ | ||
PyObject_Del, /* tp_free */ | ||
PyObject_Free, /* tp_free */ | ||
}; | ||
|
||
static PyTypeObject Int_InfoType; | ||
|
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.
OOI, why move this?
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.
I was trying to avoid a dependence between the
pycore_...
includes. The unicodeobject.c and tupleobject.c implementations both only usedpycore_pyerrors
for_Py_FatalRefcountError()
, which doesn't really concern itself with the implementation details of exceptions.