From 36ef5c374a11f881cb77bcb784af7b52483ee646 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Fri, 27 Jun 2014 19:23:37 -0700 Subject: [PATCH] SI-8638 Empty UnrolledBuffer hangs on prepend. Tracked down bug to incorrect recursion in insertAll. Fixed by adding a missing case (which incidentally will provide better performance when adding to the end of a block). No specific tests, as this is caught by quasi-complete collections tests. --- .../collection/mutable/UnrolledBuffer.scala | 48 +++++++++++-------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/library/scala/collection/mutable/UnrolledBuffer.scala b/src/library/scala/collection/mutable/UnrolledBuffer.scala index 1f89199bdcd9..693c47d86ecd 100644 --- a/src/library/scala/collection/mutable/UnrolledBuffer.scala +++ b/src/library/scala/collection/mutable/UnrolledBuffer.scala @@ -300,27 +300,33 @@ object UnrolledBuffer extends ClassTagTraversableFactory[UnrolledBuffer] { if (next eq null) true else false // checks if last node was thrown out } else false - @tailrec final def insertAll(idx: Int, t: scala.collection.Traversable[T], buffer: UnrolledBuffer[T]): Unit = if (idx < size) { - // divide this node at the appropriate position and insert all into head - // update new next - val newnextnode = new Unrolled[T](0, new Array(array.length), null, buff) - Array.copy(array, idx, newnextnode.array, 0, size - idx) - newnextnode.size = size - idx - newnextnode.next = next - - // update this - nullout(idx, size) - size = idx - next = null - - // insert everything from iterable to this - var curr = this - for (elem <- t) curr = curr append elem - curr.next = newnextnode - - // try to merge the last node of this with the newnextnode - if (curr.tryMergeWithNext()) buffer.lastPtr = curr - } else insertAll(idx - size, t, buffer) + @tailrec final def insertAll(idx: Int, t: scala.collection.Traversable[T], buffer: UnrolledBuffer[T]): Unit = { + if (idx < size) { + // divide this node at the appropriate position and insert all into head + // update new next + val newnextnode = new Unrolled[T](0, new Array(array.length), null, buff) + Array.copy(array, idx, newnextnode.array, 0, size - idx) + newnextnode.size = size - idx + newnextnode.next = next + + // update this + nullout(idx, size) + size = idx + next = null + + // insert everything from iterable to this + var curr = this + for (elem <- t) curr = curr append elem + curr.next = newnextnode + + // try to merge the last node of this with the newnextnode + if (curr.tryMergeWithNext()) buffer.lastPtr = curr + } + else if (idx == size) { + var curr = this + for (elem <- t) curr = curr append elem + } else insertAll(idx - size, t, buffer) + } private def nullout(from: Int, until: Int) { var idx = from while (idx < until) {