3

Background:

Before asking my question, I wish to state that I have checked the following links:

Identify loops in java byte code

goto in Java bytecode

http://blog.jamesdbloom.com/JavaCodeToByteCode_PartOne.html

I can detect the loops in the bytecode (class files) using dominator analysis algorithm-based approach of detecting back edges on the control-flow graphs (https://en.wikipedia.org/wiki/Control_flow_graph).

My problem:

After detection of loops, you can end up having two loops (defined by two distinct back edges) sharing the same loop head. This can be created by the following two cases as I have realized: (Case 1) In the source code, you have a for or while loop with a continue statement, (Case 2) In the source code, you have two loops - an outer loop that is a do-while and an inner loop; and no instructions between these loops.

My question is the following: By only looking at the bytecode, how can you distinguish between these two cases?

My thoughts:

In a do-while loop (that is without any continue statements), you don't expect a go-to statement that goes back to the loop head, in other words, creating a back edge.

For a while or for loop (that is again without any continue statements), it appears that there can be a go-to statement (I am not sure if there must be one). My compiler generates (I am using a standard 1.7 compiler) this go-to instruction outside of the loop, not as a back edge unlike what is mentioned in the given links (this go-to statement creates a control-flow to the head of the loop, but not as a jump back from the end of the loop).

So, my guess is, (repeating, in case of two back edges), if one of them is a back edge created by a go-to statement, then there is only one loop in the source code and it includes a continue statement (Case 1). Otherwise, there are two loops in the source code (Case 2).

Thank you.

Community
  • 1
  • 1

2 Answers2

4

When two loops are equivalent all you can do is to take the simplest one.

e.g. there is no way to tell the difference between while (true), do { } while (true) and for (;;)

If you have do { something(); } while (false) this loop might not appear in the byte code at all.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
3

As Peter Lawrey already pointed out, there is no way to determine the source code form by looking at the bytecode. To name an example closer to your intention, the following single-loop code

do action(); while(condition1() || condition2());

produces exactly the same code as the nested loop

do do action(); while(condition1()); while(condition2());

Likewise the following loop

do {
    action();
    if(condition1()) continue;
    break;
} while(condition2());

produces exactly the same code as

do action(); while(condition1() && condition2());

with current javac, whereas surprisingly

do {
    action();
    if(!condition1()) break;
} while(condition2());

does not, which only shows how much the exact form depends on compiler internals. The next version of javac might compile them differently.

Community
  • 1
  • 1
Holger
  • 285,553
  • 42
  • 434
  • 765