Skip to content

Commit f3e0a15

Browse files
committed
Reorganize tracing
- Enable only if global config option is true (this avoids clutter in traced methods). - Move out of context into separate object `reporting.trace`. - Avoid default arguments, since these are loaded before inlining. The net effect of these methods is no parts of tracing calls remain in generated code if config.tracingEnabled is false.
1 parent afce192 commit f3e0a15

23 files changed

+157
-95
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import typer.FrontEnd
1212
import collection.mutable.ListBuffer
1313
import util.Property
1414
import reporting.diagnostic.messages._
15+
import reporting.trace
1516

1617
object desugar {
1718
import untpd._
@@ -886,7 +887,7 @@ object desugar {
886887
* @param enums The enumerators in the for expression
887888
* @param body The body of the for expression
888889
*/
889-
def makeFor(mapName: TermName, flatMapName: TermName, enums: List[Tree], body: Tree): Tree = ctx.traceIndented(i"make for ${ForYield(enums, body)}", show = true) {
890+
def makeFor(mapName: TermName, flatMapName: TermName, enums: List[Tree], body: Tree): Tree = trace(i"make for ${ForYield(enums, body)}", show = true) {
890891

891892
/** Make a function value pat => body.
892893
* If pat is a var pattern id: T then this gives (id: T) => body

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Flags._, Trees._, Types._, Contexts._
77
import Names._, StdNames._, NameOps._, Decorators._, Symbols._
88
import util.HashSet
99
import typer.ConstFold
10+
import reporting.trace
1011

1112
trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
1213
import TreeInfo._
@@ -577,7 +578,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
577578
* if no such path exists.
578579
* Pre: `sym` must have a position.
579580
*/
580-
def defPath(sym: Symbol, root: Tree)(implicit ctx: Context): List[Tree] = ctx.debugTraceIndented(s"defpath($sym with position ${sym.pos}, ${root.show})") {
581+
def defPath(sym: Symbol, root: Tree)(implicit ctx: Context): List[Tree] = trace.onDebug(s"defpath($sym with position ${sym.pos}, ${root.show})") {
581582
require(sym.pos.exists)
582583
object accum extends TreeAccumulator[List[Tree]] {
583584
def apply(x: List[Tree], tree: Tree)(implicit ctx: Context): List[Tree] = {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ object Config {
147147
/** If set, prints a trace of all symbol completions */
148148
final val showCompletions = false
149149

150-
/** Initial size of superId table */
151-
final val InitialSuperIdsSize = 4096
150+
/** If set, enables tracing */
151+
final val tracingEnabled = false
152152

153153
/** Initial capacity of uniques HashMap.
154154
* Note: This MUST BE a power of two to work with util.HashSet

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import util.Stats
1818
import java.util.WeakHashMap
1919
import config.Config
2020
import config.Printers.{incremental, noPrinter}
21+
import reporting.trace
2122

2223
trait SymDenotations { this: Context =>
2324
import SymDenotations._
@@ -1672,7 +1673,7 @@ object SymDenotations {
16721673
}
16731674
}
16741675

1675-
/*>|>*/ ctx.debugTraceIndented(s"$tp.baseType($this)") /*<|<*/ {
1676+
/*>|>*/ trace.onDebug(s"$tp.baseType($this)") /*<|<*/ {
16761677
Stats.record("baseTypeOf")
16771678
tp.stripTypeVar match { // @!!! dealias?
16781679
case tp: CachedType =>

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import classfile.ClassfileParser
1818
import util.Stats
1919
import scala.util.control.NonFatal
2020
import ast.Trees._
21+
import reporting.trace
2122

2223
object SymbolLoaders {
2324
/** A marker trait for a completer that replaces the original
@@ -265,7 +266,7 @@ abstract class SymbolLoader extends LazyType {
265266
try {
266267
val start = currentTime
267268
if (ctx.settings.debugTrace.value)
268-
ctx.doTraceIndented(s">>>> loading ${root.debugString}", _ => s"<<<< loaded ${root.debugString}") {
269+
trace(s">>>> loading ${root.debugString}", _ => s"<<<< loaded ${root.debugString}") {
269270
doComplete(root)
270271
}
271272
else

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import config.Printers.{typr, constr, subtyping, noPrinter}
1212
import TypeErasure.{erasedLub, erasedGlb}
1313
import TypeApplications._
1414
import scala.util.control.NonFatal
15+
import reporting.trace
1516

1617
/** Provides methods to compare types.
1718
*/
@@ -105,7 +106,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
105106
assert(isSatisfiable, constraint.show)
106107
}
107108

108-
protected def isSubType(tp1: Type, tp2: Type): Boolean = ctx.traceIndented(s"isSubType ${traceInfo(tp1, tp2)}", subtyping) {
109+
protected def isSubType(tp1: Type, tp2: Type): Boolean = trace(s"isSubType ${traceInfo(tp1, tp2)}", subtyping) {
109110
if (tp2 eq NoType) false
110111
else if (tp1 eq tp2) true
111112
else {
@@ -948,7 +949,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
948949
* rebase both itself and the member info of `tp` on a freshly created skolem type.
949950
*/
950951
protected def hasMatchingMember(name: Name, tp1: Type, tp2: RefinedType): Boolean =
951-
/*>|>*/ ctx.traceIndented(i"hasMatchingMember($tp1 . $name :? ${tp2.refinedInfo}), mbr: ${tp1.member(name).info}", subtyping) /*<|<*/ {
952+
/*>|>*/ trace(i"hasMatchingMember($tp1 . $name :? ${tp2.refinedInfo}), mbr: ${tp1.member(name).info}", subtyping) /*<|<*/ {
952953
val rinfo2 = tp2.refinedInfo
953954

954955
// If the member is an abstract type, compare the member itself
@@ -1159,7 +1160,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
11591160
/** Same as `isSameType` but also can be applied to overloaded TermRefs, where
11601161
* two overloaded refs are the same if they have pairwise equal alternatives
11611162
*/
1162-
def isSameRef(tp1: Type, tp2: Type): Boolean = ctx.traceIndented(s"isSameRef($tp1, $tp2") {
1163+
def isSameRef(tp1: Type, tp2: Type): Boolean = trace(s"isSameRef($tp1, $tp2") {
11631164
def isSubRef(tp1: Type, tp2: Type): Boolean = tp1 match {
11641165
case tp1: TermRef if tp1.isOverloaded =>
11651166
tp1.alternatives forall (isSubRef(_, tp2))
@@ -1175,7 +1176,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
11751176
}
11761177

11771178
/** The greatest lower bound of two types */
1178-
def glb(tp1: Type, tp2: Type): Type = /*>|>*/ ctx.traceIndented(s"glb(${tp1.show}, ${tp2.show})", subtyping, show = true) /*<|<*/ {
1179+
def glb(tp1: Type, tp2: Type): Type = /*>|>*/ trace(s"glb(${tp1.show}, ${tp2.show})", subtyping, show = true) /*<|<*/ {
11791180
if (tp1 eq tp2) tp1
11801181
else if (!tp1.exists) tp2
11811182
else if (!tp2.exists) tp1
@@ -1224,7 +1225,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
12241225
* @param canConstrain If true, new constraints might be added to simplify the lub.
12251226
* @note We do not admit singleton types in or-types as lubs.
12261227
*/
1227-
def lub(tp1: Type, tp2: Type, canConstrain: Boolean = false): Type = /*>|>*/ ctx.traceIndented(s"lub(${tp1.show}, ${tp2.show}, canConstrain=$canConstrain)", subtyping, show = true) /*<|<*/ {
1228+
def lub(tp1: Type, tp2: Type, canConstrain: Boolean = false): Type = /*>|>*/ trace(s"lub(${tp1.show}, ${tp2.show}, canConstrain=$canConstrain)", subtyping, show = true) /*<|<*/ {
12281229
if (tp1 eq tp2) tp1
12291230
else if (!tp1.exists) tp1
12301231
else if (!tp2.exists) tp2
@@ -1383,7 +1384,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
13831384
*
13841385
* In these cases, a MergeError is thrown.
13851386
*/
1386-
final def andType(tp1: Type, tp2: Type, erased: Boolean = ctx.erasedTypes) = ctx.traceIndented(s"glb(${tp1.show}, ${tp2.show})", subtyping, show = true) {
1387+
final def andType(tp1: Type, tp2: Type, erased: Boolean = ctx.erasedTypes) = trace(s"glb(${tp1.show}, ${tp2.show})", subtyping, show = true) {
13871388
val t1 = distributeAnd(tp1, tp2)
13881389
if (t1.exists) t1
13891390
else {

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import config.Config
1616
import util.{SimpleMap, Property}
1717
import collection.mutable
1818
import ast.tpd._
19+
import reporting.trace
1920

2021
trait TypeOps { this: Context => // TODO: Make standalone object.
2122

@@ -33,7 +34,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
3334
/** Map a `C.this` type to the right prefix. If the prefix is unstable, and
3435
* the current variance is <= 0, return a range.
3536
*/
36-
def toPrefix(pre: Type, cls: Symbol, thiscls: ClassSymbol): Type = /*>|>*/ ctx.conditionalTraceIndented(TypeOps.track, s"toPrefix($pre, $cls, $thiscls)") /*<|<*/ {
37+
def toPrefix(pre: Type, cls: Symbol, thiscls: ClassSymbol): Type = /*>|>*/ trace.conditionally(TypeOps.track, s"toPrefix($pre, $cls, $thiscls)", show = true) /*<|<*/ {
3738
if ((pre eq NoType) || (pre eq NoPrefix) || (cls is PackageClass))
3839
tp
3940
else pre match {
@@ -49,7 +50,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
4950
}
5051
}
5152

52-
/*>|>*/ ctx.conditionalTraceIndented(TypeOps.track, s"asSeen ${tp.show} from (${pre.show}, ${cls.show})", show = true) /*<|<*/ { // !!! DEBUG
53+
/*>|>*/ trace.conditionally(TypeOps.track, s"asSeen ${tp.show} from (${pre.show}, ${cls.show})", show = true) /*<|<*/ { // !!! DEBUG
5354
// All cases except for ThisType are the same as in Map. Inlined for performance
5455
// TODO: generalize the inlining trick?
5556
tp match {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,7 @@ object Types {
824824
}
825825

826826
/** The basetype of this type with given class symbol, NoType if `base` is not a class. */
827-
final def baseType(base: Symbol)(implicit ctx: Context): Type = /*ctx.traceIndented(s"$this baseType $base")*/ /*>|>*/ track("base type") /*<|<*/ {
827+
final def baseType(base: Symbol)(implicit ctx: Context): Type = /*trace(s"$this baseType $base")*/ /*>|>*/ track("base type") /*<|<*/ {
828828
base.denot match {
829829
case classd: ClassDenotation => classd.baseTypeOf(this)
830830
case _ => NoType

compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import classfile.ClassfileParser
2828
import scala.collection.{ mutable, immutable }
2929
import scala.collection.mutable.ListBuffer
3030
import scala.annotation.switch
31+
import reporting.trace
3132

3233
object Scala2Unpickler {
3334

@@ -571,7 +572,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
571572
} else {
572573
assert(denot.is(ParamAccessor) || denot.isSuperAccessor, denot)
573574
def disambiguate(alt: Symbol) = { // !!! DEBUG
574-
ctx.debugTraceIndented(s"disambiguating ${denot.info} =:= ${denot.owner.thisType.memberInfo(alt)} ${denot.owner}") {
575+
trace.onDebug(s"disambiguating ${denot.info} =:= ${denot.owner.thisType.memberInfo(alt)} ${denot.owner}") {
575576
denot.info matches denot.owner.thisType.memberInfo(alt)
576577
}
577578
}

compiler/src/dotty/tools/dotc/reporting/Reporter.scala

Lines changed: 1 addition & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import core.Contexts._
66
import util.{SourcePosition, NoSourcePosition}
77
import core.Decorators.PhaseListDecorator
88
import collection.mutable
9-
import config.Printers
109
import java.lang.System.currentTimeMillis
1110
import core.Mode
1211
import dotty.tools.dotc.core.Symbols.Symbol
@@ -118,63 +117,13 @@ trait Reporting { this: Context =>
118117
def informProgress(msg: => String) =
119118
inform("[" + msg + "]")
120119

121-
def trace[T](msg: => String)(value: T) = {
120+
def logWith[T](msg: => String)(value: T) = {
122121
log(msg + " " + value)
123122
value
124123
}
125124

126125
def debugwarn(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
127126
if (this.settings.debug.value) warning(msg, pos)
128-
129-
@inline
130-
def debugTraceIndented[TD](question: => String, printer: Printers.Printer = Printers.default, show: Boolean = false)(op: => TD): TD =
131-
conditionalTraceIndented(this.settings.debugTrace.value, question, printer, show)(op)
132-
133-
@inline
134-
def conditionalTraceIndented[TC](cond: Boolean, question: => String, printer: Printers.Printer = Printers.default, show: Boolean = false)(op: => TC): TC =
135-
if (cond) traceIndented[TC](question, printer, show)(op)
136-
else op
137-
138-
@inline
139-
def traceIndented[T](question: => String, printer: Printers.Printer = Printers.default, show: Boolean = false)(op: => T): T =
140-
if (printer eq config.Printers.noPrinter) op
141-
else doTraceIndented[T](question, printer, show)(op)
142-
143-
private def doTraceIndented[T](question: => String, printer: Printers.Printer = Printers.default, show: Boolean = false)(op: => T): T = {
144-
def resStr(res: Any): String = res match {
145-
case res: printing.Showable if show => res.show
146-
case _ => String.valueOf(res)
147-
}
148-
// Avoid evaluating question multiple time, since each evaluation
149-
// may cause some extra logging output.
150-
lazy val q: String = question
151-
doTraceIndented[T](s"==> $q?", (res: Any) => s"<== $q = ${resStr(res)}")(op)
152-
}
153-
154-
def doTraceIndented[T](leading: => String, trailing: Any => String)(op: => T): T =
155-
if (ctx.mode.is(Mode.Printing)) op
156-
else {
157-
var finalized = false
158-
var logctx = this
159-
while (logctx.reporter.isInstanceOf[StoreReporter]) logctx = logctx.outer
160-
def finalize(result: Any, note: String) =
161-
if (!finalized) {
162-
base.indent -= 1
163-
logctx.log(s"${base.indentTab * base.indent}${trailing(result)}$note")
164-
finalized = true
165-
}
166-
try {
167-
logctx.log(s"${base.indentTab * base.indent}$leading")
168-
base.indent += 1
169-
val res = op
170-
finalize(res, "")
171-
res
172-
} catch {
173-
case ex: Throwable =>
174-
finalize("<missing>", s" (with exception $ex)")
175-
throw ex
176-
}
177-
}
178127
}
179128

180129
/**
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package dotty.tools
2+
package dotc
3+
package reporting
4+
5+
import core.Contexts.Context
6+
import config.Config
7+
import config.Printers
8+
import core.Mode
9+
10+
object trace {
11+
12+
@inline
13+
def onDebug[TD](question: => String)(op: => TD)(implicit ctx: Context): TD =
14+
conditionally(ctx.settings.debugTrace.value, question, false)(op)
15+
16+
@inline
17+
def conditionally[TC](cond: Boolean, question: => String, show: Boolean)(op: => TC)(implicit ctx: Context): TC =
18+
if (Config.tracingEnabled && cond) apply[TC](question, Printers.default, show)(op)
19+
else op
20+
21+
@inline
22+
def apply[T](question: => String, printer: Printers.Printer, show: Boolean)(op: => T)(implicit ctx: Context): T =
23+
if (!Config.tracingEnabled || printer.eq(config.Printers.noPrinter)) op
24+
else doTrace[T](question, printer, show)(op)
25+
26+
@inline
27+
def apply[T](question: => String, printer: Printers.Printer)(op: => T)(implicit ctx: Context): T =
28+
apply[T](question, printer, false)(op)
29+
30+
@inline
31+
def apply[T](question: => String, show: Boolean)(op: => T)(implicit ctx: Context): T =
32+
apply[T](question, Printers.default, show)(op)
33+
34+
@inline
35+
def apply[T](question: => String)(op: => T)(implicit ctx: Context): T =
36+
apply[T](question, Printers.default, false)(op)
37+
38+
private def doTrace[T](question: => String, printer: Printers.Printer = Printers.default, show: Boolean = false)
39+
(op: => T)(implicit ctx: Context): T = {
40+
def resStr(res: Any): String = res match {
41+
case res: printing.Showable if show => res.show
42+
case _ => String.valueOf(res)
43+
}
44+
// Avoid evaluating question multiple time, since each evaluation
45+
// may cause some extra logging output.
46+
lazy val q: String = question
47+
apply[T](s"==> $q?", (res: Any) => s"<== $q = ${resStr(res)}")(op)
48+
}
49+
50+
def apply[T](leading: => String, trailing: Any => String)(op: => T)(implicit ctx: Context): T =
51+
if (ctx.mode.is(Mode.Printing)) op
52+
else {
53+
var finalized = false
54+
var logctx = ctx
55+
while (logctx.reporter.isInstanceOf[StoreReporter]) logctx = logctx.outer
56+
def finalize(result: Any, note: String) =
57+
if (!finalized) {
58+
ctx.base.indent -= 1
59+
logctx.log(s"${ctx.base.indentTab * ctx.base.indent}${trailing(result)}$note")
60+
finalized = true
61+
}
62+
try {
63+
logctx.log(s"${ctx.base.indentTab * ctx.base.indent}$leading")
64+
ctx.base.indent += 1
65+
val res = op
66+
finalize(res, "")
67+
res
68+
} catch {
69+
case ex: Throwable =>
70+
finalize("<missing>", s" (with exception $ex)")
71+
throw ex
72+
}
73+
}
74+
}

compiler/src/dotty/tools/dotc/transform/Erasure.scala

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import TypeUtils._
2929
import ExplicitOuter._
3030
import core.Mode
3131
import core.PhantomErasure
32+
import reporting.trace
3233

3334
class Erasure extends Phase with DenotTransformer { thisTransformer =>
3435

@@ -175,7 +176,7 @@ object Erasure {
175176
(if (isPureExpr(tree)) const else Block(tree :: Nil, const))
176177
.withPos(tree.pos)
177178

178-
final def box(tree: Tree, target: => String = "")(implicit ctx: Context): Tree = ctx.traceIndented(i"boxing ${tree.showSummary}: ${tree.tpe} into $target") {
179+
final def box(tree: Tree, target: => String = "")(implicit ctx: Context): Tree = trace(i"boxing ${tree.showSummary}: ${tree.tpe} into $target") {
179180
tree.tpe.widen match {
180181
case ErasedValueType(tycon, _) =>
181182
New(tycon, cast(tree, underlyingOfValueClass(tycon.symbol.asClass)) :: Nil) // todo: use adaptToType?
@@ -195,7 +196,7 @@ object Erasure {
195196
}
196197
}
197198

198-
def unbox(tree: Tree, pt: Type)(implicit ctx: Context): Tree = ctx.traceIndented(i"unboxing ${tree.showSummary}: ${tree.tpe} as a $pt") {
199+
def unbox(tree: Tree, pt: Type)(implicit ctx: Context): Tree = trace(i"unboxing ${tree.showSummary}: ${tree.tpe} as a $pt") {
199200
pt match {
200201
case ErasedValueType(tycon, underlying) =>
201202
def unboxedTree(t: Tree) =
@@ -239,7 +240,7 @@ object Erasure {
239240
* Casts from and to ErasedValueType are special, see the explanation
240241
* in ExtensionMethods#transform.
241242
*/
242-
def cast(tree: Tree, pt: Type)(implicit ctx: Context): Tree = ctx.traceIndented(i"cast ${tree.tpe.widen} --> $pt", show = true) {
243+
def cast(tree: Tree, pt: Type)(implicit ctx: Context): Tree = trace(i"cast ${tree.tpe.widen} --> $pt", show = true) {
243244
def wrap(tycon: TypeRef) =
244245
ref(u2evt(tycon.typeSymbol.asClass)).appliedTo(tree)
245246
def unwrap(tycon: TypeRef) =
@@ -662,7 +663,7 @@ object Erasure {
662663
}
663664

664665
override def adapt(tree: Tree, pt: Type)(implicit ctx: Context): Tree =
665-
ctx.traceIndented(i"adapting ${tree.showSummary}: ${tree.tpe} to $pt", show = true) {
666+
trace(i"adapting ${tree.showSummary}: ${tree.tpe} to $pt", show = true) {
666667
assert(ctx.phase == ctx.erasurePhase.next, ctx.phase)
667668
if (tree.isEmpty) tree
668669
else if (ctx.mode is Mode.Pattern) tree // TODO: replace with assertion once pattern matcher is active

0 commit comments

Comments
 (0)