ARC: ported the GC tests over to --gc:arc

This commit is contained in:
Araq
2019-11-25 15:29:41 +01:00
committed by Andreas Rumpf
parent 879801c639
commit 72237e2bcf
14 changed files with 79 additions and 29 deletions

View File

@@ -60,6 +60,7 @@ proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
var temp = newSym(skTemp, getIdent(g.cache, genPrefix), owner, value.info, g.config.options)
temp.typ = skipTypes(value.typ, abstractInst)
incl(temp.flags, sfFromGeneric)
incl(temp.flags, sfCursor)
var v = newNodeI(nkVarSection, value.info)
let tempAsNode = newSymNode(temp)

View File

@@ -759,6 +759,7 @@ proc track(tracked: PEffects, n: PNode) =
# check required for 'nim check':
if n[1].typ.len > 0:
createTypeBoundOps(tracked, n[1].typ.lastSon, n.info)
createTypeBoundOps(tracked, n[1].typ, n.info)
for i in 0 ..< safeLen(n):
track(tracked, n.sons[i])
of nkDotExpr:

View File

@@ -886,6 +886,10 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType =
t.flags.incl tfHasOwned
t.rawAddSonNoPropagationOfTypeFlags result
result = t
#if result.kind == tyRef and c.config.selectedGC == gcDestructors:
# result.flags.incl tfHasAsgn
# XXX Something like this is a good idea but it should be done
# in sempass2!
proc findEnforcedStaticType(t: PType): PType =
# This handles types such as `static[T] and Foo`,

View File

@@ -135,6 +135,18 @@ proc GC_ref*[T](x: ref T) =
## New runtime only supports this operation for 'ref T'.
if x != nil: nimIncRef(cast[pointer](x))
template GC_fullCollect* =
## Forces a full garbage collection pass. With ``--gc:arc`` a nop.
discard
template setupForeignThreadGc* =
## With ``--gc:arc`` a nop.
discard
template tearDownForeignThreadGc* =
## With ``--gc:arc`` a nop.
discard
proc isObj(obj: PNimType, subclass: cstring): bool {.compilerRtl, inl.} =
proc strstr(s, sub: cstring): cstring {.header: "<string.h>", importc.}

View File

@@ -250,18 +250,19 @@ const ThisIsSystem = true
proc internalNew*[T](a: var ref T) {.magic: "New", noSideEffect.}
## Leaked implementation detail. Do not use.
proc new*[T](a: var ref T, finalizer: proc (x: ref T) {.nimcall.}) {.
magic: "NewFinalize", noSideEffect.}
## Creates a new object of type ``T`` and returns a safe (traced)
## reference to it in ``a``.
##
## When the garbage collector frees the object, `finalizer` is called.
## The `finalizer` may not keep a reference to the
## object pointed to by `x`. The `finalizer` cannot prevent the GC from
## freeing the object.
##
## **Note**: The `finalizer` refers to the type `T`, not to the object!
## This means that for each object of type `T` the finalizer will be called!
when not defined(gcDestructors):
proc new*[T](a: var ref T, finalizer: proc (x: ref T) {.nimcall.}) {.
magic: "NewFinalize", noSideEffect.}
## Creates a new object of type ``T`` and returns a safe (traced)
## reference to it in ``a``.
##
## When the garbage collector frees the object, `finalizer` is called.
## The `finalizer` may not keep a reference to the
## object pointed to by `x`. The `finalizer` cannot prevent the GC from
## freeing the object.
##
## **Note**: The `finalizer` refers to the type `T`, not to the object!
## This means that for each object of type `T` the finalizer will be called!
when defined(nimV2):
proc reset*[T](obj: var T) {.magic: "Destroy", noSideEffect.}

View File

@@ -304,3 +304,12 @@ proc `$`*(x: uint64): string {.noSideEffect, raises: [].} =
let half = i div 2
# Reverse
for t in 0 .. half-1: swap(result[t], result[i-t-1])
when defined(gcDestructors):
proc GC_getStatistics*(): string =
result = "[GC] total memory: "
result.addInt getTotalMem()
result.add "\n[GC] occupied memory: "
result.addInt getOccupiedMem()
result.add '\n'
#"[GC] cycle collections: " & $gch.stat.cycleCollections & "\n" &

