issue #110 update doc
parent
2d646a0bde
commit
2fa8a00291
@ -1,56 +0,0 @@
|
||||
Ravi's JIT Implementation
|
||||
=========================
|
||||
There are two JIT backends available for Ravi.
|
||||
|
||||
* The LLVM JIT backend is described in `JIT Status <http://the-ravi-programming-language.readthedocs.org/en/latest/ravi-jit-status.html>`_ page.
|
||||
* The Eclipse OMR JIT backend is in development. This backend uses a C intermediate layer.
|
||||
|
||||
JIT API
|
||||
-------
|
||||
auto mode
|
||||
in this mode the compiler decides when to compile a Lua function. The current implementation is very simple -
|
||||
any Lua function call is checked to see if the bytecodes contained in it can be compiled. If this is true then
|
||||
the function is compiled provided either a) function has a fornum loop, or b) it is largish (greater than 150 bytecodes)
|
||||
or c) it is being executed many times (> 50). Because of the simplistic behaviour performance the benefit of JIT
|
||||
compilation is only available if the JIT compiled functions will be executed many times so that the cost of JIT
|
||||
compilation can be amortized.
|
||||
manual mode
|
||||
in this mode user must explicitly request compilation. This is the default mode. This mode is suitable for library
|
||||
developers who can pre compile the functions in library module table.
|
||||
|
||||
A JIT api is available with following functions:
|
||||
|
||||
``ravi.jit([b])``
|
||||
returns enabled setting of JIT compiler; also enables/disables the JIT compiler; defaults to true
|
||||
``ravi.auto([b [, min_size [, min_executions]]])``
|
||||
returns setting of auto compilation and compilation thresholds; also sets the new settings if values are supplied; defaults are false, 150, 50.
|
||||
``ravi.compile(func_or_table[, options])``
|
||||
compiles a Lua function (or functions if a table is supplied) if possible, returns ``true`` if compilation was
|
||||
successful for at least one function. ``options`` is an optional table with compilation options - in particular
|
||||
``omitArrayGetRangeCheck`` - which disables range checks in array get operations to improve performance in some cases.
|
||||
Note that at present if the first argument is a table of functions and has more than 100 functions then only the
|
||||
first 100 will be compiled. You can invoke compile() repeatedly on the table until it returns false. Each
|
||||
invocation leads to a new module being created; any functions already compiled are skipped.
|
||||
``ravi.iscompiled(func)``
|
||||
returns the JIT status of a function
|
||||
``ravi.dumplua(func)``
|
||||
dumps the Lua bytecode of the function
|
||||
``ravi.dumpir(func)``
|
||||
dumps the IR of the compiled function (only if function was compiled; only available in LLVM 4.0 and earlier)
|
||||
``ravi.dumpasm(func)``
|
||||
(deprecated) dumps the machine code using the currently set optimization level (only if function was compiled; only available in LLVM version 4.0 and earlier)
|
||||
``ravi.optlevel([n])``
|
||||
sets LLVM optimization level (0, 1, 2, 3); defaults to 2. These levels are handled by reusing LLVMs default pass definitions which are geared towards C/C++ programs, but appear to work well here. If level is set to 0, then an attempt is made to use fast instruction selection to further speed up compilation.
|
||||
``ravi.sizelevel([n])``
|
||||
sets LLVM size level (0, 1, 2); defaults to 0
|
||||
``ravi.tracehook([b])``
|
||||
Enables support for line hooks via the debug api. Note that enabling this option will result in inefficient JIT as a call to a C function will be inserted at beginning of every Lua bytecode boundary; use this option only when you want to use the debug api to step through code line by line
|
||||
``ravi.verbosity([b])``
|
||||
Controls the amount of verbose messages generated during compilation.
|
||||
|
||||
Performance
|
||||
===========
|
||||
For performance benchmarks please visit the `Ravi Performance Benchmarks <http://the-ravi-programming-language.readthedocs.org/en/latest/ravi-benchmarks.html>`_ page.
|
||||
|
||||
To obtain the best possible performance, types must be annotated so that Ravi's JIT compiler can generate efficient code.
|
||||
Additionally function calls are expensive - as the JIT compiler cannot inline function calls, all function calls go via the Lua call protocol which has a large overhead. This is true for both Lua functions and C functions. For best performance avoid function calls inside loops.
|
@ -0,0 +1,140 @@
|
||||
============================================
|
||||
Ravi Build Instructions with Eclipse OMR JIT
|
||||
============================================
|
||||
|
||||
.. contents:: Table of Contents
|
||||
:depth: 2
|
||||
:backlinks: top
|
||||
|
||||
Overview
|
||||
========
|
||||
..note:: The Eclipse OMR JIT backend is work in progress. The code generation is not yet optimal.
|
||||
|
||||
Recently support has been added in Ravi to use the Eclipse OMR JIT backend.
|
||||
A [trimmed down version of the Eclipse OMR JIT](https://github.com/dibyendumajumdar/nj) is used to ensure that the resulting
|
||||
binaries are smaller in size.
|
||||
|
||||
The main advantages / disadvantages of the OMR JIT backend over LLVM are:
|
||||
|
||||
* The OMR JIT backend is much smaller compared to LLVM. On my iMac it takes less than 3 minutes to compile and build the library.
|
||||
* The OMR JIT engine contains an optimizing compiler, therefore the generated code is much better than say [NanoJIT](https://github.com/dibyendumajumdar/nanojit),
|
||||
although not as good as LLVM.
|
||||
|
||||
The approach taken with the OMR JIT backend is somewhat different compared with the LLVM backend.
|
||||
|
||||
* An intermediate C compiler is used; this is based on the [dmr_C](https://github.com/dibyendumajumdar/dmr_c) project. Using a C intermediate layer Makefiles
|
||||
development of the JIT backend easier to evolve. In comparison the LLVM backed was written by hand, using the LLVM api.
|
||||
* Users can view the intermediate C code for a Lua function by simply invoking ``ravi.dumpir(function)`` on any function::
|
||||
|
||||
Ravi 5.3.4
|
||||
Copyright (C) 1994-2017 Lua.org, PUC-Rio
|
||||
Portions Copyright (C) 2015-2017 Dibyendu Majumdar
|
||||
Options assertions ltests omrjit
|
||||
> x = function() print 'hello world' end
|
||||
> ravi.dumpir(x)
|
||||
|
||||
Above results in (note that only the function code is shown below)::
|
||||
|
||||
int jit_function(lua_State *L) {
|
||||
int error_code = 0;
|
||||
lua_Integer i = 0;
|
||||
lua_Integer ic = 0;
|
||||
lua_Number n = 0.0;
|
||||
lua_Number nc = 0.0;
|
||||
int result = 0;
|
||||
StkId ra = NULL;
|
||||
StkId rb = NULL;
|
||||
StkId rc = NULL;
|
||||
lua_Unsigned ukey = 0;
|
||||
lua_Integer *iptr = NULL;
|
||||
lua_Number *nptr = NULL;
|
||||
Table *t = NULL;
|
||||
CallInfo *ci = L->ci;
|
||||
LClosure *cl = clLvalue(ci->func);
|
||||
TValue *k = cl->p->k;
|
||||
StkId base = ci->u.l.base;
|
||||
ra = R(0);
|
||||
rc = K(0);
|
||||
raviV_gettable_sskey(L, cl->upvals[0]->v, rc, ra);
|
||||
base = ci->u.l.base;
|
||||
ra = R(1);
|
||||
rb = K(1);
|
||||
setobj2s(L, ra, rb);
|
||||
L->top = R(2);
|
||||
ra = R(0);
|
||||
result = luaD_precall(L, ra, 0, 1);
|
||||
if (result) {
|
||||
if (result == 1 && 0 >= 0)
|
||||
L->top = ci->top;
|
||||
}
|
||||
else { /* Lua function */
|
||||
result = luaV_execute(L);
|
||||
if (result) L->top = ci->top;
|
||||
}
|
||||
base = ci->u.l.base;
|
||||
ra = R(0);
|
||||
if (cl->p->sizep > 0) luaF_close(L, base);
|
||||
result = (1 != 0 ? 1 - 1 : cast_int(L->top - ra));
|
||||
return luaD_poscall(L, ci, ra, result);
|
||||
Lraise_error:
|
||||
raise_error(L, error_code); /* does not return */
|
||||
return 0;
|
||||
}
|
||||
|
||||
Build Instructions
|
||||
==================
|
||||
* Ravi uses a cut-down version of the `Eclipse OMR JIT engine <https://github.com/dibyendumajumdar/nj>`_. First build this library and install it.
|
||||
* The Ravi CMake build assumes you have installed the OMR JIT library under ``\Software\omr`` on Windows and ``$HOME/Software/omr`` on Linux or Mac OSX.
|
||||
* Now you can build Ravi as follows on Linux or Mac OSX::
|
||||
|
||||
cd build
|
||||
cmake -DOMR_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" ..
|
||||
make
|
||||
|
||||
If you did not use the default locations above to install OMR, then you will need to amend the file ``cmake/FindOMRJIT.cmake``.
|
||||
|
||||
JIT API for OMR backend
|
||||
=======================
|
||||
auto mode
|
||||
in this mode the compiler decides when to compile a Lua function. The current implementation is very simple -
|
||||
any Lua function call is checked to see if the bytecodes contained in it can be compiled. If this is true then
|
||||
the function is compiled provided either a) function has a fornum loop, or b) it is largish (greater than 150 bytecodes)
|
||||
or c) it is being executed many times (> 50). Because of the simplistic behaviour performance the benefit of JIT
|
||||
compilation is only available if the JIT compiled functions will be executed many times so that the cost of JIT
|
||||
compilation can be amortized.
|
||||
manual mode
|
||||
in this mode user must explicitly request compilation. This is the default mode. This mode is suitable for library
|
||||
developers who can pre compile the functions in library module table.
|
||||
|
||||
A JIT api is available with following functions:
|
||||
|
||||
``ravi.jit([b])``
|
||||
returns enabled setting of JIT compiler; also enables/disables the JIT compiler; defaults to true
|
||||
``ravi.auto([b [, min_size [, min_executions]]])``
|
||||
returns setting of auto compilation and compilation thresholds; also sets the new settings if values are supplied; defaults are false, 150, 50.
|
||||
``ravi.compile(func_or_table[, options])``
|
||||
compiles a Lua function (or functions if a table is supplied) if possible, returns ``true`` if compilation was
|
||||
successful for at least one function.
|
||||
``options`` is an optional table with compilation options - in particular
|
||||
``omitArrayGetRangeCheck`` - which disables range checks in array get operations to improve performance in some cases.
|
||||
``inlineLuaArithmeticOperators`` - if this is set then inline code is generated for Lua arithemtic op codes such as
|
||||
``OP_ADD``, ``OP_MUL`` and ``OP_SUB``.
|
||||
``ravi.iscompiled(func)``
|
||||
returns the JIT status of a function
|
||||
``ravi.dumplua(func)``
|
||||
dumps the Lua bytecode of the function
|
||||
``ravi.dumpir(func)``
|
||||
dumps the C intermediate code for a Lua function
|
||||
``ravi.optlevel([n])``
|
||||
sets optimization level (0, 1, 2); defaults to 2.
|
||||
``ravi.verbosity([b])``
|
||||
If set to 1 then everytime a Lua function is compiled the C intermediate code will be dumped.
|
||||
|
||||
Compiler Trace Output from OMR
|
||||
==============================
|
||||
The OMR JIT backend can generate detailed compilation traces if you define following environment variable::
|
||||
|
||||
export TR_Options=traceIlGen,traceFull,log=trtrace.log
|
||||
|
||||
Note that the generated traces can be huge!
|
||||
|
Loading…
Reference in new issue