I’ve been working steadily on replacing gcj’s front end with the
Java compiler from Eclipse. This is largely working now. I have a
new main program for the Eclipse compiler, and I have gcc set up to
invoke this (via the magic of gcc specs — an evil little ad hoc
scripting language that you should hope you never have to learn).
The new driver is a little funny. When ecj compiles a file, it
writes the classes to a jar which gcj compiles. This way we don’t
have to have an arbitrary number of temporary files for communication,
e.g. for all the inner classes. This takes advantage of java’s
built-in ability to make jars, and gcj’s existing ability to compile a
jar file all at one. I thought this was amusing, anyway… maybe I’ve
been working too much.
I thought this would be very simple, but I should have realized
that this would reveal every bizarre class file compilation bug in
gcj, some of which can only be seen if you are compiling the core
class library this way. For example, the bytecode verifier needed a
special case to handle the constructor in
In any case, I can now build all of libgcj this way. I’m
debugging a few runtime failures now.
Aside from the whole exception handling mess — which experts more
expert than I are, hopefully, busily hacking on — the JIT seems to be
working reasonably well. I’m just about ready to clean up the API and
check it in (as an experimental preview), I don’t think any more
changes in that area will be needed in the near future.
There are still a few lurking code generation bugs. Nothing too
hard, just mishandling
jsr a little.
I recently added the first bits of recompilation to the JIT. Now
it will realize when it resolves a constant pool entry, and mark the
method as ready for re-jitting. The idea here is that before linking,
a constant pool reference requires a method call to incrementally link
the class, whereas after linking, a constant pool reference is simply
a constant. Another similar optimization is that when we initialize a
class, we mark the method as ready for re-jitting — the code to lower
from bytecode to LLVM will check a class’ state and avoid emitting
initialization calls as needed.
This still hasn’t seen much testing. And, to really do a good job
here we have to add profiling code of some kind. I really need to
read the literature here. If only there were time.