diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-03-15 11:01:34 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-03-15 11:01:34 -0300 |
| commit | 3823fc6c814d20f2b2a0a1e3be8782084440040f (patch) | |
| tree | cb9b5ef3919dea45cb917ad79cc23c74a3c87681 /ltable.c | |
| parent | 52aa2b5d24c560fb4d7a642971571ff9cbeabfcd (diff) | |
| download | lua-3823fc6c814d20f2b2a0a1e3be8782084440040f.tar.gz lua-3823fc6c814d20f2b2a0a1e3be8782084440040f.tar.bz2 lua-3823fc6c814d20f2b2a0a1e3be8782084440040f.zip | |
Added "bulk operations" to arrays
A few operations on arrays can be performed "in bulk", treating all
tags of a cell as a simple (or a few) word(s).
Diffstat (limited to 'ltable.c')
| -rw-r--r-- | ltable.c | 57 |
1 files changed, 42 insertions, 15 deletions
| @@ -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 | */ | ||
| 660 | static 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 | */ | ||
| 681 | static 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 | */ |
| 669 | void luaH_resize (lua_State *L, Table *t, unsigned int newasize, | 707 | void 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 */ |
