@@ -92,19 +92,36 @@ internal class TrieNode<E>(
92
92
// assert(buffer[nodeIndex] !== newNode)
93
93
94
94
val newBuffer = buffer.copyOf()
95
- newBuffer[nodeIndex] = newNode
95
+
96
+ // TODO: check how this changes affect `add` operation performance.
97
+ // Try to not create this newNode, but pass here the remained element.
98
+ val newNodeBuffer = newNode.buffer
99
+ if (newNodeBuffer.size == 1 && newNodeBuffer[0 ] !is TrieNode <* >) {
100
+ newBuffer[nodeIndex] = newNodeBuffer[0 ]
101
+ } else {
102
+ newBuffer[nodeIndex] = newNode
103
+ }
104
+
96
105
return TrieNode (bitmap, newBuffer)
97
106
}
98
107
99
108
private fun mutableUpdateNodeAtIndex (nodeIndex : Int , newNode : TrieNode <E >, owner : MutabilityOwnership ): TrieNode <E > {
100
109
// assert(buffer[nodeIndex] !== newNode)
101
110
111
+ val cell: Any?
112
+ val newNodeBuffer = newNode.buffer
113
+ if (newNodeBuffer.size == 1 && newNodeBuffer[0 ] !is TrieNode <* >) {
114
+ cell = newNodeBuffer[0 ]
115
+ } else {
116
+ cell = newNode
117
+ }
118
+
102
119
if (ownedBy == = owner) {
103
- buffer[nodeIndex] = newNode
120
+ buffer[nodeIndex] = cell
104
121
return this
105
122
}
106
123
val newBuffer = buffer.copyOf()
107
- newBuffer[nodeIndex] = newNode
124
+ newBuffer[nodeIndex] = cell
108
125
return TrieNode (bitmap, newBuffer, owner)
109
126
}
110
127
@@ -184,6 +201,7 @@ internal class TrieNode<E>(
184
201
185
202
private fun removeCellAtIndex (cellIndex : Int , positionMask : Int ): TrieNode <E >? {
186
203
// assert(!hasNoCellAt(positionMask))
204
+ // It is possible only when this node is the root node
187
205
if (buffer.size == 1 ) return null
188
206
189
207
val newBuffer = buffer.removeCellAtIndex(cellIndex)
@@ -355,11 +373,9 @@ internal class TrieNode<E>(
355
373
if (buffer[cellIndex] is TrieNode <* >) { // element may be in node
356
374
val targetNode = nodeAtIndex(cellIndex)
357
375
val newNode = targetNode.remove(elementHash, element, shift + LOG_MAX_BRANCHING_FACTOR )
358
- return when {
359
- targetNode == = newNode -> this
360
- newNode == null -> removeCellAtIndex(cellIndex, cellPositionMask)
361
- else -> updateNodeAtIndex(cellIndex, newNode)
362
- }
376
+ checkNotNull(newNode)
377
+ if (targetNode == = newNode) return this
378
+ return updateNodeAtIndex(cellIndex, newNode)
363
379
}
364
380
// element is directly in buffer
365
381
if (element == buffer[cellIndex]) {
@@ -383,11 +399,11 @@ internal class TrieNode<E>(
383
399
if (buffer[cellIndex] is TrieNode <* >) { // element may be in node
384
400
val targetNode = nodeAtIndex(cellIndex)
385
401
val newNode = targetNode.mutableRemove(elementHash, element, shift + LOG_MAX_BRANCHING_FACTOR , mutator)
386
- return when {
387
- targetNode == = newNode -> this
388
- newNode == null -> mutableRemoveCellAtIndex(cellIndex, cellPositionMask, mutator.ownership)
389
- else -> mutableUpdateNodeAtIndex(cellIndex, newNode, mutator.ownership)
402
+ checkNotNull(newNode)
403
+ if (ownedBy == = mutator.ownership || targetNode != = newNode) {
404
+ return mutableUpdateNodeAtIndex(cellIndex, newNode, mutator.ownership)
390
405
}
406
+ return this
391
407
}
392
408
// element is directly in buffer
393
409
if (element == buffer[cellIndex]) {
0 commit comments