Commit 137545fd authored by Stefan Behnel's avatar Stefan Behnel

handle simple swap assignments without ref-counting

parent 166ffcdb
...@@ -61,11 +61,13 @@ class ExprNode(Node): ...@@ -61,11 +61,13 @@ class ExprNode(Node):
# saved_subexpr_nodes # saved_subexpr_nodes
# [ExprNode or [ExprNode or None] or None] # [ExprNode or [ExprNode or None] or None]
# Cached result of subexpr_nodes() # Cached result of subexpr_nodes()
# use_managed_ref boolean use ref-counted temps/assignments/etc.
result_ctype = None result_ctype = None
type = None type = None
temp_code = None temp_code = None
old_temp = None # error checker for multiple frees etc. 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 # The Analyse Expressions phase for expressions is split
# into two sub-phases: # into two sub-phases:
...@@ -419,7 +421,7 @@ class ExprNode(Node): ...@@ -419,7 +421,7 @@ class ExprNode(Node):
if type.is_pyobject: if type.is_pyobject:
type = PyrexTypes.py_object_type type = PyrexTypes.py_object_type
self.temp_code = code.funcstate.allocate_temp( self.temp_code = code.funcstate.allocate_temp(
type, manage_ref=True) type, manage_ref=self.use_managed_ref)
else: else:
self.temp_code = None self.temp_code = None
...@@ -1346,14 +1348,15 @@ class NameNode(AtomicExprNode): ...@@ -1346,14 +1348,15 @@ class NameNode(AtomicExprNode):
self.generate_acquire_buffer(rhs, code) self.generate_acquire_buffer(rhs, code)
if self.type.is_pyobject: if self.type.is_pyobject:
rhs.make_owned_reference(code)
#print "NameNode.generate_assignment_code: to", self.name ### #print "NameNode.generate_assignment_code: to", self.name ###
#print "...from", rhs ### #print "...from", rhs ###
#print "...LHS type", self.type, "ctype", self.ctype() ### #print "...LHS type", self.type, "ctype", self.ctype() ###
#print "...RHS type", rhs.type, "ctype", rhs.ctype() ### #print "...RHS type", rhs.type, "ctype", rhs.ctype() ###
if self.use_managed_ref:
rhs.make_owned_reference(code)
if entry.is_cglobal: if entry.is_cglobal:
code.put_gotref(self.py_result()) code.put_gotref(self.py_result())
if not self.lhs_of_first_assignment: if self.use_managed_ref and not self.lhs_of_first_assignment:
if entry.is_local and not Options.init_local_none: if entry.is_local and not Options.init_local_none:
initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos) initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
if initalized is True: if initalized is True:
...@@ -1362,6 +1365,7 @@ class NameNode(AtomicExprNode): ...@@ -1362,6 +1365,7 @@ class NameNode(AtomicExprNode):
code.put_xdecref(self.result(), self.ctype()) code.put_xdecref(self.result(), self.ctype())
else: else:
code.put_decref(self.result(), self.ctype()) code.put_decref(self.result(), self.ctype())
if self.use_managed_ref:
if entry.is_cglobal: if entry.is_cglobal:
code.put_giveref(rhs.py_result()) code.put_giveref(rhs.py_result())
code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype()))) code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
...@@ -5784,7 +5788,7 @@ class CoerceToTempNode(CoercionNode): ...@@ -5784,7 +5788,7 @@ class CoerceToTempNode(CoercionNode):
# by generic generate_subexpr_evaluation_code! # by generic generate_subexpr_evaluation_code!
code.putln("%s = %s;" % ( code.putln("%s = %s;" % (
self.result(), self.arg.result_as(self.ctype()))) 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()) code.put_incref(self.result(), self.ctype())
......
...@@ -20,6 +20,11 @@ try: ...@@ -20,6 +20,11 @@ try:
except NameError: except NameError:
from functools import reduce from functools import reduce
try:
set
except NameError:
from sets import Set as set
def unwrap_node(node): def unwrap_node(node):
while isinstance(node, UtilNodes.ResultRefNode): while isinstance(node, UtilNodes.ResultRefNode):
node = node.expression node = node.expression
...@@ -517,6 +522,46 @@ class FlattenInListTransform(Visitor.VisitorTransform, SkipDeclarations): ...@@ -517,6 +522,46 @@ class FlattenInListTransform(Visitor.VisitorTransform, SkipDeclarations):
visit_Node = Visitor.VisitorTransform.recurse_to_children 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): class OptimizeBuiltinCalls(Visitor.VisitorTransform):
"""Optimize some common methods calls and instantiation patterns """Optimize some common methods calls and instantiation patterns
for builtin types. for builtin types.
......
__doc__ = u"""
>>> swap(1,2)
(2, 1)
"""
def swap(a,b):
a,b = b,a
return a,b
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