Skip to content

Commit f618606

Browse files
committed
Add closure count instrumentation
Add a miniphase, enabled by -Yinstrument-closures that counts closure allocation by invoking Stats.doRecord. Todo: Find a generally shippable way to use this. Right now it depends on the compiler-internal utility class Stats.
1 parent e724058 commit f618606

File tree

5 files changed

+22
-5
lines changed

5 files changed

+22
-5
lines changed

compiler/src/dotty/tools/dotc/Compiler.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ class Compiler {
9797
List(new Constructors, // Collect initialization code in primary constructors
9898
// Note: constructors changes decls in transformTemplate, no InfoTransformers should be added after it
9999
new FunctionalInterfaces, // Rewrites closures to implement @specialized types of Functions.
100+
new InstrumentClosures, // Count closure allocations under -Yinstrument-closures
100101
new GetClass) :: // Rewrites getClass calls on primitive types.
101102
List(new LinkScala2Impls, // Redirect calls to trait methods defined by Scala 2.x, so that they now go to their implementations
102103
new LambdaLift, // Lifts out nested functions to class scope, storing free variables in environments

compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ class ScalaSettings extends Settings.SettingGroup {
149149

150150
val YnoDecodeStacktraces: Setting[Boolean] = BooleanSetting("-Yno-decode-stacktraces", "Show raw StackOverflow stacktraces, instead of decoding them into triggering operations.")
151151

152+
val YinstrumentClosures: Setting[Boolean] = BooleanSetting("-Yinstrument-closures", "Add instrumentation code that counts closure creations.")
153+
152154
/** Dottydoc specific settings */
153155
val siteRoot: Setting[String] = StringSetting(
154156
"-siteroot",

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,9 @@ class Definitions {
719719
lazy val ValueOfType: TypeRef = ctx.requiredClassRef("scala.ValueOf")
720720
def ValueOfClass(implicit ctx: Context): ClassSymbol = ValueOfType.symbol.asClass
721721

722+
lazy val StatsModule = ctx.requiredModule("dotty.tools.dotc.util.Stats")
723+
def Stats_doRecord(implicit ctx: Context): TermSymbol = StatsModule.requiredMethod("doRecord")
724+
722725
lazy val XMLTopScopeModuleRef: TermRef = ctx.requiredModuleRef("scala.xml.TopScope")
723726

724727
lazy val TupleTypeRef: TypeRef = ctx.requiredClassRef("scala.Tuple")

compiler/src/dotty/tools/dotc/core/Phases.scala

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,16 +79,25 @@ object Phases {
7979
* whereas a combined TreeTransformer gets period equal to union of periods of it's TreeTransforms
8080
*/
8181
final def squashPhases(phasess: List[List[Phase]],
82-
phasesToSkip: List[String], stopBeforePhases: List[String], stopAfterPhases: List[String], YCheckAfter: List[String]): List[Phase] = {
82+
phasesToSkip: List[String],
83+
stopBeforePhases: List[String],
84+
stopAfterPhases: List[String],
85+
YCheckAfter: List[String])(implicit ctx: Context): List[Phase] = {
8386
val squashedPhases = ListBuffer[Phase]()
8487
var prevPhases: Set[String] = Set.empty
8588
val YCheckAll = YCheckAfter.contains("all")
8689

8790
var stop = false
91+
92+
def isEnabled(p: Phase): Boolean =
93+
!stop &&
94+
!stopBeforePhases.contains(p.phaseName) &&
95+
!phasesToSkip.contains(p.phaseName) &&
96+
p.isEnabled
97+
8898
val filteredPhases = phasess.map(_.filter { p =>
89-
val pstop = stop
90-
stop = stop | stopBeforePhases.contains(p.phaseName) | stopAfterPhases.contains(p.phaseName)
91-
!(pstop || stopBeforePhases.contains(p.phaseName) || phasesToSkip.contains(p.phaseName))
99+
try isEnabled(p)
100+
finally stop |= stopBeforePhases.contains(p.phaseName) | stopAfterPhases.contains(p.phaseName)
92101
})
93102

94103
var i = 0
@@ -323,6 +332,8 @@ object Phases {
323332
/** Can this transform change the base types of a type? */
324333
def changesBaseTypes: Boolean = changesParents
325334

335+
def isEnabled(implicit ctx: Context): Boolean = true
336+
326337
def exists: Boolean = true
327338

328339
def initContext(ctx: FreshContext): Unit = ()

compiler/src/dotty/tools/dotc/util/Stats.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import collection.mutable
2626
def record(fn: => String, n: => Int = 1): Unit =
2727
if (enabled) doRecord(fn, n)
2828

29-
private def doRecord(fn: String, n: Int) =
29+
def doRecord(fn: String, n: Int) =
3030
if (monitored) {
3131
val name = if (fn.startsWith("member-")) "member" else fn
3232
hits(name) += n

0 commit comments

Comments
 (0)