Skip to content

Commit 3eb424c

Browse files
author
Abduqodiri Qurbonzoda
committed
Do note create node containing a single other node
1 parent 5dde861 commit 3eb424c

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

core/commonMain/src/implementations/immutableMap/TrieNode.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,17 @@ internal class TrieNode<K, V>(
172172
return TrieNode(dataMap, nodeMap, newBuffer, mutator.ownership)
173173
}
174174

175+
/** The given [newNode] must not be a part of any persistent map instance. */
175176
private fun updateNodeAtIndex(nodeIndex: Int, positionMask: Int, newNode: TrieNode<K, V>): TrieNode<K, V> {
176177
// assert(buffer[nodeIndex] !== newNode)
177178
val newNodeBuffer = newNode.buffer
178179
if (newNodeBuffer.size == 2 && newNode.nodeMap == 0) {
180+
if (buffer.size == 1) {
181+
// assert(dataMap == 0 && nodeMap xor positionMask == 0)
182+
newNode.dataMap = nodeMap
183+
return newNode
184+
}
185+
179186
val keyIndex = entryKeyIndex(positionMask)
180187
val newBuffer = buffer.replaceNodeWithEntry(nodeIndex, keyIndex, newNodeBuffer[0], newNodeBuffer[1])
181188
return TrieNode(dataMap xor positionMask, nodeMap xor positionMask, newBuffer)
@@ -186,11 +193,18 @@ internal class TrieNode<K, V>(
186193
return TrieNode(dataMap, nodeMap, newBuffer)
187194
}
188195

196+
/** The given [newNode] must not be a part of any persistent map instance. */
189197
private fun mutableUpdateNodeAtIndex(nodeIndex: Int, positionMask: Int, newNode: TrieNode<K, V>, owner: MutabilityOwnership): TrieNode<K, V> {
190198
// assert(buffer[nodeIndex] !== newNode)
191199

192200
val newNodeBuffer = newNode.buffer
193201
if (newNodeBuffer.size == 2 && newNode.nodeMap == 0) {
202+
if (buffer.size == 1) {
203+
// assert(dataMap == 0 && nodeMap xor positionMask == 0)
204+
newNode.dataMap = nodeMap
205+
return newNode
206+
}
207+
194208
val keyIndex = entryKeyIndex(positionMask)
195209
val newBuffer = buffer.replaceNodeWithEntry(nodeIndex, keyIndex, newNodeBuffer[0], newNodeBuffer[1])
196210

core/commonMain/src/implementations/immutableSet/TrieNode.kt

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,29 +89,39 @@ internal class TrieNode<E>(
8989
return TrieNode(bitmap or positionMask, newBuffer, owner)
9090
}
9191

92+
/** The given [newNode] must not be a part of any persistent set instance. */
9293
private fun updateNodeAtIndex(nodeIndex: Int, newNode: TrieNode<E>): TrieNode<E> {
9394
// assert(buffer[nodeIndex] !== newNode)
95+
val cell: Any?
9496

95-
val newBuffer = buffer.copyOf()
96-
97-
// TODO: check how this changes affect `add` operation performance.
98-
// Try to not create this newNode, but pass here the remained element.
9997
val newNodeBuffer = newNode.buffer
10098
if (newNodeBuffer.size == 1 && newNodeBuffer[0] !is TrieNode<*>) {
101-
newBuffer[nodeIndex] = newNodeBuffer[0]
99+
if (buffer.size == 1) {
100+
newNode.bitmap = bitmap
101+
return newNode
102+
}
103+
cell = newNodeBuffer[0]
102104
} else {
103-
newBuffer[nodeIndex] = newNode
105+
cell = newNode
104106
}
105107

108+
val newBuffer = buffer.copyOf()
109+
newBuffer[nodeIndex] = cell
106110
return TrieNode(bitmap, newBuffer)
107111
}
108112

113+
/** The given [newNode] must not be a part of any persistent set instance. */
109114
private fun mutableUpdateNodeAtIndex(nodeIndex: Int, newNode: TrieNode<E>, owner: MutabilityOwnership): TrieNode<E> {
110115
// assert(buffer[nodeIndex] !== newNode)
111116

112117
val cell: Any?
118+
113119
val newNodeBuffer = newNode.buffer
114120
if (newNodeBuffer.size == 1 && newNodeBuffer[0] !is TrieNode<*>) {
121+
if (buffer.size == 1) {
122+
newNode.bitmap = bitmap
123+
return newNode
124+
}
115125
cell = newNodeBuffer[0]
116126
} else {
117127
cell = newNode

0 commit comments

Comments
 (0)