Skip to content

v0.1.3 — string garbage collection

Choose a tag to compare

@fizzexual fizzexual released this 15 Jun 20:26
· 4 commits to main since this release

Sprout v0.1.3 closes the last big memory-model gap: heap strings are now garbage-collected too.

The conservative mark-sweep GC (v0.1.0) already reclaimed lists, maps, environments, and closures — but strings still leaked (a deliberate, safe first step). This was the planned next slice, and it's done: long-running programs now stay bounded for real.

How it works (no language change — the freeze holds; this is invisible)

  • Every Value's text is now a GC-owned copy: vstr() copies its argument into a new GC_STR and never takes ownership, so it can never free borrowed/AST memory; vstr_take() copies a malloc-owned buffer and frees the original.
  • gc_push_value marks strings; the sweep frees an unmarked GC_STR like any leaf object.
  • Strings owned by map keys, environment names, and the module tables stay plain malloc on purpose — they live where the conservative stack scan never reaches, so the GC must not touch them.

Validated

  • Full suite + 12 examples pass normally and under SPROUT_GC_STRESS=1 (collect on every statement — any wrongly-freed live string corrupts a result).
  • A new string torture test (concat loops, strings as map keys + values, a closure capturing a string, heavy upper/split/join/replace churn) stays intact under stress.
  • 3,000,000 throwaway strings now peak at ~37 MB instead of leaking to hundreds.
  • AddressSanitizer + GC-stress green in CI on Linux; an adversarial memory-safety review (ownership, root-completeness, error-unwinding) found nothing.

Also

  • Corrected stale docs: the README and gc-design.md now reflect a fully collected runtime, and the "no closures yet" note is fixed (closures shipped in v0.0.24).

Windows installer: SproutSetup.exe below.