aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lapi.c69
-rw-r--r--lcode.c5
-rw-r--r--ldump.c5
-rw-r--r--lobject.h26
-rw-r--r--ltable.c48
-rw-r--r--ltable.h29
-rw-r--r--ltests.c6
-rw-r--r--lundump.c3
-rw-r--r--lvm.c61
-rw-r--r--lvm.h18
10 files changed, 138 insertions, 132 deletions
diff --git a/lapi.c b/lapi.c
index a6ef5663..2b14c15e 100644
--- a/lapi.c
+++ b/lapi.c
@@ -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
668static int auxgetstr (lua_State *L, const TValue *t, const char *k) { 668static 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
685static TValue getGlobalTable (lua_State *L) { 685static 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
691LUA_API int lua_getglobal (lua_State *L, const char *name) { 693LUA_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, &gt);
695 return auxgetstr(L, &gt, name); 697 return auxgetstr(L, &gt, name);
696} 698}
697 699
698 700
699LUA_API int lua_gettable (lua_State *L, int idx) { 701LUA_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
719LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { 721LUA_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
736l_sinline int finishrawget (lua_State *L, TValue res) { 738static 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
754LUA_API int lua_rawget (lua_State *L, int idx) { 754LUA_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
766LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { 766LUA_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) {
872LUA_API void lua_setglobal (lua_State *L, const char *name) { 872LUA_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, &gt);
876 auxsetstr(L, &gt, name); 876 auxsetstr(L, &gt, 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, &gt);
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, &gt); 1128 setobj(L, f->upvals[0]->v.p, &gt);
1128 luaC_barrier(L, f->upvals[0], &gt); 1129 luaC_barrier(L, f->upvals[0], &gt);
@@ -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}
diff --git a/lcode.c b/lcode.c
index 18bf9413..2c57fdaf 100644
--- a/lcode.c
+++ b/lcode.c
@@ -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*/
543static int addk (FuncState *fs, TValue *key, TValue *v) { 543static 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) &&
diff --git a/ldump.c b/ldump.c
index 34b63a8a..ca708a41 100644
--- a/ldump.c
+++ b/ldump.c
@@ -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 }
diff --git a/lobject.h b/lobject.h
index 69fa6260..b42539cf 100644
--- a/lobject.h
+++ b/lobject.h
@@ -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)))
diff --git a/ltable.c b/ltable.c
index f675f39b..f62f36bc 100644
--- a/ltable.c
+++ b/ltable.c
@@ -904,14 +904,23 @@ static int hashkeyisempty (Table *t, lua_Integer key) {
904} 904}
905 905
906 906
907TValue luaH_getint (Table *t, lua_Integer key) { 907static 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
915int 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
937TValue luaH_getshortstr (Table *t, TString *key) { 946int 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
953TValue luaH_getstr (Table *t, TString *key) { 962int 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*/
970TValue luaH_get (Table *t, const TValue *key) { 979int 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
992static int finishnodeset (Table *t, const TValue *slot, TValue *val) { 1004static 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}
diff --git a/ltable.h b/ltable.h
index 10dae5c7..1f2ea3ee 100644
--- a/ltable.h
+++ b/ltable.h
@@ -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
129LUAI_FUNC TValue luaH_get (Table *t, const TValue *key); 131LUAI_FUNC int luaH_get (Table *t, const TValue *key, TValue *res);
130LUAI_FUNC TValue luaH_getshortstr (Table *t, TString *key); 132LUAI_FUNC int luaH_getshortstr (Table *t, TString *key, TValue *res);
131LUAI_FUNC TValue luaH_getstr (Table *t, TString *key); 133LUAI_FUNC int luaH_getstr (Table *t, TString *key, TValue *res);
132LUAI_FUNC TValue luaH_getint (Table *t, lua_Integer key); 134LUAI_FUNC int luaH_getint (Table *t, lua_Integer key, TValue *res);
133 135
136/* Special get for metamethods */
134LUAI_FUNC const TValue *luaH_Hgetshortstr (Table *t, TString *key); 137LUAI_FUNC const TValue *luaH_Hgetshortstr (Table *t, TString *key);
135 138
136LUAI_FUNC TString *luaH_getstrkey (Table *t, TString *key); 139LUAI_FUNC TString *luaH_getstrkey (Table *t, TString *key);
diff --git a/ltests.c b/ltests.c
index 59df7cad..1a34870e 100644
--- a/ltests.c
+++ b/ltests.c
@@ -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));
diff --git a/lundump.c b/lundump.c
index 593a4951..51d5dc66 100644
--- a/lundump.c
+++ b/lundump.c
@@ -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 */
diff --git a/lvm.c b/lvm.c
index a251f423..cfa9961b 100644
--- a/lvm.c
+++ b/lvm.c
@@ -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*/
290void luaV_finishget_ (lua_State *L, const TValue *t, TValue *key, StkId val, 290int 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) {
diff --git a/lvm.h b/lvm.h
index 3b11e789..a11db83c 100644
--- a/lvm.h
+++ b/lvm.h
@@ -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);
122LUAI_FUNC int luaV_tointegerns (const TValue *obj, lua_Integer *p, 120LUAI_FUNC int luaV_tointegerns (const TValue *obj, lua_Integer *p,
123 F2Imod mode); 121 F2Imod mode);
124LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode); 122LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode);
125#define luaV_finishget(L,t,key,val,aux) \ 123LUAI_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);
127LUAI_FUNC void luaV_finishget_ (lua_State *L, const TValue *t, TValue *key,
128 StkId val, int tag);
129LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, 125LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
130 TValue *val, int aux); 126 TValue *val, int aux);
131LUAI_FUNC void luaV_finishOp (lua_State *L); 127LUAI_FUNC void luaV_finishOp (lua_State *L);