From 940b3ceca8562e677f2527e705b24c1a4af8f860 Mon Sep 17 00:00:00 2001 From: Araq Date: Mon, 31 Aug 2015 15:07:39 +0200 Subject: [PATCH] write tracking: leaner code; minor bug fixes (still unusable) --- compiler/writetracking.nim | 146 ++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 85 deletions(-) diff --git a/compiler/writetracking.nim b/compiler/writetracking.nim index cf9ad91ccf..2589959e8c 100644 --- a/compiler/writetracking.nim +++ b/compiler/writetracking.nim @@ -42,7 +42,7 @@ proc returnsNewExpr*(n: PNode): NewLocation = of nkCurly, nkBracket, nkPar, nkObjConstr, nkClosure, nkIfExpr, nkIfStmt, nkWhenStmt, nkCaseStmt, nkTryStmt: result = newLit - for i in 0 .. treat as 'let tmp = p(); tmp.foo = x' - result = newSym(skTemp, getIdent(":tmp"), owner, n.sons[0].info) - #result.typ = n.sons[0].typ.sons[0] - #result.ast = n.sons[0] - # XXX - of nkPar: - localError(n.info, "writeSetAnalysis: too implement") - else: - discard - proc deps(w: var W; dest, src: PNode) = # let x = (localA, localB) # compute 'returnsNew' property: @@ -141,20 +111,32 @@ proc deps(w: var W; n: PNode) = else: depsArgs(w, n) -proc allRoots(n: PNode; result: var seq[PSym]) = +type + RootInfo = enum + rootIsResultOrParam, + rootIsHeapAccess + +proc allRoots(n: PNode; result: var seq[PSym]; info: var set[RootInfo]) = case n.kind of nkSym: - if n.sym notin result: result.add n.sym - of nkDotExpr, nkBracketExpr, nkHiddenDeref, nkDerefExpr, nkCheckedFieldExpr, + if n.sym.kind in {skParam, skVar, skTemp, skLet, skResult, skForVar}: + if result.isNil: result = @[] + if n.sym notin result: + if n.sym.kind in {skResult, skParam}: incl(info, rootIsResultOrParam) + result.add n.sym + of nkHiddenDeref, nkDerefExpr: + incl(info, rootIsHeapAccess) + allRoots(n.sons[0], result, info) + of nkDotExpr, nkBracketExpr, nkCheckedFieldExpr, nkHiddenAddr, nkObjUpConv, nkObjDownConv: - allRoots(n.sons[0], result) + allRoots(n.sons[0], result, info) of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv, nkConv, nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr, nkOfBranch, nkElifBranch, nkElse, nkExceptBranch, nkFinally, nkCast: - allRoots(n.lastSon, result) + allRoots(n.lastSon, result, info) of nkCallKinds: if getMagic(n) == mSlice: - allRoots(n.sons[1], result) + allRoots(n.sons[1], result, info) else: # we do significantly better here by using the available escape # information: @@ -172,12 +154,16 @@ proc allRoots(n: PNode; result: var seq[PSym]) = let paramType = typ.n.sons[i] if paramType.typ.isCompileTimeOnly: continue if sfEscapes in paramType.sym.flags or paramType.typ.kind == tyVar: - allRoots(it, result) + allRoots(it, result, info) else: - allRoots(it, result) + allRoots(it, result, info) else: for i in 0.. check which parameter it may alias and mark these parameters - # as dirty: - let aliases = possibleAliases(w, r) - for a in aliases: - if a.kind == skParam and a.owner == w.owner: - incl(a.flags, sfWrittenTo) - else: - internalError(dest.info, "dunno what to do " & $r.kind) + if rootIsHeapAccess in info or src == w.markAsWrittenTo: + # we have an assignment like: + # local.foo = bar + # --> check which parameter it may alias and mark these parameters + # as dirty: + possibleAliases(w, r) + for a in r: + if a.kind == skParam and a.owner == w.owner: + incl(a.flags, sfWrittenTo) proc markEscaping(w: W) = # let p1 = p # let p2 = q # p2.x = call(..., p1, ...) for dest, src in items(w.assignments): - var heapAccess = src == w.markAsEscaping - let r = root(w.owner, dest, heapAccess) - if r != nil and (heapAccess or r.kind == skResult): - if r.kind in {skParam, skVar, skTemp, skLet, skResult, skForVar}: - let aliases = possibleAliases(w, r) - var destIsParam = false - for a in aliases: - if a.kind in {skResult, skParam} and a.owner == w.owner: - destIsParam = true - break - if destIsParam: - var victims: seq[PSym] = @[] - allRoots(src, victims) - possibleAliases(w, victims) - for v in victims: - if v.kind == skParam and v.owner == w.owner: - incl(v.flags, sfEscapes) - else: - internalError(dest.info, "dunno what to do " & $r.kind) + var r: seq[PSym] = nil + var info: set[RootInfo] + allRoots(dest, r, info) + + if (r.len > 0) and (info != {} or src == w.markAsEscaping): + possibleAliases(w, r) + var destIsParam = false + for a in r: + if a.kind in {skResult, skParam} and a.owner == w.owner: + destIsParam = true + break + if destIsParam: + var victims: seq[PSym] = @[] + allRoots(src, victims) + possibleAliases(w, victims) + for v in victims: + if v.kind == skParam and v.owner == w.owner: + incl(v.flags, sfEscapes) proc trackWrites*(owner: PSym; body: PNode) = var w: W