mirror of
https://github.com/python/cpython.git
synced 2025-08-01 15:43:13 +00:00
gh-112529: Remove PyGC_Head from object pre-header in free-threaded build (#114564)
* gh-112529: Remove PyGC_Head from object pre-header in free-threaded build This avoids allocating space for PyGC_Head in the free-threaded build. The GC implementation for free-threaded CPython does not use the PyGC_Head structure. * The trashcan mechanism uses the `ob_tid` field instead of `_gc_prev` in the free-threaded build. * The GDB libpython.py file now determines the offset of the managed dict field based on whether the running process is a free-threaded build. Those are identified by the `ob_ref_local` field in PyObject. * Fixes `_PySys_GetSizeOf()` which incorrectly incorrectly included the size of `PyGC_Head` in the size of static `PyTypeObject`.
This commit is contained in:
parent
500ede0117
commit
587d480203
9 changed files with 86 additions and 26 deletions
|
@ -315,16 +315,15 @@ static inline void _PyObject_GC_TRACK(
|
|||
_PyObject_ASSERT_FROM(op, !_PyObject_GC_IS_TRACKED(op),
|
||||
"object already tracked by the garbage collector",
|
||||
filename, lineno, __func__);
|
||||
|
||||
#ifdef Py_GIL_DISABLED
|
||||
op->ob_gc_bits |= _PyGC_BITS_TRACKED;
|
||||
#else
|
||||
PyGC_Head *gc = _Py_AS_GC(op);
|
||||
_PyObject_ASSERT_FROM(op,
|
||||
(gc->_gc_prev & _PyGC_PREV_MASK_COLLECTING) == 0,
|
||||
"object is in generation which is garbage collected",
|
||||
filename, lineno, __func__);
|
||||
|
||||
#ifdef Py_GIL_DISABLED
|
||||
op->ob_gc_bits |= _PyGC_BITS_TRACKED;
|
||||
#else
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
PyGC_Head *generation0 = interp->gc.generation0;
|
||||
PyGC_Head *last = (PyGC_Head*)(generation0->_gc_prev);
|
||||
|
@ -594,8 +593,12 @@ _PyObject_IS_GC(PyObject *obj)
|
|||
static inline size_t
|
||||
_PyType_PreHeaderSize(PyTypeObject *tp)
|
||||
{
|
||||
return _PyType_IS_GC(tp) * sizeof(PyGC_Head) +
|
||||
_PyType_HasFeature(tp, Py_TPFLAGS_PREHEADER) * 2 * sizeof(PyObject *);
|
||||
return (
|
||||
#ifndef Py_GIL_DISABLED
|
||||
_PyType_IS_GC(tp) * sizeof(PyGC_Head) +
|
||||
#endif
|
||||
_PyType_HasFeature(tp, Py_TPFLAGS_PREHEADER) * 2 * sizeof(PyObject *)
|
||||
);
|
||||
}
|
||||
|
||||
void _PyObject_GC_Link(PyObject *op);
|
||||
|
@ -625,6 +628,14 @@ extern int _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
|
|||
PyObject * _PyObject_GetInstanceAttribute(PyObject *obj, PyDictValues *values,
|
||||
PyObject *name);
|
||||
|
||||
#ifdef Py_GIL_DISABLED
|
||||
# define MANAGED_DICT_OFFSET (((Py_ssize_t)sizeof(PyObject *))*-1)
|
||||
# define MANAGED_WEAKREF_OFFSET (((Py_ssize_t)sizeof(PyObject *))*-2)
|
||||
#else
|
||||
# define MANAGED_DICT_OFFSET (((Py_ssize_t)sizeof(PyObject *))*-3)
|
||||
# define MANAGED_WEAKREF_OFFSET (((Py_ssize_t)sizeof(PyObject *))*-4)
|
||||
#endif
|
||||
|
||||
typedef union {
|
||||
PyObject *dict;
|
||||
/* Use a char* to generate a warning if directly assigning a PyDictValues */
|
||||
|
@ -635,7 +646,7 @@ static inline PyDictOrValues *
|
|||
_PyObject_DictOrValuesPointer(PyObject *obj)
|
||||
{
|
||||
assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
|
||||
return ((PyDictOrValues *)obj)-3;
|
||||
return (PyDictOrValues *)((char *)obj + MANAGED_DICT_OFFSET);
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
@ -664,8 +675,6 @@ _PyDictOrValues_SetValues(PyDictOrValues *ptr, PyDictValues *values)
|
|||
ptr->values = ((char *)values) - 1;
|
||||
}
|
||||
|
||||
#define MANAGED_WEAKREF_OFFSET (((Py_ssize_t)sizeof(PyObject *))*-4)
|
||||
|
||||
extern PyObject ** _PyObject_ComputedDictPointer(PyObject *);
|
||||
extern void _PyObject_FreeInstanceAttributes(PyObject *obj);
|
||||
extern int _PyObject_IsInstanceDictEmpty(PyObject *);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue