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
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
cython
Commits
7ce3caa5
Commit
7ce3caa5
authored
May 29, 2019
by
gsamain
Committed by
Xavier Thompson
Aug 17, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
first batch for locking on assignment
parent
ebc09d17
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 @
7ce3caa5
...
...
@@ -884,7 +884,8 @@ class ExprNode(Node):
self
.
generate_subexpr_disposal_code
(
code
)
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
# the LHS of an assignment. An error will have
# been reported earlier.
...
...
@@ -2364,7 +2365,8 @@ class NameNode(AtomicExprNode):
code
.
put_error_if_unbound
(
self
.
pos
,
entry
,
self
.
in_nogil_context
)
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 ###
entry
=
self
.
entry
if
entry
is
None
:
...
...
@@ -2454,6 +2456,8 @@ class NameNode(AtomicExprNode):
code
.
put_cyxdecref
(
self
.
result
())
if
not
self
.
type
.
is_memoryviewslice
:
if
not
assigned
:
if
needs_unlock
:
code
.
putln
(
"Cy_UNLOCK(%s);"
%
self
.
result
())
if
overloaded_assignment
:
result
=
rhs
.
move_result_rhs
()
if
exception_check
==
'+'
:
...
...
@@ -2471,6 +2475,10 @@ class NameNode(AtomicExprNode):
code
.
putln
(
'new (&%s) decltype(%s){%s};'
%
(
self
.
result
(),
self
.
result
(),
result
))
elif
result
!=
self
.
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
:
print
(
"NameNode.generate_assignment_code:"
)
print
(
"...generating post-assignment code for %s"
%
rhs
)
...
...
@@ -6201,6 +6209,9 @@ class SimpleCallNode(CallNode):
exc_checks
.
append
(
"__Pyx_ErrOccurredWithGIL()"
)
else
:
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
:
rhs
=
self
.
c_call_code
()
if
self
.
result
():
...
...
@@ -6984,7 +6995,6 @@ class AttributeNode(ExprNode):
is_memslice_transpose
=
False
is_special_lookup
=
False
is_py_attr
=
0
needs_autolock
=
False
def
as_cython_attribute
(
self
):
if
(
isinstance
(
self
.
obj
,
NameNode
)
and
...
...
@@ -7360,9 +7370,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
)
\
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"
:
print
"
We will
autolock here"
self
.
needs_autolock
=
True
self
.
obj
.
entry
.
is_wlocked
=
True
print
"
Request read lock
autolock here"
self
.
obj
.
entry
.
is_rlocked
=
True
self
.
obj
.
entry
.
locking_node
.
needs_rlock
=
True
elif
obj
.
entry
.
type
.
lock_mode
==
"checklock"
:
return
False
return
True
...
...
@@ -7371,12 +7381,10 @@ class AttributeNode(ExprNode):
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
obj
.
entry
.
type
.
lock_mode
==
"autolock"
:
print
"
We will
autolock here"
print
"
Request write lock
autolock here"
self
.
needs_autolock
=
True
self
.
obj
.
entry
.
is_wlocked
=
True
# FIXME: this needs to be obj.result(), because maybe we have to lock
# an intermediate object (obj.att.__autolocked_obj__.attribute)
env
.
autolocked_entries
.
append
(
self
.
obj
.
entry
)
self
.
obj
.
entry
.
locking_node
.
needs_wlock
=
True
elif
obj
.
entry
.
type
.
lock_mode
==
"checklock"
:
return
False
return
True
...
...
@@ -7487,9 +7495,6 @@ class AttributeNode(ExprNode):
elif
self
.
entry
and
self
.
entry
.
is_cmethod
:
# C method implemented as function call with utility code
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
):
if
self
.
is_temp
and
self
.
type
.
is_memoryviewslice
and
self
.
is_memslice_transpose
:
...
...
@@ -7499,7 +7504,8 @@ class AttributeNode(ExprNode):
ExprNode
.
generate_disposal_code
(
self
,
code
)
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
)
if
self
.
is_py_attr
:
code
.
globalstate
.
use_utility_code
(
...
...
@@ -7535,15 +7541,19 @@ class AttributeNode(ExprNode):
code
.
put_cygotref
(
select_code
)
code
.
put_cyxdecref
(
select_code
)
if
self
.
needs_autolock
:
code
.
putln
(
"Cy_WLOCK(%s);"
%
self
.
obj
.
result
())
if
needs_unlock
:
code
.
putln
(
"Cy_UNLOCK(%s);"
%
select_code
)
if
not
self
.
type
.
is_memoryviewslice
:
code
.
putln
(
"%s = %s;"
%
(
select_code
,
rhs
.
move_result_rhs_as
(
self
.
ctype
())))
#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
.
free_temps
(
code
)
self
.
obj
.
generate_disposal_code
(
code
)
...
...
Cython/Compiler/Nodes.py
View file @
7ce3caa5
...
...
@@ -2240,8 +2240,8 @@ class FuncDefNode(StatNode, BlockNode):
# FIXME ideally use entry.xdecref_cleanup but this currently isn't reliable
code
.
put_var_xdecref
(
entry
,
have_gil
=
gil_owned
[
'success'
])
for
entry
in
lenv
.
autolocked_entri
es
:
code
.
putln
(
"Cy_UNLOCK(%s);"
%
entry
.
cname
)
for
node
in
lenv
.
autolocked_nod
es
:
code
.
putln
(
"Cy_UNLOCK(%s);"
%
node
.
result
()
)
# Decref any increfed args
for
entry
in
lenv
.
arg_entries
:
...
...
@@ -5694,6 +5694,9 @@ class SingleAssignmentNode(AssignmentNode):
first
=
False
is_overloaded_assignment
=
False
declaration_only
=
False
needs_unlock
=
False
needs_rlock
=
False
needs_wlock
=
False
def
analyse_declarations
(
self
,
env
):
from
.
import
ExprNodes
...
...
@@ -5790,6 +5793,16 @@ class SingleAssignmentNode(AssignmentNode):
self
.
lhs
=
self
.
lhs
.
analyse_target_types
(
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
.
lhs
.
check_lhs_locked
(
env
)
unrolled_assignment
=
self
.
unroll_lhs
(
env
)
...
...
@@ -5972,9 +5985,17 @@ class SingleAssignmentNode(AssignmentNode):
code
,
overloaded_assignment
=
self
.
is_overloaded_assignment
,
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
:
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
):
self
.
rhs
.
generate_function_definitions
(
env
,
code
)
...
...
Cython/Compiler/Symtab.py
View file @
7ce3caa5
...
...
@@ -160,6 +160,7 @@ class Entry(object):
# is_cgetter boolean Is a c-level getter function
# is_wlocked boolean Is locked with a write 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...
...
...
@@ -233,6 +234,7 @@ class Entry(object):
is_cgetter
=
False
is_wlocked
=
False
is_rlocked
=
False
locking_node
=
None
def
__init__
(
self
,
name
,
cname
,
type
,
pos
=
None
,
init
=
None
):
self
.
name
=
name
...
...
@@ -320,7 +322,7 @@ class Scope(object):
# pyfunc_entries [Entry] Python function entries
# cfunc_entries [Entry] C function 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
# return_type PyrexType or None Return type of function owning scope
# is_builtin_scope boolean Is the builtin scope of Python/Cython
...
...
@@ -380,7 +382,7 @@ class Scope(object):
self
.
cfunc_entries
=
[]
self
.
c_class_entries
=
[]
self
.
defined_c_classes
=
[]
self
.
autolocked_
entri
es
=
[]
self
.
autolocked_
nod
es
=
[]
self
.
imported_c_classes
=
{}
self
.
cname_to_entry
=
{}
self
.
identifier_to_entry
=
{}
...
...
@@ -1877,10 +1879,18 @@ class LocalScope(Scope):
if
type
.
is_pyobject
:
entry
.
init
=
"0"
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
self
.
arg_entries
.
append
(
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
,
cname
=
None
,
visibility
=
'private'
,
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