OP_SELF restricted to constant short strings

Optimize this opcode for the common case. For long names or method
calls after too many constants, operation can be coded as a move
followed by 'gettable'.
This commit is contained in:
Roberto Ierusalimschy 2024-12-11 13:56:03 -03:00
parent b4b616bdf2
commit 25a491fe34
5 changed files with 35 additions and 34 deletions

43
lcode.c
View File

@ -1085,22 +1085,6 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
}
/*
** Emit SELF instruction (convert expression 'e' into 'e:key(e,').
*/
void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
int ereg;
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; /* self expression has a fixed register */
luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */
codeABRK(fs, OP_SELF, e->u.info, ereg, key);
freeexp(fs, key);
}
/*
** Negate condition 'e' (where 'e' is a comparison).
*/
@ -1275,6 +1259,33 @@ static int isSCnumber (expdesc *e, int *pi, int *isfloat) {
}
/*
** Emit SELF instruction or equivalent: the code will convert
** expression 'e' into 'e.key(e,'.
*/
void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
int ereg, base;
luaK_exp2anyreg(fs, e);
ereg = e->u.info; /* register where 'e' (the receiver) was placed */
freeexp(fs, e);
base = e->u.info = fs->freereg; /* base register for op_self */
e->k = VNONRELOC; /* self expression has a fixed register */
luaK_reserveregs(fs, 2); /* method and 'self' produced by op_self */
lua_assert(key->k == VKSTR);
/* is method name a short string in a valid K index? */
if (strisshr(key->u.strval) && luaK_exp2K(fs, key)) {
/* can use 'self' opcode */
luaK_codeABCk(fs, OP_SELF, base, ereg, key->u.info, 0);
}
else { /* cannot use 'self' opcode; use move+gettable */
luaK_exp2anyreg(fs, key); /* put method name in a register */
luaK_codeABC(fs, OP_MOVE, base + 1, ereg, 0); /* copy self to base+1 */
luaK_codeABC(fs, OP_GETTABLE, base, ereg, key->u.info); /* get method */
}
freeexp(fs, key);
}
/*
** Create expression 't[k]'. 't' must have its final result already in a
** register or upvalue. Upvalues can only be indexed by literal strings.

View File

@ -541,18 +541,6 @@ static void rname (const Proto *p, int pc, int c, const char **name) {
}
/*
** Find a "name" for a 'C' value in an RK instruction.
*/
static void rkname (const Proto *p, int pc, Instruction i, const char **name) {
int c = GETARG_C(i); /* key index */
if (GETARG_k(i)) /* is 'c' a constant? */
kname(p, c, name);
else /* 'c' is a register */
rname(p, pc, c, name);
}
/*
** Check whether table being indexed by instruction 'i' is the
** environment '_ENV'
@ -600,7 +588,8 @@ static const char *getobjname (const Proto *p, int lastpc, int reg,
return isEnv(p, lastpc, i, 0);
}
case OP_SELF: {
rkname(p, lastpc, i, name);
int k = GETARG_C(i); /* key index */
kname(p, k, name);
return "method";
}
default: break; /* go through to return NULL */

View File

@ -256,7 +256,7 @@ OP_SETFIELD,/* A B C R[A][K[B]:shortstring] := RK(C) */
OP_NEWTABLE,/* A B C k R[A] := {} */
OP_SELF,/* A B C R[A+1] := R[B]; R[A] := R[B][RK(C):string] */
OP_SELF,/* A B C R[A+1] := R[B]; R[A] := R[B][K[C]:shortstring] */
OP_ADDI,/* A B sC R[A] := R[B] + sC */

6
lvm.c
View File

@ -1382,10 +1382,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
StkId ra = RA(i);
lu_byte tag;
TValue *rb = vRB(i);
TValue *rc = RKC(i);
TString *key = tsvalue(rc); /* key must be a string */
TValue *rc = KC(i);
TString *key = tsvalue(rc); /* key must be a short string */
setobj2s(L, ra + 1, rb);
luaV_fastget(rb, key, s2v(ra), luaH_getstr, tag);
luaV_fastget(rb, key, s2v(ra), luaH_getshortstr, tag);
if (tagisempty(tag))
Protect(luaV_finishget(L, rb, rc, ra, tag));
vmbreak;

View File

@ -321,7 +321,8 @@ t = nil
checkmessage(s.."; aaa = bbb + 1", "global 'bbb'")
checkmessage("local _ENV=_ENV;"..s.."; aaa = bbb + 1", "global 'bbb'")
checkmessage(s.."; local t = {}; aaa = t.bbb + 1", "field 'bbb'")
checkmessage(s.."; local t = {}; t:bbb()", "method 'bbb'")
-- cannot use 'self' opcode
checkmessage(s.."; local t = {}; t:bbb()", "field 'bbb'")
checkmessage([[aaa=9
repeat until 3==3