Skip to content

Optimize core and frontend #9867

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 7 commits into from
Oct 9, 2020
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
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ object Trees {
def toList: List[Tree[T]] = this :: Nil

/** if this tree is the empty tree, the alternative, else this tree */
def orElse[U >: Untyped <: T](that: => Tree[U]): Tree[U] =
inline def orElse[U >: Untyped <: T](inline that: Tree[U]): Tree[U] =
if (this eq genericEmptyTree) that else this

/** The number of nodes in this tree */
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ class ScalaSettings extends Settings.SettingGroup {
val YnoDecodeStacktraces: Setting[Boolean] = BooleanSetting("-Yno-decode-stacktraces", "Show raw StackOverflow stacktraces, instead of decoding them into triggering operations.")

val Yinstrument: Setting[Boolean] = BooleanSetting("-Yinstrument", "Add instrumentation code that counts allocations and closure creations.")
val YinstrumentDefs: Setting[Boolean] = BooleanSetting("-Yinstrument-defs", "Add instrumentation code that counts method calls; needs -Yinstrument to be set, too.")

/** Dottydoc specific settings */
val siteRoot: Setting[String] = StringSetting(
Expand Down
6 changes: 5 additions & 1 deletion compiler/src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ object Contexts {
final def retractMode(mode: Mode): c.type = c.setMode(c.mode &~ mode)
}

private def exploreCtx(using Context): Context =
private def exploreCtx(using Context): FreshContext =
util.Stats.record("explore")
val base = ctx.base
import base._
Expand All @@ -701,6 +701,10 @@ object Contexts {
val ectx = exploreCtx
try op(using ectx) finally wrapUpExplore(ectx)

inline def exploreInFreshCtx[T](inline op: FreshContext ?=> T)(using Context): T =
val ectx = exploreCtx
try op(using ectx) finally wrapUpExplore(ectx)

private def changeOwnerCtx(owner: Symbol)(using Context): Context =
val base = ctx.base
import base._
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/Denotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ object Denotations {
def mapInfo(f: Type => Type)(using Context): Denotation

/** If this denotation does not exist, fallback to alternative */
final def orElse(that: => Denotation): Denotation = if (this.exists) this else that
inline def orElse(inline that: Denotation): Denotation = if (this.exists) this else that

/** The set of alternative single-denotations making up this denotation */
final def alternatives: List[SingleDenotation] = altsWith(alwaysTrue)
Expand Down Expand Up @@ -596,7 +596,7 @@ object Denotations {
def mapInfo(f: Type => Type)(using Context): SingleDenotation =
derivedSingleDenotation(symbol, f(info))

def orElse(that: => SingleDenotation): SingleDenotation = if (this.exists) this else that
inline def orElse(inline that: SingleDenotation): SingleDenotation = if (this.exists) this else that

def altsWith(p: Symbol => Boolean): List[SingleDenotation] =
if (exists && p(symbol)) this :: Nil else Nil
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Symbols.scala
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ object Symbols {
}

/** This symbol, if it exists, otherwise the result of evaluating `that` */
def orElse(that: => Symbol)(using Context): Symbol =
inline def orElse(inline that: Symbol)(using Context): Symbol =
if (this.exists) this else that

/** If this symbol satisfies predicate `p` this symbol, otherwise `NoSymbol` */
Expand Down
16 changes: 15 additions & 1 deletion compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,8 @@ object Types {
*/
final def memberNames(keepOnly: NameFilter, pre: Type = this)(using Context): Set[Name] = this match {
case tp: ClassInfo =>
tp.cls.classDenot.memberNames(keepOnly) filter (keepOnly(pre, _))
val names = tp.cls.classDenot.memberNames(keepOnly)
if keepOnly.isStable then names else names.filter(keepOnly(pre, _))
case tp: RefinedType =>
val ns = tp.parent.memberNames(keepOnly, pre)
if (keepOnly(pre, tp.refinedName)) ns + tp.refinedName else ns
Expand Down Expand Up @@ -5665,6 +5666,11 @@ object Types {
*/
abstract class NameFilter {
def apply(pre: Type, name: Name)(using Context): Boolean

/** Filter does not need to be rechecked with full prefix, if it
* has been already checked for the class denotation of the prefix
*/
def isStable: Boolean
}

/** A filter for names of abstract types of a given type */
Expand All @@ -5674,6 +5680,7 @@ object Types {
val mbr = pre.nonPrivateMember(name)
mbr.symbol.is(Deferred) && mbr.info.isInstanceOf[RealTypeBounds]
}
def isStable = false
}

/** A filter for names of abstract types of a given type */
Expand All @@ -5683,12 +5690,14 @@ object Types {
val mbr = pre.member(name)
mbr.symbol.isType && !mbr.symbol.isClass
}
def isStable = false
}

/** A filter for names of deferred term definitions of a given type */
object abstractTermNameFilter extends NameFilter {
def apply(pre: Type, name: Name)(using Context): Boolean =
name.isTermName && pre.nonPrivateMember(name).hasAltWith(_.symbol.is(Deferred))
def isStable = false
}

/** A filter for names of type aliases of a given type */
Expand All @@ -5698,19 +5707,23 @@ object Types {
val mbr = pre.nonPrivateMember(name)
mbr.symbol.isAliasType
}
def isStable = false
}

object typeNameFilter extends NameFilter {
def apply(pre: Type, name: Name)(using Context): Boolean = name.isTypeName
def isStable = true
}

object fieldFilter extends NameFilter {
def apply(pre: Type, name: Name)(using Context): Boolean =
name.isTermName && (pre member name).hasAltWith(!_.symbol.is(Method))
def isStable = true
}

object takeAllFilter extends NameFilter {
def apply(pre: Type, name: Name)(using Context): Boolean = true
def isStable = true
}

object implicitFilter extends NameFilter {
Expand All @@ -5719,6 +5732,7 @@ object Types {
* no post-filtering is needed.
*/
def apply(pre: Type, name: Name)(using Context): Boolean = true
def isStable = true
}

// ----- Debug ---------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/interactive/Completion.scala
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ object Completion {
private object completionsFilter extends NameFilter {
def apply(pre: Type, name: Name)(using Context): Boolean =
!name.isConstructorName && name.toTermName.info.kind == SimpleNameKind
def isStable = true
}
}

Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/parsing/Scanners.scala
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ object Scanners {
lastOffset = prev.lastOffset
lineOffset = prev.lineOffset
}
token match {
(token: @switch) match {
case CASE =>
lookAhead()
if (token == CLASS) fuse(CASECLASS)
Expand Down Expand Up @@ -601,8 +601,8 @@ object Scanners {
if colonSyntax then observeColonEOL()
case RBRACE | RPAREN | RBRACKET =>
closeIndented()
case EOF if !source.maybeIncomplete =>
closeIndented()
case EOF =>
if !source.maybeIncomplete then closeIndented()
case _ =>
}
}
Expand Down
15 changes: 15 additions & 0 deletions compiler/src/dotty/tools/dotc/transform/Instrumentation.scala
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,21 @@ class Instrumentation extends MiniPhase { thisPhase =>
private def ok(using Context) =
!ctx.owner.ownersIterator.exists(_.name.toString.startsWith("Stats"))

override def transformDefDef(tree: DefDef)(using Context): Tree =
val sym = tree.symbol
if ctx.settings.YinstrumentDefs.value
&& ok
&& sym.exists
&& !sym.isOneOf(Synthetic | Artifact)
then
def icall = record(i"method/${sym.fullName}", tree)
def rhs1 = tree.rhs match
case rhs @ Block(stats, expr) => cpy.Block(rhs)(icall :: stats, expr)
case _: Match | _: If | _: Try | _: Labeled => cpy.Block(tree.rhs)(icall :: Nil, tree.rhs)
case rhs => rhs
cpy.DefDef(tree)(rhs = rhs1)
else tree

override def transformApply(tree: Apply)(using Context): Tree = tree.fun match {
case Select(nu: New, _) =>
cpy.Block(tree)(record(i"alloc/${nu.tpe}", tree) :: Nil, tree)
Expand Down
11 changes: 9 additions & 2 deletions compiler/src/dotty/tools/dotc/transform/SymUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,19 @@ object SymUtils {

extension (self: Symbol) {

/** All traits implemented by a class or trait except for those inherited through the superclass. */
/** All traits implemented by a class or trait except for those inherited
* through the superclass. Traits are given in the order they appear in the
* parents clause (which is the reverse of their order in baseClasses)
*/
def directlyInheritedTraits(using Context): List[ClassSymbol] = {
val superCls = self.asClass.superClass
val baseClasses = self.asClass.baseClasses
if (baseClasses.isEmpty) Nil
else baseClasses.tail.takeWhile(_ ne superCls).reverse
else
def recur(bcs: List[ClassSymbol], acc: List[ClassSymbol]): List[ClassSymbol] = bcs match
case bc :: bcs1 => if bc eq superCls then acc else recur(bcs1, bc :: acc)
case nil => acc
recur(baseClasses.tail, Nil)
}

/** All traits implemented by a class, except for those inherited through the superclass.
Expand Down
6 changes: 4 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -245,10 +245,12 @@ object Implicits:
if refs.isEmpty && (!considerExtension || companionRefs.isEmpty) then
Nil
else
val nestedCtx = ctx.fresh.addMode(Mode.TypevarsMissContext)
val candidates = new mutable.ListBuffer[Candidate]
def tryCandidate(extensionOnly: Boolean)(ref: ImplicitRef) =
var ckind = explore(candidateKind(ref.underlyingRef))(using nestedCtx)
var ckind = exploreInFreshCtx { (using ctx: FreshContext) =>
ctx.setMode(ctx.mode | Mode.TypevarsMissContext)
candidateKind(ref.underlyingRef)
}
if extensionOnly then ckind &= Candidate.Extension
if ckind != Candidate.None then
candidates += Candidate(ref, ckind, level)
Expand Down
8 changes: 4 additions & 4 deletions compiler/src/dotty/tools/dotc/typer/RefChecks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ object RefChecks {

private val defaultMethodFilter = new NameFilter {
def apply(pre: Type, name: Name)(using Context): Boolean = name.is(DefaultGetterName)
def isStable = true
}

/** Only one overloaded alternative is allowed to define default arguments */
Expand Down Expand Up @@ -490,10 +491,9 @@ object RefChecks {
*/
def missingTermSymbols: List[Symbol] =
val buf = new mutable.ListBuffer[Symbol]
for bc <- clazz.baseClasses
sym <- bc.info.decls.toList
if sym.is(DeferredTerm) && !isImplemented(sym) && !ignoreDeferred(sym)
do buf += sym
for bc <- clazz.baseClasses; sym <- bc.info.decls.toList do
if sym.is(DeferredTerm) && !isImplemented(sym) && !ignoreDeferred(sym) then
buf += sym
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then is required after #9859 -- the benchmarks fail due to this.

buf.toList

// 2. Check that only abstract classes have deferred members
Expand Down