Skip to content

Commit

Permalink
add API to enable JIT, set optlevel and sizelevel; set default auto m…
Browse files Browse the repository at this point in the history
…ode to false
  • Loading branch information
Dibyendu Majumdar committed Apr 3, 2015
1 parent 3c7539c commit 15c4665
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 47 deletions.
7 changes: 5 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,18 @@ I am currently working on JIT compilation of Ravi using LLVM. As of now not all
There are two modes of JIT compilation.

* 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 is checked to see if the bytecodes contained in it can be compiled. If this is true then the function is compiled. Because of this simplistic behaviour performance will be degraded so user should disable auto compilation and instead compile specific functions using the API described below.
* manual mode - in this mode user must explicitly request compilation.
* manual mode - in this mode user must explicitly request compilation. This is the default mode.

A JIT api is available with following functions:

* ``ravi.auto([b])`` - returns setting of auto compilation; also sets the new setting if ``b`` is supplied
* ``ravi.jit([b])`` - returns enabled setting of JIT compiler; also enables/disables the JIT compiler; defaults to true
* ``ravi.auto([b])`` - returns setting of auto compilation; also sets the new setting if ``b`` is supplied; defaults to false
* ``ravi.compile(func)`` - compiles a Lua function if possible, returns ``true`` if compilation was successful
* ``ravi.iscompiled(func)`` - returns the JIT status of a function
* ``ravi.dumplua(func)`` - dumps the Lua bytecode of the function
* ``ravi.dumpllvm(func)`` - dumps the LLVM IR of the compiled function (only if function was compiled)
* ``ravi.optlevel([n])`` - sets LLVM optimization level (0, 1, 2, 3); defaults to 2
* ``ravi.sizelevel([n])`` - sets LLVM size level (0, 1, 2); defaults to 0

