Two chefs.
Chef A gets really easy to use ingredients and produces a good dish with them.
Chef B gets rubbish ingredients but spends time doing amazing techniques with them anyway and produces a good dish as well, maybe even a bit better!
If this is all we know about the chefs, I'd say it looks like Chef B is the 'better' chef. It's not their fault they got worse ingredients, and they managed to do a great job with them.
You didn't need Chef B to handle Chef A's ingredients, because they were simple. Perhaps we should thank the supplier for that! But Chef B is still the 'better' chef.
It still might be nice if Chef A could do some of the amazing techniques that Chef B did, even though their ingredients mean they aren't required all of the time. They may help in some cases.
The .NET CLR JIT is Chef A, the JVM's HotSpot C2 JIT is Chef B.
I mean if we judge a JIT just by the quality of the output and don't consider the input, then reducing to absurdity an identity JIT for already-optimised machine code to the same machine code is the best JIT in the world. Clearly it isn't.
This is why people judge chefs independently from the ingredients they are given, but don't judge languages and implementations independently from each other. In the first case they are actually (mostly) independent in the real world, whereas in the second case they are frequently dependent on each other, and it is not possible to mix-and-match languages with compilers. (But I certainly do hope we get to a point where the latter would be possible, too.)
I would argue that it just isn't the case in practice that MSIL includes anything that would make optimisations that the JVM does significantly harder, but I only have my academic and professional experience working on both systems, nothing that I can cite or prove to you.
Well fine I welcome and respect your opinions on this topic, and you're not even wrong, but that's it's not remotely what anyone else is talking about in this thread!
We're talking about what the two main JIT compilers on the two teams have decided to implement, given the constraints they have from their input. We're not talking about how generics were implemented, or language design changes, because we're talking about how the JIT compilers work.