revamp of fast track for table access (table set uses the same
macros as table get + new macro for integer keys)
This commit is contained in:
41
lapi.c
41
lapi.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lapi.c,v 2.264 2017/04/20 18:22:44 roberto Exp roberto $
|
** $Id: lapi.c,v 2.265 2017/04/24 16:59:26 roberto Exp roberto $
|
||||||
** Lua API
|
** Lua API
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -609,10 +609,15 @@ LUA_API int lua_getglobal (lua_State *L, const char *name) {
|
|||||||
|
|
||||||
|
|
||||||
LUA_API int lua_gettable (lua_State *L, int idx) {
|
LUA_API int lua_gettable (lua_State *L, int idx) {
|
||||||
|
const TValue *slot;
|
||||||
StkId t;
|
StkId t;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
t = index2addr(L, idx);
|
t = index2addr(L, idx);
|
||||||
luaV_gettable(L, t, L->top - 1, L->top - 1);
|
if (luaV_fastget(L, t, L->top - 1, slot, luaH_get)) {
|
||||||
|
setobj2s(L, L->top - 1, slot);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
luaV_finishget(L, t, L->top - 1, L->top - 1, slot);
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
return ttnov(L->top - 1);
|
return ttnov(L->top - 1);
|
||||||
}
|
}
|
||||||
@@ -629,15 +634,15 @@ LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
|
|||||||
const TValue *slot;
|
const TValue *slot;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
t = index2addr(L, idx);
|
t = index2addr(L, idx);
|
||||||
if (luaV_fastget(L, t, n, slot, luaH_getint)) {
|
if (luaV_fastgeti(L, t, n, slot)) {
|
||||||
setobj2s(L, L->top, slot);
|
setobj2s(L, L->top, slot);
|
||||||
api_incr_top(L);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setivalue(L->top, n);
|
TValue aux;
|
||||||
api_incr_top(L);
|
setivalue(&aux, n);
|
||||||
luaV_finishget(L, t, L->top - 1, L->top - 1, slot);
|
luaV_finishget(L, t, &aux, L->top, slot);
|
||||||
}
|
}
|
||||||
|
api_incr_top(L);
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
return ttnov(L->top - 1);
|
return ttnov(L->top - 1);
|
||||||
}
|
}
|
||||||
@@ -743,8 +748,10 @@ static void auxsetstr (lua_State *L, const TValue *t, const char *k) {
|
|||||||
const TValue *slot;
|
const TValue *slot;
|
||||||
TString *str = luaS_new(L, k);
|
TString *str = luaS_new(L, k);
|
||||||
api_checknelems(L, 1);
|
api_checknelems(L, 1);
|
||||||
if (luaV_fastset(L, t, str, slot, luaH_getstr, L->top - 1))
|
if (luaV_fastget(L, t, str, slot, luaH_getstr)) {
|
||||||
|
luaV_finishfastset(L, t, slot, L->top - 1);
|
||||||
L->top--; /* pop value */
|
L->top--; /* pop value */
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */
|
setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */
|
||||||
api_incr_top(L);
|
api_incr_top(L);
|
||||||
@@ -764,10 +771,14 @@ LUA_API void lua_setglobal (lua_State *L, const char *name) {
|
|||||||
|
|
||||||
LUA_API void lua_settable (lua_State *L, int idx) {
|
LUA_API void lua_settable (lua_State *L, int idx) {
|
||||||
StkId t;
|
StkId t;
|
||||||
|
const TValue *slot;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
api_checknelems(L, 2);
|
api_checknelems(L, 2);
|
||||||
t = index2addr(L, idx);
|
t = index2addr(L, idx);
|
||||||
luaV_settable(L, t, L->top - 2, L->top - 1);
|
if (luaV_fastget(L, t, L->top - 2, slot, luaH_get))
|
||||||
|
luaV_finishfastset(L, t, slot, L->top - 1);
|
||||||
|
else
|
||||||
|
luaV_finishset(L, t, L->top - 2, L->top - 1, slot);
|
||||||
L->top -= 2; /* pop index and value */
|
L->top -= 2; /* pop index and value */
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
}
|
}
|
||||||
@@ -785,14 +796,14 @@ LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) {
|
|||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
api_checknelems(L, 1);
|
api_checknelems(L, 1);
|
||||||
t = index2addr(L, idx);
|
t = index2addr(L, idx);
|
||||||
if (luaV_fastset(L, t, n, slot, luaH_getint, L->top - 1))
|
if (luaV_fastgeti(L, t, n, slot))
|
||||||
L->top--; /* pop value */
|
luaV_finishfastset(L, t, slot, L->top - 1);
|
||||||
else {
|
else {
|
||||||
setivalue(L->top, n);
|
TValue aux;
|
||||||
api_incr_top(L);
|
setivalue(&aux, n);
|
||||||
luaV_finishset(L, t, L->top - 1, L->top - 2, slot);
|
luaV_finishset(L, t, &aux, L->top - 1, slot);
|
||||||
L->top -= 2; /* pop value and key */
|
|
||||||
}
|
}
|
||||||
|
L->top--; /* pop value */
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
87
lvm.c
87
lvm.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lvm.c,v 2.278 2017/05/08 16:08:01 roberto Exp roberto $
|
** $Id: lvm.c,v 2.279 2017/05/10 17:32:19 roberto Exp roberto $
|
||||||
** Lua virtual machine
|
** Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -182,7 +182,7 @@ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
t = tm; /* else try to access 'tm[key]' */
|
t = tm; /* else try to access 'tm[key]' */
|
||||||
if (luaV_fastget(L,t,key,slot,luaH_get)) { /* fast track? */
|
if (luaV_fastget(L, t, key, slot, luaH_get)) { /* fast track? */
|
||||||
setobj2s(L, val, slot); /* done */
|
setobj2s(L, val, slot); /* done */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -196,7 +196,7 @@ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
|
|||||||
** Finish a table assignment 't[key] = val'.
|
** Finish a table assignment 't[key] = val'.
|
||||||
** If 'slot' is NULL, 't' is not a table. Otherwise, 'slot' points
|
** If 'slot' is NULL, 't' is not a table. Otherwise, 'slot' points
|
||||||
** to the entry 't[key]', or to 'luaO_nilobject' if there is no such
|
** to the entry 't[key]', or to 'luaO_nilobject' if there is no such
|
||||||
** entry. (The value at 'slot' must be nil, otherwise 'luaV_fastset'
|
** entry. (The value at 'slot' must be nil, otherwise 'luaV_fastget'
|
||||||
** would have done the job.)
|
** would have done the job.)
|
||||||
*/
|
*/
|
||||||
void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
|
void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
|
||||||
@@ -229,9 +229,11 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
t = tm; /* else repeat assignment over 'tm' */
|
t = tm; /* else repeat assignment over 'tm' */
|
||||||
if (luaV_fastset(L, t, key, slot, luaH_get, val))
|
if (luaV_fastget(L, t, key, slot, luaH_get)) {
|
||||||
|
luaV_finishfastset(L, t, slot, val);
|
||||||
return; /* done */
|
return; /* done */
|
||||||
/* else loop */
|
}
|
||||||
|
/* else 'return luaV_finishset(L, t, key, val, slot)' (loop) */
|
||||||
}
|
}
|
||||||
luaG_runerror(L, "'__newindex' chain too long; possible loop");
|
luaG_runerror(L, "'__newindex' chain too long; possible loop");
|
||||||
}
|
}
|
||||||
@@ -791,35 +793,6 @@ void luaV_finishOp (lua_State *L) {
|
|||||||
#define vmbreak break
|
#define vmbreak break
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** copy of 'luaV_gettable', but protecting the call to potential
|
|
||||||
** metamethod (which can reallocate the stack)
|
|
||||||
*/
|
|
||||||
#define gettableProtected(L,t,k,v) { const TValue *slot; \
|
|
||||||
if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \
|
|
||||||
else Protect(luaV_finishget(L,t,k,v,slot)); }
|
|
||||||
|
|
||||||
|
|
||||||
/* same for 'luaV_settable' */
|
|
||||||
#define settableProtected(L,t,k,v) { const TValue *slot; \
|
|
||||||
if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \
|
|
||||||
Protect(luaV_finishset(L,t,k,v,slot)); }
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Predicate for integer fast track in GET/SETTABLE.
|
|
||||||
** (Strings are usually constant and therefore coded with
|
|
||||||
** GET/SETFIELD). Check that index is an integer, "table" is
|
|
||||||
** a table, index is in the array part, and value is not nil
|
|
||||||
** (otherwise it will need metamethods). Use 'n' and 't' for
|
|
||||||
** for caching the integer and table values.
|
|
||||||
*/
|
|
||||||
#define fastintindex(tbl,idx,t,n) \
|
|
||||||
(ttisinteger(idx) && ttistable(tbl) && \
|
|
||||||
(n = l_castS2U(ivalue(idx)) - 1u, t = hvalue(tbl), \
|
|
||||||
n < t->sizearray) && !ttisnil(&t->array[n]))
|
|
||||||
|
|
||||||
|
|
||||||
void luaV_execute (lua_State *L) {
|
void luaV_execute (lua_State *L) {
|
||||||
CallInfo *ci = L->ci;
|
CallInfo *ci = L->ci;
|
||||||
LClosure *cl;
|
LClosure *cl;
|
||||||
@@ -899,21 +872,24 @@ void luaV_execute (lua_State *L) {
|
|||||||
vmbreak;
|
vmbreak;
|
||||||
}
|
}
|
||||||
vmcase(OP_GETTABLE) {
|
vmcase(OP_GETTABLE) {
|
||||||
|
const TValue *slot;
|
||||||
StkId rb = RB(i);
|
StkId rb = RB(i);
|
||||||
TValue *rc = RC(i);
|
TValue *rc = RC(i);
|
||||||
Table *t; lua_Unsigned n;
|
lua_Unsigned n;
|
||||||
if (fastintindex(rb, rc, t, n)) {
|
if (ttisinteger(rc) /* fast track for integers? */
|
||||||
setobj2s(L, ra, &t->array[n]);
|
? (n = ivalue(rc), luaV_fastgeti(L, rb, n, slot))
|
||||||
|
: luaV_fastget(L, rb, rc, slot, luaH_get)) {
|
||||||
|
setobj2s(L, ra, slot);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
gettableProtected(L, rb, rc, ra);
|
Protect(luaV_finishget(L, rb, rc, ra, slot));
|
||||||
vmbreak;
|
vmbreak;
|
||||||
}
|
}
|
||||||
vmcase(OP_GETI) {
|
vmcase(OP_GETI) {
|
||||||
const TValue *slot;
|
const TValue *slot;
|
||||||
StkId rb = RB(i);
|
StkId rb = RB(i);
|
||||||
int c = GETARG_C(i);
|
int c = GETARG_C(i);
|
||||||
if (luaV_fastget(L, rb, c, slot, luaH_getint)) {
|
if (luaV_fastgeti(L, rb, c, slot)) {
|
||||||
setobj2s(L, ra, slot);
|
setobj2s(L, ra, slot);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -940,26 +916,32 @@ void luaV_execute (lua_State *L) {
|
|||||||
TValue *rb = KB(i);
|
TValue *rb = KB(i);
|
||||||
TValue *rc = RKC(i);
|
TValue *rc = RKC(i);
|
||||||
TString *key = tsvalue(rb); /* key must be a string */
|
TString *key = tsvalue(rb); /* key must be a string */
|
||||||
if (!luaV_fastset(L, upval, key, slot, luaH_getstr, rc))
|
if (luaV_fastget(L, upval, key, slot, luaH_getstr))
|
||||||
|
luaV_finishfastset(L, upval, slot, rc);
|
||||||
|
else
|
||||||
Protect(luaV_finishset(L, upval, rb, rc, slot));
|
Protect(luaV_finishset(L, upval, rb, rc, slot));
|
||||||
vmbreak;
|
vmbreak;
|
||||||
}
|
}
|
||||||
vmcase(OP_SETTABLE) {
|
vmcase(OP_SETTABLE) {
|
||||||
TValue *rb = RB(i);
|
const TValue *slot;
|
||||||
TValue *rc = RKC(i);
|
TValue *rb = RB(i); /* key (table is in 'ra') */
|
||||||
Table *t; lua_Unsigned n;
|
TValue *rc = RKC(i); /* value */
|
||||||
if (fastintindex(ra, rb, t, n)) {
|
lua_Unsigned n;
|
||||||
setobj2t(L, &t->array[n], rc);
|
if (ttisinteger(rb) /* fast track for integers? */
|
||||||
}
|
? (n = ivalue(rb), luaV_fastgeti(L, ra, n, slot))
|
||||||
|
: luaV_fastget(L, ra, rb, slot, luaH_get))
|
||||||
|
luaV_finishfastset(L, ra, slot, rc);
|
||||||
else
|
else
|
||||||
settableProtected(L, ra, rb, rc);
|
Protect(luaV_finishset(L, ra, rb, rc, slot));
|
||||||
vmbreak;
|
vmbreak;
|
||||||
}
|
}
|
||||||
vmcase(OP_SETI) {
|
vmcase(OP_SETI) {
|
||||||
const TValue *slot;
|
const TValue *slot;
|
||||||
int c = GETARG_B(i);
|
int c = GETARG_B(i);
|
||||||
TValue *rc = RKC(i);
|
TValue *rc = RKC(i);
|
||||||
if (!luaV_fastset(L, ra, c, slot, luaH_getint, rc)) {
|
if (luaV_fastgeti(L, ra, c, slot))
|
||||||
|
luaV_finishfastset(L, ra, slot, rc);
|
||||||
|
else {
|
||||||
TValue key;
|
TValue key;
|
||||||
setivalue(&key, c);
|
setivalue(&key, c);
|
||||||
Protect(luaV_finishset(L, ra, &key, rc, slot));
|
Protect(luaV_finishset(L, ra, &key, rc, slot));
|
||||||
@@ -971,7 +953,9 @@ void luaV_execute (lua_State *L) {
|
|||||||
TValue *rb = KB(i);
|
TValue *rb = KB(i);
|
||||||
TValue *rc = RKC(i);
|
TValue *rc = RKC(i);
|
||||||
TString *key = tsvalue(rb); /* key must be a string */
|
TString *key = tsvalue(rb); /* key must be a string */
|
||||||
if (!luaV_fastset(L, ra, key, slot, luaH_getstr, rc))
|
if (luaV_fastget(L, ra, key, slot, luaH_getstr))
|
||||||
|
luaV_finishfastset(L, ra, slot, rc);
|
||||||
|
else
|
||||||
Protect(luaV_finishset(L, ra, rb, rc, slot));
|
Protect(luaV_finishset(L, ra, rb, rc, slot));
|
||||||
vmbreak;
|
vmbreak;
|
||||||
}
|
}
|
||||||
@@ -1427,8 +1411,9 @@ void luaV_execute (lua_State *L) {
|
|||||||
if (last > h->sizearray) /* needs more space? */
|
if (last > h->sizearray) /* needs more space? */
|
||||||
luaH_resizearray(L, h, last); /* preallocate it at once */
|
luaH_resizearray(L, h, last); /* preallocate it at once */
|
||||||
for (; n > 0; n--) {
|
for (; n > 0; n--) {
|
||||||
TValue *val = ra+n;
|
TValue *val = ra + n;
|
||||||
luaH_setint(L, h, last--, val);
|
setobj2t(L, &h->array[last - 1], val);
|
||||||
|
last--;
|
||||||
luaC_barrierback(L, h, val);
|
luaC_barrierback(L, h, val);
|
||||||
}
|
}
|
||||||
L->top = ci->top; /* correct top (in case of previous open call) */
|
L->top = ci->top; /* correct top (in case of previous open call) */
|
||||||
|
|||||||
45
lvm.h
45
lvm.h
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lvm.h,v 2.40 2016/01/05 16:07:21 roberto Exp roberto $
|
** $Id: lvm.h,v 2.41 2016/12/22 13:08:50 roberto Exp roberto $
|
||||||
** Lua virtual machine
|
** Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -50,10 +50,10 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** fast track for 'gettable': if 't' is a table and 't[k]' is not nil,
|
** fast track for 'gettable': if 't' is a table and 't[k]' is not nil,
|
||||||
** return 1 with 'slot' pointing to 't[k]' (final result). Otherwise,
|
** return 1 with 'slot' pointing to 't[k]' (position of final result).
|
||||||
** return 0 (meaning it will have to check metamethod) with 'slot'
|
** Otherwise, return 0 (meaning it will have to check metamethod)
|
||||||
** pointing to a nil 't[k]' (if 't' is a table) or NULL (otherwise).
|
** with 'slot' pointing to a nil 't[k]' (if 't' is a table) or NULL
|
||||||
** 'f' is the raw get function to use.
|
** (otherwise). 'f' is the raw get function to use.
|
||||||
*/
|
*/
|
||||||
#define luaV_fastget(L,t,k,slot,f) \
|
#define luaV_fastget(L,t,k,slot,f) \
|
||||||
(!ttistable(t) \
|
(!ttistable(t) \
|
||||||
@@ -61,36 +61,27 @@
|
|||||||
: (slot = f(hvalue(t), k), /* else, do raw access */ \
|
: (slot = f(hvalue(t), k), /* else, do raw access */ \
|
||||||
!ttisnil(slot))) /* result not nil? */
|
!ttisnil(slot))) /* result not nil? */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** standard implementation for 'gettable'
|
** Special case of 'luaV_fastget' for integers, inlining the fast case
|
||||||
|
** of 'luaH_getint'.
|
||||||
*/
|
*/
|
||||||
#define luaV_gettable(L,t,k,v) { const TValue *slot; \
|
#define luaV_fastgeti(L,t,k,slot) \
|
||||||
if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \
|
(!ttistable(t) \
|
||||||
else luaV_finishget(L,t,k,v,slot); }
|
? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \
|
||||||
|
: (slot = (l_castS2U(k) - 1u < hvalue(t)->sizearray) \
|
||||||
|
? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \
|
||||||
|
!ttisnil(slot))) /* result not nil? */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Fast track for set table. If 't' is a table and 't[k]' is not nil,
|
** Finish a fast set operation (when fast get succeeds). In that case,
|
||||||
** call GC barrier, do a raw 't[k]=v', and return true; otherwise,
|
** 'slot' points to the place to put the value.
|
||||||
** return false with 'slot' equal to NULL (if 't' is not a table) or
|
|
||||||
** 'nil'. (This is needed by 'luaV_finishget'.) Note that, if the macro
|
|
||||||
** returns true, there is no need to 'invalidateTMcache', because the
|
|
||||||
** call is not creating a new entry.
|
|
||||||
*/
|
*/
|
||||||
#define luaV_fastset(L,t,k,slot,f,v) \
|
#define luaV_finishfastset(L,t,slot,v) \
|
||||||
(!ttistable(t) \
|
(setobj2t(L, cast(TValue *,slot), v), luaC_barrierback(L, hvalue(t), v))
|
||||||
? (slot = NULL, 0) \
|
|
||||||
: (slot = f(hvalue(t), k), \
|
|
||||||
ttisnil(slot) ? 0 \
|
|
||||||
: (luaC_barrierback(L, hvalue(t), v), \
|
|
||||||
setobj2t(L, cast(TValue *,slot), v), \
|
|
||||||
1)))
|
|
||||||
|
|
||||||
|
|
||||||
#define luaV_settable(L,t,k,v) { const TValue *slot; \
|
|
||||||
if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \
|
|
||||||
luaV_finishset(L,t,k,v,slot); }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2);
|
LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2);
|
||||||
|
|||||||
Reference in New Issue
Block a user