Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
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
Boxiang Sun
Pyston
Commits
2ea5f3e3
Commit
2ea5f3e3
authored
Oct 12, 2015
by
Marius Wachtler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add cpythons method cache
parent
bedadcce
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
114 additions
and
9 deletions
+114
-9
from_cpython/CMakeLists.txt
from_cpython/CMakeLists.txt
+1
-1
src/CMakeLists.txt
src/CMakeLists.txt
+2
-2
src/capi/typeobject.cpp
src/capi/typeobject.cpp
+19
-1
src/jit.cpp
src/jit.cpp
+1
-1
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+91
-4
No files found.
from_cpython/CMakeLists.txt
View file @
2ea5f3e3
...
...
@@ -111,7 +111,7 @@ file(GLOB_RECURSE STDPARSER_SRCS Parser
myreadline.c
)
set
(
CMAKE_C_FLAGS
"
${
CMAKE_C_FLAGS
}
-Wno-missing-field-initializers -Wno-tautological-compare -Wno-type-limits -Wno-unused-result -Wno-strict-aliasing"
)
set
(
CMAKE_C_FLAGS
"
${
CMAKE_C_FLAGS
}
-Wno-missing-field-initializers -Wno-tautological-compare -Wno-type-limits -Wno-unused-result -Wno-strict-aliasing
-DPy_BUILD_CORE
"
)
add_library
(
FROM_CPYTHON OBJECT
${
STDMODULE_SRCS
}
${
STDOBJECT_SRCS
}
${
STDPYTHON_SRCS
}
${
STDPARSER_SRCS
}
)
add_dependencies
(
FROM_CPYTHON copy_stdlib
)
...
...
src/CMakeLists.txt
View file @
2ea5f3e3
set
(
CMAKE_INCLUDE_CURRENT_DIR ON
)
set
(
CMAKE_CXX_FLAGS_DEBUG
"-g -DBINARY_SUFFIX= -DBINARY_STRIPPED_SUFFIX=_stripped"
)
set
(
CMAKE_CXX_FLAGS_RELEASE
"
${
CMAKE_CXX_FLAGS_RELEASE
}
-fstrict-aliasing -enable-tbaa -DNVALGRIND -DBINARY_SUFFIX=_release -DBINARY_STRIPPED_SUFFIX="
)
set
(
CMAKE_CXX_FLAGS_DEBUG
"-g -DBINARY_SUFFIX= -DBINARY_STRIPPED_SUFFIX=_stripped
-DPy_BUILD_CORE
"
)
set
(
CMAKE_CXX_FLAGS_RELEASE
"
${
CMAKE_CXX_FLAGS_RELEASE
}
-fstrict-aliasing -enable-tbaa -DNVALGRIND -DBINARY_SUFFIX=_release -DBINARY_STRIPPED_SUFFIX=
-DPy_BUILD_CORE
"
)
execute_process
(
COMMAND git rev-parse HEAD WORKING_DIRECTORY
${
CMAKE_SOURCE_DIR
}
OUTPUT_VARIABLE GITREV OUTPUT_STRIP_TRAILING_WHITESPACE
)
set_source_files_properties
(
jit.cpp PROPERTIES COMPILE_DEFINITIONS
"GITREV=
${
GITREV
}
"
)
...
...
src/capi/typeobject.cpp
View file @
2ea5f3e3
...
...
@@ -3301,7 +3301,24 @@ void commonClassSetup(BoxedClass* cls) {
}
extern
"C"
void
PyType_Modified
(
PyTypeObject
*
type
)
noexcept
{
// We don't cache anything yet that would need to be invalidated:
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
)
{
PyType_Modified
((
PyTypeObject
*
)
ref
);
}
}
}
type
->
tp_flags
&=
~
Py_TPFLAGS_VALID_VERSION_TAG
;
}
template
<
ExceptionStyle
S
>
...
...
@@ -3504,6 +3521,7 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
exception_types
.
push_back
(
cls
);
}
cls
->
tp_flags
|=
Py_TPFLAGS_READY
;
return
0
;
}
...
...
src/jit.cpp
View file @
2ea5f3e3
...
...
@@ -455,7 +455,7 @@ static int main(int argc, char** argv) {
main_module
=
createModule
(
boxString
(
"__main__"
),
"<string>"
);
rtncode
=
(
RunModule
(
module
,
1
)
!=
0
);
}
else
{
main_module
=
createModule
(
boxString
(
"__main__"
),
fn
);
main_module
=
createModule
(
boxString
(
"__main__"
),
fn
?
fn
:
"<string>"
);
rtncode
=
0
;
if
(
fn
!=
NULL
)
{
rtncode
=
RunMainFromImporter
(
fn
);
...
...
src/runtime/objmodel.cpp
View file @
2ea5f3e3
...
...
@@ -426,7 +426,7 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset
tp_weaklistoffset
=
weaklist_offset
;
tp_name
=
name
;
tp_flags
|=
Py_TPFLAGS_DEFAULT_
EXTERNAL
;
tp_flags
|=
Py_TPFLAGS_DEFAULT_
CORE
;
tp_flags
|=
Py_TPFLAGS_CHECKTYPES
;
tp_flags
|=
Py_TPFLAGS_BASETYPE
;
tp_flags
|=
Py_TPFLAGS_HAVE_GC
;
...
...
@@ -535,6 +535,7 @@ void BoxedClass::finishInitialization() {
this
->
tp_dict
=
this
->
getAttrWrapper
();
commonClassSetup
(
this
);
tp_flags
|=
Py_TPFLAGS_READY
;
}
BoxedHeapClass
::
BoxedHeapClass
(
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
weaklist_offset
,
...
...
@@ -948,13 +949,75 @@ extern "C" PyObject* _PyType_Lookup(PyTypeObject* type, PyObject* name) noexcept
}
}
#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, ((BoxedString*)(name))->hash)
#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
;
int
assign_version_tag
(
PyTypeObject
*
type
)
noexcept
{
/* 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 */
PyType_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
;
}
template
<
Rewritable
rewritable
>
Box
*
typeLookup
(
BoxedClass
*
cls
,
BoxedString
*
attr
,
GetattrRewriteArgs
*
rewrite_args
)
{
if
(
rewritable
==
NOT_REWRITABLE
)
{
assert
(
!
rewrite_args
);
rewrite_args
=
NULL
;
}
Box
*
val
;
Box
*
val
=
NULL
;
if
(
rewrite_args
)
{
assert
(
!
rewrite_args
->
isSuccessful
());
...
...
@@ -1009,6 +1072,17 @@ template <Rewritable rewritable> Box* typeLookup(BoxedClass* cls, BoxedString* a
assert
(
attr
->
interned_state
!=
SSTATE_NOT_INTERNED
);
assert
(
cls
->
tp_mro
);
assert
(
cls
->
tp_mro
->
cls
==
tuple_cls
);
if
(
MCACHE_CACHEABLE_NAME
(
attr
)
&&
PyType_HasFeature
(
cls
,
Py_TPFLAGS_VALID_VERSION_TAG
))
{
if
(
attr
->
hash
==
-
1
)
strHashUnboxed
(
attr
);
/* fast path */
unsigned
int
h
=
MCACHE_HASH_METHOD
(
cls
,
attr
);
if
(
method_cache
[
h
].
version
==
cls
->
tp_version_tag
&&
method_cache
[
h
].
name
==
attr
)
return
method_cache
[
h
].
value
;
}
for
(
auto
b
:
*
static_cast
<
BoxedTuple
*>
(
cls
->
tp_mro
))
{
// object_cls will get checked very often, but it only
// has attributes that start with an underscore.
...
...
@@ -1021,9 +1095,18 @@ template <Rewritable rewritable> Box* typeLookup(BoxedClass* cls, BoxedString* a
val
=
b
->
getattr
(
attr
);
if
(
val
)
return
val
;
break
;
}
return
NULL
;
if
(
MCACHE_CACHEABLE_NAME
(
attr
)
&&
assign_version_tag
(
cls
))
{
unsigned
int
h
=
MCACHE_HASH_METHOD
(
cls
,
attr
);
method_cache
[
h
].
version
=
cls
->
tp_version_tag
;
method_cache
[
h
].
value
=
val
;
/* borrowed */
Py_INCREF
(
attr
);
Py_DECREF
(
method_cache
[
h
].
name
);
method_cache
[
h
].
name
=
attr
;
}
return
val
;
}
}
template
Box
*
typeLookup
<
REWRITABLE
>(
BoxedClass
*
,
BoxedString
*
,
GetattrRewriteArgs
*
);
...
...
@@ -2282,6 +2365,10 @@ void setattrGeneric(Box* obj, BoxedString* attr, Box* val, SetattrRewriteArgs* r
rewrite_args
=
NULL
;
REWRITE_ABORTED
(
""
);
}
// update_slot() calls PyType_Modified() internally so we only have to explicitly call it inside the IC
if
(
rewrite_args
)
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
PyType_Modified
,
rewrite_args
->
obj
);
}
}
...
...
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