# 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)))
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
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)
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
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
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)
# 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
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:
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;" %