Skip to content

Commit ec9c3bf

Browse files
author
georg.brandl
committed
Back out r59931 - test_ctypes fails with it.
git-svn-id: http://svn.python.org/projects/python/trunk@59940 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent da7706b commit ec9c3bf

4 files changed

Lines changed: 6 additions & 219 deletions

File tree

Include/object.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -345,9 +345,6 @@ typedef struct _typeobject {
345345
PyObject *tp_weaklist;
346346
destructor tp_del;
347347

348-
/* Type attribute cache version tag. Added in version 2.6 */
349-
unsigned int tp_version_tag;
350-
351348
#ifdef COUNT_ALLOCS
352349
/* these must be last and never explicitly initialized */
353350
Py_ssize_t tp_allocs;
@@ -532,10 +529,6 @@ given type object has a specified feature.
532529
/* Objects support nb_index in PyNumberMethods */
533530
#define Py_TPFLAGS_HAVE_INDEX (1L<<17)
534531

535-
/* Objects support type attribute cache */
536-
#define Py_TPFLAGS_HAVE_VERSION_TAG (1L<<18)
537-
#define Py_TPFLAGS_VALID_VERSION_TAG (1L<<19)
538-
539532
/* These flags are used to determine if a type is a subclass. */
540533
#define Py_TPFLAGS_INT_SUBCLASS (1L<<23)
541534
#define Py_TPFLAGS_LONG_SUBCLASS (1L<<24)
@@ -557,7 +550,6 @@ given type object has a specified feature.
557550
Py_TPFLAGS_HAVE_CLASS | \
558551
Py_TPFLAGS_HAVE_STACKLESS_EXTENSION | \
559552
Py_TPFLAGS_HAVE_INDEX | \
560-
Py_TPFLAGS_HAVE_VERSION_TAG | \
561553
0)
562554

563555
#define PyType_HasFeature(t,f) (((t)->tp_flags & (f)) != 0)

Misc/NEWS

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ What's New in Python 2.6 alpha 1?
1212
Core and builtins
1313
-----------------
1414

15-
- Patch #1700288: added a type attribute cache that caches method accesses,
16-
resulting in speedups in heavily object-oriented code.
17-
1815
- Bug #1776: __import__() no longer accepts filenames on any platform.
1916
The first parameter to __import__() must be a valid module name.
2017

Objects/object.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,7 +1287,6 @@ PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
12871287
goto done;
12881288
}
12891289

1290-
#if 0 /* XXX this is not quite _PyType_Lookup anymore */
12911290
/* Inline _PyType_Lookup */
12921291
{
12931292
Py_ssize_t i, n;
@@ -1312,9 +1311,6 @@ PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
13121311
break;
13131312
}
13141313
}
1315-
#else
1316-
descr = _PyType_Lookup(tp, name);
1317-
#endif
13181314

13191315
Py_XINCREF(descr);
13201316

Objects/typeobject.c

Lines changed: 6 additions & 204 deletions
Original file line numberDiff line numberDiff line change
@@ -5,171 +5,6 @@
55

66
#include <ctype.h>
77

