diff --git a/compiler/layeredtable.nim b/compiler/layeredtable.nim index 81c6c63d75..a2f958769b 100644 --- a/compiler/layeredtable.nim +++ b/compiler/layeredtable.nim @@ -46,12 +46,11 @@ proc setToPreviousLayer*(pt: var LayeredIdTable) {.inline.} = when useRef: pt = pt.nextLayer else: - when defined(gcDestructors): - pt = pt.nextLayer[] - else: - # workaround refc - let tmp = pt.nextLayer[] - pt = tmp + # Must read nextLayer into a temp before destroying pt: + # `pt = pt.nextLayer[]` would call eqcopy(&pt, &(*pt.nextLayer)) which + # decrements pt.nextLayer's rc (freeing it) before reading pt.nextLayer.nextLayer. + let tmp = pt.nextLayer[] + pt = tmp iterator pairs*(pt: LayeredIdTable): (ItemId, PType) = var tm = pt diff --git a/lib/system/strs_v3.nim b/lib/system/strs_v3.nim index 81c52d3134..14b495f629 100644 --- a/lib/system/strs_v3.nim +++ b/lib/system/strs_v3.nim @@ -133,7 +133,9 @@ proc ensureUniqueLong(s: var SmallString; oldLen, newLen: int) = if isHeap and s.more.rc == 1 and newLen <= cap: s.more.fullLen = newLen else: - let newCap = max(newLen, resize(cap)) + # Only grow capacity when actually needed; pure COW copies (newLen <= cap) + # preserve the existing capacity to avoid exponential growth via repeated COW. + let newCap = if newLen > cap: max(newLen, resize(cap)) else: cap let p = cast[ptr LongString](alloc(sizeof(int) * 3 + newCap + 1)) p.rc = 1 p.fullLen = newLen