(Very) small patch for the jit event listener

Gaël Thomas gael.thomas at lip6.fr
Wed Nov 13 14:46:14 PST 2013

Hi Andrew, hi all,

I already saw that the old jit was (almost) deprecated. So, I'm
currently playing with the new jit and it's look very interesting.
(I'm working locally and I haven't pushed anything new on VMKit
because I'm also changing a little the design vmkit). For the moment,
MCJIT does not work with VMKit (but I haven't yet tested the
safepoint/stackmap patch), I don't know if it comes from what I'm
doing or if something is still missing in MCJIT.

Sorry, my mail will be too long, but I want first to explain what I'm
currently doing and then open the discussion to explain what I would
like to see in MCJIT :) Of course, I can help to develop something or
to give feed back, I'm hardly working on vmkit currently and I have
time to spend on that (but I'm far from an expert in compilation

Basically, I want to compile lazily my functions (we have a Java
virtual machine built upon vmkit and compiling all the rt.jar during
the bootstrap is not very realistic:)). So, by lazy compilation, I
mean that I want to compile (and even resolve) a function only when it
is used. For example, during the compilation of
void f() { g() }
I don't want to compile g(). I will only compile g() when it will be called.

For the moment, I use a home-made stub (I have attached the asm code,
it can give you some ideas if you plan to integrate a stub generator
able to perform dynamic dispatch like virtual call in c++) because
MCJIT does not provide this facility. So, for each function, I define
a module. In each module, I have to define the runtime function (such
as gcmalloc, throwException and this kind of functions). They are
defined in a separated runtime module populated during the bootstrap.
I have thus this picture

  |                                    |                        |
Runtime module     module for f   module for g

When I see that I need g during the compilation of f, I define an
external symbol g in f's module and I add a global mapping between g
and its stub in MCJIT. Everything works perfectly in the old JIT, so
the code is correct in this case. The problem that I face with
multiple modules in the old JIT is that the symbol g defined in f's
module and the symbol g defined in g's module are not the same, I thus
have to define multiple symbol in the old JIT for the same entity,
which is far from perfect. Anyway, it works.

With MCJIT, I can call f from my C++ code (relatively easy as f is
defined in its own module),  the stub of g is called and I can
generate its code (which use other functions). But I can not find a
way to compile g and to update the mapping between g and the new
function pointer. When I use recompileAndRelinkFunction, I see that it
is not implemented in MCJIT, and when I use getFunctionPointer, I
obtain.... a null pointer? I have not investigated further, but
probably, having two symbols g in the same MCJIT does not work. And I
don't see what I can do at this step? Maybe that I have missed

Otherwise, I already predict that I will also have one big problem
latter: I would like to inline functions from the runtime module in f
or g, and I would like to inline the code of an already compiled
function h in g. So, I would like to inline functions that comes from
different modules. It means that I would like to see MCJIT working
like an llvm::Linker, able to resolve the h symbol during the
compilation of g. And for the moment, as MCJIT can not see that the g
defined in f's module and the g defined in g's module represent the
same function, I think that I will have a problem latter.

So, for the moment, I'm a little bit stuck with MCJIT. Something that
could be really useful could be a mcjit that acts as a linker. If
MCJIT could have a map like this (I give a pseudo-c++ code)

