Index: Objects/descrobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/descrobject.c,v retrieving revision 2.38 diff -c -r2.38 descrobject.c *** Objects/descrobject.c 13 Dec 2003 11:58:56 -0000 2.38 --- Objects/descrobject.c 30 Mar 2005 16:53:20 -0000 *************** *** 129,138 **** member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type) { PyObject *res; if (descr_check((PyDescrObject *)descr, obj, &res)) return res; ! return PyMember_GetOne((char *)obj, descr->d_member); } static PyObject * --- 129,152 ---- member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type) { PyObject *res; + char *addr = (char*)obj; if (descr_check((PyDescrObject *)descr, obj, &res)) return res; ! if (descr->d_member->offset < 0) { ! int tsize; ! size_t size; ! ! tsize = ((PyVarObject *)obj)->ob_size; ! if (tsize < 0) ! tsize = -tsize; ! size = descr->d_type->tp_basicsize + tsize * descr->d_type->tp_itemsize; ! size = (size + (SIZEOF_VOID_P - 1)) & ~(SIZEOF_VOID_P - 1); ! ! addr += (long)size; ! assert(addr - (char*)obj > 0); ! } ! return PyMember_GetOne(addr, descr->d_member); } static PyObject * *************** *** 183,192 **** member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value) { int res; if (descr_setcheck((PyDescrObject *)descr, obj, value, &res)) return res; ! return PyMember_SetOne((char *)obj, descr->d_member, value); } static int --- 197,220 ---- member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value) { int res; + char *addr = (char*)obj; if (descr_setcheck((PyDescrObject *)descr, obj, value, &res)) return res; ! if (descr->d_member->offset < 0) { ! int tsize; ! size_t size; ! ! tsize = ((PyVarObject *)obj)->ob_size; ! if (tsize < 0) ! tsize = -tsize; ! size = descr->d_type->tp_basicsize + tsize * descr->d_type->tp_itemsize; ! size = (size + (SIZEOF_VOID_P - 1)) & ~(SIZEOF_VOID_P - 1); ! ! addr += (long)size; ! assert(addr - (char*)obj > 0); ! } ! return PyMember_SetOne(addr, descr->d_member, value); } static int Index: Objects/typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.265 diff -c -r2.265 typeobject.c *** Objects/typeobject.c 3 Mar 2005 16:45:19 -0000 2.265 --- Objects/typeobject.c 30 Mar 2005 16:54:09 -0000 *************** *** 351,362 **** --- 351,374 ---- return result; } + static PyTypeObject *solid_base(PyTypeObject *type); + + static PyObject * + type_get_solid(PyTypeObject *type, void *context) + { + PyObject *result; + result = (PyObject*)solid_base(type); + Py_INCREF(result); + return result; + } + static PyGetSetDef type_getsets[] = { {"__name__", (getter)type_name, (setter)type_set_name, NULL}, {"__bases__", (getter)type_get_bases, (setter)type_set_bases, NULL}, {"__module__", (getter)type_module, (setter)type_set_module, NULL}, {"__dict__", (getter)type_dict, NULL, NULL}, {"__doc__", (getter)type_get_doc, NULL, NULL}, + {"__solid__", (getter)type_get_solid, NULL, NULL}, {0} }; *************** *** 491,497 **** 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) --- 503,522 ---- for (i = 0; i < n; i++, mp++) { if (mp->type == T_OBJECT_EX) { char *addr = (char *)self + mp->offset; ! PyObject *obj; ! if (mp->offset < 0) { ! int tsize; ! size_t size; ! ! tsize = ((PyVarObject *)self)->ob_size; ! if (tsize < 0) ! tsize = -tsize; ! size = type->tp_basicsize + tsize * type->tp_itemsize; ! size = (size + (SIZEOF_VOID_P - 1)) & ~(SIZEOF_VOID_P - 1); ! ! addr += size; ! } ! obj = *(PyObject **)addr; if (obj != NULL) { int err = visit(obj, arg); if (err) *************** *** 556,562 **** 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; --- 581,600 ---- for (i = 0; i < n; i++, mp++) { if (mp->type == T_OBJECT_EX && !(mp->flags & READONLY)) { char *addr = (char *)self + mp->offset; ! PyObject *obj; ! if (mp->offset < 0) { ! int tsize; ! size_t size; ! ! tsize = ((PyVarObject *)self)->ob_size; ! if (tsize < 0) ! tsize = -tsize; ! size = type->tp_basicsize + tsize * type->tp_itemsize; ! size = (size + (SIZEOF_VOID_P - 1)) & ~(SIZEOF_VOID_P - 1); ! ! addr += size; ! } ! obj = *(PyObject **)addr; if (obj != NULL) { Py_DECREF(obj); *(PyObject **)addr = NULL; *************** *** 809,816 **** */ } - static PyTypeObject *solid_base(PyTypeObject *type); - /* type test with subclassing support */ int --- 847,852 ---- *************** *** 1371,1387 **** size_t b_size = base->tp_basicsize; assert(t_size >= b_size); /* Else type smaller than base! */ if (type->tp_itemsize || base->tp_itemsize) { /* If itemsize is involved, stricter rules */ return t_size != b_size || type->tp_itemsize != base->tp_itemsize; } - if (type->tp_weaklistoffset && base->tp_weaklistoffset == 0 && - type->tp_weaklistoffset + sizeof(PyObject *) == t_size) - t_size -= sizeof(PyObject *); - if (type->tp_dictoffset && base->tp_dictoffset == 0 && - type->tp_dictoffset + sizeof(PyObject *) == t_size) - t_size -= sizeof(PyObject *); return t_size != b_size; } --- 1429,1446 ---- size_t b_size = base->tp_basicsize; assert(t_size >= b_size); /* Else type smaller than base! */ + + if (type->tp_weaklistoffset && base->tp_weaklistoffset == 0) + t_size -= sizeof(PyObject *); + + if (type->tp_dictoffset && base->tp_dictoffset == 0) + t_size -= sizeof(PyObject *); + if (type->tp_itemsize || base->tp_itemsize) { /* If itemsize is involved, stricter rules */ return t_size != b_size || type->tp_itemsize != base->tp_itemsize; } return t_size != b_size; } *************** *** 1461,1468 **** assert(obj->ob_type->tp_weaklistoffset > 0); assert(obj->ob_type->tp_weaklistoffset + sizeof(PyObject *) <= (size_t)(obj->ob_type->tp_basicsize)); ! weaklistptr = (PyObject **) ! ((char *)obj + obj->ob_type->tp_weaklistoffset); if (*weaklistptr == NULL) result = Py_None; else --- 1520,1526 ---- assert(obj->ob_type->tp_weaklistoffset > 0); assert(obj->ob_type->tp_weaklistoffset + sizeof(PyObject *) <= (size_t)(obj->ob_type->tp_basicsize)); ! weaklistptr = PyObject_GetWeakrefsListptr(obj); if (*weaklistptr == NULL) result = Py_None; else *************** *** 1562,1568 **** PyHeapTypeObject *et; PyMemberDef *mp; int i, nbases, nslots, slotoffset, add_dict, add_weak; ! int j, may_add_dict, may_add_weak; assert(args != NULL && PyTuple_Check(args)); assert(kwds == NULL || PyDict_Check(kwds)); --- 1620,1626 ---- PyHeapTypeObject *et; PyMemberDef *mp; int i, nbases, nslots, slotoffset, add_dict, add_weak; ! int j, may_add_dict, may_add_weak, delta; assert(args != NULL && PyTuple_Check(args)); assert(kwds == NULL || PyDict_Check(kwds)); *************** *** 1657,1663 **** add_dict = 0; add_weak = 0; may_add_dict = base->tp_dictoffset == 0; ! may_add_weak = base->tp_weaklistoffset == 0 && base->tp_itemsize == 0; if (slots == NULL) { if (may_add_dict) { add_dict++; --- 1715,1721 ---- add_dict = 0; add_weak = 0; may_add_dict = base->tp_dictoffset == 0; ! may_add_weak = base->tp_weaklistoffset == 0; if (slots == NULL) { if (may_add_dict) { add_dict++; *************** *** 1682,1692 **** /* Are slots allowed? */ nslots = PyTuple_GET_SIZE(slots); ! if (nslots > 0 && base->tp_itemsize != 0) { ! PyErr_Format(PyExc_TypeError, ! "nonempty __slots__ " ! "not supported for subtype of '%s'", ! base->tp_name); bad_slots: Py_DECREF(bases); Py_DECREF(slots); --- 1740,1746 ---- /* Are slots allowed? */ nslots = PyTuple_GET_SIZE(slots); ! if (0) { bad_slots: Py_DECREF(bases); Py_DECREF(slots); *************** *** 1886,1892 **** /* Add descriptors for custom slots from __slots__, or for __dict__ */ mp = PyHeapType_GET_MEMBERS(et); ! slotoffset = base->tp_basicsize; if (slots != NULL) { for (i = 0; i < nslots; i++, mp++) { mp->name = PyString_AS_STRING( --- 1940,1953 ---- /* Add descriptors for custom slots from __slots__, or for __dict__ */ mp = PyHeapType_GET_MEMBERS(et); ! if (base->tp_itemsize) { ! slotoffset = -sizeof(PyObject*); ! delta = -sizeof(PyObject*); ! } ! else { ! slotoffset = base->tp_basicsize; ! delta = sizeof(PyObject*); ! } if (slots != NULL) { for (i = 0; i < nslots; i++, mp++) { mp->name = PyString_AS_STRING( *************** *** 1900,1921 **** mp->flags = READONLY; type->tp_weaklistoffset = slotoffset; } ! slotoffset += sizeof(PyObject *); } } if (add_dict) { ! if (base->tp_itemsize) ! type->tp_dictoffset = -(long)sizeof(PyObject *); else type->tp_dictoffset = slotoffset; ! slotoffset += sizeof(PyObject *); } if (add_weak) { ! assert(!base->tp_itemsize); ! type->tp_weaklistoffset = slotoffset; ! slotoffset += sizeof(PyObject *); } - type->tp_basicsize = slotoffset; type->tp_itemsize = base->tp_itemsize; type->tp_members = PyHeapType_GET_MEMBERS(et); --- 1961,1998 ---- mp->flags = READONLY; type->tp_weaklistoffset = slotoffset; } ! slotoffset += delta; } } if (add_dict) { ! if (base->tp_itemsize) { ! if (add_weak) ! type->tp_dictoffset = -2*(long)sizeof(PyObject *); ! else ! type->tp_dictoffset = -(long)sizeof(PyObject *); ! } else type->tp_dictoffset = slotoffset; ! slotoffset += delta; ! } ! else { ! if (add_weak && base->tp_itemsize && base->tp_dictoffset < 0) ! type->tp_dictoffset = base->tp_dictoffset - (long)sizeof(PyObject *); } if (add_weak) { ! if (base->tp_itemsize) { ! type->tp_weaklistoffset = -(long)sizeof(PyObject *); ! } ! else ! type->tp_weaklistoffset = slotoffset; ! slotoffset += delta; ! } ! if (base->tp_itemsize) { ! type->tp_basicsize = base->tp_basicsize - slotoffset - 4; ! } ! else { ! type->tp_basicsize = slotoffset; } type->tp_itemsize = base->tp_itemsize; type->tp_members = PyHeapType_GET_MEMBERS(et); Index: Objects/weakrefobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/weakrefobject.c,v retrieving revision 1.21 diff -c -r1.21 weakrefobject.c *** Objects/weakrefobject.c 27 Mar 2005 03:04:54 -0000 1.21 --- Objects/weakrefobject.c 30 Mar 2005 16:54:20 -0000 *************** *** 846,851 **** --- 846,878 ---- return PyWeakref_GET_OBJECT(ref); } + PyObject ** + PyObject_GetWeakrefsListptr(PyObject *obj) + { + long weaklistoffset; + PyTypeObject *tp = obj->ob_type; + + if (!(tp->tp_flags & Py_TPFLAGS_HAVE_WEAKREFS)) + return NULL; + weaklistoffset = tp->tp_weaklistoffset; + if (weaklistoffset == 0) + return NULL; + if (weaklistoffset < 0) { + int tsize; + size_t size; + + tsize = ((PyVarObject *)obj)->ob_size; + if (tsize < 0) + tsize = -tsize; + size = _PyObject_VAR_SIZE(tp, tsize); + + weaklistoffset += (long)size; + assert(weaklistoffset > 0); + assert(weaklistoffset % SIZEOF_VOID_P == 0); + } + return (PyObject **) ((char *)obj + weaklistoffset); + } + /* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's * handle_weakrefs(). */ Index: Include/objimpl.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/objimpl.h,v retrieving revision 2.60 diff -c -r2.60 objimpl.h *** Include/objimpl.h 15 Jul 2004 04:05:59 -0000 2.60 --- Include/objimpl.h 30 Mar 2005 16:54:22 -0000 *************** *** 329,338 **** /* Test if a type supports weak references */ #define PyType_SUPPORTS_WEAKREFS(t) \ (PyType_HasFeature((t), Py_TPFLAGS_HAVE_WEAKREFS) \ ! && ((t)->tp_weaklistoffset > 0)) #define PyObject_GET_WEAKREFS_LISTPTR(o) \ ! ((PyObject **) (((char *) (o)) + (o)->ob_type->tp_weaklistoffset)) #ifdef __cplusplus } --- 329,341 ---- /* Test if a type supports weak references */ #define PyType_SUPPORTS_WEAKREFS(t) \ (PyType_HasFeature((t), Py_TPFLAGS_HAVE_WEAKREFS) \ ! && ((t)->tp_weaklistoffset != 0)) ! ! PyAPI_FUNC(PyObject **) PyObject_GetWeakrefsListptr(PyObject *); #define PyObject_GET_WEAKREFS_LISTPTR(o) \ ! PyObject_GetWeakrefsListptr(o) ! #ifdef __cplusplus } Index: Lib/test/test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_descr.py,v retrieving revision 1.204 diff -c -r1.204 test_descr.py *** Lib/test/test_descr.py 3 Mar 2005 16:45:19 -0000 1.204 --- Lib/test/test_descr.py 30 Mar 2005 16:54:59 -0000 *************** *** 1907,1912 **** --- 1928,1953 ---- del yes verify(r() is None) del r + + # object is not a variable sized type, str is + for base in object, str: + # acquire the weakref slot in different orders: + class A(base): + pass + class _B(base): + __slots__ = ['__weakref__'] + class B(_B): + __slots__ = ['__dict__'] + class _C(base): + __slots__ = ['__dict__'] + class C(_C): + __slots__ = ['__weakref__'] + for cls in A, B, C: + inst = cls() + r = weakref.ref(inst) + verify(r() is inst) + del inst + verify(r() is None) def properties(): if verbose: print "Testing property..."