[Mono-list] Future of JIT

Ilya Minkov midiclub@tiscali.de
Sun, 02 Feb 2003 02:34:02 +0100

Have you considered VCODE/ICODE to become a basis for your JIT backend?

It was developed/used for runtime code generation in Tick C Compiler, 
which is in turn based upon LCC. And since its command set is tuned for 
LCC, it should also fit the .NET architecture if i'm not wrong. I 
haven't read many important papers because of lack of time, so don't 
consider what i tell here sole truth, it can have rumors/ 
misconceptions/ stuff mixed in.

It has been well ported to all (widespread) RISC CPUs, and there is a 
half-broken x86 port. I have been intending to make a "real" x86 port 
for use in some project of mine. But i think MONO could be a better use 
for me, and i would like to be of use if i have time and our targets match.

VCODE is a set of C macros, generating target machine code out of the 
generalized RISC set without intermediate representation, like GNU 
Lightning does. With a difference that GNU Lightning is broken.

ICODE is a form of binary representation for VCODE, which also 
integrates a number of generic optimisations and register allocation, 
reaching considerable execution speeds.

The thing to check: *licensing issues* (?), i don't know under which 
condition it has been licensed.
- checked already. It's "fair use" - not to sell, else use as desired, 
retain copyright. It even allows usage in commercial products but it 
doesn't matter.

I think the system should be as staged as possible, so that only a minor 
part should be ported to another architecture, and that improving some 
actually platform-independant stuff wouldn't break some platform while 
leaving others working. Besides, this VCODE already contain a lot of 
work done by others.

I also think that it should be possible to attach a peephole optimiser 
to VCODE. Any time a label is issued, if optimiser is enabled, it would 
disassemble (simplified, extracting a minimum of information) all the 
code generated since the last label, and write "tags", noting where each 
CPU command starts and some basic properties of it, like LCC-Win32 does 
it. Then, peephole optimisation is basically pattern-matching and 
disassembling certaing commands as this information is needed, and so on 
as usual. Finally, the last label should be moved back.

Then i think, compilation should be "lazy". The first time a function is 
compiled, it is done the fastest way, optimising nothing. Functions 
which it requieres are not compiled. Inputs are placed on stack as 
usual, but with a CALL to some (assembly-written) dispatcher function. 
This dispatcher when called does the folowing:
  - Looks at return adress. Using that, finds out what function exactly 
is to be called in this place. (This information needs to be generated 
when compiling that original function)
  - If the function to be called is already compiled, then change the 
call adress (which is just placed before the return adress) with the 
actual function adress to be called, and call this function, then return.
  - If the function is not yet compiled, compile it, then procede as in 
previous case.
The next time a function will call another function directly

First time a function is compiled it is compiled without optimisations. 
I guess it would be OK to place a call to counter in the beginning of 
such a function - since it's not compiled for speed...
As soon as this counter decides that the function has been called "often 
enough", it should recompile the function with all optimisations on, 
this time without embedding the counter. The system to replace adresses 
might either be the same as previous, or more a more rapid one so that 
the unoptimised function can be deleted at once.

Of course, there can just as well be multiple optimisation steps, but it 
might be the next step.