Just In Time Compiler (old version)

On May 24, 2012, Gambas got a Just In Time compiler.

The compiler was implemented by Emil Lenngren.

The compiler uses LLVM to produce machine code for x86 or x86_64.

You need LLVM version 3.1-3.5 on your computer for the Just In Time compiler to work.

Since 3.3

Find more instructions in the gb.jit/README file.

Syntax

To use it, place the keyword FAST at the top of a Gambas Class file, for a class that you want all functions JIT-compiled instead of interpreted, or at the beginning of a function declaration, so that only that function is JIT-compiled.

As it takes some milliseconds for LLVM to emit machine code and do optimizations, you should only use it for functions that really need optimization.

Additional Type Checking

As the JIT compiler analyses the whole function before execution starts, some extra type safety is added. In interpreter mode, you can normally do things like:

Print "hello"
Print 1.3 \ 5

You would first see hello on the screen, and then an error message complaining you can't do integer division on floats.

If you run the same function in the JIT compiler, the error message will be thrown before execution starts. Hopefully, this will make programs less buggy.

As a consequence, you can not have code like Try Print 1.3 \ 5 either.

Performance

The biggest increases in speed will be in functions that use a lot of low-level calculations and control flows (except For Each loops), such as functions that do a lot of math. However, if the function mostly calls other libraries, you won't see any great increase in speed.

There is still the same overhead when calling functions, since the Gambas stack must be maintained as before, to make error handling work. Using Try=/=Catch is probably slightly slower too, because a real exception handler must be set up.

Something the LLVM optimizer is very good at is transforming a chain of if-else statements to a jump table, so code like:

Select Case x
  Case 1
    ...
  Case 2
    ...
  Case 3
    ...
End Select

will be much faster than before, so you don't have to use the ON GOTO syntax and a lot of labels. This will produce identical machine code.

Some of the benchmarks from the benchmarking page:
  • Polynom: 100 seconds to 9.2 seconds.

  • Primes: 20.4 seconds to 5.95 seconds.

  • Nbody: 20.8 seconds to 3.07 seconds.

Caveats

Most things are implemented, but there are still some features and bugs to fix.

Some of the (so far) unimplemented features are:
  • Making a callback function pointer of a Gambas function in another class, for use with external libraries.

  • Using Component.Load to load functions that are executed one right after in the same function.

  • Breakpoints.

  • Automatic conversion between classes.

Debugging

If you are curious and want to see the optimized LLVM IR, just define the GB_JIT environment variable with a non-null string.