8000 Merge pull request #5875 from retronym/faster/typer · scala/scala@f35ab66 · GitHub
[go: up one dir, main page]

Skip to content

Commit f35ab66

Browse files
authored
Merge pull request #5875 from retronym/faster/typer
Optimizations in Namer and Typer
2 parents 56daf3a + fe8b2ef commit f35ab66

File tree

6 files changed

+42
-33
lines changed

6 files changed

+42
-33
lines changed

src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
451451
)
452452

453453
private def hasUnspecializableAnnotation(sym: Symbol): Boolean =
454-
sym.ownerChain.exists(_ hasAnnotation UnspecializedClass)
454+
sym.ownersIterator.exists(_ hasAnnotation UnspecializedClass)
455455

456456
def isNormalizedMember(m: Symbol) = m.isSpecialized && (info get m exists {
457457
case NormalizedMember(_) => true

src/compiler/scala/tools/nsc/typechecker/Implicits.scala

Lines changed: 9 addi 8000 tions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,10 @@ trait Implicits {
357357
/** The type parameters to instantiate */
358358
val undetParams = if (isView) Nil else context.outer.undetparams
359359
val wildPt = approximate(pt)
360+
private val ptFunctionArity: Int = {
361+
val dealiased = pt.dealiasWiden
362+
if (isFunctionTypeDirect(dealiased)) dealiased.typeArgs.length - 1 else -1
363+
}
360364

361365
private val stableRunDefsForImport = currentRun.runDefinitions
362366
import stableRunDefsForImport._
@@ -543,9 +547,7 @@ trait Implicits {
543547
if (sym.isAliasType) loop(tp, pt.dealias)
544548
else if (sym.isAbstractType) loop(tp, pt.bounds.lo)
545549
else {
546-
val len = args.length - 1
547-
hasLength(params, len) &&
548-
sym == FunctionClass(len) && {
550+
ptFunctionArity > 0 && hasLength(params, ptFunctionArity) && {
549551
var ps = params
550552
var as = args
551553
if (fast) {
@@ -588,9 +590,12 @@ trait Implicits {
588590
// We can only rule out a subtype relationship if the left hand
589591
// side is a class, else we may not know enough.
590592
case tr1 @ TypeRef(_, sym1, _) if sym1.isClass =>
593+
def typeRefHasMember(tp: TypeRef, name: Name) = {
594+
tp.baseClasses.exists(_.info.decls.lookupEntry(name) != null)
595+
}
591596
tp2.dealiasWiden match {
592597
case TypeRef(_, sym2, _) => ((sym1 eq ByNameParamClass) != (sym2 eq ByNameParamClass)) || (sym2.isClass && !(sym1 isWeakSubClass sym2))
593-
case RefinedType(parents, decls) => decls.nonEmpty && tr1.member(decls.head.name) == NoSymbol
598+
case RefinedType(parents, decls) => decls.nonEmpty && !typeRefHasMember(tr1, decls.head.name) // opt avoid full call to .member
594599
case _ => false
595600
}
596601
case _ => false

src/compiler/scala/tools/nsc/typechecker/Namers.scala

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,11 +1374,6 @@ trait Namers extends MethodSynthesis {
13741374
if (mexists(vparamss)(_.symbol.hasDefault) || mexists(overridden.paramss)(_.hasDefault))
13751375
addDefaultGetters(meth, ddef, vparamss, tparams, overridden)
13761376

1377-
// fast track macros, i.e. macros defined inside the compiler, are hardcoded
1378-
// hence we make use of that and let them have whatever right-hand side they need
1379-
// (either "macro ???" as they used to or just "???" to maximally simplify their compilation)
1380-
if (fastTrack contains meth) meth setFlag MACRO
1381-
13821377
// macro defs need to be typechecked in advance
13831378
// because @macroImpl annotation only gets assigned during typechecking
13841379
// otherwise macro defs wouldn't be able to robustly coexist with their clients

src/compiler/scala/tools/nsc/typechecker/Typers.scala

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -254,10 +254,6 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
254254
var context = context0
255255
def context1 = context
256256

257-
// for use with silent type checking to when we can't have results with undetermined type params
258-
// note that this captures the context var
259-
val isMonoContext = (_: Any) => context.undetparams.isEmpty
260-
261257
def dropExistential(tp: Type): Type = tp match {
262258
case ExistentialType(tparams, tpe) =>
263259
new SubstWildcardMap(tparams).apply(tp)
@@ -2425,7 +2421,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
24252421
block match {
24262422
case Block(List(classDef @ ClassDef(_, _, _, _)), Apply(Select(New(_), _), _)) =>
24272423
val classDecls = classDef.symbol.info.decls
2428-
val visibleMembers = pt match {
2424+
lazy val visibleMembers = pt match {
24292425
case WildcardType => classDecls.toList
24302426
case BoundedWildcardType(TypeBounds(lo, _)) => lo.members
24312427
case _ => pt.members
@@ -2972,7 +2968,11 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
29722968
// We're looking for a method (as indicated by FUNmode in the silent typed below),
29732969
// so let's make sure our expected type is a MethodType
29742970
val methArgs = NoSymbol.newSyntheticValueParams(argpts map { case NoType => WildcardType case tp => tp })
2975-
silent(_.typed(meth, mode.forFunMode, MethodType(methArgs, respt))) filter (isMonoContext) map { methTyped =>
2971+
2972+
val result = silent(_.typed(meth, mode.forFunMode, MethodType(methArgs, respt)))
2973+
// we can't have results with undetermined type params
2974+
val resultMono = result filter (_ => context.undetparams.isEmpty)
2975+
resultMono map { methTyped =>
29762976
// if context.undetparams is not empty, the method was polymorphic,
29772977
// so we need the missing arguments to infer its type. See #871
29782978
val funPt = normalize(methTyped.tpe) baseType FunctionClass(numVparams)
@@ -4875,17 +4875,16 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
48754875
dyna.wrapErrors(t, (_.typed1(t, mode, pt)))
48764876
}
48774877

4878-
val sym = tree.symbol orElse member(qual, name) orElse inCompanionForJavaStatic(qual.tpe.prefix, qual.symbol, name) orElse {
4878+
val sym = tree.symbol orElse member(qual, name) orElse inCompanionForJavaStatic(qual.tpe.prefix, qual.symbol, name)
4879+
if ((sym eq NoSymbol) && name != nme.CONSTRUCTOR && mode.inAny(EXPRmode | PATTERNmode)) {
48794880
// symbol not found? --> try to convert implicitly to a type that does have the required
48804881
// member. Added `| PATTERNmode` to allow enrichment in patterns (so we can add e.g., an
48814882
// xml member to StringContext, which in turn has an unapply[Seq] method)
4882-
if (name != nme.CONSTRUCTOR && mode.inAny(EXPRmode | PATTERNmode)) {
4883-
val qual1 = adaptToMemberWithArgs(tree, qual, name, mode)
4884-
if ((qual1 ne qual) && !qual1.isErrorTyped)
4885-
return typed(treeCopy.Select(tree, qual1, name), mode, pt)
4886-
}
4887-
NoSymbol
4883+
val qual1 = adaptToMemberWithArgs(tree, qual, name, mode)
4884+
if ((qual1 ne qual) && !qual1.isErrorTyped)
4885+
return typed(treeCopy.Select(tree, qual1, name), mode, pt)
48884886
}
4887+
48894888
if (phase.erasedTypes && qual.isInstanceOf[Super] && tree.symbol != NoSymbol)
48904889
qual setType tree.symbol.owner.tpe
48914890

@@ -5050,7 +5049,10 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
50505049
}
50515050
else {
50525051
val pre1 = if (sym.isTopLevel) sym.owner.thisType else if (qual == EmptyTree) NoPrefix else qual.tpe
5053-
val tree1 = if (qual == EmptyTree) tree else atPos(tree.pos)(Select(atPos(tree.pos.focusStart)(qual), name))
5052+
val tree1 = if (qual == EmptyTree) tree else {
5053+
val pos = tree.pos
5054+
Select(atPos(pos.focusStart)(qual), name).setPos(pos)
5055+
}
50545056
val (tree2, pre2) = makeAccessible(tree1, sym, pre1, qual)
50555057
// scala/bug#5967 Important to replace param type A* with Seq[A] when seen from from a reference, to avoid
50565058
// inference errors in pattern matching.

src/compiler/scala/tools/nsc/typechecker/Unapplies.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@ trait Unapplies extends ast.TreeDSL {
5353
}
5454

5555
private def constrParamss(cdef: ClassDef): List[List[ValDef]] = {
56-
val ClassDef(_, _, _, Template(_, _, body)) = resetAttrs(cdef.duplicate)
57-
val DefDef(_, _, _, vparamss, _, _) = treeInfo firstConstructor body
56+
val prunedClassDef = deriveClassDef(cdef)(tmpl => deriveTemplate(tmpl)(stats => treeInfo.firstConstructor(stats).duplicate :: Nil))
57+
val ClassDef(_, _, _, Template(_, _, firstConstructor :: Nil)) = resetAttrs(prunedClassDef)
58+
val DefDef(_, _, _, vparamss, _, _) = firstConstructor
5859
vparamss
5960
}
6061

src/reflect/scala/reflect/internal/SymbolTable.scala

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -171,11 +171,12 @@ abstract class SymbolTable extends macros.Universe
171171
final val NoRunId = 0
172172

173173
// sigh, this has to be public or enteringPhase doesn't inline.
174-
var phStack: List[Phase] = Nil
174+
var phStack: Array[Phase] = new Array(128)
175+
var phStackIndex = 0
175176
private[this] var ph: Phase = NoPhase
176177
private[this] var per = NoPeriod
177178

178-
final def atPhaseStack: List[Phase] = phStack
179+
final def atPhaseStack: List[Phase] = List.tabulate(phStackIndex)(i => phStack(i))
179180
final def phase: Phase = {
180181
if (Statistics.hotEnabled)
181182
Statistics.incCounter(SymbolTableStats.phaseCounter)
@@ -196,11 +197,13 @@ abstract class SymbolTable extends macros.Universe
196197
final def pushPhase(ph: Phase): Phase = {
197198
val current = phase
198199
phase = ph
199-
phStack ::= ph
200+
phStack(phStackIndex) = ph
201+
phStackIndex += 1
200202
current
201203
}
202204
final def popPhase(ph: Phase) {
203-
phStack = phStack.tail
205+
phStack(phStackIndex) = null
206+
phStackIndex -= 1
204207
phase = ph
205208
}
206209

@@ -231,9 +234,12 @@ abstract class SymbolTable extends macros.Universe
231234

232235
/** Perform given operation at given phase. */
233236
@inline final def enteringPhase[T](ph: Phase)(op: => T): T = {
234-
val saved = pushPhase(ph)
235-
try op
236-
finally popPhase(saved)
237+
if (ph eq phase) op // opt
238+
else {
239+
val saved = pushPhase(ph)
240+
try op
241+
finally popPhase(saved)
242+
}
237243
}
238244

239245
final def findPhaseWithName(phaseName: String): Phase = {

0 commit comments

Comments
 (0)
0