Do any compilers for the JVM use the "wide" goto?
There is no reason to use goto_w
when the branch fits into a goto
. But you seem to have missed that the branches are relative, using a signed offset, as a branch can also go backward.
You don’t notice it when looking at the output of a tool like javap
, as it calculates the resulting absolute target address before printing.
So goto
’s range of -327678 … +32767
is not always enough to address each possible target location in the 0 … +65535
range.
For example, the following method will have a goto_w
instruction at the beginning:
public static void methodWithLargeJump(int i) {
for(; i == 0;) {
try {x();} finally { switch(i){ case 1: try {x();} finally { switch(i){ case 1:
try {x();} finally { switch(i){ case 1: try {x();} finally { switch(i){ case 1:
try {x();} finally { switch(i){ case 1: try {x();} finally { switch(i){ case 1:
try {x();} finally { switch(i){ case 1: try {x();} finally { switch(i){ case 1:
try {x();} finally { switch(i){ case 1: try {x();} finally { switch(i){ case 1:
} } } } } } } } } } } } } } } } } } } }
}
}
static void x() {}
Demo on Ideone
Compiled from "Main.java"
class LargeJump {
public static void methodWithLargeJump(int);
Code:
0: iload_0
1: ifeq 9
4: goto_w 57567
…
The size of the method code can be as large as 64K.
The branch offset of the short goto
is a signed 16-bit integer: from -32768 to 32767.
So, the short offset is not enough to make a jump from the beginning of 65K method to the end.
Even javac
sometimes emits goto_w
. Here is an example:
public class WideGoto {
public static void main(String[] args) {
for (int i = 0; i < 1_000_000_000; ) {
i += 123456;
// ... repeat 10K times ...
}
}
}
Decompiling with javap -c
:
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_1
2: iload_1
3: ldc #2
5: if_icmplt 13
8: goto_w 50018 // <<< Here it is! A jump to the end of the loop
...