Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
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
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Xavier Thompson
cython
Commits
cbec2d11
Commit
cbec2d11
authored
Jul 31, 2017
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
speed up type checks, especially for exceptions (which are used a lot in yield/await)
parent
b797b427
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
130 additions
and
34 deletions
+130
-34
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+6
-6
Cython/Compiler/ModuleNode.py
Cython/Compiler/ModuleNode.py
+1
-0
Cython/Utility/AsyncGen.c
Cython/Utility/AsyncGen.c
+1
-4
Cython/Utility/Buffer.c
Cython/Utility/Buffer.c
+2
-2
Cython/Utility/Coroutine.c
Cython/Utility/Coroutine.c
+6
-11
Cython/Utility/CythonFunction.c
Cython/Utility/CythonFunction.c
+2
-2
Cython/Utility/Exceptions.c
Cython/Utility/Exceptions.c
+1
-1
Cython/Utility/FunctionArguments.c
Cython/Utility/FunctionArguments.c
+1
-1
Cython/Utility/ModuleSetupCode.c
Cython/Utility/ModuleSetupCode.c
+105
-1
Cython/Utility/ObjectHandling.c
Cython/Utility/ObjectHandling.c
+5
-6
No files found.
Cython/Compiler/ExprNodes.py
View file @
cbec2d11
...
...
@@ -2700,8 +2700,7 @@ class IteratorNode(ExprNode):
code
.
putln
(
"if (unlikely(!%s)) {"
%
result_name
)
code
.
putln
(
"PyObject* exc_type = PyErr_Occurred();"
)
code
.
putln
(
"if (exc_type) {"
)
code
.
putln
(
"if (likely(exc_type == PyExc_StopIteration ||"
" PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();"
)
code
.
putln
(
"if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();"
)
code
.
putln
(
"else %s"
%
code
.
error_goto
(
self
.
pos
))
code
.
putln
(
"}"
)
code
.
putln
(
"break;"
)
...
...
@@ -9532,8 +9531,8 @@ class _YieldDelegationExprNode(YieldExprNode):
def
handle_iteration_exception
(
self
,
code
):
code
.
putln
(
"PyObject* exc_type = PyErr_Occurred();"
)
code
.
putln
(
"if (exc_type) {"
)
code
.
putln
(
"if (likely(exc_type == PyExc_StopIteration ||"
" PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();"
)
code
.
putln
(
"if (likely(exc_type == PyExc_StopIteration ||
exc_type != PyExc_GeneratorExit &&
"
"
__Pyx_
PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();"
)
code
.
putln
(
"else %s"
%
code
.
error_goto
(
self
.
pos
))
code
.
putln
(
"}"
)
...
...
@@ -9588,8 +9587,9 @@ class AwaitIterNextExprNode(AwaitExprNode):
def
_generate_break
(
self
,
code
):
code
.
globalstate
.
use_utility_code
(
UtilityCode
.
load_cached
(
"StopAsyncIteration"
,
"Coroutine.c"
))
code
.
putln
(
"PyObject* exc_type = PyErr_Occurred();"
)
code
.
putln
(
"if (exc_type && likely(exc_type == __Pyx_PyExc_StopAsyncIteration ||"
" PyErr_GivenExceptionMatches(exc_type, __Pyx_PyExc_StopAsyncIteration))) {"
)
code
.
putln
(
"if (unlikely(exc_type && (exc_type == __Pyx_PyExc_StopAsyncIteration || ("
" exc_type != PyExc_StopIteration && exc_type != PyExc_GeneratorExit &&"
" __Pyx_PyErr_GivenExceptionMatches(exc_type, __Pyx_PyExc_StopAsyncIteration))))) {"
)
code
.
putln
(
"PyErr_Clear();"
)
code
.
putln
(
"break;"
)
code
.
putln
(
"}"
)
...
...
Cython/Compiler/ModuleNode.py
View file @
cbec2d11
...
...
@@ -717,6 +717,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code
.
putln
(
'static const char * %s= %s;'
%
(
Naming
.
cfilenm_cname
,
Naming
.
file_c_macro
))
code
.
putln
(
'static const char *%s;'
%
Naming
.
filename_cname
)
env
.
use_utility_code
(
UtilityCode
.
load_cached
(
"FastTypeChecks"
,
"ModuleSetupCode.c"
))
if
has_np_pythran
(
env
):
env
.
use_utility_code
(
UtilityCode
.
load_cached
(
"PythranConversion"
,
"CppSupport.cpp"
))
...
...
Cython/Utility/AsyncGen.c
View file @
cbec2d11
...
...
@@ -432,10 +432,7 @@ __Pyx_async_gen_unwrap_value(__pyx_PyAsyncGenObject *gen, PyObject *result)
if
(
!
exc_type
)
{
PyErr_SetNone
(
__Pyx_PyExc_StopAsyncIteration
);
gen
->
ag_closed
=
1
;
}
else
if
(
exc_type
==
__Pyx_PyExc_StopAsyncIteration
||
exc_type
==
PyExc_GeneratorExit
||
PyErr_GivenExceptionMatches
(
exc_type
,
__Pyx_PyExc_StopAsyncIteration
)
||
PyErr_GivenExceptionMatches
(
exc_type
,
PyExc_GeneratorExit
))
{
}
else
if
(
__Pyx_PyErr_GivenExceptionMatches2
(
exc_type
,
__Pyx_PyExc_StopAsyncIteration
,
PyExc_GeneratorExit
))
{
gen
->
ag_closed
=
1
;
}
...
...
Cython/Utility/Buffer.c
View file @
cbec2d11
...
...
@@ -111,7 +111,7 @@ static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) {
{{
for
type_ptr
,
getbuffer
,
releasebuffer
in
types
}}
{{
if
getbuffer
}}
if
(
PyObject
_TypeCheck
(
obj
,
{{
type_ptr
}}))
return
{{
getbuffer
}}(
obj
,
view
,
flags
);
if
(
__Pyx
_TypeCheck
(
obj
,
{{
type_ptr
}}))
return
{{
getbuffer
}}(
obj
,
view
,
flags
);
{{
endif
}}
{{
endfor
}}
...
...
@@ -130,7 +130,7 @@ static void __Pyx_ReleaseBuffer(Py_buffer *view) {
{{
for
type_ptr
,
getbuffer
,
releasebuffer
in
types
}}
{{
if
releasebuffer
}}
if
(
PyObject
_TypeCheck
(
obj
,
{{
type_ptr
}}))
{
{{
releasebuffer
}}(
obj
,
view
);
return
;
}
if
(
__Pyx
_TypeCheck
(
obj
,
{{
type_ptr
}}))
{
{{
releasebuffer
}}(
obj
,
view
);
return
;
}
{{
endif
}}
{{
endfor
}}
...
...
Cython/Utility/Coroutine.c
View file @
cbec2d11
...
...
@@ -343,9 +343,9 @@ static void __Pyx_Generator_Replace_StopIteration(CYTHON_UNUSED int in_async_gen
#endif
cur_exc
=
PyErr_Occurred
();
if
(
likely
(
!
PyErr_GivenExceptionMatches
(
cur_exc
,
PyExc_StopIteration
)))
{
if
(
likely
(
!
__Pyx_
PyErr_GivenExceptionMatches
(
cur_exc
,
PyExc_StopIteration
)))
{
#ifdef __Pyx_StopAsyncIteration_USED
if
(
in_async_gen
&&
unlikely
(
PyErr_GivenExceptionMatches
(
cur_exc
,
__Pyx_PyExc_StopAsyncIteration
)))
{
if
(
in_async_gen
&&
unlikely
(
__Pyx_
PyErr_GivenExceptionMatches
(
cur_exc
,
__Pyx_PyExc_StopAsyncIteration
)))
{
is_async_stopiteration
=
1
;
}
else
#endif
...
...
@@ -509,7 +509,7 @@ static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue) {
}
Py_DECREF
(
ev
);
}
else
if
(
!
PyObject
_TypeCheck
(
ev
,
(
PyTypeObject
*
)
PyExc_StopIteration
))
{
else
if
(
!
__Pyx
_TypeCheck
(
ev
,
(
PyTypeObject
*
)
PyExc_StopIteration
))
{
// 'steal' reference to ev
value
=
ev
;
}
...
...
@@ -519,7 +519,7 @@ static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue) {
*
pvalue
=
value
;
return
0
;
}
}
else
if
(
!
PyErr_GivenExceptionMatches
(
et
,
PyExc_StopIteration
))
{
}
else
if
(
!
__Pyx_
PyErr_GivenExceptionMatches
(
et
,
PyExc_StopIteration
))
{
__Pyx_ErrRestore
(
et
,
ev
,
tb
);
return
-
1
;
}
...
...
@@ -876,12 +876,7 @@ static PyObject *__Pyx_Coroutine_Close(PyObject *self) {
return
NULL
;
}
raised_exception
=
PyErr_Occurred
();
if
(
!
raised_exception
||
raised_exception
==
PyExc_StopIteration
||
raised_exception
==
PyExc_GeneratorExit
||
PyErr_GivenExceptionMatches
(
raised_exception
,
PyExc_GeneratorExit
)
||
PyErr_GivenExceptionMatches
(
raised_exception
,
PyExc_StopIteration
))
{
if
(
!
raised_exception
||
__Pyx_PyErr_GivenExceptionMatches2
(
raised_exception
,
PyExc_GeneratorExit
,
PyExc_StopIteration
))
{
// ignore these errors
if
(
raised_exception
)
PyErr_Clear
();
Py_INCREF
(
Py_None
);
...
...
@@ -901,7 +896,7 @@ static PyObject *__Pyx__Coroutine_Throw(PyObject *self, PyObject *typ, PyObject
if
(
yf
)
{
PyObject
*
ret
;
Py_INCREF
(
yf
);
if
(
PyErr_GivenExceptionMatches
(
typ
,
PyExc_GeneratorExit
)
&&
close_on_genexit
)
{
if
(
__Pyx_
PyErr_GivenExceptionMatches
(
typ
,
PyExc_GeneratorExit
)
&&
close_on_genexit
)
{
// Asynchronous generators *should not* be closed right away.
// We have to allow some awaits to work it through, hence the
// `close_on_genexit` parameter here.
...
...
Cython/Utility/CythonFunction.c
View file @
cbec2d11
...
...
@@ -1218,7 +1218,7 @@ static PyObject* __Pyx_Method_ClassMethod(PyObject *method) {
methoddescr_type
=
Py_TYPE
(
meth
);
Py_DECREF
(
meth
);
}
if
(
PyObject
_TypeCheck
(
method
,
methoddescr_type
))
{
if
(
__Pyx
_TypeCheck
(
method
,
methoddescr_type
))
{
#endif
// cdef classes
PyMethodDescrObject
*
descr
=
(
PyMethodDescrObject
*
)
method
;
...
...
@@ -1238,7 +1238,7 @@ static PyObject* __Pyx_Method_ClassMethod(PyObject *method) {
return
PyClassMethod_New
(
method
);
}
#ifdef __Pyx_CyFunction_USED
else
if
(
PyObject
_TypeCheck
(
method
,
__pyx_CyFunctionType
))
{
else
if
(
__Pyx
_TypeCheck
(
method
,
__pyx_CyFunctionType
))
{
return
PyClassMethod_New
(
method
);
}
#endif
...
...
Cython/Utility/Exceptions.c
View file @
cbec2d11
...
...
@@ -35,7 +35,7 @@ static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tsta
PyObject
*
exc_type
=
tstate
->
curexc_type
;
if
(
exc_type
==
err
)
return
1
;
if
(
unlikely
(
!
exc_type
))
return
0
;
return
PyErr_GivenExceptionMatches
(
exc_type
,
err
);
return
__Pyx_
PyErr_GivenExceptionMatches
(
exc_type
,
err
);
}
#endif
...
...
Cython/Utility/FunctionArguments.c
View file @
cbec2d11
...
...
@@ -26,7 +26,7 @@ static CYTHON_INLINE int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, in
#endif
}
else
{
if
(
likely
(
PyObject
_TypeCheck
(
obj
,
type
)))
return
1
;
if
(
likely
(
__Pyx
_TypeCheck
(
obj
,
type
)))
return
1
;
}
__Pyx_RaiseArgumentTypeInvalid
(
name
,
obj
,
type
);
return
0
;
...
...
Cython/Utility/ModuleSetupCode.c
View file @
cbec2d11
...
...
@@ -326,7 +326,6 @@
#define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type)
#endif
#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type)
#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception)
#if PY_MAJOR_VERSION >= 3
...
...
@@ -537,6 +536,111 @@ class __Pyx_FakeReference {
};
/////////////// FastTypeChecks.proto ///////////////
#if CYTHON_COMPILING_IN_CPYTHON
#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type)
static
CYTHON_INLINE
int
__Pyx_IsSubtype
(
PyTypeObject
*
a
,
PyTypeObject
*
b
);
/*proto*/
static
CYTHON_INLINE
int
__Pyx_PyErr_GivenExceptionMatches
(
PyObject
*
err
,
PyObject
*
type
);
/*proto*/
static
CYTHON_INLINE
int
__Pyx_PyErr_GivenExceptionMatches2
(
PyObject
*
err
,
PyObject
*
type1
,
PyObject
*
type2
);
/*proto*/
#else
#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type)
#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type)
#define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2))
#endif
/////////////// FastTypeChecks ///////////////
//@requires: Exceptions.c::PyThreadStateGet
//@requires: Exceptions.c::PyErrFetchRestore
#if CYTHON_COMPILING_IN_CPYTHON
static
int
__Pyx_InBases
(
PyTypeObject
*
a
,
PyTypeObject
*
b
)
{
while
(
a
)
{
a
=
a
->
tp_base
;
if
(
a
==
b
)
return
1
;
}
return
b
==
&
PyBaseObject_Type
;
}
static
CYTHON_INLINE
int
__Pyx_IsSubtype
(
PyTypeObject
*
a
,
PyTypeObject
*
b
)
{
PyObject
*
mro
;
if
(
a
==
b
)
return
1
;
mro
=
a
->
tp_mro
;
if
(
likely
(
mro
))
{
Py_ssize_t
i
,
n
;
n
=
PyTuple_GET_SIZE
(
mro
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
if
(
PyTuple_GET_ITEM
(
mro
,
i
)
==
(
PyObject
*
)
b
)
return
1
;
}
return
0
;
}
// should only get here for incompletely initialised types, i.e. never under normal usage patterns
return
__Pyx_InBases
(
a
,
b
);
}
#if PY_MAJOR_VERSION == 2
static
int
__Pyx_inner_PyErr_GivenExceptionMatches2
(
PyTypeObject
*
err
,
PyTypeObject
*
exc_type1
,
PyTypeObject
*
exc_type2
)
{
// PyObject_IsSubclass() can recurse and therefore is not safe
PyObject
*
exception
,
*
value
,
*
tb
;
int
res
;
__Pyx_PyThreadState_declare
__Pyx_PyThreadState_assign
__Pyx_ErrFetch
(
&
exception
,
&
value
,
&
tb
);
res
=
exc_type1
?
PyObject_IsSubclass
(
err
,
exc_type1
)
:
0
;
// This function must not fail, so print the error here
if
(
unlikely
(
res
==
-
1
))
{
PyErr_WriteUnraisable
(
err
);
res
=
0
;
}
if
(
!
res
)
{
__Pyx_ErrRestore
(
exception
,
value
,
tb
);
res
=
PyObject_IsSubclass
(
err
,
exc_type2
);
// This function must not fail, so print the error here
if
(
unlikely
(
res
==
-
1
))
{
PyErr_WriteUnraisable
(
err
);
res
=
0
;
}
}
__Pyx_ErrRestore
(
exception
,
value
,
tb
);
return
res
;
}
#else
static
CYTHON_INLINE
int
__Pyx_inner_PyErr_GivenExceptionMatches2
(
PyTypeObject
*
err
,
PyTypeObject
*
exc_type1
,
PyTypeObject
*
exc_type2
)
{
int
res
=
exc_type1
?
__Pyx_IsSubtype
(
err
,
exc_type1
)
:
0
;
if
(
!
res
)
{
res
=
__Pyx_IsSubtype
(
err
,
exc_type2
);
}
return
res
;
}
#endif
// so far, we only call PyErr_GivenExceptionMatches() with an exception type (not instance) as first argument
// => optimise for that case
static
CYTHON_INLINE
int
__Pyx_PyErr_GivenExceptionMatches
(
PyObject
*
err
,
PyObject
*
exc_type
)
{
if
(
likely
(
err
==
exc_type
))
return
1
;
if
(
likely
(
PyExceptionClass_Check
(
err
)))
{
return
__Pyx_inner_PyErr_GivenExceptionMatches2
((
PyTypeObject
*
)
err
,
NULL
,
(
PyTypeObject
*
)
exc_type
);
}
return
PyErr_GivenExceptionMatches
(
err
,
exc_type
);
}
static
CYTHON_INLINE
int
__Pyx_PyErr_GivenExceptionMatches2
(
PyObject
*
err
,
PyObject
*
exc_type1
,
PyObject
*
exc_type2
)
{
if
(
likely
(
err
==
exc_type1
||
err
==
exc_type2
))
return
1
;
if
(
likely
(
PyExceptionClass_Check
(
err
)))
{
return
__Pyx_inner_PyErr_GivenExceptionMatches2
((
PyTypeObject
*
)
err
,
(
PyTypeObject
*
)
exc_type1
,
(
PyTypeObject
*
)
exc_type2
);
}
return
(
PyErr_GivenExceptionMatches
(
err
,
exc_type1
)
||
PyErr_GivenExceptionMatches
(
err
,
exc_type2
));
}
#endif
/////////////// MathInitCode ///////////////
#if defined(WIN32) || defined(MS_WINDOWS)
...
...
Cython/Utility/ObjectHandling.c
View file @
cbec2d11
...
...
@@ -166,8 +166,7 @@ static CYTHON_INLINE PyObject *__Pyx_PyIter_Next2(PyObject* iterator, PyObject*
if
(
defval
)
{
PyObject
*
exc_type
=
PyErr_Occurred
();
if
(
exc_type
)
{
if
(
unlikely
(
exc_type
!=
PyExc_StopIteration
)
&&
!
PyErr_GivenExceptionMatches
(
exc_type
,
PyExc_StopIteration
))
if
(
unlikely
(
!
__Pyx_PyErr_GivenExceptionMatches
(
exc_type
,
PyExc_StopIteration
)))
return
NULL
;
PyErr_Clear
();
}
...
...
@@ -194,7 +193,7 @@ static CYTHON_INLINE int __Pyx_IterFinish(void) {
PyThreadState
*
tstate
=
PyThreadState_GET
();
PyObject
*
exc_type
=
tstate
->
curexc_type
;
if
(
unlikely
(
exc_type
))
{
if
(
likely
(
exc_type
==
PyExc_StopIteration
)
||
PyErr_GivenExceptionMatches
(
exc_type
,
PyExc_StopIteration
))
{
if
(
likely
(
__Pyx_PyErr_GivenExceptionMatches
(
exc_type
,
PyExc_StopIteration
)
))
{
PyObject
*
exc_value
,
*
exc_tb
;
exc_value
=
tstate
->
curexc_value
;
exc_tb
=
tstate
->
curexc_traceback
;
...
...
@@ -917,7 +916,7 @@ static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
PyErr_SetString
(
PyExc_SystemError
,
"Missing type object"
);
return
0
;
}
if
(
likely
(
PyObject
_TypeCheck
(
obj
,
type
)))
if
(
likely
(
__Pyx
_TypeCheck
(
obj
,
type
)))
return
1
;
PyErr_Format
(
PyExc_TypeError
,
"Cannot convert %.200s to %.200s"
,
Py_TYPE
(
obj
)
->
tp_name
,
type
->
tp_name
);
...
...
@@ -1123,7 +1122,7 @@ static int __Pyx_TryUnpackUnboundCMethod(__Pyx_CachedCFunction* target) {
#if CYTHON_COMPILING_IN_CPYTHON
#if PY_MAJOR_VERSION >= 3
// method dscriptor type isn't exported in Py2.x, cannot easily check the type there
if
(
likely
(
PyObject
_TypeCheck
(
method
,
&
PyMethodDescr_Type
)))
if
(
likely
(
__Pyx
_TypeCheck
(
method
,
&
PyMethodDescr_Type
)))
#endif
{
PyMethodDescrObject
*
descr
=
(
PyMethodDescrObject
*
)
method
;
...
...
@@ -1747,7 +1746,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) {
}
#endif
#ifdef __Pyx_CyFunction_USED
if
(
likely
(
PyCFunction_Check
(
func
)
||
PyObject
_TypeCheck
(
func
,
__pyx_CyFunctionType
)))
{
if
(
likely
(
PyCFunction_Check
(
func
)
||
__Pyx
_TypeCheck
(
func
,
__pyx_CyFunctionType
)))
{
#else
if
(
likely
(
PyCFunction_Check
(
func
)))
{
#endif
...
...
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