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
Gwenaël Samain
cython
Commits
86bb8a8f
Commit
86bb8a8f
authored
Mar 15, 2009
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactored GIL checking into separate transform (ticket #205)
parent
c93d8837
Changes
5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
139 additions
and
76 deletions
+139
-76
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+69
-47
Cython/Compiler/Main.py
Cython/Compiler/Main.py
+2
-0
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+28
-24
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/ParseTreeTransforms.py
+37
-1
tests/errors/nogil.pyx
tests/errors/nogil.pyx
+3
-4
No files found.
Cython/Compiler/ExprNodes.py
View file @
86bb8a8f
This diff is collapsed.
Click to expand it.
Cython/Compiler/Main.py
View file @
86bb8a8f
...
...
@@ -81,6 +81,7 @@ class Context(object):
from
ParseTreeTransforms
import
CreateClosureClasses
,
MarkClosureVisitor
,
DecoratorTransform
from
ParseTreeTransforms
import
InterpretCompilerDirectives
,
TransformBuiltinMethods
from
ParseTreeTransforms
import
ComprehensionTransform
,
AlignFunctionDefinitions
from
ParseTreeTransforms
import
GilCheck
from
AutoDocTransforms
import
EmbedSignature
from
Optimize
import
FlattenInListTransform
,
SwitchTransform
,
IterationTransform
from
Optimize
import
FlattenBuiltinTypeCreation
,
ConstantFolding
,
FinalOptimizePhase
...
...
@@ -129,6 +130,7 @@ class Context(object):
IterationTransform
(),
SwitchTransform
(),
FinalOptimizePhase
(
self
),
GilCheck
(),
# ClearResultCodes(self),
# SpecialFunctions(self),
# CreateClosureClasses(context),
...
...
Cython/Compiler/Nodes.py
View file @
86bb8a8f
...
...
@@ -134,7 +134,8 @@ class Node(object):
gil_message
=
"Operation"
def
gil_check
(
self
,
env
):
gil_check
=
None
def
_gil_check
(
self
,
env
):
if
env
.
nogil
:
self
.
gil_error
()
...
...
@@ -539,9 +540,6 @@ class CFuncDeclaratorNode(CDeclaratorNode):
# Catch attempted C-style func(void) decl
if
type
.
is_void
:
error
(
arg_node
.
pos
,
"Use spam() rather than spam(void) to declare a function with no arguments."
)
# if type.is_pyobject and self.nogil:
# error(self.pos,
# "Function with Python argument cannot be declared nogil")
func_type_args
.
append
(
PyrexTypes
.
CFuncTypeArg
(
name
,
type
,
arg_node
.
pos
))
if
arg_node
.
default
:
...
...
@@ -1378,18 +1376,20 @@ class CFuncDefNode(FuncDefNode):
if
not
arg
.
name
:
error
(
arg
.
pos
,
"Missing argument name"
)
self
.
declare_argument
(
env
,
arg
)
def
need_gil_acquisition
(
self
,
lenv
):
return
self
.
type
.
with_gil
def
gil_check
(
self
,
env
):
type
=
self
.
type
with_gil
=
self
.
type
.
with_gil
with_gil
=
type
.
with_gil
if
type
.
nogil
and
not
with_gil
:
if
type
.
return_type
.
is_pyobject
:
error
(
self
.
pos
,
"Function with Python return type cannot be declared nogil"
)
for
entry
in
lenv
.
var_entries
+
l
env
.
temp_entries
:
for
entry
in
env
.
var_entries
+
env
.
temp_entries
:
if
entry
.
type
.
is_pyobject
:
error
(
self
.
pos
,
"Function declared nogil has Python locals or temporaries"
)
return
with_gil
def
analyse_expressions
(
self
,
env
):
self
.
analyse_default_values
(
env
)
...
...
@@ -3227,8 +3227,8 @@ class PrintStatNode(StatNode):
env
.
use_utility_code
(
printing_utility_code
)
if
len
(
self
.
arg_tuple
.
args
)
==
1
and
self
.
append_newline
:
env
.
use_utility_code
(
printing_one_utility_code
)
self
.
gil_check
(
env
)
gil_check
=
StatNode
.
_gil_check
gil_message
=
"Python print statement"
def
generate_execution_code
(
self
,
code
):
...
...
@@ -3272,8 +3272,8 @@ class ExecStatNode(StatNode):
self
.
temp_result
=
env
.
allocate_temp_pyobject
()
env
.
release_temp
(
self
.
temp_result
)
env
.
use_utility_code
(
Builtin
.
pyexec_utility_code
)
self
.
gil_check
(
env
)
gil_check
=
StatNode
.
_gil_check
gil_message
=
"Python exec statement"
def
generate_execution_code
(
self
,
code
):
...
...
@@ -3311,12 +3311,15 @@ class DelStatNode(StatNode):
def
analyse_expressions
(
self
,
env
):
for
arg
in
self
.
args
:
arg
.
analyse_target_expression
(
env
,
None
)
if
arg
.
type
.
is_pyobject
:
self
.
gil_check
(
env
)
else
:
if
not
arg
.
type
.
is_pyobject
:
error
(
arg
.
pos
,
"Deletion of non-Python object"
)
#arg.release_target_temp(env)
def
gil_check
(
self
,
env
):
for
arg
in
self
.
args
:
if
arg
.
type
.
is_pyobject
:
self
.
_gil_check
(
env
)
gil_message
=
"Deleting Python object"
def
generate_execution_code
(
self
,
code
):
...
...
@@ -3402,8 +3405,10 @@ class ReturnStatNode(StatNode):
and
not
return_type
.
is_pyobject
and
not
return_type
.
is_returncode
):
error
(
self
.
pos
,
"Return value required"
)
if
return_type
.
is_pyobject
:
self
.
gil_check
(
env
)
def
gil_check
(
self
,
env
):
if
self
.
return_type
.
is_pyobject
:
self
.
_gil_check
(
env
)
gil_message
=
"Returning Python object"
...
...
@@ -3478,8 +3483,8 @@ class RaiseStatNode(StatNode):
self
.
exc_tb
.
release_temp
(
env
)
env
.
use_utility_code
(
raise_utility_code
)
env
.
use_utility_code
(
restore_exception_utility_code
)
self
.
gil_check
(
env
)
gil_check
=
StatNode
.
_gil_check
gil_message
=
"Raising exception"
def
generate_execution_code
(
self
,
code
):
...
...
@@ -3528,10 +3533,10 @@ class ReraiseStatNode(StatNode):
child_attrs
=
[]
def
analyse_expressions
(
self
,
env
):
self
.
gil_check
(
env
)
env
.
use_utility_code
(
raise_utility_code
)
env
.
use_utility_code
(
restore_exception_utility_code
)
gil_check
=
StatNode
.
_gil_check
gil_message
=
"Raising exception"
def
generate_execution_code
(
self
,
code
):
...
...
@@ -3560,9 +3565,9 @@ class AssertStatNode(StatNode):
self
.
cond
.
release_temp
(
env
)
if
self
.
value
:
self
.
value
.
release_temp
(
env
)
self
.
gil_check
(
env
)
#env.recycle_pending_temps() # TEMPORARY
gil_check
=
StatNode
.
_gil_check
gil_message
=
"Raising exception"
def
generate_execution_code
(
self
,
code
):
...
...
@@ -4069,9 +4074,8 @@ class TryExceptStatNode(StatNode):
except_clause
.
analyse_declarations
(
env
)
if
self
.
else_clause
:
self
.
else_clause
.
analyse_declarations
(
env
)
self
.
gil_check
(
env
)
env
.
use_utility_code
(
reset_exception_utility_code
)
def
analyse_expressions
(
self
,
env
):
self
.
body
.
analyse_expressions
(
env
)
self
.
cleanup_list
=
env
.
free_temp_entries
[:]
...
...
@@ -4085,8 +4089,8 @@ class TryExceptStatNode(StatNode):
self
.
has_default_clause
=
default_clause_seen
if
self
.
else_clause
:
self
.
else_clause
.
analyse_expressions
(
env
)
self
.
gil_check
(
env
)
gil_check
=
StatNode
.
_gil_check
gil_message
=
"Try-except statement"
def
generate_execution_code
(
self
,
code
):
...
...
@@ -4368,8 +4372,8 @@ class TryFinallyStatNode(StatNode):
self
.
body
.
analyse_expressions
(
env
)
self
.
cleanup_list
=
env
.
free_temp_entries
[:]
self
.
finally_clause
.
analyse_expressions
(
env
)
self
.
gil_check
(
env
)
gil_check
=
StatNode
.
_gil_check
gil_message
=
"Try-finally statement"
def
generate_execution_code
(
self
,
code
):
...
...
@@ -4516,8 +4520,8 @@ class GILStatNode(TryFinallyStatNode):
# 'with gil' or 'with nogil' statement
#
# state string 'gil' or 'nogil'
child_attrs
=
[]
#
child_attrs = []
preserve_exception
=
0
...
...
Cython/Compiler/ParseTreeTransforms.py
View file @
86bb8a8f
...
...
@@ -845,7 +845,43 @@ class CreateClosureClasses(CythonTransform):
def
visit_FuncDefNode
(
self
,
node
):
self
.
create_class_from_scope
(
node
,
self
.
module_scope
)
return
node
class
GilCheck
(
VisitorTransform
):
"""
Call `node.gil_check(env)` on each node to make sure we hold the
GIL when we need it. Raise an error when on Python operations
inside a `nogil` environment.
"""
def
__call__
(
self
,
root
):
self
.
env_stack
=
[
root
.
scope
]
return
super
(
GilCheck
,
self
).
__call__
(
root
)
def
visit_FuncDefNode
(
self
,
node
):
self
.
env_stack
.
append
(
node
.
local_scope
)
if
node
.
gil_check
is
not
None
:
node
.
gil_check
(
self
.
env_stack
[
-
1
])
self
.
visitchildren
(
node
)
self
.
env_stack
.
pop
()
return
node
def
visit_GILStatNode
(
self
,
node
):
# FIXME: should we do some kind of GIL checking here, too?
# if node.gil_check is not None:
# node.gil_check(self.env_stack[-1])
env
=
self
.
env_stack
[
-
1
]
was_nogil
=
env
.
nogil
env
.
nogil
=
node
.
state
==
'nogil'
self
.
visitchildren
(
node
)
env
.
nogil
=
was_nogil
return
node
def
visit_Node
(
self
,
node
):
if
self
.
env_stack
and
node
.
gil_check
is
not
None
:
node
.
gil_check
(
self
.
env_stack
[
-
1
])
self
.
visitchildren
(
node
)
return
node
class
EnvTransform
(
CythonTransform
):
"""
...
...
tests/errors/nogil.pyx
View file @
86bb8a8f
...
...
@@ -82,14 +82,14 @@ _ERRORS = u"""
6: 6: Assignment of Python object not allowed without gil
4: 5: Function declared nogil has Python locals or temporaries
11: 5: Function with Python return type cannot be declared nogil
15: 5: Calling gil-requiring function without gil
24: 9: Calling gil-requiring function without gil
15: 5: Calling gil-requiring function
not allowed
without gil
24: 9: Calling gil-requiring function
not allowed
without gil
26:12: Assignment of Python object not allowed without gil
28: 8: Constructing complex number not allowed without gil
29:12: Accessing Python global or builtin not allowed without gil
30: 8: Backquote expression not allowed without gil
31:15: Python import not allowed without gil
31:15: Assignment of Python object not allowed without gil
31:15: Python import not allowed without gil
32:13: Python import not allowed without gil
32:25: Constructing Python list not allowed without gil
33:17: Iterating over Python object not allowed without gil
...
...
@@ -126,7 +126,6 @@ _ERRORS = u"""
54: 8: Raising exception not allowed without gil
55:14: Truth-testing Python object not allowed without gil
57:17: Truth-testing Python object not allowed without gil
59: 8: Converting to Python object not allowed without gil
61: 8: Try-except statement not allowed without gil
65: 8: Try-finally statement not allowed without gil
"""
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