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
1c1c8b9a
Commit
1c1c8b9a
authored
May 29, 2019
by
gsamain
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
first batch for locking on assignment
parent
bc47d4b5
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
64 additions
and
23 deletions
+64
-23
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+27
-17
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+25
-4
Cython/Compiler/Symtab.py
Cython/Compiler/Symtab.py
+12
-2
No files found.
Cython/Compiler/ExprNodes.py
View file @
1c1c8b9a
...
@@ -848,7 +848,8 @@ class ExprNode(Node):
...
@@ -848,7 +848,8 @@ class ExprNode(Node):
self
.
generate_subexpr_disposal_code
(
code
)
self
.
generate_subexpr_disposal_code
(
code
)
def
generate_assignment_code
(
self
,
rhs
,
code
,
overloaded_assignment
=
False
,
def
generate_assignment_code
(
self
,
rhs
,
code
,
overloaded_assignment
=
False
,
exception_check
=
None
,
exception_value
=
None
):
exception_check
=
None
,
exception_value
=
None
,
needs_unlock
=
False
,
needs_rlock
=
False
,
needs_wlock
=
False
):
# Stub method for nodes which are not legal as
# Stub method for nodes which are not legal as
# the LHS of an assignment. An error will have
# the LHS of an assignment. An error will have
# been reported earlier.
# been reported earlier.
...
@@ -2301,7 +2302,8 @@ class NameNode(AtomicExprNode):
...
@@ -2301,7 +2302,8 @@ class NameNode(AtomicExprNode):
code
.
put_error_if_unbound
(
self
.
pos
,
entry
,
self
.
in_nogil_context
)
code
.
put_error_if_unbound
(
self
.
pos
,
entry
,
self
.
in_nogil_context
)
def
generate_assignment_code
(
self
,
rhs
,
code
,
overloaded_assignment
=
False
,
def
generate_assignment_code
(
self
,
rhs
,
code
,
overloaded_assignment
=
False
,
exception_check
=
None
,
exception_value
=
None
):
exception_check
=
None
,
exception_value
=
None
,
needs_unlock
=
False
,
needs_rlock
=
False
,
needs_wlock
=
False
):
#print "NameNode.generate_assignment_code:", self.name ###
#print "NameNode.generate_assignment_code:", self.name ###
entry
=
self
.
entry
entry
=
self
.
entry
if
entry
is
None
:
if
entry
is
None
:
...
@@ -2396,6 +2398,8 @@ class NameNode(AtomicExprNode):
...
@@ -2396,6 +2398,8 @@ class NameNode(AtomicExprNode):
code
.
put_cyxdecref
(
self
.
result
())
code
.
put_cyxdecref
(
self
.
result
())
if
not
self
.
type
.
is_memoryviewslice
:
if
not
self
.
type
.
is_memoryviewslice
:
if
not
assigned
:
if
not
assigned
:
if
needs_unlock
:
code
.
putln
(
"Cy_UNLOCK(%s);"
%
self
.
result
())
if
overloaded_assignment
:
if
overloaded_assignment
:
result
=
rhs
.
result
()
result
=
rhs
.
result
()
if
exception_check
==
'+'
:
if
exception_check
==
'+'
:
...
@@ -2413,6 +2417,10 @@ class NameNode(AtomicExprNode):
...
@@ -2413,6 +2417,10 @@ class NameNode(AtomicExprNode):
code
.
putln
(
'new (&%s) decltype(%s){%s};'
%
(
self
.
result
(),
self
.
result
(),
result
))
code
.
putln
(
'new (&%s) decltype(%s){%s};'
%
(
self
.
result
(),
self
.
result
(),
result
))
elif
result
!=
self
.
result
():
elif
result
!=
self
.
result
():
code
.
putln
(
'%s = %s;'
%
(
self
.
result
(),
result
))
code
.
putln
(
'%s = %s;'
%
(
self
.
result
(),
result
))
if
needs_wlock
:
code
.
putln
(
"Cy_WLOCK(%s);"
%
self
.
result
())
elif
needs_rlock
:
code
.
putln
(
"Cy_RLOCK(%s);"
%
self
.
result
())
if
debug_disposal_code
:
if
debug_disposal_code
:
print
(
"NameNode.generate_assignment_code:"
)
print
(
"NameNode.generate_assignment_code:"
)
print
(
"...generating post-assignment code for %s"
%
rhs
)
print
(
"...generating post-assignment code for %s"
%
rhs
)
...
@@ -6045,6 +6053,9 @@ class SimpleCallNode(CallNode):
...
@@ -6045,6 +6053,9 @@ class SimpleCallNode(CallNode):
exc_checks
.
append
(
"__Pyx_ErrOccurredWithGIL()"
)
exc_checks
.
append
(
"__Pyx_ErrOccurredWithGIL()"
)
else
:
else
:
exc_checks
.
append
(
"PyErr_Occurred()"
)
exc_checks
.
append
(
"PyErr_Occurred()"
)
for
arg
in
self
.
args
:
if
arg
.
type
.
is_cyp_class
and
arg
.
type
.
lock_mode
==
"autolock"
:
code
.
putln
(
"Cy_WLOCK(%s);"
%
arg
.
result
())
if
self
.
is_temp
or
exc_checks
:
if
self
.
is_temp
or
exc_checks
:
rhs
=
self
.
c_call_code
()
rhs
=
self
.
c_call_code
()
if
self
.
result
():
if
self
.
result
():
...
@@ -6833,7 +6844,6 @@ class AttributeNode(ExprNode):
...
@@ -6833,7 +6844,6 @@ class AttributeNode(ExprNode):
is_memslice_transpose
=
False
is_memslice_transpose
=
False
is_special_lookup
=
False
is_special_lookup
=
False
is_py_attr
=
0
is_py_attr
=
0
needs_autolock
=
False
def
as_cython_attribute
(
self
):
def
as_cython_attribute
(
self
):
if
(
isinstance
(
self
.
obj
,
NameNode
)
and
if
(
isinstance
(
self
.
obj
,
NameNode
)
and
...
@@ -7201,9 +7211,9 @@ class AttributeNode(ExprNode):
...
@@ -7201,9 +7211,9 @@ class AttributeNode(ExprNode):
if
hasattr
(
obj
,
'entry'
)
and
obj
.
entry
.
type
.
is_cyp_class
and
(
obj
.
entry
.
is_variable
or
obj
.
entry
.
is_cfunction
)
\
if
hasattr
(
obj
,
'entry'
)
and
obj
.
entry
.
type
.
is_cyp_class
and
(
obj
.
entry
.
is_variable
or
obj
.
entry
.
is_cfunction
)
\
and
not
(
obj
.
entry
.
is_rlocked
and
(
not
self
.
entry
.
is_cfunction
or
self
.
entry
.
type
.
is_const_method
)
or
obj
.
entry
.
is_wlocked
):
and
not
(
obj
.
entry
.
is_rlocked
and
(
not
self
.
entry
.
is_cfunction
or
self
.
entry
.
type
.
is_const_method
)
or
obj
.
entry
.
is_wlocked
):
if
obj
.
entry
.
type
.
lock_mode
==
"autolock"
:
if
obj
.
entry
.
type
.
lock_mode
==
"autolock"
:
print
"
We will
autolock here"
print
"
Request read lock
autolock here"
self
.
needs_autolock
=
True
self
.
obj
.
entry
.
is_rlocked
=
True
self
.
obj
.
entry
.
is_wlocked
=
True
self
.
obj
.
entry
.
locking_node
.
needs_rlock
=
True
elif
obj
.
entry
.
type
.
lock_mode
==
"checklock"
:
elif
obj
.
entry
.
type
.
lock_mode
==
"checklock"
:
return
False
return
False
return
True
return
True
...
@@ -7212,12 +7222,10 @@ class AttributeNode(ExprNode):
...
@@ -7212,12 +7222,10 @@ class AttributeNode(ExprNode):
obj
=
self
.
obj
obj
=
self
.
obj
if
self
.
is_lvalue
()
and
hasattr
(
obj
,
'entry'
)
and
obj
.
entry
.
type
.
is_cyp_class
and
not
obj
.
entry
.
is_wlocked
:
if
self
.
is_lvalue
()
and
hasattr
(
obj
,
'entry'
)
and
obj
.
entry
.
type
.
is_cyp_class
and
not
obj
.
entry
.
is_wlocked
:
if
obj
.
entry
.
type
.
lock_mode
==
"autolock"
:
if
obj
.
entry
.
type
.
lock_mode
==
"autolock"
:
print
"
We will
autolock here"
print
"
Request write lock
autolock here"
self
.
needs_autolock
=
True
self
.
needs_autolock
=
True
self
.
obj
.
entry
.
is_wlocked
=
True
self
.
obj
.
entry
.
is_wlocked
=
True
# FIXME: this needs to be obj.result(), because maybe we have to lock
self
.
obj
.
entry
.
locking_node
.
needs_wlock
=
True
# an intermediate object (obj.att.__autolocked_obj__.attribute)
env
.
autolocked_entries
.
append
(
self
.
obj
.
entry
)
elif
obj
.
entry
.
type
.
lock_mode
==
"checklock"
:
elif
obj
.
entry
.
type
.
lock_mode
==
"checklock"
:
return
False
return
False
return
True
return
True
...
@@ -7329,9 +7337,6 @@ class AttributeNode(ExprNode):
...
@@ -7329,9 +7337,6 @@ class AttributeNode(ExprNode):
elif
self
.
entry
and
self
.
entry
.
is_cmethod
:
elif
self
.
entry
and
self
.
entry
.
is_cmethod
:
# C method implemented as function call with utility code
# C method implemented as function call with utility code
code
.
globalstate
.
use_entry_utility_code
(
self
.
entry
)
code
.
globalstate
.
use_entry_utility_code
(
self
.
entry
)
if
self
.
needs_autolock
:
obj_code
=
self
.
obj
.
result_as
(
self
.
obj
.
type
)
code
.
putln
(
"Cy_WLOCK(%s);"
%
obj_code
)
def
generate_disposal_code
(
self
,
code
):
def
generate_disposal_code
(
self
,
code
):
if
self
.
is_temp
and
self
.
type
.
is_memoryviewslice
and
self
.
is_memslice_transpose
:
if
self
.
is_temp
and
self
.
type
.
is_memoryviewslice
and
self
.
is_memslice_transpose
:
...
@@ -7344,7 +7349,8 @@ class AttributeNode(ExprNode):
...
@@ -7344,7 +7349,8 @@ class AttributeNode(ExprNode):
ExprNode
.
generate_disposal_code
(
self
,
code
)
ExprNode
.
generate_disposal_code
(
self
,
code
)
def
generate_assignment_code
(
self
,
rhs
,
code
,
overloaded_assignment
=
False
,
def
generate_assignment_code
(
self
,
rhs
,
code
,
overloaded_assignment
=
False
,
exception_check
=
None
,
exception_value
=
None
):
exception_check
=
None
,
exception_value
=
None
,
needs_unlock
=
False
,
needs_rlock
=
False
,
needs_wlock
=
False
):
self
.
obj
.
generate_evaluation_code
(
code
)
self
.
obj
.
generate_evaluation_code
(
code
)
if
self
.
is_py_attr
:
if
self
.
is_py_attr
:
code
.
globalstate
.
use_utility_code
(
code
.
globalstate
.
use_utility_code
(
...
@@ -7378,15 +7384,19 @@ class AttributeNode(ExprNode):
...
@@ -7378,15 +7384,19 @@ class AttributeNode(ExprNode):
code
.
put_cygotref
(
select_code
)
code
.
put_cygotref
(
select_code
)
code
.
put_cyxdecref
(
select_code
)
code
.
put_cyxdecref
(
select_code
)
if
self
.
needs_autolock
:
if
needs_unlock
:
code
.
putln
(
"Cy_WLOCK(%s);"
%
self
.
obj
.
result
())
code
.
putln
(
"Cy_UNLOCK(%s);"
%
select_code
)
if
not
self
.
type
.
is_memoryviewslice
:
if
not
self
.
type
.
is_memoryviewslice
:
code
.
putln
(
code
.
putln
(
"%s = %s;"
%
(
"%s = %s;"
%
(
select_code
,
select_code
,
rhs
.
result_as
(
self
.
ctype
())))
rhs
.
result_as
(
self
.
ctype
())))
#rhs.result()))
#rhs.result()))
if
needs_wlock
:
code
.
putln
(
"Cy_WLOCK(%s);"
%
select_code
)
elif
needs_rlock
:
code
.
putln
(
"Cy_RLOCK(%s);"
%
select_code
)
rhs
.
generate_post_assignment_code
(
code
)
rhs
.
generate_post_assignment_code
(
code
)
rhs
.
free_temps
(
code
)
rhs
.
free_temps
(
code
)
self
.
obj
.
generate_disposal_code
(
code
)
self
.
obj
.
generate_disposal_code
(
code
)
...
...
Cython/Compiler/Nodes.py
View file @
1c1c8b9a
...
@@ -2186,8 +2186,8 @@ class FuncDefNode(StatNode, BlockNode):
...
@@ -2186,8 +2186,8 @@ class FuncDefNode(StatNode, BlockNode):
# NULL as a valid cypclass (with a typecast)
# NULL as a valid cypclass (with a typecast)
code
.
put_cyxdecref
(
entry
.
cname
)
code
.
put_cyxdecref
(
entry
.
cname
)
for
entry
in
lenv
.
autolocked_entri
es
:
for
node
in
lenv
.
autolocked_nod
es
:
code
.
putln
(
"Cy_UNLOCK(%s);"
%
entry
.
cname
)
code
.
putln
(
"Cy_UNLOCK(%s);"
%
node
.
result
()
)
# Decref any increfed args
# Decref any increfed args
for
entry
in
lenv
.
arg_entries
:
for
entry
in
lenv
.
arg_entries
:
...
@@ -5448,6 +5448,9 @@ class SingleAssignmentNode(AssignmentNode):
...
@@ -5448,6 +5448,9 @@ class SingleAssignmentNode(AssignmentNode):
first
=
False
first
=
False
is_overloaded_assignment
=
False
is_overloaded_assignment
=
False
declaration_only
=
False
declaration_only
=
False
needs_unlock
=
False
needs_rlock
=
False
needs_wlock
=
False
def
analyse_declarations
(
self
,
env
):
def
analyse_declarations
(
self
,
env
):
from
.
import
ExprNodes
from
.
import
ExprNodes
...
@@ -5544,6 +5547,16 @@ class SingleAssignmentNode(AssignmentNode):
...
@@ -5544,6 +5547,16 @@ class SingleAssignmentNode(AssignmentNode):
self
.
lhs
=
self
.
lhs
.
analyse_target_types
(
env
)
self
.
lhs
=
self
.
lhs
.
analyse_target_types
(
env
)
self
.
lhs
.
gil_assignment_check
(
env
)
self
.
lhs
.
gil_assignment_check
(
env
)
if
hasattr
(
self
.
lhs
,
'entry'
):
entry
=
self
.
lhs
.
entry
if
entry
.
type
.
is_cyp_class
and
entry
.
type
.
lock_mode
==
"autolock"
:
if
entry
.
locking_node
is
None
:
env
.
declare_autolocked
(
self
.
lhs
)
else
:
self
.
needs_unlock
=
True
self
.
lhs
.
entry
.
locking_node
=
self
self
.
lhs
.
entry
.
is_wlocked
=
False
self
.
lhs
.
entry
.
is_rlocked
=
False
self
.
rhs
.
check_rhs_locked
(
env
)
self
.
rhs
.
check_rhs_locked
(
env
)
self
.
lhs
.
check_lhs_locked
(
env
)
self
.
lhs
.
check_lhs_locked
(
env
)
unrolled_assignment
=
self
.
unroll_lhs
(
env
)
unrolled_assignment
=
self
.
unroll_lhs
(
env
)
...
@@ -5726,9 +5739,17 @@ class SingleAssignmentNode(AssignmentNode):
...
@@ -5726,9 +5739,17 @@ class SingleAssignmentNode(AssignmentNode):
code
,
code
,
overloaded_assignment
=
self
.
is_overloaded_assignment
,
overloaded_assignment
=
self
.
is_overloaded_assignment
,
exception_check
=
self
.
exception_check
,
exception_check
=
self
.
exception_check
,
exception_value
=
self
.
exception_value
)
exception_value
=
self
.
exception_value
,
needs_unlock
=
self
.
needs_unlock
,
needs_rlock
=
self
.
needs_rlock
,
needs_wlock
=
self
.
needs_wlock
)
else
:
else
:
self
.
lhs
.
generate_assignment_code
(
self
.
rhs
,
code
)
self
.
lhs
.
generate_assignment_code
(
self
.
rhs
,
code
,
needs_unlock
=
self
.
needs_unlock
,
needs_rlock
=
self
.
needs_rlock
,
needs_wlock
=
self
.
needs_wlock
)
def
generate_function_definitions
(
self
,
env
,
code
):
def
generate_function_definitions
(
self
,
env
,
code
):
self
.
rhs
.
generate_function_definitions
(
env
,
code
)
self
.
rhs
.
generate_function_definitions
(
env
,
code
)
...
...
Cython/Compiler/Symtab.py
View file @
1c1c8b9a
...
@@ -137,6 +137,7 @@ class Entry(object):
...
@@ -137,6 +137,7 @@ class Entry(object):
# is_cgetter boolean Is a c-level getter function
# is_cgetter boolean Is a c-level getter function
# is_wlocked boolean Is locked with a write lock (used for cypclass)
# is_wlocked boolean Is locked with a write lock (used for cypclass)
# is_rlocked boolean Is locked with a read lock (used for cypclass)
# is_rlocked boolean Is locked with a read lock (used for cypclass)
# locking_node Node The assignment node doing the locking
# TODO: utility_code and utility_code_definition serves the same purpose...
# TODO: utility_code and utility_code_definition serves the same purpose...
...
@@ -209,6 +210,7 @@ class Entry(object):
...
@@ -209,6 +210,7 @@ class Entry(object):
is_cgetter
=
False
is_cgetter
=
False
is_wlocked
=
False
is_wlocked
=
False
is_rlocked
=
False
is_rlocked
=
False
locking_node
=
None
def
__init__
(
self
,
name
,
cname
,
type
,
pos
=
None
,
init
=
None
):
def
__init__
(
self
,
name
,
cname
,
type
,
pos
=
None
,
init
=
None
):
self
.
name
=
name
self
.
name
=
name
...
@@ -292,7 +294,7 @@ class Scope(object):
...
@@ -292,7 +294,7 @@ class Scope(object):
# pyfunc_entries [Entry] Python function entries
# pyfunc_entries [Entry] Python function entries
# cfunc_entries [Entry] C function entries
# cfunc_entries [Entry] C function entries
# c_class_entries [Entry] All extension type entries
# c_class_entries [Entry] All extension type entries
# autolocked_
entries[Entry] All autolocked entri
es that needs unlocking
# autolocked_
nodes [ExprNodes] All autolocked nod
es that needs unlocking
# cname_to_entry {string : Entry} Temp cname to entry mapping
# cname_to_entry {string : Entry} Temp cname to entry mapping
# return_type PyrexType or None Return type of function owning scope
# return_type PyrexType or None Return type of function owning scope
# is_builtin_scope boolean Is the builtin scope of Python/Cython
# is_builtin_scope boolean Is the builtin scope of Python/Cython
...
@@ -352,7 +354,7 @@ class Scope(object):
...
@@ -352,7 +354,7 @@ class Scope(object):
self
.
cfunc_entries
=
[]
self
.
cfunc_entries
=
[]
self
.
c_class_entries
=
[]
self
.
c_class_entries
=
[]
self
.
defined_c_classes
=
[]
self
.
defined_c_classes
=
[]
self
.
autolocked_
entri
es
=
[]
self
.
autolocked_
nod
es
=
[]
self
.
imported_c_classes
=
{}
self
.
imported_c_classes
=
{}
self
.
cname_to_entry
=
{}
self
.
cname_to_entry
=
{}
self
.
identifier_to_entry
=
{}
self
.
identifier_to_entry
=
{}
...
@@ -1794,10 +1796,18 @@ class LocalScope(Scope):
...
@@ -1794,10 +1796,18 @@ class LocalScope(Scope):
if
type
.
is_pyobject
:
if
type
.
is_pyobject
:
entry
.
init
=
"0"
entry
.
init
=
"0"
entry
.
is_arg
=
1
entry
.
is_arg
=
1
if
type
.
is_cyp_class
and
type
.
lock_mode
==
"autolock"
:
entry
.
is_wlocked
=
True
#entry.borrowed = 1 # Not using borrowed arg refs for now
#entry.borrowed = 1 # Not using borrowed arg refs for now
self
.
arg_entries
.
append
(
entry
)
self
.
arg_entries
.
append
(
entry
)
return
entry
return
entry
def
declare_autolocked
(
self
,
node
):
# Add an entry for autolocked cypclass
if
not
(
node
.
type
.
is_cyp_class
and
node
.
type
.
lock_mode
==
"autolock"
):
error
(
pos
,
"Trying to autolock a non cypclass object !"
)
self
.
autolocked_nodes
.
append
(
node
)
def
declare_var
(
self
,
name
,
type
,
pos
,
def
declare_var
(
self
,
name
,
type
,
pos
,
cname
=
None
,
visibility
=
'private'
,
cname
=
None
,
visibility
=
'private'
,
api
=
0
,
in_pxd
=
0
,
is_cdef
=
0
):
api
=
0
,
in_pxd
=
0
,
is_cdef
=
0
):
...
...
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