diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/Global.scala | 19 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/Phase.scala | 34 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/PhaseAssembly.scala | 34 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/plugins/Plugins.scala | 8 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/util/TableDef.scala | 2 | ||||
-rw-r--r-- | test/files/run/t3895b.scala | 7 |
6 files changed, 75 insertions, 29 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 45fb691904..1f10d304c1 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -144,10 +144,13 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable if (opt.fatalWarnings) globalError(msg) else reporter.warning(NoPosition, msg) + private def elapsedMessage(msg: String, start: Long) = + msg + " in " + (currentTime - start) + "ms" + def informComplete(msg: String): Unit = reporter.withoutTruncating(inform(msg)) def informProgress(msg: String) = if (opt.verbose) inform("[" + msg + "]") def inform[T](msg: String, value: T): T = returning(value)(x => inform(msg + x)) - def informTime(msg: String, start: Long) = informProgress(msg + " in " + (currentTime - start) + "ms") + def informTime(msg: String, start: Long) = informProgress(elapsedMessage(msg, start)) def logError(msg: String, t: Throwable): Unit = () def log(msg: => AnyRef): Unit = if (opt.logPhase) inform("[log " + phase + "] " + msg) @@ -231,6 +234,10 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable def encoding = optSetting[String](settings.encoding) def sourceReader = optSetting[String](settings.sourceReader) + // XXX: short term, but I can't bear to add another option. + // scalac -Dscala.timings will make this true. + def timings = system.props contains "scala.timings" + def debug = settings.debug.value def deprecation = settings.deprecation.value def experimental = settings.Xexperimental.value @@ -605,6 +612,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable /* The set of phase objects that is the basis for the compiler phase chain */ protected lazy val phasesSet = new mutable.HashSet[SubComponent] protected lazy val phasesDescMap = new mutable.HashMap[SubComponent, String] withDefaultValue "" + private lazy val phaseTimings = new Phase.TimingModel // tracking phase stats protected def addToPhasesSet(sub: SubComponent, descr: String) { phasesSet += sub phasesDescMap(sub) = descr @@ -868,6 +876,10 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable } else globalPhase.run + // progress update + informTime(globalPhase.description, startTime) + phaseTimings(globalPhase) = currentTime - startTime + // write icode to *.icode files if (opt.writeICode && (runIsAt(icodePhase) || opt.printPhase && runIsPast(icodePhase))) writeICode() @@ -885,8 +897,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable if (opt.browsePhase) treeBrowser browse (phase.name, units) - // progress update - informTime(globalPhase.description, startTime) + // move the pointer globalPhase = globalPhase.next // run tree/icode checkers @@ -903,6 +914,8 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable profiler.stopProfiling() profiler.captureSnapshot() } + if (opt.timings) + inform(phaseTimings.formatted) // If no phase was specified for -Xshow-class/object, show it now. if (settings.Yshow.isDefault) diff --git a/src/compiler/scala/tools/nsc/Phase.scala b/src/compiler/scala/tools/nsc/Phase.scala index 9726834b88..f4cdfdadee 100644 --- a/src/compiler/scala/tools/nsc/Phase.scala +++ b/src/compiler/scala/tools/nsc/Phase.scala @@ -6,6 +6,7 @@ package scala.tools.nsc import symtab.Flags +import util.TableDef abstract class Phase(val prev: Phase) { @@ -48,4 +49,37 @@ abstract class Phase(val prev: Phase) { } } +object Phase { + val MaxPhases = 64 + + /** A class for tracking something about each phase. + */ + class Model[T: Manifest] { + case class Cell(ph: Phase, value: T) { + def name = ph.name + def id = ph.id + } + val values = new Array[Cell](MaxPhases + 1) + def results = values filterNot (_ == null) + def apply(ph: Phase): T = values(ph.id).value + def update(ph: Phase, value: T): Unit = values(ph.id) = Cell(ph, value) + } + /** A class for recording the elapsed time of each phase in the + * interests of generating a classy and informative table. + */ + class TimingModel extends Model[Long] { + var total: Long = 0 + def table() = { + total = results map (_.value) sum; + new Format.Table(results sortBy (-_.value)) + } + object Format extends TableDef[Cell] { + >> ("phase" -> (_.name)) >+ " " + << ("id" -> (_.id)) >+ " " + >> ("ms" -> (_.value)) >+ " " + << ("share" -> (_.value.toDouble * 100 / total formatted "%.2f")) + } + def formatted = "" + table() + } +} diff --git a/src/compiler/scala/tools/nsc/PhaseAssembly.scala b/src/compiler/scala/tools/nsc/PhaseAssembly.scala index c121098d56..9a306d939c 100644 --- a/src/compiler/scala/tools/nsc/PhaseAssembly.scala +++ b/src/compiler/scala/tools/nsc/PhaseAssembly.scala @@ -6,8 +6,8 @@ package scala.tools.nsc -import scala.collection.mutable.{HashSet, HashMap} -import java.io.{BufferedWriter, FileWriter} +import java.io.{ BufferedWriter, FileWriter } +import scala.collection.mutable /** * PhaseAssembly @@ -15,7 +15,8 @@ import java.io.{BufferedWriter, FileWriter} * the rest of the compiler. See SIP 00002 * */ -trait PhaseAssembly { self: Global => +trait PhaseAssembly { + self: Global => /** * Aux datastructure for solving the constraint system @@ -35,8 +36,8 @@ trait PhaseAssembly { self: Global => class Node(name: String) { val phasename = name var phaseobj: Option[List[SubComponent]] = None - val after = new HashSet[Edge]() - var before = new HashSet[Edge]() + val after = new mutable.HashSet[Edge]() + var before = new mutable.HashSet[Edge]() var visited = false var level = 0 @@ -46,8 +47,8 @@ trait PhaseAssembly { self: Global => } } - val nodes = new HashMap[String,Node]() - val edges = new HashSet[Edge]() + val nodes = new mutable.HashMap[String,Node]() + val edges = new mutable.HashSet[Edge]() /* Given a phase object, get the node for this phase object. If the * node object does not exist, then create it. @@ -184,22 +185,19 @@ trait PhaseAssembly { self: Global => * dependency on something that is dropped. */ def removeDanglingNodes() { - var dnodes = nodes.valuesIterator filter (_.phaseobj.isEmpty) - for (node <- dnodes) { + for (node <- nodes.valuesIterator filter (_.phaseobj.isEmpty)) { val msg = "dropping dependency on node with no phase object: "+node.phasename informProgress(msg) nodes -= node.phasename + for (edge <- node.before) { edges -= edge edge.frm.after -= edge - edge.frm.phaseobj match { - case Some(lsc) => if (! lsc.head.internal) warning(msg) - case _ => - } + if (edge.frm.phaseobj exists (lsc => !lsc.head.internal)) + warning(msg) } } } - } /* Method called from computePhaseDescriptors in class Global @@ -241,7 +239,7 @@ trait PhaseAssembly { self: Global => /** Given the phases set, will build a dependency graph from the phases set * Using the aux. method of the DependencyGraph to create nodes and egdes. */ - private def phasesSetToDepGraph(phsSet: HashSet[SubComponent]): DependencyGraph = { + private def phasesSetToDepGraph(phsSet: mutable.HashSet[SubComponent]): DependencyGraph = { val graph = new DependencyGraph() for (phs <- phsSet) { @@ -283,9 +281,9 @@ trait PhaseAssembly { self: Global => * Plug-in supplied phases are marked as green nodes and hard links are marked as blue edges. */ private def graphToDotFile(graph: DependencyGraph, filename: String) { - var sbuf = new StringBuilder - var extnodes = new HashSet[graph.Node]() - var fatnodes = new HashSet[graph.Node]() + val sbuf = new StringBuilder + val extnodes = new mutable.HashSet[graph.Node]() + val fatnodes = new mutable.HashSet[graph.Node]() sbuf.append("digraph G {\n") for (edge <- graph.edges) { sbuf.append("\"" + edge.frm.allPhaseNames + "(" + edge.frm.level + ")" + "\"->\"" + edge.to.allPhaseNames + "(" + edge.to.level + ")" + "\"") diff --git a/src/compiler/scala/tools/nsc/plugins/Plugins.scala b/src/compiler/scala/tools/nsc/plugins/Plugins.scala index 24962ee085..e2f4806c01 100644 --- a/src/compiler/scala/tools/nsc/plugins/Plugins.scala +++ b/src/compiler/scala/tools/nsc/plugins/Plugins.scala @@ -105,8 +105,12 @@ trait Plugins { * Extract all phases supplied by plugins and add them to the phasesSet. * @see phasesSet */ - protected def computePluginPhases(): Unit = - phasesSet ++= (plugins flatMap (_.components)) + protected def computePluginPhases(): Unit = { + // For reasons not yet apparent to me, plugins started appearing + // as null when I added phaseTimings to global. + if (plugins != null) + phasesSet ++= (plugins flatMap (_.components)) + } /** Summary of the options for all loaded plugins */ def pluginOptionsHelp: String = diff --git a/src/compiler/scala/tools/nsc/util/TableDef.scala b/src/compiler/scala/tools/nsc/util/TableDef.scala index b18eaaa400..10c63eeee2 100644 --- a/src/compiler/scala/tools/nsc/util/TableDef.scala +++ b/src/compiler/scala/tools/nsc/util/TableDef.scala @@ -4,7 +4,7 @@ package util import TableDef._ /** A class for representing tabular data in a way that preserves - * its inner beauty. See JavaStackFrame for an example usage. + * its inner beauty. See Exceptional for an example usage. * One creates an instance of TableDef by defining the columns of * the table, then uses that to create an instance of Table by * passing in a sequence of rows. diff --git a/test/files/run/t3895b.scala b/test/files/run/t3895b.scala index fd74aab125..a74f7b2ead 100644 --- a/test/files/run/t3895b.scala +++ b/test/files/run/t3895b.scala @@ -1,5 +1,4 @@ -class DryRun -{ +class DryRun { import scala.tools.nsc.{Global, Settings, CompilerCommand} import scala.tools.nsc.reporters.ConsoleReporter @@ -7,12 +6,10 @@ class DryRun settings.classpath.value = System.getProperty("java.class.path") val command = new CompilerCommand(List(), settings) val reporter = new ConsoleReporter(settings, scala.Console.in, new java.io.PrintWriter(new java.io.PrintStream(scala.Console.out))) - object compiler extends Global(command.settings, reporter) - { + object compiler extends Global(command.settings, reporter) { object test1 lazy val test2 = 1 object test3 - } def test { compiler.test1 |