Skip to content

rc/own: a record literal with a run-time field leaks the array in its fields #485

Description

@ASDAlexander77

Under -mm=rc and -mm=own, a record literal that has a field known only at run time never releases the array in one of its fields. In the repro this happens when another local that owns memory follows the record.

function f(i: number) {
    const o = { items: [i, 2], n: i };
    o.items.push(3);
    const b: number[] = [i];
    b.push(4);
    return o.items.length;
}

function main() {
    let s = 0;
    for (let i = 0; i < 1000000; i++) s += f(i);
    print(s);
}

Peak memory, ahead of time (tslang/test/tester/tools/measure.ps1, built from #484's branch; this path is the same on main):

gc rc none own
5.9 MB 96.5 MB 4.3 MB 96.5 MB

Expected: rc and own flat, about 4.4 MB. Under none LLVM removes the allocations entirely, which is why none is low.

Under the JIT on main (77d9a6a), rc peaks at 144 MB and own at 150 MB. #484's build gives the same.

Without const b (or another owning local such as const s = "x" + i) the leak does not show, but the IR is the same. LLVM elides the allocation in that case, so a flat reading there proves nothing.

What the IR shows (--emit=mlir-affine -mm=rc): the record is built in a temporary slot (ts.Variable initialised from a const_tuple with unit holes, then ts.Store of each run-time field). const o reads that slot (ts.Load {__owned_result_named}). The ts.CreateArray stored into items gets no ts.Release, and the slot gets no ReleaseSlot. Nothing gives back the array's reference.

Since #484, a record whose constant array field is built in a slot takes this path too: { items: [1, 2], n: i } leaks the same way.

Found while testing #484 (#479).

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions