Skip to content

Commit

Permalink
Correctly presize table when setting from varags
Browse files Browse the repository at this point in the history
 - Change LuaTable.presize to allocate the exact size, rather than the
   next power of two. Unfortunately this does matter when searching for
   nil boundaries.

 - Presize tables when assigning from varargs. Again, while this should
   be invisible in theory, it does have an observable difference when
   getting the table length.

Fixes #85
  • Loading branch information
SquidDev committed Jan 15, 2024
1 parent 826d6f0 commit 2e9c89b
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/main/java/org/squiddev/cobalt/LuaTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public LuaTable checkTable() {
*/
public void presize(int nArray) {
if (nArray > array.length) {
resize(1 << log2(nArray), nodes.length, false);
resize(nArray, nodes.length, false);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,8 @@ static Varargs execute(final LuaState state, DebugFrame di, LuaInterpretedFuncti
if (b == 0) {
b = di.top - a - 1;
int m = b - di.extras.count();
tbl.presize(offset + b);

int j = 1;
for (; j <= m; j++) tbl.rawset(offset + j, stack[a + j]);
for (; j <= b; j++) tbl.rawset(offset + j, di.extras.arg(j - m));
Expand Down
25 changes: 25 additions & 0 deletions src/test/resources/spec/table_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,31 @@ describe("Lua tables", function()
expect(#{ 1, 2, 3, nil, 5, nil, 7, 8, 9 }):eq(9)
expect(#{ 1, nil, [2] = 2, 3 }):eq(3)
end)

it("behaves identically to PUC Lua after resizing", function()
local n = 8

-- We grow the array part to be of length N.
local tbl = {}
for i = 1, n do tbl[i] = true end
expect(#tbl):eq(n)

-- Then clear out all but the last value. This does not shrink the array part, so we
-- still have a length N.
for i = 1, n - 1 do tbl[i] = nil end
expect(#tbl):eq(n)
end)
end)

describe("can be constructed from varargs", function()
it("presizes the array", function()
local function create(...) return { ... } end

-- If we'd constructed this table normally, it'd have a length of 5. However,
-- SETLIST will presize the table to ensure the array part is of length 5. As
-- the last slot is full, the array is considered saturated.
expect(#create(nil, nil, nil, nil, 1)):eq(5)
end)
end)

describe("weak tables", function()
Expand Down

0 comments on commit 2e9c89b

Please sign in to comment.