Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why does COMPUTE_FRAMES generate a lot of redundant instructions?

I’m writing a compiler that outputs JVM byte code, and using ASM 9.4 for the backend. This works fine, but I am puzzled about one particular quirk.

I’m specifying COMPUTE_FRAMES to automatically compute the stack frames. It is said that the tradeoff is that this (understandably) makes code generation take more time, but it seems to be fast enough.

What is not documented anywhere that I have been able to find, is that specifying COMPUTE_FRAMES causes a lot of redundant instructions to be generated. Specifically, an athrow at the end of each method, and in some cases, a bunch of long runs of nops scattered through the method.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

This does not seem to be doing any harm; my initial test cases are passing okay, and I suppose the JIT compiler won’t actually generate any machine code for the redundant instructions. But it is a little disconcerting. Why is it doing this? Am I doing anything wrong?

>Solution :

This is a sign that you have unreachable code in your generated bytecode. With stackmaps, every instruction not reachable by its preceding instruction must have a stack frame, even if not being the target of a branch. This is necessary to verify the code in a single linear pass.

But for unreachable code, there is no known initial state and it would be very challenging to invent a valid initial state for an arbitrary sequence of instructions. ASM’s solution is to replace the entire unreachable code with nop instructions, followed by a single athrow statement. For this sequence, it’s possible to specify a valid initial stack frame; it’s a frame having a single throwable on the stack. This sequence also has no impact on the subsequent, potentially reachable code.

Since the code is unreachable, this replacement has no impact on the execution, as you already noticed in your test. And you’re right, the JIT compiler won’t generate any native code for it.

But to git rid of this disconcerting code, you’d have to revise your compiler code, to find out at which part it generates unreachable code.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading