Skip to content

Commit

Permalink
ARC: ported the GC tests over to --gc:arc
Browse files Browse the repository at this point in the history
  • Loading branch information
Araq committed Nov 26, 2019
1 parent 879801c commit 72237e2
Show file tree
Hide file tree
Showing 14 changed files with 79 additions and 29 deletions.
1 change: 1 addition & 0 deletions compiler/lowerings.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions compiler/sempass2.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
4 changes: 4 additions & 0 deletions compiler/semtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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`,
Expand Down
12 changes: 12 additions & 0 deletions lib/core/runtime_v2.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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.}

Expand Down
25 changes: 13 additions & 12 deletions lib/system.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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.}
Expand Down
9 changes: 9 additions & 0 deletions lib/system/strmantle.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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" &
8 changes: 7 additions & 1 deletion testament/categories.nim
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ const
"coroutines",
"osproc",
"shouldfail",
"dir with space"
"dir with space",
"destructor"
]

proc isTestFile*(file: string): bool =
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion tests/destructor/tmisc_destructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
22 changes: 15 additions & 7 deletions tests/gc/closureleak.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion tests/gc/cycleleak.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion tests/gc/gcemscripten.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
8 changes: 4 additions & 4 deletions tests/gc/gcleak4.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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!"

Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion tests/gc/stackrefleak.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
9 changes: 8 additions & 1 deletion tests/gc/weakrefs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 72237e2

Please sign in to comment.