@@ -92,19 +92,36 @@ internal class TrieNode<E>(
9292// assert(buffer[nodeIndex] !== newNode)
9393
9494 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+
96105 return TrieNode (bitmap, newBuffer)
97106 }
98107
99108 private fun mutableUpdateNodeAtIndex (nodeIndex : Int , newNode : TrieNode <E >, owner : MutabilityOwnership ): TrieNode <E > {
100109// assert(buffer[nodeIndex] !== newNode)
101110
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+
102119 if (ownedBy == = owner) {
103- buffer[nodeIndex] = newNode
120+ buffer[nodeIndex] = cell
104121 return this
105122 }
106123 val newBuffer = buffer.copyOf()
107- newBuffer[nodeIndex] = newNode
124+ newBuffer[nodeIndex] = cell
108125 return TrieNode (bitmap, newBuffer, owner)
109126 }
110127
@@ -184,6 +201,7 @@ internal class TrieNode<E>(
184201
185202 private fun removeCellAtIndex (cellIndex : Int , positionMask : Int ): TrieNode <E >? {
186203// assert(!hasNoCellAt(positionMask))
204+ // It is possible only when this node is the root node
187205 if (buffer.size == 1 ) return null
188206
189207 val newBuffer = buffer.removeCellAtIndex(cellIndex)
@@ -355,11 +373,9 @@ internal class TrieNode<E>(
355373 if (buffer[cellIndex] is TrieNode <* >) { // element may be in node
356374 val targetNode = nodeAtIndex(cellIndex)
357375 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)
363379 }
364380 // element is directly in buffer
365381 if (element == buffer[cellIndex]) {
@@ -383,11 +399,11 @@ internal class TrieNode<E>(
383399 if (buffer[cellIndex] is TrieNode <* >) { // element may be in node
384400 val targetNode = nodeAtIndex(cellIndex)
385401 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)
390405 }
406+ return this
391407 }
392408 // element is directly in buffer
393409 if (element == buffer[cellIndex]) {
0 commit comments