Introduced manage_ref parameter in funcstate.allocate_temp and used it to fix crash...
authorDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Thu, 27 Nov 2008 11:01:35 +0000 (12:01 +0100)
committerDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Thu, 27 Nov 2008 11:01:35 +0000 (12:01 +0100)
Cython/Compiler/Buffer.py
Cython/Compiler/Code.py
Cython/Compiler/Nodes.py
Cython/Compiler/UtilNodes.py

index 9134f825b9e0536d1a02621827acb4f20631e561..7ce7046842d3091d9ae8ed66bcb4a927f17becbf 100644 (file)
@@ -298,7 +298,7 @@ def put_assign_to_buffer(lhs_cname, rhs_cname, buffer_aux, buffer_type,
         # before raising the exception. A failure of reacquisition
         # will cause the reacquisition exception to be reported, one
         # can consider working around this later.
-        type, value, tb = [code.funcstate.allocate_temp(PyrexTypes.py_object_type)
+        type, value, tb = [code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=False)
                            for i in range(3)]
         code.putln('PyErr_Fetch(&%s, &%s, &%s);' % (type, value, tb))
         code.putln('if (%s) {' % code.unlikely("%s == -1" % (getbuffer % lhs_cname)))
index 075c6719c8458b614406bf69c953bd7307d4ea57..3841e608956ae55373252c962d4a56cecd6cada9 100644 (file)
@@ -40,7 +40,7 @@ class FunctionState(object):
         self.in_try_finally = 0
         self.exc_vars = None
 
-        self.temps_allocated = [] # of (name, type)
+        self.temps_allocated = [] # of (name, type, manage_ref)
         self.temps_free = {} # type -> list of free vars
         self.temps_used_type = {} # name -> type
         self.temp_counter = 0
@@ -104,12 +104,17 @@ class FunctionState(object):
     def label_used(self, lbl):
         return lbl in self.labels_used
 
-    def allocate_temp(self, type):
+    def allocate_temp(self, type, manage_ref=True):
         """
         Allocates a temporary (which may create a new one or get a previously
         allocated and released one of the same type). Type is simply registered
         and handed back, but will usually be a PyrexType.
 
+        If type.is_pyobject, manage_ref comes into play. If manage_ref is set to
+        True, the temp will be decref-ed on return statements and in exception
+        handling clauses. Otherwise the caller has to deal with any reference
+        counting of the variable.
+
         A C string referring to the variable is returned.
         """
         freelist = self.temps_free.get(type)
@@ -120,7 +125,7 @@ class FunctionState(object):
                 self.temp_counter += 1
                 result = "%s%d" % (Naming.codewriter_temp_prefix, self.temp_counter)
                 if not result in self.names_taken: break
-            self.temps_allocated.append((result, type))
+            self.temps_allocated.append((result, type, manage_ref))
         self.temps_used_type[result] = type
         return result
 
@@ -138,23 +143,24 @@ class FunctionState(object):
         freelist.append(name)
 
     def temps_in_use(self):
-        """Return a list of (cname,type) tuples of temp names and their type
+        """Return a list of (cname,type,manage_ref) tuples of temp names and their type
         that are currently in use.
         """
         used = []
-        for name, type in self.temps_allocated:
+        for name, type, manage_ref in self.temps_allocated:
             freelist = self.temps_free.get(type)
             if freelist is None or name not in freelist:
-                used.append((name, type))
+                used.append((name, type, manage_ref))
         return used
 
-    def py_temps_in_use(self):
+    def temps_holding_reference(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.
+        that are currently in use. This includes only temps of a
+        Python object type which owns its reference.
         """
         return [(name, type)
-                for name, type in self.temps_in_use()
-                if type.is_pyobject]
+                for name, type, manage_ref in self.temps_in_use()
+                if (type.is_pyobject and manage_ref)]
 
 class GlobalState(object):
     # filename_table   {string : int}  for finding filename table indexes
@@ -674,7 +680,7 @@ class CCodeWriter(object):
         self.putln(";")
 
     def put_temp_declarations(self, func_context):
-        for name, type in func_context.temps_allocated:
+        for name, type, manage_ref in func_context.temps_allocated:
             decl = type.declaration_code(name)
             if type.is_pyobject:
                 self.putln("%s = NULL;" % decl)
index 3c6348619b27a75063747a801c5ad2c1f31f5b6e..e7b168be3f4ba79fe14ed6ed99b7fa2d75af1c58 100644 (file)
@@ -1063,8 +1063,8 @@ class FuncDefNode(StatNode, BlockNode):
             # 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:
+            for cname, type, manage_ref in code.funcstate.temps_allocated:
+                if type.is_pyobject and manage_ref:
                     code.put_xdecref(cname, type)
 
             # Clean up buffers -- this calls a Python function
@@ -2369,7 +2369,7 @@ class PyClassDefNode(ClassDefNode):
         
     def as_cclass(self):
         """
-        Return this node as if it were declared as an extension class"
+        Return this node as if it were declared as an extension class
         """
         bases = self.classobj.bases.args
         if len(bases) == 0:
@@ -3296,7 +3296,7 @@ class ReturnStatNode(StatNode):
         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():
+        for cname, type in code.funcstate.temps_holding_reference():
             code.put_decref_clear(cname, type)
         #code.putln(
         #      "goto %s;" %
index ec3727a93a97d0d06f88f83f1aa059962dc5ffba..7fcf6fda27745fc4633bc9384a3e23bd5b91a090 100644 (file)
@@ -79,7 +79,7 @@ class TempsBlockNode(Node):
 
     def generate_execution_code(self, code):
         for handle in self.temps:
-            handle.temp = code.funcstate.allocate_temp(handle.type)
+            handle.temp = code.funcstate.allocate_temp(handle.type, manage_ref=True)
         self.body.generate_execution_code(code)
         for handle in self.temps:
             if handle.needs_cleanup: