clean up new-style temps after use (breaks code for now)
authorStefan Behnel <scoder@users.berlios.de>
Thu, 27 Nov 2008 07:43:32 +0000 (08:43 +0100)
committerStefan Behnel <scoder@users.berlios.de>
Thu, 27 Nov 2008 07:43:32 +0000 (08:43 +0100)
Cython/Compiler/Code.py
Cython/Compiler/Nodes.py
Cython/Compiler/UtilNodes.py

index f83b800ce4635d92a4821ddb3dbe5f965b0c4461..075c6719c8458b614406bf69c953bd7307d4ea57 100644 (file)
@@ -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
index a2efeed51fb28ed76b450db75b99a2a91e9c632b..3c6348619b27a75063747a801c5ad2c1f31f5b6e 100644 (file)
@@ -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)
index 369634cb3e92c6f0802e4415a8ebf198917bae3d..ec3727a93a97d0d06f88f83f1aa059962dc5ffba 100644 (file)
@@ -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):