Skip to content

Default GC: array from a direct function call, stored in a variable, is lost when its backing store grows past 32MiB; object arrays get corrupted length #6228

Description

@dlee

What happened

An array built with push inside a function, returned from a direct call,
and stored into any variable (local or global) is lost once its backing store
exceeds 32MiB. Deterministic, default GC, perry run and compiled binaries
alike. Numeric arrays come back with length === 0 (OOB reads give NaN);
object-element arrays get a garbage length (e.g. 2775006632) — memory
corruption. Exact boundary: build(4194304) (2^22 f64 slots = 32MiB) is
correct, build(4194305) is empty; object arrays fail from 2^21 (same 32MiB).

Same size works via: direct use (build(n).length), indirect call
(var f = build; f(n)), IIFE, or inline module-scope build.

What you expected

b.length === 4194305 (Node agrees). Perry prints 0.

Minimal reproduction

function build(n) {
  var a = [];
  for (var i = 0; i < n; i++) a.push(i);
  return a;
}
var b = build(4194305); // 2^22 elements is fine; 2^22+1 loses everything
console.log(b.length, b[0]);

Command you ran:

perry run arrayloss.js

Environment

  • Perry version: 0.5.1220
  • Host OS: macOS 27.0 (arm64)
  • Target: native
  • Installed via: npm

Diagnostic output

$ perry run arrayloss.js
0 NaN
$ node arrayloss.js
4194305 0

PERRY_GC_DIAG=1 on the compiled binary: one full collection frees ~32MiB —
the array's live buffer is swept (evacuation never runs, moved_objects: 0):

[gc] blocks: general=1 (1 live), longlived=10 (1 live), freed_bytes=33538224 retained_forwarded_stub_bytes=16368 retained_forwarded_stub_objects=7

Looks like the grow past 32MiB triggers a full GC that doesn't see the
direct-call return value as a root.

Anything else

Reproduces with PERRY_NO_CACHE=1; no PERRY_GEN_GC* / stack-scan setting
changes the outcome. Distinct from #5467/#5459/#6219, which need
PERRY_GC_FORCE_EVACUATE=1 or explicit gc() — this is default settings,
and no evacuation is involved. Found while benchmarking for #6223.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions