If the JVM has one bytecode compiler that it uses only during startup and another that it used the rest of the time, shouldn't it dump the bytecode generated by the first compiler from the cache at the point when it switches to the second compiler?
Now, sometimes optimizations can be "wrong", in the sense that something new has happened that invalidates an assumption used during second-tier compilation. Here's a real-world example: I have an interface and only one loaded class that implements that interface. The second-tier compiler will use this information to basically do this:
function doStuff(MyInterface a) {
if (a.getClass() != MyClass.class)
deoptimize();
// Do everything from here on assuming
// that a is an instance of MyClass.
// This includes inlining simple getter
// methods to pure field accesses, etc.
}
Now, when a second class that implements `MyInterface` is loaded and makes it to that function, it will hit the `deoptimize` branch and go back to first-tier or even interpreted mode. Eventually the function will be recompiled by both tiers with the new assumption -- two implementing classes.So, in the case of deoptimization, it can be a win to keep the first-tier code to fall-back to.
Yes, I agree if C2 recompiles something C1 already compiled, the C1-compiled machine code should be freed from the codecache.