Skip to content

Commit c1b4343

Browse files
oderskyanatoliykmetyuk
authored andcommitted
Optimize SimpleIdentitySet some more
- drop -- since it is not used anymore. - optimize ++ by special casing empty sets and large, array-backed sets.
1 parent a1d9c55 commit c1b4343

File tree

1 file changed

+37
-6
lines changed

1 file changed

+37
-6
lines changed

compiler/src/dotty/tools/dotc/util/SimpleIdentitySet.scala

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package dotty.tools.dotc.util
22

3-
import collection.mutable.ListBuffer
3+
import collection.mutable
44

55
/** A simple linked set with `eq` as the comparison, optimized for small sets.
66
* It has linear complexity for `contains`, `+`, and `-`.
@@ -15,10 +15,13 @@ abstract class SimpleIdentitySet[+Elem <: AnyRef] {
1515
def exists[E >: Elem <: AnyRef](p: E => Boolean): Boolean
1616
def /: [A, E >: Elem <: AnyRef](z: A)(f: (A, E) => A): A
1717
def toList: List[Elem]
18-
final def ++ [E >: Elem <: AnyRef](that: SimpleIdentitySet[E]): SimpleIdentitySet[E] =
18+
def ++ [E >: Elem <: AnyRef](that: SimpleIdentitySet[E]): SimpleIdentitySet[E] = {
19+
if (this.size == 0) that
20+
else if (that.size == 0) this
21+
else concat(that)
22+
}
23+
protected def concat[E >: Elem <: AnyRef](that: SimpleIdentitySet[E]): SimpleIdentitySet[E] =
1924
((this: SimpleIdentitySet[E]) /: that)(_ + _)
20-
final def -- [E >: Elem <: AnyRef](that: SimpleIdentitySet[E]): SimpleIdentitySet[Elem] =
21-
(this /: that)(_ - _)
2225
override def toString: String = toList.mkString("(", ", ", ")")
2326
}
2427

@@ -96,7 +99,7 @@ object SimpleIdentitySet {
9699
def toList = x0.asInstanceOf[Elem] :: x1.asInstanceOf[Elem] :: x2.asInstanceOf[Elem] :: Nil
97100
}
98101

99-
private class SetN[+Elem <: AnyRef](xs: Array[AnyRef]) extends SimpleIdentitySet[Elem] {
102+
private class SetN[+Elem <: AnyRef](val xs: Array[AnyRef]) extends SimpleIdentitySet[Elem] {
100103
def size = xs.length
101104
def + [E >: Elem <: AnyRef](x: E): SimpleIdentitySet[E] =
102105
if (contains(x)) this
@@ -136,9 +139,37 @@ object SimpleIdentitySet {
136139
def /: [A, E >: Elem <: AnyRef](z: A)(f: (A, E) => A): A =
137140
(z /: xs.asInstanceOf[Array[E]])(f)
138141
def toList: List[Elem] = {
139-
val buf = new ListBuffer[Elem]
142+
val buf = new mutable.ListBuffer[Elem]
140143
foreach(buf += _)
141144
buf.toList
142145
}
146+
override def concat [E >: Elem <: AnyRef](that: SimpleIdentitySet[E]): SimpleIdentitySet[E] =
147+
that match {
148+
case that: SetN[_] =>
149+
var toAdd: mutable.ArrayBuffer[AnyRef] = null
150+
var i = 0
151+
val limit = that.xs.length
152+
while (i < limit) {
153+
val elem = that.xs(i)
154+
if (!contains(elem)) {
155+
if (toAdd == null) toAdd = new mutable.ArrayBuffer
156+
toAdd += elem
157+
}
158+
i += 1
159+
}
160+
if (toAdd == null) this
161+
else {
162+
val numAdded = toAdd.size
163+
val xs1 = new Array[AnyRef](size + numAdded)
164+
System.arraycopy(xs, 0, xs1, 0, size)
165+
var i = 0
166+
while (i < numAdded) {
167+
xs1(i + size) = toAdd(i)
168+
i += 1
169+
}
170+
new SetN[E](xs1)
171+
}
172+
case _ => super.concat(that)
173+
}
143174
}
144175
}

0 commit comments

Comments
 (0)