[backport:1.2] Avoid inlining of newObj and newObjRC1 calls (#17582)

This is taken from:
af69b3ceae

Full original comment:

This is to avoid heavy inlining happening when two allocation calls
would occur shortly after each other.

This inlining would sometimes be accompanied with an optimisation
as the compiler is able to see that cellToUsr ending the first
allocation call is shortly followed by an usrToCell call. The
pointer arithmetic is redundant and the compiler can eliminate it,
leaving only the cell address in a register (and later the stack)
instead of the actual pointer to the user data, as one would expect.

This combined with a GC collect cycle will cause the stack scan to
only notice the cell address, which is of no good due to a usrToCell
in the gcMark call which shifts that address to an adjacent cell.
This means that the actual cell of importance will not get marked
and thus cause a premature collection of that cell. BOOM.

(cherry picked from commit 40093b4a93)
This commit is contained in:
Miran
2021-03-30 10:20:58 +02:00
committed by narimiran
parent 7f834c69fb
commit fe8b84496f

View File

@@ -436,7 +436,7 @@ proc newObjNoInit(typ: PNimType, size: int): pointer {.compilerRtl.} =
result = rawNewObj(typ, size, gch)
when defined(memProfiler): nimProfile(size)
proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} =
proc newObj(typ: PNimType, size: int): pointer {.compilerRtl, noinline.} =
result = rawNewObj(typ, size, gch)
zeroMem(result, size)
when defined(memProfiler): nimProfile(size)
@@ -451,7 +451,7 @@ proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
when defined(memProfiler): nimProfile(size)
{.pop.}
proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} =
proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl, noinline.} =
# generates a new object and sets its reference counter to 1
incTypeSize typ, size
sysAssert(allocInv(gch.region), "newObjRC1 begin")