Added __Pyx_GOTREF calls (probably not everywhere needed)
authorDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Thu, 4 Dec 2008 20:17:28 +0000 (21:17 +0100)
committerDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Thu, 4 Dec 2008 20:17:28 +0000 (21:17 +0100)
Cython/Compiler/Code.py
Cython/Compiler/DebugFlags.py
Cython/Compiler/ExprNodes.py
Cython/Compiler/Nodes.py

index 761bd967c6d4043555d65214f76416d55d8135c3..df1ac58fb9779d4c2a55b6bf5e0b2d40aa85d987 100644 (file)
@@ -10,6 +10,7 @@ from PyrexTypes import py_object_type, typecast
 from TypeSlots import method_coexist
 from Scanning import SourceDescriptor
 from Cython.StringIOTree import StringIOTree
+import DebugFlags
 try:
     set
 except NameError:
@@ -671,6 +672,10 @@ class CCodeWriter(object):
     def as_pyobject(self, cname, type):
         return typecast(py_object_type, type, cname)
     
+    def put_gotref(self, cname):
+        if DebugFlags.debug_ref_check_code:
+            self.putln("__Pyx_GOTREF(%s);" % cname)
+    
     def put_incref(self, cname, type):
         self.putln("Py_INCREF(%s);" % self.as_pyobject(cname, type))
     
@@ -756,7 +761,7 @@ class CCodeWriter(object):
                     "|".join(method_flags),
                     doc_code,
                     term))
-    
+
     def put_error_if_neg(self, pos, value):
 #        return self.putln("if (unlikely(%s < 0)) %s" % (value, self.error_goto(pos)))  # TODO this path is almost _never_ taken, yet this macro makes is slower!
         return self.putln("if (%s < 0) %s" % (value, self.error_goto(pos)))
index e36e0bd2686caab74064ebd8dd9bd5fea23a6dbf..2d096a4c1960a24ebc6c7b2ecc074c02c92a9bea 100644 (file)
@@ -2,3 +2,4 @@ debug_disposal_code = 0
 debug_temp_alloc = 0
 debug_coercion = 0
 
+debug_ref_check_code = 1
index 9603776e36c941dda77185d315c5b0b4fa2c8fdd..58341265cd6618ee182d2b7937b9260016d3d46d 100644 (file)
@@ -903,6 +903,7 @@ class LongNode(AtomicExprNode):
                 self.result(),
                 self.value,
                 code.error_goto_if_null(self.result(), self.pos)))
+        code.put_gotref(self.result())
 
 
 class ImagNode(AtomicExprNode):
@@ -926,6 +927,8 @@ class ImagNode(AtomicExprNode):
                 self.result(),
                 self.value,
                 code.error_goto_if_null(self.result(), self.pos)))
+        code.put_gotref(self.result())
+        
 
 
 class NameNode(AtomicExprNode):
@@ -1146,13 +1149,16 @@ class NameNode(AtomicExprNode):
                 namespace, 
                 self.interned_cname,
                 code.error_goto_if_null(self.result(), self.pos)))
+            code.put_gotref(self.result())
+            
         elif entry.is_local and False:
             # control flow not good enough yet
             assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
             if assigned is False:
                 error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
             elif not Options.init_local_none and assigned is None:
-                code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' % (entry.cname, entry.name, code.error_goto(self.pos)))
+                code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
+                           (entry.cname, entry.name, code.error_goto(self.pos)))
                 entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
 
     def generate_assignment_code(self, rhs, code):
@@ -1277,6 +1283,8 @@ class BackquoteNode(ExprNode):
                 self.result(),
                 self.arg.py_result(),
                 code.error_goto_if_null(self.result(), self.pos)))
+        code.put_gotref(self.result())
+        
 
 
 class ImportNode(ExprNode):
@@ -1313,6 +1321,7 @@ class ImportNode(ExprNode):
                 self.module_name.py_result(),
                 name_list_code,
                 code.error_goto_if_null(self.result(), self.pos)))
+        code.put_gotref(self.result())
 
 
 class IteratorNode(ExprNode):
@@ -1356,6 +1365,7 @@ class IteratorNode(ExprNode):
                 self.result(),
                 self.sequence.py_result(),
                 code.error_goto_if_null(self.result(), self.pos)))
+        code.put_gotref(self.result())
         code.putln("}")
 
 
@@ -1402,6 +1412,7 @@ class NextNode(AtomicExprNode):
         code.putln(code.error_goto_if_PyErr(self.pos))
         code.putln("break;")
         code.putln("}")
+        code.put_gotref(self.result())
         code.putln("}")
 
 
