Skip to content

Commit ce2f515

Browse files
committed
Mark statically allocated objects
1 parent 5188c1c commit ce2f515

File tree

3 files changed

+28
-3
lines changed

3 files changed

+28
-3
lines changed

Include/internal/pycore_object.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,24 @@ PyAPI_FUNC(int) _PyObject_IsFreed(PyObject *);
7373
#define _PyObject_HEAD_INIT(type) \
7474
{ \
7575
.ob_ref_local = _Py_IMMORTAL_REFCNT_LOCAL, \
76+
.ob_flags = _Py_STATICALLY_ALLOCATED_FLAG, \
7677
.ob_type = (type) \
7778
}
7879
#else
80+
#if SIZEOF_VOID_P > 4
7981
#define _PyObject_HEAD_INIT(type) \
8082
{ \
81-
.ob_refcnt = _Py_IMMORTAL_INITIAL_REFCNT, \
83+
.ob_refcnt = _Py_IMMORTAL_INITIAL_REFCNT, \
84+
.ob_flags = _Py_STATICALLY_ALLOCATED_FLAG, \
8285
.ob_type = (type) \
8386
}
87+
#else
88+
#define _PyObject_HEAD_INIT(type) \
89+
{ \
90+
.ob_refcnt = _Py_STATIC_IMMORTAL_INITIAL_REFCNT, \
91+
.ob_type = (type) \
92+
}
93+
#endif
8494
#endif
8595
#define _PyVarObject_HEAD_INIT(type, size) \
8696
{ \

Include/object.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ struct _object {
152152
// trashcan mechanism as a linked list pointer and by the GC to store the
153153
// computed "gc_refs" refcount.
154154
uintptr_t ob_tid;
155-
uint16_t _padding;
155+
uint16_t ob_flags;
156156
PyMutex ob_mutex; // per-object lock
157157
uint8_t ob_gc_bits; // gc-related state
158158
uint32_t ob_ref_local; // local reference count

Include/refcount.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,15 @@ immortality, but the execution would still be correct.
5454
Reference count increases and decreases will first go through an immortality
5555
check by comparing the reference count field to the minimum immortality refcount.
5656
*/
57-
#define _Py_IMMORTAL_INITIAL_REFCNT ((Py_ssize_t)(3L << 29))
57+
#define _Py_IMMORTAL_INITIAL_REFCNT ((Py_ssize_t)(5L << 28))
5858
#define _Py_IMMORTAL_MINIMUM_REFCNT ((Py_ssize_t)(1L << 30))
59+
#define _Py_STATIC_IMMORTAL_INITIAL_REFCNT ((Py_ssize_t)(7L << 28))
60+
#define _Py_STATIC_IMMORTAL_MINIMUM_REFCNT ((Py_ssize_t)(6L << 28))
5961
#endif
6062

63+
/* Leave the low bits for refcount overflow for old stable ABI code */
64+
#define _Py_STATICALLY_ALLOCATED_FLAG (1 << 7)
65+
6166
// Py_GIL_DISABLED builds indicate immortal objects using `ob_ref_local`, which is
6267
// always 32-bits.
6368
#ifdef Py_GIL_DISABLED
@@ -123,6 +128,16 @@ static inline Py_ALWAYS_INLINE int _Py_IsImmortal(PyObject *op)
123128
#define _Py_IsImmortal(op) _Py_IsImmortal(_PyObject_CAST(op))
124129

125130

131+
static inline Py_ALWAYS_INLINE int _Py_IsStaticImmortal(PyObject *op)
132+
{
133+
#if defined(Py_GIL_DISABLED) || SIZEOF_VOID_P > 4
134+
return (op->ob_flags & _Py_STATICALLY_ALLOCATED_FLAG) != 0;
135+
#else
136+
return op->ob_refcnt >= _Py_STATIC_IMMORTAL_MINIMUM_REFCNT;
137+
#endif
138+
}
139+
#define _Py_IsStaticImmortal(op) _Py_IsStaticImmortal(_PyObject_CAST(op))
140+
126141
// Py_SET_REFCNT() implementation for stable ABI
127142
PyAPI_FUNC(void) _Py_SetRefcnt(PyObject *ob, Py_ssize_t refcnt);
128143

0 commit comments

Comments
 (0)