issue #71 add specialised bytecode for method calls when type is table and key is short string

pull/81/head
Dibyendu Majumdar 9 years ago
parent a11f7bbd27
commit 852cfee3da

@ -306,11 +306,12 @@ OP_RAVI_SETTABLE_S,/* A B C R(A)[RK(B)] := RK(C), string key */
OP_RAVI_TOTAB, /* A R(A) := to_table(R(A)) */
OP_RAVI_MOVETAB, /* A B R(A) := R(B), check R(B) is a table */
OP_RAVI_SETUPVALT,/* A B UpValue[B] := to_table(R(A)) */
OP_RAVI_SELF_S,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
} OpCode;
#define NUM_OPCODES (cast(int, OP_RAVI_SETUPVALT) + 1)
#define NUM_OPCODES (cast(int, OP_RAVI_SELF_S) + 1)
/*===========================================================================
Notes:

@ -994,6 +994,10 @@ public:
void emit_SELF(RaviFunctionDef *def, int A, int B, int C, int pc);
void emit_SELF_S(RaviFunctionDef *def, int A, int B, int C, int pc, TString *key);
void emit_common_GETTABLE_S(RaviFunctionDef *def, int A, int B, int C, TString *key);
void emit_GETUPVAL(RaviFunctionDef *def, int A, int B, int pc);
void emit_SETUPVAL(RaviFunctionDef *def, int A, int B, int pc);

@ -112,6 +112,7 @@ opcodes_coverage.SETTABLE_S = 0
opcodes_coverage.TOTAB = 0
opcodes_coverage.MOVETAB = 0
opcodes_coverage.SETUPVALT = 0
opcodes_coverage.SELF_S = 0
local compile = function(f)
@ -1084,7 +1085,7 @@ function test_idiv()
local s2=x(4.1,2.0)
assert(s1 == s2)
end
assert(compile(test_idiv))
compile(test_idiv)
test_idiv()
print'test 47 (IDIV) OK'
@ -1136,6 +1137,20 @@ end
test_tableaccess()
print 'Test 48 OK'
function test_self_s()
local t : table = {}
t.name_ = 'dibyendu majumdar'
t.name = function (t:table) return t.name_ end
print(t:name())
return t:name()
end
check(test_self_s, 'NEWTABLE', 'SETTABLE_S', 'CLOSURE',
'SETTABLE_S', 'GETTABUP', 'SELF_S', 'CALL', 'CALL', 'SELF_S', 'TAILCALL',
'RETURN')
assert(test_self_s() == 'dibyendu majumdar')
compile(test_self_s)
assert(test_self_s() == 'dibyendu majumdar')
print 'Test 49 OK'
for k,v in pairs(opcodes_coverage)
do

@ -796,13 +796,17 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
int ereg;
int table_and_string = e->ravi_type == RAVI_TTABLE &&
key->k == VK &&
key->ravi_type == RAVI_TSTRING &&
isshortstr(fs, RKASK(key->u.info));
luaK_exp2anyreg(fs, e);
ereg = e->u.info; /* register where 'e' was placed */
freeexp(fs, e);
e->u.info = fs->freereg; /* base register for op_self */
e->k = VNONRELOC;
luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */
luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key));
luaK_codeABC(fs, table_and_string ? OP_RAVI_SELF_S : OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key));
freeexp(fs, key);
}

@ -482,6 +482,7 @@ static const char *getobjname (Proto *p, int lastpc, int reg,
}
break;
}
case OP_RAVI_SELF_S:
case OP_SELF: {
int k = GETARG_C(i); /* key index */
kname(p, pc, k, name);

@ -155,6 +155,7 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
"TOTAB", /* A R(A) := to_table(R(A)) */
"MOVETAB", /* A B R(A) := R(B), check R(B) is a table */
"SETUPVALT", /* A B UpValue[B] := to_table(R(A)) */
"SELF_S", /* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
NULL
};
@ -287,6 +288,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
,opmode(0, 1, OpArgN, OpArgN, iABC) /* OP_RAVI_TOTAB A R(A) := check_table(R(A)) */
,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_RAVI_MOVETAB A B R(A) := R(B), check R(B) is a table */
,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RAVI_SETUPVALT */
,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */
};

