issue #15 add new JIT option tracehook to enable per bytecode updates to savedpc and call to luaG_traceexec

pull/81/head
Dibyendu Majumdar 9 years ago
parent b4b54485d4
commit 40570edbfc

@ -1,5 +1,24 @@
#include "lua_hdr.h"
/*
** Event codes
*/
#define LUA_HOOKCALL 0
#define LUA_HOOKRET 1
#define LUA_HOOKLINE 2
#define LUA_HOOKCOUNT 3
#define LUA_HOOKTAILCALL 4
/*
** Event masks
*/
#define LUA_MASKCALL (1 << LUA_HOOKCALL)
#define LUA_MASKRET (1 << LUA_HOOKRET)
#define LUA_MASKLINE (1 << LUA_HOOKLINE)
#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT)
extern void luaG_traceexec(struct lua_State *L);
void test1(struct lua_State *L, int b) {
/* This is the function prologue */
@ -12,4 +31,8 @@ void test1(struct lua_State *L, int b) {
p = cl->p;
ci->l.savedpc = &p->code[b];
if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
luaG_traceexec(L);
}
}

@ -65,23 +65,58 @@ entry:
%l = getelementptr inbounds %struct.CallInfoLua, %struct.CallInfoLua* %14, i32 0, i32 4
%savedpc = getelementptr inbounds %struct.CallInfoL, %struct.CallInfoL* %l, i32 0, i32 1
store i32* %arrayidx, i32** %savedpc, align 4, !tbaa !20
%15 = bitcast %struct.Proto** %p to i8*
call void @llvm.lifetime.end(i64 4, i8* %15) #1
%16 = bitcast %struct.LClosure** %cl to i8*
call void @llvm.lifetime.end(i64 4, i8* %16) #1
%17 = bitcast %struct.CallInfoLua** %ci to i8*
call void @llvm.lifetime.end(i64 4, i8* %17) #1
%15 = load %struct.lua_State*, %struct.lua_State** %L.addr, align 4, !tbaa !1
%hookmask = getelementptr inbounds %struct.lua_State, %struct.lua_State* %15, i32 0, i32 22
%16 = load i8, i8* %hookmask, align 1, !tbaa !21
%conv = zext i8 %16 to i32
%and = and i32 %conv, 12
%tobool = icmp ne i32 %and, 0
br i1 %tobool, label %land.lhs.true, label %if.end
land.lhs.true: ; preds = %entry
%17 = load %struct.lua_State*, %struct.lua_State** %L.addr, align 4, !tbaa !1
%hookcount = getelementptr inbounds %struct.lua_State, %struct.lua_State* %17, i32 0, i32 19
%18 = load i32, i32* %hookcount, align 4, !tbaa !22
%dec = add nsw i32 %18, -1
store i32 %dec, i32* %hookcount, align 4, !tbaa !22
%cmp = icmp eq i32 %dec, 0
br i1 %cmp, label %if.then, label %lor.lhs.false
lor.lhs.false: ; preds = %land.lhs.true
%19 = load %struct.lua_State*, %struct.lua_State** %L.addr, align 4, !tbaa !1
%hookmask4 = getelementptr inbounds %struct.lua_State, %struct.lua_State* %19, i32 0, i32 22
%20 = load i8, i8* %hookmask4, align 1, !tbaa !21
%conv5 = zext i8 %20 to i32
%and6 = and i32 %conv5, 4
%tobool7 = icmp ne i32 %and6, 0
br i1 %tobool7, label %if.then, label %if.end
if.then: ; preds = %lor.lhs.false, %land.lhs.true
%21 = load %struct.lua_State*, %struct.lua_State** %L.addr, align 4, !tbaa !1
call void @luaG_traceexec(%struct.lua_State* %21)
br label %if.end
if.end: ; preds = %if.then, %lor.lhs.false, %entry
%22 = bitcast %struct.Proto** %p to i8*
call void @llvm.lifetime.end(i64 4, i8* %22) #1
%23 = bitcast %struct.LClosure** %cl to i8*
call void @llvm.lifetime.end(i64 4, i8* %23) #1
%24 = bitcast %struct.CallInfoLua** %ci to i8*
call void @llvm.lifetime.end(i64 4, i8* %24) #1
ret void
}
; Function Attrs: nounwind
declare void @llvm.lifetime.start(i64, i8* nocapture) #1
declare void @luaG_traceexec(%struct.lua_State*) #2
; Function Attrs: nounwind
declare void @llvm.lifetime.end(i64, i8* nocapture) #1
attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { nounwind }
attributes #2 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.ident = !{!0}
@ -106,3 +141,5 @@ attributes #1 = { nounwind }
!18 = !{!"Proto", !2, i64 0, !3, i64 4, !3, i64 5, !3, i64 6, !3, i64 7, !3, i64 8, !6, i64 12, !6, i64 16, !6, i64 20, !6, i64 24, !6, i64 28, !6, i64 32, !6, i64 36, !6, i64 40, !2, i64 44, !2, i64 48, !2, i64 52, !2, i64 56, !2, i64 60, !2, i64 64, !2, i64 68, !2, i64 72, !2, i64 76, !19, i64 80}
!19 = !{!"RaviJITProto", !3, i64 0, !2, i64 4, !2, i64 8}
!20 = !{!13, !2, i64 20}
!21 = !{!8, !3, i64 136}
!22 = !{!8, !6, i64 128}

