[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Emacs Lisp JIT Compiler

From: Burton Samograd
Subject: Re: Emacs Lisp JIT Compiler
Date: Mon, 5 Dec 2016 21:03:52 +0000

On Dec 5, 2016, at 12:32 PM, Daniel Colascione <address@hidden> wrote:

Thanks for doing this work.

On 12/05/2016 10:16 AM, Burton Samograd wrote:

I’ve published my Emacs Lisp JIT compiler for comments and review:


The JIT compiler implements a strategy of turning the byte code
execution loop into a series of function calls, moving the overhead of
the loop into the CPU execution unit.  I call this ‘compiling down the
spine’ of the byte code vector.  No other changes have been done to the
byte code instructions other than to map them to the new execution strategy.

This is work in progress and about ~90% complete and was done about 4
years ago, so it’s quite a bit off of HEAD right now.  It ‘works’ to the
point of being able to JIT compile and run my included ray-tracer with a
25% speed improvement.  Enabling full JIT during compilation shows bugs
and will fail; I haven’t been able to track down the cause of these
failures yet.

Let's benchmark it after making sure it's correct.


By default, this build will provide the Lisp function 'jit-compile’
which takes a lambda _expression_ or a symbol.

A new byte code instruction has been added Bjitcall.  When a function is
JIT compiled, it’s code vector is replaced by the single Bjitcall
instruction followed by the JIT compiled code block.

I'm hesitant to call this work a "JIT compiler", since it's not doing any "compilation" --- CFG construction, register allocation, machine-code generation.

Technically, there is compilation into a linear series of function calls to the byte code interpreter code. That part is handled by libjit.  No, I didn’t write the entire JIT compiler that it uses, but it does compile the interpreter loop into a more efficient dispatch structure, giving the speed improvemet.  It’s a simple technique and easy to see where the improvement comes from, but yes, this implementation does cause maintenance problems by duplicating the code from the original interpreter loop.

we're still executing the same bits of the interpreter code ---- just reaching them more efficiency. (It's a step in that direction though.) Since each function pointer (four or eight bytes) is much larger than the corresponding bytecode instruction, for cache efficiency reasons, I'd apply this optimization only to hot functions.

That’s the intention with the stub jit_hotspot_compile, but of course, getting this correct is obviously more important first.

Four years ago, GCC's JIT API was unavailable. I suggest taking a close look at it. It will deliver far greater speedups to computation than the techniques in this work can, and it's much lower-maintenance to boot.

I didn’t realize GCC had a JIT API now.  Is that also linked in 

BTW: we don't use C99 dynamic arrays in Emacs.

Noted, thanks.

By showing this ida/work I’m hoping not to get it included in emacs proper, but to show a relatively simple way to speed things up.  I’m sure there are better/alternate implementations that would both be cleaner and give better speedups, but this was as far as this POC went so far.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]