diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2016-01-05 14:07:21 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2016-01-05 14:07:21 -0200 |
commit | 1a44e822009752513ce895b9eabc51a4ee4a195a (patch) | |
tree | dc8c1dc1ca01601335e447d3d627b4354247a31d /lvm.c | |
parent | a272fa66f0c149689e2a2c896434967b7248a0eb (diff) | |
download | lua-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.c | 61 |
1 files changed, 37 insertions, 24 deletions
@@ -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 | */ |
159 | void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, | 160 | void 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 | */ |
190 | void luaV_finishset (lua_State *L, const TValue *t, TValue *key, | 203 | void 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' */ |