@@ -18,8 +18,8 @@ which is almost like a regular function with a prolog and epilog. A
18
18
custom calling convention gives the funclet access to the parent stack
19
19
frame.
20
20
21
- In this proposal we outline two optimizations for finallys: removing
22
- empty finallys and finally cloning.
21
+ In this proposal we outline three optimizations for finallys: removing
22
+ empty trys, removing empty finallys and finally cloning.
23
23
24
24
Empty Finally Removal
25
25
---------------------
@@ -175,6 +175,42 @@ G_M60484_IG06:
175
175
Empty finally removal is unconditionally profitable: it should always
176
176
reduce code size and improve code speed.
177
177
178
+ Empty Try Removal
179
+ ---------------------
180
+
181
+ If the try region of a try-finally is empty, and the jitted code will
182
+ execute on a runtime that does not protect finally execution from
183
+ thread abort, then the try-finally can be replaced with just the
184
+ content of the finally.
185
+
186
+ Empty trys with non-empty finallys often exist in code that must run
187
+ under both thread-abort aware and non-thread-abort aware runtimes. In
188
+ the former case the placement of cleanup code in the finally ensures
189
+ that the cleanup code will execute fully. But if thread abort is not
190
+ possible, the extra protection offered by the finally is not needed.
191
+
192
+ Empty try removal looks for try-finallys where the try region does
193
+ nothing except invoke the finally. There are currently two different
194
+ EH implementation models, so the try screening has two cases:
195
+
196
+ * callfinally thunks (x64/arm64): the try must be a single empty
197
+ basic block that always jumps to a callfinally that is the first
198
+ half of a callfinally/always pair;
199
+ * non-callfinally thunks (x86/arm32): the try must be a
200
+ callfinally/always pair where the first block is an empty callfinally.
201
+
202
+ The screening then verifies that the callfinally identified above is
203
+ the only callfinally for the try. No other callfinallys are expected
204
+ because this try cannot have multiple leaves and its handler cannot be
205
+ reached by nested exit paths.
206
+
207
+ When the empty try is identified, the jit modifies the
208
+ callfinally/always pair to branch to the handler, modifies the
209
+ handler's return to branch directly to the continuation (the
210
+ branch target of the second half of the callfinally/always pair),
211
+ updates various status flags on the blocks, and then removes the
212
+ try-finally region.
213
+
178
214
Finally Cloning
179
215
---------------
180
216
0 commit comments