Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a JIT compiler

Tags:

c++

jit

brainfuck

I've written a Brainfuck implementation (C++) that works like this:

  1. Read input brainfuck file
  2. Do trivial optimizations
  3. Convert brainfuck to machine code for the VM
  4. Execute this machine code in the VM

This is pretty fast, but the bottleneck is now at the VM. It's written in C++ and reads a token, executes an action (which aren't many at all, if you know Brainfuck) and so on.

What I want to do is strip out the VM and generate native machine code on the fly (so basicly, a JIT compiler). This can easily be a 20x speedup.

This would mean step 3 gets replaced by a JIT compiler and step 4 with the executing of the generated machine code.

I don't know really where to start, so I have a few questions:

  1. How does this work, how does the generated machine code get executed?
  2. Are there any C++ libraries for generating native machine code?
like image 329
orlp Avatar asked May 13 '11 01:05

orlp


People also ask

What is JIT compiler?

The Just-In-Time (JIT) compiler is a component of the Java™ Runtime Environment that improves the performance of Java applications at run time. Java programs consists of classes, which contain platform-neutral bytecodes that can be interpreted by a JVM on many different computer architectures.

Does Python have a JIT compiler?

There are two common approaches to compiling Python code - using a Just-In-Time (JIT) compiler and using Cython for Ahead of Time (AOT) compilation.

Is JIT faster than compiled?

A JIT compiler can be faster because the machine code is being generated on the exact machine that it will also execute on. This means that the JIT has the best possible information available to it to emit optimized code.

What is the JIT compiler and how does it work?

The JIT compiler is enabled by default, and is activated when a Java method is called. The JIT compiler compiles the bytecodes of that method into native machine code, compiling it "just in time" to run. When a method has been compiled, the JVM calls the compiled code of that method directly instead of interpreting it.


1 Answers

  1. Generated machine code is just jmp-ed to or call-ed as usual function. Sometimes it also needed to disable no-execution flag (NX bit) on memory, containing generated code. In linux, this is done with mprotect(addr, size, PROT_READ | PROT_WRITE | PROT_EXEC.) In windows the NX is called DEP.

  2. There are some... E.g. http://www.gnu.org/software/lightning/ - GNU Lightning (universal) and https://developer.mozilla.org/En/Nanojit - Nanojit, which is used in Firefox JavaScript JIT engines. More powerful and modern JIT is LLVM, you just need to translate BF code into LLVM IR, and then LLVM can do optimisations and code generation for many platforms, or run LLVM IR on interpreter (virtual machine) with JIT capabilities. There is a post about BF & LLVM with complete LLVM JIT compiler for BF http://www.remcobloemen.nl/2010/02/brainfuck-using-llvm/

Another BF +LLVM compiler is here, in the svn of LLVM: https://llvm.org/svn/llvm-project/llvm/trunk/examples/BrainF/BrainF.cpp

like image 142
osgx Avatar answered Oct 07 '22 01:10

osgx