Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
2df25c35
Commit
2df25c35
authored
Jan 13, 2008
by
Georg Brandl
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Back out r59931 - test_ctypes fails with it.
parent
fe25d0c8
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
6 additions
and
219 deletions
+6
-219
Include/object.h
Include/object.h
+0
-8
Misc/NEWS
Misc/NEWS
+0
-3
Objects/object.c
Objects/object.c
+0
-4
Objects/typeobject.c
Objects/typeobject.c
+6
-204
No files found.
Include/object.h
View file @
2df25c35
...
...
@@ -345,9 +345,6 @@ typedef struct _typeobject {
PyObject
*
tp_weaklist
;
destructor
tp_del
;
/* Type attribute cache version tag. Added in version 2.6 */
unsigned
int
tp_version_tag
;
#ifdef COUNT_ALLOCS
/* these must be last and never explicitly initialized */
Py_ssize_t
tp_allocs
;
...
...
@@ -532,10 +529,6 @@ given type object has a specified feature.
/* Objects support nb_index in PyNumberMethods */
#define Py_TPFLAGS_HAVE_INDEX (1L<<17)
/* Objects support type attribute cache */
#define Py_TPFLAGS_HAVE_VERSION_TAG (1L<<18)
#define Py_TPFLAGS_VALID_VERSION_TAG (1L<<19)
/* These flags are used to determine if a type is a subclass. */
#define Py_TPFLAGS_INT_SUBCLASS (1L<<23)
#define Py_TPFLAGS_LONG_SUBCLASS (1L<<24)
...
...
@@ -557,7 +550,6 @@ given type object has a specified feature.
Py_TPFLAGS_HAVE_CLASS | \
Py_TPFLAGS_HAVE_STACKLESS_EXTENSION | \
Py_TPFLAGS_HAVE_INDEX | \
Py_TPFLAGS_HAVE_VERSION_TAG | \
0)
#define PyType_HasFeature(t,f) (((t)->tp_flags & (f)) != 0)
...
...
Misc/NEWS
View file @
2df25c35
...
...
@@ -12,9 +12,6 @@ What's New in Python 2.6 alpha 1?
Core and builtins
-----------------
- Patch #1700288: added a type attribute cache that caches method accesses,
resulting in speedups in heavily object-oriented code.
- Bug #1776: __import__() no longer accepts filenames on any platform.
The first parameter to __import__() must be a valid module name.
...
...
Objects/object.c
View file @
2df25c35
...
...
@@ -1287,7 +1287,6 @@ PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
goto
done
;
}
#if 0 /* XXX this is not quite _PyType_Lookup anymore */
/* Inline _PyType_Lookup */
{
Py_ssize_t
i
,
n
;
...
...
@@ -1312,9 +1311,6 @@ PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
break
;
}
}
#else
descr
=
_PyType_Lookup
(
tp
,
name
);
#endif
Py_XINCREF
(
descr
);
...
...
Objects/typeobject.c
View file @
2df25c35
...
...
@@ -5,171 +5,6 @@
#include <ctype.h>
/* Support type attribute cache */
/* The cache can keep references to the names alive for longer than
they normally would. This is why the maximum size is limited to
MCACHE_MAX_ATTR_SIZE, since it might be a problem if very large
strings are used as attribute names. */
#define MCACHE_MAX_ATTR_SIZE 100
#define MCACHE_SIZE_EXP 10
#define MCACHE_HASH(version, name_hash) \
(((unsigned int)(version) * (unsigned int)(name_hash)) \
>> (8*sizeof(unsigned int) - MCACHE_SIZE_EXP))
#define MCACHE_HASH_METHOD(type, name) \
MCACHE_HASH((type)->tp_version_tag, \
((PyStringObject *)(name))->ob_shash)
#define MCACHE_CACHEABLE_NAME(name) \
PyString_CheckExact(name) && \
PyString_GET_SIZE(name) <= MCACHE_MAX_ATTR_SIZE
struct
method_cache_entry
{
unsigned
int
version
;
PyObject
*
name
;
/* reference to exactly a str or None */
PyObject
*
value
;
/* borrowed */
};
static
struct
method_cache_entry
method_cache
[
1
<<
MCACHE_SIZE_EXP
];
static
unsigned
int
next_version_tag
=
0
;
static
void
type_modified
(
PyTypeObject
*
type
)
{
/* Invalidate any cached data for the specified type and all
subclasses. This function is called after the base
classes, mro, or attributes of the type are altered.
Invariants:
- Py_TPFLAGS_VALID_VERSION_TAG is never set if
Py_TPFLAGS_HAVE_VERSION_TAG is not set (e.g. on type
objects coming from non-recompiled extension modules)
- before Py_TPFLAGS_VALID_VERSION_TAG can be set on a type,
it must first be set on all super types.
This function clears the Py_TPFLAGS_VALID_VERSION_TAG of a
type (so it must first clear it on all subclasses). The
tp_version_tag value is meaningless unless this flag is set.
We don't assign new version tags eagerly, but only as
needed.
*/
PyObject
*
raw
,
*
ref
;
Py_ssize_t
i
,
n
;
if
(
!
PyType_HasFeature
(
type
,
Py_TPFLAGS_VALID_VERSION_TAG
))
return
;
raw
=
type
->
tp_subclasses
;
if
(
raw
!=
NULL
)
{
n
=
PyList_GET_SIZE
(
raw
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
ref
=
PyList_GET_ITEM
(
raw
,
i
);
ref
=
PyWeakref_GET_OBJECT
(
ref
);
if
(
ref
!=
Py_None
)
{
type_modified
((
PyTypeObject
*
)
ref
);
}
}
}
type
->
tp_flags
&=
~
Py_TPFLAGS_VALID_VERSION_TAG
;
}
static
void
type_mro_modified
(
PyTypeObject
*
type
,
PyObject
*
bases
)
{
/*
Check that all base classes or elements of the mro of type are
able to be cached. This function is called after the base
classes or mro of the type are altered.
Unset HAVE_VERSION_TAG and VALID_VERSION_TAG if the type
inherits from an old-style class, either directly or if it
appears in the MRO of a new-style class. No support either for
custom MROs that include types that are not officially super
types.
Called from mro_internal, which will subsequently be called on
each subclass when their mro is recursively updated.
*/
Py_ssize_t
i
,
n
;
int
clear
=
0
;
if
(
!
PyType_HasFeature
(
type
,
Py_TPFLAGS_HAVE_VERSION_TAG
))
return
;
n
=
PyTuple_GET_SIZE
(
bases
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
PyObject
*
b
=
PyTuple_GET_ITEM
(
bases
,
i
);
PyTypeObject
*
cls
;
if
(
!
PyType_Check
(
b
)
)
{
clear
=
1
;
break
;
}
cls
=
(
PyTypeObject
*
)
b
;
if
(
!
PyType_HasFeature
(
cls
,
Py_TPFLAGS_HAVE_VERSION_TAG
)
||
!
PyType_IsSubtype
(
type
,
cls
))
{
clear
=
1
;
break
;
}
}
if
(
clear
)
type
->
tp_flags
&=
~
(
Py_TPFLAGS_HAVE_VERSION_TAG
|
Py_TPFLAGS_VALID_VERSION_TAG
);
}
static
int
assign_version_tag
(
PyTypeObject
*
type
)
{
/* Ensure that the tp_version_tag is valid and set
Py_TPFLAGS_VALID_VERSION_TAG. To respect the invariant, this
must first be done on all super classes. Return 0 if this
cannot be done, 1 if Py_TPFLAGS_VALID_VERSION_TAG.
*/
Py_ssize_t
i
,
n
;
PyObject
*
bases
;
if
(
PyType_HasFeature
(
type
,
Py_TPFLAGS_VALID_VERSION_TAG
))
return
1
;
if
(
!
PyType_HasFeature
(
type
,
Py_TPFLAGS_HAVE_VERSION_TAG
))
return
0
;
if
(
!
PyType_HasFeature
(
type
,
Py_TPFLAGS_READY
))
return
0
;
type
->
tp_version_tag
=
next_version_tag
++
;
/* for stress-testing: next_version_tag &= 0xFF; */
if
(
type
->
tp_version_tag
==
0
)
{
/* wrap-around or just starting Python - clear the whole
cache by filling names with references to Py_None.
Values are also set to NULL for added protection, as they
are borrowed reference */
for
(
i
=
0
;
i
<
(
1
<<
MCACHE_SIZE_EXP
);
i
++
)
{
method_cache
[
i
].
value
=
NULL
;
Py_XDECREF
(
method_cache
[
i
].
name
);
method_cache
[
i
].
name
=
Py_None
;
Py_INCREF
(
Py_None
);
}
/* mark all version tags as invalid */
type_modified
(
&
PyBaseObject_Type
);
return
1
;
}
bases
=
type
->
tp_bases
;
n
=
PyTuple_GET_SIZE
(
bases
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
PyObject
*
b
=
PyTuple_GET_ITEM
(
bases
,
i
);
assert
(
PyType_Check
(
b
));
if
(
!
assign_version_tag
((
PyTypeObject
*
)
b
))
return
0
;
}
type
->
tp_flags
|=
Py_TPFLAGS_VALID_VERSION_TAG
;
return
1
;
}
static
PyMemberDef
type_members
[]
=
{
{
"__basicsize__"
,
T_INT
,
offsetof
(
PyTypeObject
,
tp_basicsize
),
READONLY
},
{
"__itemsize__"
,
T_INT
,
offsetof
(
PyTypeObject
,
tp_itemsize
),
READONLY
},
...
...
@@ -282,8 +117,6 @@ type_set_module(PyTypeObject *type, PyObject *value, void *context)
return
-
1
;
}
type_modified
(
type
);
return
PyDict_SetItemString
(
type
->
tp_dict
,
"__module__"
,
value
);
}
...
...
@@ -1518,14 +1351,6 @@ mro_internal(PyTypeObject *type)
}
}
type
->
tp_mro
=
tuple
;
type_mro_modified
(
type
,
type
->
tp_mro
);
/* corner case: the old-style super class might have been hidden
from the custom MRO */
type_mro_modified
(
type
,
type
->
tp_bases
);
type_modified
(
type
);
return
0
;
}
...
...
@@ -2318,16 +2143,6 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name)
{
Py_ssize_t
i
,
n
;
PyObject
*
mro
,
*
res
,
*
base
,
*
dict
;
unsigned
int
h
;
if
(
MCACHE_CACHEABLE_NAME
(
name
)
&&
PyType_HasFeature
(
type
,
Py_TPFLAGS_VALID_VERSION_TAG
))
{
/* fast path */
h
=
MCACHE_HASH_METHOD
(
type
,
name
);
if
(
method_cache
[
h
].
version
==
type
->
tp_version_tag
&&
method_cache
[
h
].
name
==
name
)
return
method_cache
[
h
].
value
;
}
/* Look in tp_dict of types in MRO */
mro
=
type
->
tp_mro
;
...
...
@@ -2338,7 +2153,6 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name)
if
(
mro
==
NULL
)
return
NULL
;
res
=
NULL
;
assert
(
PyTuple_Check
(
mro
));
n
=
PyTuple_GET_SIZE
(
mro
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
...
...
@@ -2352,18 +2166,9 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name)
assert
(
dict
&&
PyDict_Check
(
dict
));
res
=
PyDict_GetItem
(
dict
,
name
);
if
(
res
!=
NULL
)
break
;
}
if
(
MCACHE_CACHEABLE_NAME
(
name
)
&&
assign_version_tag
(
type
))
{
h
=
MCACHE_HASH_METHOD
(
type
,
name
);
method_cache
[
h
].
version
=
type
->
tp_version_tag
;
method_cache
[
h
].
value
=
res
;
/* borrowed */
Py_INCREF
(
name
);
Py_DECREF
(
method_cache
[
h
].
name
);
method_cache
[
h
].
name
=
name
;
}
return
res
;
}
return
NULL
;
}
/* This is similar to PyObject_GenericGetAttr(),
...
...
@@ -2453,6 +2258,10 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
type
->
tp_name
);
return
-
1
;
}
/* XXX Example of how I expect this to be used...
if (update_subclasses(type, name, invalidate_cache, NULL) < 0)
return -1;
*/
if
(
PyObject_GenericSetAttr
((
PyObject
*
)
type
,
name
,
value
)
<
0
)
return
-
1
;
return
update_slot
(
type
,
name
);
...
...
@@ -5875,13 +5684,6 @@ update_slot(PyTypeObject *type, PyObject *name)
slotdef
**
pp
;
int
offset
;
/* Clear the VALID_VERSION flag of 'type' and all its
subclasses. This could possibly be unified with the
update_subclasses() recursion below, but carefully:
they each have their own conditions on which to stop
recursing into subclasses. */
type_modified
(
type
);
init_slotdefs
();
pp
=
ptrs
;
for
(
p
=
slotdefs
;
p
->
name
;
p
++
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment