From 14d9fc2dae48f0a45b5aa42046139c15589c1107 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 14 Sep 2017 10:44:57 +0200 Subject: [PATCH 1/2] Homogenize mutable symbol maps Use IdentityHashMap instead of mutable.HashMap to make fast equality check --- compiler/sjs/backend/sjs/JSPrimitives.scala | 2 +- .../dotty/tools/backend/jvm/GenBCode.scala | 2 +- .../dotty/tools/backend/jvm/LabelDefs.scala | 6 +- .../tools/backend/jvm/scalaPrimitives.scala | 2 +- .../src/dotty/tools/dotc/core/Comments.scala | 8 +-- .../src/dotty/tools/dotc/core/Symbols.scala | 66 +++++++++++++++++++ .../tools/dotc/core/tasty/TreePickler.scala | 10 +-- .../dotty/tools/dotc/transform/Bridges.scala | 2 +- .../dotc/transform/ExtensionMethods.scala | 2 +- .../dotc/transform/NonLocalReturns.scala | 2 +- .../dotc/transform/OverridingPairs.scala | 2 +- .../tools/dotc/transform/PatternMatcher.scala | 10 +-- .../dotc/transform/ShortcutImplicits.scala | 6 +- .../tools/dotc/transform/SuperAccessors.scala | 2 +- .../tools/dotc/transform/TreeChecker.scala | 2 +- .../dotc/transform/localopt/Devalify.scala | 20 +++--- .../localopt/InlineLabelsCalledOnce.scala | 4 +- .../transform/localopt/InlineOptions.scala | 2 +- .../dotc/transform/localopt/Jumpjump.scala | 2 +- .../RemoveUnnecessaryNullChecks.scala | 2 +- .../dotc/transform/localopt/Valify.scala | 8 +-- .../dotc/transform/localopt/Varify.scala | 8 +-- 22 files changed, 117 insertions(+), 53 deletions(-) diff --git a/compiler/sjs/backend/sjs/JSPrimitives.scala b/compiler/sjs/backend/sjs/JSPrimitives.scala index 6c3c5715cac9..f8a5a31bef99 100644 --- a/compiler/sjs/backend/sjs/JSPrimitives.scala +++ b/compiler/sjs/backend/sjs/JSPrimitives.scala @@ -59,7 +59,7 @@ class JSPrimitives(ctx: Context) extends DottyPrimitives(ctx) { /** Initialize the primitive map */ private def initJSPrimitives(implicit ctx: Context): Map[Symbol, Int] = { - val primitives = new mutable.HashMap[Symbol, Int]() + val primitives = newMutableSymbolMap[Int] // !!! Code duplicate with DottyPrimitives /** Add a primitive operation to the map */ diff --git a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala index ad84bde680d1..a26686b52b93 100644 --- a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala @@ -40,7 +40,7 @@ class GenBCode extends Phase { private val entryPoints = new mutable.HashSet[Symbol]() def registerEntryPoint(sym: Symbol) = entryPoints += sym - private val superCallsMap = new mutable.HashMap[Symbol, Set[ClassSymbol]]() + private val superCallsMap = newMutableSymbolMap[Set[ClassSymbol]] def registerSuperCall(sym: Symbol, calls: ClassSymbol) = { val old = superCallsMap.getOrElse(sym, Set.empty) superCallsMap.put(sym, old + calls) diff --git a/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala b/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala index 26efb7257a5f..841f5135c6b5 100644 --- a/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala +++ b/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala @@ -76,7 +76,7 @@ class LabelDefs extends MiniPhase { case t: DefDef => assert(t.symbol is Label) EmptyTree - case _ => if (labelDefs.nonEmpty) super.transform(tree) else tree + case _ => if (!labelDefs.isEmpty) super.transform(tree) else tree } } } @@ -86,9 +86,9 @@ class LabelDefs extends MiniPhase { } } - private def collectLabelDefs(tree: Tree)(implicit ctx: Context): mutable.HashMap[Symbol, DefDef] = { + private def collectLabelDefs(tree: Tree)(implicit ctx: Context): MutableSymbolMap[DefDef] = { // labelSymbol -> Defining tree - val labelDefs = new mutable.HashMap[Symbol, DefDef]() + val labelDefs = newMutableSymbolMap[DefDef] new TreeTraverser { override def traverse(tree: Tree)(implicit ctx: Context): Unit = tree match { case t: DefDef => diff --git a/compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala b/compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala index 851cacaa2275..24f7dcc9c3e0 100644 --- a/compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala +++ b/compiler/src/dotty/tools/backend/jvm/scalaPrimitives.scala @@ -128,7 +128,7 @@ class DottyPrimitives(ctx: Context) { implicit val ctx = this.ctx import core.Symbols.defn - val primitives = new mutable.HashMap[Symbol, Int]() + val primitives = core.Symbols.newMutableSymbolMap[Int] /** Add a primitive operation to the map */ def addPrimitive(s: Symbol, code: Int): Unit = { diff --git a/compiler/src/dotty/tools/dotc/core/Comments.scala b/compiler/src/dotty/tools/dotc/core/Comments.scala index 2559209c3b97..96203315f4e1 100644 --- a/compiler/src/dotty/tools/dotc/core/Comments.scala +++ b/compiler/src/dotty/tools/dotc/core/Comments.scala @@ -23,10 +23,8 @@ object Comments { * docstrings via `Symbol` and expanding templates */ class ContextDocstrings { - import scala.collection.mutable - private[this] val _docstrings: mutable.Map[Symbol, Comment] = - mutable.Map.empty + private[this] val _docstrings: MutableSymbolMap[Comment] = newMutableSymbolMap val templateExpander = new CommentExpander @@ -35,7 +33,7 @@ object Comments { def docstring(sym: Symbol): Option[Comment] = _docstrings.get(sym) def addDocstring(sym: Symbol, doc: Option[Comment]): Unit = - doc.map(d => _docstrings += (sym -> d)) + doc.map(d => _docstrings.put(sym, d)) } /** A `Comment` contains the unformatted docstring as well as a position @@ -182,7 +180,7 @@ object Comments { protected def superComment(sym: Symbol)(implicit ctx: Context): Option[String] = allInheritedOverriddenSymbols(sym).iterator map (x => cookedDocComment(x)) find (_ != "") - private val cookedDocComments = mutable.HashMap[Symbol, String]() + private val cookedDocComments = newMutableSymbolMap[String] /** The raw doc comment of symbol `sym`, minus usecase and define sections, augmented by * missing sections of an inherited doc comment. diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 2e3661a52039..32ca0ced78b1 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -678,4 +678,70 @@ object Symbols { def currentClass(implicit ctx: Context): ClassSymbol = ctx.owner.enclosingClass.asClass @sharable var stubs: List[Symbol] = Nil // diagnostic only + + /* Mutable map from symbols any T */ + class MutableSymbolMap[T](private[Symbols] val value: java.util.IdentityHashMap[Symbol, T]) extends AnyVal { + + def apply(sym: Symbol): T = value.get(sym) + + def get(sym: Symbol): Option[T] = Option(value.get(sym)) + + def getOrElse[U >: T](sym: Symbol, default: => U): U = { + val v = value.get(sym) + if (v != null) v else default + } + + def getOrElseUpdate(sym: Symbol, op: => T): T = { + val v = value.get(sym) + if (v != null) v + else { + val v = op + assert(v != null) + value.put(sym, v) + v + } + } + + def update(sym: Symbol, x: T): Unit = { + assert(x != null) + value.put(sym, x) + } + def put(sym: Symbol, x: T): T = { + assert(x != null) + value.put(sym, x) + } + + def -=(sym: Symbol): Unit = value.remove(sym) + def remove(sym: Symbol): Option[T] = Option(value.remove(sym)) + + def contains(sym: Symbol): Boolean = value.containsKey(sym) + + def isEmpty: Boolean = value.isEmpty + + def clear(): Unit = value.clear() + + def filter(p: ((Symbol, T)) => Boolean): Map[Symbol, T] = { + import scala.collection.JavaConversions._ + value.toMap.filter(p) + } + + def iterator: Iterator[(Symbol, T)] = { + import scala.collection.JavaConversions._ + value.iterator + } + + def keysIterator: Iterator[Symbol] = { + import scala.collection.JavaConversions._ + value.keySet().iterator + } + + def toMap: Map[Symbol, T] = { + import scala.collection.JavaConversions._ + value.toMap + } + } + + @inline def newMutableSymbolMap[T]: MutableSymbolMap[T] = + new MutableSymbolMap(new java.util.IdentityHashMap[Symbol, T]()) + } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 1d829855ccd5..0f727cf8f101 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -23,8 +23,8 @@ class TreePickler(pickler: TastyPickler) { import pickler.nameBuffer.nameIndex import ast.tpd._ - private val symRefs = new mutable.HashMap[Symbol, Addr] - private val forwardSymRefs = new mutable.HashMap[Symbol, List[Addr]] + private val symRefs = Symbols.newMutableSymbolMap[Addr] + private val forwardSymRefs = Symbols.newMutableSymbolMap[List[Addr]] private val pickledTypes = new java.util.IdentityHashMap[Type, Any] // Value type is really Addr, but that's not compatible with null private def withLength(op: => Unit) = { @@ -586,15 +586,15 @@ class TreePickler(pickler: TastyPickler) { def pickle(trees: List[Tree])(implicit ctx: Context) = { trees.foreach(tree => if (!tree.isEmpty) pickleTree(tree)) - def missing = forwardSymRefs.keySet.toList.map(_.showLocated) + def missing = forwardSymRefs.keysIterator.map(_.showLocated).toList assert(forwardSymRefs.isEmpty, i"unresolved symbols: $missing%, % when pickling ${ctx.source}") } def compactify() = { buf.compactify() - def updateMapWithDeltas[T](mp: collection.mutable.Map[T, Addr]) = - for (key <- mp.keysIterator.toBuffer[T]) mp(key) = adjusted(mp(key)) + def updateMapWithDeltas(mp: MutableSymbolMap[Addr]) = + for (key <- mp.keysIterator.toBuffer[Symbol]) mp(key) = adjusted(mp(key)) updateMapWithDeltas(symRefs) } diff --git a/compiler/src/dotty/tools/dotc/transform/Bridges.scala b/compiler/src/dotty/tools/dotc/transform/Bridges.scala index 08c0d4fcf700..c2a758363240 100644 --- a/compiler/src/dotty/tools/dotc/transform/Bridges.scala +++ b/compiler/src/dotty/tools/dotc/transform/Bridges.scala @@ -33,7 +33,7 @@ class Bridges(root: ClassSymbol)(implicit ctx: Context) { private[this] var toBeRemoved = immutable.Set[Symbol]() private val bridges = mutable.ListBuffer[Tree]() private val bridgesScope = newScope - private val bridgeTarget = mutable.HashMap[Symbol, Symbol]() + private val bridgeTarget = newMutableSymbolMap[Symbol] /** Add a bridge between `member` and `other`, where `member` overrides `other` * before erasure, if the following conditions are satisfied. diff --git a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala index 6bb2b29ee522..3e743ebe52b7 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala @@ -139,7 +139,7 @@ class ExtensionMethods extends MiniPhase with DenotTransformer with FullParamete extensionMeth } - private val extensionDefs = mutable.Map[Symbol, mutable.ListBuffer[Tree]]() + private val extensionDefs = newMutableSymbolMap[mutable.ListBuffer[Tree]] // TODO: this is state and should be per-run // todo: check that when transformation finished map is empty diff --git a/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala b/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala index 70ae9a77574a..18eb68f0c9fd 100644 --- a/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala +++ b/compiler/src/dotty/tools/dotc/transform/NonLocalReturns.scala @@ -33,7 +33,7 @@ class NonLocalReturns extends MiniPhase { defn.NonLocalReturnControlType.appliedTo(argtype) /** A hashmap from method symbols to non-local return keys */ - private val nonLocalReturnKeys = mutable.Map[Symbol, TermSymbol]() + private val nonLocalReturnKeys = newMutableSymbolMap[TermSymbol] /** Return non-local return key for given method */ private def nonLocalReturnKey(meth: Symbol)(implicit ctx: Context) = diff --git a/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala b/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala index a37d06505d42..57858600dad6 100644 --- a/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala +++ b/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala @@ -67,7 +67,7 @@ object OverridingPairs { } private val subParents = { - val subParents = new mutable.HashMap[Symbol, BitSet] + val subParents = newMutableSymbolMap[BitSet] for (bc <- base.info.baseClasses) subParents(bc) = BitSet(parents.indices.filter(parents(_).derivesFrom(bc)): _*) subParents diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index 512ee80472e0..a16f7ab427f7 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -76,8 +76,8 @@ object PatternMatcher { /** A map from variable symbols to their defining trees * and from labels to their defining plans */ - private val initializer = mutable.Map[Symbol, Tree]() - private val labelled = mutable.Map[Symbol, Plan]() + private val initializer = newMutableSymbolMap[Tree] + private val labelled = newMutableSymbolMap[Plan] private def newVar(rhs: Tree, flags: FlagSet): TermSymbol = ctx.newSymbol(ctx.owner, PatMatStdBinderName.fresh(), Synthetic | Case | flags, @@ -529,7 +529,7 @@ object PatternMatcher { tests1.filter { case(test, outcome) => tests2.get(test) == Some(outcome) } /** The tests with known outcomes valid at entry to label */ - val seenAtLabel = mutable.HashMap[Symbol, SeenTests]() + val seenAtLabel = newMutableSymbolMap[SeenTests] class ElimRedundant(seenTests: SeenTests) extends PlanTransform { override def apply(plan: TestPlan): Plan = { @@ -609,12 +609,12 @@ object PatternMatcher { type SeenVars = Map[RHS, TermSymbol] /** The variables known at entry to label */ - val seenAtLabel = mutable.HashMap[Symbol, SeenVars]() + val seenAtLabel = newMutableSymbolMap[SeenVars] /** Parameters of label; these are passed additional variables * which are known at all callsites. */ - val paramsOfLabel = mutable.HashMap[Symbol, SeenVars]() + val paramsOfLabel = newMutableSymbolMap[SeenVars] class Merge(seenVars: SeenVars) extends PlanTransform { override val treeMap = new TreeMap { diff --git a/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala b/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala index 453bb7508d7b..77e735bdfe0a 100644 --- a/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala +++ b/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala @@ -55,11 +55,11 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisPh /** A map to cache mapping local methods to their direct counterparts. * A fresh map is created for each unit. */ - private var DirectMeth: Store.Location[mutable.HashMap[Symbol, Symbol]] = _ + private var DirectMeth: Store.Location[MutableSymbolMap[Symbol]] = _ private def directMeth(implicit ctx: Context) = ctx.store(DirectMeth) override def initContext(ctx: FreshContext) = - DirectMeth = ctx.addLocation[mutable.HashMap[Symbol, Symbol]]() + DirectMeth = ctx.addLocation[MutableSymbolMap[Symbol]]() /** If this option is true, we don't specialize symbols that are known to be only * targets of monomorphic calls. @@ -70,7 +70,7 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisPh final val specializeMonoTargets = true override def prepareForUnit(tree: Tree)(implicit ctx: Context) = - ctx.fresh.updateStore(DirectMeth, new mutable.HashMap[Symbol, Symbol]) + ctx.fresh.updateStore(DirectMeth, newMutableSymbolMap[Symbol]) /** Should `sym` get a ..$direct companion? * This is the case if (1) `sym` is a method with an implicit function type as final result type. diff --git a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala index 4f7e588a2548..404709d2cc91 100644 --- a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala @@ -65,7 +65,7 @@ class SuperAccessors(thisPhase: DenotTransformer) { ctx.owner.enclosingClass != invalidEnclClass /** List buffers for new accessor definitions, indexed by class */ - private val accDefs = mutable.Map[Symbol, mutable.ListBuffer[Tree]]() + private val accDefs = newMutableSymbolMap[mutable.ListBuffer[Tree]] /** A super accessor call corresponding to `sel` */ private def superAccessorCall(sel: Select)(implicit ctx: Context) = { diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index ddd3ccd827cf..bfd571a565fe 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -142,7 +142,7 @@ class TreeChecker extends Phase with SymTransformer { class Checker(phasesToCheck: Seq[Phase]) extends ReTyper with Checking { val nowDefinedSyms = new mutable.HashSet[Symbol] - val everDefinedSyms = new mutable.HashMap[Symbol, untpd.Tree] + val everDefinedSyms = newMutableSymbolMap[untpd.Tree] // don't check value classes after typer, as the constraint about constructors doesn't hold after transform override def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context) = () diff --git a/compiler/src/dotty/tools/dotc/transform/localopt/Devalify.scala b/compiler/src/dotty/tools/dotc/transform/localopt/Devalify.scala index 3cdcd3744328..689b6c35cbcc 100644 --- a/compiler/src/dotty/tools/dotc/transform/localopt/Devalify.scala +++ b/compiler/src/dotty/tools/dotc/transform/localopt/Devalify.scala @@ -23,13 +23,13 @@ import transform.SymUtils._ class Devalify extends Optimisation { import ast.tpd._ - val timesUsed = mutable.HashMap[Symbol, Int]() - val timesUsedAsType = mutable.HashMap[Symbol, Int]() + val timesUsed = newMutableSymbolMap[Int] + val timesUsedAsType = newMutableSymbolMap[Int] val defined = mutable.HashSet[Symbol]() - val usedInInnerClass = mutable.HashMap[Symbol, Int]() + val usedInInnerClass = newMutableSymbolMap[Int] // Either a duplicate or a read through series of immutable fields - val copies = mutable.HashMap[Symbol, Tree]() + val copies = newMutableSymbolMap[Tree] def clear(): Unit = { timesUsed.clear() @@ -48,7 +48,7 @@ class Devalify extends Optimisation { }) } - def doVisit(tree: Tree, used: mutable.HashMap[Symbol, Int])(implicit ctx: Context): Unit = tree match { + def doVisit(tree: Tree, used: MutableSymbolMap[Int])(implicit ctx: Context): Unit = tree match { case valdef: ValDef if !valdef.symbol.is(Param | Mutable | Module | Lazy) && valdef.symbol.exists && !valdef.symbol.owner.isClass => defined += valdef.symbol @@ -63,7 +63,7 @@ class Devalify extends Optimisation { val normalized = t.tpt.tpe.normalizedPrefix val symIfExists = normalized.termSymbol val b4 = used.getOrElseUpdate(symIfExists, 0) - used.put(symIfExists, b4 + 1) + used(symIfExists) = b4 + 1 visitType(normalized) case valdef: ValDef if valdef.symbol.exists && !valdef.symbol.owner.isClass && @@ -107,11 +107,11 @@ class Devalify extends Optimisation { } def transformer(implicit ctx: Context): Tree => Tree = { - val valsToDrop = defined -- timesUsed.keySet -- timesUsedAsType.keySet + val valsToDrop = defined -- timesUsed.keysIterator -- timesUsedAsType.keysIterator val copiesToReplaceAsDuplicates = copies.filter { x => val rhs = dropCasts(x._2) rhs.isInstanceOf[Literal] || (!rhs.symbol.owner.isClass && !rhs.symbol.is(Method | Mutable)) - } -- timesUsedAsType.keySet + } -- timesUsedAsType.keysIterator // TODO: if a non-synthetic val is duplicate of a synthetic one, rename a synthetic one and drop synthetic flag? val copiesToReplaceAsUsedOnce = @@ -119,9 +119,9 @@ class Devalify extends Optimisation { .flatMap(x => copies.get(x._1) match { case Some(tr) => List((x._1, tr)) case None => Nil - }) -- timesUsedAsType.keySet + }) -- timesUsedAsType.keysIterator - val replacements = copiesToReplaceAsDuplicates ++ copiesToReplaceAsUsedOnce -- usedInInnerClass.keySet + val replacements = copiesToReplaceAsDuplicates ++ copiesToReplaceAsUsedOnce -- usedInInnerClass.keysIterator val deepReplacer = new TreeMap() { override def transform(tree: Tree)(implicit ctx: Context): Tree = { diff --git a/compiler/src/dotty/tools/dotc/transform/localopt/InlineLabelsCalledOnce.scala b/compiler/src/dotty/tools/dotc/transform/localopt/InlineLabelsCalledOnce.scala index 194a28c2028a..9c3087f60610 100644 --- a/compiler/src/dotty/tools/dotc/transform/localopt/InlineLabelsCalledOnce.scala +++ b/compiler/src/dotty/tools/dotc/transform/localopt/InlineLabelsCalledOnce.scala @@ -15,8 +15,8 @@ import config.Printers.simplify class InlineLabelsCalledOnce extends Optimisation { import ast.tpd._ - val timesUsed = mutable.HashMap[Symbol, Int]() - val defined = mutable.HashMap[Symbol, DefDef]() + val timesUsed = newMutableSymbolMap[Int] + val defined = newMutableSymbolMap[DefDef] def clear(): Unit = { timesUsed.clear() diff --git a/compiler/src/dotty/tools/dotc/transform/localopt/InlineOptions.scala b/compiler/src/dotty/tools/dotc/transform/localopt/InlineOptions.scala index ee767a37c1b7..3edaa96d5f2f 100644 --- a/compiler/src/dotty/tools/dotc/transform/localopt/InlineOptions.scala +++ b/compiler/src/dotty/tools/dotc/transform/localopt/InlineOptions.scala @@ -17,7 +17,7 @@ import scala.collection.mutable class InlineOptions extends Optimisation { import ast.tpd._ - val somes = mutable.HashMap[Symbol, Tree]() + val somes = newMutableSymbolMap[Tree] val nones = mutable.HashSet[Symbol]() def clear(): Unit = { diff --git a/compiler/src/dotty/tools/dotc/transform/localopt/Jumpjump.scala b/compiler/src/dotty/tools/dotc/transform/localopt/Jumpjump.scala index 77fe85caf7cb..9f4f9a8fc82c 100644 --- a/compiler/src/dotty/tools/dotc/transform/localopt/Jumpjump.scala +++ b/compiler/src/dotty/tools/dotc/transform/localopt/Jumpjump.scala @@ -18,7 +18,7 @@ import core.Flags._ class Jumpjump extends Optimisation { import ast.tpd._ - val defined = mutable.HashMap[Symbol, Symbol]() + val defined = newMutableSymbolMap[Symbol] def clear(): Unit = defined.clear() diff --git a/compiler/src/dotty/tools/dotc/transform/localopt/RemoveUnnecessaryNullChecks.scala b/compiler/src/dotty/tools/dotc/transform/localopt/RemoveUnnecessaryNullChecks.scala index e2662405b176..8b8e5d62beb8 100644 --- a/compiler/src/dotty/tools/dotc/transform/localopt/RemoveUnnecessaryNullChecks.scala +++ b/compiler/src/dotty/tools/dotc/transform/localopt/RemoveUnnecessaryNullChecks.scala @@ -24,7 +24,7 @@ import scala.collection.mutable val initializedVals = mutable.HashSet[Symbol]() - val checkGood = mutable.HashMap[Symbol, Set[Symbol]]() + val checkGood = newMutableSymbolMap[Set[Symbol]] def clear(): Unit = { initializedVals.clear() diff --git a/compiler/src/dotty/tools/dotc/transform/localopt/Valify.scala b/compiler/src/dotty/tools/dotc/transform/localopt/Valify.scala index 7f463c4d5362..a3b18f72169e 100644 --- a/compiler/src/dotty/tools/dotc/transform/localopt/Valify.scala +++ b/compiler/src/dotty/tools/dotc/transform/localopt/Valify.scala @@ -16,13 +16,13 @@ class Valify(val simplifyPhase: Simplify) extends Optimisation { import ast.tpd._ // Either a duplicate or a read through series of immutable fields. - val defined: mutable.Map[Symbol, ValDef] = mutable.Map() + val defined: MutableSymbolMap[ValDef] = newMutableSymbolMap - val firstRead: mutable.Map[Symbol, RefTree] = mutable.Map() + val firstRead: MutableSymbolMap[RefTree] = newMutableSymbolMap - val firstWrite: mutable.Map[Symbol, Assign] = mutable.Map() + val firstWrite: MutableSymbolMap[Assign] = newMutableSymbolMap - val secondWrite: mutable.Map[Symbol, Assign] = mutable.Map() + val secondWrite: MutableSymbolMap[Assign] = newMutableSymbolMap def clear(): Unit = { defined.clear() diff --git a/compiler/src/dotty/tools/dotc/transform/localopt/Varify.scala b/compiler/src/dotty/tools/dotc/transform/localopt/Varify.scala index 19a53d4496a8..218d54d9e992 100644 --- a/compiler/src/dotty/tools/dotc/transform/localopt/Varify.scala +++ b/compiler/src/dotty/tools/dotc/transform/localopt/Varify.scala @@ -27,9 +27,9 @@ import scala.collection.mutable class Varify extends Optimisation { import ast.tpd._ - val paramsTimesUsed = mutable.HashMap[Symbol, Int]() + val paramsTimesUsed = newMutableSymbolMap[Int] - val possibleRenames = mutable.HashMap[Symbol, Set[Symbol]]() + val possibleRenames = newMutableSymbolMap[Set[Symbol]] def clear(): Unit = { paramsTimesUsed.clear() @@ -38,7 +38,7 @@ import scala.collection.mutable def visitor(implicit ctx: Context): Tree => Unit = { case t: ValDef if t.symbol.is(Param) => - paramsTimesUsed += (t.symbol -> 0) + paramsTimesUsed.put(t.symbol, 0) case t: ValDef if t.symbol.is(Mutable) => t.rhs.foreachSubTree { subtree => @@ -52,7 +52,7 @@ import scala.collection.mutable case t: RefTree if paramsTimesUsed.contains(t.symbol) => val param = t.symbol val current = paramsTimesUsed.get(param) - current foreach { c => paramsTimesUsed += (param -> (c + 1)) } + current foreach { c => paramsTimesUsed.put(param, c + 1) } case _ => } From 9ce9ea374c18b7d4122a6afbaa2ccd17921727fc Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 20 Sep 2017 10:00:16 +0200 Subject: [PATCH 2/2] Use MutableSymbolMap update instead of put --- compiler/src/dotty/tools/backend/jvm/GenBCode.scala | 2 +- compiler/src/dotty/tools/dotc/core/Comments.scala | 2 +- .../src/dotty/tools/dotc/transform/localopt/Devalify.scala | 6 +++--- .../dotc/transform/localopt/InlineLabelsCalledOnce.scala | 6 +++--- .../transform/localopt/RemoveUnnecessaryNullChecks.scala | 4 ++-- .../src/dotty/tools/dotc/transform/localopt/Varify.scala | 6 +++--- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala index a26686b52b93..63b9cf972a08 100644 --- a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala @@ -43,7 +43,7 @@ class GenBCode extends Phase { private val superCallsMap = newMutableSymbolMap[Set[ClassSymbol]] def registerSuperCall(sym: Symbol, calls: ClassSymbol) = { val old = superCallsMap.getOrElse(sym, Set.empty) - superCallsMap.put(sym, old + calls) + superCallsMap.update(sym, old + calls) } def outputDir(implicit ctx: Context): AbstractFile = diff --git a/compiler/src/dotty/tools/dotc/core/Comments.scala b/compiler/src/dotty/tools/dotc/core/Comments.scala index 96203315f4e1..39530d718c3e 100644 --- a/compiler/src/dotty/tools/dotc/core/Comments.scala +++ b/compiler/src/dotty/tools/dotc/core/Comments.scala @@ -33,7 +33,7 @@ object Comments { def docstring(sym: Symbol): Option[Comment] = _docstrings.get(sym) def addDocstring(sym: Symbol, doc: Option[Comment]): Unit = - doc.map(d => _docstrings.put(sym, d)) + doc.map(d => _docstrings.update(sym, d)) } /** A `Comment` contains the unformatted docstring as well as a position diff --git a/compiler/src/dotty/tools/dotc/transform/localopt/Devalify.scala b/compiler/src/dotty/tools/dotc/transform/localopt/Devalify.scala index 689b6c35cbcc..bf12c8296372 100644 --- a/compiler/src/dotty/tools/dotc/transform/localopt/Devalify.scala +++ b/compiler/src/dotty/tools/dotc/transform/localopt/Devalify.scala @@ -43,7 +43,7 @@ class Devalify extends Optimisation { tp.foreachPart(x => x match { case TermRef(NoPrefix, _) => val b4 = timesUsedAsType.getOrElseUpdate(x.termSymbol, 0) - timesUsedAsType.put(x.termSymbol, b4 + 1) + timesUsedAsType.update(x.termSymbol, b4 + 1) case _ => }) } @@ -55,7 +55,7 @@ class Devalify extends Optimisation { dropCasts(valdef.rhs) match { case t: Tree if readingOnlyVals(t) => - copies.put(valdef.symbol, valdef.rhs) + copies.update(valdef.symbol, valdef.rhs) case _ => } visitType(valdef.symbol.info) @@ -77,7 +77,7 @@ class Devalify extends Optimisation { case t: TypeApply => t.args.foreach(x => visitType(x.tpe)) case t: RefTree => val b4 = used.getOrElseUpdate(t.symbol, 0) - used.put(t.symbol, b4 + 1) + used.update(t.symbol, b4 + 1) case _ => } diff --git a/compiler/src/dotty/tools/dotc/transform/localopt/InlineLabelsCalledOnce.scala b/compiler/src/dotty/tools/dotc/transform/localopt/InlineLabelsCalledOnce.scala index 9c3087f60610..d993ac983288 100644 --- a/compiler/src/dotty/tools/dotc/transform/localopt/InlineLabelsCalledOnce.scala +++ b/compiler/src/dotty/tools/dotc/transform/localopt/InlineLabelsCalledOnce.scala @@ -31,11 +31,11 @@ class InlineLabelsCalledOnce extends Optimisation { isRecursive = true } if (!isRecursive) - defined.put(d.symbol, d) + defined.update(d.symbol, d) case t: Apply if t.symbol.is(Label) => val b4 = timesUsed.getOrElseUpdate(t.symbol, 0) - timesUsed.put(t.symbol, b4 + 1) + timesUsed.update(t.symbol, b4 + 1) case _ => } @@ -55,7 +55,7 @@ class InlineLabelsCalledOnce extends Optimisation { case d: DefDef if usedOnce(d) => simplify.println(s"Dropping labeldef (used once) ${d.name} ${timesUsed.get(d.symbol)}") - defined.put(d.symbol, d) + defined.update(d.symbol, d) EmptyTree case d: DefDef if neverUsed(d) => diff --git a/compiler/src/dotty/tools/dotc/transform/localopt/RemoveUnnecessaryNullChecks.scala b/compiler/src/dotty/tools/dotc/transform/localopt/RemoveUnnecessaryNullChecks.scala index 8b8e5d62beb8..72144b031a5b 100644 --- a/compiler/src/dotty/tools/dotc/transform/localopt/RemoveUnnecessaryNullChecks.scala +++ b/compiler/src/dotty/tools/dotc/transform/localopt/RemoveUnnecessaryNullChecks.scala @@ -62,11 +62,11 @@ import scala.collection.mutable case t: Literal => t.const.value != null case t: Ident if !t.symbol.owner.isClass => - checkGood.put(target, checkGood.getOrElse(target, Set.empty) + t.symbol) + checkGood.update(target, checkGood.getOrElse(target, Set.empty) + t.symbol) true case t: Apply if !t.symbol.owner.isClass => - checkGood.put(target, checkGood.getOrElse(target, Set.empty) + t.symbol) + checkGood.update(target, checkGood.getOrElse(target, Set.empty) + t.symbol) true case t: Typed => diff --git a/compiler/src/dotty/tools/dotc/transform/localopt/Varify.scala b/compiler/src/dotty/tools/dotc/transform/localopt/Varify.scala index 218d54d9e992..a97e117ae9fb 100644 --- a/compiler/src/dotty/tools/dotc/transform/localopt/Varify.scala +++ b/compiler/src/dotty/tools/dotc/transform/localopt/Varify.scala @@ -38,21 +38,21 @@ import scala.collection.mutable def visitor(implicit ctx: Context): Tree => Unit = { case t: ValDef if t.symbol.is(Param) => - paramsTimesUsed.put(t.symbol, 0) + paramsTimesUsed.update(t.symbol, 0) case t: ValDef if t.symbol.is(Mutable) => t.rhs.foreachSubTree { subtree => if (paramsTimesUsed.contains(subtree.symbol) && t.symbol.info.widenDealias <:< subtree.symbol.info.widenDealias) { val newSet = possibleRenames.getOrElse(t.symbol, Set.empty) + subtree.symbol - possibleRenames.put(t.symbol, newSet) + possibleRenames.update(t.symbol, newSet) } } case t: RefTree if paramsTimesUsed.contains(t.symbol) => val param = t.symbol val current = paramsTimesUsed.get(param) - current foreach { c => paramsTimesUsed.put(param, c + 1) } + current foreach { c => paramsTimesUsed.update(param, c + 1) } case _ => }