aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lapi.c110
-rw-r--r--lcode.c8
-rw-r--r--lgc.c25
-rw-r--r--llex.c10
-rw-r--r--lobject.h7
-rw-r--r--lstate.c7
-rw-r--r--ltable.c328
-rw-r--r--ltable.h99
-rw-r--r--ltests.c10
-rw-r--r--ltm.c11
-rw-r--r--lvm.c135
-rw-r--r--lvm.h51
12 files changed, 528 insertions, 273 deletions
diff --git a/lapi.c b/lapi.c
index 767fa55e..34b335fd 100644
--- a/lapi.c
+++ b/lapi.c
@@ -637,50 +637,44 @@ LUA_API int lua_pushthread (lua_State *L) {
637 637
638 638
639l_sinline int auxgetstr (lua_State *L, const TValue *t, const char *k) { 639l_sinline int auxgetstr (lua_State *L, const TValue *t, const char *k) {
640 const TValue *slot; 640 int hres;
641 TString *str = luaS_new(L, k); 641 TString *str = luaS_new(L, k);
642 if (luaV_fastget(L, t, str, slot, luaH_getstr)) { 642 luaV_fastget(t, str, s2v(L->top.p), luaH_getstr, hres);
643 setobj2s(L, L->top.p, slot); 643 if (hres == HOK) {
644 api_incr_top(L); 644 api_incr_top(L);
645 } 645 }
646 else { 646 else {
647 setsvalue2s(L, L->top.p, str); 647 setsvalue2s(L, L->top.p, str);
648 api_incr_top(L); 648 api_incr_top(L);
649 luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, slot); 649 luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, hres);
650 } 650 }
651 lua_unlock(L); 651 lua_unlock(L);
652 return ttype(s2v(L->top.p - 1)); 652 return ttype(s2v(L->top.p - 1));
653} 653}
654 654
655 655
656/* 656static void getGlobalTable (lua_State *L, TValue *gt) {
657** Get the global table in the registry. Since all predefined 657 Table *registry = hvalue(&G(L)->l_registry);
658** indices in the registry were inserted right when the registry 658 luaH_getint(registry, LUA_RIDX_GLOBALS, gt);
659** was created and never removed, they must always be in the array 659}
660** part of the registry.
661*/
662#define getGtable(L) \
663 (&hvalue(&G(L)->l_registry)->array[LUA_RIDX_GLOBALS - 1])
664 660
665 661
666LUA_API int lua_getglobal (lua_State *L, const char *name) { 662LUA_API int lua_getglobal (lua_State *L, const char *name) {
667 const TValue *G; 663 TValue gt;
668 lua_lock(L); 664 lua_lock(L);
669 G = getGtable(L); 665 getGlobalTable(L, &gt);
670 return auxgetstr(L, G, name); 666 return auxgetstr(L, &gt, name);
671} 667}
672 668
673 669
674LUA_API int lua_gettable (lua_State *L, int idx) { 670LUA_API int lua_gettable (lua_State *L, int idx) {
675 const TValue *slot; 671 int hres;
676 TValue *t; 672 TValue *t;
677 lua_lock(L); 673 lua_lock(L);
678 t = index2value(L, idx); 674 t = index2value(L, idx);
679 if (luaV_fastget(L, t, s2v(L->top.p - 1), slot, luaH_get)) { 675 luaV_fastget(t, s2v(L->top.p - 1), s2v(L->top.p - 1), luaH_get, hres);
680 setobj2s(L, L->top.p - 1, slot); 676 if (hres != HOK)
681 } 677 luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, hres);
682 else
683 luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, slot);
684 lua_unlock(L); 678 lua_unlock(L);
685 return ttype(s2v(L->top.p - 1)); 679 return ttype(s2v(L->top.p - 1));
686} 680}
@@ -694,16 +688,14 @@ LUA_API int lua_getfield (lua_State *L, int idx, const char *k) {
694 688
695LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { 689LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
696 TValue *t; 690 TValue *t;
697 const TValue *slot; 691 int hres;
698 lua_lock(L); 692 lua_lock(L);
699 t = index2value(L, idx); 693 t = index2value(L, idx);
700 if (luaV_fastgeti(L, t, n, slot)) { 694 luaV_fastgeti(t, n, s2v(L->top.p), hres);
701 setobj2s(L, L->top.p, slot); 695 if (hres != HOK) {
702 } 696 TValue key;
703 else { 697 setivalue(&key, n);
704 TValue aux; 698 luaV_finishget(L, t, &key, L->top.p, hres);
705 setivalue(&aux, n);
706 luaV_finishget(L, t, &aux, L->top.p, slot);
707 } 699 }
708 api_incr_top(L); 700 api_incr_top(L);
709 lua_unlock(L); 701 lua_unlock(L);
@@ -711,11 +703,9 @@ LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
711} 703}
712 704
713 705
714l_sinline int finishrawget (lua_State *L, const TValue *val) { 706l_sinline int finishrawget (lua_State *L, int hres) {
715 if (isempty(val)) /* avoid copying empty items to the stack */ 707 if (hres != HOK) /* avoid copying empty items to the stack */
716 setnilvalue(s2v(L->top.p)); 708 setnilvalue(s2v(L->top.p));
717 else
718 setobj2s(L, L->top.p, val);
719 api_incr_top(L); 709 api_incr_top(L);
720 lua_unlock(L); 710 lua_unlock(L);
721 return ttype(s2v(L->top.p - 1)); 711 return ttype(s2v(L->top.p - 1));
@@ -731,13 +721,13 @@ static Table *gettable (lua_State *L, int idx) {
731 721
732LUA_API int lua_rawget (lua_State *L, int idx) { 722LUA_API int lua_rawget (lua_State *L, int idx) {
733 Table *t; 723 Table *t;
734 const TValue *val; 724 int hres;
735 lua_lock(L); 725 lua_lock(L);
736 api_checknelems(L, 1); 726 api_checknelems(L, 1);
737 t = gettable(L, idx); 727 t = gettable(L, idx);
738 val = luaH_get(t, s2v(L->top.p - 1)); 728 hres = luaH_get(t, s2v(L->top.p - 1), s2v(L->top.p - 1));
739 L->top.p--; /* remove key */ 729 L->top.p--; /* remove key */
740 return finishrawget(L, val); 730 return finishrawget(L, hres);
741} 731}
742 732
743 733
@@ -745,7 +735,7 @@ LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) {
745 Table *t; 735 Table *t;
746 lua_lock(L); 736 lua_lock(L);
747 t = gettable(L, idx); 737 t = gettable(L, idx);
748 return finishrawget(L, luaH_getint(t, n)); 738 return finishrawget(L, luaH_getint(t, n, s2v(L->top.p)));
749} 739}
750 740
751 741
@@ -755,7 +745,7 @@ LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) {
755 lua_lock(L); 745 lua_lock(L);
756 t = gettable(L, idx); 746 t = gettable(L, idx);
757 setpvalue(&k, cast_voidp(p)); 747 setpvalue(&k, cast_voidp(p));
758 return finishrawget(L, luaH_get(t, &k)); 748 return finishrawget(L, luaH_get(t, &k, s2v(L->top.p)));
759} 749}
760 750
761 751
@@ -827,17 +817,18 @@ LUA_API int lua_getiuservalue (lua_State *L, int idx, int n) {
827** t[k] = value at the top of the stack (where 'k' is a string) 817** t[k] = value at the top of the stack (where 'k' is a string)
828*/ 818*/
829static void auxsetstr (lua_State *L, const TValue *t, const char *k) { 819static void auxsetstr (lua_State *L, const TValue *t, const char *k) {
830 const TValue *slot; 820 int hres;
831 TString *str = luaS_new(L, k); 821 TString *str = luaS_new(L, k);
832 api_checknelems(L, 1); 822 api_checknelems(L, 1);
833 if (luaV_fastget(L, t, str, slot, luaH_getstr)) { 823 luaV_fastset(t, str, s2v(L->top.p - 1), hres, luaH_psetstr);
834 luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); 824 if (hres == HOK) {
825 luaV_finishfastset(L, t, s2v(L->top.p - 1));
835 L->top.p--; /* pop value */ 826 L->top.p--; /* pop value */
836 } 827 }
837 else { 828 else {
838 setsvalue2s(L, L->top.p, str); /* push 'str' (to make it a TValue) */ 829 setsvalue2s(L, L->top.p, str); /* push 'str' (to make it a TValue) */
839 api_incr_top(L); 830 api_incr_top(L);
840 luaV_finishset(L, t, s2v(L->top.p - 1), s2v(L->top.p - 2), slot); 831 luaV_finishset(L, t, s2v(L->top.p - 1), s2v(L->top.p - 2), hres);
841 L->top.p -= 2; /* pop value and key */ 832 L->top.p -= 2; /* pop value and key */
842 } 833 }
843 lua_unlock(L); /* lock done by caller */ 834 lua_unlock(L); /* lock done by caller */
@@ -845,24 +836,25 @@ static void auxsetstr (lua_State *L, const TValue *t, const char *k) {
845 836
846 837
847LUA_API void lua_setglobal (lua_State *L, const char *name) { 838LUA_API void lua_setglobal (lua_State *L, const char *name) {
848 const TValue *G; 839 TValue gt;
849 lua_lock(L); /* unlock done in 'auxsetstr' */ 840 lua_lock(L); /* unlock done in 'auxsetstr' */
850 G = getGtable(L); 841 getGlobalTable(L, &gt);
851 auxsetstr(L, G, name); 842 auxsetstr(L, &gt, name);
852} 843}
853 844
854 845
855LUA_API void lua_settable (lua_State *L, int idx) { 846LUA_API void lua_settable (lua_State *L, int idx) {
856 TValue *t; 847 TValue *t;
857 const TValue *slot; 848 int hres;
858 lua_lock(L); 849 lua_lock(L);
859 api_checknelems(L, 2); 850 api_checknelems(L, 2);
860 t = index2value(L, idx); 851 t = index2value(L, idx);
861 if (luaV_fastget(L, t, s2v(L->top.p - 2), slot, luaH_get)) { 852 luaV_fastset(t, s2v(L->top.p - 2), s2v(L->top.p - 1), hres, luaH_pset);
862 luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); 853 if (hres == HOK) {
854 luaV_finishfastset(L, t, s2v(L->top.p - 1));
863 } 855 }
864 else 856 else
865 luaV_finishset(L, t, s2v(L->top.p - 2), s2v(L->top.p - 1), slot); 857 luaV_finishset(L, t, s2v(L->top.p - 2), s2v(L->top.p - 1), hres);
866 L->top.p -= 2; /* pop index and value */ 858 L->top.p -= 2; /* pop index and value */
867 lua_unlock(L); 859 lua_unlock(L);
868} 860}
@@ -876,17 +868,18 @@ LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
876 868
877LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { 869LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) {
878 TValue *t; 870 TValue *t;
879 const TValue *slot; 871 int hres;
880 lua_lock(L); 872 lua_lock(L);
881 api_checknelems(L, 1); 873 api_checknelems(L, 1);
882 t = index2value(L, idx); 874 t = index2value(L, idx);
883 if (luaV_fastgeti(L, t, n, slot)) { 875 luaV_fastseti(t, n, s2v(L->top.p - 1), hres);
884 luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); 876 if (hres == HOK) {
877 luaV_finishfastset(L, t, s2v(L->top.p - 1));
885 } 878 }
886 else { 879 else {
887 TValue aux; 880 TValue temp;
888 setivalue(&aux, n); 881 setivalue(&temp, n);
889 luaV_finishset(L, t, &aux, s2v(L->top.p - 1), slot); 882 luaV_finishset(L, t, &temp, s2v(L->top.p - 1), hres);
890 } 883 }
891 L->top.p--; /* pop value */ 884 L->top.p--; /* pop value */
892 lua_unlock(L); 885 lua_unlock(L);
@@ -1096,10 +1089,11 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
1096 LClosure *f = clLvalue(s2v(L->top.p - 1)); /* get new function */ 1089 LClosure *f = clLvalue(s2v(L->top.p - 1)); /* get new function */
1097 if (f->nupvalues >= 1) { /* does it have an upvalue? */ 1090 if (f->nupvalues >= 1) { /* does it have an upvalue? */
1098 /* get global table from registry */ 1091 /* get global table from registry */
1099 const TValue *gt = getGtable(L); 1092 TValue gt;
1093 getGlobalTable(L, &gt);
1100 /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ 1094 /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
1101 setobj(L, f->upvals[0]->v.p, gt); 1095 setobj(L, f->upvals[0]->v.p, &gt);
1102 luaC_barrier(L, f->upvals[0], gt); 1096 luaC_barrier(L, f->upvals[0], &gt);
1103 } 1097 }
1104 } 1098 }
1105 lua_unlock(L); 1099 lua_unlock(L);
diff --git a/lcode.c b/lcode.c
index 914d8cd0..0d888822 100644
--- a/lcode.c
+++ b/lcode.c
@@ -544,10 +544,10 @@ static int addk (FuncState *fs, TValue *key, TValue *v) {
544 TValue val; 544 TValue val;
545 lua_State *L = fs->ls->L; 545 lua_State *L = fs->ls->L;
546 Proto *f = fs->f; 546 Proto *f = fs->f;
547 const TValue *idx = luaH_get(fs->ls->h, key); /* query scanner table */ 547 int aux = luaH_get(fs->ls->h, key, &val); /* query scanner table */
548 int k, oldsize; 548 int k, oldsize;
549 if (ttisinteger(idx)) { /* is there an index there? */ 549 if (aux == HOK && ttisinteger(&val)) { /* is there an index there? */
550 k = cast_int(ivalue(idx)); 550 k = cast_int(ivalue(&val));
551 /* correct value? (warning: must distinguish floats from integers!) */ 551 /* correct value? (warning: must distinguish floats from integers!) */
552 if (k < fs->nk && ttypetag(&f->k[k]) == ttypetag(v) && 552 if (k < fs->nk && ttypetag(&f->k[k]) == ttypetag(v) &&
553 luaV_rawequalobj(&f->k[k], v)) 553 luaV_rawequalobj(&f->k[k], v))
@@ -559,7 +559,7 @@ static int addk (FuncState *fs, TValue *key, TValue *v) {
559 /* numerical value does not need GC barrier; 559 /* numerical value does not need GC barrier;
560 table has no metatable, so it does not need to invalidate cache */ 560 table has no metatable, so it does not need to invalidate cache */
561 setivalue(&val, k); 561 setivalue(&val, k);
562 luaH_finishset(L, fs->ls->h, key, idx, &val); 562 luaH_set(L, fs->ls->h, key, &val);
563 luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); 563 luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants");
564 while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); 564 while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
565 setobj(L, &f->k[k], v); 565 setobj(L, &f->k[k], v);
diff --git a/lgc.c b/lgc.c
index 81682454..e4f8e396 100644
--- a/lgc.c
+++ b/lgc.c
@@ -73,6 +73,13 @@
73#define gcvalueN(o) (iscollectable(o) ? gcvalue(o) : NULL) 73#define gcvalueN(o) (iscollectable(o) ? gcvalue(o) : NULL)
74 74
75 75
76/*
77** Access to collectable objects in array part of tables
78*/
79#define gcvalarr(t,i) \
80 ((*getArrTag(t,i) & BIT_ISCOLLECTABLE) ? getArrVal(t,i)->gc : NULL)
81
82
76#define markvalue(g,o) { checkliveness(g->mainthread,o); \ 83#define markvalue(g,o) { checkliveness(g->mainthread,o); \
77 if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } 84 if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
78 85
@@ -477,9 +484,10 @@ static int traverseephemeron (global_State *g, Table *h, int inv) {
477 unsigned int nsize = sizenode(h); 484 unsigned int nsize = sizenode(h);
478 /* traverse array part */ 485 /* traverse array part */
479 for (i = 0; i < asize; i++) { 486 for (i = 0; i < asize; i++) {
480 if (valiswhite(&h->array[i])) { 487 GCObject *o = gcvalarr(h, i);
488 if (o != NULL && iswhite(o)) {
481 marked = 1; 489 marked = 1;
482 reallymarkobject(g, gcvalue(&h->array[i])); 490 reallymarkobject(g, o);
483 } 491 }
484 } 492 }
485 /* traverse hash part; if 'inv', traverse descending 493 /* traverse hash part; if 'inv', traverse descending
@@ -515,8 +523,11 @@ static void traversestrongtable (global_State *g, Table *h) {
515 Node *n, *limit = gnodelast(h); 523 Node *n, *limit = gnodelast(h);
516 unsigned int i; 524 unsigned int i;
517 unsigned int asize = luaH_realasize(h); 525 unsigned int asize = luaH_realasize(h);
518 for (i = 0; i < asize; i++) /* traverse array part */ 526 for (i = 0; i < asize; i++) { /* traverse array part */
519 markvalue(g, &h->array[i]); 527 GCObject *o = gcvalarr(h, i);
528 if (o != NULL && iswhite(o))
529 reallymarkobject(g, o);
530 }
520 for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ 531 for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */
521 if (isempty(gval(n))) /* entry is empty? */ 532 if (isempty(gval(n))) /* entry is empty? */
522 clearkey(n); /* clear its key */ 533 clearkey(n); /* clear its key */
@@ -741,9 +752,9 @@ static l_obj clearbyvalues (global_State *g, GCObject *l, GCObject *f) {
741 unsigned int i; 752 unsigned int i;
742 unsigned int asize = luaH_realasize(h); 753 unsigned int asize = luaH_realasize(h);
743 for (i = 0; i < asize; i++) { 754 for (i = 0; i < asize; i++) {
744 TValue *o = &h->array[i]; 755 GCObject *o = gcvalarr(h, i);
745 if (iscleared(g, gcvalueN(o))) /* value was collected? */ 756 if (iscleared(g, o)) /* value was collected? */
746 setempty(o); /* remove entry */ 757 *getArrTag(h, i) = LUA_VEMPTY; /* remove entry */
747 } 758 }
748 for (n = gnode(h, 0); n < limit; n++) { 759 for (n = gnode(h, 0); n < limit; n++) {
749 if (iscleared(g, gcvalueN(gval(n)))) /* unmarked value? */ 760 if (iscleared(g, gcvalueN(gval(n)))) /* unmarked value? */
diff --git a/llex.c b/llex.c
index 5fc39a5c..9f20d3c8 100644
--- a/llex.c
+++ b/llex.c
@@ -134,13 +134,13 @@ l_noret luaX_syntaxerror (LexState *ls, const char *msg) {
134TString *luaX_newstring (LexState *ls, const char *str, size_t l) { 134TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
135 lua_State *L = ls->L; 135 lua_State *L = ls->L;
136 TString *ts = luaS_newlstr(L, str, l); /* create new string */ 136 TString *ts = luaS_newlstr(L, str, l); /* create new string */
137 const TValue *o = luaH_getstr(ls->h, ts); 137 TString *oldts = luaH_getstrkey(ls->h, ts);
138 if (!ttisnil(o)) /* string already present? */ 138 if (oldts != NULL) /* string already present? */
139 ts = keystrval(nodefromval(o)); /* get saved copy */ 139 return oldts; /* use it */
140 else { /* not in use yet */ 140 else { /* create a new entry */
141 TValue *stv = s2v(L->top.p++); /* reserve stack space for string */ 141 TValue *stv = s2v(L->top.p++); /* reserve stack space for string */
142 setsvalue(L, stv, ts); /* temporarily anchor the string */ 142 setsvalue(L, stv, ts); /* temporarily anchor the string */
143 luaH_finishset(L, ls->h, stv, o, stv); /* t[string] = string */ 143 luaH_set(L, ls->h, stv, stv); /* t[string] = string */
144 /* table is not a metatable, so it does not need to invalidate cache */ 144 /* table is not a metatable, so it does not need to invalidate cache */
145 luaC_checkGC(L); 145 luaC_checkGC(L);
146 L->top.p--; /* remove string from stack */ 146 L->top.p--; /* remove string from stack */
diff --git a/lobject.h b/lobject.h
index 209a87fc..c6c43647 100644
--- a/lobject.h
+++ b/lobject.h
@@ -192,6 +192,8 @@ typedef union {
192/* macro to test for (any kind of) nil */ 192/* macro to test for (any kind of) nil */
193#define ttisnil(v) checktype((v), LUA_TNIL) 193#define ttisnil(v) checktype((v), LUA_TNIL)
194 194
195#define tagisempty(tag) (novariant(tag) == LUA_TNIL)
196
195 197
196/* macro to test for a standard nil */ 198/* macro to test for a standard nil */
197#define ttisstrictnil(o) checktag((o), LUA_VNIL) 199#define ttisstrictnil(o) checktag((o), LUA_VNIL)
@@ -749,12 +751,15 @@ typedef union Node {
749#define setnorealasize(t) ((t)->flags |= BITRAS) 751#define setnorealasize(t) ((t)->flags |= BITRAS)
750 752
751 753
754typedef union ArrayCell ArrayCell;
755
756
752typedef struct Table { 757typedef struct Table {
753 CommonHeader; 758 CommonHeader;
754 lu_byte flags; /* 1<<p means tagmethod(p) is not present */ 759 lu_byte flags; /* 1<<p means tagmethod(p) is not present */
755 lu_byte lsizenode; /* log2 of size of 'node' array */ 760 lu_byte lsizenode; /* log2 of size of 'node' array */
756 unsigned int alimit; /* "limit" of 'array' array */ 761 unsigned int alimit; /* "limit" of 'array' array */
757 TValue *array; /* array part */ 762 ArrayCell *array; /* array part */
758 Node *node; 763 Node *node;
759 struct Table *metatable; 764 struct Table *metatable;
760 GCObject *gclist; 765 GCObject *gclist;
diff --git a/lstate.c b/lstate.c
index 6f4c7e28..c01e53ed 100644
--- a/lstate.c
+++ b/lstate.c
@@ -184,13 +184,16 @@ static void freestack (lua_State *L) {
184*/ 184*/
185static void init_registry (lua_State *L, global_State *g) { 185static void init_registry (lua_State *L, global_State *g) {
186 /* create registry */ 186 /* create registry */
187 TValue aux;
187 Table *registry = luaH_new(L); 188 Table *registry = luaH_new(L);
188 sethvalue(L, &g->l_registry, registry); 189 sethvalue(L, &g->l_registry, registry);
189 luaH_resize(L, registry, LUA_RIDX_LAST, 0); 190 luaH_resize(L, registry, LUA_RIDX_LAST, 0);
190 /* registry[LUA_RIDX_MAINTHREAD] = L */ 191 /* registry[LUA_RIDX_MAINTHREAD] = L */
191 setthvalue(L, &registry->array[LUA_RIDX_MAINTHREAD - 1], L); 192 setthvalue(L, &aux, L);
193 luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &aux);
192 /* registry[LUA_RIDX_GLOBALS] = new table (table of globals) */ 194 /* registry[LUA_RIDX_GLOBALS] = new table (table of globals) */
193 sethvalue(L, &registry->array[LUA_RIDX_GLOBALS - 1], luaH_new(L)); 195 sethvalue(L, &aux, luaH_new(L));
196 luaH_setint(L, registry, LUA_RIDX_GLOBALS, &aux);
194} 197}
195 198
196 199
diff --git a/ltable.c b/ltable.c
index 103478fb..c9f66b3c 100644
--- a/ltable.c
+++ b/ltable.c
@@ -371,9 +371,10 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
371 unsigned int asize = luaH_realasize(t); 371 unsigned int asize = luaH_realasize(t);
372 unsigned int i = findindex(L, t, s2v(key), asize); /* find original key */ 372 unsigned int i = findindex(L, t, s2v(key), asize); /* find original key */
373 for (; i < asize; i++) { /* try first array part */ 373 for (; i < asize; i++) { /* try first array part */
374 if (!isempty(&t->array[i])) { /* a non-empty entry? */ 374 int tag = *getArrTag(t, i);
375 if (!tagisempty(tag)) { /* a non-empty entry? */
375 setivalue(s2v(key), i + 1); 376 setivalue(s2v(key), i + 1);
376 setobj2s(L, key + 1, &t->array[i]); 377 farr2val(t, i + 1, tag, s2v(key + 1));
377 return 1; 378 return 1;
378 } 379 }
379 } 380 }
@@ -403,6 +404,41 @@ static void freehash (lua_State *L, Table *t) {
403 404
404 405
405/* 406/*
407** Check whether an integer key is in the array part. If 'alimit' is
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'
410** is smaller than the real size.
411** The trick works as follow: let 'p' be an integer such that
412** '2^(p+1) >= alimit > 2^p', or '2^(p+1) > alimit-1 >= 2^p'.
413** That is, 2^(p+1) is the real size of the array, and 'p' is the highest
414** bit on in 'alimit-1'. What we have to check becomes 'key-1 < 2^(p+1)'.
415** We compute '(key-1) & ~(alimit-1)', which we call 'res'; it will
416** have the 'p' bit cleared. If the key is outside the array, that is,
417** 'key-1 >= 2^(p+1)', then 'res' will have some 1-bit higher than 'p',
418** 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** '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** 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** If key is 0 or negative, 'res' will have its higher bit on, so that
425** if cannot be smaller than alimit.
426*/
427static int keyinarray (Table *t, lua_Integer key) {
428 lua_Unsigned alimit = t->alimit;
429 if (l_castS2U(key) - 1u < alimit) /* 'key' in [1, t->alimit]? */
430 return 1;
431 else if (!isrealasize(t) && /* key still may be in the array part? */
432 (((l_castS2U(key) - 1u) & ~(alimit - 1u)) < alimit)) {
433 t->alimit = cast_uint(key); /* probably '#t' is here now */
434 return 1;
435 }
436 else
437 return 0;
438}
439
440
441/*
406** {============================================================= 442** {=============================================================
407** Rehash 443** Rehash
408** ============================================================== 444** ==============================================================
@@ -449,6 +485,12 @@ static int countint (lua_Integer key, unsigned int *nums) {
449} 485}
450 486
451 487
488l_sinline int arraykeyisempty (const Table *t, lua_Integer key) {
489 int tag = *getArrTag(t, key - 1);
490 return tagisempty(tag);
491}
492
493
452/* 494/*
453** Count keys in array part of table 't': Fill 'nums[i]' with 495** Count keys in array part of table 't': Fill 'nums[i]' with
454** number of keys that will go into corresponding slice and return 496** number of keys that will go into corresponding slice and return
@@ -471,7 +513,7 @@ static unsigned int numusearray (const Table *t, unsigned int *nums) {
471 } 513 }
472 /* count elements in range (2^(lg - 1), 2^lg] */ 514 /* count elements in range (2^(lg - 1), 2^lg] */
473 for (; i <= lim; i++) { 515 for (; i <= lim; i++) {
474 if (!isempty(&t->array[i-1])) 516 if (!arraykeyisempty(t, i))
475 lc++; 517 lc++;
476 } 518 }
477 nums[lg] += lc; 519 nums[lg] += lc;
@@ -499,6 +541,33 @@ static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) {
499 541
500 542
501/* 543/*
544** Convert an "abstract size" (number of values in an array) to
545** "concrete size" (number of cell elements in the array). Cells
546** do not need to be full; we only must make sure it has the values
547** needed and its 'tag' element. So, we compute the concrete tag index
548** and the concrete value index of the last element, get their maximum
549** and adds 1.
550*/
551static unsigned int concretesize (unsigned int size) {
552 if (size == 0) return 0;
553 else {
554 unsigned int ts = TagIndex(size - 1);
555 unsigned int vs = ValueIndex(size - 1);
556 return ((ts >= vs) ? ts : vs) + 1;
557 }
558}
559
560
561static ArrayCell *resizearray (lua_State *L , Table *t,
562 unsigned int oldasize,
563 unsigned int newasize) {
564 oldasize = concretesize(oldasize);
565 newasize = concretesize(newasize);
566 return luaM_reallocvector(L, t->array, oldasize, newasize, ArrayCell);
567}
568
569
570/*
502** Creates an array for the hash part of a table with the given 571** Creates an array for the hash part of a table with the given
503** size, or reuses the dummy node if size is zero. 572** size, or reuses the dummy node if size is zero.
504** The computation for size overflow is in two steps: the first 573** The computation for size overflow is in two steps: the first
@@ -593,7 +662,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
593 unsigned int i; 662 unsigned int i;
594 Table newt; /* to keep the new hash part */ 663 Table newt; /* to keep the new hash part */
595 unsigned int oldasize = setlimittosize(t); 664 unsigned int oldasize = setlimittosize(t);
596 TValue *newarray; 665 ArrayCell *newarray;
597 /* create new hash part with appropriate size into 'newt' */ 666 /* create new hash part with appropriate size into 'newt' */
598 newt.flags = 0; 667 newt.flags = 0;
599 setnodevector(L, &newt, nhsize); 668 setnodevector(L, &newt, nhsize);
@@ -602,14 +671,18 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
602 exchangehashpart(t, &newt); /* and new hash */ 671 exchangehashpart(t, &newt); /* and new hash */
603 /* re-insert into the new hash the elements from vanishing slice */ 672 /* re-insert into the new hash the elements from vanishing slice */
604 for (i = newasize; i < oldasize; i++) { 673 for (i = newasize; i < oldasize; i++) {
605 if (!isempty(&t->array[i])) 674 int tag = *getArrTag(t, i);
606 luaH_setint(L, t, i + 1, &t->array[i]); 675 if (!tagisempty(tag)) { /* a non-empty entry? */
676 TValue aux;
677 farr2val(t, i + 1, tag, &aux);
678 luaH_setint(L, t, i + 1, &aux);
679 }
607 } 680 }
608 t->alimit = oldasize; /* restore current size... */ 681 t->alimit = oldasize; /* restore current size... */
609 exchangehashpart(t, &newt); /* and hash (in case of errors) */ 682 exchangehashpart(t, &newt); /* and hash (in case of errors) */
610 } 683 }
611 /* allocate new array */ 684 /* allocate new array */
612 newarray = luaM_reallocvector(L, t->array, oldasize, newasize, TValue); 685 newarray = resizearray(L, t, oldasize, newasize);
613 if (l_unlikely(newarray == NULL && newasize > 0)) { /* allocation failed? */ 686 if (l_unlikely(newarray == NULL && newasize > 0)) { /* allocation failed? */
614 freehash(L, &newt); /* release new hash part */ 687 freehash(L, &newt); /* release new hash part */
615 luaM_error(L); /* raise error (with array unchanged) */ 688 luaM_error(L); /* raise error (with array unchanged) */
@@ -619,7 +692,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
619 t->array = newarray; /* set new array part */ 692 t->array = newarray; /* set new array part */
620 t->alimit = newasize; 693 t->alimit = newasize;
621 for (i = oldasize; i < newasize; i++) /* clear new slice of the array */ 694 for (i = oldasize; i < newasize; i++) /* clear new slice of the array */
622 setempty(&t->array[i]); 695 *getArrTag(t, i) = LUA_VEMPTY;
623 /* re-insert elements from old hash part into new parts */ 696 /* re-insert elements from old hash part into new parts */
624 reinsert(L, &newt, t); /* 'newt' now has the old hash */ 697 reinsert(L, &newt, t); /* 'newt' now has the old hash */
625 freehash(L, &newt); /* free old hash part */ 698 freehash(L, &newt); /* free old hash part */
@@ -675,8 +748,9 @@ Table *luaH_new (lua_State *L) {
675 748
676 749
677void luaH_free (lua_State *L, Table *t) { 750void luaH_free (lua_State *L, Table *t) {
751 unsigned ps = concretesize(luaH_realasize(t));
678 freehash(L, t); 752 freehash(L, t);
679 luaM_freearray(L, t->array, luaH_realasize(t)); 753 luaM_freearray(L, t->array, ps);
680 luaM_free(L, t); 754 luaM_free(L, t);
681} 755}
682 756
@@ -770,57 +844,57 @@ static void luaH_newkey (lua_State *L, Table *t, const TValue *key,
770} 844}
771 845
772 846
773/* 847static const TValue *getintfromhash (Table *t, lua_Integer key) {
774** Search function for integers. If integer is inside 'alimit', get it 848 Node *n = hashint(t, key);
775** directly from the array part. Otherwise, if 'alimit' is not 849 lua_assert(l_castS2U(key) - 1u >= luaH_realasize(t));
776** the real size of the array, the key still can be in the array part. 850 for (;;) { /* check whether 'key' is somewhere in the chain */
777** In this case, do the "Xmilia trick" to check whether 'key-1' is 851 if (keyisinteger(n) && keyival(n) == key)
778** smaller than the real size. 852 return gval(n); /* that's it */
779** The trick works as follow: let 'p' be an integer such that 853 else {
780** '2^(p+1) >= alimit > 2^p', or '2^(p+1) > alimit-1 >= 2^p'. 854 int nx = gnext(n);
781** That is, 2^(p+1) is the real size of the array, and 'p' is the highest 855 if (nx == 0) break;
782** bit on in 'alimit-1'. What we have to check becomes 'key-1 < 2^(p+1)'. 856 n += nx;
783** We compute '(key-1) & ~(alimit-1)', which we call 'res'; it will 857 }
784** have the 'p' bit cleared. If the key is outside the array, that is,
785** 'key-1 >= 2^(p+1)', then 'res' will have some bit on higher than 'p',
786** therefore it will be larger or equal to 'alimit', and the check
787** will fail. If 'key-1 < 2^(p+1)', then 'res' has no bit on higher than
788** 'p', and as the bit 'p' itself was cleared, 'res' will be smaller
789** than 2^p, therefore smaller than 'alimit', and the check succeeds.
790** As special cases, when 'alimit' is 0 the condition is trivially false,
791** and when 'alimit' is 1 the condition simplifies to 'key-1 < alimit'.
792** If key is 0 or negative, 'res' will have its higher bit on, so that
793** if cannot be smaller than alimit.
794*/
795const TValue *luaH_getint (Table *t, lua_Integer key) {
796 lua_Unsigned alimit = t->alimit;
797 if (l_castS2U(key) - 1u < alimit) /* 'key' in [1, t->alimit]? */
798 return &t->array[key - 1];
799 else if (!isrealasize(t) && /* key still may be in the array part? */
800 (((l_castS2U(key) - 1u) & ~(alimit - 1u)) < alimit)) {
801 t->alimit = cast_uint(key); /* probably '#t' is here now */
802 return &t->array[key - 1];
803 } 858 }
804 else { /* key is not in the array part; check the hash */ 859 return &absentkey;
805 Node *n = hashint(t, key); 860}
806 for (;;) { /* check whether 'key' is somewhere in the chain */ 861
807 if (keyisinteger(n) && keyival(n) == key) 862
808 return gval(n); /* that's it */ 863static int hashkeyisempty (Table *t, lua_Integer key) {
809 else { 864 const TValue *val = getintfromhash(t, key);
810 int nx = gnext(n); 865 return isempty(val);
811 if (nx == 0) break; 866}
812 n += nx; 867
813 } 868
869static int finishnodeget (const TValue *val, TValue *res) {
870 if (!ttisnil(val)) {
871 setobj(((lua_State*)NULL), res, val);
872 return HOK; /* success */
873 }
874 else
875 return HNOTFOUND; /* could not get value */
876}
877
878
879int luaH_getint (Table *t, lua_Integer key, TValue *res) {
880 if (keyinarray(t, key)) {
881 int tag = *getArrTag(t, key - 1);
882 if (!tagisempty(tag)) {
883 farr2val(t, key, tag, res);
884 return HOK; /* success */
814 } 885 }
815 return &absentkey; 886 else
887 return ~cast_int(key); /* empty slot in the array part */
816 } 888 }
889 else
890 return finishnodeget(getintfromhash(t, key), res);
817} 891}
818 892
819 893
820/* 894/*
821** search function for short strings 895** search function for short strings
822*/ 896*/
823const TValue *luaH_getshortstr (Table *t, TString *key) { 897const TValue *luaH_Hgetshortstr (Table *t, TString *key) {
824 Node *n = hashstr(t, key); 898 Node *n = hashstr(t, key);
825 lua_assert(key->tt == LUA_VSHRSTR); 899 lua_assert(key->tt == LUA_VSHRSTR);
826 for (;;) { /* check whether 'key' is somewhere in the chain */ 900 for (;;) { /* check whether 'key' is somewhere in the chain */
@@ -836,9 +910,14 @@ const TValue *luaH_getshortstr (Table *t, TString *key) {
836} 910}
837 911
838 912
839const TValue *luaH_getstr (Table *t, TString *key) { 913int luaH_getshortstr (Table *t, TString *key, TValue *res) {
914 return finishnodeget(luaH_Hgetshortstr(t, key), res);
915}
916
917
918static const TValue *Hgetstr (Table *t, TString *key) {
840 if (key->tt == LUA_VSHRSTR) 919 if (key->tt == LUA_VSHRSTR)
841 return luaH_getshortstr(t, key); 920 return luaH_Hgetshortstr(t, key);
842 else { /* for long strings, use generic case */ 921 else { /* for long strings, use generic case */
843 TValue ko; 922 TValue ko;
844 setsvalue(cast(lua_State *, NULL), &ko, key); 923 setsvalue(cast(lua_State *, NULL), &ko, key);
@@ -847,38 +926,121 @@ const TValue *luaH_getstr (Table *t, TString *key) {
847} 926}
848 927
849 928
929int luaH_getstr (Table *t, TString *key, TValue *res) {
930 return finishnodeget(Hgetstr(t, key), res);
931}
932
933
934TString *luaH_getstrkey (Table *t, TString *key) {
935 const TValue *o = Hgetstr(t, key);
936 if (!isabstkey(o)) /* string already present? */
937 return keystrval(nodefromval(o)); /* get saved copy */
938 else
939 return NULL;
940}
941
942
850/* 943/*
851** main search function 944** main search function
852*/ 945*/
853const TValue *luaH_get (Table *t, const TValue *key) { 946int luaH_get (Table *t, const TValue *key, TValue *res) {
947 const TValue *slot;
854 switch (ttypetag(key)) { 948 switch (ttypetag(key)) {
855 case LUA_VSHRSTR: return luaH_getshortstr(t, tsvalue(key)); 949 case LUA_VSHRSTR:
856 case LUA_VNUMINT: return luaH_getint(t, ivalue(key)); 950 slot = luaH_Hgetshortstr(t, tsvalue(key));
857 case LUA_VNIL: return &absentkey; 951 break;
952 case LUA_VNUMINT:
953 return luaH_getint(t, ivalue(key), res);
954 case LUA_VNIL:
955 slot = &absentkey;
956 break;
858 case LUA_VNUMFLT: { 957 case LUA_VNUMFLT: {
859 lua_Integer k; 958 lua_Integer k;
860 if (luaV_flttointeger(fltvalue(key), &k, F2Ieq)) /* integral index? */ 959 if (luaV_flttointeger(fltvalue(key), &k, F2Ieq)) /* integral index? */
861 return luaH_getint(t, k); /* use specialized version */ 960 return luaH_getint(t, k, res); /* use specialized version */
862 /* else... */ 961 /* else... */
863 } /* FALLTHROUGH */ 962 } /* FALLTHROUGH */
864 default: 963 default:
865 return getgeneric(t, key, 0); 964 slot = getgeneric(t, key, 0);
965 break;
866 } 966 }
967 return finishnodeget(slot, res);
867} 968}
868 969
869 970
971static int finishnodeset (Table *t, const TValue *slot, TValue *val) {
972 if (!ttisnil(slot)) {
973 setobj(((lua_State*)NULL), cast(TValue*, slot), val);
974 return HOK; /* success */
975 }
976 else if (isabstkey(slot))
977 return HNOTFOUND; /* no slot with that key */
978 else return (cast(Node*, slot) - t->node) + HFIRSTNODE; /* node encoded */
979}
980
981
982int luaH_psetint (Table *t, lua_Integer key, TValue *val) {
983 if (keyinarray(t, key)) {
984 lu_byte *tag = getArrTag(t, key - 1);
985 if (!tagisempty(*tag)) {
986 fval2arr(t, key, tag, val);
987 return HOK; /* success */
988 }
989 else
990 return ~cast_int(key); /* empty slot in the array part */
991 }
992 else
993 return finishnodeset(t, getintfromhash(t, key), val);
994}
995
996
997int luaH_psetshortstr (Table *t, TString *key, TValue *val) {
998 return finishnodeset(t, luaH_Hgetshortstr(t, key), val);
999}
1000
1001
1002int luaH_psetstr (Table *t, TString *key, TValue *val) {
1003 return finishnodeset(t, Hgetstr(t, key), val);
1004}
1005
1006
1007int luaH_pset (Table *t, const TValue *key, TValue *val) {
1008 switch (ttypetag(key)) {
1009 case LUA_VSHRSTR: return luaH_psetshortstr(t, tsvalue(key), val);
1010 case LUA_VNUMINT: return luaH_psetint(t, ivalue(key), val);
1011 case LUA_VNIL: return HNOTFOUND;
1012 case LUA_VNUMFLT: {
1013 lua_Integer k;
1014 if (luaV_flttointeger(fltvalue(key), &k, F2Ieq)) /* integral index? */
1015 return luaH_psetint(t, k, val); /* use specialized version */
1016 /* else... */
1017 } /* FALLTHROUGH */
1018 default:
1019 return finishnodeset(t, getgeneric(t, key, 0), val);
1020 }
1021}
1022
870/* 1023/*
871** Finish a raw "set table" operation, where 'slot' is where the value 1024** Finish a raw "set table" operation, where 'slot' is where the value
872** should have been (the result of a previous "get table"). 1025** should have been (the result of a previous "get table").
873** Beware: when using this function you probably need to check a GC 1026** Beware: when using this function you probably need to check a GC
874** barrier and invalidate the TM cache. 1027** barrier and invalidate the TM cache.
875*/ 1028*/
1029
1030
876void luaH_finishset (lua_State *L, Table *t, const TValue *key, 1031void luaH_finishset (lua_State *L, Table *t, const TValue *key,
877 const TValue *slot, TValue *value) { 1032 TValue *value, int hres) {
878 if (isabstkey(slot)) 1033 lua_assert(hres != HOK);
1034 if (hres == HNOTFOUND) {
879 luaH_newkey(L, t, key, value); 1035 luaH_newkey(L, t, key, value);
880 else 1036 }
881 setobj2t(L, cast(TValue *, slot), value); 1037 else if (hres > 0) { /* regular Node? */
1038 setobj2t(L, gval(gnode(t, hres - HFIRSTNODE)), value);
1039 }
1040 else { /* array entry */
1041 hres = ~hres; /* real index */
1042 obj2arr(t, hres, value);
1043 }
882} 1044}
883 1045
884 1046
@@ -887,20 +1049,19 @@ void luaH_finishset (lua_State *L, Table *t, const TValue *key,
887** barrier and invalidate the TM cache. 1049** barrier and invalidate the TM cache.
888*/ 1050*/
889void luaH_set (lua_State *L, Table *t, const TValue *key, TValue *value) { 1051void luaH_set (lua_State *L, Table *t, const TValue *key, TValue *value) {
890 const TValue *slot = luaH_get(t, key); 1052 int hres = luaH_pset(t, key, value);
891 luaH_finishset(L, t, key, slot, value); 1053 if (hres != HOK)
1054 luaH_finishset(L, t, key, value, hres);
892} 1055}
893 1056
894 1057
895void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { 1058void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) {
896 const TValue *p = luaH_getint(t, key); 1059 int hres = luaH_psetint(t, key, value);
897 if (isabstkey(p)) { 1060 if (hres != HOK) {
898 TValue k; 1061 TValue k;
899 setivalue(&k, key); 1062 setivalue(&k, key);
900 luaH_newkey(L, t, &k, value); 1063 luaH_finishset(L, t, &k, value, hres);
901 } 1064 }
902 else
903 setobj2t(L, cast(TValue *, p), value);
904} 1065}
905 1066
906 1067
@@ -926,27 +1087,26 @@ static lua_Unsigned hash_search (Table *t, lua_Unsigned j) {
926 j *= 2; 1087 j *= 2;
927 else { 1088 else {
928 j = LUA_MAXINTEGER; 1089 j = LUA_MAXINTEGER;
929 if (isempty(luaH_getint(t, j))) /* t[j] not present? */ 1090 if (hashkeyisempty(t, j)) /* t[j] not present? */
930 break; /* 'j' now is an absent index */ 1091 break; /* 'j' now is an absent index */
931 else /* weird case */ 1092 else /* weird case */
932 return j; /* well, max integer is a boundary... */ 1093 return j; /* well, max integer is a boundary... */
933 } 1094 }
934 } while (!isempty(luaH_getint(t, j))); /* repeat until an absent t[j] */ 1095 } while (!hashkeyisempty(t, j)); /* repeat until an absent t[j] */
935 /* i < j && t[i] present && t[j] absent */ 1096 /* i < j && t[i] present && t[j] absent */
936 while (j - i > 1u) { /* do a binary search between them */ 1097 while (j - i > 1u) { /* do a binary search between them */
937 lua_Unsigned m = (i + j) / 2; 1098 lua_Unsigned m = (i + j) / 2;
938 if (isempty(luaH_getint(t, m))) j = m; 1099 if (hashkeyisempty(t, m)) j = m;
939 else i = m; 1100 else i = m;
940 } 1101 }
941 return i; 1102 return i;
942} 1103}
943 1104
944 1105
945static unsigned int binsearch (const TValue *array, unsigned int i, 1106static unsigned int binsearch (Table *array, unsigned int i, unsigned int j) {
946 unsigned int j) {
947 while (j - i > 1u) { /* binary search */ 1107 while (j - i > 1u) { /* binary search */
948 unsigned int m = (i + j) / 2; 1108 unsigned int m = (i + j) / 2;
949 if (isempty(&array[m - 1])) j = m; 1109 if (arraykeyisempty(array, m)) j = m;
950 else i = m; 1110 else i = m;
951 } 1111 }
952 return i; 1112 return i;
@@ -987,9 +1147,9 @@ static unsigned int binsearch (const TValue *array, unsigned int i,
987*/ 1147*/
988lua_Unsigned luaH_getn (Table *t) { 1148lua_Unsigned luaH_getn (Table *t) {
989 unsigned int limit = t->alimit; 1149 unsigned int limit = t->alimit;
990 if (limit > 0 && isempty(&t->array[limit - 1])) { /* (1)? */ 1150 if (limit > 0 && arraykeyisempty(t, limit)) { /* (1)? */
991 /* there must be a boundary before 'limit' */ 1151 /* there must be a boundary before 'limit' */
992 if (limit >= 2 && !isempty(&t->array[limit - 2])) { 1152 if (limit >= 2 && !arraykeyisempty(t, limit - 1)) {
993 /* 'limit - 1' is a boundary; can it be a new limit? */ 1153 /* 'limit - 1' is a boundary; can it be a new limit? */
994 if (ispow2realasize(t) && !ispow2(limit - 1)) { 1154 if (ispow2realasize(t) && !ispow2(limit - 1)) {
995 t->alimit = limit - 1; 1155 t->alimit = limit - 1;
@@ -998,7 +1158,7 @@ lua_Unsigned luaH_getn (Table *t) {
998 return limit - 1; 1158 return limit - 1;
999 } 1159 }
1000 else { /* must search for a boundary in [0, limit] */ 1160 else { /* must search for a boundary in [0, limit] */
1001 unsigned int boundary = binsearch(t->array, 0, limit); 1161 unsigned int boundary = binsearch(t, 0, limit);
1002 /* can this boundary represent the real size of the array? */ 1162 /* can this boundary represent the real size of the array? */
1003 if (ispow2realasize(t) && boundary > luaH_realasize(t) / 2) { 1163 if (ispow2realasize(t) && boundary > luaH_realasize(t) / 2) {
1004 t->alimit = boundary; /* use it as the new limit */ 1164 t->alimit = boundary; /* use it as the new limit */
@@ -1010,14 +1170,14 @@ lua_Unsigned luaH_getn (Table *t) {
1010 /* 'limit' is zero or present in table */ 1170 /* 'limit' is zero or present in table */
1011 if (!limitequalsasize(t)) { /* (2)? */ 1171 if (!limitequalsasize(t)) { /* (2)? */
1012 /* 'limit' > 0 and array has more elements after 'limit' */ 1172 /* 'limit' > 0 and array has more elements after 'limit' */
1013 if (isempty(&t->array[limit])) /* 'limit + 1' is empty? */ 1173 if (arraykeyisempty(t, limit + 1)) /* 'limit + 1' is empty? */
1014 return limit; /* this is the boundary */ 1174 return limit; /* this is the boundary */
1015 /* else, try last element in the array */ 1175 /* else, try last element in the array */
1016 limit = luaH_realasize(t); 1176 limit = luaH_realasize(t);
1017 if (isempty(&t->array[limit - 1])) { /* empty? */ 1177 if (arraykeyisempty(t, limit)) { /* empty? */
1018 /* there must be a boundary in the array after old limit, 1178 /* there must be a boundary in the array after old limit,
1019 and it must be a valid new limit */ 1179 and it must be a valid new limit */
1020 unsigned int boundary = binsearch(t->array, t->alimit, limit); 1180 unsigned int boundary = binsearch(t, t->alimit, limit);
1021 t->alimit = boundary; 1181 t->alimit = boundary;
1022 return boundary; 1182 return boundary;
1023 } 1183 }
@@ -1025,8 +1185,8 @@ lua_Unsigned luaH_getn (Table *t) {
1025 } 1185 }
1026 /* (3) 'limit' is the last element and either is zero or present in table */ 1186 /* (3) 'limit' is the last element and either is zero or present in table */
1027 lua_assert(limit == luaH_realasize(t) && 1187 lua_assert(limit == luaH_realasize(t) &&
1028 (limit == 0 || !isempty(&t->array[limit - 1]))); 1188 (limit == 0 || !arraykeyisempty(t, limit)));
1029 if (isdummy(t) || isempty(luaH_getint(t, cast(lua_Integer, limit + 1)))) 1189 if (isdummy(t) || hashkeyisempty(t, cast(lua_Integer, limit + 1)))
1030 return limit; /* 'limit + 1' is absent */ 1190 return limit; /* 'limit + 1' is absent */
1031 else /* 'limit + 1' is also present */ 1191 else /* 'limit + 1' is also present */
1032 return hash_search(t, limit); 1192 return hash_search(t, limit);
diff --git a/ltable.h b/ltable.h
index 30cfc8be..210ae7ac 100644
--- a/ltable.h
+++ b/ltable.h
@@ -45,16 +45,105 @@
45#define nodefromval(v) cast(Node *, (v)) 45#define nodefromval(v) cast(Node *, (v))
46 46
47 47
48LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); 48/* results from get/pset */
49#define HOK 0
50#define HNOTFOUND 1
51#define HNOTATABLE 2
52#define HFIRSTNODE 3
53
54/*
55** Besides these values, pset (pre-set) operations may also return an
56** encoding of where the value should go (usually called 'hres'). That
57** means that there is a slot with that key but with no value. (pset
58** cannot set that value because there might be a metamethod.) If the
59** slot is in the hash part, the encoding is (HFIRSTNODE + hash index);
60** if the slot is in the array part, the encoding is (~array index).
61*/
62
63
64/*
65** The array part of a table is represented by an array of cells.
66** Each cell is composed of (NM + 1) elements, and each element has the
67** type 'ArrayCell'. In each cell, only one element has the variant
68** 'tag', while the other NM elements have the variant 'value'. The
69** array in the 'tag' element holds the tags of the other elements in
70** that cell.
71*/
72#define NM ((unsigned int)sizeof(Value))
73
74union ArrayCell {
75 unsigned char tag[NM];
76 Value value;
77};
78
79
80/*
81** 'NMTag' defines which cell element has the tags; that could be any
82** value between 0 (tags come before all values) and NM (tags come after
83** all values).
84*/
85#define NMTag 0
86
87
88/*
89** Computes the concrete index that holds the tag of abstract index 'i'
90*/
91#define TagIndex(i) (((i)/NM * (NM + 1u)) + NMTag)
92
93/*
94** Computes the concrete index that holds the value of abstract index 'i'
95*/
96#define ValueIndex(i) ((i) + (((i) + (NM - NMTag))/NM))
97
98
99/* Computes the address of the tag for the abstract index 'k' */
100#define getArrTag(t,k) (&(t)->array[TagIndex(k)].tag[(k)%NM])
101
102/* Computes the address of the value for the abstract index 'k' */
103#define getArrVal(t,k) (&(t)->array[ValueIndex(k)].value)
104
105
106/*
107** Move TValues to/from arrays, using Lua indices
108*/
109#define arr2obj(h,k,val) \
110 ((val)->tt_ = *getArrTag(h,(k)-1u), (val)->value_ = *getArrVal(h,(k)-1u))
111
112#define obj2arr(h,k,val) \
113 (*getArrTag(h,(k)-1u) = (val)->tt_, *getArrVal(h,(k)-1u) = (val)->value_)
114
115
116/*
117** Often, we need to check the tag of a value before moving it. These
118** macros also move TValues to/from arrays, but receive the precomputed
119** tag value or address as an extra argument.
120*/
121#define farr2val(h,k,tag,res) \
122 ((res)->tt_ = tag, (res)->value_ = *getArrVal(h,(k)-1u))
123
124#define fval2arr(h,k,tag,val) \
125 (*tag = (val)->tt_, *getArrVal(h,(k)-1u) = (val)->value_)
126
127
128LUAI_FUNC int luaH_getshortstr (Table *t, TString *key, TValue *res);
129LUAI_FUNC int luaH_getstr (Table *t, TString *key, TValue *res);
130LUAI_FUNC int luaH_get (Table *t, const TValue *key, TValue *res);
131LUAI_FUNC int luaH_getint (Table *t, lua_Integer key, TValue *res);
132
133LUAI_FUNC TString *luaH_getstrkey (Table *t, TString *key);
134
135LUAI_FUNC int luaH_psetint (Table *t, lua_Integer key, TValue *val);
136LUAI_FUNC int luaH_psetshortstr (Table *t, TString *key, TValue *val);
137LUAI_FUNC int luaH_psetstr (Table *t, TString *key, TValue *val);
138LUAI_FUNC int luaH_pset (Table *t, const TValue *key, TValue *val);
139
49LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, 140LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key,
50 TValue *value); 141 TValue *value);
51LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key); 142LUAI_FUNC const TValue *luaH_Hgetshortstr (Table *t, TString *key);
52LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
53LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
54LUAI_FUNC void luaH_set (lua_State *L, Table *t, const TValue *key, 143LUAI_FUNC void luaH_set (lua_State *L, Table *t, const TValue *key,
55 TValue *value); 144 TValue *value);
56LUAI_FUNC void luaH_finishset (lua_State *L, Table *t, const TValue *key, 145LUAI_FUNC void luaH_finishset (lua_State *L, Table *t, const TValue *key,
57 const TValue *slot, TValue *value); 146 TValue *value, int aux);
58LUAI_FUNC Table *luaH_new (lua_State *L); 147LUAI_FUNC Table *luaH_new (lua_State *L);
59LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize, 148LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
60 unsigned int nhsize); 149 unsigned int nhsize);
diff --git a/ltests.c b/ltests.c
index 15d1a564..6f556dc9 100644
--- a/ltests.c
+++ b/ltests.c
@@ -362,8 +362,11 @@ static void checktable (global_State *g, Table *h) {
362 Node *n, *limit = gnode(h, sizenode(h)); 362 Node *n, *limit = gnode(h, sizenode(h));
363 GCObject *hgc = obj2gco(h); 363 GCObject *hgc = obj2gco(h);
364 checkobjrefN(g, hgc, h->metatable); 364 checkobjrefN(g, hgc, h->metatable);
365 for (i = 0; i < asize; i++) 365 for (i = 0; i < asize; i++) {
366 checkvalref(g, hgc, &h->array[i]); 366 TValue aux;
367 arr2obj(h, i + 1, &aux);
368 checkvalref(g, hgc, &aux);
369 }
367 for (n = gnode(h, 0); n < limit; n++) { 370 for (n = gnode(h, 0); n < limit; n++) {
368 if (!isempty(gval(n))) { 371 if (!isempty(gval(n))) {
369 TValue k; 372 TValue k;
@@ -1004,7 +1007,8 @@ static int table_query (lua_State *L) {
1004 } 1007 }
1005 else if ((unsigned int)i < asize) { 1008 else if ((unsigned int)i < asize) {
1006 lua_pushinteger(L, i); 1009 lua_pushinteger(L, i);
1007 pushobject(L, &t->array[i]); 1010 arr2obj(t, i + 1, s2v(L->top.p));
1011 api_incr_top(L);
1008 lua_pushnil(L); 1012 lua_pushnil(L);
1009 } 1013 }
1010 else if ((i -= asize) < sizenode(t)) { 1014 else if ((i -= asize) < sizenode(t)) {
diff --git a/ltm.c b/ltm.c
index 8e0d2222..c943bc7b 100644
--- a/ltm.c
+++ b/ltm.c
@@ -58,7 +58,7 @@ void luaT_init (lua_State *L) {
58** tag methods 58** tag methods
59*/ 59*/
60const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { 60const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
61 const TValue *tm = luaH_getshortstr(events, ename); 61 const TValue *tm = luaH_Hgetshortstr(events, ename);
62 lua_assert(event <= TM_EQ); 62 lua_assert(event <= TM_EQ);
63 if (notm(tm)) { /* no tag method? */ 63 if (notm(tm)) { /* no tag method? */
64 events->flags |= cast_byte(1u<<event); /* cache this fact */ 64 events->flags |= cast_byte(1u<<event); /* cache this fact */
@@ -80,7 +80,7 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
80 default: 80 default:
81 mt = G(L)->mt[ttype(o)]; 81 mt = G(L)->mt[ttype(o)];
82 } 82 }
83 return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : &G(L)->nilvalue); 83 return (mt ? luaH_Hgetshortstr(mt, G(L)->tmname[event]) : &G(L)->nilvalue);
84} 84}
85 85
86 86
@@ -92,9 +92,10 @@ const char *luaT_objtypename (lua_State *L, const TValue *o) {
92 Table *mt; 92 Table *mt;
93 if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) || 93 if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) ||
94 (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) { 94 (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) {
95 const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name")); 95 TValue name;
96 if (ttisstring(name)) /* is '__name' a string? */ 96 int hres = luaH_getshortstr(mt, luaS_new(L, "__name"), &name);
97 return getstr(tsvalue(name)); /* use it as type name */ 97 if (hres == HOK && ttisstring(&name)) /* is '__name' a string? */
98 return getstr(tsvalue(&name)); /* use it as type name */
98 } 99 }
99 return ttypename(ttype(o)); /* else use standard type name */ 100 return ttypename(ttype(o)); /* else use standard type name */
100} 101}
diff --git a/lvm.c b/lvm.c
index 0a6d6270..e4c026fd 100644
--- a/lvm.c
+++ b/lvm.c
@@ -286,15 +286,13 @@ static int floatforloop (StkId ra) {
286 286
287/* 287/*
288** Finish the table access 'val = t[key]'. 288** Finish the table access 'val = t[key]'.
289** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to
290** t[k] entry (which must be empty).
291*/ 289*/
292void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, 290void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
293 const TValue *slot) { 291 int hres) {
294 int loop; /* counter to avoid infinite loops */ 292 int loop; /* counter to avoid infinite loops */
295 const TValue *tm; /* metamethod */ 293 const TValue *tm; /* metamethod */
296 for (loop = 0; loop < MAXTAGLOOP; loop++) { 294 for (loop = 0; loop < MAXTAGLOOP; loop++) {
297 if (slot == NULL) { /* 't' is not a table? */ 295 if (hres == HNOTATABLE) { /* 't' is not a table? */
298 lua_assert(!ttistable(t)); 296 lua_assert(!ttistable(t));
299 tm = luaT_gettmbyobj(L, t, TM_INDEX); 297 tm = luaT_gettmbyobj(L, t, TM_INDEX);
300 if (l_unlikely(notm(tm))) 298 if (l_unlikely(notm(tm)))
@@ -302,7 +300,6 @@ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
302 /* else will try the metamethod */ 300 /* else will try the metamethod */
303 } 301 }
304 else { /* 't' is a table */ 302 else { /* 't' is a table */
305 lua_assert(isempty(slot));
306 tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */ 303 tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */
307 if (tm == NULL) { /* no metamethod? */ 304 if (tm == NULL) { /* no metamethod? */
308 setnilvalue(s2v(val)); /* result is nil */ 305 setnilvalue(s2v(val)); /* result is nil */
@@ -315,10 +312,9 @@ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
315 return; 312 return;
316 } 313 }
317 t = tm; /* else try to access 'tm[key]' */ 314 t = tm; /* else try to access 'tm[key]' */
318 if (luaV_fastget(L, t, key, slot, luaH_get)) { /* fast track? */ 315 luaV_fastget(t, key, s2v(val), luaH_get, hres);
319 setobj2s(L, val, slot); /* done */ 316 if (hres == HOK)
320 return; 317 return; /* done */
321 }
322 /* else repeat (tail call 'luaV_finishget') */ 318 /* else repeat (tail call 'luaV_finishget') */
323 } 319 }
324 luaG_runerror(L, "'__index' chain too long; possible loop"); 320 luaG_runerror(L, "'__index' chain too long; possible loop");
@@ -327,22 +323,17 @@ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
327 323
328/* 324/*
329** Finish a table assignment 't[key] = val'. 325** Finish a table assignment 't[key] = val'.
330** If 'slot' is NULL, 't' is not a table. Otherwise, 'slot' points
331** to the entry 't[key]', or to a value with an absent key if there
332** is no such entry. (The value at 'slot' must be empty, otherwise
333** 'luaV_fastget' would have done the job.)
334*/ 326*/
335void luaV_finishset (lua_State *L, const TValue *t, TValue *key, 327void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
336 TValue *val, const TValue *slot) { 328 TValue *val, int hres) {
337 int loop; /* counter to avoid infinite loops */ 329 int loop; /* counter to avoid infinite loops */
338 for (loop = 0; loop < MAXTAGLOOP; loop++) { 330 for (loop = 0; loop < MAXTAGLOOP; loop++) {
339 const TValue *tm; /* '__newindex' metamethod */ 331 const TValue *tm; /* '__newindex' metamethod */
340 if (slot != NULL) { /* is 't' a table? */ 332 if (hres != HNOTATABLE) { /* is 't' a table? */
341 Table *h = hvalue(t); /* save 't' table */ 333 Table *h = hvalue(t); /* save 't' table */
342 lua_assert(isempty(slot)); /* slot must be empty */
343 tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ 334 tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */
344 if (tm == NULL) { /* no metamethod? */ 335 if (tm == NULL) { /* no metamethod? */
345 luaH_finishset(L, h, key, slot, val); /* set new value */ 336 luaH_finishset(L, h, key, val, hres); /* set new value */
346 invalidateTMcache(h); 337 invalidateTMcache(h);
347 luaC_barrierback(L, obj2gco(h), val); 338 luaC_barrierback(L, obj2gco(h), val);
348 return; 339 return;
@@ -360,10 +351,9 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
360 return; 351 return;
361 } 352 }
362 t = tm; /* else repeat assignment over 'tm' */ 353 t = tm; /* else repeat assignment over 'tm' */
363 if (luaV_fastget(L, t, key, slot, luaH_get)) { 354 luaV_fastset(t, key, val, hres, luaH_pset);
364 luaV_finishfastset(L, t, slot, val); 355 if (hres == HOK)
365 return; /* done */ 356 return; /* done */
366 }
367 /* else 'return luaV_finishset(L, t, key, val, slot)' (loop) */ 357 /* else 'return luaV_finishset(L, t, key, val, slot)' (loop) */
368 } 358 }
369 luaG_runerror(L, "'__newindex' chain too long; possible loop"); 359 luaG_runerror(L, "'__newindex' chain too long; possible loop");
@@ -1252,114 +1242,109 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1252 } 1242 }
1253 vmcase(OP_GETTABUP) { 1243 vmcase(OP_GETTABUP) {
1254 StkId ra = RA(i); 1244 StkId ra = RA(i);
1255 const TValue *slot;
1256 TValue *upval = cl->upvals[GETARG_B(i)]->v.p; 1245 TValue *upval = cl->upvals[GETARG_B(i)]->v.p;
1257 TValue *rc = KC(i); 1246 TValue *rc = KC(i);
1258 TString *key = tsvalue(rc); /* key must be a short string */ 1247 TString *key = tsvalue(rc); /* key must be a short string */
1259 if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) { 1248 int hres;
1260 setobj2s(L, ra, slot); 1249 luaV_fastget(upval, key, s2v(ra), luaH_getshortstr, hres);
1261 } 1250 if (hres != HOK)
1262 else 1251 Protect(luaV_finishget(L, upval, rc, ra, hres));
1263 Protect(luaV_finishget(L, upval, rc, ra, slot));
1264 vmbreak; 1252 vmbreak;
1265 } 1253 }
1266 vmcase(OP_GETTABLE) { 1254 vmcase(OP_GETTABLE) {
1267 StkId ra = RA(i); 1255 StkId ra = RA(i);
1268 const TValue *slot;
1269 TValue *rb = vRB(i); 1256 TValue *rb = vRB(i);
1270 TValue *rc = vRC(i); 1257 TValue *rc = vRC(i);
1271 lua_Unsigned n; 1258 int hres;
1272 if (ttisinteger(rc) /* fast track for integers? */ 1259 if (ttisinteger(rc)) { /* fast track for integers? */
1273 ? (cast_void(n = ivalue(rc)), luaV_fastgeti(L, rb, n, slot)) 1260 luaV_fastgeti(rb, ivalue(rc), s2v(ra), hres);
1274 : luaV_fastget(L, rb, rc, slot, luaH_get)) {
1275 setobj2s(L, ra, slot);
1276 } 1261 }
1277 else 1262 else
1278 Protect(luaV_finishget(L, rb, rc, ra, slot)); 1263 luaV_fastget(rb, rc, s2v(ra), luaH_get, hres);
1264 if (hres != HOK) /* fast track for integers? */
1265 Protect(luaV_finishget(L, rb, rc, ra, hres));
1279 vmbreak; 1266 vmbreak;
1280 } 1267 }
1281 vmcase(OP_GETI) { 1268 vmcase(OP_GETI) {
1282 StkId ra = RA(i); 1269 StkId ra = RA(i);
1283 const TValue *slot;
1284 TValue *rb = vRB(i); 1270 TValue *rb = vRB(i);
1285 int c = GETARG_C(i); 1271 int c = GETARG_C(i);
1286 if (luaV_fastgeti(L, rb, c, slot)) { 1272 int hres;
1287 setobj2s(L, ra, slot); 1273 luaV_fastgeti(rb, c, s2v(ra), hres);
1288 } 1274 if (hres != HOK) {
1289 else {
1290 TValue key; 1275 TValue key;
1291 setivalue(&key, c); 1276 setivalue(&key, c);
1292 Protect(luaV_finishget(L, rb, &key, ra, slot)); 1277 Protect(luaV_finishget(L, rb, &key, ra, hres));
1293 } 1278 }
1294 vmbreak; 1279 vmbreak;
1295 } 1280 }
1296 vmcase(OP_GETFIELD) { 1281 vmcase(OP_GETFIELD) {
1297 StkId ra = RA(i); 1282 StkId ra = RA(i);
1298 const TValue *slot;
1299 TValue *rb = vRB(i); 1283 TValue *rb = vRB(i);
1300 TValue *rc = KC(i); 1284 TValue *rc = KC(i);
1301 TString *key = tsvalue(rc); /* key must be a short string */ 1285 TString *key = tsvalue(rc); /* key must be a short string */
1302 if (luaV_fastget(L, rb, key, slot, luaH_getshortstr)) { 1286 int hres;
1303 setobj2s(L, ra, slot); 1287 luaV_fastget(rb, key, s2v(ra), luaH_getshortstr, hres);
1304 } 1288 if (hres != HOK)
1305 else 1289 Protect(luaV_finishget(L, rb, rc, ra, hres));
1306 Protect(luaV_finishget(L, rb, rc, ra, slot));
1307 vmbreak; 1290 vmbreak;
1308 } 1291 }
1309 vmcase(OP_SETTABUP) { 1292 vmcase(OP_SETTABUP) {
1310 const TValue *slot; 1293 int hres;
1311 TValue *upval = cl->upvals[GETARG_A(i)]->v.p; 1294 TValue *upval = cl->upvals[GETARG_A(i)]->v.p;
1312 TValue *rb = KB(i); 1295 TValue *rb = KB(i);
1313 TValue *rc = RKC(i); 1296 TValue *rc = RKC(i);
1314 TString *key = tsvalue(rb); /* key must be a short string */ 1297 TString *key = tsvalue(rb); /* key must be a short string */
1315 if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) { 1298 luaV_fastset(upval, key, rc, hres, luaH_psetshortstr);
1316 luaV_finishfastset(L, upval, slot, rc); 1299 if (hres == HOK)
1317 } 1300 luaV_finishfastset(L, upval, rc);
1318 else 1301 else
1319 Protect(luaV_finishset(L, upval, rb, rc, slot)); 1302 Protect(luaV_finishset(L, upval, rb, rc, hres));
1320 vmbreak; 1303 vmbreak;
1321 } 1304 }
1322 vmcase(OP_SETTABLE) { 1305 vmcase(OP_SETTABLE) {
1323 StkId ra = RA(i); 1306 StkId ra = RA(i);
1324 const TValue *slot; 1307 int hres;
1325 TValue *rb = vRB(i); /* key (table is in 'ra') */ 1308 TValue *rb = vRB(i); /* key (table is in 'ra') */
1326 TValue *rc = RKC(i); /* value */ 1309 TValue *rc = RKC(i); /* value */
1327 lua_Unsigned n; 1310 if (ttisinteger(rb)) { /* fast track for integers? */
1328 if (ttisinteger(rb) /* fast track for integers? */ 1311 luaV_fastseti(s2v(ra), ivalue(rb), rc, hres);
1329 ? (cast_void(n = ivalue(rb)), luaV_fastgeti(L, s2v(ra), n, slot)) 1312 }
1330 : luaV_fastget(L, s2v(ra), rb, slot, luaH_get)) { 1313 else {
1331 luaV_finishfastset(L, s2v(ra), slot, rc); 1314 luaV_fastset(s2v(ra), rb, rc, hres, luaH_pset);
1332 } 1315 }
1316 if (hres == HOK)
1317 luaV_finishfastset(L, s2v(ra), rc);
1333 else 1318 else
1334 Protect(luaV_finishset(L, s2v(ra), rb, rc, slot)); 1319 Protect(luaV_finishset(L, s2v(ra), rb, rc, hres));
1335 vmbreak; 1320 vmbreak;
1336 } 1321 }
1337 vmcase(OP_SETI) { 1322 vmcase(OP_SETI) {
1338 StkId ra = RA(i); 1323 StkId ra = RA(i);
1339 const TValue *slot; 1324 int hres;
1340 int c = GETARG_B(i); 1325 int b = GETARG_B(i);
1341 TValue *rc = RKC(i); 1326 TValue *rc = RKC(i);
1342 if (luaV_fastgeti(L, s2v(ra), c, slot)) { 1327 luaV_fastseti(s2v(ra), b, rc, hres);
1343 luaV_finishfastset(L, s2v(ra), slot, rc); 1328 if (hres == HOK)
1344 } 1329 luaV_finishfastset(L, s2v(ra), rc);
1345 else { 1330 else {
1346 TValue key; 1331 TValue key;
1347 setivalue(&key, c); 1332 setivalue(&key, b);
1348 Protect(luaV_finishset(L, s2v(ra), &key, rc, slot)); 1333 Protect(luaV_finishset(L, s2v(ra), &key, rc, hres));
1349 } 1334 }
1350 vmbreak; 1335 vmbreak;
1351 } 1336 }
1352 vmcase(OP_SETFIELD) { 1337 vmcase(OP_SETFIELD) {
1353 StkId ra = RA(i); 1338 StkId ra = RA(i);
1354 const TValue *slot; 1339 int hres;
1355 TValue *rb = KB(i); 1340 TValue *rb = KB(i);
1356 TValue *rc = RKC(i); 1341 TValue *rc = RKC(i);
1357 TString *key = tsvalue(rb); /* key must be a short string */ 1342 TString *key = tsvalue(rb); /* key must be a short string */
1358 if (luaV_fastget(L, s2v(ra), key, slot, luaH_getshortstr)) { 1343 luaV_fastset(s2v(ra), key, rc, hres, luaH_psetshortstr);
1359 luaV_finishfastset(L, s2v(ra), slot, rc); 1344 if (hres == HOK)
1360 } 1345 luaV_finishfastset(L, s2v(ra), rc);
1361 else 1346 else
1362 Protect(luaV_finishset(L, s2v(ra), rb, rc, slot)); 1347 Protect(luaV_finishset(L, s2v(ra), rb, rc, hres));
1363 vmbreak; 1348 vmbreak;
1364 } 1349 }
1365 vmcase(OP_NEWTABLE) { 1350 vmcase(OP_NEWTABLE) {
@@ -1383,16 +1368,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1383 } 1368 }
1384 vmcase(OP_SELF) { 1369 vmcase(OP_SELF) {
1385 StkId ra = RA(i); 1370 StkId ra = RA(i);
1386 const TValue *slot; 1371 int hres;
1387 TValue *rb = vRB(i); 1372 TValue *rb = vRB(i);
1388 TValue *rc = RKC(i); 1373 TValue *rc = RKC(i);
1389 TString *key = tsvalue(rc); /* key must be a string */ 1374 TString *key = tsvalue(rc); /* key must be a string */
1390 setobj2s(L, ra + 1, rb); 1375 setobj2s(L, ra + 1, rb);
1391 if (luaV_fastget(L, rb, key, slot, luaH_getstr)) { 1376 luaV_fastget(rb, key, s2v(ra), luaH_getstr, hres);
1392 setobj2s(L, ra, slot); 1377 if (hres != HOK)
1393 } 1378 Protect(luaV_finishget(L, rb, rc, ra, hres));
1394 else
1395 Protect(luaV_finishget(L, rb, rc, ra, slot));
1396 vmbreak; 1379 vmbreak;
1397 } 1380 }
1398 vmcase(OP_ADDI) { 1381 vmcase(OP_ADDI) {
@@ -1873,7 +1856,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1873 luaH_resizearray(L, h, last); /* preallocate it at once */ 1856 luaH_resizearray(L, h, last); /* preallocate it at once */
1874 for (; n > 0; n--) { 1857 for (; n > 0; n--) {
1875 TValue *val = s2v(ra + n); 1858 TValue *val = s2v(ra + n);
1876 setobj2t(L, &h->array[last - 1], val); 1859 obj2arr(h, last, val);
1877 last--; 1860 last--;
1878 luaC_barrierback(L, obj2gco(h), val); 1861 luaC_barrierback(L, obj2gco(h), val);
1879 } 1862 }
diff --git a/lvm.h b/lvm.h
index dba1ad27..c74c81f8 100644
--- a/lvm.h
+++ b/lvm.h
@@ -76,38 +76,43 @@ typedef enum {
76 76
77 77
78/* 78/*
79** fast track for 'gettable': if 't' is a table and 't[k]' is present, 79** fast track for 'gettable'
80** return 1 with 'slot' pointing to 't[k]' (position of final result).
81** Otherwise, return 0 (meaning it will have to check metamethod)
82** with 'slot' pointing to an empty 't[k]' (if 't' is a table) or NULL
83** (otherwise). 'f' is the raw get function to use.
84*/ 80*/
85#define luaV_fastget(L,t,k,slot,f) \ 81#define luaV_fastget(t,k,res,f, aux) \
86 (!ttistable(t) \ 82 (aux = (!ttistable(t) ? HNOTATABLE : f(hvalue(t), k, res)))
87 ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \
88 : (slot = f(hvalue(t), k), /* else, do raw access */ \
89 !isempty(slot))) /* result not empty? */
90 83
91 84
92/* 85/*
93** Special case of 'luaV_fastget' for integers, inlining the fast case 86** Special case of 'luaV_fastget' for integers, inlining the fast case
94** of 'luaH_getint'. 87** of 'luaH_getint'.
95*/ 88*/
96#define luaV_fastgeti(L,t,k,slot) \ 89#define luaV_fastgeti(t,k,res,aux) \
97 (!ttistable(t) \ 90 if (!ttistable(t)) aux = HNOTATABLE; \
98 ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \ 91 else { Table *h = hvalue(t); lua_Unsigned u = l_castS2U(k); \
99 : (slot = (l_castS2U(k) - 1u < hvalue(t)->alimit) \ 92 if ((u - 1u < h->alimit)) { \
100 ? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \ 93 int tag = *getArrTag(h,(u)-1u); \
101 !isempty(slot))) /* result not empty? */ 94 if (tagisempty(tag)) aux = HNOTFOUND; \
95 else { farr2val(h, u, tag, res); aux = HOK; }} \
96 else { aux = luaH_getint(h, u, res); }}
97
98
99#define luaV_fastset(t,k,val,aux,f) \
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); }}
102 110
103 111
104/* 112/*
105** Finish a fast set operation (when fast get succeeds). In that case, 113** Finish a fast set operation (when fast set succeeds).
106** 'slot' points to the place to put the value.
107*/ 114*/
108#define luaV_finishfastset(L,t,slot,v) \ 115#define luaV_finishfastset(L,t,v) luaC_barrierback(L, gcvalue(t), v)
109 { setobj2t(L, cast(TValue *,slot), v); \
110 luaC_barrierback(L, gcvalue(t), v); }
111 116
112 117
113/* 118/*
@@ -126,9 +131,9 @@ LUAI_FUNC int luaV_tointegerns (const TValue *obj, lua_Integer *p,
126 F2Imod mode); 131 F2Imod mode);
127LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode); 132LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode);
128LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key, 133LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key,
129 StkId val, const TValue *slot); 134 StkId val, int aux);
130LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, 135LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
131 TValue *val, const TValue *slot); 136 TValue *val, int aux);
132LUAI_FUNC void luaV_finishOp (lua_State *L); 137LUAI_FUNC void luaV_finishOp (lua_State *L);
133LUAI_FUNC void luaV_execute (lua_State *L, CallInfo *ci); 138LUAI_FUNC void luaV_execute (lua_State *L, CallInfo *ci);
134LUAI_FUNC void luaV_concat (lua_State *L, int total); 139LUAI_FUNC void luaV_concat (lua_State *L, int total);