Skip to content

Commit c8cee34

Browse files
authored
Merge pull request scala/scala#8707 from rorygraves/mike/2.12.x_quick_hasForEachEntry
Add HasForeachEntry to support optimizations to avoid `Tuple2` allocations.
2 parents 6a3a3c6 + a74c4c0 commit c8cee34

File tree

5 files changed

+48
-7
lines changed

5 files changed

+48
-7
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Scala (https://www.scala-lang.org)
3+
*
4+
* Copyright EPFL and Lightbend, Inc.
5+
*
6+
* Licensed under Apache License 2.0
7+
* (http://www.apache.org/licenses/LICENSE-2.0).
8+
*
9+
* See the NOTICE file distributed with this work for
10+
* additional information regarding copyright ownership.
11+
*/
12+
13+
package scala.collection.immutable
14+
15+
private[immutable] trait HasForeachEntry[A, +B] {
16+
private[immutable] def foreachEntry[U](f: (A, B) => U): Unit
17+
}

library/src/scala/collection/immutable/HashMap.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ sealed class HashMap[A, +B] extends AbstractMap[A, B]
4444
with MapLike[A, B, HashMap[A, B]]
4545
with Serializable
4646
with CustomParallelizable[(A, B), ParHashMap[A, B]]
47+
with HasForeachEntry[A, B]
4748
{
4849
import HashMap.{nullToEmpty, bufferSize}
4950

library/src/scala/collection/immutable/ListMap.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ object ListMap extends ImmutableMapFactory[ListMap] {
7373
sealed class ListMap[A, +B] extends AbstractMap[A, B]
7474
with Map[A, B]
7575
with MapLike[A, B, ListMap[A, B]]
76-
with Serializable {
76+
with Serializable
77+
with HasForeachEntry[A,B] {
7778

7879
override def empty = ListMap.empty
7980

library/src/scala/collection/immutable/Map.scala

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ object Map extends ImmutableMapFactory[Map] {
9999
}
100100

101101
@SerialVersionUID(-5626373049574850357L)
102-
private object EmptyMap extends AbstractMap[Any, Nothing] with Map[Any, Nothing] with Serializable {
102+
private object EmptyMap extends AbstractMap[Any, Nothing] with Map[Any, Nothing] with Serializable with HasForeachEntry[Any, Nothing]{
103103
override def size: Int = 0
104104
override def apply(key: Any) = throw new NoSuchElementException("key not found: " + key)
105105
override def contains(key: Any) = false
@@ -110,10 +110,11 @@ object Map extends ImmutableMapFactory[Map] {
110110
def + [V1](kv: (Any, V1)): Map[Any, V1] = updated(kv._1, kv._2)
111111
def - (key: Any): Map[Any, Nothing] = this
112112
override def hashCode: Int = MurmurHash3.emptyMapHash
113+
override private[immutable] def foreachEntry[U](f: (Any, Nothing) => U): Unit = ()
113114
}
114115

115116
@SerialVersionUID(-9131943191104946031L)
116-
class Map1[K, +V](key1: K, value1: V) extends AbstractMap[K, V] with Map[K, V] with Serializable {
117+
class Map1[K, +V](key1: K, value1: V) extends AbstractMap[K, V] with Map[K, V] with Serializable with HasForeachEntry[K, V] {
117118
override def size = 1
118119
override def apply(key: K) = if (key == key1) value1 else throw new NoSuchElementException("key not found: " + key)
119120
override def contains(key: K) = key == key1
@@ -148,10 +149,13 @@ object Map extends ImmutableMapFactory[Map] {
148149
h = MurmurHash3.mixLast(h, c)
149150
MurmurHash3.finalizeHash(h, N)
150151
}
152+
override private[immutable] def foreachEntry[U](f: (K, V) => U): Unit = {
153+
f(key1, value1)
154+
}
151155
}
152156

153157
@SerialVersionUID(-85684685400398742L)
154-
class Map2[K, +V](key1: K, value1: V, key2: K, value2: V) extends AbstractMap[K, V] with Map[K, V] with Serializable {
158+
class Map2[K, +V](key1: K, value1: V, key2: K, value2: V) extends AbstractMap[K, V] with Map[K, V] with Serializable with HasForeachEntry[K, V] {
155159
override def size = 2
156160
override def apply(key: K) =
157161
if (key == key1) value1
@@ -201,10 +205,14 @@ object Map extends ImmutableMapFactory[Map] {
201205
h = MurmurHash3.mixLast(h, c)
202206
MurmurHash3.finalizeHash(h, N)
203207
}
208+
override private[immutable] def foreachEntry[U](f: (K, V) => U): Unit = {
209+
f(key1, value1)
210+
f(key2, value2)
211+
}
204212
}
205213

206214
@SerialVersionUID(-6400718707310517135L)
207-
class Map3[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V) extends AbstractMap[K, V] with Map[K, V] with Serializable {
215+
class Map3[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V) extends AbstractMap[K, V] with Map[K, V] with Serializable with HasForeachEntry[K, V] {
208216
override def size = 3
209217
override def apply(key: K) =
210218
if (key == key1) value1
@@ -264,10 +272,15 @@ object Map extends ImmutableMapFactory[Map] {
264272
h = MurmurHash3.mixLast(h, c)
265273
MurmurHash3.finalizeHash(h, N)
266274
}
275+
override private[immutable] def foreachEntry[U](f: (K, V) => U): Unit = {
276+
f(key1, value1)
277+
f(key2, value2)
278+
f(key3, value3)
279+
}
267280
}
268281

269282
@SerialVersionUID(-7992135791595275193L)
270-
class Map4[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V, key4: K, value4: V) extends AbstractMap[K, V] with Map[K, V] with Serializable {
283+
class Map4[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V, key4: K, value4: V) extends AbstractMap[K, V] with Map[K, V] with Serializable with HasForeachEntry[K, V] {
271284
override def size = 4
272285
override def apply(key: K) =
273286
if (key == key1) value1
@@ -337,6 +350,12 @@ object Map extends ImmutableMapFactory[Map] {
337350
h = MurmurHash3.mixLast(h, c)
338351
MurmurHash3.finalizeHash(h, N)
339352
}
353+
override private[immutable] def foreachEntry[U](f: (K, V) => U): Unit = {
354+
f(key1, value1)
355+
f(key2, value2)
356+
f(key3, value3)
357+
f(key4, value4)
358+
}
340359
}
341360
private [immutable] final class HashCodeAccumulator extends scala.runtime.AbstractFunction2[Any, Any, Unit] {
342361
import scala.util.hashing.MurmurHash3

library/src/scala/collection/immutable/TreeMap.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ final class TreeMap[A, +B] private (tree: RB.Tree[A, B])(implicit val ordering:
5252
extends SortedMap[A, B]
5353
with SortedMapLike[A, B, TreeMap[A, B]]
5454
with MapLike[A, B, TreeMap[A, B]]
55-
with Serializable {
55+
with Serializable
56+
with HasForeachEntry[A, B] {
5657

5758
override protected[this] def newBuilder : Builder[(A, B), TreeMap[A, B]] =
5859
TreeMap.newBuilder[A, B]
@@ -205,6 +206,8 @@ final class TreeMap[A, +B] private (tree: RB.Tree[A, B])(implicit val ordering:
205206

206207
override def foreach[U](f : ((A,B)) => U) = RB.foreach(tree, f)
207208

209+
override private[immutable] def foreachEntry[U](f: (A, B) => U): Unit = RB.foreachEntry(tree, f)
210+
208211
override def hashCode(): Int = {
209212
if (isEmpty) {
210213
MurmurHash3.emptyMapHash

0 commit comments

Comments
 (0)