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.