Skip to content

Optimizations: Make code inlining friendlier #3265

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import typer.FrontEnd
import collection.mutable.ListBuffer
import util.Property
import reporting.diagnostic.messages._
import reporting.trace

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

/** Make a function value pat => body.
* If pat is a var pattern id: T then this gives (id: T) => body
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Flags._, Trees._, Types._, Contexts._
import Names._, StdNames._, NameOps._, Decorators._, Symbols._
import util.HashSet
import typer.ConstFold
import reporting.trace

trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
import TreeInfo._
Expand Down Expand Up @@ -578,7 +579,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
* if no such path exists.
* Pre: `sym` must have a position.
*/
def defPath(sym: Symbol, root: Tree)(implicit ctx: Context): List[Tree] = ctx.debugTraceIndented(s"defpath($sym with position ${sym.pos}, ${root.show})") {
def defPath(sym: Symbol, root: Tree)(implicit ctx: Context): List[Tree] = trace.onDebug(s"defpath($sym with position ${sym.pos}, ${root.show})") {
require(sym.pos.exists)
object accum extends TreeAccumulator[List[Tree]] {
def apply(x: List[Tree], tree: Tree)(implicit ctx: Context): List[Tree] = {
Expand Down
7 changes: 5 additions & 2 deletions compiler/src/dotty/tools/dotc/config/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,11 @@ object Config {
*/
final val simplifyApplications = true

/** Initial size of superId table */
final val InitialSuperIdsSize = 4096
/** If set, prints a trace of all symbol completions */
final val showCompletions = false

/** If set, enables tracing */
final val tracingEnabled = false

/** Initial capacity of uniques HashMap.
* Note: This MUST BE a power of two to work with util.HashSet
Expand Down
1 change: 0 additions & 1 deletion compiler/src/dotty/tools/dotc/config/Printers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ object Printers {
val incremental: Printer = noPrinter
val config: Printer = noPrinter
val transforms: Printer = noPrinter
val completions: Printer = noPrinter
val cyclicErrors: Printer = noPrinter
val pickling: Printer = noPrinter
val inlining: Printer = noPrinter
Expand Down
51 changes: 29 additions & 22 deletions compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import util.SimpleIdentityMap
import util.Stats
import java.util.WeakHashMap
import config.Config
import config.Printers.{completions, incremental, noPrinter}
import config.Printers.{incremental, noPrinter}
import reporting.trace

trait SymDenotations { this: Context =>
import SymDenotations._
Expand Down Expand Up @@ -214,28 +215,31 @@ object SymDenotations {
case _ => Some(myInfo)
}

private def completeFrom(completer: LazyType)(implicit ctx: Context): Unit = {
if (completions ne noPrinter) {
completions.println(i"${" " * indent}completing ${if (isType) "type" else "val"} $name")
private def completeFrom(completer: LazyType)(implicit ctx: Context): Unit =
if (Config.showCompletions) {
println(i"${" " * indent}completing ${if (isType) "type" else "val"} $name")
indent += 1
}
if (myFlags is Touched) throw CyclicReference(this)
myFlags |= Touched

// completions.println(s"completing ${this.debugString}")
try completer.complete(this)(ctx.withPhase(validFor.firstPhaseId))
catch {
case ex: CyclicReference =>
completions.println(s"error while completing ${this.debugString}")
throw ex
}
finally
if (completions ne noPrinter) {

if (myFlags is Touched) throw CyclicReference(this)
myFlags |= Touched

// completions.println(s"completing ${this.debugString}")
try completer.complete(this)(ctx.withPhase(validFor.firstPhaseId))
catch {
case ex: CyclicReference =>
println(s"error while completing ${this.debugString}")
throw ex
}
finally {
indent -= 1
completions.println(i"${" " * indent}completed $name in $owner")
println(i"${" " * indent}completed $name in $owner")
}
// completions.println(s"completed ${this.debugString}")
}
}
else {
if (myFlags is Touched) throw CyclicReference(this)
myFlags |= Touched
completer.complete(this)(ctx.withPhase(validFor.firstPhaseId))
}

protected[dotc] def info_=(tp: Type) = {
/* // DEBUG
Expand Down Expand Up @@ -797,7 +801,10 @@ object SymDenotations {
*/
/** The class implementing this module, NoSymbol if not applicable. */
final def moduleClass(implicit ctx: Context): Symbol = {
def notFound = { completions.println(s"missing module class for $name: $myInfo"); NoSymbol }
def notFound = {
if (Config.showCompletions) println(s"missing module class for $name: $myInfo")
NoSymbol
}
if (this is ModuleVal)
myInfo match {
case info: TypeRef => info.symbol
Expand Down Expand Up @@ -1666,7 +1673,7 @@ object SymDenotations {
}
}

/*>|>*/ ctx.debugTraceIndented(s"$tp.baseType($this)") /*<|<*/ {
/*>|>*/ trace.onDebug(s"$tp.baseType($this)") /*<|<*/ {
Stats.record("baseTypeOf")
tp.stripTypeVar match { // @!!! dealias?
case tp: CachedType =>
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import classfile.ClassfileParser
import util.Stats
import scala.util.control.NonFatal
import ast.Trees._
import reporting.trace

object SymbolLoaders {
/** A marker trait for a completer that replaces the original
Expand Down Expand Up @@ -265,7 +266,7 @@ abstract class SymbolLoader extends LazyType {
try {
val start = currentTime
if (ctx.settings.debugTrace.value)
ctx.doTraceIndented(s">>>> loading ${root.debugString}", _ => s"<<<< loaded ${root.debugString}") {
trace(s">>>> loading ${root.debugString}", _ => s"<<<< loaded ${root.debugString}") {
doComplete(root)
}
else
Expand Down
13 changes: 7 additions & 6 deletions compiler/src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import config.Printers.{typr, constr, subtyping, noPrinter}
import TypeErasure.{erasedLub, erasedGlb}
import TypeApplications._
import scala.util.control.NonFatal
import reporting.trace

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

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

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

/** The greatest lower bound of two types */
def glb(tp1: Type, tp2: Type): Type = /*>|>*/ ctx.traceIndented(s"glb(${tp1.show}, ${tp2.show})", subtyping, show = true) /*<|<*/ {
def glb(tp1: Type, tp2: Type): Type = /*>|>*/ trace(s"glb(${tp1.show}, ${tp2.show})", subtyping, show = true) /*<|<*/ {
if (tp1 eq tp2) tp1
else if (!tp1.exists) tp2
else if (!tp2.exists) tp1
Expand Down Expand Up @@ -1224,7 +1225,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
* @param canConstrain If true, new constraints might be added to simplify the lub.
* @note We do not admit singleton types in or-types as lubs.
*/
def lub(tp1: Type, tp2: Type, canConstrain: Boolean = false): Type = /*>|>*/ ctx.traceIndented(s"lub(${tp1.show}, ${tp2.show}, canConstrain=$canConstrain)", subtyping, show = true) /*<|<*/ {
def lub(tp1: Type, tp2: Type, canConstrain: Boolean = false): Type = /*>|>*/ trace(s"lub(${tp1.show}, ${tp2.show}, canConstrain=$canConstrain)", subtyping, show = true) /*<|<*/ {
if (tp1 eq tp2) tp1
else if (!tp1.exists) tp1
else if (!tp2.exists) tp2
Expand Down Expand Up @@ -1383,7 +1384,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
*
* In these cases, a MergeError is thrown.
*/
final def andType(tp1: Type, tp2: Type, erased: Boolean = ctx.erasedTypes) = ctx.traceIndented(s"glb(${tp1.show}, ${tp2.show})", subtyping, show = true) {
final def andType(tp1: Type, tp2: Type, erased: Boolean = ctx.erasedTypes) = trace(s"glb(${tp1.show}, ${tp2.show})", subtyping, show = true) {
val t1 = distributeAnd(tp1, tp2)
if (t1.exists) t1
else {
Expand Down
5 changes: 3 additions & 2 deletions compiler/src/dotty/tools/dotc/core/TypeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import config.Config
import util.Property
import collection.mutable
import ast.tpd._
import reporting.trace

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

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

/*>|>*/ ctx.conditionalTraceIndented(TypeOps.track, s"asSeen ${tp.show} from (${pre.show}, ${cls.show})", show = true) /*<|<*/ { // !!! DEBUG
/*>|>*/ trace.conditionally(TypeOps.track, s"asSeen ${tp.show} from (${pre.show}, ${cls.show})", show = true) /*<|<*/ { // !!! DEBUG
// All cases except for ThisType are the same as in Map. Inlined for performance
// TODO: generalize the inlining trick?
tp match {
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -830,7 +830,7 @@ object Types {
}

/** The basetype of this type with given class symbol, NoType if `base` is not a class. */
final def baseType(base: Symbol)(implicit ctx: Context): Type = /*ctx.traceIndented(s"$this baseType $base")*/ /*>|>*/ track("base type") /*<|<*/ {
final def baseType(base: Symbol)(implicit ctx: Context): Type = /*trace(s"$this baseType $base")*/ /*>|>*/ track("base type") /*<|<*/ {
base.denot match {
case classd: ClassDenotation => classd.baseTypeOf(this)
case _ => NoType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import classfile.ClassfileParser
import scala.collection.{ mutable, immutable }
import scala.collection.mutable.ListBuffer
import scala.annotation.switch
import reporting.trace

object Scala2Unpickler {

Expand Down Expand Up @@ -571,7 +572,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
} else {
assert(denot.is(ParamAccessor) || denot.isSuperAccessor, denot)
def disambiguate(alt: Symbol) = { // !!! DEBUG
ctx.debugTraceIndented(s"disambiguating ${denot.info} =:= ${denot.owner.thisType.memberInfo(alt)} ${denot.owner}") {
trace.onDebug(s"disambiguating ${denot.info} =:= ${denot.owner.thisType.memberInfo(alt)} ${denot.owner}") {
denot.info matches denot.owner.thisType.memberInfo(alt)
}
}
Expand Down
53 changes: 1 addition & 52 deletions compiler/src/dotty/tools/dotc/reporting/Reporter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import core.Contexts._
import util.{SourcePosition, NoSourcePosition}
import core.Decorators.PhaseListDecorator
import collection.mutable
import config.Printers
import java.lang.System.currentTimeMillis
import core.Mode
import dotty.tools.dotc.core.Symbols.Symbol
Expand Down Expand Up @@ -118,63 +117,13 @@ trait Reporting { this: Context =>
def informProgress(msg: => String) =
inform("[" + msg + "]")

def trace[T](msg: => String)(value: T) = {
def logWith[T](msg: => String)(value: T) = {
log(msg + " " + value)
value
}

def debugwarn(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
if (this.settings.debug.value) warning(msg, pos)

@inline
def debugTraceIndented[TD](question: => String, printer: Printers.Printer = Printers.default, show: Boolean = false)(op: => TD): TD =
conditionalTraceIndented(this.settings.debugTrace.value, question, printer, show)(op)

@inline
def conditionalTraceIndented[TC](cond: Boolean, question: => String, printer: Printers.Printer = Printers.default, show: Boolean = false)(op: => TC): TC =
if (cond) traceIndented[TC](question, printer, show)(op)
else op

@inline
def traceIndented[T](question: => String, printer: Printers.Printer = Printers.default, show: Boolean = false)(op: => T): T =
if (printer eq config.Printers.noPrinter) op
else doTraceIndented[T](question, printer, show)(op)

private def doTraceIndented[T](question: => String, printer: Printers.Printer = Printers.default, show: Boolean = false)(op: => T): T = {
def resStr(res: Any): String = res match {
case res: printing.Showable if show => res.show
case _ => String.valueOf(res)
}
// Avoid evaluating question multiple time, since each evaluation
// may cause some extra logging output.
lazy val q: String = question
doTraceIndented[T](s"==> $q?", (res: Any) => s"<== $q = ${resStr(res)}")(op)
}

def doTraceIndented[T](leading: => String, trailing: Any => String)(op: => T): T =
if (ctx.mode.is(Mode.Printing)) op
else {
var finalized = false
var logctx = this
while (logctx.reporter.isInstanceOf[StoreReporter]) logctx = logctx.outer
def finalize(result: Any, note: String) =
if (!finalized) {
base.indent -= 1
logctx.log(s"${base.indentTab * base.indent}${trailing(result)}$note")
finalized = true
}
try {
logctx.log(s"${base.indentTab * base.indent}$leading")
base.indent += 1
val res = op
finalize(res, "")
res
} catch {
case ex: Throwable =>
finalize("<missing>", s" (with exception $ex)")
throw ex
}
}
}

/**
Expand Down
Loading