@@ -93,19 +93,36 @@ internal class TrieNode<E>(
9393// assert(buffer[nodeIndex] !== newNode)
9494
9595 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+
97106 return TrieNode (bitmap, newBuffer)
98107 }
99108
100109 private fun mutableUpdateNodeAtIndex (nodeIndex : Int , newNode : TrieNode <E >, owner : MutabilityOwnership ): TrieNode <E > {
101110// assert(buffer[nodeIndex] !== newNode)
102111
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+
103120 if (ownedBy == = owner) {
104- buffer[nodeIndex] = newNode
121+ buffer[nodeIndex] = cell
105122 return this
106123 }
107124 val newBuffer = buffer.copyOf()
108- newBuffer[nodeIndex] = newNode
125+ newBuffer[nodeIndex] = cell
109126 return TrieNode (bitmap, newBuffer, owner)
110127 }
111128
@@ -161,6 +178,7 @@ internal class TrieNode<E>(
161178
162179 private fun removeCellAtIndex (cellIndex : Int , positionMask : Int ): TrieNode <E >? {
163180// assert(!hasNoCellAt(positionMask))
181+ // It is possible only when this node is the root node
164182 if (buffer.size == 1 ) return null
165183
166184 val newBuffer = buffer.removeCellAtIndex(cellIndex)
@@ -318,11 +336,9 @@ internal class TrieNode<E>(
318336 } else {
319337 targetNode.remove(elementHash, element, shift + LOG_MAX_BRANCHING_FACTOR )
320338 }
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)
326342 }
327343 // element is directly in buffer
328344 if (element == buffer[cellIndex]) {
@@ -346,11 +362,11 @@ internal class TrieNode<E>(
346362 } else {
347363 targetNode.mutableRemove(elementHash, element, shift + LOG_MAX_BRANCHING_FACTOR , mutator)
348364 }
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)
353368 }
369+ return this
354370 }
355371 // element is directly in buffer
356372 if (element == buffer[cellIndex]) {
0 commit comments