View File

@@ -40,7 +40,8 @@ const
"coroutines",
"osproc",
"shouldfail",
"dir with space"
"dir with space",
"destructor"
]
proc isTestFile*(file: string): bool =
@@ -176,6 +177,11 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
" -d:release", cat)
testSpec r, makeTest("tests/gc" / filename, options &
" -d:release -d:useRealtimeGC", cat)
when filename != "gctest":
testSpec r, makeTest("tests/gc" / filename, options &
" --gc:arc", cat)
testSpec r, makeTest("tests/gc" / filename, options &
" --gc:arc -d:release", cat)
template testWithoutBoehm(filename: untyped) =
testWithoutMs filename

View File

@@ -28,7 +28,7 @@ proc test(): auto =
var (a, b, _) = test()
doAssert assign_counter == 0
doAssert sink_counter == 12 # + 3 because of the conservative tuple unpacking transformation
doAssert sink_counter == 9 # XXX this is still silly and needs to be investigated
# bug #11510
proc main =

View File

@@ -3,20 +3,28 @@ discard """
disabled: "32bit"
"""
from strutils import join
type
TFoo * = object
TFoo* = object
id: int
fn: proc(){.closure.}
var foo_counter = 0
var alive_foos = newseq[int](0)
proc free*(some: ref TFoo) =
#echo "Tfoo #", some.id, " freed"
alive_foos.del alive_foos.find(some.id)
when defined(gcDestructors):
proc `=destroy`(some: var TFoo) =
alive_foos.del alive_foos.find(some.id)
`=destroy`(some.fn)
else:
proc free*(some: ref TFoo) =
#echo "Tfoo #", some.id, " freed"
alive_foos.del alive_foos.find(some.id)
proc newFoo*(): ref TFoo =
new result, free
when defined(gcDestructors):
new result
else:
new result, free
result.id = foo_counter
alive_foos.add result.id

View File

@@ -10,7 +10,7 @@ type
PModule = ref Module
Node = object
owner*: PModule
owner* {.cursor.}: PModule
data*: array[0..200, char] # some fat to drain memory faster
id: int

View File

@@ -15,7 +15,7 @@ when defined(allow_print):
else:
const print = false
proc myResult3*(i:int):X {.exportc.} =
proc myResult3*(i:int): X {.exportc.} =
if print: echo "3"
new(result)
if print: echo "3-2"

View File

@@ -2,11 +2,11 @@ discard """
outputsub: "no leak: "
"""
when defined(GC_setMaxPause):
when declared(GC_setMaxPause):
GC_setMaxPause 2_000
type
TExpr = object {.inheritable.} ## abstract base class for an expression
TExpr {.inheritable.} = object ## abstract base class for an expression
PLiteral = ref TLiteral
TLiteral = object of TExpr
x: int
@@ -15,7 +15,7 @@ type
a, b: ref TExpr
op2: string
method eval(e: ref TExpr): int =
method eval(e: ref TExpr): int {.base.} =
# override this base method
quit "to override!"
@@ -30,7 +30,7 @@ proc newLit(x: int): ref TLiteral =
result.x = x
result.op1 = $getOccupiedMem()
proc newPlus(a, b: ref TExpr): ref TPlusExpr =
proc newPlus(a, b: sink(ref TExpr)): ref TPlusExpr =
new(result)
result.a = a
result.b = b

View File

@@ -12,7 +12,8 @@ type
proc makePair: PCyclic =
new(result)
new(result.sibling)
result.sibling.sibling = result
when not defined(gcDestructors):
result.sibling.sibling = result
proc loop =
for i in 0..10000:

View File

@@ -19,8 +19,15 @@ var
proc finalizer(x: StrongObject) =
valid.excl(x.id)
when defined(gcDestructors):
proc `=destroy`(x: var TMyObject) =
valid.excl(x.id)
proc create: StrongObject =
new(result, finalizer)
when defined(gcDestructors):
new(result)
else:
new(result, finalizer)
result.id = gid
valid.incl(gid)
inc gid