ORC: progress (#18000)
* ORC: progress * ORC: bugfix; don't follow acyclic data even if only at runtime the subtype is marked as acyclic * progress * minor style changes
This commit is contained in:
parent
60b4fa71a8
commit
3bc625aff1
11 changed files with 50 additions and 27 deletions
|
|
@ -16,7 +16,7 @@ const
|
||||||
Mhalf = M div 2
|
Mhalf = M div 2
|
||||||
|
|
||||||
type
|
type
|
||||||
Node[Key, Val] = ref object
|
Node[Key, Val] {.acyclic.} = ref object
|
||||||
entries: int
|
entries: int
|
||||||
keys: array[M, Key]
|
keys: array[M, Key]
|
||||||
case isInternal: bool
|
case isInternal: bool
|
||||||
|
|
|
||||||
|
|
@ -1301,6 +1301,10 @@ proc genHook(m: BModule; t: PType; info: TLineInfo; op: TTypeAttachedOp): Rope =
|
||||||
|
|
||||||
genProc(m, theProc)
|
genProc(m, theProc)
|
||||||
result = theProc.loc.r
|
result = theProc.loc.r
|
||||||
|
|
||||||
|
when false:
|
||||||
|
if not canFormAcycle(t) and op == attachedTrace:
|
||||||
|
echo "ayclic but has this =trace ", t, " ", theProc.ast
|
||||||
else:
|
else:
|
||||||
when false:
|
when false:
|
||||||
if op == attachedTrace and m.config.selectedGC == gcOrc and
|
if op == attachedTrace and m.config.selectedGC == gcOrc and
|
||||||
|
|
@ -1326,9 +1330,12 @@ proc genTypeInfoV2Impl(m: BModule, t, origType: PType, name: Rope; info: TLineIn
|
||||||
let traceImpl = genHook(m, t, info, attachedTrace)
|
let traceImpl = genHook(m, t, info, attachedTrace)
|
||||||
let disposeImpl = genHook(m, t, info, attachedDispose)
|
let disposeImpl = genHook(m, t, info, attachedDispose)
|
||||||
|
|
||||||
addf(m.s[cfsTypeInit3], "$1.destructor = (void*)$2; $1.size = sizeof($3); $1.align = NIM_ALIGNOF($3); $1.name = $4;$n; $1.traceImpl = (void*)$5; $1.disposeImpl = (void*)$6;", [
|
var flags = 0
|
||||||
|
if not canFormAcycle(t): flags = flags or 1
|
||||||
|
|
||||||
|
addf(m.s[cfsTypeInit3], "$1.destructor = (void*)$2; $1.size = sizeof($3); $1.align = NIM_ALIGNOF($3); $1.name = $4;$n; $1.traceImpl = (void*)$5; $1.disposeImpl = (void*)$6; $1.flags = $7;", [
|
||||||
name, destroyImpl, getTypeDesc(m, t), typeName,
|
name, destroyImpl, getTypeDesc(m, t), typeName,
|
||||||
traceImpl, disposeImpl])
|
traceImpl, disposeImpl, rope(flags)])
|
||||||
|
|
||||||
if t.kind == tyObject and t.len > 0 and t[0] != nil and optEnableDeepCopy in m.config.globalOptions:
|
if t.kind == tyObject and t.len > 0 and t[0] != nil and optEnableDeepCopy in m.config.globalOptions:
|
||||||
discard genTypeInfoV1(m, t, info)
|
discard genTypeInfoV1(m, t, info)
|
||||||
|
|
|
||||||
|
|
@ -513,6 +513,7 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
forallElements(c, t, body, x, y)
|
forallElements(c, t, body, x, y)
|
||||||
body.add genBuiltin(c, mDestroy, "destroy", x)
|
body.add genBuiltin(c, mDestroy, "destroy", x)
|
||||||
of attachedTrace:
|
of attachedTrace:
|
||||||
|
if canFormAcycle(t.elemType):
|
||||||
# follow all elements:
|
# follow all elements:
|
||||||
forallElements(c, t, body, x, y)
|
forallElements(c, t, body, x, y)
|
||||||
of attachedDispose:
|
of attachedDispose:
|
||||||
|
|
@ -550,6 +551,7 @@ proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
doAssert t.destructor != nil
|
doAssert t.destructor != nil
|
||||||
body.add destructorCall(c, t.destructor, x)
|
body.add destructorCall(c, t.destructor, x)
|
||||||
of attachedTrace:
|
of attachedTrace:
|
||||||
|
if t.kind != tyString and canFormAcycle(t.elemType):
|
||||||
let op = getAttachedOp(c.g, t, c.kind)
|
let op = getAttachedOp(c.g, t, c.kind)
|
||||||
if op == nil:
|
if op == nil:
|
||||||
return # protect from recursion
|
return # protect from recursion
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ type
|
||||||
|
|
||||||
POptionEntry* = ref TOptionEntry
|
POptionEntry* = ref TOptionEntry
|
||||||
PProcCon* = ref TProcCon
|
PProcCon* = ref TProcCon
|
||||||
TProcCon* = object # procedure context; also used for top-level
|
TProcCon* {.acyclic.} = object # procedure context; also used for top-level
|
||||||
# statements
|
# statements
|
||||||
owner*: PSym # the symbol this context belongs to
|
owner*: PSym # the symbol this context belongs to
|
||||||
resultSym*: PSym # the result symbol (if we are in a proc)
|
resultSym*: PSym # the result symbol (if we are in a proc)
|
||||||
|
|
|
||||||
|
|
@ -359,13 +359,13 @@ proc canFormAcycleAux(marker: var IntSet, typ: PType, startId: int): bool =
|
||||||
if tfAcyclic in t.flags: return
|
if tfAcyclic in t.flags: return
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyTuple, tyObject, tyRef, tySequence, tyArray, tyOpenArray, tyVarargs:
|
of tyTuple, tyObject, tyRef, tySequence, tyArray, tyOpenArray, tyVarargs:
|
||||||
if not containsOrIncl(marker, t.id):
|
if t.id == startId:
|
||||||
|
result = true
|
||||||
|
elif not containsOrIncl(marker, t.id):
|
||||||
for i in 0..<t.len:
|
for i in 0..<t.len:
|
||||||
result = canFormAcycleAux(marker, t[i], startId)
|
result = canFormAcycleAux(marker, t[i], startId)
|
||||||
if result: return
|
if result: return
|
||||||
if t.n != nil: result = canFormAcycleNode(marker, t.n, startId)
|
if t.n != nil: result = canFormAcycleNode(marker, t.n, startId)
|
||||||
else:
|
|
||||||
result = t.id == startId
|
|
||||||
# Inheritance can introduce cyclic types, however this is not relevant
|
# Inheritance can introduce cyclic types, however this is not relevant
|
||||||
# as the type that is passed to 'new' is statically known!
|
# as the type that is passed to 'new' is statically known!
|
||||||
# er but we use it also for the write barrier ...
|
# er but we use it also for the write barrier ...
|
||||||
|
|
|
||||||
|
|
@ -524,7 +524,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
# Used to keep track of where the execution is resumed.
|
# Used to keep track of where the execution is resumed.
|
||||||
var savedPC = -1
|
var savedPC = -1
|
||||||
var savedFrame: PStackFrame
|
var savedFrame: PStackFrame
|
||||||
when defined(gcArc):
|
when defined(gcArc) or defined(gcOrc):
|
||||||
template updateRegsAlias = discard
|
template updateRegsAlias = discard
|
||||||
template regs: untyped = tos.slots
|
template regs: untyped = tos.slots
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -270,7 +270,7 @@ type
|
||||||
procToCodePos*: Table[int, int]
|
procToCodePos*: Table[int, int]
|
||||||
|
|
||||||
PStackFrame* = ref TStackFrame
|
PStackFrame* = ref TStackFrame
|
||||||
TStackFrame* = object
|
TStackFrame* {.acyclic.} = object
|
||||||
prc*: PSym # current prc; proc that is evaluated
|
prc*: PSym # current prc; proc that is evaluated
|
||||||
slots*: seq[TFullReg] # parameters passed to the proc + locals;
|
slots*: seq[TFullReg] # parameters passed to the proc + locals;
|
||||||
# parameters come first
|
# parameters come first
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ const
|
||||||
IntMask = 1 shl IntShift - 1
|
IntMask = 1 shl IntShift - 1
|
||||||
|
|
||||||
type
|
type
|
||||||
Trunk = ref object
|
Trunk {.acyclic.} = ref object
|
||||||
next: Trunk # all nodes are connected with this pointer
|
next: Trunk # all nodes are connected with this pointer
|
||||||
key: int # start address at bit 0
|
key: int # start address at bit 0
|
||||||
bits: array[0..IntsPerTrunk - 1, BitScalar] # a bit vector
|
bits: array[0..IntsPerTrunk - 1, BitScalar] # a bit vector
|
||||||
|
|
|
||||||
|
|
@ -1805,6 +1805,7 @@ when not defined(js) and defined(nimV2):
|
||||||
traceImpl: pointer
|
traceImpl: pointer
|
||||||
disposeImpl: pointer
|
disposeImpl: pointer
|
||||||
typeInfoV1: pointer # for backwards compat, usually nil
|
typeInfoV1: pointer # for backwards compat, usually nil
|
||||||
|
flags: int
|
||||||
PNimTypeV2 = ptr TNimTypeV2
|
PNimTypeV2 = ptr TNimTypeV2
|
||||||
|
|
||||||
when notJSnotNims and defined(nimSeqsV2):
|
when notJSnotNims and defined(nimSeqsV2):
|
||||||
|
|
|
||||||
|
|
@ -109,9 +109,21 @@ proc free(s: Cell; desc: PNimTypeV2) {.inline.} =
|
||||||
|
|
||||||
nimRawDispose(p, desc.align)
|
nimRawDispose(p, desc.align)
|
||||||
|
|
||||||
|
template orcAssert(cond, msg) =
|
||||||
|
when logOrc:
|
||||||
|
if not cond:
|
||||||
|
cfprintf(cstderr, "[Bug!] %s\n", msg)
|
||||||
|
quit 1
|
||||||
|
|
||||||
|
when logOrc:
|
||||||
|
proc strstr(s, sub: cstring): cstring {.header: "<string.h>", importc.}
|
||||||
|
|
||||||
proc nimTraceRef(q: pointer; desc: PNimTypeV2; env: pointer) {.compilerRtl, inline.} =
|
proc nimTraceRef(q: pointer; desc: PNimTypeV2; env: pointer) {.compilerRtl, inline.} =
|
||||||
let p = cast[ptr pointer](q)
|
let p = cast[ptr pointer](q)
|
||||||
if p[] != nil:
|
if p[] != nil:
|
||||||
|
|
||||||
|
orcAssert strstr(desc.name, "TType") == nil, "following a TType but it's acyclic!"
|
||||||
|
|
||||||
var j = cast[ptr GcEnv](env)
|
var j = cast[ptr GcEnv](env)
|
||||||
j.traceStack.add(head p[], desc)
|
j.traceStack.add(head p[], desc)
|
||||||
|
|
||||||
|
|
@ -121,12 +133,6 @@ proc nimTraceRefDyn(q: pointer; env: pointer) {.compilerRtl, inline.} =
|
||||||
var j = cast[ptr GcEnv](env)
|
var j = cast[ptr GcEnv](env)
|
||||||
j.traceStack.add(head p[], cast[ptr PNimTypeV2](p[])[])
|
j.traceStack.add(head p[], cast[ptr PNimTypeV2](p[])[])
|
||||||
|
|
||||||
template orcAssert(cond, msg) =
|
|
||||||
when logOrc:
|
|
||||||
if not cond:
|
|
||||||
cfprintf(cstderr, "[Bug!] %s\n", msg)
|
|
||||||
quit 1
|
|
||||||
|
|
||||||
var
|
var
|
||||||
roots {.threadvar.}: CellSeq
|
roots {.threadvar.}: CellSeq
|
||||||
|
|
||||||
|
|
@ -402,6 +408,8 @@ proc registerCycle(s: Cell; desc: PNimTypeV2) =
|
||||||
when logOrc:
|
when logOrc:
|
||||||
writeCell("[added root]", s, desc)
|
writeCell("[added root]", s, desc)
|
||||||
|
|
||||||
|
orcAssert strstr(desc.name, "TType") == nil, "added a TType as a root!"
|
||||||
|
|
||||||
proc GC_runOrc* =
|
proc GC_runOrc* =
|
||||||
## Forces a cycle collection pass.
|
## Forces a cycle collection pass.
|
||||||
collectCycles()
|
collectCycles()
|
||||||
|
|
@ -436,10 +444,15 @@ proc GC_disableMarkAndSweep*() =
|
||||||
## For `--gc:orc` an alias for `GC_disableOrc`.
|
## For `--gc:orc` an alias for `GC_disableOrc`.
|
||||||
GC_disableOrc()
|
GC_disableOrc()
|
||||||
|
|
||||||
|
const
|
||||||
|
acyclicFlag = 1 # see also cggtypes.nim, proc genTypeInfoV2Impl
|
||||||
|
|
||||||
when optimizedOrc:
|
when optimizedOrc:
|
||||||
template markedAsCyclic(s: Cell): bool = (s.rc and maybeCycle) != 0
|
template markedAsCyclic(s: Cell; desc: PNimTypeV2): bool =
|
||||||
|
(desc.flags and acyclicFlag) == 0 and (s.rc and maybeCycle) != 0
|
||||||
else:
|
else:
|
||||||
template markedAsCyclic(s: Cell): bool = true
|
template markedAsCyclic(s: Cell; desc: PNimTypeV2): bool =
|
||||||
|
(desc.flags and acyclicFlag) == 0
|
||||||
|
|
||||||
proc rememberCycle(isDestroyAction: bool; s: Cell; desc: PNimTypeV2) {.noinline.} =
|
proc rememberCycle(isDestroyAction: bool; s: Cell; desc: PNimTypeV2) {.noinline.} =
|
||||||
if isDestroyAction:
|
if isDestroyAction:
|
||||||
|
|
@ -448,7 +461,7 @@ proc rememberCycle(isDestroyAction: bool; s: Cell; desc: PNimTypeV2) {.noinline.
|
||||||
else:
|
else:
|
||||||
# do not call 'rememberCycle' again unless this cell
|
# do not call 'rememberCycle' again unless this cell
|
||||||
# got an 'incRef' event:
|
# got an 'incRef' event:
|
||||||
if s.rootIdx == 0 and markedAsCyclic(s):
|
if s.rootIdx == 0 and markedAsCyclic(s, desc):
|
||||||
s.setColor colBlack
|
s.setColor colBlack
|
||||||
registerCycle(s, desc)
|
registerCycle(s, desc)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue