gh-135125: Fix Py_STACKREF_DEBUG build (GH-139475)

* Use the same pattern of refcounting for stackrefs as in production build
This commit is contained in:
Mikhail Efimov 2025-10-23 19:00:23 +03:00 committed by GitHub
parent 61e759c2ee
commit 918a9ac9f4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 143 additions and 60 deletions

View file

@ -109,18 +109,19 @@ _Py_stackref_close(_PyStackRef ref, const char *filename, int linenumber)
}
_PyStackRef
_Py_stackref_create(PyObject *obj, const char *filename, int linenumber)
_Py_stackref_create(PyObject *obj, uint16_t flags, const char *filename, int linenumber)
{
if (obj == NULL) {
Py_FatalError("Cannot create a stackref for NULL");
}
PyInterpreterState *interp = PyInterpreterState_Get();
uint64_t new_id = interp->next_stackref;
interp->next_stackref = new_id + 2;
interp->next_stackref = new_id + (1 << Py_TAGGED_SHIFT);
TableEntry *entry = make_table_entry(obj, filename, linenumber);
if (entry == NULL) {
Py_FatalError("No memory left for stackref debug table");
}
new_id |= flags;
if (_Py_hashtable_set(interp->open_stackrefs_table, (void *)new_id, entry) < 0) {
Py_FatalError("No memory left for stackref debug table");
}
@ -194,16 +195,10 @@ _Py_stackref_report_leaks(PyInterpreterState *interp)
}
}
void
_PyStackRef_CLOSE_SPECIALIZED(_PyStackRef ref, destructor destruct, const char *filename, int linenumber)
{
PyObject *obj = _Py_stackref_close(ref, filename, linenumber);
_Py_DECREF_SPECIALIZED(obj, destruct);
}
_PyStackRef PyStackRef_TagInt(intptr_t i)
{
return (_PyStackRef){ .index = (i << 1) + 1 };
assert(Py_ARITHMETIC_RIGHT_SHIFT(intptr_t, (i << Py_TAGGED_SHIFT), Py_TAGGED_SHIFT) == i);
return (_PyStackRef){ .index = (i << Py_TAGGED_SHIFT) | Py_INT_TAG };
}
intptr_t
@ -211,7 +206,7 @@ PyStackRef_UntagInt(_PyStackRef i)
{
assert(PyStackRef_IsTaggedInt(i));
intptr_t val = (intptr_t)i.index;
return Py_ARITHMETIC_RIGHT_SHIFT(intptr_t, val, 1);
return Py_ARITHMETIC_RIGHT_SHIFT(intptr_t, val, Py_TAGGED_SHIFT);
}
bool
@ -223,8 +218,9 @@ PyStackRef_IsNullOrInt(_PyStackRef ref)
_PyStackRef
PyStackRef_IncrementTaggedIntNoOverflow(_PyStackRef ref)
{
assert(ref.index <= INT_MAX - 2); // No overflow
return (_PyStackRef){ .index = ref.index + 2 };
assert(PyStackRef_IsTaggedInt(ref));
assert((ref.index & (~Py_TAG_BITS)) != (INTPTR_MAX & (~Py_TAG_BITS))); // Isn't about to overflow
return (_PyStackRef){ .index = ref.index + (1 << Py_TAGGED_SHIFT) };
}