summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2015-08-31 15:07:39 +0200
committerAraq <rumpf_a@web.de>2015-08-31 23:06:35 +0200
commit940b3ceca8562e677f2527e705b24c1a4af8f860 (patch)
treee17df618103640846859f81d05cef179c1abd705 /compiler
parente733debec706b8449b8bc000b1695b7df5e9839c (diff)
downloadNim-940b3ceca8562e677f2527e705b24c1a4af8f860.tar.gz
write tracking: leaner code; minor bug fixes (still unusable)
Diffstat (limited to 'compiler')
-rw-r--r--compiler/writetracking.nim146
1 files changed, 61 insertions, 85 deletions
diff --git a/compiler/writetracking.nim b/compiler/writetracking.nim
index cf9ad91cc..2589959e8 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 .. <n.len:
+    for i in ord(n.kind == nkObjConstr) .. <n.len:
       let x = returnsNewExpr(n.sons[i])
       case x
       of newNone: return newNone
@@ -54,36 +54,6 @@ proc returnsNewExpr*(n: PNode): NewLocation =
   else:
     result = newNone
 
-proc root(owner: PSym; n: PNode; heapAccess: var bool): PSym =
-  ## returns 'nil' if the 'root' could not be detected.
-  case n.kind
-  of nkSym:
-    result = n.sym
-  of nkHiddenDeref, nkDerefExpr:
-    result = root(owner, n.sons[0], heapAccess)
-    heapAccess = true
-  of nkHiddenAddr, nkObjUpConv, nkObjDownConv,
-      nkDotExpr, nkBracketExpr, nkCheckedFieldExpr:
-    result = root(owner, n.sons[0], heapAccess)
-  of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkStmtList, nkStmtListExpr,
-      nkBlockStmt, nkBlockExpr, nkCast:
-    result = root(owner, n.lastSon, heapAccess)
-  of nkCallKinds:
-    # builtin slice keeps lvalue-ness:
-    if getMagic(n) == mSlice:
-      result = root(owner, n.sons[1], heapAccess)
-      heapAccess = true
-    else:
-      # 'p().foo = x' --> 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..<n.safeLen:
-      allRoots(n.sons[i], result)
+      allRoots(n.sons[i], result, info)
+
+proc allRoots(n: PNode; result: var seq[PSym]) =
+  var dummy: set[RootInfo]
+  allRoots(n, result, dummy)
 
 proc hasSym(n: PNode; x: PSym): bool =
   when false:
@@ -187,9 +173,9 @@ proc hasSym(n: PNode; x: PSym): bool =
       for i in 0..safeLen(n)-1:
         if hasSym(n.sons[i], x): return true
   else:
-    var tmp: seq[PSym] = @[]
+    var tmp: seq[PSym]
     allRoots(n, tmp)
-    result = x in tmp
+    result = not tmp.isNil and x in tmp
 
 when debug:
   proc `$`*(x: PSym): string = x.name.s
@@ -204,15 +190,12 @@ proc possibleAliases(w: W; result: var seq[PSym]) =
     inc todo
     when debug:
       if w.owner.name.s == "m3": echo "select ", x, " ", todo, " ", result.len
-    var dummy = false
     for dest, src in items(w.assignments):
       if src.hasSym(x):
         # dest = f(..., s, ...)
-        let r = root(w.owner, dest, dummy)
-        if r != nil and r notin result:
-          result.add r
-          when debug:
-            if w.owner.name.s == "m3": echo "A ", result
+        allRoots(dest, result)
+        when debug:
+          if w.owner.name.s == "m3": echo "A ", result
       elif dest.kind == nkSym and dest.sym == x:
         # s = f(..., x, ....)
         allRoots(src, result)
@@ -222,54 +205,47 @@ proc possibleAliases(w: W; result: var seq[PSym]) =
         when debug:
           if w.owner.name.s == "m3": echo "C ", x, " ", todo, " ", result.len
 
-proc possibleAliases(w: W; s: PSym): seq[PSym] =
-  result = @[s]
-  possibleAliases(w, result)
-
 proc markDirty(w: W) =
   for dest, src in items(w.assignments):
-    var heapAccess = src == w.markAsWrittenTo
-    let r = root(w.owner, dest, heapAccess)
+    var r: seq[PSym] = nil
+    var info: set[RootInfo]
+    allRoots(dest, r, info)
     when debug:
       if w.owner.info ?? "temp18":
         echo "ASGN ", dest,  " = ", src, " |", heapAccess, " ", r.name.s
-    if heapAccess and r != nil:
-      if r.kind in {skParam, skVar, skTemp, skLet, skResult, skForVar}:
-        # we have an assignment like:
-        # local.foo = bar
-        # --> 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