Reputation: 15273
Suppose we have 3 methods: method 2 is called from method 1, method 3 is called from method 2. Methods 2 and 3 are of size 30 bytecodes each. Also, suppose for definiteness method 2 is always called from method 1 exactly once, and method 3 is always called from method 2 exaclty once.
If method 2 is inlined first, method 3 will be called from the body of method 1 directly, and could be inlined in its turn. If method 3 is inlined into method 2 first, the size of the latter will become about 60 bytecodes, and it couldn't be inlined, because default MaxInlineSize
threshold is 35 bytecodes.
In which order HotSpot JIT inlines methods: top-down or down-top?
Upvotes: 15
Views: 3425
Reputation: 298153
The MaxInlineSize
affects compilations of methods executed at least one time but less than MinInliningThreshold
times only. For methods executed more than MinInliningThreshold
there is a different setting -XX:FreqInlineSize=…
having a far bigger (platform dependent) default value. Hotspots are still inlined regardless of the MaxInlineSize
. You may test it by running an application with -XX:+UnlockDiagnosticVMOptions
-XX:+PrintInlining
-XX:MaxInlineSize=0
. It will still report inlining of hot spots (these with the comment “(hot)”). Only methods formerly reported as inlined with the comment “executed < MinInliningThreshold times” might then get the comment to “too big”. If you set down the FreqInlineSize
you might receive comments like “hot method too big”. I never saw them with the default setting.
Upvotes: 19
Reputation: 1489
Running the below code with the parameters reveals that both methods m3 is inlined first.
i used the following parameters for jvm: -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining
. Apparenly the method who's first execution count reaches the inlining threshold is inlined first. In our case m3. So for the hotspot i used for testing is down-top as m3
is first executed and the m2
execution ends.
Code was run with jdk7_u40 with TieredCompilation disabled, server mode on windows 8 box. Output of the command was:
@ 66 java.lang.String::indexOfSupplementary (71 bytes) too big
@ 21 methodTest::m3 (31 bytes) inline (hot)
@ 11 methodTest::m2 (35 bytes) inline (hot)
@ 21 methodTest::m3 (31 bytes) inline (hot)
@ 14 methodTest::m1 (25 bytes) inline (hot)
@ 11 methodTest::m2 (35 bytes) inline (hot)
@ 21 methodTest::m3 (31 bytes) inline (hot)
m1
is 25 bytes
in size, m2
is 35 bytes
and m3
has 31 bytes
.
public class methodTest {
public static void main(String[] args) {
doTest();
}
int i = 0;
int j = 0;
int k = 0;
private static void doTest() {
methodTest m = new methodTest();
for (int i = 0; i < 1000000000; i++) {
m.m1();
}
System.out.println(m.i);
System.out.println(m.j);
System.out.println(m.k);
}
private void m1() {
i++;
m2();
j++;
}
private void m2() {
i++;
i++;
m3();
j++;
}
private void m3() {
i++;
j++;
k++;
}
}
Upvotes: 3