@@ -1649,7 +1660,8 @@ class IndexNode(ExprNode):
                     self.index_unsigned_parameter(),
                     self.result(),
                     code.error_goto(self.pos)))
-
+            code.put_gotref(self.result())
+            
     def generate_setitem_code(self, value_code, code):
         if self.index.type.is_int:
             function = "__Pyx_SetItemInt"
@@ -1666,6 +1678,7 @@ class IndexNode(ExprNode):
                 value_code,
                 self.index_unsigned_parameter(),
                 code.error_goto(self.pos)))
+        code.put_gotref(self.base.py_result())
 
     def generate_buffer_setitem_code(self, rhs, code, op=""):
         # Used from generate_assignment_code and InPlaceAssignmentNode
@@ -1799,6 +1812,7 @@ class SliceIndexNode(ExprNode):
                 self.start_code(),
                 self.stop_code(),
                 code.error_goto_if_null(self.result(), self.pos)))
+        code.put_gotref(self.result())
     
     def generate_assignment_code(self, rhs, code):
         self.generate_subexpr_evaluation_code(code)
@@ -1882,6 +1896,7 @@ class SliceNode(ExprNode):
                 self.stop.py_result(), 
                 self.step.py_result(),
                 code.error_goto_if_null(self.result(), self.pos)))
+        code.put_gotref(self.result())
 
 
 class CallNode(ExprNode):
@@ -2102,6 +2117,7 @@ class SimpleCallNode(CallNode):
                     self.function.py_result(),
                     arg_code,
                     code.error_goto_if_null(self.result(), self.pos)))
+            code.put_gotref(self.result())
         elif func_type.is_cfunction:
             if self.has_optional_args:
                 actual_nargs = len(self.args)
@@ -2156,6 +2172,9 @@ class SimpleCallNode(CallNode):
                     else:
                         goto_error = ""
                     code.putln("%s%s; %s" % (lhs, rhs, goto_error))
+                if self.type.is_pyobject and self.result():
+                    code.put_gotref(self.result())
+                    
 
 class GeneralCallNode(CallNode):
     #  General Python function call, including keyword,
@@ -2231,6 +2250,7 @@ class GeneralCallNode(CallNode):
                 self.result(),
                 call_code,
                 code.error_goto_if_null(self.result(), self.pos)))
+        code.put_gotref(self.result())
 
 
 class AsTupleNode(ExprNode):
@@ -2263,6 +2283,7 @@ class AsTupleNode(ExprNode):
                 self.result(),
                 self.arg.py_result(),
                 code.error_goto_if_null(self.result(), self.pos)))
+        code.put_gotref(self.result())
     
 
 class AttributeNode(ExprNode):
@@ -2526,6 +2547,7 @@ class AttributeNode(ExprNode):
                     self.obj.py_result(),
                     self.interned_attr_cname,
                     code.error_goto_if_null(self.result(), self.pos)))
+            code.put_gotref(self.result())
         else:
             # result_code contains what is needed, but we may need to insert
             # a check and raise an exception
@@ -2683,6 +2705,7 @@ class SequenceNode(ExprNode):
                 self.iterator.result(),
                 rhs.py_result(),
                 code.error_goto_if_null(self.iterator.result(), self.pos)))
+        code.put_gotref(self.iterator.result())
         rhs.generate_disposal_code(code)
         for i in range(len(self.args)):
             item = self.unpacked_items[i]
@@ -2693,6 +2716,7 @@ class SequenceNode(ExprNode):
                     item.result(),
                     typecast(item.ctype(), py_object_type, unpack_code),
                     code.error_goto_if_null(item.result(), self.pos)))
+            code.put_gotref(item.result())
             value_node = self.coerced_unpacked_items[i]
             value_node.generate_evaluation_code(code)
             self.args[i].generate_assignment_code(value_node, code)
@@ -2751,6 +2775,7 @@ class TupleNode(SequenceNode):
                 self.result(),
                 len(self.args),
                 code.error_goto_if_null(self.result(), self.pos)))
+        code.put_gotref(self.result())
         for i in range(len(self.args)):
             arg = self.args[i]
             if not arg.result_in_temp():
@@ -2895,6 +2920,7 @@ class ListComprehensionNode(SequenceNode):
             (self.result(),
             0,
             code.error_goto_if_null(self.result(), self.pos)))
+        code.put_gotref(self.result())
         self.loop.generate_execution_code(code)
         
     def annotate(self, code):
@@ -3006,6 +3032,7 @@ class DictNode(ExprNode):
                 "%s = PyDict_New(); %s" % (
                     self.result(),
                     code.error_goto_if_null(self.result(), self.pos)))
