@@ -41,20 +41,22 @@ private fun Array<Any?>.replaceEntryWithNode(keyIndex: Int, nodeIndex: Int, newN
4141 return newBuffer
4242}
4343
44+ private fun <K , V > Array<Any?>.replaceNodeWithEntry (nodeIndex : Int , keyIndex : Int , key : K , value : V ): Array <Any ?> {
45+ val newBuffer = this .copyOf(this .size + 1 )
46+ newBuffer.copyInto(newBuffer, nodeIndex + 2 , nodeIndex + 1 , this .size)
47+ newBuffer.copyInto(newBuffer, keyIndex + 2 , keyIndex , nodeIndex)
48+ newBuffer[keyIndex] = key
49+ newBuffer[keyIndex + 1 ] = value
50+ return newBuffer
51+ }
52+
4453private fun Array<Any?>.removeEntryAtIndex (keyIndex : Int ): Array <Any ?> {
4554 val newBuffer = arrayOfNulls<Any ?>(this .size - ENTRY_SIZE )
4655 this .copyInto(newBuffer, endIndex = keyIndex)
4756 this .copyInto(newBuffer, keyIndex, startIndex = keyIndex + ENTRY_SIZE , endIndex = this .size)
4857 return newBuffer
4958}
5059
51- private fun Array<Any?>.removeNodeAtIndex (nodeIndex : Int ): Array <Any ?> {
52- val newBuffer = arrayOfNulls<Any ?>(this .size - 1 )
53- this .copyInto(newBuffer, endIndex = nodeIndex)
54- this .copyInto(newBuffer, nodeIndex, startIndex = nodeIndex + 1 , endIndex = this .size)
55- return newBuffer
56- }
57-
5860
5961
6062internal class TrieNode <K , V >(
@@ -173,17 +175,40 @@ internal class TrieNode<K, V>(
173175 return TrieNode (dataMap, nodeMap, newBuffer, mutator.ownership)
174176 }
175177
176- private fun updateNodeAtIndex (nodeIndex : Int , newNode : TrieNode <K , V >): TrieNode <K , V > {
178+ private fun updateNodeAtIndex (nodeIndex : Int , positionMask : Int , newNode : TrieNode <K , V >): TrieNode <K , V > {
177179// assert(buffer[nodeIndex] !== newNode)
180+ // TODO: check how this changes affect `put` and non-collision `remove` operations performance.
178181
179- val newBuffer = buffer.copyOf()
182+ val newNodeBuffer = newNode.buffer
183+ if (newNodeBuffer.size == 2 && newNode.nodeMap == 0 ) {
184+ val keyIndex = entryKeyIndex(positionMask)
185+ val newBuffer = buffer.replaceNodeWithEntry(nodeIndex, keyIndex, newNodeBuffer[0 ], newNodeBuffer[1 ])
186+ return TrieNode (dataMap xor positionMask, nodeMap xor positionMask, newBuffer)
187+ }
188+
189+ val newBuffer = buffer.copyOf(buffer.size)
180190 newBuffer[nodeIndex] = newNode
181191 return TrieNode (dataMap, nodeMap, newBuffer)
182192 }
183193
184- private fun mutableUpdateNodeAtIndex (nodeIndex : Int , newNode : TrieNode <K , V >, owner : MutabilityOwnership ): TrieNode <K , V > {
194+ private fun mutableUpdateNodeAtIndex (nodeIndex : Int , positionMask : Int , newNode : TrieNode <K , V >, owner : MutabilityOwnership ): TrieNode <K , V > {
185195// assert(buffer[nodeIndex] !== newNode)
186196
197+ val newNodeBuffer = newNode.buffer
198+ if (newNodeBuffer.size == 2 && newNode.nodeMap == 0 ) {
199+ val keyIndex = entryKeyIndex(positionMask)
200+ val newBuffer = buffer.replaceNodeWithEntry(nodeIndex, keyIndex, newNodeBuffer[0 ], newNodeBuffer[1 ])
201+
202+ if (ownedBy == = owner) {
203+ buffer = newBuffer
204+ dataMap = dataMap xor positionMask
205+ nodeMap = nodeMap xor positionMask
206+ return this
207+ }
208+
209+ return TrieNode (dataMap xor positionMask, nodeMap xor positionMask, newBuffer)
210+ }
211+
187212 if (ownedBy == = owner) {
188213 buffer[nodeIndex] = newNode
189214 return this
@@ -274,6 +299,7 @@ internal class TrieNode<K, V>(
274299
275300 private fun removeEntryAtIndex (keyIndex : Int , positionMask : Int ): TrieNode <K , V >? {
276301// assert(hasEntryAt(positionMask))
302+ // It is possible only when this node is the root node
277303 if (buffer.size == ENTRY_SIZE ) return null
278304
279305 val newBuffer = buffer.removeEntryAtIndex(keyIndex)
@@ -315,27 +341,6 @@ internal class TrieNode<K, V>(
315341 return makeCollisionNode(newBuffer, mutator.ownership)
316342 }
317343
318- private fun removeNodeAtIndex (nodeIndex : Int , positionMask : Int ): TrieNode <K , V >? {
319- // assert(hasNodeAt(positionMask))
320- if (buffer.size == 1 ) return null
321-
322- val newBuffer = buffer.removeNodeAtIndex(nodeIndex)
323- return TrieNode (dataMap, nodeMap xor positionMask, newBuffer)
324- }
325-
326- private fun mutableRemoveNodeAtIndex (nodeIndex : Int , positionMask : Int , owner : MutabilityOwnership ): TrieNode <K , V >? {
327- // assert(hasNodeAt(positionMask))
328- if (buffer.size == 1 ) return null
329-
330- if (ownedBy == = owner) {
331- buffer = buffer.removeNodeAtIndex(nodeIndex)
332- nodeMap = nodeMap xor positionMask
333- return this
334- }
335- val newBuffer = buffer.removeNodeAtIndex(nodeIndex)
336- return TrieNode (dataMap, nodeMap xor positionMask, newBuffer, owner)
337- }
338-
339344 private fun collisionContainsKey (key : K ): Boolean {
340345 val collisionHash = keyAtIndex(0 ).hashCode()
341346 val keyHash = key.hashCode()
@@ -551,7 +556,7 @@ internal class TrieNode<K, V>(
551556
552557 val targetNode = nodeAtIndex(nodeIndex)
553558 val putResult = targetNode.put(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR ) ? : return null
554- return putResult.replaceNode { node -> updateNodeAtIndex(nodeIndex, node) }
559+ return putResult.replaceNode { node -> updateNodeAtIndex(nodeIndex, keyPositionMask, node) }
555560 }
556561
557562 // no entry at this key hash segment
@@ -587,7 +592,7 @@ internal class TrieNode<K, V>(
587592 if (targetNode == = newNode) {
588593 return this
589594 }
590- return mutableUpdateNodeAtIndex(nodeIndex, newNode, mutator.ownership)
595+ return mutableUpdateNodeAtIndex(nodeIndex, keyPositionMask, newNode, mutator.ownership)
591596 }
592597
593598 // key is absent
@@ -615,11 +620,9 @@ internal class TrieNode<K, V>(
615620
616621 val targetNode = nodeAtIndex(nodeIndex)
617622 val newNode = targetNode.remove(keyHash, key, shift + LOG_MAX_BRANCHING_FACTOR )
618- return when {
619- targetNode == = newNode -> this
620- newNode == null -> removeNodeAtIndex(nodeIndex, keyPositionMask)
621- else -> updateNodeAtIndex(nodeIndex, newNode)
622- }
623+ checkNotNull(newNode)
624+ if (targetNode == = newNode) return this
625+ return updateNodeAtIndex(nodeIndex, keyPositionMask, newNode)
623626 }
624627
625628 // key is absent
@@ -646,11 +649,11 @@ internal class TrieNode<K, V>(
646649
647650 val targetNode = nodeAtIndex(nodeIndex)
648651 val newNode = targetNode.mutableRemove(keyHash, key, shift + LOG_MAX_BRANCHING_FACTOR , mutator)
649- return when {
650- targetNode == = newNode -> this
651- newNode == null -> mutableRemoveNodeAtIndex(nodeIndex, keyPositionMask, mutator.ownership)
652- else -> mutableUpdateNodeAtIndex(nodeIndex, newNode, mutator.ownership)
652+ checkNotNull(newNode)
653+ if (ownedBy == = mutator.ownership || targetNode != = newNode) {
654+ return mutableUpdateNodeAtIndex(nodeIndex, keyPositionMask, newNode, mutator.ownership)
653655 }
656+ return this
654657 }
655658
656659 // key is absent
@@ -677,11 +680,9 @@ internal class TrieNode<K, V>(
677680
678681 val targetNode = nodeAtIndex(nodeIndex)
679682 val newNode = targetNode.remove(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR )
680- return when {
681- targetNode == = newNode -> this
682- newNode == null -> removeNodeAtIndex(nodeIndex, keyPositionMask)
683- else -> updateNodeAtIndex(nodeIndex, newNode)
684- }
683+ checkNotNull(newNode)
684+ if (targetNode == = newNode) return this
685+ return updateNodeAtIndex(nodeIndex, keyPositionMask, newNode)
685686 }
686687
687688 // key is absent
@@ -708,11 +709,11 @@ internal class TrieNode<K, V>(
708709
709710 val targetNode = nodeAtIndex(nodeIndex)
710711 val newNode = targetNode.mutableRemove(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR , mutator)
711- return when {
712- targetNode == = newNode -> this
713- newNode == null -> mutableRemoveNodeAtIndex(nodeIndex, keyPositionMask, mutator.ownership)
714- else -> mutableUpdateNodeAtIndex(nodeIndex, newNode, mutator.ownership)
712+ checkNotNull(newNode)
713+ if (ownedBy == = mutator.ownership || targetNode != = newNode) {
714+ return mutableUpdateNodeAtIndex(nodeIndex, keyPositionMask, newNode, mutator.ownership)
715715 }
716+ return this
716717 }
717718
718719 // key is absent
0 commit comments