Skip to content

Commit 6460af0

Browse files
markshannonmiss-islington
authored andcommitted
pythonGH-133932: Tagged ints are heap safe (pythonGH-134244)
(cherry picked from commit 29f6dc6) Co-authored-by: Mark Shannon <[email protected]>
1 parent 64c265a commit 6460af0

File tree

1 file changed

+7
-13
lines changed

1 file changed

+7
-13
lines changed

Include/internal/pycore_stackref.h

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ PyStackRef_IsNullOrInt(_PyStackRef ref);
239239
#else
240240

241241
#define Py_INT_TAG 3
242+
#define Py_TAG_REFCNT 1
242243

243244
static inline bool
244245
PyStackRef_IsTaggedInt(_PyStackRef i)
@@ -264,7 +265,7 @@ PyStackRef_UntagInt(_PyStackRef i)
264265

265266
#ifdef Py_GIL_DISABLED
266267

267-
#define Py_TAG_DEFERRED (1)
268+
#define Py_TAG_DEFERRED Py_TAG_REFCNT
268269

269270
#define Py_TAG_PTR ((uintptr_t)0)
270271
#define Py_TAG_BITS ((uintptr_t)1)
@@ -442,14 +443,13 @@ PyStackRef_AsStrongReference(_PyStackRef stackref)
442443
/* References to immortal objects always have their tag bit set to Py_TAG_REFCNT
443444
* as they can (must) have their reclamation deferred */
444445

445-
#define Py_TAG_BITS 1
446-
#define Py_TAG_REFCNT 1
446+
#define Py_TAG_BITS 3
447447
#if _Py_IMMORTAL_FLAGS != Py_TAG_REFCNT
448448
# error "_Py_IMMORTAL_FLAGS != Py_TAG_REFCNT"
449449
#endif
450450

451451
#define BITS_TO_PTR(REF) ((PyObject *)((REF).bits))
452-
#define BITS_TO_PTR_MASKED(REF) ((PyObject *)(((REF).bits) & (~Py_TAG_BITS)))
452+
#define BITS_TO_PTR_MASKED(REF) ((PyObject *)(((REF).bits) & (~Py_TAG_REFCNT)))
453453

454454
#define PyStackRef_NULL_BITS Py_TAG_REFCNT
455455
static const _PyStackRef PyStackRef_NULL = { .bits = PyStackRef_NULL_BITS };
@@ -529,7 +529,7 @@ PyStackRef_FromPyObjectSteal(PyObject *obj)
529529
{
530530
assert(obj != NULL);
531531
#if SIZEOF_VOID_P > 4
532-
unsigned int tag = obj->ob_flags & Py_TAG_BITS;
532+
unsigned int tag = obj->ob_flags & Py_TAG_REFCNT;
533533
#else
534534
unsigned int tag = _Py_IsImmortal(obj) ? Py_TAG_REFCNT : 0;
535535
#endif
@@ -548,12 +548,6 @@ PyStackRef_FromPyObjectStealMortal(PyObject *obj)
548548
return ref;
549549
}
550550

551-
// Check if a stackref is exactly the same as another stackref, including the
552-
// the deferred bit. This can only be used safely if you know that the deferred
553-
// bits of `a` and `b` match.
554-
#define PyStackRef_IsExactly(a, b) \
555-
(assert(((a).bits & Py_TAG_BITS) == ((b).bits & Py_TAG_BITS)), (a).bits == (b).bits)
556-
557551
static inline _PyStackRef
558552
_PyStackRef_FromPyObjectNew(PyObject *obj)
559553
{
@@ -606,7 +600,7 @@ PyStackRef_DUP(_PyStackRef ref)
606600
static inline bool
607601
PyStackRef_IsHeapSafe(_PyStackRef ref)
608602
{
609-
return (ref.bits & Py_TAG_BITS) == 0 || ref.bits == PyStackRef_NULL_BITS || _Py_IsImmortal(BITS_TO_PTR_MASKED(ref));
603+
return (ref.bits & Py_TAG_BITS) != Py_TAG_REFCNT || ref.bits == PyStackRef_NULL_BITS || _Py_IsImmortal(BITS_TO_PTR_MASKED(ref));
610604
}
611605

612606
static inline _PyStackRef
@@ -681,7 +675,7 @@ PyStackRef_XCLOSE(_PyStackRef ref)
681675

682676
// Note: this is a macro because MSVC (Windows) has trouble inlining it.
683677

684-
#define PyStackRef_Is(a, b) (((a).bits & (~Py_TAG_BITS)) == ((b).bits & (~Py_TAG_BITS)))
678+
#define PyStackRef_Is(a, b) (((a).bits & (~Py_TAG_REFCNT)) == ((b).bits & (~Py_TAG_REFCNT)))
685679

686680

687681
#endif // !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)

0 commit comments

Comments
 (0)