aboutsummaryrefslogtreecommitdiff
path: root/lvm.c
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 /lvm.c
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)
Diffstat (limited to 'lvm.c')
-rw-r--r--lvm.c61
1 files changed, 37 insertions, 24 deletions
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' */