for cname, type, manage_ref in self.temps_allocated
if manage_ref]
+ def all_free_managed_temps(self):
+ """Return a list of (cname, type) tuples of refcount-managed Python
+ objects that are not currently in use. This is used by
+ try-except and try-finally blocks to clean up temps in the
+ error case.
+ """
+ return [(cname, type)
+ for (type, manage_ref), freelist in self.temps_free.iteritems()
+ if manage_ref
+ for cname in freelist]
+
class GlobalState(object):
# filename_table {string : int} for finding filename table indexes
# filename_list [string] filenames in filename table order
# body StatNode
# except_clauses [ExceptClauseNode]
# else_clause StatNode or None
- # cleanup_list [Entry] temps to clean up on error
+ # cleanup_list [Entry] old style temps to clean up on error
child_attrs = ["body", "except_clauses", "else_clause"]
self.body.generate_execution_code(code)
code.putln(
"}")
+ temps_to_clean_up = code.funcstate.all_free_managed_temps()
code.error_label = except_error_label
code.return_label = except_return_label
if self.else_clause:
code.put_goto(try_end_label)
code.put_label(our_error_label)
code.put_var_xdecrefs_clear(self.cleanup_list)
+ for temp_name, type in temps_to_clean_up:
+ code.put_xdecref_clear(temp_name, type)
for except_clause in self.except_clauses:
except_clause.generate_handling_code(code, except_end_label)
# body StatNode
# finally_clause StatNode
#
- # cleanup_list [Entry] temps to clean up on error
+ # cleanup_list [Entry] old_style temps to clean up on error
#
# The plan is that we funnel all continue, break
# return and error gotos into the beginning of the
code.funcstate.in_try_finally = was_in_try_finally
code.putln(
"}")
+ temps_to_clean_up = code.funcstate.all_free_managed_temps()
code.putln(
"/*finally:*/ {")
cases_used = []
#if new_label and new_label != "<try>":
if new_label == new_error_label and self.preserve_exception:
self.put_error_catcher(code,
- new_error_label, i+1, catch_label)
+ new_error_label, i+1, catch_label, temps_to_clean_up)
else:
code.put('%s: ' % new_label)
if exc_var_init_zero:
code.putln(
"}")
- def put_error_catcher(self, code, error_label, i, catch_label):
+ def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
code.globalstate.use_utility_code(restore_exception_utility_code)
code.putln(
"%s: {" %
"__pyx_why = %s;" %
i)
code.put_var_xdecrefs_clear(self.cleanup_list)
+ for temp_name, type in temps_to_clean_up:
+ code.put_xdecref_clear(temp_name, type)
code.putln(
"__Pyx_ErrFetch(&%s, &%s, &%s);" %
Naming.exc_vars)