Commit 1c8feb34 authored by Stefan Behnel's avatar Stefan Behnel

fix kwargs argument refcounting in the case that we optimised away the kwargs value

parent b55d368d
...@@ -1798,6 +1798,10 @@ class CCodeWriter(object): ...@@ -1798,6 +1798,10 @@ class CCodeWriter(object):
if entry.type.is_pyobject: if entry.type.is_pyobject:
self.putln("__Pyx_INCREF(%s);" % self.entry_as_pyobject(entry)) self.putln("__Pyx_INCREF(%s);" % self.entry_as_pyobject(entry))
def put_var_xincref(self, entry):
if entry.type.is_pyobject:
self.putln("__Pyx_XINCREF(%s);" % self.entry_as_pyobject(entry))
def put_decref_clear(self, cname, type, nanny=True, clear_before_decref=False): def put_decref_clear(self, cname, type, nanny=True, clear_before_decref=False):
self._put_decref(cname, type, nanny, null_check=False, self._put_decref(cname, type, nanny, null_check=False,
clear=True, clear_before_decref=clear_before_decref) clear=True, clear_before_decref=clear_before_decref)
......
...@@ -1863,19 +1863,20 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1863,19 +1863,20 @@ class FuncDefNode(StatNode, BlockNode):
is_cdef = isinstance(self, CFuncDefNode) is_cdef = isinstance(self, CFuncDefNode)
for entry in lenv.arg_entries: for entry in lenv.arg_entries:
if entry.type.is_pyobject: if entry.type.is_pyobject:
if ((acquire_gil or len(entry.cf_assignments) > 1) and if (acquire_gil or len(entry.cf_assignments) > 1) and not entry.in_closure:
not entry.in_closure):
code.put_var_incref(entry) code.put_var_incref(entry)
# Note: defaults are always incref-ed. For def functions, we # Note: defaults are always incref-ed. For def functions, we
# we aquire arguments from object converstion, so we have # we aquire arguments from object converstion, so we have
# new references. If we are a cdef function, we need to # new references. If we are a cdef function, we need to
# incref our arguments # incref our arguments
elif (is_cdef and entry.type.is_memoryviewslice and elif is_cdef and entry.type.is_memoryviewslice and len(entry.cf_assignments) > 1:
len(entry.cf_assignments) > 1):
code.put_incref_memoryviewslice(entry.cname, have_gil=code.funcstate.gil_owned) code.put_incref_memoryviewslice(entry.cname, have_gil=code.funcstate.gil_owned)
for entry in lenv.var_entries: for entry in lenv.var_entries:
if entry.is_arg and len(entry.cf_assignments) > 1: if entry.is_arg and len(entry.cf_assignments) > 1:
if entry.xdecref_cleanup:
code.put_var_xincref(entry)
else:
code.put_var_incref(entry) code.put_var_incref(entry)
# ----- Initialise local buffer auxiliary variables # ----- Initialise local buffer auxiliary variables
...@@ -2017,6 +2018,9 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -2017,6 +2018,9 @@ class FuncDefNode(StatNode, BlockNode):
have_gil=not lenv.nogil) have_gil=not lenv.nogil)
elif entry.type.is_pyobject: elif entry.type.is_pyobject:
if not entry.is_arg or len(entry.cf_assignments) > 1: if not entry.is_arg or len(entry.cf_assignments) > 1:
if entry.xdecref_cleanup:
code.put_var_xdecref(entry)
else:
code.put_var_decref(entry) code.put_var_decref(entry)
# Decref any increfed args # Decref any increfed args
...@@ -3131,6 +3135,15 @@ class DefNodeWrapper(FuncDefNode): ...@@ -3131,6 +3135,15 @@ class DefNodeWrapper(FuncDefNode):
if not arg.hdr_type.create_to_py_utility_code(env): if not arg.hdr_type.create_to_py_utility_code(env):
pass # will fail later pass # will fail later
if self.starstar_arg and not self.starstar_arg.entry.cf_used:
# we will set the kwargs argument to NULL instead of a new dict
# and must therefore correct the control flow state
entry = self.starstar_arg.entry
entry.xdecref_cleanup = 1
for ass in entry.cf_assignments:
if not ass.is_arg and ass.lhs.is_name:
ass.lhs.cf_maybe_null = True
def signature_has_nongeneric_args(self): def signature_has_nongeneric_args(self):
argcount = len(self.args) argcount = len(self.args)
if argcount == 0 or ( if argcount == 0 or (
...@@ -3423,9 +3436,9 @@ class DefNodeWrapper(FuncDefNode): ...@@ -3423,9 +3436,9 @@ class DefNodeWrapper(FuncDefNode):
self.star_arg.entry.cname, self.star_arg.entry.cname,
Naming.args_cname, Naming.args_cname,
self.star_arg.entry.cname)) self.star_arg.entry.cname))
if self.starstar_arg: if self.starstar_arg and self.starstar_arg.entry.cf_used:
code.putln("{") code.putln("{")
code.put_decref_clear(self.starstar_arg.entry.cname, py_object_type) code.put_xdecref_clear(self.starstar_arg.entry.cname, py_object_type)
code.putln("return %s;" % self.error_value()) code.putln("return %s;" % self.error_value())
code.putln("}") code.putln("}")
else: else:
......
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