aboutsummaryrefslogtreecommitdiff
path: root/ltable.c
diff options
context:
space:
mode:
Diffstat (limited to 'ltable.c')
-rw-r--r--ltable.c57
1 files changed, 42 insertions, 15 deletions
diff --git a/ltable.c b/ltable.c
index cb7eb648..6eb5f3e3 100644
--- a/ltable.c
+++ b/ltable.c
@@ -654,6 +654,44 @@ static void exchangehashpart (Table *t1, Table *t2) {
654 654
655 655
656/* 656/*
657** Re-insert into the new hash part of a table the elements from the
658** vanishing slice of the array part.
659*/
660static void reinsertOldSlice (lua_State *L, Table *t, unsigned oldasize,
661 unsigned newasize) {
662 unsigned i;
663 t->alimit = newasize; /* pretend array has new size... */
664 for (i = newasize; i < oldasize; i++) { /* traverse vanishing slice */
665 int tag = *getArrTag(t, i);
666 if (!tagisempty(tag)) { /* a non-empty entry? */
667 TValue aux;
668 farr2val(t, i + 1, tag, &aux);
669 luaH_setint(L, t, i + 1, &aux); /* re-insert it into the table */
670 }
671 }
672 t->alimit = oldasize; /* restore current size... */
673}
674
675
676#define BK1(x) cast(lua_Unsigned, ((x) << 8) | LUA_VEMPTY)
677
678/*
679** Clear new slice of the array, in bulk.
680*/
681static void clearNewSlice (Table *t, unsigned oldasize, unsigned newasize) {
682 int i, j;
683 int firstcell = (oldasize + NM - 1) / NM;
684 int lastcell = cast_int((newasize + NM - 1) / NM) - 1;
685 for (i = firstcell; i <= lastcell; i++) {
686 /* empty tag repeated for all tags in a word */
687 const lua_Unsigned empty = BK1(BK1(BK1(BK1(BK1(BK1(BK1(BK1(0))))))));
688 for (j = 0; j < BKSZ; j++)
689 t->array[i].u.bulk[j] = empty;
690 }
691}
692
693
694/*
657** Resize table 't' for the new given sizes. Both allocations (for 695** Resize table 't' for the new given sizes. Both allocations (for
658** the hash part and for the array part) can fail, which creates some 696** the hash part and for the array part) can fail, which creates some
659** subtleties. If the first allocation, for the hash part, fails, an 697** subtleties. If the first allocation, for the hash part, fails, an
@@ -668,7 +706,6 @@ static void exchangehashpart (Table *t1, Table *t2) {
668*/ 706*/
669void luaH_resize (lua_State *L, Table *t, unsigned int newasize, 707void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
670 unsigned int nhsize) { 708 unsigned int nhsize) {
671 unsigned int i;
672 Table newt; /* to keep the new hash part */ 709 Table newt; /* to keep the new hash part */
673 unsigned int oldasize = setlimittosize(t); 710 unsigned int oldasize = setlimittosize(t);
674 ArrayCell *newarray; 711 ArrayCell *newarray;
@@ -678,19 +715,10 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
678 newt.flags = 0; 715 newt.flags = 0;
679 setnodevector(L, &newt, nhsize); 716 setnodevector(L, &newt, nhsize);
680 if (newasize < oldasize) { /* will array shrink? */ 717 if (newasize < oldasize) { /* will array shrink? */
681 t->alimit = newasize; /* pretend array has new size... */
682 exchangehashpart(t, &newt); /* and new hash */
683 /* re-insert into the new hash the elements from vanishing slice */ 718 /* re-insert into the new hash the elements from vanishing slice */
684 for (i = newasize; i < oldasize; i++) { 719 exchangehashpart(t, &newt); /* pretend table has new hash */
685 int tag = *getArrTag(t, i); 720 reinsertOldSlice(L, t, oldasize, newasize);
686 if (!tagisempty(tag)) { /* a non-empty entry? */ 721 exchangehashpart(t, &newt); /* restore old hash (in case of errors) */
687 TValue aux;
688 farr2val(t, i + 1, tag, &aux);
689 luaH_setint(L, t, i + 1, &aux);
690 }
691 }
692 t->alimit = oldasize; /* restore current size... */
693 exchangehashpart(t, &newt); /* and hash (in case of errors) */
694 } 722 }
695 /* allocate new array */ 723 /* allocate new array */
696 newarray = resizearray(L, t, oldasize, newasize); 724 newarray = resizearray(L, t, oldasize, newasize);
@@ -702,8 +730,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
702 exchangehashpart(t, &newt); /* 't' has the new hash ('newt' has the old) */ 730 exchangehashpart(t, &newt); /* 't' has the new hash ('newt' has the old) */
703 t->array = newarray; /* set new array part */ 731 t->array = newarray; /* set new array part */
704 t->alimit = newasize; 732 t->alimit = newasize;
705 for (i = oldasize; i < newasize; i++) /* clear new slice of the array */ 733 clearNewSlice(t, oldasize, newasize);
706 *getArrTag(t, i) = LUA_VEMPTY;
707 /* re-insert elements from old hash part into new parts */ 734 /* re-insert elements from old hash part into new parts */
708 reinsert(L, &newt, t); /* 'newt' now has the old hash */ 735 reinsert(L, &newt, t); /* 'newt' now has the old hash */
709 freehash(L, &newt); /* free old hash part */ 736 freehash(L, &newt); /* free old hash part */