]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
- The extended type structure used for heap types (new-style
authorGuido van Rossum <guido@python.org>
Fri, 7 Mar 2003 15:13:17 +0000 (15:13 +0000)
committerGuido van Rossum <guido@python.org>
Fri, 7 Mar 2003 15:13:17 +0000 (15:13 +0000)
  classes defined by Python code using a class statement) is now
  exported from object.h as PyHeapTypeObject.  (SF patch #696193.)

Include/object.h
Misc/NEWS
Objects/typeobject.c

index 5e509b41a0f027111eda78aeb498501745d34221..7b93230f182309232ec3f9628955221c8bb6c30f 100644 (file)
@@ -327,6 +327,28 @@ typedef struct _typeobject {
 } PyTypeObject;
 
 
+/* The *real* layout of a type object when allocated on the heap */
+typedef struct _heaptypeobject {
+       /* Note: there's a dependency on the order of these members
+          in slotptr() in typeobject.c . */
+       PyTypeObject type;
+       PyNumberMethods as_number;
+       PyMappingMethods as_mapping;
+       PySequenceMethods as_sequence; /* as_sequence comes after as_mapping,
+                                         so that the mapping wins when both
+                                         the mapping and the sequence define
+                                         a given operator (e.g. __getitem__).
+                                         see add_operators() in typeobject.c . */
+       PyBufferProcs as_buffer;
+       PyObject *name, *slots;
+       /* here are optional user slots, followed by the members. */
+} PyHeapTypeObject;
+
+/* access macro to the members which are floating "behind" the object */
+#define PyHeapType_GET_MEMBERS(etype) \
+    ((PyMemberDef *)(((char *)etype) + (etype)->type.ob_type->tp_basicsize))
+
+
 /* Generic type check */
 PyAPI_FUNC(int) PyType_IsSubtype(PyTypeObject *, PyTypeObject *);
 #define PyObject_TypeCheck(ob, tp) \
index 0a446df4a27f519efd9cb72c90f6e38a3b308584..a83e28287f2a4c448500d7d0ddc718e98bd92b4b 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -80,7 +80,9 @@ Build
 C API
 -----
 
-TBD
+- The extended type structure used for heap types (new-style
+  classes defined by Python code using a class statement) is now
+  exported from object.h as PyHeapTypeObject.  (SF patch #696193.)
 
 New platforms
 -------------
index e61eae882c2b1d5848da0e55591f7e18e014af49..a067cd5963fbcbca1895368d93d043a82db6b196 100644 (file)
@@ -5,24 +5,6 @@
 
 #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 {
-       /* Note: there's a dependency on the order of these members
-          in slotptr() below. */
-       PyTypeObject type;
-       PyNumberMethods as_number;
-       PyMappingMethods as_mapping;
-       PySequenceMethods as_sequence; /* as_sequence comes after as_mapping,
-                                         so that the mapping wins when both
-                                         the mapping and the sequence define
-                                         a given operator (e.g. __getitem__).
-                                         see add_operators() below. */
-       PyBufferProcs as_buffer;
-       PyObject *name, *slots;
-       PyMemberDef members[1];
-} etype;
-
 static PyMemberDef type_members[] = {
        {"__basicsize__", T_INT, offsetof(PyTypeObject,tp_basicsize),READONLY},
        {"__itemsize__", T_INT, offsetof(PyTypeObject, tp_itemsize), READONLY},
@@ -42,7 +24,7 @@ type_name(PyTypeObject *type, void *context)
        char *s;
 
        if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
-               etype* et = (etype*)type;
+               PyHeapTypeObject* et = (PyHeapTypeObject*)type;
 
                Py_INCREF(et->name);
                return et->name;
@@ -60,7 +42,7 @@ type_name(PyTypeObject *type, void *context)
 static int
 type_set_name(PyTypeObject *type, PyObject *value, void *context)
 {
-       etype* et;
+       PyHeapTypeObject* et;
 
        if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
                PyErr_Format(PyExc_TypeError,
@@ -85,7 +67,7 @@ type_set_name(PyTypeObject *type, PyObject *value, void *context)
                return -1;
        }
 
-       et = (etype*)type;
+       et = (PyHeapTypeObject*)type;
 
        Py_INCREF(value);
 
@@ -449,7 +431,8 @@ PyObject *
 PyType_GenericAlloc(PyTypeObject *type, int nitems)
 {
        PyObject *obj;
-       const size_t size = _PyObject_VAR_SIZE(type, nitems);
+       const size_t size = _PyObject_VAR_SIZE(type, nitems+1);
+       /* note that we need to add one, for the sentinel */
 
        if (PyType_IS_GC(type))
                obj = _PyObject_GC_Malloc(size);
@@ -489,7 +472,7 @@ traverse_slots(PyTypeObject *type, PyObject *self, visitproc visit, void *arg)
        PyMemberDef *mp;
 
        n = type->ob_size;
-       mp = ((etype *)type)->members;
+       mp = PyHeapType_GET_MEMBERS((PyHeapTypeObject *)type);
        for (i = 0; i < n; i++, mp++) {
                if (mp->type == T_OBJECT_EX) {
                        char *addr = (char *)self + mp->offset;
@@ -554,7 +537,7 @@ clear_slots(PyTypeObject *type, PyObject *self)
        PyMemberDef *mp;
 
        n = type->ob_size;
-       mp = ((etype *)type)->members;
+       mp = PyHeapType_GET_MEMBERS((PyHeapTypeObject *)type);
        for (i = 0; i < n; i++, mp++) {
                if (mp->type == T_OBJECT_EX && !(mp->flags & READONLY)) {
                        char *addr = (char *)self + mp->offset;
@@ -1534,7 +1517,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
        static char *kwlist[] = {"name", "bases", "dict", 0};
        PyObject *slots, *tmp, *newslots;
        PyTypeObject *type, *base, *tmptype, *winner;
-       etype *et;
+       PyHeapTypeObject *et;
        PyMemberDef *mp;
        int i, nbases, nslots, slotoffset, add_dict, add_weak;
        int j, may_add_dict, may_add_weak;
@@ -1649,7 +1632,8 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
 
                /* Are slots allowed? */
                nslots = PyTuple_GET_SIZE(slots);
-               if (nslots > 0 && base->tp_itemsize != 0) {
+               if (nslots > 0 && base->tp_itemsize != 0 && !PyType_Check(base)) {
+                       /* for the special case of meta types, allow slots */
                        PyErr_Format(PyExc_TypeError,
                                     "nonempty __slots__ "
                                     "not supported for subtype of '%s'",
@@ -1770,7 +1754,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
        }
 
        /* Keep name and slots alive in the extended type object */
-       et = (etype *)type;
+       et = (PyHeapTypeObject *)type;
        Py_INCREF(name);
        et->name = name;
        et->slots = slots;
@@ -1850,7 +1834,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
        }
 
        /* Add descriptors for custom slots from __slots__, or for __dict__ */
-       mp = et->members;
+       mp = PyHeapType_GET_MEMBERS(et);
        slotoffset = base->tp_basicsize;
        if (slots != NULL) {
                for (i = 0; i < nslots; i++, mp++) {
@@ -1882,7 +1866,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
        }
        type->tp_basicsize = slotoffset;
        type->tp_itemsize = base->tp_itemsize;
-       type->tp_members = et->members;
+       type->tp_members = PyHeapType_GET_MEMBERS(et);
 
        if (type->tp_weaklistoffset && type->tp_dictoffset)
                type->tp_getset = subtype_getsets_full;
@@ -2052,13 +2036,13 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
 static void
 type_dealloc(PyTypeObject *type)
 {
-       etype *et;
+       PyHeapTypeObject *et;
 
        /* Assert this is a heap-allocated type object */
        assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
        _PyObject_GC_UNTRACK(type);
        PyObject_ClearWeakRefs((PyObject *)type);
-       et = (etype *)type;
+       et = (PyHeapTypeObject *)type;
        Py_XDECREF(type->tp_base);
        Py_XDECREF(type->tp_dict);
        Py_XDECREF(type->tp_bases);
@@ -2134,7 +2118,7 @@ type_traverse(PyTypeObject *type, visitproc visit, void *arg)
        VISIT(type->tp_base);
 
        /* There's no need to visit type->tp_subclasses or
-          ((etype *)type)->slots, because they can't be involved
+          ((PyHeapTypeObject *)type)->slots, because they can't be involved
           in cycles; tp_subclasses is a list of weak references,
           and slots is a tuple of strings. */
 
@@ -2180,7 +2164,7 @@ type_clear(PyTypeObject *type)
               A list of weak references can't be part of a cycle; and
               lists have their own tp_clear.
 
-          slots (in etype):
+          slots (in PyHeapTypeObject):
               A tuple of strings can't be part of a cycle.
        */
 
@@ -2201,7 +2185,7 @@ PyTypeObject PyType_Type = {
        PyObject_HEAD_INIT(&PyType_Type)
        0,                                      /* ob_size */
        "type",                                 /* tp_name */
-       sizeof(etype),                          /* tp_basicsize */
+       sizeof(PyHeapTypeObject),               /* tp_basicsize */
        sizeof(PyMemberDef),                    /* tp_itemsize */
        (destructor)type_dealloc,               /* tp_dealloc */
        0,                                      /* tp_print */
@@ -4686,9 +4670,10 @@ slot_tp_del(PyObject *self)
 
 
 /* Table mapping __foo__ names to tp_foo offsets and slot_tp_foo wrapper
-   functions.  The offsets here are relative to the 'etype' structure, which
-   incorporates the additional structures used for numbers, sequences and
-   mappings.  Note that multiple names may map to the same slot (e.g. __eq__,
+   functions.  The offsets here are relative to the 'PyHeapTypeObject' 
+   structure, which incorporates the additional structures used for numbers,
+   sequences and mappings.
+   Note that multiple names may map to the same slot (e.g. __eq__,
    __ne__ etc. all map to tp_richcompare) and one name may map to multiple
    slots (e.g. __str__ affects tp_str as well as tp_repr). The table is
    terminated with an all-zero entry.  (This table is further initialized and
@@ -4714,7 +4699,7 @@ typedef struct wrapperbase slotdef;
        {NAME, offsetof(PyTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \
         PyDoc_STR(DOC), FLAGS}
 #define ETSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
-       {NAME, offsetof(etype, SLOT), (void *)(FUNCTION), WRAPPER, \
+       {NAME, offsetof(PyHeapTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \
         PyDoc_STR(DOC)}
 #define SQSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
        ETSLOT(NAME, as_sequence.SLOT, FUNCTION, WRAPPER, DOC)
@@ -4928,20 +4913,20 @@ slotptr(PyTypeObject *type, int offset)
 {
        char *ptr;
 
-       /* Note: this depends on the order of the members of etype! */
+       /* Note: this depends on the order of the members of PyHeapTypeObject! */
        assert(offset >= 0);
-       assert(offset < offsetof(etype, as_buffer));
-       if (offset >= offsetof(etype, as_sequence)) {
+       assert(offset < offsetof(PyHeapTypeObject, as_buffer));
+       if (offset >= offsetof(PyHeapTypeObject, as_sequence)) {
                ptr = (void *)type->tp_as_sequence;
-               offset -= offsetof(etype, as_sequence);
+               offset -= offsetof(PyHeapTypeObject, as_sequence);
        }
-       else if (offset >= offsetof(etype, as_mapping)) {
+       else if (offset >= offsetof(PyHeapTypeObject, as_mapping)) {
                ptr = (void *)type->tp_as_mapping;
-               offset -= offsetof(etype, as_mapping);
+               offset -= offsetof(PyHeapTypeObject, as_mapping);
        }
-       else if (offset >= offsetof(etype, as_number)) {
+       else if (offset >= offsetof(PyHeapTypeObject, as_number)) {
                ptr = (void *)type->tp_as_number;
-               offset -= offsetof(etype, as_number);
+               offset -= offsetof(PyHeapTypeObject, as_number);
        }
        else {
                ptr = (void *)type;
@@ -5216,9 +5201,9 @@ update_all_slots(PyTypeObject* type)
    mp_subscript generate a __getitem__ descriptor).
 
    In the latter case, the first slotdef entry encoutered wins.  Since
-   slotdef entries are sorted by the offset of the slot in the etype
-   struct, this gives us some control over disambiguating between
-   competing slots: the members of struct etype are listed from most
+   slotdef entries are sorted by the offset of the slot in the 
+   PyHeapTypeObject, this gives us some control over disambiguating
+   between competing slots: the members of PyHeapTypeObject are listed from most
    general to least general, so the most general slot is preferred.  In
    particular, because as_mapping comes before as_sequence, for a type
    that defines both mp_subscript and sq_item, mp_subscript wins.