Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Adoption after merge main, review addressed
  • Loading branch information
efimov-mikhail committed Oct 22, 2025
commit a2754b7cfe34ee13b1c12342e56b5e102989ab90
41 changes: 22 additions & 19 deletions Include/internal/pycore_stackref.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,28 +50,29 @@ extern "C" {
CPython refcounting operations on it!
*/


#if !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)

#define Py_INT_TAG 3
#define Py_TAG_INVALID 2
#define Py_TAG_REFCNT 1
#define Py_TAG_BITS 3

#define Py_TAGGED_SHIFT 2

#if !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)

PyAPI_FUNC(PyObject *) _Py_stackref_get_object(_PyStackRef ref);
PyAPI_FUNC(PyObject *) _Py_stackref_close(_PyStackRef ref, const char *filename, int linenumber);
PyAPI_FUNC(_PyStackRef) _Py_stackref_create(PyObject *obj, uint16_t flags, const char *filename, int linenumber);
PyAPI_FUNC(void) _Py_stackref_record_borrow(_PyStackRef ref, const char *filename, int linenumber);
extern void _Py_stackref_associate(PyInterpreterState *interp, PyObject *obj, _PyStackRef ref);

static const _PyStackRef PyStackRef_NULL = { .index = 0 };
static const _PyStackRef PyStackRef_ERROR = { .index = 4 };
static const _PyStackRef PyStackRef_ERROR = { .index = (1 << Py_TAGGED_SHIFT) };

#define PyStackRef_None ((_PyStackRef){ .index = 8 } )
#define PyStackRef_False ((_PyStackRef){ .index = 12 })
#define PyStackRef_True ((_PyStackRef){ .index = 16 })
#define PyStackRef_None ((_PyStackRef){ .index = (2 << Py_TAGGED_SHIFT) } )
#define PyStackRef_False ((_PyStackRef){ .index = (3 << Py_TAGGED_SHIFT) })
#define PyStackRef_True ((_PyStackRef){ .index = (4 << Py_TAGGED_SHIFT) })

#define INITIAL_STACKREF_INDEX 20
#define INITIAL_STACKREF_INDEX (5 << Py_TAGGED_SHIFT)

static inline _PyStackRef
PyStackRef_Wrap(void *ptr)
Expand Down Expand Up @@ -111,7 +112,13 @@ PyStackRef_IsNull(_PyStackRef ref)
static inline bool
PyStackRef_IsError(_PyStackRef ref)
{
return ref.index == 4;
return ref.index == (1 << Py_TAGGED_SHIFT);
}

static inline bool
PyStackRef_IsMalformed(_PyStackRef ref)
{
return (ref.index & Py_TAG_BITS) == Py_TAG_INVALID;
}

static inline bool
Expand Down Expand Up @@ -315,6 +322,7 @@ _PyStackRef_MakeHeapSafe(_PyStackRef ref, const char *filename, int linenumber)
static inline _PyStackRef
_PyStackRef_FromPyObjectNewMortal(PyObject *obj, const char *filename, int linenumber)
{
assert(obj != NULL);
assert(!_Py_IsStaticImmortal(obj));
Comment thread
sergey-miryanov marked this conversation as resolved.
Py_XINCREF(obj);
Comment thread
sergey-miryanov marked this conversation as resolved.
Outdated
return _Py_stackref_create(obj, 0, filename, linenumber);
Expand All @@ -337,11 +345,6 @@ PyStackRef_IsNullOrInt(_PyStackRef ref);

#else

#define Py_INT_TAG 3
#define Py_TAG_INVALID 2
#define Py_TAG_REFCNT 1
#define Py_TAG_BITS 3

static const _PyStackRef PyStackRef_ERROR = { .bits = Py_TAG_INVALID };

/* Wrap a pointer in a stack ref.
Expand Down Expand Up @@ -399,25 +402,25 @@ PyStackRef_IsTaggedInt(_PyStackRef i)
static inline _PyStackRef
PyStackRef_TagInt(intptr_t i)
{
assert(Py_ARITHMETIC_RIGHT_SHIFT(intptr_t, (i << 2), 2) == i);
return (_PyStackRef){ .bits = ((((uintptr_t)i) << 2) | Py_INT_TAG) };
assert(Py_ARITHMETIC_RIGHT_SHIFT(intptr_t, (i << Py_TAGGED_SHIFT), Py_TAGGED_SHIFT) == i);
return (_PyStackRef){ .bits = ((((uintptr_t)i) << Py_TAGGED_SHIFT) | Py_INT_TAG) };
}

static inline intptr_t
PyStackRef_UntagInt(_PyStackRef i)
{
assert(PyStackRef_IsTaggedInt(i));
intptr_t val = (intptr_t)i.bits;
return Py_ARITHMETIC_RIGHT_SHIFT(intptr_t, val, 2);
return Py_ARITHMETIC_RIGHT_SHIFT(intptr_t, val, Py_TAGGED_SHIFT);
}


static inline _PyStackRef
PyStackRef_IncrementTaggedIntNoOverflow(_PyStackRef ref)
{
assert((ref.bits & Py_TAG_BITS) == Py_INT_TAG); // Is tagged int
assert((ref.bits & (~Py_TAG_BITS)) != (INT_MAX & (~Py_TAG_BITS))); // Isn't about to overflow
return (_PyStackRef){ .bits = ref.bits + 4 };
assert((ref.bits & (~Py_TAG_BITS)) != (INTPTR_MAX & (~Py_TAG_BITS))); // Isn't about to overflow
return (_PyStackRef){ .bits = ref.bits + (1 << Py_TAGGED_SHIFT) };
Comment thread
sergey-miryanov marked this conversation as resolved.
}

#define PyStackRef_IsDeferredOrTaggedInt(ref) (((ref).bits & Py_TAG_REFCNT) != 0)
Expand Down
12 changes: 6 additions & 6 deletions Python/stackrefs.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ _Py_stackref_create(PyObject *obj, uint16_t flags, const char *filename, int lin
}
PyInterpreterState *interp = PyInterpreterState_Get();
uint64_t new_id = interp->next_stackref;
interp->next_stackref = new_id + 4;
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");
Expand Down Expand Up @@ -197,16 +197,16 @@ _Py_stackref_report_leaks(PyInterpreterState *interp)

_PyStackRef PyStackRef_TagInt(intptr_t i)
{
assert(Py_ARITHMETIC_RIGHT_SHIFT(intptr_t, (i << 2), 2) == i);
return (_PyStackRef){ .index = (i << 2) | Py_INT_TAG };
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
PyStackRef_UntagInt(_PyStackRef i)
{
assert(PyStackRef_IsTaggedInt(i));
intptr_t val = (intptr_t)i.index;
return Py_ARITHMETIC_RIGHT_SHIFT(intptr_t, val, 2);
return Py_ARITHMETIC_RIGHT_SHIFT(intptr_t, val, Py_TAGGED_SHIFT);
}

bool
Expand All @@ -219,8 +219,8 @@ _PyStackRef
PyStackRef_IncrementTaggedIntNoOverflow(_PyStackRef ref)
{
assert(PyStackRef_IsTaggedInt(ref));
assert((ref.index & (~Py_TAG_BITS)) != (INT_MAX & (~Py_TAG_BITS))); // Isn't about to overflow
return (_PyStackRef){ .index = ref.index + 4 };
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) };
}


Expand Down
Loading