class FnDescriptor {
  StringRef name;
  FunctionType fnType;
  LinkageType linkage;

class FnState {
  llvm::Module* definedModule;
/* maybe a  llvm::ObjectImage* ? */
  List<RelocationTable*>* users,
  void* currentPointer

map<FnDescriptor, FnState>

it could be really useful. Let's imagine the same scenario with f that
calls g while g is not yet compiled. At the beginning of this
scenario, "g" "void ()" could simply be associated to a FnState with

<null, List<>, stubForG>.

After f's compilation, it could be something like that

<null, List<RelocationTable-of-module-f>, stubForG>.

And after the compilation of g, something like

<moduleOfG, List<Reloc-f, Reloc-g>, compiledCode-of-g>

with the relocation entries updated?

Otherwise, for safepoints, and for exception tables, it could be also
really useful to install call backs to let VMKit manages them itself
(but it's maybe provided by the safepoint/patchpoint patch?)? (with
something that can make the association between a MCSymbol and it's
actual address of course :) )

See you!

PS: by the way, Yaron, we currently face almost the same problems

2013/11/13 Yaron Keren <yaron.keren at gmail.com>:
> Hi Andy,
> We had previous discussions about this, I'd like to state more exactly what
> features would make MCJIT a replacement for the JIT.
> After putting significant effort trying to move to MCJIT, I'm currently back
> with the JIT. This is in a REPL environment where functions are added and
> removed dynamically and response time is important. The issue is the legacy
> JIT provides great flexibility for this use case which is currently missing
> from MCJIT because of their very different design and goals.
> With JIT, you can modify Function(s) in an already-compiled Module, unload
> the machine code and the JIT will automatically recompile and relink the
> function next time it is called. To make MCJIT work like that it would need
> at least :
> 1) Automatic module splitting into function-modules.
> 2) Module delete: from module list, from linker namespace, machine code
> unload, unregister EH and debuginfo.
> 3) Stub functions.
> 4) Relinking with stub functions so that new modules are relinked without
> changing already-finalized modules. This is critical to response time as you
> may change just one function out of 1000.
> 5) Module addition should register EH and debuginfo (this is not done with
> current JIT but while at it...).
> REPL environments using the LLVM JIT would likely encounter great difficulty
> moving to the current MCJIT without the above. 1) could be done by the
> programmer but the a helper function should provide this service. 2)-4)
> could be done only in the MCJIT. 5) is a bonus.
> Until MCJIT has this kind of flexibility, I hope the JIT would be kept
> alive.
> Yaron
> 2013/11/13 Kaylor, Andrew <andrew.kaylor at intel.com>
>> Hi Gaël,
>> I'm not familiar enough with the details of the old JIT engine and its
>> event interface to comment on whether or not your changes are appropriate,
>> but I'm not sure anyone is so the patch is probably OK as is.  I don't see
>> any obvious problems with it.
>> However, your description of the changes raises a bigger issue in my mind.
>> I'm not sure if you are aware of this, but we're planning to deprecate the
>> old JIT engine in a future release -- possibly as soon as LLVM 3.5.  In
>> order to do so we need to make sure the MCJIT engine is capable of meeting
>> the needs of current JIT users, and I'm not sure we've got your case fully
>> covered yet.
>> Can you tell me a little bit more about the details of how you are using
>> the JIT engine?  I'm putting together a document describing various models
>> for MCJIT use and if your model isn't covered by one of the cases I've got
>> now I'd like to add it.
>> Also, have you looked at the recently added Stackmap and Patchpoint
>> intrinsics.  Without knowing a lot about either your case or those
>> intrinsics, I think that there may be a possible match there.  The thing
>> that raised a red flag for me in your message was that MCJIT doesn't
>> maintain mappings between the generated code and the LLVM classes from which
>> it is produced, so we'll probably need a different way to handle your
>> safepoints.
>> (BTW, it's probably appropriate to move further discussion to the LLVMDev
>> list rather than llvm-commits.)
>> Thanks,
>> Andy
>> -----Original Message-----
>> From: llvm-commits-bounces at cs.uiuc.edu
>> [mailto:llvm-commits-bounces at cs.uiuc.edu] On Behalf Of Gaël Thomas
>> Sent: Wednesday, November 13, 2013 6:09 AM
>> To: llvm-commits at cs.uiuc.edu
>> Subject: (Very) small patch for the jit event listener
>> Hi all,
>> We have a small problem for vmkit. We rely on the JITEventListener to
>> register the safepoints generated for the garbage collector, and for that
>> purpose, we have to use the JITCodeEmitter (the
>> MachineCodeEmitter) that was used to generate the MachineFunction in order
>> to find the physical address of the safepoints (aka, the MCSymbols). A long
>> time ago, it was not a problem as the JIT class was in the llvm interface,
>> but today, the header is hidden inside the lib directory and not installed
>> by llvm. Currently, we directly use this header, but it means that during
>> the compilation of vmkit, we need the sources of llvm. But, as we are
>> currently developing a debian package of vmkit, we would like to avoid the
>> installation of the llvm sources to compile vmkit.
>> So, I made a small patch that just adds a new MachineCodeEmitter field in
>> JITEvent_EmittedFunctionDetails and fill it in JITCodeEmitter. As the patch
>> only adds a new field in the JITEvent_EmittedFunctionDetails, it should not
>> break anything. At least, my llvm and my vmkit are still running :) (by the
>> way, I had to execute a make clean before recompiling llvm because I think
>> that a dependency is missing)
>> As it is my first patch, I hope that I have used the llvm coding style...
>> See you,
>> Gaël
>> --
>> -------------------------------------------------------------------
>> Gaël Thomas, Associate Professor, UPMC
>> http://pagesperso-systeme.lip6.fr/Gael.Thomas/
>> -------------------------------------------------------------------
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

Gaël Thomas, Associate Professor, UPMC

More information about the llvm-commits mailing list