Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Araq committed Nov 29, 2019
1 parent a114a40 commit b688250
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 8 deletions.
20 changes: 12 additions & 8 deletions compiler/injectdestructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ proc getTemp(c: var Con; typ: PType; info: TLineInfo): PNode =
proc genWasMoved(n: PNode; c: var Con): PNode =
result = newNodeI(nkCall, n.info)
result.add(newSymNode(createMagic(c.graph, "wasMoved", mWasMoved)))
result.add n #mWasMoved does not take the address
result.add copyTree(n) #mWasMoved does not take the address

proc genDefaultCall(t: PType; c: Con; info: TLineInfo): PNode =
result = newNodeI(nkCall, info)
Expand Down Expand Up @@ -401,6 +401,7 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
# different and can deal with 'const string sunk into var'.
result = passCopyToSink(arg, c)
elif arg.kind in nkLiterals:
# literals are save to share accross ASTs (for now!)
result = arg # literal to sink parameter: nothing to do
elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkClosure}:
# object construction to sink parameter: nothing to do
Expand Down Expand Up @@ -497,19 +498,22 @@ proc p(n: PNode; c: var Con; consumed = false): PNode =
of nkCallKinds:
let parameters = n[0].typ
let L = if parameters != nil: parameters.len else: 0
result = shallowCopy(n)
for i in 1..<n.len:
n[i] = pArg(n[i], c, i < L and isSinkTypeForParam(parameters[i]))
result = n
if result[0].kind == nkSym and result[0].sym.magic in {mNew, mNewFinalize}:
result[i] = pArg(n[i], c, i < L and isSinkTypeForParam(parameters[i]))
if n[0].kind == nkSym and n[0].sym.magic in {mNew, mNewFinalize}:
result[0] = copyTree(n[0])
if c.graph.config.selectedGC in {gcHooks, gcDestructors}:
let destroyOld = genDestroy(c, result[1])
result = newTree(nkStmtList, destroyOld, result)
else:
result[0] = pArg(result[0], c, isSink = false)
result[0] = pArg(n[0], c, isSink = false)
of nkDiscardStmt: # Small optimization
result = shallowCopy(n)
if n[0].kind != nkEmpty:
n[0] = pArg(n[0], c, false)
result = n
result[0] = pArg(n[0], c, false)
else:
result[0] = copyNode(n[0])
of nkBracket:
result = copyTree(n)
for i in 0..<n.len:
Expand Down Expand Up @@ -580,7 +584,7 @@ proc p(n: PNode; c: var Con; consumed = false): PNode =
result = moveOrCopy(n[0], n[1], c)
else:
result = copyNode(n)
result.add n[0]
result.add copyTree(n[0])
result.add p(n[1], c)
of nkRaiseStmt:
if optOwnedRefs in c.graph.config.globalOptions and n[0].kind != nkEmpty:
Expand Down
77 changes: 77 additions & 0 deletions tests/destructor/const_smart_ptr.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
type
ConstPtr*[T] = object
val: ptr T

proc `=destroy`*[T](p: var ConstPtr[T]) =
if p.val != nil:
`=destroy`(p.val[])
dealloc(p.val)
p.val = nil

proc `=`*[T](dest: var ConstPtr[T], src: ConstPtr[T]) {.error.}

proc `=sink`*[T](dest: var ConstPtr[T], src: ConstPtr[T]) {.inline.} =
if dest.val != nil and dest.val != src.val:
`=destroy`(dest)
dest.val = src.val

proc newConstPtr*[T](val: sink T): ConstPtr[T] {.inline.} =
result.val = cast[type(result.val)](alloc(sizeof(result.val[])))
reset(result.val[])
result.val[] = val

converter convertConstPtrToObj*[T](p: ConstPtr[T]): lent T =
result = p.val[]


#-------------------------------------------------------------

type
MySeqNonCopyable* = object
len: int
data: ptr UncheckedArray[float]

proc `=destroy`*(m: var MySeqNonCopyable) {.inline.} =
if m.data != nil:
deallocShared(m.data)
m.data = nil

proc `=`*(m: var MySeqNonCopyable, m2: MySeqNonCopyable) {.error.}

proc `=sink`*(m: var MySeqNonCopyable, m2: MySeqNonCopyable) {.inline.} =
if m.data != m2.data:
if m.data != nil:
`=destroy`(m)
m.len = m2.len
m.data = m2.data

proc len*(m: MySeqNonCopyable): int {.inline.} = m.len

proc `[]`*(m: MySeqNonCopyable; i: int): float {.inline.} =
m.data[i.int]

proc `[]=`*(m: var MySeqNonCopyable; i: int, val: float) {.inline.} =
m.data[i.int] = val

proc setTo(s: var MySeqNonCopyable, val: float) =
for i in 0..<s.len.int:
s.data[i] = val

proc newMySeq*(size: int, initial_value = 0.0): MySeqNonCopyable =
result.len = size
if size > 0:
result.data = cast[ptr UncheckedArray[float]](createShared(float, size))
result.setTo(initial_value)

#----------------------------------------------------------------------


proc test*(x1: int): ConstPtr[MySeqNonCopyable] {.inline.} = # remove inline here to make it work as expected
if x1 == 0:
let x = newMySeq(1, 0.0)
result = newConstPtr(x)
else:
let y = newMySeq(x1, 0.0)
result = newConstPtr(y)

discard test(10)
7 changes: 7 additions & 0 deletions tests/destructor/tconst_smart_ptr.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
discard """
action: "compile"
"""

import const_smart_ptr

discard test(0)

0 comments on commit b688250

Please sign in to comment.