SF bug [#467145] Python 2.2a4 build problem on HPUX 11.0.

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).
This commit is contained in:
Tim Peters 2001-10-11 18:31:31 +00:00
parent f3623f310e
commit 9e4ca10ce4
2 changed files with 71 additions and 68 deletions

View 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)

View 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--;