v24: discarded vm contexts cause OOM; possible V8 backport
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 122k
- Forks
- 37.3k
- Avg merge
- 4d 2h
- Merged PRs (30d)
- 283
Description
Version
v24.21.0
Platform
Linux x86_64, kernel 6.8.0-139-generic
Subsystem
vm, V8
What steps will reproduce the bug?
Save as repro.mjs; run node --max-old-space-size=128 repro.mjs.
import { runInNewContext } from "node:vm";
import { setImmediate } from "node:timers/promises";
const source = `
globalThis.payload = new Array(1_000_000).fill(0);
${Array.from({ length: 30 }, (_, index) => `
function work${index}(values) {
let result = 0;
for (let i = 0; i < values.length; ++i) {
result += Math.sqrt(values[i] * values[i] + ${index});
}
return result;
}
`).join("\n")}
const values = [1, 2, 3, 4, 5];
for (let i = 0; i < 1000; ++i) {
${Array.from({ length: 30 }, (_, index) => `work${index}(values);`).join("\n")}
}
`;
for (let i = 0; i < 100; ++i) {
runInNewContext(source + `\n// ${i}`);
await setImmediate();
}
console.log("Completed");
How often does it reproduce? Is there a required condition?
Repeatedly on v24.15.0, v24.16.0, and v24.21.0. Completes on v22.23.2, v26.8.2, or with --no-concurrent-recompilation on v24.
What is the expected behavior? Why is that the expected behavior?
Print Completed; discarded contexts should be collectible.
What do you see instead?
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
Additional information
This surfaced in jsdom’s WPT runner with the default ~4 GB heap; the smaller limit makes this reproduction quick. Sampled heap retainers point through V8’s IdentityMapBase to realm prototypes, keeping entire windows alive.
Could V8’s “Stop collecting array and object prototypes” change be backported to v24? Its later thread-safety follow-up might also be relevant.
I haven't verified that those commits are the key ones, but it's worth trying.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with repro.mjs and run it under v24 with --max-old-space-size=128, then compare v22, v26, and v24 with --no-concurrent-recompilation. Investigate the IdentityMapBase retainers and the two linked V8 commits to determine whether they address discarded vm contexts. Done means the reproduction prints "Completed" without exhausting the heap and discarded contexts can be collected.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100