I'm sure that's possible in other languages, but the program I was trying to compile wasn't that complicated... It had just been written by someone who believed every concrete class needed an abstract interface it was implementing.
I'm sure that's possible in other languages, but the program I was trying to compile wasn't that complicated... It had just been written by someone who believed every concrete class needed an abstract interface it was implementing.
Here for example: https://godbolt.org/z/4nzPY3h57 javac doesn't even bother to resolve that static field at compile time, which wouldn't even have observable side effects. Nope, just blindly emits a static initializer to invoke square(2) at runtime.
Or for a real fun one, enums: https://godbolt.org/z/xjbYvc8dx
Now some of that is necessary to handle all the stuff other classes could do with the enum, but some of it is just unnecessary. Like building the values array, which invokevirtuals all the ordinals of all the enum values. Ordinals the compiler already knew, since it's literally in the same .class file further up (and these are always in the same .class file, they are in lock-step, so there's again no observable difference if the values array was defined with constants instead of invoking ordinals on each field).
And then the trivial switch statement there isn't optimized at all, either, which again wouldn't be observable (compare against what eg. gcc would produce: https://godbolt.org/z/414rGjbE1 )
Further note that these examples are both static initializers, which means the JIT never "fixes" these (and thus instead perpetually contribute to slow startup). So if javac was going to bother with any attempt to optimize at all, you'd think it'd be here.
Bad bytecode is the kludge of byte code you get when you try to write the same thing in kotlin: https://godbolt.org/z/9sGa6csa6
And the bytecode is of comparable quality to javac's.
I remember there was some simple way to crash a Haskell compiler with an out of memory error by defining a series of types, where each successive type required twice as much memory as the previous type to represent.
It's a real problem.
Anecdotally: I maintain a Debian package with a large-ish (but far from huge), template-heavy C++ codebase. I had to give up on compiling on 32 bit machines long ago, simply because not enough addressable memory was available to the compiler. I know other maintainers have to heavily tune the compiler to work around the problem, too.
I was once asked by the Ubuntu folks to disable parallel builds altogether, due to even their 64 bit builders running out of memory altogether.
And this package is just large-ish – it's nowhere near truly large (like a browser or an office suite).