package scala package reflect.internal package util import scala.collection.{ mutable, immutable } import scala.language.postfixOps trait TraceSymbolActivity { val global: SymbolTable import global._ private[this] var enabled = traceSymbolActivity if (enabled && global.isCompilerUniverse) scala.sys addShutdownHook showAllSymbols() val allSymbols = mutable.Map[Int, Symbol]() val allChildren = mutable.Map[Int, List[Int]]() withDefaultValue Nil val prevOwners = mutable.Map[Int, List[(Int, Phase)]]() withDefaultValue Nil val allTrees = mutable.Set[Tree]() def recordSymbolsInTree(tree: Tree) { if (enabled) allTrees += tree } def recordNewSymbol(sym: Symbol) { if (enabled && sym.id > 1) { allSymbols(sym.id) = sym allChildren(sym.owner.id) ::= sym.id } } def recordNewSymbolOwner(sym: Symbol, newOwner: Symbol) { if (enabled) { val sid = sym.id val oid = sym.owner.id val nid = newOwner.id prevOwners(sid) ::= (oid -> phase) allChildren(oid) = allChildren(oid) filterNot (_ == sid) allChildren(nid) ::= sid } } private lazy val erasurePhase = findPhaseWithName("erasure") private def signature(id: Int) = enteringPhase(erasurePhase)(allSymbols(id).defString) private def dashes(s: Any): String = ("" + s) map (_ => '-') private def show(s1: Any, ss: Any*) { println("%-12s".format(s1) +: ss mkString " ") } private def showHeader(s1: Any, ss: Any*) { show(s1, ss: _*) show(dashes(s1), ss map dashes: _*) } private def showSym(sym: Symbol) { def prefix = (" " * (sym.ownerChain.length - 1)) + sym.id try println("%s#%s %s".format(prefix, sym.accurateKindString, sym.name.decode)) catch { case x: Throwable => println(prefix + " failed: " + x) } allChildren(sym.id).sorted foreach showIdAndRemove } private def showIdAndRemove(id: Int) { allSymbols remove id foreach showSym } private def symbolStr(id: Int): String = { if (id == 1) "NoSymbol" else { val sym = allSymbols(id) sym.accurateKindString + " " + sym.name.decode } } private def ownerStr(id: Int): String = { val sym = allSymbols(id) sym.name.decode + "#" + sym.id } private def freq[T, U](xs: scala.collection.Traversable[T])(fn: T => U): List[(U, Int)] = { val ys = xs groupBy fn mapValues (_.size) ys.toList sortBy (-_._2) } private def showMapFreq[T](xs: scala.collection.Map[T, Traversable[_]])(showFn: T => String) { xs.mapValues(_.size).toList.sortBy(-_._2) take 100 foreach { case (k, size) => show(size, showFn(k)) } println("\n") } private def showFreq[T, U](xs: Traversable[T])(groupFn: T => U, showFn: U => String) = { showMapFreq(xs.toList groupBy groupFn)(showFn) } def showAllSymbols() { if (!enabled) return enabled = false allSymbols(1) = NoSymbol println("" + allSymbols.size + " symbols created.") println("") showHeader("descendants", "symbol") showFreq(allSymbols.values flatMap (_.ownerChain drop 1))(_.id, symbolStr) showHeader("children", "symbol") showMapFreq(allChildren)(symbolStr) if (prevOwners.nonEmpty) { showHeader("prev owners", "symbol") showMapFreq(prevOwners) { k => val owners = (((allSymbols(k).owner.id, NoPhase)) :: prevOwners(k)) map { case (oid, NoPhase) => "-> owned by " + ownerStr(oid) case (oid, ph) => "-> owned by %s (until %s)".format(ownerStr(oid), ph) } signature(k) :: owners mkString "\n " } } val nameFreq = allSymbols.values.toList groupBy (_.name) showHeader("frequency", "%-15s".format("name"), "owners") showMapFreq(nameFreq) { name => "%-15s %s".format(name.decode, { val owners = freq(nameFreq(name))(_.owner) "%4s owners (%s)".format( owners.size, owners.take(3).map({ case (k, v) => v + "/" + k }).mkString(", ") + ", ..." ) }) } allSymbols.keys.toList.sorted foreach showIdAndRemove } }