summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2011-11-22 23:10:26 +0000
committerAdriaan Moors <adriaan.moors@epfl.ch>2011-11-22 23:10:26 +0000
commit4fca89bfd0a6a27a3aed03daad96bfc55eb88f09 (patch)
tree3d0013ff8eecc88b431ef316b9b4bdd1e4ec12bd
parentaa1219dcdb273ac5a44521c255528b243b8e5a04 (diff)
downloadscala-4fca89bfd0a6a27a3aed03daad96bfc55eb88f09.tar.gz
scala-4fca89bfd0a6a27a3aed03daad96bfc55eb88f09.tar.bz2
scala-4fca89bfd0a6a27a3aed03daad96bfc55eb88f09.zip
optimized typedSubst
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala43
1 files changed, 24 insertions, 19 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala
index 9fb6c7668a..49f3330297 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala
@@ -206,7 +206,7 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer =>
if (needsTypeTest(patBinder.info.widen, extractor.paramType)) {
// chain a type-testing extractor before the actual extractor call
// it tests the type, checks the outer pointer and casts to the expected type
- // the outer check is mandated by the spec for case classes, but we do it for user-defined unapplies as well
+ // TODO: the outer check is mandated by the spec for case classes, but we do it for user-defined unapplies as well [SPEC]
// (the prefix of the argument passed to the unapply must equal the prefix of the type of the binder)
val treeMaker = TypeTestTreeMaker(patBinder, extractor.paramType, pos)
(List(treeMaker), treeMaker.nextBinder)
@@ -807,26 +807,31 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer =>
def matchingStrategy: Tree
def typed(tree: Tree, mode: Int, pt: Type): Tree // implemented in MatchTranslator
+ @inline private def typedIfOrigTyped(to: Tree, origTp: Type): Tree =
+ if (origTp == null || origTp == NoType) to
+ // important: only type when actually substing and when original tree was typed
+ // (don't need to use origTp as the expected type, though, and can't always do this anyway due to unknown type params stemming from polymorphic extractors)
+ else typed(to, EXPRmode, WildcardType)
+
// We must explicitly type the trees that we replace inside some other tree, since the latter may already have been typed,
// and will thus not be retyped. This means we might end up with untyped subtrees inside bigger, typed trees.
- def typedSubst(from: List[Symbol], to: List[Tree]): Transformer = new Transformer {
- override def transform(tree: Tree): Tree = {
- def subst(from: List[Symbol], to: List[Tree]): Tree =
- if (from.isEmpty) tree
- else if (tree.symbol == from.head) typedIfOrigTyped(to.head.shallowDuplicate, tree.tpe)
- else subst(from.tail, to.tail)
-
- tree match {
- case Ident(_) => subst(from, to)
- case _ => super.transform(tree)
+ def typedSubst(tree: Tree, from: List[Symbol], to: List[Tree]): Tree = {
+ // according to -Ystatistics 10% of translateMatch's time is spent in this method...
+ // since about half of the typedSubst's end up being no-ops, the check below shaves off 5% of the time spent in typedSubst
+ if (!tree.exists { case i@Ident(_) => from contains i.symbol case _ => false}) tree
+ else (new Transformer {
+ override def transform(tree: Tree): Tree = {
+ def subst(from: List[Symbol], to: List[Tree]): Tree =
+ if (from.isEmpty) tree
+ else if (tree.symbol == from.head) typedIfOrigTyped(to.head.shallowDuplicate, tree.tpe)
+ else subst(from.tail, to.tail)
+
+ tree match {
+ case Ident(_) => subst(from, to)
+ case _ => super.transform(tree)
+ }
}
- }
-
- @inline private def typedIfOrigTyped(to: Tree, origTp: Type): Tree =
- if (origTp == null || origTp == NoType) to
- // important: only type when actually substing and when original tree was typed
- // (don't need to use origTp as the expected type, though, and can't always do this anyway due to unknown type params stemming from polymorphic extractors)
- else typed(to, EXPRmode, WildcardType)
+ }).transform(tree)
}
lazy val pmgen: CommonCodeGen with MatchingStrategyGen with MonadInstGen =
@@ -964,7 +969,7 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer =>
BLOCK(
v,
- IF (vs DOT isEmpty) THEN zero ELSE typedSubst(List(x.symbol), List(vs DOT get)).transform(body)
+ IF (vs DOT isEmpty) THEN zero ELSE typedSubst(body, List(x.symbol), List(vs DOT get))
)
case _ => println("huh?")
(opt DOT vpmName.flatMap)(fun)