--gc:destructors now means Nim uses pure refcounting (#12557)
This commit is contained in:
parent
b5bb581642
commit
1746da2d9e
12 changed files with 123 additions and 35 deletions
|
|
@ -1206,7 +1206,7 @@ proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) =
|
||||||
if sizeExpr.isNil:
|
if sizeExpr.isNil:
|
||||||
sizeExpr = "sizeof($1)" % [getTypeDesc(p.module, bt)]
|
sizeExpr = "sizeof($1)" % [getTypeDesc(p.module, bt)]
|
||||||
|
|
||||||
if optOwnedRefs in p.config.globalOptions:
|
if optTinyRtti in p.config.globalOptions:
|
||||||
b.r = ropecg(p.module, "($1) #nimNewObj($2)",
|
b.r = ropecg(p.module, "($1) #nimNewObj($2)",
|
||||||
[getTypeDesc(p.module, typ), sizeExpr])
|
[getTypeDesc(p.module, typ), sizeExpr])
|
||||||
genAssignment(p, a, b, {})
|
genAssignment(p, a, b, {})
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ const
|
||||||
# above X strings a hash-switch for strings is generated
|
# above X strings a hash-switch for strings is generated
|
||||||
|
|
||||||
proc getTraverseProc(p: BProc, v: PSym): Rope =
|
proc getTraverseProc(p: BProc, v: PSym): Rope =
|
||||||
if p.config.selectedGC in {gcMarkAndSweep, gcDestructors, gcV2, gcRefc} and
|
if p.config.selectedGC in {gcMarkAndSweep, gcHooks, gcV2, gcRefc} and
|
||||||
optOwnedRefs notin p.config.globalOptions and
|
optOwnedRefs notin p.config.globalOptions and
|
||||||
containsGarbageCollectedRef(v.loc.t):
|
containsGarbageCollectedRef(v.loc.t):
|
||||||
# we register a specialized marked proc here; this has the advantage
|
# we register a specialized marked proc here; this has the advantage
|
||||||
|
|
|
||||||
|
|
@ -230,6 +230,7 @@ proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo
|
||||||
of "markandsweep": result = conf.selectedGC == gcMarkAndSweep
|
of "markandsweep": result = conf.selectedGC == gcMarkAndSweep
|
||||||
of "generational": result = false
|
of "generational": result = false
|
||||||
of "destructors": result = conf.selectedGC == gcDestructors
|
of "destructors": result = conf.selectedGC == gcDestructors
|
||||||
|
of "hooks": result = conf.selectedGC == gcHooks
|
||||||
of "go": result = conf.selectedGC == gcGo
|
of "go": result = conf.selectedGC == gcGo
|
||||||
of "none": result = conf.selectedGC == gcNone
|
of "none": result = conf.selectedGC == gcNone
|
||||||
of "stack", "regions": result = conf.selectedGC == gcRegions
|
of "stack", "regions": result = conf.selectedGC == gcRegions
|
||||||
|
|
@ -453,6 +454,17 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||||
conf.selectedGC = gcDestructors
|
conf.selectedGC = gcDestructors
|
||||||
defineSymbol(conf.symbols, "gcdestructors")
|
defineSymbol(conf.symbols, "gcdestructors")
|
||||||
incl conf.globalOptions, optSeqDestructors
|
incl conf.globalOptions, optSeqDestructors
|
||||||
|
incl conf.globalOptions, optTinyRtti
|
||||||
|
if pass in {passCmd2, passPP}:
|
||||||
|
defineSymbol(conf.symbols, "nimSeqsV2")
|
||||||
|
defineSymbol(conf.symbols, "nimV2")
|
||||||
|
of "hooks":
|
||||||
|
conf.selectedGC = gcHooks
|
||||||
|
defineSymbol(conf.symbols, "gchooks")
|
||||||
|
incl conf.globalOptions, optSeqDestructors
|
||||||
|
processOnOffSwitchG(conf, {optSeqDestructors}, arg, pass, info)
|
||||||
|
if pass in {passCmd2, passPP}:
|
||||||
|
defineSymbol(conf.symbols, "nimSeqsV2")
|
||||||
of "go":
|
of "go":
|
||||||
conf.selectedGC = gcGo
|
conf.selectedGC = gcGo
|
||||||
defineSymbol(conf.symbols, "gogc")
|
defineSymbol(conf.symbols, "gogc")
|
||||||
|
|
@ -460,7 +472,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||||
conf.selectedGC = gcNone
|
conf.selectedGC = gcNone
|
||||||
defineSymbol(conf.symbols, "nogc")
|
defineSymbol(conf.symbols, "nogc")
|
||||||
of "stack", "regions":
|
of "stack", "regions":
|
||||||
conf.selectedGC= gcRegions
|
conf.selectedGC = gcRegions
|
||||||
defineSymbol(conf.symbols, "gcregions")
|
defineSymbol(conf.symbols, "gcregions")
|
||||||
else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
|
else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
|
||||||
of "warnings", "w":
|
of "warnings", "w":
|
||||||
|
|
@ -509,7 +521,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||||
undefSymbol(conf.symbols, "useNimRtl")
|
undefSymbol(conf.symbols, "useNimRtl")
|
||||||
of "oldnewlines":
|
of "oldnewlines":
|
||||||
case arg.normalize
|
case arg.normalize
|
||||||
of "","on":
|
of "", "on":
|
||||||
conf.oldNewlines = true
|
conf.oldNewlines = true
|
||||||
defineSymbol(conf.symbols, "nimOldNewlines")
|
defineSymbol(conf.symbols, "nimOldNewlines")
|
||||||
of "off":
|
of "off":
|
||||||
|
|
@ -763,9 +775,10 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||||
incl(conf.globalOptions, optOwnedRefs)
|
incl(conf.globalOptions, optOwnedRefs)
|
||||||
incl(conf.globalOptions, optSeqDestructors)
|
incl(conf.globalOptions, optSeqDestructors)
|
||||||
defineSymbol(conf.symbols, "nimV2")
|
defineSymbol(conf.symbols, "nimV2")
|
||||||
conf.selectedGC = gcDestructors
|
conf.selectedGC = gcHooks
|
||||||
defineSymbol(conf.symbols, "gcdestructors")
|
defineSymbol(conf.symbols, "gchooks")
|
||||||
defineSymbol(conf.symbols, "nimSeqsV2")
|
defineSymbol(conf.symbols, "nimSeqsV2")
|
||||||
|
defineSymbol(conf.symbols, "nimOwnedEnabled")
|
||||||
of "seqsv2":
|
of "seqsv2":
|
||||||
processOnOffSwitchG(conf, {optSeqDestructors}, arg, pass, info)
|
processOnOffSwitchG(conf, {optSeqDestructors}, arg, pass, info)
|
||||||
if pass in {passCmd2, passPP}:
|
if pass in {passCmd2, passPP}:
|
||||||
|
|
|
||||||
|
|
@ -344,7 +344,8 @@ proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) =
|
||||||
# with cycles properly, so it's better to produce a weak ref (=ptr) here.
|
# with cycles properly, so it's better to produce a weak ref (=ptr) here.
|
||||||
# This seems to be generally correct but since it's a bit risky it's disabled
|
# This seems to be generally correct but since it's a bit risky it's disabled
|
||||||
# for now.
|
# for now.
|
||||||
let fieldType = if isDefined(c.graph.config, "nimCycleBreaker"):
|
let fieldType = if isDefined(c.graph.config, "nimCycleBreaker") or
|
||||||
|
c.graph.config.selectedGC == gcDestructors:
|
||||||
c.getEnvTypeForOwnerUp(dep, info) #getHiddenParam(dep).typ
|
c.getEnvTypeForOwnerUp(dep, info) #getHiddenParam(dep).typ
|
||||||
else:
|
else:
|
||||||
c.getEnvTypeForOwner(dep, info)
|
c.getEnvTypeForOwner(dep, info)
|
||||||
|
|
|
||||||
|
|
@ -359,6 +359,58 @@ proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
of attachedDestructor:
|
of attachedDestructor:
|
||||||
body.add genBuiltin(c.g, mDestroy, "destroy", x)
|
body.add genBuiltin(c.g, mDestroy, "destroy", x)
|
||||||
|
|
||||||
|
proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
|
var actions = newNodeI(nkStmtList, c.info)
|
||||||
|
let elemType = t.lastSon
|
||||||
|
|
||||||
|
if isFinal(elemType):
|
||||||
|
addDestructorCall(c, elemType, actions, genDeref(x, nkDerefExpr))
|
||||||
|
actions.add callCodegenProc(c.g, "nimRawDispose", c.info, x)
|
||||||
|
else:
|
||||||
|
addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(x, nkDerefExpr))
|
||||||
|
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, x)
|
||||||
|
|
||||||
|
let cond = callCodegenProc(c.g, "nimDecRefIsLast", c.info, x)
|
||||||
|
cond.typ = getSysType(c.g, x.info, tyBool)
|
||||||
|
|
||||||
|
case c.kind
|
||||||
|
of attachedSink:
|
||||||
|
body.add genIf(c, cond, actions)
|
||||||
|
body.add newAsgnStmt(x, y)
|
||||||
|
of attachedAsgn:
|
||||||
|
body.add genIf(c, y, callCodegenProc(c.g, "nimIncRef", c.info, y))
|
||||||
|
body.add genIf(c, cond, actions)
|
||||||
|
body.add newAsgnStmt(x, y)
|
||||||
|
of attachedDestructor:
|
||||||
|
body.add genIf(c, cond, actions)
|
||||||
|
of attachedDeepCopy: assert(false, "cannot happen")
|
||||||
|
|
||||||
|
proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
|
## Closures are really like refs except they always use a virtual destructor
|
||||||
|
## and we need to do the refcounting only on the ref field which we call 'xenv':
|
||||||
|
let xenv = genBuiltin(c.g, mAccessEnv, "accessEnv", x)
|
||||||
|
xenv.typ = getSysType(c.g, c.info, tyPointer)
|
||||||
|
|
||||||
|
var actions = newNodeI(nkStmtList, c.info)
|
||||||
|
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, xenv)
|
||||||
|
|
||||||
|
let cond = callCodegenProc(c.g, "nimDecRefIsLast", c.info, xenv)
|
||||||
|
cond.typ = getSysType(c.g, x.info, tyBool)
|
||||||
|
|
||||||
|
case c.kind
|
||||||
|
of attachedSink:
|
||||||
|
body.add genIf(c, cond, actions)
|
||||||
|
body.add newAsgnStmt(x, y)
|
||||||
|
of attachedAsgn:
|
||||||
|
let yenv = genBuiltin(c.g, mAccessEnv, "accessEnv", y)
|
||||||
|
yenv.typ = getSysType(c.g, c.info, tyPointer)
|
||||||
|
body.add genIf(c, yenv, callCodegenProc(c.g, "nimIncRef", c.info, yenv))
|
||||||
|
body.add genIf(c, cond, actions)
|
||||||
|
body.add newAsgnStmt(x, y)
|
||||||
|
of attachedDestructor:
|
||||||
|
body.add genIf(c, cond, actions)
|
||||||
|
of attachedDeepCopy: assert(false, "cannot happen")
|
||||||
|
|
||||||
proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
case c.kind
|
case c.kind
|
||||||
of attachedSink:
|
of attachedSink:
|
||||||
|
|
@ -367,7 +419,7 @@ proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
body.add genIf(c, x, callCodegenProc(c.g, "nimDecWeakRef", c.info, x))
|
body.add genIf(c, x, callCodegenProc(c.g, "nimDecWeakRef", c.info, x))
|
||||||
body.add newAsgnStmt(x, y)
|
body.add newAsgnStmt(x, y)
|
||||||
of attachedAsgn:
|
of attachedAsgn:
|
||||||
body.add genIf(c, y, callCodegenProc(c.g, "nimIncWeakRef", c.info, y))
|
body.add genIf(c, y, callCodegenProc(c.g, "nimIncRef", c.info, y))
|
||||||
body.add genIf(c, x, callCodegenProc(c.g, "nimDecWeakRef", c.info, x))
|
body.add genIf(c, x, callCodegenProc(c.g, "nimDecWeakRef", c.info, x))
|
||||||
body.add newAsgnStmt(x, y)
|
body.add newAsgnStmt(x, y)
|
||||||
of attachedDestructor:
|
of attachedDestructor:
|
||||||
|
|
@ -411,8 +463,8 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
call.sons[0] = newSymNode(createMagic(c.g, "deepCopy", mDeepCopy))
|
call.sons[0] = newSymNode(createMagic(c.g, "deepCopy", mDeepCopy))
|
||||||
call.sons[1] = y
|
call.sons[1] = y
|
||||||
body.add newAsgnStmt(x, call)
|
body.add newAsgnStmt(x, call)
|
||||||
elif optOwnedRefs in c.g.config.globalOptions and
|
elif (optOwnedRefs in c.g.config.globalOptions and
|
||||||
optRefCheck in c.g.config.options:
|
optRefCheck in c.g.config.options) or c.g.config.selectedGC == gcDestructors:
|
||||||
let xx = genBuiltin(c.g, mAccessEnv, "accessEnv", x)
|
let xx = genBuiltin(c.g, mAccessEnv, "accessEnv", x)
|
||||||
xx.typ = getSysType(c.g, c.info, tyPointer)
|
xx.typ = getSysType(c.g, c.info, tyPointer)
|
||||||
case c.kind
|
case c.kind
|
||||||
|
|
@ -424,7 +476,7 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
of attachedAsgn:
|
of attachedAsgn:
|
||||||
let yy = genBuiltin(c.g, mAccessEnv, "accessEnv", y)
|
let yy = genBuiltin(c.g, mAccessEnv, "accessEnv", y)
|
||||||
yy.typ = getSysType(c.g, c.info, tyPointer)
|
yy.typ = getSysType(c.g, c.info, tyPointer)
|
||||||
body.add genIf(c, yy, callCodegenProc(c.g, "nimIncWeakRef", c.info, yy))
|
body.add genIf(c, yy, callCodegenProc(c.g, "nimIncRef", c.info, yy))
|
||||||
body.add genIf(c, xx, callCodegenProc(c.g, "nimDecWeakRef", c.info, xx))
|
body.add genIf(c, xx, callCodegenProc(c.g, "nimDecWeakRef", c.info, xx))
|
||||||
body.add newAsgnStmt(x, y)
|
body.add newAsgnStmt(x, y)
|
||||||
of attachedDestructor:
|
of attachedDestructor:
|
||||||
|
|
@ -439,7 +491,6 @@ proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
let xx = genBuiltin(c.g, mAccessEnv, "accessEnv", x)
|
let xx = genBuiltin(c.g, mAccessEnv, "accessEnv", x)
|
||||||
xx.typ = getSysType(c.g, c.info, tyPointer)
|
xx.typ = getSysType(c.g, c.info, tyPointer)
|
||||||
var actions = newNodeI(nkStmtList, c.info)
|
var actions = newNodeI(nkStmtList, c.info)
|
||||||
let elemType = t.lastSon
|
|
||||||
#discard addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(xx))
|
#discard addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(xx))
|
||||||
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, xx)
|
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, xx)
|
||||||
case c.kind
|
case c.kind
|
||||||
|
|
@ -457,14 +508,19 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
tyPtr, tyOpt, tyUncheckedArray:
|
tyPtr, tyOpt, tyUncheckedArray:
|
||||||
defaultOp(c, t, body, x, y)
|
defaultOp(c, t, body, x, y)
|
||||||
of tyRef:
|
of tyRef:
|
||||||
if optOwnedRefs in c.g.config.globalOptions and
|
if c.g.config.selectedGC == gcDestructors:
|
||||||
optRefCheck in c.g.config.options:
|
atomicRefOp(c, t, body, x, y)
|
||||||
|
elif (optOwnedRefs in c.g.config.globalOptions and
|
||||||
|
optRefCheck in c.g.config.options):
|
||||||
weakrefOp(c, t, body, x, y)
|
weakrefOp(c, t, body, x, y)
|
||||||
else:
|
else:
|
||||||
defaultOp(c, t, body, x, y)
|
defaultOp(c, t, body, x, y)
|
||||||
of tyProc:
|
of tyProc:
|
||||||
if t.callConv == ccClosure:
|
if t.callConv == ccClosure:
|
||||||
closureOp(c, t, body, x, y)
|
if c.g.config.selectedGC == gcDestructors:
|
||||||
|
atomicClosureOp(c, t, body, x, y)
|
||||||
|
else:
|
||||||
|
closureOp(c, t, body, x, y)
|
||||||
else:
|
else:
|
||||||
defaultOp(c, t, body, x, y)
|
defaultOp(c, t, body, x, y)
|
||||||
of tyOwned:
|
of tyOwned:
|
||||||
|
|
@ -532,7 +588,8 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
tyGenericInst, tyStatic, tyAlias, tySink:
|
tyGenericInst, tyStatic, tyAlias, tySink:
|
||||||
fillBody(c, lastSon(t), body, x, y)
|
fillBody(c, lastSon(t), body, x, y)
|
||||||
|
|
||||||
proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp; info: TLineInfo): PSym =
|
proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType;
|
||||||
|
kind: TTypeAttachedOp; info: TLineInfo): PSym =
|
||||||
assert typ.kind == tyDistinct
|
assert typ.kind == tyDistinct
|
||||||
let baseType = typ[0]
|
let baseType = typ[0]
|
||||||
if baseType.attachedOps[kind] == nil:
|
if baseType.attachedOps[kind] == nil:
|
||||||
|
|
@ -571,7 +628,7 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||||
typ.attachedOps[kind] = result
|
typ.attachedOps[kind] = result
|
||||||
|
|
||||||
var tk: TTypeKind
|
var tk: TTypeKind
|
||||||
if g.config.selectedGC == gcDestructors:
|
if g.config.selectedGC in {gcDestructors, gcHooks}:
|
||||||
tk = skipTypes(typ, {tyOrdinal, tyRange, tyInferred, tyGenericInst, tyStatic, tyAlias, tySink}).kind
|
tk = skipTypes(typ, {tyOrdinal, tyRange, tyInferred, tyGenericInst, tyStatic, tyAlias, tySink}).kind
|
||||||
else:
|
else:
|
||||||
tk = tyNone # no special casing for strings and seqs
|
tk = tyNone # no special casing for strings and seqs
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,7 @@ type
|
||||||
TStringSeq* = seq[string]
|
TStringSeq* = seq[string]
|
||||||
TGCMode* = enum # the selected GC
|
TGCMode* = enum # the selected GC
|
||||||
gcUnselected, gcNone, gcBoehm, gcRegions, gcMarkAndSweep, gcDestructors,
|
gcUnselected, gcNone, gcBoehm, gcRegions, gcMarkAndSweep, gcDestructors,
|
||||||
|
gcHooks,
|
||||||
gcRefc, gcV2, gcGo
|
gcRefc, gcV2, gcGo
|
||||||
# gcRefc and the GCs that follow it use a write barrier,
|
# gcRefc and the GCs that follow it use a write barrier,
|
||||||
# as far as usesWriteBarrier() is concerned
|
# as far as usesWriteBarrier() is concerned
|
||||||
|
|
|
||||||
|
|
@ -57,13 +57,13 @@ proc nimNewObj(size: int): pointer {.compilerRtl.} =
|
||||||
else:
|
else:
|
||||||
inc allocs
|
inc allocs
|
||||||
|
|
||||||
proc nimDecWeakRef(p: pointer) {.compilerRtl.} =
|
proc nimDecWeakRef(p: pointer) {.compilerRtl, inl.} =
|
||||||
when hasThreadSupport:
|
when hasThreadSupport:
|
||||||
atomicDec head(p).rc
|
atomicDec head(p).rc
|
||||||
else:
|
else:
|
||||||
dec head(p).rc
|
dec head(p).rc
|
||||||
|
|
||||||
proc nimIncWeakRef(p: pointer) {.compilerRtl.} =
|
proc nimIncRef(p: pointer) {.compilerRtl, inl.} =
|
||||||
when hasThreadSupport:
|
when hasThreadSupport:
|
||||||
atomicInc head(p).rc
|
atomicInc head(p).rc
|
||||||
else:
|
else:
|
||||||
|
|
@ -106,11 +106,25 @@ proc nimDestroyAndDispose(p: pointer) {.compilerRtl.} =
|
||||||
cstderr.rawWrite "has destructor!\n"
|
cstderr.rawWrite "has destructor!\n"
|
||||||
nimRawDispose(p)
|
nimRawDispose(p)
|
||||||
|
|
||||||
proc isObj(obj: PNimType, subclass: cstring): bool {.compilerproc.} =
|
proc nimDecRefIsLast(p: pointer): bool {.compilerRtl, inl.} =
|
||||||
|
if p != nil:
|
||||||
|
when hasThreadSupport:
|
||||||
|
if atomicLoadN(addr head(p).rc, ATOMIC_RELAXED) == 0:
|
||||||
|
result = true
|
||||||
|
else:
|
||||||
|
if atomicDec(head(p).rc) <= 0:
|
||||||
|
result = true
|
||||||
|
else:
|
||||||
|
if head(p).rc == 0:
|
||||||
|
result = true
|
||||||
|
else:
|
||||||
|
dec head(p).rc
|
||||||
|
|
||||||
|
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.}
|
||||||
|
|
||||||
result = strstr(obj.name, subclass) != nil
|
result = strstr(obj.name, subclass) != nil
|
||||||
|
|
||||||
proc chckObj(obj: PNimType, subclass: cstring) {.compilerproc.} =
|
proc chckObj(obj: PNimType, subclass: cstring) {.compilerRtl.} =
|
||||||
# checks if obj is of type subclass:
|
# checks if obj is of type subclass:
|
||||||
if not isObj(obj, subclass): sysFatal(ObjectConversionError, "invalid object conversion")
|
if not isObj(obj, subclass): sysFatal(ObjectConversionError, "invalid object conversion")
|
||||||
|
|
|
||||||
|
|
@ -1722,12 +1722,12 @@ template `isnot`*(x, y: untyped): untyped = not (x is y)
|
||||||
## assert 42 isnot float
|
## assert 42 isnot float
|
||||||
## assert @[1, 2] isnot enum
|
## assert @[1, 2] isnot enum
|
||||||
|
|
||||||
when (defined(nimV2) and not defined(nimscript)) or defined(nimFixedOwned):
|
when (defined(nimOwnedEnabled) and not defined(nimscript)) or defined(nimFixedOwned):
|
||||||
type owned*[T]{.magic: "BuiltinType".} ## type constructor to mark a ref/ptr or a closure as `owned`.
|
type owned*[T]{.magic: "BuiltinType".} ## type constructor to mark a ref/ptr or a closure as `owned`.
|
||||||
else:
|
else:
|
||||||
template owned*(t: typedesc): typedesc = t
|
template owned*(t: typedesc): typedesc = t
|
||||||
|
|
||||||
when defined(nimV2) and not defined(nimscript):
|
when defined(nimOwnedEnabled) and not defined(nimscript):
|
||||||
proc new*[T](a: var owned(ref T)) {.magic: "New", noSideEffect.}
|
proc new*[T](a: var owned(ref T)) {.magic: "New", 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)
|
||||||
## reference to it in ``a``.
|
## reference to it in ``a``.
|
||||||
|
|
@ -3237,6 +3237,8 @@ proc `<`*[T: tuple](x, y: T): bool =
|
||||||
|
|
||||||
|
|
||||||
# ----------------- GC interface ---------------------------------------------
|
# ----------------- GC interface ---------------------------------------------
|
||||||
|
const
|
||||||
|
usesDestructors = defined(gcDestructors) or defined(gcHooks)
|
||||||
|
|
||||||
when not defined(nimscript) and hasAlloc:
|
when not defined(nimscript) and hasAlloc:
|
||||||
type
|
type
|
||||||
|
|
@ -3246,7 +3248,7 @@ when not defined(nimscript) and hasAlloc:
|
||||||
gcOptimizeTime, ## optimize for speed
|
gcOptimizeTime, ## optimize for speed
|
||||||
gcOptimizeSpace ## optimize for memory footprint
|
gcOptimizeSpace ## optimize for memory footprint
|
||||||
|
|
||||||
when not defined(JS) and not defined(gcDestructors):
|
when not defined(JS) and not usesDestructors:
|
||||||
proc GC_disable*() {.rtl, inl, benign.}
|
proc GC_disable*() {.rtl, inl, benign.}
|
||||||
## Disables the GC. If called `n` times, `n` calls to `GC_enable`
|
## Disables the GC. If called `n` times, `n` calls to `GC_enable`
|
||||||
## are needed to reactivate the GC.
|
## are needed to reactivate the GC.
|
||||||
|
|
@ -3602,7 +3604,7 @@ when not defined(JS): #and not defined(nimscript):
|
||||||
{.push stack_trace: off, profiler:off.}
|
{.push stack_trace: off, profiler:off.}
|
||||||
|
|
||||||
when hasAlloc:
|
when hasAlloc:
|
||||||
when not defined(gcRegions) and not defined(gcDestructors):
|
when not defined(gcRegions) and not usesDestructors:
|
||||||
proc initGC() {.gcsafe.}
|
proc initGC() {.gcsafe.}
|
||||||
|
|
||||||
proc initStackBottom() {.inline, compilerproc.} =
|
proc initStackBottom() {.inline, compilerproc.} =
|
||||||
|
|
@ -3620,7 +3622,7 @@ when not defined(JS): #and not defined(nimscript):
|
||||||
when declared(nimGC_setStackBottom):
|
when declared(nimGC_setStackBottom):
|
||||||
nimGC_setStackBottom(locals)
|
nimGC_setStackBottom(locals)
|
||||||
|
|
||||||
when not defined(gcDestructors):
|
when not usesDestructors:
|
||||||
{.push profiler: off.}
|
{.push profiler: off.}
|
||||||
var
|
var
|
||||||
strDesc = TNimType(size: sizeof(string), kind: tyString, flags: {ntfAcyclic})
|
strDesc = TNimType(size: sizeof(string), kind: tyString, flags: {ntfAcyclic})
|
||||||
|
|
@ -3792,10 +3794,10 @@ when not defined(JS): #and not defined(nimscript):
|
||||||
when hasAlloc: include "system/strmantle"
|
when hasAlloc: include "system/strmantle"
|
||||||
|
|
||||||
when hasThreadSupport:
|
when hasThreadSupport:
|
||||||
when hostOS != "standalone" and not defined(gcDestructors): include "system/channels"
|
when hostOS != "standalone" and not usesDestructors: include "system/channels"
|
||||||
|
|
||||||
when not defined(nimscript) and hasAlloc:
|
when not defined(nimscript) and hasAlloc:
|
||||||
when not defined(gcDestructors):
|
when not usesDestructors:
|
||||||
include "system/assign"
|
include "system/assign"
|
||||||
when not defined(nimV2):
|
when not defined(nimV2):
|
||||||
include "system/repr"
|
include "system/repr"
|
||||||
|
|
@ -4396,7 +4398,7 @@ proc locals*(): RootObj {.magic: "Plugin", noSideEffect.} =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
when hasAlloc and not defined(nimscript) and not defined(JS) and
|
when hasAlloc and not defined(nimscript) and not defined(JS) and
|
||||||
not defined(gcDestructors):
|
not usesDestructors:
|
||||||
# XXX how to implement 'deepCopy' is an open problem.
|
# XXX how to implement 'deepCopy' is an open problem.
|
||||||
proc deepCopy*[T](x: var T, y: T) {.noSideEffect, magic: "DeepCopy".} =
|
proc deepCopy*[T](x: var T, y: T) {.noSideEffect, magic: "DeepCopy".} =
|
||||||
## Performs a deep copy of `y` and copies it into `x`.
|
## Performs a deep copy of `y` and copies it into `x`.
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ type
|
||||||
ntfEnumHole = 2 # enum has holes and thus `$` for them needs the slow
|
ntfEnumHole = 2 # enum has holes and thus `$` for them needs the slow
|
||||||
# version
|
# version
|
||||||
TNimType {.compilerproc.} = object
|
TNimType {.compilerproc.} = object
|
||||||
when defined(gcDestructors):
|
when defined(gcHooks):
|
||||||
head*: pointer
|
head*: pointer
|
||||||
size*: int
|
size*: int
|
||||||
kind: TNimKind
|
kind: TNimKind
|
||||||
|
|
@ -103,7 +103,7 @@ type
|
||||||
instances: int # count the number of instances
|
instances: int # count the number of instances
|
||||||
sizes: int # sizes of all instances in bytes
|
sizes: int # sizes of all instances in bytes
|
||||||
|
|
||||||
when defined(gcDestructors):
|
when defined(gcHooks):
|
||||||
type
|
type
|
||||||
PNimType* = ptr TNimType
|
PNimType* = ptr TNimType
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -507,10 +507,10 @@ else:
|
||||||
elif defined(gcRegions):
|
elif defined(gcRegions):
|
||||||
# XXX due to bootstrapping reasons, we cannot use compileOption("gc", "stack") here
|
# XXX due to bootstrapping reasons, we cannot use compileOption("gc", "stack") here
|
||||||
include "system/gc_regions"
|
include "system/gc_regions"
|
||||||
elif defined(nimV2) or defined(gcDestructors):
|
elif defined(nimV2) or usesDestructors:
|
||||||
var allocator {.rtlThreadVar.}: MemRegion
|
var allocator {.rtlThreadVar.}: MemRegion
|
||||||
instantiateForRegion(allocator)
|
instantiateForRegion(allocator)
|
||||||
when defined(gcDestructors):
|
when defined(gcHooks):
|
||||||
include "system/gc_hooks"
|
include "system/gc_hooks"
|
||||||
elif defined(gcMarkAndSweep):
|
elif defined(gcMarkAndSweep):
|
||||||
# XXX use 'compileOption' here
|
# XXX use 'compileOption' here
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,7 @@ when not defined(useNimRtl):
|
||||||
cl: var ReprClosure) =
|
cl: var ReprClosure) =
|
||||||
# we know that p is not nil here:
|
# we know that p is not nil here:
|
||||||
when declared(CellSet):
|
when declared(CellSet):
|
||||||
when defined(boehmGC) or defined(gogc) or defined(nogc) or defined(gcDestructors):
|
when defined(boehmGC) or defined(gogc) or defined(nogc) or usesDestructors:
|
||||||
var cell = cast[PCell](p)
|
var cell = cast[PCell](p)
|
||||||
else:
|
else:
|
||||||
var cell = usrToCell(p)
|
var cell = usrToCell(p)
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,7 @@ else:
|
||||||
proc threadProcWrapStackFrame[TArg](thrd: ptr Thread[TArg]) =
|
proc threadProcWrapStackFrame[TArg](thrd: ptr Thread[TArg]) =
|
||||||
when defined(boehmgc):
|
when defined(boehmgc):
|
||||||
boehmGC_call_with_stack_base(threadProcWrapDispatch[TArg], thrd)
|
boehmGC_call_with_stack_base(threadProcWrapDispatch[TArg], thrd)
|
||||||
elif not defined(nogc) and not defined(gogc) and not defined(gcRegions) and not defined(gcDestructors):
|
elif not defined(nogc) and not defined(gogc) and not defined(gcRegions) and not usesDestructors:
|
||||||
var p {.volatile.}: proc(a: ptr Thread[TArg]) {.nimcall, gcsafe.} =
|
var p {.volatile.}: proc(a: ptr Thread[TArg]) {.nimcall, gcsafe.} =
|
||||||
threadProcWrapDispatch[TArg]
|
threadProcWrapDispatch[TArg]
|
||||||
# init the GC for refc/markandsweep
|
# init the GC for refc/markandsweep
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue