From 5a643d958e3b8e661dbf3884326a16e73364e335 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 18 Apr 2018 13:13:23 +0200 Subject: [PATCH] Optimize scala2Mode Profile showed that `scala2Mode` takes about 1% of compute type when run on dotc/typer/*.scala. We can reduce this by caching previously computed results. --- .../src/dotty/tools/dotc/core/TypeOps.scala | 28 +++++++------------ .../dotty/tools/dotc/typer/Implicits.scala | 2 +- .../dotty/tools/dotc/typer/ImportInfo.scala | 22 +++++++++++++++ 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 498660c9d82b..d59c540432c3 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -292,25 +292,17 @@ trait TypeOps { this: Context => // TODO: Make standalone object. * the prefix "dotty.language.". */ def featureEnabled(owner: ClassSymbol, feature: TermName): Boolean = { - def toPrefix(sym: Symbol): String = - if (!sym.exists || (sym eq defn.LanguageModuleClass)) "" - else toPrefix(sym.owner) + sym.name + "." - def featureName = toPrefix(owner) + feature - def hasImport(implicit ctx: Context): Boolean = { - if (ctx.importInfo eq null) false - else { - val isImportOwner = ctx.importInfo.site.widen.typeSymbol eq owner - if (isImportOwner && ctx.importInfo.originals.contains(feature)) true - else if (isImportOwner && ctx.importInfo.excluded.contains(feature)) false - else { - var c = ctx.outer - while (c.importInfo eq ctx.importInfo) c = c.outer - hasImport(c) - } - } + val hasImport = + ctx.importInfo != null && + ctx.importInfo.featureImported(owner, feature)(ctx.withPhase(ctx.typerPhase)) + def hasOption = { + def toPrefix(sym: Symbol): String = + if (!sym.exists || (sym eq defn.LanguageModuleClass)) "" + else toPrefix(sym.owner) + sym.name + "." + val featureName = toPrefix(owner) + feature + ctx.base.settings.language.value exists (s => s == featureName || s == "_") } - def hasOption = ctx.base.settings.language.value exists (s => s == featureName || s == "_") - hasImport(ctx.withPhase(ctx.typerPhase)) || hasOption + hasImport || hasOption } /** Is auto-tupling enabled? */ diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index b9bca83a70d9..0c0c43dcc9aa 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -79,7 +79,7 @@ object Implicits { def discardForView(tpw: Type, argType: Type): Boolean = tpw match { case mt: MethodType => mt.isImplicitMethod || - mt.paramInfos.length != 1 || + mt.paramInfos.lengthCompare(1) != 0 || !ctx.test(implicit ctx => argType relaxed_<:< mt.paramInfos.head) case poly: PolyType => // We do not need to call ProtoTypes#constrained on `poly` because diff --git a/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala b/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala index 596a6092bd5d..eecf905169eb 100644 --- a/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala +++ b/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala @@ -138,5 +138,27 @@ class ImportInfo(symf: Context => Symbol, val selectors: List[untpd.Tree], } private[this] var myUnimported: Symbol = _ + /** Does this import clause or a preceding import clause import `owner.feature`? */ + def featureImported(owner: Symbol, feature: TermName)(implicit ctx: Context): Boolean = { + def compute = { + val isImportOwner = site.widen.typeSymbol `eq` owner + if (isImportOwner && originals.contains(feature)) true + else if (isImportOwner && excluded.contains(feature)) false + else { + var c = ctx.outer + while (c.importInfo eq ctx.importInfo) c = c.outer + (c.importInfo != null) && c.importInfo.featureImported(owner, feature)(c) + } + } + if (lastOwner.ne(owner) || !lastResults.contains(feature)) { + lastOwner = owner + lastResults = lastResults.updated(feature, compute) + } + lastResults(feature) + } + + private[this] var lastOwner: Symbol = null + private[this] var lastResults: SimpleIdentityMap[TermName, java.lang.Boolean] = SimpleIdentityMap.Empty + def toText(printer: Printer) = printer.toText(this) }