uforth: every PYTHON-bodied word call leaked heap blocks (TYPE ~20 per call) — FIXED
Summary: FIXED 2026-09-27. There were two mechanisms in
compiler/builtin/pyeval.pas, and both apply to any code run through exec,
not only uforth's.
- Double reference on a fresh object. A site that CREATES an object (it
starts at refcount 1) then retained it again for the result slot. Nothing
ever dropped the creator's +1. This covered list, dict, set and tuple
literals,
range(),list(),reversed(), genexps, and instances built by a class call or__new__. Those sites now adopt the construction reference (PyBoxObjNew). - Method calls never freed their argument list. In
ParseMethodCall,argswas never freed andkwNameswas freed on only two paths, so everyx.m(...)leaked both. Both are now freed in atry … finally.
Still retained twice: sites that box a CALL's result (the host-call return,
int.to_bytes, str.encode, bytes(...)). Nobody has measured their
ownership. The mechanism that would spring it is a callee that returns a fresh
object at refcount 1 and a boxing site that retains it again.
Measured 2026-09-27
uforth 07ffdb1, -dPXX_ALLOC_CENSUS, live= at exit for 110 and 1110 input
lines of 1 2 TYPE CR:
| compiler | tree | 110 | 1110 |
|---|---|---|---|
| pin v445 | caf21ac399f1 | 3680 | 24034 |
| HEAD | d96d826cd5fb @ 5581e895ee | 3680 | 24018 |
| fixed | 5581e895ee + patch | 2924 | 2929 |
Kept blocks per call before the fix were 10.7 × 56 bytes and 9.7 × 128 bytes.
They were found with a live-per-size census (a scratch-only change to
CensusBins in PXXFree) and then with -dPXX_OBJTRACE.
test/test_nilpy_exec_body_objects_release.npy is the regression row: 400
exec'd bodies. HEAD gives live=23407; the fix gives 176; the keep control
gives 925. The bound is 400.
Earlier standalone repros read FLAT for two reasons. hold()/push() in env
only resolve through a VM class (a bare function reports "no RTTI"). And
pyeval has no list comprehension, so a body using one errored before doing
any work. Check that the body RAN before you trust a flat census.