Commit 218a35f3 authored by Stefan Behnel's avatar Stefan Behnel

free new style temps when catching exceptions

parent 71265979
...@@ -184,6 +184,17 @@ class FunctionState(object): ...@@ -184,6 +184,17 @@ class FunctionState(object):
for cname, type, manage_ref in self.temps_allocated for cname, type, manage_ref in self.temps_allocated
if manage_ref] 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): class GlobalState(object):
# filename_table {string : int} for finding filename table indexes # filename_table {string : int} for finding filename table indexes
# filename_list [string] filenames in filename table order # filename_list [string] filenames in filename table order
......
...@@ -3926,7 +3926,7 @@ class TryExceptStatNode(StatNode): ...@@ -3926,7 +3926,7 @@ class TryExceptStatNode(StatNode):
# body StatNode # body StatNode
# except_clauses [ExceptClauseNode] # except_clauses [ExceptClauseNode]
# else_clause StatNode or None # 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"] child_attrs = ["body", "except_clauses", "else_clause"]
...@@ -3993,6 +3993,7 @@ class TryExceptStatNode(StatNode): ...@@ -3993,6 +3993,7 @@ class TryExceptStatNode(StatNode):
self.body.generate_execution_code(code) self.body.generate_execution_code(code)
code.putln( code.putln(
"}") "}")
temps_to_clean_up = code.funcstate.all_free_managed_temps()
code.error_label = except_error_label code.error_label = except_error_label
code.return_label = except_return_label code.return_label = except_return_label
if self.else_clause: if self.else_clause:
...@@ -4006,6 +4007,8 @@ class TryExceptStatNode(StatNode): ...@@ -4006,6 +4007,8 @@ class TryExceptStatNode(StatNode):
code.put_goto(try_end_label) code.put_goto(try_end_label)
code.put_label(our_error_label) code.put_label(our_error_label)
code.put_var_xdecrefs_clear(self.cleanup_list) 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: for except_clause in self.except_clauses:
except_clause.generate_handling_code(code, except_end_label) except_clause.generate_handling_code(code, except_end_label)
...@@ -4154,7 +4157,7 @@ class TryFinallyStatNode(StatNode): ...@@ -4154,7 +4157,7 @@ class TryFinallyStatNode(StatNode):
# body StatNode # body StatNode
# finally_clause 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 # The plan is that we funnel all continue, break
# return and error gotos into the beginning of the # return and error gotos into the beginning of the
...@@ -4215,6 +4218,7 @@ class TryFinallyStatNode(StatNode): ...@@ -4215,6 +4218,7 @@ class TryFinallyStatNode(StatNode):
code.funcstate.in_try_finally = was_in_try_finally code.funcstate.in_try_finally = was_in_try_finally
code.putln( code.putln(
"}") "}")
temps_to_clean_up = code.funcstate.all_free_managed_temps()
code.putln( code.putln(
"/*finally:*/ {") "/*finally:*/ {")
cases_used = [] cases_used = []
...@@ -4246,7 +4250,7 @@ class TryFinallyStatNode(StatNode): ...@@ -4246,7 +4250,7 @@ class TryFinallyStatNode(StatNode):
#if new_label and new_label != "<try>": #if new_label and new_label != "<try>":
if new_label == new_error_label and self.preserve_exception: if new_label == new_error_label and self.preserve_exception:
self.put_error_catcher(code, self.put_error_catcher(code,
new_error_label, i+1, catch_label) new_error_label, i+1, catch_label, temps_to_clean_up)
else: else:
code.put('%s: ' % new_label) code.put('%s: ' % new_label)
if exc_var_init_zero: if exc_var_init_zero:
...@@ -4290,7 +4294,7 @@ class TryFinallyStatNode(StatNode): ...@@ -4290,7 +4294,7 @@ class TryFinallyStatNode(StatNode):
code.putln( 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.globalstate.use_utility_code(restore_exception_utility_code)
code.putln( code.putln(
"%s: {" % "%s: {" %
...@@ -4299,6 +4303,8 @@ class TryFinallyStatNode(StatNode): ...@@ -4299,6 +4303,8 @@ class TryFinallyStatNode(StatNode):
"__pyx_why = %s;" % "__pyx_why = %s;" %
i) i)
code.put_var_xdecrefs_clear(self.cleanup_list) 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( code.putln(
"__Pyx_ErrFetch(&%s, &%s, &%s);" % "__Pyx_ErrFetch(&%s, &%s, &%s);" %
Naming.exc_vars) Naming.exc_vars)
......
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