Just In Time Compiler
Desde 3.12
The old just-in-time compiler didn't work anymore because of LLVM being not backward-compatible. As we have no news from the author, I decided to write a new just-in-time compiler from scratch.
By the way, I'd like to know if the LLVM developers and the GTK+ developers are the same guys...
This unfortunate experience has burned me, so I decided to design it differently. Instead of relying on a undeterministic moving beta API of all possible compilers, the new Gambas JIT compiler translates the Gambas code into C.
How it works
The process is the following:
-
When a function marked with the FAST keyword is called for the first time, the JIT compiler is called.
-
If not yet done, the JIT compiler translates all the fast methods of the current project (or component) into a big C source file.
-
Then the C compiler is called to generate a shared library from that big C source file.
-
The shared lbrary is loaded dynamically.
-
The JIT compiled function is called.
This design has many advantages:
-
You can use either
gcc
or clang
, or tcc
(see below).
-
As long as the C standard does not change, the JIT compiler will not break.
But some disadvantages too:
-
The code generation is slower (and even slower with gcc). To workaround this slowness, the compilation is done in background processes.
-
Sometimes a compiler quirk bites you (for example, using
__attribute__((noreturn))
makes the gcc optimizer become mad and slow as hell).
The JIT compiler is implemented in a component that is automatically loaded when needed. It has a C part that implements the Gambas to C code translator, and a Gambas part that deals with extracting Gambas source code from executable archive files and assembling all the translations into one big file.
Syntax
The syntax did not change: 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.
JIT compiling has a cost, so try to use it only on specific methods that need a boost.
Caveats
Some language syntax is not supported at the moment:
-
The BYREF keyword.
-
Propagating variable arguments to another function call with the
...
syntax.
-
Using
tcc
is possible, but that compiler is not very reliable and may generate incorrect code.
Performance
The biggest increases in speed will be in functions that use a lot of low-level
computations 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.
You won't see any significative gain in string management.
See
Benchmarks for more details.
Debugging
At the moment, some environment variables control the behavior of the JIT compiler.
Environment variable
|
Description
|
GB_NO_JIT
|
Set to 1 if you want to disable the JIT compiler entirely.
|
GB_JIT_DEBUG
|
Set to 1 if you want to see the debugging message emitted by the JIT compiler.
|
GB_JIT_CC
|
Set to the name of the compiler to use. By default gcc is used. But you can put clang instead, or anything else provided that it uses the same options as gcc or support for it is added in the JIT compiler Gambas part.
|
GB_JIT_CFLAGS
|
Set it to the flags used for compiling the C code. The default is -O3 .
|
See also