@@ -290,51 +290,30 @@ final class Vector[+A] private[immutable] (private[collection] val startIndex: I
290290 dropRight(1 )
291291 }
292292
293- override def appendedAll [B >: A ](suffix : collection.IterableOnce [B ]): Vector [B ] =
294- suffix match {
295- case v : Vector [B ] =>
296- val thisLength = this .length
297- val thatLength = v.length
298- if (thisLength == 0 ) v
299- else if (thatLength == 0 ) this
300- else if (thatLength <= Vector .TinyAppendFaster ) {
301- // Often it's better to append small numbers of elements (or prepend if RHS is a vector)
302- var v0 : Vector [B ] = this
303- var i = 0
304- while (i < thatLength) {
305- v0 = v0.appended(v(i))
306- i += 1
307- }
308- v0
309- } else {
310- if (thisLength < (thatLength >>> Vector .Log2ConcatFaster )) {
311- var v0 = v
312- val iter = this .reverseIterator
313- while (iter.hasNext) {
314- v0 = iter.next() +: v0
315- }
316- v0
317- } else {
318- new VectorBuilder [B ]().addAll(this ).addAll(suffix).result()
319- }
320- }
321- case _ =>
322- val thatKnownSize = suffix.knownSize
323- if (thatKnownSize == 0 ) this
324- else if (thatKnownSize > 0 && thatKnownSize <= Vector .TinyAppendFaster ) {
325- var v0 : Vector [B ] = this
326- val iter = suffix.iterator
327- while (iter.hasNext) {
328- v0 = v0.appended(iter.next())
293+ // appendAll (suboptimal but avoids worst performance gotchas)
294+ override def appendedAll [B >: A ](suffix : collection.IterableOnce [B ]): Vector [B ] = {
295+ import Vector .{Log2ConcatFaster , TinyAppendFaster }
296+ if (suffix.iterator.isEmpty) this
297+ else {
298+ suffix match {
299+ case suffix : collection.Iterable [B ] =>
300+ suffix.size match {
301+ // Often it's better to append small numbers of elements (or prepend if RHS is a vector)
302+ case n if n <= TinyAppendFaster || n < (this .size >>> Log2ConcatFaster ) =>
303+ var v : Vector [B ] = this
304+ for (x <- suffix) v = v :+ x
305+ v
306+ case n if this .size < (n >>> Log2ConcatFaster ) && suffix.isInstanceOf [Vector [_]] =>
307+ var v = suffix.asInstanceOf [Vector [B ]]
308+ val ri = this .reverseIterator
309+ while (ri.hasNext) v = ri.next() +: v
310+ v
311+ case _ => super .appendedAll(suffix)
329312 }
330- v0
331- } else {
332- val iter = suffix.iterator
333- if (iter.hasNext) {
334- new VectorBuilder [B ]().addAll(this ).addAll(suffix).result()
335- } else this
336- }
313+ case _ => super .appendedAll(suffix)
314+ }
337315 }
316+ }
338317
339318 override def prependedAll [B >: A ](prefix : collection.IterableOnce [B ]): Vector [B ] = {
340319 // Implementation similar to `appendAll`: when of the collections to concatenate (either `this` or `prefix`)
@@ -851,21 +830,10 @@ final class VectorBuilder[A]() extends ReusableBuilder[A, Vector[A]] with Vector
851830 display0 = new Array [AnyRef ](32 )
852831 depth = 1
853832
854- /** The index within the final Vector of `this.display0(0)` */
855833 private [this ] var blockIndex = 0
856- /** The index within `this.display0` which is the next available index to write to.
857- * This value may be equal to display0.length, in which case before writing, a new block
858- * should be created (see advanceToNextBlockIfNecessary)*/
859834 private [this ] var lo = 0
860- /** Indicates an offset of the final vector from the actual underlying array elements. This is
861- * used for example in `drop(1)` where instead of copying the entire Vector, only the startIndex is changed.
862- *
863- * This is present in the Builder because we may be able to share structure with a Vector that is `addAll`'d to this.
864- * In which case we must track that Vector's startIndex offset.
865- * */
866- private [this ] var startIndex = 0
867-
868- def size : Int = (blockIndex & ~ 31 ) + lo - startIndex
835+
836+ def size : Int = blockIndex + lo
869837 def isEmpty : Boolean = size == 0
870838 def nonEmpty : Boolean = size != 0
871839
@@ -888,49 +856,10 @@ final class VectorBuilder[A]() extends ReusableBuilder[A, Vector[A]] with Vector
888856 }
889857
890858 override def addAll (xs : IterableOnce [A ]): this .type = {
891-
892- xs match {
893- case v : Vector [A ] if this .isEmpty && v.length >= 32 =>
894- depth = v.depth
895- blockIndex = (v.endIndex - 1 ) & ~ 31
896- lo = v.endIndex - blockIndex
897- startIndex = v.startIndex
898-
899- /** `initFrom` will overwrite display0. Keep reference to it so we can reuse the array.*/
900- val initialDisplay0 = display0
901- initFrom(v)
902- stabilize(v.focus)
903- gotoPosWritable1(v.focus, blockIndex, v.focus ^ blockIndex, initialDisplay0)
904-
905- depth match {
906- case 2 =>
907- display1((blockIndex >>> 5 ) & 31 ) = display0
908- case 3 =>
909- display1((blockIndex >>> 5 ) & 31 ) = display0
910- display2((blockIndex >>> 10 ) & 31 ) = display1
911- case 4 =>
912- display1((blockIndex >>> 5 ) & 31 ) = display0
913- display2((blockIndex >>> 10 ) & 31 ) = display1
914- display3((blockIndex >>> 15 ) & 31 ) = display2
915- case 5 =>
916- display1((blockIndex >>> 5 ) & 31 ) = display0
917- display2((blockIndex >>> 10 ) & 31 ) = display1
918- display3((blockIndex >>> 15 ) & 31 ) = display2
919- display4((blockIndex >>> 20 ) & 31 ) = display3
920- case 6 =>
921- display1((blockIndex >>> 5 ) & 31 ) = display0
922- display2((blockIndex >>> 10 ) & 31 ) = display1
923- display3((blockIndex >>> 15 ) & 31 ) = display2
924- display4((blockIndex >>> 20 ) & 31 ) = display3
925- display5((blockIndex >>> 25 ) & 31 ) = display4
926- case _ => ()
927- }
928- case _ =>
929- val it = (xs.iterator : Iterator [A ]).asInstanceOf [Iterator [AnyRef ]]
930- while (it.hasNext) {
931- advanceToNextBlockIfNecessary()
932- lo += it.copyToArray(xs = display0, start = lo, len = display0.length - lo)
933- }
859+ val it = (xs.iterator : Iterator [A ]).asInstanceOf [Iterator [AnyRef ]]
860+ while (it.hasNext) {
861+ advanceToNextBlockIfNecessary()
862+ lo += it.copyToArray(xs = display0, start = lo, len = display0.length - lo)
934863 }
935864 this
936865 }
@@ -939,9 +868,9 @@ final class VectorBuilder[A]() extends ReusableBuilder[A, Vector[A]] with Vector
939868 val size = this .size
940869 if (size == 0 )
941870 return Vector .empty
942- val s = new Vector [A ](startIndex, blockIndex + lo , 0 ) // should focus front or back?
871+ val s = new Vector [A ](0 , size , 0 ) // should focus front or back?
943872 s.initFrom(this )
944- if (depth > 1 ) s.gotoPos(startIndex, blockIndex + lo - 1 ) // we're currently focused to size - 1, not size!
873+ if (depth > 1 ) s.gotoPos(0 , size - 1 ) // we're currently focused to size - 1, not size!
945874 releaseFence()
946875 s
947876 }
@@ -951,7 +880,6 @@ final class VectorBuilder[A]() extends ReusableBuilder[A, Vector[A]] with Vector
951880 display0 = new Array [AnyRef ](32 )
952881 blockIndex = 0
953882 lo = 0
954- startIndex = 0
955883 }
956884}
957885
@@ -1147,19 +1075,10 @@ private[immutable] trait VectorPointer[+T] {
11471075
11481076 // STUFF BELOW USED BY APPEND / UPDATE
11491077
1150- /** Sets array(index) to null and returns an array with same contents as what was previously at array(index)
1151- *
1152- * If `destination` array is not null, original contents of array(index) will be copied to it, and it will be returned.
1153- * Otherwise array(index).clone() is returned
1154- */
1155- private [immutable] final def nullSlotAndCopy [T <: AnyRef ](array : Array [Array [T ]], index : Int , destination : Array [T ] = null ): Array [T ] = {
1078+ private [immutable] final def nullSlotAndCopy [T <: AnyRef ](array : Array [Array [T ]], index : Int ): Array [T ] = {
11561079 val x = array(index)
11571080 array(index) = null
1158- if (destination == null ) x.clone()
1159- else {
1160- x.copyToArray(destination, 0 )
1161- destination
1162- }
1081+ x.clone()
11631082 }
11641083
11651084 // make sure there is no aliasing
@@ -1242,9 +1161,10 @@ private[immutable] trait VectorPointer[+T] {
12421161 display0 = display0.clone()
12431162 }
12441163
1164+
12451165 // requires structure is dirty and at pos oldIndex,
12461166 // ensures structure is dirty and at pos newIndex and writable at level 0
1247- private [immutable] final def gotoPosWritable1 (oldIndex : Int , newIndex : Int , xor : Int , reuseDisplay0 : Array [ AnyRef ] = null ): Unit = {
1167+ private [immutable] final def gotoPosWritable1 (oldIndex : Int , newIndex : Int , xor : Int ): Unit = {
12481168 if (xor < (1 << 5 )) { // level = 0
12491169 display0 = display0.clone()
12501170 } else if (xor < (1 << 10 )) { // level = 1
@@ -1257,7 +1177,7 @@ private[immutable] trait VectorPointer[+T] {
12571177 display1((oldIndex >>> 5 ) & 31 ) = display0
12581178 display2((oldIndex >>> 10 ) & 31 ) = display1
12591179 display1 = nullSlotAndCopy(display2, (newIndex >>> 10 ) & 31 )
1260- display0 = nullSlotAndCopy(display1, (newIndex >>> 5 ) & 31 , reuseDisplay0 )
1180+ display0 = nullSlotAndCopy(display1, (newIndex >>> 5 ) & 31 )
12611181 } else if (xor < (1 << 20 )) { // level = 3
12621182 display1 = display1.clone()
12631183 display2 = display2.clone()
@@ -1267,7 +1187,7 @@ private[immutable] trait VectorPointer[+T] {
12671187 display3((oldIndex >>> 15 ) & 31 ) = display2
12681188 display2 = nullSlotAndCopy(display3, (newIndex >>> 15 ) & 31 )
12691189 display1 = nullSlotAndCopy(display2, (newIndex >>> 10 ) & 31 )
1270- display0 = nullSlotAndCopy(display1, (newIndex >>> 5 ) & 31 , reuseDisplay0 )
1190+ display0 = nullSlotAndCopy(display1, (newIndex >>> 5 ) & 31 )
12711191 } else if (xor < (1 << 25 )) { // level = 4
12721192 display1 = display1.clone()
12731193 display2 = display2.clone()
@@ -1280,7 +1200,7 @@ private[immutable] trait VectorPointer[+T] {
12801200 display3 = nullSlotAndCopy(display4, (newIndex >>> 20 ) & 31 )
12811201 display2 = nullSlotAndCopy(display3, (newIndex >>> 15 ) & 31 )
12821202 display1 = nullSlotAndCopy(display2, (newIndex >>> 10 ) & 31 )
1283- display0 = nullSlotAndCopy(display1, (newIndex >>> 5 ) & 31 , reuseDisplay0 )
1203+ display0 = nullSlotAndCopy(display1, (newIndex >>> 5 ) & 31 )
12841204 } else if (xor < (1 << 30 )) { // level = 5
12851205 display1 = display1.clone()
12861206 display2 = display2.clone()
@@ -1296,7 +1216,7 @@ private[immutable] trait VectorPointer[+T] {
12961216 display3 = nullSlotAndCopy(display4, (newIndex >>> 20 ) & 31 )
12971217 display2 = nullSlotAndCopy(display3, (newIndex >>> 15 ) & 31 )
12981218 display1 = nullSlotAndCopy(display2, (newIndex >>> 10 ) & 31 )
1299- display0 = nullSlotAndCopy(display1, (newIndex >>> 5 ) & 31 , reuseDisplay0 )
1219+ display0 = nullSlotAndCopy(display1, (newIndex >>> 5 ) & 31 )
13001220 } else { // level = 6
13011221 throw new IllegalArgumentException ()
13021222 }
0 commit comments