8-
9-
/* Support type attribute cache */
10-
11-
/* The cache can keep references to the names alive for longer than
12-
they normally would. This is why the maximum size is limited to
13-
MCACHE_MAX_ATTR_SIZE, since it might be a problem if very large
14-
strings are used as attribute names. */
15-
#define MCACHE_MAX_ATTR_SIZE 100
16-
#define MCACHE_SIZE_EXP 10
17-
#define MCACHE_HASH(version, name_hash) \
18-
(((unsigned int)(version) * (unsigned int)(name_hash)) \
19-
>> (8*sizeof(unsigned int) - MCACHE_SIZE_EXP))
20-
#define MCACHE_HASH_METHOD(type, name) \
21-
MCACHE_HASH((type)->tp_version_tag, \
22-
((PyStringObject *)(name))->ob_shash)
23-
#define MCACHE_CACHEABLE_NAME(name) \
24-
PyString_CheckExact(name) && \
25-
PyString_GET_SIZE(name) <= MCACHE_MAX_ATTR_SIZE
26-
27-
struct method_cache_entry {
28-
unsigned int version;
29-
PyObject *name; /* reference to exactly a str or None */
30-
PyObject *value; /* borrowed */
31-
};
32-
33-
static struct method_cache_entry method_cache[1 << MCACHE_SIZE_EXP];
34-
static unsigned int next_version_tag = 0;
35-
36-
static void
37-
type_modified(PyTypeObject *type)
38-
{
39-
/* Invalidate any cached data for the specified type and all
40-
subclasses. This function is called after the base
41-
classes, mro, or attributes of the type are altered.
42-
43-
Invariants:
44-
45-
- Py_TPFLAGS_VALID_VERSION_TAG is never set if
46-
Py_TPFLAGS_HAVE_VERSION_TAG is not set (e.g. on type
47-
objects coming from non-recompiled extension modules)
48-
49-
- before Py_TPFLAGS_VALID_VERSION_TAG can be set on a type,
50-
it must first be set on all super types.
51-
52-
This function clears the Py_TPFLAGS_VALID_VERSION_TAG of a
53-
type (so it must first clear it on all subclasses). The
54-
tp_version_tag value is meaningless unless this flag is set.
55-
We don't assign new version tags eagerly, but only as
56-
needed.
57-
*/
58-
PyObject *raw, *ref;
59-
Py_ssize_t i, n;
60-
61-
if(!PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG))
62-
return;
63-
64-
raw = type->tp_subclasses;
65-
if (raw != NULL) {
66-
n = PyList_GET_SIZE(raw);
67-
for (i = 0; i < n; i++) {
68-
ref = PyList_GET_ITEM(raw, i);
69-
ref = PyWeakref_GET_OBJECT(ref);
70-
if (ref != Py_None) {
71-
type_modified((PyTypeObject *)ref);
72-
}
73-
}
74-
}
75-
type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
76-
}
77-
78-
static void
79-
type_mro_modified(PyTypeObject *type, PyObject *bases) {
80-
/*
81-
Check that all base classes or elements of the mro of type are
82-
able to be cached. This function is called after the base
83-
classes or mro of the type are altered.
84-
85-
Unset HAVE_VERSION_TAG and VALID_VERSION_TAG if the type
86-
inherits from an old-style class, either directly or if it
87-
appears in the MRO of a new-style class. No support either for
88-
custom MROs that include types that are not officially super
89-
types.
90-
91-
Called from mro_internal, which will subsequently be called on
92-
each subclass when their mro is recursively updated.
93-
*/
94-
Py_ssize_t i, n;
95-
int clear = 0;
96-
97-
if(!PyType_HasFeature(type, Py_TPFLAGS_HAVE_VERSION_TAG))
98-
return;
99-
100-
n = PyTuple_GET_SIZE(bases);
101-
for (i = 0; i < n; i++) {
102-
PyObject *b = PyTuple_GET_ITEM(bases, i);
103-
PyTypeObject *cls;
104-
105-
if (!PyType_Check(b) ) {
106-
clear = 1;
107-
break;
108-
}
109-
110-
cls = (PyTypeObject *)b;
111-
112-
if (!PyType_HasFeature(cls, Py_TPFLAGS_HAVE_VERSION_TAG) ||
113-
!PyType_IsSubtype(type, cls)) {
114-
clear = 1;
115-
break;
116-
}
117-
}
118-
119-
if (clear)
120-
type->tp_flags &= ~(Py_TPFLAGS_HAVE_VERSION_TAG|
121-
Py_TPFLAGS_VALID_VERSION_TAG);
122-
}
123-
124-
static int
125-
assign_version_tag(PyTypeObject *type)
126-
{
127-
/* Ensure that the tp_version_tag is valid and set
128-
Py_TPFLAGS_VALID_VERSION_TAG. To respect the invariant, this
129-
must first be done on all super classes. Return 0 if this
130-
cannot be done, 1 if Py_TPFLAGS_VALID_VERSION_TAG.
131-
*/
132-
Py_ssize_t i, n;
133-
PyObject *bases;
134-
135-
if (PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG))
136-
return 1;
137-
if (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_VERSION_TAG))
138-
return 0;
139-
if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
140-
return 0;
141-
142-
type->tp_version_tag = next_version_tag++;
143-
/* for stress-testing: next_version_tag &= 0xFF; */
144-
145-
if (type->tp_version_tag == 0) {
146-
/* wrap-around or just starting Python - clear the whole
147-
cache by filling names with references to Py_None.
148-
Values are also set to NULL for added protection, as they
149-
are borrowed reference */
150-
for (i = 0; i < (1 << MCACHE_SIZE_EXP); i++) {
151-
method_cache[i].value = NULL;
152-
Py_XDECREF(method_cache[i].name);
153-
method_cache[i].name = Py_None;
154-
Py_INCREF(Py_None);
155-
}
156-
/* mark all version tags as invalid */
157-
type_modified(&PyBaseObject_Type);
158-
return 1;
159-
}
160-
bases = type->tp_bases;
161-
n = PyTuple_GET_SIZE(bases);
162-
for (i = 0; i < n; i++) {
163-
PyObject *b = PyTuple_GET_ITEM(bases, i);
164-
assert(PyType_Check(b));
165-
if (!assign_version_tag((PyTypeObject *)b))
166-
return 0;
167-
}
168-
type->tp_flags |= Py_TPFLAGS_VALID_VERSION_TAG;
169-
return 1;
170-
}
171-
172-
1738
static PyMemberDef type_members[] = {
1749
{"__basicsize__", T_INT, offsetof(PyTypeObject,tp_basicsize),READONLY},
17510
{"__itemsize__", T_INT, offsetof(PyTypeObject, tp_itemsize), READONLY},
@@ -282,8 +117,6 @@ type_set_module(PyTypeObject *type, PyObject *value, void *context)
282117
return -1;
283118
}
284119

