Reputation: 4412
If I have two constants known at compile time, the Java compiler will fold them.
final static int foo = 2;
final static int bar = 17;
int myVariable;
int myFunction(){
return foo*bar + myVariable;
}
At runtime, myFunction will return 34 + myVariable, and won't need to calculate 2*17 as that was done at compile time.
My question is: would it do the same if the constants aren't known until runtime? I believe this is called runtime code specialization.
final int foo;
final int bar;
int myVariable;
int myFunction(){
return foo*bar + myVariable;
}
If foo and bar were initialised as 2 and 17 in the object's constructor, would myFunction be specialised to return 34 + myVariable, or would it still calculate foo*bar every time the function was called, even though foo*bar would never change?
*Edit: I'm referring to the newest version of the JVM, 1.7.0_45.
Upvotes: 3
Views: 739
Reputation: 2143
mov r10d,DWORD PTR [rsi+0x8]
shl r10,0x3
cmp rax,r10
jne 0x00007fb509045b60 ; {runtime_call}
data32 xchg ax,ax
nop WORD PTR [rax+rax*1+0x0]
nop WORD PTR [rax+rax*1+0x0]
[Verified Entry Point]
sub rsp,0x18
mov QWORD PTR [rsp+0x10],rbp ;*synchronization entry
;- Main$TestClass::myFunction@-1 (line 25)
mov eax,DWORD PTR [rsi+0x10]
imul eax,DWORD PTR [rsi+0xc]
add eax,DWORD PTR [rsi+0x14] ;*iadd
;- Main$TestClass::myFunction@13 (line 25)
add rsp,0x10
pop rbp
test DWORD PTR [rip+0x15f7a8bf],eax # 0x00007fb51f087000
;{poll_return}
ret
public class Main {
public static void main(String... args) {
int accm = 0;
TestClass t = new TestClass(542,452);
while(true){
t.myVariable = accm;
accm += t.myFunction();
if(false) break;
}
System.out.println(accm);
}
public static class TestClass{
final int foo;
final int bar;
public int myVariable = 2;
public TestClass(int foo, int bar){
this.foo = foo;
this.bar = bar;
}
int myFunction(){
return foo*bar + myVariable;
}
}
}
java version "1.8.0-ea"
Java(TM) SE Runtime Environment (build 1.8.0-ea-b124)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b66, mixed mode)
No, it can't.
While I do not understand most of what is going on there, it appears that the function has been inlined into the loop at [Verified Entry Point]
, but that the constants are not folded because there is a multiplication is still occurring at imul eax,DWORD PTR [rsi+0xc]
.
Upvotes: 2
Reputation: 136082
I have JDK 1.7.0_45 and I compiled this code
class X {
final int foo;
final int bar;
X() {
foo = 2;
bar = 17;
}
int myVariable;
int myFunction() {
return foo * bar + myVariable;
}
and got this bytecote for myFunction
myFunction()I
L0
LINENUMBER 22 L0
ALOAD 0
GETFIELD test/X.foo : I <-- load 2
ALOAD 0
GETFIELD test/X.bar : I <-- load 17
IMUL <-- 2 x 17
ALOAD 0
GETFIELD test/X.myVariable : I
IADD
IRETURN
so answer to "would it calculate foo*bar every time the function was called?" is yes (unless JVM optimizes it)
Upvotes: 4
Reputation: 41208
Foo and Bar would never change in that instance they could well be different in different instances though and the system doesn't compile the code separately for every instance of every object. The overhead from doing so would be terrible.
It's possible that the system may detect this but its unlikely, and you certainly couldn't expect all or even most environments to do so. Your best bet will be to store foobar = foo*bar
yourself and use that if you think the multiplication is going to have a significant performance impact. (Which is unlikely).
Upvotes: 7