https://github.com/python/cpython/commit/29f6dc6323759ab89ddc33096bf075037db5de5a
commit: 29f6dc6323759ab89ddc33096bf075037db5de5a
branch: main
author: Mark Shannon <[email protected]>
committer: markshannon <[email protected]>
date: 2025-05-22T09:54:04+01:00
summary:
GH-133932: Tagged ints are heap safe (GH-134244)
files:
M Include/internal/pycore_stackref.h
diff --git a/Include/internal/pycore_stackref.h
b/Include/internal/pycore_stackref.h
index 3ead6bc63c1d12..40ec00c8119108 100644
--- a/Include/internal/pycore_stackref.h
+++ b/Include/internal/pycore_stackref.h
@@ -238,6 +238,7 @@ PyStackRef_IsNullOrInt(_PyStackRef ref);
#else
#define Py_INT_TAG 3
+#define Py_TAG_REFCNT 1
static inline bool
PyStackRef_IsTaggedInt(_PyStackRef i)
@@ -263,7 +264,7 @@ PyStackRef_UntagInt(_PyStackRef i)
#ifdef Py_GIL_DISABLED
-#define Py_TAG_DEFERRED (1)
+#define Py_TAG_DEFERRED Py_TAG_REFCNT
#define Py_TAG_PTR ((uintptr_t)0)
#define Py_TAG_BITS ((uintptr_t)1)
@@ -441,14 +442,13 @@ PyStackRef_AsStrongReference(_PyStackRef stackref)
/* References to immortal objects always have their tag bit set to
Py_TAG_REFCNT
* as they can (must) have their reclamation deferred */
-#define Py_TAG_BITS 1
-#define Py_TAG_REFCNT 1
+#define Py_TAG_BITS 3
#if _Py_IMMORTAL_FLAGS != Py_TAG_REFCNT
# error "_Py_IMMORTAL_FLAGS != Py_TAG_REFCNT"
#endif
#define BITS_TO_PTR(REF) ((PyObject *)((REF).bits))
-#define BITS_TO_PTR_MASKED(REF) ((PyObject *)(((REF).bits) & (~Py_TAG_BITS)))
+#define BITS_TO_PTR_MASKED(REF) ((PyObject *)(((REF).bits) & (~Py_TAG_REFCNT)))
#define PyStackRef_NULL_BITS Py_TAG_REFCNT
static const _PyStackRef PyStackRef_NULL = { .bits = PyStackRef_NULL_BITS };
@@ -528,7 +528,7 @@ PyStackRef_FromPyObjectSteal(PyObject *obj)
{
assert(obj != NULL);
#if SIZEOF_VOID_P > 4
- unsigned int tag = obj->ob_flags & Py_TAG_BITS;
+ unsigned int tag = obj->ob_flags & Py_TAG_REFCNT;
#else
unsigned int tag = _Py_IsImmortal(obj) ? Py_TAG_REFCNT : 0;
#endif
@@ -547,12 +547,6 @@ PyStackRef_FromPyObjectStealMortal(PyObject *obj)
return ref;
}
-// Check if a stackref is exactly the same as another stackref, including the
-// the deferred bit. This can only be used safely if you know that the deferred
-// bits of `a` and `b` match.
-#define PyStackRef_IsExactly(a, b) \
- (assert(((a).bits & Py_TAG_BITS) == ((b).bits & Py_TAG_BITS)), (a).bits ==
(b).bits)
-
static inline _PyStackRef
_PyStackRef_FromPyObjectNew(PyObject *obj)
{
@@ -604,7 +598,7 @@ PyStackRef_DUP(_PyStackRef ref)
static inline bool
PyStackRef_IsHeapSafe(_PyStackRef ref)
{
- return (ref.bits & Py_TAG_BITS) == 0 || ref.bits == PyStackRef_NULL_BITS
|| _Py_IsImmortal(BITS_TO_PTR_MASKED(ref));
+ return (ref.bits & Py_TAG_BITS) != Py_TAG_REFCNT || ref.bits ==
PyStackRef_NULL_BITS || _Py_IsImmortal(BITS_TO_PTR_MASKED(ref));
}
static inline _PyStackRef
@@ -679,7 +673,7 @@ PyStackRef_XCLOSE(_PyStackRef ref)
// Note: this is a macro because MSVC (Windows) has trouble inlining it.
-#define PyStackRef_Is(a, b) (((a).bits & (~Py_TAG_BITS)) == ((b).bits &
(~Py_TAG_BITS)))
+#define PyStackRef_Is(a, b) (((a).bits & (~Py_TAG_REFCNT)) == ((b).bits &
(~Py_TAG_REFCNT)))
#endif // !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]