issue #110 update doc

pull/167/head
Dibyendu Majumdar 6 years ago
parent 2d646a0bde
commit 2fa8a00291

@ -13,15 +13,12 @@ Contents:
ravi-overview
ravi-reference
ravi-build-instructions
ravi-jit-overview
ravi-omr-instructions
ravi-llvm-instructions
lua-introduction
lua_bytecode_reference
lua-parser
ravi-internals
llvm-notes
ravi-jit-initial
ravi-jit-infra
ravi-jit-compilation-hook
ravi-lua-types
llvm-tbaa

@ -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.

@ -1,6 +1,6 @@
=============
Building Ravi
=============
===================================
Building Ravi with LLVM JIT backend
===================================
.. contents:: Table of Contents
:depth: 2
@ -17,6 +17,7 @@ Build Dependencies
* `CMake <https://cmake.org/>`_ is required for more advanced builds
* On Windows you will need Visual Studio 2017 Community edition
* LLVM versions >= 3.5
LLVM JIT Backend
================
@ -94,17 +95,6 @@ On MAC OS X I use::
I open the generated project in Xcode and do a build from there. You can also use the command line build tools if you wish - generate the make files in the same way as for Linux.
Eclipse OMR JIT Backend
=======================
* 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
Building without JIT
====================
You can omit ``-DLLVM_JIT=ON`` and ``OMR_JIT=ON`` options to build Ravi with a null JIT implementation.
@ -113,20 +103,55 @@ Building Static Libraries
=========================
By default the build generates a shared library for Ravi. You can choose to create a static library and statically linked executables by supplying the argument ``-DSTATIC_BUILD=ON`` to CMake.
Build Artifacts
===============
The Ravi build creates a shared or static depending upon options supplied to CMake, the Ravi executable and some test programs. Additionally when JIT compilation is switched off, the ``ravidebug`` executable is generated which is the `debug adapter for use by Visual Studio Code <https://github.com/dibyendumajumdar/ravi/tree/master/vscode-debugger>`_.
The ``ravi`` command recognizes following environment variables. Note that these are only for internal debugging purposes.
``RAVI_DEBUG_EXPR``
if set to a value this triggers debug output of expression parsing
``RAVI_DEBUG_CODEGEN``
if set to a value this triggers a dump of the code being generated
``RAVI_DEBUG_VARS``
if set this triggers a dump of local variables construction and destruction
Also see section above on available API for dumping either Lua bytecode or LLVM IR for compiled code.
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.
Testing
=======

@ -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!

@ -39,7 +39,8 @@ Features
Documentation
=============
* For the Lua extensions in Ravi see the `Reference Manual <https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-reference.html>`_.
* `Build instructions <https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-build-instructions.html>`_.
* `OMR JIT Build instructions <https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-omr-instructions.html>`_.
* `LLVM JIT Build instructions <https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-llvm-instructions.html>`_.
* Also see `Ravi Documentation <http://the-ravi-programming-language.readthedocs.org/en/latest/index.html>`_.
* and the slides I presented at the `Lua 2015 Workshop <http://www.lua.org/wshop15.html>`_.

Loading…
Cancel
Save