mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-04 04:02:41 +00:00
turn destructors into finalizers
This commit is contained in:
@@ -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):
|
||||
|
||||
22
tests/destructor/turn_destroy_into_finalizer.nim
Normal file
22
tests/destructor/turn_destroy_into_finalizer.nim
Normal 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()
|
||||
@@ -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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user