+            code.put_gotref(self.result())
         for item in self.key_value_pairs:
             item.generate_evaluation_code(code)
             if self.type.is_pyobject:
@@ -3092,6 +3119,7 @@ class ClassNode(ExprNode):
                 self.cname,
                 self.module_name,
                 code.error_goto_if_null(self.result(), self.pos)))
+        code.put_gotref(self.result())
 
 
 class UnboundMethodNode(ExprNode):
@@ -3119,7 +3147,7 @@ class UnboundMethodNode(ExprNode):
                 self.function.py_result(),
                 self.class_cname,
                 code.error_goto_if_null(self.result(), self.pos)))
-
+        code.put_gotref(self.result())
 
 class PyCFunctionNode(AtomicExprNode):
     #  Helper class used in the implementation of Python
@@ -3141,6 +3169,7 @@ class PyCFunctionNode(AtomicExprNode):
                 self.result(),
                 self.pymethdef_cname,
                 code.error_goto_if_null(self.result(), self.pos)))
+        code.put_gotref(self.result())
 
 #-------------------------------------------------------------------
 #
@@ -3215,6 +3244,7 @@ class UnopNode(ExprNode):
                 function, 
                 self.operand.py_result(),
                 code.error_goto_if_null(self.result(), self.pos)))
+        code.put_gotref(self.result())
         
     def type_error(self):
         if not self.operand.type.is_error:
@@ -3609,6 +3639,7 @@ class BinopNode(NewTempExprNode):
                     self.operand2.py_result(),
                     extra_args,
                     code.error_goto_if_null(self.result(), self.pos)))
+            code.put_gotref(self.result())
         else:
             if self.is_temp:
                 self.generate_c_operation_code(code)
@@ -4068,6 +4099,7 @@ class CmpNode:
                         operand2.py_result(), 
                         richcmp_constants[op],
                         code.error_goto_if_null(result_code, self.pos)))
+                code.put_gotref(result_code)
         else:
             type1 = operand1.type
             type2 = operand2.type
@@ -4441,6 +4473,7 @@ class CoerceToPyTypeNode(CoercionNode):
             function, 
             self.arg.result(), 
             code.error_goto_if_null(self.result(), self.pos)))
+        code.put_gotref(self.result())
 
 
 class CoerceFromPyTypeNode(CoercionNode):
@@ -4472,6 +4505,8 @@ class CoerceFromPyTypeNode(CoercionNode):
             self.result(), 
             rhs,
             code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
+        if self.type.is_pyobject:
+            code.put_gotref(self.result())
 
 
 class CoerceToBooleanNode(CoercionNode):
index a70f976ce0f2e9050a14971609c12bcacd9fea46..7f64bdcf57421c44de792a62b77988af94b7b12d 100644 (file)
@@ -850,6 +850,7 @@ class CEnumDefNode(StatNode):
                         self.temp,
                         item.cname,
                         code.error_goto_if_null(self.temp, item.pos)))
+                code.put_gotref(self.temp) #TODO: Is this right?
                 code.putln('if (PyObject_SetAttrString(%s, "%s", %s) < 0) %s' % (
                         Naming.module_cname, 
                         item.name, 
@@ -2199,6 +2200,7 @@ class DefNode(FuncDefNode):
                 func,
                 arg.hdr_cname,
                 code.error_goto_if_null(arg.entry.cname, arg.pos)))
+            code.put_gotref(arg.entry.cname)
         else:
             error(arg.pos,
                 "Cannot convert argument of type '%s' to Python object"
@@ -2278,6 +2280,7 @@ class OverrideCheckNode(StatNode):
         else:
             code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
         err = code.error_goto_if_null(self.func_node.result(), self.pos)
+        code.put_gotref(self.func_node.result())
         # need to get attribute manually--scope would return cdef method
         code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err))
         # It appears that this type is not anywhere exposed in the Python/C API
@@ -2327,7 +2330,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:
@@ -2968,6 +2971,7 @@ class InPlaceAssignmentNode(AssignmentNode):
                     self.rhs.py_result(),
                     extra,
                     code.error_goto_if_null(self.result_value.py_result(), self.pos)))
+            code.put_gotref(self.result_value.result())
             self.result_value.generate_evaluation_code(code) # May be a type check...
             self.rhs.generate_disposal_code(code)
             self.dup.generate_disposal_code(code)
@@ -4443,6 +4447,7 @@ class FromImportStatNode(StatNode):
                     self.module.py_result(),
                     cname,
                     code.error_goto_if_null(self.item.result(), self.pos)))
+            code.put_gotref(self.item.result())
             target.generate_assignment_code(self.item, code)
         self.module.generate_disposal_code(code)