Cleanup, make manage_ref mandatory for allocate_temp. This caught a bug too.
authorDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Thu, 27 Nov 2008 12:11:43 +0000 (13:11 +0100)
committerDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Thu, 27 Nov 2008 12:11:43 +0000 (13:11 +0100)
Cython/Compiler/Buffer.py
Cython/Compiler/Code.py
Cython/Compiler/ExprNodes.py
Cython/Compiler/Nodes.py

index 7ce7046842d3091d9ae8ed66bcb4a927f17becbf..0a5f78bf19a09b89b652529d0808faa508542ff4 100644 (file)
@@ -291,7 +291,7 @@ def put_assign_to_buffer(lhs_cname, rhs_cname, buffer_aux, buffer_type,
         # Release any existing buffer
         code.putln('__Pyx_SafeReleaseBuffer(&%s);' % bufstruct)
         # Acquire
-        retcode_cname = code.funcstate.allocate_temp(PyrexTypes.c_int_type)
+        retcode_cname = code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False)
         code.putln("%s = %s;" % (retcode_cname, getbuffer % rhs_cname))
         code.putln('if (%s) {' % (code.unlikely("%s < 0" % retcode_cname)))
         # If acquisition failed, attempt to reacquire the old buffer
@@ -353,7 +353,7 @@ def put_buffer_lookup_code(entry, index_signeds, index_cnames, options, pos, cod
         # We allocate a temporary which is initialized to -1, meaning OK (!).
         # If an error occurs, the temp is set to the dimension index the
         # error is occuring at.
-        tmp_cname = code.funcstate.allocate_temp(PyrexTypes.c_int_type)
+        tmp_cname = code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False)
         code.putln("%s = -1;" % tmp_cname)
         for dim, (signed, cname, shape) in enumerate(zip(index_signeds, index_cnames,
                                                          bufaux.shapevars)):
index 1bafa015bf799ffcb1991d4ed28778a71edc3f7a..10558f16d24dba60a7f1bc97b147728da95e06bd 100644 (file)
@@ -104,7 +104,7 @@ class FunctionState(object):
     def label_used(self, lbl):
         return lbl in self.labels_used
 
-    def allocate_temp(self, type, manage_ref=True):
+    def allocate_temp(self, type, manage_ref):
         """
         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
@@ -115,11 +115,16 @@ class FunctionState(object):
         handling clauses. Otherwise the caller has to deal with any reference
         counting of the variable.
 
+        If not type.is_pyobject, then manage_ref will be ignored, but it
+        still has to be passed. It is recommended to pass False by convention
+        if it is known that type will never be a Python object.
+
         A C string referring to the variable is returned.
         """
-        if not type.is_pyobject and manage_ref is not True:
-            # Make manage_ref canonical for temps_free lookup purposes
-            raise ValueError("manage_ref only applicable when type.is_pyobject")
+        if not type.is_pyobject:
+            # Make manage_ref canonical, so that manage_ref will always mean
+            # a decref is needed.
+            manage_ref = False
         freelist = self.temps_free.get((type, manage_ref))
         if freelist is not None and len(freelist) > 0:
             result = freelist.pop()
@@ -163,7 +168,14 @@ class FunctionState(object):
         """
         return [(name, type)
                 for name, type, manage_ref in self.temps_in_use()
-                if (type.is_pyobject and manage_ref)]
+                if manage_ref]
+
+    def all_managed_temps(self):
+        """Return a list of (cname, type) tuples of refcount-managed Python objects.
+        """
+        return [(cname, type)
+                for cname, type, manage_ref in self.temps_allocated
+                if manage_ref]
 
 class GlobalState(object):
     # filename_table   {string : int}  for finding filename table indexes
index 87ea05c9c18d3bce085c77e7ebfbc1c5a2f4c388..d7190b909d6a886d7b5a69c964f34513ef87ac01 100644 (file)
@@ -613,7 +613,7 @@ class NewTempExprNode(ExprNode):
                 if self.backwards_compatible_result:
                     self.temp_code = self.backwards_compatible_result
                 else:
-                    self.temp_code = code.funcstate.allocate_temp(type)
+                    self.temp_code = code.funcstate.allocate_temp(type, manage_ref=True)
             else:
                 self.temp_code = None
 
@@ -1718,9 +1718,9 @@ class IndexNode(ExprNode):
         if self.buffer_type.dtype.is_pyobject:
             # Must manage refcounts. Decref what is already there
             # and incref what we put in.
-            ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type)
+            ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False)
             if rhs.is_temp:
-                rhs_code = code.funcstate.allocate_temp(rhs.type)
+                rhs_code = code.funcstate.allocate_temp(rhs.type, manage_ref=False)
             else:
                 rhs_code = rhs.result()
             code.putln("%s = %s;" % (ptr, ptrexpr))
@@ -1772,7 +1772,7 @@ class IndexNode(ExprNode):
 
     def buffer_lookup_code(self, code):
         # Assign indices to temps
-        index_temps = [code.funcstate.allocate_temp(i.type) for i in self.indices]
+        index_temps = [code.funcstate.allocate_temp(i.type, manage_ref=False) for i in self.indices]
         for temp, index in zip(index_temps, self.indices):
             code.putln("%s = %s;" % (temp, index.result()))
         # Generate buffer access code using these temps
index e7b168be3f4ba79fe14ed6ed99b7fa2d75af1c58..5cf0e39d177030d779c7c9c9ff5c8e209dc06858 100644 (file)
@@ -1063,9 +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, manage_ref in code.funcstate.temps_allocated:
-                if type.is_pyobject and manage_ref:
-                    code.put_xdecref(cname, type)
+            for cname, type in code.funcstate.all_managed_temps():
+                code.put_xdecref(cname, type)
 
             # Clean up buffers -- this calls a Python function
             # so need to save and restore error state