Commit f4cb6c7b authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

merge

parents d1a841b9 cf38d155
......@@ -6,3 +6,4 @@ a09347d7b470290076b983aef98707921445a038 0.9.8.1
a89b05b78236a27a654f3004bdffc7b8a56311a7 0.10
ef9d2c680684d0df7d81f529cda29e9e1741f575 cython-0.10.1
92baafe0edf3cea00deb7ce1e31e337bb485af1a 0.10.2
cdf889c30e7a7053de20bae3a578dad09ebcbdf5 0.10.3
......@@ -64,6 +64,9 @@ class IntroduceBufferAuxiliaryVars(CythonTransform):
# for now...note that pos is wrong
raise CompileError(node.pos, "Buffer vars not allowed in module scope")
for entry in bufvars:
if entry.type.dtype.is_ptr:
raise CompileError(node.pos, "Buffers with pointer types not yet supported.")
name = entry.name
buftype = entry.type
if buftype.ndim > self.max_ndim:
......@@ -497,7 +500,7 @@ def mangle_dtype_name(dtype):
elif dtype.is_ptr:
return "ptr"
else:
if dtype.typestring is None:
if dtype.is_typedef or dtype.is_struct_or_union:
prefix = "nn_"
else:
prefix = ""
......@@ -549,10 +552,8 @@ def create_typestringchecker(protocode, defcode, name, dtype):
defcode.putln("int ok;")
defcode.putln("ts = __Pyx_ConsumeWhitespace(ts); if (!ts) return NULL;")
defcode.putln("if (*ts == '1') ++ts;")
if dtype.typestring is not None:
assert len(dtype.typestring) == 1
# Can use direct comparison
defcode.putln("ok = (*ts == '%s');" % dtype.typestring)
if dtype.is_pyobject:
defcode.putln("ok = (*ts == 'O');")
else:
# Cannot trust declared size; but rely on int vs float and
# signed/unsigned to be correctly declared. Use a switch statement
......
......@@ -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:
......@@ -737,47 +738,53 @@ class CCodeWriter(object):
def as_pyobject(self, cname, type):
return typecast(py_object_type, type, cname)
def put_gotref(self, cname):
self.putln("__Pyx_GOTREF(%s);" % cname)
def put_giveref(self, cname):
self.putln("__Pyx_GIVEREF(%s);" % cname)
def put_incref(self, cname, type):
self.putln("Py_INCREF(%s);" % self.as_pyobject(cname, type))
self.putln("__Pyx_INCREF(%s);" % self.as_pyobject(cname, type))
def put_decref(self, cname, type):
self.putln("Py_DECREF(%s);" % self.as_pyobject(cname, type))
self.putln("__Pyx_DECREF(%s);" % self.as_pyobject(cname, type))
def put_var_incref(self, entry):
if entry.type.is_pyobject:
self.putln("Py_INCREF(%s);" % self.entry_as_pyobject(entry))
self.putln("__Pyx_INCREF(%s);" % self.entry_as_pyobject(entry))
def put_decref_clear(self, cname, type):
self.putln("Py_DECREF(%s); %s = 0;" % (
self.putln("__Pyx_DECREF(%s); %s = 0;" % (
typecast(py_object_type, type, cname), cname))
#self.as_pyobject(cname, type), cname))
def put_xdecref(self, cname, type):
self.putln("Py_XDECREF(%s);" % self.as_pyobject(cname, type))
self.putln("__Pyx_XDECREF(%s);" % self.as_pyobject(cname, type))
def put_xdecref_clear(self, cname, type):
self.putln("Py_XDECREF(%s); %s = 0;" % (
self.putln("__Pyx_XDECREF(%s); %s = 0;" % (
self.as_pyobject(cname, type), cname))
def put_var_decref(self, entry):
if entry.type.is_pyobject:
if entry.init_to_none is False:
self.putln("Py_XDECREF(%s);" % self.entry_as_pyobject(entry))
self.putln("__Pyx_XDECREF(%s);" % self.entry_as_pyobject(entry))
else:
self.putln("Py_DECREF(%s);" % self.entry_as_pyobject(entry))
self.putln("__Pyx_DECREF(%s);" % self.entry_as_pyobject(entry))
def put_var_decref_clear(self, entry):
if entry.type.is_pyobject:
self.putln("Py_DECREF(%s); %s = 0;" % (
self.putln("__Pyx_DECREF(%s); %s = 0;" % (
self.entry_as_pyobject(entry), entry.cname))
def put_var_xdecref(self, entry):
if entry.type.is_pyobject:
self.putln("Py_XDECREF(%s);" % self.entry_as_pyobject(entry))
self.putln("__Pyx_XDECREF(%s);" % self.entry_as_pyobject(entry))
def put_var_xdecref_clear(self, entry):
if entry.type.is_pyobject:
self.putln("Py_XDECREF(%s); %s = 0;" % (
self.putln("__Pyx_XDECREF(%s); %s = 0;" % (
self.entry_as_pyobject(entry), entry.cname))
def put_var_decrefs(self, entries, used_only = 0):
......@@ -798,7 +805,7 @@ class CCodeWriter(object):
def put_init_to_py_none(self, cname, type):
py_none = typecast(type, py_object_type, "Py_None")
self.putln("%s = %s; Py_INCREF(Py_None);" % (cname, py_none))
self.putln("%s = %s; __Pyx_INCREF(Py_None);" % (cname, py_none))
def put_init_var_to_py_none(self, entry, template = "%s"):
code = template % entry.cname
......@@ -822,7 +829,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)))
......@@ -836,21 +843,25 @@ class CCodeWriter(object):
return 'unlikely(%s)' % cond
else:
return cond
def error_goto(self, pos):
lbl = self.funcstate.error_label
self.funcstate.use_label(lbl)
def set_error_info(self, pos):
if Options.c_line_in_traceback:
cinfo = " %s = %s;" % (Naming.clineno_cname, Naming.line_c_macro)
else:
cinfo = ""
return "{%s = %s[%s]; %s = %s;%s goto %s;}" % (
return "%s = %s[%s]; %s = %s;%s" % (
Naming.filename_cname,
Naming.filetable_cname,
self.lookup_filename(pos[0]),
Naming.lineno_cname,
pos[1],
cinfo,
cinfo)
def error_goto(self, pos):
lbl = self.funcstate.error_label
self.funcstate.use_label(lbl)
return "{%s goto %s;}" % (
self.set_error_info(pos),
lbl)
def error_goto_if(self, cond, pos):
......
......@@ -3,3 +3,4 @@ debug_temp_alloc = 0
debug_coercion = 0
debug_temp_code_comments = 1
......@@ -1016,6 +1016,7 @@ class LongNode(AtomicNewTempExprNode):
self.result(),
self.value,
code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
class ImagNode(AtomicNewTempExprNode):
......@@ -1042,6 +1043,8 @@ class ImagNode(AtomicNewTempExprNode):
self.result(),
self.value,
code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
class NameNode(AtomicExprNode):
......@@ -1262,13 +1265,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):
......@@ -1406,6 +1412,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):
......@@ -1442,6 +1450,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(NewTempExprNode):
......@@ -1500,6 +1509,7 @@ class IteratorNode(NewTempExprNode):
self.result(),
self.sequence.py_result(),
code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
code.putln("}")
......@@ -1558,6 +1568,7 @@ class NextNode(AtomicNewTempExprNode):
code.putln(code.error_goto_if_PyErr(self.pos))
code.putln("break;")
code.putln("}")
code.put_gotref(self.result())
code.putln("}")
......@@ -1819,7 +1830,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"
......@@ -1994,6 +2006,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)
......@@ -2158,6 +2171,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(NewTempExprNode):
......@@ -2378,6 +2392,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)
......@@ -2432,6 +2447,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,
......@@ -2507,6 +2525,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):
......@@ -2542,6 +2561,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):
......@@ -2811,6 +2831,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
......@@ -2980,6 +3001,7 @@ class SequenceNode(NewTempExprNode):
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]
......@@ -2990,6 +3012,7 @@ class SequenceNode(NewTempExprNode):
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)
code.put_error_if_neg(self.pos,
......@@ -3056,6 +3079,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():
......@@ -3065,6 +3089,7 @@ class TupleNode(SequenceNode):
self.result(),
i,
arg.py_result()))
code.put_giveref(arg.py_result())
def generate_subexpr_disposal_code(self, code):
# We call generate_post_assignment_code here instead
......@@ -3150,6 +3175,7 @@ class ListNode(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.is_temp:
......@@ -3159,6 +3185,7 @@ class ListNode(SequenceNode):
(self.result(),
i,
arg.py_result()))
code.put_giveref(arg.py_result())
elif self.type.is_array:
for i, arg in enumerate(self.args):
code.putln("%s[%s] = %s;" % (
......@@ -3397,6 +3424,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:
......@@ -3492,6 +3520,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):
......@@ -3519,7 +3548,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(AtomicNewTempExprNode):
# Helper class used in the implementation of Python
......@@ -3541,6 +3570,7 @@ class PyCFunctionNode(AtomicNewTempExprNode):
self.result(),
self.pymethdef_cname,
code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.result())
#-------------------------------------------------------------------
#
......@@ -3619,6 +3649,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:
......@@ -4025,6 +4056,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)
......@@ -4522,6 +4554,7 @@ class CmpNode(object):
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
......@@ -4923,6 +4956,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):
......@@ -4954,6 +4988,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):
......
......@@ -19,6 +19,7 @@ import Options
import PyrexTypes
import TypeSlots
import Version
import DebugFlags
from Errors import error, warning
from PyrexTypes import py_object_type
......@@ -250,6 +251,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.globalstate.module_pos = self.pos
code.globalstate.directives = self.directives
code.globalstate.use_utility_code(refcount_utility_code)
code.putln("")
code.putln("/* Implementation of %s */" % env.qualified_name)
self.generate_const_definitions(env, code)
......@@ -553,7 +556,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln('')
code.putln('static char %s[] = "%s";' % (
env.doc_cname, escape_byte_string(docstr)))
def generate_extern_c_macro_definition(self, code):
name = Naming.extern_c_macro
code.putln("#ifdef __cplusplus")
......@@ -1586,6 +1589,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("#endif")
code.putln("{")
tempdecl_code = code.insertion_point()
code.putln('__Pyx_SetupRefcountContext("%s");' % header3)
code.putln("%s = PyTuple_New(0); %s" % (Naming.empty_tuple, code.error_goto_if_null(Naming.empty_tuple, self.pos)));
code.putln("/*--- Library function declarations ---*/")
......@@ -2312,3 +2318,36 @@ bad:
}
""" % {'IMPORT_STAR' : Naming.import_star,
'IMPORT_STAR_SET' : Naming.import_star_set }
refcount_utility_code = UtilityCode(proto="""
#ifdef CYTHON_REFNANNY
void __Pyx_Refnanny_INCREF(void*, PyObject*, int);
void __Pyx_Refnanny_GOTREF(void*, PyObject*, int);
void __Pyx_Refnanny_GIVEREF(void*, PyObject*, int);
void __Pyx_Refnanny_INCREF(void*, PyObject*, int);
void __Pyx_Refnanny_DECREF(void*, PyObject*, int);
void* __Pyx_Refnanny_NewContext(char*, int);
int __Pyx_Refnanny_FinishContext(void*);
#define __Pyx_INCREF(r) __Pyx_Refnanny_INCREF(__pyx_refchk, r, __LINE__)
#define __Pyx_GOTREF(r) __Pyx_Refnanny_GOTREF(__pyx_refchk, r, __LINE__)
#define __Pyx_GIVEREF(r) __Pyx_Refnanny_GIVEREF(__pyx_refchk, r, __LINE__)
#define __Pyx_DECREF(r) __Pyx_Refnanny_DECREF(__pyx_refchk, r, __LINE__)
#define __Pyx_XDECREF(r) (r ? __Pyx_Refnanny_DECREF(__pyx_refchk, r, __LINE__) : 0)
#define __Pyx_SetupRefcountContext(name) \
void* __pyx_refchk = __Pyx_Refnanny_NewContext(name, __LINE__)
#define __Pyx_FinishRefcountContext() __Pyx_Refnanny_FinishContext(__pyx_refchk)
#else
#define __Pyx_INCREF(r) Py_INCREF(r)
#define __Pyx_GOTREF(r)
#define __Pyx_GIVEREF(r)
#define __Pyx_DECREF(r) Py_DECREF(r)
#define __Pyx_XDECREF(r) Py_XDECREF(r)
#define __Pyx_SetupRefcountContext(name)
#define __Pyx_FinishRefcountContext() 0
#endif /* CYTHON_REFNANNY */
""")
......@@ -17,6 +17,7 @@ from Cython.Utils import open_new_file, replace_suffix, UtilityCode
from StringEncoding import EncodedString, escape_byte_string, split_docstring
import Options
import ControlFlow
import DebugFlags
from DebugFlags import debug_disposal_code
......@@ -1022,6 +1023,7 @@ class FuncDefNode(StatNode, BlockNode):
# ----- Automatic lead-ins for certain special functions
if is_getbuffer_slot:
self.getbuffer_init(code)
code.putln('__Pyx_SetupRefcountContext("%s");' % self.entry.name)
# ----- Fetch arguments
self.generate_argument_parsing_code(env, code)
# If an argument is assigned to in the body, we must
......@@ -1135,8 +1137,24 @@ class FuncDefNode(StatNode, BlockNode):
code.putln("PyGILState_Release(_save);")
# code.putln("/* TODO: decref scope object */")
# ----- Return
default_retval = self.return_type.default_value
err_val = self.error_value()
if err_val is None and default_retval:
err_val = default_retval
if self.return_type.is_pyobject:
code.put_giveref(Naming.retval_cname)
if err_val is None:
code.putln('__Pyx_FinishRefcountContext();')
else:
code.putln('if (__Pyx_FinishRefcountContext() == -1) {')
code.putln(code.set_error_info(self.pos))
code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
code.putln('%s = %s;' % (Naming.retval_cname, err_val))
code.putln('}')
if not self.return_type.is_void:
code.putln("return %s;" % Naming.retval_cname)
code.putln("}")
# ----- Go back and insert temp variable declarations
tempvardecl_code.put_var_declarations(lenv.temp_entries)
......@@ -1188,16 +1206,16 @@ class FuncDefNode(StatNode, BlockNode):
# getbuffer with a NULL parameter. For now we work around this;
# the following line should be removed when this bug is fixed.
code.putln("if (%s == NULL) return 0;" % info)
code.putln("%s->obj = Py_None; Py_INCREF(Py_None);" % info)
code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
def getbuffer_error_cleanup(self, code):
info = self.local_scope.arg_entries[1].cname
code.putln("Py_DECREF(%s->obj); %s->obj = NULL;" %
code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
(info, info))
def getbuffer_normal_cleanup(self, code):
info = self.local_scope.arg_entries[1].cname
code.putln("if (%s->obj == Py_None) { Py_DECREF(Py_None); %s->obj = NULL; }" %
code.putln("if (%s->obj == Py_None) { __Pyx_DECREF(Py_None); %s->obj = NULL; }" %
(info, info))
class CFuncDefNode(FuncDefNode):
......@@ -2268,6 +2286,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"
......@@ -2347,6 +2366,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
......@@ -3047,6 +3067,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.rhs.free_temps(code)
......@@ -3981,6 +4002,7 @@ class TryExceptStatNode(StatNode):
except_end_label = code.new_label('exception_handled')
except_error_label = code.new_label('except_error')
except_return_label = code.new_label('except_return')
try_return_label = code.new_label('try_return')
try_end_label = code.new_label('try')
code.putln("{")
......@@ -3990,6 +4012,7 @@ class TryExceptStatNode(StatNode):
', '.join(['&%s' % var for var in Naming.exc_save_vars]))
code.putln(
"/*try:*/ {")
code.return_label = try_return_label
self.body.generate_execution_code(code)
code.putln(
"}")
......@@ -4005,6 +4028,11 @@ class TryExceptStatNode(StatNode):
for var in Naming.exc_save_vars:
code.put_xdecref_clear(var, py_object_type)
code.put_goto(try_end_label)
if code.label_used(try_return_label):
code.put_label(try_return_label)
for var in Naming.exc_save_vars:
code.put_xdecref_clear(var, py_object_type)
code.put_goto(old_return_label)
code.put_label(our_error_label)
code.put_var_xdecrefs_clear(self.cleanup_list)
for temp_name, type in temps_to_clean_up:
......@@ -4138,7 +4166,7 @@ class ExceptClauseNode(Node):
self.body.generate_execution_code(code)
code.funcstate.exc_vars = old_exc_vars
for var in self.exc_vars:
code.putln("Py_DECREF(%s); %s = 0;" % (var, var))
code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
code.put_goto(end_label)
code.putln(
"}")
......@@ -4551,6 +4579,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)
self.module.free_temps(code)
......
......@@ -49,7 +49,6 @@ class PyrexType(BaseType):
# default_value string Initial value
# parsetuple_format string Format char for PyArg_ParseTuple
# pymemberdef_typecode string Type code for PyMemberDef struct
# typestring string String char defining the type (see Python struct module)
#
# declaration_code(entity_code,
# for_display = 0, dll_linkage = None, pyrex = 0)
......@@ -101,7 +100,6 @@ class PyrexType(BaseType):
default_value = ""
parsetuple_format = ""
pymemberdef_typecode = None
typestring = None
def resolve(self):
# If a typedef, returns the base type.
......@@ -157,7 +155,6 @@ class CTypedefType(BaseType):
# typedef_base_type PyrexType
is_typedef = 1
typestring = None # Because typedefs are not known exactly
def __init__(self, cname, base_type):
self.typedef_cname = cname
......@@ -243,7 +240,6 @@ class PyObjectType(PyrexType):
parsetuple_format = "O"
pymemberdef_typecode = "T_OBJECT"
buffer_defaults = None
typestring = "O"
def __str__(self):
return "Python object"
......@@ -469,10 +465,9 @@ class CNumericType(CType):
sign_words = ("unsigned ", "", "signed ")
def __init__(self, rank, signed = 1, pymemberdef_typecode = None, typestring = None):
def __init__(self, rank, signed = 1, pymemberdef_typecode = None):
self.rank = rank
self.signed = signed
self.typestring = typestring
ptf = self.parsetuple_formats[signed][rank]
if ptf == '?':
ptf = None
......@@ -507,9 +502,8 @@ class CIntType(CNumericType):
from_py_function = "__pyx_PyInt_AsLong"
exception_value = -1
def __init__(self, rank, signed, pymemberdef_typecode = None, is_returncode = 0,
typestring=None):
CNumericType.__init__(self, rank, signed, pymemberdef_typecode, typestring=typestring)
def __init__(self, rank, signed, pymemberdef_typecode = None, is_returncode = 0):
CNumericType.__init__(self, rank, signed, pymemberdef_typecode)
self.is_returncode = is_returncode
if self.from_py_function == '__pyx_PyInt_AsLong':
self.from_py_function = self.get_type_conversion()
......@@ -602,8 +596,8 @@ class CFloatType(CNumericType):
to_py_function = "PyFloat_FromDouble"
from_py_function = "__pyx_PyFloat_AsDouble"
def __init__(self, rank, pymemberdef_typecode = None, typestring=None):
CNumericType.__init__(self, rank, 1, pymemberdef_typecode, typestring = typestring)
def __init__(self, rank, pymemberdef_typecode = None):
CNumericType.__init__(self, rank, 1, pymemberdef_typecode)
def assignable_from_resolved_type(self, src_type):
return src_type.is_numeric or src_type is error_type
......@@ -1133,7 +1127,6 @@ class ErrorType(PyrexType):
exception_check = 0
to_py_function = "dummy"
from_py_function = "dummy"
typestring = None
def create_convert_utility_code(self, env):
return True
......@@ -1167,29 +1160,29 @@ c_void_type = CVoidType()
c_void_ptr_type = CPtrType(c_void_type)
c_void_ptr_ptr_type = CPtrType(c_void_ptr_type)
c_uchar_type = CIntType(0, 0, "T_UBYTE", typestring="B")
c_ushort_type = CIntType(1, 0, "T_USHORT", typestring="H")
c_uint_type = CUIntType(2, 0, "T_UINT", typestring="I")
c_ulong_type = CULongType(3, 0, "T_ULONG", typestring="L")
c_ulonglong_type = CULongLongType(4, 0, "T_ULONGLONG", typestring="Q")
c_char_type = CIntType(0, 1, "T_CHAR", typestring="b")
c_short_type = CIntType(1, 1, "T_SHORT", typestring="h")
c_int_type = CIntType(2, 1, "T_INT", typestring="i")
c_long_type = CIntType(3, 1, "T_LONG", typestring="l")
c_longlong_type = CLongLongType(4, 1, "T_LONGLONG", typestring="q")
c_uchar_type = CIntType(0, 0, "T_UBYTE")
c_ushort_type = CIntType(1, 0, "T_USHORT")
c_uint_type = CUIntType(2, 0, "T_UINT")
c_ulong_type = CULongType(3, 0, "T_ULONG")
c_ulonglong_type = CULongLongType(4, 0, "T_ULONGLONG")
c_char_type = CIntType(0, 1, "T_CHAR")
c_short_type = CIntType(1, 1, "T_SHORT")
c_int_type = CIntType(2, 1, "T_INT")
c_long_type = CIntType(3, 1, "T_LONG")
c_longlong_type = CLongLongType(4, 1, "T_LONGLONG")
c_py_ssize_t_type = CPySSizeTType(5, 1)
c_bint_type = CBIntType(2, 1, "T_INT", typestring="i")
c_bint_type = CBIntType(2, 1, "T_INT")
c_schar_type = CIntType(0, 2, "T_CHAR", typestring="b")
c_sshort_type = CIntType(1, 2, "T_SHORT", typestring="h")
c_sint_type = CIntType(2, 2, "T_INT", typestring="i")
c_slong_type = CIntType(3, 2, "T_LONG", typestring="l")
c_slonglong_type = CLongLongType(4, 2, "T_LONGLONG", typestring="q")
c_schar_type = CIntType(0, 2, "T_CHAR")
c_sshort_type = CIntType(1, 2, "T_SHORT")
c_sint_type = CIntType(2, 2, "T_INT")
c_slong_type = CIntType(3, 2, "T_LONG")
c_slonglong_type = CLongLongType(4, 2, "T_LONGLONG")
c_float_type = CFloatType(6, "T_FLOAT", typestring="f")
c_double_type = CFloatType(7, "T_DOUBLE", typestring="d")
c_longdouble_type = CFloatType(8, typestring="g")
c_float_type = CFloatType(6, "T_FLOAT")
c_double_type = CFloatType(7, "T_DOUBLE")
c_longdouble_type = CFloatType(8)
c_null_ptr_type = CNullPtrType(c_void_type)
c_char_array_type = CCharArrayType(None)
......
version = '0.10.2'
version = '0.10.3'
......@@ -26,19 +26,19 @@ class BasicVisitor(object):
# Must resolve, try entire hierarchy
pattern = "visit_%s"
mro = inspect.getmro(cls)
handler_method = None
for mro_cls in mro:
try:
if hasattr(self, pattern % mro_cls.__name__):
handler_method = getattr(self, pattern % mro_cls.__name__)
break
except AttributeError:
pass
else:
if handler_method is None:
print type(self), type(obj)
if hasattr(self, 'access_path') and self.access_path:
print self.access_path
print self.access_path[-1][0].pos
print self.access_path[-1][0].__dict__
raise RuntimeError("Visitor does not accept object: %s" % (obj,))
if self.access_path:
print self.access_path[-1][0].pos
print self.access_path[-1][0].__dict__
raise RuntimeError("Visitor does not accept object: %s" % obj)
#print "Caching " + cls.__name__
self.dispatch_table[cls] = handler_method
return handler_method(obj)
......
cat <<EOF > ../../Cython/Compiler/DebugFlags.py
debug_disposal_code = 0
debug_temp_alloc = 0
debug_coercion = 0
debug_refnanny = 0
EOF
python ../../cython.py refnanny.pyx
gcc -shared -pthread -fPIC -fwrapv -O2 -Wall \
-fno-strict-aliasing -I/local/include/python2.5 \
-o refnanny.so -I. refnanny.c
cat <<EOF > ../../Cython/Compiler/DebugFlags.py
debug_disposal_code = 0
debug_temp_alloc = 0
debug_coercion = 0
debug_refnanny = 1
EOF
from python_ref cimport Py_INCREF, Py_DECREF
loglevel = 0
reflog = []
cdef log(level, action, obj, lineno):
if loglevel >= level:
reflog.append((lineno, action, id(obj)))
LOG_NONE, LOG_ALL = range(2)
class RefnannyException(Exception):
pass
class RefnannyContext(object):
def __init__(self):
self.refs = {} # id -> (count, [lineno])
self.errors = []
def regref(self, obj, lineno):
log(LOG_ALL, 'regref', obj, lineno)
id_ = id(obj)
count, linenumbers = self.refs.get(id_, (0, []))
self.refs[id_] = (count + 1, linenumbers)
linenumbers.append(lineno)
def delref(self, obj, lineno):
log(LOG_ALL, 'delref', obj, lineno)
id_ = id(obj)
count, linenumbers = self.refs.get(id_, (0, []))
if count == 0:
self.errors.append("Too many decrefs on line %d, reference acquired on lines %r" %
(lineno, linenumbers))
elif count == 1:
del self.refs[id_]
else:
self.refs[id_] = (count - 1, linenumbers)
def end(self):
if len(self.refs) > 0:
msg = ""
for count, linenos in self.refs.itervalues():
msg += "\n Acquired on lines: " + ", ".join(["%d" % x for x in linenos])
self.errors.append("References leaked: %s" % msg)
if self.errors:
raise RefnannyException("\n".join(self.errors))
cdef public void* __Pyx_Refnanny_NewContext(char* funcname, int lineno) except NULL:
ctx = RefnannyContext()
Py_INCREF(ctx)
return <void*>ctx
cdef public void __Pyx_Refnanny_GOTREF(void* ctx, object obj, int lineno):
if ctx == NULL: return
(<object>ctx).regref(obj, lineno)
cdef public void __Pyx_Refnanny_GIVEREF(void* ctx, object obj, int lineno):
if ctx == NULL: return
(<object>ctx).delref(obj, lineno)
cdef public void __Pyx_Refnanny_INCREF(void* ctx, object obj, int lineno):
Py_INCREF(obj)
__Pyx_Refnanny_GOTREF(ctx, obj, lineno)
cdef public void __Pyx_Refnanny_DECREF(void* ctx, object obj, int lineno):
# GIVEREF raises exception if we hit 0
#
__Pyx_Refnanny_GIVEREF(ctx, obj, lineno)
Py_DECREF(obj)
cdef public int __Pyx_Refnanny_FinishContext(void* ctx) except -1:
obj = <object>ctx
try:
obj.end()
finally:
Py_DECREF(obj)
return 0
#!/usr/bin/python
import os, sys, re, shutil, unittest, doctest
import os, sys, re, shutil, unittest, doctest, ctypes
WITH_CYTHON = True
......@@ -480,6 +480,9 @@ if __name__ == '__main__':
parser.add_option("--cython-only", dest="cython_only",
action="store_true", default=False,
help="only compile pyx to c, do not run C compiler or run the tests")
parser.add_option("--refnanny", dest="with_refnanny",
action="store_true", default=False,
help="also test that Cython-generated code does correct reference counting")
parser.add_option("--sys-pyregr", dest="system_pyregr",
action="store_true", default=False,
help="run the regression tests of the CPython installation")
......@@ -523,6 +526,13 @@ if __name__ == '__main__':
from Cython.Compiler import Errors
Errors.LEVEL = 0 # show all warnings
if options.with_refnanny:
ctypes.PyDLL("Cython/Runtime/refnanny.so", mode=ctypes.RTLD_GLOBAL)
sys.path.append("Cython/Runtime")
import refnanny
del sys.path[-1]
CFLAGS.append("-DCYTHON_REFNANNY")
# RUN ALL TESTS!
ROOTDIR = os.path.join(os.getcwd(), os.path.dirname(sys.argv[0]), 'tests')
WORKDIR = os.path.join(os.getcwd(), 'BUILD')
......@@ -603,3 +613,6 @@ if __name__ == '__main__':
sys.stderr.write("Following tests excluded because of missing dependencies on your system:\n")
for test in missing_dep_excluder.tests_missing_deps:
sys.stderr.write(" %s\n" % test)
if options.with_refnanny:
sys.stderr.write("\n".join([repr(x) for x in refnanny.reflog]))
......@@ -384,6 +384,17 @@ def wrong_string(object[int] buf):
"""
print buf[1]
@testcase
def int_and_long_are_same():
"""
>>> int_and_long_are_same()
"""
cdef object[int] intarr
cdef object[long] longarr
if sizeof(int) == sizeof(long):
intarr = IntMockBuffer(None, [1,2], format='l')
longarr = IntMockBuffer(None, [1,2])
#
# Getting items and index bounds checking
#
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment