diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 07389b5c2d9f..431bdec16563 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -1281,11 +1281,8 @@ class Global(var currentSettings: Settings, reporter0: Reporter) checkPhaseSettings(including = true, inclusions.toSeq: _*) checkPhaseSettings(including = false, exclusions map (_.value): _*) - // Enable or disable depending on the current setting -- useful for interactive behaviour - statistics.initFromSettings(settings) - // Report the overhead of statistics measurements per every run - if (statistics.areStatisticsLocallyEnabled) + if (settings.areStatisticsEnabled) statistics.reportStatisticsOverhead(reporter) phase = first //parserPhase @@ -1510,7 +1507,7 @@ class Global(var currentSettings: Settings, reporter0: Reporter) warnDeprecatedAndConflictingSettings() globalPhase = fromPhase - val timePhases = statistics.areStatisticsLocallyEnabled + val timePhases = settings.areStatisticsEnabled val startTotal = if (timePhases) statistics.startTimer(totalCompileTime) else null while (globalPhase.hasNext && !reporter.hasErrors) { diff --git a/src/compiler/scala/tools/nsc/MainBench.scala b/src/compiler/scala/tools/nsc/MainBench.scala index ca78db7e2dfe..84b3b6e603e7 100644 --- a/src/compiler/scala/tools/nsc/MainBench.scala +++ b/src/compiler/scala/tools/nsc/MainBench.scala @@ -29,9 +29,8 @@ object MainBench extends Driver with EvalLoop { var start = System.nanoTime() for (i <- 0 until NIter) { if (i == NIter-1) { - theCompiler.settings.Ystatistics.value = List("all") - theCompiler.statistics.enabled = true - theCompiler.statistics.hotEnabled = true + theCompiler.settings.Ystatistics.value = List("all") + theCompiler.settings.YhotStatisticsEnabled.value = true } process(args) val end = System.nanoTime() diff --git a/src/compiler/scala/tools/nsc/backend/jvm/ClassfileWriters.scala b/src/compiler/scala/tools/nsc/backend/jvm/ClassfileWriters.scala index 716a1d6de31f..15bce5921204 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/ClassfileWriters.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/ClassfileWriters.scala @@ -63,7 +63,7 @@ abstract class ClassfileWriters { def apply(global: Global): ClassfileWriter = { //Note dont import global._ - its too easy to leak non threadsafe structures - import global.{cleanup, log, settings, statistics} + import global.{ cleanup, log, settings } def jarManifestMainClass: Option[String] = settings.mainClass.valueSetByUser.orElse { cleanup.getEntryPoints match { case List(name) => Some(name) @@ -91,7 +91,7 @@ abstract class ClassfileWriters { new DebugClassWriter(basicClassWriter, asmp, dump) } - val enableStats = statistics.enabled && settings.YaddBackendThreads.value == 1 + val enableStats = settings.areStatisticsEnabled && settings.YaddBackendThreads.value == 1 if (enableStats) new WithStatsWriter(withAdditionalFormats) else withAdditionalFormats } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GeneratedClassHandler.scala b/src/compiler/scala/tools/nsc/backend/jvm/GeneratedClassHandler.scala index beec1ade9d06..5853b52a3142 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GeneratedClassHandler.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GeneratedClassHandler.scala @@ -59,7 +59,7 @@ private[jvm] object GeneratedClassHandler { new SyncWritingClassHandler(postProcessor) case maxThreads => - if (statistics.enabled) + if (settings.areStatisticsEnabled) runReporting.warning(NoPosition, "jvm statistics are not reliable with multi-threaded jvm class writing", WarningCategory.Other, site = "") val additionalThreads = maxThreads - 1 // The thread pool queue is limited in size. When it's full, the `CallerRunsPolicy` causes diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index c3b224d888c0..7e640d05afc1 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -23,7 +23,7 @@ import scala.language.existentials import scala.annotation.elidable import scala.tools.util.PathResolver.Defaults import scala.collection.mutable -import scala.reflect.internal.util.StringContextStripMarginOps +import scala.reflect.internal.util.{ StatisticsStatics, StringContextStripMarginOps } import scala.tools.nsc.util.DefaultJarFactory import scala.util.chaining._ @@ -496,9 +496,9 @@ trait ScalaSettings extends StandardScalaSettings with Warnings { _: MutableSett val Ystatistics = PhasesSetting("-Vstatistics", "Print compiler statistics for specific phases", "parser,typer,patmat,erasure,cleanup,jvm") .withPostSetHook(s => YstatisticsEnabled.value = s.value.nonEmpty) .withAbbreviation("-Ystatistics") - val YstatisticsEnabled = BooleanSetting("-Ystatistics-enabled", "Internal setting, indicating that statistics are enabled for some phase.").internalOnly() + val YstatisticsEnabled = BooleanSetting("-Ystatistics-enabled", "Internal setting, indicating that statistics are enabled for some phase.").internalOnly().withPostSetHook(s => if (s) StatisticsStatics.enableColdStatsAndDeoptimize()) val YhotStatisticsEnabled = BooleanSetting("-Vhot-statistics", s"Enable `${Ystatistics.name}` to also print hot statistics.") - .withAbbreviation("-Yhot-statistics") + .withAbbreviation("-Yhot-statistics").withPostSetHook(s => if (s && YstatisticsEnabled) StatisticsStatics.enableHotStatsAndDeoptimize()) val Yshowsyms = BooleanSetting("-Vsymbols", "Print the AST symbol hierarchy after each phase.") withAbbreviation "-Yshow-syms" val Ytyperdebug = BooleanSetting("-Vtyper", "Trace type assignments.") withAbbreviation "-Ytyper-debug" val Vimplicits = BooleanSetting("-Vimplicits", "Print dependent missing implicits.").withAbbreviation("-Xlog-implicits") diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 54b82ebe4fdf..a3bc5d0615e2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -6003,7 +6003,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper def typed(tree: Tree, mode: Mode, pt: Type): Tree = { lastTreeToTyper = tree - val statsEnabled = StatisticsStatics.areSomeHotStatsEnabled() && statistics.areHotStatsLocallyEnabled + val statsEnabled = StatisticsStatics.areSomeHotStatsEnabled && settings.areStatisticsEnabled && settings.YhotStatisticsEnabled val startByType = if (statsEnabled) statistics.pushTimer(byTypeStack, byTypeNanos(tree.getClass)) else null if (statsEnabled) statistics.incCounter(visitsByType, tree.getClass) val shouldPrintTyping = printTypings && !phase.erasedTypes && !noPrintTyping(tree) diff --git a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala index df656fd53c69..0e84fe6c90d7 100644 --- a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala +++ b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala @@ -16,6 +16,8 @@ package scala package reflect.internal package settings +import scala.reflect.internal.util.StatisticsStatics + /** A mutable Settings object. */ abstract class MutableSettings extends AbsSettings { @@ -69,4 +71,8 @@ object MutableSettings { import scala.language.implicitConversions /** Support the common use case, `if (settings.debug) println("Hello, martin.")` */ @inline implicit def reflectSettingToBoolean(s: MutableSettings#BooleanSetting): Boolean = s.value + + implicit class SettingsOps(private val settings: MutableSettings) extends AnyVal { + @inline final def areStatisticsEnabled = StatisticsStatics.areSomeColdStatsEnabled && settings.YstatisticsEnabled + } } diff --git a/src/reflect/scala/reflect/internal/util/Statistics.scala b/src/reflect/scala/reflect/internal/util/Statistics.scala index 28cb4f133446..ce12b1c7a159 100644 --- a/src/reflect/scala/reflect/internal/util/Statistics.scala +++ b/src/reflect/scala/reflect/internal/util/Statistics.scala @@ -22,57 +22,49 @@ import scala.annotation.nowarn import scala.runtime.LongRef abstract class Statistics(val symbolTable: SymbolTable, settings: MutableSettings) { - - initFromSettings(settings) - - def initFromSettings(currentSettings: MutableSettings): Unit = { - enabled = currentSettings.YstatisticsEnabled - hotEnabled = currentSettings.YhotStatisticsEnabled - } - type TimerSnapshot = (Long, Long) /** If enabled, increment counter by one */ @inline final def incCounter(c: Counter): Unit = { - if (areStatisticsLocallyEnabled && c != null) c.value += 1 + if (enabled && c != null) c.value += 1 } /** If enabled, increment counter by given delta */ @inline final def incCounter(c: Counter, delta: Int): Unit = { - if (areStatisticsLocallyEnabled && c != null) c.value += delta + if (enabled && c != null) c.value += delta } /** If enabled, increment counter in map `ctrs` at index `key` by one */ @inline final def incCounter[K](ctrs: QuantMap[K, Counter], key: K) = - if (areStatisticsLocallyEnabled && ctrs != null) ctrs(key).value += 1 + if (enabled && ctrs != null) ctrs(key).value += 1 /** If enabled, start subcounter. While active it will track all increments of * its base counter. */ @inline final def startCounter(sc: SubCounter): (Int, Int) = - if (areStatisticsLocallyEnabled && sc != null) sc.start() else null + if (enabled && sc != null) sc.start() else null /** If enabled, stop subcounter from tracking its base counter. */ @inline final def stopCounter(sc: SubCounter, start: (Int, Int)): Unit = { - if (areStatisticsLocallyEnabled && sc != null) sc.stop(start) + if (enabled && sc != null) sc.stop(start) } /** If enabled, start timer */ @inline final def startTimer(tm: Timer): TimerSnapshot = - if (areStatisticsLocallyEnabled && tm != null) tm.start() else null + if (enabled && tm != null) tm.start() else null /** If enabled, stop timer */ @inline final def stopTimer(tm: Timer, start: TimerSnapshot): Unit = { - if (areStatisticsLocallyEnabled && tm != null) tm.stop(start) + if (enabled && tm != null) tm.stop(start) } /** If enabled, push and start a new timer in timer stack */ @inline final def pushTimer(timers: TimerStack, timer: => StackableTimer): TimerSnapshot = - if (areStatisticsLocallyEnabled && timers != null) timers.push(timer) else null + if (enabled && timers != null) timers.push(timer) else null /** If enabled, stop and pop timer from timer stack */ @inline final def popTimer(timers: TimerStack, prev: TimerSnapshot): Unit = { - if (areStatisticsLocallyEnabled && timers != null) timers.pop(prev) + if (enabled && timers != null) timers.pop(prev) } /** Create a new counter that shows as `prefix` and is active in given phases */ @@ -294,29 +286,8 @@ quant) } private[this] val qs = new mutable.HashMap[String, Quantity] - private[scala] var areColdStatsLocallyEnabled: Boolean = false - private[scala] var areHotStatsLocallyEnabled: Boolean = false - - /** Represents whether normal statistics can or cannot be enabled. */ - @inline final def enabled: Boolean = areColdStatsLocallyEnabled - def enabled_=(cond: Boolean) = { - if (cond && !enabled) { - StatisticsStatics.enableColdStatsAndDeoptimize() - areColdStatsLocallyEnabled = true - } - } - - /** Represents whether hot statistics can or cannot be enabled. */ - @inline final def hotEnabled: Boolean = enabled && areHotStatsLocallyEnabled - def hotEnabled_=(cond: Boolean) = { - if (cond && enabled && !areHotStatsLocallyEnabled) { - StatisticsStatics.enableHotStatsAndDeoptimize() - areHotStatsLocallyEnabled = true - } - } - /** Tells whether statistics should be definitely reported to the user for this `Global` instance. */ - @inline final def areStatisticsLocallyEnabled: Boolean = areColdStatsLocallyEnabled + @inline final def enabled: Boolean = settings.areStatisticsEnabled import scala.reflect.internal.Reporter /** Reports the overhead of measuring statistics via the nanoseconds variation. */ diff --git a/src/reflect/scala/reflect/runtime/Settings.scala b/src/reflect/scala/reflect/runtime/Settings.scala index 5ab2be417955..21acdff3b990 100644 --- a/src/reflect/scala/reflect/runtime/Settings.scala +++ b/src/reflect/scala/reflect/runtime/Settings.scala @@ -15,6 +15,7 @@ package reflect package runtime import scala.reflect.internal.settings.MutableSettings +import scala.reflect.internal.util.StatisticsStatics /** The Settings class for runtime reflection. * This should be refined, so that settings are settable via command @@ -57,8 +58,8 @@ private[reflect] class Settings extends MutableSettings { val uniqid = new BooleanSetting(false) val verbose = new BooleanSetting(false) - val YhotStatisticsEnabled = new BooleanSetting(false) - val YstatisticsEnabled = new BooleanSetting(false) + val YhotStatisticsEnabled = new BooleanSetting(false) { override def postSetHook() = if (v && YstatisticsEnabled) StatisticsStatics.enableHotStatsAndDeoptimize() } + val YstatisticsEnabled = new BooleanSetting(false) { override def postSetHook() = if (v) StatisticsStatics.enableColdStatsAndDeoptimize() } val Yrecursion = new IntSetting(0) def isScala212 = true