diff options
Diffstat (limited to '')
-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 | /* |