From fdb1e699911ccf4467c6663a799736e42c18eb83 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Wed, 5 Jan 2011 23:39:35 +0000 Subject: Avoids the creation of an amazing 106,700,793 e... Avoids the creation of an amazing 106,700,793 empty arrays (I counted on my fingers) during the compilation of quick.lib and quick.comp by reusing an empty Array[Object]. (And another ten million or so after quick.comp, but who is counting.) It sounds like it would make a bigger difference than it does. Also eliminated some strange indirection from WrappedArray to LowPriorityImplicits back to WrappedArray on each creation. Review by dragos. --- src/library/scala/LowPriorityImplicits.scala | 13 +++++++-- .../scala/collection/mutable/WrappedArray.scala | 34 ++++++++++++++-------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/library/scala/LowPriorityImplicits.scala b/src/library/scala/LowPriorityImplicits.scala index 0182ecdae9..6fce638061 100644 --- a/src/library/scala/LowPriorityImplicits.scala +++ b/src/library/scala/LowPriorityImplicits.scala @@ -37,9 +37,18 @@ class LowPriorityImplicits { implicit def booleanWrapper(x: Boolean) = new runtime.RichBoolean(x) implicit def genericWrapArray[T](xs: Array[T]): WrappedArray[T] = - if (xs ne null) WrappedArray.make(xs) else null + if (xs eq null) null + else WrappedArray.make(xs) + + // Since the JVM thinks arrays are covariant, one 0-length Array[AnyRef] + // is as good as another for all T <: AnyRef. Instead of creating 100,000,000 + // unique ones by way of this implicit, let's share one. + implicit def wrapRefArray[T <: AnyRef](xs: Array[T]): WrappedArray[T] = { + if (xs eq null) null + else if (xs.length == 0) WrappedArray.empty[T] + else new WrappedArray.ofRef[T](xs) + } - implicit def wrapRefArray[T <: AnyRef](xs: Array[T]): WrappedArray[T] = if (xs ne null) new WrappedArray.ofRef[T](xs) else null implicit def wrapIntArray(xs: Array[Int]): WrappedArray[Int] = if (xs ne null) new WrappedArray.ofInt(xs) else null implicit def wrapDoubleArray(xs: Array[Double]): WrappedArray[Double] = if (xs ne null) new WrappedArray.ofDouble(xs) else null implicit def wrapLongArray(xs: Array[Long]): WrappedArray[Long] = if (xs ne null) new WrappedArray.ofLong(xs) else null diff --git a/src/library/scala/collection/mutable/WrappedArray.scala b/src/library/scala/collection/mutable/WrappedArray.scala index a5fba22846..b08a76c234 100644 --- a/src/library/scala/collection/mutable/WrappedArray.scala +++ b/src/library/scala/collection/mutable/WrappedArray.scala @@ -81,18 +81,28 @@ extends IndexedSeq[T] /** A companion object used to create instances of `WrappedArray`. */ object WrappedArray { - def make[T](x: AnyRef): WrappedArray[T] = x match { - case x: Array[AnyRef] => wrapRefArray[AnyRef](x).asInstanceOf[WrappedArray[T]] - case x: Array[Int] => wrapIntArray(x).asInstanceOf[WrappedArray[T]] - case x: Array[Double] => wrapDoubleArray(x).asInstanceOf[WrappedArray[T]] - case x: Array[Long] => wrapLongArray(x).asInstanceOf[WrappedArray[T]] - case x: Array[Float] => wrapFloatArray(x).asInstanceOf[WrappedArray[T]] - case x: Array[Char] => wrapCharArray(x).asInstanceOf[WrappedArray[T]] - case x: Array[Byte] => wrapByteArray(x).asInstanceOf[WrappedArray[T]] - case x: Array[Short] => wrapShortArray(x).asInstanceOf[WrappedArray[T]] - case x: Array[Boolean] => wrapBooleanArray(x).asInstanceOf[WrappedArray[T]] - case x: Array[Unit] => wrapUnitArray(x).asInstanceOf[WrappedArray[T]] - } + // This is reused for all calls to empty. + private val EmptyWrappedArray = new ofRef[AnyRef](new Array[AnyRef](0)) + def empty[T <: AnyRef]: WrappedArray[T] = EmptyWrappedArray.asInstanceOf[WrappedArray[T]] + + // If make is called explicitly we use whatever we're given, even if it's + // empty. This may be unnecesssary (if WrappedArray is to honor the collections + // contract all empty ones must be equal, so discriminating based on the reference + // equality of an empty array should not come up) but we may as well be + // conservative since wrapRefArray contributes most of the unnecessary allocations. + def make[T](x: AnyRef): WrappedArray[T] = (x match { + case null => null + case x: Array[AnyRef] => new ofRef[AnyRef](x) + case x: Array[Int] => new ofInt(x) + case x: Array[Double] => new ofDouble(x) + case x: Array[Long] => new ofLong(x) + case x: Array[Float] => new ofFloat(x) + case x: Array[Char] => new ofChar(x) + case x: Array[Byte] => new ofByte(x) + case x: Array[Short] => new ofShort(x) + case x: Array[Boolean] => new ofBoolean(x) + case x: Array[Unit] => new ofUnit(x) + }).asInstanceOf[WrappedArray[T]] implicit def canBuildFrom[T](implicit m: ClassManifest[T]): CanBuildFrom[WrappedArray[_], T, WrappedArray[T]] = new CanBuildFrom[WrappedArray[_], T, WrappedArray[T]] { -- cgit v1.2.3