@@ -42,20 +42,22 @@ private fun Array<Any?>.replaceEntryWithNode(keyIndex: Int, nodeIndex: Int, newN
4242 return newBuffer
4343}
4444
45+ private fun <K , V > Array<Any?>.replaceNodeWithEntry (nodeIndex : Int , keyIndex : Int , key : K , value : V ): Array <Any ?> {
46+ val newBuffer = this .copyOf(this .size + 1 )
47+ newBuffer.copyInto(newBuffer, nodeIndex + 2 , nodeIndex + 1 , this .size)
48+ newBuffer.copyInto(newBuffer, keyIndex + 2 , keyIndex , nodeIndex)
49+ newBuffer[keyIndex] = key
50+ newBuffer[keyIndex + 1 ] = value
51+ return newBuffer
52+ }
53+
4554private fun Array<Any?>.removeEntryAtIndex (keyIndex : Int ): Array <Any ?> {
4655 val newBuffer = arrayOfNulls<Any ?>(this .size - ENTRY_SIZE )
4756 this .copyInto(newBuffer, endIndex = keyIndex)
4857 this .copyInto(newBuffer, keyIndex, startIndex = keyIndex + ENTRY_SIZE , endIndex = this .size)
4958 return newBuffer
5059}
5160
52- private fun Array<Any?>.removeNodeAtIndex (nodeIndex : Int ): Array <Any ?> {
53- val newBuffer = arrayOfNulls<Any ?>(this .size - 1 )
54- this .copyInto(newBuffer, endIndex = nodeIndex)
55- this .copyInto(newBuffer, nodeIndex, startIndex = nodeIndex + 1 , endIndex = this .size)
56- return newBuffer
57- }
58-
5961
6062
6163internal class TrieNode <K , V >(
@@ -170,17 +172,40 @@ internal class TrieNode<K, V>(
170172 return TrieNode (dataMap, nodeMap, newBuffer, mutator.ownership)
171173 }
172174
173- private fun updateNodeAtIndex (nodeIndex : Int , newNode : TrieNode <K , V >): TrieNode <K , V > {
175+ private fun updateNodeAtIndex (nodeIndex : Int , positionMask : Int , newNode : TrieNode <K , V >): TrieNode <K , V > {
174176// assert(buffer[nodeIndex] !== newNode)
177+ // TODO: check how this changes affect `put` and non-collision `remove` operations performance.
175178
176- val newBuffer = buffer.copyOf()
179+ val newNodeBuffer = newNode.buffer
180+ if (newNodeBuffer.size == 2 && newNode.nodeMap == 0 ) {
181+ val keyIndex = entryKeyIndex(positionMask)
182+ val newBuffer = buffer.replaceNodeWithEntry(nodeIndex, keyIndex, newNodeBuffer[0 ], newNodeBuffer[1 ])
183+ return TrieNode (dataMap xor positionMask, nodeMap xor positionMask, newBuffer)
184+ }
185+
186+ val newBuffer = buffer.copyOf(buffer.size)
177187 newBuffer[nodeIndex] = newNode
178188 return TrieNode (dataMap, nodeMap, newBuffer)
179189 }
180190
181- private fun mutableUpdateNodeAtIndex (nodeIndex : Int , newNode : TrieNode <K , V >, owner : MutabilityOwnership ): TrieNode <K , V > {
191+ private fun mutableUpdateNodeAtIndex (nodeIndex : Int , positionMask : Int , newNode : TrieNode <K , V >, owner : MutabilityOwnership ): TrieNode <K , V > {
182192// assert(buffer[nodeIndex] !== newNode)
183193
194+ val newNodeBuffer = newNode.buffer
195+ if (newNodeBuffer.size == 2 && newNode.nodeMap == 0 ) {
196+ val keyIndex = entryKeyIndex(positionMask)
197+ val newBuffer = buffer.replaceNodeWithEntry(nodeIndex, keyIndex, newNodeBuffer[0 ], newNodeBuffer[1 ])
198+
199+ if (ownedBy == = owner) {
200+ buffer = newBuffer
201+ dataMap = dataMap xor positionMask
202+ nodeMap = nodeMap xor positionMask
203+ return this
204+ }
205+
206+ return TrieNode (dataMap xor positionMask, nodeMap xor positionMask, newBuffer)
207+ }
208+
184209 if (ownedBy == = owner) {
185210 buffer[nodeIndex] = newNode
186211 return this
@@ -255,6 +280,7 @@ internal class TrieNode<K, V>(
255280
256281 private fun removeEntryAtIndex (keyIndex : Int , positionMask : Int ): TrieNode <K , V >? {
257282// assert(hasEntryAt(positionMask))
283+ // It is possible only when this node is the root node
258284 if (buffer.size == ENTRY_SIZE ) return null
259285
260286 val newBuffer = buffer.removeEntryAtIndex(keyIndex)
@@ -296,27 +322,6 @@ internal class TrieNode<K, V>(
296322 return TrieNode (0 , 0 , newBuffer, mutator.ownership)
297323 }
298324
299- private fun removeNodeAtIndex (nodeIndex : Int , positionMask : Int ): TrieNode <K , V >? {
300- // assert(hasNodeAt(positionMask))
301- if (buffer.size == 1 ) return null
302-
303- val newBuffer = buffer.removeNodeAtIndex(nodeIndex)
304- return TrieNode (dataMap, nodeMap xor positionMask, newBuffer)
305- }
306-
307- private fun mutableRemoveNodeAtIndex (nodeIndex : Int , positionMask : Int , owner : MutabilityOwnership ): TrieNode <K , V >? {
308- // assert(hasNodeAt(positionMask))
309- if (buffer.size == 1 ) return null
310-
311- if (ownedBy == = owner) {
312- buffer = buffer.removeNodeAtIndex(nodeIndex)
313- nodeMap = nodeMap xor positionMask
314- return this
315- }
316- val newBuffer = buffer.removeNodeAtIndex(nodeIndex)
317- return TrieNode (dataMap, nodeMap xor positionMask, newBuffer, owner)
318- }
319-
320325 private fun collisionContainsKey (key : K ): Boolean {
321326 for (i in 0 until buffer.size step ENTRY_SIZE ) {
322327 if (key == buffer[i]) return true
@@ -473,7 +478,7 @@ internal class TrieNode<K, V>(
473478 } else {
474479 targetNode.put(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR ) ? : return null
475480 }
476- return putResult.replaceNode { node -> updateNodeAtIndex(nodeIndex, node) }
481+ return putResult.replaceNode { node -> updateNodeAtIndex(nodeIndex, keyPositionMask, node) }
477482 }
478483
479484 // no entry at this key hash segment
@@ -509,7 +514,7 @@ internal class TrieNode<K, V>(
509514 if (targetNode == = newNode) {
510515 return this
511516 }
512- return mutableUpdateNodeAtIndex(nodeIndex, newNode, mutator.ownership)
517+ return mutableUpdateNodeAtIndex(nodeIndex, keyPositionMask, newNode, mutator.ownership)
513518 }
514519
515520 // key is absent
@@ -537,11 +542,9 @@ internal class TrieNode<K, V>(
537542 } else {
538543 targetNode.remove(keyHash, key, shift + LOG_MAX_BRANCHING_FACTOR )
539544 }
540- return when {
541- targetNode == = newNode -> this
542- newNode == null -> removeNodeAtIndex(nodeIndex, keyPositionMask)
543- else -> updateNodeAtIndex(nodeIndex, newNode)
544- }
545+ checkNotNull(newNode)
546+ if (targetNode == = newNode) return this
547+ return updateNodeAtIndex(nodeIndex, keyPositionMask, newNode)
545548 }
546549
547550 // key is absent
@@ -568,11 +571,11 @@ internal class TrieNode<K, V>(
568571 } else {
569572 targetNode.mutableRemove(keyHash, key, shift + LOG_MAX_BRANCHING_FACTOR , mutator)
570573 }
571- return when {
572- targetNode == = newNode -> this
573- newNode == null -> mutableRemoveNodeAtIndex(nodeIndex, keyPositionMask, mutator.ownership)
574- else -> mutableUpdateNodeAtIndex(nodeIndex, newNode, mutator.ownership)
574+ checkNotNull(newNode)
575+ if (ownedBy == = mutator.ownership || targetNode != = newNode) {
576+ return mutableUpdateNodeAtIndex(nodeIndex, keyPositionMask, newNode, mutator.ownership)
575577 }
578+ return this
576579 }
577580
578581 // key is absent
@@ -599,11 +602,9 @@ internal class TrieNode<K, V>(
599602 } else {
600603 targetNode.remove(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR )
601604 }
602- return when {
603- targetNode == = newNode -> this
604- newNode == null -> removeNodeAtIndex(nodeIndex, keyPositionMask)
605- else -> updateNodeAtIndex(nodeIndex, newNode)
606- }
605+ checkNotNull(newNode)
606+ if (targetNode == = newNode) return this
607+ return updateNodeAtIndex(nodeIndex, keyPositionMask, newNode)
607608 }
608609
609610 // key is absent
@@ -630,11 +631,11 @@ internal class TrieNode<K, V>(
630631 } else {
631632 targetNode.mutableRemove(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR , mutator)
632633 }
633- return when {
634- targetNode == = newNode -> this
635- newNode == null -> mutableRemoveNodeAtIndex(nodeIndex, keyPositionMask, mutator.ownership)
636- else -> mutableUpdateNodeAtIndex(nodeIndex, newNode, mutator.ownership)
634+ checkNotNull(newNode)
635+ if (ownedBy == = mutator.ownership || targetNode != = newNode) {
636+ return mutableUpdateNodeAtIndex(nodeIndex, keyPositionMask, newNode, mutator.ownership)
637637 }
638+ return this
638639 }
639640
640641 // key is absent
0 commit comments