fix(runtime): release deep node chains iteratively #327

Merged
argus merged 2 commits from loop/211-iterative-release into main 2026-10-12 13:55:45 +00:00
Collaborator

Closes #211

Releasing a long persistent chain (a ConsStack, the cons lists of a BankersQueue) recursed one C frame per node and overflowed the stack around some tens of thousands of nodes.

  • runtime/memory.c: torb_release and torb_free_counted count per thread how many drops they are inside of. A block whose last count runs out 256 drops deep goes onto a per-thread pending list, and the outermost release drains it (LIFO). Stack use is bounded, and below the bound the drop and close() order is unchanged.
  • runtime/machine.c: the VM kernel releases its blocks through torb_release/torb_free_counted with a shape-walking drop function, so the bound holds in both back ends.
  • runtime/panic.c, torb.h: a recovery point saves the depth and the jump restores it. The runtime test harness's panic hook does the same.
  • Tests: runtime tests for a 1,000,000-node chain, depth-first order of a short chain, and a shared tail freed exactly once. New conformance test release-long-chain (BankersQueue and ConsStack of 1,000,000 items, shared tails), tier B, both back ends.
  • Docs: the limitation paragraph is removed from BankersQueue. DESTRUCTORS.md 2a and VM.md section 7 describe the bound.

The .allocations budget of the new conformance test is set from the CI count.

Closes #211 Releasing a long persistent chain (a `ConsStack`, the cons lists of a `BankersQueue`) recursed one C frame per node and overflowed the stack around some tens of thousands of nodes. - `runtime/memory.c`: `torb_release` and `torb_free_counted` count per thread how many drops they are inside of. A block whose last count runs out 256 drops deep goes onto a per-thread pending list, and the outermost release drains it (LIFO). Stack use is bounded, and below the bound the drop and `close()` order is unchanged. - `runtime/machine.c`: the VM kernel releases its blocks through `torb_release`/`torb_free_counted` with a shape-walking drop function, so the bound holds in both back ends. - `runtime/panic.c`, `torb.h`: a recovery point saves the depth and the jump restores it. The runtime test harness's panic hook does the same. - Tests: runtime tests for a 1,000,000-node chain, depth-first order of a short chain, and a shared tail freed exactly once. New conformance test `release-long-chain` (BankersQueue and ConsStack of 1,000,000 items, shared tails), tier B, both back ends. - Docs: the limitation paragraph is removed from `BankersQueue`. `DESTRUCTORS.md` 2a and `VM.md` section 7 describe the bound. The `.allocations` budget of the new conformance test is set from the CI count.
docs(collections): drop the deep-release limitation
Some checks failed
ci / commit messages (pull_request) Successful in 6s
ci / what the change touches (pull_request) Successful in 8s
pdisc / pdisc (pull_request) Successful in 10s
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / the VS Code extension (editors/vscode) (pull_request) Successful in 13s
ci / bootstrap (linux-x64) (pull_request) Successful in 5m23s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tier A (linux-x64) (pull_request) Successful in 4m25s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 1m47s
ci / tier B (linux-x64) (pull_request) Failing after 9m55s
ci / pack the seed (pull_request) Has been skipped
ci / every host emits the same C (pull_request) Successful in 4m35s
ci / archives (pull_request) Has been skipped
ci / gates (pull_request) Has been cancelled
ci / the playground (torb as WebAssembly) (pull_request) Has been cancelled
5e79af7594
orion force-pushed loop/211-iterative-release from 5e79af7594
Some checks failed
ci / commit messages (pull_request) Successful in 6s
ci / what the change touches (pull_request) Successful in 8s
pdisc / pdisc (pull_request) Successful in 10s
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / the VS Code extension (editors/vscode) (pull_request) Successful in 13s
ci / bootstrap (linux-x64) (pull_request) Successful in 5m23s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tier A (linux-x64) (pull_request) Successful in 4m25s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 1m47s
ci / tier B (linux-x64) (pull_request) Failing after 9m55s
ci / pack the seed (pull_request) Has been skipped
ci / every host emits the same C (pull_request) Successful in 4m35s
ci / archives (pull_request) Has been skipped
ci / gates (pull_request) Has been cancelled
ci / the playground (torb as WebAssembly) (pull_request) Has been cancelled
to c0c9f8b872
Some checks failed
ci / commit messages (pull_request) Successful in 10s
ci / what the change touches (pull_request) Successful in 9s
pdisc / pdisc (pull_request) Successful in 13s
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / the VS Code extension (editors/vscode) (pull_request) Successful in 16s
ci / bootstrap (linux-x64) (pull_request) Successful in 5m23s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tier A (linux-x64) (pull_request) Successful in 4m16s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 1m35s
ci / every host emits the same C (pull_request) Successful in 4m24s
ci / tier B (linux-x64) (pull_request) Failing after 11m5s
ci / pack the seed (pull_request) Has been skipped
ci / archives (pull_request) Has been skipped
ci / the playground (torb as WebAssembly) (pull_request) Successful in 1m51s
ci / gates (pull_request) Failing after 0s
2026-10-12 11:47:56 +00:00
Compare
orion force-pushed loop/211-iterative-release from c0c9f8b872
Some checks failed
ci / commit messages (pull_request) Successful in 10s
ci / what the change touches (pull_request) Successful in 9s
pdisc / pdisc (pull_request) Successful in 13s
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / the VS Code extension (editors/vscode) (pull_request) Successful in 16s
ci / bootstrap (linux-x64) (pull_request) Successful in 5m23s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tier A (linux-x64) (pull_request) Successful in 4m16s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 1m35s
ci / every host emits the same C (pull_request) Successful in 4m24s
ci / tier B (linux-x64) (pull_request) Failing after 11m5s
ci / pack the seed (pull_request) Has been skipped
ci / archives (pull_request) Has been skipped
ci / the playground (torb as WebAssembly) (pull_request) Successful in 1m51s
ci / gates (pull_request) Failing after 0s
to 315907f857
All checks were successful
ci / commit messages (pull_request) Successful in 7s
ci / what the change touches (pull_request) Successful in 6s
pdisc / pdisc (pull_request) Successful in 11s
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / the VS Code extension (editors/vscode) (pull_request) Successful in 14s
ci / bootstrap (linux-x64) (pull_request) Successful in 5m31s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tier A (linux-x64) (pull_request) Successful in 4m19s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 1m40s
ci / every host emits the same C (pull_request) Successful in 4m37s
ci / tier B (linux-x64) (pull_request) Successful in 11m58s
ci / pack the seed (pull_request) Has been skipped
ci / archives (pull_request) Has been skipped
ci / the playground (torb as WebAssembly) (pull_request) Successful in 1m50s
ci / gates (pull_request) Successful in 0s
2026-10-12 12:36:16 +00:00
Compare
argus approved these changes 2026-10-12 13:55:44 +00:00
argus left a comment

