From: Stefan Behnel Date: Thu, 27 Nov 2008 07:43:32 +0000 (+0100) Subject: clean up new-style temps after use (breaks code for now) X-Git-Tag: 0.11-beta~208 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=fcfaa4167bf01cf03a7006b17d9aca4622b8742e;p=cython.git clean up new-style temps after use (breaks code for now) --- diff --git a/Cython/Compiler/Code.py b/Cython/Compiler/Code.py index f83b800c..075c6719 100644 --- a/Cython/Compiler/Code.py +++ b/Cython/Compiler/Code.py @@ -137,6 +137,25 @@ class FunctionState(object): self.temps_free[type] = freelist freelist.append(name) + def temps_in_use(self): + """Return a list of (cname,type) tuples of temp names and their type + that are currently in use. + """ + used = [] + for name, type in self.temps_allocated: + freelist = self.temps_free.get(type) + if freelist is None or name not in freelist: + used.append((name, type)) + return used + + def py_temps_in_use(self): + """Return a list of (cname,type) tuples of temp names and their type + that are currently in use. This includes only Python object types. + """ + return [(name, type) + for name, type in self.temps_in_use() + if type.is_pyobject] + class GlobalState(object): # filename_table {string : int} for finding filename table indexes # filename_list [string] filenames in filename table order diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index a2efeed5..3c634861 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -1060,7 +1060,12 @@ class FuncDefNode(StatNode, BlockNode): if code.error_label in code.labels_used: code.put_goto(code.return_label) code.put_label(code.error_label) + # cleanup temps the old way code.put_var_xdecrefs(lenv.temp_entries) + # cleanup temps the new way + for cname, type in code.funcstate.temps_allocated: + if type.is_pyobject: + code.put_xdecref(cname, type) # Clean up buffers -- this calls a Python function # so need to save and restore error state @@ -3287,8 +3292,12 @@ class ReturnStatNode(StatNode): "%s = %s;" % ( Naming.retval_cname, self.return_type.default_value)) + # free temps the old way for entry in self.temps_in_use: code.put_var_decref_clear(entry) + # free temps the new way + for cname, type in code.funcstate.py_temps_in_use(): + code.put_decref_clear(cname, type) #code.putln( # "goto %s;" % # code.return_label) diff --git a/Cython/Compiler/UtilNodes.py b/Cython/Compiler/UtilNodes.py index 369634cb..ec3727a9 100644 --- a/Cython/Compiler/UtilNodes.py +++ b/Cython/Compiler/UtilNodes.py @@ -11,12 +11,17 @@ from ExprNodes import AtomicExprNode class TempHandle(object): temp = None + needs_xdecref = False def __init__(self, type): self.type = type + self.needs_cleanup = type.is_pyobject def ref(self, pos): return TempRefNode(pos, handle=self, type=self.type) + def cleanup_ref(self, pos): + return CleanupTempRefNode(pos, handle=self, type=self.type) + class TempRefNode(AtomicExprNode): # handle TempHandle @@ -40,10 +45,22 @@ class TempRefNode(AtomicExprNode): def generate_assignment_code(self, rhs, code): if self.type.is_pyobject: rhs.make_owned_reference(code) + # TODO: analyse control flow to see if this is necessary code.put_xdecref(self.result(), self.ctype()) code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype()))) rhs.generate_post_assignment_code(code) +class CleanupTempRefNode(TempRefNode): + # handle TempHandle + + def generate_assignment_code(self, rhs, code): + pass + + def generate_execution_code(self, code): + if self.type.is_pyobject: + code.put_decref_clear(self.result(), self.type) + self.handle.needs_cleanup = False + class TempsBlockNode(Node): """ Creates a block which allocates temporary variables. @@ -65,6 +82,11 @@ class TempsBlockNode(Node): handle.temp = code.funcstate.allocate_temp(handle.type) self.body.generate_execution_code(code) for handle in self.temps: + if handle.needs_cleanup: + if handle.needs_xdecref: + code.put_xdecref_clear(handle.temp, handle.type) + else: + code.put_decref_clear(handle.temp, handle.type) code.funcstate.release_temp(handle.temp) def analyse_control_flow(self, env):