summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-07-06 15:55:45 -0700
committerAdriaan Moors <adriaan.moors@epfl.ch>2012-07-12 09:57:08 +0200
commite6ac99e6a9871cb6f6931890d65f17a3663c3a4e (patch)
tree58c22a66b70388e96a85be7adcab3ac0c4afce6e /src
parente90f79a446414541402cf55e9ac664106a5bc355 (diff)
downloadscala-e6ac99e6a9871cb6f6931890d65f17a3663c3a4e.tar.gz
scala-e6ac99e6a9871cb6f6931890d65f17a3663c3a4e.tar.bz2
scala-e6ac99e6a9871cb6f6931890d65f17a3663c3a4e.zip
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 https://github.com/scala/scala/pull/835)
Diffstat (limited to 'src')
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala49
1 files changed, 27 insertions, 22 deletions
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 246e32a147..f3dd1f03ad 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -693,28 +693,21 @@ trait Types extends api.Types { self: SymbolTable =>
* = Int
*/
def asSeenFrom(pre: Type, clazz: Symbol): Type = {
- if (isTrivial || phase.erasedTypes && pre.typeSymbol != ArrayClass) this
- else {
- // scala.tools.nsc.util.trace.when(pre.isInstanceOf[ExistentialType])("X "+this+".asSeenfrom("+pre+","+clazz+" = ")
- Statistics.incCounter(asSeenFromCount)
- val start = Statistics.pushTimer(typeOpsStack, asSeenFromNanos)
- val pre1 = pre.normalize
-
- val result: Type = (
- if (pre1.isTrivial && (clazz.isPackageClass || !clazz.isClass)) this
- else {
- val m = new AsSeenFromMap(pre1, clazz)
- val tp = m apply this
- val tp1 = existentialAbstraction(m.capturedParams, tp)
- if (m.capturedSkolems.isEmpty) tp1
- else deriveType(m.capturedSkolems, _.cloneSymbol setFlag CAPTURED)(tp1)
- }
+ TypesStats.timedTypeOp(asSeenFromNanos) {
+ val trivial = (
+ this.isTrivial
+ || phase.erasedTypes && pre.typeSymbol != ArrayClass
+ || pre.normalize.isTrivial && !isPossiblePrefix(clazz)
)
- Statistics.popTimer(typeOpsStack, start)
- if ((result ne this) && pre1.isTrivial)
- debuglog(s"asSeenFrom($pre1, $clazz)\n old: ${this}\n new: $result")
+ if (trivial) this
+ else {
+ val m = new AsSeenFromMap(pre.normalize, clazz)
+ val tp = m(this)
+ val tp1 = existentialAbstraction(m.capturedParams, tp)
- result
+ if (m.capturedSkolems.isEmpty) tp1
+ else deriveType(m.capturedSkolems, _.cloneSymbol setFlag CAPTURED)(tp1)
+ }
}
}
@@ -4265,15 +4258,21 @@ trait Types extends api.Types { self: SymbolTable =>
def singletonBounds(hi: Type) = TypeBounds.upper(intersectionType(List(hi, SingletonClass.tpe)))
+ /** Might the given symbol be important when calculating the prefix
+ * of a type? When tp.asSeenFrom(pre, clazz) is called on `tp`,
+ * the result will be `tp` unchanged if `pre` is trivial and `clazz`
+ * is a symbol such that isPossiblePrefix(clazz) == false.
+ */
+ def isPossiblePrefix(clazz: Symbol) = clazz.isClass && !clazz.isPackageClass
+
/** A map to compute the asSeenFrom method */
class AsSeenFromMap(pre: Type, clazz: Symbol) extends TypeMap with KeepOnlyTypeConstraints {
var capturedSkolems: List[Symbol] = List()
var capturedParams: List[Symbol] = List()
@inline private def skipPrefixOf(pre: Type, clazz: Symbol) = (
- (pre eq NoType) || (pre eq NoPrefix) || !clazz.isClass
+ (pre eq NoType) || (pre eq NoPrefix) || !isPossiblePrefix(clazz)
)
-
override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = {
object annotationArgRewriter extends TypeMapTransformer {
private def canRewriteThis(sym: Symbol) = (
@@ -6922,4 +6921,10 @@ object TypesStats {
val typerefBaseTypeSeqCount = Statistics.newSubCounter(" of which for typerefs", baseTypeSeqCount)
val singletonBaseTypeSeqCount = Statistics.newSubCounter(" of which for singletons", baseTypeSeqCount)
val typeOpsStack = Statistics.newTimerStack()
+
+ @inline final def timedTypeOp[T](c: Statistics.StackableTimer)(op: => T): T = {
+ val start = Statistics.pushTimer(typeOpsStack, c)
+ try op
+ finally Statistics.popTimer(typeOpsStack, start)
+ }
}