diff options
author | Paul Phillips <paulp@improving.org> | 2012-12-31 08:57:19 -0800 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-12-31 08:57:19 -0800 |
commit | 666572261c41cc92b06c03bf4aa260c198240cd8 (patch) | |
tree | b1501ddc2b6126507a9234dc0e2f5d858cdfebef /src/library | |
parent | 39641b4593196b11d0aeba1777fdffc72ed50be4 (diff) | |
parent | 6a288b632e0e78a96f1298be9b4e8231728183af (diff) | |
download | scala-666572261c41cc92b06c03bf4aa260c198240cd8.tar.gz scala-666572261c41cc92b06c03bf4aa260c198240cd8.tar.bz2 scala-666572261c41cc92b06c03bf4aa260c198240cd8.zip |
Merge pull request #1823 from paulp/pr/eliminate-allocations
Eliminating allocations.
Diffstat (limited to 'src/library')
-rwxr-xr-x | src/library/scala/collection/IndexedSeqOptimized.scala | 10 | ||||
-rw-r--r-- | src/library/scala/collection/TraversableLike.scala | 17 | ||||
-rw-r--r-- | src/library/scala/collection/generic/Growable.scala | 17 | ||||
-rw-r--r-- | src/library/scala/collection/mutable/ListBuffer.scala | 9 | ||||
-rw-r--r-- | src/library/scala/io/Codec.scala | 55 |
5 files changed, 63 insertions, 45 deletions
diff --git a/src/library/scala/collection/IndexedSeqOptimized.scala b/src/library/scala/collection/IndexedSeqOptimized.scala index 09c4b14ba0..9721a42e91 100755 --- a/src/library/scala/collection/IndexedSeqOptimized.scala +++ b/src/library/scala/collection/IndexedSeqOptimized.scala @@ -33,11 +33,17 @@ trait IndexedSeqOptimized[+A, +Repr] extends Any with IndexedSeqLike[A, Repr] { while (i < len) { f(this(i)); i += 1 } } + private def prefixLengthImpl(p: A => Boolean, expectTrue: Boolean): Int = { + var i = 0 + while (i < length && p(apply(i)) == expectTrue) i += 1 + i + } + override /*IterableLike*/ - def forall(p: A => Boolean): Boolean = prefixLength(p(_)) == length + def forall(p: A => Boolean): Boolean = prefixLengthImpl(p, expectTrue = true) == length override /*IterableLike*/ - def exists(p: A => Boolean): Boolean = prefixLength(!p(_)) != length + def exists(p: A => Boolean): Boolean = prefixLengthImpl(p, expectTrue = false) != length override /*IterableLike*/ def find(p: A => Boolean): Option[A] = { diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala index c1a68b6b16..a55257d128 100644 --- a/src/library/scala/collection/TraversableLike.scala +++ b/src/library/scala/collection/TraversableLike.scala @@ -252,18 +252,21 @@ trait TraversableLike[+A, +Repr] extends Any b.result } + private def filterImpl(p: A => Boolean, isFlipped: Boolean): Repr = { + val b = newBuilder + for (x <- this) + if (p(x) != isFlipped) b += x + + b.result + } + /** Selects all elements of this $coll which satisfy a predicate. * * @param p the predicate used to test elements. * @return a new $coll consisting of all elements of this $coll that satisfy the given * predicate `p`. The order of the elements is preserved. */ - def filter(p: A => Boolean): Repr = { - val b = newBuilder - for (x <- this) - if (p(x)) b += x - b.result - } + def filter(p: A => Boolean): Repr = filterImpl(p, isFlipped = false) /** Selects all elements of this $coll which do not satisfy a predicate. * @@ -271,7 +274,7 @@ trait TraversableLike[+A, +Repr] extends Any * @return a new $coll consisting of all elements of this $coll that do not satisfy the given * predicate `p`. The order of the elements is preserved. */ - def filterNot(p: A => Boolean): Repr = filter(!p(_)) + def filterNot(p: A => Boolean): Repr = filterImpl(p, isFlipped = true) def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[Repr, B, That]): That = { val b = bf(repr) diff --git a/src/library/scala/collection/generic/Growable.scala b/src/library/scala/collection/generic/Growable.scala index cb75212e3d..52a0d32de1 100644 --- a/src/library/scala/collection/generic/Growable.scala +++ b/src/library/scala/collection/generic/Growable.scala @@ -6,10 +6,11 @@ ** |/ ** \* */ - package scala.collection package generic +import scala.annotation.tailrec + /** This trait forms part of collections that can be augmented * using a `+=` operator and that can be cleared of all elements using * a `clear` method. @@ -45,7 +46,19 @@ trait Growable[-A] extends Clearable { * @param xs the TraversableOnce producing the elements to $add. * @return the $coll itself. */ - def ++=(xs: TraversableOnce[A]): this.type = { xs.seq foreach += ; this } + def ++=(xs: TraversableOnce[A]): this.type = { + @tailrec def loop(xs: collection.LinearSeq[A]) { + if (xs.nonEmpty) { + this += xs.head + loop(xs.tail) + } + } + xs.seq match { + case xs: collection.LinearSeq[_] => loop(xs) + case xs => xs foreach += + } + this + } /** Clears the $coll's contents. After this operation, the * $coll is empty. diff --git a/src/library/scala/collection/mutable/ListBuffer.scala b/src/library/scala/collection/mutable/ListBuffer.scala index b7b487964c..97d469bca2 100644 --- a/src/library/scala/collection/mutable/ListBuffer.scala +++ b/src/library/scala/collection/mutable/ListBuffer.scala @@ -6,8 +6,6 @@ ** |/ ** \* */ - - package scala.collection package mutable @@ -178,8 +176,11 @@ final class ListBuffer[A] this } - override def ++=(xs: TraversableOnce[A]): this.type = - if (xs.asInstanceOf[AnyRef] eq this) ++= (this take size) else super.++=(xs) + override def ++=(xs: TraversableOnce[A]): this.type = xs match { + case x: AnyRef if x eq this => this ++= (this take size) + case _ => super.++=(xs) + + } override def ++=:(xs: TraversableOnce[A]): this.type = if (xs.asInstanceOf[AnyRef] eq this) ++=: (this take size) else super.++=:(xs) diff --git a/src/library/scala/io/Codec.scala b/src/library/scala/io/Codec.scala index 5d046e48b0..bda4234460 100644 --- a/src/library/scala/io/Codec.scala +++ b/src/library/scala/io/Codec.scala @@ -43,42 +43,37 @@ class Codec(val charSet: Charset) { override def toString = name // these methods can be chained to configure the variables above - def onMalformedInput(newAction: Action): this.type = { _onMalformedInput = newAction ; this } - def onUnmappableCharacter(newAction: Action): this.type = { _onUnmappableCharacter = newAction ; this } - def decodingReplaceWith(newReplacement: String): this.type = { _decodingReplacement = newReplacement ; this } + def onMalformedInput(newAction: Action): this.type = { _onMalformedInput = newAction ; this } + def onUnmappableCharacter(newAction: Action): this.type = { _onUnmappableCharacter = newAction ; this } + def decodingReplaceWith(newReplacement: String): this.type = { _decodingReplacement = newReplacement ; this } def encodingReplaceWith(newReplacement: Array[Byte]): this.type = { _encodingReplacement = newReplacement ; this } - def onCodingException(handler: Handler): this.type = { _onCodingException = handler ; this } + def onCodingException(handler: Handler): this.type = { _onCodingException = handler ; this } def name = charSet.name - def encoder = - applyFunctions[CharsetEncoder](charSet.newEncoder(), - (_ onMalformedInput _onMalformedInput, _onMalformedInput != null), - (_ onUnmappableCharacter _onUnmappableCharacter, _onUnmappableCharacter != null), - (_ replaceWith _encodingReplacement, _encodingReplacement != null) - ) - - def decoder = - applyFunctions[CharsetDecoder](charSet.newDecoder(), - (_ onMalformedInput _onMalformedInput, _onMalformedInput != null), - (_ onUnmappableCharacter _onUnmappableCharacter, _onUnmappableCharacter != null), - (_ replaceWith _decodingReplacement, _decodingReplacement != null) - ) + def encoder: CharsetEncoder = { + val enc = charSet.newEncoder() + if (_onMalformedInput ne null) enc onMalformedInput _onMalformedInput + if (_onUnmappableCharacter ne null) enc onUnmappableCharacter _onUnmappableCharacter + if (_encodingReplacement ne null) enc replaceWith _encodingReplacement + enc + } + def decoder: CharsetDecoder = { + val dec = charSet.newDecoder() + if (_onMalformedInput ne null) dec onMalformedInput _onMalformedInput + if (_onUnmappableCharacter ne null) dec onUnmappableCharacter _onUnmappableCharacter + if (_decodingReplacement ne null) dec replaceWith _decodingReplacement + dec + } def wrap(body: => Int): Int = try body catch { case e: CharacterCodingException => _onCodingException(e) } - - // call a series of side effecting methods on an object, finally returning the object - private def applyFunctions[T](x: T, fs: Configure[T]*) = - fs.foldLeft(x)((x, pair) => pair match { - case (f, cond) => if (cond) f(x) else x - }) } trait LowPriorityCodecImplicits { self: Codec.type => /** The Codec of Last Resort. */ - implicit def fallbackSystemCodec: Codec = defaultCharsetCodec + implicit lazy val fallbackSystemCodec: Codec = defaultCharsetCodec } object Codec extends LowPriorityCodecImplicits { @@ -90,9 +85,9 @@ object Codec extends LowPriorityCodecImplicits { * the fact that you can influence anything at all via -Dfile.encoding * as an accident, with any anomalies considered "not a bug". */ - def defaultCharsetCodec = apply(Charset.defaultCharset) - def fileEncodingCodec = apply(scala.util.Properties.encodingString) - def default = defaultCharsetCodec + def defaultCharsetCodec = apply(Charset.defaultCharset) + def fileEncodingCodec = apply(scala.util.Properties.encodingString) + def default = defaultCharsetCodec def apply(encoding: String): Codec = new Codec(Charset forName encoding) def apply(charSet: Charset): Codec = new Codec(charSet) @@ -130,7 +125,7 @@ object Codec extends LowPriorityCodecImplicits { bytes } - implicit def string2codec(s: String) = apply(s) - implicit def charset2codec(c: Charset) = apply(c) - implicit def decoder2codec(cd: CharsetDecoder) = apply(cd) + implicit def string2codec(s: String): Codec = apply(s) + implicit def charset2codec(c: Charset): Codec = apply(c) + implicit def decoder2codec(cd: CharsetDecoder): Codec = apply(cd) } |