self.temps_free[type] = freelist
freelist.append(name)
+ def temps_in_use(self):
+ """Return a list of (cname,type) tuples of temp names and their type
+ that are currently in use.
+ """
+ used = []
+ for name, type in self.temps_allocated:
+ freelist = self.temps_free.get(type)
+ if freelist is None or name not in freelist:
+ used.append((name, type))
+ return used
+
+ def py_temps_in_use(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.
+ """
+ return [(name, type)
+ for name, type in self.temps_in_use()
+ if type.is_pyobject]
+
class GlobalState(object):
# filename_table {string : int} for finding filename table indexes
# filename_list [string] filenames in filename table order
if code.error_label in code.labels_used:
code.put_goto(code.return_label)
code.put_label(code.error_label)
+ # 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:
+ code.put_xdecref(cname, type)
# Clean up buffers -- this calls a Python function
# so need to save and restore error state
"%s = %s;" % (
Naming.retval_cname,
self.return_type.default_value))
+ # free temps the old way
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():
+ code.put_decref_clear(cname, type)
#code.putln(
# "goto %s;" %
# code.return_label)
class TempHandle(object):
temp = None
+ needs_xdecref = False
def __init__(self, type):
self.type = type
+ self.needs_cleanup = type.is_pyobject
def ref(self, pos):
return TempRefNode(pos, handle=self, type=self.type)
+ def cleanup_ref(self, pos):
+ return CleanupTempRefNode(pos, handle=self, type=self.type)
+
class TempRefNode(AtomicExprNode):
# handle TempHandle
def generate_assignment_code(self, rhs, code):
if self.type.is_pyobject:
rhs.make_owned_reference(code)
+ # TODO: analyse control flow to see if this is necessary
code.put_xdecref(self.result(), self.ctype())
code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
rhs.generate_post_assignment_code(code)
+class CleanupTempRefNode(TempRefNode):
+ # handle TempHandle
+
+ def generate_assignment_code(self, rhs, code):
+ pass
+
+ def generate_execution_code(self, code):
+ if self.type.is_pyobject:
+ code.put_decref_clear(self.result(), self.type)
+ self.handle.needs_cleanup = False
+
class TempsBlockNode(Node):
"""
Creates a block which allocates temporary variables.
handle.temp = code.funcstate.allocate_temp(handle.type)
self.body.generate_execution_code(code)
for handle in self.temps:
+ if handle.needs_cleanup:
+ if handle.needs_xdecref:
+ code.put_xdecref_clear(handle.temp, handle.type)
+ else:
+ code.put_decref_clear(handle.temp, handle.type)
code.funcstate.release_temp(handle.temp)
def analyse_control_flow(self, env):