[LLVMdev] Dynamic updates of current executed code

Chris Lattner sabre at nondot.org
Mon Apr 19 01:52:01 PDT 2004


On Mon, 19 Apr 2004, Anders Alexandersson wrote:

> Hello!
>
> I saw that you just got the recent llvm paper published in IEEE!
> Congratulations! :-)

Thanks!

> More issues regarding the Ruby compiler:
>
> Ruby supports the possibility of the user to enter new Ruby code during
> execution, after which it is executed. Also, all classes are open,
> meaning that a user is able to redefine a class overriding or replacing
> methods therein at run-time (this is deep...).

Sure, many dynamic languages are like this...

> My question is how the llvm-jitter works on a low level. Say for example
> that a user redefines a method during execution. My compiler (in llvm
> code form) takes care of compiling that code into llvm code dynamically.

Okay, at the low-level, your class will have a hash-table or vtable or
something that represents the methods in the class.  This vtable or hash
table is a global LLVM variable.  In the case of our C++ front-end, each
object with a virtual method has a pointer to a class descriptor global,
and the class descriptor global has a pointer to the vtable for the class.

> Now, how do the mechanisms work that loads new llvm code and lets it
> co-exist with the code already running? In this case I want to update a
> function pointer in the struct in the already running code representing
> the changed class, to point to the newly compiled code representing the
> newly entered method instead.

In this case, just don't mark the ruby vtables/hash-tables as "constant",
and update the pointers in the global at runtime.  All code will
automatically start executing the new method that you defined.

> Is this functionality at all accessible by an executing llvm program?

Sure.  There are multiple ways of doing this.  First, you want to codegen
the new method that was added, by creating an LLVM function for it and
adding it to the current module being run.  You then call
ExecutionEngine::getPointerToGlobal(F), passing in the LLVM Function
object that you compiled.  This will cause the function to be code
generated and give you a pointer to it.

Next, ask the execution engine for a pointer to the vtable or whatever you
are using for method dispatch, using the same method.  Once you have the
pointer to the global in memory, and a pointer to the function you want to
stick into it, go ahead and do it.  :)

The other option for *replacing* a method that has already been code
generated is to use the ExecutionEngine::recompileAndRelinkFunction
method, which tells the JIT to discard the previously compiled version of
an LLVM function and recompile it from scratch.

A lot of the details depend intrinsically on how you are representing Ruby
objects and method dispatch in general.  That said, all of the needed LLVM
functionality should be in place.

Feel free to ask if you have any other questions.  :)

-Chris

-- 
http://llvm.cs.uiuc.edu/
http://www.nondot.org/~sabre/Projects/




More information about the llvm-dev mailing list