Skip to content

Commit

Permalink
gc: swap order of PyGC_Head and managed dict/weakref
Browse files Browse the repository at this point in the history
This is a temporary change to make rebasing easier. The tracing garbage
collector needs to identify live vs. dead blocks. This was combined with
the checking of tracked objects: tracked objects always have the low bit
of PyGC_Head->_gc_prev set to 1. Unallocated mimalloc blocks always have
a pointer (or NULL) in the first word; the LSB is never 1.

Ensuring that PyGC_Head comes at the beginning of the allocation makes
this easier.
  • Loading branch information
colesbury committed Apr 23, 2023
1 parent 254e419 commit e8c13ea
Show file tree
Hide file tree
Showing 6 changed files with 20 additions and 13 deletions.
13 changes: 11 additions & 2 deletions Include/internal/pycore_gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,19 @@ typedef struct {
uintptr_t _gc_prev;
} PyGC_Head;

typedef struct {
PyGC_Head _gc_head;
PyObject *_dict_or_values;
PyObject *_weakref;
} _PyGC_Preheader_UNUSED;

#define PyGC_Head_OFFSET (((Py_ssize_t)sizeof(PyObject *))*-4)

static inline PyGC_Head* _Py_AS_GC(PyObject *op) {
return (_Py_CAST(PyGC_Head*, op) - 1);
char *mem = _Py_STATIC_CAST(char*, op);
return _Py_STATIC_CAST(PyGC_Head*, mem + PyGC_Head_OFFSET);
}
#define _PyGC_Head_UNUSED PyGC_Head
#define _PyGC_Head_UNUSED _PyGC_Preheader_UNUSED

/* True if the object is currently tracked by the GC. */
static inline int _PyObject_GC_IS_TRACKED(PyObject *op) {
Expand Down
4 changes: 2 additions & 2 deletions Include/internal/pycore_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -469,8 +469,8 @@ extern int _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values,
PyObject * _PyObject_GetInstanceAttribute(PyObject *obj, PyDictValues *values,
PyObject *name);

#define MANAGED_WEAKREF_OFFSET (((Py_ssize_t)sizeof(PyObject *))*-4)
#define MANAGED_DICT_OFFSET (((Py_ssize_t)sizeof(PyObject *))*-3)
#define MANAGED_WEAKREF_OFFSET (((Py_ssize_t)sizeof(PyObject *))*-2)
#define MANAGED_DICT_OFFSET (((Py_ssize_t)sizeof(PyObject *))*-1)

typedef union {
PyObject *dict;
Expand Down
8 changes: 4 additions & 4 deletions Modules/gcmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ module gc
#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(o) ((PyGC_Head *)(((char *)(o))+PyGC_Head_OFFSET))

/* Get the object given the GC head */
#define FROM_GC(g) ((PyObject *)(((char *)(g))+sizeof(PyGC_Head)))
#define FROM_GC(g) ((PyObject *)(((char *)(g))-PyGC_Head_OFFSET))

static inline int
gc_is_collecting(PyGC_Head *g)
Expand Down Expand Up @@ -2349,8 +2349,8 @@ gc_alloc(size_t basicsize, size_t presize)
if (mem == NULL) {
return _PyErr_NoMemory(tstate);
}
((PyObject **)mem)[0] = NULL;
((PyObject **)mem)[1] = NULL;
((PyObject **)mem)[2] = NULL;
((PyObject **)mem)[3] = NULL;
PyObject *op = (PyObject *)(mem + presize);
_PyObject_GC_Link(op);
return op;
Expand Down
4 changes: 1 addition & 3 deletions Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1297,13 +1297,11 @@ _PyType_AllocNoTrack(PyTypeObject *type, Py_ssize_t nitems)
if (alloc == NULL) {
return PyErr_NoMemory();
}
memset(alloc, '\0', size + presize);
obj = (PyObject *)(alloc + presize);
if (presize) {
((PyObject **)alloc)[0] = NULL;
((PyObject **)alloc)[1] = NULL;
_PyObject_GC_Link(obj);
}
memset(obj, '\0', size);

if (type->tp_itemsize == 0) {
_PyObject_Init(obj, type);
Expand Down
2 changes: 1 addition & 1 deletion Tools/build/deepfreeze.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ def generate_tuple(self, name: str, t: Tuple[object, ...]) -> str:
self.write("static")
with self.indent():
with self.block("struct"):
self.write("PyGC_Head _gc_head;")
self.write("_PyGC_Head_UNUSED _gc_head;")
with self.block("struct", "_object;"):
self.write("PyObject_VAR_HEAD")
if t:
Expand Down
2 changes: 1 addition & 1 deletion Tools/gdb/libpython.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def _sizeof_void_p():
Py_TPFLAGS_TYPE_SUBCLASS = (1 << 31)

#From pycore_object.h
MANAGED_DICT_OFFSET = -3
MANAGED_DICT_OFFSET = -1

#From pycore_frame.h
FRAME_OWNED_BY_CSTACK = 3
Expand Down

0 comments on commit e8c13ea

Please sign in to comment.