diff options
author | Grzegorz Kossakowski <grzegorz.kossakowski@gmail.com> | 2014-02-25 18:49:07 +0100 |
---|---|---|
committer | Grzegorz Kossakowski <grzegorz.kossakowski@gmail.com> | 2014-02-25 18:49:07 +0100 |
commit | 5ae2fe02722d637c1d2683d18918c8a2e1ab3425 (patch) | |
tree | d891a3a19126d7dd805d8a5b6ffb38eac65ec84f /src | |
parent | 1382c85106373932d3f4a3c1b7e10138bddcddac (diff) | |
parent | c5962b1871f8093fe200fe0c47cd9c202b07a8f9 (diff) | |
download | scala-5ae2fe02722d637c1d2683d18918c8a2e1ab3425.tar.gz scala-5ae2fe02722d637c1d2683d18918c8a2e1ab3425.tar.bz2 scala-5ae2fe02722d637c1d2683d18918c8a2e1ab3425.zip |
Merge pull request #3498 from Ichoran/issue/8240
SI-8240 Consider rolling back optimizations for List
Diffstat (limited to 'src')
-rw-r--r-- | src/library/scala/collection/immutable/List.scala | 101 |
1 files changed, 92 insertions, 9 deletions
diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index c3728fa02a..930e13a9d3 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -203,17 +203,19 @@ sealed abstract class List[+A] extends AbstractSeq[A] override def toList: List[A] = this - override def take(n: Int): List[A] = { - val b = new ListBuffer[A] - var i = 0 - var these = this - while (!these.isEmpty && i < n) { + override def take(n: Int): List[A] = if (isEmpty || n <= 0) Nil else { + val h = new ::(head, Nil) + var t = h + var rest = tail + var i = 1 + while ({if (rest.isEmpty) return this; i < n}) { i += 1 - b += these.head - these = these.tail + val nx = new ::(rest.head, Nil) + t.tl = nx + t = nx + rest = rest.tail } - if (these.isEmpty) this - else b.toList + h } override def drop(n: Int): List[A] = { @@ -264,6 +266,85 @@ sealed abstract class List[+A] extends AbstractSeq[A] } (b.toList, these) } + + @noinline // TODO - fix optimizer bug that requires noinline (see SI-8334) + final override def map[B, That](f: A => B)(implicit bf: CanBuildFrom[List[A], B, That]): That = { + if (bf eq List.ReusableCBF) { + if (this eq Nil) Nil.asInstanceOf[That] else { + val h = new ::[B](f(head), Nil) + var t: ::[B] = h + var rest = tail + while (rest ne Nil) { + val nx = new ::(f(rest.head), Nil) + t.tl = nx + t = nx + rest = rest.tail + } + h.asInstanceOf[That] + } + } + else super.map(f) + } + + @noinline // TODO - fix optimizer bug that requires noinline for map; applied here to be safe (see SI-8334) + final override def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[List[A], B, That]): That = { + if (bf eq List.ReusableCBF) { + if (this eq Nil) Nil.asInstanceOf[That] else { + var rest = this + var h: ::[B] = null + var x: A = null.asInstanceOf[A] + // Special case for first element + do { + val x: Any = pf.applyOrElse(rest.head, List.partialNotApplied) + if (x.asInstanceOf[AnyRef] ne List.partialNotApplied) h = new ::(x.asInstanceOf[B], Nil) + rest = rest.tail + if (rest eq Nil) return (if (h eq null ) Nil else h).asInstanceOf[That] + } while (h eq null) + var t = h + // Remaining elements + do { + val x: Any = pf.applyOrElse(rest.head, List.partialNotApplied) + if (x.asInstanceOf[AnyRef] ne List.partialNotApplied) { + val nx = new ::(x.asInstanceOf[B], Nil) + t.tl = nx + t = nx + } + rest = rest.tail + } while (rest ne Nil) + h.asInstanceOf[That] + } + } + else super.collect(pf) + } + + @noinline // TODO - fix optimizer bug that requires noinline for map; applied here to be safe (see SI-8334) + final override def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[List[A], B, That]): That = { + if (bf eq List.ReusableCBF) { + if (this eq Nil) Nil.asInstanceOf[That] else { + var rest = this + var found = false + var h: ::[B] = null + var t: ::[B] = null + while (rest ne Nil) { + f(rest.head).foreach{ b => + if (!found) { + h = new ::(b, Nil) + t = h + found = true + } + else { + val nx = new ::(b, Nil) + t.tl = nx + t = nx + } + } + rest = rest.tail + } + (if (!found) Nil else h).asInstanceOf[That] + } + } + else super.flatMap(f) + } @inline final override def takeWhile(p: A => Boolean): List[A] = { val b = new ListBuffer[A] @@ -375,6 +456,8 @@ object List extends SeqFactory[List] { override def empty[A]: List[A] = Nil override def apply[A](xs: A*): List[A] = xs.toList + + private[collection] val partialNotApplied = new Function1[Any, Any] { def apply(x: Any): Any = this } @SerialVersionUID(1L) private class SerializationProxy[A](@transient private var orig: List[A]) extends Serializable { |