Without this extra space, sequences of insertions/deletions (and
some other uses) can have unpexpected low performances. See the
added tests for an example, and *Mathematical Models to Analyze Lua
Hybrid Tables and Why They Need a Fix* (Martínez, Nicaud, Rotondo;
arXiv:2208.13602v2) for detais.
Array part needs 1/3 of its elements filled, instead of 1/2.
Array entries use ~1/3 the memory of hash entries, so this new rule
still ensures that array parts do not use more memory than keeping
the values in the hash, while allowing more uses of the array part,
which is more efficient than the hash.
If there are no integer keys outside the array part, there is no
reason to resize it, saving the time to count its elements. Moreover,
assignments to non-integer keys will not collapse a table created with
'table.create'.
Undoing previous commit. Returning TValue increases code size without
any visible gains. Returning the tag is a little simpler than returning
a special code (HOK/HNOTFOUND) and the tag is useful by itself in
some cases.
Instead of receiving a parameter telling them where to put the result
of the query, these functions return the TValue directly. (That is,
they return a structure.)
Avoid silent conversions from int to unsigned int when calling
'luaH_resize'; avoid silent conversions from lua_Integer to int in
'table.create'; MAXASIZE corrected for the new implementation of arrays;
'luaH_resize' checks explicitly whether new size respects MAXASIZE.
(Even constructors were bypassing that check.)
It is quite common to write to empty but existing cells in the array
part of a table, so 'luaH_psetint' checks for the common case that
the table doesn't have a newindex metamethod to complete the write.
'lua_rawgeti' now uses "fast track"; 'lua_rawseti' still calls
'luaH_setint', but the latter was recoded to avoid extra overhead
when writing to the array part after 'alimit'.
The array part of a table wastes too much space, due to padding.
To avoid that, we need to store values in the array as something
different from a TValue. Therefore, the API for table access
should not assume that any value in a table lives in a *TValue.
This commit is the first step to remove that assumption: functions
luaH_get*, instead of returning a *TValue where the value lives,
receive a *TValue where to put the value being accessed.
(We still have to change the luaH_set* functions.)
When integer keys do not form a sequence, it is better to use all their
bits to compute their hashes. (The previous implementation was quite bad
for integer keys with common lower bits, and disastrous for integer keys
changing only in their upper 32 bits.)
More uses of macros 'likely'/'unlikely' (renamed to
'l_likely'/'l_unlikely'), both in range (extended to the
libraries) and in scope (extended to hooks, stack growth).
Fixed the bug that a key removed from a table might not be found
again by 'next'. (This is needed to allow keys to be removed during a
traversal.) This bug was introduced in commit 73ec04fc.
Tables were using this bit to indicate their array sizes were real
('isrealasize'), but this bit can be useful for tests. Instead, they
can use bit 7 of their 'flag' field for that purpose. (There are only
six fast-access metamethods.) This 'flag' field only exists in tables,
so this use does not affect other types.