turn destructors into finalizers

This commit is contained in:
Andreas Rumpf
2018-07-05 11:31:27 +02:00
parent 683c60e2fd
commit 9b31f67859
3 changed files with 40 additions and 6 deletions

View File

@@ -1135,9 +1135,21 @@ proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) =
if sizeExpr.isNil:
sizeExpr = "sizeof($1)" %
[getTypeDesc(p.module, bt)]
let args = [getTypeDesc(p.module, typ),
genTypeInfo(p.module, typ, a.lode.info),
sizeExpr]
let ti = genTypeInfo(p.module, typ, a.lode.info)
if bt.destructor != nil:
# the prototype of a destructor is ``=destroy(x: var T)`` and that of a
# finalizer is: ``proc (x: ref T) {.nimcall.}``. We need to check the calling
# convention at least:
if bt.destructor.typ == nil or bt.destructor.typ.callConv != ccDefault:
localError(p.module.config, a.lode.info,
"the destructor that is turned into a finalizer needs " &
"to have the 'nimcall' calling convention")
var f: TLoc
initLocExpr(p, newSymNode(bt.destructor), f)
addf(p.module.s[cfsTypeInit3], "$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)])
let args = [getTypeDesc(p.module, typ), ti, sizeExpr]
if a.storage == OnHeap and usesNativeGC(p.config):
# use newObjRC1 as an optimization
if canFormAcycle(a.t):

View File

@@ -0,0 +1,22 @@
discard """
output: '''true'''
"""
type
Foo = object
id: int
var destroyed: int
proc `=destroy`(x: var Foo) =
#echo "finally ", x.id
inc destroyed
proc main =
var r: ref Foo
for i in 1..50_000:
new(r)
r.id = i
echo destroyed > 30_000
main()

View File

@@ -6,16 +6,16 @@ when defined(GC_setMaxPause):
GC_setMaxPause 2_000
type
TTestObj = object of TObject
TTestObj = object of RootObj
x: string
proc MakeObj(): TTestObj =
proc makeObj(): TTestObj =
result.x = "Hello"
for i in 1 .. 1_000_000:
when defined(gcMarkAndSweep) or defined(boehmgc):
GC_fullcollect()
var obj = MakeObj()
var obj = makeObj()
if getOccupiedMem() > 300_000: quit("still a leak!")
# echo GC_getstatistics()