# saved_subexpr_nodes
# [ExprNode or [ExprNode or None] or None]
# Cached result of subexpr_nodes()
+ # use_managed_ref boolean use ref-counted temps/assignments/etc.
result_ctype = None
type = None
temp_code = None
old_temp = None # error checker for multiple frees etc.
+ use_managed_ref = True # can be set by optimisation transforms
# The Analyse Expressions phase for expressions is split
# into two sub-phases:
if type.is_pyobject:
type = PyrexTypes.py_object_type
self.temp_code = code.funcstate.allocate_temp(
- type, manage_ref=True)
+ type, manage_ref=self.use_managed_ref)
else:
self.temp_code = None
self.generate_acquire_buffer(rhs, code)
if self.type.is_pyobject:
- rhs.make_owned_reference(code)
#print "NameNode.generate_assignment_code: to", self.name ###
#print "...from", rhs ###
#print "...LHS type", self.type, "ctype", self.ctype() ###
#print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
- if entry.is_cglobal:
- code.put_gotref(self.py_result())
- if not self.lhs_of_first_assignment:
+ if self.use_managed_ref:
+ rhs.make_owned_reference(code)
+ if entry.is_cglobal:
+ code.put_gotref(self.py_result())
+ if self.use_managed_ref and not self.lhs_of_first_assignment:
if entry.is_local and not Options.init_local_none:
initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
if initalized is True:
code.put_xdecref(self.result(), self.ctype())
else:
code.put_decref(self.result(), self.ctype())
- if entry.is_cglobal:
- code.put_giveref(rhs.py_result())
+ if self.use_managed_ref:
+ if entry.is_cglobal:
+ code.put_giveref(rhs.py_result())
code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
if debug_disposal_code:
print("NameNode.generate_assignment_code:")
# by generic generate_subexpr_evaluation_code!
code.putln("%s = %s;" % (
self.result(), self.arg.result_as(self.ctype())))
- if self.type.is_pyobject:
+ if self.type.is_pyobject and self.use_managed_ref:
code.put_incref(self.result(), self.ctype())
except NameError:
from functools import reduce
+try:
+ set
+except NameError:
+ from sets import Set as set
+
def unwrap_node(node):
while isinstance(node, UtilNodes.ResultRefNode):
node = node.expression
visit_Node = Visitor.VisitorTransform.recurse_to_children
+class DropRefcountingTransform(Visitor.VisitorTransform):
+ """Drop ref-counting in safe places.
+ """
+ visit_Node = Visitor.VisitorTransform.recurse_to_children
+
+ def visit_ParallelAssignmentNode(self, node):
+ left, right, temps = [], [], []
+ for stat in node.stats:
+ if isinstance(stat, Nodes.SingleAssignmentNode):
+ lhs = unwrap_node(stat.lhs)
+ if not isinstance(lhs, ExprNodes.NameNode):
+ return node
+ left.append(lhs)
+ rhs = unwrap_node(stat.rhs)
+ if isinstance(rhs, ExprNodes.CoerceToTempNode):
+ temps.append(rhs)
+ rhs = rhs.arg
+ if not isinstance(rhs, ExprNodes.NameNode):
+ return node
+ right.append(rhs)
+ else:
+ return node
+
+ for name_node in left + right:
+ if name_node.entry.is_builtin or name_node.entry.is_pyglobal:
+ return node
+
+ left_names = [n.name for n in left]
+ right_names = [n.name for n in right]
+ if set(left_names) != set(right_names):
+ return node
+ if len(set(left_names)) != len(right):
+ return node
+
+ for name_node in left + right + temps:
+ name_node.use_managed_ref = False
+
+ return node
+
+
class OptimizeBuiltinCalls(Visitor.VisitorTransform):
"""Optimize some common methods calls and instantiation patterns
for builtin types.