templatetypedef
templatetypedef

Reputation: 373482

Can a compliant Java compiler optimize this code?

I was teaching an introductory programming course today and was walking through some simple code involving variable assignments in Java. The point of the code wasn't to show off anything particular exciting, but mostly to make sure students understood variable assignment statements.

I had the following method up on the board and was tracing through it one line at a time:

private void simpleMethod() {
    int myInt = 137;
    myInt = 42;
    myInt = myInt + 1;

    /* ... code using myInt ... */
}

A student asked me whether myInt would ever actually hold the values 137 and 42 when the program ran, or if it would just jump straight to holding 43. I told the student that the code would execute each line in turn, so the variable would actually hold these intermediate values.

Honestly, though, I wasn't sure what bytecode javac would emit (completely ignoring the optimizations done by the JVM). Is javac (or any Java compiler) legally allowed to optimize the silly assignment statements away and to instead just directly initialize myInt to 43?

According to javap, on my system, the above code compiled with javac produces

   0: sipush        137
   3: istore_1      
   4: bipush        42
   6: istore_1      
   7: iload_1       
   8: iconst_1      
   9: iadd          
  10: istore_1      
  11: return        

So there is no optimization going on here. My question, though, is whether it's legal to optimize this or not, so this doesn't resolve anything.

Upvotes: 16

Views: 909

Answers (4)

Alan
Alan

Reputation: 3895

Although this is true, my question is whether the compiler is legally permitted to do this optimization

By traditional data flow analysis (flow/transfer functions, in-sets, out-sets, gen-sets, kill-sets, etc.), specifically some-paths forward data flow, a.k.a. reaching definitions (or use-def chains)... yes. Essentially, the optimizer can link each use of a variable to the definitions that reach it.

In this case, an optimizer could determine that the initial definition of myInt (=137) never reaches its use, while the other definition (=42 1) does reach its use since it is never redefined on any (some) path from that definition to its use.

References:

  • Dragon book 1ed (1986) chapter 10
  • Dragon book 2ed (2007) chapter 9 (9.2 specifically)

1 - I use 42 all the time in my teaching code. I bet we all do.

Upvotes: 0

Peter Lawrey
Peter Lawrey

Reputation: 533880

So there is no optimization going on here.

This shouldn't be too surprising given Java uses dynamic compilation.

The JVM optimises almost all the code at runtime, this means that no matter whether you use code compiled for Java 1.0 in 1996 or Scala or JRuby, JGo etc, you get the full benefit of the optimisation to native code of your particular CPU model.

For this reason many languages have JVM implementations so they don't need to be able to produce optimal code for all the platforms the JVM runs on.

Upvotes: 0

yshavit
yshavit

Reputation: 43456

The JLS specifies only the contract of observable behavior that your program produces. Since myInt is local, the optimization can indeed be optimized at compile time, since this would produce a behavior consistent with the spec, and there's nothing in the spec that says it's not allowed (at least, not that I found!). Chapter 1 of the spec specifies the observable-ness of the spec explicitly: This document fully specifies the (apparent) order of evaluation of expressions.... Since the apparent behavior is unchanged by constant-folding to myInt = 43, the optimization would be consistent with the JLS.

In fact, the compilation target of a Java application isn't even specified in the JLS. Chapter 1 says that Java applications "normally" compile to the bytecode specified in the JVM spec (a separate document), but it does not require that they do so. There are some statements that must be optimized at compile time, but myInt is not one such. Even if myInt were a field, I think the optimization would be allowed; the different behavior would still be valid behavior, even if myInt is volatile (since it represents one valid ordering of events).

So, short answer, I think your student is correct; it's perfectly fine to optimize it to just myInt = 43. That said, javac generally does very little -- virtually nothing -- in the way of optimization. Optimizations are pretty much all done in the JIT.

Upvotes: 8

mikera
mikera

Reputation: 106401

I believe the Java compiler is allowed to do any constant folding that it can statically determine at compile time.

So yes, this could be optimised by javac.

However javac does not need to make this optimisation because the JVM JIT compiler will almost certainly do the same optimisation for you a bit further down the line. From that point of view, whether or not the Java -> Bytecode compiler does this optimisation is probably irrelevant in terms of impact on the actual native code executed at runtime.

Upvotes: 5

Related Questions