Re: Jit Implementation

"bartc" <>
Wed, 24 Mar 2010 18:05:34 -0000

          From comp.compilers

Related articles
[9 earlier articles]
Re: Jit Implementation (Philip Herron) (2010-03-21)
Re: Jit Implementation (Barry Kelly) (2010-03-22)
Re: Jit Implementation (bartc) (2010-03-23)
Re: Jit Implementation (bartc) (2010-03-23)
Re: Jit Implementation (cr88192) (2010-03-23)
Re: Jit Implementation (BGB / cr88192) (2010-03-23)
Re: Jit Implementation (bartc) (2010-03-24)
Re: Jit Implementation (BGB / cr88192) (2010-03-26)
Re: Jit Implementation (bartc) (2010-03-28)
Re: Jit Implementation (BGB / cr88192) (2010-03-28)
| List of all articles for this month |

From: "bartc" <>
Newsgroups: comp.compilers
Date: Wed, 24 Mar 2010 18:05:34 -0000
Organization: Netfront
References: 10-03-070 10-03-078 10-03-082
Keywords: code
Posted-Date: 26 Mar 2010 00:51:35 EDT

"BGB / cr88192" <> wrote in message
> "bartc" <> wrote in message
>> "BGB / cr88192" <> wrote in message
>>> "bartc" <> wrote in message

>> I wanted to avoid assemblers, and all that goes with them,

> I originally wrote my assembler specifically for the purpose of doing JIT.

> for example:
> I added syntax as using an API to emit opcodes was lame;

You mean using: genmc(hlt_opc) is lame but genmc("hlt") isn't?

I did also consider textual asm at one time, but now have a record-based
form (which yet needs to be translated to runnable binary). This form is
also easier to analyse, if that is needed.

> I added basic linking as simply emitting code and data to sequential
> memory addresses was limiting;

I dealt with some of the problems years ago to do with dynamic linking of
bytecode files, and hopefully some of that experience will work here.

I have some unusual requirements (for example fixing up type-ids across
modules: converting local type-ids to global ones, and doing this at runtime
if necessary) that a normal linker won't help with (afaik).

> this allowed some of my first JIT experiments: in late 2006 / early
> 2007, I had success JIT'ing a script language of mine, and at the
> time was pulling off performance loosely comprable to that of
> GCC-compiled C code.

My interpreted project performed well within a magnitude of optimised gcc.
Not bad, but still not good enough to write itself in, hence I'm now using
proper compilation.

>> But in the dynamic language I was using, this [assembler] added
>> less than 300 lines to the compiler, plus various tables.

> in my case, the assembler + linker is not a particularly large component,

> granted, it is still a bit larger than 300 loc though.

(I think I left a lot of the error checking to the loader (so it accepts,
for example, mov [a],[b] syntax, but won't be able to find an x86 opcode for
it later).)

>> My original 'P' IL mapped to byte-code and needed to be interpreted.
>> That imposed many restrictons, but now that I don't have the
>> headache of dealing with it efficiently at runtime, it's now fairly
>> high-level: it has a stack, registers and operands in any
>> combination, but is still just a linear sequence of instructions.
> yeah.
> many of mine are variants of RPN and abstract stack machines...

Stack machines are really, really simple to program for. And would solve
some problems I've having with registers: for example, when you pop a
complex value, you know it's time to free any associated resources.

With registers, you don't really know when you've finished with a register,
and can put something else into it. (I know there are lots of complex
analyses that can be done, but I'm trying to keep things simple and within
my capabilities.)

>> However, it has fewer registers: just one main register, plus one or two
>> auxilliary ones (I've never figured out how to compile for multiple
>> registers).
> more than a few registers means using a register allocator.
> in the trivial case, one is not needed (my early codegens didn't use on,
> but
> instead assigned registers to a complicated set of rules and roles).
> later on, I added a register allocator.

I really have only about 1.5 registers (in the IL). My data types are 32-,
64- and 96-bits, with the latter used for variant and dynamic data. R1 is
max 96-bits, but R2 is only max 64-bits (and R3 is just the top half of R2).

Of course most of the physical registers do end up being used in one form or
another (in implementing the IL and the runtime for example), it's not as
though they're just sitting there empty.


--- news:// - complaints: ---

Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.