aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lgc.c15
-rw-r--r--lobject.h17
-rw-r--r--ltable.c197
-rw-r--r--ltable.h3
-rw-r--r--ltests.c15
-rw-r--r--lvm.c4
-rw-r--r--lvm.h4
7 files changed, 201 insertions, 54 deletions
diff --git a/lgc.c b/lgc.c
index 2e401cbd..b0e3c363 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.252 2018/02/26 13:35:03 roberto Exp roberto $ 2** $Id: lgc.c,v 2.253 2018/03/16 14:22:09 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -398,7 +398,7 @@ static void traverseweakvalue (global_State *g, Table *h) {
398 Node *n, *limit = gnodelast(h); 398 Node *n, *limit = gnodelast(h);
399 /* if there is array part, assume it may have white values (it is not 399 /* if there is array part, assume it may have white values (it is not
400 worth traversing it now just to check) */ 400 worth traversing it now just to check) */
401 int hasclears = (h->sizearray > 0); 401 int hasclears = (h->alimit > 0);
402 for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ 402 for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */
403 if (isempty(gval(n))) /* entry is empty? */ 403 if (isempty(gval(n))) /* entry is empty? */
404 clearkey(n); /* clear its key */ 404 clearkey(n); /* clear its key */
@@ -433,8 +433,9 @@ static int traverseephemeron (global_State *g, Table *h) {
433 int hasww = 0; /* true if table has entry "white-key -> white-value" */ 433 int hasww = 0; /* true if table has entry "white-key -> white-value" */
434 Node *n, *limit = gnodelast(h); 434 Node *n, *limit = gnodelast(h);
435 unsigned int i; 435 unsigned int i;
436 unsigned int asize = luaH_realasize(h);
436 /* traverse array part */ 437 /* traverse array part */
437 for (i = 0; i < h->sizearray; i++) { 438 for (i = 0; i < asize; i++) {
438 if (valiswhite(&h->array[i])) { 439 if (valiswhite(&h->array[i])) {
439 marked = 1; 440 marked = 1;
440 reallymarkobject(g, gcvalue(&h->array[i])); 441 reallymarkobject(g, gcvalue(&h->array[i]));
@@ -472,7 +473,8 @@ static int traverseephemeron (global_State *g, Table *h) {
472static void traversestrongtable (global_State *g, Table *h) { 473static void traversestrongtable (global_State *g, Table *h) {
473 Node *n, *limit = gnodelast(h); 474 Node *n, *limit = gnodelast(h);
474 unsigned int i; 475 unsigned int i;
475 for (i = 0; i < h->sizearray; i++) /* traverse array part */ 476 unsigned int asize = luaH_realasize(h);
477 for (i = 0; i < asize; i++) /* traverse array part */
476 markvalue(g, &h->array[i]); 478 markvalue(g, &h->array[i]);
477 for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ 479 for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */
478 if (isempty(gval(n))) /* entry is empty? */ 480 if (isempty(gval(n))) /* entry is empty? */
@@ -508,7 +510,7 @@ static lu_mem traversetable (global_State *g, Table *h) {
508 } 510 }
509 else /* not weak */ 511 else /* not weak */
510 traversestrongtable(g, h); 512 traversestrongtable(g, h);
511 return 1 + h->sizearray + 2 * allocsizenode(h); 513 return 1 + h->alimit + 2 * allocsizenode(h);
512} 514}
513 515
514 516
@@ -719,7 +721,8 @@ static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) {
719 Table *h = gco2t(l); 721 Table *h = gco2t(l);
720 Node *n, *limit = gnodelast(h); 722 Node *n, *limit = gnodelast(h);
721 unsigned int i; 723 unsigned int i;
722 for (i = 0; i < h->sizearray; i++) { 724 unsigned int asize = luaH_realasize(h);
725 for (i = 0; i < asize; i++) {
723 TValue *o = &h->array[i]; 726 TValue *o = &h->array[i];
724 if (iscleared(g, gcvalueN(o))) /* value was collected? */ 727 if (iscleared(g, gcvalueN(o))) /* value was collected? */
725 setempty(o); /* remove entry */ 728 setempty(o); /* remove entry */
diff --git a/lobject.h b/lobject.h
index da896662..7c2b3f84 100644
--- a/lobject.h
+++ b/lobject.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lobject.h,v 2.143 2018/06/01 16:51:34 roberto Exp roberto $ 2** $Id: lobject.h,v 2.144 2018/06/01 17:40:38 roberto Exp roberto $
3** Type definitions for Lua objects 3** Type definitions for Lua objects
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -669,11 +669,24 @@ typedef union Node {
669 (void)L; checkliveness(L,io_); } 669 (void)L; checkliveness(L,io_); }
670 670
671 671
672/*
673** About 'alimit': if 'isrealasize(t)' is true, then 'alimit' is the
674** real size of 'array'. Otherwise, the real size of 'array' is the
675** smallest power of two not smaller than 'alimit' (or zero iff 'alimit'
676** is zero); 'alimit' is then used as a hint for #t.
677*/
678
679#define BITRAS (1 << 7)
680#define isrealasize(t) (!((t)->marked & BITRAS))
681#define setrealasize(t) ((t)->marked &= cast_byte(~BITRAS))
682#define setnorealasize(t) ((t)->marked |= BITRAS)
683
684
672typedef struct Table { 685typedef struct Table {
673 CommonHeader; 686 CommonHeader;
674 lu_byte flags; /* 1<<p means tagmethod(p) is not present */ 687 lu_byte flags; /* 1<<p means tagmethod(p) is not present */
675 lu_byte lsizenode; /* log2 of size of 'node' array */ 688 lu_byte lsizenode; /* log2 of size of 'node' array */
676 unsigned int sizearray; /* size of 'array' array */ 689 unsigned int alimit; /* "limit" of 'array' array */
677 TValue *array; /* array part */ 690 TValue *array; /* array part */
678 Node *node; 691 Node *node;
679 Node *lastfree; /* any free position is before this position */ 692 Node *lastfree; /* any free position is before this position */
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
diff --git a/ltable.h b/ltable.h
index 9b1a3464..ba2dddc8 100644
--- a/ltable.h
+++ b/ltable.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltable.h,v 2.26 2018/02/23 13:13:31 roberto Exp roberto $ 2** $Id: ltable.h,v 2.27 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*/
@@ -45,6 +45,7 @@ LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize);
45LUAI_FUNC void luaH_free (lua_State *L, Table *t); 45LUAI_FUNC void luaH_free (lua_State *L, Table *t);
46LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); 46LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
47LUAI_FUNC lua_Unsigned luaH_getn (Table *t); 47LUAI_FUNC lua_Unsigned luaH_getn (Table *t);
48LUAI_FUNC unsigned int luaH_realasize (const Table *t);
48 49
49 50
50#if defined(LUA_DEBUG) 51#if defined(LUA_DEBUG)
diff --git a/ltests.c b/ltests.c
index 452785c3..82d6463a 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 2.243 2018/03/09 19:24:45 roberto Exp roberto $ 2** $Id: ltests.c,v 2.244 2018/06/11 14:19:50 roberto Exp roberto $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -248,10 +248,11 @@ static void checkvalref (global_State *g, GCObject *f, const TValue *t) {
248 248
249static void checktable (global_State *g, Table *h) { 249static void checktable (global_State *g, Table *h) {
250 unsigned int i; 250 unsigned int i;
251 unsigned int asize = luaH_realasize(h);
251 Node *n, *limit = gnode(h, sizenode(h)); 252 Node *n, *limit = gnode(h, sizenode(h));
252 GCObject *hgc = obj2gco(h); 253 GCObject *hgc = obj2gco(h);
253 checkobjref(g, hgc, h->metatable); 254 checkobjref(g, hgc, h->metatable);
254 for (i = 0; i < h->sizearray; i++) 255 for (i = 0; i < asize; i++)
255 checkvalref(g, hgc, &h->array[i]); 256 checkvalref(g, hgc, &h->array[i]);
256 for (n = gnode(h, 0); n < limit; n++) { 257 for (n = gnode(h, 0); n < limit; n++) {
257 if (!isempty(gval(n))) { 258 if (!isempty(gval(n))) {
@@ -810,19 +811,23 @@ static int stacklevel (lua_State *L) {
810static int table_query (lua_State *L) { 811static int table_query (lua_State *L) {
811 const Table *t; 812 const Table *t;
812 int i = cast_int(luaL_optinteger(L, 2, -1)); 813 int i = cast_int(luaL_optinteger(L, 2, -1));
814 unsigned int asize;
813 luaL_checktype(L, 1, LUA_TTABLE); 815 luaL_checktype(L, 1, LUA_TTABLE);
814 t = hvalue(obj_at(L, 1)); 816 t = hvalue(obj_at(L, 1));
817 asize = luaH_realasize(t);
815 if (i == -1) { 818 if (i == -1) {
816 lua_pushinteger(L, t->sizearray); 819 lua_pushinteger(L, asize);
817 lua_pushinteger(L, allocsizenode(t)); 820 lua_pushinteger(L, allocsizenode(t));
818 lua_pushinteger(L, isdummy(t) ? 0 : t->lastfree - t->node); 821 lua_pushinteger(L, isdummy(t) ? 0 : t->lastfree - t->node);
822 lua_pushinteger(L, t->alimit);
823 return 4;
819 } 824 }
820 else if ((unsigned int)i < t->sizearray) { 825 else if ((unsigned int)i < asize) {
821 lua_pushinteger(L, i); 826 lua_pushinteger(L, i);
822 pushobject(L, &t->array[i]); 827 pushobject(L, &t->array[i]);
823 lua_pushnil(L); 828 lua_pushnil(L);
824 } 829 }
825 else if ((i -= t->sizearray) < sizenode(t)) { 830 else if ((i -= asize) < sizenode(t)) {
826 TValue k; 831 TValue k;
827 getnodekey(L, &k, gnode(t, i)); 832 getnodekey(L, &k, gnode(t, i));
828 if (!isempty(gval(gnode(t, i))) || 833 if (!isempty(gval(gnode(t, i))) ||
diff --git a/lvm.c b/lvm.c
index 3fed2a27..1e45e2ce 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.356 2018/05/30 14:25:52 roberto Exp roberto $ 2** $Id: lvm.c,v 2.357 2018/06/01 16:51:34 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -1766,7 +1766,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1766 } 1766 }
1767 h = hvalue(s2v(ra)); 1767 h = hvalue(s2v(ra));
1768 last = ((c-1)*LFIELDS_PER_FLUSH) + n; 1768 last = ((c-1)*LFIELDS_PER_FLUSH) + n;
1769 if (last > h->sizearray) /* needs more space? */ 1769 if (last > luaH_realasize(h)) /* needs more space? */
1770 luaH_resizearray(L, h, last); /* preallocate it at once */ 1770 luaH_resizearray(L, h, last); /* preallocate it at once */
1771 for (; n > 0; n--) { 1771 for (; n > 0; n--) {
1772 TValue *val = s2v(ra + n); 1772 TValue *val = s2v(ra + n);
diff --git a/lvm.h b/lvm.h
index c5d5206d..a789acc4 100644
--- a/lvm.h
+++ b/lvm.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.h,v 2.50 2018/02/21 12:54:26 roberto Exp roberto $ 2** $Id: lvm.h,v 2.51 2018/02/23 13:13:31 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -84,7 +84,7 @@
84#define luaV_fastgeti(L,t,k,slot) \ 84#define luaV_fastgeti(L,t,k,slot) \
85 (!ttistable(t) \ 85 (!ttistable(t) \
86 ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \ 86 ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \
87 : (slot = (l_castS2U(k) - 1u < hvalue(t)->sizearray) \ 87 : (slot = (l_castS2U(k) - 1u < hvalue(t)->alimit) \
88 ? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \ 88 ? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \
89 !isempty(slot))) /* result not empty? */ 89 !isempty(slot))) /* result not empty? */
90 90