@ -935,6 +935,14 @@ newframe: /* reentry point when frame changes (call/return) */
luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c));
checkGC(L, ra + 1);
} break;
case OP_RAVI_SELF_S: {
StkId rb = RB(i);
setobjs2s(L, ra + 1, rb);
TValue *kv = k + INDEXK(GETARG_C(i));
TString *key = tsvalue(kv);
const TValue *v = luaH_getstr(hvalue(rb), key);
setobj2s(L, ra, v);
} break;
case OP_SELF: {
StkId rb = RB(i);
setobjs2s(L, ra+1, rb);

@ -882,6 +882,7 @@ bool RaviCodeGenerator::canCompile(Proto *p) {
case OP_RAVI_SETUPVALAI:
case OP_RAVI_SETUPVALAF:
case OP_RAVI_SETUPVALT:
case OP_RAVI_SELF_S:
break;
default:
return false;
@ -1576,6 +1577,15 @@ void RaviCodeGenerator::compile(lua_State *L, Proto *p,
lua_assert(key->tt == LUA_TSHRSTR);
emit_GETTABLE_S(def, A, B, C, pc, key);
} break;
case OP_RAVI_SELF_S: {
int C = GETARG_C(i);
int B = GETARG_B(i);
lua_assert(ISK(C));
TValue *kv = k + INDEXK(C);
TString *key = tsvalue(kv);
lua_assert(key->tt == LUA_TSHRSTR);
emit_SELF_S(def, A, B, C, pc, key);
} break;
case OP_RAVI_GETTABLE_I: {
int B = GETARG_B(i);
int C = GETARG_C(i);
@ -1824,7 +1834,6 @@ void RaviCodeGenerator::compile(lua_State *L, Proto *p,
} else {
p->ravi_jit.jit_status = RAVI_JIT_COMPILED;
}
// printf("compiled function\n");
}
void RaviCodeGenerator::scan_jump_targets(RaviFunctionDef *def, Proto *p) {

@ -43,6 +43,23 @@ void RaviCodeGenerator::emit_SELF(RaviFunctionDef *def, int A, int B, int C,
CreateCall4(def->builder, def->luaV_gettableF, 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) {
//StkId rb = RB(i);
//setobjs2s(L, ra + 1, rb);
//TValue *kv = k + INDEXK(GETARG_C(i));
//TString *key = tsvalue(kv);
//const TValue *v = luaH_getstr(hvalue(rb), key);
//setobj2s(L, ra, v);
emit_debug_trace(def, OP_RAVI_SELF_S, pc);
emit_load_base(def);
llvm::Value *rb = emit_gep_register(def, B);
llvm::Value *ra1 = emit_gep_register(def, A + 1);
emit_assign(def, ra1, rb);
emit_common_GETTABLE_S(def, A, B, C, key);
}
// R(A) := length of R(B)
void RaviCodeGenerator::emit_LEN(RaviFunctionDef *def, int A, int B, int pc) {
// Protect(luaV_objlen(L, ra, RB(i)));
@ -163,8 +180,8 @@ void RaviCodeGenerator::emit_GETTABLE_I(RaviFunctionDef *def, int A, int B,
// key is not in the main position then we fall back on luaH_getstr().
// IMPORTANT - this emitter should only be called when key is known to
// to be short string
void RaviCodeGenerator::emit_GETTABLE_S(RaviFunctionDef *def, int A, int B,
int C, int pc, TString *key) {
void RaviCodeGenerator::emit_common_GETTABLE_S(RaviFunctionDef *def, int A, int B,
int C, TString *key) {
// The code we want to generate is this:
// struct Node *n = hashstr(t, key);
@ -176,9 +193,6 @@ void RaviCodeGenerator::emit_GETTABLE_S(RaviFunctionDef *def, int A, int B,
// A number of macros are involved above do the
// the generated code is somewhat more complex
emit_debug_trace(def, OP_RAVI_GETTABLE_S, pc);
emit_load_base(def);
llvm::Value *ra = emit_gep_register(def, A);
llvm::Value *rb = emit_gep_register(def, B);
@ -197,15 +211,15 @@ void RaviCodeGenerator::emit_GETTABLE_S(RaviFunctionDef *def, int A, int B,
// 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
@ -217,9 +231,9 @@ void RaviCodeGenerator::emit_GETTABLE_S(RaviFunctionDef *def, int A, int B,
// 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);
@ -237,7 +251,7 @@ void RaviCodeGenerator::emit_GETTABLE_S(RaviFunctionDef *def, int A, int B,
def->builder->SetInsertPoint(testfail);
llvm::Value *rc = emit_gep_register_or_constant(def, C);
llvm::Value *value2 =
CreateCall2(def->builder, def->luaH_getstrF, t, emit_load_reg_s(def, rc));
CreateCall2(def->builder, def->luaH_getstrF, t, emit_load_reg_s(def, rc));
def->builder->CreateBr(testend);
// merge
@ -249,6 +263,27 @@ void RaviCodeGenerator::emit_GETTABLE_S(RaviFunctionDef *def, int A, int B,
emit_assign(def, ra, phi);
}
// R(A) := R(B)[RK(C)]
// Emit inline code for accessing a table element using a string key
// We try to access the element using the hash part but if the
// key is not in the main position then we fall back on luaH_getstr().
// IMPORTANT - this emitter should only be called when key is known to
// to be short string
void RaviCodeGenerator::emit_GETTABLE_S(RaviFunctionDef *def, int A, int B,
int C, int pc, TString *key) {
// The code we want to generate is this:
// struct Node *n = hashstr(t, key);
// const struct TValue *k = gkey(n);
// if (ttisshrstring(k) && eqshrstr(tsvalue(k), key))
// return gval(n);
// return luaH_getstr(t, key);
emit_debug_trace(def, OP_RAVI_GETTABLE_S, pc);
emit_load_base(def);
emit_common_GETTABLE_S(def, A, B, C, key);
}
void RaviCodeGenerator::emit_GETTABLE_AF(RaviFunctionDef *def, int A, int B,
int C, bool omitArrayGetRangeCheck,
int pc) {

Loading…
Cancel
Save