aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2016-01-05 14:07:21 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2016-01-05 14:07:21 -0200
commit1a44e822009752513ce895b9eabc51a4ee4a195a (patch)
treedc8c1dc1ca01601335e447d3d627b4354247a31d
parenta272fa66f0c149689e2a2c896434967b7248a0eb (diff)
downloadlua-1a44e822009752513ce895b9eabc51a4ee4a195a.tar.gz
lua-1a44e822009752513ce895b9eabc51a4ee4a195a.tar.bz2
lua-1a44e822009752513ce895b9eabc51a4ee4a195a.zip
'luaV_fastget' only treats the real fast case (table with a non-nil
value at given key, so that it does not need to check metamethods)
-rw-r--r--lapi.c30
-rw-r--r--lvm.c61
-rw-r--r--lvm.h31
3 files changed, 67 insertions, 55 deletions
diff --git a/lapi.c b/lapi.c
index 9daf0545..2f492754 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lapi.c,v 2.256 2015/10/06 16:10:22 roberto Exp roberto $ 2** $Id: lapi.c,v 2.257 2015/11/02 18:48:07 roberto Exp roberto $
3** Lua API 3** Lua API
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -585,16 +585,16 @@ LUA_API int lua_pushthread (lua_State *L) {
585 585
586 586
587static int auxgetstr (lua_State *L, const TValue *t, const char *k) { 587static int auxgetstr (lua_State *L, const TValue *t, const char *k) {
588 const TValue *aux; 588 const TValue *slot;
589 TString *str = luaS_new(L, k); 589 TString *str = luaS_new(L, k);
590 if (luaV_fastget(L, t, str, aux, luaH_getstr)) { 590 if (luaV_fastget(L, t, str, slot, luaH_getstr)) {
591 setobj2s(L, L->top, aux); 591 setobj2s(L, L->top, slot);
592 api_incr_top(L); 592 api_incr_top(L);
593 } 593 }
594 else { 594 else {
595 setsvalue2s(L, L->top, str); 595 setsvalue2s(L, L->top, str);
596 api_incr_top(L); 596 api_incr_top(L);
597 luaV_finishget(L, t, L->top - 1, L->top - 1, aux); 597 luaV_finishget(L, t, L->top - 1, L->top - 1, slot);
598 } 598 }
599 lua_unlock(L); 599 lua_unlock(L);
600 return ttnov(L->top - 1); 600 return ttnov(L->top - 1);
@@ -626,17 +626,17 @@ LUA_API int lua_getfield (lua_State *L, int idx, const char *k) {
626 626
627LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { 627LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
628 StkId t; 628 StkId t;
629 const TValue *aux; 629 const TValue *slot;
630 lua_lock(L); 630 lua_lock(L);
631 t = index2addr(L, idx); 631 t = index2addr(L, idx);
632 if (luaV_fastget(L, t, n, aux, luaH_getint)) { 632 if (luaV_fastget(L, t, n, slot, luaH_getint)) {
633 setobj2s(L, L->top, aux); 633 setobj2s(L, L->top, slot);
634 api_incr_top(L); 634 api_incr_top(L);
635 } 635 }
636 else { 636 else {
637 setivalue(L->top, n); 637 setivalue(L->top, n);
638 api_incr_top(L); 638 api_incr_top(L);
639 luaV_finishget(L, t, L->top - 1, L->top - 1, aux); 639 luaV_finishget(L, t, L->top - 1, L->top - 1, slot);
640 } 640 }
641 lua_unlock(L); 641 lua_unlock(L);
642 return ttnov(L->top - 1); 642 return ttnov(L->top - 1);
@@ -740,15 +740,15 @@ LUA_API int lua_getuservalue (lua_State *L, int idx) {
740** t[k] = value at the top of the stack (where 'k' is a string) 740** t[k] = value at the top of the stack (where 'k' is a string)
741*/ 741*/
742static void auxsetstr (lua_State *L, const TValue *t, const char *k) { 742static void auxsetstr (lua_State *L, const TValue *t, const char *k) {
743 const TValue *aux; 743 const TValue *slot;
744 TString *str = luaS_new(L, k); 744 TString *str = luaS_new(L, k);
745 api_checknelems(L, 1); 745 api_checknelems(L, 1);
746 if (luaV_fastset(L, t, str, aux, luaH_getstr, L->top - 1)) 746 if (luaV_fastset(L, t, str, slot, luaH_getstr, L->top - 1))
747 L->top--; /* pop value */ 747 L->top--; /* pop value */
748 else { 748 else {
749 setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */ 749 setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */
750 api_incr_top(L); 750 api_incr_top(L);
751 luaV_finishset(L, t, L->top - 1, L->top - 2, aux); 751 luaV_finishset(L, t, L->top - 1, L->top - 2, slot);
752 L->top -= 2; /* pop value and key */ 752 L->top -= 2; /* pop value and key */
753 } 753 }
754 lua_unlock(L); /* lock done by caller */ 754 lua_unlock(L); /* lock done by caller */
@@ -781,16 +781,16 @@ LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
781 781
782LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { 782LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) {
783 StkId t; 783 StkId t;
784 const TValue *aux; 784 const TValue *slot;
785 lua_lock(L); 785 lua_lock(L);
786 api_checknelems(L, 1); 786 api_checknelems(L, 1);
787 t = index2addr(L, idx); 787 t = index2addr(L, idx);
788 if (luaV_fastset(L, t, n, aux, luaH_getint, L->top - 1)) 788 if (luaV_fastset(L, t, n, slot, luaH_getint, L->top - 1))
789 L->top--; /* pop value */ 789 L->top--; /* pop value */
790 else { 790 else {
791 setivalue(L->top, n); 791 setivalue(L->top, n);
792 api_incr_top(L); 792 api_incr_top(L);
793 luaV_finishset(L, t, L->top - 1, L->top - 2, aux); 793 luaV_finishset(L, t, L->top - 1, L->top - 2, slot);
794 L->top -= 2; /* pop value and key */ 794 L->top -= 2; /* pop value and key */
795 } 795 }
796 lua_unlock(L); 796 lua_unlock(L);
diff --git a/lvm.c b/lvm.c
index 060321a5..99a04d07 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.265 2015/11/23 11:30:45 roberto Exp roberto $ 2** $Id: lvm.c,v 2.266 2016/01/04 16:44:50 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -153,28 +153,41 @@ static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
153 153
154 154
155/* 155/*
156** Finish a table access: if 't' is a table, 'tm' has its metamethod; 156** Finish the table access 'val = t[key]'.
157** otherwise, 'tm' is NULL. 157** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to
158** t[k] entry (which must be nil).
158*/ 159*/
159void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, 160void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
160 const TValue *tm) { 161 const TValue *slot) {
161 int loop; /* counter to avoid infinite loops */ 162 int loop; /* counter to avoid infinite loops */
162 lua_assert(tm != NULL || !ttistable(t)); 163 const TValue *tm; /* metamethod */
163 for (loop = 0; loop < MAXTAGLOOP; loop++) { 164 for (loop = 0; loop < MAXTAGLOOP; loop++) {
164 if (tm == NULL) { /* no metamethod (from a table)? */ 165 if (slot == NULL) { /* 't' is not a table? */
165 if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) 166 lua_assert(!ttistable(t));
167 tm = luaT_gettmbyobj(L, t, TM_INDEX);
168 if (ttisnil(tm))
166 luaG_typeerror(L, t, "index"); /* no metamethod */ 169 luaG_typeerror(L, t, "index"); /* no metamethod */
170 /* else will try the metamethod */
171 }
172 else { /* 't' is a table */
173 lua_assert(ttisnil(slot));
174 tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */
175 if (tm == NULL) { /* no metamethod? */
176 setnilvalue(val); /* result is nil */
177 return;
178 }
179 /* else will try the metamethod */
167 } 180 }
168 if (ttisfunction(tm)) { /* metamethod is a function */ 181 if (ttisfunction(tm)) { /* is metamethod a function? */
169 luaT_callTM(L, tm, t, key, val, 1); /* call it */ 182 luaT_callTM(L, tm, t, key, val, 1); /* call it */
170 return; 183 return;
171 } 184 }
172 t = tm; /* else repeat access over 'tm' */ 185 t = tm; /* else try to access 'tm[key]' */
173 if (luaV_fastget(L,t,key,tm,luaH_get)) { /* try fast track */ 186 if (luaV_fastget(L,t,key,slot,luaH_get)) { /* fast track? */
174 setobj2s(L, val, tm); /* done */ 187 setobj2s(L, val, slot); /* done */
175 return; 188 return;
176 } 189 }
177 /* else repeat */ 190 /* else repeat (tail call 'luaV_finishget') */
178 } 191 }
179 luaG_runerror(L, "'__index' chain too long; possible loop"); 192 luaG_runerror(L, "'__index' chain too long; possible loop");
180} 193}
@@ -182,25 +195,25 @@ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
182 195
183/* 196/*
184** Finish a table assignment 't[key] = val'. 197** Finish a table assignment 't[key] = val'.
185** If 'oldval' is NULL, 't' is not a table. Otherwise, 'oldval' points 198** If 'slot' is NULL, 't' is not a table. Otherwise, 'slot' points
186** to the entry 't[key]', or to 'luaO_nilobject' if there is no such 199** to the entry 't[key]', or to 'luaO_nilobject' if there is no such
187** entry. (The value at 'oldval' must be nil, otherwise 'luaV_fastset' 200** entry. (The value at 'slot' must be nil, otherwise 'luaV_fastset'
188** would have done the job.) 201** would have done the job.)
189*/ 202*/
190void luaV_finishset (lua_State *L, const TValue *t, TValue *key, 203void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
191 StkId val, const TValue *oldval) { 204 StkId val, const TValue *slot) {
192 int loop; /* counter to avoid infinite loops */ 205 int loop; /* counter to avoid infinite loops */
193 for (loop = 0; loop < MAXTAGLOOP; loop++) { 206 for (loop = 0; loop < MAXTAGLOOP; loop++) {
194 const TValue *tm; /* '__newindex' metamethod */ 207 const TValue *tm; /* '__newindex' metamethod */
195 if (oldval != NULL) { /* is 't' a table? */ 208 if (slot != NULL) { /* is 't' a table? */
196 Table *h = hvalue(t); /* save 't' table */ 209 Table *h = hvalue(t); /* save 't' table */
197 lua_assert(ttisnil(oldval)); /* old value must be nil */ 210 lua_assert(ttisnil(slot)); /* old value must be nil */
198 tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ 211 tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */
199 if (tm == NULL) { /* no metamethod? */ 212 if (tm == NULL) { /* no metamethod? */
200 if (oldval == luaO_nilobject) /* no previous entry? */ 213 if (slot == luaO_nilobject) /* no previous entry? */
201 oldval = luaH_newkey(L, h, key); /* create one */ 214 slot = luaH_newkey(L, h, key); /* create one */
202 /* no metamethod and (now) there is an entry with given key */ 215 /* no metamethod and (now) there is an entry with given key */
203 setobj2t(L, cast(TValue *, oldval), val); /* set its new value */ 216 setobj2t(L, cast(TValue *, slot), val); /* set its new value */
204 invalidateTMcache(h); 217 invalidateTMcache(h);
205 luaC_barrierback(L, h, val); 218 luaC_barrierback(L, h, val);
206 return; 219 return;
@@ -217,7 +230,7 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
217 return; 230 return;
218 } 231 }
219 t = tm; /* else repeat assignment over 'tm' */ 232 t = tm; /* else repeat assignment over 'tm' */
220 if (luaV_fastset(L, t, key, oldval, luaH_get, val)) 233 if (luaV_fastset(L, t, key, slot, luaH_get, val))
221 return; /* done */ 234 return; /* done */
222 /* else loop */ 235 /* else loop */
223 } 236 }
@@ -748,9 +761,9 @@ void luaV_finishOp (lua_State *L) {
748** copy of 'luaV_gettable', but protecting the call to potential 761** copy of 'luaV_gettable', but protecting the call to potential
749** metamethod (which can reallocate the stack) 762** metamethod (which can reallocate the stack)
750*/ 763*/
751#define gettableProtected(L,t,k,v) { const TValue *aux; \ 764#define gettableProtected(L,t,k,v) { const TValue *slot; \
752 if (luaV_fastget(L,t,k,aux,luaH_get)) { setobj2s(L, v, aux); } \ 765 if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \
753 else Protect(luaV_finishget(L,t,k,v,aux)); } 766 else Protect(luaV_finishget(L,t,k,v,slot)); }
754 767
755 768
756/* same for 'luaV_settable' */ 769/* same for 'luaV_settable' */
diff --git a/lvm.h b/lvm.h
index b65061ac..f6f99c7a 100644
--- a/lvm.h
+++ b/lvm.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.h,v 2.38 2015/08/03 20:40:26 roberto Exp roberto $ 2** $Id: lvm.h,v 2.39 2015/09/09 13:44:07 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -49,25 +49,24 @@
49 49
50 50
51/* 51/*
52** fast track for 'gettable': 1 means 'aux' points to resulted value; 52** fast track for 'gettable': if 't' is a table and 't[k]' is not nil,
53** 0 means 'aux' is metamethod (if 't' is a table) or NULL. 'f' is 53** return 1 with 'slot' pointing to 't[k]' (final result). Otherwise,
54** the raw get function to use. 54** return 0 (meaning it will have to check metamethod) with 'slot'
55** pointing to a nil 't[k]' (if 't' is a table) or NULL (otherwise).
56** 'f' is the raw get function to use.
55*/ 57*/
56#define luaV_fastget(L,t,k,aux,f) \ 58#define luaV_fastget(L,t,k,slot,f) \
57 (!ttistable(t) \ 59 (!ttistable(t) \
58 ? (aux = NULL, 0) /* not a table; 'aux' is NULL and result is 0 */ \ 60 ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \
59 : (aux = f(hvalue(t), k), /* else, do raw access */ \ 61 : (slot = f(hvalue(t), k), /* else, do raw access */ \
60 !ttisnil(aux) ? 1 /* result not nil? 'aux' has it */ \ 62 !ttisnil(slot))) /* result not nil? */
61 : (aux = fasttm(L, hvalue(t)->metatable, TM_INDEX), /* get metamethod */\
62 aux != NULL ? 0 /* has metamethod? must call it */ \
63 : (aux = luaO_nilobject, 1)))) /* else, final result is nil */
64 63
65/* 64/*
66** standard implementation for 'gettable' 65** standard implementation for 'gettable'
67*/ 66*/
68#define luaV_gettable(L,t,k,v) { const TValue *aux; \ 67#define luaV_gettable(L,t,k,v) { const TValue *slot; \
69 if (luaV_fastget(L,t,k,aux,luaH_get)) { setobj2s(L, v, aux); } \ 68 if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \
70 else luaV_finishget(L,t,k,v,aux); } 69 else luaV_finishget(L,t,k,v,slot); }
71 70
72 71
73/* 72/*
@@ -100,9 +99,9 @@ LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r);
100LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); 99LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n);
101LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode); 100LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode);
102LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key, 101LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key,
103 StkId val, const TValue *tm); 102 StkId val, const TValue *slot);
104LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, 103LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
105 StkId val, const TValue *oldval); 104 StkId val, const TValue *slot);
106LUAI_FUNC void luaV_finishOp (lua_State *L); 105LUAI_FUNC void luaV_finishOp (lua_State *L);
107LUAI_FUNC void luaV_execute (lua_State *L); 106LUAI_FUNC void luaV_execute (lua_State *L);
108LUAI_FUNC void luaV_concat (lua_State *L, int total); 107LUAI_FUNC void luaV_concat (lua_State *L, int total);