Commit f1f41e51 authored by Xavier Thompson's avatar Xavier Thompson

Fix automatic lock acquisition for inplace assignments

parent 097b08db
...@@ -438,6 +438,13 @@ class CypclassLockTransform(Visitor.EnvTransform): ...@@ -438,6 +438,13 @@ class CypclassLockTransform(Visitor.EnvTransform):
return obj.entry return obj.entry
return None return None
def is_locked(self, obj):
try:
lock = self.locked[self.id(obj)]
return True
except:
return False
def lock(self, obj, exclusive=True): def lock(self, obj, exclusive=True):
try: try:
lock = self.locked[self.id(obj)] lock = self.locked[self.id(obj)]
...@@ -511,16 +518,18 @@ class CypclassLockTransform(Visitor.EnvTransform): ...@@ -511,16 +518,18 @@ class CypclassLockTransform(Visitor.EnvTransform):
autolocks = self.autolocks autolocks = self.autolocks
node = self.visit(node) node = self.visit(node)
if self.autolocks > autolocks: if self.autolocks > autolocks:
self.autolocks = autolocks
return node.coerce_to_temp(self.current_env()) return node.coerce_to_temp(self.current_env())
return node return node
def visit_assignment(self, node): def visit_assignment(self, node, rhs_attr='rhs'):
autowlocks = self.autowlocks autowlocks = self.autowlocks
self.visitchildren(node, exclude=['rhs']) self.visitchildren(node, exclude=[rhs_attr])
if self.autowlocks > autowlocks: if self.autowlocks > autowlocks:
node.rhs = self.visit_value(node.rhs) self.autowlocks = autowlocks
setattr(node, rhs_attr, self.visit_value(getattr(node, rhs_attr)))
else: else:
node.rhs = self.visit(node.rhs) setattr(node, rhs_attr, self.visit(getattr(node, rhs_attr)))
def visit_SingleAssignmentNode(self, node): def visit_SingleAssignmentNode(self, node):
lhs = node.lhs lhs = node.lhs
...@@ -544,6 +553,23 @@ class CypclassLockTransform(Visitor.EnvTransform): ...@@ -544,6 +553,23 @@ class CypclassLockTransform(Visitor.EnvTransform):
self.visit_assignment(node) self.visit_assignment(node)
return node return node
def visit_BinopNode(self, node):
if node.inplace:
if not node.operator.endswith('='):
# operand1 will already be evaluated as lhs of assignment node.
operand1 = node.operand1
if operand1.is_attribute and operand1.obj.type.is_cyp_class and not self.is_locked(operand1.obj):
node.operand2 = self.visit_value(node.operand2)
else:
self.visitchildren(node, exclude=["operand1"])
else:
old, node.operand1.is_target = node.operand1.is_target, True
self.visit_assignment(node, rhs_attr="operand2")
node.operand1.is_target = old
else:
self.visitchildren(node)
return node
def visit_DelStatNode(self, node): def visit_DelStatNode(self, node):
for arg in node.args: for arg in node.args:
arg_entry = self.id(arg) arg_entry = self.id(arg)
......
...@@ -11530,7 +11530,7 @@ class BinopNode(ExprNode): ...@@ -11530,7 +11530,7 @@ class BinopNode(ExprNode):
# - Determine result type and result code fragment. # - Determine result type and result code fragment.
# - Allocate temporary for result if needed. # - Allocate temporary for result if needed.
subexprs = ['operand1', 'operand2'] subexprs = ['operand2', 'operand1']
inplace = False inplace = False
op_func_type = None op_func_type = None
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment