diff --git a/lapi.c b/lapi.c index 2b045bb5..6e5a0d3d 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.249 2015/04/06 12:23:48 roberto Exp roberto $ +** $Id: lapi.c,v 2.250 2015/06/18 14:19:52 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -579,19 +579,30 @@ LUA_API int lua_pushthread (lua_State *L) { */ -LUA_API int lua_getglobal (lua_State *L, const char *name) { - Table *reg = hvalue(&G(L)->l_registry); - const TValue *gt; /* global table */ - lua_lock(L); - gt = luaH_getint(reg, LUA_RIDX_GLOBALS); - setsvalue2s(L, L->top, luaS_new(L, name)); - api_incr_top(L); - luaV_gettable(L, gt, L->top - 1, L->top - 1); +static int auxgetstr (lua_State *L, const TValue *t, const char *k) { + const TValue *aux; + TString *str = luaS_new(L, k); + if (luaV_fastget(L, t, str, aux, luaH_getstr)) { + setobj2s(L, L->top, aux); + api_incr_top(L); + } + else { + setsvalue2s(L, L->top, str); + api_incr_top(L); + luaV_finishget(L, t, L->top - 1, L->top - 1, aux); + } lua_unlock(L); return ttnov(L->top - 1); } +LUA_API int lua_getglobal (lua_State *L, const char *name) { + Table *reg = hvalue(&G(L)->l_registry); + lua_lock(L); + return auxgetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); +} + + LUA_API int lua_gettable (lua_State *L, int idx) { StkId t; lua_lock(L); @@ -603,24 +614,25 @@ LUA_API int lua_gettable (lua_State *L, int idx) { LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { - StkId t; lua_lock(L); - t = index2addr(L, idx); - setsvalue2s(L, L->top, luaS_new(L, k)); - api_incr_top(L); - luaV_gettable(L, t, L->top - 1, L->top - 1); - lua_unlock(L); - return ttnov(L->top - 1); + return auxgetstr(L, index2addr(L, idx), k); } LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { StkId t; + const TValue *aux; lua_lock(L); t = index2addr(L, idx); - setivalue(L->top, n); - api_incr_top(L); - luaV_gettable(L, t, L->top - 1, L->top - 1); + if (luaV_fastget(L, t, n, aux, luaH_getint)) { + setobj2s(L, L->top, aux); + api_incr_top(L); + } + else { + setivalue(L->top, n); + api_incr_top(L); + luaV_finishget(L, t, L->top - 1, L->top - 1, aux); + } lua_unlock(L); return ttnov(L->top - 1); } diff --git a/lvm.c b/lvm.c index 164fe476..4cb557f9 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.246 2015/06/25 14:00:01 roberto Exp roberto $ +** $Id: lvm.c,v 2.247 2015/07/04 16:31:03 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -153,30 +153,28 @@ static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, /* -** Main function for table access (invoking metamethods if needed). -** Compute 'val = t[key]' +** Complete a table access: if 't' is a table, 'tm' has its metamethod; +** otherwise, 'tm' is NULL. */ -void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { +void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, + const TValue *tm) { int loop; /* counter to avoid infinite loops */ + lua_assert(tm != NULL || !ttistable(t)); for (loop = 0; loop < MAXTAGLOOP; loop++) { - const TValue *tm; - if (ttistable(t)) { /* 't' is a table? */ - Table *h = hvalue(t); - const TValue *res = luaH_get(h, key); /* do a primitive get */ - if (!ttisnil(res) || /* result is not nil? */ - (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ - setobj2s(L, val, res); /* result is the raw get */ - return; - } - /* else will try metamethod */ + if (tm == NULL) { /* no metamethod (from a table)? */ + if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) + luaG_typeerror(L, t, "index"); /* no metamethod */ } - else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) - luaG_typeerror(L, t, "index"); /* no metamethod */ if (ttisfunction(tm)) { /* metamethod is a function */ - luaT_callTM(L, tm, t, key, val, 1); + luaT_callTM(L, tm, t, key, val, 1); /* call it */ return; } t = tm; /* else repeat access over 'tm' */ + if (luaV_fastget(L,t,key,tm,luaH_get)) { /* try fast track */ + setobj2s(L, val, tm); /* done */ + return; + } + /* else repeat */ } luaG_runerror(L, "gettable chain too long; possible loop"); } diff --git a/lvm.h b/lvm.h index a50fb981..9f7d028f 100644 --- a/lvm.h +++ b/lvm.h @@ -1,5 +1,5 @@ /* -** $Id: lvm.h,v 2.34 2014/08/01 17:24:02 roberto Exp roberto $ +** $Id: lvm.h,v 2.35 2015/02/20 14:27:53 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -48,13 +48,35 @@ #define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) +/* +** fast track for 'gettable': 1 means 'aux' points to resulted value; +** 0 means 'aux' is metamethod (if 't' is a table) or NULL. 'f' is +** the raw get function to use. +*/ +#define luaV_fastget(L,t,k,aux,f) \ + (!ttistable(t) \ + ? (aux = NULL, 0) /* not a table; 'aux' is NULL and result is 0 */ \ + : (aux = f(hvalue(t), k), /* else, do raw access */ \ + !ttisnil(aux) ? 1 /* result not nil? 'aux' has it */ \ + : (aux = fasttm(L, hvalue(t)->metatable, TM_INDEX), /* get metamethod */\ + aux != NULL ? 0 /* has metamethod? must call it */ \ + : (aux = luaO_nilobject, 1)))) /* else, final result is nil */ + +/* +** standard implementation for 'gettable' +*/ +#define luaV_gettable(L,t,k,v) { const TValue *aux; \ + if (luaV_fastget(L,t,k,aux,luaH_get)) { setobj2s(L, v, aux); } \ + else luaV_finishget(L,t,k,v,aux); } + + LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode); -LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, - StkId val); +LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key, + StkId val, const TValue *tm); LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val); LUAI_FUNC void luaV_finishOp (lua_State *L);