Skip to content

Commit 37404cd

Browse files
committed
Use only new SparseInArray scheme for tree addresses
1 parent 96c18fb commit 37404cd

File tree

2 files changed

+47
-30
lines changed

2 files changed

+47
-30
lines changed

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

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -21,29 +21,20 @@ class TreeBuffer extends TastyBuffer(50000) {
2121
private var delta: Array[Int] = _
2222
private var numOffsets = 0
2323

24-
/** A map from trees to the address at which a tree is pickled. */
25-
private val treeAddrs = new java.util.IdentityHashMap[Tree, Any] // really: Addr | Null
26-
private val treeAddrs2 = SparseIntArray()
27-
28-
def registerTreeAddr(tree: Tree): Addr = treeAddrs.get(tree) match {
29-
case null =>
30-
treeAddrs.put(tree, currentAddr)
31-
treeAddrs2(tree.uniqueId) = currentAddr.index
24+
/** A map from tree unique ids to the address index at which a tree is pickled. */
25+
private val addrOfTree = SparseIntArray()
26+
27+
def registerTreeAddr(tree: Tree): Addr =
28+
val id = tree.uniqueId
29+
if addrOfTree.contains(id) then Addr(addrOfTree(id))
30+
else
31+
addrOfTree(tree.uniqueId) = currentAddr.index
3232
currentAddr
33-
case addr: Addr => addr
34-
}
3533

3634
def addrOfTree(tree: Tree): Addr =
37-
val old = treeAddrs.get(tree) match {
38-
case null => NoAddr
39-
case addr: Addr => addr
40-
}
41-
val now =
42-
val idx = tree.uniqueId
43-
if treeAddrs2.contains(idx) then Addr(treeAddrs2(idx))
44-
else NoAddr
45-
assert(old == now)
46-
now
35+
val idx = tree.uniqueId
36+
if addrOfTree.contains(idx) then Addr(addrOfTree(idx))
37+
else NoAddr
4738

4839
private def offset(i: Int): Addr = Addr(offsets(i))
4940

@@ -168,16 +159,8 @@ class TreeBuffer extends TastyBuffer(50000) {
168159
wasted
169160
}
170161

171-
def adjustTreeAddrs(): Unit = {
172-
val it = treeAddrs.keySet.iterator
173-
while (it.hasNext) {
174-
val tree = it.next
175-
treeAddrs.get(tree) match {
176-
case addr: Addr => treeAddrs.put(tree, adjusted(addr))
177-
}
178-
}
179-
treeAddrs2.transform((id, addr) => adjusted(Addr(addr)).index)
180-
}
162+
def adjustTreeAddrs(): Unit =
163+
addrOfTree.transform((id, addr) => adjusted(Addr(addr)).index)
181164

182165
/** Final assembly, involving the following steps:
183166
* - compute deltas

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,16 @@ class SparseIntArray:
4242
result
4343
}
4444

45+
/** All defined indices in an iterator */
46+
def keysIterator: Iterator[Int] = root.keysIterator(0)
47+
48+
/** Perform operation for each key/value pair */
4549
def foreachBinding(op: (Int, Value) => Unit): Unit =
4650
root.foreachBinding(op, 0)
4751

52+
/** Transform each defined value with transformation `op`.
53+
* The transformation gets the element index and value as parameters.
54+
*/
4855
def transform(op: (Int, Value) => Value): Unit =
4956
root.transform(op, 0)
5057

@@ -82,6 +89,7 @@ object SparseIntArray:
8289
def update(index: Int, value: Value): Boolean
8390
def remove(index: Int): Boolean
8491
def isEmpty: Boolean
92+
def keysIterator(offset: Int): Iterator[Int]
8593
def foreachBinding(op: (Int, Value) => Unit, offset: Int): Unit
8694
def transform(op: (Int, Value) => Value, offset: Int): Unit
8795
def nodeCount: Int
@@ -111,6 +119,17 @@ object SparseIntArray:
111119

112120
def isEmpty = present == 0
113121

122+
private def skipUndefined(i: Int): Int =
123+
if i < NodeSize && !contains(i) then skipUndefined(i + 1) else i
124+
125+
def keysIterator(offset: Int) = new Iterator[Int]:
126+
private var curIdx = skipUndefined(0)
127+
def hasNext = curIdx < NodeSize
128+
def next(): Int =
129+
val result = curIdx + offset
130+
curIdx = skipUndefined(curIdx + 1)
131+
result
132+
114133
def foreachBinding(op: (Int, Value) => Unit, offset: Int): Unit =
115134
var i = 0
116135
while i < NodeSize do
@@ -167,6 +186,20 @@ object SparseIntArray:
167186

168187
def isEmpty = empty
169188

189+
private def skipUndefined(i: Int): Int =
190+
if i < NodeSize && elems(i) == null then skipUndefined(i + 1) else i
191+
192+
def keysIterator(offset: Int) = new Iterator[Value]:
193+
private var curIdx = skipUndefined(0)
194+
private var elemIt = Iterator.empty[Int]
195+
def hasNext = elemIt.hasNext || curIdx < NodeSize
196+
def next(): Value =
197+
if elemIt.hasNext then elemIt.next()
198+
else
199+
elemIt = elems(curIdx).keysIterator(offset + curIdx * elemSize)
200+
curIdx = skipUndefined(curIdx + 1)
201+
elemIt.next()
202+
170203
def foreachBinding(op: (Int, Value) => Unit, offset: Int): Unit =
171204
var i = 0
172205
while i < NodeSize do
@@ -205,6 +238,7 @@ end SparseIntArray
205238
println(s"a = $a")
206239
a(55555) = 44
207240
println(s"a = $a")
241+
println(s"iterator of a yields ${a.keysIterator.toList}")
208242
assert(a.size == 3, a)
209243
assert(a.contains(1), a)
210244
assert(a.contains(222), a)

0 commit comments

Comments
 (0)