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:
Andreas Rumpf
2021-05-12 22:00:37 +02:00
committed by GitHub
parent 60b4fa71a8
commit 3bc625aff1
11 changed files with 50 additions and 27 deletions

View File

@@ -16,7 +16,7 @@ const
Mhalf = M div 2
type
Node[Key, Val] = ref object
Node[Key, Val] {.acyclic.} = ref object
entries: int
keys: array[M, Key]
case isInternal: bool

View File

@@ -1301,6 +1301,10 @@ proc genHook(m: BModule; t: PType; info: TLineInfo; op: TTypeAttachedOp): Rope =
genProc(m, theProc)
result = theProc.loc.r
when false:
if not canFormAcycle(t) and op == attachedTrace:
echo "ayclic but has this =trace ", t, " ", theProc.ast
else:
when false:
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 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,
traceImpl, disposeImpl])
traceImpl, disposeImpl, rope(flags)])
if t.kind == tyObject and t.len > 0 and t[0] != nil and optEnableDeepCopy in m.config.globalOptions:
discard genTypeInfoV1(m, t, info)

View File

@@ -467,7 +467,7 @@ proc genCase(c: var Con; n: PNode) =
# treat the last branch as 'else' if this is an exhaustive case statement.
c.gen(it.lastSon)
if endings.len != 0:
c.patch(endings[^1])
c.patch(endings[^1])
else:
forkT(it.lastSon):
c.gen(it.lastSon)

View File

@@ -513,8 +513,9 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
forallElements(c, t, body, x, y)
body.add genBuiltin(c, mDestroy, "destroy", x)
of attachedTrace:
# follow all elements:
forallElements(c, t, body, x, y)
if canFormAcycle(t.elemType):
# follow all elements:
forallElements(c, t, body, x, y)
of attachedDispose:
forallElements(c, t, body, x, y)
body.add genBuiltin(c, mDestroy, "destroy", x)
@@ -550,10 +551,11 @@ proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
doAssert t.destructor != nil
body.add destructorCall(c, t.destructor, x)
of attachedTrace:
let op = getAttachedOp(c.g, t, c.kind)
if op == nil:
return # protect from recursion
body.add newHookCall(c, op, x, y)
if t.kind != tyString and canFormAcycle(t.elemType):
let op = getAttachedOp(c.g, t, c.kind)
if op == nil:
return # protect from recursion
body.add newHookCall(c, op, x, y)
of attachedDispose:
let op = getAttachedOp(c.g, t, c.kind)
if op == nil:

View File

@@ -29,8 +29,8 @@ type
POptionEntry* = ref TOptionEntry
PProcCon* = ref TProcCon
TProcCon* = object # procedure context; also used for top-level
# statements
TProcCon* {.acyclic.} = object # procedure context; also used for top-level
# statements
owner*: PSym # the symbol this context belongs to
resultSym*: PSym # the result symbol (if we are in a proc)
selfSym*: PSym # the 'self' symbol (if available)

View File

@@ -359,13 +359,13 @@ proc canFormAcycleAux(marker: var IntSet, typ: PType, startId: int): bool =
if tfAcyclic in t.flags: return
case t.kind
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:
result = canFormAcycleAux(marker, t[i], startId)
if result: return
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
# as the type that is passed to 'new' is statically known!
# er but we use it also for the write barrier ...

View File

@@ -524,7 +524,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
# Used to keep track of where the execution is resumed.
var savedPC = -1
var savedFrame: PStackFrame
when defined(gcArc):
when defined(gcArc) or defined(gcOrc):
template updateRegsAlias = discard
template regs: untyped = tos.slots
else:

View File

@@ -270,7 +270,7 @@ type
procToCodePos*: Table[int, int]
PStackFrame* = ref TStackFrame
TStackFrame* = object
TStackFrame* {.acyclic.} = object
prc*: PSym # current prc; proc that is evaluated
slots*: seq[TFullReg] # parameters passed to the proc + locals;
# parameters come first

View File

@@ -38,7 +38,7 @@ const
IntMask = 1 shl IntShift - 1
type
Trunk = ref object
Trunk {.acyclic.} = ref object
next: Trunk # all nodes are connected with this pointer
key: int # start address at bit 0
bits: array[0..IntsPerTrunk - 1, BitScalar] # a bit vector

View File

@@ -1805,6 +1805,7 @@ when not defined(js) and defined(nimV2):
traceImpl: pointer
disposeImpl: pointer
typeInfoV1: pointer # for backwards compat, usually nil
flags: int
PNimTypeV2 = ptr TNimTypeV2
when notJSnotNims and defined(nimSeqsV2):

View File

@@ -109,9 +109,21 @@ proc free(s: Cell; desc: PNimTypeV2) {.inline.} =
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.} =
let p = cast[ptr pointer](q)
if p[] != nil:
orcAssert strstr(desc.name, "TType") == nil, "following a TType but it's acyclic!"
var j = cast[ptr GcEnv](env)
j.traceStack.add(head p[], desc)
@@ -121,12 +133,6 @@ proc nimTraceRefDyn(q: pointer; env: pointer) {.compilerRtl, inline.} =
var j = cast[ptr GcEnv](env)
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
roots {.threadvar.}: CellSeq
@@ -402,6 +408,8 @@ proc registerCycle(s: Cell; desc: PNimTypeV2) =
when logOrc:
writeCell("[added root]", s, desc)
orcAssert strstr(desc.name, "TType") == nil, "added a TType as a root!"
proc GC_runOrc* =
## Forces a cycle collection pass.
collectCycles()
@@ -436,10 +444,15 @@ proc GC_disableMarkAndSweep*() =
## For `--gc:orc` an alias for `GC_disableOrc`.
GC_disableOrc()
const
acyclicFlag = 1 # see also cggtypes.nim, proc genTypeInfoV2Impl
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:
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.} =
if isDestroyAction:
@@ -448,7 +461,7 @@ proc rememberCycle(isDestroyAction: bool; s: Cell; desc: PNimTypeV2) {.noinline.
else:
# do not call 'rememberCycle' again unless this cell
# got an 'incRef' event:
if s.rootIdx == 0 and markedAsCyclic(s):
if s.rootIdx == 0 and markedAsCyclic(s, desc):
s.setColor colBlack
registerCycle(s, desc)