From 6d49dfd60664110f66801467755cdc7b06ccd09e Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 27 Feb 2020 11:26:36 +1000 Subject: [PATCH] temp --- .../scala/collection/immutable/HashMap.scala | 56 ++++++++++--------- .../scala/collection/mutable/HashMap.scala | 8 ++- 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/src/library/scala/collection/immutable/HashMap.scala b/src/library/scala/collection/immutable/HashMap.scala index d104f62a09f..88782263e93 100644 --- a/src/library/scala/collection/immutable/HashMap.scala +++ b/src/library/scala/collection/immutable/HashMap.scala @@ -22,6 +22,7 @@ import scala.collection.Stepper.EfficientSplit import scala.collection.generic.DefaultSerializable import scala.collection.mutable.ReusableBuilder import scala.collection.{Iterator, MapFactory, MapFactoryDefaults, Stepper, StepperShape, mutable} +import scala.runtime.AbstractFunction2 import scala.runtime.Statics.releaseFence import scala.util.hashing.MurmurHash3 @@ -184,35 +185,38 @@ final class HashMap[K, +V] private[immutable] (private[immutable] val rootNode: } this case _ => - val iter = that.iterator - var current: BitmapIndexedMapNode[K, V1] = rootNode - while (iter.hasNext) { - val (key, value) = iter.next() - val originalHash = key.## - val improved = improve(originalHash) - current = current.updated(key, value, originalHash, improved, 0, replaceValue = true) - - if (current ne rootNode) { - // Note: We could have started with shallowlyMutableNodeMap = 0, however this way, in the case that - // the first changed key ended up in a subnode beneath root, we mark that root right away as being - // shallowly mutable. - // - // since key->value has just been inserted, and certainly caused a new root node to be created, we can say with - // certainty that it either caused a new subnode to be created underneath `current`, in which case we should - // carry on mutating that subnode, or it ended up as a child data pair of the root, in which case, no harm is - // done by including its bit position in the shallowlyMutableNodeMap anyways. - var shallowlyMutableNodeMap = Node.bitposFrom(Node.maskFrom(improved, 0)) - - while (iter.hasNext) { - val (key, value) = iter.next() - val originalHash = key.## - val improved = improve(originalHash) + object accum extends AbstractFunction2[K, V1, Unit] with Function1[(K, V1), Unit] { + var changed = false + var shallowlyMutableNodeMap: Int = 0 + var current: BitmapIndexedMapNode[K, V1] = rootNode + def apply(kv: (K, V1)) = apply(kv._1, kv._2) + def apply(key: K, value: V1): Unit = { + val originalHash = key.## + val improved = improve(originalHash) + if (!changed) { + current = current.updated(key, value, originalHash, improved, 0, replaceValue = true) + if (current ne rootNode) { + // Note: We could have started with shallowlyMutableNodeMap = 0, however this way, in the case that + // the first changed key ended up in a subnode beneath root, we mark that root right away as being + // shallowly mutable. + // + // since key->value has just been inserted, and certainly caused a new root node to be created, we can say with + // certainty that it either caused a new subnode to be created underneath `current`, in which case we should + // carry on mutating that subnode, or it ended up as a child data pair of the root, in which case, no harm is + // done by including its bit position in the shallowlyMutableNodeMap anyways. + changed = true + shallowlyMutableNodeMap = Node.bitposFrom(Node.maskFrom(improved, 0)) + } + } else { shallowlyMutableNodeMap = current.updateWithShallowMutations(key, value, originalHash, improved, 0, shallowlyMutableNodeMap) } - return new HashMap(current) } } - this + that match { + case thatMap: Map[K, V1] => thatMap.foreachEntry(accum) + case _ => that.iterator.foreach(accum) + } + newHashMapOrThis(accum.current) } override def tail: HashMap[K, V] = this - head._1 @@ -2331,6 +2335,8 @@ private[immutable] final class HashMapBuilder[K, V] extends ReusableBuilder[(K, val hash = improve(originalHash) update(rootNode, next.key, next.value, originalHash, hash, 0) } + case thatMap: Map[K, V] => + thatMap.foreachEntry((key, value) => addOne(key, value)) case other => val it = other.iterator while(it.hasNext) addOne(it.next()) diff --git a/src/library/scala/collection/mutable/HashMap.scala b/src/library/scala/collection/mutable/HashMap.scala index fa07b836b1c..94e97402f9a 100644 --- a/src/library/scala/collection/mutable/HashMap.scala +++ b/src/library/scala/collection/mutable/HashMap.scala @@ -102,7 +102,13 @@ class HashMap[K, V](initialCapacity: Int, loadFactor: Double) put0(next.key, next.value, next.hash, getOld = false) } this - case _ => super.addAll(xs) + case thatMap: Map[K, V] => + thatMap.foreachEntry { (key: K, value: V) => + put0(key, value, key.##, getOld = false) + } + this + case _ => + super.addAll(xs) } }