aboutsummaryrefslogtreecommitdiff
path: root/src/lj_tab.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_tab.c')
-rw-r--r--src/lj_tab.c222
1 files changed, 131 insertions, 91 deletions
diff --git a/src/lj_tab.c b/src/lj_tab.c
index c5b6bcbf..c3609b38 100644
--- a/src/lj_tab.c
+++ b/src/lj_tab.c
@@ -16,25 +16,10 @@
16 16
17/* -- Object hashing ------------------------------------------------------ */ 17/* -- Object hashing ------------------------------------------------------ */
18 18
19/* Hash values are masked with the table hash mask and used as an index. */
20static LJ_AINLINE Node *hashmask(const GCtab *t, uint32_t hash)
21{
22 Node *n = noderef(t->node);
23 return &n[hash & t->hmask];
24}
25
26/* String hashes are precomputed when they are interned. */
27#define hashstr(t, s) hashmask(t, (s)->hash)
28
29#define hashlohi(t, lo, hi) hashmask((t), hashrot((lo), (hi)))
30#define hashnum(t, o) hashlohi((t), (o)->u32.lo, ((o)->u32.hi << 1))
31#define hashptr(t, p) hashlohi((t), u32ptr(p), u32ptr(p) + HASH_BIAS)
32#define hashgcref(t, r) hashlohi((t), gcrefu(r), gcrefu(r) + HASH_BIAS)
33
34/* Hash an arbitrary key and return its anchor position in the hash table. */ 19/* Hash an arbitrary key and return its anchor position in the hash table. */
35static Node *hashkey(const GCtab *t, cTValue *key) 20static Node *hashkey(const GCtab *t, cTValue *key)
36{ 21{
37 lua_assert(!tvisint(key)); 22 lj_assertX(!tvisint(key), "attempt to hash integer");
38 if (tvisstr(key)) 23 if (tvisstr(key))
39 return hashstr(t, strV(key)); 24 return hashstr(t, strV(key));
40 else if (tvisnum(key)) 25 else if (tvisnum(key))
@@ -53,13 +38,13 @@ static LJ_AINLINE void newhpart(lua_State *L, GCtab *t, uint32_t hbits)
53{ 38{
54 uint32_t hsize; 39 uint32_t hsize;
55 Node *node; 40 Node *node;
56 lua_assert(hbits != 0); 41 lj_assertL(hbits != 0, "zero hash size");
57 if (hbits > LJ_MAX_HBITS) 42 if (hbits > LJ_MAX_HBITS)
58 lj_err_msg(L, LJ_ERR_TABOV); 43 lj_err_msg(L, LJ_ERR_TABOV);
59 hsize = 1u << hbits; 44 hsize = 1u << hbits;
60 node = lj_mem_newvec(L, hsize, Node); 45 node = lj_mem_newvec(L, hsize, Node);
61 setmref(node->freetop, &node[hsize]);
62 setmref(t->node, node); 46 setmref(t->node, node);
47 setfreetop(t, node, &node[hsize]);
63 t->hmask = hsize-1; 48 t->hmask = hsize-1;
64} 49}
65 50
@@ -74,7 +59,7 @@ static LJ_AINLINE void clearhpart(GCtab *t)
74{ 59{
75 uint32_t i, hmask = t->hmask; 60 uint32_t i, hmask = t->hmask;
76 Node *node = noderef(t->node); 61 Node *node = noderef(t->node);
77 lua_assert(t->hmask != 0); 62 lj_assertX(t->hmask != 0, "empty hash part");
78 for (i = 0; i <= hmask; i++) { 63 for (i = 0; i <= hmask; i++) {
79 Node *n = &node[i]; 64 Node *n = &node[i];
80 setmref(n->next, NULL); 65 setmref(n->next, NULL);
@@ -98,7 +83,8 @@ static GCtab *newtab(lua_State *L, uint32_t asize, uint32_t hbits)
98 GCtab *t; 83 GCtab *t;
99 /* First try to colocate the array part. */ 84 /* First try to colocate the array part. */
100 if (LJ_MAX_COLOSIZE != 0 && asize > 0 && asize <= LJ_MAX_COLOSIZE) { 85 if (LJ_MAX_COLOSIZE != 0 && asize > 0 && asize <= LJ_MAX_COLOSIZE) {
101 lua_assert((sizeof(GCtab) & 7) == 0); 86 Node *nilnode;
87 lj_assertL((sizeof(GCtab) & 7) == 0, "bad GCtab size");
102 t = (GCtab *)lj_mem_newgco(L, sizetabcolo(asize)); 88 t = (GCtab *)lj_mem_newgco(L, sizetabcolo(asize));
103 t->gct = ~LJ_TTAB; 89 t->gct = ~LJ_TTAB;
104 t->nomm = (uint8_t)~0; 90 t->nomm = (uint8_t)~0;
@@ -107,8 +93,13 @@ static GCtab *newtab(lua_State *L, uint32_t asize, uint32_t hbits)
107 setgcrefnull(t->metatable); 93 setgcrefnull(t->metatable);
108 t->asize = asize; 94 t->asize = asize;
109 t->hmask = 0; 95 t->hmask = 0;
110 setmref(t->node, &G(L)->nilnode); 96 nilnode = &G(L)->nilnode;
97 setmref(t->node, nilnode);
98#if LJ_GC64
99 setmref(t->freetop, nilnode);
100#endif
111 } else { /* Otherwise separately allocate the array part. */ 101 } else { /* Otherwise separately allocate the array part. */
102 Node *nilnode;
112 t = lj_mem_newobj(L, GCtab); 103 t = lj_mem_newobj(L, GCtab);
113 t->gct = ~LJ_TTAB; 104 t->gct = ~LJ_TTAB;
114 t->nomm = (uint8_t)~0; 105 t->nomm = (uint8_t)~0;
@@ -117,7 +108,11 @@ static GCtab *newtab(lua_State *L, uint32_t asize, uint32_t hbits)
117 setgcrefnull(t->metatable); 108 setgcrefnull(t->metatable);
118 t->asize = 0; /* In case the array allocation fails. */ 109 t->asize = 0; /* In case the array allocation fails. */
119 t->hmask = 0; 110 t->hmask = 0;
120 setmref(t->node, &G(L)->nilnode); 111 nilnode = &G(L)->nilnode;
112 setmref(t->node, nilnode);
113#if LJ_GC64
114 setmref(t->freetop, nilnode);
115#endif
121 if (asize > 0) { 116 if (asize > 0) {
122 if (asize > LJ_MAX_ASIZE) 117 if (asize > LJ_MAX_ASIZE)
123 lj_err_msg(L, LJ_ERR_TABOV); 118 lj_err_msg(L, LJ_ERR_TABOV);
@@ -149,6 +144,12 @@ GCtab *lj_tab_new(lua_State *L, uint32_t asize, uint32_t hbits)
149 return t; 144 return t;
150} 145}
151 146
147/* The API of this function conforms to lua_createtable(). */
148GCtab *lj_tab_new_ah(lua_State *L, int32_t a, int32_t h)
149{
150 return lj_tab_new(L, (uint32_t)(a > 0 ? a+1 : 0), hsize2hbits(h));
151}
152
152#if LJ_HASJIT 153#if LJ_HASJIT
153GCtab * LJ_FASTCALL lj_tab_new1(lua_State *L, uint32_t ahsize) 154GCtab * LJ_FASTCALL lj_tab_new1(lua_State *L, uint32_t ahsize)
154{ 155{
@@ -165,7 +166,8 @@ GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt)
165 GCtab *t; 166 GCtab *t;
166 uint32_t asize, hmask; 167 uint32_t asize, hmask;
167 t = newtab(L, kt->asize, kt->hmask > 0 ? lj_fls(kt->hmask)+1 : 0); 168 t = newtab(L, kt->asize, kt->hmask > 0 ? lj_fls(kt->hmask)+1 : 0);
168 lua_assert(kt->asize == t->asize && kt->hmask == t->hmask); 169 lj_assertL(kt->asize == t->asize && kt->hmask == t->hmask,
170 "mismatched size of table and template");
169 t->nomm = 0; /* Keys with metamethod names may be present. */ 171 t->nomm = 0; /* Keys with metamethod names may be present. */
170 asize = kt->asize; 172 asize = kt->asize;
171 if (asize > 0) { 173 if (asize > 0) {
@@ -185,7 +187,7 @@ GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt)
185 Node *node = noderef(t->node); 187 Node *node = noderef(t->node);
186 Node *knode = noderef(kt->node); 188 Node *knode = noderef(kt->node);
187 ptrdiff_t d = (char *)node - (char *)knode; 189 ptrdiff_t d = (char *)node - (char *)knode;
188 setmref(node->freetop, (Node *)((char *)noderef(knode->freetop) + d)); 190 setfreetop(t, node, (Node *)((char *)getfreetop(kt, knode) + d));
189 for (i = 0; i <= hmask; i++) { 191 for (i = 0; i <= hmask; i++) {
190 Node *kn = &knode[i]; 192 Node *kn = &knode[i];
191 Node *n = &node[i]; 193 Node *n = &node[i];
@@ -198,6 +200,17 @@ GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt)
198 return t; 200 return t;
199} 201}
200 202
203/* Clear a table. */
204void LJ_FASTCALL lj_tab_clear(GCtab *t)
205{
206 clearapart(t);
207 if (t->hmask > 0) {
208 Node *node = noderef(t->node);
209 setfreetop(t, node, &node[t->hmask+1]);
210 clearhpart(t);
211 }
212}
213
201/* Free a table. */ 214/* Free a table. */
202void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t) 215void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t)
203{ 216{
@@ -214,7 +227,7 @@ void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t)
214/* -- Table resizing ------------------------------------------------------ */ 227/* -- Table resizing ------------------------------------------------------ */
215 228
216/* Resize a table to fit the new array/hash part sizes. */ 229/* Resize a table to fit the new array/hash part sizes. */
217static void resizetab(lua_State *L, GCtab *t, uint32_t asize, uint32_t hbits) 230void lj_tab_resize(lua_State *L, GCtab *t, uint32_t asize, uint32_t hbits)
218{ 231{
219 Node *oldnode = noderef(t->node); 232 Node *oldnode = noderef(t->node);
220 uint32_t oldasize = t->asize; 233 uint32_t oldasize = t->asize;
@@ -247,6 +260,9 @@ static void resizetab(lua_State *L, GCtab *t, uint32_t asize, uint32_t hbits)
247 } else { 260 } else {
248 global_State *g = G(L); 261 global_State *g = G(L);
249 setmref(t->node, &g->nilnode); 262 setmref(t->node, &g->nilnode);
263#if LJ_GC64
264 setmref(t->freetop, &g->nilnode);
265#endif
250 t->hmask = 0; 266 t->hmask = 0;
251 } 267 }
252 if (asize < oldasize) { /* Array part shrinks? */ 268 if (asize < oldasize) { /* Array part shrinks? */
@@ -276,7 +292,7 @@ static void resizetab(lua_State *L, GCtab *t, uint32_t asize, uint32_t hbits)
276 292
277static uint32_t countint(cTValue *key, uint32_t *bins) 293static uint32_t countint(cTValue *key, uint32_t *bins)
278{ 294{
279 lua_assert(!tvisint(key)); 295 lj_assertX(!tvisint(key), "bad integer key");
280 if (tvisnum(key)) { 296 if (tvisnum(key)) {
281 lua_Number nk = numV(key); 297 lua_Number nk = numV(key);
282 int32_t k = lj_num2int(nk); 298 int32_t k = lj_num2int(nk);
@@ -348,7 +364,7 @@ static void rehashtab(lua_State *L, GCtab *t, cTValue *ek)
348 asize += countint(ek, bins); 364 asize += countint(ek, bins);
349 na = bestasize(bins, &asize); 365 na = bestasize(bins, &asize);
350 total -= na; 366 total -= na;
351 resizetab(L, t, asize, hsize2hbits(total)); 367 lj_tab_resize(L, t, asize, hsize2hbits(total));
352} 368}
353 369
354#if LJ_HASFFI 370#if LJ_HASFFI
@@ -360,7 +376,7 @@ void lj_tab_rehash(lua_State *L, GCtab *t)
360 376
361void lj_tab_reasize(lua_State *L, GCtab *t, uint32_t nasize) 377void lj_tab_reasize(lua_State *L, GCtab *t, uint32_t nasize)
362{ 378{
363 resizetab(L, t, nasize+1, t->hmask > 0 ? lj_fls(t->hmask)+1 : 0); 379 lj_tab_resize(L, t, nasize+1, t->hmask > 0 ? lj_fls(t->hmask)+1 : 0);
364} 380}
365 381
366/* -- Table getters ------------------------------------------------------- */ 382/* -- Table getters ------------------------------------------------------- */
@@ -378,7 +394,7 @@ cTValue * LJ_FASTCALL lj_tab_getinth(GCtab *t, int32_t key)
378 return NULL; 394 return NULL;
379} 395}
380 396
381cTValue *lj_tab_getstr(GCtab *t, GCstr *key) 397cTValue *lj_tab_getstr(GCtab *t, const GCstr *key)
382{ 398{
383 Node *n = hashstr(t, key); 399 Node *n = hashstr(t, key);
384 do { 400 do {
@@ -428,16 +444,17 @@ TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key)
428 Node *n = hashkey(t, key); 444 Node *n = hashkey(t, key);
429 if (!tvisnil(&n->val) || t->hmask == 0) { 445 if (!tvisnil(&n->val) || t->hmask == 0) {
430 Node *nodebase = noderef(t->node); 446 Node *nodebase = noderef(t->node);
431 Node *collide, *freenode = noderef(nodebase->freetop); 447 Node *collide, *freenode = getfreetop(t, nodebase);
432 lua_assert(freenode >= nodebase && freenode <= nodebase+t->hmask+1); 448 lj_assertL(freenode >= nodebase && freenode <= nodebase+t->hmask+1,
449 "bad freenode");
433 do { 450 do {
434 if (freenode == nodebase) { /* No free node found? */ 451 if (freenode == nodebase) { /* No free node found? */
435 rehashtab(L, t, key); /* Rehash table. */ 452 rehashtab(L, t, key); /* Rehash table. */
436 return lj_tab_set(L, t, key); /* Retry key insertion. */ 453 return lj_tab_set(L, t, key); /* Retry key insertion. */
437 } 454 }
438 } while (!tvisnil(&(--freenode)->key)); 455 } while (!tvisnil(&(--freenode)->key));
439 setmref(nodebase->freetop, freenode); 456 setfreetop(t, nodebase, freenode);
440 lua_assert(freenode != &G(L)->nilnode); 457 lj_assertL(freenode != &G(L)->nilnode, "store to fallback hash");
441 collide = hashkey(t, &n->key); 458 collide = hashkey(t, &n->key);
442 if (collide != n) { /* Colliding node not the main node? */ 459 if (collide != n) { /* Colliding node not the main node? */
443 while (noderef(collide->next) != n) /* Find predecessor. */ 460 while (noderef(collide->next) != n) /* Find predecessor. */
@@ -493,7 +510,7 @@ TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key)
493 if (LJ_UNLIKELY(tvismzero(&n->key))) 510 if (LJ_UNLIKELY(tvismzero(&n->key)))
494 n->key.u64 = 0; 511 n->key.u64 = 0;
495 lj_gc_anybarriert(L, t); 512 lj_gc_anybarriert(L, t);
496 lua_assert(tvisnil(&n->val)); 513 lj_assertL(tvisnil(&n->val), "new hash slot is not empty");
497 return &n->val; 514 return &n->val;
498} 515}
499 516
@@ -510,7 +527,7 @@ TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key)
510 return lj_tab_newkey(L, t, &k); 527 return lj_tab_newkey(L, t, &k);
511} 528}
512 529
513TValue *lj_tab_setstr(lua_State *L, GCtab *t, GCstr *key) 530TValue *lj_tab_setstr(lua_State *L, GCtab *t, const GCstr *key)
514{ 531{
515 TValue k; 532 TValue k;
516 Node *n = hashstr(t, key); 533 Node *n = hashstr(t, key);
@@ -551,103 +568,126 @@ TValue *lj_tab_set(lua_State *L, GCtab *t, cTValue *key)
551 568
552/* -- Table traversal ----------------------------------------------------- */ 569/* -- Table traversal ----------------------------------------------------- */
553 570
554/* Get the traversal index of a key. */ 571/* Table traversal indexes:
555static uint32_t keyindex(lua_State *L, GCtab *t, cTValue *key) 572**
573** Array key index: [0 .. t->asize-1]
574** Hash key index: [t->asize .. t->asize+t->hmask]
575** Invalid key: ~0
576*/
577
578/* Get the successor traversal index of a key. */
579uint32_t LJ_FASTCALL lj_tab_keyindex(GCtab *t, cTValue *key)
556{ 580{
557 TValue tmp; 581 TValue tmp;
558 if (tvisint(key)) { 582 if (tvisint(key)) {
559 int32_t k = intV(key); 583 int32_t k = intV(key);
560 if ((uint32_t)k < t->asize) 584 if ((uint32_t)k < t->asize)
561 return (uint32_t)k; /* Array key indexes: [0..t->asize-1] */ 585 return (uint32_t)k + 1;
562 setnumV(&tmp, (lua_Number)k); 586 setnumV(&tmp, (lua_Number)k);
563 key = &tmp; 587 key = &tmp;
564 } else if (tvisnum(key)) { 588 } else if (tvisnum(key)) {
565 lua_Number nk = numV(key); 589 lua_Number nk = numV(key);
566 int32_t k = lj_num2int(nk); 590 int32_t k = lj_num2int(nk);
567 if ((uint32_t)k < t->asize && nk == (lua_Number)k) 591 if ((uint32_t)k < t->asize && nk == (lua_Number)k)
568 return (uint32_t)k; /* Array key indexes: [0..t->asize-1] */ 592 return (uint32_t)k + 1;
569 } 593 }
570 if (!tvisnil(key)) { 594 if (!tvisnil(key)) {
571 Node *n = hashkey(t, key); 595 Node *n = hashkey(t, key);
572 do { 596 do {
573 if (lj_obj_equal(&n->key, key)) 597 if (lj_obj_equal(&n->key, key))
574 return t->asize + (uint32_t)(n - noderef(t->node)); 598 return t->asize + (uint32_t)((n+1) - noderef(t->node));
575 /* Hash key indexes: [t->asize..t->asize+t->nmask] */
576 } while ((n = nextnode(n))); 599 } while ((n = nextnode(n)));
577 if (key->u32.hi == 0xfffe7fff) /* ITERN was despecialized while running. */ 600 if (key->u32.hi == LJ_KEYINDEX) /* Despecialized ITERN while running. */
578 return key->u32.lo - 1; 601 return key->u32.lo;
579 lj_err_msg(L, LJ_ERR_NEXTIDX); 602 return ~0u; /* Invalid key to next. */
580 return 0; /* unreachable */
581 } 603 }
582 return ~0u; /* A nil key starts the traversal. */ 604 return 0; /* A nil key starts the traversal. */
583} 605}
584 606
585/* Advance to the next step in a table traversal. */ 607/* Get the next key/value pair of a table traversal. */
586int lj_tab_next(lua_State *L, GCtab *t, TValue *key) 608int lj_tab_next(GCtab *t, cTValue *key, TValue *o)
587{ 609{
588 uint32_t i = keyindex(L, t, key); /* Find predecessor key index. */ 610 uint32_t idx = lj_tab_keyindex(t, key); /* Find successor index of key. */
589 for (i++; i < t->asize; i++) /* First traverse the array keys. */ 611 /* First traverse the array part. */
590 if (!tvisnil(arrayslot(t, i))) { 612 for (; idx < t->asize; idx++) {
591 setintV(key, i); 613 cTValue *a = arrayslot(t, idx);
592 copyTV(L, key+1, arrayslot(t, i)); 614 if (LJ_LIKELY(!tvisnil(a))) {
615 setintV(o, idx);
616 o[1] = *a;
593 return 1; 617 return 1;
594 } 618 }
595 for (i -= t->asize; i <= t->hmask; i++) { /* Then traverse the hash keys. */ 619 }
596 Node *n = &noderef(t->node)[i]; 620 idx -= t->asize;
621 /* Then traverse the hash part. */
622 for (; idx <= t->hmask; idx++) {
623 Node *n = &noderef(t->node)[idx];
597 if (!tvisnil(&n->val)) { 624 if (!tvisnil(&n->val)) {
598 copyTV(L, key, &n->key); 625 o[0] = n->key;
599 copyTV(L, key+1, &n->val); 626 o[1] = n->val;
600 return 1; 627 return 1;
601 } 628 }
602 } 629 }
603 return 0; /* End of traversal. */ 630 return (int32_t)idx < 0 ? -1 : 0; /* Invalid key or end of traversal. */
604} 631}
605 632
606/* -- Table length calculation -------------------------------------------- */ 633/* -- Table length calculation -------------------------------------------- */
607 634
608static MSize unbound_search(GCtab *t, MSize j) 635/* Compute table length. Slow path with mixed array/hash lookups. */
636LJ_NOINLINE static MSize tab_len_slow(GCtab *t, size_t hi)
609{ 637{
610 cTValue *tv; 638 cTValue *tv;
611 MSize i = j; /* i is zero or a present index */ 639 size_t lo = hi;
612 j++; 640 hi++;
613 /* find `i' and `j' such that i is present and j is not */ 641 /* Widening search for an upper bound. */
614 while ((tv = lj_tab_getint(t, (int32_t)j)) && !tvisnil(tv)) { 642 while ((tv = lj_tab_getint(t, (int32_t)hi)) && !tvisnil(tv)) {
615 i = j; 643 lo = hi;
616 j *= 2; 644 hi += hi;
617 if (j > (MSize)(INT_MAX-2)) { /* overflow? */ 645 if (hi > (size_t)(INT_MAX-2)) { /* Punt and do a linear search. */
618 /* table was built with bad purposes: resort to linear search */ 646 lo = 1;
619 i = 1; 647 while ((tv = lj_tab_getint(t, (int32_t)lo)) && !tvisnil(tv)) lo++;
620 while ((tv = lj_tab_getint(t, (int32_t)i)) && !tvisnil(tv)) i++; 648 return (MSize)(lo - 1);
621 return i - 1;
622 } 649 }
623 } 650 }
624 /* now do a binary search between them */ 651 /* Binary search to find a non-nil to nil transition. */
625 while (j - i > 1) { 652 while (hi - lo > 1) {
626 MSize m = (i+j)/2; 653 size_t mid = (lo+hi) >> 1;
627 cTValue *tvb = lj_tab_getint(t, (int32_t)m); 654 cTValue *tvb = lj_tab_getint(t, (int32_t)mid);
628 if (tvb && !tvisnil(tvb)) i = m; else j = m; 655 if (tvb && !tvisnil(tvb)) lo = mid; else hi = mid;
629 } 656 }
630 return i; 657 return (MSize)lo;
631} 658}
632 659
633/* 660/* Compute table length. Fast path. */
634** Try to find a boundary in table `t'. A `boundary' is an integer index
635** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
636*/
637MSize LJ_FASTCALL lj_tab_len(GCtab *t) 661MSize LJ_FASTCALL lj_tab_len(GCtab *t)
638{ 662{
639 MSize j = (MSize)t->asize; 663 size_t hi = (size_t)t->asize;
640 if (j > 1 && tvisnil(arrayslot(t, j-1))) { 664 if (hi) hi--;
641 MSize i = 1; 665 /* In a growing array the last array element is very likely nil. */
642 while (j - i > 1) { 666 if (hi > 0 && LJ_LIKELY(tvisnil(arrayslot(t, hi)))) {
643 MSize m = (i+j)/2; 667 /* Binary search to find a non-nil to nil transition in the array. */
644 if (tvisnil(arrayslot(t, m-1))) j = m; else i = m; 668 size_t lo = 0;
669 while (hi - lo > 1) {
670 size_t mid = (lo+hi) >> 1;
671 if (tvisnil(arrayslot(t, mid))) hi = mid; else lo = mid;
645 } 672 }
646 return i-1; 673 return (MSize)lo;
647 } 674 }
648 if (j) j--; 675 /* Without a hash part, there's an implicit nil after the last element. */
649 if (t->hmask <= 0) 676 return t->hmask ? tab_len_slow(t, hi) : (MSize)hi;
650 return j;
651 return unbound_search(t, j);
652} 677}
653 678
679#if LJ_HASJIT
680/* Verify hinted table length or compute it. */
681MSize LJ_FASTCALL lj_tab_len_hint(GCtab *t, size_t hint)
682{
683 size_t asize = (size_t)t->asize;
684 cTValue *tv = arrayslot(t, hint);
685 if (LJ_LIKELY(hint+1 < asize)) {
686 if (LJ_LIKELY(!tvisnil(tv) && tvisnil(tv+1))) return (MSize)hint;
687 } else if (hint+1 <= asize && LJ_LIKELY(t->hmask == 0) && !tvisnil(tv)) {
688 return (MSize)hint;
689 }
690 return lj_tab_len(t);
691}
692#endif
693