aboutsummaryrefslogtreecommitdiff
path: root/ltable.c
diff options
context:
space:
mode:
Diffstat (limited to 'ltable.c')
-rw-r--r--ltable.c197
1 files changed, 161 insertions, 36 deletions
diff --git a/ltable.c b/ltable.c
index cc98f456..b0d3944d 100644
--- a/ltable.c
+++ b/ltable.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltable.c,v 2.137 2018/05/30 14:25:52 roberto Exp roberto $ 2** $Id: ltable.c,v 2.138 2018/06/01 16:51:34 roberto Exp roberto $
3** Lua tables (hash) 3** Lua tables (hash)
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -193,6 +193,59 @@ static int equalkey (const TValue *k1, const Node *n2) {
193 193
194 194
195/* 195/*
196** True if value of 'alimit' is equal to the real size of the array
197** part of table 't'. (Otherwise, the array part must be larger than
198** 'alimit'.)
199*/
200#define limitequalsasize(t) (isrealasize(t) || ispow2((t)->alimit))
201
202
203/*
204** Returns the real size of the 'array' array
205*/
206LUAI_FUNC unsigned int luaH_realasize (const Table *t) {
207 if (limitequalsasize(t))
208 return t->alimit; /* this is the size */
209 else {
210 unsigned int size = t->alimit;
211 /* compute the smallest power of 2 not smaller than 'n' */
212 size |= (size >> 1);
213 size |= (size >> 2);
214 size |= (size >> 4);
215 size |= (size >> 8);
216 size |= (size >> 16);
217#if (INT_MAX >> 30 >> 1) > 0
218 size |= (size >> 32); /* int has more than 32 bits */
219#endif
220 size++;
221 lua_assert(ispow2(size) && size/2 < t->alimit && t->alimit < size);
222 return size;
223 }
224}
225
226
227/*
228** Check whether real size of the array is a power of 2.
229** (If it is not, 'alimit' cannot be changed to any other value
230** without changing the real size.)
231*/
232static int ispow2realasize (const Table *t) {
233 return (!isrealasize(t) || ispow2(t->alimit));
234}
235
236
237static unsigned int setlimittosize (Table *t) {
238 t->alimit = luaH_realasize(t);
239 setrealasize(t);
240 return t->alimit;
241}
242
243
244#define limitasasize(t) check_exp(isrealasize(t), t->alimit)
245
246
247
248/*
196** "Generic" get version. (Not that generic: not valid for integers, 249** "Generic" get version. (Not that generic: not valid for integers,
197** which may be in array part, nor for floats with integral values.) 250** which may be in array part, nor for floats with integral values.)
198*/ 251*/
@@ -228,11 +281,12 @@ static unsigned int arrayindex (lua_Integer k) {
228** elements in the array part, then elements in the hash part. The 281** elements in the array part, then elements in the hash part. The
229** beginning of a traversal is signaled by 0. 282** beginning of a traversal is signaled by 0.
230*/ 283*/
231static unsigned int findindex (lua_State *L, Table *t, TValue *key) { 284static unsigned int findindex (lua_State *L, Table *t, TValue *key,
285 unsigned int asize) {
232 unsigned int i; 286 unsigned int i;
233 if (ttisnil(key)) return 0; /* first iteration */ 287 if (ttisnil(key)) return 0; /* first iteration */
234 i = ttisinteger(key) ? arrayindex(ivalue(key)) : 0; 288 i = ttisinteger(key) ? arrayindex(ivalue(key)) : 0;
235 if (i != 0 && i <= t->sizearray) /* is 'key' inside array part? */ 289 if (i != 0 && i <= asize) /* is 'key' inside array part? */
236 return i; /* yes; that's the index */ 290 return i; /* yes; that's the index */
237 else { 291 else {
238 const TValue *n = getgeneric(t, key); 292 const TValue *n = getgeneric(t, key);
@@ -240,21 +294,22 @@ static unsigned int findindex (lua_State *L, Table *t, TValue *key) {
240 luaG_runerror(L, "invalid key to 'next'"); /* key not found */ 294 luaG_runerror(L, "invalid key to 'next'"); /* key not found */
241 i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */ 295 i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */
242 /* hash elements are numbered after array ones */ 296 /* hash elements are numbered after array ones */
243 return (i + 1) + t->sizearray; 297 return (i + 1) + asize;
244 } 298 }
245} 299}
246 300
247 301
248int luaH_next (lua_State *L, Table *t, StkId key) { 302int luaH_next (lua_State *L, Table *t, StkId key) {
249 unsigned int i = findindex(L, t, s2v(key)); /* find original element */ 303 unsigned int asize = luaH_realasize(t);
250 for (; i < t->sizearray; i++) { /* try first array part */ 304 unsigned int i = findindex(L, t, s2v(key), asize); /* find original key */
305 for (; i < asize; i++) { /* try first array part */
251 if (!isempty(&t->array[i])) { /* a non-empty entry? */ 306 if (!isempty(&t->array[i])) { /* a non-empty entry? */
252 setivalue(s2v(key), i + 1); 307 setivalue(s2v(key), i + 1);
253 setobj2s(L, key + 1, &t->array[i]); 308 setobj2s(L, key + 1, &t->array[i]);
254 return 1; 309 return 1;
255 } 310 }
256 } 311 }
257 for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) { /* hash part */ 312 for (i -= asize; cast_int(i) < sizenode(t); i++) { /* hash part */
258 if (!isempty(gval(gnode(t, i)))) { /* a non-empty entry? */ 313 if (!isempty(gval(gnode(t, i)))) { /* a non-empty entry? */
259 Node *n = gnode(t, i); 314 Node *n = gnode(t, i);
260 getnodekey(L, s2v(key), n); 315 getnodekey(L, s2v(key), n);
@@ -329,12 +384,13 @@ static unsigned int numusearray (const Table *t, unsigned int *nums) {
329 unsigned int ttlg; /* 2^lg */ 384 unsigned int ttlg; /* 2^lg */
330 unsigned int ause = 0; /* summation of 'nums' */ 385 unsigned int ause = 0; /* summation of 'nums' */
331 unsigned int i = 1; /* count to traverse all array keys */ 386 unsigned int i = 1; /* count to traverse all array keys */
387 unsigned int asize = limitasasize(t); /* real array size */
332 /* traverse each slice */ 388 /* traverse each slice */
333 for (lg = 0, ttlg = 1; lg <= MAXABITS; lg++, ttlg *= 2) { 389 for (lg = 0, ttlg = 1; lg <= MAXABITS; lg++, ttlg *= 2) {
334 unsigned int lc = 0; /* counter */ 390 unsigned int lc = 0; /* counter */
335 unsigned int lim = ttlg; 391 unsigned int lim = ttlg;
336 if (lim > t->sizearray) { 392 if (lim > asize) {
337 lim = t->sizearray; /* adjust upper limit */ 393 lim = asize; /* adjust upper limit */
338 if (i > lim) 394 if (i > lim)
339 break; /* no more elements to count */ 395 break; /* no more elements to count */
340 } 396 }
@@ -451,19 +507,19 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
451 unsigned int nhsize) { 507 unsigned int nhsize) {
452 unsigned int i; 508 unsigned int i;
453 Table newt; /* to keep the new hash part */ 509 Table newt; /* to keep the new hash part */
454 unsigned int oldasize = t->sizearray; 510 unsigned int oldasize = setlimittosize(t);
455 TValue *newarray; 511 TValue *newarray;
456 /* create new hash part with appropriate size into 'newt' */ 512 /* create new hash part with appropriate size into 'newt' */
457 setnodevector(L, &newt, nhsize); 513 setnodevector(L, &newt, nhsize);
458 if (newasize < oldasize) { /* will array shrink? */ 514 if (newasize < oldasize) { /* will array shrink? */
459 t->sizearray = newasize; /* pretend array has new size... */ 515 t->alimit = newasize; /* pretend array has new size... */
460 exchangehashpart(t, &newt); /* and new hash */ 516 exchangehashpart(t, &newt); /* and new hash */
461 /* re-insert into the new hash the elements from vanishing slice */ 517 /* re-insert into the new hash the elements from vanishing slice */
462 for (i = newasize; i < oldasize; i++) { 518 for (i = newasize; i < oldasize; i++) {
463 if (!isempty(&t->array[i])) 519 if (!isempty(&t->array[i]))
464 luaH_setint(L, t, i + 1, &t->array[i]); 520 luaH_setint(L, t, i + 1, &t->array[i]);
465 } 521 }
466 t->sizearray = oldasize; /* restore current size... */ 522 t->alimit = oldasize; /* restore current size... */
467 exchangehashpart(t, &newt); /* and hash (in case of errors) */ 523 exchangehashpart(t, &newt); /* and hash (in case of errors) */
468 } 524 }
469 /* allocate new array */ 525 /* allocate new array */
@@ -475,7 +531,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
475 /* allocation ok; initialize new part of the array */ 531 /* allocation ok; initialize new part of the array */
476 exchangehashpart(t, &newt); /* 't' has the new hash ('newt' has the old) */ 532 exchangehashpart(t, &newt); /* 't' has the new hash ('newt' has the old) */
477 t->array = newarray; /* set new array part */ 533 t->array = newarray; /* set new array part */
478 t->sizearray = newasize; 534 t->alimit = newasize;
479 for (i = oldasize; i < newasize; i++) /* clear new slice of the array */ 535 for (i = oldasize; i < newasize; i++) /* clear new slice of the array */
480 setempty(&t->array[i]); 536 setempty(&t->array[i]);
481 /* re-insert elements from old hash part into new parts */ 537 /* re-insert elements from old hash part into new parts */
@@ -499,6 +555,7 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) {
499 int i; 555 int i;
500 int totaluse; 556 int totaluse;
501 for (i = 0; i <= MAXABITS; i++) nums[i] = 0; /* reset counts */ 557 for (i = 0; i <= MAXABITS; i++) nums[i] = 0; /* reset counts */
558 setlimittosize(t);
502 na = numusearray(t, nums); /* count keys in array part */ 559 na = numusearray(t, nums); /* count keys in array part */
503 totaluse = na; /* all those keys are integer keys */ 560 totaluse = na; /* all those keys are integer keys */
504 totaluse += numusehash(t, nums, &na); /* count keys in hash part */ 561 totaluse += numusehash(t, nums, &na); /* count keys in hash part */
@@ -525,7 +582,7 @@ Table *luaH_new (lua_State *L) {
525 t->metatable = NULL; 582 t->metatable = NULL;
526 t->flags = cast_byte(~0); 583 t->flags = cast_byte(~0);
527 t->array = NULL; 584 t->array = NULL;
528 t->sizearray = 0; 585 t->alimit = 0;
529 setnodevector(L, t, 0); 586 setnodevector(L, t, 0);
530 return t; 587 return t;
531} 588}
@@ -533,7 +590,7 @@ Table *luaH_new (lua_State *L) {
533 590
534void luaH_free (lua_State *L, Table *t) { 591void luaH_free (lua_State *L, Table *t) {
535 freehash(L, t); 592 freehash(L, t);
536 luaM_freearray(L, t->array, t->sizearray); 593 luaM_freearray(L, t->array, luaH_realasize(t));
537 luaM_free(L, t); 594 luaM_free(L, t);
538} 595}
539 596
@@ -613,12 +670,21 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
613 670
614 671
615/* 672/*
616** search function for integers 673** Search function for integers. If integer is inside 'alimit', get it
674** directly from the array part. Otherwise, if 'alimit' is not equal to
675** the real size of the array, key still can be in the array part. In
676** this case, try to avoid a call to 'luaH_realasize' when key is just
677** one more than the limit (so that it can be incremented without
678** changing the real size of the array).
617*/ 679*/
618const TValue *luaH_getint (Table *t, lua_Integer key) { 680const TValue *luaH_getint (Table *t, lua_Integer key) {
619 /* (1 <= key && key <= t->sizearray) */ 681 if (l_castS2U(key) - 1u < t->alimit) /* (1 <= key && key <= t->alimit)? */
620 if (l_castS2U(key) - 1u < t->sizearray)
621 return &t->array[key - 1]; 682 return &t->array[key - 1];
683 else if (!limitequalsasize(t) && /* key still may be in the array part? */
684 (key == t->alimit + 1 || l_castS2U(key) - 1u < luaH_realasize(t))) {
685 t->alimit = cast_uint(key); /* probably '#t' is here now */
686 return &t->array[key - 1];
687 }
622 else { 688 else {
623 Node *n = hashint(t, key); 689 Node *n = hashint(t, key);
624 for (;;) { /* check whether 'key' is somewhere in the chain */ 690 for (;;) { /* check whether 'key' is somewhere in the chain */
@@ -749,33 +815,92 @@ static lua_Unsigned hash_search (Table *t, lua_Unsigned j) {
749} 815}
750 816
751 817
818static unsigned int binsearch (const TValue *array, unsigned int i,
819 unsigned int j) {
820 while (j - i > 1u) { /* binary search */
821 unsigned int m = (i + j) / 2;
822 if (isempty(&array[m - 1])) j = m;
823 else i = m;
824 }
825 return i;
826}
827
828
752/* 829/*
753** Try to find a boundary in table 't'. (A 'boundary' is an integer index 830** Try to find a boundary in table 't'. (A 'boundary' is an integer index
754** such that t[i] is present and t[i+1] is absent, or 0 if t[1] is absent 831** such that t[i] is present and t[i+1] is absent, or 0 if t[1] is absent
755** and 'maxinteger' if t[maxinteger] is present.) 832** and 'maxinteger' if t[maxinteger] is present.)
756** First, try the array part: if there is an array part and its last 833** (In the next explanation, we use Lua indices, that is, with base 1.
757** element is absent, there must be a boundary there; a binary search 834** The code itself uses base 0 when indexing the array part of the table.)
758** finds that boundary. Otherwise, if the hash part is empty or does not 835** The code starts with 'limit', a position in the array part that may
759** contain 'j + 1', 'j' is a boundary. Otherwize, call 'hash_search' 836** be a boundary.
760** to find a boundary in the hash part. 837** (1) If 't[limit]' is empty, there must be a boundary before it.
838** As a common case (e.g., after 't[#t]=nil'), check whether 'hint-1'
839** is present. If so, it is a boundary. Otherwise, do a binary search
840** between 0 and limit to find a boundary. In both cases, try to
841** use this boundary as the new 'limit', as a hint for the next call.
842** (2) If 't[limit]' is not empty and the array has more elements
843** after 'limit', try to find a boundary there. Again, try first
844** the special case (which should be quite frequent) where 'limit+1'
845** is empty, so that 'limit' is a boundary. Otherwise, check the
846** last element of the array part (set it as a new limit). If it is empty,
847** there must be a boundary between the old limit (present) and the new
848** limit (absent), which is found with a binary search. (This boundary
849** always can be a new limit.)
850** (3) The last case is when there are no elements in the array part
851** (limit == 0) or its last element (the new limit) is present.
852** In this case, must check the hash part. If there is no hash part,
853** the boundary is 0. Otherwise, if 'limit+1' is absent, 'limit' is
854** a boundary. Finally, if 'limit+1' is present, call 'hash_search'
855** to find a boundary in the hash part of the table. (In those
856** cases, the boundary is not inside the array part, and therefore
857** cannot be used as a new limit.)
761*/ 858*/
762lua_Unsigned luaH_getn (Table *t) { 859lua_Unsigned luaH_getn (Table *t) {
763 unsigned int j = t->sizearray; 860 unsigned int limit = t->alimit;
764 if (j > 0 && isempty(&t->array[j - 1])) { 861 if (limit > 0 && isempty(&t->array[limit - 1])) {
765 unsigned int i = 0; 862 /* (1) there must be a boundary before 'limit' */
766 while (j - i > 1u) { /* binary search */ 863 if (limit >= 2 && !isempty(&t->array[limit - 2])) {
767 unsigned int m = (i + j) / 2; 864 /* 'limit - 1' is a boundary; can it be a new limit? */
768 if (isempty(&t->array[m - 1])) j = m; 865 if (ispow2realasize(t) && !ispow2(limit - 1)) {
769 else i = m; 866 t->alimit = limit - 1;
867 setnorealasize(t);
868 }
869 return limit - 1;
870 }
871 else { /* must search for a boundary in [0, limit] */
872 unsigned int boundary = binsearch(t->array, 0, limit);
873 /* can this boundary represent the real size of the array? */
874 if (ispow2realasize(t) && boundary > luaH_realasize(t) / 2) {
875 t->alimit = boundary; /* use it as the new limit */
876 setnorealasize(t);
877 }
878 return boundary;
770 } 879 }
771 return i;
772 } 880 }
773 else { /* 'j' is zero or present in table */ 881 /* 'limit' is zero or present in table */
774 if (isdummy(t) || isempty(luaH_getint(t, cast(lua_Integer, j + 1)))) 882 if (!limitequalsasize(t)) {
775 return j; /* 'j + 1' is absent... */ 883 /* (2) 'limit' > 0 and array has more elements after 'limit' */
776 else /* 'j + 1' is also present */ 884 if (isempty(&t->array[limit])) /* 'limit + 1' is empty? */
777 return hash_search(t, j); 885 return limit; /* this is the boundary */
886 /* else, try last element in the array */
887 limit = luaH_realasize(t);
888 if (isempty(&t->array[limit - 1])) { /* empty? */
889 /* there must be a boundary in the array after old limit,
890 and it must be a valid new limit */
891 unsigned int boundary = binsearch(t->array, t->alimit, limit);
892 t->alimit = boundary;
893 return boundary;
894 }
895 /* else, new limit is present in the table; check the hash part */
778 } 896 }
897 /* (3) 'limit' is the last element and either is zero or present in table */
898 lua_assert(limit == luaH_realasize(t) &&
899 (limit == 0 || !isempty(&t->array[limit - 1])));
900 if (isdummy(t) || isempty(luaH_getint(t, cast(lua_Integer, limit + 1))))
901 return limit; /* 'limit + 1' is absent... */
902 else /* 'limit + 1' is also present */
903 return hash_search(t, limit);
779} 904}
780 905
781 906