Skip to content

Commit 0e9c6c2

Browse files
committed
pythongh-110481: Non-limited Py_INCREF/DECREF() in cpython/object.h
Move the non-limited implementation of Py_INCREF() and Py_DECREF() from Include/object.h to Include/cpython/object.h. Move static inline functions using Py_INCREF/DECREF() after the cpython/object.h include: Py_XINCREF(), Py_XDECREF(), Py_NewRef() and Py_XNewRef().
1 parent 940ee96 commit 0e9c6c2

File tree

2 files changed

+132
-109
lines changed

2 files changed

+132
-109
lines changed

Include/cpython/object.h

+70
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,76 @@
22
# error "this header file must not be included directly"
33
#endif
44

5+
#if defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG))
6+
// Implemented in ../object.h
7+
#else
8+
static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
9+
{
10+
// Non-limited C API and limited C API for Python 3.9 and older access
11+
// directly PyObject.ob_refcnt.
12+
#if SIZEOF_VOID_P > 4
13+
// Portable saturated add, branching on the carry flag and set low bits
14+
PY_UINT32_T cur_refcnt = op->ob_refcnt_split[PY_BIG_ENDIAN];
15+
PY_UINT32_T new_refcnt = cur_refcnt + 1;
16+
if (new_refcnt == 0) {
17+
return;
18+
}
19+
op->ob_refcnt_split[PY_BIG_ENDIAN] = new_refcnt;
20+
#else
21+
// Explicitly check immortality against the immortal value
22+
if (_Py_IsImmortal(op)) {
23+
return;
24+
}
25+
op->ob_refcnt++;
26+
#endif
27+
_Py_INCREF_STAT_INC();
28+
#ifdef Py_REF_DEBUG
29+
_Py_INCREF_IncRefTotal();
30+
#endif
31+
}
32+
33+
# if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
34+
# define Py_INCREF(op) Py_INCREF(_PyObject_CAST(op))
35+
# endif
36+
#endif
37+
38+
39+
#if defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG))
40+
// Implemented in ../object.h
41+
#elif defined(Py_REF_DEBUG)
42+
static inline void Py_DECREF(const char *filename, int lineno, PyObject *op)
43+
{
44+
if (op->ob_refcnt <= 0) {
45+
_Py_NegativeRefcount(filename, lineno, op);
46+
}
47+
if (_Py_IsImmortal(op)) {
48+
return;
49+
}
50+
_Py_DECREF_STAT_INC();
51+
_Py_DECREF_DecRefTotal();
52+
if (--op->ob_refcnt == 0) {
53+
_Py_Dealloc(op);
54+
}
55+
}
56+
#define Py_DECREF(op) Py_DECREF(__FILE__, __LINE__, _PyObject_CAST(op))
57+
58+
#else
59+
static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject *op)
60+
{
61+
// Non-limited C API and limited C API for Python 3.9 and older access
62+
// directly PyObject.ob_refcnt.
63+
if (_Py_IsImmortal(op)) {
64+
return;
65+
}
66+
_Py_DECREF_STAT_INC();
67+
if (--op->ob_refcnt == 0) {
68+
_Py_Dealloc(op);
69+
}
70+
}
71+
#define Py_DECREF(op) Py_DECREF(_PyObject_CAST(op))
72+
#endif
73+
74+
575
PyAPI_FUNC(void) _Py_NewReference(PyObject *op);
676
PyAPI_FUNC(void) _Py_NewReferenceNoTotal(PyObject *op);
777

Include/object.h

+62-109
Original file line numberDiff line numberDiff line change
@@ -603,9 +603,9 @@ PyAPI_FUNC(void) Py_DecRef(PyObject *);
603603
PyAPI_FUNC(void) _Py_IncRef(PyObject *);
604604
PyAPI_FUNC(void) _Py_DecRef(PyObject *);
605605

606+
#if defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG))
606607
static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
607608
{
608-
#if defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG))
609609
// Stable ABI implements Py_INCREF() as a function call on limited C API
610610
// version 3.12 and newer, and on Python built in debug mode. _Py_IncRef()
611611
// was added to Python 3.10.0a7, use Py_IncRef() on older Python versions.
@@ -615,34 +615,17 @@ static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
615615
# else
616616
Py_IncRef(op);
617617
# endif
618-
#else
619-
// Non-limited C API and limited C API for Python 3.9 and older access
620-
// directly PyObject.ob_refcnt.
621-
#if SIZEOF_VOID_P > 4
622-
// Portable saturated add, branching on the carry flag and set low bits
623-
PY_UINT32_T cur_refcnt = op->ob_refcnt_split[PY_BIG_ENDIAN];
624-
PY_UINT32_T new_refcnt = cur_refcnt + 1;
625-
if (new_refcnt == 0) {
626-
return;
627-
}
628-
op->ob_refcnt_split[PY_BIG_ENDIAN] = new_refcnt;
629-
#else
630-
// Explicitly check immortality against the immortal value
631-
if (_Py_IsImmortal(op)) {
632-
return;
633-
}
634-
op->ob_refcnt++;
635-
#endif
636-
_Py_INCREF_STAT_INC();
637-
#ifdef Py_REF_DEBUG
638-
_Py_INCREF_IncRefTotal();
639-
#endif
640-
#endif
641618
}
642-
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
643-
# define Py_INCREF(op) Py_INCREF(_PyObject_CAST(op))
619+
620+
# if Py_LIMITED_API+0 < 0x030b0000
621+
# define Py_INCREF(op) Py_INCREF(_PyObject_CAST(op))
622+
# endif
623+
624+
#else
625+
// Implemented in cpython/object.h
644626
#endif
645627

