[Python-checkins] python/dist/src/Objects typeobject.c,2.126.4.12,2.126.4.13
gvanrossum@users.sourceforge.net
gvanrossum@users.sourceforge.net
Tue, 04 Jun 2002 14:19:58 -0700
Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv27530/Objects
Modified Files:
Tag: release22-maint
typeobject.c
Log Message:
Backport to 2.2.x:
Address SF bug 519621: slots weren't traversed by GC.
While I was at it, I added a tp_clear handler and changed the
tp_dealloc handler to use the clear_slots helper for the tp_clear
handler.
Also set mp->flags = READONLY for the __weakref__ pseudo-slot.
[Note that I am *not* backporting the part of that patch that
tightened the __slot__ rules.]
Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.126.4.12
retrieving revision 2.126.4.13
diff -C2 -d -r2.126.4.12 -r2.126.4.13
*** typeobject.c 3 Jun 2002 19:54:10 -0000 2.126.4.12
--- typeobject.c 4 Jun 2002 21:19:55 -0000 2.126.4.13
***************
*** 5,8 ****
--- 5,22 ----
#include "structmember.h"
+ #include <ctype.h>
+
+ /* The *real* layout of a type object when allocated on the heap */
+ /* XXX Should we publish this in a header file? */
+ typedef struct {
+ PyTypeObject type;
+ PyNumberMethods as_number;
+ PySequenceMethods as_sequence;
+ PyMappingMethods as_mapping;
+ PyBufferProcs as_buffer;
+ PyObject *name, *slots;
+ PyMemberDef members[1];
+ } etype;
+
static PyMemberDef type_members[] = {
{"__basicsize__", T_INT, offsetof(PyTypeObject,tp_basicsize),READONLY},
***************
*** 224,237 ****
static int
subtype_traverse(PyObject *self, visitproc visit, void *arg)
{
PyTypeObject *type, *base;
! traverseproc f;
! int err;
! /* Find the nearest base with a different tp_traverse */
type = self->ob_type;
! base = type->tp_base;
! while ((f = base->tp_traverse) == subtype_traverse) {
base = base->tp_base;
assert(base);
--- 238,278 ----
static int
+ traverse_slots(PyTypeObject *type, PyObject *self, visitproc visit, void *arg)
+ {
+ int i, n;
+ PyMemberDef *mp;
+
+ n = type->ob_size;
+ mp = ((etype *)type)->members;
+ for (i = 0; i < n; i++, mp++) {
+ if (mp->type == T_OBJECT_EX) {
+ char *addr = (char *)self + mp->offset;
+ PyObject *obj = *(PyObject **)addr;
+ if (obj != NULL) {
+ int err = visit(obj, arg);
+ if (err)
+ return err;
+ }
+ }
+ }
+ return 0;
+ }
+
+ static int
subtype_traverse(PyObject *self, visitproc visit, void *arg)
{
PyTypeObject *type, *base;
! traverseproc basetraverse;
! /* Find the nearest base with a different tp_traverse,
! and traverse slots while we're at it */
type = self->ob_type;
! base = type;
! while ((basetraverse = base->tp_traverse) == subtype_traverse) {
! if (base->ob_size) {
! int err = traverse_slots(base, self, visit, arg);
! if (err)
! return err;
! }
base = base->tp_base;
assert(base);
***************
*** 241,245 ****
PyObject **dictptr = _PyObject_GetDictPtr(self);
if (dictptr && *dictptr) {
! err = visit(*dictptr, arg);
if (err)
return err;
--- 282,286 ----
PyObject **dictptr = _PyObject_GetDictPtr(self);
if (dictptr && *dictptr) {
! int err = visit(*dictptr, arg);
if (err)
return err;
***************
*** 247,252 ****
}
! if (f)
! return f(self, visit, arg);
return 0;
}
--- 288,342 ----
}
! if (basetraverse)
! return basetraverse(self, visit, arg);
! return 0;
! }
!
! static void
! clear_slots(PyTypeObject *type, PyObject *self)
! {
! int i, n;
! PyMemberDef *mp;
!
! n = type->ob_size;
! mp = ((etype *)type)->members;
! for (i = 0; i < n; i++, mp++) {
! if (mp->type == T_OBJECT_EX && !(mp->flags & READONLY)) {
! char *addr = (char *)self + mp->offset;
! PyObject *obj = *(PyObject **)addr;
! if (obj != NULL) {
! Py_DECREF(obj);
! *(PyObject **)addr = NULL;
! }
! }
! }
! }
!
! static int
! subtype_clear(PyObject *self)
! {
! PyTypeObject *type, *base;
! inquiry baseclear;
!
! /* Find the nearest base with a different tp_clear
! and clear slots while we're at it */
! type = self->ob_type;
! base = type;
! while ((baseclear = base->tp_clear) == subtype_clear) {
! if (base->ob_size)
! clear_slots(base, self);
! base = base->tp_base;
! assert(base);
! }
!
! if (type->tp_dictoffset != base->tp_dictoffset) {
! PyObject **dictptr = _PyObject_GetDictPtr(self);
! if (dictptr && *dictptr) {
! PyDict_Clear(*dictptr);
! }
! }
!
! if (baseclear)
! return baseclear(self);
return 0;
}
***************
*** 327,331 ****
{
PyTypeObject *type, *base;
! destructor f;
/* This exists so we can DECREF self->ob_type */
--- 417,421 ----
{
PyTypeObject *type, *base;
! destructor basedealloc;
/* This exists so we can DECREF self->ob_type */
***************
*** 334,365 ****
return;
! /* Find the nearest base with a different tp_dealloc */
type = self->ob_type;
! base = type->tp_base;
! while ((f = base->tp_dealloc) == subtype_dealloc) {
base = base->tp_base;
assert(base);
}
- /* Clear __slots__ variables */
- if (type->tp_basicsize != base->tp_basicsize &&
- type->tp_itemsize == 0)
- {
- char *addr = ((char *)self);
- char *p = addr + base->tp_basicsize;
- char *q = addr + type->tp_basicsize;
- for (; p < q; p += sizeof(PyObject *)) {
- PyObject **pp;
- if (p == addr + type->tp_dictoffset ||
- p == addr + type->tp_weaklistoffset)
- continue;
- pp = (PyObject **)p;
- if (*pp != NULL) {
- Py_DECREF(*pp);
- *pp = NULL;
- }
- }
- }
-
/* If we added a dict, DECREF it */
if (type->tp_dictoffset && !base->tp_dictoffset) {
--- 424,438 ----
return;
! /* Find the nearest base with a different tp_dealloc
! and clear slots while we're at it */
type = self->ob_type;
! base = type;
! while ((basedealloc = base->tp_dealloc) == subtype_dealloc) {
! if (base->ob_size)
! clear_slots(base, self);
base = base->tp_base;
assert(base);
}
/* If we added a dict, DECREF it */
if (type->tp_dictoffset && !base->tp_dictoffset) {
***************
*** 383,388 ****
/* Call the base tp_dealloc() */
! assert(f);
! f(self);
/* Can't reference self beyond this point */
--- 456,461 ----
/* Call the base tp_dealloc() */
! assert(basedealloc);
! basedealloc(self);
/* Can't reference self beyond this point */
***************
*** 394,407 ****
staticforward PyTypeObject *solid_base(PyTypeObject *type);
- typedef struct {
- PyTypeObject type;
- PyNumberMethods as_number;
- PySequenceMethods as_sequence;
- PyMappingMethods as_mapping;
- PyBufferProcs as_buffer;
- PyObject *name, *slots;
- PyMemberDef members[1];
- } etype;
-
/* type test with subclassing support */
--- 467,470 ----
***************
*** 1143,1146 ****
--- 1206,1210 ----
strcmp(mp->name, "__weakref__") == 0) {
mp->type = T_OBJECT;
+ mp->flags = READONLY;
type->tp_weaklistoffset = slotoffset;
}
***************
*** 1192,1196 ****
type->tp_free = _PyObject_GC_Del;
type->tp_traverse = subtype_traverse;
! type->tp_clear = base->tp_clear;
}
else
--- 1256,1260 ----
type->tp_free = _PyObject_GC_Del;
type->tp_traverse = subtype_traverse;
! type->tp_clear = subtype_clear;
}
else