From 01a8ede7210245ed21d56380b0ed2742eb57682b Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Fri, 18 Oct 2024 22:00:53 +0800 Subject: [PATCH 1/2] `.byref` always optimizes sink call into a bitwise memcopy --- compiler/ccgcalls.nim | 3 ++- compiler/injectdestructors.nim | 3 ++- tests/arc/tarc_orc.nim | 33 +++++++++++++++++++++++++++++++-- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index 788f7a470bde..191e1c5c65d1 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -84,7 +84,8 @@ proc cleanupTemp(p: BProc; returnType: PType, tmp: TLoc): bool = let dtor = getAttachedOp(p.module.g.graph, returnType, attachedDestructor) var op = initLocExpr(p, newSymNode(dtor)) var callee = rdLoc(op) - let destroy = if dtor.typ.firstParamType.kind == tyVar: + let destroy = if dtor.typ.firstParamType.kind == tyVar or + tfByRef in dtor.typ.firstParamType.flags: callee & "(&" & rdLoc(tmp) & ")" else: callee & "(" & rdLoc(tmp) & ")" diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index e6b6d5b42a33..5d1e782d4dda 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -277,7 +277,8 @@ proc deepAliases(dest, ri: PNode): bool = proc genSink(c: var Con; s: var Scope; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNode = if (c.inLoopCond == 0 and (isUnpackedTuple(dest) or IsDecl in flags or (isAnalysableFieldAccess(dest, c.owner) and isFirstWrite(dest, c)))) or - isNoInit(dest) or IsReturn in flags: + isNoInit(dest) or IsReturn in flags or + tfByRef in dest.typ.flags: # optimize sink call into a bitwise memcopy result = newTree(nkFastAsgn, dest, ri) else: diff --git a/tests/arc/tarc_orc.nim b/tests/arc/tarc_orc.nim index f2c7de2fca41..99fdc6152574 100644 --- a/tests/arc/tarc_orc.nim +++ b/tests/arc/tarc_orc.nim @@ -99,7 +99,7 @@ type proc imageCopy*(image: Image): Image {.nodestroy.} -proc `=destroy`*(x: var Image) = +proc `=destroy`*(x: Image) = discard proc `=sink`*(dest: var Image; source: Image) = `=destroy`(dest) @@ -111,7 +111,7 @@ proc `=dup`*(source: Image): Image {.nodestroy.} = proc `=copy`*(dest: var Image; source: Image) = dest = imageCopy(source) # calls =sink implicitly -proc `=destroy`*(x: var EmbeddedImage) = discard +proc `=destroy`*(x: EmbeddedImage) = discard proc `=dup`*(source: EmbeddedImage): EmbeddedImage {.nodestroy.} = source @@ -184,3 +184,32 @@ block: # bug #24147 let oo = OO(val: "hello world") var ooCopy : OO `=copy`(ooCopy, oo) + +block: + type MyObj {.byref.} = object + value: int + + proc `=copy`(a: var MyObj, b: MyObj) {.error.} + proc `=sink`(a: var MyObj, b: MyObj) {.error.} + + proc createMyObj(value: int): MyObj = + result.value = value + + var x: MyObj + x = createMyObj(3) + +block: + type MyObj {.byref.} = object + value: int + + proc `=copy`(a: var MyObj, b: MyObj) {.error.} + proc `=sink`(a: var MyObj, b: MyObj) {.error.} + + proc createMyObj(value: int): MyObj = + result.value = value + + proc foo = + var x: MyObj + x = createMyObj(3) + + foo() From 3b6f01551c5a7117ad0d61ee134045a277d0d9f9 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Sat, 19 Oct 2024 10:56:11 +0800 Subject: [PATCH 2/2] only applied to byref with disabled `=sink` --- compiler/injectdestructors.nim | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index 5d1e782d4dda..99db09666264 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -275,14 +275,16 @@ proc deepAliases(dest, ri: PNode): bool = return aliases(dest, ri) != no proc genSink(c: var Con; s: var Scope; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNode = + let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink}) if (c.inLoopCond == 0 and (isUnpackedTuple(dest) or IsDecl in flags or (isAnalysableFieldAccess(dest, c.owner) and isFirstWrite(dest, c)))) or isNoInit(dest) or IsReturn in flags or - tfByRef in dest.typ.flags: + (tfByRef in dest.typ.flags and getAttachedOp(c.graph, t, attachedSink) != nil and + sfError in getAttachedOp(c.graph, t, attachedSink).flags + ): # optimize sink call into a bitwise memcopy result = newTree(nkFastAsgn, dest, ri) else: - let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink}) if getAttachedOp(c.graph, t, attachedSink) != nil: result = c.genOp(t, attachedSink, dest, ri) result.add ri