@@ -26,7 +26,7 @@ struct BlockReducer: Reducer {
2626 reduceLoop ( loop: group. block ( 0 ) , in: & code, with: verifier)
2727
2828 case is BeginTry :
29- reduceTryCatch ( tryCatch: group, in: & code, with: verifier)
29+ reduceTryCatchFinally ( tryCatch: group, in: & code, with: verifier)
3030
3131 case is BeginIf :
3232 // We reduce ifs simply by removing the whole block group.
@@ -115,10 +115,10 @@ struct BlockReducer: Reducer {
115115 reduceGenericBlockGroup ( codestring, in: & code, with: verifier)
116116 }
117117
118- private func reduceTryCatch ( tryCatch: BlockGroup , in code: inout Code , with verifier: ReductionVerifier ) {
119- // We first try to remove only the try-catch block instructions.
118+ private func reduceTryCatchFinally ( tryCatch: BlockGroup , in code: inout Code , with verifier: ReductionVerifier ) {
119+ // We first try to remove only the try-catch-finally block instructions.
120120 // If that doesn't work, then we try to remove the try block including
121- // its last instruction but keepp the body of the catch block.
121+ // its last instruction but keep the body of the catch and/or finally block.
122122 // If the body isn't required, it will be removed by the
123123 // other reducers. On the other hand, this successfully
124124 // reduces code like
@@ -128,35 +128,40 @@ struct BlockReducer: Reducer {
128128 // throw 42;
129129 // } catch {
130130 // do_something_important2();
131+ // } finally {
132+ // do_something_important3();
131133 // }
132134 //
133135 // to
134136 //
135137 // do_something_important1();
136138 // do_something_important2();
139+ // do_something_important3();
137140 //
138141
139142 var candidates = [ Int] ( )
140143
141- candidates . append ( tryCatch [ 0 ] . index )
142- candidates. append ( tryCatch [ 1 ] . index)
143- candidates . append ( tryCatch [ 2 ] . index )
144+ for i in 0 ... tryCatch. numBlocks {
145+ candidates. append ( tryCatch [ i ] . index)
146+ }
144147
145148 if verifier. tryNopping ( candidates, in: & code) {
146149 return
147150 }
148151
152+ var removedLastTryBlockInstruction = false
149153 // Find the last instruction in try block and try removing that as well.
150154 for i in stride ( from: tryCatch [ 1 ] . index - 1 , to: tryCatch [ 0 ] . index, by: - 1 ) {
151155 if !( code [ i] . op is Nop ) {
152156 if !code[ i] . isBlock {
153157 candidates. append ( i)
158+ removedLastTryBlockInstruction = true
154159 }
155160 break
156161 }
157162 }
158163
159- if candidates . count == 4 && verifier. tryNopping ( candidates, in: & code) {
164+ if removedLastTryBlockInstruction && verifier. tryNopping ( candidates, in: & code) {
160165 return
161166 }
162167
@@ -168,15 +173,16 @@ struct BlockReducer: Reducer {
168173 // const v17 = Math(v16,v16);
169174 // }
170175 // } catch {
176+ // } finally {
171177 // }
172178 //
173- if candidates . count == 4 {
179+ if removedLastTryBlockInstruction {
174180 candidates. removeLast ( )
175181 }
176182
177- // Find last instruction in try block
183+ // Remove all instructions in the body of the try block
178184 for i in stride ( from: tryCatch [ 1 ] . index - 1 , to: tryCatch [ 0 ] . index, by: - 1 ) {
179- if !( tryCatch . code [ i] . op is Nop ) {
185+ if !( code [ i] . op is Nop ) {
180186 candidates. append ( i)
181187 }
182188 }
0 commit comments