Compatibility with Lua
----------------------
Expand Down
14 changes: 14 additions & 0 deletions include/ravi_llvmcodegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,14 @@ class RAVI_API RaviJITStateImpl : public RaviJITState {
// Should we auto compile what we can?
bool auto_;

// Is JIT enabled
bool enabled_;

// Optimizer level (LLVM PassManagerBuilder)
int opt_level_;

// Size level (LLVM PassManagerBuilder)
int size_level_;
public:
RaviJITStateImpl();
virtual ~RaviJITStateImpl();
Expand All @@ -367,6 +375,12 @@ class RAVI_API RaviJITStateImpl : public RaviJITState {
const std::string &triple() const { return triple_; }
bool is_auto() const { return auto_; }
void set_auto(bool value) { auto_ = value; }
bool is_enabled() const { return enabled_; }
void set_enabled(bool value) { enabled_ = value; }
int get_optlevel() const { return opt_level_; }
void set_optlevel(int value) { if (value >= 0 && value <= 3) opt_level_ = value; }
int get_sizelevel() const { return size_level_; }
void set_sizelevel(int value) { if (value >= 0 && value <= 2) size_level_ = value; }
};

// To optimise fornum loops
Expand Down
6 changes: 6 additions & 0 deletions include/ravillvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ class RAVI_API RaviJITState {
virtual llvm::LLVMContext &context() = 0;
virtual bool is_auto() const = 0;
virtual void set_auto(bool value) = 0;
virtual bool is_enabled() const = 0;
virtual void set_enabled(bool value) = 0;
virtual int get_optlevel() const = 0;
virtual void set_optlevel(int value) = 0;
virtual int get_sizelevel() const = 0;
virtual void set_sizelevel(int value) = 0;
protected:
RaviJITState() {}
private:
Expand Down
2 changes: 2 additions & 0 deletions ravi-tests/ravi_tests1.ravi
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
ravi.auto(true)

local z,x,y

-- test 1
Expand Down
7 changes: 5 additions & 2 deletions readthedocs/ravi-overview.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,18 @@ I am currently working on JIT compilation of Ravi using LLVM. As of now not all
There are two modes of JIT compilation.

* 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 is checked to see if the bytecodes contained in it can be compiled. If this is true then the function is compiled. Because of this simplistic behaviour performance will be degraded so user should disable auto compilation and instead compile specific functions using the API described below.
* manual mode - in this mode user must explicitly request compilation.
* manual mode - in this mode user must explicitly request compilation. This is the default mode.

A JIT api is available with following functions:

* ``ravi.auto([b])`` - returns setting of auto compilation; also sets the new setting if ``b`` is supplied
* ``ravi.jit([b])`` - returns enabled setting of JIT compiler; also enables/disables the JIT compiler; defaults to true
* ``ravi.auto([b])`` - returns setting of auto compilation; also sets the new setting if ``b`` is supplied; defaults to false
* ``ravi.compile(func)`` - compiles a Lua function if possible, returns ``true`` if compilation was successful
* ``ravi.iscompiled(func)`` - returns the JIT status of a function
* ``ravi.dumplua(func)`` - dumps the Lua bytecode of the function
* ``ravi.dumpllvm(func)`` - dumps the LLVM IR of the compiled function (only if function was compiled)
* ``ravi.optlevel([n])`` - sets LLVM optimization level (0, 1, 2, 3); defaults to 2
* ``ravi.sizelevel([n])`` - sets LLVM size level (0, 1, 2); defaults to 0

Compatibility with Lua
----------------------
Expand Down
11 changes: 6 additions & 5 deletions src/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ The LLVM JIT implementation is in following sources:

* ravijit.cpp - basic LLVM infrastructure and Ravi API definition
* ravi_llvmtypes.cpp - contains LLVM type definitions for Lua objects
* ravi_llvmcodegen.cpp - LLVM JIT compiler - main driver for compiling Lua bytecodes into LLVM IR, also contains implementations of opcodes like OP_JMP
* ravi_llvmload.cpp - implements OP_LOADK and OP_MOVE, and related operations
* ravi_llvmcodegen.cpp - LLVM JIT compiler - main driver for compiling Lua bytecodes into LLVM IR
* ravi_llvmload.cpp - implements OP_LOADK and OP_MOVE, and related operations, also OP_LOADBOOL
* ravi_llvmcomp.cpp - implements OP_EQ, OP_LT, OP_LE, OP_TEST and OP_TESTSET.
* ravi_llvmreturn.cpp - implements OP_RETURN
* ravi_llvmforprep.cpp - implements OP_FORPREP
* ravi_llvmforloop.cpp - implements OP_FORLOOP
* ravi_llvmarith1.cpp - implements various type specialized arithmetic operations - these are Ravi extensions
* ravi_llvmarith2.cpp - implements Lua opcodes such as OP_ADD, OP_SUB, OP_MUL, OP_DIV
* ravi_llvmcall.cpp - implements OP_CALL
* ravi_llvmtable.cpp - implements OP_GETTABLE, OP_SETTABLE etc. table operations
* ravi_llvmarith2.cpp - implements Lua opcodes such as OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_POW, OP_IDIV, OP_MOD, OP_UNM
* ravi_llvmcall.cpp - implements OP_CALL, OP_JMP
* ravi_llvmtable.cpp - implements OP_GETTABLE, OP_SETTABLE and various other table operations, OP_SELF, and also upvalue operations
* ravi_llvmrest.cpp - OP_CLOSURE, OP_VARARG, OP_CONCAT
63 changes: 58 additions & 5 deletions src/ravijit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ static std::atomic_int init;

RaviJITState *RaviJITFunctionImpl::owner() const { return owner_; }

RaviJITStateImpl::RaviJITStateImpl() : context_(llvm::getGlobalContext()), auto_(true) {
RaviJITStateImpl::RaviJITStateImpl()
: context_(llvm::getGlobalContext()), auto_(false), enabled_(true),
opt_level_(2), size_level_(0) {
// Unless following three lines are not executed then
// ExecutionEngine cannot be created
// This should ideally be an atomic check but because LLVM docs
Expand Down Expand Up @@ -142,7 +144,7 @@ RaviJITFunctionImpl::~RaviJITFunctionImpl() {

void *RaviJITFunctionImpl::compile() {

//module_->dump();
// module_->dump();

// Create a function pass manager for this engine
llvm::FunctionPassManager *FPM = new llvm::FunctionPassManager(module_);
Expand All @@ -159,8 +161,8 @@ void *RaviJITFunctionImpl::compile() {
FPM->add(new llvm::DataLayoutPass(*engine_->getDataLayout()));
#endif
llvm::PassManagerBuilder pmb;
pmb.OptLevel = 1;
pmb.SizeLevel = 0;
pmb.OptLevel = owner_->get_optlevel();
pmb.SizeLevel = owner_->get_sizelevel();
pmb.populateFunctionPassManager(*FPM);
FPM->doInitialization();
FPM->run(*function_);
Expand Down Expand Up @@ -251,6 +253,9 @@ int raviV_compile(struct lua_State *L, struct Proto *p, int manual_request) {
global_State *G = G(L);
if (G->ravi_state == NULL)
return 0;
if (!G->ravi_state->jit->is_enabled()) {
return 0;
}
if (G->ravi_state->jit->is_auto() || manual_request)
G->ravi_state->code_generator->compile(L, p);
return p->ravi_jit.jit_status == 2;
Expand Down Expand Up @@ -331,16 +336,64 @@ static int ravi_auto(lua_State *L) {
lua_pushboolean(L, 0);
else
lua_pushboolean(L, G->ravi_state->jit->is_auto());
if (n == 1)
if (n == 1 && G->ravi_state)
G->ravi_state->jit->set_auto(value);
return 1;
}

static int ravi_jitenable(lua_State *L) {
global_State *G = G(L);
int n = lua_gettop(L);
bool value = false;
if (n == 1)
value = lua_toboolean(L, 1);
if (G->ravi_state == NULL)
lua_pushboolean(L, 0);
else
lua_pushboolean(L, G->ravi_state->jit->is_enabled());
if (n == 1 && G->ravi_state)
G->ravi_state->jit->set_enabled(value);
return 1;
}

static int ravi_optlevel(lua_State *L) {
global_State *G = G(L);
int n = lua_gettop(L);
int value = 1;
if (n == 1)
value = lua_tointeger(L, 1);
if (G->ravi_state == NULL)
lua_pushinteger(L, 0);
else
lua_pushinteger(L, G->ravi_state->jit->get_optlevel());
if (n == 1 && G->ravi_state)
G->ravi_state->jit->set_optlevel(value);
return 1;
}

static int ravi_sizelevel(lua_State *L) {
global_State *G = G(L);
int n = lua_gettop(L);
int value = 0;
if (n == 1)
value = lua_tointeger(L, 1);
if (G->ravi_state == NULL)
lua_pushinteger(L, 0);
else
lua_pushinteger(L, G->ravi_state->jit->get_sizelevel());
if (n == 1 && G->ravi_state)
G->ravi_state->jit->set_sizelevel(value);
return 1;
}

static const luaL_Reg ravilib[] = {{"iscompiled", ravi_is_compiled},
{"compile", ravi_compile},
{"dumplua", ravi_dump_luacode},
{"dumpllvm", ravi_dump_llvmir},
{"auto", ravi_auto},
{"jit", ravi_jitenable},
{"optlevel", ravi_optlevel},
{"sizelevel", ravi_sizelevel},
{NULL, NULL}};

LUAMOD_API int raviopen_llvmjit(lua_State *L) {
Expand Down

0 comments on commit 15c4665

Please sign in to comment.