summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala19
-rw-r--r--src/compiler/scala/tools/nsc/Phase.scala34
-rw-r--r--src/compiler/scala/tools/nsc/PhaseAssembly.scala34
-rw-r--r--src/compiler/scala/tools/nsc/plugins/Plugins.scala8
-rw-r--r--src/compiler/scala/tools/nsc/util/TableDef.scala2
-rw-r--r--test/files/run/t3895b.scala7
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