From 0dd6ec7c5be9004eefa6b38938a621a5b55c2490 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Mon, 11 Nov 2019 22:10:38 +0100 Subject: [PATCH 01/32] Add benchmarks for map and zip --- bench-run/inputs/map.in | 1 + bench-run/inputs/zip.in | 1 + bench-run/src/main/scala/tuples/Map.scala | 40 +++++++++++++++++++++++ bench-run/src/main/scala/tuples/Zip.scala | 38 +++++++++++++++++++++ 4 files changed, 80 insertions(+) create mode 100644 bench-run/inputs/map.in create mode 100644 bench-run/inputs/zip.in create mode 100644 bench-run/src/main/scala/tuples/Map.scala create mode 100644 bench-run/src/main/scala/tuples/Zip.scala diff --git a/bench-run/inputs/map.in b/bench-run/inputs/map.in new file mode 100644 index 000000000000..4555a56acbc3 --- /dev/null +++ b/bench-run/inputs/map.in @@ -0,0 +1 @@ +size:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50 diff --git a/bench-run/inputs/zip.in b/bench-run/inputs/zip.in new file mode 100644 index 000000000000..4555a56acbc3 --- /dev/null +++ b/bench-run/inputs/zip.in @@ -0,0 +1 @@ +size:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50 diff --git a/bench-run/src/main/scala/tuples/Map.scala b/bench-run/src/main/scala/tuples/Map.scala new file mode 100644 index 000000000000..9b3807355087 --- /dev/null +++ b/bench-run/src/main/scala/tuples/Map.scala @@ -0,0 +1,40 @@ +package dotty.tools.benchmarks.tuples + +import org.openjdk.jmh.annotations._ +import scala.runtime.DynamicTuple + +@State(Scope.Thread) +class Map { + @Param(Array("0")) + var size: Int = _ + var tuple: Tuple = _ + var array: Array[Object] = _ + + @Setup + def setup(): Unit = { + tuple = () + + for (i <- 1 to size) + tuple = "elem" *: tuple + + array = Array.fill(size)("elem") + } + + def f: PolyFunction = new PolyFunction { + def apply[T](x: T): T = { + x.asInstanceOf[String].updated(0, 'a').asInstanceOf[T] + } + } + + type Id[X] = X + + @Benchmark + def tupleMap(): Tuple = { + DynamicTuple.dynamicMap[Tuple, Id](tuple, [T] => (x:T) => x.asInstanceOf[String].updated(0, 'a').asInstanceOf[T]) + } + + @Benchmark + def arrayMap(): Array[Object] = { + array.map(x => x.asInstanceOf[String].updated(0, 'a')) + } +} diff --git a/bench-run/src/main/scala/tuples/Zip.scala b/bench-run/src/main/scala/tuples/Zip.scala new file mode 100644 index 000000000000..1b95922a01f9 --- /dev/null +++ b/bench-run/src/main/scala/tuples/Zip.scala @@ -0,0 +1,38 @@ +package dotty.tools.benchmarks.tuples + +import org.openjdk.jmh.annotations._ +import scala.runtime.DynamicTuple + +@State(Scope.Thread) +class Zip { + @Param(Array("0")) + var size: Int = _ + var tuple1: Tuple = _ + var tuple2: Tuple = _ + var array1: Array[Object] = _ + var array2: Array[Object] = _ + + @Setup + def setup(): Unit = { + tuple1 = () + tuple2 = () + + for (i <- 1 to size) { + tuple1 = "el" *: tuple1 + tuple2 = "em" *: tuple2 + } + + array1 = Array.fill(size)("el") + array2 = Array.fill(size)("em") + } + + @Benchmark + def tupleZip(): Tuple = { + DynamicTuple.dynamicZip(tuple1, tuple2) + } + + @Benchmark + def arrayZip(): Array[(Object, Object)] = { + array1.zip(array2) + } +} From 57177ba60fc1871bbb75561c931aee562734e181 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Sat, 12 Oct 2019 16:15:35 +0200 Subject: [PATCH 02/32] Kept the improvments from tuple-tweaks-01 --- .../dotty/tools/benchmarks/tuples/Concat.scala | 2 +- .../tuples/{ArrayOps.scala => Conversions.scala} | 0 library/src/scala/runtime/DynamicTuple.scala | 15 +++++++++++++-- 3 files changed, 14 insertions(+), 3 deletions(-) rename bench-run/src/main/scala/dotty/tools/benchmarks/tuples/{ArrayOps.scala => Conversions.scala} (100%) diff --git a/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Concat.scala b/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Concat.scala index 4f216f3db9d6..e645145fb5d7 100644 --- a/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Concat.scala +++ b/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Concat.scala @@ -37,6 +37,6 @@ class Concat { @Benchmark def arrayConcat(): Array[Object] = { - array1 ++ array2 + DynamicTuple.concat$Array(array1, array2) } } diff --git a/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/ArrayOps.scala b/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Conversions.scala similarity index 100% rename from bench-run/src/main/scala/dotty/tools/benchmarks/tuples/ArrayOps.scala rename to bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Conversions.scala diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index 53d44f75d449..28096cbfe2f6 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -24,6 +24,13 @@ object DynamicTuple { elems1 } + def concat$Array(a1: Array[Object], a2: Array[Object]): Array[Object] = { + val result = new Array[Object](a1.length + a2.length) + System.arraycopy(a1, 0, result, 0, a1.length) + System.arraycopy(a2, 0, result, a1.length, a2.length) + result + } + def dynamicFromArray[T <: Tuple](xs: Array[Object]): T = xs.length match { case 0 => ().asInstanceOf[T] case 1 => Tuple1(xs(0)).asInstanceOf[T] @@ -188,7 +195,11 @@ object DynamicTuple { def productToArray(self: Product): Array[Object] = { val arr = new Array[Object](self.productArity) - for (i <- 0 until arr.length) arr(i) = self.productElement(i).asInstanceOf[Object] + var i = 0 + while (i < arr.length) { + arr(i) = self.productElement(i).asInstanceOf[Object] + i += 1 + } arr } @@ -220,7 +231,7 @@ object DynamicTuple { case that: Unit => return self.asInstanceOf[Result] case _ => } - dynamicFromArray[Result](dynamicToArray(self) ++ dynamicToArray(that)) + dynamicFromArray[Result](concat$Array(dynamicToArray(self), dynamicToArray(that))) } def dynamicSize[This <: Tuple](self: This): Size[This] = (self: Any) match { From 45044d357528976a9e386390040b901ddf177423 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Sun, 13 Oct 2019 09:44:57 +0200 Subject: [PATCH 03/32] Rename class for consistency --- .../main/scala/dotty/tools/benchmarks/tuples/Conversions.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Conversions.scala b/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Conversions.scala index bef4a99a3d46..e2e64d85df76 100644 --- a/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Conversions.scala +++ b/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Conversions.scala @@ -4,7 +4,7 @@ import org.openjdk.jmh.annotations._ import scala.runtime.DynamicTuple @State(Scope.Thread) -class ArrayOps { +class Conversions { @Param(Array("1")) var size: Int = _ var tuple: Tuple = _ From 1dc402798161c1688934c6aea44940b63e265e0d Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Wed, 16 Oct 2019 14:40:02 +0200 Subject: [PATCH 04/32] Special cased dynamicCons and dynamicTail --- library/src/scala/runtime/DynamicTuple.scala | 97 ++++++++++++++++++-- 1 file changed, 87 insertions(+), 10 deletions(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index 28096cbfe2f6..ab117775ad0f 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -205,20 +205,57 @@ object DynamicTuple { def dynamicCons[H, This <: Tuple](x: H, self: Tuple): H *: This = { type Result = H *: This - (self: Any) match { + val res = (self: Any) match { case () => - Tuple1(x).asInstanceOf[Result] + Tuple1(x) case self: Tuple1[_] => - Tuple2(x, self._1).asInstanceOf[Result] + Tuple2(x, self._1) case self: Tuple2[_, _] => - Tuple3(x, self._1, self._2).asInstanceOf[Result] + Tuple3(x, self._1, self._2) case self: Tuple3[_, _, _] => - Tuple4(x, self._1, self._2, self._3).asInstanceOf[Result] + Tuple4(x, self._1, self._2, self._3) case self: Tuple4[_, _, _, _] => - Tuple5(x, self._1, self._2, self._3, self._4).asInstanceOf[Result] + Tuple5(x, self._1, self._2, self._3, self._4) + case self: Tuple5[_, _, _, _, _] => + Tuple6(x, self._1, self._2, self._3, self._4, self._5) + case self: Tuple6[_, _, _, _, _, _] => + Tuple7(x, self._1, self._2, self._3, self._4, self._5, self._6) + case self: Tuple7[_, _, _, _, _, _, _] => + Tuple8(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7) + case self: Tuple8[_, _, _, _, _, _, _, _] => + Tuple9(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8) + case self: Tuple9[_, _, _, _, _, _, _, _, _] => + Tuple10(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9) + case self: Tuple10[_, _, _, _, _, _, _, _, _, _] => + Tuple11(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10) + case self: Tuple11[_, _, _, _, _, _, _, _, _, _, _] => + Tuple12(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11) + case self: Tuple12[_, _, _, _, _, _, _, _, _, _, _, _] => + Tuple13(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12) + case self: Tuple13[_, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple14(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13) + case self: Tuple14[_, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple15(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14) + case self: Tuple15[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple16(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15) + case self: Tuple16[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple17(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16) + case self: Tuple17[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple18(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17) + case self: Tuple18[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple19(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18) + case self: Tuple19[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple20(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19) + case self: Tuple20[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple21(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20) + case self: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple22(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21) + case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + TupleXXL.fromIArray(Array(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21, self._22)) case _ => dynamicFromArray[Result](cons$Array(x, dynamicToArray(self))) } + res.asInstanceOf[Result] } def dynamicConcat[This <: Tuple, That <: Tuple](self: This, that: That): Concat[This, That] = { @@ -242,10 +279,50 @@ object DynamicTuple { def dynamicTail[This <: NonEmptyTuple] (self: This): Tail[This] = { type Result = Tail[This] val res = (self: Any) match { - case self: Tuple1[_] => () - case self: Tuple2[_, _] => Tuple1(self._2) - case self: Tuple3[_, _, _] => Tuple2(self._2, self._3) - case self: Tuple4[_, _, _, _] => Tuple3(self._2, self._3, self._4) + case self: Tuple1[_] => + () + case self: Tuple2[_, _] => + Tuple1(self._2) + case self: Tuple3[_, _, _] => + Tuple2(self._2, self._3) + case self: Tuple4[_, _, _, _] => + Tuple3(self._2, self._3, self._4) + case self: Tuple5[_, _, _, _, _] => + Tuple4(self._2, self._3, self._4, self._5) + case self: Tuple6[_, _, _, _, _, _] => + Tuple5(self._2, self._3, self._4, self._5, self._6) + case self: Tuple7[_, _, _, _, _, _, _] => + Tuple6(self._2, self._3, self._4, self._5, self._6, self._7) + case self: Tuple8[_, _, _, _, _, _, _, _] => + Tuple7(self._2, self._3, self._4, self._5, self._6, self._7, self._8) + case self: Tuple9[_, _, _, _, _, _, _, _, _] => + Tuple8(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9) + case self: Tuple10[_, _, _, _, _, _, _, _, _, _] => + Tuple9(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10) + case self: Tuple11[_, _, _, _, _, _, _, _, _, _, _] => + Tuple10(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11) + case self: Tuple12[_, _, _, _, _, _, _, _, _, _, _, _] => + Tuple11(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12) + case self: Tuple13[_, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple12(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13) + case self: Tuple14[_, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple13(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14) + case self: Tuple15[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple14(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15) + case self: Tuple16[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple15(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16) + case self: Tuple17[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple16(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17) + case self: Tuple18[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple17(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18) + case self: Tuple19[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple18(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19) + case self: Tuple20[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple19(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20) + case self: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple20(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21) + case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple21(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21, self._22) case _ => dynamicFromArray[Result](dynamicToArray(self).tail) } res.asInstanceOf[Result] From 9fd94e57d5438164328941959c35d96762c48327 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Thu, 17 Oct 2019 22:14:29 +0200 Subject: [PATCH 05/32] Special cased some more code --- library/src/scala/runtime/DynamicTuple.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index ab117775ad0f..c3560e683055 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -251,7 +251,7 @@ object DynamicTuple { case self: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => Tuple22(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21) case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - TupleXXL.fromIArray(Array(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21, self._22)) + TupleXXL.fromIArray(Array(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21, self._22).asInstanceOf[IArray[Object]]) case _ => dynamicFromArray[Result](cons$Array(x, dynamicToArray(self))) } From 5e32838bfb9d1959e38dcd3cdff386ad36130336 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Wed, 23 Oct 2019 20:49:27 +0200 Subject: [PATCH 06/32] Improve tuple cons by removing a useless array copy --- library/src/scala/runtime/DynamicTuple.scala | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index c3560e683055..4bd6cd7a9069 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -6,15 +6,13 @@ object DynamicTuple { inline val MaxSpecialized = 22 inline private val XXL = MaxSpecialized + 1 - def to$Array(xs: Tuple, n: Int) = { - val arr = new Array[Object](n) + def to$Array(xs: Tuple, n: Int, arr: Array[Object], offset: Int): Unit = { var i = 0 var it = xs.asInstanceOf[Product].productIterator while (i < n) { - arr(i) = it.next().asInstanceOf[Object] + arr(offset + i) = it.next().asInstanceOf[Object] i += 1 } - arr } def cons$Array[H](x: H, elems: Array[Object]): Array[Object] = { @@ -253,7 +251,10 @@ object DynamicTuple { case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => TupleXXL.fromIArray(Array(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21, self._22).asInstanceOf[IArray[Object]]) case _ => - dynamicFromArray[Result](cons$Array(x, dynamicToArray(self))) + val arr = new Array[Object](self.size) + to$Array(self, self.size, arr, 1) + arr(0) = x.asInstanceOf[Object] + TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]) } res.asInstanceOf[Result] } From 0d0735cb6259486ac6ef8793d4399401a0de0250 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Thu, 24 Oct 2019 21:36:01 +0200 Subject: [PATCH 07/32] Fix invalid size in DynamicCons --- library/src/scala/runtime/DynamicTuple.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index 4bd6cd7a9069..04cc8041841c 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -251,7 +251,7 @@ object DynamicTuple { case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => TupleXXL.fromIArray(Array(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21, self._22).asInstanceOf[IArray[Object]]) case _ => - val arr = new Array[Object](self.size) + val arr = new Array[Object](self.size + 1) to$Array(self, self.size, arr, 1) arr(0) = x.asInstanceOf[Object] TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]) From 2fdc0d4881df42988f275bbe7b620c0a4421d8a5 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Sun, 3 Nov 2019 10:28:34 +0100 Subject: [PATCH 08/32] Remove the tuple22 special case from tupleCons --- library/src/scala/runtime/DynamicTuple.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index 04cc8041841c..e965205b1bd2 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -248,8 +248,6 @@ object DynamicTuple { Tuple21(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20) case self: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => Tuple22(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21) - case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - TupleXXL.fromIArray(Array(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21, self._22).asInstanceOf[IArray[Object]]) case _ => val arr = new Array[Object](self.size + 1) to$Array(self, self.size, arr, 1) From 3090540d09eb3f87e4f4eaa58765def33eb403a2 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Mon, 4 Nov 2019 08:18:00 +0100 Subject: [PATCH 09/32] Report the changes of tupleCons to tupleConcat and tupleTail --- library/src/scala/runtime/DynamicTuple.scala | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index e965205b1bd2..439d8baf546c 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -6,9 +6,8 @@ object DynamicTuple { inline val MaxSpecialized = 22 inline private val XXL = MaxSpecialized + 1 - def to$Array(xs: Tuple, n: Int, arr: Array[Object], offset: Int): Unit = { + def to$Array(it: Iterator[Any], n: Int, arr: Array[Object], offset: Int): Unit = { var i = 0 - var it = xs.asInstanceOf[Product].productIterator while (i < n) { arr(offset + i) = it.next().asInstanceOf[Object] i += 1 @@ -250,7 +249,7 @@ object DynamicTuple { Tuple22(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21) case _ => val arr = new Array[Object](self.size + 1) - to$Array(self, self.size, arr, 1) + to$Array(self.asInstanceOf[Product].productIterator, self.size, arr, 1) arr(0) = x.asInstanceOf[Object] TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]) } @@ -267,7 +266,10 @@ object DynamicTuple { case that: Unit => return self.asInstanceOf[Result] case _ => } - dynamicFromArray[Result](concat$Array(dynamicToArray(self), dynamicToArray(that))) + val arr = new Array[Object](self.size + that.size) + to$Array(self.asInstanceOf[Product].productIterator, self.size, arr, 0) + to$Array(that.asInstanceOf[Product].productIterator, that.size, arr, self.size) + TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] } def dynamicSize[This <: Tuple](self: This): Size[This] = (self: Any) match { @@ -322,7 +324,12 @@ object DynamicTuple { Tuple20(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21) case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => Tuple21(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21, self._22) - case _ => dynamicFromArray[Result](dynamicToArray(self).tail) + case _ => + val arr = new Array[Object](self.size - 1) + val it = self.asInstanceOf[Product].productIterator + it.next() + to$Array(it, self.size - 1, arr, 0) + TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]) } res.asInstanceOf[Result] } From bfde674afc1561735050e43ae4cdbe3a01d595ca Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Mon, 4 Nov 2019 10:58:29 +0100 Subject: [PATCH 10/32] Fix error in DynamicTuple --- library/src/scala/runtime/DynamicTuple.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index 439d8baf546c..b5513abccaa9 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -251,7 +251,7 @@ object DynamicTuple { val arr = new Array[Object](self.size + 1) to$Array(self.asInstanceOf[Product].productIterator, self.size, arr, 1) arr(0) = x.asInstanceOf[Object] - TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]) + dynamicFromIArray(arr.asInstanceOf[IArray[Object]]) } res.asInstanceOf[Result] } @@ -269,7 +269,7 @@ object DynamicTuple { val arr = new Array[Object](self.size + that.size) to$Array(self.asInstanceOf[Product].productIterator, self.size, arr, 0) to$Array(that.asInstanceOf[Product].productIterator, that.size, arr, self.size) - TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] + dynamicFromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] } def dynamicSize[This <: Tuple](self: This): Size[This] = (self: Any) match { @@ -329,7 +329,7 @@ object DynamicTuple { val it = self.asInstanceOf[Product].productIterator it.next() to$Array(it, self.size - 1, arr, 0) - TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]) + dynamicFromIArray(arr.asInstanceOf[IArray[Object]]) } res.asInstanceOf[Result] } From bf81b5dc545485f9a42cec6b3dc7dc182c9e9dce Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Mon, 4 Nov 2019 11:38:48 +0100 Subject: [PATCH 11/32] Fix a problem with parameter type in dynamicCons --- library/src/scala/runtime/DynamicTuple.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index b5513abccaa9..6d9baa3f8736 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -200,7 +200,7 @@ object DynamicTuple { arr } - def dynamicCons[H, This <: Tuple](x: H, self: Tuple): H *: This = { + def dynamicCons[H, This <: Tuple](x: H, self: This): H *: This = { type Result = H *: This val res = (self: Any) match { case () => @@ -251,7 +251,7 @@ object DynamicTuple { val arr = new Array[Object](self.size + 1) to$Array(self.asInstanceOf[Product].productIterator, self.size, arr, 1) arr(0) = x.asInstanceOf[Object] - dynamicFromIArray(arr.asInstanceOf[IArray[Object]]) + dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) } res.asInstanceOf[Result] } @@ -269,7 +269,7 @@ object DynamicTuple { val arr = new Array[Object](self.size + that.size) to$Array(self.asInstanceOf[Product].productIterator, self.size, arr, 0) to$Array(that.asInstanceOf[Product].productIterator, that.size, arr, self.size) - dynamicFromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] + dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] } def dynamicSize[This <: Tuple](self: This): Size[This] = (self: Any) match { @@ -329,7 +329,7 @@ object DynamicTuple { val it = self.asInstanceOf[Product].productIterator it.next() to$Array(it, self.size - 1, arr, 0) - dynamicFromIArray(arr.asInstanceOf[IArray[Object]]) + dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) } res.asInstanceOf[Result] } From fc6a694c5033afde16c89fed61224ff73200ad4f Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Tue, 5 Nov 2019 11:48:34 +0100 Subject: [PATCH 12/32] Use iterators concatenation --- library/src/scala/runtime/DynamicTuple.scala | 49 +++++++++++++++----- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index 6d9baa3f8736..4c93d7091751 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -28,6 +28,39 @@ object DynamicTuple { result } + def dynamicFromIterator[T <: Tuple](it: Iterator[Object], size: Int): T = size match { + case 1 => Tuple1(it.next()).asInstanceOf[T] + case 2 => Tuple2(it.next(), it.next()).asInstanceOf[T] + case 3 => Tuple3(it.next(), it.next(), it.next()).asInstanceOf[T] + case 4 => Tuple4(it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] + case 5 => Tuple5(it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] + case 6 => Tuple6(it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] + case 7 => Tuple7(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] + case 8 => Tuple8(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] + case 9 => Tuple9(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] + case 10 => Tuple10(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] + case 11 => Tuple11(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] + case 12 => Tuple12(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] + case 13 => Tuple13(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] + case 14 => Tuple14(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] + case 15 => Tuple15(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] + case 16 => Tuple16(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] + case 17 => Tuple17(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] + case 18 => Tuple18(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] + case 19 => Tuple19(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] + case 20 => Tuple20(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] + case 21 => Tuple21(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] + case 22 => Tuple22(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] + case _ => + val arr: Array[Object] = new Array[Object](size) + var i = 0 + while (i < size) { + arr(i) = it.next() + i += 1 + } + TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[T] + } + def dynamicFromArray[T <: Tuple](xs: Array[Object]): T = xs.length match { case 0 => ().asInstanceOf[T] case 1 => Tuple1(xs(0)).asInstanceOf[T] @@ -248,10 +281,7 @@ object DynamicTuple { case self: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => Tuple22(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21) case _ => - val arr = new Array[Object](self.size + 1) - to$Array(self.asInstanceOf[Product].productIterator, self.size, arr, 1) - arr(0) = x.asInstanceOf[Object] - dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) + dynamicFromIterator[Result](consIterator(x, self).asInstanceOf[Iterator[Object]], self.size + 1) } res.asInstanceOf[Result] } @@ -266,10 +296,7 @@ object DynamicTuple { case that: Unit => return self.asInstanceOf[Result] case _ => } - val arr = new Array[Object](self.size + that.size) - to$Array(self.asInstanceOf[Product].productIterator, self.size, arr, 0) - to$Array(that.asInstanceOf[Product].productIterator, that.size, arr, self.size) - dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] + dynamicFromIterator[Result](concatIterator(self, that).asInstanceOf[Iterator[Object]], self.size + that.size) } def dynamicSize[This <: Tuple](self: This): Size[This] = (self: Any) match { @@ -325,11 +352,9 @@ object DynamicTuple { case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => Tuple21(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21, self._22) case _ => - val arr = new Array[Object](self.size - 1) - val it = self.asInstanceOf[Product].productIterator + val it = self.asInstanceOf[Product].productIterator.asInstanceOf[Iterator[Object]] it.next() - to$Array(it, self.size - 1, arr, 0) - dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) + dynamicFromIterator(it, self.size - 1) } res.asInstanceOf[Result] } From 78a3211c8c51025375a03686755b84611103d7c5 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Tue, 5 Nov 2019 22:03:04 +0100 Subject: [PATCH 13/32] Try yet another tweak --- .../tools/benchmarks/tuples/Concat.scala | 7 -- .../dotty/tools/benchmarks/tuples/Cons.scala | 7 -- library/src/scala/runtime/DynamicTuple.scala | 90 +++++++------------ 3 files changed, 33 insertions(+), 71 deletions(-) diff --git a/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Concat.scala b/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Concat.scala index e645145fb5d7..1853b71d2a8b 100644 --- a/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Concat.scala +++ b/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Concat.scala @@ -26,17 +26,10 @@ class Concat { val size2 = sizes.split(' ')(1).toInt tuple1 = tupleOfSize(size1) tuple2 = tupleOfSize(size2) - array1 = Array.fill(size1)("elem") - array2 = Array.fill(size2)("elem") } @Benchmark def tupleConcat(): Tuple = { DynamicTuple.dynamicConcat(tuple1, tuple2) } - - @Benchmark - def arrayConcat(): Array[Object] = { - DynamicTuple.concat$Array(array1, array2) - } } diff --git a/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Cons.scala b/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Cons.scala index ea65e1dcf2ee..f1129bf2383b 100644 --- a/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Cons.scala +++ b/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Cons.scala @@ -16,17 +16,10 @@ class Cons { for (i <- 1 to size) tuple = "elem" *: tuple - - array = Array.fill(size)("elem") } @Benchmark def tupleCons(): Tuple = { DynamicTuple.dynamicCons("elem", tuple) } - - @Benchmark - def arrayCons(): Array[Object] = { - DynamicTuple.cons$Array("elem", array) - } } diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index 4c93d7091751..3a9c834b3b57 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -6,61 +6,14 @@ object DynamicTuple { inline val MaxSpecialized = 22 inline private val XXL = MaxSpecialized + 1 - def to$Array(it: Iterator[Any], n: Int, arr: Array[Object], offset: Int): Unit = { + def itToArray(it: Iterator[Any], size: Int, dest: Array[Object], offset: Int): Unit = { var i = 0 - while (i < n) { - arr(offset + i) = it.next().asInstanceOf[Object] + while (i < size) { + dest(offset + i) = it.next().asInstanceOf[Object] i += 1 } } - def cons$Array[H](x: H, elems: Array[Object]): Array[Object] = { - val elems1 = new Array[Object](elems.length + 1) - elems1(0) = x.asInstanceOf[Object] - System.arraycopy(elems, 0, elems1, 1, elems.length) - elems1 - } - - def concat$Array(a1: Array[Object], a2: Array[Object]): Array[Object] = { - val result = new Array[Object](a1.length + a2.length) - System.arraycopy(a1, 0, result, 0, a1.length) - System.arraycopy(a2, 0, result, a1.length, a2.length) - result - } - - def dynamicFromIterator[T <: Tuple](it: Iterator[Object], size: Int): T = size match { - case 1 => Tuple1(it.next()).asInstanceOf[T] - case 2 => Tuple2(it.next(), it.next()).asInstanceOf[T] - case 3 => Tuple3(it.next(), it.next(), it.next()).asInstanceOf[T] - case 4 => Tuple4(it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] - case 5 => Tuple5(it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] - case 6 => Tuple6(it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] - case 7 => Tuple7(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] - case 8 => Tuple8(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] - case 9 => Tuple9(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] - case 10 => Tuple10(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] - case 11 => Tuple11(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] - case 12 => Tuple12(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] - case 13 => Tuple13(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] - case 14 => Tuple14(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] - case 15 => Tuple15(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] - case 16 => Tuple16(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] - case 17 => Tuple17(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] - case 18 => Tuple18(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] - case 19 => Tuple19(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] - case 20 => Tuple20(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] - case 21 => Tuple21(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] - case 22 => Tuple22(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T] - case _ => - val arr: Array[Object] = new Array[Object](size) - var i = 0 - while (i < size) { - arr(i) = it.next() - i += 1 - } - TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[T] - } - def dynamicFromArray[T <: Tuple](xs: Array[Object]): T = xs.length match { case 0 => ().asInstanceOf[T] case 1 => Tuple1(xs(0)).asInstanceOf[T] @@ -280,8 +233,16 @@ object DynamicTuple { Tuple21(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20) case self: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => Tuple22(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21) - case _ => - dynamicFromIterator[Result](consIterator(x, self).asInstanceOf[Iterator[Object]], self.size + 1) + case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + val arr = new Array[Object](23) + itToArray(self.asInstanceOf[Product].productIterator, 22, arr, 1) + arr(0) = x.asInstanceOf[Object] + dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) + case xxl: TupleXXL => + val arr = new Array[Object](self.size + 1) + System.arraycopy(xxl.elems, 0, arr, 1, self.size) + arr(0) = x.asInstanceOf[Object] + dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) } res.asInstanceOf[Result] } @@ -296,7 +257,22 @@ object DynamicTuple { case that: Unit => return self.asInstanceOf[Result] case _ => } - dynamicFromIterator[Result](concatIterator(self, that).asInstanceOf[Iterator[Object]], self.size + that.size) + + val arr = new Array[Object](self.size + that.size) + + if (self.size <= 22) { + itToArray(self.asInstanceOf[Product].productIterator, self.size, arr, 0) + } else { + System.arraycopy(self.asInstanceOf[TupleXXL].elems, 0, arr, 0, self.size) + } + + if (that.size <= 22) { + itToArray(that.asInstanceOf[Product].productIterator, that.size, arr, 0) + } else { + System.arraycopy(that.asInstanceOf[TupleXXL].elems, 0, arr, self.size, that.size) + } + + dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] } def dynamicSize[This <: Tuple](self: This): Size[This] = (self: Any) match { @@ -351,10 +327,10 @@ object DynamicTuple { Tuple20(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21) case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => Tuple21(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21, self._22) - case _ => - val it = self.asInstanceOf[Product].productIterator.asInstanceOf[Iterator[Object]] - it.next() - dynamicFromIterator(it, self.size - 1) + case xxl: TupleXXL => + val arr = new Array[Object](self.size - 1) + System.arraycopy(xxl.elems, 1, arr, 0, self.size - 1) + dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) } res.asInstanceOf[Result] } From d4e8ebe49667d0a5950768e40611ed1c27477a92 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Wed, 6 Nov 2019 11:29:43 +0100 Subject: [PATCH 14/32] Try to improve the performance in edge cases (n = 22 or n = 23) --- library/src/scala/runtime/DynamicTuple.scala | 58 +++++++++++++++----- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index 3a9c834b3b57..0ae3f02095ff 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -235,14 +235,24 @@ object DynamicTuple { Tuple22(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21) case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => val arr = new Array[Object](23) - itToArray(self.asInstanceOf[Product].productIterator, 22, arr, 1) - arr(0) = x.asInstanceOf[Object] - dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) + arr(0) = x.asInstanceOf[Object]; + arr(1) = self._1.asInstanceOf[Object]; arr(2) = self._2.asInstanceOf[Object]; + arr(3) = self._3.asInstanceOf[Object]; arr(4) = self._4.asInstanceOf[Object]; + arr(5) = self._5.asInstanceOf[Object]; arr(6) = self._6.asInstanceOf[Object]; + arr(7) = self._7.asInstanceOf[Object]; arr(8) = self._8.asInstanceOf[Object]; + arr(9) = self._9.asInstanceOf[Object]; arr(10) = self._10.asInstanceOf[Object]; + arr(11) = self._11.asInstanceOf[Object]; arr(12) = self._12.asInstanceOf[Object]; + arr(13) = self._13.asInstanceOf[Object]; arr(14) = self._14.asInstanceOf[Object]; + arr(15) = self._15.asInstanceOf[Object]; arr(16) = self._16.asInstanceOf[Object]; + arr(17) = self._17.asInstanceOf[Object]; arr(18) = self._18.asInstanceOf[Object]; + arr(19) = self._19.asInstanceOf[Object]; arr(20) = self._20.asInstanceOf[Object]; + arr(21) = self._21.asInstanceOf[Object]; arr(22) = self._22.asInstanceOf[Object]; + TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] case xxl: TupleXXL => - val arr = new Array[Object](self.size + 1) - System.arraycopy(xxl.elems, 0, arr, 1, self.size) + val arr = new Array[Object](xxl.productArity + 1) + System.arraycopy(xxl.elems, 0, arr, 1, xxl.productArity) arr(0) = x.asInstanceOf[Object] - dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) + TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] } res.asInstanceOf[Result] } @@ -253,6 +263,7 @@ object DynamicTuple { case self: Unit => return that.asInstanceOf[Result] case _ => } + (that: Any) match { case that: Unit => return self.asInstanceOf[Result] case _ => @@ -260,16 +271,18 @@ object DynamicTuple { val arr = new Array[Object](self.size + that.size) - if (self.size <= 22) { - itToArray(self.asInstanceOf[Product].productIterator, self.size, arr, 0) - } else { - System.arraycopy(self.asInstanceOf[TupleXXL].elems, 0, arr, 0, self.size) + (self: Any) match { + case xxl: TupleXXL => + System.arraycopy(xxl.elems, 0, arr, 0, self.size) + case _ => + itToArray(self.asInstanceOf[Product].productIterator, self.size, arr, 0) } - if (that.size <= 22) { - itToArray(that.asInstanceOf[Product].productIterator, that.size, arr, 0) - } else { - System.arraycopy(that.asInstanceOf[TupleXXL].elems, 0, arr, self.size, that.size) + (that: Any) match { + case xxl: TupleXXL => + System.arraycopy(xxl.elems, 0, arr, self.size, that.size) + case _ => + itToArray(that.asInstanceOf[Product].productIterator, that.size, arr, 0) } dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] @@ -328,8 +341,23 @@ object DynamicTuple { case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => Tuple21(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21, self._22) case xxl: TupleXXL => + if (xxl.productArity == 23) { + val elems = xxl.elems + Tuple22( + xxl.elems(1), xxl.elems(2), xxl.elems(3), xxl.elems(4), xxl.elems(5), xxl.elems(6), xxl.elems(7), + xxl.elems(8), xxl.elems(9), xxl.elems(10), xxl.elems(11), xxl.elems(12), xxl.elems(13), xxl.elems(14), + xxl.elems(15), xxl.elems(16), xxl.elems(17), xxl.elems(18), xxl.elems(19), xxl.elems(20), + xxl.elems(21), xxl.elems(22) + ).asInstanceOf[Result] + } else { + val arr = new Array[Object](self.size - 1) + System.arraycopy(xxl.elems, 1, arr, 0, self.size - 1) + dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) + } + case _ => val arr = new Array[Object](self.size - 1) - System.arraycopy(xxl.elems, 1, arr, 0, self.size - 1) + val it = self.asInstanceOf[Product].productIterator.asInstanceOf[Iterator[Object]] + itToArray(it, self.size - 1, arr, 0) dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) } res.asInstanceOf[Result] From a68109849953d88043825b7f32ce50bacdfd4b3c Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Wed, 6 Nov 2019 15:03:03 +0100 Subject: [PATCH 15/32] Remove unnecessary dynamicFromIArray (replaced by TupleXXL.fromIArray) --- library/src/scala/runtime/DynamicTuple.scala | 42 ++++++++------------ 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index 0ae3f02095ff..8bf03b367a5a 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -234,19 +234,16 @@ object DynamicTuple { case self: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => Tuple22(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21) case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - val arr = new Array[Object](23) - arr(0) = x.asInstanceOf[Object]; - arr(1) = self._1.asInstanceOf[Object]; arr(2) = self._2.asInstanceOf[Object]; - arr(3) = self._3.asInstanceOf[Object]; arr(4) = self._4.asInstanceOf[Object]; - arr(5) = self._5.asInstanceOf[Object]; arr(6) = self._6.asInstanceOf[Object]; - arr(7) = self._7.asInstanceOf[Object]; arr(8) = self._8.asInstanceOf[Object]; - arr(9) = self._9.asInstanceOf[Object]; arr(10) = self._10.asInstanceOf[Object]; - arr(11) = self._11.asInstanceOf[Object]; arr(12) = self._12.asInstanceOf[Object]; - arr(13) = self._13.asInstanceOf[Object]; arr(14) = self._14.asInstanceOf[Object]; - arr(15) = self._15.asInstanceOf[Object]; arr(16) = self._16.asInstanceOf[Object]; - arr(17) = self._17.asInstanceOf[Object]; arr(18) = self._18.asInstanceOf[Object]; - arr(19) = self._19.asInstanceOf[Object]; arr(20) = self._20.asInstanceOf[Object]; - arr(21) = self._21.asInstanceOf[Object]; arr(22) = self._22.asInstanceOf[Object]; + val arr: Array[Object] = Array( + x.asInstanceOf[Object], self._1.asInstanceOf[Object], self._2.asInstanceOf[Object], + self._3.asInstanceOf[Object], self._4.asInstanceOf[Object], self._5.asInstanceOf[Object], + self._6.asInstanceOf[Object], self._7.asInstanceOf[Object], self._8.asInstanceOf[Object], + self._9.asInstanceOf[Object], self._10.asInstanceOf[Object], self._11.asInstanceOf[Object], + self._12.asInstanceOf[Object], self._13.asInstanceOf[Object], self._14.asInstanceOf[Object], + self._15.asInstanceOf[Object], self._16.asInstanceOf[Object], self._17.asInstanceOf[Object], + self._18.asInstanceOf[Object], self._19.asInstanceOf[Object], self._20.asInstanceOf[Object], + self._21.asInstanceOf[Object], self._22.asInstanceOf[Object], + ) TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] case xxl: TupleXXL => val arr = new Array[Object](xxl.productArity + 1) @@ -282,10 +279,10 @@ object DynamicTuple { case xxl: TupleXXL => System.arraycopy(xxl.elems, 0, arr, self.size, that.size) case _ => - itToArray(that.asInstanceOf[Product].productIterator, that.size, arr, 0) + itToArray(that.asInstanceOf[Product].productIterator, that.size, arr, self.size) } - dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] + dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) } def dynamicSize[This <: Tuple](self: This): Size[This] = (self: Any) match { @@ -344,21 +341,16 @@ object DynamicTuple { if (xxl.productArity == 23) { val elems = xxl.elems Tuple22( - xxl.elems(1), xxl.elems(2), xxl.elems(3), xxl.elems(4), xxl.elems(5), xxl.elems(6), xxl.elems(7), - xxl.elems(8), xxl.elems(9), xxl.elems(10), xxl.elems(11), xxl.elems(12), xxl.elems(13), xxl.elems(14), - xxl.elems(15), xxl.elems(16), xxl.elems(17), xxl.elems(18), xxl.elems(19), xxl.elems(20), - xxl.elems(21), xxl.elems(22) + elems(1), elems(2), elems(3), elems(4), elems(5), elems(6), elems(7), + elems(8), elems(9), elems(10), elems(11), elems(12), elems(13), elems(14), + elems(15), elems(16), elems(17), elems(18), elems(19), elems(20), + elems(21), elems(22) ).asInstanceOf[Result] } else { val arr = new Array[Object](self.size - 1) System.arraycopy(xxl.elems, 1, arr, 0, self.size - 1) - dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) + TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] } - case _ => - val arr = new Array[Object](self.size - 1) - val it = self.asInstanceOf[Product].productIterator.asInstanceOf[Iterator[Object]] - itToArray(it, self.size - 1, arr, 0) - dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) } res.asInstanceOf[Result] } From 3286379b744029186e880a8d9fe867bd04494435 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Wed, 6 Nov 2019 21:04:49 +0100 Subject: [PATCH 16/32] Add some benchmarks in tupleCons --- .../dotty/tools/benchmarks/tuples/Concat.scala | 2 -- .../dotty/tools/benchmarks/tuples/Cons.scala | 17 ++++++++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Concat.scala b/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Concat.scala index 1853b71d2a8b..c3eab96e5662 100644 --- a/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Concat.scala +++ b/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Concat.scala @@ -10,8 +10,6 @@ class Concat { var sizes: String = _ var tuple1: Tuple = _ var tuple2: Tuple = _ - var array1: Array[Object] = _ - var array2: Array[Object] = _ def tupleOfSize(n: Int): Tuple = { var t: Tuple = () diff --git a/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Cons.scala b/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Cons.scala index f1129bf2383b..474e76671841 100644 --- a/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Cons.scala +++ b/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/Cons.scala @@ -8,7 +8,8 @@ class Cons { @Param(Array("0")) var size: Int = _ var tuple: Tuple = _ - var array: Array[Object] = _ + var array1: Array[Object] = _ + var array2: Array[Object] = _ @Setup def setup(): Unit = { @@ -16,10 +17,24 @@ class Cons { for (i <- 1 to size) tuple = "elem" *: tuple + + array1 = new Array[Object](size) + array2 = new Array[Object](size + 1) } @Benchmark def tupleCons(): Tuple = { DynamicTuple.dynamicCons("elem", tuple) } + + @Benchmark + def createArray(): Array[Object] = { + new Array[Object](size + 1) + } + + @Benchmark + def consArray(): Array[Object] = { + System.arraycopy(array1, 0, array2, 1, size) + array2 + } } From fe4eaa4d215e21c4c91ee8ae5bb4da523e4fe899 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Thu, 7 Nov 2019 15:09:49 +0100 Subject: [PATCH 17/32] Trying to see if tupleCons is too big for optimizations --- library/src/scala/runtime/DynamicTuple.scala | 116 +++---------------- 1 file changed, 15 insertions(+), 101 deletions(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index 8bf03b367a5a..bcd7bd6c4f69 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -189,67 +189,17 @@ object DynamicTuple { def dynamicCons[H, This <: Tuple](x: H, self: This): H *: This = { type Result = H *: This val res = (self: Any) match { - case () => - Tuple1(x) - case self: Tuple1[_] => - Tuple2(x, self._1) - case self: Tuple2[_, _] => - Tuple3(x, self._1, self._2) - case self: Tuple3[_, _, _] => - Tuple4(x, self._1, self._2, self._3) - case self: Tuple4[_, _, _, _] => - Tuple5(x, self._1, self._2, self._3, self._4) - case self: Tuple5[_, _, _, _, _] => - Tuple6(x, self._1, self._2, self._3, self._4, self._5) - case self: Tuple6[_, _, _, _, _, _] => - Tuple7(x, self._1, self._2, self._3, self._4, self._5, self._6) - case self: Tuple7[_, _, _, _, _, _, _] => - Tuple8(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7) - case self: Tuple8[_, _, _, _, _, _, _, _] => - Tuple9(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8) - case self: Tuple9[_, _, _, _, _, _, _, _, _] => - Tuple10(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9) - case self: Tuple10[_, _, _, _, _, _, _, _, _, _] => - Tuple11(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10) - case self: Tuple11[_, _, _, _, _, _, _, _, _, _, _] => - Tuple12(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11) - case self: Tuple12[_, _, _, _, _, _, _, _, _, _, _, _] => - Tuple13(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12) - case self: Tuple13[_, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple14(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13) - case self: Tuple14[_, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple15(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14) - case self: Tuple15[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple16(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15) - case self: Tuple16[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple17(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16) - case self: Tuple17[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple18(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17) - case self: Tuple18[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple19(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18) - case self: Tuple19[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple20(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19) - case self: Tuple20[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple21(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20) - case self: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple22(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21) - case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - val arr: Array[Object] = Array( - x.asInstanceOf[Object], self._1.asInstanceOf[Object], self._2.asInstanceOf[Object], - self._3.asInstanceOf[Object], self._4.asInstanceOf[Object], self._5.asInstanceOf[Object], - self._6.asInstanceOf[Object], self._7.asInstanceOf[Object], self._8.asInstanceOf[Object], - self._9.asInstanceOf[Object], self._10.asInstanceOf[Object], self._11.asInstanceOf[Object], - self._12.asInstanceOf[Object], self._13.asInstanceOf[Object], self._14.asInstanceOf[Object], - self._15.asInstanceOf[Object], self._16.asInstanceOf[Object], self._17.asInstanceOf[Object], - self._18.asInstanceOf[Object], self._19.asInstanceOf[Object], self._20.asInstanceOf[Object], - self._21.asInstanceOf[Object], self._22.asInstanceOf[Object], - ) - TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] case xxl: TupleXXL => val arr = new Array[Object](xxl.productArity + 1) System.arraycopy(xxl.elems, 0, arr, 1, xxl.productArity) arr(0) = x.asInstanceOf[Object] - TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] + TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]) + case () => + Tuple1(x) + case _ => + val arr = new Array[Object](self.size + 1) + itToArray(self.asInstanceOf[Product].productIterator, self.size, arr, 1) + dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) } res.asInstanceOf[Result] } @@ -295,48 +245,6 @@ object DynamicTuple { val res = (self: Any) match { case self: Tuple1[_] => () - case self: Tuple2[_, _] => - Tuple1(self._2) - case self: Tuple3[_, _, _] => - Tuple2(self._2, self._3) - case self: Tuple4[_, _, _, _] => - Tuple3(self._2, self._3, self._4) - case self: Tuple5[_, _, _, _, _] => - Tuple4(self._2, self._3, self._4, self._5) - case self: Tuple6[_, _, _, _, _, _] => - Tuple5(self._2, self._3, self._4, self._5, self._6) - case self: Tuple7[_, _, _, _, _, _, _] => - Tuple6(self._2, self._3, self._4, self._5, self._6, self._7) - case self: Tuple8[_, _, _, _, _, _, _, _] => - Tuple7(self._2, self._3, self._4, self._5, self._6, self._7, self._8) - case self: Tuple9[_, _, _, _, _, _, _, _, _] => - Tuple8(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9) - case self: Tuple10[_, _, _, _, _, _, _, _, _, _] => - Tuple9(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10) - case self: Tuple11[_, _, _, _, _, _, _, _, _, _, _] => - Tuple10(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11) - case self: Tuple12[_, _, _, _, _, _, _, _, _, _, _, _] => - Tuple11(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12) - case self: Tuple13[_, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple12(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13) - case self: Tuple14[_, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple13(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14) - case self: Tuple15[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple14(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15) - case self: Tuple16[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple15(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16) - case self: Tuple17[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple16(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17) - case self: Tuple18[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple17(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18) - case self: Tuple19[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple18(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19) - case self: Tuple20[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple19(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20) - case self: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple20(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21) - case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple21(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21, self._22) case xxl: TupleXXL => if (xxl.productArity == 23) { val elems = xxl.elems @@ -345,12 +253,18 @@ object DynamicTuple { elems(8), elems(9), elems(10), elems(11), elems(12), elems(13), elems(14), elems(15), elems(16), elems(17), elems(18), elems(19), elems(20), elems(21), elems(22) - ).asInstanceOf[Result] + ) } else { val arr = new Array[Object](self.size - 1) System.arraycopy(xxl.elems, 1, arr, 0, self.size - 1) - TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] + TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]) } + case _ => + val arr = new Array[Object](self.size - 1) + val it = self.asInstanceOf[Product].productIterator + it.next() + itToArray(it, self.size - 1, arr, 0) + dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) } res.asInstanceOf[Result] } From 18fe0c8c36ed39b7118326420536df86c3f819b4 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Sat, 9 Nov 2019 11:42:38 +0100 Subject: [PATCH 18/32] Try to reduce function bodies so that the JIT compiler optimizes them better --- library/src/scala/runtime/DynamicTuple.scala | 177 +++++++++++++++---- 1 file changed, 138 insertions(+), 39 deletions(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index bcd7bd6c4f69..8a5d84fd1bae 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -14,6 +14,28 @@ object DynamicTuple { } } + def dynamicToArray(self: Tuple): Array[Object] = (self: Any) match { + case self: Unit => Array.emptyObjectArray + case self: TupleXXL => self.toArray + case self: Product => productToArray(self) + } + + def dynamicToIArray(self: Tuple): IArray[Object] = (self: Any) match { + case self: Unit => Array.emptyObjectArray.asInstanceOf[IArray[Object]] // TODO use IArray.emptyObjectIArray + case self: TupleXXL => self.elems + case self: Product => productToArray(self).asInstanceOf[IArray[Object]] + } + + def productToArray(self: Product): Array[Object] = { + val arr = new Array[Object](self.productArity) + var i = 0 + while (i < arr.length) { + arr(i) = self.productElement(i).asInstanceOf[Object] + i += 1 + } + arr + } + def dynamicFromArray[T <: Tuple](xs: Array[Object]): T = xs.length match { case 0 => ().asInstanceOf[T] case 1 => Tuple1(xs(0)).asInstanceOf[T] @@ -163,45 +185,79 @@ object DynamicTuple { } }).asInstanceOf[T] - - def dynamicToArray(self: Tuple): Array[Object] = (self: Any) match { - case self: Unit => Array.emptyObjectArray - case self: TupleXXL => self.toArray - case self: Product => productToArray(self) - } - - def dynamicToIArray(self: Tuple): IArray[Object] = (self: Any) match { - case self: Unit => Array.emptyObjectArray.asInstanceOf[IArray[Object]] // TODO use IArray.emptyObjectIArray - case self: TupleXXL => self.elems - case self: Product => productToArray(self).asInstanceOf[IArray[Object]] - } - - def productToArray(self: Product): Array[Object] = { - val arr = new Array[Object](self.productArity) - var i = 0 - while (i < arr.length) { - arr(i) = self.productElement(i).asInstanceOf[Object] - i += 1 + def specialCaseCons[H, This <: Tuple](x: H, self: This): H *: This = { + type Result = H *: This + val res = (self: Any) match { + case () => + Tuple1(x) + case self: Tuple1[_] => + Tuple2(x, self._1) + case self: Tuple2[_, _] => + Tuple3(x, self._1, self._2) + case self: Tuple3[_, _, _] => + Tuple4(x, self._1, self._2, self._3) + case self: Tuple4[_, _, _, _] => + Tuple5(x, self._1, self._2, self._3, self._4) + case self: Tuple5[_, _, _, _, _] => + Tuple6(x, self._1, self._2, self._3, self._4, self._5) + case self: Tuple6[_, _, _, _, _, _] => + Tuple7(x, self._1, self._2, self._3, self._4, self._5, self._6) + case self: Tuple7[_, _, _, _, _, _, _] => + Tuple8(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7) + case self: Tuple8[_, _, _, _, _, _, _, _] => + Tuple9(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8) + case self: Tuple9[_, _, _, _, _, _, _, _, _] => + Tuple10(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9) + case self: Tuple10[_, _, _, _, _, _, _, _, _, _] => + Tuple11(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10) + case self: Tuple11[_, _, _, _, _, _, _, _, _, _, _] => + Tuple12(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11) + case self: Tuple12[_, _, _, _, _, _, _, _, _, _, _, _] => + Tuple13(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12) + case self: Tuple13[_, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple14(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13) + case self: Tuple14[_, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple15(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14) + case self: Tuple15[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple16(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15) + case self: Tuple16[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple17(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16) + case self: Tuple17[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple18(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17) + case self: Tuple18[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple19(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18) + case self: Tuple19[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple20(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19) + case self: Tuple20[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple21(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20) + case self: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple22(x, self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21) + case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + val arr: Array[Object] = Array( + x.asInstanceOf[Object], self._1.asInstanceOf[Object], self._2.asInstanceOf[Object], + self._3.asInstanceOf[Object], self._4.asInstanceOf[Object], self._5.asInstanceOf[Object], + self._6.asInstanceOf[Object], self._7.asInstanceOf[Object], self._8.asInstanceOf[Object], + self._9.asInstanceOf[Object], self._10.asInstanceOf[Object], self._11.asInstanceOf[Object], + self._12.asInstanceOf[Object], self._13.asInstanceOf[Object], self._14.asInstanceOf[Object], + self._15.asInstanceOf[Object], self._16.asInstanceOf[Object], self._17.asInstanceOf[Object], + self._18.asInstanceOf[Object], self._19.asInstanceOf[Object], self._20.asInstanceOf[Object], + self._21.asInstanceOf[Object], self._22.asInstanceOf[Object], + ) + TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]) } - arr + res.asInstanceOf[Result] } def dynamicCons[H, This <: Tuple](x: H, self: This): H *: This = { type Result = H *: This - val res = (self: Any) match { + (self: Any) match { case xxl: TupleXXL => val arr = new Array[Object](xxl.productArity + 1) System.arraycopy(xxl.elems, 0, arr, 1, xxl.productArity) arr(0) = x.asInstanceOf[Object] - TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]) - case () => - Tuple1(x) - case _ => - val arr = new Array[Object](self.size + 1) - itToArray(self.asInstanceOf[Product].productIterator, self.size, arr, 1) - dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) + TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] + case _ => specialCaseCons(x, self) } - res.asInstanceOf[Result] } def dynamicConcat[This <: Tuple, That <: Tuple](self: This, that: That): Concat[This, That] = { @@ -240,11 +296,60 @@ object DynamicTuple { case self: Product => self.productArity.asInstanceOf[Size[This]] } - def dynamicTail[This <: NonEmptyTuple] (self: This): Tail[This] = { + def specialCaseTail[This <: NonEmptyTuple] (self: This): Tail[This] = { type Result = Tail[This] val res = (self: Any) match { case self: Tuple1[_] => () + case self: Tuple2[_, _] => + Tuple1(self._2) + case self: Tuple3[_, _, _] => + Tuple2(self._2, self._3) + case self: Tuple4[_, _, _, _] => + Tuple3(self._2, self._3, self._4) + case self: Tuple5[_, _, _, _, _] => + Tuple4(self._2, self._3, self._4, self._5) + case self: Tuple6[_, _, _, _, _, _] => + Tuple5(self._2, self._3, self._4, self._5, self._6) + case self: Tuple7[_, _, _, _, _, _, _] => + Tuple6(self._2, self._3, self._4, self._5, self._6, self._7) + case self: Tuple8[_, _, _, _, _, _, _, _] => + Tuple7(self._2, self._3, self._4, self._5, self._6, self._7, self._8) + case self: Tuple9[_, _, _, _, _, _, _, _, _] => + Tuple8(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9) + case self: Tuple10[_, _, _, _, _, _, _, _, _, _] => + Tuple9(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10) + case self: Tuple11[_, _, _, _, _, _, _, _, _, _, _] => + Tuple10(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11) + case self: Tuple12[_, _, _, _, _, _, _, _, _, _, _, _] => + Tuple11(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12) + case self: Tuple13[_, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple12(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13) + case self: Tuple14[_, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple13(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14) + case self: Tuple15[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple14(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15) + case self: Tuple16[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple15(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16) + case self: Tuple17[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple16(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17) + case self: Tuple18[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple17(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18) + case self: Tuple19[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple18(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19) + case self: Tuple20[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple19(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20) + case self: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple20(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21) + case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple21(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21, self._22) + } + res.asInstanceOf[Result] + } + + def dynamicTail[This <: NonEmptyTuple] (self: This): Tail[This] = { + type Result = Tail[This] + (self: Any) match { case xxl: TupleXXL => if (xxl.productArity == 23) { val elems = xxl.elems @@ -253,20 +358,14 @@ object DynamicTuple { elems(8), elems(9), elems(10), elems(11), elems(12), elems(13), elems(14), elems(15), elems(16), elems(17), elems(18), elems(19), elems(20), elems(21), elems(22) - ) + ).asInstanceOf[Result] } else { val arr = new Array[Object](self.size - 1) System.arraycopy(xxl.elems, 1, arr, 0, self.size - 1) - TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]) + TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] } - case _ => - val arr = new Array[Object](self.size - 1) - val it = self.asInstanceOf[Product].productIterator - it.next() - itToArray(it, self.size - 1, arr, 0) - dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) + case _ => specialCaseTail(self) } - res.asInstanceOf[Result] } def dynamicApply[This <: NonEmptyTuple, N <: Int] (self: This, n: Int): Elem[This, N] = { From e1a01d2f0dcc62cb670683657d39a872c616eee7 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Wed, 13 Nov 2019 14:25:12 +0100 Subject: [PATCH 19/32] Try to optimize dynamicMap --- library/src/scala/runtime/DynamicTuple.scala | 68 ++++++++++++++++++-- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index 8a5d84fd1bae..3ec97484eb94 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -188,7 +188,7 @@ object DynamicTuple { def specialCaseCons[H, This <: Tuple](x: H, self: This): H *: This = { type Result = H *: This val res = (self: Any) match { - case () => + case self: Unit => Tuple1(x) case self: Tuple1[_] => Tuple2(x, self._1) @@ -385,11 +385,67 @@ object DynamicTuple { ).asInstanceOf[Zip[This, T2]] } - def dynamicMap[This <: Tuple, F[_]](self: This, f: [t] => t => F[t]): Map[This, F] = (self: Any) match { - case self: Unit => ().asInstanceOf[Map[This, F]] - case _ => - Tuple.fromArray(self.asInstanceOf[Product].productIterator.map(f(_)).toArray) // TODO use toIArray of Object to avoid double/triple array copy - .asInstanceOf[Map[This, F]] + def specialCaseMap[This <: Tuple, F[_]](self: This, f: [t] => t => F[t]): Map[This, F] = { + type Result = Map[This, F] + val res = (self: Any) match { + case sekf: Unit => + () + case self: Tuple1[_] => + Tuple1(f(self._1)) + case self: Tuple2[_, _] => + Tuple2(f(self._1), f(self._2)) + case self: Tuple3[_, _, _] => + Tuple3(f(self._1), f(self._2), f(self._3)) + case self: Tuple4[_, _, _, _] => + Tuple4(f(self._1), f(self._2), f(self._3), f(self._4)) + case self: Tuple5[_, _, _, _, _] => + Tuple5(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5)) + case self: Tuple6[_, _, _, _, _, _] => + Tuple6(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6)) + case self: Tuple7[_, _, _, _, _, _, _] => + Tuple7(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7)) + case self: Tuple8[_, _, _, _, _, _, _, _] => + Tuple8(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8)) + case self: Tuple9[_, _, _, _, _, _, _, _, _] => + Tuple9(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9)) + case self: Tuple10[_, _, _, _, _, _, _, _, _, _] => + Tuple10(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10)) + case self: Tuple11[_, _, _, _, _, _, _, _, _, _, _] => + Tuple11(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11)) + case self: Tuple12[_, _, _, _, _, _, _, _, _, _, _, _] => + Tuple12(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12)) + case self: Tuple13[_, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple13(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13)) + case self: Tuple14[_, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple14(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13), f(self._14)) + case self: Tuple15[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple15(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13), f(self._14), f(self._15)) + case self: Tuple16[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple16(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13), f(self._14), f(self._15), f(self._16)) + case self: Tuple17[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple17(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13), f(self._14), f(self._15), f(self._16), f(self._17)) + case self: Tuple18[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple18(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13), f(self._14), f(self._15), f(self._16), f(self._17), f(self._18)) + case self: Tuple19[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple19(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13), f(self._14), f(self._15), f(self._16), f(self._17), f(self._18), f(self._19)) + case self: Tuple20[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple20(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13), f(self._14), f(self._15), f(self._16), f(self._17), f(self._18), f(self._19), f(self._20)) + case self: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple21(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13), f(self._14), f(self._15), f(self._16), f(self._17), f(self._18), f(self._19), f(self._20), f(self._21)) + case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => + Tuple22(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13), f(self._14), f(self._15), f(self._16), f(self._17), f(self._18), f(self._19), f(self._20), f(self._21), f(self._22)) + } + res.asInstanceOf[Result] + } + + def dynamicMap[This <: Tuple, F[_]](self: This, f: [t] => t => F[t]): Map[This, F] = { + type Result = Map[This, F] + (self: Any) match { + case xxl: TupleXXL => + TupleXXL.fromIArray(xxl.elems.asInstanceOf[Array[Object]].map(f[Object]).asInstanceOf[IArray[Object]]).asInstanceOf[Result] + case _ => + specialCaseMap(self, f) + } } def consIterator(head: Any, tail: Tuple): Iterator[Any] = From 86ca3253bde96ae09e440d7ca604bb532c4884cc Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Thu, 14 Nov 2019 16:58:39 +0100 Subject: [PATCH 20/32] Try to improve even more tupleCons and tupleTail by making them really short --- library/src/scala/runtime/DynamicTuple.scala | 54 ++++++++++---------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index 3ec97484eb94..128f96234ece 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -186,7 +186,6 @@ object DynamicTuple { }).asInstanceOf[T] def specialCaseCons[H, This <: Tuple](x: H, self: This): H *: This = { - type Result = H *: This val res = (self: Any) match { case self: Unit => Tuple1(x) @@ -245,17 +244,19 @@ object DynamicTuple { ) TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]) } - res.asInstanceOf[Result] + res.asInstanceOf[H *: This] + } + + def xxlCons[H, This <: Tuple](x: H, xxl: TupleXXL): H *: This = { + val arr = new Array[Object](xxl.productArity + 1) + System.arraycopy(xxl.elems, 0, arr, 1, xxl.productArity) + arr(0) = x.asInstanceOf[Object] + TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[H *: This] } def dynamicCons[H, This <: Tuple](x: H, self: This): H *: This = { - type Result = H *: This (self: Any) match { - case xxl: TupleXXL => - val arr = new Array[Object](xxl.productArity + 1) - System.arraycopy(xxl.elems, 0, arr, 1, xxl.productArity) - arr(0) = x.asInstanceOf[Object] - TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] + case xxl: TupleXXL => xxlCons(x, xxl) case _ => specialCaseCons(x, self) } } @@ -297,7 +298,6 @@ object DynamicTuple { } def specialCaseTail[This <: NonEmptyTuple] (self: This): Tail[This] = { - type Result = Tail[This] val res = (self: Any) match { case self: Tuple1[_] => () @@ -344,26 +344,28 @@ object DynamicTuple { case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => Tuple21(self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21, self._22) } - res.asInstanceOf[Result] + res.asInstanceOf[Tail[This]] } - def dynamicTail[This <: NonEmptyTuple] (self: This): Tail[This] = { - type Result = Tail[This] + def xxlTail[This <: NonEmptyTuple](xxl: TupleXXL): Tail[This] = { + if (xxl.productArity == 23) { + val elems = xxl.elems + Tuple22( + elems(1), elems(2), elems(3), elems(4), elems(5), elems(6), elems(7), + elems(8), elems(9), elems(10), elems(11), elems(12), elems(13), elems(14), + elems(15), elems(16), elems(17), elems(18), elems(19), elems(20), + elems(21), elems(22) + ).asInstanceOf[Tail[This]] + } else { + val arr = new Array[Object](xxl.elems.length - 1) + System.arraycopy(xxl.elems, 1, arr, 0, xxl.elems.length - 1) + TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Tail[This]] + } + } + + def dynamicTail[This <: NonEmptyTuple](self: This): Tail[This] = { (self: Any) match { - case xxl: TupleXXL => - if (xxl.productArity == 23) { - val elems = xxl.elems - Tuple22( - elems(1), elems(2), elems(3), elems(4), elems(5), elems(6), elems(7), - elems(8), elems(9), elems(10), elems(11), elems(12), elems(13), elems(14), - elems(15), elems(16), elems(17), elems(18), elems(19), elems(20), - elems(21), elems(22) - ).asInstanceOf[Result] - } else { - val arr = new Array[Object](self.size - 1) - System.arraycopy(xxl.elems, 1, arr, 0, self.size - 1) - TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Result] - } + case xxl: TupleXXL => xxlTail(xxl) case _ => specialCaseTail(self) } } From f517abeca18c6ea273992d3c89e2d09871b7efee Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Thu, 14 Nov 2019 17:16:34 +0100 Subject: [PATCH 21/32] Trying to improve tupleZip --- library/src/scala/runtime/DynamicTuple.scala | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index 128f96234ece..5f4173fdbc96 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -379,12 +379,20 @@ object DynamicTuple { res.asInstanceOf[Result] } + def zipIt(it1: Iterator[Any], it2: Iterator[Any], size: Int): IArray[Object] = { + val arr = new Array[Object](size) + var i = 0 + while (i < size) { + arr(i) = (it1.next(), it2.next()) + i += 1 + } + arr.asInstanceOf[IArray[Object]] + } + def dynamicZip[This <: Tuple, T2 <: Tuple](t1: This, t2: T2): Zip[This, T2] = { - if (t1.size == 0 || t2.size == 0) ().asInstanceOf[Zip[This, T2]] - else Tuple.fromArray( - t1.asInstanceOf[Product].productIterator.zip( - t2.asInstanceOf[Product].productIterator).toArray // TODO use toIArray of Object to avoid double/triple array copy - ).asInstanceOf[Zip[This, T2]] + if (t1.size == 0 || t2.size == 0) return ().asInstanceOf[Zip[This, T2]] + val size = Math.min(t1.size, t2.size) + Tuple.fromIArray(zipIt(t1.asInstanceOf[Product].productIterator, t2.asInstanceOf[Product].productIterator, size)).asInstanceOf[Zip[This, T2]] } def specialCaseMap[This <: Tuple, F[_]](self: This, f: [t] => t => F[t]): Map[This, F] = { From 324822770d718a5c073ad866231fc9bf17578445 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Thu, 14 Nov 2019 18:14:07 +0100 Subject: [PATCH 22/32] Add a new folder for test files --- tests/run/tuple-tests/tuple-concat.check | 2 ++ tests/run/tuple-tests/tuple-concat.scala | 27 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 tests/run/tuple-tests/tuple-concat.check create mode 100644 tests/run/tuple-tests/tuple-concat.scala diff --git a/tests/run/tuple-tests/tuple-concat.check b/tests/run/tuple-tests/tuple-concat.check new file mode 100644 index 000000000000..0d325df6921e --- /dev/null +++ b/tests/run/tuple-tests/tuple-concat.check @@ -0,0 +1,2 @@ +(1,2,3,4,5) +(1,2,3,4,5) diff --git a/tests/run/tuple-tests/tuple-concat.scala b/tests/run/tuple-tests/tuple-concat.scala new file mode 100644 index 000000000000..b943537edd13 --- /dev/null +++ b/tests/run/tuple-tests/tuple-concat.scala @@ -0,0 +1,27 @@ + +object Test extends App { + val emptyTuple: Tuple = () + val tuple1: Tuple = ("1", "2", "3", "4", "5") + val tuple2: Tuple = ("6", "7", "8", "9", "10") + val tupleXXL1: Tuple = ("11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35") + val tupleXXL2: Tuple = ("36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60") + + // Try all possible kinds of concatenations (small === <=22): + // empty + empty + // small + empty + // empty + small + // xxl + empty + // empty + xxl + // small + small + // small + xxl + // xxl + small + // xxl + xxl + println(tuple1 ++ emptyTuple) + println(emptyTuple ++ tuple1) + + // Concatenation with an empty tuple should be a no-op + assert((tuple1 ++ emptyTuple).asInstanceOf[AnyRef] eq tuple1.asInstanceOf[AnyRef]) + assert((tupleXXL1 ++ emptyTuple).asInstanceOf[AnyRef] eq tupleXXL1.asInstanceOf[AnyRef]) + assert((emptyTuple ++tuple1).asInstanceOf[AnyRef] eq tuple1.asInstanceOf[AnyRef]) + assert((emptyTuple ++ tupleXXL1).asInstanceOf[AnyRef] eq tupleXXL1.asInstanceOf[AnyRef]) +} From 20f7f39b3a90a94e1974952c2a09d57a57b04991 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Thu, 14 Nov 2019 18:40:58 +0100 Subject: [PATCH 23/32] Add tests for tupleConcat --- tests/run/tuple-tests.check | 9 +++++++++ tests/run/tuple-tests/tuple-concat.check | 2 -- tests/run/tuple-tests/tuple-concat.scala | 9 ++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 tests/run/tuple-tests.check delete mode 100644 tests/run/tuple-tests/tuple-concat.check diff --git a/tests/run/tuple-tests.check b/tests/run/tuple-tests.check new file mode 100644 index 000000000000..9529173cc978 --- /dev/null +++ b/tests/run/tuple-tests.check @@ -0,0 +1,9 @@ +() +(1,2,3,4,5) +(1,2,3,4,5) +(11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35) +(11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35) +(1,2,3,4,5,6,7,8,9,10) +(1,2,3,4,5,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35) +(11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,1,2,3,4,5) +(11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60) diff --git a/tests/run/tuple-tests/tuple-concat.check b/tests/run/tuple-tests/tuple-concat.check deleted file mode 100644 index 0d325df6921e..000000000000 --- a/tests/run/tuple-tests/tuple-concat.check +++ /dev/null @@ -1,2 +0,0 @@ -(1,2,3,4,5) -(1,2,3,4,5) diff --git a/tests/run/tuple-tests/tuple-concat.scala b/tests/run/tuple-tests/tuple-concat.scala index b943537edd13..16dda1a96899 100644 --- a/tests/run/tuple-tests/tuple-concat.scala +++ b/tests/run/tuple-tests/tuple-concat.scala @@ -16,8 +16,15 @@ object Test extends App { // small + xxl // xxl + small // xxl + xxl - println(tuple1 ++ emptyTuple) + println(emptyTuple ++ emptyTuple) println(emptyTuple ++ tuple1) + println(tuple1 ++ emptyTuple) + println(tupleXXL1 ++ emptyTuple) + println(emptyTuple ++ tupleXXL1) + println(tuple1 ++ tuple2) + println(tuple1 ++ tupleXXL1) + println(tupleXXL1 ++ tuple1) + println(tupleXXL1 ++ tupleXXL2) // Concatenation with an empty tuple should be a no-op assert((tuple1 ++ emptyTuple).asInstanceOf[AnyRef] eq tuple1.asInstanceOf[AnyRef]) From 036683da159007268edd1d11dd822218eb62898e Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Thu, 14 Nov 2019 21:54:12 +0100 Subject: [PATCH 24/32] Add some tests to all current tuple operations --- tests/run/tuple-tests.check | 20 ++++++++++++++++++++ tests/run/tuple-tests/tuple-concat.scala | 13 ++----------- tests/run/tuple-tests/tuple-cons.scala | 13 +++++++++++++ tests/run/tuple-tests/tuple-map.scala | 17 +++++++++++++++++ tests/run/tuple-tests/tuple-tail.scala | 13 +++++++++++++ tests/run/tuple-tests/tuple-tests.scala | 8 ++++++++ tests/run/tuple-tests/tuple-zip.scala | 20 ++++++++++++++++++++ 7 files changed, 93 insertions(+), 11 deletions(-) create mode 100644 tests/run/tuple-tests/tuple-cons.scala create mode 100644 tests/run/tuple-tests/tuple-map.scala create mode 100644 tests/run/tuple-tests/tuple-tail.scala create mode 100644 tests/run/tuple-tests/tuple-tests.scala create mode 100644 tests/run/tuple-tests/tuple-zip.scala diff --git a/tests/run/tuple-tests.check b/tests/run/tuple-tests.check index 9529173cc978..1407b3e49d1e 100644 --- a/tests/run/tuple-tests.check +++ b/tests/run/tuple-tests.check @@ -7,3 +7,23 @@ (1,2,3,4,5,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35) (11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,1,2,3,4,5) (11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60) +(head) +(head,1,2,3,4,5) +(head,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35) +(head,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57) +() +(2,3,4,5) +(12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35) +(37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58) +() +(2,3,4,5,6) +(21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45) +() +() +() +() +() +((1,6),(2,7),(3,8),(4,9),(5,10)) +((1,11),(2,12),(3,13),(4,14),(5,15)) +((11,1),(12,2),(13,3),(14,4),(15,5)) +((11,36),(12,37),(13,38),(14,39),(15,40),(16,41),(17,42),(18,43),(19,44),(20,45),(21,46),(22,47),(23,48),(24,49),(25,50),(26,51),(27,52),(28,53),(29,54),(30,55),(31,56),(32,57),(33,58),(34,59),(35,60)) diff --git a/tests/run/tuple-tests/tuple-concat.scala b/tests/run/tuple-tests/tuple-concat.scala index 16dda1a96899..c06819765932 100644 --- a/tests/run/tuple-tests/tuple-concat.scala +++ b/tests/run/tuple-tests/tuple-concat.scala @@ -1,21 +1,12 @@ -object Test extends App { +def concat(): Unit = { val emptyTuple: Tuple = () val tuple1: Tuple = ("1", "2", "3", "4", "5") val tuple2: Tuple = ("6", "7", "8", "9", "10") val tupleXXL1: Tuple = ("11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35") val tupleXXL2: Tuple = ("36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60") - // Try all possible kinds of concatenations (small === <=22): - // empty + empty - // small + empty - // empty + small - // xxl + empty - // empty + xxl - // small + small - // small + xxl - // xxl + small - // xxl + xxl + // All possible combinations of concatenating two tuples println(emptyTuple ++ emptyTuple) println(emptyTuple ++ tuple1) println(tuple1 ++ emptyTuple) diff --git a/tests/run/tuple-tests/tuple-cons.scala b/tests/run/tuple-tests/tuple-cons.scala new file mode 100644 index 000000000000..ac3eb864cbb9 --- /dev/null +++ b/tests/run/tuple-tests/tuple-cons.scala @@ -0,0 +1,13 @@ + +def cons(): Unit = { + val emptyTuple: Tuple = () + val tuple: Tuple = ("1", "2", "3", "4", "5") + val tupleXXL: Tuple = ("11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35") + val tuple22: Tuple = ("36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57") + + // Test all possible combinations of making + println("head" *: emptyTuple) + println("head" *: tuple) + println("head" *: tupleXXL) + println("head" *: tuple22) +} diff --git a/tests/run/tuple-tests/tuple-map.scala b/tests/run/tuple-tests/tuple-map.scala new file mode 100644 index 000000000000..f24cae41e45c --- /dev/null +++ b/tests/run/tuple-tests/tuple-map.scala @@ -0,0 +1,17 @@ + +def map(): Unit = { + val emptyTuple: Tuple = () + val tuple: Tuple = ("1", "2", "3", "4", "5") + val tupleXXL: Tuple = ("11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35") + + type Id[X] = X + val f: [t] => t => Id[t] = [t] => (x: t) => { + val str = x.asInstanceOf[String] + str.updated(0, (str(0) + 1).toChar).asInstanceOf[t] + } + + // Test all possible combinations of making + println(emptyTuple.map(f)) + println(tuple.map(f)) + println(tupleXXL.map(f)) +} diff --git a/tests/run/tuple-tests/tuple-tail.scala b/tests/run/tuple-tests/tuple-tail.scala new file mode 100644 index 000000000000..e3f16edfe9f3 --- /dev/null +++ b/tests/run/tuple-tests/tuple-tail.scala @@ -0,0 +1,13 @@ + +def tail(): Unit = { + val singletonTuple: NonEmptyTuple = Tuple1("59") + val tuple: NonEmptyTuple = ("1", "2", "3", "4", "5") + val tupleXXL: NonEmptyTuple = ("11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35") + val tuple23: NonEmptyTuple = ("36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58") + + // Test all possible combinations of making + println(singletonTuple.tail) + println(tuple.tail) + println(tupleXXL.tail) + println(tuple23.tail) +} diff --git a/tests/run/tuple-tests/tuple-tests.scala b/tests/run/tuple-tests/tuple-tests.scala new file mode 100644 index 000000000000..8abd56378b8f --- /dev/null +++ b/tests/run/tuple-tests/tuple-tests.scala @@ -0,0 +1,8 @@ + +object Test extends App { + concat() + cons() + tail() + map() + zip() +} diff --git a/tests/run/tuple-tests/tuple-zip.scala b/tests/run/tuple-tests/tuple-zip.scala new file mode 100644 index 000000000000..e906be443f5e --- /dev/null +++ b/tests/run/tuple-tests/tuple-zip.scala @@ -0,0 +1,20 @@ + +def zip(): Unit = { + val emptyTuple: Tuple = () + val tuple1: Tuple = ("1", "2", "3", "4", "5") + val tuple2: Tuple = ("6", "7", "8", "9", "10") + val tupleXXL1: Tuple = ("11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35") + val tupleXXL2: Tuple = ("36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60") + + // All possible combinations of zipping two tuples + println(emptyTuple zip emptyTuple) + println(emptyTuple zip tuple1) + println(tuple1 zip emptyTuple) + println(tupleXXL1 zip emptyTuple) + println(emptyTuple zip tupleXXL1) + println(tuple1 zip tuple2) + println(tuple1 zip tupleXXL1) + println(tupleXXL1 zip tuple1) + println(tupleXXL1 zip tupleXXL2) +} + From 4d47151fdd7fccf6959eced3dda85becdf52717e Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Wed, 20 Nov 2019 21:00:14 +0100 Subject: [PATCH 25/32] Make the tuple tests independent for better granularity --- tests/run/tuple-tests.check | 29 ------------------------ tests/run/tuple-tests/tuple-concat.scala | 25 -------------------- tests/run/tuple-tests/tuple-cons.scala | 13 ----------- tests/run/tuple-tests/tuple-map.scala | 17 -------------- tests/run/tuple-tests/tuple-tail.scala | 13 ----------- tests/run/tuple-tests/tuple-tests.scala | 8 ------- tests/run/tuple-tests/tuple-zip.scala | 20 ---------------- 7 files changed, 125 deletions(-) delete mode 100644 tests/run/tuple-tests.check delete mode 100644 tests/run/tuple-tests/tuple-concat.scala delete mode 100644 tests/run/tuple-tests/tuple-cons.scala delete mode 100644 tests/run/tuple-tests/tuple-map.scala delete mode 100644 tests/run/tuple-tests/tuple-tail.scala delete mode 100644 tests/run/tuple-tests/tuple-tests.scala delete mode 100644 tests/run/tuple-tests/tuple-zip.scala diff --git a/tests/run/tuple-tests.check b/tests/run/tuple-tests.check deleted file mode 100644 index 1407b3e49d1e..000000000000 --- a/tests/run/tuple-tests.check +++ /dev/null @@ -1,29 +0,0 @@ -() -(1,2,3,4,5) -(1,2,3,4,5) -(11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35) -(11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35) -(1,2,3,4,5,6,7,8,9,10) -(1,2,3,4,5,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35) -(11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,1,2,3,4,5) -(11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60) -(head) -(head,1,2,3,4,5) -(head,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35) -(head,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57) -() -(2,3,4,5) -(12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35) -(37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58) -() -(2,3,4,5,6) -(21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45) -() -() -() -() -() -((1,6),(2,7),(3,8),(4,9),(5,10)) -((1,11),(2,12),(3,13),(4,14),(5,15)) -((11,1),(12,2),(13,3),(14,4),(15,5)) -((11,36),(12,37),(13,38),(14,39),(15,40),(16,41),(17,42),(18,43),(19,44),(20,45),(21,46),(22,47),(23,48),(24,49),(25,50),(26,51),(27,52),(28,53),(29,54),(30,55),(31,56),(32,57),(33,58),(34,59),(35,60)) diff --git a/tests/run/tuple-tests/tuple-concat.scala b/tests/run/tuple-tests/tuple-concat.scala deleted file mode 100644 index c06819765932..000000000000 --- a/tests/run/tuple-tests/tuple-concat.scala +++ /dev/null @@ -1,25 +0,0 @@ - -def concat(): Unit = { - val emptyTuple: Tuple = () - val tuple1: Tuple = ("1", "2", "3", "4", "5") - val tuple2: Tuple = ("6", "7", "8", "9", "10") - val tupleXXL1: Tuple = ("11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35") - val tupleXXL2: Tuple = ("36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60") - - // All possible combinations of concatenating two tuples - println(emptyTuple ++ emptyTuple) - println(emptyTuple ++ tuple1) - println(tuple1 ++ emptyTuple) - println(tupleXXL1 ++ emptyTuple) - println(emptyTuple ++ tupleXXL1) - println(tuple1 ++ tuple2) - println(tuple1 ++ tupleXXL1) - println(tupleXXL1 ++ tuple1) - println(tupleXXL1 ++ tupleXXL2) - - // Concatenation with an empty tuple should be a no-op - assert((tuple1 ++ emptyTuple).asInstanceOf[AnyRef] eq tuple1.asInstanceOf[AnyRef]) - assert((tupleXXL1 ++ emptyTuple).asInstanceOf[AnyRef] eq tupleXXL1.asInstanceOf[AnyRef]) - assert((emptyTuple ++tuple1).asInstanceOf[AnyRef] eq tuple1.asInstanceOf[AnyRef]) - assert((emptyTuple ++ tupleXXL1).asInstanceOf[AnyRef] eq tupleXXL1.asInstanceOf[AnyRef]) -} diff --git a/tests/run/tuple-tests/tuple-cons.scala b/tests/run/tuple-tests/tuple-cons.scala deleted file mode 100644 index ac3eb864cbb9..000000000000 --- a/tests/run/tuple-tests/tuple-cons.scala +++ /dev/null @@ -1,13 +0,0 @@ - -def cons(): Unit = { - val emptyTuple: Tuple = () - val tuple: Tuple = ("1", "2", "3", "4", "5") - val tupleXXL: Tuple = ("11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35") - val tuple22: Tuple = ("36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57") - - // Test all possible combinations of making - println("head" *: emptyTuple) - println("head" *: tuple) - println("head" *: tupleXXL) - println("head" *: tuple22) -} diff --git a/tests/run/tuple-tests/tuple-map.scala b/tests/run/tuple-tests/tuple-map.scala deleted file mode 100644 index f24cae41e45c..000000000000 --- a/tests/run/tuple-tests/tuple-map.scala +++ /dev/null @@ -1,17 +0,0 @@ - -def map(): Unit = { - val emptyTuple: Tuple = () - val tuple: Tuple = ("1", "2", "3", "4", "5") - val tupleXXL: Tuple = ("11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35") - - type Id[X] = X - val f: [t] => t => Id[t] = [t] => (x: t) => { - val str = x.asInstanceOf[String] - str.updated(0, (str(0) + 1).toChar).asInstanceOf[t] - } - - // Test all possible combinations of making - println(emptyTuple.map(f)) - println(tuple.map(f)) - println(tupleXXL.map(f)) -} diff --git a/tests/run/tuple-tests/tuple-tail.scala b/tests/run/tuple-tests/tuple-tail.scala deleted file mode 100644 index e3f16edfe9f3..000000000000 --- a/tests/run/tuple-tests/tuple-tail.scala +++ /dev/null @@ -1,13 +0,0 @@ - -def tail(): Unit = { - val singletonTuple: NonEmptyTuple = Tuple1("59") - val tuple: NonEmptyTuple = ("1", "2", "3", "4", "5") - val tupleXXL: NonEmptyTuple = ("11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35") - val tuple23: NonEmptyTuple = ("36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58") - - // Test all possible combinations of making - println(singletonTuple.tail) - println(tuple.tail) - println(tupleXXL.tail) - println(tuple23.tail) -} diff --git a/tests/run/tuple-tests/tuple-tests.scala b/tests/run/tuple-tests/tuple-tests.scala deleted file mode 100644 index 8abd56378b8f..000000000000 --- a/tests/run/tuple-tests/tuple-tests.scala +++ /dev/null @@ -1,8 +0,0 @@ - -object Test extends App { - concat() - cons() - tail() - map() - zip() -} diff --git a/tests/run/tuple-tests/tuple-zip.scala b/tests/run/tuple-tests/tuple-zip.scala deleted file mode 100644 index e906be443f5e..000000000000 --- a/tests/run/tuple-tests/tuple-zip.scala +++ /dev/null @@ -1,20 +0,0 @@ - -def zip(): Unit = { - val emptyTuple: Tuple = () - val tuple1: Tuple = ("1", "2", "3", "4", "5") - val tuple2: Tuple = ("6", "7", "8", "9", "10") - val tupleXXL1: Tuple = ("11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35") - val tupleXXL2: Tuple = ("36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60") - - // All possible combinations of zipping two tuples - println(emptyTuple zip emptyTuple) - println(emptyTuple zip tuple1) - println(tuple1 zip emptyTuple) - println(tupleXXL1 zip emptyTuple) - println(emptyTuple zip tupleXXL1) - println(tuple1 zip tuple2) - println(tuple1 zip tupleXXL1) - println(tupleXXL1 zip tuple1) - println(tupleXXL1 zip tupleXXL2) -} - From 6ee2edb67ba342e8f54bd0639a96e2c696ae0c27 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Wed, 27 Nov 2019 12:11:26 +0100 Subject: [PATCH 26/32] Factorize code in tuple concat --- library/src/scala/runtime/DynamicTuple.scala | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index 5f4173fdbc96..b52ba0622878 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -263,6 +263,7 @@ object DynamicTuple { def dynamicConcat[This <: Tuple, That <: Tuple](self: This, that: That): Concat[This, That] = { type Result = Concat[This, That] + (self: Any) match { case self: Unit => return that.asInstanceOf[Result] case _ => @@ -275,20 +276,15 @@ object DynamicTuple { val arr = new Array[Object](self.size + that.size) - (self: Any) match { - case xxl: TupleXXL => - System.arraycopy(xxl.elems, 0, arr, 0, self.size) - case _ => - itToArray(self.asInstanceOf[Product].productIterator, self.size, arr, 0) - } - - (that: Any) match { + inline def copyToArray[T <: Tuple](tuple: T, array: Array[Object], offset: Int): Unit = (tuple: Any) match { case xxl: TupleXXL => - System.arraycopy(xxl.elems, 0, arr, self.size, that.size) + System.arraycopy(xxl.elems, 0, array, offset, tuple.size) case _ => - itToArray(that.asInstanceOf[Product].productIterator, that.size, arr, self.size) + itToArray(tuple.asInstanceOf[Product].productIterator, tuple.size, array, offset) } + copyToArray(self, arr, 0) + copyToArray(that, arr, self.size) dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) } From 3cabf8459e4043347fb26285b962499815538f8a Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Wed, 27 Nov 2019 17:59:14 +0100 Subject: [PATCH 27/32] Replace itToArray by Iterator.copyToArray(...) --- library/src/scala/runtime/DynamicTuple.scala | 43 ++++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index b52ba0622878..21e9f92139ce 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -6,14 +6,6 @@ object DynamicTuple { inline val MaxSpecialized = 22 inline private val XXL = MaxSpecialized + 1 - def itToArray(it: Iterator[Any], size: Int, dest: Array[Object], offset: Int): Unit = { - var i = 0 - while (i < size) { - dest(offset + i) = it.next().asInstanceOf[Object] - i += 1 - } - } - def dynamicToArray(self: Tuple): Array[Object] = (self: Any) match { case self: Unit => Array.emptyObjectArray case self: TupleXXL => self.toArray @@ -254,16 +246,15 @@ object DynamicTuple { TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[H *: This] } - def dynamicCons[H, This <: Tuple](x: H, self: This): H *: This = { - (self: Any) match { - case xxl: TupleXXL => xxlCons(x, xxl) - case _ => specialCaseCons(x, self) - } + def dynamicCons[H, This <: Tuple](x: H, self: This): H *: This = (self: Any) match { + case xxl: TupleXXL => xxlCons(x, xxl) + case _ => specialCaseCons(x, self) } def dynamicConcat[This <: Tuple, That <: Tuple](self: This, that: That): Concat[This, That] = { type Result = Concat[This, That] + // If either of the tuple is empty, we can leave early (self: Any) match { case self: Unit => return that.asInstanceOf[Result] case _ => @@ -280,7 +271,8 @@ object DynamicTuple { case xxl: TupleXXL => System.arraycopy(xxl.elems, 0, array, offset, tuple.size) case _ => - itToArray(tuple.asInstanceOf[Product].productIterator, tuple.size, array, offset) + tuple.asInstanceOf[Product].productIterator.asInstanceOf[Iterator[Object]] + .copyToArray(array, offset, tuple.size) } copyToArray(self, arr, 0) @@ -359,11 +351,9 @@ object DynamicTuple { } } - def dynamicTail[This <: NonEmptyTuple](self: This): Tail[This] = { - (self: Any) match { - case xxl: TupleXXL => xxlTail(xxl) - case _ => specialCaseTail(self) - } + def dynamicTail[This <: NonEmptyTuple](self: This): Tail[This] = (self: Any) match { + case xxl: TupleXXL => xxlTail(xxl) + case _ => specialCaseTail(self) } def dynamicApply[This <: NonEmptyTuple, N <: Int] (self: This, n: Int): Elem[This, N] = { @@ -375,7 +365,8 @@ object DynamicTuple { res.asInstanceOf[Result] } - def zipIt(it1: Iterator[Any], it2: Iterator[Any], size: Int): IArray[Object] = { + // Benchmarks showed that this is faster than doing (it1 zip it2).copyToArray(...) + def zipIterators(it1: Iterator[Any], it2: Iterator[Any], size: Int): IArray[Object] = { val arr = new Array[Object](size) var i = 0 while (i < size) { @@ -388,7 +379,13 @@ object DynamicTuple { def dynamicZip[This <: Tuple, T2 <: Tuple](t1: This, t2: T2): Zip[This, T2] = { if (t1.size == 0 || t2.size == 0) return ().asInstanceOf[Zip[This, T2]] val size = Math.min(t1.size, t2.size) - Tuple.fromIArray(zipIt(t1.asInstanceOf[Product].productIterator, t2.asInstanceOf[Product].productIterator, size)).asInstanceOf[Zip[This, T2]] + Tuple.fromIArray( + zipIterators( + t1.asInstanceOf[Product].productIterator, + t2.asInstanceOf[Product].productIterator, + size + ) + ).asInstanceOf[Zip[This, T2]] } def specialCaseMap[This <: Tuple, F[_]](self: This, f: [t] => t => F[t]): Map[This, F] = { @@ -448,7 +445,9 @@ object DynamicTuple { type Result = Map[This, F] (self: Any) match { case xxl: TupleXXL => - TupleXXL.fromIArray(xxl.elems.asInstanceOf[Array[Object]].map(f[Object]).asInstanceOf[IArray[Object]]).asInstanceOf[Result] + TupleXXL.fromIArray( + xxl.elems.asInstanceOf[Array[Object]].map(f[Object]).asInstanceOf[IArray[Object]] + ).asInstanceOf[Result] case _ => specialCaseMap(self, f) } From 348a44819e12fa2e4eff3d724c64a0fc96872044 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Thu, 5 Dec 2019 17:28:05 +0100 Subject: [PATCH 28/32] Rebase and comment --- bench-run/src/main/scala/tuples/Map.scala | 40 -------------------- bench-run/src/main/scala/tuples/Zip.scala | 38 ------------------- library/src/scala/runtime/DynamicTuple.scala | 9 ++++- 3 files changed, 8 insertions(+), 79 deletions(-) delete mode 100644 bench-run/src/main/scala/tuples/Map.scala delete mode 100644 bench-run/src/main/scala/tuples/Zip.scala diff --git a/bench-run/src/main/scala/tuples/Map.scala b/bench-run/src/main/scala/tuples/Map.scala deleted file mode 100644 index 9b3807355087..000000000000 --- a/bench-run/src/main/scala/tuples/Map.scala +++ /dev/null @@ -1,40 +0,0 @@ -package dotty.tools.benchmarks.tuples - -import org.openjdk.jmh.annotations._ -import scala.runtime.DynamicTuple - -@State(Scope.Thread) -class Map { - @Param(Array("0")) - var size: Int = _ - var tuple: Tuple = _ - var array: Array[Object] = _ - - @Setup - def setup(): Unit = { - tuple = () - - for (i <- 1 to size) - tuple = "elem" *: tuple - - array = Array.fill(size)("elem") - } - - def f: PolyFunction = new PolyFunction { - def apply[T](x: T): T = { - x.asInstanceOf[String].updated(0, 'a').asInstanceOf[T] - } - } - - type Id[X] = X - - @Benchmark - def tupleMap(): Tuple = { - DynamicTuple.dynamicMap[Tuple, Id](tuple, [T] => (x:T) => x.asInstanceOf[String].updated(0, 'a').asInstanceOf[T]) - } - - @Benchmark - def arrayMap(): Array[Object] = { - array.map(x => x.asInstanceOf[String].updated(0, 'a')) - } -} diff --git a/bench-run/src/main/scala/tuples/Zip.scala b/bench-run/src/main/scala/tuples/Zip.scala deleted file mode 100644 index 1b95922a01f9..000000000000 --- a/bench-run/src/main/scala/tuples/Zip.scala +++ /dev/null @@ -1,38 +0,0 @@ -package dotty.tools.benchmarks.tuples - -import org.openjdk.jmh.annotations._ -import scala.runtime.DynamicTuple - -@State(Scope.Thread) -class Zip { - @Param(Array("0")) - var size: Int = _ - var tuple1: Tuple = _ - var tuple2: Tuple = _ - var array1: Array[Object] = _ - var array2: Array[Object] = _ - - @Setup - def setup(): Unit = { - tuple1 = () - tuple2 = () - - for (i <- 1 to size) { - tuple1 = "el" *: tuple1 - tuple2 = "em" *: tuple2 - } - - array1 = Array.fill(size)("el") - array2 = Array.fill(size)("em") - } - - @Benchmark - def tupleZip(): Tuple = { - DynamicTuple.dynamicZip(tuple1, tuple2) - } - - @Benchmark - def arrayZip(): Array[(Object, Object)] = { - array1.zip(array2) - } -} diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index 21e9f92139ce..db9b4b9b7959 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -177,6 +177,7 @@ object DynamicTuple { } }).asInstanceOf[T] + // Cons for Tuple1 to Tuple22 def specialCaseCons[H, This <: Tuple](x: H, self: This): H *: This = { val res = (self: Any) match { case self: Unit => @@ -239,6 +240,7 @@ object DynamicTuple { res.asInstanceOf[H *: This] } + // Cons for TupleXXL def xxlCons[H, This <: Tuple](x: H, xxl: TupleXXL): H *: This = { val arr = new Array[Object](xxl.productArity + 1) System.arraycopy(xxl.elems, 0, arr, 1, xxl.productArity) @@ -254,7 +256,7 @@ object DynamicTuple { def dynamicConcat[This <: Tuple, That <: Tuple](self: This, that: That): Concat[This, That] = { type Result = Concat[This, That] - // If either of the tuple is empty, we can leave early + // If one of the tuples is empty, we can leave early (self: Any) match { case self: Unit => return that.asInstanceOf[Result] case _ => @@ -267,6 +269,7 @@ object DynamicTuple { val arr = new Array[Object](self.size + that.size) + // Copies the tuple to an array, at the given offset inline def copyToArray[T <: Tuple](tuple: T, array: Array[Object], offset: Int): Unit = (tuple: Any) match { case xxl: TupleXXL => System.arraycopy(xxl.elems, 0, array, offset, tuple.size) @@ -275,6 +278,7 @@ object DynamicTuple { .copyToArray(array, offset, tuple.size) } + // In the general case, we copy the two tuples to an array, and convert it back to a tuple copyToArray(self, arr, 0) copyToArray(that, arr, self.size) dynamicFromIArray[Result](arr.asInstanceOf[IArray[Object]]) @@ -285,6 +289,7 @@ object DynamicTuple { case self: Product => self.productArity.asInstanceOf[Size[This]] } + // Tail for Tuple1 to Tuple22 def specialCaseTail[This <: NonEmptyTuple] (self: This): Tail[This] = { val res = (self: Any) match { case self: Tuple1[_] => @@ -335,6 +340,7 @@ object DynamicTuple { res.asInstanceOf[Tail[This]] } + // Tail for TupleXXL def xxlTail[This <: NonEmptyTuple](xxl: TupleXXL): Tail[This] = { if (xxl.productArity == 23) { val elems = xxl.elems @@ -388,6 +394,7 @@ object DynamicTuple { ).asInstanceOf[Zip[This, T2]] } + // Map for Tuple1 to Tuple22 def specialCaseMap[This <: Tuple, F[_]](self: This, f: [t] => t => F[t]): Map[This, F] = { type Result = Map[This, F] val res = (self: Any) match { From 646caa40d0cdbffdad09933121c9147153384ef9 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Sat, 7 Dec 2019 10:58:08 +0100 Subject: [PATCH 29/32] Fix issue in dynamic map --- library/src/scala/runtime/DynamicTuple.scala | 76 +++++++++++--------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index db9b4b9b7959..fd0b40c7bd7c 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -401,63 +401,75 @@ object DynamicTuple { case sekf: Unit => () case self: Tuple1[_] => - Tuple1(f(self._1)) + Tuple1(f[Object](self._1.asInstanceOf[Object])) case self: Tuple2[_, _] => - Tuple2(f(self._1), f(self._2)) + Tuple2(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object])) case self: Tuple3[_, _, _] => - Tuple3(f(self._1), f(self._2), f(self._3)) + Tuple3(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object])) case self: Tuple4[_, _, _, _] => - Tuple4(f(self._1), f(self._2), f(self._3), f(self._4)) + Tuple4(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object]), f[Object](self._4.asInstanceOf[Object])) case self: Tuple5[_, _, _, _, _] => - Tuple5(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5)) + Tuple5(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object]), f[Object](self._4.asInstanceOf[Object]), f[Object](self._5.asInstanceOf[Object])) case self: Tuple6[_, _, _, _, _, _] => - Tuple6(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6)) + Tuple6(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object]), f[Object](self._4.asInstanceOf[Object]), f[Object](self._5.asInstanceOf[Object]), f[Object](self._6.asInstanceOf[Object])) case self: Tuple7[_, _, _, _, _, _, _] => - Tuple7(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7)) + Tuple7(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object]), f[Object](self._4.asInstanceOf[Object]), f[Object](self._5.asInstanceOf[Object]), f[Object](self._6.asInstanceOf[Object]), f[Object](self._7.asInstanceOf[Object])) case self: Tuple8[_, _, _, _, _, _, _, _] => - Tuple8(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8)) + Tuple8(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object]), f[Object](self._4.asInstanceOf[Object]), f[Object](self._5.asInstanceOf[Object]), f[Object](self._6.asInstanceOf[Object]), f[Object](self._7.asInstanceOf[Object]), f[Object](self._8.asInstanceOf[Object])) case self: Tuple9[_, _, _, _, _, _, _, _, _] => - Tuple9(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9)) + Tuple9(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object]), f[Object](self._4.asInstanceOf[Object]), f[Object](self._5.asInstanceOf[Object]), f[Object](self._6.asInstanceOf[Object]), f[Object](self._7.asInstanceOf[Object]), f[Object](self._8.asInstanceOf[Object]), f[Object](self._9.asInstanceOf[Object])) case self: Tuple10[_, _, _, _, _, _, _, _, _, _] => - Tuple10(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10)) + Tuple10(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object]), f[Object](self._4.asInstanceOf[Object]), f[Object](self._5.asInstanceOf[Object]), f[Object](self._6.asInstanceOf[Object]), f[Object](self._7.asInstanceOf[Object]), f[Object](self._8.asInstanceOf[Object]), f[Object](self._9.asInstanceOf[Object]), f[Object](self._10.asInstanceOf[Object])) case self: Tuple11[_, _, _, _, _, _, _, _, _, _, _] => - Tuple11(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11)) + Tuple11(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object]), f[Object](self._4.asInstanceOf[Object]), f[Object](self._5.asInstanceOf[Object]), f[Object](self._6.asInstanceOf[Object]), f[Object](self._7.asInstanceOf[Object]), f[Object](self._8.asInstanceOf[Object]), f[Object](self._9.asInstanceOf[Object]), f[Object](self._10.asInstanceOf[Object]), f[Object](self._11.asInstanceOf[Object])) case self: Tuple12[_, _, _, _, _, _, _, _, _, _, _, _] => - Tuple12(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12)) + Tuple12(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object]), f[Object](self._4.asInstanceOf[Object]), f[Object](self._5.asInstanceOf[Object]), f[Object](self._6.asInstanceOf[Object]), f[Object](self._7.asInstanceOf[Object]), f[Object](self._8.asInstanceOf[Object]), f[Object](self._9.asInstanceOf[Object]), f[Object](self._10.asInstanceOf[Object]), f[Object](self._11.asInstanceOf[Object]), f[Object](self._12.asInstanceOf[Object])) case self: Tuple13[_, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple13(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13)) + Tuple13(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object]), f[Object](self._4.asInstanceOf[Object]), f[Object](self._5.asInstanceOf[Object]), f[Object](self._6.asInstanceOf[Object]), f[Object](self._7.asInstanceOf[Object]), f[Object](self._8.asInstanceOf[Object]), f[Object](self._9.asInstanceOf[Object]), f[Object](self._10.asInstanceOf[Object]), f[Object](self._11.asInstanceOf[Object]), f[Object](self._12.asInstanceOf[Object]), f[Object](self._13.asInstanceOf[Object])) case self: Tuple14[_, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple14(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13), f(self._14)) + Tuple14(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object]), f[Object](self._4.asInstanceOf[Object]), f[Object](self._5.asInstanceOf[Object]), f[Object](self._6.asInstanceOf[Object]), f[Object](self._7.asInstanceOf[Object]), f[Object](self._8.asInstanceOf[Object]), f[Object](self._9.asInstanceOf[Object]), f[Object](self._10.asInstanceOf[Object]), f[Object](self._11.asInstanceOf[Object]), f[Object](self._12.asInstanceOf[Object]), f[Object](self._13.asInstanceOf[Object]), f[Object](self._14.asInstanceOf[Object])) case self: Tuple15[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple15(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13), f(self._14), f(self._15)) + Tuple15(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object]), f[Object](self._4.asInstanceOf[Object]), f[Object](self._5.asInstanceOf[Object]), f[Object](self._6.asInstanceOf[Object]), f[Object](self._7.asInstanceOf[Object]), f[Object](self._8.asInstanceOf[Object]), f[Object](self._9.asInstanceOf[Object]), f[Object](self._10.asInstanceOf[Object]), f[Object](self._11.asInstanceOf[Object]), f[Object](self._12.asInstanceOf[Object]), f[Object](self._13.asInstanceOf[Object]), f[Object](self._14.asInstanceOf[Object]), f[Object](self._15.asInstanceOf[Object])) case self: Tuple16[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple16(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13), f(self._14), f(self._15), f(self._16)) + Tuple16(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object]), f[Object](self._4.asInstanceOf[Object]), f[Object](self._5.asInstanceOf[Object]), f[Object](self._6.asInstanceOf[Object]), f[Object](self._7.asInstanceOf[Object]), f[Object](self._8.asInstanceOf[Object]), f[Object](self._9.asInstanceOf[Object]), f[Object](self._10.asInstanceOf[Object]), f[Object](self._11.asInstanceOf[Object]), f[Object](self._12.asInstanceOf[Object]), f[Object](self._13.asInstanceOf[Object]), f[Object](self._14.asInstanceOf[Object]), f[Object](self._15.asInstanceOf[Object]), f[Object](self._16.asInstanceOf[Object])) case self: Tuple17[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple17(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13), f(self._14), f(self._15), f(self._16), f(self._17)) + Tuple17(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object]), f[Object](self._4.asInstanceOf[Object]), f[Object](self._5.asInstanceOf[Object]), f[Object](self._6.asInstanceOf[Object]), f[Object](self._7.asInstanceOf[Object]), f[Object](self._8.asInstanceOf[Object]), f[Object](self._9.asInstanceOf[Object]), f[Object](self._10.asInstanceOf[Object]), f[Object](self._11.asInstanceOf[Object]), f[Object](self._12.asInstanceOf[Object]), f[Object](self._13.asInstanceOf[Object]), f[Object](self._14.asInstanceOf[Object]), f[Object](self._15.asInstanceOf[Object]), f[Object](self._16.asInstanceOf[Object]), f[Object](self._17.asInstanceOf[Object])) case self: Tuple18[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple18(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13), f(self._14), f(self._15), f(self._16), f(self._17), f(self._18)) + Tuple18(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object]), f[Object](self._4.asInstanceOf[Object]), f[Object](self._5.asInstanceOf[Object]), f[Object](self._6.asInstanceOf[Object]), f[Object](self._7.asInstanceOf[Object]), f[Object](self._8.asInstanceOf[Object]), f[Object](self._9.asInstanceOf[Object]), f[Object](self._10.asInstanceOf[Object]), f[Object](self._11.asInstanceOf[Object]), f[Object](self._12.asInstanceOf[Object]), f[Object](self._13.asInstanceOf[Object]), f[Object](self._14.asInstanceOf[Object]), f[Object](self._15.asInstanceOf[Object]), f[Object](self._16.asInstanceOf[Object]), f[Object](self._17.asInstanceOf[Object]), f[Object](self._18.asInstanceOf[Object])) case self: Tuple19[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple19(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13), f(self._14), f(self._15), f(self._16), f(self._17), f(self._18), f(self._19)) + Tuple19(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object]), f[Object](self._4.asInstanceOf[Object]), f[Object](self._5.asInstanceOf[Object]), f[Object](self._6.asInstanceOf[Object]), f[Object](self._7.asInstanceOf[Object]), f[Object](self._8.asInstanceOf[Object]), f[Object](self._9.asInstanceOf[Object]), f[Object](self._10.asInstanceOf[Object]), f[Object](self._11.asInstanceOf[Object]), f[Object](self._12.asInstanceOf[Object]), f[Object](self._13.asInstanceOf[Object]), f[Object](self._14.asInstanceOf[Object]), f[Object](self._15.asInstanceOf[Object]), f[Object](self._16.asInstanceOf[Object]), f[Object](self._17.asInstanceOf[Object]), f[Object](self._18.asInstanceOf[Object]), f[Object](self._19.asInstanceOf[Object])) case self: Tuple20[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple20(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13), f(self._14), f(self._15), f(self._16), f(self._17), f(self._18), f(self._19), f(self._20)) + Tuple20(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object]), f[Object](self._4.asInstanceOf[Object]), f[Object](self._5.asInstanceOf[Object]), f[Object](self._6.asInstanceOf[Object]), f[Object](self._7.asInstanceOf[Object]), f[Object](self._8.asInstanceOf[Object]), f[Object](self._9.asInstanceOf[Object]), f[Object](self._10.asInstanceOf[Object]), f[Object](self._11.asInstanceOf[Object]), f[Object](self._12.asInstanceOf[Object]), f[Object](self._13.asInstanceOf[Object]), f[Object](self._14.asInstanceOf[Object]), f[Object](self._15.asInstanceOf[Object]), f[Object](self._16.asInstanceOf[Object]), f[Object](self._17.asInstanceOf[Object]), f[Object](self._18.asInstanceOf[Object]), f[Object](self._19.asInstanceOf[Object]), f[Object](self._20.asInstanceOf[Object])) case self: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple21(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13), f(self._14), f(self._15), f(self._16), f(self._17), f(self._18), f(self._19), f(self._20), f(self._21)) + Tuple21(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object]), f[Object](self._4.asInstanceOf[Object]), f[Object](self._5.asInstanceOf[Object]), f[Object](self._6.asInstanceOf[Object]), f[Object](self._7.asInstanceOf[Object]), f[Object](self._8.asInstanceOf[Object]), f[Object](self._9.asInstanceOf[Object]), f[Object](self._10.asInstanceOf[Object]), f[Object](self._11.asInstanceOf[Object]), f[Object](self._12.asInstanceOf[Object]), f[Object](self._13.asInstanceOf[Object]), f[Object](self._14.asInstanceOf[Object]), f[Object](self._15.asInstanceOf[Object]), f[Object](self._16.asInstanceOf[Object]), f[Object](self._17.asInstanceOf[Object]), f[Object](self._18.asInstanceOf[Object]), f[Object](self._19.asInstanceOf[Object]), f[Object](self._20.asInstanceOf[Object]), f[Object](self._21.asInstanceOf[Object])) case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] => - Tuple22(f(self._1), f(self._2), f(self._3), f(self._4), f(self._5), f(self._6), f(self._7), f(self._8), f(self._9), f(self._10), f(self._11), f(self._12), f(self._13), f(self._14), f(self._15), f(self._16), f(self._17), f(self._18), f(self._19), f(self._20), f(self._21), f(self._22)) + Tuple22(f[Object](self._1.asInstanceOf[Object]), f[Object](self._2.asInstanceOf[Object]), f[Object](self._3.asInstanceOf[Object]), f[Object](self._4.asInstanceOf[Object]), f[Object](self._5.asInstanceOf[Object]), f[Object](self._6.asInstanceOf[Object]), f[Object](self._7.asInstanceOf[Object]), f[Object](self._8.asInstanceOf[Object]), f[Object](self._9.asInstanceOf[Object]), f[Object](self._10.asInstanceOf[Object]), f[Object](self._11.asInstanceOf[Object]), f[Object](self._12.asInstanceOf[Object]), f[Object](self._13.asInstanceOf[Object]), f[Object](self._14.asInstanceOf[Object]), f[Object](self._15.asInstanceOf[Object]), f[Object](self._16.asInstanceOf[Object]), f[Object](self._17.asInstanceOf[Object]), f[Object](self._18.asInstanceOf[Object]), f[Object](self._19.asInstanceOf[Object]), f[Object](self._20.asInstanceOf[Object]), f[Object](self._21.asInstanceOf[Object]), f[Object](self._22.asInstanceOf[Object])) } res.asInstanceOf[Result] } - def dynamicMap[This <: Tuple, F[_]](self: This, f: [t] => t => F[t]): Map[This, F] = { - type Result = Map[This, F] - (self: Any) match { - case xxl: TupleXXL => - TupleXXL.fromIArray( - xxl.elems.asInstanceOf[Array[Object]].map(f[Object]).asInstanceOf[IArray[Object]] - ).asInstanceOf[Result] - case _ => - specialCaseMap(self, f) - } + // def dynamicMap[This <: Tuple, F[_]](self: This, f: [t] => t => F[t]): Map[This, F] = { + // type Result = Map[This, F] + // (self: Any) match { + // case xxl: TupleXXL => + // TupleXXL.fromIArray( + // xxl.elems.asInstanceOf[Array[Object]].map(f[Object]).asInstanceOf[IArray[Object]] + // ).asInstanceOf[Result] + // case _ => + // specialCaseMap(self, f) + // } + // } + + // def dynamicMap[This <: Tuple, F[_]](self: This, f: [t] => t => F[t]): Map[This, F] = { + // type Result = Map[This, F] + // dynamicFromIArray[Result](dynamicToIArray(self).asInstanceOf[Array[Object]].map(f[Object]).asInstanceOf[IArray[Object]]) + // } + + def dynamicMap[This <: Tuple, F[_]](self: This, f: [t] => t => F[t]): Map[This, F] = (self: Any) match { + case self: Unit => ().asInstanceOf[Map[This, F]] + case _ => + Tuple.fromArray(self.asInstanceOf[Product].productIterator.map(f(_)).toArray) // TODO use toIArray of Object to avoid double/triple array copy + .asInstanceOf[Map[This, F]] } def consIterator(head: Any, tail: Tuple): Iterator[Any] = From 025e91fa6ce4f053212598a55d7992794b81153e Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Sat, 7 Dec 2019 14:41:27 +0100 Subject: [PATCH 30/32] Add necessary method for bootstrapped compilation --- library/src/scala/runtime/DynamicTuple.scala | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index fd0b40c7bd7c..0673e9f20591 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -6,6 +6,24 @@ object DynamicTuple { inline val MaxSpecialized = 22 inline private val XXL = MaxSpecialized + 1 + def to$Array(xs: Tuple, n: Int) = { + val arr = new Array[Object](n) + var i = 0 + var it = xs.asInstanceOf[Product].productIterator + while (i < n) { + arr(i) = it.next().asInstanceOf[Object] + i += 1 + } + arr + } + + def cons$Array[H](x: H, elems: Array[Object]): Array[Object] = { + val elems1 = new Array[Object](elems.length + 1) + elems1(0) = x.asInstanceOf[Object] + System.arraycopy(elems, 0, elems1, 1, elems.length) + elems1 + } + def dynamicToArray(self: Tuple): Array[Object] = (self: Any) match { case self: Unit => Array.emptyObjectArray case self: TupleXXL => self.toArray From b1977cb639aa87e4b92f3a49ec1a4b94957c9aa5 Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Thu, 12 Dec 2019 17:44:18 +0100 Subject: [PATCH 31/32] Remove unintentionnal comments --- library/src/scala/runtime/DynamicTuple.scala | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index 0673e9f20591..7a87819273f2 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -466,23 +466,6 @@ object DynamicTuple { res.asInstanceOf[Result] } - // def dynamicMap[This <: Tuple, F[_]](self: This, f: [t] => t => F[t]): Map[This, F] = { - // type Result = Map[This, F] - // (self: Any) match { - // case xxl: TupleXXL => - // TupleXXL.fromIArray( - // xxl.elems.asInstanceOf[Array[Object]].map(f[Object]).asInstanceOf[IArray[Object]] - // ).asInstanceOf[Result] - // case _ => - // specialCaseMap(self, f) - // } - // } - - // def dynamicMap[This <: Tuple, F[_]](self: This, f: [t] => t => F[t]): Map[This, F] = { - // type Result = Map[This, F] - // dynamicFromIArray[Result](dynamicToIArray(self).asInstanceOf[Array[Object]].map(f[Object]).asInstanceOf[IArray[Object]]) - // } - def dynamicMap[This <: Tuple, F[_]](self: This, f: [t] => t => F[t]): Map[This, F] = (self: Any) match { case self: Unit => ().asInstanceOf[Map[This, F]] case _ => From 08613cba238d1bf97fd8826be51ceae88b40252f Mon Sep 17 00:00:00 2001 From: Antoine Brunner Date: Sun, 15 Dec 2019 10:07:40 +0100 Subject: [PATCH 32/32] Move unit cases to improve performance --- library/src/scala/runtime/DynamicTuple.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/src/scala/runtime/DynamicTuple.scala b/library/src/scala/runtime/DynamicTuple.scala index 7a87819273f2..7338de49ca22 100644 --- a/library/src/scala/runtime/DynamicTuple.scala +++ b/library/src/scala/runtime/DynamicTuple.scala @@ -25,15 +25,15 @@ object DynamicTuple { } def dynamicToArray(self: Tuple): Array[Object] = (self: Any) match { - case self: Unit => Array.emptyObjectArray case self: TupleXXL => self.toArray case self: Product => productToArray(self) + case self: Unit => Array.emptyObjectArray } def dynamicToIArray(self: Tuple): IArray[Object] = (self: Any) match { - case self: Unit => Array.emptyObjectArray.asInstanceOf[IArray[Object]] // TODO use IArray.emptyObjectIArray case self: TupleXXL => self.elems case self: Product => productToArray(self).asInstanceOf[IArray[Object]] + case self: Unit => Array.emptyObjectArray.asInstanceOf[IArray[Object]] } def productToArray(self: Product): Array[Object] = {