Well, there are some close to native code speeds for some (very constrained) use-cases.
They way it's done is that if you use a certain stile of C the compiler will speculative do assumptions about the code allowing it to basically add all the C optimizations. Except that it always has to check if the assumptions are uphold and then fallback and that because it's a JIT it has much less time to optimize the code and do cross-code-section optimizations.
It's both. With bad language design you won't get fast code (at least without going through insane loops).
But even with good language design the compiler need to use them, which needs time to be implemented etc.
So in practice it's often more a mixture between how easy/hard the language makes optimizations and how much work (with given expertise) was put into the compiler optimizations.
Through there are insane optimization which need to high amount of knowledge about the code and as such which you will have a really had time to ever realize with Asm,C or similar. But most time they aren't worth it as getting them right is hard and the time is often better spend with adding more straight forward optimizations, maintaining the compiler code etc.