<div dir="ltr"><div dir="ltr">On Fri, Jul 28, 2023 at 3:17 AM Jan Lahoda <<a href="mailto:jan.lahoda@oracle.com">jan.lahoda@oracle.com</a>> wrote:</div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div>I believe a few of us were looking at this some time ago.</div></blockquote><div><br></div><div>I played around with this some more and now realize there is a bigger (and more subtle) obstacle with this idea or any other similar variant that attempts to "reuse" the same finally block bytecode for both normal and exceptional execution paths.<br></div><div><br></div><div>Suppose you have code like this:<br></div><div><br></div><div style="margin-left:40px"><span style="font-family:monospace">public int method() {<br>   int x;</span></div><div style="margin-left:40px"><span style="font-family:monospace">   </span><span style="font-family:monospace">try {</span></div><div style="margin-left:40px"><span style="font-family:monospace">   </span><span style="font-family:monospace">   </span><span style="font-family:monospace">x = 7;</span></div><div style="margin-left:40px"><span style="font-family:monospace">   </span><span style="font-family:monospace">} finally {</span></div><div style="margin-left:40px"><span style="font-family:monospace">  </span><span style="font-family:monospace">   </span><span style="font-family:monospace">doWhatever();</span></div><div style="margin-left:40px"><span style="font-family:monospace">   </span><span style="font-family:monospace">}</span></div><div style="margin-left:40px"><span style="font-family:monospace">   </span><span style="font-family:monospace">return x;</span></div><div style="margin-left:40px"><span style="font-family:monospace">}<br></span></div><div><br></div><div>If the finally block is only emitted once, then there must be two possible exit paths out of it - one where it rethrows some caught exception, and the other where it falls through to the return statement.</div><div><br></div><div>My idea was to store the caught exception (in the former case) or a null placeholder (in the latter case) in a local variable as a way of telling the finally block which exit path to take:</div><div><span style="font-family:monospace"><br></span></div><div style="margin-left:40px"><span style="font-family:monospace">public int method();<br>  descriptor: ()I<br>  Code:<br>    0: bipush     7<br>    2: istore_1<br>    3: aconst_null<br>    4: astore_2<br>    5: aload_0<br>    6: invokevirtual #14         // Method doWhatever:()V<br>    9: aload_2<br>   10: ifnull     15<br>   13: aload_2<br>   14: athrow<br>   15: iload_1<br>   16: ireturn<br>  Exception table:<br>    from   to  target type<br>      0   4   4  any</span><br></div><div><br></div><div>The problem is that there's no way to prove to the verifier that in the second case, the local variable corresponding to 'x' (Local#1) is always definitely assigned, even though of course we know that it always will be in that case. So you get a 'Bad local variable type' verifier error.<br></div></div><div class="gmail_quote"><br></div><div class="gmail_quote">This could be worked-around by initializing, prior to entering the try block, the locals that get (a) assigned for the first time within the try block and (b) referenced in the finally block. Not very elegant though.<br></div><div class="gmail_quote"><br></div><div class="gmail_quote">In summary, JSR/RET is gone now, and the verifier also makes it difficult to synthesize "subroutines". This makes the compiler's job a lot harder wrt. finally blocks.<br></div><div class="gmail_quote"><br></div><div class="gmail_quote">-Archie<br></div><div class="gmail_quote"><br></div><span class="gmail_signature_prefix">-- </span><br><div dir="ltr" class="gmail_signature">Archie L. Cobbs<br></div></div>