Skip to content

Commit 6011847

Browse files
authored
Merge pull request #12935 from dotty-staging/uniques-weakhashset-3
Use WeakHashSet instead of HashSet for hash-consing types
2 parents 4b5a351 + f36f95b commit 6011847

File tree

6 files changed

+91
-128
lines changed

6 files changed

+91
-128
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/core/Contexts.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ object Contexts {
559559
def platform: Platform = base.platform
560560
def pendingUnderlying: util.HashSet[Type] = base.pendingUnderlying
561561
def uniqueNamedTypes: Uniques.NamedTypeUniques = base.uniqueNamedTypes
562-
def uniques: util.HashSet[Type] = base.uniques
562+
def uniques: util.WeakHashSet[Type] = base.uniques
563563

564564
def initialize()(using Context): Unit = base.initialize()
565565
}

compiler/src/dotty/tools/dotc/core/Uniques.scala

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ package core
44
import Types._, Contexts._, util.Stats._, Hashable._, Names._
55
import config.Config
66
import Decorators._
7-
import util.{HashSet, Stats}
7+
import util.{WeakHashSet, Stats}
8+
import WeakHashSet.Entry
9+
import scala.annotation.tailrec
810

9-
class Uniques extends HashSet[Type](Config.initialUniquesCapacity):
11+
class Uniques extends WeakHashSet[Type](Config.initialUniquesCapacity):
1012
override def hash(x: Type): Int = x.hash
1113
override def isEqual(x: Type, y: Type) = x.eql(y)
1214

@@ -32,7 +34,7 @@ object Uniques:
3234
if tp.hash == NotCached then tp
3335
else ctx.uniques.put(tp).asInstanceOf[T]
3436

35-
final class NamedTypeUniques extends HashSet[NamedType](Config.initialUniquesCapacity * 4) with Hashable:
37+
final class NamedTypeUniques extends WeakHashSet[NamedType](Config.initialUniquesCapacity * 4) with Hashable:
3638
override def hash(x: NamedType): Int = x.hash
3739

3840
def enterIfNew(prefix: Type, designator: Designator, isTerm: Boolean)(using Context): NamedType =
@@ -43,17 +45,25 @@ object Uniques:
4345
else new CachedTypeRef(prefix, designator, h)
4446
if h == NotCached then newType
4547
else
48+
// Inlined from WeakHashSet#put
4649
Stats.record(statsItem("put"))
47-
var idx = index(h)
48-
var e = entryAt(idx)
49-
while e != null do
50-
if (e.prefix eq prefix) && (e.designator eq designator) && (e.isTerm == isTerm) then return e
51-
idx = nextIndex(idx)
52-
e = entryAt(idx)
53-
addEntryAt(idx, newType)
50+
removeStaleEntries()
51+
val bucket = index(h)
52+
val oldHead = table(bucket)
53+
54+
@tailrec
55+
def linkedListLoop(entry: Entry[NamedType]): NamedType = entry match
56+
case null => addEntryAt(bucket, newType, h, oldHead)
57+
case _ =>
58+
val e = entry.get
59+
if e != null && (e.prefix eq prefix) && (e.designator eq designator) && (e.isTerm == isTerm) then e
60+
else linkedListLoop(entry.tail)
61+
62+
linkedListLoop(oldHead)
63+
end if
5464
end NamedTypeUniques
5565

56-
final class AppliedUniques extends HashSet[AppliedType](Config.initialUniquesCapacity * 2) with Hashable:
66+
final class AppliedUniques extends WeakHashSet[AppliedType](Config.initialUniquesCapacity * 2) with Hashable:
5767
override def hash(x: AppliedType): Int = x.hash
5868

5969
def enterIfNew(tycon: Type, args: List[Type]): AppliedType =
@@ -62,13 +72,21 @@ object Uniques:
6272
if monitored then recordCaching(h, classOf[CachedAppliedType])
6373
if h == NotCached then newType
6474
else
75+
// Inlined from WeakHashSet#put
6576
Stats.record(statsItem("put"))
66-
var idx = index(h)
67-
var e = entryAt(idx)
68-
while e != null do
69-
if (e.tycon eq tycon) && e.args.eqElements(args) then return e
70-
idx = nextIndex(idx)
71-
e = entryAt(idx)
72-
addEntryAt(idx, newType)
77+
removeStaleEntries()
78+
val bucket = index(h)
79+
val oldHead = table(bucket)
80+
81+
@tailrec
82+
def linkedListLoop(entry: Entry[AppliedType]): AppliedType = entry match
83+
case null => addEntryAt(bucket, newType, h, oldHead)
84+
case _ =>
85+
val e = entry.get
86+
if e != null && (e.tycon eq tycon) && e.args.eqElements(args) then e
87+
else linkedListLoop(entry.tail)
88+
89+
linkedListLoop(oldHead)
90+
end if
7391
end AppliedUniques
7492
end Uniques

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

0 commit comments

Comments
 (0)