@ -144,6 +144,8 @@ public:
virtual void set_minexeccount(int) = 0;
virtual int get_gcstep() const = 0;
virtual void set_gcstep(int) = 0;
virtual bool is_tracehook_enabled() const = 0;
virtual void set_tracehook_enabled(bool) = 0;
protected:
RaviJITState() {}

@ -405,6 +405,10 @@ class RAVI_API RaviJITStateImpl : public RaviJITState {
// gc step size; defaults to 200
int gc_step_;
// enable calls to luaG_traceexec() at every bytecode
// instruction; this is expensive!
bool tracehook_enabled_;
public:
RaviJITStateImpl();
virtual ~RaviJITStateImpl();
@ -449,6 +453,8 @@ public:
}
int get_gcstep() const { return gc_step_; }
void set_gcstep(int value) { gc_step_ = value > 0 ? value : gc_step_; }
bool is_tracehook_enabled() const { return tracehook_enabled_; }
void set_tracehook_enabled(bool value) { tracehook_enabled_ = value; }
};
// To optimise fornum loops

@ -86,6 +86,10 @@ int raviV_getminexeccount(struct lua_State *L);
void raviV_setgcstep(struct lua_State *L, int stepsize);
int raviV_getgcstep(struct lua_State *L);
/* Enable or disable trace hook */
void raviV_settraceenabled(struct lua_State *L, int enabled);
int raviV_gettraceenabled(struct lua_State *L);
/* Dumps the IR if available */
void raviV_dumpIR(struct lua_State *L, struct Proto *p);

