Skip to content

Commit

Permalink
Avoids the creation of an amazing 106,700,793 e...
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
paulp committed Jan 5, 2011
1 parent 6915e7e commit fdb1e69
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 14 deletions.
13 changes: 11 additions & 2 deletions src/library/scala/LowPriorityImplicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
34 changes: 22 additions & 12 deletions src/library/scala/collection/mutable/WrappedArray.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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]] {
Expand Down

0 comments on commit fdb1e69

Please sign in to comment.