From d444a436049d5573477c9e14eb731c1aa294245b Mon Sep 17 00:00:00 2001 From: Dag Sverre Seljebotn Date: Thu, 4 Dec 2008 21:17:28 +0100 Subject: [PATCH] Added __Pyx_GOTREF calls (probably not everywhere needed) --- Cython/Compiler/Code.py | 7 +++++- Cython/Compiler/DebugFlags.py | 1 + Cython/Compiler/ExprNodes.py | 41 ++++++++++++++++++++++++++++++++--- Cython/Compiler/Nodes.py | 7 +++++- 4 files changed, 51 insertions(+), 5 deletions(-) diff --git a/Cython/Compiler/Code.py b/Cython/Compiler/Code.py index 761bd967..df1ac58f 100644 --- a/Cython/Compiler/Code.py +++ b/Cython/Compiler/Code.py @@ -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))) diff --git a/Cython/Compiler/DebugFlags.py b/Cython/Compiler/DebugFlags.py index e36e0bd2..2d096a4c 100644 --- a/Cython/Compiler/DebugFlags.py +++ b/Cython/Compiler/DebugFlags.py @@ -2,3 +2,4 @@ debug_disposal_code = 0 debug_temp_alloc = 0 debug_coercion = 0 +debug_ref_check_code = 1 diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 9603776e..58341265 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -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): diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index a70f976c..7f64bdcf 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -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) -- 2.26.2