@@ -93,19 +93,36 @@ internal class TrieNode<E>(
93
93
// assert(buffer[nodeIndex] !== newNode)
94
94
95
95
val newBuffer = buffer.copyOf()
96
- newBuffer[nodeIndex] = newNode
96
+
97
+ // TODO: check how this changes affect `add` operation performance.
98
+ // Try to not create this newNode, but pass here the remained element.
99
+ val newNodeBuffer = newNode.buffer
100
+ if (newNodeBuffer.size == 1 && newNodeBuffer[0 ] !is TrieNode <* >) {
101
+ newBuffer[nodeIndex] = newNodeBuffer[0 ]
102
+ } else {
103
+ newBuffer[nodeIndex] = newNode
104
+ }
105
+
97
106
return TrieNode (bitmap, newBuffer)
98
107
}
99
108
100
109
private fun mutableUpdateNodeAtIndex (nodeIndex : Int , newNode : TrieNode <E >, owner : MutabilityOwnership ): TrieNode <E > {
101
110
// assert(buffer[nodeIndex] !== newNode)
102
111
112
+ val cell: Any?
113
+ val newNodeBuffer = newNode.buffer
114
+ if (newNodeBuffer.size == 1 && newNodeBuffer[0 ] !is TrieNode <* >) {
115
+ cell = newNodeBuffer[0 ]
116
+ } else {
117
+ cell = newNode
118
+ }
119
+
103
120
if (ownedBy == = owner) {
104
- buffer[nodeIndex] = newNode
121
+ buffer[nodeIndex] = cell
105
122
return this
106
123
}
107
124
val newBuffer = buffer.copyOf()
108
- newBuffer[nodeIndex] = newNode
125
+ newBuffer[nodeIndex] = cell
109
126
return TrieNode (bitmap, newBuffer, owner)
110
127
}
111
128
@@ -161,6 +178,7 @@ internal class TrieNode<E>(
161
178
162
179
private fun removeCellAtIndex (cellIndex : Int , positionMask : Int ): TrieNode <E >? {
163
180
// assert(!hasNoCellAt(positionMask))
181
+ // It is possible only when this node is the root node
164
182
if (buffer.size == 1 ) return null
165
183
166
184
val newBuffer = buffer.removeCellAtIndex(cellIndex)
@@ -318,11 +336,9 @@ internal class TrieNode<E>(
318
336
} else {
319
337
targetNode.remove(elementHash, element, shift + LOG_MAX_BRANCHING_FACTOR )
320
338
}
321
- return when {
322
- targetNode == = newNode -> this
323
- newNode == null -> removeCellAtIndex(cellIndex, cellPositionMask)
324
- else -> updateNodeAtIndex(cellIndex, newNode)
325
- }
339
+ checkNotNull(newNode)
340
+ if (targetNode == = newNode) return this
341
+ return updateNodeAtIndex(cellIndex, newNode)
326
342
}
327
343
// element is directly in buffer
328
344
if (element == buffer[cellIndex]) {
@@ -346,11 +362,11 @@ internal class TrieNode<E>(
346
362
} else {
347
363
targetNode.mutableRemove(elementHash, element, shift + LOG_MAX_BRANCHING_FACTOR , mutator)
348
364
}
349
- return when {
350
- targetNode == = newNode -> this
351
- newNode == null -> mutableRemoveCellAtIndex(cellIndex, cellPositionMask, mutator.ownership)
352
- else -> mutableUpdateNodeAtIndex(cellIndex, newNode, mutator.ownership)
365
+ checkNotNull(newNode)
366
+ if (ownedBy == = mutator.ownership || targetNode != = newNode) {
367
+ return mutableUpdateNodeAtIndex(cellIndex, newNode, mutator.ownership)
353
368
}
369
+ return this
354
370
}
355
371
// element is directly in buffer
356
372
if (element == buffer[cellIndex]) {
0 commit comments