diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-05-16 14:55:49 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-05-16 14:55:49 -0300 |
| commit | f8d30826dda6ee8e99200de57a1997734b853db2 (patch) | |
| tree | d3a24665802f41fe3216714252ed189006f302cd | |
| parent | 351ccd733298e08c41937c1baf22a68e62bfeca9 (diff) | |
| download | lua-f8d30826dda6ee8e99200de57a1997734b853db2.tar.gz lua-f8d30826dda6ee8e99200de57a1997734b853db2.tar.bz2 lua-f8d30826dda6ee8e99200de57a1997734b853db2.zip | |
New table API for 'set' functions
| -rw-r--r-- | lapi.c | 31 | ||||
| -rw-r--r-- | ltable.c | 120 | ||||
| -rw-r--r-- | ltable.h | 11 | ||||
| -rw-r--r-- | lvm.c | 64 | ||||
| -rw-r--r-- | lvm.h | 25 |
5 files changed, 180 insertions, 71 deletions
| @@ -823,17 +823,18 @@ LUA_API int lua_getiuservalue (lua_State *L, int idx, int n) { | |||
| 823 | ** t[k] = value at the top of the stack (where 'k' is a string) | 823 | ** t[k] = value at the top of the stack (where 'k' is a string) |
| 824 | */ | 824 | */ |
| 825 | static void auxsetstr (lua_State *L, const TValue *t, const char *k) { | 825 | static void auxsetstr (lua_State *L, const TValue *t, const char *k) { |
| 826 | const TValue *slot; | 826 | int aux; |
| 827 | TString *str = luaS_new(L, k); | 827 | TString *str = luaS_new(L, k); |
| 828 | api_checknelems(L, 1); | 828 | api_checknelems(L, 1); |
| 829 | if (luaV_fastget(L, t, str, slot, luaH_getstr)) { | 829 | luaV_fastset1(t, str, s2v(L->top.p - 1), aux, luaH_setstr1); |
| 830 | luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); | 830 | if (aux == HOK) { |
| 831 | luaV_finishfastset1(L, t, s2v(L->top.p - 1)); | ||
| 831 | L->top.p--; /* pop value */ | 832 | L->top.p--; /* pop value */ |
| 832 | } | 833 | } |
| 833 | else { | 834 | else { |
| 834 | setsvalue2s(L, L->top.p, str); /* push 'str' (to make it a TValue) */ | 835 | setsvalue2s(L, L->top.p, str); /* push 'str' (to make it a TValue) */ |
| 835 | api_incr_top(L); | 836 | api_incr_top(L); |
| 836 | luaV_finishset(L, t, s2v(L->top.p - 1), s2v(L->top.p - 2), slot); | 837 | luaV_finishset1(L, t, s2v(L->top.p - 1), s2v(L->top.p - 2), aux); |
| 837 | L->top.p -= 2; /* pop value and key */ | 838 | L->top.p -= 2; /* pop value and key */ |
| 838 | } | 839 | } |
| 839 | lua_unlock(L); /* lock done by caller */ | 840 | lua_unlock(L); /* lock done by caller */ |
| @@ -850,15 +851,16 @@ LUA_API void lua_setglobal (lua_State *L, const char *name) { | |||
| 850 | 851 | ||
| 851 | LUA_API void lua_settable (lua_State *L, int idx) { | 852 | LUA_API void lua_settable (lua_State *L, int idx) { |
| 852 | TValue *t; | 853 | TValue *t; |
| 853 | const TValue *slot; | 854 | int aux; |
| 854 | lua_lock(L); | 855 | lua_lock(L); |
| 855 | api_checknelems(L, 2); | 856 | api_checknelems(L, 2); |
| 856 | t = index2value(L, idx); | 857 | t = index2value(L, idx); |
| 857 | if (luaV_fastget(L, t, s2v(L->top.p - 2), slot, luaH_get)) { | 858 | luaV_fastset1(t, s2v(L->top.p - 2), s2v(L->top.p - 1), aux, luaH_set1); |
| 858 | luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); | 859 | if (aux == HOK) { |
| 860 | luaV_finishfastset1(L, t, s2v(L->top.p - 1)); | ||
| 859 | } | 861 | } |
| 860 | else | 862 | else |
| 861 | luaV_finishset(L, t, s2v(L->top.p - 2), s2v(L->top.p - 1), slot); | 863 | luaV_finishset1(L, t, s2v(L->top.p - 2), s2v(L->top.p - 1), aux); |
| 862 | L->top.p -= 2; /* pop index and value */ | 864 | L->top.p -= 2; /* pop index and value */ |
| 863 | lua_unlock(L); | 865 | lua_unlock(L); |
| 864 | } | 866 | } |
| @@ -872,17 +874,18 @@ LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { | |||
| 872 | 874 | ||
| 873 | LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { | 875 | LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { |
| 874 | TValue *t; | 876 | TValue *t; |
| 875 | const TValue *slot; | 877 | int aux; |
| 876 | lua_lock(L); | 878 | lua_lock(L); |
| 877 | api_checknelems(L, 1); | 879 | api_checknelems(L, 1); |
| 878 | t = index2value(L, idx); | 880 | t = index2value(L, idx); |
| 879 | if (luaV_fastgeti(L, t, n, slot)) { | 881 | luaV_fastseti1(t, n, s2v(L->top.p - 1), aux); |
| 880 | luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); | 882 | if (aux == HOK) { |
| 883 | luaV_finishfastset1(L, t, s2v(L->top.p - 1)); | ||
| 881 | } | 884 | } |
| 882 | else { | 885 | else { |
| 883 | TValue aux; | 886 | TValue temp; |
| 884 | setivalue(&aux, n); | 887 | setivalue(&temp, n); |
| 885 | luaV_finishset(L, t, &aux, s2v(L->top.p - 1), slot); | 888 | luaV_finishset1(L, t, &temp, s2v(L->top.p - 1), aux); |
| 886 | } | 889 | } |
| 887 | L->top.p--; /* pop value */ | 890 | L->top.p--; /* pop value */ |
| 888 | lua_unlock(L); | 891 | lua_unlock(L); |
| @@ -719,15 +719,7 @@ void luaH_newkey (lua_State *L, Table *t, const TValue *key, TValue *value) { | |||
| 719 | } | 719 | } |
| 720 | 720 | ||
| 721 | 721 | ||
| 722 | /* | 722 | static const TValue *getintfromarray (Table *t, lua_Integer key) { |
| 723 | ** Search function for integers. If integer is inside 'alimit', get it | ||
| 724 | ** directly from the array part. Otherwise, if 'alimit' is not equal to | ||
| 725 | ** the real size of the array, key still can be in the array part. In | ||
| 726 | ** this case, try to avoid a call to 'luaH_realasize' when key is just | ||
| 727 | ** one more than the limit (so that it can be incremented without | ||
| 728 | ** changing the real size of the array). | ||
| 729 | */ | ||
| 730 | const TValue *luaH_getint (Table *t, lua_Integer key) { | ||
| 731 | if (l_castS2U(key) - 1u < t->alimit) /* 'key' in [1, t->alimit]? */ | 723 | if (l_castS2U(key) - 1u < t->alimit) /* 'key' in [1, t->alimit]? */ |
| 732 | return &t->array[key - 1]; | 724 | return &t->array[key - 1]; |
| 733 | else if (!limitequalsasize(t) && /* key still may be in the array part? */ | 725 | else if (!limitequalsasize(t) && /* key still may be in the array part? */ |
| @@ -736,19 +728,40 @@ const TValue *luaH_getint (Table *t, lua_Integer key) { | |||
| 736 | t->alimit = cast_uint(key); /* probably '#t' is here now */ | 728 | t->alimit = cast_uint(key); /* probably '#t' is here now */ |
| 737 | return &t->array[key - 1]; | 729 | return &t->array[key - 1]; |
| 738 | } | 730 | } |
| 739 | else { | 731 | else return NULL; /* key is not in the array part */ |
| 740 | Node *n = hashint(t, key); | 732 | } |
| 741 | for (;;) { /* check whether 'key' is somewhere in the chain */ | 733 | |
| 742 | if (keyisinteger(n) && keyival(n) == key) | 734 | |
| 743 | return gval(n); /* that's it */ | 735 | static const TValue *getintfromhash (Table *t, lua_Integer key) { |
| 744 | else { | 736 | Node *n = hashint(t, key); |
| 745 | int nx = gnext(n); | 737 | lua_assert(l_castS2U(key) - 1u >= luaH_realasize(t)); |
| 746 | if (nx == 0) break; | 738 | for (;;) { /* check whether 'key' is somewhere in the chain */ |
| 747 | n += nx; | 739 | if (keyisinteger(n) && keyival(n) == key) |
| 748 | } | 740 | return gval(n); /* that's it */ |
| 741 | else { | ||
| 742 | int nx = gnext(n); | ||
| 743 | if (nx == 0) break; | ||
| 744 | n += nx; | ||
| 749 | } | 745 | } |
| 750 | return &absentkey; | ||
| 751 | } | 746 | } |
| 747 | return &absentkey; | ||
| 748 | } | ||
| 749 | |||
| 750 | |||
| 751 | /* | ||
| 752 | ** Search function for integers. If integer is inside 'alimit', get it | ||
| 753 | ** directly from the array part. Otherwise, if 'alimit' is not equal to | ||
| 754 | ** the real size of the array, key still can be in the array part. In | ||
| 755 | ** this case, try to avoid a call to 'luaH_realasize' when key is just | ||
| 756 | ** one more than the limit (so that it can be incremented without | ||
| 757 | ** changing the real size of the array). | ||
| 758 | */ | ||
| 759 | const TValue *luaH_getint (Table *t, lua_Integer key) { | ||
| 760 | const TValue *slot = getintfromarray(t, key); | ||
| 761 | if (slot != NULL) | ||
| 762 | return slot; | ||
| 763 | else | ||
| 764 | return getintfromhash(t, key); | ||
| 752 | } | 765 | } |
| 753 | 766 | ||
| 754 | 767 | ||
| @@ -832,6 +845,58 @@ int luaH_get1 (Table *t, const TValue *key, TValue *res) { | |||
| 832 | } | 845 | } |
| 833 | 846 | ||
| 834 | 847 | ||
| 848 | static int finishnodeset (Table *t, const TValue *slot, TValue *val) { | ||
| 849 | if (!ttisnil(slot)) { | ||
| 850 | setobj(((lua_State*)NULL), cast(TValue*, slot), val); | ||
| 851 | return HOK; /* success */ | ||
| 852 | } | ||
| 853 | else if (isabstkey(slot)) | ||
| 854 | return HNOTFOUND; /* no slot with that key */ | ||
| 855 | else return (cast(Node*, slot) - t->node) + HFIRSTNODE; /* node encoded */ | ||
| 856 | } | ||
| 857 | |||
| 858 | |||
| 859 | int luaH_setint1 (Table *t, lua_Integer key, TValue *val) { | ||
| 860 | const TValue *slot = getintfromarray(t, key); | ||
| 861 | if (slot != NULL) { | ||
| 862 | if (!ttisnil(slot)) { | ||
| 863 | setobj(((lua_State*)NULL), cast(TValue*, slot), val); | ||
| 864 | return HOK; /* success */ | ||
| 865 | } | ||
| 866 | else | ||
| 867 | return ~cast_int(key); /* empty slot in the array part */ | ||
| 868 | } | ||
| 869 | else | ||
| 870 | return finishnodeset(t, getintfromhash(t, key), val); | ||
| 871 | } | ||
| 872 | |||
| 873 | |||
| 874 | int luaH_setshortstr1 (Table *t, TString *key, TValue *val) { | ||
| 875 | return finishnodeset(t, luaH_getshortstr(t, key), val); | ||
| 876 | } | ||
| 877 | |||
| 878 | |||
| 879 | int luaH_setstr1 (Table *t, TString *key, TValue *val) { | ||
| 880 | return finishnodeset(t, luaH_getstr(t, key), val); | ||
| 881 | } | ||
| 882 | |||
| 883 | |||
| 884 | int luaH_set1 (Table *t, const TValue *key, TValue *val) { | ||
| 885 | switch (ttypetag(key)) { | ||
| 886 | case LUA_VSHRSTR: return luaH_setshortstr1(t, tsvalue(key), val); | ||
| 887 | case LUA_VNUMINT: return luaH_setint1(t, ivalue(key), val); | ||
| 888 | case LUA_VNIL: return HNOTFOUND; | ||
| 889 | case LUA_VNUMFLT: { | ||
| 890 | lua_Integer k; | ||
| 891 | if (luaV_flttointeger(fltvalue(key), &k, F2Ieq)) /* integral index? */ | ||
| 892 | return luaH_setint1(t, k, val); /* use specialized version */ | ||
| 893 | /* else... */ | ||
| 894 | } /* FALLTHROUGH */ | ||
| 895 | default: | ||
| 896 | return finishnodeset(t, getgeneric(t, key, 0), val); | ||
| 897 | } | ||
| 898 | } | ||
| 899 | |||
| 835 | /* | 900 | /* |
| 836 | ** Finish a raw "set table" operation, where 'slot' is where the value | 901 | ** Finish a raw "set table" operation, where 'slot' is where the value |
| 837 | ** should have been (the result of a previous "get table"). | 902 | ** should have been (the result of a previous "get table"). |
| @@ -847,6 +912,21 @@ void luaH_finishset (lua_State *L, Table *t, const TValue *key, | |||
| 847 | } | 912 | } |
| 848 | 913 | ||
| 849 | 914 | ||
| 915 | void luaH_finishset1 (lua_State *L, Table *t, const TValue *key, | ||
| 916 | TValue *value, int aux) { | ||
| 917 | if (aux == HNOTFOUND) { | ||
| 918 | luaH_newkey(L, t, key, value); | ||
| 919 | } | ||
| 920 | else if (aux > 0) { /* regular Node? */ | ||
| 921 | setobj2t(L, gval(gnode(t, aux - HFIRSTNODE)), value); | ||
| 922 | } | ||
| 923 | else { /* array entry */ | ||
| 924 | aux = ~aux; /* real index */ | ||
| 925 | val2arr(t, aux, getArrTag(t, aux), value); | ||
| 926 | } | ||
| 927 | } | ||
| 928 | |||
| 929 | |||
| 850 | /* | 930 | /* |
| 851 | ** beware: when using this function you probably need to check a GC | 931 | ** beware: when using this function you probably need to check a GC |
| 852 | ** barrier and invalidate the TM cache. | 932 | ** barrier and invalidate the TM cache. |
| @@ -39,6 +39,7 @@ | |||
| 39 | #define HOK 0 | 39 | #define HOK 0 |
| 40 | #define HNOTFOUND 1 | 40 | #define HNOTFOUND 1 |
| 41 | #define HNOTATABLE 2 | 41 | #define HNOTATABLE 2 |
| 42 | #define HFIRSTNODE 3 | ||
| 42 | 43 | ||
| 43 | 44 | ||
| 44 | /* fast access to components of array values */ | 45 | /* fast access to components of array values */ |
| @@ -50,12 +51,20 @@ | |||
| 50 | #define arr2val(h,k,tag,res) \ | 51 | #define arr2val(h,k,tag,res) \ |
| 51 | ((res)->tt_ = tag, (res)->value_ = *getArrVal(h,k)) | 52 | ((res)->tt_ = tag, (res)->value_ = *getArrVal(h,k)) |
| 52 | 53 | ||
| 54 | #define val2arr(h,k,tag,val) \ | ||
| 55 | (*tag = (val)->tt_, *getArrVal(h,k) = (val)->value_) | ||
| 56 | |||
| 53 | 57 | ||
| 54 | LUAI_FUNC int luaH_getshortstr1 (Table *t, TString *key, TValue *res); | 58 | LUAI_FUNC int luaH_getshortstr1 (Table *t, TString *key, TValue *res); |
| 55 | LUAI_FUNC int luaH_getstr1 (Table *t, TString *key, TValue *res); | 59 | LUAI_FUNC int luaH_getstr1 (Table *t, TString *key, TValue *res); |
| 56 | LUAI_FUNC int luaH_get1 (Table *t, const TValue *key, TValue *res); | 60 | LUAI_FUNC int luaH_get1 (Table *t, const TValue *key, TValue *res); |
| 57 | LUAI_FUNC int luaH_getint1 (Table *t, lua_Integer key, TValue *res); | 61 | LUAI_FUNC int luaH_getint1 (Table *t, lua_Integer key, TValue *res); |
| 58 | 62 | ||
| 63 | LUAI_FUNC int luaH_setint1 (Table *t, lua_Integer key, TValue *val); | ||
| 64 | LUAI_FUNC int luaH_setshortstr1 (Table *t, TString *key, TValue *val); | ||
| 65 | LUAI_FUNC int luaH_setstr1 (Table *t, TString *key, TValue *val); | ||
| 66 | LUAI_FUNC int luaH_set1 (Table *t, const TValue *key, TValue *val); | ||
| 67 | |||
| 59 | LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); | 68 | LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); |
| 60 | LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, | 69 | LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, |
| 61 | TValue *value); | 70 | TValue *value); |
| @@ -68,6 +77,8 @@ LUAI_FUNC void luaH_set (lua_State *L, Table *t, const TValue *key, | |||
| 68 | TValue *value); | 77 | TValue *value); |
| 69 | LUAI_FUNC void luaH_finishset (lua_State *L, Table *t, const TValue *key, | 78 | LUAI_FUNC void luaH_finishset (lua_State *L, Table *t, const TValue *key, |
| 70 | const TValue *slot, TValue *value); | 79 | const TValue *slot, TValue *value); |
| 80 | LUAI_FUNC void luaH_finishset1 (lua_State *L, Table *t, const TValue *key, | ||
| 81 | TValue *value, int aux); | ||
| 71 | LUAI_FUNC Table *luaH_new (lua_State *L); | 82 | LUAI_FUNC Table *luaH_new (lua_State *L); |
| 72 | LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize, | 83 | LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize, |
| 73 | unsigned int nhsize); | 84 | unsigned int nhsize); |
| @@ -325,17 +325,16 @@ void luaV_finishget1 (lua_State *L, const TValue *t, TValue *key, StkId val, | |||
| 325 | ** is no such entry. (The value at 'slot' must be empty, otherwise | 325 | ** is no such entry. (The value at 'slot' must be empty, otherwise |
| 326 | ** 'luaV_fastget' would have done the job.) | 326 | ** 'luaV_fastget' would have done the job.) |
| 327 | */ | 327 | */ |
| 328 | void luaV_finishset (lua_State *L, const TValue *t, TValue *key, | 328 | void luaV_finishset1 (lua_State *L, const TValue *t, TValue *key, |
| 329 | TValue *val, const TValue *slot) { | 329 | TValue *val, int aux) { |
| 330 | int loop; /* counter to avoid infinite loops */ | 330 | int loop; /* counter to avoid infinite loops */ |
| 331 | for (loop = 0; loop < MAXTAGLOOP; loop++) { | 331 | for (loop = 0; loop < MAXTAGLOOP; loop++) { |
| 332 | const TValue *tm; /* '__newindex' metamethod */ | 332 | const TValue *tm; /* '__newindex' metamethod */ |
| 333 | if (slot != NULL) { /* is 't' a table? */ | 333 | if (aux != HNOTATABLE) { /* is 't' a table? */ |
| 334 | Table *h = hvalue(t); /* save 't' table */ | 334 | Table *h = hvalue(t); /* save 't' table */ |
| 335 | lua_assert(isempty(slot)); /* slot must be empty */ | ||
| 336 | tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ | 335 | tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ |
| 337 | if (tm == NULL) { /* no metamethod? */ | 336 | if (tm == NULL) { /* no metamethod? */ |
| 338 | luaH_finishset(L, h, key, slot, val); /* set new value */ | 337 | luaH_finishset1(L, h, key, val, aux); /* set new value */ |
| 339 | invalidateTMcache(h); | 338 | invalidateTMcache(h); |
| 340 | luaC_barrierback(L, obj2gco(h), val); | 339 | luaC_barrierback(L, obj2gco(h), val); |
| 341 | return; | 340 | return; |
| @@ -353,10 +352,9 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key, | |||
| 353 | return; | 352 | return; |
| 354 | } | 353 | } |
| 355 | t = tm; /* else repeat assignment over 'tm' */ | 354 | t = tm; /* else repeat assignment over 'tm' */ |
| 356 | if (luaV_fastget(L, t, key, slot, luaH_get)) { | 355 | luaV_fastset1(t, key, val, aux, luaH_set1); |
| 357 | luaV_finishfastset(L, t, slot, val); | 356 | if (aux == HOK) |
| 358 | return; /* done */ | 357 | return; /* done */ |
| 359 | } | ||
| 360 | /* else 'return luaV_finishset(L, t, key, val, slot)' (loop) */ | 358 | /* else 'return luaV_finishset(L, t, key, val, slot)' (loop) */ |
| 361 | } | 359 | } |
| 362 | luaG_runerror(L, "'__newindex' chain too long; possible loop"); | 360 | luaG_runerror(L, "'__newindex' chain too long; possible loop"); |
| @@ -1296,59 +1294,61 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1296 | vmbreak; | 1294 | vmbreak; |
| 1297 | } | 1295 | } |
| 1298 | vmcase(OP_SETTABUP) { | 1296 | vmcase(OP_SETTABUP) { |
| 1299 | const TValue *slot; | 1297 | int aux; |
| 1300 | TValue *upval = cl->upvals[GETARG_A(i)]->v.p; | 1298 | TValue *upval = cl->upvals[GETARG_A(i)]->v.p; |
| 1301 | TValue *rb = KB(i); | 1299 | TValue *rb = KB(i); |
| 1302 | TValue *rc = RKC(i); | 1300 | TValue *rc = RKC(i); |
| 1303 | TString *key = tsvalue(rb); /* key must be a string */ | 1301 | TString *key = tsvalue(rb); /* key must be a string */ |
| 1304 | if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) { | 1302 | luaV_fastset1(upval, key, rc, aux, luaH_setshortstr1); |
| 1305 | luaV_finishfastset(L, upval, slot, rc); | 1303 | if (aux == HOK) |
| 1306 | } | 1304 | luaV_finishfastset1(L, upval, rc); |
| 1307 | else | 1305 | else |
| 1308 | Protect(luaV_finishset(L, upval, rb, rc, slot)); | 1306 | Protect(luaV_finishset1(L, upval, rb, rc, aux)); |
| 1309 | vmbreak; | 1307 | vmbreak; |
| 1310 | } | 1308 | } |
| 1311 | vmcase(OP_SETTABLE) { | 1309 | vmcase(OP_SETTABLE) { |
| 1312 | StkId ra = RA(i); | 1310 | StkId ra = RA(i); |
| 1313 | const TValue *slot; | 1311 | int aux; |
| 1314 | TValue *rb = vRB(i); /* key (table is in 'ra') */ | 1312 | TValue *rb = vRB(i); /* key (table is in 'ra') */ |
| 1315 | TValue *rc = RKC(i); /* value */ | 1313 | TValue *rc = RKC(i); /* value */ |
| 1316 | lua_Unsigned n; | 1314 | if (ttisinteger(rb)) { /* fast track for integers? */ |
| 1317 | if (ttisinteger(rb) /* fast track for integers? */ | 1315 | luaV_fastseti1(s2v(ra), ivalue(rb), rc, aux); |
| 1318 | ? (cast_void(n = ivalue(rb)), luaV_fastgeti(L, s2v(ra), n, slot)) | 1316 | } |
| 1319 | : luaV_fastget(L, s2v(ra), rb, slot, luaH_get)) { | 1317 | else { |
| 1320 | luaV_finishfastset(L, s2v(ra), slot, rc); | 1318 | luaV_fastset1(s2v(ra), rb, rc, aux, luaH_set1); |
| 1321 | } | 1319 | } |
| 1320 | if (aux == HOK) | ||
| 1321 | luaV_finishfastset1(L, s2v(ra), rc); | ||
| 1322 | else | 1322 | else |
| 1323 | Protect(luaV_finishset(L, s2v(ra), rb, rc, slot)); | 1323 | Protect(luaV_finishset1(L, s2v(ra), rb, rc, aux)); |
| 1324 | vmbreak; | 1324 | vmbreak; |
| 1325 | } | 1325 | } |
| 1326 | vmcase(OP_SETI) { | 1326 | vmcase(OP_SETI) { |
| 1327 | StkId ra = RA(i); | 1327 | StkId ra = RA(i); |
| 1328 | const TValue *slot; | 1328 | int aux; |
| 1329 | int c = GETARG_B(i); | 1329 | int b = GETARG_B(i); |
| 1330 | TValue *rc = RKC(i); | 1330 | TValue *rc = RKC(i); |
| 1331 | if (luaV_fastgeti(L, s2v(ra), c, slot)) { | 1331 | luaV_fastseti1(s2v(ra), b, rc, aux); |
| 1332 | luaV_finishfastset(L, s2v(ra), slot, rc); | 1332 | if (aux == HOK) |
| 1333 | } | 1333 | luaV_finishfastset1(L, s2v(ra), rc); |
| 1334 | else { | 1334 | else { |
| 1335 | TValue key; | 1335 | TValue key; |
| 1336 | setivalue(&key, c); | 1336 | setivalue(&key, b); |
| 1337 | Protect(luaV_finishset(L, s2v(ra), &key, rc, slot)); | 1337 | Protect(luaV_finishset1(L, s2v(ra), &key, rc, aux)); |
| 1338 | } | 1338 | } |
| 1339 | vmbreak; | 1339 | vmbreak; |
| 1340 | } | 1340 | } |
| 1341 | vmcase(OP_SETFIELD) { | 1341 | vmcase(OP_SETFIELD) { |
| 1342 | StkId ra = RA(i); | 1342 | StkId ra = RA(i); |
| 1343 | const TValue *slot; | 1343 | int aux; |
| 1344 | TValue *rb = KB(i); | 1344 | TValue *rb = KB(i); |
| 1345 | TValue *rc = RKC(i); | 1345 | TValue *rc = RKC(i); |
| 1346 | TString *key = tsvalue(rb); /* key must be a string */ | 1346 | TString *key = tsvalue(rb); /* key must be a string */ |
| 1347 | if (luaV_fastget(L, s2v(ra), key, slot, luaH_getshortstr)) { | 1347 | luaV_fastset1(s2v(ra), key, rc, aux, luaH_setshortstr1); |
| 1348 | luaV_finishfastset(L, s2v(ra), slot, rc); | 1348 | if (aux == HOK) |
| 1349 | } | 1349 | luaV_finishfastset1(L, s2v(ra), rc); |
| 1350 | else | 1350 | else |
| 1351 | Protect(luaV_finishset(L, s2v(ra), rb, rc, slot)); | 1351 | Protect(luaV_finishset1(L, s2v(ra), rb, rc, aux)); |
| 1352 | vmbreak; | 1352 | vmbreak; |
| 1353 | } | 1353 | } |
| 1354 | vmcase(OP_NEWTABLE) { | 1354 | vmcase(OP_NEWTABLE) { |
| @@ -104,14 +104,27 @@ typedef enum { | |||
| 104 | ? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \ | 104 | ? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \ |
| 105 | !isempty(slot))) /* result not empty? */ | 105 | !isempty(slot))) /* result not empty? */ |
| 106 | 106 | ||
| 107 | #define luaV_fastgeti1(t,k,val,aux) \ | 107 | #define luaV_fastgeti1(t,k,res,aux) \ |
| 108 | if (!ttistable(t)) aux = HNOTATABLE; \ | 108 | if (!ttistable(t)) aux = HNOTATABLE; \ |
| 109 | else { Table *h = hvalue(t); lua_Unsigned u = l_castS2U(k); \ | 109 | else { Table *h = hvalue(t); lua_Unsigned u = l_castS2U(k); \ |
| 110 | if ((u - 1u < h->alimit)) { \ | 110 | if ((u - 1u < h->alimit)) { \ |
| 111 | int tag = *getArrTag(h,u); \ | 111 | int tag = *getArrTag(h,u); \ |
| 112 | if (tagisempty(tag)) aux = HNOTFOUND; \ | 112 | if (tagisempty(tag)) aux = HNOTFOUND; \ |
| 113 | else { arr2val(h, u, tag, val); aux = HOK; }} \ | 113 | else { arr2val(h, u, tag, res); aux = HOK; }} \ |
| 114 | else { aux = luaH_getint1(h, u, val); }} | 114 | else { aux = luaH_getint1(h, u, res); }} |
| 115 | |||
| 116 | |||
| 117 | #define luaV_fastset1(t,k,val,aux,f) \ | ||
| 118 | (aux = (!ttistable(t) ? HNOTATABLE : f(hvalue(t), k, val))) | ||
| 119 | |||
| 120 | #define luaV_fastseti1(t,k,val,aux) \ | ||
| 121 | if (!ttistable(t)) aux = HNOTATABLE; \ | ||
| 122 | else { Table *h = hvalue(t); lua_Unsigned u = l_castS2U(k); \ | ||
| 123 | if ((u - 1u < h->alimit)) { \ | ||
| 124 | lu_byte *tag = getArrTag(h,u); \ | ||
| 125 | if (tagisempty(*tag)) aux = ~cast_int(u); \ | ||
| 126 | else { val2arr(h, u, tag, val); aux = HOK; }} \ | ||
| 127 | else { aux = luaH_setint1(h, u, val); }} | ||
| 115 | 128 | ||
| 116 | 129 | ||
| 117 | /* | 130 | /* |
| @@ -122,6 +135,8 @@ typedef enum { | |||
| 122 | { setobj2t(L, cast(TValue *,slot), v); \ | 135 | { setobj2t(L, cast(TValue *,slot), v); \ |
| 123 | luaC_barrierback(L, gcvalue(t), v); } | 136 | luaC_barrierback(L, gcvalue(t), v); } |
| 124 | 137 | ||
| 138 | #define luaV_finishfastset1(L,t,v) luaC_barrierback(L, gcvalue(t), v) | ||
| 139 | |||
| 125 | 140 | ||
| 126 | /* | 141 | /* |
| 127 | ** Shift right is the same as shift left with a negative 'y' | 142 | ** Shift right is the same as shift left with a negative 'y' |
| @@ -140,8 +155,8 @@ LUAI_FUNC int luaV_tointegerns (const TValue *obj, lua_Integer *p, | |||
| 140 | LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode); | 155 | LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode); |
| 141 | LUAI_FUNC void luaV_finishget1 (lua_State *L, const TValue *t, TValue *key, | 156 | LUAI_FUNC void luaV_finishget1 (lua_State *L, const TValue *t, TValue *key, |
| 142 | StkId val, int aux); | 157 | StkId val, int aux); |
| 143 | LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, | 158 | LUAI_FUNC void luaV_finishset1 (lua_State *L, const TValue *t, TValue *key, |
| 144 | TValue *val, const TValue *slot); | 159 | TValue *val, int aux); |
| 145 | LUAI_FUNC void luaV_finishOp (lua_State *L); | 160 | LUAI_FUNC void luaV_finishOp (lua_State *L); |
| 146 | LUAI_FUNC void luaV_execute (lua_State *L, CallInfo *ci); | 161 | LUAI_FUNC void luaV_execute (lua_State *L, CallInfo *ci); |
| 147 | LUAI_FUNC void luaV_concat (lua_State *L, int total); | 162 | LUAI_FUNC void luaV_concat (lua_State *L, int total); |
