@@ -78,6 +78,25 @@ whose size is determined when the object is allocated.
7878/* PyObject_HEAD defines the initial segment of every PyObject. */
7979#define PyObject_HEAD PyObject ob_base;
8080
81+ /*
82+ Immutability:
83+
84+ Immutability is tracked in the top bit of the reference count. The immutability
85+ system also uses the second-to-top bit for managing immutable graphs.
86+ */
87+
88+ #if SIZEOF_VOID_P > 4
89+ #define _Py_REFCNT_MASK 0xFFFFFFFF
90+ #define _Py_IMMUTABLE_MASK 0xC000000000000000
91+ #define _Py_IMMUTABLE_FLAG 0x8000000000000000
92+ #define _Py_IMMUTABLE_SCC_FLAG 0x4000000000000000
93+ #else
94+ #define _Py_REFCNT_MASK 0x3FFFFFFF
95+ #define _Py_IMMUTABLE_MASK 0xC0000000
96+ #define _Py_IMMUTABLE_FLAG 0x80000000
97+ #define _Py_IMMUTABLE_SCC_FLAG 0x40000000
98+ #endif
99+
81100/*
82101Immortalization:
83102
@@ -112,17 +131,17 @@ be done by checking the bit sign flag in the lower 32 bits.
112131#else
113132/*
114133In 32 bit systems, an object will be marked as immortal by setting all of the
115- lower 30 bits of the reference count field, which is equal to: 0x3FFFFFFF
134+ lower 28 bits of the reference count field, which is equal to: 0x0FFFFFFF.
116135
117- Using the lower 30 bits makes the value backwards compatible by allowing
136+ Using the lower 28 bits makes the value backwards compatible by allowing
118137C-Extensions without the updated checks in Py_INCREF and Py_DECREF to safely
119138increase and decrease the objects reference count. The object would lose its
120139immortality, but the execution would still be correct.
121140
122141Reference count increases and decreases will first go through an immortality
123142check by comparing the reference count field to the immortality reference count.
124143*/
125- #define _Py_IMMORTAL_REFCNT (UINT_MAX >> 2 )
144+ #define _Py_IMMORTAL_REFCNT (UINT_MAX >> 4 )
126145#endif
127146
128147// Make all internal uses of PyObject_HEAD_INIT immortal while preserving the
@@ -208,7 +227,7 @@ PyAPI_FUNC(int) Py_Is(PyObject *x, PyObject *y);
208227
209228
210229static inline Py_ssize_t Py_REFCNT (PyObject * ob ) {
211- return ob -> ob_refcnt ;
230+ return ob -> ob_refcnt & _Py_REFCNT_MASK ;
212231}
213232#if !defined(Py_LIMITED_API ) || Py_LIMITED_API + 0 < 0x030b0000
214233# define Py_REFCNT (ob ) Py_REFCNT(_PyObject_CAST(ob))
@@ -242,7 +261,7 @@ static inline Py_ALWAYS_INLINE int _Py_IsImmortal(PyObject *op)
242261#if SIZEOF_VOID_P > 4
243262 return _Py_CAST (PY_INT32_T , op -> ob_refcnt ) < 0 ;
244263#else
245- return op -> ob_refcnt == _Py_IMMORTAL_REFCNT ;
264+ return ( op -> ob_refcnt & _Py_REFCNT_MASK ) == _Py_IMMORTAL_REFCNT ;
246265#endif
247266}
248267#define _Py_IsImmortal (op ) _Py_IsImmortal(_PyObject_CAST(op))
@@ -254,6 +273,15 @@ static inline int Py_IS_TYPE(PyObject *ob, PyTypeObject *type) {
254273# define Py_IS_TYPE (ob , type ) Py_IS_TYPE(_PyObject_CAST(ob), (type))
255274#endif
256275
276+ static inline Py_ALWAYS_INLINE int _Py_IsImmutable (PyObject * op )
277+ {
278+ #if SIZEOF_VOID_P > 4
279+ return _Py_CAST (PY_INT64_T , op -> ob_refcnt ) < 0 ;
280+ #else
281+ return _Py_CAST (PY_INT32_T , op -> ob_refcnt ) < 0 ;
282+ #endif
283+ }
284+ #define _Py_IsImmutable (op ) _Py_IsImmutable(_PyObject_CAST(op))
257285
258286static inline void Py_SET_REFCNT (PyObject * ob , Py_ssize_t refcnt ) {
259287 // This immortal check is for code that is unaware of immortal objects.
@@ -263,7 +291,7 @@ static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
263291 if (_Py_IsImmortal (ob )) {
264292 return ;
265293 }
266- ob -> ob_refcnt = refcnt ;
294+ ob -> ob_refcnt = ( ob -> ob_refcnt & _Py_IMMUTABLE_MASK ) | ( refcnt & _Py_REFCNT_MASK ) ;
267295}
268296#if !defined(Py_LIMITED_API ) || Py_LIMITED_API + 0 < 0x030b0000
269297# define Py_SET_REFCNT (ob , refcnt ) Py_SET_REFCNT(_PyObject_CAST(ob), (refcnt))
@@ -687,7 +715,8 @@ static inline void Py_DECREF(const char *filename, int lineno, PyObject *op)
687715 }
688716 _Py_DECREF_STAT_INC ();
689717 _Py_DECREF_DecRefTotal ();
690- if (-- op -> ob_refcnt == 0 ) {
718+ op -> ob_refcnt -= 1 ;
719+ if ((op -> ob_refcnt & _Py_REFCNT_MASK ) == 0 ) {
691720 _Py_Dealloc (op );
692721 }
693722}
@@ -702,7 +731,8 @@ static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject *op)
702731 return ;
703732 }
704733 _Py_DECREF_STAT_INC ();
705- if (-- op -> ob_refcnt == 0 ) {
734+ op -> ob_refcnt -= 1 ;
735+ if ((op -> ob_refcnt & _Py_REFCNT_MASK ) == 0 ) {
706736 _Py_Dealloc (op );
707737 }
708738}
0 commit comments