mirror of https://github.com/python/cpython
GH-84436: Skip refcounting for known immortals (GH-107605)
This commit is contained in:
parent
ec0a0d2bd9
commit
05a824f294
|
@ -64,19 +64,19 @@ extern void _PyLong_FiniTypes(PyInterpreterState *interp);
|
|||
# error "_PY_NSMALLPOSINTS must be greater than or equal to 257"
|
||||
#endif
|
||||
|
||||
// Return a borrowed reference to the zero singleton.
|
||||
// Return a reference to the immortal zero singleton.
|
||||
// The function cannot return NULL.
|
||||
static inline PyObject* _PyLong_GetZero(void)
|
||||
{ return (PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS]; }
|
||||
|
||||
// Return a borrowed reference to the one singleton.
|
||||
// Return a reference to the immortal one singleton.
|
||||
// The function cannot return NULL.
|
||||
static inline PyObject* _PyLong_GetOne(void)
|
||||
{ return (PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS+1]; }
|
||||
|
||||
static inline PyObject* _PyLong_FromUnsignedChar(unsigned char i)
|
||||
{
|
||||
return Py_NewRef((PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS+i]);
|
||||
return (PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS+i];
|
||||
}
|
||||
|
||||
extern PyObject *_PyLong_Add(PyLongObject *left, PyLongObject *right);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Skip reference count modifications for many known immortal objects.
|
|
@ -1398,7 +1398,8 @@ FutureObj_get_state(FutureObj *fut, void *Py_UNUSED(ignored))
|
|||
default:
|
||||
assert (0);
|
||||
}
|
||||
return Py_XNewRef(ret);
|
||||
assert(_Py_IsImmortal(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
|
|
@ -234,7 +234,7 @@ _io_IncrementalNewlineDecoder___init___impl(nldecoder_object *self,
|
|||
{
|
||||
|
||||
if (errors == NULL) {
|
||||
errors = Py_NewRef(&_Py_ID(strict));
|
||||
errors = &_Py_ID(strict);
|
||||
}
|
||||
else {
|
||||
errors = Py_NewRef(errors);
|
||||
|
@ -1138,7 +1138,7 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
|
|||
|
||||
if (encoding == NULL && _PyRuntime.preconfig.utf8_mode) {
|
||||
_Py_DECLARE_STR(utf_8, "utf-8");
|
||||
self->encoding = Py_NewRef(&_Py_STR(utf_8));
|
||||
self->encoding = &_Py_STR(utf_8);
|
||||
}
|
||||
else if (encoding == NULL || (strcmp(encoding, "locale") == 0)) {
|
||||
self->encoding = _Py_GetLocaleEncodingObject();
|
||||
|
@ -2267,7 +2267,7 @@ _textiowrapper_readline(textio *self, Py_ssize_t limit)
|
|||
Py_CLEAR(chunks);
|
||||
}
|
||||
if (line == NULL) {
|
||||
line = Py_NewRef(&_Py_STR(empty));
|
||||
line = &_Py_STR(empty);
|
||||
}
|
||||
|
||||
return line;
|
||||
|
|
|
@ -1277,13 +1277,13 @@ _encoded_const(PyObject *obj)
|
|||
{
|
||||
/* Return the JSON string representation of None, True, False */
|
||||
if (obj == Py_None) {
|
||||
return Py_NewRef(&_Py_ID(null));
|
||||
return &_Py_ID(null);
|
||||
}
|
||||
else if (obj == Py_True) {
|
||||
return Py_NewRef(&_Py_ID(true));
|
||||
return &_Py_ID(true);
|
||||
}
|
||||
else if (obj == Py_False) {
|
||||
return Py_NewRef(&_Py_ID(false));
|
||||
return &_Py_ID(false);
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(PyExc_ValueError, "not a const");
|
||||
|
|
|
@ -2029,8 +2029,7 @@ whichmodule(PyObject *global, PyObject *dotted_path)
|
|||
}
|
||||
|
||||
/* If no module is found, use __main__. */
|
||||
module_name = &_Py_ID(__main__);
|
||||
return Py_NewRef(module_name);
|
||||
return &_Py_ID(__main__);
|
||||
}
|
||||
|
||||
/* fast_save_enter() and fast_save_leave() are guards against recursive
|
||||
|
|
|
@ -13,8 +13,7 @@
|
|||
static PyObject *
|
||||
bool_repr(PyObject *self)
|
||||
{
|
||||
PyObject *res = self == Py_True ? &_Py_ID(True) : &_Py_ID(False);
|
||||
return Py_NewRef(res);
|
||||
return self == Py_True ? &_Py_ID(True) : &_Py_ID(False);
|
||||
}
|
||||
|
||||
/* Function to return a bool from a C long */
|
||||
|
|
|
@ -41,17 +41,12 @@ Py_LOCAL_INLINE(Py_ssize_t) _PyBytesWriter_GetSize(_PyBytesWriter *writer,
|
|||
#define EMPTY (&_Py_SINGLETON(bytes_empty))
|
||||
|
||||
|
||||
// Return a borrowed reference to the empty bytes string singleton.
|
||||
// Return a reference to the immortal empty bytes string singleton.
|
||||
static inline PyObject* bytes_get_empty(void)
|
||||
{
|
||||
return &EMPTY->ob_base.ob_base;
|
||||
}
|
||||
|
||||
|
||||
// Return a strong reference to the empty bytes string singleton.
|
||||
static inline PyObject* bytes_new_empty(void)
|
||||
{
|
||||
return Py_NewRef(EMPTY);
|
||||
PyObject *empty = &EMPTY->ob_base.ob_base;
|
||||
assert(_Py_IsImmortal(empty));
|
||||
return empty;
|
||||
}
|
||||
|
||||
|
||||
|
@ -84,7 +79,7 @@ _PyBytes_FromSize(Py_ssize_t size, int use_calloc)
|
|||
assert(size >= 0);
|
||||
|
||||
if (size == 0) {
|
||||
return bytes_new_empty();
|
||||
return bytes_get_empty();
|
||||
}
|
||||
|
||||
if ((size_t)size > (size_t)PY_SSIZE_T_MAX - PyBytesObject_SIZE) {
|
||||
|
@ -123,10 +118,11 @@ PyBytes_FromStringAndSize(const char *str, Py_ssize_t size)
|
|||
}
|
||||
if (size == 1 && str != NULL) {
|
||||
op = CHARACTER(*str & 255);
|
||||
return Py_NewRef(op);
|
||||
assert(_Py_IsImmortal(op));
|
||||
return (PyObject *)op;
|
||||
}
|
||||
if (size == 0) {
|
||||
return bytes_new_empty();
|
||||
return bytes_get_empty();
|
||||
}
|
||||
|
||||
op = (PyBytesObject *)_PyBytes_FromSize(size, 0);
|
||||
|
@ -154,11 +150,12 @@ PyBytes_FromString(const char *str)
|
|||
}
|
||||
|
||||
if (size == 0) {
|
||||
return bytes_new_empty();
|
||||
return bytes_get_empty();
|
||||
}
|
||||
else if (size == 1) {
|
||||
op = CHARACTER(*str & 255);
|
||||
return Py_NewRef(op);
|
||||
assert(_Py_IsImmortal(op));
|
||||
return (PyObject *)op;
|
||||
}
|
||||
|
||||
/* Inline PyObject_NewVar */
|
||||
|
@ -3065,7 +3062,7 @@ _PyBytes_Resize(PyObject **pv, Py_ssize_t newsize)
|
|||
goto error;
|
||||
}
|
||||
if (newsize == 0) {
|
||||
*pv = bytes_new_empty();
|
||||
*pv = bytes_get_empty();
|
||||
Py_DECREF(v);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -831,8 +831,8 @@ func_clear(PyFunctionObject *op)
|
|||
// However, name and qualname could be str subclasses, so they
|
||||
// could have reference cycles. The solution is to replace them
|
||||
// with a genuinely immutable string.
|
||||
Py_SETREF(op->func_name, Py_NewRef(&_Py_STR(empty)));
|
||||
Py_SETREF(op->func_qualname, Py_NewRef(&_Py_STR(empty)));
|
||||
Py_SETREF(op->func_name, &_Py_STR(empty));
|
||||
Py_SETREF(op->func_qualname, &_Py_STR(empty));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -174,7 +174,7 @@ _PyLong_FromDigits(int negative, Py_ssize_t digit_count, digit *digits)
|
|||
{
|
||||
assert(digit_count >= 0);
|
||||
if (digit_count == 0) {
|
||||
return (PyLongObject *)Py_NewRef(_PyLong_GetZero());
|
||||
return (PyLongObject *)_PyLong_GetZero();
|
||||
}
|
||||
PyLongObject *result = _PyLong_New(digit_count);
|
||||
if (result == NULL) {
|
||||
|
@ -2857,8 +2857,7 @@ long_divrem(PyLongObject *a, PyLongObject *b,
|
|||
if (*prem == NULL) {
|
||||
return -1;
|
||||
}
|
||||
PyObject *zero = _PyLong_GetZero();
|
||||
*pdiv = (PyLongObject*)Py_NewRef(zero);
|
||||
*pdiv = (PyLongObject*)_PyLong_GetZero();
|
||||
return 0;
|
||||
}
|
||||
if (size_b == 1) {
|
||||
|
|
|
@ -106,8 +106,8 @@ range_from_array(PyTypeObject *type, PyObject *const *args, Py_ssize_t num_args)
|
|||
if (!stop) {
|
||||
return NULL;
|
||||
}
|
||||
start = Py_NewRef(_PyLong_GetZero());
|
||||
step = Py_NewRef(_PyLong_GetOne());
|
||||
start = _PyLong_GetZero();
|
||||
step = _PyLong_GetOne();
|
||||
break;
|
||||
case 0:
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
|
|
|
@ -415,7 +415,7 @@ _PySlice_GetLongIndices(PySliceObject *self, PyObject *length,
|
|||
|
||||
/* Convert step to an integer; raise for zero step. */
|
||||
if (self->step == Py_None) {
|
||||
step = Py_NewRef(_PyLong_GetOne());
|
||||
step = _PyLong_GetOne();
|
||||
step_is_negative = 0;
|
||||
}
|
||||
else {
|
||||
|
@ -443,7 +443,7 @@ _PySlice_GetLongIndices(PySliceObject *self, PyObject *length,
|
|||
goto error;
|
||||
}
|
||||
else {
|
||||
lower = Py_NewRef(_PyLong_GetZero());
|
||||
lower = _PyLong_GetZero();
|
||||
upper = Py_NewRef(length);
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ tuple_alloc(Py_ssize_t size)
|
|||
static inline PyObject *
|
||||
tuple_get_empty(void)
|
||||
{
|
||||
return Py_NewRef(&_Py_SINGLETON(tuple_empty));
|
||||
return (PyObject *)&_Py_SINGLETON(tuple_empty);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
|
|
|
@ -1085,7 +1085,7 @@ type_module(PyTypeObject *type, void *context)
|
|||
PyUnicode_InternInPlace(&mod);
|
||||
}
|
||||
else {
|
||||
mod = Py_NewRef(&_Py_ID(builtins));
|
||||
mod = &_Py_ID(builtins);
|
||||
}
|
||||
}
|
||||
return mod;
|
||||
|
|
|
@ -211,21 +211,13 @@ static int unicode_is_singleton(PyObject *unicode);
|
|||
#endif
|
||||
|
||||
|
||||
// Return a borrowed reference to the empty string singleton.
|
||||
// Return a reference to the immortal empty string singleton.
|
||||
static inline PyObject* unicode_get_empty(void)
|
||||
{
|
||||
_Py_DECLARE_STR(empty, "");
|
||||
return &_Py_STR(empty);
|
||||
}
|
||||
|
||||
|
||||
// Return a strong reference to the empty string singleton.
|
||||
static inline PyObject* unicode_new_empty(void)
|
||||
{
|
||||
PyObject *empty = unicode_get_empty();
|
||||
return Py_NewRef(empty);
|
||||
}
|
||||
|
||||
/* This dictionary holds all interned unicode strings. Note that references
|
||||
to strings in this dictionary are *not* counted in the string's ob_refcnt.
|
||||
When the interned string reaches a refcnt of 0 the string deallocation
|
||||
|
@ -310,7 +302,7 @@ clear_interned_dict(PyInterpreterState *interp)
|
|||
|
||||
#define _Py_RETURN_UNICODE_EMPTY() \
|
||||
do { \
|
||||
return unicode_new_empty(); \
|
||||
return unicode_get_empty(); \
|
||||
} while (0)
|
||||
|
||||
static inline void
|
||||
|
@ -650,7 +642,6 @@ unicode_result(PyObject *unicode)
|
|||
PyObject *empty = unicode_get_empty();
|
||||
if (unicode != empty) {
|
||||
Py_DECREF(unicode);
|
||||
Py_INCREF(empty);
|
||||
}
|
||||
return empty;
|
||||
}
|
||||
|
@ -662,7 +653,6 @@ unicode_result(PyObject *unicode)
|
|||
Py_UCS1 ch = data[0];
|
||||
PyObject *latin1_char = LATIN1(ch);
|
||||
if (unicode != latin1_char) {
|
||||
Py_INCREF(latin1_char);
|
||||
Py_DECREF(unicode);
|
||||
}
|
||||
return latin1_char;
|
||||
|
@ -1199,7 +1189,7 @@ PyUnicode_New(Py_ssize_t size, Py_UCS4 maxchar)
|
|||
{
|
||||
/* Optimization for empty strings */
|
||||
if (size == 0) {
|
||||
return unicode_new_empty();
|
||||
return unicode_get_empty();
|
||||
}
|
||||
|
||||
PyObject *obj;
|
||||
|
@ -1669,7 +1659,7 @@ unicode_resize(PyObject **p_unicode, Py_ssize_t length)
|
|||
return 0;
|
||||
|
||||
if (length == 0) {
|
||||
PyObject *empty = unicode_new_empty();
|
||||
PyObject *empty = unicode_get_empty();
|
||||
Py_SETREF(*p_unicode, empty);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1764,7 +1754,9 @@ unicode_write_cstr(PyObject *unicode, Py_ssize_t index,
|
|||
static PyObject*
|
||||
get_latin1_char(Py_UCS1 ch)
|
||||
{
|
||||
return Py_NewRef(LATIN1(ch));
|
||||
PyObject *o = LATIN1(ch);
|
||||
assert(_Py_IsImmortal(o));
|
||||
return o;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
|
@ -1891,7 +1883,7 @@ PyUnicode_FromStringAndSize(const char *u, Py_ssize_t size)
|
|||
"NULL string with positive size with NULL passed to PyUnicode_FromStringAndSize");
|
||||
return NULL;
|
||||
}
|
||||
return unicode_new_empty();
|
||||
return unicode_get_empty();
|
||||
}
|
||||
|
||||
PyObject *
|
||||
|
@ -10261,7 +10253,7 @@ replace(PyObject *self, PyObject *str1,
|
|||
}
|
||||
new_size = slen + n * (len2 - len1);
|
||||
if (new_size == 0) {
|
||||
u = unicode_new_empty();
|
||||
u = unicode_get_empty();
|
||||
goto done;
|
||||
}
|
||||
if (new_size > (PY_SSIZE_T_MAX / rkind)) {
|
||||
|
@ -14505,7 +14497,7 @@ unicode_new_impl(PyTypeObject *type, PyObject *x, const char *encoding,
|
|||
{
|
||||
PyObject *unicode;
|
||||
if (x == NULL) {
|
||||
unicode = unicode_new_empty();
|
||||
unicode = unicode_get_empty();
|
||||
}
|
||||
else if (encoding == NULL && errors == NULL) {
|
||||
unicode = PyObject_Str(x);
|
||||
|
@ -14994,8 +14986,7 @@ unicode_ascii_iter_next(unicodeiterobject *it)
|
|||
Py_UCS1 chr = (Py_UCS1)PyUnicode_READ(PyUnicode_1BYTE_KIND,
|
||||
data, it->it_index);
|
||||
it->it_index++;
|
||||
PyObject *item = (PyObject*)&_Py_SINGLETON(strings).ascii[chr];
|
||||
return Py_NewRef(item);
|
||||
return (PyObject*)&_Py_SINGLETON(strings).ascii[chr];
|
||||
}
|
||||
it->it_seq = NULL;
|
||||
Py_DECREF(seq);
|
||||
|
@ -15025,7 +15016,7 @@ unicodeiter_reduce(unicodeiterobject *it, PyObject *Py_UNUSED(ignored))
|
|||
if (it->it_seq != NULL) {
|
||||
return Py_BuildValue("N(O)n", iter, it->it_seq, it->it_index);
|
||||
} else {
|
||||
PyObject *u = unicode_new_empty();
|
||||
PyObject *u = unicode_get_empty();
|
||||
if (u == NULL) {
|
||||
Py_XDECREF(iter);
|
||||
return NULL;
|
||||
|
|
|
@ -1265,7 +1265,7 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func,
|
|||
if (co->co_flags & CO_VARARGS) {
|
||||
PyObject *u = NULL;
|
||||
if (argcount == n) {
|
||||
u = Py_NewRef(&_Py_SINGLETON(tuple_empty));
|
||||
u = (PyObject *)&_Py_SINGLETON(tuple_empty);
|
||||
}
|
||||
else {
|
||||
assert(args != NULL);
|
||||
|
|
|
@ -1267,7 +1267,7 @@ PyTypeObject _PyContextTokenMissing_Type = {
|
|||
static PyObject *
|
||||
get_token_missing(void)
|
||||
{
|
||||
return Py_NewRef(&_Py_SINGLETON(context_token_missing));
|
||||
return (PyObject *)&_Py_SINGLETON(context_token_missing);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ _Py_device_encoding(int fd)
|
|||
#else
|
||||
if (_PyRuntime.preconfig.utf8_mode) {
|
||||
_Py_DECLARE_STR(utf_8, "utf-8");
|
||||
return Py_NewRef(&_Py_STR(utf_8));
|
||||
return &_Py_STR(utf_8);
|
||||
}
|
||||
return _Py_GetLocaleEncodingObject();
|
||||
#endif
|
||||
|
|
|
@ -514,7 +514,7 @@ hamt_node_bitmap_new(Py_ssize_t size)
|
|||
/* Since bitmap nodes are immutable, we can cache the instance
|
||||
for size=0 and reuse it whenever we need an empty bitmap node.
|
||||
*/
|
||||
return (PyHamtNode *)Py_NewRef(&_Py_SINGLETON(hamt_bitmap_node_empty));
|
||||
return (PyHamtNode *)&_Py_SINGLETON(hamt_bitmap_node_empty);
|
||||
}
|
||||
|
||||
assert(size >= 0);
|
||||
|
|
Loading…
Reference in New Issue