Search code examples
javajvmconstantfolding

Does the JVM do runtime constant folding?


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.


Solution

  • Hotspot Compiled Assembler

    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
    

    Java Code

    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

    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)
    

    Conclusions

    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].