issue #115 experiment with table performance - use LuaJIt approach of precomputed hashmask

gccjit-ravi534
Dibyendu Majumdar 7 years ago
parent 4c813450f2
commit 9eb8f1d98d

@ -23,7 +23,9 @@
#define twoto(x) (1<<(x))
#define sizenode(t) (twoto((t)->lsizenode))
#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
//#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
// Following uses cached hmask which is basically precomputed lmod()
#define hashpow2(t, h) (gnode(t, (h & (t)->hmask)))
#define hashstr(t,str) hashpow2(t, (str)->hash)
#define eqshrstr(a,b) ((a) == (b))

@ -1,10 +1,11 @@
; ModuleID = 'inline_getstr.c'
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-S32"
target triple = "i686-pc-windows-gnu"
source_filename = "inline_getstr.c"
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
target triple = "i686-pc-windows-msvc"
%struct.TValue = type { %union.Value, i32 }
%union.Value = type { i64 }
%struct.Table = type { %struct.GCObject*, i8, i8, i8, i8, i32, %struct.TValue*, %struct.Node*, %struct.Node*, %struct.Table*, %struct.GCObject*, %struct.RaviArray }
%struct.Table = type { %struct.GCObject*, i8, i8, i8, i8, i32, %struct.TValue*, %struct.Node*, %struct.Node*, %struct.Table*, %struct.GCObject*, %struct.RaviArray, i32 }
%struct.Node = type { %struct.TValue, %union.TKey }
%union.TKey = type { %struct.anon.1 }
%struct.anon.1 = type { %union.Value, i32, i32 }
@ -14,36 +15,33 @@ target triple = "i686-pc-windows-gnu"
%union.anon.2 = type { i64 }
; Function Attrs: nounwind
define %struct.TValue* @ravi_getstr(%struct.Table* %t, %struct.TString* %key) #0 {
define %struct.TValue* @ravi_getstr(%struct.Table* %t, %struct.TString* %key) local_unnamed_addr #0 {
entry:
%hash = getelementptr inbounds %struct.TString, %struct.TString* %key, i32 0, i32 5
%0 = load i32, i32* %hash, align 4, !tbaa !1
%lsizenode = getelementptr inbounds %struct.Table, %struct.Table* %t, i32 0, i32 4
%1 = load i8, i8* %lsizenode, align 1, !tbaa !7
%conv = zext i8 %1 to i32
%shl = shl i32 1, %conv
%sub = add nsw i32 %shl, -1
%and = and i32 %sub, %0
%0 = load i32, i32* %hash, align 8, !tbaa !1
%hmask = getelementptr inbounds %struct.Table, %struct.Table* %t, i32 0, i32 12
%1 = load i32, i32* %hmask, align 4, !tbaa !7
%and = and i32 %1, %0
%node = getelementptr inbounds %struct.Table, %struct.Table* %t, i32 0, i32 7
%2 = load %struct.Node*, %struct.Node** %node, align 4, !tbaa !10
%3 = getelementptr inbounds %struct.Node, %struct.Node* %2, i32 %and, i32 1, i32 0, i32 1
%4 = load i32, i32* %3, align 4, !tbaa !11
%4 = load i32, i32* %3, align 8, !tbaa !11
%cmp = icmp eq i32 %4, 68
br i1 %cmp, label %land.lhs.true, label %if.end
land.lhs.true: ; preds = %entry
%value_ = getelementptr inbounds %struct.Node, %struct.Node* %2, i32 %and, i32 1, i32 0, i32 0
%5 = bitcast %union.Value* %value_ to %struct.TString**
%6 = load %struct.TString*, %struct.TString** %5, align 4, !tbaa !13
%cmp2 = icmp eq %struct.TString* %6, %key
br i1 %cmp2, label %if.then, label %if.end
%6 = load %struct.TString*, %struct.TString** %5, align 8, !tbaa !13
%cmp1 = icmp eq %struct.TString* %6, %key
br i1 %cmp1, label %if.then, label %if.end
if.then: ; preds = %land.lhs.true
%i_val = getelementptr inbounds %struct.Node, %struct.Node* %2, i32 %and, i32 0
br label %cleanup
if.end: ; preds = %land.lhs.true, %entry
%call = tail call %struct.TValue* @luaH_getstr(%struct.Table* %t, %struct.TString* %key) #2
%call = tail call %struct.TValue* @luaH_getstr(%struct.Table* nonnull %t, %struct.TString* nonnull %key) #2
br label %cleanup
cleanup: ; preds = %if.end, %if.then
@ -51,23 +49,23 @@ cleanup: ; preds = %if.end, %if.then
ret %struct.TValue* %retval.0
}
declare %struct.TValue* @luaH_getstr(%struct.Table*, %struct.TString*) #1
declare %struct.TValue* @luaH_getstr(%struct.Table*, %struct.TString*) local_unnamed_addr #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 = { "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 #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-features"="+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-features"="+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #2 = { nounwind }
!llvm.ident = !{!0}
!0 = !{!"clang version 3.7.0 (trunk)"}
!0 = !{!"clang version 3.9.0 (trunk)"}
!1 = !{!2, !6, i64 8}
!2 = !{!"TString", !3, i64 0, !4, i64 4, !4, i64 5, !4, i64 6, !4, i64 7, !6, i64 8, !4, i64 16}
!3 = !{!"any pointer", !4, i64 0}
!4 = !{!"omnipotent char", !5, i64 0}
!5 = !{!"Simple C/C++ TBAA"}
!6 = !{!"int", !4, i64 0}
!7 = !{!8, !4, i64 7}
!8 = !{!"Table", !3, i64 0, !4, i64 4, !4, i64 5, !4, i64 6, !4, i64 7, !6, i64 8, !3, i64 12, !3, i64 16, !3, i64 20, !3, i64 24, !3, i64 28, !9, i64 32}
!7 = !{!8, !6, i64 48}
!8 = !{!"Table", !3, i64 0, !4, i64 4, !4, i64 5, !4, i64 6, !4, i64 7, !6, i64 8, !3, i64 12, !3, i64 16, !3, i64 20, !3, i64 24, !3, i64 28, !9, i64 32, !6, i64 48}
!9 = !{!"RaviArray", !3, i64 0, !4, i64 4, !6, i64 8, !6, i64 12}
!10 = !{!8, !3, i64 16}
!11 = !{!12, !6, i64 8}

