<html><body><div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000"><div><br></div><div><br></div><hr id="zwchr" data-marker="__DIVIDER__"><div data-marker="__HEADERS__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From: </b>"Archie Cobbs" <archie.cobbs@gmail.com><br><b>To: </b>"compiler-dev" <compiler-dev@openjdk.java.net><br><b>Sent: </b>Thursday, July 27, 2023 8:33:41 PM<br><b>Subject: </b>JDK-8308023 - Exponential classfile blowup with nested try/finally<br></blockquote></div><div data-marker="__QUOTED_TEXT__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir="ltr">This issue caught my eye: <a class="gmail-issue-link" href="https://bugs.openjdk.org/browse/JDK-8308023" id="gmail-key-val" rel="5100833" target="_blank">JDK-8308023</a> - Javac generates exponentially large class file with nested try catch statements<br><div>In a nutshell, since JSR/RET is no longer allowed/used, we now compile <span style="font-family:monospace">try { X } finally { Y }</span> into this:<br></div><br><div><span style="font-family:monospace"> X</span></div><div><span style="font-family:monospace">Y</span></div><div><span style="font-family:monospace"> goto L2<br></span></div><div><span style="font-family:monospace">L1:</span><span style="font-family:monospace">Store</span><span style="font-family:monospace"> exception in local e1<br></span></div><div><span style="font-family:monospace">Y</span></div><div><span style="font-family:monospace"> Load exception from local e1<br></span></div><div><span style="font-family:monospace"> Throw exception</span></div><div><span style="font-family:monospace">L2: ...<br></span></div><br><div>The<span style="font-family:monospace"> L1 </span><span style="font-family:arial,sans-serif">label is the</span> target for the exception range surrounding <span style="font-family:monospace">X</span>.</div><br><div>Note that the finally block <span style="font-family:monospace">Y</span> is duplicated.</div><br><div>This means that if we hare N nested finally's:<br></div><br><div><span style="font-family:monospace"> try {<br> X0<br> } finally {<br> try {<br> X1<br> } finally {<br> try {<br> X2<br> } finally {<br> .... try {<br> XN<br> } finally {<br> // done<br> ... }<br> }<br> }<br> }<br> }</span><br></div><br><div>then each block <span style="font-family:monospace">Xi</span> will be replicated 2^i times in the classfile.<br></div><br><div>Question: Can we solve this problem simply by avoiding the duplication of finally blocks?<br></div><br><div>What if we compiled <span style="font-family:monospace">try { X } finally { Y }</span> into this:</div><br><div><div><span style="font-family:monospace"> X</span></div><div><span style="font-family:monospace"> Store null in local e1 // new instruction<br></span></div><div><span style="font-family:monospace"> goto L2<br></span></div>L1:<span style="font-family:monospace"> Store exception in local e1<br></span><div><span style="font-family:monospace">L2:</span><span style="font-family:monospace">Y</span></div><div><span style="font-family:monospace"> Load exception from local e1<br></span></div><div><span style="font-family:monospace"> If null, goto L3 </span><span style="font-family:monospace">// new instruction</span></div><div><div><span style="font-family:monospace"> Load exception from local e1</span><span style="font-family:monospace">// new instruction</span></div><span style="font-family:monospace"> Throw exception</span></div><div><span style="font-family:monospace">L3: ...<br></span></div><br><div>There are three new instructions, so in trivial cases this would make the classfile larger. But in the highly nested cases it would change the classfile growth from exponential to linear.</div><br><div>Thoughts? What am I missing?</div></div></div></blockquote><div><br></div><div>It's a well known issue since the introduction of the split-verifier, the alternative is exponential verification time.<br></div><div>If you try to generate the code above most JITs will refuse to optimize the code, sharing the nominal path and the exception path is a big no no.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>The official workaround if there are a lot on enclosed try/finally blocks is to use several methods.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir="ltr"><div><div><br></div><br><div>-Archie</div></div></div></blockquote><div><br></div><div>regards,<br data-mce-bogus="1"></div><div>RĂ©mi<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir="ltr"><div><div><br></div><br><span class="gmail_signature_prefix">-- </span><br><div dir="ltr" class="gmail_signature">Archie L. Cobbs</div></div></div><br></blockquote></div></div></body></html>