628+
646629
#if defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG))
647630
// Stable ABI implements Py_DECREF() as a function call on limited C API
648631
// version 3.12 and newer, and on Python built in debug mode. _Py_DecRef() was
@@ -656,38 +639,8 @@ static inline void Py_DECREF(PyObject *op) {
656639
# endif
657640
}
658641
#define Py_DECREF(op) Py_DECREF(_PyObject_CAST(op))
659-
660-
#elif defined(Py_REF_DEBUG)
661-
static inline void Py_DECREF(const char *filename, int lineno, PyObject *op)
662-
{
663-
if (op->ob_refcnt <= 0) {
664-
_Py_NegativeRefcount(filename, lineno, op);
665-
}
666-
if (_Py_IsImmortal(op)) {
667-
return;
668-
}
669-
_Py_DECREF_STAT_INC();
670-
_Py_DECREF_DecRefTotal();
671-
if (--op->ob_refcnt == 0) {
672-
_Py_Dealloc(op);
673-
}
674-
}
675-
#define Py_DECREF(op) Py_DECREF(__FILE__, __LINE__, _PyObject_CAST(op))
676-
677642
#else
678-
static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject *op)
679-
{
680-
// Non-limited C API and limited C API for Python 3.9 and older access
681-
// directly PyObject.ob_refcnt.
682-
if (_Py_IsImmortal(op)) {
683-
return;
684-
}
685-
_Py_DECREF_STAT_INC();
686-
if (--op->ob_refcnt == 0) {
687-
_Py_Dealloc(op);
688-
}
689-
}
690-
#define Py_DECREF(op) Py_DECREF(_PyObject_CAST(op))
643+
// Implemented in cpython/object.h
691644
#endif
692645

693646

@@ -763,58 +716,6 @@ static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject *op)
763716
#endif
764717

765718

766-
/* Function to use in case the object pointer can be NULL: */
767-
static inline void Py_XINCREF(PyObject *op)
768-
{
769-
if (op != _Py_NULL) {
770-
Py_INCREF(op);
771-
}
772-
}
773-
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
774-
# define Py_XINCREF(op) Py_XINCREF(_PyObject_CAST(op))
775-
#endif
776-
777-
static inline void Py_XDECREF(PyObject *op)
778-
{
779-
if (op != _Py_NULL) {
780-
Py_DECREF(op);
781-
}
782-
}
783-
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
784-
# define Py_XDECREF(op) Py_XDECREF(_PyObject_CAST(op))
785-
#endif
786-
787-
// Create a new strong reference to an object:
788-
// increment the reference count of the object and return the object.
789-
PyAPI_FUNC(PyObject*) Py_NewRef(PyObject *obj);
790-
791-
// Similar to Py_NewRef(), but the object can be NULL.
792-
PyAPI_FUNC(PyObject*) Py_XNewRef(PyObject *obj);
793-
794-
static inline PyObject* _Py_NewRef(PyObject *obj)
795-
{
796-
Py_INCREF(obj);
797-
return obj;
798-
}
799-
800-
static inline PyObject* _Py_XNewRef(PyObject *obj)
801-
{
802-
Py_XINCREF(obj);
803-
return obj;
804-
}
805-
806-
// Py_NewRef() and Py_XNewRef() are exported as functions for the stable ABI.
807-
// Names overridden with macros by static inline functions for best
808-
// performances.
809-
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
810-
# define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj))
811-
# define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj))
812-
#else
813-
# define Py_NewRef(obj) _Py_NewRef(obj)
814-
# define Py_XNewRef(obj) _Py_XNewRef(obj)
815-
#endif
816-
817-
818719
/*
819720
_Py_NoneStruct is an object of undefined type which can be used in contexts
820721
where NULL (nil) is not suitable (since NULL often means 'error').
@@ -935,6 +836,58 @@ times.
935836
#endif
936837

937838

839+
/* Function to use in case the object pointer can be NULL: */
840+
static inline void Py_XINCREF(PyObject *op)
841+
{
842+
if (op != _Py_NULL) {
843+
Py_INCREF(op);
844+
}
845+
}
846+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
847+
# define Py_XINCREF(op) Py_XINCREF(_PyObject_CAST(op))
848+
#endif
849+
850+
static inline void Py_XDECREF(PyObject *op)
851+
{
852+
if (op != _Py_NULL) {
853+
Py_DECREF(op);
854+
}
855+
}
856+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
857+
# define Py_XDECREF(op) Py_XDECREF(_PyObject_CAST(op))
858+
#endif
859+
860+
// Create a new strong reference to an object:
861+
// increment the reference count of the object and return the object.
862+
PyAPI_FUNC(PyObject*) Py_NewRef(PyObject *obj);
863+
864+
// Similar to Py_NewRef(), but the object can be NULL.
865+
PyAPI_FUNC(PyObject*) Py_XNewRef(PyObject *obj);
866+
867+
static inline PyObject* _Py_NewRef(PyObject *obj)
868+
{
869+
Py_INCREF(obj);
870+
return obj;
871+
}
872+
873+
static inline PyObject* _Py_XNewRef(PyObject *obj)
874+
{
875+
Py_XINCREF(obj);
876+
return obj;
877+
}
878+
879+
// Py_NewRef() and Py_XNewRef() are exported as functions for the stable ABI.
880+
// Names overridden with macros by static inline functions for best
881+
// performances.
882+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
883+
# define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj))
884+
# define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj))
885+
#else
886+
# define Py_NewRef(obj) _Py_NewRef(obj)
887+
# define Py_XNewRef(obj) _Py_XNewRef(obj)
888+
#endif
889+
890+
938891
static inline int
939892
PyType_HasFeature(PyTypeObject *type, unsigned long feature)
940893
{

0 commit comments

Comments
 (0)