Skip to content

Commit

Permalink
Optimisations: avoid List allocations in the RefChecks.
Browse files Browse the repository at this point in the history
We add some small optimisations to the code in the RefChecks
- We replace the `map length` calls with the utility methods in the
  Collections traits.
- We replace a combined use of flatten, map, zip, and filter with
  the use of an iterator and a special iterator function.
- We add to the Collections utils a function to create a special
  iterator, which combines zip, filter, and collect functions.
  • Loading branch information
diesalbla committed Mar 14, 2019
1 parent 9f5d27d commit 6a58cce
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 6 deletions.
16 changes: 10 additions & 6 deletions src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -686,16 +686,20 @@ abstract class RefChecks extends Transform {
val matchingArity = matchingName filter { m =>
!m.isDeferred &&
(m.name == underlying.name) &&
(m.paramLists.length == abstractParamLists.length) &&
(m.paramLists.map(_.length).sum == abstractParamLists.map(_.length).sum) &&
(m.tpe.typeParams.size == underlying.tpe.typeParams.size)
sameLength(m.paramLists, abstractParamLists) &&
sumSize(m.paramLists, 0) == sumSize(abstractParamLists, 0) &&
sameLength(m.tpe.typeParams, underlying.tpe.typeParams)
}

matchingArity match {
// So far so good: only one candidate method
case Scope(concrete) =>
val mismatches = abstractParamLists.flatten.map(_.tpe) zip concrete.paramLists.flatten.map(_.tpe) filterNot { case (x, y) => x =:= y }
mismatches match {
val aplIter = abstractParamLists .iterator.flatten
val cplIter = concrete.paramLists.iterator.flatten
def mismatch(apl: Symbol, cpl: Symbol): Option[(Type, Type)] =
if (apl.tpe =:= cpl.tpe) None else Some(apl.tpe -> cpl.tpe)

mapFilter2(aplIter, cplIter)(mismatch).take(2).toList match {
// Only one mismatched parameter: say something useful.
case (pa, pc) :: Nil =>
val abstractSym = pa.typeSymbol
Expand Down Expand Up @@ -724,7 +728,7 @@ abstract class RefChecks extends Transform {
)

undefined("\n(Note that %s does not match %s%s)".format(pa, pc, addendum))
case xs =>
case _ =>
undefined("")
}
case _ =>
Expand Down
24 changes: 24 additions & 0 deletions src/reflect/scala/reflect/internal/util/Collections.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package reflect.internal.util
import scala.collection.{ mutable, immutable }
import scala.annotation.tailrec
import mutable.ListBuffer
import java.util.NoSuchElementException

/** Profiler driven changes.
* TODO - inlining doesn't work from here because of the bug that
Expand Down Expand Up @@ -308,6 +309,29 @@ trait Collections {
true
}

final def mapFilter2[A, B, C](itA: Iterator[A], itB: Iterator[B])(f: (A, B) => Option[C]): Iterator[C] =
new Iterator[C] {
private[this] var head: Option[C] = None
private[this] def advanceHead(): Unit =
while (head.isEmpty && itA.hasNext && itB.hasNext) {
val x = itA.next
val y = itB.next
head = f(x, y)
}

def hasNext: Boolean = {
advanceHead()
! head.isEmpty
}

def next(): C = {
advanceHead()
val res = head getOrElse (throw new NoSuchElementException("next on empty Iterator"))
head = None
res
}
}

// "Opt" suffix or traverse clashes with the various traversers' traverses
final def sequenceOpt[A](as: List[Option[A]]): Option[List[A]] = traverseOpt(as)(identity)
final def traverseOpt[A, B](as: List[A])(f: A => Option[B]): Option[List[B]] =
Expand Down

0 comments on commit 6a58cce

Please sign in to comment.