Skip to content

Commit 5188c1c

Browse files
committed
Make explicit that refcnt is 32 bits even on 64 bit machines
1 parent cef0a90 commit 5188c1c

File tree

3 files changed

+23
-5
lines changed

3 files changed

+23
-5
lines changed

Include/object.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,19 @@ struct _object {
120120
__pragma(warning(disable: 4201))
121121
#endif
122122
union {
123-
Py_ssize_t ob_refcnt;
124123
#if SIZEOF_VOID_P > 4
125-
PY_UINT32_T ob_refcnt_split[2];
124+
PY_INT64_T ob_refcnt_full; /* This field is needed for efficient initialization with Clang on ARM */
125+
struct {
126+
# if PY_BIG_ENDIAN
127+
PY_UINT32_T ob_flags;
128+
PY_UINT32_T ob_refcnt;
129+
# else
130+
PY_UINT32_T ob_refcnt;
131+
PY_UINT32_T ob_flags;
132+
# endif
133+
};
134+
#else
135+
Py_ssize_t ob_refcnt;
126136
#endif
127137
};
128138
#ifdef _MSC_VER

Include/refcount.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,13 +252,13 @@ static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
252252
_Py_atomic_add_ssize(&op->ob_ref_shared, (1 << _Py_REF_SHARED_SHIFT));
253253
}
254254
#elif SIZEOF_VOID_P > 4
255-
PY_UINT32_T cur_refcnt = op->ob_refcnt_split[PY_BIG_ENDIAN];
255+
PY_UINT32_T cur_refcnt = op->ob_refcnt;
256256
if (((int32_t)cur_refcnt) < 0) {
257257
// the object is immortal
258258
_Py_INCREF_IMMORTAL_STAT_INC();
259259
return;
260260
}
261-
op->ob_refcnt_split[PY_BIG_ENDIAN] = cur_refcnt + 1;
261+
op->ob_refcnt = cur_refcnt + 1;
262262
#else
263263
if (_Py_IsImmortal(op)) {
264264
_Py_INCREF_IMMORTAL_STAT_INC();
@@ -354,7 +354,13 @@ static inline void Py_DECREF(PyObject *op)
354354
#elif defined(Py_REF_DEBUG)
355355
static inline void Py_DECREF(const char *filename, int lineno, PyObject *op)
356356
{
357+
#if SIZEOF_VOID_P > 4
358+
/* If an object has been freed, it will have a negative full refcnt
359+
* If it has not it been freed, will have a very large refcnt */
360+
if (op->ob_refcnt_full <= 0 || op->ob_refcnt > (UINT32_MAX - (1<<20))) {
361+
#else
357362
if (op->ob_refcnt <= 0) {
363+
#endif
358364
_Py_NegativeRefcount(filename, lineno, op);
359365
}
360366
if (_Py_IsImmortal(op)) {

Objects/object.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2475,7 +2475,9 @@ new_reference(PyObject *op)
24752475
{
24762476
// Skip the immortal object check in Py_SET_REFCNT; always set refcnt to 1
24772477
#if !defined(Py_GIL_DISABLED)
2478-
op->ob_refcnt = 1;
2478+
op->ob_refcnt_full = 1;
2479+
assert(op->ob_refcnt == 1);
2480+
assert(op->ob_flags == 0);
24792481
#else
24802482
op->ob_tid = _Py_ThreadId();
24812483
op->_padding = 0;

0 commit comments

Comments
 (0)