Skip to content

Commit 82cd467

Browse files
committed
Make util.WeakHashSet a subclass of util.MutableSet
Thus making it a drop-in replacement for util.HashSet which will be useful in the next commit where we'll use it in Uniques. Also add `@constructorOnly` annotations for clarity. Also remove all existing references to WeakHashSet in the code base since it turns out they were all dead code.
1 parent 0722bf4 commit 82cd467

File tree

4 files changed

+24
-59
lines changed

4 files changed

+24
-59
lines changed

compiler/src/dotty/tools/backend/jvm/BTypesFromSymbols.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import dotty.tools.dotc.core.Phases._
1313
import dotty.tools.dotc.core.Symbols._
1414
import dotty.tools.dotc.core.Phases.Phase
1515
import dotty.tools.dotc.transform.SymUtils._
16-
import dotty.tools.dotc.util.WeakHashSet
1716

1817
/**
1918
* This class mainly contains the method classBTypeFromSymbol, which extracts the necessary
@@ -49,7 +48,6 @@ class BTypesFromSymbols[I <: DottyBackendInterface](val int: I) extends BTypes {
4948
def newAnyRefMap[K <: AnyRef, V](): mutable.AnyRefMap[K, V] = new mutable.AnyRefMap[K, V]()
5049
def newWeakMap[K, V](): mutable.WeakHashMap[K, V] = new mutable.WeakHashMap[K, V]()
5150
def recordCache[T <: Clearable](cache: T): T = cache
52-
def newWeakSet[K >: Null <: AnyRef](): WeakHashSet[K] = new WeakHashSet[K]()
5351
def newMap[K, V](): mutable.HashMap[K, V] = new mutable.HashMap[K, V]()
5452
def newSet[K](): mutable.Set[K] = new mutable.HashSet[K]
5553
}
@@ -60,7 +58,6 @@ class BTypesFromSymbols[I <: DottyBackendInterface](val int: I) extends BTypes {
6058
def newWeakMap[K, V](): collection.mutable.WeakHashMap[K, V]
6159
def newMap[K, V](): collection.mutable.HashMap[K, V]
6260
def newSet[K](): collection.mutable.Set[K]
63-
def newWeakSet[K >: Null <: AnyRef](): dotty.tools.dotc.util.WeakHashSet[K]
6461
def newAnyRefMap[K <: AnyRef, V](): collection.mutable.AnyRefMap[K, V]
6562
}
6663

compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import scala.annotation.threadUnsafe
1212
import scala.collection.generic.Clearable
1313
import scala.collection.mutable
1414
import scala.reflect.ClassTag
15-
import dotty.tools.dotc.util.WeakHashSet
1615
import dotty.tools.io.AbstractFile
1716
import scala.tools.asm.AnnotationVisitor
1817
import dotty.tools.dotc.core._

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ abstract class MutableSet[T] extends ReadOnlySet[T]:
88
def +=(x: T): Unit
99

1010
/** Like `+=` but return existing element equal to `x` of it exists,
11-
* `x` itself otherwose.
11+
* `x` itself otherwise.
1212
*/
1313
def put(x: T): T
1414

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

Lines changed: 23 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
/** Taken from the original implementation of WeakHashSet in scala-reflect
1+
/** Adapted from the original implementation of WeakHashSet in scala-reflect
22
*/
33
package dotty.tools.dotc.util
44

55
import java.lang.ref.{ReferenceQueue, WeakReference}
66

7-
import scala.annotation.tailrec
7+
import scala.annotation.{ constructorOnly, tailrec }
88
import scala.collection.mutable
99

