From 961468ed08138b9d95778e61fab01de0f3688427 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 6 Jun 2023 12:17:50 +0200 Subject: [PATCH] gh-105268: Add _Py_FROM_GC() function to pycore_gc.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * gcmodule.c reuses _Py_AS_GC(op) for AS_GC() * Move gcmodule.c FROM_GC() implementation to a new _Py_FROM_GC() static inline function in pycore_gc.h. * _PyObject_IS_GC(): only get the type once * gc_is_finalized(à) and PyObject_GC_IsFinalized() use _PyGC_FINALIZED(), instead of _PyGCHead_FINALIZED(). * Remove _Py_CAST() in pycore_gc.h: this header file is not built with C++. --- Include/internal/pycore_gc.h | 23 +++++++++++++++++------ Include/internal/pycore_object.h | 6 +++--- Modules/gcmodule.c | 14 ++++++-------- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/Include/internal/pycore_gc.h b/Include/internal/pycore_gc.h index b3abe2030a03da..2d33aa76d78229 100644 --- a/Include/internal/pycore_gc.h +++ b/Include/internal/pycore_gc.h @@ -19,10 +19,21 @@ typedef struct { uintptr_t _gc_prev; } PyGC_Head; +#define _PyGC_Head_UNUSED PyGC_Head + + +/* Get an object's GC head */ static inline PyGC_Head* _Py_AS_GC(PyObject *op) { - return (_Py_CAST(PyGC_Head*, op) - 1); + char *gc = ((char*)op) - sizeof(PyGC_Head); + return (PyGC_Head*)gc; } -#define _PyGC_Head_UNUSED PyGC_Head + +/* Get the object given the GC head */ +static inline PyObject* _Py_FROM_GC(PyGC_Head *gc) { + char *op = ((char *)gc) + sizeof(PyGC_Head); + return (PyObject *)op; +} + /* True if the object is currently tracked by the GC. */ static inline int _PyObject_GC_IS_TRACKED(PyObject *op) { @@ -57,19 +68,19 @@ static inline int _PyObject_GC_MAY_BE_TRACKED(PyObject *obj) { // But it is always 0 for normal code. static inline PyGC_Head* _PyGCHead_NEXT(PyGC_Head *gc) { uintptr_t next = gc->_gc_next; - return _Py_CAST(PyGC_Head*, next); + return (PyGC_Head*)next; } static inline void _PyGCHead_SET_NEXT(PyGC_Head *gc, PyGC_Head *next) { - gc->_gc_next = _Py_CAST(uintptr_t, next); + gc->_gc_next = (uintptr_t)next; } // Lowest two bits of _gc_prev is used for _PyGC_PREV_MASK_* flags. static inline PyGC_Head* _PyGCHead_PREV(PyGC_Head *gc) { uintptr_t prev = (gc->_gc_prev & _PyGC_PREV_MASK); - return _Py_CAST(PyGC_Head*, prev); + return (PyGC_Head*)prev; } static inline void _PyGCHead_SET_PREV(PyGC_Head *gc, PyGC_Head *prev) { - uintptr_t uprev = _Py_CAST(uintptr_t, prev); + uintptr_t uprev = (uintptr_t)prev; assert((uprev & ~_PyGC_PREV_MASK) == 0); gc->_gc_prev = ((gc->_gc_prev & ~_PyGC_PREV_MASK) | uprev); } diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index 0981d1122fec54..3ac7e89bbf5345 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -326,9 +326,9 @@ _PyObject_GET_WEAKREFS_LISTPTR_FROM_OFFSET(PyObject *op) static inline int _PyObject_IS_GC(PyObject *obj) { - return (PyType_IS_GC(Py_TYPE(obj)) - && (Py_TYPE(obj)->tp_is_gc == NULL - || Py_TYPE(obj)->tp_is_gc(obj))); + PyTypeObject *type = Py_TYPE(obj); + return (PyType_IS_GC(type) + && (type->tp_is_gc == NULL || type->tp_is_gc(obj))); } // Fast inlined version of PyType_IS_GC() diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 26ddcdd538a4d4..c51c100be8361d 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -68,11 +68,9 @@ module gc // most gc_list_* functions for it. #define NEXT_MASK_UNREACHABLE (1) -/* Get an object's GC head */ -#define AS_GC(o) ((PyGC_Head *)(((char *)(o))-sizeof(PyGC_Head))) +#define AS_GC(op) _Py_AS_GC(op) +#define FROM_GC(gc) _Py_FROM_GC(gc) -/* Get the object given the GC head */ -#define FROM_GC(g) ((PyObject *)(((char *)(g))+sizeof(PyGC_Head))) static inline int gc_is_collecting(PyGC_Head *g) @@ -861,7 +859,7 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old) * to imagine how calling it later could create a problem for us. wr * is moved to wrcb_to_call in this case. */ - if (gc_is_collecting(AS_GC(wr))) { + if (gc_is_collecting(AS_GC((PyObject *)wr))) { /* it should already have been cleared above */ assert(wr->wr_object == Py_None); continue; @@ -873,7 +871,7 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old) Py_INCREF(wr); /* Move wr to wrcb_to_call, for the next pass. */ - wrasgc = AS_GC(wr); + wrasgc = AS_GC((PyObject *)wr); assert(wrasgc != next); /* wrasgc is reachable, but next isn't, so they can't be the same */ @@ -1909,7 +1907,7 @@ static PyObject * gc_is_finalized(PyObject *module, PyObject *obj) /*[clinic end generated code: output=e1516ac119a918ed input=201d0c58f69ae390]*/ { - if (_PyObject_IS_GC(obj) && _PyGCHead_FINALIZED(AS_GC(obj))) { + if (_PyObject_IS_GC(obj) && _PyGC_FINALIZED(obj)) { Py_RETURN_TRUE; } Py_RETURN_FALSE; @@ -2409,7 +2407,7 @@ PyObject_GC_IsTracked(PyObject* obj) int PyObject_GC_IsFinalized(PyObject *obj) { - if (_PyObject_IS_GC(obj) && _PyGCHead_FINALIZED(AS_GC(obj))) { + if (_PyObject_IS_GC(obj) && _PyGC_FINALIZED(obj)) { return 1; } return 0;