Commit ad29a1e1 authored by gsamain's avatar gsamain

cypclass lock check/autotake refacto (ensure_[rl]hs_locked)

parent efdf3160
...@@ -691,39 +691,52 @@ class ExprNode(Node): ...@@ -691,39 +691,52 @@ class ExprNode(Node):
def addr_not_const(self): def addr_not_const(self):
error(self.pos, "Address is not constant") error(self.pos, "Address is not constant")
def set_autorlock(self, env):
self.entry.is_rlocked = True
self.entry.needs_rlock = True
def set_autowlock(self, env):
print "Setting wlock"
self.entry.is_wlocked = True
self.entry.needs_wlock = True
def is_autolock(self, env):
return self.type.is_cyp_class and self.type.lock_mode == "autolock"
def is_checklock(self, env):
return self.type.is_cyp_class and self.type.lock_mode == "checklock"
def is_rhs_locked(self, env): def is_rhs_locked(self, env):
if hasattr(self, 'entry') and self.entry.type.is_cyp_class and self.entry.is_variable\ return not(hasattr(self, 'entry') and self.entry.type.is_cyp_class and not (self.entry.is_rlocked or self.entry.is_wlocked))
and not (self.entry.is_rlocked or self.entry.is_wlocked):
if self.entry.type.lock_mode == "autolock":
print "Request read lock autolock here", self.entry.name
self.entry.is_rlocked = True
self.entry.needs_rlock = True
elif self.entry.type.lock_mode == "checklock":
return False
return True
def is_lhs_locked(self, env): def is_lhs_locked(self, env):
if hasattr(self, 'entry') and self.entry.type.is_cyp_class and self.entry.is_variable\ return not(hasattr(self, 'entry') and self.entry.type.is_cyp_class and not self.entry.is_wlocked)
and not self.entry.is_wlocked:
if self.entry.type.lock_mode == "autolock":
print "Request write lock autolock here", self.entry.name
self.entry.is_wlocked = True
self.entry.needs_wlock = True
elif self.entry.type.lock_mode == "checklock":
return False
return True
def check_rhs_locked(self, env): def ensure_subexpr_rhs_locked(self, env):
for node in self.subexpr_nodes(): for node in self.subexpr_nodes():
node.check_rhs_locked(env) node.ensure_rhs_locked(env)
if not self.is_rhs_locked(env):
error(self.pos, "This rhs is not correctly locked (write lock for non-const methods, read lock is sufficient for everything else)")
def check_lhs_locked(self, env): def ensure_subexpr_lhs_locked(self, env):
for node in self.subexpr_nodes(): for node in self.subexpr_nodes():
node.check_lhs_locked(env) node.ensure_lhs_locked(env)
if not self.is_lhs_locked(env):
error(self.pos, "This lhs is not correctly locked (write lock needed)") def ensure_rhs_locked(self, env, is_dereferenced = False):
self.ensure_subexpr_rhs_locked(env)
if is_dereferenced:
if not self.is_rhs_locked(env):
if self.is_checklock(env):
error(self.pos, "This expression is not correctly locked (read lock needed)")
elif self.is_autolock(env):
self.set_autorlock(env)
def ensure_lhs_locked(self, env, is_dereferenced = False):
self.ensure_subexpr_lhs_locked(env)
if is_dereferenced:
if not self.is_lhs_locked(env):
if self.is_checklock(env):
error(self.pos, "This expression is not correctly locked (write lock needed)")
elif self.is_autolock(env):
self.set_autowlock(env)
# ----------------- Result Allocation ----------------- # ----------------- Result Allocation -----------------
...@@ -5614,6 +5627,8 @@ class SimpleCallNode(CallNode): ...@@ -5614,6 +5627,8 @@ class SimpleCallNode(CallNode):
analysed = False analysed = False
overflowcheck = False overflowcheck = False
explicit_cpp_self = None explicit_cpp_self = None
rlocked = False
wlocked = False
def compile_time_value(self, denv): def compile_time_value(self, denv):
function = self.function.compile_time_value(denv) function = self.function.compile_time_value(denv)
...@@ -5813,9 +5828,9 @@ class SimpleCallNode(CallNode): ...@@ -5813,9 +5828,9 @@ class SimpleCallNode(CallNode):
formal_arg = func_type.args[i] formal_arg = func_type.args[i]
actual_arg = args[i] actual_arg = args[i]
if formal_arg.type.is_const: if formal_arg.type.is_const:
actual_arg.check_rhs_locked(env) actual_arg.ensure_rhs_locked(env, is_dereferenced = True)
else: else:
actual_arg.check_lhs_locked(env) actual_arg.ensure_lhs_locked(env, is_dereferenced = True)
# Coerce arguments # Coerce arguments
some_args_in_temps = False some_args_in_temps = False
for i in range(min(max_nargs, actual_nargs)): for i in range(min(max_nargs, actual_nargs)):
...@@ -5938,10 +5953,17 @@ class SimpleCallNode(CallNode): ...@@ -5938,10 +5953,17 @@ class SimpleCallNode(CallNode):
self.overflowcheck = env.directives['overflowcheck'] self.overflowcheck = env.directives['overflowcheck']
def check_rhs_locked(self, env): def is_lhs_locked(self, env):
self.function.check_rhs_locked(env) return self.wlocked
#if not self.is_rhs_locked(env):
# error(self.pos, "RHS lock needed") def is_rhs_locked(self, env):
return self.rlocked
def set_autorlock(self, env):
self.rlocked = True
def set_autowlock(self, env):
self.wlocked = True
def calculate_result_code(self): def calculate_result_code(self):
return self.c_call_code() return self.c_call_code()
...@@ -7231,16 +7253,14 @@ class AttributeNode(ExprNode): ...@@ -7231,16 +7253,14 @@ class AttributeNode(ExprNode):
gil_message = "Accessing Python attribute" gil_message = "Accessing Python attribute"
def is_rhs_locked(self, env): def ensure_subexpr_rhs_locked(self, env):
obj = self.obj
# The subexpr mechanism will here issue check_rhs_lock on self.obj
# BUT if we are calling a non-const method, the object can be modified.
# So here we're calling directly check_lhs_lock if this is needed.
if self.entry.is_cfunction and not self.entry.type.is_const_method: if self.entry.is_cfunction and not self.entry.type.is_const_method:
self.obj.check_lhs_locked(env) self.obj.ensure_lhs_locked(env, is_dereferenced = True)
else:
self.obj.ensure_rhs_locked(env, is_dereferenced = True)
return ExprNode.is_rhs_locked(self, env) def ensure_subexpr_lhs_locked(self, env):
self.obj.ensure_lhs_locked(env, is_dereferenced = True)
def is_cimported_module_without_shadow(self, env): def is_cimported_module_without_shadow(self, env):
return self.obj.is_cimported_module_without_shadow(env) return self.obj.is_cimported_module_without_shadow(env)
...@@ -12726,11 +12746,11 @@ class PrimaryCmpNode(ExprNode, CmpNode): ...@@ -12726,11 +12746,11 @@ class PrimaryCmpNode(ExprNode, CmpNode):
operand1 = self.operand1.compile_time_value(denv) operand1 = self.operand1.compile_time_value(denv)
return self.cascaded_compile_time_value(operand1, denv) return self.cascaded_compile_time_value(operand1, denv)
def check_rhs_locked(self, env): #def check_rhs_locked(self, env):
self.operand1.check_rhs_locked(env) # self.operand1.check_rhs_locked(env)
self.operand2.check_rhs_locked(env) # self.operand2.check_rhs_locked(env)
if self.cascade: # if self.cascade:
self.cascade.check_rhs_locked(env) # self.cascade.check_rhs_locked(env)
def analyse_types(self, env): def analyse_types(self, env):
self.operand1 = self.operand1.analyse_types(env) self.operand1 = self.operand1.analyse_types(env)
...@@ -12998,10 +13018,10 @@ class CascadedCmpNode(Node, CmpNode): ...@@ -12998,10 +13018,10 @@ class CascadedCmpNode(Node, CmpNode):
return self.constant_result is not constant_value_not_set and \ return self.constant_result is not constant_value_not_set and \
self.constant_result is not not_a_constant self.constant_result is not not_a_constant
def check_rhs_locked(self, env): #def check_rhs_locked(self, env):
self.operand2.check_rhs_locked(env) # self.operand2.check_rhs_locked(env)
if self.cascade: # if self.cascade:
self.cascade.check_rhs_locked(env) # self.cascade.check_rhs_locked(env)
def analyse_types(self, env): def analyse_types(self, env):
self.operand2 = self.operand2.analyse_types(env) self.operand2 = self.operand2.analyse_types(env)
......
...@@ -5379,7 +5379,7 @@ class ExprStatNode(StatNode): ...@@ -5379,7 +5379,7 @@ class ExprStatNode(StatNode):
def analyse_expressions(self, env): def analyse_expressions(self, env):
self.expr.result_is_used = False # hint that .result() may safely be left empty self.expr.result_is_used = False # hint that .result() may safely be left empty
self.expr = self.expr.analyse_expressions(env) self.expr = self.expr.analyse_expressions(env)
self.expr.check_rhs_locked(env) self.expr.ensure_rhs_locked(env)
# Repeat in case of node replacement. # Repeat in case of node replacement.
self.expr.result_is_used = False # hint that .result() may safely be left empty self.expr.result_is_used = False # hint that .result() may safely be left empty
return self return self
...@@ -5555,12 +5555,8 @@ class SingleAssignmentNode(AssignmentNode): ...@@ -5555,12 +5555,8 @@ class SingleAssignmentNode(AssignmentNode):
if entry.type.is_cyp_class and entry.type.lock_mode == "autolock"\ if entry.type.is_cyp_class and entry.type.lock_mode == "autolock"\
and not (entry.needs_rlock or entry.needs_wlock): and not (entry.needs_rlock or entry.needs_wlock):
env.declare_autolocked(self.lhs) env.declare_autolocked(self.lhs)
#self.lhs.entry.is_wlocked = False self.rhs.ensure_rhs_locked(env)
#self.lhs.entry.is_rlocked = False self.lhs.ensure_lhs_locked(env)
if self.rhs.is_attribute:
self.rhs.obj.check_rhs_locked(env)
if self.lhs.is_attribute:
self.lhs.obj.check_lhs_locked(env)
unrolled_assignment = self.unroll_lhs(env) unrolled_assignment = self.unroll_lhs(env)
if unrolled_assignment: if unrolled_assignment:
return unrolled_assignment return unrolled_assignment
...@@ -5784,11 +5780,11 @@ class CascadedAssignmentNode(AssignmentNode): ...@@ -5784,11 +5780,11 @@ class CascadedAssignmentNode(AssignmentNode):
for i, lhs in enumerate(self.lhs_list): for i, lhs in enumerate(self.lhs_list):
lhs = self.lhs_list[i] = lhs.analyse_target_types(env) lhs = self.lhs_list[i] = lhs.analyse_target_types(env)
lhs.gil_assignment_check(env) lhs.gil_assignment_check(env)
lhs.check_lhs_locked(env) lhs.ensure_lhs_locked(env)
lhs_types.add(lhs.type) lhs_types.add(lhs.type)
rhs = self.rhs.analyse_types(env) rhs = self.rhs.analyse_types(env)
rhs.check_rhs_locked(env) rhs.ensure_rhs_locked(env)
# common special case: only one type needed on the LHS => coerce only once # common special case: only one type needed on the LHS => coerce only once
if len(lhs_types) == 1: if len(lhs_types) == 1:
# Avoid coercion for overloaded assignment operators. # Avoid coercion for overloaded assignment operators.
......
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