Commit 687ae004 authored by Guido van Rossum's avatar Guido van Rossum

Get rid of __defined__ and tp_defined -- there's no need to

distinguish __dict__ and __defined__ any more.  In the C structure,
tp_cache takes its place -- but this hasn't been implemented yet.
parent 66426538
...@@ -288,7 +288,7 @@ typedef struct _typeobject { ...@@ -288,7 +288,7 @@ typedef struct _typeobject {
inquiry tp_is_gc; /* For PyObject_IS_GC */ inquiry tp_is_gc; /* For PyObject_IS_GC */
PyObject *tp_bases; PyObject *tp_bases;
PyObject *tp_mro; /* method resolution order */ PyObject *tp_mro; /* method resolution order */
PyObject *tp_defined; PyObject *tp_cache;
PyObject *tp_subclasses; PyObject *tp_subclasses;
PyObject *tp_weaklist; PyObject *tp_weaklist;
......
...@@ -200,24 +200,9 @@ def classify_class_attrs(cls): ...@@ -200,24 +200,9 @@ def classify_class_attrs(cls):
obj = getattr(cls, name) obj = getattr(cls, name)
# Figure out where it was defined. # Figure out where it was defined.
# A complication: static classes in 2.2 copy dict entries from
# bases into derived classes, so it's not enough just to look for
# "the first" class with the name in its dict. OTOH:
# 1. Some-- but not all --methods in 2.2 come with an __objclass__
# attr that answers the question directly.
# 2. Some-- but not all --classes in 2.2 have a __defined__ dict
# saying which names were defined by the class.
homecls = getattr(obj, "__objclass__", None) homecls = getattr(obj, "__objclass__", None)
if homecls is None: if homecls is None:
# Try __defined__. # search the dicts.
for base in mro:
if hasattr(base, "__defined__"):
if name in base.__defined__:
homecls = base
break
if homecls is None:
# Last chance (and first chance for classic classes): search
# the dicts.
for base in mro: for base in mro:
if name in base.__dict__: if name in base.__dict__:
homecls = base homecls = base
......
...@@ -4,15 +4,14 @@ Release date: 28-Sep-2100 ...@@ -4,15 +4,14 @@ Release date: 28-Sep-2100
Type/class unification and new-style classes Type/class unification and new-style classes
- New-style classes are now dynamic by default. Previous, they were - New-style classes are now always dynamic (except for built-in and
static (meaning class attributes could not be assigned to) and extension types). There was no longer a performance penalty, and I
dynamic classes had to be requested by adding __dynamic__ = 1 to the no longer see another reason to keep this baggage around. One relic
body of the class or to the module. Static classes are faster than remains: the __dict__ or a new-style class is a read-only proxy.
dynamic classes, but dynamic classes are now at most 50% slower than You must set the class's attribute to modify. As a consequence, the
static classes; previously, they could be up to 10x slower. (This __defined__ attribute of new-style types no longer exists, for lack
was accomplished by making dynamic classes faster, not by making of need: there is once again only one __dict__ (although in the
static classes slower. :-) Note that according to one benchmark, future a __cache__ may be resurrected in its place).
static classes are about the same speed as classic classes.
- C.__doc__ now works as expected for new-style classes (in 2.2a4 it - C.__doc__ now works as expected for new-style classes (in 2.2a4 it
always returned None, even when there was a class docstring). always returned None, even when there was a class docstring).
......
...@@ -44,7 +44,7 @@ type_module(PyTypeObject *type, void *context) ...@@ -44,7 +44,7 @@ type_module(PyTypeObject *type, void *context)
(int)(s - type->tp_name)); (int)(s - type->tp_name));
if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE))
return PyString_FromString("__builtin__"); return PyString_FromString("__builtin__");
mod = PyDict_GetItemString(type->tp_defined, "__module__"); mod = PyDict_GetItemString(type->tp_dict, "__module__");
if (mod != NULL && PyString_Check(mod)) { if (mod != NULL && PyString_Check(mod)) {
Py_INCREF(mod); Py_INCREF(mod);
return mod; return mod;
...@@ -80,21 +80,10 @@ type_dict(PyTypeObject *type, void *context) ...@@ -80,21 +80,10 @@ type_dict(PyTypeObject *type, void *context)
return PyDictProxy_New(type->tp_dict); return PyDictProxy_New(type->tp_dict);
} }
static PyObject *
type_defined(PyTypeObject *type, void *context)
{
if (type->tp_defined == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
return PyDictProxy_New(type->tp_defined);
}
PyGetSetDef type_getsets[] = { PyGetSetDef type_getsets[] = {
{"__name__", (getter)type_name, NULL, NULL}, {"__name__", (getter)type_name, NULL, NULL},
{"__module__", (getter)type_module, (setter)type_set_module, NULL}, {"__module__", (getter)type_module, (setter)type_set_module, NULL},
{"__dict__", (getter)type_dict, NULL, NULL}, {"__dict__", (getter)type_dict, NULL, NULL},
{"__defined__", (getter)type_defined, NULL, NULL},
{0} {0}
}; };
...@@ -838,8 +827,8 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) ...@@ -838,8 +827,8 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
Py_INCREF(base); Py_INCREF(base);
type->tp_base = base; type->tp_base = base;
/* Initialize tp_defined from passed-in dict */ /* Initialize tp_dict from passed-in dict */
type->tp_defined = dict = PyDict_Copy(dict); type->tp_dict = dict = PyDict_Copy(dict);
if (dict == NULL) { if (dict == NULL) {
Py_DECREF(type); Py_DECREF(type);
return NULL; return NULL;
...@@ -973,14 +962,14 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name) ...@@ -973,14 +962,14 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name)
int i, n; int i, n;
PyObject *mro, *res, *dict; PyObject *mro, *res, *dict;
/* Look in tp_defined of types in MRO */ /* Look in tp_dict of types in MRO */
mro = type->tp_mro; mro = type->tp_mro;
assert(PyTuple_Check(mro)); assert(PyTuple_Check(mro));
n = PyTuple_GET_SIZE(mro); n = PyTuple_GET_SIZE(mro);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
type = (PyTypeObject *) PyTuple_GET_ITEM(mro, i); type = (PyTypeObject *) PyTuple_GET_ITEM(mro, i);
assert(PyType_Check(type)); assert(PyType_Check(type));
dict = type->tp_defined; dict = type->tp_dict;
assert(dict && PyDict_Check(dict)); assert(dict && PyDict_Check(dict));
res = PyDict_GetItem(dict, name); res = PyDict_GetItem(dict, name);
if (res != NULL) if (res != NULL)
...@@ -1014,7 +1003,7 @@ type_getattro(PyTypeObject *type, PyObject *name) ...@@ -1014,7 +1003,7 @@ type_getattro(PyTypeObject *type, PyObject *name)
(PyObject *)type, (PyObject *)metatype); (PyObject *)type, (PyObject *)metatype);
} }
/* Look in tp_defined of this type and its bases */ /* Look in tp_dict of this type and its bases */
res = _PyType_Lookup(type, name); res = _PyType_Lookup(type, name);
if (res != NULL) { if (res != NULL) {
f = res->ob_type->tp_descr_get; f = res->ob_type->tp_descr_get;
...@@ -1070,7 +1059,7 @@ type_dealloc(PyTypeObject *type) ...@@ -1070,7 +1059,7 @@ type_dealloc(PyTypeObject *type)
Py_XDECREF(type->tp_dict); Py_XDECREF(type->tp_dict);
Py_XDECREF(type->tp_bases); Py_XDECREF(type->tp_bases);
Py_XDECREF(type->tp_mro); Py_XDECREF(type->tp_mro);
Py_XDECREF(type->tp_defined); Py_XDECREF(type->tp_cache);
Py_XDECREF(type->tp_subclasses); Py_XDECREF(type->tp_subclasses);
Py_XDECREF(et->name); Py_XDECREF(et->name);
Py_XDECREF(et->slots); Py_XDECREF(et->slots);
...@@ -1136,7 +1125,7 @@ type_traverse(PyTypeObject *type, visitproc visit, void *arg) ...@@ -1136,7 +1125,7 @@ type_traverse(PyTypeObject *type, visitproc visit, void *arg)
} }
VISIT(type->tp_dict); VISIT(type->tp_dict);
VISIT(type->tp_defined); VISIT(type->tp_cache);
VISIT(type->tp_mro); VISIT(type->tp_mro);
VISIT(type->tp_bases); VISIT(type->tp_bases);
VISIT(type->tp_base); VISIT(type->tp_base);
...@@ -1167,7 +1156,7 @@ type_clear(PyTypeObject *type) ...@@ -1167,7 +1156,7 @@ type_clear(PyTypeObject *type)
} }
CLEAR(type->tp_dict); CLEAR(type->tp_dict);
CLEAR(type->tp_defined); CLEAR(type->tp_cache);
CLEAR(type->tp_mro); CLEAR(type->tp_mro);
CLEAR(type->tp_bases); CLEAR(type->tp_bases);
CLEAR(type->tp_base); CLEAR(type->tp_base);
...@@ -1455,7 +1444,7 @@ PyTypeObject PyBaseObject_Type = { ...@@ -1455,7 +1444,7 @@ PyTypeObject PyBaseObject_Type = {
static int static int
add_methods(PyTypeObject *type, PyMethodDef *meth) add_methods(PyTypeObject *type, PyMethodDef *meth)
{ {
PyObject *dict = type->tp_defined; PyObject *dict = type->tp_dict;
for (; meth->ml_name != NULL; meth++) { for (; meth->ml_name != NULL; meth++) {
PyObject *descr; PyObject *descr;
...@@ -1474,7 +1463,7 @@ add_methods(PyTypeObject *type, PyMethodDef *meth) ...@@ -1474,7 +1463,7 @@ add_methods(PyTypeObject *type, PyMethodDef *meth)
static int static int
add_members(PyTypeObject *type, PyMemberDef *memb) add_members(PyTypeObject *type, PyMemberDef *memb)
{ {
PyObject *dict = type->tp_defined; PyObject *dict = type->tp_dict;
for (; memb->name != NULL; memb++) { for (; memb->name != NULL; memb++) {
PyObject *descr; PyObject *descr;
...@@ -1493,7 +1482,7 @@ add_members(PyTypeObject *type, PyMemberDef *memb) ...@@ -1493,7 +1482,7 @@ add_members(PyTypeObject *type, PyMemberDef *memb)
static int static int
add_getset(PyTypeObject *type, PyGetSetDef *gsp) add_getset(PyTypeObject *type, PyGetSetDef *gsp)
{ {
PyObject *dict = type->tp_defined; PyObject *dict = type->tp_dict;
for (; gsp->name != NULL; gsp++) { for (; gsp->name != NULL; gsp++) {
PyObject *descr; PyObject *descr;
...@@ -1746,7 +1735,6 @@ PyType_Ready(PyTypeObject *type) ...@@ -1746,7 +1735,6 @@ PyType_Ready(PyTypeObject *type)
return 0; return 0;
} }
assert((type->tp_flags & Py_TPFLAGS_READYING) == 0); assert((type->tp_flags & Py_TPFLAGS_READYING) == 0);
assert(type->tp_dict == NULL);
type->tp_flags |= Py_TPFLAGS_READYING; type->tp_flags |= Py_TPFLAGS_READYING;
...@@ -1773,16 +1761,16 @@ PyType_Ready(PyTypeObject *type) ...@@ -1773,16 +1761,16 @@ PyType_Ready(PyTypeObject *type)
goto error; goto error;
} }
/* Initialize tp_defined */ /* Initialize tp_dict */
dict = type->tp_defined; dict = type->tp_dict;
if (dict == NULL) { if (dict == NULL) {
dict = PyDict_New(); dict = PyDict_New();
if (dict == NULL) if (dict == NULL)
goto error; goto error;
type->tp_defined = dict; type->tp_dict = dict;
} }
/* Add type-specific descriptors to tp_defined */ /* Add type-specific descriptors to tp_dict */
if (add_operators(type) < 0) if (add_operators(type) < 0)
goto error; goto error;
if (type->tp_methods != NULL) { if (type->tp_methods != NULL) {
...@@ -1798,12 +1786,6 @@ PyType_Ready(PyTypeObject *type) ...@@ -1798,12 +1786,6 @@ PyType_Ready(PyTypeObject *type)
goto error; goto error;
} }
/* Temporarily make tp_dict the same object as tp_defined.
(This is needed to call mro(), and can stay this way for
dynamic types). */
Py_INCREF(type->tp_defined);
type->tp_dict = type->tp_defined;
/* Calculate method resolution order */ /* Calculate method resolution order */
if (mro_internal(type) < 0) { if (mro_internal(type) < 0) {
goto error; goto error;
...@@ -2676,18 +2658,18 @@ add_tp_new_wrapper(PyTypeObject *type) ...@@ -2676,18 +2658,18 @@ add_tp_new_wrapper(PyTypeObject *type)
{ {
PyObject *func; PyObject *func;
if (PyDict_GetItemString(type->tp_defined, "__new__") != NULL) if (PyDict_GetItemString(type->tp_dict, "__new__") != NULL)
return 0; return 0;
func = PyCFunction_New(tp_new_methoddef, (PyObject *)type); func = PyCFunction_New(tp_new_methoddef, (PyObject *)type);
if (func == NULL) if (func == NULL)
return -1; return -1;
return PyDict_SetItemString(type->tp_defined, "__new__", func); return PyDict_SetItemString(type->tp_dict, "__new__", func);
} }
static int static int
add_wrappers(PyTypeObject *type, struct wrapperbase *wraps, void *wrapped) add_wrappers(PyTypeObject *type, struct wrapperbase *wraps, void *wrapped)
{ {
PyObject *dict = type->tp_defined; PyObject *dict = type->tp_dict;
for (; wraps->name != NULL; wraps++) { for (; wraps->name != NULL; wraps++) {
PyObject *descr; PyObject *descr;
...@@ -2706,14 +2688,14 @@ add_wrappers(PyTypeObject *type, struct wrapperbase *wraps, void *wrapped) ...@@ -2706,14 +2688,14 @@ add_wrappers(PyTypeObject *type, struct wrapperbase *wraps, void *wrapped)
/* This function is called by PyType_Ready() to populate the type's /* This function is called by PyType_Ready() to populate the type's
dictionary with method descriptors for function slots. For each dictionary with method descriptors for function slots. For each
function slot (like tp_repr) that's defined in the type, one or function slot (like tp_repr) that's defined in the type, one or
more corresponding descriptors are added in the type's tp_defined more corresponding descriptors are added in the type's tp_dict
dictionary under the appropriate name (like __repr__). Some dictionary under the appropriate name (like __repr__). Some
function slots cause more than one descriptor to be added (for function slots cause more than one descriptor to be added (for
example, the nb_add slot adds both __add__ and __radd__ example, the nb_add slot adds both __add__ and __radd__
descriptors) and some function slots compete for the same descriptors) and some function slots compete for the same
descriptor (for example both sq_item and mp_subscript generate a descriptor (for example both sq_item and mp_subscript generate a
__getitem__ descriptor). This only adds new descriptors and __getitem__ descriptor). This only adds new descriptors and
doesn't overwrite entries in tp_defined that were previously doesn't overwrite entries in tp_dict that were previously
defined. The descriptors contain a reference to the C function defined. The descriptors contain a reference to the C function
they must call, so that it's safe if they are copied into a they must call, so that it's safe if they are copied into a
subtype's __dict__ and the subtype has a different C function in subtype's __dict__ and the subtype has a different C function in
...@@ -3942,7 +3924,7 @@ fixup_slot_dispatchers(PyTypeObject *type) ...@@ -3942,7 +3924,7 @@ fixup_slot_dispatchers(PyTypeObject *type)
base = (PyTypeObject *)PyTuple_GET_ITEM(mro, i); base = (PyTypeObject *)PyTuple_GET_ITEM(mro, i);
assert(PyType_Check(base)); assert(PyType_Check(base));
descr = PyDict_GetItem( descr = PyDict_GetItem(
base->tp_defined, p->name_strobj); base->tp_dict, p->name_strobj);
if (descr != NULL) if (descr != NULL)
break; break;
} }
...@@ -4055,7 +4037,7 @@ super_getattro(PyObject *self, PyObject *name) ...@@ -4055,7 +4037,7 @@ super_getattro(PyObject *self, PyObject *name)
tmp = PyTuple_GET_ITEM(mro, i); tmp = PyTuple_GET_ITEM(mro, i);
assert(PyType_Check(tmp)); assert(PyType_Check(tmp));
res = PyDict_GetItem( res = PyDict_GetItem(
((PyTypeObject *)tmp)->tp_defined, name); ((PyTypeObject *)tmp)->tp_dict, name);
if (res != NULL) { if (res != NULL) {
Py_INCREF(res); Py_INCREF(res);
f = res->ob_type->tp_descr_get; f = res->ob_type->tp_descr_get;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment