Commit 36056016 authored by Stefan Behnel's avatar Stefan Behnel

optimise away redundant ref-counting of unused yield result values

parent bcf5763f
...@@ -77,12 +77,15 @@ class ExprNode(Node): ...@@ -77,12 +77,15 @@ class ExprNode(Node):
# [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. # use_managed_ref boolean use ref-counted temps/assignments/etc.
# result_is_used boolean indicates that the result will be dropped and the
# result_code/temp_result can safely be set to None
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 use_managed_ref = True # can be set by optimisation transforms
result_is_used = True
# The Analyse Expressions phase for expressions is split # The Analyse Expressions phase for expressions is split
# into two sub-phases: # into two sub-phases:
...@@ -447,6 +450,9 @@ class ExprNode(Node): ...@@ -447,6 +450,9 @@ class ExprNode(Node):
def release_temp_result(self, code): def release_temp_result(self, code):
if not self.temp_code: if not self.temp_code:
if not self.result_is_used:
# not used anyway, so ignore if not set up
return
if self.old_temp: if self.old_temp:
raise RuntimeError("temp %s released multiple times in %s" % ( raise RuntimeError("temp %s released multiple times in %s" % (
self.old_temp, self.__class__.__name__)) self.old_temp, self.__class__.__name__))
...@@ -492,7 +498,7 @@ class ExprNode(Node): ...@@ -492,7 +498,7 @@ class ExprNode(Node):
def generate_disposal_code(self, code): def generate_disposal_code(self, code):
if self.is_temp: if self.is_temp:
if self.type.is_pyobject: if self.type.is_pyobject and self.result():
code.put_decref_clear(self.result(), self.ctype()) code.put_decref_clear(self.result(), self.ctype())
else: else:
# Already done if self.is_temp # Already done if self.is_temp
...@@ -5018,11 +5024,14 @@ class YieldExprNode(ExprNode): ...@@ -5018,11 +5024,14 @@ class YieldExprNode(ExprNode):
code.putln('%s = %s->%s;' % (cname, Naming.cur_scope_cname, save_cname)) code.putln('%s = %s->%s;' % (cname, Naming.cur_scope_cname, save_cname))
if type.is_pyobject: if type.is_pyobject:
code.putln('%s->%s = 0;' % (Naming.cur_scope_cname, save_cname)) code.putln('%s->%s = 0;' % (Naming.cur_scope_cname, save_cname))
if self.result_is_used:
self.allocate_temp_result(code) self.allocate_temp_result(code)
code.putln('%s = %s; %s' % code.putln('%s = %s; %s' %
(self.result(), Naming.sent_value_cname, (self.result(), Naming.sent_value_cname,
code.error_goto_if_null(self.result(), self.pos))) code.error_goto_if_null(self.result(), self.pos)))
code.put_incref(self.result(), py_object_type) code.put_incref(self.result(), py_object_type)
else:
code.putln(code.error_goto_if_null(Naming.sent_value_cname, self.pos))
class StopIterationNode(Node): class StopIterationNode(Node):
# XXX: is it okay? # XXX: is it okay?
......
...@@ -3450,6 +3450,7 @@ class ExprStatNode(StatNode): ...@@ -3450,6 +3450,7 @@ class ExprStatNode(StatNode):
self.__class__ = PassStatNode self.__class__ = PassStatNode
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.analyse_expressions(env) self.expr.analyse_expressions(env)
def generate_execution_code(self, code): def generate_execution_code(self, code):
......
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