cleaner GC switching

This commit is contained in:
Araq 2013-01-31 16:34:39 +01:00
commit 2a2b630757
7 changed files with 32 additions and 25 deletions

View file

@ -164,7 +164,7 @@ proc getStorageLoc(n: PNode): TStorageLoc =
else: result = OnUnknown else: result = OnUnknown
proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
if dest.s == OnStack or optRefcGC notin gGlobalOptions: if dest.s == OnStack or not usesNativeGC():
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
if needToKeepAlive in flags: keepAlive(p, dest) if needToKeepAlive in flags: keepAlive(p, dest)
elif dest.s == OnHeap: elif dest.s == OnHeap:
@ -204,7 +204,7 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
# (for objects, etc.): # (for objects, etc.):
if needToCopy notin flags or if needToCopy notin flags or
tfShallow in skipTypes(dest.t, abstractVarRange).flags: tfShallow in skipTypes(dest.t, abstractVarRange).flags:
if dest.s == OnStack or optRefcGC notin gGlobalOptions: if dest.s == OnStack or not usesNativeGC():
linefmt(p, cpsStmts, linefmt(p, cpsStmts,
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n", "memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
addrLoc(dest), addrLoc(src), rdLoc(dest)) addrLoc(dest), addrLoc(src), rdLoc(dest))
@ -237,7 +237,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
if needToCopy notin flags: if needToCopy notin flags:
genRefAssign(p, dest, src, flags) genRefAssign(p, dest, src, flags)
else: else:
if dest.s == OnStack or optRefcGC notin gGlobalOptions: if dest.s == OnStack or not usesNativeGC():
linefmt(p, cpsStmts, "$1 = #copyString($2);$n", dest.rdLoc, src.rdLoc) linefmt(p, cpsStmts, "$1 = #copyString($2);$n", dest.rdLoc, src.rdLoc)
if needToKeepAlive in flags: keepAlive(p, dest) if needToKeepAlive in flags: keepAlive(p, dest)
elif dest.s == OnHeap: elif dest.s == OnHeap:
@ -954,7 +954,7 @@ proc genNew(p: BProc, e: PNode) =
let args = [getTypeDesc(p.module, reftype), let args = [getTypeDesc(p.module, reftype),
genTypeInfo(p.module, refType), genTypeInfo(p.module, refType),
sizeExpr] sizeExpr]
if a.s == OnHeap and optRefcGc in gGlobalOptions: if a.s == OnHeap and usesNativeGC():
# use newObjRC1 as an optimization; and we don't need 'keepAlive' either # use newObjRC1 as an optimization; and we don't need 'keepAlive' either
if canFormAcycle(a.t): if canFormAcycle(a.t):
linefmt(p, cpsStmts, "if ($1) #nimGCunref($1);$n", a.rdLoc) linefmt(p, cpsStmts, "if ($1) #nimGCunref($1);$n", a.rdLoc)
@ -974,7 +974,7 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: PRope) =
genTypeInfo(p.module, seqType), length] genTypeInfo(p.module, seqType), length]
var call: TLoc var call: TLoc
initLoc(call, locExpr, dest.t, OnHeap) initLoc(call, locExpr, dest.t, OnHeap)
if dest.s == OnHeap and optRefcGc in gGlobalOptions: if dest.s == OnHeap and usesNativeGC():
linefmt(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", dest.rdLoc) linefmt(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", dest.rdLoc)
call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", args) call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", args)
linefmt(p, cpsStmts, "$1 = $2;$n", dest.rdLoc, call.rdLoc) linefmt(p, cpsStmts, "$1 = $2;$n", dest.rdLoc, call.rdLoc)

View file

@ -938,7 +938,7 @@ proc genTypeInfo(m: BModule, typ: PType): PRope =
genTupleInfo(m, fakeClosureType(t.owner), result) genTupleInfo(m, fakeClosureType(t.owner), result)
of tySequence, tyRef: of tySequence, tyRef:
genTypeInfoAux(m, t, result) genTypeInfoAux(m, t, result)
if optRefcGC in gGlobalOptions: if usesNativeGC():
let markerProc = genTraverseProc(m, t, tiNew) let markerProc = genTraverseProc(m, t, tiNew)
appf(m.s[cfsTypeInit3], "$1.marker = $2;$n", [result, markerProc]) appf(m.s[cfsTypeInit3], "$1.marker = $2;$n", [result, markerProc])
of tyPtr, tyRange: genTypeInfoAux(m, t, result) of tyPtr, tyRange: genTypeInfoAux(m, t, result)

View file

