Skip to content

Commit ffcc7cd

Browse files
authored
gh-89653: PEP 670: Convert pycore_gc.h macros to functions (#92649)
Convert the following macros to static inline functions: * _Py_AS_GC() * _PyGCHead_FINALIZED(), _PyGCHead_SET_FINALIZED() * _PyGCHead_NEXT(), _PyGCHead_SET_NEXT() * _PyGCHead_PREV(), _PyGCHead_SET_PREV() * _PyGC_FINALIZED(), _PyGC_SET_FINALIZED() * _PyObject_GC_IS_TRACKED() * _PyObject_GC_MAY_BE_TRACKED() Add a macro wrapping the _PyObject_GC_IS_TRACKED() function to cast the argument to PyObject*.
1 parent 707839b commit ffcc7cd

File tree

2 files changed

+50
-24
lines changed

2 files changed

+50
-24
lines changed

Include/internal/pycore_gc.h

+49-23
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,29 @@ typedef struct {
1919
uintptr_t _gc_prev;
2020
} PyGC_Head;
2121

22-
#define _Py_AS_GC(o) ((PyGC_Head *)(o)-1)
22+
static inline PyGC_Head* _Py_AS_GC(PyObject *op) {
23+
return (_Py_CAST(PyGC_Head*, op) - 1);
24+
}
2325
#define _PyGC_Head_UNUSED PyGC_Head
2426

2527
/* True if the object is currently tracked by the GC. */
26-
#define _PyObject_GC_IS_TRACKED(o) (_Py_AS_GC(o)->_gc_next != 0)
28+
static inline int _PyObject_GC_IS_TRACKED(PyObject *op) {
29+
PyGC_Head *gc = _Py_AS_GC(op);
30+
return (gc->_gc_next != 0);
31+
}
32+
#define _PyObject_GC_IS_TRACKED(op) _PyObject_GC_IS_TRACKED(_Py_CAST(PyObject*, op))
2733

2834
/* True if the object may be tracked by the GC in the future, or already is.
2935
This can be useful to implement some optimizations. */
30-
#define _PyObject_GC_MAY_BE_TRACKED(obj) \
31-
(PyObject_IS_GC(obj) && \
32-
(!PyTuple_CheckExact(obj) || _PyObject_GC_IS_TRACKED(obj)))
36+
static inline int _PyObject_GC_MAY_BE_TRACKED(PyObject *obj) {
37+
if (!PyObject_IS_GC(obj)) {
38+
return 0;
39+
}
40+
if (PyTuple_CheckExact(obj)) {
41+
return _PyObject_GC_IS_TRACKED(obj);
42+
}
43+
return 1;
44+
}
3345

3446

3547
/* Bit flags for _gc_prev */
@@ -43,26 +55,40 @@ typedef struct {
4355

4456
// Lowest bit of _gc_next is used for flags only in GC.
4557
// But it is always 0 for normal code.
46-
#define _PyGCHead_NEXT(g) ((PyGC_Head*)(g)->_gc_next)
47-
#define _PyGCHead_SET_NEXT(g, p) _Py_RVALUE((g)->_gc_next = (uintptr_t)(p))
58+
static inline PyGC_Head* _PyGCHead_NEXT(PyGC_Head *gc) {
59+
uintptr_t next = gc->_gc_next;
60+
return _Py_CAST(PyGC_Head*, next);
61+
}
62+
static inline void _PyGCHead_SET_NEXT(PyGC_Head *gc, PyGC_Head *next) {
63+
gc->_gc_next = _Py_CAST(uintptr_t, next);
64+
}
4865

4966
// Lowest two bits of _gc_prev is used for _PyGC_PREV_MASK_* flags.
50-
#define _PyGCHead_PREV(g) ((PyGC_Head*)((g)->_gc_prev & _PyGC_PREV_MASK))
51-
#define _PyGCHead_SET_PREV(g, p) do { \
52-
assert(((uintptr_t)p & ~_PyGC_PREV_MASK) == 0); \
53-
(g)->_gc_prev = ((g)->_gc_prev & ~_PyGC_PREV_MASK) \
54-
| ((uintptr_t)(p)); \
55-
} while (0)
56-
57-
#define _PyGCHead_FINALIZED(g) \
58-
(((g)->_gc_prev & _PyGC_PREV_MASK_FINALIZED) != 0)
59-
#define _PyGCHead_SET_FINALIZED(g) \
60-
_Py_RVALUE((g)->_gc_prev |= _PyGC_PREV_MASK_FINALIZED)
61-
62-
#define _PyGC_FINALIZED(o) \
63-
_PyGCHead_FINALIZED(_Py_AS_GC(o))
64-
#define _PyGC_SET_FINALIZED(o) \
65-
_PyGCHead_SET_FINALIZED(_Py_AS_GC(o))
67+
static inline PyGC_Head* _PyGCHead_PREV(PyGC_Head *gc) {
68+
uintptr_t prev = (gc->_gc_prev & _PyGC_PREV_MASK);
69+
return _Py_CAST(PyGC_Head*, prev);
70+
}
71+
static inline void _PyGCHead_SET_PREV(PyGC_Head *gc, PyGC_Head *prev) {
72+
uintptr_t uprev = _Py_CAST(uintptr_t, prev);
73+
assert((uprev & ~_PyGC_PREV_MASK) == 0);
74+
gc->_gc_prev = ((gc->_gc_prev & ~_PyGC_PREV_MASK) | uprev);
75+
}
76+
77+
static inline int _PyGCHead_FINALIZED(PyGC_Head *gc) {
78+
return ((gc->_gc_prev & _PyGC_PREV_MASK_FINALIZED) != 0);
79+
}
80+
static inline void _PyGCHead_SET_FINALIZED(PyGC_Head *gc) {
81+
gc->_gc_prev |= _PyGC_PREV_MASK_FINALIZED;
82+
}
83+
84+
static inline int _PyGC_FINALIZED(PyObject *op) {
85+
PyGC_Head *gc = _Py_AS_GC(op);
86+
return _PyGCHead_FINALIZED(gc);
87+
}
88+
static inline void _PyGC_SET_FINALIZED(PyObject *op) {
89+
PyGC_Head *gc = _Py_AS_GC(op);
90+
_PyGCHead_SET_FINALIZED(gc);
91+
}
6692

6793

6894
/* GC runtime state */

Objects/object.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -2228,7 +2228,7 @@ _PyTrash_thread_deposit_object(PyObject *op)
22282228
_PyObject_ASSERT(op, _PyObject_IS_GC(op));
22292229
_PyObject_ASSERT(op, !_PyObject_GC_IS_TRACKED(op));
22302230
_PyObject_ASSERT(op, Py_REFCNT(op) == 0);
2231-
_PyGCHead_SET_PREV(_Py_AS_GC(op), tstate->trash_delete_later);
2231+
_PyGCHead_SET_PREV(_Py_AS_GC(op), (PyGC_Head*)tstate->trash_delete_later);
22322232
tstate->trash_delete_later = op;
22332233
}
22342234

0 commit comments

Comments
 (0)