mirror of
https://github.com/lua/lua
synced 2025-02-23 16:44:14 +03:00
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:
parent
b4b616bdf2
commit
25a491fe34
43
lcode.c
43
lcode.c
@ -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.
|
||||
|
15
ldebug.c
15
ldebug.c
@ -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 */
|
||||
|
@ -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
6
lvm.c
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user