Deferred from #162: the property-key intern cache (src/interpreter/key_intern.rs) never evicts, so distinct non-index dynamic property names accumulate for the thread's lifetime.
Original feedback by @chatgpt-codex-connector on PR #162 (#162):
Avoid retaining every dynamic property name forever. For workloads that create short-lived objects with many unique non-index property names (for example obj["k" + i] followed by deletion/GC, or multiple Interpreter instances on the same thread), this strong thread-local cache never releases those names: the cache stores both a Box<str> key and an Rc<str> value, so object cleanup cannot drop the allocation. This changes property storage from reclaimable per-object strings into process/thread-lifetime memory growth for arbitrary user-supplied keys; consider using weak entries, bounding/clearing the cache, or only interning a fixed/common set of names.
Context: src/interpreter/key_intern.rs — KeyCache is a thread_local! HashMap<Box<str>, Rc<str>> with no eviction. Canonical array-index keys are already excluded (the integer-index gate), so the exposure is limited to distinct non-numeric string keys (e.g. obj["k" + i]).
Why deferred: scope-creep — #162's stated scope is the storage-layer key-type change (String → Rc<str>). A correct eviction policy is a separable design problem: naive Weak<str> values still leak the Box<str> key without active pruning, and LRU/bounding adds a fast-path cost to the ~1100-call-site property-write path. Two independent AI reviewers (Claude Opus 4.8 and Codex GPT-5.x) both classified this DEFER / scope-creep with high confidence.
Possible directions to evaluate (follow-up):
- Weak-value entries (
Weak<str>) with periodic pruning of dead entries (and their dangling Box<str> keys).
- A bounded cache (size cap / LRU) that falls back to a fresh
Rc::from on overflow.
- Restricting interning to a fixed common set (the existing
SEED_KEYS plus measured high-frequency names), treating arbitrary user keys as non-interned.
Any chosen policy must keep the hot-path interning cost negligible and preserve the byte-exact key semantics that symbol-encoded keys depend on.
Filed automatically by pm-autofix-pr after dual-evaluator triage by Claude Opus 4.8 and Codex GPT-5.x.
Deferred from #162: the property-key intern cache (
src/interpreter/key_intern.rs) never evicts, so distinct non-index dynamic property names accumulate for the thread's lifetime.Original feedback by @chatgpt-codex-connector on PR #162 (#162):
Context:
src/interpreter/key_intern.rs—KeyCacheis athread_local!HashMap<Box<str>, Rc<str>>with no eviction. Canonical array-index keys are already excluded (the integer-index gate), so the exposure is limited to distinct non-numeric string keys (e.g.obj["k" + i]).Why deferred: scope-creep — #162's stated scope is the storage-layer key-type change (
String→Rc<str>). A correct eviction policy is a separable design problem: naiveWeak<str>values still leak theBox<str>key without active pruning, and LRU/bounding adds a fast-path cost to the ~1100-call-site property-write path. Two independent AI reviewers (Claude Opus 4.8 and Codex GPT-5.x) both classified this DEFER / scope-creep with high confidence.Possible directions to evaluate (follow-up):
Weak<str>) with periodic pruning of dead entries (and their danglingBox<str>keys).Rc::fromon overflow.SEED_KEYSplus measured high-frequency names), treating arbitrary user keys as non-interned.Any chosen policy must keep the hot-path interning cost negligible and preserve the byte-exact key semantics that symbol-encoded keys depend on.
Filed automatically by
pm-autofix-prafter dual-evaluator triage by Claude Opus 4.8 and Codex GPT-5.x.