summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-10-11 18:31:31 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-10-11 18:31:31 (GMT)
commit9e4ca10ce439845c939a9fa4264146a4cfa87fee (patch)
tree177a1b1f5fac5e873c72fdd2206b839c3947bab8
parentf3623f310e92ddb499e020635fe4977aae38a719 (diff)
downloadcpython-9e4ca10ce439845c939a9fa4264146a4cfa87fee.zip
cpython-9e4ca10ce439845c939a9fa4264146a4cfa87fee.tar.gz
cpython-9e4ca10ce439845c939a9fa4264146a4cfa87fee.tar.bz2
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).
-rw-r--r--Include/objimpl.h27
-rw-r--r--Modules/gcmodule.c112
2 files changed, 71 insertions, 68 deletions
diff --git a/Include/objimpl.h b/Include/objimpl.h
index db4cb6d..e8aad54 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 34503e4..db35b3d 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--;