Thomas Calc
Thomas Calc

Reputation: 3014

Scope of temporary variables -- does Eclipse/compiler optimize?

First of all, I ask those with "premature optimization" phobia to spare me: I don't want to optimize anything, I'm just curious.

I read/observed two things, including on stackoverflow (can't find the link now):

I'm wondering what the compiler/JIT/whatever can actually optimize, and what it can't.

Here is the following method (assume that the variables are actually used, so they can't be optimized away for that reason):

// The method does many (useful) things, but these were cut here
public void myMethod() {
    int var1 = 1;
    ... // do work
    if (something) {
        int var2 = 2;
        int var3 = 3;
        ... // do work
    }
    int var4 = 4;
    int var5 = 5;
    ... // do work
}

1.) Is the compiler able to detect that the space for var2 and var3 can be reused for var4 and var5? I don't remember seeing such a thing in disassembled bytecodes.

2.) Is the code method above equivalent to the case when the end of the method is put to {} too?

public void myMethod() {
    int var1 = 1;
    ... // do work
    if (something) {
        int var2 = 2;
        int var3 = 3;
        ... // do work
    }
    {
        int var4 = 4;
        int var5 = 5;
        ... // do work
    }
}

Finally, let's see a simpler case:

public void myMethod() {
    int var1 = 1;
    ... // do work, and then don't refer to var1 any more

    int var4 = 4;
    int var5 = 5;
    ... // do work      
}

3.) In this case, can var1 memory be reused for var4 (or var5)? I.e. in such a case, it is enough for the method to have memory for two local int variables, not for three.

(I know that in theory, these are obvious cases for the compiler, but sometimes I overlook things e.g. why a compiler can't do or assume anything.)

Upvotes: 4

Views: 403

Answers (2)

user207421
user207421

Reputation: 311018

  1. Yes. The stack slot can be reused after the nested }, and I have seen javac do so.

  2. Yes. Cases 1 and 2 are equivalent. The second nested {} changes nothing, unless something follows it.

  3. The Java compiler won't optimize this, although in theory given all the right conditions it conceivably could. If the variables are final it is possible not to assign a slot for them at all.

Another thing you should note is that there is no byte code instruction corresponding to the nested }, so the JVM and therefore HotSpot has no basis for knowing where a nested scope ends and therefore where a stack slot changes usage.

Upvotes: 1

Jack
Jack

Reputation: 133609

I can speak for compilers for real CPUs, I'm not sure about JVM compiler and I don't think that at compile level code is optimized as much as you think (the Java platform simply don't care too much about memory foorprint as you can imagine).

For real compilers these scenarios are actually optimized very often. This is done not at high level language level but at a lower intermediate level like at RTL level. Everything is made with the purpose of register allocation or stack allocation and works by computing living sets for variables inside functions.

This means that when the code is compiled everything is translated to RTL by assuming an arbitrary number of temporary registers and then for each temporary, its live state is calculated through the so-called live variable analysis. This is just one of the ways to optimize such things.

Eg

  • var1 live scope is from instruction 1 to 10
  • var2 live scope is from instruction 5 to 17
  • var3 live scope is from instruction 3 to 25
  • and so on

This is done after having splitted the code into blocks which does not contain jumps or labels so that you are sure about the flow inside any specified block.

After this computation you can easily see which variables are needed for most time, which become useless and can free their reserved space and so on. This is done so that you are able to fit as much variables as possible into registers and optimize the assembled code a lot.

Personally I don't think the javac does any of this (even because the JVM is stack based so this would just break memory allocation on objects without any need nowadays), but my is just speculation.

Upvotes: 3

Related Questions