fixes #18238; Nested object construction can zero same memory multiple times for --mm:refc (#25834)

fixes #18238

This pull request makes a targeted change to the object construction
logic in the `genObjConstr` procedure. The main update refines the
conditions under which memory zeroing is required during object
construction, making the behavior more accurate for different garbage
collection and destructor options.

Key logic update:

- Improved the `needsZeroMem` condition in `genObjConstr` to check for
the presence of garbage-collected references and the `optSeqDestructors`
option, instead of relying solely on the selected garbage collector and
field flags. This ensures memory is zeroed only when necessary,
potentially improving performance and correctness.


```c
T1_ = NIM_NIL;
T1_ = ((tyObject_E__uEKympBdEK4SY9anUbpNaLQ*) newObj((&NTIrefe__bJ9cSuxv8xHYxmdolQqFkUw_), sizeof(tyObject_E__uEKympBdEK4SY9anUbpNaLQ)));
nimZeroMem(((void*) ((&(*T1_).z.z.z.z))), sizeof(tyObject_A__G2lWlL9cFqoiWWwZmWqfJ9bA));
(*T1_).z.z.z.z.y = ((NI) 5);
asgnRef(((void**) ((&z1__test8_u12))), T1_);
asgnRef(((void**) ((&z2__test8_u55))), new__test8_u13());
(*z2__test8_u55).z.z.z.z.y = ((NI) 5);
T2_ = NIM_NIL;
T2_ = ((tyObject_E__uEKympBdEK4SY9anUbpNaLQ*) newObj((&NTIrefe__bJ9cSuxv8xHYxmdolQqFkUw_), sizeof(tyObject_E__uEKympBdEK4SY9anUbpNaLQ)));
asgnRef(((void**) ((&z3__test8_u56))), T2_);
(*z3__test8_u56).z.z.z.z.y = ((NI) 5);
```


The original test case has already been fixed for `ORC`, now extends it
to `refc`: if a constructor is fully initialized, it does not need a
zero-fill step
This commit is contained in:
ringabout
2026-06-08 14:54:15 +08:00
committed by GitHub
parent f959a02037
commit 4497d89267

View File

@@ -1904,7 +1904,9 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
var tmp: TLoc = default(TLoc)
var r: Rope
let needsZeroMem = p.config.selectedGC notin {gcArc, gcAtomicArc, gcOrc, gcYrc} or nfAllFieldsSet notin e.flags
let needsZeroMem =
nfAllFieldsSet notin e.flags or
(optSeqDestructors notin p.config.globalOptions and containsGarbageCollectedRef(t))
if useTemp:
tmp = getTemp(p, t)
r = rdLoc(tmp)