Fixes space leak by switching to objects

The integer-arena approach (parallel global arrays) never freed nodes,
causing 6GB+ memory usage when running the self-hosted kernel. PHP
arrays don't shrink and we have no GC for them.

- Replace int-arena with plain Node objects so PHP's refcounting GC
  reclaims unreachable subtrees automatically.
- Hash-cons Stem/Fork nodes to collapse duplicate immutable subtrees.
- Cache ofNumber(0..255) to avoid re-creating byte trees.
- Eliminate indirection (tag 4) nodes entirely; projection rules now
  eagerly reduce and copy tag/a/b into the original App node.
- Remove all deref() loops — every node is exactly what it says.

Memory: 6GB+ → 24MB for `id "hello"` with runArboricxToString kernel
This commit is contained in:
2026-05-10 16:56:00 -05:00
parent 1885c9b4ba
commit 8a673e282d
5 changed files with 209 additions and 133 deletions

View File

@@ -26,6 +26,7 @@ require __DIR__ . '/src/functions.php';
require __DIR__ . '/src/codecs.php';
require __DIR__ . '/src/kernel.php';
use Arboricx\Node;
use function Arboricx\{app, reduce, ofString, ofNumber, ofBytes, ofList,
formatTree, unwrapResult, unwrapHostValue, decodeHostPayload,
getRunArboricxToString};
@@ -67,7 +68,7 @@ function cmdRun(string $bundlePath, array $args): void
// Kernel application: runArboricxToString bundle args
$expr = app(app($kernel, $bundleTree), $argsTree);
fwrite(STDERR, "Reducing kernel application...\n");
$result = reduce($expr, 1_000_000_000);
$result = reduce($expr, 1_000_000_000_000);
// The kernel returns an ok/err pair. On ok, the value is a
// Host ABI envelope: Fork(tag_number, payload_tree).
@@ -96,7 +97,7 @@ function cmdRun(string $bundlePath, array $args): void
}
}
function encodeArg(string $arg): int
function encodeArg(string $arg): Node
{
return ctype_digit($arg) ? ofNumber((int)$arg) : ofString($arg);
}