1010
/**
@@ -17,7 +17,7 @@ import scala.collection.mutable
1717
* This set implementation is not in general thread safe without external concurrency control. However it behaves
1818
* properly when GC concurrently collects elements in this set.
1919
*/
20-
final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) extends mutable.Set[A] {
20+
final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) extends MutableSet[A] {
2121

2222
import WeakHashSet._
2323

@@ -61,8 +61,6 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
6161

6262
private def computeThreshold: Int = (table.size * loadFactor).ceil.toInt
6363

64-
def get(elem: A): Option[A] = Option(findEntry(elem))
65-
6664
/**
6765
* find the bucket associated with an element's hash code
6866
*/
@@ -86,6 +84,7 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
8684
* remove a single entry from a linked list in a given bucket
8785
*/
8886
private def remove(bucket: Int, prevEntry: Entry[A], entry: Entry[A]): Unit = {
87+
Stats.record(statsItem("remove"))
8988
prevEntry match {
9089
case null => table(bucket) = entry.tail
9190
case _ => prevEntry.tail = entry.tail
@@ -122,6 +121,7 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
122121
* Double the size of the internal table
123122
*/
124123
private def resize(): Unit = {
124+
Stats.record(statsItem("resize"))
125125
val oldTable = table
126126
table = new Array[Entry[A]](oldTable.size * 2)
127127
threshold = computeThreshold
@@ -145,12 +145,10 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
145145
tableLoop(0)
146146
}
147147

148-
def contains(elem: A): Boolean = findEntry(elem) ne null
149-
150-
// from scala.reflect.internal.Set, find an element or null if it isn't contained
151-
def findEntry(elem: A): A = elem match {
148+
def lookup(elem: A): A | Null = elem match {
152149
case null => throw new NullPointerException("WeakHashSet cannot hold nulls")
153150
case _ =>
151+
Stats.record(statsItem("lookup"))
154152
removeStaleEntries()
155153
val hash = elem.hashCode
156154
val bucket = bucketFor(hash)
@@ -166,10 +164,11 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
166164

167165
linkedListLoop(table(bucket))
168166
}
169-
// add an element to this set unless it's already in there and return the element
170-
def findEntryOrUpdate(elem: A): A = elem match {
167+
168+
def put(elem: A): A = elem match {
171169
case null => throw new NullPointerException("WeakHashSet cannot hold nulls")
172170
case _ =>
171+
Stats.record(statsItem("put"))
173172
removeStaleEntries()
174173
val hash = elem.hashCode
175174
val bucket = bucketFor(hash)
@@ -194,36 +193,12 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
194193
linkedListLoop(oldHead)
195194
}
196195

197-
// add an element to this set unless it's already in there and return this set
198-
override def addOne(elem: A): this.type = elem match {
199-
case null => throw new NullPointerException("WeakHashSet cannot hold nulls")
200-
case _ =>
201-
removeStaleEntries()
202-
val hash = elem.hashCode
203-
val bucket = bucketFor(hash)
204-
val oldHead = table(bucket)
205-
206-
def add(): Unit = {
207-
table(bucket) = new Entry(elem, hash, oldHead, queue)
208-
count += 1
209-
if (count > threshold) resize()
210-
}
211-
212-
@tailrec
213-
def linkedListLoop(entry: Entry[A]): Unit = entry match {
214-
case null => add()
215-
case _ if elem.equals(entry.get) => ()
216-
case _ => linkedListLoop(entry.tail)
217-
}
196+
def +=(elem: A): Unit = put(elem)
218197

219-
linkedListLoop(oldHead)
220-
this
221-
}
222-
223-
// remove an element from this set and return this set
224-
override def subtractOne(elem: A): this.type = elem match {
225-
case null => this
198+
def -=(elem: A): Unit = elem match {
199+
case null =>
226200
case _ =>
201+
Stats.record(statsItem("-="))
227202
removeStaleEntries()
228203
val bucket = bucketFor(elem.hashCode)
229204

@@ -237,11 +212,9 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
237212
}
238213

239214
linkedListLoop(null, table(bucket))
240-
this
241215
}
242216

243-
// empty this set
244-
override def clear(): Unit = {
217+
def clear(): Unit = {
245218
table = new Array[Entry[A]](table.size)
246219
threshold = computeThreshold
247220
count = 0
@@ -251,21 +224,11 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
251224
queueLoop()
252225
}
253226

254-
// true if this set is empty
255-
override def empty: This = new WeakHashSet[A](initialCapacity, loadFactor)
256-
257-
// the number of elements in this set
258-
override def size: Int = {
227+
def size: Int = {
259228
removeStaleEntries()
260229
count
261230
}
262231

263-
override def isEmpty: Boolean = size == 0
264-
override def foreach[U](f: A => U): Unit = iterator foreach f
265-
266-
// It has the `()` because iterator runs `removeStaleEntries()`
267-
override def toList(): List[A] = iterator.toList
268-
269232
// Iterator over all the elements in this set in no particular order
270233
override def iterator: Iterator[A] = {
271234
removeStaleEntries()
@@ -318,6 +281,12 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
318281
}
319282
}
320283

284+
protected def statsItem(op: String): String = {
285+
val prefix = "WeakHashSet."
286+
val suffix = getClass.getSimpleName
287+
s"$prefix$op $suffix"
288+
}
289+
321290
/**
322291
* Diagnostic information about the internals of this set. Not normally
323292
* needed by ordinary code, but may be useful for diagnosing performance problems
@@ -386,7 +355,7 @@ object WeakHashSet {
386355
* A single entry in a WeakHashSet. It's a WeakReference plus a cached hash code and
387356
* a link to the next Entry in the same bucket
388357
*/
389-
private class Entry[A](element: A, val hash:Int, var tail: Entry[A], queue: ReferenceQueue[A]) extends WeakReference[A](element, queue)
358+
private class Entry[A](@constructorOnly element: A, val hash:Int, var tail: Entry[A], @constructorOnly queue: ReferenceQueue[A]) extends WeakReference[A](element, queue)
390359

391360
private final val defaultInitialCapacity = 16
392361
private final val defaultLoadFactor = .75

0 commit comments

Comments
 (0)