@ -139,9 +139,10 @@ proc testCompileOptionArg*(switch, arg: string, info: TLineInfo): bool =
case switch.normalize case switch.normalize
of "gc": of "gc":
case arg.normalize case arg.normalize
of "boehm": result = contains(gGlobalOptions, optBoehmGC) of "boehm": result = gSelectedGC == gcBoehm
of "refc": result = contains(gGlobalOptions, optRefcGC) of "refc": result = gSelectedGC == gcRefc
of "none": result = gGlobalOptions * {optBoehmGC, optRefcGC} == {} of "v2": result = gSelectedGC == gcV2
of "none": result = gSelectedGC == gcNone
else: LocalError(info, errNoneBoehmRefcExpectedButXFound, arg) else: LocalError(info, errNoneBoehmRefcExpectedButXFound, arg)
of "opt": of "opt":
case arg.normalize case arg.normalize
@ -269,15 +270,14 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
expectArg(switch, arg, pass, info) expectArg(switch, arg, pass, info)
case arg.normalize case arg.normalize
of "boehm": of "boehm":
incl(gGlobalOptions, optBoehmGC) gSelectedGC = gcBoehm
excl(gGlobalOptions, optRefcGC)
DefineSymbol("boehmgc") DefineSymbol("boehmgc")
of "refc": of "refc":
excl(gGlobalOptions, optBoehmGC) gSelectedGC = gcRefc
incl(gGlobalOptions, optRefcGC) of "v2":
gSelectedGC = gcV2
of "none": of "none":
excl(gGlobalOptions, optRefcGC) gSelectedGC = gcNone
excl(gGlobalOptions, optBoehmGC)
defineSymbol("nogc") defineSymbol("nogc")
else: LocalError(info, errNoneBoehmRefcExpectedButXFound, arg) else: LocalError(info, errNoneBoehmRefcExpectedButXFound, arg)
of "warnings", "w": ProcessOnOffSwitch({optWarns}, arg, pass, info) of "warnings", "w": ProcessOnOffSwitch({optWarns}, arg, pass, info)

View file

@ -34,7 +34,7 @@ type # please make sure we have under 32 options
TOptions* = set[TOption] TOptions* = set[TOption]
TGlobalOption* = enum # **keep binary compatible** TGlobalOption* = enum # **keep binary compatible**
gloptNone, optForceFullMake, optBoehmGC, optRefcGC, optDeadCodeElim, gloptNone, optForceFullMake, optDeadCodeElim,
optListCmd, optCompileOnly, optNoLinking, optListCmd, optCompileOnly, optNoLinking,
optSafeCode, # only allow safe code optSafeCode, # only allow safe code
optCDebug, # turn on debugging information optCDebug, # turn on debugging information
@ -80,6 +80,8 @@ type # please make sure we have under 32 options
cmdInteractive, # start interactive session cmdInteractive, # start interactive session
cmdRun # run the project via TCC backend cmdRun # run the project via TCC backend
TStringSeq* = seq[string] TStringSeq* = seq[string]
TGCMode* = enum # the selected GC
gcNone, gcBoehm, gcRefc, gcV2 #
const const
ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck, optNilCheck, ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck, optNilCheck,
@ -90,12 +92,13 @@ var
optBoundsCheck, optOverflowCheck, optAssert, optWarns, optBoundsCheck, optOverflowCheck, optAssert, optWarns,
optHints, optStackTrace, optLineTrace, optHints, optStackTrace, optLineTrace,
optPatterns} optPatterns}
gGlobalOptions*: TGlobalOptions = {optRefcGC, optThreadAnalysis} gGlobalOptions*: TGlobalOptions = {optThreadAnalysis}
gExitcode*: int8 gExitcode*: int8
gCmd*: TCommands = cmdNone # the command
gSelectedGC* = gcRefc # the selected GC
searchPaths*, lazyPaths*: TLinkedList searchPaths*, lazyPaths*: TLinkedList
outFile*: string = "" outFile*: string = ""
headerFile*: string = "" headerFile*: string = ""
gCmd*: TCommands = cmdNone # the command
gVerbosity*: int # how verbose the compiler is gVerbosity*: int # how verbose the compiler is
gNumberOfProcessors*: int # number of processors gNumberOfProcessors*: int # number of processors
gWholeProject*: bool # for 'doc2': output any dependency gWholeProject*: bool # for 'doc2': output any dependency
@ -104,6 +107,7 @@ var
gListFullPaths*: bool gListFullPaths*: bool
proc importantComments*(): bool {.inline.} = gCmd in {cmdDoc, cmdIdeTools} proc importantComments*(): bool {.inline.} = gCmd in {cmdDoc, cmdIdeTools}
proc usesNativeGC*(): bool {.inline.} = gSelectedGC >= gcRefc
const const
genSubDir* = "nimcache" genSubDir* = "nimcache"

View file

@ -64,7 +64,7 @@ Advanced options:
--skipUserCfg do not read the user's configuration file --skipUserCfg do not read the user's configuration file
--skipParentCfg do not read the parent dirs' configuration files --skipParentCfg do not read the parent dirs' configuration files
--skipProjCfg do not read the project's configuration file --skipProjCfg do not read the project's configuration file
--gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC --gc:refc|v2|boehm|none use Nimrod's native GC|V2|Boehm GC|no GC
--index:on|off turn index file generation on|off --index:on|off turn index file generation on|off
--putenv:key=value set an environment variable --putenv:key=value set an environment variable
--babelPath:PATH add a path for Babel support --babelPath:PATH add a path for Babel support

View file

@ -126,6 +126,7 @@ proc runGcTests(r: var TResults, options: string) =
test "gctest" test "gctest"
test "gcleak3" test "gcleak3"
test "weakrefs" test "weakrefs"
test "cycleleak"
# ------------------------- threading tests ----------------------------------- # ------------------------- threading tests -----------------------------------

View file

@ -46,6 +46,8 @@ Concurrency
an ``injectLoop`` pragma an ``injectLoop`` pragma
- 'writes: []' effect; track reads/writes for shared types - 'writes: []' effect; track reads/writes for shared types
- use the effect system for static deadlock prevention and race detection - use the effect system for static deadlock prevention and race detection
- introduce 'noaddr' pragma to prevent taking the address of a location; this
is very handy to prevent aliasing of global data
version 0.9.XX version 0.9.XX