diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-05-11 15:57:46 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-05-11 15:57:46 -0300 |
commit | 7647d5d13d016f114dac4be0b9da62d502eab400 (patch) | |
tree | 7240a95fd732596e658648f6052b29e551a01265 /lvm.c | |
parent | 7184f6343a0074d02f6f0e35654cfa55427710d3 (diff) | |
download | lua-7647d5d13d016f114dac4be0b9da62d502eab400.tar.gz lua-7647d5d13d016f114dac4be0b9da62d502eab400.tar.bz2 lua-7647d5d13d016f114dac4be0b9da62d502eab400.zip |
revamp of fast track for table access (table set uses the same
macros as table get + new macro for integer keys)
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 87 |
1 files changed, 36 insertions, 51 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.278 2017/05/08 16:08:01 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.279 2017/05/10 17:32:19 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 | */ |
@@ -182,7 +182,7 @@ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, | |||
182 | return; | 182 | return; |
183 | } | 183 | } |
184 | t = tm; /* else try to access 'tm[key]' */ | 184 | t = tm; /* else try to access 'tm[key]' */ |
185 | if (luaV_fastget(L,t,key,slot,luaH_get)) { /* fast track? */ | 185 | if (luaV_fastget(L, t, key, slot, luaH_get)) { /* fast track? */ |
186 | setobj2s(L, val, slot); /* done */ | 186 | setobj2s(L, val, slot); /* done */ |
187 | return; | 187 | return; |
188 | } | 188 | } |
@@ -196,7 +196,7 @@ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, | |||
196 | ** Finish a table assignment 't[key] = val'. | 196 | ** Finish a table assignment 't[key] = val'. |
197 | ** If 'slot' is NULL, 't' is not a table. Otherwise, 'slot' points | 197 | ** If 'slot' is NULL, 't' is not a table. Otherwise, 'slot' points |
198 | ** to the entry 't[key]', or to 'luaO_nilobject' if there is no such | 198 | ** to the entry 't[key]', or to 'luaO_nilobject' if there is no such |
199 | ** entry. (The value at 'slot' must be nil, otherwise 'luaV_fastset' | 199 | ** entry. (The value at 'slot' must be nil, otherwise 'luaV_fastget' |
200 | ** would have done the job.) | 200 | ** would have done the job.) |
201 | */ | 201 | */ |
202 | void luaV_finishset (lua_State *L, const TValue *t, TValue *key, | 202 | 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, | |||
229 | return; | 229 | return; |
230 | } | 230 | } |
231 | t = tm; /* else repeat assignment over 'tm' */ | 231 | t = tm; /* else repeat assignment over 'tm' */ |
232 | if (luaV_fastset(L, t, key, slot, luaH_get, val)) | 232 | if (luaV_fastget(L, t, key, slot, luaH_get)) { |
233 | luaV_finishfastset(L, t, slot, val); | ||
233 | return; /* done */ | 234 | return; /* done */ |
234 | /* else loop */ | 235 | } |
236 | /* else 'return luaV_finishset(L, t, key, val, slot)' (loop) */ | ||
235 | } | 237 | } |
236 | luaG_runerror(L, "'__newindex' chain too long; possible loop"); | 238 | luaG_runerror(L, "'__newindex' chain too long; possible loop"); |
237 | } | 239 | } |
@@ -791,35 +793,6 @@ void luaV_finishOp (lua_State *L) { | |||
791 | #define vmbreak break | 793 | #define vmbreak break |
792 | 794 | ||
793 | 795 | ||
794 | /* | ||
795 | ** copy of 'luaV_gettable', but protecting the call to potential | ||
796 | ** metamethod (which can reallocate the stack) | ||
797 | */ | ||
798 | #define gettableProtected(L,t,k,v) { const TValue *slot; \ | ||
799 | if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \ | ||
800 | else Protect(luaV_finishget(L,t,k,v,slot)); } | ||
801 | |||
802 | |||
803 | /* same for 'luaV_settable' */ | ||
804 | #define settableProtected(L,t,k,v) { const TValue *slot; \ | ||
805 | if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \ | ||
806 | Protect(luaV_finishset(L,t,k,v,slot)); } | ||
807 | |||
808 | |||
809 | /* | ||
810 | ** Predicate for integer fast track in GET/SETTABLE. | ||
811 | ** (Strings are usually constant and therefore coded with | ||
812 | ** GET/SETFIELD). Check that index is an integer, "table" is | ||
813 | ** a table, index is in the array part, and value is not nil | ||
814 | ** (otherwise it will need metamethods). Use 'n' and 't' for | ||
815 | ** for caching the integer and table values. | ||
816 | */ | ||
817 | #define fastintindex(tbl,idx,t,n) \ | ||
818 | (ttisinteger(idx) && ttistable(tbl) && \ | ||
819 | (n = l_castS2U(ivalue(idx)) - 1u, t = hvalue(tbl), \ | ||
820 | n < t->sizearray) && !ttisnil(&t->array[n])) | ||
821 | |||
822 | |||
823 | void luaV_execute (lua_State *L) { | 796 | void luaV_execute (lua_State *L) { |
824 | CallInfo *ci = L->ci; | 797 | CallInfo *ci = L->ci; |
825 | LClosure *cl; | 798 | LClosure *cl; |
@@ -899,21 +872,24 @@ void luaV_execute (lua_State *L) { | |||
899 | vmbreak; | 872 | vmbreak; |
900 | } | 873 | } |
901 | vmcase(OP_GETTABLE) { | 874 | vmcase(OP_GETTABLE) { |
875 | const TValue *slot; | ||
902 | StkId rb = RB(i); | 876 | StkId rb = RB(i); |
903 | TValue *rc = RC(i); | 877 | TValue *rc = RC(i); |
904 | Table *t; lua_Unsigned n; | 878 | lua_Unsigned n; |
905 | if (fastintindex(rb, rc, t, n)) { | 879 | if (ttisinteger(rc) /* fast track for integers? */ |
906 | setobj2s(L, ra, &t->array[n]); | 880 | ? (n = ivalue(rc), luaV_fastgeti(L, rb, n, slot)) |
881 | : luaV_fastget(L, rb, rc, slot, luaH_get)) { | ||
882 | setobj2s(L, ra, slot); | ||
907 | } | 883 | } |
908 | else | 884 | else |
909 | gettableProtected(L, rb, rc, ra); | 885 | Protect(luaV_finishget(L, rb, rc, ra, slot)); |
910 | vmbreak; | 886 | vmbreak; |
911 | } | 887 | } |
912 | vmcase(OP_GETI) { | 888 | vmcase(OP_GETI) { |
913 | const TValue *slot; | 889 | const TValue *slot; |
914 | StkId rb = RB(i); | 890 | StkId rb = RB(i); |
915 | int c = GETARG_C(i); | 891 | int c = GETARG_C(i); |
916 | if (luaV_fastget(L, rb, c, slot, luaH_getint)) { | 892 | if (luaV_fastgeti(L, rb, c, slot)) { |
917 | setobj2s(L, ra, slot); | 893 | setobj2s(L, ra, slot); |
918 | } | 894 | } |
919 | else { | 895 | else { |
@@ -940,26 +916,32 @@ void luaV_execute (lua_State *L) { | |||
940 | TValue *rb = KB(i); | 916 | TValue *rb = KB(i); |
941 | TValue *rc = RKC(i); | 917 | TValue *rc = RKC(i); |
942 | TString *key = tsvalue(rb); /* key must be a string */ | 918 | TString *key = tsvalue(rb); /* key must be a string */ |
943 | if (!luaV_fastset(L, upval, key, slot, luaH_getstr, rc)) | 919 | if (luaV_fastget(L, upval, key, slot, luaH_getstr)) |
920 | luaV_finishfastset(L, upval, slot, rc); | ||
921 | else | ||
944 | Protect(luaV_finishset(L, upval, rb, rc, slot)); | 922 | Protect(luaV_finishset(L, upval, rb, rc, slot)); |
945 | vmbreak; | 923 | vmbreak; |
946 | } | 924 | } |
947 | vmcase(OP_SETTABLE) { | 925 | vmcase(OP_SETTABLE) { |
948 | TValue *rb = RB(i); | 926 | const TValue *slot; |
949 | TValue *rc = RKC(i); | 927 | TValue *rb = RB(i); /* key (table is in 'ra') */ |
950 | Table *t; lua_Unsigned n; | 928 | TValue *rc = RKC(i); /* value */ |
951 | if (fastintindex(ra, rb, t, n)) { | 929 | lua_Unsigned n; |
952 | setobj2t(L, &t->array[n], rc); | 930 | if (ttisinteger(rb) /* fast track for integers? */ |
953 | } | 931 | ? (n = ivalue(rb), luaV_fastgeti(L, ra, n, slot)) |
932 | : luaV_fastget(L, ra, rb, slot, luaH_get)) | ||
933 | luaV_finishfastset(L, ra, slot, rc); | ||
954 | else | 934 | else |
955 | settableProtected(L, ra, rb, rc); | 935 | Protect(luaV_finishset(L, ra, rb, rc, slot)); |
956 | vmbreak; | 936 | vmbreak; |
957 | } | 937 | } |
958 | vmcase(OP_SETI) { | 938 | vmcase(OP_SETI) { |
959 | const TValue *slot; | 939 | const TValue *slot; |
960 | int c = GETARG_B(i); | 940 | int c = GETARG_B(i); |
961 | TValue *rc = RKC(i); | 941 | TValue *rc = RKC(i); |
962 | if (!luaV_fastset(L, ra, c, slot, luaH_getint, rc)) { | 942 | if (luaV_fastgeti(L, ra, c, slot)) |
943 | luaV_finishfastset(L, ra, slot, rc); | ||
944 | else { | ||
963 | TValue key; | 945 | TValue key; |
964 | setivalue(&key, c); | 946 | setivalue(&key, c); |
965 | Protect(luaV_finishset(L, ra, &key, rc, slot)); | 947 | Protect(luaV_finishset(L, ra, &key, rc, slot)); |
@@ -971,7 +953,9 @@ void luaV_execute (lua_State *L) { | |||
971 | TValue *rb = KB(i); | 953 | TValue *rb = KB(i); |
972 | TValue *rc = RKC(i); | 954 | TValue *rc = RKC(i); |
973 | TString *key = tsvalue(rb); /* key must be a string */ | 955 | TString *key = tsvalue(rb); /* key must be a string */ |
974 | if (!luaV_fastset(L, ra, key, slot, luaH_getstr, rc)) | 956 | if (luaV_fastget(L, ra, key, slot, luaH_getstr)) |
957 | luaV_finishfastset(L, ra, slot, rc); | ||
958 | else | ||
975 | Protect(luaV_finishset(L, ra, rb, rc, slot)); | 959 | Protect(luaV_finishset(L, ra, rb, rc, slot)); |
976 | vmbreak; | 960 | vmbreak; |
977 | } | 961 | } |
@@ -1427,8 +1411,9 @@ void luaV_execute (lua_State *L) { | |||
1427 | if (last > h->sizearray) /* needs more space? */ | 1411 | if (last > h->sizearray) /* needs more space? */ |
1428 | luaH_resizearray(L, h, last); /* preallocate it at once */ | 1412 | luaH_resizearray(L, h, last); /* preallocate it at once */ |
1429 | for (; n > 0; n--) { | 1413 | for (; n > 0; n--) { |
1430 | TValue *val = ra+n; | 1414 | TValue *val = ra + n; |
1431 | luaH_setint(L, h, last--, val); | 1415 | setobj2t(L, &h->array[last - 1], val); |
1416 | last--; | ||
1432 | luaC_barrierback(L, h, val); | 1417 | luaC_barrierback(L, h, val); |
1433 | } | 1418 | } |
1434 | L->top = ci->top; /* correct top (in case of previous open call) */ | 1419 | L->top = ci->top; /* correct top (in case of previous open call) */ |