Skip to content

Commit e6ac99e

Browse files
paulpAdriaan Moors
authored andcommitted
Further optimization of asSeenFrom.
After some more early exclusion of uninteresting arguments, asSeenFrom is now over twice as fast. Compiling the collections, three runs: -- Without these two commits: 8108775ms, 8132052ms, 8257527ms in asSeenFrom Wall clock: 0m54.202s, 0m54.877s, 0m55.925s -- With these two commits: 3568719ms, 3542860ms, 3570892ms in asSeenFrom Wall clock: 0m50.730s, 0m51.213s, 0m50.850s (Rebase of scala#835)
1 parent e90f79a commit e6ac99e

File tree

1 file changed

+27
-22
lines changed

1 file changed

+27
-22
lines changed

src/reflect/scala/reflect/internal/Types.scala

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -693,28 +693,21 @@ trait Types extends api.Types { self: SymbolTable =>
693693
* = Int
694694
*/
695695
def asSeenFrom(pre: Type, clazz: Symbol): Type = {
696-
if (isTrivial || phase.erasedTypes && pre.typeSymbol != ArrayClass) this
697-
else {
698-
// scala.tools.nsc.util.trace.when(pre.isInstanceOf[ExistentialType])("X "+this+".asSeenfrom("+pre+","+clazz+" = ")
699-
Statistics.incCounter(asSeenFromCount)
700-
val start = Statistics.pushTimer(typeOpsStack, asSeenFromNanos)
701-
val pre1 = pre.normalize
702-
703-
val result: Type = (
704-
if (pre1.isTrivial && (clazz.isPackageClass || !clazz.isClass)) this
705-
else {
706-
val m = new AsSeenFromMap(pre1, clazz)
707-
val tp = m apply this
708-
val tp1 = existentialAbstraction(m.capturedParams, tp)
709-
if (m.capturedSkolems.isEmpty) tp1
710-
else deriveType(m.capturedSkolems, _.cloneSymbol setFlag CAPTURED)(tp1)
711-
}
696+
TypesStats.timedTypeOp(asSeenFromNanos) {
697+
val trivial = (
698+
this.isTrivial
699+
|| phase.erasedTypes && pre.typeSymbol != ArrayClass
700+
|| pre.normalize.isTrivial && !isPossiblePrefix(clazz)
712701
)
713-
Statistics.popTimer(typeOpsStack, start)
714-
if ((result ne this) && pre1.isTrivial)
715-
debuglog(s"asSeenFrom($pre1, $clazz)\n old: ${this}\n new: $result")
702+
if (trivial) this
703+
else {
704+
val m = new AsSeenFromMap(pre.normalize, clazz)
705+
val tp = m(this)
706+
val tp1 = existentialAbstraction(m.capturedParams, tp)
716707

717-
result
708+
if (m.capturedSkolems.isEmpty) tp1
709+
else deriveType(m.capturedSkolems, _.cloneSymbol setFlag CAPTURED)(tp1)
710+
}
718711
}
719712
}
720713

@@ -4265,15 +4258,21 @@ trait Types extends api.Types { self: SymbolTable =>
42654258

42664259
def singletonBounds(hi: Type) = TypeBounds.upper(intersectionType(List(hi, SingletonClass.tpe)))
42674260

4261+
/** Might the given symbol be important when calculating the prefix
4262+
* of a type? When tp.asSeenFrom(pre, clazz) is called on `tp`,
4263+
* the result will be `tp` unchanged if `pre` is trivial and `clazz`
4264+
* is a symbol such that isPossiblePrefix(clazz) == false.
4265+
*/
4266+
def isPossiblePrefix(clazz: Symbol) = clazz.isClass && !clazz.isPackageClass
4267+
42684268
/** A map to compute the asSeenFrom method */
42694269
class AsSeenFromMap(pre: Type, clazz: Symbol) extends TypeMap with KeepOnlyTypeConstraints {
42704270
var capturedSkolems: List[Symbol] = List()
42714271
var capturedParams: List[Symbol] = List()
42724272

42734273
@inline private def skipPrefixOf(pre: Type, clazz: Symbol) = (
4274-
(pre eq NoType) || (pre eq NoPrefix) || !clazz.isClass
4274+
(pre eq NoType) || (pre eq NoPrefix) || !isPossiblePrefix(clazz)
42754275
)
4276-
42774276
override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = {
42784277
object annotationArgRewriter extends TypeMapTransformer {
42794278
private def canRewriteThis(sym: Symbol) = (
@@ -6922,4 +6921,10 @@ object TypesStats {
69226921
val typerefBaseTypeSeqCount = Statistics.newSubCounter(" of which for typerefs", baseTypeSeqCount)
69236922
val singletonBaseTypeSeqCount = Statistics.newSubCounter(" of which for singletons", baseTypeSeqCount)
69246923
val typeOpsStack = Statistics.newTimerStack()
6924+
6925+
@inline final def timedTypeOp[T](c: Statistics.StackableTimer)(op: => T): T = {
6926+
val start = Statistics.pushTimer(typeOpsStack, c)
6927+
try op
6928+
finally Statistics.popTimer(typeOpsStack, start)
6929+
}
69256930
}

0 commit comments

Comments
 (0)