From fe8b84496ffe40cd86b9db688cf5494187b437e4 Mon Sep 17 00:00:00 2001 From: Miran Date: Tue, 30 Mar 2021 10:20:58 +0200 Subject: [PATCH] [backport:1.2] Avoid inlining of newObj and newObjRC1 calls (#17582) This is taken from: https://github.com/status-im/Nim/commit/af69b3ceae16281efd45cbee4ce1bedd14282304 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 40093b4a937d751ef43b5c2ca447677bb858dff4) --- lib/system/gc.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/system/gc.nim b/lib/system/gc.nim index 15f316cccb..2793c47bd1 100644 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -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")