Skip to content

Commit 2acc7b3

Browse files
Merge pull request #3122 from dotty-staging/homogenize-symbol-maps
Homogenize mutable symbol maps
2 parents 9a0c822 + 9ce9ea3 commit 2acc7b3

22 files changed

+127
-63
lines changed

compiler/sjs/backend/sjs/JSPrimitives.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class JSPrimitives(ctx: Context) extends DottyPrimitives(ctx) {
5959
/** Initialize the primitive map */
6060
private def initJSPrimitives(implicit ctx: Context): Map[Symbol, Int] = {
6161

62-
val primitives = new mutable.HashMap[Symbol, Int]()
62+
val primitives = newMutableSymbolMap[Int]
6363

6464
// !!! Code duplicate with DottyPrimitives
6565
/** Add a primitive operation to the map */

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ class GenBCode extends Phase {
4343
private val entryPoints = new mutable.HashSet[Symbol]()
4444
def registerEntryPoint(sym: Symbol) = entryPoints += sym
4545

46-
private val superCallsMap = new mutable.HashMap[Symbol, Set[ClassSymbol]]()
46+
private val superCallsMap = newMutableSymbolMap[Set[ClassSymbol]]
4747
def registerSuperCall(sym: Symbol, calls: ClassSymbol) = {
4848
val old = superCallsMap.getOrElse(sym, Set.empty)
49-
superCallsMap.put(sym, old + calls)
49+
superCallsMap.update(sym, old + calls)
5050
}
5151

5252
private[this] var myOutput: AbstractFile = _

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class LabelDefs extends MiniPhase {
7676
case t: DefDef =>
7777
assert(t.symbol is Label)
7878
EmptyTree
79-
case _ => if (labelDefs.nonEmpty) super.transform(tree) else tree
79+
case _ => if (!labelDefs.isEmpty) super.transform(tree) else tree
8080
}
8181
}
8282
}
@@ -86,9 +86,9 @@ class LabelDefs extends MiniPhase {
8686
}
8787
}
8888