@ -1851,17 +1851,31 @@ void ravi_dump_stacktop(lua_State *L, const char *s) {
top, ci_top);
}
/*
** This function is called from JIT compiled code when JIT trace is
** enabled; the function needs to update the savedpc and
** call luaG_traceexec() if necessary
*/
void ravi_debug_trace(lua_State *L, int opCode, int pc) {
char buf[100];
CallInfo *ci = L->ci;
int funcpos = (int)(ci->func - L->stack);
int top = (int)(L->top - L->stack);
int ci_top = (int)(ci->top - L->stack);
int base = (int)(ci->u.l.base - L->stack);
raviP_instruction_to_str(buf, sizeof buf, clvalue(L->ci->func)->l.p->code[pc]);
printf("Stack dump %s (%s) function %d, pc=%d, L->top = %d, ci->top = %d\n",
luaP_opnames[opCode], buf, funcpos, pc, (top-base), (ci_top-base));
lua_assert(L->ci->u.l.base <= L->top && L->top < L->stack + L->stacksize);
RAVI_DEBUG_STACK(
char buf[100]; CallInfo *ci = L->ci;
int funcpos = (int)(ci->func - L->stack);
int top = (int)(L->top - L->stack);
int ci_top = (int)(ci->top - L->stack);
int base = (int)(ci->u.l.base - L->stack); raviP_instruction_to_str(
buf, sizeof buf, clvalue(L->ci->func)->l.p->code[pc]);
printf(
"Stack dump %s (%s) function %d, pc=%d, L->top = %d, ci->top = %d\n",
luaP_opnames[opCode], buf, funcpos, pc, (top - base),
(ci_top - base));
lua_assert(L->ci->u.l.base <= L->top &&
L->top < L->stack + L->stacksize);)
LClosure *closure = clLvalue(L->ci->func);
L->ci->u.l.savedpc = &closure->p->code[pc + 1];
if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
luaG_traceexec(L);
}
}
void raviV_op_newarrayint(lua_State *L, CallInfo *ci, TValue *ra) {

@ -249,4 +249,14 @@ void raviV_setgcstep(lua_State *L, int value) {
int raviV_getgcstep(lua_State *L) {
(void)L;
return 0;
}
// Turn on/off the JIT compiler
void raviV_settraceenabled(lua_State *L, int value) {
(void)L;
(void)value;
}
int raviV_gettraceenabled(lua_State *L) {
(void)L;
return 0;
}

@ -799,10 +799,11 @@ void RaviCodeGenerator::emit_dump_stacktop(RaviFunctionDef *def,
void RaviCodeGenerator::emit_debug_trace(RaviFunctionDef *def, int opCode,
int pc) {
RAVI_DEBUG_STACK(
CreateCall3(def->builder, def->ravi_debug_traceF, def->L,
llvm::ConstantInt::get(def->types->C_intT, opCode),
llvm::ConstantInt::get(def->types->C_intT, pc)));
if (def->jitState->is_tracehook_enabled()) {
CreateCall3(def->builder, def->ravi_debug_traceF, def->L,
llvm::ConstantInt::get(def->types->C_intT, opCode),
llvm::ConstantInt::get(def->types->C_intT, pc));
}
}
void RaviCodeGenerator::emit_raise_lua_error(RaviFunctionDef *def,

@ -44,7 +44,7 @@ RaviJITState *RaviJITFunctionImpl::owner() const { return owner_; }
RaviJITStateImpl::RaviJITStateImpl()
: auto_(false), enabled_(true),
opt_level_(2), size_level_(0), min_code_size_(150), min_exec_count_(50),
gc_step_(200) {
gc_step_(200), tracehook_enabled_(false) {
// LLVM needs to be initialized else
// ExecutionEngine cannot be created
// This should ideally be an atomic check but because LLVM docs
@ -579,3 +579,16 @@ int raviV_getgcstep(lua_State *L) {
return G->ravi_state->jit->get_gcstep();
}
// Turn on/off the JIT compiler
void raviV_settraceenabled(lua_State *L, int value) {
global_State *G = G(L);
if (!G->ravi_state)
return;
G->ravi_state->jit->set_tracehook_enabled(value != 0);
}
int raviV_gettraceenabled(lua_State *L) {
global_State *G = G(L);
if (!G->ravi_state)
return 0;
return G->ravi_state->jit->is_tracehook_enabled();
}

@ -190,6 +190,18 @@ static int ravi_gcstep(lua_State *L) {
return 1;
}
// Turn on/off the trace hook
static int ravi_traceenable(lua_State *L) {
int n = lua_gettop(L);
int oldvalue = raviV_gettraceenabled(L);
if (n == 1) {
int value = lua_toboolean(L, 1);
raviV_settraceenabled(L, value);
}
lua_pushboolean(L, oldvalue != 0);
return 1;
}
static const luaL_Reg ravilib[] = {{"iscompiled", ravi_is_compiled},
{"compile", ravi_compile},
@ -203,6 +215,7 @@ static const luaL_Reg ravilib[] = {{"iscompiled", ravi_is_compiled},
{"optlevel", ravi_optlevel},
{"sizelevel", ravi_sizelevel},
{"gcstep", ravi_gcstep},
{"tracehook", ravi_traceenable},
{NULL, NULL}};
LUAMOD_API int raviopen_llvmjit(lua_State *L) {

Loading…
Cancel
Save