diff --git a/Include/objimpl.h b/Include/objimpl.h index db4cb6d4dd2..e8aad544c64 100644 --- a/Include/objimpl.h +++ b/Include/objimpl.h @@ -266,10 +266,13 @@ extern DL_IMPORT(void) _PyObject_GC_UnTrack(PyObject *); #ifdef WITH_CYCLE_GC /* GC information is stored BEFORE the object structure */ -typedef struct _gc_head { - struct _gc_head *gc_next; /* not NULL if object is tracked */ - struct _gc_head *gc_prev; - int gc_refs; +typedef union _gc_head { + struct { + union _gc_head *gc_next; /* not NULL if object is tracked */ + union _gc_head *gc_prev; + int gc_refs; + } gc; + double dummy; /* force worst-case alignment */ } PyGC_Head; extern PyGC_Head _PyGC_generation0; @@ -278,20 +281,20 @@ extern PyGC_Head _PyGC_generation0; * collector it must be safe to call the ob_traverse method. */ #define _PyObject_GC_TRACK(o) do { \ PyGC_Head *g = (PyGC_Head *)(o)-1; \ - if (g->gc_next != NULL) \ + if (g->gc.gc_next != NULL) \ Py_FatalError("GC object already in linked list"); \ - g->gc_next = &_PyGC_generation0; \ - g->gc_prev = _PyGC_generation0.gc_prev; \ - g->gc_prev->gc_next = g; \ - _PyGC_generation0.gc_prev = g; \ + g->gc.gc_next = &_PyGC_generation0; \ + g->gc.gc_prev = _PyGC_generation0.gc.gc_prev; \ + g->gc.gc_prev->gc.gc_next = g; \ + _PyGC_generation0.gc.gc_prev = g; \ } while (0); /* Tell the GC to stop tracking this object. */ #define _PyObject_GC_UNTRACK(o) do { \ PyGC_Head *g = (PyGC_Head *)(o)-1; \ - g->gc_prev->gc_next = g->gc_next; \ - g->gc_next->gc_prev = g->gc_prev; \ - g->gc_next = NULL; \ + g->gc.gc_prev->gc.gc_next = g->gc.gc_next; \ + g->gc.gc_next->gc.gc_prev = g->gc.gc_prev; \ + g->gc.gc_next = NULL; \ } while (0); #define PyObject_GC_Track(op) _PyObject_GC_Track((PyObject *)op) diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 34503e43a3e..db35b3deae6 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -77,39 +77,39 @@ static PyObject *gc_str; static void gc_list_init(PyGC_Head *list) { - list->gc_prev = list; - list->gc_next = list; + list->gc.gc_prev = list; + list->gc.gc_next = list; } static void gc_list_append(PyGC_Head *node, PyGC_Head *list) { - node->gc_next = list; - node->gc_prev = list->gc_prev; - node->gc_prev->gc_next = node; - list->gc_prev = node; + node->gc.gc_next = list; + node->gc.gc_prev = list->gc.gc_prev; + node->gc.gc_prev->gc.gc_next = node; + list->gc.gc_prev = node; } static void gc_list_remove(PyGC_Head *node) { - node->gc_prev->gc_next = node->gc_next; - node->gc_next->gc_prev = node->gc_prev; - node->gc_next = NULL; /* object is not currently tracked */ + node->gc.gc_prev->gc.gc_next = node->gc.gc_next; + node->gc.gc_next->gc.gc_prev = node->gc.gc_prev; + node->gc.gc_next = NULL; /* object is not currently tracked */ } static void gc_list_move(PyGC_Head *from, PyGC_Head *to) { - if (from->gc_next == from) { + if (from->gc.gc_next == from) { /* empty from list */ gc_list_init(to); } else { - to->gc_next = from->gc_next; - to->gc_next->gc_prev = to; - to->gc_prev = from->gc_prev; - to->gc_prev->gc_next = to; + to->gc.gc_next = from->gc.gc_next; + to->gc.gc_next->gc.gc_prev = to; + to->gc.gc_prev = from->gc.gc_prev; + to->gc.gc_prev->gc.gc_next = to; } gc_list_init(from); } @@ -119,12 +119,12 @@ static void gc_list_merge(PyGC_Head *from, PyGC_Head *to) { PyGC_Head *tail; - if (from->gc_next != from) { - tail = to->gc_prev; - tail->gc_next = from->gc_next; - tail->gc_next->gc_prev = tail; - to->gc_prev = from->gc_prev; - to->gc_prev->gc_next = to; + if (from->gc.gc_next != from) { + tail = to->gc.gc_prev; + tail->gc.gc_next = from->gc.gc_next; + tail->gc.gc_next->gc.gc_prev = tail; + to->gc.gc_prev = from->gc.gc_prev; + to->gc.gc_prev->gc.gc_next = to; } gc_list_init(from); } @@ -134,7 +134,7 @@ gc_list_size(PyGC_Head *list) { PyGC_Head *gc; long n = 0; - for (gc = list->gc_next; gc != list; gc = gc->gc_next) { + for (gc = list->gc.gc_next; gc != list; gc = gc->gc.gc_next) { n++; } return n; @@ -148,9 +148,9 @@ gc_list_size(PyGC_Head *list) static void update_refs(PyGC_Head *containers) { - PyGC_Head *gc = containers->gc_next; - for (; gc != containers; gc=gc->gc_next) { - gc->gc_refs = FROM_GC(gc)->ob_refcnt; + PyGC_Head *gc = containers->gc.gc_next; + for (; gc != containers; gc=gc->gc.gc_next) { + gc->gc.gc_refs = FROM_GC(gc)->ob_refcnt; } } @@ -159,8 +159,8 @@ visit_decref(PyObject *op, void *data) { if (op && PyObject_IS_GC(op)) { PyGC_Head *gc = AS_GC(op); - if (gc->gc_next != NULL) - AS_GC(op)->gc_refs--; + if (gc->gc.gc_next != NULL) + AS_GC(op)->gc.gc_refs--; } return 0; } @@ -170,8 +170,8 @@ static void subtract_refs(PyGC_Head *containers) { traverseproc traverse; - PyGC_Head *gc = containers->gc_next; - for (; gc != containers; gc=gc->gc_next) { + PyGC_Head *gc = containers->gc.gc_next; + for (; gc != containers; gc=gc->gc.gc_next) { traverse = FROM_GC(gc)->ob_type->tp_traverse; (void) traverse(FROM_GC(gc), (visitproc)visit_decref, @@ -184,13 +184,13 @@ static void move_roots(PyGC_Head *containers, PyGC_Head *roots) { PyGC_Head *next; - PyGC_Head *gc = containers->gc_next; + PyGC_Head *gc = containers->gc.gc_next; while (gc != containers) { - next = gc->gc_next; - if (gc->gc_refs > 0) { + next = gc->gc.gc_next; + if (gc->gc.gc_refs > 0) { gc_list_remove(gc); gc_list_append(gc, roots); - gc->gc_refs = GC_MOVED; + gc->gc.gc_refs = GC_MOVED; } gc = next; } @@ -201,10 +201,10 @@ visit_move(PyObject *op, PyGC_Head *tolist) { if (PyObject_IS_GC(op)) { PyGC_Head *gc = AS_GC(op); - if (gc->gc_next != NULL && gc->gc_refs != GC_MOVED) { + if (gc->gc.gc_next != NULL && gc->gc.gc_refs != GC_MOVED) { gc_list_remove(gc); gc_list_append(gc, tolist); - gc->gc_refs = GC_MOVED; + gc->gc.gc_refs = GC_MOVED; } } return 0; @@ -215,8 +215,8 @@ static void move_root_reachable(PyGC_Head *reachable) { traverseproc traverse; - PyGC_Head *gc = reachable->gc_next; - for (; gc != reachable; gc=gc->gc_next) { + PyGC_Head *gc = reachable->gc.gc_next; + for (; gc != reachable; gc=gc->gc.gc_next) { /* careful, reachable list is growing here */ PyObject *op = FROM_GC(gc); traverse = op->ob_type->tp_traverse; @@ -231,7 +231,7 @@ static void move_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers) { PyGC_Head *next; - PyGC_Head *gc = unreachable->gc_next; + PyGC_Head *gc = unreachable->gc.gc_next; static PyObject *delstr = NULL; if (delstr == NULL) { delstr = PyString_InternFromString("__del__"); @@ -240,7 +240,7 @@ move_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers) } for (; gc != unreachable; gc=next) { PyObject *op = FROM_GC(gc); - next = gc->gc_next; + next = gc->gc.gc_next; if (PyInstance_Check(op) && PyObject_HasAttr(op, delstr)) { gc_list_remove(gc); gc_list_append(gc, finalizers); @@ -253,8 +253,8 @@ static void move_finalizer_reachable(PyGC_Head *finalizers) { traverseproc traverse; - PyGC_Head *gc = finalizers->gc_next; - for (; gc != finalizers; gc=gc->gc_next) { + PyGC_Head *gc = finalizers->gc.gc_next; + for (; gc != finalizers; gc=gc->gc.gc_next) { /* careful, finalizers list is growing here */ traverse = FROM_GC(gc)->ob_type->tp_traverse; (void) traverse(FROM_GC(gc), @@ -297,8 +297,8 @@ handle_finalizers(PyGC_Head *finalizers, PyGC_Head *old) if (garbage == NULL) { garbage = PyList_New(0); } - for (gc = finalizers->gc_next; gc != finalizers; - gc = finalizers->gc_next) { + for (gc = finalizers->gc.gc_next; gc != finalizers; + gc = finalizers->gc.gc_next) { PyObject *op = FROM_GC(gc); if ((debug & DEBUG_SAVEALL) || PyInstance_Check(op)) { /* If SAVEALL is not set then just append @@ -321,8 +321,8 @@ delete_garbage(PyGC_Head *unreachable, PyGC_Head *old) { inquiry clear; - while (unreachable->gc_next != unreachable) { - PyGC_Head *gc = unreachable->gc_next; + while (unreachable->gc.gc_next != unreachable) { + PyGC_Head *gc = unreachable->gc.gc_next; PyObject *op = FROM_GC(gc); if (debug & DEBUG_SAVEALL) { PyList_Append(garbage, op); @@ -334,7 +334,7 @@ delete_garbage(PyGC_Head *unreachable, PyGC_Head *old) Py_DECREF(op); } } - if (unreachable->gc_next == gc) { + if (unreachable->gc.gc_next == gc) { /* object is still alive, move it, it may die later */ gc_list_remove(gc); gc_list_append(gc, old); @@ -396,8 +396,8 @@ collect(PyGC_Head *young, PyGC_Head *old) /* Collect statistics on collectable objects found and print * debugging information. */ - for (gc = unreachable.gc_next; gc != &unreachable; - gc = gc->gc_next) { + for (gc = unreachable.gc.gc_next; gc != &unreachable; + gc = gc->gc.gc_next) { m++; if (debug & DEBUG_COLLECTABLE) { debug_cycle("collectable", FROM_GC(gc)); @@ -410,8 +410,8 @@ collect(PyGC_Head *young, PyGC_Head *old) /* Collect statistics on uncollectable objects found and print * debugging information. */ - for (gc = finalizers.gc_next; gc != &finalizers; - gc = gc->gc_next) { + for (gc = finalizers.gc.gc_next; gc != &finalizers; + gc = gc->gc.gc_next) { n++; if (debug & DEBUG_UNCOLLECTABLE) { debug_cycle("uncollectable", FROM_GC(gc)); @@ -456,7 +456,7 @@ collect_generations(void) generation = 2; gc_list_merge(&_PyGC_generation0, &generation2); gc_list_merge(&generation1, &generation2); - if (generation2.gc_next != &generation2) { + if (generation2.gc.gc_next != &generation2) { n = collect(&generation2, &generation2); } collections1 = 0; @@ -465,7 +465,7 @@ collect_generations(void) generation = 1; collections1++; gc_list_merge(&_PyGC_generation0, &generation1); - if (generation1.gc_next != &generation1) { + if (generation1.gc.gc_next != &generation1) { n = collect(&generation1, &generation2); } collections0 = 0; @@ -473,7 +473,7 @@ collect_generations(void) else { generation = 0; collections0++; - if (_PyGC_generation0.gc_next != &_PyGC_generation0) { + if (_PyGC_generation0.gc.gc_next != &_PyGC_generation0) { n = collect(&_PyGC_generation0, &generation1); } } @@ -646,7 +646,7 @@ gc_referents_for(PyObject *objs, PyGC_Head *list, PyObject *resultlist) PyGC_Head *gc; PyObject *obj; traverseproc traverse; - for (gc = list->gc_next; gc != list; gc = gc->gc_next) { + for (gc = list->gc.gc_next; gc != list; gc = gc->gc.gc_next) { obj = FROM_GC(gc); traverse = obj->ob_type->tp_traverse; if (obj == objs || obj == resultlist) @@ -688,7 +688,7 @@ static void append_objects(PyObject *py_list, PyGC_Head *gc_list) { PyGC_Head *gc; - for (gc = gc_list->gc_next; gc != gc_list; gc = gc->gc_next) { + for (gc = gc_list->gc.gc_next; gc != gc_list; gc = gc->gc.gc_next) { PyObject *op = FROM_GC(gc); if (op != py_list) { Py_INCREF(op); @@ -807,7 +807,7 @@ _PyObject_GC_Malloc(PyTypeObject *tp, int nitems) PyGC_Head *g = PyObject_MALLOC(nbytes); if (g == NULL) return (PyObject *)PyErr_NoMemory(); - g->gc_next = NULL; + g->gc.gc_next = NULL; allocated++; if (allocated > threshold0 && enabled && @@ -866,7 +866,7 @@ _PyObject_GC_Del(PyObject *op) { #ifdef WITH_CYCLE_GC PyGC_Head *g = AS_GC(op); - if (g->gc_next != NULL) + if (g->gc.gc_next != NULL) gc_list_remove(g); if (allocated > 0) { allocated--;