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, ...@@ -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 # before raising the exception. A failure of reacquisition
# will cause the reacquisition exception to be reported, one # will cause the reacquisition exception to be reported, one
# can consider working around this later. # 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)] for i in range(3)]
code.putln('PyErr_Fetch(&%s, &%s, &%s);' % (type, value, tb)) code.putln('PyErr_Fetch(&%s, &%s, &%s);' % (type, value, tb))
code.putln('if (%s) {' % code.unlikely("%s == -1" % (getbuffer % lhs_cname))) code.putln('if (%s) {' % code.unlikely("%s == -1" % (getbuffer % lhs_cname)))
......
...@@ -40,7 +40,7 @@ class FunctionState(object): ...@@ -40,7 +40,7 @@ class FunctionState(object):
self.in_try_finally = 0 self.in_try_finally = 0
self.exc_vars = None 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_free = {} # type -> list of free vars
self.temps_used_type = {} # name -> type self.temps_used_type = {} # name -> type
self.temp_counter = 0 self.temp_counter = 0
...@@ -104,12 +104,17 @@ class FunctionState(object): ...@@ -104,12 +104,17 @@ class FunctionState(object):
def label_used(self, lbl): def label_used(self, lbl):
return lbl in self.labels_used 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 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 allocated and released one of the same type). Type is simply registered
and handed back, but will usually be a PyrexType. 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. A C string referring to the variable is returned.
""" """
freelist = self.temps_free.get(type) freelist = self.temps_free.get(type)
...@@ -120,7 +125,7 @@ class FunctionState(object): ...@@ -120,7 +125,7 @@ class FunctionState(object):
self.temp_counter += 1 self.temp_counter += 1
result = "%s%d" % (Naming.codewriter_temp_prefix, self.temp_counter) result = "%s%d" % (Naming.codewriter_temp_prefix, self.temp_counter)
if not result in self.names_taken: break 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 self.temps_used_type[result] = type
return result return result
...@@ -138,23 +143,24 @@ class FunctionState(object): ...@@ -138,23 +143,24 @@ class FunctionState(object):
freelist.append(name) freelist.append(name)
def temps_in_use(self): 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. that are currently in use.
""" """
used = [] used = []
for name, type in self.temps_allocated: for name, type, manage_ref in self.temps_allocated:
freelist = self.temps_free.get(type) freelist = self.temps_free.get(type)
if freelist is None or name not in freelist: if freelist is None or name not in freelist:
used.append((name, type)) used.append((name, type, manage_ref))
return used 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 """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) return [(name, type)
for name, type in self.temps_in_use() for name, type, manage_ref in self.temps_in_use()
if type.is_pyobject] if (type.is_pyobject and manage_ref)]
class GlobalState(object): class GlobalState(object):
# filename_table {string : int} for finding filename table indexes # filename_table {string : int} for finding filename table indexes
...@@ -674,7 +680,7 @@ class CCodeWriter(object): ...@@ -674,7 +680,7 @@ class CCodeWriter(object):
self.putln(";") self.putln(";")
def put_temp_declarations(self, func_context): 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) decl = type.declaration_code(name)
if type.is_pyobject: if type.is_pyobject:
self.putln("%s = NULL;" % decl) self.putln("%s = NULL;" % decl)
......
...@@ -1063,8 +1063,8 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1063,8 +1063,8 @@ class FuncDefNode(StatNode, BlockNode):
# cleanup temps the old way # cleanup temps the old way
code.put_var_xdecrefs(lenv.temp_entries) code.put_var_xdecrefs(lenv.temp_entries)
# cleanup temps the new way # cleanup temps the new way
for cname, type in code.funcstate.temps_allocated: for cname, type, manage_ref in code.funcstate.temps_allocated:
if type.is_pyobject: if type.is_pyobject and manage_ref:
code.put_xdecref(cname, type) code.put_xdecref(cname, type)
# Clean up buffers -- this calls a Python function # Clean up buffers -- this calls a Python function
...@@ -2369,7 +2369,7 @@ class PyClassDefNode(ClassDefNode): ...@@ -2369,7 +2369,7 @@ class PyClassDefNode(ClassDefNode):
def as_cclass(self): 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 bases = self.classobj.bases.args
if len(bases) == 0: if len(bases) == 0:
...@@ -3296,7 +3296,7 @@ class ReturnStatNode(StatNode): ...@@ -3296,7 +3296,7 @@ class ReturnStatNode(StatNode):
for entry in self.temps_in_use: for entry in self.temps_in_use:
code.put_var_decref_clear(entry) code.put_var_decref_clear(entry)
# free temps the new way # 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.put_decref_clear(cname, type)
#code.putln( #code.putln(
# "goto %s;" % # "goto %s;" %
......
...@@ -79,7 +79,7 @@ class TempsBlockNode(Node): ...@@ -79,7 +79,7 @@ class TempsBlockNode(Node):
def generate_execution_code(self, code): def generate_execution_code(self, code):
for handle in self.temps: 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) self.body.generate_execution_code(code)
for handle in self.temps: for handle in self.temps:
if handle.needs_cleanup: 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