@ -204,6 +204,7 @@ struct Table {
struct Table *metatable;
struct GCObject *gclist;
struct RaviArray ravi_array;
unsigned int hmask;
};
/* lzio.h */

@ -588,6 +588,7 @@ typedef struct Table {
GCObject *gclist;
/** RAVI extension */
RaviArray ravi_array;
unsigned int hmask; /* Hash part mask (size of hash part - 1) - borrowed from LuaJIT */
} Table;

@ -43,8 +43,28 @@
LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key,
TValue *value);
/** RAVI change start - attempt to inline some functions **/
#if defined(RAVI_ENABLED)
#define NEW_HASH 1
#if NEW_HASH
/*
Like LuaJIT we use a pre-computed hmask to minimise the number of steps
required to get to a node in the hash table
*/
#define hashpow2(t, h) (gnode(t, (h & (t)->hmask)))
#define hashstr(t, str) hashpow2(t, (str)->hash)
#define hashboolean(t, p) hashpow2(t, p)
#define hashint(t, i) hashpow2(t, i)
/*
** for some types, it is better to avoid modulus by power of 2, as
** they tend to have many 2 factors.
*/
#define hashmod(t, n) (gnode(t, ((n) % ((t)->hmask|1))))
#define hashpointer(t, p) hashmod(t, point2uint(p))
#else
#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
#define hashstr(t,str) hashpow2(t, (str)->hash)
#define hashboolean(t,p) hashpow2(t, p)
@ -55,6 +75,9 @@ LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key,
*/
#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1))))
#define hashpointer(t,p) hashmod(t, point2uint(p))
#endif
#if defined(RAVI_ENABLED)
/*
** search function for short strings
*/

