Skip to content

Commit e8b9503

Browse files
committed
Also allow to count allocations in instrumentation
1 parent f618606 commit e8b9503

File tree

3 files changed

+62
-1
lines changed

3 files changed

+62
-1
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +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
100+
new Instrumentation, // Count closure allocations under -Yinstrument-closures
101101
new GetClass) :: // Rewrites getClass calls on primitive types.
102102
List(new LinkScala2Impls, // Redirect calls to trait methods defined by Scala 2.x, so that they now go to their implementations
103103
new LambdaLift, // Lifts out nested functions to class scope, storing free variables in environments

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ class ScalaSettings extends Settings.SettingGroup {
150150
val YnoDecodeStacktraces: Setting[Boolean] = BooleanSetting("-Yno-decode-stacktraces", "Show raw StackOverflow stacktraces, instead of decoding them into triggering operations.")
151151

152152
val YinstrumentClosures: Setting[Boolean] = BooleanSetting("-Yinstrument-closures", "Add instrumentation code that counts closure creations.")
153+
val YinstrumentAllocations: Setting[Boolean] = BooleanSetting("-Yinstrument-allocations", "Add instrumentation code that counts allocations.")
153154

154155
/** Dottydoc specific settings */
155156
val siteRoot: Setting[String] = StringSetting(
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package dotty.tools.dotc
2+
package transform
3+
4+
import core._
5+
import Contexts.Context
6+
import Symbols._
7+
import Flags._
8+
import SymDenotations._
9+
10+
import Decorators._
11+
import ast.Trees._
12+
import MegaPhase._
13+
import StdNames.nme
14+
import Names.TermName
15+
import Constants.Constant
16+
17+
18+
/** The phase is enabled if a -Yinstrument-... option is set.
19+
* If enabled, it counts the number of closures or allocations for each source position.
20+
* It does this by generating a call to dotty.tools.dotc.util.Stats.doRecord.
21+
*/
22+
class Instrumentation extends MiniPhase { thisPhase =>
23+
import ast.tpd._
24+
25+
override def phaseName: String = "instrumentation"
26+
27+
override def isEnabled(implicit ctx: Context) =
28+
ctx.settings.YinstrumentClosures.value ||
29+
ctx.settings.YinstrumentAllocations.value
30+
31+
private var consName: TermName = _
32+
private var consEqName: TermName = _
33+
34+
override def prepareForUnit(tree: Tree)(implicit ctx: Context): Context = {
35+
consName = "::".toTermName
36+
consEqName = "+=".toTermName
37+
ctx
38+
}
39+
40+
private def record(category: String, tree: Tree)(implicit ctx: Context): Tree = {
41+
val key = Literal(Constant(s"$category${tree.sourcePos.show}"))
42+
ref(defn.Stats_doRecord).appliedTo(key, Literal(Constant(1)))
43+
}
44+
45+
override def transformApply(tree: Apply)(implicit ctx: Context): Tree = tree.fun match {
46+
case Select(nu: New, _) =>
47+
cpy.Block(tree)(record(i"alloc/${nu.tpe}@", tree) :: Nil, tree)
48+
case Select(_, name) if name == consName || name == consEqName =>
49+
cpy.Block(tree)(record("alloc/::", tree) :: Nil, tree)
50+
case _ =>
51+
tree
52+
}
53+
54+
override def transformBlock(tree: Block)(implicit ctx: Context): Block = tree.expr match {
55+
case _: Closure =>
56+
cpy.Block(tree)(record("closure/", tree) :: tree.stats, tree.expr)
57+
case _ =>
58+
tree
59+
}
60+
}

0 commit comments

Comments
 (0)