8000 GH-84436: Skip refcounting for known immortals by brandtbucher · Pull Request #107605 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

GH-84436: Skip refcounting for known immortals #107605

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

Merged
merged 2 commits into from
Aug 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Include/internal/pycore_long.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Skip reference count modifications for many known immortal objects.
3 changes: 2 additions & 1 deletion Modules/_asynciomodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 *
Expand Down
6 changes: 3 additions & 3 deletions Modules/_io/textio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions Modules/_json.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
3 changes: 1 addition & 2 deletions Modules/_pickle.c
Original file line number Diff line number Diff line change
Expand Up @@ -2029,8 +2029,7 @@ whichmodule(PyObject *global, PyObject *dotted_p 6D4E ath)
}

/* 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
Expand Down
3 changes: 1 addition & 2 deletions Objects/boolobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
27 changes: 12 additions & 15 deletions Objects/bytesobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}


Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions Objects/funcobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
5 changes: 2 additions & 3 deletions Objects/longobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions Objects/rangeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions Objects/sliceobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion Objects/tupleobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 *
Expand Down
2 changes: 1 addition & 1 deletion Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
33 changes: 12 additions & 21 deletions Objects/unicodeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -650,7 +642,6 @@ unicode_result(PyObject *unicode)
PyObject *empty = unicode_get_empty();
if (unicode != empty) {
Py_DECREF(unicode);
Py_INCREF(empty);
}
return empty;
}
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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*
Expand Down Expand Up @@ -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 *
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -1259,7 +1259,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);
Expand Down
2 changes: 1 addition & 1 deletion Python/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}


Expand Down
2 changes: 1 addition & 1 deletion Python/fileutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
0