Skip to content

Commit

Permalink
New way to keep hints for table length
Browse files Browse the repository at this point in the history
Instead of using 'alimit' for keeping the size of the array and at
the same time being a hint for '#t', a table now keeps these two
values separate. The Table structure has a field 'asize' with the
size of the array, while the length hint is kept in the array itself.
That way, tables with no array part waste no space with that field.
Moreover, the space for the hint may have zero cost for small arrays,
if the array of tags plus the hint still fits in a single word.
  • Loading branch information
roberto-ieru committed Nov 29, 2024
1 parent 9329eea commit 002beee
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 249 deletions.
8 changes: 4 additions & 4 deletions lgc.c
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ static void traverseweakvalue (global_State *g, Table *h) {
Node *n, *limit = gnodelast(h);
/* if there is array part, assume it may have white values (it is not
worth traversing it now just to check) */
int hasclears = (h->alimit > 0);
int hasclears = (h->asize > 0);
for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */
if (isempty(gval(n))) /* entry is empty? */
clearkey(n); /* clear its key */
Expand All @@ -508,7 +508,7 @@ static void traverseweakvalue (global_State *g, Table *h) {
** Traverse the array part of a table.
*/
static int traversearray (global_State *g, Table *h) {
unsigned asize = luaH_realasize(h);
unsigned asize = h->asize;
int marked = 0; /* true if some object is marked in this traversal */
unsigned i;
for (i = 0; i < asize; i++) {
Expand Down Expand Up @@ -604,7 +604,7 @@ static l_mem traversetable (global_State *g, Table *h) {
}
else /* not weak */
traversestrongtable(g, h);
return 1 + 2*sizenode(h) + h->alimit;
return 1 + 2*sizenode(h) + h->asize;
}


Expand Down Expand Up @@ -790,7 +790,7 @@ static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) {
Table *h = gco2t(l);
Node *n, *limit = gnodelast(h);
unsigned int i;
unsigned int asize = luaH_realasize(h);
unsigned int asize = h->asize;
for (i = 0; i < asize; i++) {
GCObject *o = gcvalarr(h, i);
if (iscleared(g, o)) /* value was collected? */
Expand Down
16 changes: 2 additions & 14 deletions lobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -763,24 +763,12 @@ typedef union Node {
checkliveness(L,io_); }


/*
** About 'alimit': if 'isrealasize(t)' is true, then 'alimit' is the
** real size of 'array'. Otherwise, the real size of 'array' is the
** smallest power of two not smaller than 'alimit' (or zero iff 'alimit'
** is zero); 'alimit' is then used as a hint for #t.
*/

#define BITRAS (1 << 7)
#define isrealasize(t) (!((t)->flags & BITRAS))
#define setrealasize(t) ((t)->flags &= cast_byte(~BITRAS))
#define setnorealasize(t) ((t)->flags |= BITRAS)


typedef struct Table {
CommonHeader;
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
lu_byte lsizenode; /* log2 of size of 'node' array */
unsigned int alimit; /* "limit" of 'array' array */
lu_byte lsizenode; /* log2 of number of slots of 'node' array */
unsigned int asize; /* number of slots in 'array' array */
Value *array; /* array part */
Node *node;
struct Table *metatable;
Expand Down
Loading

0 comments on commit 002beee

Please sign in to comment.