Commit 7b49db41 authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

Introduced manage_ref parameter in funcstate.allocate_temp and used it to fix crash bug.

parent 55c6aaa9
......@@ -298,7 +298,7 @@ def put_assign_to_buffer(lhs_cname, rhs_cname, buffer_aux, buffer_type,
# before raising the exception. A failure of reacquisition
# will cause the reacquisition exception to be reported, one
# can consider working around this later.
type, value, tb = [code.funcstate.allocate_temp(PyrexTypes.py_object_type)
type, value, tb = [code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=False)
for i in range(3)]
code.putln('PyErr_Fetch(&%s, &%s, &%s);' % (type, value, tb))
code.putln('if (%s) {' % code.unlikely("%s == -1" % (getbuffer % lhs_cname)))
......
......@@ -40,7 +40,7 @@ class FunctionState(object):
self.in_try_finally = 0
self.exc_vars = None
self.temps_allocated = [] # of (name, type)
self.temps_allocated = [] # of (name, type, manage_ref)
self.temps_free = {} # type -> list of free vars
self.temps_used_type = {} # name -> type
self.temp_counter = 0
......@@ -104,12 +104,17 @@ class FunctionState(object):
def label_used(self, lbl):
return lbl in self.labels_used
def allocate_temp(self, type):
def allocate_temp(self, type, manage_ref=True):
"""
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
and handed back, but will usually be a PyrexType.
If type.is_pyobject, manage_ref comes into play. If manage_ref is set to
True, the temp will be decref-ed on return statements and in exception
handling clauses. Otherwise the caller has to deal with any reference
counting of the variable.
A C string referring to the variable is returned.
"""
freelist = self.temps_free.get(type)
......@@ -120,7 +125,7 @@ class FunctionState(object):
self.temp_counter += 1
result = "%s%d" % (Naming.codewriter_temp_prefix, self.temp_counter)
if not result in self.names_taken: break
self.temps_allocated.append((result, type))
self.temps_allocated.append((result, type, manage_ref))
self.temps_used_type[result] = type
return result
......@@ -138,23 +143,24 @@ class FunctionState(object):
freelist.append(name)
def temps_in_use(self):
"""Return a list of (cname,type) tuples of temp names and their type
"""Return a list of (cname,type,manage_ref) tuples of temp names and their type
that are currently in use.
"""
used = []
for name, type in self.temps_allocated:
for name, type, manage_ref in self.temps_allocated:
freelist = self.temps_free.get(type)
if freelist is None or name not in freelist:
used.append((name, type))
used.append((name, type, manage_ref))
return used
def py_temps_in_use(self):
def temps_holding_reference(self):
"""Return a list of (cname,type) tuples of temp names and their type
that are currently in use. This includes only Python object types.
that are currently in use. This includes only temps of a
Python object type which owns its reference.
"""
return [(name, type)
for name, type in self.temps_in_use()
if type.is_pyobject]
for name, type, manage_ref in self.temps_in_use()
if (type.is_pyobject and manage_ref)]
class GlobalState(object):
# filename_table {string : int} for finding filename table indexes
......@@ -674,7 +680,7 @@ class CCodeWriter(object):
self.putln(";")
def put_temp_declarations(self, func_context):
for name, type in func_context.temps_allocated:
for name, type, manage_ref in func_context.temps_allocated:
decl = type.declaration_code(name)
if type.is_pyobject:
self.putln("%s = NULL;" % decl)
......
......@@ -1063,8 +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 in code.funcstate.temps_allocated:
if type.is_pyobject:
for cname, type, manage_ref in code.funcstate.temps_allocated:
if type.is_pyobject and manage_ref:
code.put_xdecref(cname, type)
# Clean up buffers -- this calls a Python function
......@@ -2369,7 +2369,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:
......@@ -3296,7 +3296,7 @@ class ReturnStatNode(StatNode):
for entry in self.temps_in_use:
code.put_var_decref_clear(entry)
# free temps the new way
for cname, type in code.funcstate.py_temps_in_use():
for cname, type in code.funcstate.temps_holding_reference():
code.put_decref_clear(cname, type)
#code.putln(
# "goto %s;" %
......
......@@ -79,7 +79,7 @@ class TempsBlockNode(Node):
def generate_execution_code(self, code):
for handle in self.temps:
handle.temp = code.funcstate.allocate_temp(handle.type)
handle.temp = code.funcstate.allocate_temp(handle.type, manage_ref=True)
self.body.generate_execution_code(code)
for handle in self.temps:
if handle.needs_cleanup:
......
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