diff options
-rw-r--r-- | lapi.c | 69 | ||||
-rw-r--r-- | lcode.c | 5 | ||||
-rw-r--r-- | ldump.c | 5 | ||||
-rw-r--r-- | lobject.h | 26 | ||||
-rw-r--r-- | ltable.c | 48 | ||||
-rw-r--r-- | ltable.h | 29 | ||||
-rw-r--r-- | ltests.c | 6 | ||||
-rw-r--r-- | lundump.c | 3 | ||||
-rw-r--r-- | lvm.c | 61 | ||||
-rw-r--r-- | lvm.h | 18 |
10 files changed, 138 insertions, 132 deletions
@@ -353,7 +353,7 @@ LUA_API void lua_arith (lua_State *L, int op) { | |||
353 | } | 353 | } |
354 | /* first operand at top - 2, second at top - 1; result go to top - 2 */ | 354 | /* first operand at top - 2, second at top - 1; result go to top - 2 */ |
355 | luaO_arith(L, op, s2v(L->top.p - 2), s2v(L->top.p - 1), L->top.p - 2); | 355 | luaO_arith(L, op, s2v(L->top.p - 2), s2v(L->top.p - 1), L->top.p - 2); |
356 | L->top.p--; /* remove second operand */ | 356 | L->top.p--; /* pop second operand */ |
357 | lua_unlock(L); | 357 | lua_unlock(L); |
358 | } | 358 | } |
359 | 359 | ||
@@ -666,47 +666,49 @@ LUA_API int lua_pushthread (lua_State *L) { | |||
666 | 666 | ||
667 | 667 | ||
668 | static int auxgetstr (lua_State *L, const TValue *t, const char *k) { | 668 | static int auxgetstr (lua_State *L, const TValue *t, const char *k) { |
669 | TValue aux; | 669 | int tag; |
670 | TString *str = luaS_new(L, k); | 670 | TString *str = luaS_new(L, k); |
671 | luaV_fastget(t, str, s2v(L->top.p), luaH_getstr, aux); | 671 | luaV_fastget(t, str, s2v(L->top.p), luaH_getstr, tag); |
672 | if (!isemptyV(aux)) { | 672 | if (!tagisempty(tag)) { |
673 | api_incr_top(L); | 673 | api_incr_top(L); |
674 | } | 674 | } |
675 | else { | 675 | else { |
676 | setsvalue2s(L, L->top.p, str); | 676 | setsvalue2s(L, L->top.p, str); |
677 | api_incr_top(L); | 677 | api_incr_top(L); |
678 | luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, aux); | 678 | tag = luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, tag); |
679 | } | 679 | } |
680 | lua_unlock(L); | 680 | lua_unlock(L); |
681 | return ttype(s2v(L->top.p - 1)); | 681 | return novariant(tag); |
682 | } | 682 | } |
683 | 683 | ||
684 | 684 | ||
685 | static TValue getGlobalTable (lua_State *L) { | 685 | static void getGlobalTable (lua_State *L, TValue *gt) { |
686 | Table *registry = hvalue(&G(L)->l_registry); | 686 | Table *registry = hvalue(&G(L)->l_registry); |
687 | return luaH_getint(registry, LUA_RIDX_GLOBALS); | 687 | int tag = luaH_getint(registry, LUA_RIDX_GLOBALS, gt); |
688 | (void)tag; /* avoid not-used warnings when checks are off */ | ||
689 | api_check(L, novariant(tag) == LUA_TTABLE, "global table must exist"); | ||
688 | } | 690 | } |
689 | 691 | ||
690 | 692 | ||
691 | LUA_API int lua_getglobal (lua_State *L, const char *name) { | 693 | LUA_API int lua_getglobal (lua_State *L, const char *name) { |
692 | TValue gt; | 694 | TValue gt; |
693 | lua_lock(L); | 695 | lua_lock(L); |
694 | gt = getGlobalTable(L); | 696 | getGlobalTable(L, >); |
695 | return auxgetstr(L, >, name); | 697 | return auxgetstr(L, >, name); |
696 | } | 698 | } |
697 | 699 | ||
698 | 700 | ||
699 | LUA_API int lua_gettable (lua_State *L, int idx) { | 701 | LUA_API int lua_gettable (lua_State *L, int idx) { |
700 | TValue aux; | 702 | int tag; |
701 | TValue *t; | 703 | TValue *t; |
702 | lua_lock(L); | 704 | lua_lock(L); |
703 | api_checkpop(L, 1); | 705 | api_checkpop(L, 1); |
704 | t = index2value(L, idx); | 706 | t = index2value(L, idx); |
705 | luaV_fastget(t, s2v(L->top.p - 1), s2v(L->top.p - 1), luaH_get, aux); | 707 | luaV_fastget(t, s2v(L->top.p - 1), s2v(L->top.p - 1), luaH_get, tag); |
706 | if (isemptyV(aux)) | 708 | if (tagisempty(tag)) |
707 | luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, aux); | 709 | tag = luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, tag); |
708 | lua_unlock(L); | 710 | lua_unlock(L); |
709 | return ttype(s2v(L->top.p - 1)); | 711 | return novariant(tag); |
710 | } | 712 | } |
711 | 713 | ||
712 | 714 | ||
@@ -718,29 +720,27 @@ LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { | |||
718 | 720 | ||
719 | LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { | 721 | LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { |
720 | TValue *t; | 722 | TValue *t; |
721 | TValue aux; | 723 | int tag; |
722 | lua_lock(L); | 724 | lua_lock(L); |
723 | t = index2value(L, idx); | 725 | t = index2value(L, idx); |
724 | luaV_fastgeti(t, n, s2v(L->top.p), aux); | 726 | luaV_fastgeti(t, n, s2v(L->top.p), tag); |
725 | if (isemptyV(aux)) { | 727 | if (tagisempty(tag)) { |
726 | TValue key; | 728 | TValue key; |
727 | setivalue(&key, n); | 729 | setivalue(&key, n); |
728 | luaV_finishget(L, t, &key, L->top.p, aux); | 730 | tag = luaV_finishget(L, t, &key, L->top.p, tag); |
729 | } | 731 | } |
730 | api_incr_top(L); | 732 | api_incr_top(L); |
731 | lua_unlock(L); | 733 | lua_unlock(L); |
732 | return ttype(s2v(L->top.p - 1)); | 734 | return novariant(tag); |
733 | } | 735 | } |
734 | 736 | ||
735 | 737 | ||
736 | l_sinline int finishrawget (lua_State *L, TValue res) { | 738 | static int finishrawget (lua_State *L, int tag) { |
737 | if (isemptyV(res)) /* avoid copying empty items to the stack */ | 739 | if (tagisempty(tag)) /* avoid copying empty items to the stack */ |
738 | setnilvalue(s2v(L->top.p)); | 740 | setnilvalue(s2v(L->top.p)); |
739 | else | ||
740 | setobjV(L, s2v(L->top.p), res); | ||
741 | api_incr_top(L); | 741 | api_incr_top(L); |
742 | lua_unlock(L); | 742 | lua_unlock(L); |
743 | return ttypeV(res); | 743 | return novariant(tag); |
744 | } | 744 | } |
745 | 745 | ||
746 | 746 | ||
@@ -753,23 +753,23 @@ l_sinline Table *gettable (lua_State *L, int idx) { | |||
753 | 753 | ||
754 | LUA_API int lua_rawget (lua_State *L, int idx) { | 754 | LUA_API int lua_rawget (lua_State *L, int idx) { |
755 | Table *t; | 755 | Table *t; |
756 | TValue res; | 756 | int tag; |
757 | lua_lock(L); | 757 | lua_lock(L); |
758 | api_checkpop(L, 1); | 758 | api_checkpop(L, 1); |
759 | t = gettable(L, idx); | 759 | t = gettable(L, idx); |
760 | res = luaH_get(t, s2v(L->top.p - 1)); | 760 | tag = luaH_get(t, s2v(L->top.p - 1), s2v(L->top.p - 1)); |
761 | L->top.p--; /* pop key */ | 761 | L->top.p--; /* pop key */ |
762 | return finishrawget(L, res); | 762 | return finishrawget(L, tag); |
763 | } | 763 | } |
764 | 764 | ||
765 | 765 | ||
766 | LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { | 766 | LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { |
767 | Table *t; | 767 | Table *t; |
768 | TValue aux; | 768 | int tag; |
769 | lua_lock(L); | 769 | lua_lock(L); |
770 | t = gettable(L, idx); | 770 | t = gettable(L, idx); |
771 | luaH_fastgeti(t, n, s2v(L->top.p), aux); | 771 | luaH_fastgeti(t, n, s2v(L->top.p), tag); |
772 | return finishrawget(L, aux); | 772 | return finishrawget(L, tag); |
773 | } | 773 | } |
774 | 774 | ||
775 | 775 | ||
@@ -779,7 +779,7 @@ LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { | |||
779 | lua_lock(L); | 779 | lua_lock(L); |
780 | t = gettable(L, idx); | 780 | t = gettable(L, idx); |
781 | setpvalue(&k, cast_voidp(p)); | 781 | setpvalue(&k, cast_voidp(p)); |
782 | return finishrawget(L, luaH_get(t, &k)); | 782 | return finishrawget(L, luaH_get(t, &k, s2v(L->top.p))); |
783 | } | 783 | } |
784 | 784 | ||
785 | 785 | ||
@@ -872,7 +872,7 @@ static void auxsetstr (lua_State *L, const TValue *t, const char *k) { | |||
872 | LUA_API void lua_setglobal (lua_State *L, const char *name) { | 872 | LUA_API void lua_setglobal (lua_State *L, const char *name) { |
873 | TValue gt; | 873 | TValue gt; |
874 | lua_lock(L); /* unlock done in 'auxsetstr' */ | 874 | lua_lock(L); /* unlock done in 'auxsetstr' */ |
875 | gt = getGlobalTable(L); | 875 | getGlobalTable(L, >); |
876 | auxsetstr(L, >, name); | 876 | auxsetstr(L, >, name); |
877 | } | 877 | } |
878 | 878 | ||
@@ -1122,7 +1122,8 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, | |||
1122 | LClosure *f = clLvalue(s2v(L->top.p - 1)); /* get new function */ | 1122 | LClosure *f = clLvalue(s2v(L->top.p - 1)); /* get new function */ |
1123 | if (f->nupvalues >= 1) { /* does it have an upvalue? */ | 1123 | if (f->nupvalues >= 1) { /* does it have an upvalue? */ |
1124 | /* get global table from registry */ | 1124 | /* get global table from registry */ |
1125 | TValue gt = getGlobalTable(L); | 1125 | TValue gt; |
1126 | getGlobalTable(L, >); | ||
1126 | /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ | 1127 | /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ |
1127 | setobj(L, f->upvals[0]->v.p, >); | 1128 | setobj(L, f->upvals[0]->v.p, >); |
1128 | luaC_barrier(L, f->upvals[0], >); | 1129 | luaC_barrier(L, f->upvals[0], >); |
@@ -1266,7 +1267,7 @@ LUA_API int lua_next (lua_State *L, int idx) { | |||
1266 | if (more) | 1267 | if (more) |
1267 | api_incr_top(L); | 1268 | api_incr_top(L); |
1268 | else /* no more elements */ | 1269 | else /* no more elements */ |
1269 | L->top.p -= 1; /* remove key */ | 1270 | L->top.p--; /* pop key */ |
1270 | lua_unlock(L); | 1271 | lua_unlock(L); |
1271 | return more; | 1272 | return more; |
1272 | } | 1273 | } |
@@ -541,11 +541,12 @@ static void freeexps (FuncState *fs, expdesc *e1, expdesc *e2) { | |||
541 | ** a function can make some indices wrong. | 541 | ** a function can make some indices wrong. |
542 | */ | 542 | */ |
543 | static int addk (FuncState *fs, TValue *key, TValue *v) { | 543 | static int addk (FuncState *fs, TValue *key, TValue *v) { |
544 | TValue val; | ||
544 | lua_State *L = fs->ls->L; | 545 | lua_State *L = fs->ls->L; |
545 | Proto *f = fs->f; | 546 | Proto *f = fs->f; |
546 | TValue val = luaH_get(fs->ls->h, key); /* query scanner table */ | 547 | int tag = luaH_get(fs->ls->h, key, &val); /* query scanner table */ |
547 | int k, oldsize; | 548 | int k, oldsize; |
548 | if (ttisintegerV(val)) { /* is there an index there? */ | 549 | if (tag == LUA_VNUMINT) { /* is there an index there? */ |
549 | k = cast_int(ivalue(&val)); | 550 | k = cast_int(ivalue(&val)); |
550 | /* correct value? (warning: must distinguish floats from integers!) */ | 551 | /* correct value? (warning: must distinguish floats from integers!) */ |
551 | if (k < fs->nk && ttypetag(&f->k[k]) == ttypetag(v) && | 552 | if (k < fs->nk && ttypetag(&f->k[k]) == ttypetag(v) && |
@@ -132,8 +132,9 @@ static void dumpString (DumpState *D, TString *ts) { | |||
132 | if (ts == NULL) | 132 | if (ts == NULL) |
133 | dumpSize(D, 0); | 133 | dumpSize(D, 0); |
134 | else { | 134 | else { |
135 | TValue idx = luaH_getstr(D->h, ts); | 135 | TValue idx; |
136 | if (!isemptyV(idx)) { /* string already saved? */ | 136 | int tag = luaH_getstr(D->h, ts, &idx); |
137 | if (!tagisempty(tag)) { /* string already saved? */ | ||
137 | dumpSize(D, 1); /* reuse a saved string */ | 138 | dumpSize(D, 1); /* reuse a saved string */ |
138 | dumpSize(D, cast_sizet(ivalue(&idx))); /* index of saved string */ | 139 | dumpSize(D, cast_sizet(ivalue(&idx))); /* index of saved string */ |
139 | } | 140 | } |
@@ -75,7 +75,6 @@ typedef struct TValue { | |||
75 | 75 | ||
76 | /* raw type tag of a TValue */ | 76 | /* raw type tag of a TValue */ |
77 | #define rawtt(o) ((o)->tt_) | 77 | #define rawtt(o) ((o)->tt_) |
78 | #define rawttV(o) ((o).tt_) | ||
79 | 78 | ||
80 | /* tag with no variants (bits 0-3) */ | 79 | /* tag with no variants (bits 0-3) */ |
81 | #define novariant(t) ((t) & 0x0F) | 80 | #define novariant(t) ((t) & 0x0F) |
@@ -83,18 +82,14 @@ typedef struct TValue { | |||
83 | /* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ | 82 | /* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ |
84 | #define withvariant(t) ((t) & 0x3F) | 83 | #define withvariant(t) ((t) & 0x3F) |
85 | #define ttypetag(o) withvariant(rawtt(o)) | 84 | #define ttypetag(o) withvariant(rawtt(o)) |
86 | #define ttypetagV(o) withvariant(rawttV(o)) | ||
87 | 85 | ||
88 | /* type of a TValue */ | 86 | /* type of a TValue */ |
89 | #define ttype(o) (novariant(rawtt(o))) | 87 | #define ttype(o) (novariant(rawtt(o))) |
90 | #define ttypeV(o) (novariant(rawttV(o))) | ||
91 | 88 | ||
92 | 89 | ||
93 | /* Macros to test type */ | 90 | /* Macros to test type */ |
94 | #define checktag(o,t) (rawtt(o) == (t)) | 91 | #define checktag(o,t) (rawtt(o) == (t)) |
95 | #define checktagV(o,t) (rawttV(o) == (t)) | ||
96 | #define checktype(o,t) (ttype(o) == (t)) | 92 | #define checktype(o,t) (ttype(o) == (t)) |
97 | #define checktypeV(o,t) (ttypeV(o) == (t)) | ||
98 | 93 | ||
99 | 94 | ||
100 | /* Macros for internal tests */ | 95 | /* Macros for internal tests */ |
@@ -117,7 +112,6 @@ typedef struct TValue { | |||
117 | 112 | ||
118 | /* set a value's tag */ | 113 | /* set a value's tag */ |
119 | #define settt_(o,t) ((o)->tt_=(t)) | 114 | #define settt_(o,t) ((o)->tt_=(t)) |
120 | #define setttV_(o,t) ((o).tt_=(t)) | ||
121 | 115 | ||
122 | 116 | ||
123 | /* main macro to copy values (from 'obj2' to 'obj1') */ | 117 | /* main macro to copy values (from 'obj2' to 'obj1') */ |
@@ -126,11 +120,6 @@ typedef struct TValue { | |||
126 | io1->value_ = io2->value_; settt_(io1, io2->tt_); \ | 120 | io1->value_ = io2->value_; settt_(io1, io2->tt_); \ |
127 | checkliveness(L,io1); lua_assert(!isnonstrictnil(io1)); } | 121 | checkliveness(L,io1); lua_assert(!isnonstrictnil(io1)); } |
128 | 122 | ||
129 | #define setobjV(L,obj1,obj2) \ | ||
130 | { TValue *io1=(obj1); const TValue io2=(obj2); \ | ||
131 | io1->value_ = io2.value_; settt_(io1, io2.tt_); \ | ||
132 | checkliveness(L,io1); lua_assert(!isnonstrictnil(io1)); } | ||
133 | |||
134 | /* | 123 | /* |
135 | ** Different types of assignments, according to source and destination. | 124 | ** Different types of assignments, according to source and destination. |
136 | ** (They are mostly equal now, but may be different in the future.) | 125 | ** (They are mostly equal now, but may be different in the future.) |
@@ -199,16 +188,19 @@ typedef union { | |||
199 | /* Value returned for a key not found in a table (absent key) */ | 188 | /* Value returned for a key not found in a table (absent key) */ |
200 | #define LUA_VABSTKEY makevariant(LUA_TNIL, 2) | 189 | #define LUA_VABSTKEY makevariant(LUA_TNIL, 2) |
201 | 190 | ||
202 | /* Special "value" to signal that a fast get is accessing a non-table */ | 191 | /* Special variant to signal that a fast get is accessing a non-table */ |
203 | #define LUA_VNOTABLE makevariant(LUA_TNIL, 3) | 192 | #define LUA_VNOTABLE makevariant(LUA_TNIL, 3) |
204 | |||
205 | #define setnotableV(obj) setttV_(obj, LUA_VNOTABLE) | ||
206 | 193 | ||
207 | 194 | ||
208 | /* macro to test for (any kind of) nil */ | 195 | /* macro to test for (any kind of) nil */ |
209 | #define ttisnil(v) checktype((v), LUA_TNIL) | 196 | #define ttisnil(v) checktype((v), LUA_TNIL) |
210 | #define ttisnilV(v) checktypeV((v), LUA_TNIL) | ||
211 | 197 | ||
198 | /* | ||
199 | ** Macro to test the result of a table access. Formally, it should | ||
200 | ** distinguish between LUA_VEMPTY/LUA_VABSTKEY/LUA_VNOTABLE and | ||
201 | ** other tags. As currently nil is equivalent to LUA_VEMPTY, it is | ||
202 | ** simpler to just test whether the value is nil. | ||
203 | */ | ||
212 | #define tagisempty(tag) (novariant(tag) == LUA_TNIL) | 204 | #define tagisempty(tag) (novariant(tag) == LUA_TNIL) |
213 | 205 | ||
214 | 206 | ||
@@ -234,7 +226,6 @@ typedef union { | |||
234 | ** be accepted as empty.) | 226 | ** be accepted as empty.) |
235 | */ | 227 | */ |
236 | #define isempty(v) ttisnil(v) | 228 | #define isempty(v) ttisnil(v) |
237 | #define isemptyV(v) checktypeV((v), LUA_TNIL) | ||
238 | 229 | ||
239 | 230 | ||
240 | /* macro defining a value corresponding to an absent key */ | 231 | /* macro defining a value corresponding to an absent key */ |
@@ -346,7 +337,6 @@ typedef struct GCObject { | |||
346 | #define ttisnumber(o) checktype((o), LUA_TNUMBER) | 337 | #define ttisnumber(o) checktype((o), LUA_TNUMBER) |
347 | #define ttisfloat(o) checktag((o), LUA_VNUMFLT) | 338 | #define ttisfloat(o) checktag((o), LUA_VNUMFLT) |
348 | #define ttisinteger(o) checktag((o), LUA_VNUMINT) | 339 | #define ttisinteger(o) checktag((o), LUA_VNUMINT) |
349 | #define ttisintegerV(o) checktagV((o), LUA_VNUMINT) | ||
350 | 340 | ||
351 | #define nvalue(o) check_exp(ttisnumber(o), \ | 341 | #define nvalue(o) check_exp(ttisnumber(o), \ |
352 | (ttisinteger(o) ? cast_num(ivalue(o)) : fltvalue(o))) | 342 | (ttisinteger(o) ? cast_num(ivalue(o)) : fltvalue(o))) |
@@ -904,14 +904,23 @@ static int hashkeyisempty (Table *t, lua_Integer key) { | |||
904 | } | 904 | } |
905 | 905 | ||
906 | 906 | ||
907 | TValue luaH_getint (Table *t, lua_Integer key) { | 907 | static int finishnodeget (const TValue *val, TValue *res) { |
908 | if (!ttisnil(val)) { | ||
909 | setobj(((lua_State*)NULL), res, val); | ||
910 | } | ||
911 | return ttypetag(val); | ||
912 | } | ||
913 | |||
914 | |||
915 | int luaH_getint (Table *t, lua_Integer key, TValue *res) { | ||
908 | if (keyinarray(t, key)) { | 916 | if (keyinarray(t, key)) { |
909 | TValue res; | 917 | int tag = *getArrTag(t, key - 1); |
910 | arr2objV(t, key, res); | 918 | if (!tagisempty(tag)) |
911 | return res; | 919 | farr2val(t, key, tag, res); |
920 | return tag; | ||
912 | } | 921 | } |
913 | else | 922 | else |
914 | return *getintfromhash(t, key); | 923 | return finishnodeget(getintfromhash(t, key), res); |
915 | } | 924 | } |
916 | 925 | ||
917 | 926 | ||
@@ -934,8 +943,8 @@ const TValue *luaH_Hgetshortstr (Table *t, TString *key) { | |||
934 | } | 943 | } |
935 | 944 | ||
936 | 945 | ||
937 | TValue luaH_getshortstr (Table *t, TString *key) { | 946 | int luaH_getshortstr (Table *t, TString *key, TValue *res) { |
938 | return *luaH_Hgetshortstr(t, key); | 947 | return finishnodeget(luaH_Hgetshortstr(t, key), res); |
939 | } | 948 | } |
940 | 949 | ||
941 | 950 | ||
@@ -950,8 +959,8 @@ static const TValue *Hgetstr (Table *t, TString *key) { | |||
950 | } | 959 | } |
951 | 960 | ||
952 | 961 | ||
953 | TValue luaH_getstr (Table *t, TString *key) { | 962 | int luaH_getstr (Table *t, TString *key, TValue *res) { |
954 | return *Hgetstr(t, key); | 963 | return finishnodeget(Hgetstr(t, key), res); |
955 | } | 964 | } |
956 | 965 | ||
957 | 966 | ||
@@ -967,31 +976,34 @@ TString *luaH_getstrkey (Table *t, TString *key) { | |||
967 | /* | 976 | /* |
968 | ** main search function | 977 | ** main search function |
969 | */ | 978 | */ |
970 | TValue luaH_get (Table *t, const TValue *key) { | 979 | int luaH_get (Table *t, const TValue *key, TValue *res) { |
980 | const TValue *slot; | ||
971 | switch (ttypetag(key)) { | 981 | switch (ttypetag(key)) { |
972 | case LUA_VSHRSTR: | 982 | case LUA_VSHRSTR: |
973 | return *luaH_Hgetshortstr(t, tsvalue(key)); | 983 | slot = luaH_Hgetshortstr(t, tsvalue(key)); |
974 | break; | 984 | break; |
975 | case LUA_VNUMINT: | 985 | case LUA_VNUMINT: |
976 | return luaH_getint(t, ivalue(key)); | 986 | return luaH_getint(t, ivalue(key), res); |
977 | case LUA_VNIL: | 987 | case LUA_VNIL: |
978 | return absentkey; | 988 | slot = &absentkey; |
979 | break; | 989 | break; |
980 | case LUA_VNUMFLT: { | 990 | case LUA_VNUMFLT: { |
981 | lua_Integer k; | 991 | lua_Integer k; |
982 | if (luaV_flttointeger(fltvalue(key), &k, F2Ieq)) /* integral index? */ | 992 | if (luaV_flttointeger(fltvalue(key), &k, F2Ieq)) /* integral index? */ |
983 | return luaH_getint(t, k); /* use specialized version */ | 993 | return luaH_getint(t, k, res); /* use specialized version */ |
984 | /* else... */ | 994 | /* else... */ |
985 | } /* FALLTHROUGH */ | 995 | } /* FALLTHROUGH */ |
986 | default: | 996 | default: |
987 | return *getgeneric(t, key, 0); | 997 | slot = getgeneric(t, key, 0); |
998 | break; | ||
988 | } | 999 | } |
1000 | return finishnodeget(slot, res); | ||
989 | } | 1001 | } |
990 | 1002 | ||
991 | 1003 | ||
992 | static int finishnodeset (Table *t, const TValue *slot, TValue *val) { | 1004 | static int finishnodeset (Table *t, const TValue *slot, TValue *val) { |
993 | if (!ttisnil(slot)) { | 1005 | if (!ttisnil(slot)) { |
994 | setobj(cast(lua_State*, NULL), cast(TValue*, slot), val); | 1006 | setobj(((lua_State*)NULL), cast(TValue*, slot), val); |
995 | return HOK; /* success */ | 1007 | return HOK; /* success */ |
996 | } | 1008 | } |
997 | else if (isabstkey(slot)) | 1009 | else if (isabstkey(slot)) |
@@ -1005,7 +1017,7 @@ static int rawfinishnodeset (const TValue *slot, TValue *val) { | |||
1005 | if (isabstkey(slot)) | 1017 | if (isabstkey(slot)) |
1006 | return 0; /* no slot with that key */ | 1018 | return 0; /* no slot with that key */ |
1007 | else { | 1019 | else { |
1008 | setobj(cast(lua_State*, NULL), cast(TValue*, slot), val); | 1020 | setobj(((lua_State*)NULL), cast(TValue*, slot), val); |
1009 | return 1; /* success */ | 1021 | return 1; /* success */ |
1010 | } | 1022 | } |
1011 | } | 1023 | } |
@@ -46,11 +46,12 @@ | |||
46 | 46 | ||
47 | 47 | ||
48 | 48 | ||
49 | #define luaH_fastgeti(t,k,res,aux) \ | 49 | #define luaH_fastgeti(t,k,res,tag) \ |
50 | { Table *h = t; lua_Unsigned u = l_castS2U(k); \ | 50 | { Table *h = t; lua_Unsigned u = l_castS2U(k); \ |
51 | if ((u - 1u < h->alimit)) arr2objV(h,u,aux); \ | 51 | if ((u - 1u < h->alimit)) { \ |
52 | else aux = luaH_getint(h, u); \ | 52 | tag = *getArrTag(h,(u)-1u); \ |
53 | if (!isemptyV(aux)) setobjV(cast(lua_State*, NULL), res, aux); } | 53 | if (!tagisempty(tag)) { farr2val(h, u, tag, res); }} \ |
54 | else { tag = luaH_getint(h, u, res); }} | ||
54 | 55 | ||
55 | 56 | ||
56 | #define luaH_fastseti(t,k,val,hres) \ | 57 | #define luaH_fastseti(t,k,val,hres) \ |
@@ -69,6 +70,8 @@ | |||
69 | #define HFIRSTNODE 3 | 70 | #define HFIRSTNODE 3 |
70 | 71 | ||
71 | /* | 72 | /* |
73 | ** 'luaH_get*' operations set 'res', unless the value is absent, and | ||
74 | ** return the tag of the result, | ||
72 | ** The 'luaH_pset*' (pre-set) operations set the given value and return | 75 | ** The 'luaH_pset*' (pre-set) operations set the given value and return |
73 | ** HOK, unless the original value is absent. In that case, if the key | 76 | ** HOK, unless the original value is absent. In that case, if the key |
74 | ** is really absent, they return HNOTFOUND. Otherwise, if there is a | 77 | ** is really absent, they return HNOTFOUND. Otherwise, if there is a |
@@ -85,7 +88,8 @@ | |||
85 | /* | 88 | /* |
86 | ** The array part of a table is represented by an array of cells. | 89 | ** The array part of a table is represented by an array of cells. |
87 | ** Each cell is composed of NM tags followed by NM values, so that | 90 | ** Each cell is composed of NM tags followed by NM values, so that |
88 | ** no space is wasted in padding. | 91 | ** no space is wasted in padding. The last cell may be incomplete, |
92 | ** that is, it may have fewer than NM values. | ||
89 | */ | 93 | */ |
90 | #define NM cast_uint(sizeof(Value)) | 94 | #define NM cast_uint(sizeof(Value)) |
91 | 95 | ||
@@ -105,10 +109,8 @@ struct ArrayCell { | |||
105 | /* | 109 | /* |
106 | ** Move TValues to/from arrays, using Lua indices | 110 | ** Move TValues to/from arrays, using Lua indices |
107 | */ | 111 | */ |
108 | #define arr2objV(h,k,val) \ | 112 | #define arr2obj(h,k,val) \ |
109 | ((val).tt_ = *getArrTag(h,(k)-1u), (val).value_ = *getArrVal(h,(k)-1u)) | 113 | ((val)->tt_ = *getArrTag(h,(k)-1u), (val)->value_ = *getArrVal(h,(k)-1u)) |
110 | |||
111 | #define arr2obj(h,k,val) arr2objV(h,k,*(val)) | ||
112 | 114 | ||
113 | #define obj2arr(h,k,val) \ | 115 | #define obj2arr(h,k,val) \ |
114 | (*getArrTag(h,(k)-1u) = (val)->tt_, *getArrVal(h,(k)-1u) = (val)->value_) | 116 | (*getArrTag(h,(k)-1u) = (val)->tt_, *getArrVal(h,(k)-1u) = (val)->value_) |
@@ -126,11 +128,12 @@ struct ArrayCell { | |||
126 | (*tag = (val)->tt_, *getArrVal(h,(k)-1u) = (val)->value_) | 128 | (*tag = (val)->tt_, *getArrVal(h,(k)-1u) = (val)->value_) |
127 | 129 | ||
128 | 130 | ||
129 | LUAI_FUNC TValue luaH_get (Table *t, const TValue *key); | 131 | LUAI_FUNC int luaH_get (Table *t, const TValue *key, TValue *res); |
130 | LUAI_FUNC TValue luaH_getshortstr (Table *t, TString *key); | 132 | LUAI_FUNC int luaH_getshortstr (Table *t, TString *key, TValue *res); |
131 | LUAI_FUNC TValue luaH_getstr (Table *t, TString *key); | 133 | LUAI_FUNC int luaH_getstr (Table *t, TString *key, TValue *res); |
132 | LUAI_FUNC TValue luaH_getint (Table *t, lua_Integer key); | 134 | LUAI_FUNC int luaH_getint (Table *t, lua_Integer key, TValue *res); |
133 | 135 | ||
136 | /* Special get for metamethods */ | ||
134 | LUAI_FUNC const TValue *luaH_Hgetshortstr (Table *t, TString *key); | 137 | LUAI_FUNC const TValue *luaH_Hgetshortstr (Table *t, TString *key); |
135 | 138 | ||
136 | LUAI_FUNC TString *luaH_getstrkey (Table *t, TString *key); | 139 | LUAI_FUNC TString *luaH_getstrkey (Table *t, TString *key); |
@@ -1538,7 +1538,8 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) { | |||
1538 | } | 1538 | } |
1539 | else if EQ("getfield") { | 1539 | else if EQ("getfield") { |
1540 | int t = getindex; | 1540 | int t = getindex; |
1541 | lua_getfield(L1, t, getstring); | 1541 | int tp = lua_getfield(L1, t, getstring); |
1542 | lua_assert(tp == lua_type(L1, -1)); | ||
1542 | } | 1543 | } |
1543 | else if EQ("getglobal") { | 1544 | else if EQ("getglobal") { |
1544 | lua_getglobal(L1, getstring); | 1545 | lua_getglobal(L1, getstring); |
@@ -1548,7 +1549,8 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) { | |||
1548 | lua_pushnil(L1); | 1549 | lua_pushnil(L1); |
1549 | } | 1550 | } |
1550 | else if EQ("gettable") { | 1551 | else if EQ("gettable") { |
1551 | lua_gettable(L1, getindex); | 1552 | int tp = lua_gettable(L1, getindex); |
1553 | lua_assert(tp == lua_type(L1, -1)); | ||
1552 | } | 1554 | } |
1553 | else if EQ("gettop") { | 1555 | else if EQ("gettop") { |
1554 | lua_pushinteger(L1, lua_gettop(L1)); | 1556 | lua_pushinteger(L1, lua_gettop(L1)); |
@@ -149,7 +149,8 @@ static void loadString (LoadState *S, Proto *p, TString **sl) { | |||
149 | } | 149 | } |
150 | else if (size == 1) { /* previously saved string? */ | 150 | else if (size == 1) { /* previously saved string? */ |
151 | lua_Integer idx = cast(lua_Integer, loadSize(S)); /* get its index */ | 151 | lua_Integer idx = cast(lua_Integer, loadSize(S)); /* get its index */ |
152 | TValue stv = luaH_getint(S->h, idx); /* get its value */ | 152 | TValue stv; |
153 | luaH_getint(S->h, idx, &stv); /* get its value */ | ||
153 | *sl = ts = tsvalue(&stv); | 154 | *sl = ts = tsvalue(&stv); |
154 | luaC_objbarrier(L, p, ts); | 155 | luaC_objbarrier(L, p, ts); |
155 | return; /* do not save it again */ | 156 | return; /* do not save it again */ |
@@ -285,13 +285,12 @@ static int floatforloop (StkId ra) { | |||
285 | 285 | ||
286 | 286 | ||
287 | /* | 287 | /* |
288 | ** Finish the table access 'val = t[key]'. | 288 | ** Finish the table access 'val = t[key]' and return the tag of the result. |
289 | */ | 289 | */ |
290 | void luaV_finishget_ (lua_State *L, const TValue *t, TValue *key, StkId val, | 290 | int luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, |
291 | int tag) { | 291 | int tag) { |
292 | int loop; /* counter to avoid infinite loops */ | 292 | int loop; /* counter to avoid infinite loops */ |
293 | const TValue *tm; /* metamethod */ | 293 | const TValue *tm; /* metamethod */ |
294 | TValue aux; | ||
295 | for (loop = 0; loop < MAXTAGLOOP; loop++) { | 294 | for (loop = 0; loop < MAXTAGLOOP; loop++) { |
296 | if (tag == LUA_VNOTABLE) { /* 't' is not a table? */ | 295 | if (tag == LUA_VNOTABLE) { /* 't' is not a table? */ |
297 | lua_assert(!ttistable(t)); | 296 | lua_assert(!ttistable(t)); |
@@ -304,22 +303,22 @@ void luaV_finishget_ (lua_State *L, const TValue *t, TValue *key, StkId val, | |||
304 | tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */ | 303 | tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */ |
305 | if (tm == NULL) { /* no metamethod? */ | 304 | if (tm == NULL) { /* no metamethod? */ |
306 | setnilvalue(s2v(val)); /* result is nil */ | 305 | setnilvalue(s2v(val)); /* result is nil */ |
307 | return; | 306 | return LUA_VNIL; |
308 | } | 307 | } |
309 | /* else will try the metamethod */ | 308 | /* else will try the metamethod */ |
310 | } | 309 | } |
311 | if (ttisfunction(tm)) { /* is metamethod a function? */ | 310 | if (ttisfunction(tm)) { /* is metamethod a function? */ |
312 | luaT_callTMres(L, tm, t, key, val); /* call it */ | 311 | luaT_callTMres(L, tm, t, key, val); /* call it */ |
313 | return; | 312 | return ttypetag(s2v(val)); |
314 | } | 313 | } |
315 | t = tm; /* else try to access 'tm[key]' */ | 314 | t = tm; /* else try to access 'tm[key]' */ |
316 | luaV_fastget(t, key, s2v(val), luaH_get, aux); | 315 | luaV_fastget(t, key, s2v(val), luaH_get, tag); |
317 | if (!isemptyV(aux)) | 316 | if (!tagisempty(tag)) |
318 | return; /* done */ | 317 | return tag; /* done */ |
319 | /* else repeat (tail call 'luaV_finishget') */ | 318 | /* else repeat (tail call 'luaV_finishget') */ |
320 | tag = ttypetagV(aux); | ||
321 | } | 319 | } |
322 | luaG_runerror(L, "'__index' chain too long; possible loop"); | 320 | luaG_runerror(L, "'__index' chain too long; possible loop"); |
321 | return 0; /* to avoid warnings */ | ||
323 | } | 322 | } |
324 | 323 | ||
325 | 324 | ||
@@ -1247,36 +1246,36 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1247 | TValue *upval = cl->upvals[GETARG_B(i)]->v.p; | 1246 | TValue *upval = cl->upvals[GETARG_B(i)]->v.p; |
1248 | TValue *rc = KC(i); | 1247 | TValue *rc = KC(i); |
1249 | TString *key = tsvalue(rc); /* key must be a short string */ | 1248 | TString *key = tsvalue(rc); /* key must be a short string */ |
1250 | TValue aux; | 1249 | int tag; |
1251 | luaV_fastget(upval, key, s2v(ra), luaH_getshortstr, aux); | 1250 | luaV_fastget(upval, key, s2v(ra), luaH_getshortstr, tag); |
1252 | if (isemptyV(aux)) | 1251 | if (tagisempty(tag)) |
1253 | Protect(luaV_finishget(L, upval, rc, ra, aux)); | 1252 | Protect(luaV_finishget(L, upval, rc, ra, tag)); |
1254 | vmbreak; | 1253 | vmbreak; |
1255 | } | 1254 | } |
1256 | vmcase(OP_GETTABLE) { | 1255 | vmcase(OP_GETTABLE) { |
1257 | StkId ra = RA(i); | 1256 | StkId ra = RA(i); |
1258 | TValue *rb = vRB(i); | 1257 | TValue *rb = vRB(i); |
1259 | TValue *rc = vRC(i); | 1258 | TValue *rc = vRC(i); |
1260 | TValue aux; | 1259 | int tag; |
1261 | if (ttisinteger(rc)) { /* fast track for integers? */ | 1260 | if (ttisinteger(rc)) { /* fast track for integers? */ |
1262 | luaV_fastgeti(rb, ivalue(rc), s2v(ra), aux); | 1261 | luaV_fastgeti(rb, ivalue(rc), s2v(ra), tag); |
1263 | } | 1262 | } |
1264 | else | 1263 | else |
1265 | luaV_fastget(rb, rc, s2v(ra), luaH_get, aux); | 1264 | luaV_fastget(rb, rc, s2v(ra), luaH_get, tag); |
1266 | if (isemptyV(aux)) /* fast track for integers? */ | 1265 | if (tagisempty(tag)) |
1267 | Protect(luaV_finishget(L, rb, rc, ra, aux)); | 1266 | Protect(luaV_finishget(L, rb, rc, ra, tag)); |
1268 | vmbreak; | 1267 | vmbreak; |
1269 | } | 1268 | } |
1270 | vmcase(OP_GETI) { | 1269 | vmcase(OP_GETI) { |
1271 | StkId ra = RA(i); | 1270 | StkId ra = RA(i); |
1272 | TValue *rb = vRB(i); | 1271 | TValue *rb = vRB(i); |
1273 | int c = GETARG_C(i); | 1272 | int c = GETARG_C(i); |
1274 | TValue aux; | 1273 | int tag; |
1275 | luaV_fastgeti(rb, c, s2v(ra), aux); | 1274 | luaV_fastgeti(rb, c, s2v(ra), tag); |
1276 | if (isemptyV(aux)) { | 1275 | if (tagisempty(tag)) { |
1277 | TValue key; | 1276 | TValue key; |
1278 | setivalue(&key, c); | 1277 | setivalue(&key, c); |
1279 | Protect(luaV_finishget(L, rb, &key, ra, aux)); | 1278 | Protect(luaV_finishget(L, rb, &key, ra, tag)); |
1280 | } | 1279 | } |
1281 | vmbreak; | 1280 | vmbreak; |
1282 | } | 1281 | } |
@@ -1285,10 +1284,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1285 | TValue *rb = vRB(i); | 1284 | TValue *rb = vRB(i); |
1286 | TValue *rc = KC(i); | 1285 | TValue *rc = KC(i); |
1287 | TString *key = tsvalue(rc); /* key must be a short string */ | 1286 | TString *key = tsvalue(rc); /* key must be a short string */ |
1288 | TValue aux; | 1287 | int tag; |
1289 | luaV_fastget(rb, key, s2v(ra), luaH_getshortstr, aux); | 1288 | luaV_fastget(rb, key, s2v(ra), luaH_getshortstr, tag); |
1290 | if (isemptyV(aux)) | 1289 | if (tagisempty(tag)) |
1291 | Protect(luaV_finishget(L, rb, rc, ra, aux)); | 1290 | Protect(luaV_finishget(L, rb, rc, ra, tag)); |
1292 | vmbreak; | 1291 | vmbreak; |
1293 | } | 1292 | } |
1294 | vmcase(OP_SETTABUP) { | 1293 | vmcase(OP_SETTABUP) { |
@@ -1370,14 +1369,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1370 | } | 1369 | } |
1371 | vmcase(OP_SELF) { | 1370 | vmcase(OP_SELF) { |
1372 | StkId ra = RA(i); | 1371 | StkId ra = RA(i); |
1373 | TValue aux; | 1372 | int tag; |
1374 | TValue *rb = vRB(i); | 1373 | TValue *rb = vRB(i); |
1375 | TValue *rc = RKC(i); | 1374 | TValue *rc = RKC(i); |
1376 | TString *key = tsvalue(rc); /* key must be a string */ | 1375 | TString *key = tsvalue(rc); /* key must be a string */ |
1377 | setobj2s(L, ra + 1, rb); | 1376 | setobj2s(L, ra + 1, rb); |
1378 | luaV_fastget(rb, key, s2v(ra), luaH_getstr, aux); | 1377 | luaV_fastget(rb, key, s2v(ra), luaH_getstr, tag); |
1379 | if (isemptyV(aux)) | 1378 | if (tagisempty(tag)) |
1380 | Protect(luaV_finishget(L, rb, rc, ra, aux)); | 1379 | Protect(luaV_finishget(L, rb, rc, ra, tag)); |
1381 | vmbreak; | 1380 | vmbreak; |
1382 | } | 1381 | } |
1383 | vmcase(OP_ADDI) { | 1382 | vmcase(OP_ADDI) { |
@@ -78,19 +78,17 @@ 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, tag) \ |
82 | {if (!ttistable(t)) setnotableV(aux); \ | 82 | (tag = (!ttistable(t) ? LUA_VNOTABLE : f(hvalue(t), k, res))) |
83 | else { aux = f(hvalue(t), k); \ | ||
84 | if (!isemptyV(aux)) { setobjV(cast(lua_State*, NULL), res, aux); } } } | ||
85 | 83 | ||
86 | 84 | ||
87 | /* | 85 | /* |
88 | ** Special case of 'luaV_fastget' for integers, inlining the fast case | 86 | ** Special case of 'luaV_fastget' for integers, inlining the fast case |
89 | ** of 'luaH_getint'. | 87 | ** of 'luaH_getint'. |
90 | */ | 88 | */ |
91 | #define luaV_fastgeti(t,k,res,aux) \ | 89 | #define luaV_fastgeti(t,k,res,tag) \ |
92 | { if (!ttistable(t)) setnotableV(aux); \ | 90 | if (!ttistable(t)) tag = LUA_VNOTABLE; \ |
93 | else { luaH_fastgeti(hvalue(t), k, res, aux); } } | 91 | else { luaH_fastgeti(hvalue(t), k, res, tag); } |
94 | 92 | ||
95 | 93 | ||
96 | #define luaV_fastset(t,k,val,hres,f) \ | 94 | #define luaV_fastset(t,k,val,hres,f) \ |
@@ -122,10 +120,8 @@ LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, F2Imod mode); | |||
122 | LUAI_FUNC int luaV_tointegerns (const TValue *obj, lua_Integer *p, | 120 | LUAI_FUNC int luaV_tointegerns (const TValue *obj, lua_Integer *p, |
123 | F2Imod mode); | 121 | F2Imod mode); |
124 | LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode); | 122 | LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode); |
125 | #define luaV_finishget(L,t,key,val,aux) \ | 123 | LUAI_FUNC int luaV_finishget (lua_State *L, const TValue *t, TValue *key, |
126 | luaV_finishget_(L,t,key,val,ttypetagV(aux)) | 124 | StkId val, int tag); |
127 | LUAI_FUNC void luaV_finishget_ (lua_State *L, const TValue *t, TValue *key, | ||
128 | StkId val, int tag); | ||
129 | LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, | 125 | LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, |
130 | TValue *val, int aux); | 126 | TValue *val, int aux); |
131 | LUAI_FUNC void luaV_finishOp (lua_State *L); | 127 | LUAI_FUNC void luaV_finishOp (lua_State *L); |