@ -351,6 +351,7 @@ struct LuaLLVMTypes {
llvm::MDNode *tbaa_Table_array;
llvm::MDNode *tbaa_Table_flags;
llvm::MDNode *tbaa_Table_metatable;
llvm::MDNode *tbaa_Table_hmask;
};
// The hierarchy of objects
@ -805,8 +806,8 @@ class RaviCodeGenerator {
// The return value is a boolean type as a result of
// integer comparison result which is i1 in LLVM
llvm::Value *emit_is_not_value_of_type_class(
RaviFunctionDef *def, llvm::Value *value_type, LuaTypeCode lua_typecode,
const char *varname = "value.not.typeof");
RaviFunctionDef *def, llvm::Value *value_type, LuaTypeCode lua_typecode,
const char *varname = "value.not.typeof");
// emit code for LClosure *cl = clLvalue(ci->func)
// this is same as:
@ -1041,9 +1042,8 @@ class RaviCodeGenerator {
void emit_ARITH(RaviFunctionDef *def, int A, int B, int C, OpCode op, TMS tms,
int pc);
void emit_ARITH_new(RaviFunctionDef *def, int A, int B, int C, OpCode op, TMS tms,
int pc);
void emit_ARITH_new(RaviFunctionDef *def, int A, int B, int C, OpCode op,
TMS tms, int pc);
void emit_MOD(RaviFunctionDef *def, int A, int B, int C, int pc);
@ -1131,7 +1131,8 @@ class RaviCodeGenerator {
void emit_GETTABLE_S(RaviFunctionDef *def, int A, int B, int C, int pc,
TString *key);
void emit_GETTABLE_SK(RaviFunctionDef *def, int A, int B, int C, int pc);
void emit_GETTABLE_SK(RaviFunctionDef *def, int A, int B, int C, int pc,
TString *key);
void emit_GETTABLE_I(RaviFunctionDef *def, int A, int B, int C, int pc);
@ -1148,8 +1149,8 @@ class RaviCodeGenerator {
void emit_common_GETTABLE_S(RaviFunctionDef *def, int A, int B, int C,
TString *key);
void emit_common_GETTABLE_S_(RaviFunctionDef *def, int A, llvm::Value *rb, int C,
TString *key);
void emit_common_GETTABLE_S_(RaviFunctionDef *def, int A, llvm::Value *rb,
int C, TString *key);
void emit_GETUPVAL(RaviFunctionDef *def, int A, int B, int pc);
@ -1236,8 +1237,8 @@ class RaviCodeGenerator {
void emit_BNOT_I(RaviFunctionDef *def, int A, int B, int pc);
void emit_BOR_BXOR_BAND(RaviFunctionDef *def, OpCode op, int A, int B,
int C, int pc);
void emit_BOR_BXOR_BAND(RaviFunctionDef *def, OpCode op, int A, int B, int C,
int pc);
void emit_BNOT(RaviFunctionDef *def, int A, int B, int pc);

@ -56,24 +56,6 @@
*/
#define MAXHBITS (MAXABITS - 1)
#if !defined(RAVI_ENABLED)
#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
#define hashstr(t,str) hashpow2(t, (str)->hash)
#define hashboolean(t,p) hashpow2(t, p)
#define hashint(t,i) hashpow2(t, i)
/*
** for some types, it is better to avoid modulus by power of 2, as
** they tend to have many 2 factors.
*/
#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1))))
#define hashpointer(t,p) hashmod(t, point2uint(p))
#endif
#define dummynode (&dummynode_)
static const Node dummynode_ = {
@ -345,6 +327,7 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) {
if (size == 0) { /* no elements to hash part? */
t->node = cast(Node *, dummynode); /* use common 'dummynode' */
t->lsizenode = 0;
t->hmask = 0;
t->lastfree = NULL; /* signal that it is using dummy node */
}
else {
@ -361,6 +344,7 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) {
setnilvalue(gval(n));
}
t->lsizenode = cast_byte(lsize);
t->hmask = size - 1;
t->lastfree = gnode(t, size); /* all positions are free */
}
}

@ -20,8 +20,8 @@
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************/
#include "ravi_llvmcodegen.h"
#include <ravijit.h>
#include "ravi_llvmcodegen.h"
namespace ravi {
@ -151,7 +151,6 @@ llvm::Value *RaviCodeGenerator::emit_array_get(RaviFunctionDef *def,
// emit code for LClosure *cl = clLvalue(ci->func);
llvm::Instruction *RaviCodeGenerator::emit_gep_ci_func_value_gc_asLClosure(
RaviFunctionDef *def) {
// clLvalue() is a macros that expands to (LClosure *)ci->func->value_.gc
// via a complex series of macros and unions
// fortunately as func is at the beginning of the CallInfo
@ -345,6 +344,14 @@ llvm::Value *RaviCodeGenerator::emit_table_get_hashsize(RaviFunctionDef *def,
llvm::Value *RaviCodeGenerator::emit_table_get_hashstr(RaviFunctionDef *def,
llvm::Value *table,
TString *key) {
#if NEW_HASH
unsigned int hash = key->hash;
llvm::Value *hmask_ptr = emit_gep(def, "hmask", table, 0, 12);
llvm::Instruction *hmask = def->builder->CreateLoad(hmask_ptr);
hmask->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_Table_hmask);
llvm::Value *offset = def->builder->CreateAnd(
llvm::ConstantInt::get(def->types->C_intT, hash), hmask);
#else
llvm::Value *size = emit_table_get_hashsize(def, table);
unsigned int hash = key->hash;
// #define lmod(s,size) (cast(int, (s) & ((size)-1)))
@ -352,6 +359,7 @@ llvm::Value *RaviCodeGenerator::emit_table_get_hashstr(RaviFunctionDef *def,
def->builder->CreateNSWSub(size, def->types->kInt[1]);
llvm::Value *offset = def->builder->CreateAnd(
llvm::ConstantInt::get(def->types->C_intT, hash), sizeminusone);
#endif
return offset;
}
@ -1644,7 +1652,11 @@ bool RaviCodeGenerator::compile(lua_State *L, Proto *p,
case OP_RAVI_GETTABLE_SK: {
int B = GETARG_B(i);
int C = GETARG_C(i);
emit_GETTABLE_SK(def, A, B, C, pc);
lua_assert(ISK(C));
TValue *kv = k + INDEXK(C);
TString *key = tsvalue(kv);
lua_assert(key->tt == LUA_TSHRSTR);
emit_GETTABLE_SK(def, A, B, C, pc, key);
} break;
case OP_GETTABLE: {
int B = GETARG_B(i);
@ -1890,7 +1902,7 @@ bool RaviCodeGenerator::compile(lua_State *L, Proto *p,
}
}
}
doVerify = true;
if (doVerify && llvm::verifyFunction(*f->function(), &llvm::errs())) {
f->dump();
fprintf(stderr, "LLVM Code Verification failed\n");

@ -44,7 +44,7 @@ void RaviCodeGenerator::emit_SELF(RaviFunctionDef *def, int A, int B, int C,
// R(A+1) := R(B); R(A) := R(B)[RK(C)]
void RaviCodeGenerator::emit_SELF_SK(RaviFunctionDef *def, int A, int B, int C,
int pc) {
int pc) {
// StkId rb = RB(i);
// setobjs2s(L, ra + 1, rb);
// Protect(raviV_gettable_sskey(L, rb, RKC(i), ra));
@ -59,7 +59,7 @@ void RaviCodeGenerator::emit_SELF_SK(RaviFunctionDef *def, int A, int B, int C,
llvm::Value *rc = emit_gep_register_or_constant(def, C);
CreateCall4(def->builder, def->raviV_gettable_sskeyF, def->L, rb, rc, ra);
}
// R(A+1) := R(B); R(A) := R(B)[RK(C)]
void RaviCodeGenerator::emit_SELF_S(RaviFunctionDef *def, int A, int B, int C,
int pc, TString *key) {
@ -97,7 +97,7 @@ void RaviCodeGenerator::emit_LEN(RaviFunctionDef *def, int A, int B, int pc) {
// b) we know the key is an integer
void RaviCodeGenerator::emit_SETTABLE_I(RaviFunctionDef *def, int A, int B,
int C, int pc) {
// This is broken as we need to handle meta methods etc.
// This is broken as we need to handle meta methods etc.
lua_assert(false);
#if 0
emit_debug_trace(def, OP_RAVI_SETTABLE_I, pc);
@ -126,8 +126,8 @@ void RaviCodeGenerator::emit_SETTABLE(RaviFunctionDef *def, int A, int B, int C,
}
// R(A)[RK(B)] := RK(C)
void RaviCodeGenerator::emit_SETTABLE_SK(RaviFunctionDef *def, int A, int B, int C,
int pc) {
void RaviCodeGenerator::emit_SETTABLE_SK(RaviFunctionDef *def, int A, int B,
int C, int pc) {
// Protect(raviV_settable_sskey(L, ra, RKB(i), RKC(i)));
bool traced = emit_debug_trace(def, OP_RAVI_SETTABLE_SK, pc);
// Below may invoke metamethod so we set savedpc
@ -139,7 +139,6 @@ void RaviCodeGenerator::emit_SETTABLE_SK(RaviFunctionDef *def, int A, int B, int
CreateCall4(def->builder, def->raviV_settable_sskeyF, def->L, ra, rb, rc);
}
// R(A) := R(B)[RK(C)]
void RaviCodeGenerator::emit_GETTABLE(RaviFunctionDef *def, int A, int B, int C,
int pc) {
@ -155,19 +154,50 @@ void RaviCodeGenerator::emit_GETTABLE(RaviFunctionDef *def, int A, int B, int C,
}
// R(A) := R(B)[RK(C)]
void RaviCodeGenerator::emit_GETTABLE_SK(RaviFunctionDef *def, int A, int B, int C,
int pc) {
// Protect(raviV_gettable_sskey(L, RB(i), RKC(i), ra));
void RaviCodeGenerator::emit_GETTABLE_SK(RaviFunctionDef *def, int A, int B,
int C, int pc, TString *key) {
bool traced = emit_debug_trace(def, OP_RAVI_GETTABLE_SK, pc);
// Below may invoke metamethod so we set savedpc
if (!traced) emit_update_savedpc(def, pc);
emit_load_base(def);
llvm::Value *ra = emit_gep_register(def, A);
llvm::Value *rb = emit_gep_register(def, B);
#if 0
// Protect(raviV_gettable_sskey(L, RB(i), RKC(i), ra));
llvm::Value *ra = emit_gep_register(def, A);
llvm::Value *rc = emit_gep_register_or_constant(def, C);
CreateCall4(def->builder, def->raviV_gettable_sskeyF, def->L, rb, rc, ra);
}
#else
llvm::Instruction *type = emit_load_type(def, rb);
// if table type try fast path
llvm::Value *cmp1 = emit_is_value_of_type(def, type, RAVI__TLTABLE,
"GETTABLE_SK_is_table_type");
llvm::BasicBlock *is_table = llvm::BasicBlock::Create(
def->jitState->context(), "GETTABLE_SK_is_table", def->f);
llvm::BasicBlock *not_table = llvm::BasicBlock::Create(
def->jitState->context(), "GETTABLE_SK_is_not_table");
llvm::BasicBlock *done =
llvm::BasicBlock::Create(def->jitState->context(), "GETTABLE_SK_done");
def->builder->CreateCondBr(cmp1, is_table, not_table);
def->builder->SetInsertPoint(is_table);
emit_common_GETTABLE_S_(def, A, rb, C, key);
def->builder->CreateBr(done);
def->f->getBasicBlockList().push_back(not_table);
def->builder->SetInsertPoint(not_table);
llvm::Value *ra = emit_gep_register(def, A);
llvm::Value *rc = emit_gep_register_or_constant(def, C);
CreateCall4(def->builder, def->raviV_gettable_sskeyF, def->L, rb, rc, ra);
def->builder->CreateBr(done);
def->f->getBasicBlockList().push_back(done);
def->builder->SetInsertPoint(done);
#endif
}
// R(A) := R(B)[RK(C)]
// This is a more optimized version that attempts to do an inline
@ -247,8 +277,9 @@ void RaviCodeGenerator::emit_finish_GETTABLE(RaviFunctionDef *def,
// or if the metatable cached flags indicate metamethod absent
llvm::Value *value_type = emit_load_type(def, phi);
llvm::Value *isnotnil = emit_is_not_value_of_type(def, value_type, LUA__TNIL);
//llvm::Value *metamethod_absent = emit_table_no_metamethod(def, t, TM_INDEX);
//llvm::Value *cond = def->builder->CreateOr(isnotnil, metamethod_absent);
// llvm::Value *metamethod_absent = emit_table_no_metamethod(def, t,
// TM_INDEX);
// llvm::Value *cond = def->builder->CreateOr(isnotnil, metamethod_absent);
llvm::Value *cond = isnotnil;
llvm::BasicBlock *if_true_block = llvm::BasicBlock::Create(
@ -285,9 +316,10 @@ void RaviCodeGenerator::emit_finish_GETTABLE(RaviFunctionDef *def,
// to be short string
// NOTE: To add support for GETTABUP_SK we now let caller supply the
// rb register as it may be a register or an upvalue reference
// See emit_GETTABUP_SK
// See emit_GETTABUP_SK
void RaviCodeGenerator::emit_common_GETTABLE_S_(RaviFunctionDef *def, int A,
llvm::Value *rb, int C, TString *key) {
llvm::Value *rb, int C,
TString *key) {
// The code we want to generate is this:
// struct Node *n = hashstr(t, key);
// const struct TValue *k = gkey(n);
@ -323,15 +355,15 @@ void RaviCodeGenerator::emit_common_GETTABLE_S_(RaviFunctionDef *def, int A,
// We need to check that the key type is also short string
llvm::Value *is_shortstring =
emit_is_value_of_type(def, ktype, LUA__TSHRSTR, "is_shortstring");
emit_is_value_of_type(def, ktype, LUA__TSHRSTR, "is_shortstring");
llvm::BasicBlock *testkey =
llvm::BasicBlock::Create(def->jitState->context(), "testkey");
llvm::BasicBlock::Create(def->jitState->context(), "testkey");
llvm::BasicBlock *testok =
llvm::BasicBlock::Create(def->jitState->context(), "testok");
llvm::BasicBlock::Create(def->jitState->context(), "testok");
llvm::BasicBlock *testfail =
llvm::BasicBlock::Create(def->jitState->context(), "testfail");
llvm::BasicBlock::Create(def->jitState->context(), "testfail");
llvm::BasicBlock *testend =
llvm::BasicBlock::Create(def->jitState->context(), "testend");
llvm::BasicBlock::Create(def->jitState->context(), "testend");
def->builder->CreateCondBr(is_shortstring, testkey, testfail);
// Now we need to compare the keys
@ -343,9 +375,9 @@ void RaviCodeGenerator::emit_common_GETTABLE_S_(RaviFunctionDef *def, int A,
// Cast the pointer to a intptr so we can compare
llvm::Value *intptr =
def->builder->CreatePtrToInt(keyvalue, def->types->C_intptr_t);
def->builder->CreatePtrToInt(keyvalue, def->types->C_intptr_t);
llvm::Value *ourptr =
llvm::ConstantInt::get(def->types->C_intptr_t, (intptr_t)key);
llvm::ConstantInt::get(def->types->C_intptr_t, (intptr_t)key);
// Compare the two pointers
// If they match then we found the element
llvm::Value *same = def->builder->CreateICmpEQ(intptr, ourptr);
@ -363,8 +395,8 @@ void RaviCodeGenerator::emit_common_GETTABLE_S_(RaviFunctionDef *def, int A,
def->f->getBasicBlockList().push_back(testfail);
def->builder->SetInsertPoint(testfail);
llvm::Value *rc2 = emit_gep_register_or_constant(def, C);
llvm::Value *value2 =
CreateCall2(def->builder, def->luaH_getstrF, t, emit_load_reg_s(def, rc2));
llvm::Value *value2 = CreateCall2(def->builder, def->luaH_getstrF, t,
emit_load_reg_s(def, rc2));
def->builder->CreateBr(testend);
// merge
@ -764,8 +796,8 @@ void RaviCodeGenerator::emit_GETTABUP(RaviFunctionDef *def, int A, int B, int C,
}
// R(A) := UpValue[B][RK(C)]
void RaviCodeGenerator::emit_GETTABUP_SK(RaviFunctionDef *def, int A, int B, int C,
int pc) {
void RaviCodeGenerator::emit_GETTABUP_SK(RaviFunctionDef *def, int A, int B,
int C, int pc) {
// int b = GETARG_B(i);
// Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra));
bool traced = emit_debug_trace(def, OP_RAVI_GETTABUP_SK, pc);
@ -781,7 +813,6 @@ void RaviCodeGenerator::emit_GETTABUP_SK(RaviFunctionDef *def, int A, int B, int
CreateCall4(def->builder, def->raviV_gettable_sskeyF, def->L, v, rc, ra);
}
// UpValue[A][RK(B)] := RK(C)
void RaviCodeGenerator::emit_SETTABUP(RaviFunctionDef *def, int A, int B, int C,
int pc) {
@ -801,8 +832,8 @@ void RaviCodeGenerator::emit_SETTABUP(RaviFunctionDef *def, int A, int B, int C,
}
// UpValue[A][RK(B)] := RK(C)
void RaviCodeGenerator::emit_SETTABUP_SK(RaviFunctionDef *def, int A, int B, int C,
int pc) {
void RaviCodeGenerator::emit_SETTABUP_SK(RaviFunctionDef *def, int A, int B,
int C, int pc) {
// int a = GETARG_A(i);
// Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i)));
@ -887,19 +918,19 @@ void RaviCodeGenerator::emit_TOARRAY(RaviFunctionDef *def, int A,
llvm::Instruction *type = emit_load_type(def, ra);
// type != expectedType
llvm::Value *cmp1 =
emit_is_not_value_of_type(def, type, expectedType, "is.not.expected.type");
llvm::Value *cmp1 = emit_is_not_value_of_type(def, type, expectedType,
"is.not.expected.type");
llvm::BasicBlock *raise_error = llvm::BasicBlock::Create(
def->jitState->context(), "if.not.expected_type", def->f);
def->jitState->context(), "if.not.expected_type", def->f);
llvm::BasicBlock *done =
llvm::BasicBlock::Create(def->jitState->context(), "done");
llvm::BasicBlock::Create(def->jitState->context(), "done");
def->builder->CreateCondBr(cmp1, raise_error, done);
def->builder->SetInsertPoint(raise_error);
// Conversion failed, so raise error
emit_raise_lua_error(def, errmsg);
def->builder->CreateBr(done);
def->f->getBasicBlockList().push_back(done);
def->builder->SetInsertPoint(done);
}

@ -469,6 +469,7 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) {
// struct Table *metatable;
// GCObject *gclist;
// RaviArray ravi_array;
// unsigned int hmask; /* Hash part mask (size of hash part - 1) */
//} Table;
elements.clear();
elements.push_back(pGCObjectT);
@ -483,6 +484,7 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) {
elements.push_back(pTableT); /* metatable */
elements.push_back(pGCObjectT); /* gclist */
elements.push_back(RaviArrayT); /* RaviArray */
elements.push_back(C_intT); /* hmask */
TableT->setBody(elements);
// struct lua_longjmp; /* defined in ldo.c */
@ -541,8 +543,10 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) {
// ptrdiff_t extra;
// short nresults; /* expected number of results from this function */
// unsigned short callstatus;
// unsigned short stacklevel; /* Ravi extension - stack level, bottom level is 0 */
// lu_byte jitstatus; /* Only valid if Lua function - if 1 means JITed - RAVI extension */
// unsigned short stacklevel; /* Ravi extension - stack level, bottom level
// is 0 */
// lu_byte jitstatus; /* Only valid if Lua function - if 1 means JITed - RAVI
// extension */
//} CallInfo;
elements.clear();
@ -571,8 +575,8 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) {
elements.push_back(C_ptrdiff_t); /* extra */
elements.push_back(llvm::Type::getInt16Ty(context)); /* nresults */
elements.push_back(C_shortT); /* callstatus */
elements.push_back(C_shortT); /* stacklevel RAVI extension */
elements.push_back(lu_byteT); /* jitstatus RAVI extension*/
elements.push_back(C_shortT); /* stacklevel RAVI extension */
elements.push_back(lu_byteT); /* jitstatus RAVI extension*/
CallInfoT->setBody(elements);
// typedef struct ravi_State ravi_State;
@ -1071,9 +1075,9 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) {
nodes.push_back(
std::pair<llvm::MDNode *, uint64_t>(tbaa_shortT, 42)); // callstatus
nodes.push_back(
std::pair<llvm::MDNode *, uint64_t>(tbaa_shortT, 44)); // stacklevel
std::pair<llvm::MDNode *, uint64_t>(tbaa_shortT, 44)); // stacklevel
nodes.push_back(
std::pair<llvm::MDNode *, uint64_t>(tbaa_charT, 46)); // jitstatus
std::pair<llvm::MDNode *, uint64_t>(tbaa_charT, 46)); // jitstatus
tbaa_CallInfoT = mdbuilder.createTBAAStructTypeNode("CallInfo", nodes);
//! 7 = metadata !{metadata !"lua_State",
@ -1283,6 +1287,8 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) {
std::pair<llvm::MDNode *, uint64_t>(tbaa_pointerT, 28)); /* gclist */
nodes.push_back(std::pair<llvm::MDNode *, uint64_t>(tbaa_RaviArrayT,
32)); /* ravi_array */
nodes.push_back(
std::pair<llvm::MDNode *, uint64_t>(tbaa_intT, 48)); /* hmask */
tbaa_TableT = mdbuilder.createTBAAStructTypeNode("Table", nodes);
tbaa_Table_flags =
@ -1297,6 +1303,8 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) {
mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_pointerT, 16);
tbaa_Table_metatable =
mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_pointerT, 24);
tbaa_Table_hmask =
mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_intT, 48);
tbaa_RaviArray_dataT =
mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_pointerT, 32);
tbaa_RaviArray_lenT =

Loading…
Cancel
Save