]> granicus.if.org Git - python/commitdiff
SF bug [#467145] Python 2.2a4 build problem on HPUX 11.0.
authorTim Peters <tim.peters@gmail.com>
Thu, 11 Oct 2001 18:31:31 +0000 (18:31 +0000)
committerTim Peters <tim.peters@gmail.com>
Thu, 11 Oct 2001 18:31:31 +0000 (18:31 +0000)
The platform requires 8-byte alignment for doubles, but the GC header
was 12 bytes and that threw off the natural alignment of the double
members of a subtype of complex.  The fix puts the GC header into a
union with a double as the other member, to force no-looser-than
double alignment of GC headers.  On boxes that require 8-byte alignment
for doubles, this may add pad bytes to the GC header accordingly; ditto
for platforms that *prefer* 8-byte alignment for doubles.  On platforms
that don't care, it shouldn't change the memory layout (because the
size of the old GC header is certainly greater than the size of a double
on all platforms, so unioning with a double shouldn't change size or
alignment on such boxes).

Include/objimpl.h
Modules/gcmodule.c

index db4cb6d4dd29e34273609b5e415a61a632009f89..e8aad544c6432fb8b2b83a3c3eb1c758d3eeb35e 100644 (file)
@@ -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)
index 34503e43a3e8d0ce4461f292d1169a7302ca69e3..db35b3deae6b8c830960caa5846a45bb240b4c8a 100644 (file)
@@ -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--;