diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2017-02-19 14:47:02 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2017-03-03 16:04:43 +1000 |
commit | 898fa00a76286786427b093f0161ea0d3d3bae29 (patch) | |
tree | bfee66012c1423057f234fa3918da31e98ce049d /src | |
parent | db8520e5c45d9ce24912849fad16a5c1b54a09b9 (diff) | |
download | scala-898fa00a76286786427b093f0161ea0d3d3bae29.tar.gz scala-898fa00a76286786427b093f0161ea0d3d3bae29.tar.bz2 scala-898fa00a76286786427b093f0161ea0d3d3bae29.zip |
SI-10187 Support mutation of mutable.HashMap in getOrElseUpdate
Scala 2.12.1 included optimizations to `HashMape.getOrElseUpdate`
to avoid recomputing the index in the hash table when adding an
the element.
However, this index could be stale if the callback added elements
to the map and triggered a resize.
This commit checks that the table is unchanged before reusing
the index, restoring the 2.12.0 behaviour.
Diffstat (limited to 'src')
-rw-r--r-- | src/library/scala/collection/mutable/HashMap.scala | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/src/library/scala/collection/mutable/HashMap.scala b/src/library/scala/collection/mutable/HashMap.scala index 11ff1f0893..de61ebb796 100644 --- a/src/library/scala/collection/mutable/HashMap.scala +++ b/src/library/scala/collection/mutable/HashMap.scala @@ -73,10 +73,18 @@ extends AbstractMap[A, B] } override def getOrElseUpdate(key: A, defaultValue: => B): B = { - val i = index(elemHashCode(key)) + val hash = elemHashCode(key) + val i = index(hash) val entry = findEntry(key, i) if (entry != null) entry.value - else addEntry(createNewEntry(key, defaultValue), i) + else { + val table0 = table + val default = defaultValue + // Avoid recomputing index if the `defaultValue()` hasn't triggered + // a table resize. + val newEntryIndex = if (table0 eq table) i else index(hash) + addEntry(createNewEntry(key, default), newEntryIndex) + } } /* inlined HashTable.findEntry0 to preserve its visibility */ |