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
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) var temp = newSym(skTemp, getIdent(g.cache, genPrefix), owner, value.info, g.config.options)
temp.typ = skipTypes(value.typ, abstractInst) temp.typ = skipTypes(value.typ, abstractInst)
incl(temp.flags, sfFromGeneric) incl(temp.flags, sfFromGeneric)
incl(temp.flags, sfCursor)
var v = newNodeI(nkVarSection, value.info) var v = newNodeI(nkVarSection, value.info)
let tempAsNode = newSymNode(temp) let tempAsNode = newSymNode(temp)

View file

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

View file

@ -886,6 +886,10 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType =
t.flags.incl tfHasOwned t.flags.incl tfHasOwned
t.rawAddSonNoPropagationOfTypeFlags result t.rawAddSonNoPropagationOfTypeFlags result
result = t 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 = proc findEnforcedStaticType(t: PType): PType =
# This handles types such as `static[T] and Foo`, # 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'. ## New runtime only supports this operation for 'ref T'.
if x != nil: nimIncRef(cast[pointer](x)) 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 isObj(obj: PNimType, subclass: cstring): bool {.compilerRtl, inl.} =
proc strstr(s, sub: cstring): cstring {.header: "<string.h>", importc.} proc strstr(s, sub: cstring): cstring {.header: "<string.h>", importc.}

View file

@ -250,6 +250,7 @@ const ThisIsSystem = true
proc internalNew*[T](a: var ref T) {.magic: "New", noSideEffect.} proc internalNew*[T](a: var ref T) {.magic: "New", noSideEffect.}
## Leaked implementation detail. Do not use. ## Leaked implementation detail. Do not use.
when not defined(gcDestructors):
proc new*[T](a: var ref T, finalizer: proc (x: ref T) {.nimcall.}) {. proc new*[T](a: var ref T, finalizer: proc (x: ref T) {.nimcall.}) {.
magic: "NewFinalize", noSideEffect.} magic: "NewFinalize", noSideEffect.}
## Creates a new object of type ``T`` and returns a safe (traced) ## Creates a new object of type ``T`` and returns a safe (traced)

View file

@ -304,3 +304,12 @@ proc `$`*(x: uint64): string {.noSideEffect, raises: [].} =
let half = i div 2 let half = i div 2
# Reverse # Reverse
for t in 0 .. half-1: swap(result[t], result[i-t-1]) 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", "coroutines",
"osproc", "osproc",
"shouldfail", "shouldfail",
"dir with space" "dir with space",
"destructor"
] ]
proc isTestFile*(file: string): bool = proc isTestFile*(file: string): bool =
@ -176,6 +177,11 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
" -d:release", cat) " -d:release", cat)
testSpec r, makeTest("tests/gc" / filename, options & testSpec r, makeTest("tests/gc" / filename, options &
" -d:release -d:useRealtimeGC", cat) " -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) = template testWithoutBoehm(filename: untyped) =
testWithoutMs filename testWithoutMs filename

View file

@ -28,7 +28,7 @@ proc test(): auto =
var (a, b, _) = test() var (a, b, _) = test()
doAssert assign_counter == 0 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 # bug #11510
proc main = proc main =

View file

@ -3,8 +3,6 @@ discard """
disabled: "32bit" disabled: "32bit"
""" """
from strutils import join
type type
TFoo* = object TFoo* = object
id: int id: int
@ -12,10 +10,20 @@ type
var foo_counter = 0 var foo_counter = 0
var alive_foos = newseq[int](0) var alive_foos = newseq[int](0)
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) = proc free*(some: ref TFoo) =
#echo "Tfoo #", some.id, " freed" #echo "Tfoo #", some.id, " freed"
alive_foos.del alive_foos.find(some.id) alive_foos.del alive_foos.find(some.id)
proc newFoo*(): ref TFoo = proc newFoo*(): ref TFoo =
when defined(gcDestructors):
new result
else:
new result, free new result, free
result.id = foo_counter result.id = foo_counter

View file

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

View file

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

View file

@ -12,6 +12,7 @@ type
proc makePair: PCyclic = proc makePair: PCyclic =
new(result) new(result)
new(result.sibling) new(result.sibling)
when not defined(gcDestructors):
result.sibling.sibling = result result.sibling.sibling = result
proc loop = proc loop =

View file

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