Checklist (head 315907f):

  • Tests: ok. Runtime tests cover a 1,000,000-node chain, the depth-first order of a short chain and a shared tail freed once; conformance release-long-chain (BankersQueue + ConsStack, shared tails, both back ends). CI green for this head (tier A/B, bootstrap, gates, pdisc).
  • Correctness: ok. torb_drop_and_free defers at 256 nested drops and only the outermost release (depth 1) drains the list, so nested releases never drain early. A deferred block already has count zero, so nothing can retain it. Recovery points and the test harness hook restore the depth after a longjmp, and the next outermost release drains what is left. The VM kernel now routes through torb_release/torb_free_counted with a shape-walking drop function, so the bound holds in both back ends.
  • Scope: ok, matches #211 (release of long node chains, VM and native).
  • Security/data: ok. The only allocation is the pending list, with an OOM panic on realloc failure, and the list is freed when the outermost release ends. No format or storage change.
  • Docs: ok. The limitation paragraph is removed from BankersQueue; DESTRUCTORS.md 2a and VM.md 7 describe the bound and the close() order caveat past 256 levels.

Non-blocking: none.

Checklist (head 315907f): - Tests: ok. Runtime tests cover a 1,000,000-node chain, the depth-first order of a short chain and a shared tail freed once; conformance `release-long-chain` (BankersQueue + ConsStack, shared tails, both back ends). CI green for this head (tier A/B, bootstrap, gates, pdisc). - Correctness: ok. `torb_drop_and_free` defers at 256 nested drops and only the outermost release (depth 1) drains the list, so nested releases never drain early. A deferred block already has count zero, so nothing can retain it. Recovery points and the test harness hook restore the depth after a longjmp, and the next outermost release drains what is left. The VM kernel now routes through `torb_release`/`torb_free_counted` with a shape-walking drop function, so the bound holds in both back ends. - Scope: ok, matches #211 (release of long node chains, VM and native). - Security/data: ok. The only allocation is the pending list, with an OOM panic on realloc failure, and the list is freed when the outermost release ends. No format or storage change. - Docs: ok. The limitation paragraph is removed from `BankersQueue`; DESTRUCTORS.md 2a and VM.md 7 describe the bound and the close() order caveat past 256 levels. Non-blocking: none.
argus merged commit a578e1e35a into main 2026-10-12 13:55:45 +00:00
argus deleted branch loop/211-iterative-release 2026-10-12 13:55:45 +00:00
Sign in to join this conversation.
No reviewers
No labels
loop
ready
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language!327
No description provided.