Large multi-language indexes crashed with `Fatal process out of memory: Zone` on Node 22/24 (including the bundled runtime) — V8's turboshaft optimizing WASM compiler exhausts its per-compilation Zone arena while compiling tree-sitter grammars on a background thread, even with tens of GB free (the Zone is a V8-internal arena, not the JS heap). Run node with V8 `--liftoff-only`, which keeps grammar compilation on the Liftoff baseline and never reaches the optimizing tier. Delivered via the bundled launcher + a one-shot CLI re-exec guard for all other launch paths. Empirically only `--liftoff-only` stops it (`--no-wasm-tier-up` / `--no-wasm-dynamic-tiering` do not), and it must be on node's command line (setFlagsFromString / worker execArgv / NODE_OPTIONS all fail). Reproduced the exact crash with the real indexer on Node 24.16 against a 2,880-file / 18-language repo and confirmed the fix eliminates it; full suite + 7 new tests pass. Bumps to 0.9.4. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
bf73f4d05c
commit
e5d633075c
+12
-2
@@ -70,9 +70,18 @@ rm -f "$STAGE/lib/package-lock.json"
|
||||
|
||||
# 4. Vendored Node + launcher (the launcher uses the bundled Node by relative
|
||||
# path, so no system Node is ever needed).
|
||||
#
|
||||
# `--liftoff-only`: keep tree-sitter's large WASM grammars on V8's Liftoff
|
||||
# baseline compiler so they never reach the turboshaft optimizing tier, whose
|
||||
# per-compilation Zone arena OOMs the whole process (`Fatal process out of
|
||||
# memory: Zone`) on Node >= 22 — even with tens of GB free. The flag is read at
|
||||
# V8 engine init so it must be on node's command line; the parse worker inherits
|
||||
# it. See issues #293/#298 and src/extraction/wasm-runtime-flags.ts. (The CLI
|
||||
# also self-relaunches with this flag when launched without it, so non-bundled
|
||||
# runs are covered too; passing it here avoids that extra spawn.)
|
||||
if [ "$OSFAM" = "win32" ]; then
|
||||
cp "$NODE_BIN" "$STAGE/node.exe"
|
||||
printf '@"%%~dp0..\\node.exe" "%%~dp0..\\lib\\dist\\bin\\codegraph.js" %%*\r\n' \
|
||||
printf '@"%%~dp0..\\node.exe" --liftoff-only "%%~dp0..\\lib\\dist\\bin\\codegraph.js" %%*\r\n' \
|
||||
> "$STAGE/bin/codegraph.cmd"
|
||||
else
|
||||
cp "$NODE_BIN" "$STAGE/node"
|
||||
@@ -89,7 +98,8 @@ while [ -L "$SELF" ]; do
|
||||
esac
|
||||
done
|
||||
DIR="$(cd "$(dirname "$SELF")/.." && pwd)"
|
||||
exec "$DIR/node" "$DIR/lib/dist/bin/codegraph.js" "$@"
|
||||
# --liftoff-only: avoid the V8 turboshaft WASM Zone OOM (issues #293/#298).
|
||||
exec "$DIR/node" --liftoff-only "$DIR/lib/dist/bin/codegraph.js" "$@"
|
||||
LAUNCH
|
||||
chmod +x "$STAGE/bin/codegraph"
|
||||
fi
|
||||
|
||||
+4
-1
@@ -31,7 +31,10 @@ try {
|
||||
if (isWindows) {
|
||||
command = require.resolve(pkg + '/node.exe');
|
||||
var entry = require.resolve(pkg + '/lib/dist/bin/codegraph.js');
|
||||
args = [entry].concat(process.argv.slice(2));
|
||||
// --liftoff-only: keep tree-sitter's WASM grammars off V8's turboshaft tier
|
||||
// to avoid the Zone OOM on Node >= 22 (issues #293/#298). The unix launcher
|
||||
// passes this too; on Windows we invoke node.exe directly so add it here.
|
||||
args = ['--liftoff-only', entry].concat(process.argv.slice(2));
|
||||
} else {
|
||||
command = require.resolve(pkg + '/bin/codegraph');
|
||||
args = process.argv.slice(2);
|
||||
|
||||
Reference in New Issue
Block a user