89-
private def collectLabelDefs(tree: Tree)(implicit ctx: Context): mutable.HashMap[Symbol, DefDef] = {
89+
private def collectLabelDefs(tree: Tree)(implicit ctx: Context): MutableSymbolMap[DefDef] = {
9090
// labelSymbol -> Defining tree
91-
val labelDefs = new mutable.HashMap[Symbol, DefDef]()
91+
val labelDefs = newMutableSymbolMap[DefDef]
9292
new TreeTraverser {
9393
override def traverse(tree: Tree)(implicit ctx: Context): Unit = tree match {
9494
case t: DefDef =>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ class DottyPrimitives(ctx: Context) {
128128
implicit val ctx = this.ctx
129129

130130
import core.Symbols.defn
131-
val primitives = new mutable.HashMap[Symbol, Int]()
131+
val primitives = core.Symbols.newMutableSymbolMap[Int]
132132

133133
/** Add a primitive operation to the map */
134134
def addPrimitive(s: Symbol, code: Int): Unit = {

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,8 @@ object Comments {
2323
* docstrings via `Symbol` and expanding templates
2424
*/
2525
class ContextDocstrings {
26-
import scala.collection.mutable
2726

28-
private[this] val _docstrings: mutable.Map[Symbol, Comment] =
29-
mutable.Map.empty
27+
private[this] val _docstrings: MutableSymbolMap[Comment] = newMutableSymbolMap
3028

3129
val templateExpander = new CommentExpander
3230

@@ -35,7 +33,7 @@ object Comments {
3533
def docstring(sym: Symbol): Option[Comment] = _docstrings.get(sym)
3634

3735
def addDocstring(sym: Symbol, doc: Option[Comment]): Unit =
38-
doc.map(d => _docstrings += (sym -> d))
36+
doc.map(d => _docstrings.update(sym, d))
3937
}
4038

4139
/** A `Comment` contains the unformatted docstring as well as a position
@@ -182,7 +180,7 @@ object Comments {
182180
protected def superComment(sym: Symbol)(implicit ctx: Context): Option[String] =
183181
allInheritedOverriddenSymbols(sym).iterator map (x => cookedDocComment(x)) find (_ != "")
184182

185-
private val cookedDocComments = mutable.HashMap[Symbol, String]()
183+
private val cookedDocComments = newMutableSymbolMap[String]
186184

187185
/** The raw doc comment of symbol `sym`, minus usecase and define sections, augmented by
188186
* missing sections of an inherited doc comment.

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

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,4 +679,70 @@ object Symbols {
679679
def currentClass(implicit ctx: Context): ClassSymbol = ctx.owner.enclosingClass.asClass
680680

681681
@sharable var stubs: List[Symbol] = Nil // diagnostic only
682+
683+
/* Mutable map from symbols any T */
684+
class MutableSymbolMap[T](private[Symbols] val value: java.util.IdentityHashMap[Symbol, T]) extends AnyVal {
685+
686+
def apply(sym: Symbol): T = value.get(sym)
687+
688+
def get(sym: Symbol): Option[T] = Option(value.get(sym))
689+
690+
def getOrElse[U >: T](sym: Symbol, default: => U): U = {
691+
val v = value.get(sym)
692+
if (v != null) v else default
693+
}
694+
695+
def getOrElseUpdate(sym: Symbol, op: => T): T = {
696+
val v = value.get(sym)
697+
if (v != null) v
698+
else {
699+
val v = op
700+
assert(v != null)
701+
value.put(sym, v)
702+
v
703+
}
704+
}
705+
706+
def update(sym: Symbol, x: T): Unit = {
707+
assert(x != null)
708+
value.put(sym, x)
709+
}
710+
def put(sym: Symbol, x: T): T = {
711+
assert(x != null)
712+
value.put(sym, x)
713+
}
714+
715+
def -=(sym: Symbol): Unit = value.remove(sym)
716+
def remove(sym: Symbol): Option[T] = Option(value.remove(sym))
717+
718+
def contains(sym: Symbol): Boolean = value.containsKey(sym)
719+
720+
def isEmpty: Boolean = value.isEmpty
721+
722+
def clear(): Unit = value.clear()
723+
724+
def filter(p: ((Symbol, T)) => Boolean): Map[Symbol, T] = {
725+
import scala.collection.JavaConversions._
726+
value.toMap.filter(p)
727+
}
728+
729+
def iterator: Iterator[(Symbol, T)] = {
730+
import scala.collection.JavaConversions._
731+
value.iterator
732+
}
733+
734+
def keysIterator: Iterator[Symbol] = {
735+
import scala.collection.JavaConversions._
736+
value.keySet().iterator
737+
}
738+
739+
def toMap: Map[Symbol, T] = {
740+
import scala.collection.JavaConversions._
741+
value.toMap
742+
}
743+
}
744+
745+
@inline def newMutableSymbolMap[T]: MutableSymbolMap[T] =
746+
new MutableSymbolMap(new java.util.IdentityHashMap[Symbol, T]())
747+
682748
}

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ class TreePickler(pickler: TastyPickler) {
2323
import pickler.nameBuffer.nameIndex
2424
import ast.tpd._
2525

26-
private val symRefs = new mutable.HashMap[Symbol, Addr]
27-
private val forwardSymRefs = new mutable.HashMap[Symbol, List[Addr]]
26+
private val symRefs = Symbols.newMutableSymbolMap[Addr]
27+
private val forwardSymRefs = Symbols.newMutableSymbolMap[List[Addr]]
2828
private val pickledTypes = new java.util.IdentityHashMap[Type, Any] // Value type is really Addr, but that's not compatible with null
2929

3030
private def withLength(op: => Unit) = {
@@ -586,15 +586,15 @@ class TreePickler(pickler: TastyPickler) {
586586

587587
def pickle(trees: List[Tree])(implicit ctx: Context) = {
588588
trees.foreach(tree => if (!tree.isEmpty) pickleTree(tree))
589-
def missing = forwardSymRefs.keySet.toList.map(_.showLocated)
589+
def missing = forwardSymRefs.keysIterator.map(_.showLocated).toList
590590
assert(forwardSymRefs.isEmpty, i"unresolved symbols: $missing%, % when pickling ${ctx.source}")
591591
}
592592

593593
def compactify() = {
594594
buf.compactify()
595595

596-
def updateMapWithDeltas[T](mp: collection.mutable.Map[T, Addr]) =
597-
for (key <- mp.keysIterator.toBuffer[T]) mp(key) = adjusted(mp(key))
596+
def updateMapWithDeltas(mp: MutableSymbolMap[Addr]) =
597+
for (key <- mp.keysIterator.toBuffer[Symbol]) mp(key) = adjusted(mp(key))
598598

599599
updateMapWithDeltas(symRefs)
600600
}

compiler/src/dotty/tools/dotc/transform/Bridges.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class Bridges(root: ClassSymbol)(implicit ctx: Context) {
3333
private[this] var toBeRemoved = immutable.Set[Symbol]()
3434
private val bridges = mutable.ListBuffer[Tree]()
3535
private val bridgesScope = newScope
36-
private val bridgeTarget = mutable.HashMap[Symbol, Symbol]()
36+
private val bridgeTarget = newMutableSymbolMap[Symbol]
3737

3838
/** Add a bridge between `member` and `other`, where `member` overrides `other`
3939
* before erasure, if the following conditions are satisfied.

compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ class ExtensionMethods extends MiniPhase with DenotTransformer with FullParamete
139139
extensionMeth
140140
}
141141

142-
private val extensionDefs = mutable.Map[Symbol, mutable.ListBuffer[Tree]]()
142+
private val extensionDefs = newMutableSymbolMap[mutable.ListBuffer[Tree]]
143143
// TODO: this is state and should be per-run
144144
// todo: check that when transformation finished map is empty
145145

compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class NonLocalReturns extends MiniPhase {
3333
defn.NonLocalReturnControlType.appliedTo(argtype)
3434

3535
/** A hashmap from method symbols to non-local return keys */
36-
private val nonLocalReturnKeys = mutable.Map[Symbol, TermSymbol]()
36+
private val nonLocalReturnKeys = newMutableSymbolMap[TermSymbol]
3737

3838
/** Return non-local return key for given method */
3939
private def nonLocalReturnKey(meth: Symbol)(implicit ctx: Context) =

compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ object OverridingPairs {
6767
}
6868

6969
private val subParents = {
70-
val subParents = new mutable.HashMap[Symbol, BitSet]
70+
val subParents = newMutableSymbolMap[BitSet]
7171
for (bc <- base.info.baseClasses)
7272
subParents(bc) = BitSet(parents.indices.filter(parents(_).derivesFrom(bc)): _*)
7373
subParents

compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ object PatternMatcher {
7676
/** A map from variable symbols to their defining trees
7777
* and from labels to their defining plans
7878
*/
79-
private val initializer = mutable.Map[Symbol, Tree]()
80-
private val labelled = mutable.Map[Symbol, Plan]()
79+
private val initializer = newMutableSymbolMap[Tree]
80+
private val labelled = newMutableSymbolMap[Plan]
8181

8282
private def newVar(rhs: Tree, flags: FlagSet): TermSymbol =
8383
ctx.newSymbol(ctx.owner, PatMatStdBinderName.fresh(), Synthetic | Case | flags,
@@ -529,7 +529,7 @@ object PatternMatcher {
529529
tests1.filter { case(test, outcome) => tests2.get(test) == Some(outcome) }
530530

531531
/** The tests with known outcomes valid at entry to label */
532-
val seenAtLabel = mutable.HashMap[Symbol, SeenTests]()
532+
val seenAtLabel = newMutableSymbolMap[SeenTests]
533533

534534
class ElimRedundant(seenTests: SeenTests) extends PlanTransform {
535535
override def apply(plan: TestPlan): Plan = {
@@ -609,12 +609,12 @@ object PatternMatcher {
609609
type SeenVars = Map[RHS, TermSymbol]
610610

611611
/** The variables known at entry to label */
612-
val seenAtLabel = mutable.HashMap[Symbol, SeenVars]()
612+
val seenAtLabel = newMutableSymbolMap[SeenVars]
613613

614614
/** Parameters of label; these are passed additional variables
615615
* which are known at all callsites.
616616
*/
617-
val paramsOfLabel = mutable.HashMap[Symbol, SeenVars]()
617+
val paramsOfLabel = newMutableSymbolMap[SeenVars]
618618

619619
class Merge(seenVars: SeenVars) extends PlanTransform {
620620
override val treeMap = new TreeMap {

compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,11 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisPh
5555
/** A map to cache mapping local methods to their direct counterparts.
5656
* A fresh map is created for each unit.
5757
*/
58-
private var DirectMeth: Store.Location[mutable.HashMap[Symbol, Symbol]] = _
58+
private var DirectMeth: Store.Location[MutableSymbolMap[Symbol]] = _
5959
private def directMeth(implicit ctx: Context) = ctx.store(DirectMeth)
6060

6161
override def initContext(ctx: FreshContext) =
62-
DirectMeth = ctx.addLocation[mutable.HashMap[Symbol, Symbol]]()
62+
DirectMeth = ctx.addLocation[MutableSymbolMap[Symbol]]()
6363

6464
/** If this option is true, we don't specialize symbols that are known to be only
6565
* targets of monomorphic calls.
@@ -70,7 +70,7 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisPh
7070
final val specializeMonoTargets = true
7171

7272
override def prepareForUnit(tree: Tree)(implicit ctx: Context) =
73-
ctx.fresh.updateStore(DirectMeth, new mutable.HashMap[Symbol, Symbol])
73+
ctx.fresh.updateStore(DirectMeth, newMutableSymbolMap[Symbol])
7474

7575
/** Should `sym` get a ..$direct companion?
7676
* This is the case if (1) `sym` is a method with an implicit function type as final result type.

compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class SuperAccessors(thisPhase: DenotTransformer) {
6565
ctx.owner.enclosingClass != invalidEnclClass
6666

6767
/** List buffers for new accessor definitions, indexed by class */
68-
private val accDefs = mutable.Map[Symbol, mutable.ListBuffer[Tree]]()
68+
private val accDefs = newMutableSymbolMap[mutable.ListBuffer[Tree]]
6969

7070
/** A super accessor call corresponding to `sel` */
7171
private def superAccessorCall(sel: Select)(implicit ctx: Context) = {

compiler/src/dotty/tools/dotc/transform/TreeChecker.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ class TreeChecker extends Phase with SymTransformer {
142142
class Checker(phasesToCheck: Seq[Phase]) extends ReTyper with Checking {
143143

144144
val nowDefinedSyms = new mutable.HashSet[Symbol]
145-
val everDefinedSyms = new mutable.HashMap[Symbol, untpd.Tree]
145+
val everDefinedSyms = newMutableSymbolMap[untpd.Tree]
146146

147147
// don't check value classes after typer, as the constraint about constructors doesn't hold after transform
148148
override def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context) = ()

compiler/src/dotty/tools/dotc/transform/localopt/Devalify.scala

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ import transform.SymUtils._
2323
class Devalify extends Optimisation {
2424
import ast.tpd._
2525

26-
val timesUsed = mutable.HashMap[Symbol, Int]()
27-
val timesUsedAsType = mutable.HashMap[Symbol, Int]()
26+
val timesUsed = newMutableSymbolMap[Int]
27+
val timesUsedAsType = newMutableSymbolMap[Int]
2828

2929
val defined = mutable.HashSet[Symbol]()
30-
val usedInInnerClass = mutable.HashMap[Symbol, Int]()
30+
val usedInInnerClass = newMutableSymbolMap[Int]
3131
// Either a duplicate or a read through series of immutable fields
32-
val copies = mutable.HashMap[Symbol, Tree]()
32+
val copies = newMutableSymbolMap[Tree]
3333

3434
def clear(): Unit = {
3535
timesUsed.clear()
@@ -43,27 +43,27 @@ class Devalify extends Optimisation {
4343
tp.foreachPart(x => x match {
4444
case TermRef(NoPrefix, _) =>
4545
val b4 = timesUsedAsType.getOrElseUpdate(x.termSymbol, 0)
46-
timesUsedAsType.put(x.termSymbol, b4 + 1)
46+
timesUsedAsType.update(x.termSymbol, b4 + 1)
4747
case _ =>
4848
})
4949
}
5050

51-
def doVisit(tree: Tree, used: mutable.HashMap[Symbol, Int])(implicit ctx: Context): Unit = tree match {
51+
def doVisit(tree: Tree, used: MutableSymbolMap[Int])(implicit ctx: Context): Unit = tree match {
5252
case valdef: ValDef if !valdef.symbol.is(Param | Mutable | Module | Lazy) &&
5353
valdef.symbol.exists && !valdef.symbol.owner.isClass =>
5454
defined += valdef.symbol
5555

5656
dropCasts(valdef.rhs) match {
5757
case t: Tree if readingOnlyVals(t) =>
58-
copies.put(valdef.symbol, valdef.rhs)
58+
copies.update(valdef.symbol, valdef.rhs)
5959
case _ =>
6060
}
6161
visitType(valdef.symbol.info)
6262
case t: New =>
6363
val normalized = t.tpt.tpe.normalizedPrefix
6464
val symIfExists = normalized.termSymbol
6565
val b4 = used.getOrElseUpdate(symIfExists, 0)
66-
used.put(symIfExists, b4 + 1)
66+
used(symIfExists) = b4 + 1
6767
visitType(normalized)
6868

6969
case valdef: ValDef if valdef.symbol.exists && !valdef.symbol.owner.isClass &&
@@ -77,7 +77,7 @@ class Devalify extends Optimisation {
7777
case t: TypeApply => t.args.foreach(x => visitType(x.tpe))
7878
case t: RefTree =>
7979
val b4 = used.getOrElseUpdate(t.symbol, 0)
80-
used.put(t.symbol, b4 + 1)
80+
used.update(t.symbol, b4 + 1)
8181
case _ =>
8282
}
8383

@@ -107,21 +107,21 @@ class Devalify extends Optimisation {
107107
}
108108

109109
def transformer(implicit ctx: Context): Tree => Tree = {
110-
val valsToDrop = defined -- timesUsed.keySet -- timesUsedAsType.keySet
110+
val valsToDrop = defined -- timesUsed.keysIterator -- timesUsedAsType.keysIterator
111111
val copiesToReplaceAsDuplicates = copies.filter { x =>
112112
val rhs = dropCasts(x._2)
113113
rhs.isInstanceOf[Literal] || (!rhs.symbol.owner.isClass && !rhs.symbol.is(Method | Mutable))
114-
} -- timesUsedAsType.keySet
114+
} -- timesUsedAsType.keysIterator
115115
// TODO: if a non-synthetic val is duplicate of a synthetic one, rename a synthetic one and drop synthetic flag?
116116

117117
val copiesToReplaceAsUsedOnce =
118118
timesUsed.filter(x => x._2 == 1)
119119
.flatMap(x => copies.get(x._1) match {
120120
case Some(tr) => List((x._1, tr))
121121
case None => Nil
122-
}) -- timesUsedAsType.keySet
122+
}) -- timesUsedAsType.keysIterator
123123

124-
val replacements = copiesToReplaceAsDuplicates ++ copiesToReplaceAsUsedOnce -- usedInInnerClass.keySet
124+
val replacements = copiesToReplaceAsDuplicates ++ copiesToReplaceAsUsedOnce -- usedInInnerClass.keysIterator
125125

126126
val deepReplacer = new TreeMap() {
127127
override def transform(tree: Tree)(implicit ctx: Context): Tree = {

0 commit comments

Comments
 (0)