Skip to content

Commit 98e132b

Browse files
committed
Use Sam's suggestion to avoid branching
1 parent d270553 commit 98e132b

File tree

4 files changed

+19
-8
lines changed

4 files changed

+19
-8
lines changed

Include/internal/pycore_stackref.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ PyStackRef_AsStrongReference(_PyStackRef stackref)
375375
// With GIL
376376

377377
#define Py_TAG_BITS 3
378-
#define Py_TAG_IMMORTAL 3
378+
#define Py_TAG_IMMORTAL _Py_IMMORTAL_FLAGS
379379
#define Py_TAG_REFCNT 1
380380
#define BITS_TO_PTR(REF) ((PyObject *)((REF).bits))
381381
#define BITS_TO_PTR_MASKED(REF) ((PyObject *)(((REF).bits) & (~Py_TAG_BITS)))
@@ -460,7 +460,12 @@ static inline _PyStackRef
460460
PyStackRef_FromPyObjectSteal(PyObject *obj)
461461
{
462462
assert(obj != NULL);
463+
unsigned int tag;
464+
#if SIZEOF_VOID_P > 4
465+
tag = obj->ob_flags & Py_TAG_BITS;
466+
#else
463467
unsigned int tag = _Py_IsImmortal(obj) ? Py_TAG_IMMORTAL : 0;
468+
#endif
464469
_PyStackRef ref = ((_PyStackRef){.bits = ((uintptr_t)(obj)) | tag});
465470
PyStackRef_CheckValid(ref);
466471
return ref;

Include/object.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,13 @@ struct _object {
124124
PY_INT64_T ob_refcnt_full; /* This field is needed for efficient initialization with Clang on ARM */
125125
struct {
126126
# if PY_BIG_ENDIAN
127-
PY_UINT32_T ob_flags;
128-
PY_UINT32_T ob_refcnt;
127+
uint16_t ob_flags;
128+
uint16_t ob_overflow;
129+
uint32_t ob_refcnt;
129130
# else
130-
PY_UINT32_T ob_refcnt;
131-
PY_UINT32_T ob_flags;
131+
uint32_t ob_refcnt;
132+
uint16_t ob_overflow;
133+
uint16_t ob_flags;
132134
# endif
133135
};
134136
#else

Include/refcount.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ cleanup during runtime finalization.
2020
*/
2121

2222
/* Leave the low bits for refcount overflow for old stable ABI code */
23-
#define _Py_STATICALLY_ALLOCATED_FLAG (1 << 7)
23+
#define _Py_STATICALLY_ALLOCATED_FLAG 4
24+
#define _Py_IMMORTAL_FLAGS 3
2425

2526
#if SIZEOF_VOID_P > 4
2627
/*
@@ -43,7 +44,8 @@ be done by checking the bit sign flag in the lower 32 bits.
4344
4445
*/
4546
#define _Py_IMMORTAL_INITIAL_REFCNT (3UL << 30)
46-
#define _Py_STATIC_IMMORTAL_INITIAL_REFCNT ((Py_ssize_t)(_Py_IMMORTAL_INITIAL_REFCNT | (((Py_ssize_t)_Py_STATICALLY_ALLOCATED_FLAG) << 32)))
47+
#define _Py_STATIC_FLAG_BITS ((Py_ssize_t)(_Py_STATICALLY_ALLOCATED_FLAG | _Py_IMMORTAL_FLAGS))
48+
#define _Py_STATIC_IMMORTAL_INITIAL_REFCNT (((Py_ssize_t)_Py_IMMORTAL_INITIAL_REFCNT) | (_Py_STATIC_FLAG_BITS << 48))
4749

4850
#else
4951
/*
@@ -114,7 +116,6 @@ PyAPI_FUNC(Py_ssize_t) Py_REFCNT(PyObject *ob);
114116
#endif
115117
#endif
116118

117-
118119
static inline Py_ALWAYS_INLINE int _Py_IsImmortal(PyObject *op)
119120
{
120121
#if defined(Py_GIL_DISABLED)

Objects/object.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2524,6 +2524,9 @@ _Py_SetImmortalUntracked(PyObject *op)
25242524
op->ob_ref_local = _Py_IMMORTAL_REFCNT_LOCAL;
25252525
op->ob_ref_shared = 0;
25262526
_Py_atomic_or_uint8(&op->ob_gc_bits, _PyGC_BITS_DEFERRED);
2527+
#elif SIZEOF_VOID_P > 4
2528+
op->ob_flags = _Py_IMMORTAL_FLAGS;
2529+
op->ob_refcnt = _Py_IMMORTAL_INITIAL_REFCNT;
25272530
#else
25282531
op->ob_refcnt = _Py_IMMORTAL_INITIAL_REFCNT;
25292532
#endif

0 commit comments

Comments
 (0)