285-
type_modified(type);
286-
287120
return PyDict_SetItemString(type->tp_dict, "__module__", value);
288121
}
289122

@@ -1518,14 +1351,6 @@ mro_internal(PyTypeObject *type)
15181351
}
15191352
}
15201353
type->tp_mro = tuple;
1521-
1522-
type_mro_modified(type, type->tp_mro);
1523-
/* corner case: the old-style super class might have been hidden
1524-
from the custom MRO */
1525-
type_mro_modified(type, type->tp_bases);
1526-
1527-
type_modified(type);
1528-
15291354
return 0;
15301355
}
15311356

@@ -2318,16 +2143,6 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name)
23182143
{
23192144
Py_ssize_t i, n;
23202145
PyObject *mro, *res, *base, *dict;
2321-
unsigned int h;
2322-
2323-
if (MCACHE_CACHEABLE_NAME(name) &&
2324-
PyType_HasFeature(type,Py_TPFLAGS_VALID_VERSION_TAG)) {
2325-
/* fast path */
2326-
h = MCACHE_HASH_METHOD(type, name);
2327-
if (method_cache[h].version == type->tp_version_tag &&
2328-
method_cache[h].name == name)
2329-
return method_cache[h].value;
2330-
}
23312146

23322147
/* Look in tp_dict of types in MRO */
23332148
mro = type->tp_mro;
@@ -2338,7 +2153,6 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name)
23382153
if (mro == NULL)
23392154
return NULL;
23402155

2341-
res = NULL;
23422156
assert(PyTuple_Check(mro));
23432157
n = PyTuple_GET_SIZE(mro);
23442158
for (i = 0; i < n; i++) {
@@ -2352,18 +2166,9 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name)
23522166
assert(dict && PyDict_Check(dict));
23532167
res = PyDict_GetItem(dict, name);
23542168
if (res != NULL)
2355-
break;
2356-
}
2357-
2358-
if (MCACHE_CACHEABLE_NAME(name) && assign_version_tag(type)) {
2359-
h = MCACHE_HASH_METHOD(type, name);
2360-
method_cache[h].version = type->tp_version_tag;
2361-
method_cache[h].value = res; /* borrowed */
2362-
Py_INCREF(name);
2363-
Py_DECREF(method_cache[h].name);
2364-
method_cache[h].name = name;
2169+
return res;
23652170
}
2366-
return res;
2171+
return NULL;
23672172
}
23682173

23692174
/* This is similar to PyObject_GenericGetAttr(),
@@ -2453,6 +2258,10 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
24532258
type->tp_name);
24542259
return -1;
24552260
}
2261+
/* XXX Example of how I expect this to be used...
2262+
if (update_subclasses(type, name, invalidate_cache, NULL) < 0)
2263+
return -1;
2264+
*/
24562265
if (PyObject_GenericSetAttr((PyObject *)type, name, value) < 0)
24572266
return -1;
24582267
return update_slot(type, name);
@@ -5875,13 +5684,6 @@ update_slot(PyTypeObject *type, PyObject *name)
58755684
slotdef **pp;
58765685
int offset;
58775686

5878-
/* Clear the VALID_VERSION flag of 'type' and all its
5879-
subclasses. This could possibly be unified with the
5880-
update_subclasses() recursion below, but carefully:
5881-
they each have their own conditions on which to stop
5882-
recursing into subclasses. */
5883-
type_modified(type);
5884-
58855687
init_slotdefs();
58865688
pp = ptrs;
58875689
for (p = slotdefs; p->name; p++) {

0 commit comments

Comments
 (0)