diff options
| -rw-r--r-- | lapi.c | 19 | ||||
| -rw-r--r-- | ltable.c | 55 | ||||
| -rw-r--r-- | ltable.h | 19 | ||||
| -rw-r--r-- | lvm.h | 36 |
4 files changed, 80 insertions, 49 deletions
| @@ -102,7 +102,7 @@ static TValue *index2value (lua_State *L, int idx) { | |||
| 102 | /* | 102 | /* |
| 103 | ** Convert a valid actual index (not a pseudo-index) to its address. | 103 | ** Convert a valid actual index (not a pseudo-index) to its address. |
| 104 | */ | 104 | */ |
| 105 | l_sinline StkId index2stack (lua_State *L, int idx) { | 105 | static StkId index2stack (lua_State *L, int idx) { |
| 106 | CallInfo *ci = L->ci; | 106 | CallInfo *ci = L->ci; |
| 107 | if (idx > 0) { | 107 | if (idx > 0) { |
| 108 | StkId o = ci->func.p + idx; | 108 | StkId o = ci->func.p + idx; |
| @@ -234,7 +234,7 @@ LUA_API void lua_closeslot (lua_State *L, int idx) { | |||
| 234 | ** Note that we move(copy) only the value inside the stack. | 234 | ** Note that we move(copy) only the value inside the stack. |
| 235 | ** (We do not move additional fields that may exist.) | 235 | ** (We do not move additional fields that may exist.) |
| 236 | */ | 236 | */ |
| 237 | l_sinline void reverse (lua_State *L, StkId from, StkId to) { | 237 | static void reverse (lua_State *L, StkId from, StkId to) { |
| 238 | for (; from < to; from++, to--) { | 238 | for (; from < to; from++, to--) { |
| 239 | TValue temp; | 239 | TValue temp; |
| 240 | setobj(L, &temp, s2v(from)); | 240 | setobj(L, &temp, s2v(from)); |
| @@ -664,7 +664,7 @@ LUA_API int lua_pushthread (lua_State *L) { | |||
| 664 | */ | 664 | */ |
| 665 | 665 | ||
| 666 | 666 | ||
| 667 | l_sinline int auxgetstr (lua_State *L, const TValue *t, const char *k) { | 667 | static int auxgetstr (lua_State *L, const TValue *t, const char *k) { |
| 668 | int hres; | 668 | int hres; |
| 669 | TString *str = luaS_new(L, k); | 669 | TString *str = luaS_new(L, k); |
| 670 | luaV_fastget(t, str, s2v(L->top.p), luaH_getstr, hres); | 670 | luaV_fastget(t, str, s2v(L->top.p), luaH_getstr, hres); |
| @@ -683,7 +683,9 @@ l_sinline int auxgetstr (lua_State *L, const TValue *t, const char *k) { | |||
| 683 | 683 | ||
| 684 | static void getGlobalTable (lua_State *L, TValue *gt) { | 684 | static void getGlobalTable (lua_State *L, TValue *gt) { |
| 685 | Table *registry = hvalue(&G(L)->l_registry); | 685 | Table *registry = hvalue(&G(L)->l_registry); |
| 686 | luaH_getint(registry, LUA_RIDX_GLOBALS, gt); | 686 | int hres = luaH_getint(registry, LUA_RIDX_GLOBALS, gt); |
| 687 | (void)hres; /* avoid warnings (not used) when checks are off */ | ||
| 688 | api_check(L, hres == HOK, "global table must exist"); | ||
| 687 | } | 689 | } |
| 688 | 690 | ||
| 689 | 691 | ||
| @@ -740,7 +742,7 @@ l_sinline int finishrawget (lua_State *L, int hres) { | |||
| 740 | } | 742 | } |
| 741 | 743 | ||
| 742 | 744 | ||
| 743 | static Table *gettable (lua_State *L, int idx) { | 745 | l_sinline Table *gettable (lua_State *L, int idx) { |
| 744 | TValue *t = index2value(L, idx); | 746 | TValue *t = index2value(L, idx); |
| 745 | api_check(L, ttistable(t), "table expected"); | 747 | api_check(L, ttistable(t), "table expected"); |
| 746 | return hvalue(t); | 748 | return hvalue(t); |
| @@ -761,9 +763,11 @@ LUA_API int lua_rawget (lua_State *L, int idx) { | |||
| 761 | 763 | ||
| 762 | LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { | 764 | LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { |
| 763 | Table *t; | 765 | Table *t; |
| 766 | int hres; | ||
| 764 | lua_lock(L); | 767 | lua_lock(L); |
| 765 | t = gettable(L, idx); | 768 | t = gettable(L, idx); |
| 766 | return finishrawget(L, luaH_getint(t, n, s2v(L->top.p))); | 769 | luaH_fastgeti(t, n, s2v(L->top.p), hres); |
| 770 | return finishrawget(L, hres); | ||
| 767 | } | 771 | } |
| 768 | 772 | ||
| 769 | 773 | ||
| @@ -901,9 +905,8 @@ LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { | |||
| 901 | api_checknelems(L, 1); | 905 | api_checknelems(L, 1); |
| 902 | t = index2value(L, idx); | 906 | t = index2value(L, idx); |
| 903 | luaV_fastseti(t, n, s2v(L->top.p - 1), hres); | 907 | luaV_fastseti(t, n, s2v(L->top.p - 1), hres); |
| 904 | if (hres == HOK) { | 908 | if (hres == HOK) |
| 905 | luaV_finishfastset(L, t, s2v(L->top.p - 1)); | 909 | luaV_finishfastset(L, t, s2v(L->top.p - 1)); |
| 906 | } | ||
| 907 | else { | 910 | else { |
| 908 | TValue temp; | 911 | TValue temp; |
| 909 | setivalue(&temp, n); | 912 | setivalue(&temp, n); |
| @@ -408,21 +408,22 @@ static void freehash (lua_State *L, Table *t) { | |||
| 408 | ** not the real size of the array, the key still can be in the array | 408 | ** not the real size of the array, the key still can be in the array |
| 409 | ** part. In this case, do the "Xmilia trick" to check whether 'key-1' | 409 | ** part. In this case, do the "Xmilia trick" to check whether 'key-1' |
| 410 | ** is smaller than the real size. | 410 | ** is smaller than the real size. |
| 411 | ** The trick works as follow: let 'p' be an integer such that | 411 | ** The trick works as follow: let 'p' be the integer such that |
| 412 | ** '2^(p+1) >= alimit > 2^p', or '2^(p+1) > alimit-1 >= 2^p'. | 412 | ** '2^(p+1) >= alimit > 2^p', or '2^(p+1) > alimit-1 >= 2^p'. That is, |
| 413 | ** That is, 2^(p+1) is the real size of the array, and 'p' is the highest | 413 | ** 'p' is the highest 1-bit in 'alimit-1', and 2^(p+1) is the real size |
| 414 | ** bit on in 'alimit-1'. What we have to check becomes 'key-1 < 2^(p+1)'. | 414 | ** of the array. What we have to check becomes 'key-1 < 2^(p+1)'. We |
| 415 | ** We compute '(key-1) & ~(alimit-1)', which we call 'res'; it will | 415 | ** compute '(key-1) & ~(alimit-1)', which we call 'res'; it will have |
| 416 | ** have the 'p' bit cleared. If the key is outside the array, that is, | 416 | ** the 'p' bit cleared. (It may also clear other bits smaller than 'p', |
| 417 | ** 'key-1 >= 2^(p+1)', then 'res' will have some 1-bit higher than 'p', | 417 | ** but no bit higher than 'p'.) If the key is outside the array, that |
| 418 | ** therefore it will be larger or equal to 'alimit', and the check | 418 | ** is, 'key-1 >= 2^(p+1)', then 'res' will have some 1-bit higher than |
| 419 | ** 'p', therefore it will be larger or equal to 'alimit', and the check | ||
| 419 | ** will fail. If 'key-1 < 2^(p+1)', then 'res' has no 1-bit higher than | 420 | ** will fail. If 'key-1 < 2^(p+1)', then 'res' has no 1-bit higher than |
| 420 | ** 'p', and as the bit 'p' itself was cleared, 'res' will be smaller | 421 | ** 'p', and as the bit 'p' itself was cleared, 'res' will be smaller |
| 421 | ** than 2^p, therefore smaller than 'alimit', and the check succeeds. | 422 | ** than 2^p, therefore smaller than 'alimit', and the check succeeds. |
| 422 | ** As special cases, when 'alimit' is 0 the condition is trivially false, | 423 | ** As special cases, when 'alimit' is 0 the condition is trivially false, |
| 423 | ** and when 'alimit' is 1 the condition simplifies to 'key-1 < alimit'. | 424 | ** and when 'alimit' is 1 the condition simplifies to 'key-1 < alimit'. |
| 424 | ** If key is 0 or negative, 'res' will have its higher bit on, so that | 425 | ** If key is 0 or negative, 'res' will have its higher bit on, so that |
| 425 | ** if cannot be smaller than alimit. | 426 | ** it cannot be smaller than 'alimit'. |
| 426 | */ | 427 | */ |
| 427 | static int keyinarray (Table *t, lua_Integer key) { | 428 | static int keyinarray (Table *t, lua_Integer key) { |
| 428 | lua_Unsigned alimit = t->alimit; | 429 | lua_Unsigned alimit = t->alimit; |
| @@ -788,11 +789,11 @@ static Node *getfreepos (Table *t) { | |||
| 788 | 789 | ||
| 789 | 790 | ||
| 790 | /* | 791 | /* |
| 791 | ** inserts a new key into a hash table; first, check whether key's main | 792 | ** Inserts a new key into a hash table; first, check whether key's main |
| 792 | ** position is free. If not, check whether colliding node is in its main | 793 | ** position is free. If not, check whether colliding node is in its main |
| 793 | ** position or not: if it is not, move colliding node to an empty place and | 794 | ** position or not: if it is not, move colliding node to an empty place |
| 794 | ** put new key in its main position; otherwise (colliding node is in its main | 795 | ** and put new key in its main position; otherwise (colliding node is in |
| 795 | ** position), new key goes to an empty position. | 796 | ** its main position), new key goes to an empty position. |
| 796 | */ | 797 | */ |
| 797 | static void luaH_newkey (lua_State *L, Table *t, const TValue *key, | 798 | static void luaH_newkey (lua_State *L, Table *t, const TValue *key, |
| 798 | TValue *value) { | 799 | TValue *value) { |
| @@ -987,6 +988,16 @@ static int finishnodeset (Table *t, const TValue *slot, TValue *val) { | |||
| 987 | } | 988 | } |
| 988 | 989 | ||
| 989 | 990 | ||
| 991 | static int rawfinishnodeset (const TValue *slot, TValue *val) { | ||
| 992 | if (isabstkey(slot)) | ||
| 993 | return 0; /* no slot with that key */ | ||
| 994 | else { | ||
| 995 | setobj(((lua_State*)NULL), cast(TValue*, slot), val); | ||
| 996 | return 1; /* success */ | ||
| 997 | } | ||
| 998 | } | ||
| 999 | |||
| 1000 | |||
| 990 | int luaH_psetint (Table *t, lua_Integer key, TValue *val) { | 1001 | int luaH_psetint (Table *t, lua_Integer key, TValue *val) { |
| 991 | if (keyinarray(t, key)) { | 1002 | if (keyinarray(t, key)) { |
| 992 | lu_byte *tag = getArrTag(t, key - 1); | 1003 | lu_byte *tag = getArrTag(t, key - 1); |
| @@ -1063,12 +1074,20 @@ void luaH_set (lua_State *L, Table *t, const TValue *key, TValue *value) { | |||
| 1063 | } | 1074 | } |
| 1064 | 1075 | ||
| 1065 | 1076 | ||
| 1077 | /* | ||
| 1078 | ** Ditto for a GC barrier. (No need to invalidate the TM cache, as | ||
| 1079 | ** integers cannot be keys to metamethods.) | ||
| 1080 | */ | ||
| 1066 | void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { | 1081 | void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { |
| 1067 | int hres = luaH_psetint(t, key, value); | 1082 | if (keyinarray(t, key)) |
| 1068 | if (hres != HOK) { | 1083 | obj2arr(t, key, value); |
| 1069 | TValue k; | 1084 | else { |
| 1070 | setivalue(&k, key); | 1085 | int ok = rawfinishnodeset(getintfromhash(t, key), value); |
| 1071 | luaH_finishset(L, t, &k, value, hres); | 1086 | if (!ok) { |
| 1087 | TValue k; | ||
| 1088 | setivalue(&k, key); | ||
| 1089 | luaH_newkey(L, t, &k, value); | ||
| 1090 | } | ||
| 1072 | } | 1091 | } |
| 1073 | } | 1092 | } |
| 1074 | 1093 | ||
| @@ -45,6 +45,25 @@ | |||
| 45 | #define nodefromval(v) cast(Node *, (v)) | 45 | #define nodefromval(v) cast(Node *, (v)) |
| 46 | 46 | ||
| 47 | 47 | ||
| 48 | |||
| 49 | #define luaH_fastgeti(t,k,res,hres) \ | ||
| 50 | { Table *h = t; lua_Unsigned u = l_castS2U(k); \ | ||
| 51 | if ((u - 1u < h->alimit)) { \ | ||
| 52 | int tag = *getArrTag(h,(u)-1u); \ | ||
| 53 | if (tagisempty(tag)) hres = HNOTFOUND; \ | ||
| 54 | else { farr2val(h, u, tag, res); hres = HOK; }} \ | ||
| 55 | else { hres = luaH_getint(h, u, res); }} | ||
| 56 | |||
| 57 | |||
| 58 | #define luaH_fastseti(t,k,val,hres) \ | ||
| 59 | { Table *h = t; lua_Unsigned u = l_castS2U(k); \ | ||
| 60 | if ((u - 1u < h->alimit)) { \ | ||
| 61 | lu_byte *tag = getArrTag(h,(u)-1u); \ | ||
| 62 | if (tagisempty(*tag)) hres = ~cast_int(u); \ | ||
| 63 | else { fval2arr(h, u, tag, val); hres = HOK; }} \ | ||
| 64 | else { hres = luaH_psetint(h, u, val); }} | ||
| 65 | |||
| 66 | |||
| 48 | /* results from get/pset */ | 67 | /* results from get/pset */ |
| 49 | #define HOK 0 | 68 | #define HOK 0 |
| 50 | #define HNOTFOUND 1 | 69 | #define HNOTFOUND 1 |
| @@ -78,35 +78,25 @@ typedef enum { | |||
| 78 | /* | 78 | /* |
| 79 | ** fast track for 'gettable' | 79 | ** fast track for 'gettable' |
| 80 | */ | 80 | */ |
| 81 | #define luaV_fastget(t,k,res,f, aux) \ | 81 | #define luaV_fastget(t,k,res,f, hres) \ |
| 82 | (aux = (!ttistable(t) ? HNOTATABLE : f(hvalue(t), k, res))) | 82 | (hres = (!ttistable(t) ? HNOTATABLE : f(hvalue(t), k, res))) |
| 83 | 83 | ||
| 84 | 84 | ||
| 85 | /* | 85 | /* |
| 86 | ** Special case of 'luaV_fastget' for integers, inlining the fast case | 86 | ** Special case of 'luaV_fastget' for integers, inlining the fast case |
| 87 | ** of 'luaH_getint'. | 87 | ** of 'luaH_getint'. |
| 88 | */ | 88 | */ |
| 89 | #define luaV_fastgeti(t,k,res,aux) \ | 89 | #define luaV_fastgeti(t,k,res,hres) \ |
| 90 | if (!ttistable(t)) aux = HNOTATABLE; \ | 90 | if (!ttistable(t)) hres = HNOTATABLE; \ |
| 91 | else { Table *h = hvalue(t); lua_Unsigned u = l_castS2U(k); \ | 91 | else { luaH_fastgeti(hvalue(t), k, res, hres); } |
| 92 | if ((u - 1u < h->alimit)) { \ | 92 | |
| 93 | int tag = *getArrTag(h,(u)-1u); \ | 93 | |
| 94 | if (tagisempty(tag)) aux = HNOTFOUND; \ | 94 | #define luaV_fastset(t,k,val,hres,f) \ |
| 95 | else { farr2val(h, u, tag, res); aux = HOK; }} \ | 95 | (hres = (!ttistable(t) ? HNOTATABLE : f(hvalue(t), k, val))) |
| 96 | else { aux = luaH_getint(h, u, res); }} | 96 | |
| 97 | 97 | #define luaV_fastseti(t,k,val,hres) \ | |
| 98 | 98 | if (!ttistable(t)) hres = HNOTATABLE; \ | |
| 99 | #define luaV_fastset(t,k,val,aux,f) \ | 99 | else { luaH_fastseti(hvalue(t), k, val, hres); } |
| 100 | (aux = (!ttistable(t) ? HNOTATABLE : f(hvalue(t), k, val))) | ||
| 101 | |||
| 102 | #define luaV_fastseti(t,k,val,aux) \ | ||
| 103 | if (!ttistable(t)) aux = HNOTATABLE; \ | ||
| 104 | else { Table *h = hvalue(t); lua_Unsigned u = l_castS2U(k); \ | ||
| 105 | if ((u - 1u < h->alimit)) { \ | ||
| 106 | lu_byte *tag = getArrTag(h,(u)-1u); \ | ||
| 107 | if (tagisempty(*tag)) aux = ~cast_int(u); \ | ||
| 108 | else { fval2arr(h, u, tag, val); aux = HOK; }} \ | ||
| 109 | else { aux = luaH_psetint(h, u, val); }} | ||
| 110 | 100 | ||
| 111 | 101 | ||
| 112 | /* | 102 | /* |
