Skip to content

Commit cdd353c

Browse files
committed
optimise getOrElseUpdate
1 parent 992f200 commit cdd353c

File tree

3 files changed

+46
-6
lines changed

3 files changed

+46
-6
lines changed

compiler/src/dotty/tools/dotc/util/EqHashMap.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,22 @@ extends GenericHashMap[Key, Value](initialCapacity, capacityMultiple):
5858
used += 1
5959
if used > limit then growTable()
6060

61+
override def getOrElseUpdate(key: Key, value: => Value): Value =
62+
// created by blending lookup and update, avoid having to recompute hash and probe
63+
Stats.record(statsItem("lookup-or-update"))
64+
var idx = firstIndex(key)
65+
var k = keyAt(idx)
66+
while k != null do
67+
if isEqual(k, key) then return valueAt(idx)
68+
idx = nextIndex(idx)
69+
k = keyAt(idx)
70+
val v = value
71+
setKey(idx, key)
72+
setValue(idx, v)
73+
used += 1
74+
if used > limit then growTable()
75+
v
76+
6177
private def addOld(key: Key, value: Value): Unit =
6278
Stats.record(statsItem("re-enter"))
6379
var idx = firstIndex(key)

compiler/src/dotty/tools/dotc/util/GenericHashMap.scala

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,20 @@ abstract class GenericHashMap[Key, Value]
129129
null
130130

131131
def getOrElseUpdate(key: Key, value: => Value): Value =
132-
var v: Value | Null = lookup(key)
133-
if v == null then
134-
val v1 = value
135-
v = v1
136-
update(key, v1)
137-
v.uncheckedNN
132+
// created by blending lookup and update, avoid having to recompute hash and probe
133+
Stats.record(statsItem("lookup-or-update"))
134+
var idx = firstIndex(key)
135+
var k = keyAt(idx)
136+
while k != null do
137+
if isEqual(k, key) then return valueAt(idx)
138+
idx = nextIndex(idx)
139+
k = keyAt(idx)
140+
val v = value
141+
setKey(idx, key)
142+
setValue(idx, v)
143+
used += 1
144+
if used > limit then growTable()
145+
v
138146

139147
private def addOld(key: Key, value: Value): Unit =
140148
Stats.record(statsItem("re-enter"))

compiler/src/dotty/tools/dotc/util/HashMap.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,22 @@ extends GenericHashMap[Key, Value](initialCapacity, capacityMultiple):
6363
used += 1
6464
if used > limit then growTable()
6565

66+
override def getOrElseUpdate(key: Key, value: => Value): Value =
67+
// created by blending lookup and update, avoid having to recompute hash and probe
68+
Stats.record(statsItem("lookup-or-update"))
69+
var idx = firstIndex(key)
70+
var k = keyAt(idx)
71+
while k != null do
72+
if isEqual(k, key) then return valueAt(idx)
73+
idx = nextIndex(idx)
74+
k = keyAt(idx)
75+
val v = value
76+
setKey(idx, key)
77+
setValue(idx, v)
78+
used += 1
79+
if used > limit then growTable()
80+
v
81+
6682
private def addOld(key: Key, value: Value): Unit =
6783
Stats.record(statsItem("re-enter"))
6884
var idx = firstIndex(key)

0 commit comments

Comments
 (0)