Let's restate the question:
Is the Java HotSpot compiler able to change a method from interpreted to compiled in the middle of its execution?
I think it can.
The task is not easy for the engine (I collected some experience in that field when working on an Ahead-of-Time compiler called JUMP for the PalmOS handhelds years ago). When the engine decides to switch, it must consider the following points, at least:
Where is the program counter? In interpreted code, it's at some bytecode offset from the beginning of the method, knowing exactly which bytecode to execute next. In optimized native code, typically the JVM bytecodes don't translate to isolated blocks of machine instructions, but are dependent on one another, rearranged out-of order and so on. So there might not be a native instruction address that exactly corresponds to the bytecode program counter when switching.
Where are the data? The interpreter (probably) keeps everything on the stack, optimized native code uses a mixture of register and stack allocation that will be different for different places in the native translation.
So I read the HotSpot whitepaper. It doesn't answer the question explicitly, but there's a hint under "deoptimization". When a new class is loaded dynamically or even replaced inside a debugging session, previous optimizations like inlining can become invalid.
Therefore the Java HotSpot VM must be able to dynamically deoptimize
(and then reoptimize, if necessary) previously optimized hot spots,
even while executing code for the hot spot.
This is also switching between compiled and interpreted code, only the other way round. As this is documented behaviour of the HotSpot engine, I come to the conclusion that the switch from interpreted to compiled code within a currently executing method call is possible.
EDIT:
I wasn't explicit enough about what I understood as being the core of the question.
I understood there's a method doing a loop with 10000 iterations as follows:
void loop() {
for (int i=0; i<10000; i++) {
// example loop body
objects[i].doSomething();
}
}
After e.g. 4000 iterations the HotSpot compiler has optimized that method. What happens then?
There are two aspects, one trivial and one complex:
The trivial one is that calls that happen inside the loop (e.g. doSomething()
) will call their compiled version as soon as it's available. I didn't mention this in my original answer as I took that for granted.
The complex aspect is: will the currently-running loop()
execution switch from interpreted to compiled code at i=4000? That's what I understood to be the OP's question.