From: Stefan Behnel Date: Tue, 30 Dec 2008 11:19:52 +0000 (+0100) Subject: free new style temps when catching exceptions X-Git-Tag: 0.11-beta~65 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=218a35f344e5035268303c9ee9cbdd94534272f6;p=cython.git free new style temps when catching exceptions --- diff --git a/Cython/Compiler/Code.py b/Cython/Compiler/Code.py index ea918f0c..fda01609 100644 --- a/Cython/Compiler/Code.py +++ b/Cython/Compiler/Code.py @@ -184,6 +184,17 @@ class FunctionState(object): 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 diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index ae0a62ff..3bdeeae7 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -3926,7 +3926,7 @@ class TryExceptStatNode(StatNode): # 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"] @@ -3993,6 +3993,7 @@ class TryExceptStatNode(StatNode): 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: @@ -4006,6 +4007,8 @@ class TryExceptStatNode(StatNode): 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) @@ -4154,7 +4157,7 @@ class TryFinallyStatNode(StatNode): # 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 @@ -4215,6 +4218,7 @@ class TryFinallyStatNode(StatNode): 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 = [] @@ -4246,7 +4250,7 @@ class TryFinallyStatNode(StatNode): #if new_label and new_label != "": 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: @@ -4290,7 +4294,7 @@ class TryFinallyStatNode(StatNode): 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: {" % @@ -4299,6 +4303,8 @@ class TryFinallyStatNode(StatNode): "__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)