Volume of temporary variables - does Eclipse / compiler optimize?

First of all, I ask those who have the phobia of "premature optimization" to spare me: I do not want to optimize anything, I'm just interested.

I read / observed two things, including in stackoverflow (now I can not find the link):

  • For method calls, memory for all local variables is reserved "at the beginning" of the method, that is, even for variables declared in lower-level areas (I know that this is a bad formulation from a scientific point of view, for example, ignoring how the call mechanism works, etc.) .d., but I hope this is clear). Obviously, there are no scopes for the running program, they are only at the source code level for better readability, versatility, code structuring, informing the compiler of our intentions (for example, giving optimization tips, see below).
  • One of the advantages of declaring variables in the smallest possible area (that is, the highest level where they are still needed) is that "the compiler can reuse memory for other temporary variables (in other blocks)." It sounds clear and logical to me.

I'm curious that the / JIT / compiler can really optimize something and that it cannot.

Here is the following method (suppose variables are actually used, so for this reason they cannot be optimized):

// 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.) Can the compiler detect that the space for var2 and var3 can be reused for var4 and var5 ? I donโ€™t remember seeing such things in disassembled byte codes.

2.) Is the code method above equivalent to the case where the end of the method is placed in {} 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, consider 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, is it possible to use var1 memory for var4 (or var5 )? That is, in this case it is enough that the method has memory for two local int variables, and not for three.

(I know that in theory these are obvious cases for the compiler, but sometimes I skip things, for example, why the compiler cannot do anything or do something.)

+4
source share
2 answers
  • Yes. The stack slot can be reused after nested}, and I saw that javac does this.

  • Yes. Cases 1 and 2 are equivalent. The second nested {} does not change anything, unless something follows it.

  • The Java compiler will not optimize this, although theoretically considering all the right conditions, he could do it. If the variables are final, it is possible not to assign a slot to them.

Another thing you should note is that there is no bytecode command corresponding to the nested}, so the JVM and therefore HotSpot have no reason to know where the nested area ends and therefore where the stack slot changes.

+1
source

I can speak for compilers for real processors, Iโ€™m not sure about the JVM compiler, and I donโ€™t think that when compiling, the level code is optimized as much as you think (the Java platform just does not care too much for memory, as you can imagine).

For real compilers, these scripts are actually optimized very often. This is not done at the high level, but at a lower intermediate level, for example, at the RTL level. Everything is done for the purpose of register allocation or stack allocation and works by calculating living sets for variables inside functions.

This means that when compiling the code, everything is translated into RTL, assuming an arbitrary number of temporary registers, and then for each temporary one, its living state is calculated using the so-called analysis of variable variables . This is just one way to optimize such things.

For instance,

  • var1 live scope - from 1 to 10
  • var2 live scope is an instruction from 5 to 17
  • var3 live scope is an instruction from 3 to 25
  • etc.

This is done after the code is divided into blocks that do not contain transitions or labels, so that you are confident in the flow inside any specified block.

After this calculation, you can easily see which variables are needed for most of the time, which become useless and can free up their reserved space and so on. This is done so that you can insert as many variables as possible into the registers and repeatedly optimize the assembled code.

Personally, I donโ€™t think javac does this (even because the JVM is stack-based, so it just breaks the memory allocation on objects without any need these days), but this is just an assumption.

+3
source

All Articles